Mercurial > wow > reaction
view classes/Bar.lua @ 123:943eed2c7def
Fixes for new ActionButton implementation
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Mon, 23 Feb 2009 19:41:11 +0000 |
parents | a2d2f23137c8 |
children | a7f18adee694 |
line wrap: on
line source
local ReAction = ReAction local L = ReAction.L local _G = _G local CreateFrame = CreateFrame local floor = math.floor local fmod = math.fmod local format = string.format ReAction:UpdateRevision("$Revision$") local Bar = { } local proto = { __index = Bar } local weak = { __mode = "k" } ReAction.Bar = Bar -- export to ReAction function Bar:New( name, config ) if type(config) ~= "table" then error("ReAction.Bar: config table required") end -- create new self self = setmetatable( { config = config, name = name, buttons = setmetatable( { }, weak ), width = config.width or 480, height = config.height or 40 }, proto ) -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is -- not mouse-clickable by the user. local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent local f = CreateFrame("Button", name and format("ReAction-%s",name), parent, "SecureHandlerStateTemplate, SecureHandlerClickTemplate") f:SetFrameStrata("MEDIUM") f:SetWidth(self.width) f:SetWidth(self.height) f:SetAlpha(config.alpha or 1.0) f:Show() f:EnableMouse(false) f:SetClampedToScreen(true) f:SetAttribute("_onstate-showgrid", -- function(self,stateid,newstate) [[ control:ChildUpdate(stateid,newstate) control:CallMethod("UpdateShowGrid") ]]) f.UpdateShowGrid = function(frame) for button in self:IterateButtons() do button:UpdateShowGrid() end end ReAction.gridProxy:AddFrame(f) -- Override the default frame accessor to provide strict read-only access function self:GetFrame() return f end self:ApplyAnchor() ReAction.RegisterCallback(self, "OnConfigModeChanged") return self end function Bar:Destroy() local f = self:GetFrame() f:UnregisterAllEvents() ReAction.UnregisterAllCallbacks(self) ReAction.gridProxy:RemoveFrame(f) f:Hide() f:SetParent(UIParent) f:ClearAllPoints() end function Bar:GetConfig() return self.config end function Bar:OnConfigModeChanged(event, mode) self:ShowControls(mode) -- Bar:ShowControls() defined in Overlay.lua end function Bar:ApplyAnchor() local f = self:GetFrame() local c = self.config local p = c.point f:SetWidth(c.width) f:SetHeight(c.height) f:ClearAllPoints() if p then local a = f:GetParent() if c.anchor then local bar = ReAction:GetBar(c.anchor) if bar then a = bar:GetFrame() else a = _G[c.anchor] end end local fr = a or f:GetParent() f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0) else f:SetPoint("CENTER") end end function Bar:SetAnchor(point, frame, relativePoint, x, y) local c = self.config c.point = point or c.point c.anchor = frame or c.anchor c.relpoint = relativePoint or c.relpoint c.x = x or c.x c.y = y or c.y self:ApplyAnchor() ReAction:RefreshBar(self) end function Bar:GetAnchor() local c = self.config return (c.point or "CENTER"), (c.anchor or self:GetFrame():GetParent():GetName()), (c.relpoint or c.point or "CENTER"), (c.x or 0), (c.y or 0) end function Bar:GetSize() local f = self:GetFrame() return f:GetWidth(), f:GetHeight() end function Bar:SetSize(w,h) local f = self:GetFrame() self.config.width = w self.config.height = h f:SetWidth(w) f:SetHeight(h) end function Bar:GetButtonSize() local w = self.config.btnWidth or 32 local h = self.config.btnHeight or 32 -- TODO: get from modules? return w,h end function Bar:SetButtonSize(w,h) if w > 0 and h > 0 then self.config.btnWidth = w self.config.btnHeight = h end ReAction:RefreshBar(self) end function Bar:GetButtonGrid() local cfg = self.config local r = cfg.btnRows or 1 local c = cfg.btnColumns or 1 local s = cfg.spacing or 4 return r,c,s end function Bar:GetNumButtons() local r,c = self:GetButtonGrid() return r*c end function Bar:SetButtonGrid(r,c,s) if r > 0 and c > 0 and s > 0 then local cfg = self.config cfg.btnRows = r cfg.btnColumns = c cfg.spacing = s end ReAction:RefreshBar(self) end function Bar:ClipNButtons( n ) local cfg = self.config local r = cfg.btnRows or 1 local c = cfg.btnColumns or 1 cfg.btnRows = ceil(n/c) cfg.btnColumns = min(n,c) end function Bar:GetName() return self.name end function Bar:GetFrame() -- this method is included for documentation purposes. It is overridden -- for each object in the :New() method. error("Invalid Bar object: used without initialization") end -- only ReAction:RenameBar() should call this function. Calling from any other -- context will desync the bar list in the ReAction class. function Bar:SetName(name) self.name = name self:SetLabel(self.name) -- Bar:SetLabel() defined in Overlay.lua end function Bar:GetAlpha() return self.config.alpha or 1.0 end function Bar:SetAlpha(value) self.config.alpha = value self:GetFrame():SetAlpha(value or 1.0) ReAction:RefreshBar(self) end function Bar:AddButton(idx, button) local f = self:GetFrame() -- store in a weak reverse-index array self.buttons[button] = idx -- Store a properly wrapped reference to the child frame as an attribute -- (accessible via "frameref-btn#") f:SetFrameRef(format("btn%d",idx), button:GetFrame()) end function Bar:RemoveButton(button) local idx = self.buttons[button] if idx then self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil) self.buttons[button] = nil end end -- iterator returns button, idx and does NOT iterate in index order function Bar:IterateButtons() return pairs(self.buttons) end function Bar:PlaceButton(button, baseW, baseH) local idx = self.buttons[button] if idx then local r, c, s = self:GetButtonGrid() local bh, bw = self:GetButtonSize() local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s) local scale = bw/baseW local b = button:GetFrame() b:ClearAllPoints() b:SetPoint("TOPLEFT",x/scale,y/scale) b:SetScale(scale) end end function Bar:SkinButton() -- does nothing by default end