Go to Page... |
Thread Tools | Display Modes |
04-10-09, 12:26 AM | #1 |
More VFL fixes
- Arrows on scroll bars now scroll one "page" at a time instead of a fixed amount.
- General fixes to VFLUI.List. Increased efficiency, no longer necessary to call Rebuild() when resizing the list, fixed an unfreed scrollbar. VFL\UI\FrameClasses\List.lua: Code:
-- List.lua -- VFL -- (C)2006 Bill Johnson -- -- A List is a frame that contains a number of subframes and (possibly) a scrollbar. VFLUI.List = {}; --- Create a new List. -- @param cellHeight The height of each cell in the list. -- @param fnAlloc The function called to allocate a new frame in the list. function VFLUI.List:new(parent, cellHeight, fnAlloc) local self = VFLUI.AcquireFrame("Frame"); if parent then self:SetParent(parent); self:SetFrameStrata(parent:GetFrameStrata()); self:SetFrameLevel(parent:GetFrameLevel()); end ------- INTERNAL PARAMETERS -- Dimensions local nCells, dy = 0, 0; -- Scrollbar local scrollbar = VFLUI.VScrollBar:new(self); local scrollEnabled = true; -- Apply data function local fnSize, fnData = VFL.EmptyLiterator(); local fnApplyData = VFL.Noop; ------- GRID CORE local grid = VFLUI.Grid:new(self); grid:SetPoint("TOPLEFT", self, "TOPLEFT"); grid:Show(); -- Anchor the scrollbar to the grid scrollbar:ClearAllPoints(); scrollbar:SetPoint("TOPLEFT", grid, "TOPRIGHT", 0, -16); scrollbar:SetPoint("BOTTOMRIGHT", grid, "BOTTOMRIGHT", 16, 16); ------- SCROLLING VIRTUALIZER local virt = VFLUI.VirtualGrid:new(grid); virt.GetVirtualSize = function() local q = fnSize() - nCells + 1; if(q < 1) then q = 1; end return 1,q; end virt.OnRenderCell = function(v, c, x, y, vx, vy) local pos = y + vy - 1; local qq = fnData(pos); if not qq then c:Hide() else c:Show(); fnApplyData(c, qq, pos, y); end end self.SetVerticalScroll = function(g, val) local oldv, newv = virt.vy, math.floor(val); if(oldv ~= newv) then virt:SetVirtualPosition(1, newv); end end ------- SCROLLBAR HANDLER local CreateScrollBar = function() -- Don't create if we already have one if scrollbar:IsShown() then return; end -- Resize the grid to accomodate the new scrollbar grid:SetCellDimensions(self:GetWidth() - 16, cellHeight); scrollbar:Show(); end local DestroyScrollBar = function() if not scrollbar:IsShown() then return; end grid:SetCellDimensions(self:GetWidth(), cellHeight); scrollbar:Hide(); end --- Enable/disable the scroll bar for this grid function self:SetScrollBarEnabled(val) if val then scrollEnabled = true; else scrollEnabled = nil; end end --- Get the underlying grid. function self:_GetGrid() return grid; end --- Rebuild the list control. This should be used when the size of the container frame changes. function self:Rebuild() grid:SetCellDimensions(self:GetWidth(), cellHeight); local oldnCells = nCells; nCells = math.floor(self:GetHeight() / cellHeight); if(nCells < 0) then nCells = 0; end if(oldnCells ~= nCells) then grid:Clear(); grid:Size(1, nCells, fnAlloc); self:Update(); end end --- Get the cell height provided at list creation. function self:GetCellHeight() return cellHeight; end --- Set the underlying data source for this list. The data source must be a _linear iterator_ -- which consists of a pair of functions; one to retrieve the size of the underlying list and -- one which takes a numerical parameter and returns the data at that index, or NIL for none. function self:SetDataSource(fnad, liSz, liData) fnSize = liSz; fnData = liData; fnApplyData = fnad; self:Update(); end --- Set this list to empty. function self:SetEmpty() self:SetDataSource(VFL.EmptyLiterator(), VFL.Noop); end --- Update the list in response to an update of the data table. function self:Update() local _,dy = virt:GetVirtualSize(); -- Get the pagesize for the scroll bar if(dy > 1) and scrollEnabled then CreateScrollBar(); scrollbar:SetMinMaxValues(1, dy); scrollbar:SetPageSize(nCells); else DestroyScrollBar(); end virt:SetVirtualPosition(1, virt.vy); if scrollbar:IsShown() then scrollbar:SetValue(virt.vy); VFLUI.ScrollBarRangeCheck(scrollbar); end end --- Change the scroll value of the list. If the second parameter is given, the scrollbar -- will be pinned to the maximum value. function self:SetScroll(n, max) -- Update the virtual position of the list if max then virt:SetVirtualPosition(virt:GetVirtualSize()); else virt:SetVirtualPosition(1, n); end -- Paint the scrollbar if scrollbar:IsShown() then scrollbar:SetValue(virt.vy); VFLUI.ScrollBarRangeCheck(scrollbar); end end -- Enable mousewheel scrolling self:EnableMouseWheel(true) self:SetScript("OnMouseWheel", function(thisframe, delta) local newpos, _, maxpos = virt.vy - delta, virt:GetVirtualSize(); if(newpos < 1) then newpos = 1; elseif (newpos > maxpos) then newpos = maxpos; end self:SetScroll(newpos); end) -- Auto-rebuild on size changed if necessary self:SetScript("OnSizeChanged", self.Rebuild); -- Destroy handler. self.Destroy = VFL.hook(function(s) s.SetVerticalScroll = nil; scrollbar:Destroy(); scrollbar = nil; virt:Destroy(); self.Rebuild = nil; self.GetCellHeight = nil; self.SetDataSource = nil; self.SetEmpty = nil; self.Update = nil; self.SetScroll = nil; self.SetScrollBarEnabled = nil; self._GetGrid = nil; self:EnableMouseWheel(false); self:SetScript("OnMouseWheel", nil); end, self.Destroy); return self; end Code:
-- Scroll.lua -- VFL -- (C)2006 Bill Johnson -- -- Generators for horizontal and vertical scrollbars, and other scrolling- -- related frametypes. -- Internal: Create a scroll button with the given textures. local function CreateScrollButton(nrm, psh, dis, hlt) local self = VFLUI.AcquireFrame("Button"); -- Size is 16x16 self:SetWidth(16); self:SetHeight(16); -- Button textures self:SetNormalTexture(nrm); self:SetPushedTexture(psh); self:SetDisabledTexture(dis); -- Highlight texture requires special handling (for blend mode) local hltTex = VFLUI.CreateTexture(self); hltTex:SetAllPoints(self); hltTex:Show(); hltTex:SetTexture(hlt); hltTex:SetBlendMode("ADD"); self:SetHighlightTexture(hltTex); self.hltTex = hltTex; self.Destroy = VFL.hook(function(s) VFLUI.ReleaseRegion(s.hltTex); s.hltTex = nil; end, self.Destroy); return self; end --- Check the value of a scroll bar, and grey out the scroll buttons -- as appropriate. function VFLUI.ScrollBarRangeCheck(sb) local min,max = sb:GetMinMaxValues(); local val = sb:GetValue(); if(VFL.close(val,min)) then sb.btnDecrease:Disable(); else sb.btnDecrease:Enable(); end if(VFL.close(val, max)) then sb.btnIncrease:Disable(); else sb.btnIncrease:Enable(); end end --- Create a button with the VFL "Scroll up" skin. function VFLUI.CreateScrollUpButton() return CreateScrollButton("Interface\\Addons\\VFL\\Skin\\sb_up", "Interface\\Addons\\VFL\\Skin\\sb_up_pressed", "Interface\\Addons\\VFL\\Skin\\sb_up_disabled", "Interface\\Addons\\VFL\\Skin\\sb_up_hlt"); end --- Create a button with the VFL "Scroll down" skin. function VFLUI.CreateScrollDownButton() return CreateScrollButton("Interface\\Addons\\VFL\\Skin\\sb_down", "Interface\\Addons\\VFL\\Skin\\sb_down_pressed", "Interface\\Addons\\VFL\\Skin\\sb_down_disabled", "Interface\\Addons\\VFL\\Skin\\sb_down_hlt"); end --- Create a button with the "Scroll right" skin function VFLUI.CreateScrollRightButton() return CreateScrollButton("Interface\\Addons\\VFL\\Skin\\sb_right", "Interface\\Addons\\VFL\\Skin\\sb_right_pressed", "Interface\\Addons\\VFL\\Skin\\sb_right_disabled", "Interface\\Addons\\VFL\\Skin\\sb_right_hlt"); end --- Create a button with the "Scroll left" skin function VFLUI.CreateScrollLeftButton() return CreateScrollButton("Interface\\Addons\\VFL\\Skin\\sb_left", "Interface\\Addons\\VFL\\Skin\\sb_left_pressed", "Interface\\Addons\\VFL\\Skin\\sb_left_disabled", "Interface\\Addons\\VFL\\Skin\\sb_left_hlt"); end local vsb_backdrop = { bgFile="Interface\\Addons\\VFL\\Skin\\sb_vgutter"; insets = { left = 0; right = 0; top = 0; bottom = 0; }; tile = true; tileSize = 16; }; VFLUI.VScrollBar = {}; --- Create a new vertical scrollbar. function VFLUI.VScrollBar:new(parent) local self = VFLUI.AcquireFrame("Slider"); self:SetWidth(16); self:SetHeight(0); if parent then self:SetParent(parent); self:SetFrameStrata(parent:GetFrameStrata()); self:SetFrameLevel(parent:GetFrameLevel() + 1); end -- Gutter texture local gutter = VFLUI.CreateTexture(self); gutter:SetAllPoints(self); gutter:SetTexture("Interface\\Addons\\VFL\\Skin\\sb_vgutter"); gutter:Show(); -- Thumb texture local sbThumb = self:CreateTexture(); sbThumb:SetWidth(16); sbThumb:SetHeight(16); sbThumb:Show(); sbThumb:SetTexture("Interface\\Addons\\VFL\\Skin\\sb_nub"); self:SetThumbTexture(sbThumb); -- Create the up/down buttons local btn = VFLUI.CreateScrollUpButton(); btn:SetParent(self); btn:SetFrameLevel(self:GetFrameLevel()); btn:Show(); btn:SetPoint("BOTTOM", self, "TOP"); btn:SetScript("OnClick", function(x) local sb = x:GetParent(); sb:SetValue(sb:GetValue() - sb:GetPageSize()); PlaySound("UChatScrollButton"); end); self.btnDecrease = btn; btn = VFLUI.CreateScrollDownButton(); btn:SetParent(self); btn:SetFrameLevel(self:GetFrameLevel()); btn:Show(); btn:SetPoint("TOP", self, "BOTTOM"); btn:SetScript("OnClick", function(x) local sb = x:GetParent(); sb:SetValue(sb:GetValue() + sb:GetPageSize()); PlaySound("UChatScrollButton"); end); self.btnIncrease = btn; -- Create the onscroll script self:SetScript("OnValueChanged", function(x, val) VFLUI.ScrollBarRangeCheck(x); local p = x:GetParent(); if p and p.SetVerticalScroll then p:SetVerticalScroll(val); end end); -- Page size handling local pageSize = nil; function self:SetPageSize(n) pageSize = tonumber(n); end function self:GetPageSize() if pageSize then return pageSize; end local min,max = self:GetMinMaxValues(); return (max-min)/5; end -- Hook the destroy handler self.Destroy = VFL.hook(function(self) self.SetPageSize = nil; self.GetPageSize = nil; self.btnDecrease:Destroy(); self.btnDecrease = nil; self.btnIncrease:Destroy(); self.btnIncrease = nil; gutter:Destroy(); gutter = nil; end, self.Destroy); -- Done return self; end --------------------------------------- -- @class VFLUI.VScrollFrame -- A class similar to a Blizzard ScrollFrame, preloaded with VFL-themed -- scrollbars and appropriate scripts. --------------------------------------- VFLUI.VScrollFrame = {}; function VFLUI.VScrollFrame:new(parent) local self = VFLUI.AcquireFrame("ScrollFrame"); self.offset = 0; self.scrollBarHideable = true; if parent then self:SetParent(parent); self:SetFrameStrata(parent:GetFrameStrata()); self:SetFrameLevel(parent:GetFrameLevel() + 1); end local sb = VFLUI.VScrollBar:new(self); sb:SetPoint("TOPLEFT", self, "TOPRIGHT", 0, -16); sb:SetPoint("BOTTOMLEFT", self, "BOTTOMRIGHT", 0, 16); sb.btnIncrease:Disable(); sb.btnDecrease:Disable(); sb:Show(); local function OnScrollRangeChanged() scrollrange = self:GetVerticalScrollRange(); sb:SetMinMaxValues(0, scrollrange); sb:SetPageSize(self:GetHeight()); local value = sb:GetValue(); if ( value > scrollrange ) then value = scrollrange; end sb:SetValue(value); if ( math.floor(scrollrange) == 0 ) then if (this.scrollBarHideable ) then sb:Hide(); else sb:Show(); sb.btnIncrease:Disable(); sb.btnIncrease:Show(); sb.btnDecrease:Disable(); sb.btnDecrease:Show(); end else sb:Show(); sb.btnDecrease:Show(); sb.btnIncrease:Show(); sb.btnIncrease:Enable(); end end self:SetScript("OnScrollRangeChanged", OnScrollRangeChanged); --- Scroll child management. local BlizzSetScrollChild = self.SetScrollChild; self.SetScrollChild = function(s, sc) -- If we had an old scroll child, be sure to undo any changes we made to it. if s._scrollChild then s._scrollChild:SetScript("OnSizeChanged", s._oldChildOnSizeChanged); s._oldChildOnSizeChanged = nil; end -- Point to the new scroll child s._scrollChild = sc; BlizzSetScrollChild(s, sc); -- If the new scroll child is extant... if sc then -- Apply a new SizeChanged script. local osc = sc:GetScript("OnSizeChanged"); s._oldChildOnSizeChanged = osc; if not osc then osc = VFL.Noop; end sc:SetScript("OnSizeChanged", function(th, w, h) osc(th, w, h); s:UpdateScrollChildRect(); OnScrollRangeChanged(); end); end end -- Enable mousewheel scrolling self:EnableMouseWheel(true) self:SetScript("OnMouseWheel", function(thisframe, delta) local curpos, minpos, maxpos = sb:GetValue(), sb:GetMinMaxValues(); -- Move a fifth of a page local mv = self:GetHeight() / 5; curpos = curpos - (delta*mv); if(curpos < minpos) then curpos = minpos; elseif (curpos > maxpos) then curpos = maxpos; end sb:SetValue(curpos); end) self:SetScript("OnVerticalScroll", function() sb:SetValue(arg1); VFLUI.ScrollBarRangeCheck(sb); end); self.Destroy = VFL.hook(function(s) s:SetScrollChild(nil); s.SetScrollChild = nil; -- Deallocate extant scroll children. s.offset = nil; s.scrollBarHideable = nil; s._oldChildOnSizeChanged = nil; sb:Destroy(); end, self.Destroy); return self; end --------------------------------------------------- -- @class VFLUI.HScrollBar -- A horizontal slider. --------------------------------------------------- local hsb_backdrop = { bgFile="Interface\\Addons\\VFL\\Skin\\sb_hgutter"; insets = { left = 0; right = 0; top = 0; bottom = 0; }; tile = true; tileSize = 16; }; VFLUI.HScrollBar = {}; function VFLUI.HScrollBar:new(parent, noButtons) local self = VFLUI.AcquireFrame("Slider"); self:SetHeight(16); self:SetWidth(0); self:SetOrientation("HORIZONTAL"); if parent then self:SetParent(parent); self:SetFrameStrata(parent:GetFrameStrata()); self:SetFrameLevel(parent:GetFrameLevel()); end -- Gutter texture self:SetBackdrop(hsb_backdrop); -- Thumb texture local sbThumb = self:CreateTexture(); sbThumb:SetWidth(16); sbThumb:SetHeight(16); sbThumb:Show(); sbThumb:SetTexture("Interface\\Addons\\VFL\\Skin\\sb_nub"); self:SetThumbTexture(sbThumb); if not noButtons then -- Create the up/down buttons local btn = VFLUI.CreateScrollLeftButton(); btn:SetParent(self); btn:Show(); btn:SetPoint("RIGHT", self, "LEFT"); btn:SetScript("OnClick", function() local sb = this:GetParent(); local min,max = sb:GetMinMaxValues(); sb:SetValue(sb:GetValue() - ((max-min) / 5)); PlaySound("UChatScrollButton"); end); self.btnDecrease = btn; btn = VFLUI.CreateScrollRightButton(); btn:SetParent(self); btn:Show(); btn:SetPoint("LEFT", self, "RIGHT"); btn:SetScript("OnClick", function() local sb = this:GetParent(); local min,max = sb:GetMinMaxValues(); sb:SetValue(sb:GetValue() + ((max-min) / 5)); PlaySound("UChatScrollButton"); end); self.btnIncrease = btn; end -- Create the onscroll script self:SetScript("OnValueChanged", function() VFLUI.ScrollBarRangeCheck(this); local p = this:GetParent(); if p and p.SetHorizontalScroll then p:SetHorizontalScroll(arg1); end end); -- Hook the destroy handler self.Destroy = VFL.hook(function(s) if s.btnDecrease then s.btnDecrease:Destroy(); s.btnDecrease = nil; end if s.btnIncrease then s.btnIncrease:Destroy(); s.btnIncrease = nil; end end, self.Destroy); -- Done return self; end ------------------------------------------------------------------------ -- Bind a slider to an edit box. ------------------------------------------------------------------------ function VFLUI.BindSliderToEdit(slider, edit) local _recurse_prevent = false; local old_ovc = slider:GetScript("OnValueChanged"); slider:SetScript("OnValueChanged", function() if not _recurse_prevent then _recurse_prevent = true; edit:SetText(string.format("%0.2f", arg1)); _recurse_prevent = false; end if old_ovc then old_ovc(); end end); local old_otc = edit:GetScript("OnTextChanged"); edit:SetScript("OnTextChanged", function() if not _recurse_prevent then _recurse_prevent = true; local n = this:GetNumber(); VFL.clamp(n, slider:GetMinMaxValues()); slider:SetValue(n); _recurse_prevent = false; end if old_otc then old_otc(); end end); edit:SetText(string.format("%0.2f", slider:GetValue())); end |
|
04-10-09, 01:24 AM | #2 |
add to the svn
|
|
WoWInterface » Featured Projects » OpenRDX » OpenRDX Community » OpenRDX: Community Chat » More VFL fixes |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|