Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: ScrollFrame Container Zerotorescue@0: Plain container that scrolls its content and doesn't grow in height. Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local Type, Version = "ScrollFrame", 20 Zerotorescue@0: local AceGUI = LibStub and LibStub("AceGUI-3.0", true) Zerotorescue@0: if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end Zerotorescue@0: Zerotorescue@0: -- Lua APIs Zerotorescue@0: local pairs, assert, type = pairs, assert, type Zerotorescue@0: local min, max, floor = math.min, math.max, math.floor Zerotorescue@0: Zerotorescue@0: -- WoW APIs Zerotorescue@0: local CreateFrame, UIParent = CreateFrame, UIParent Zerotorescue@0: Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: Support functions Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local function FixScrollOnUpdate(frame) Zerotorescue@0: frame:SetScript("OnUpdate", nil) Zerotorescue@0: frame.obj:FixScroll() Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: Scripts Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local function ScrollFrame_OnMouseWheel(frame, value) Zerotorescue@0: frame.obj:MoveScroll(value) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function ScrollFrame_OnSizeChanged(frame) Zerotorescue@0: frame:SetScript("OnUpdate", FixScrollOnUpdate) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function ScrollBar_OnScrollValueChanged(frame, value) Zerotorescue@0: frame.obj:SetScroll(value) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: Methods Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local methods = { Zerotorescue@0: ["OnAcquire"] = function(self) Zerotorescue@0: self:SetScroll(0) Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["OnRelease"] = function(self) Zerotorescue@0: self.status = nil Zerotorescue@0: for k in pairs(self.localstatus) do Zerotorescue@0: self.localstatus[k] = nil Zerotorescue@0: end Zerotorescue@0: self.scrollframe:SetPoint("BOTTOMRIGHT") Zerotorescue@0: self.scrollbar:Hide() Zerotorescue@0: self.scrollBarShown = nil Zerotorescue@0: self.content.height, self.content.width = nil, nil Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["SetScroll"] = function(self, value) Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: local viewheight = self.scrollframe:GetHeight() Zerotorescue@0: local height = self.content:GetHeight() Zerotorescue@0: local offset Zerotorescue@0: Zerotorescue@0: if viewheight > height then Zerotorescue@0: offset = 0 Zerotorescue@0: else Zerotorescue@0: offset = floor((height - viewheight) / 1000.0 * value) Zerotorescue@0: end Zerotorescue@0: self.content:ClearAllPoints() Zerotorescue@0: self.content:SetPoint("TOPLEFT", 0, offset) Zerotorescue@0: self.content:SetPoint("TOPRIGHT", 0, offset) Zerotorescue@0: status.offset = offset Zerotorescue@0: status.scrollvalue = value Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["MoveScroll"] = function(self, value) Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight() Zerotorescue@0: Zerotorescue@0: if height > viewheight then Zerotorescue@0: self.scrollbar:Hide() Zerotorescue@0: else Zerotorescue@0: self.scrollbar:Show() Zerotorescue@0: local diff = height - viewheight Zerotorescue@0: local delta = 1 Zerotorescue@0: if value < 0 then Zerotorescue@0: delta = -1 Zerotorescue@0: end Zerotorescue@0: self.scrollbar:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000)) Zerotorescue@0: end Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["FixScroll"] = function(self) Zerotorescue@0: if self.updateLock then return end Zerotorescue@0: self.updateLock = true Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight() Zerotorescue@0: local offset = status.offset or 0 Zerotorescue@0: local curvalue = self.scrollbar:GetValue() Zerotorescue@0: if viewheight < height then Zerotorescue@0: if self.scrollBarShown then Zerotorescue@0: self.scrollBarShown = nil Zerotorescue@0: self.scrollbar:Hide() Zerotorescue@0: self.scrollbar:SetValue(0) Zerotorescue@0: self.scrollframe:SetPoint("BOTTOMRIGHT") Zerotorescue@0: self:DoLayout() Zerotorescue@0: end Zerotorescue@0: else Zerotorescue@0: if not self.scrollBarShown then Zerotorescue@0: self.scrollBarShown = true Zerotorescue@0: self.scrollbar:Show() Zerotorescue@0: self.scrollframe:SetPoint("BOTTOMRIGHT", -20, 0) Zerotorescue@0: self:DoLayout() Zerotorescue@0: end Zerotorescue@0: local value = (offset / (viewheight - height) * 1000) Zerotorescue@0: if value > 1000 then value = 1000 end Zerotorescue@0: self.scrollbar:SetValue(value) Zerotorescue@0: self:SetScroll(value) Zerotorescue@0: if value < 1000 then Zerotorescue@0: self.content:ClearAllPoints() Zerotorescue@0: self.content:SetPoint("TOPLEFT", 0, offset) Zerotorescue@0: self.content:SetPoint("TOPRIGHT", 0, offset) Zerotorescue@0: status.offset = offset Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: self.updateLock = nil Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["LayoutFinished"] = function(self, width, height) Zerotorescue@0: self.content:SetHeight(height or 0 + 20) Zerotorescue@0: self.scrollframe:SetScript("OnUpdate", FixScrollOnUpdate) Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["SetStatusTable"] = function(self, status) Zerotorescue@0: assert(type(status) == "table") Zerotorescue@0: self.status = status Zerotorescue@0: if not status.scrollvalue then Zerotorescue@0: status.scrollvalue = 0 Zerotorescue@0: end Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["OnWidthSet"] = function(self, width) Zerotorescue@0: local content = self.content Zerotorescue@0: content.width = width Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["OnHeightSet"] = function(self, height) Zerotorescue@0: local content = self.content Zerotorescue@0: content.height = height Zerotorescue@0: end Zerotorescue@0: } Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: Constructor Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local function Constructor() Zerotorescue@0: local frame = CreateFrame("Frame", nil, UIParent) Zerotorescue@0: local num = AceGUI:GetNextWidgetNum(Type) Zerotorescue@0: Zerotorescue@0: local scrollframe = CreateFrame("ScrollFrame", nil, frame) Zerotorescue@0: scrollframe:SetPoint("TOPLEFT") Zerotorescue@0: scrollframe:SetPoint("BOTTOMRIGHT") Zerotorescue@0: scrollframe:EnableMouseWheel(true) Zerotorescue@0: scrollframe:SetScript("OnMouseWheel", ScrollFrame_OnMouseWheel) Zerotorescue@0: scrollframe:SetScript("OnSizeChanged", ScrollFrame_OnSizeChanged) Zerotorescue@0: Zerotorescue@0: local scrollbar = CreateFrame("Slider", ("AceConfigDialogScrollFrame%dScrollBar"):format(num), scrollframe, "UIPanelScrollBarTemplate") Zerotorescue@0: scrollbar:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, -16) Zerotorescue@0: scrollbar:SetPoint("BOTTOMLEFT", scrollframe, "BOTTOMRIGHT", 4, 16) Zerotorescue@0: scrollbar:SetMinMaxValues(0, 1000) Zerotorescue@0: scrollbar:SetValueStep(1) Zerotorescue@0: scrollbar:SetValue(0) Zerotorescue@0: scrollbar:SetWidth(16) Zerotorescue@0: scrollbar:Hide() Zerotorescue@0: -- set the script as the last step, so it doesn't fire yet Zerotorescue@0: scrollbar:SetScript("OnValueChanged", ScrollBar_OnScrollValueChanged) Zerotorescue@0: Zerotorescue@0: local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND") Zerotorescue@0: scrollbg:SetAllPoints(scrollbar) Zerotorescue@0: scrollbg:SetTexture(0, 0, 0, 0.4) Zerotorescue@0: Zerotorescue@0: --Container Support Zerotorescue@0: local content = CreateFrame("Frame", nil, scrollframe) Zerotorescue@0: content:SetPoint("TOPLEFT") Zerotorescue@0: content:SetPoint("TOPRIGHT") Zerotorescue@0: content:SetHeight(400) Zerotorescue@0: scrollframe:SetScrollChild(content) Zerotorescue@0: Zerotorescue@0: local widget = { Zerotorescue@0: localstatus = { scrollvalue = 0 }, Zerotorescue@0: scrollframe = scrollframe, Zerotorescue@0: scrollbar = scrollbar, Zerotorescue@0: content = content, Zerotorescue@0: frame = frame, Zerotorescue@0: type = Type Zerotorescue@0: } Zerotorescue@0: for method, func in pairs(methods) do Zerotorescue@0: widget[method] = func Zerotorescue@0: end Zerotorescue@0: scrollframe.obj, scrollbar.obj = widget, widget Zerotorescue@0: Zerotorescue@0: return AceGUI:RegisterAsContainer(widget) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: AceGUI:RegisterWidgetType(Type, Constructor, Version)