annotate classes/Bar.lua @ 125:a7f18adee694

fixed bar overlay getting orphaned when deleting a bar
author Flick <flickerstreak@gmail.com>
date Tue, 03 Mar 2009 23:18:05 +0000
parents 943eed2c7def
children 729232aeeb5e
rev   line source
flickerstreak@122 1 local ReAction = ReAction
flickerstreak@122 2 local L = ReAction.L
flickerstreak@122 3 local _G = _G
flickerstreak@122 4 local CreateFrame = CreateFrame
flickerstreak@122 5 local floor = math.floor
flickerstreak@122 6 local fmod = math.fmod
flickerstreak@122 7 local format = string.format
flickerstreak@122 8
flickerstreak@122 9 ReAction:UpdateRevision("$Revision$")
flickerstreak@122 10
flickerstreak@122 11 local Bar = { }
flickerstreak@122 12 local proto = { __index = Bar }
flickerstreak@122 13 local weak = { __mode = "k" }
flickerstreak@122 14
flickerstreak@122 15 ReAction.Bar = Bar -- export to ReAction
flickerstreak@122 16
flickerstreak@122 17 function Bar:New( name, config )
flickerstreak@122 18 if type(config) ~= "table" then
flickerstreak@122 19 error("ReAction.Bar: config table required")
flickerstreak@122 20 end
flickerstreak@122 21
flickerstreak@122 22 -- create new self
flickerstreak@122 23 self = setmetatable(
flickerstreak@122 24 {
flickerstreak@122 25 config = config,
flickerstreak@122 26 name = name,
flickerstreak@122 27 buttons = setmetatable( { }, weak ),
flickerstreak@122 28 width = config.width or 480,
flickerstreak@122 29 height = config.height or 40
flickerstreak@122 30 },
flickerstreak@122 31 proto )
flickerstreak@122 32
flickerstreak@122 33 -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is
flickerstreak@122 34 -- not mouse-clickable by the user.
flickerstreak@122 35 local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent
flickerstreak@122 36 local f = CreateFrame("Button", name and format("ReAction-%s",name), parent,
flickerstreak@122 37 "SecureHandlerStateTemplate, SecureHandlerClickTemplate")
flickerstreak@122 38 f:SetFrameStrata("MEDIUM")
flickerstreak@122 39 f:SetWidth(self.width)
flickerstreak@122 40 f:SetWidth(self.height)
flickerstreak@122 41 f:SetAlpha(config.alpha or 1.0)
flickerstreak@122 42 f:Show()
flickerstreak@122 43 f:EnableMouse(false)
flickerstreak@122 44 f:SetClampedToScreen(true)
flickerstreak@122 45
flickerstreak@122 46 f:SetAttribute("_onstate-showgrid",
flickerstreak@122 47 -- function(self,stateid,newstate)
flickerstreak@122 48 [[
flickerstreak@122 49 control:ChildUpdate(stateid,newstate)
flickerstreak@122 50 control:CallMethod("UpdateShowGrid")
flickerstreak@122 51 ]])
flickerstreak@122 52 f.UpdateShowGrid = function(frame)
flickerstreak@122 53 for button in self:IterateButtons() do
flickerstreak@122 54 button:UpdateShowGrid()
flickerstreak@122 55 end
flickerstreak@122 56 end
flickerstreak@122 57 ReAction.gridProxy:AddFrame(f)
flickerstreak@122 58
flickerstreak@122 59 -- Override the default frame accessor to provide strict read-only access
flickerstreak@122 60 function self:GetFrame()
flickerstreak@122 61 return f
flickerstreak@122 62 end
flickerstreak@122 63
flickerstreak@122 64 self:ApplyAnchor()
flickerstreak@122 65 ReAction.RegisterCallback(self, "OnConfigModeChanged")
flickerstreak@122 66
flickerstreak@122 67 return self
flickerstreak@122 68 end
flickerstreak@122 69
flickerstreak@122 70 function Bar:Destroy()
flickerstreak@122 71 local f = self:GetFrame()
flickerstreak@122 72 f:UnregisterAllEvents()
flickerstreak@125 73 self:ShowControls(false)
flickerstreak@122 74 ReAction.UnregisterAllCallbacks(self)
flickerstreak@122 75 ReAction.gridProxy:RemoveFrame(f)
flickerstreak@122 76 f:Hide()
flickerstreak@122 77 f:SetParent(UIParent)
flickerstreak@122 78 f:ClearAllPoints()
flickerstreak@122 79 end
flickerstreak@122 80
flickerstreak@123 81 function Bar:GetConfig()
flickerstreak@123 82 return self.config
flickerstreak@123 83 end
flickerstreak@123 84
flickerstreak@122 85 function Bar:OnConfigModeChanged(event, mode)
flickerstreak@122 86 self:ShowControls(mode) -- Bar:ShowControls() defined in Overlay.lua
flickerstreak@122 87 end
flickerstreak@122 88
flickerstreak@122 89 function Bar:ApplyAnchor()
flickerstreak@122 90 local f = self:GetFrame()
flickerstreak@122 91 local c = self.config
flickerstreak@122 92 local p = c.point
flickerstreak@122 93
flickerstreak@122 94 f:SetWidth(c.width)
flickerstreak@122 95 f:SetHeight(c.height)
flickerstreak@122 96 f:ClearAllPoints()
flickerstreak@122 97
flickerstreak@122 98 if p then
flickerstreak@122 99 local a = f:GetParent()
flickerstreak@122 100 if c.anchor then
flickerstreak@122 101 local bar = ReAction:GetBar(c.anchor)
flickerstreak@122 102 if bar then
flickerstreak@122 103 a = bar:GetFrame()
flickerstreak@122 104 else
flickerstreak@122 105 a = _G[c.anchor]
flickerstreak@122 106 end
flickerstreak@122 107 end
flickerstreak@122 108 local fr = a or f:GetParent()
flickerstreak@122 109 f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0)
flickerstreak@122 110 else
flickerstreak@122 111 f:SetPoint("CENTER")
flickerstreak@122 112 end
flickerstreak@122 113 end
flickerstreak@122 114
flickerstreak@122 115 function Bar:SetAnchor(point, frame, relativePoint, x, y)
flickerstreak@122 116 local c = self.config
flickerstreak@122 117 c.point = point or c.point
flickerstreak@122 118 c.anchor = frame or c.anchor
flickerstreak@122 119 c.relpoint = relativePoint or c.relpoint
flickerstreak@122 120 c.x = x or c.x
flickerstreak@122 121 c.y = y or c.y
flickerstreak@122 122 self:ApplyAnchor()
flickerstreak@122 123 ReAction:RefreshBar(self)
flickerstreak@122 124 end
flickerstreak@122 125
flickerstreak@122 126 function Bar:GetAnchor()
flickerstreak@122 127 local c = self.config
flickerstreak@122 128 return (c.point or "CENTER"),
flickerstreak@122 129 (c.anchor or self:GetFrame():GetParent():GetName()),
flickerstreak@122 130 (c.relpoint or c.point or "CENTER"),
flickerstreak@122 131 (c.x or 0),
flickerstreak@122 132 (c.y or 0)
flickerstreak@122 133 end
flickerstreak@122 134
flickerstreak@122 135 function Bar:GetSize()
flickerstreak@122 136 local f = self:GetFrame()
flickerstreak@122 137 return f:GetWidth(), f:GetHeight()
flickerstreak@122 138 end
flickerstreak@122 139
flickerstreak@122 140 function Bar:SetSize(w,h)
flickerstreak@122 141 local f = self:GetFrame()
flickerstreak@122 142 self.config.width = w
flickerstreak@122 143 self.config.height = h
flickerstreak@122 144 f:SetWidth(w)
flickerstreak@122 145 f:SetHeight(h)
flickerstreak@122 146 end
flickerstreak@122 147
flickerstreak@122 148 function Bar:GetButtonSize()
flickerstreak@122 149 local w = self.config.btnWidth or 32
flickerstreak@122 150 local h = self.config.btnHeight or 32
flickerstreak@122 151 -- TODO: get from modules?
flickerstreak@122 152 return w,h
flickerstreak@122 153 end
flickerstreak@122 154
flickerstreak@122 155 function Bar:SetButtonSize(w,h)
flickerstreak@122 156 if w > 0 and h > 0 then
flickerstreak@122 157 self.config.btnWidth = w
flickerstreak@122 158 self.config.btnHeight = h
flickerstreak@122 159 end
flickerstreak@122 160 ReAction:RefreshBar(self)
flickerstreak@122 161 end
flickerstreak@122 162
flickerstreak@122 163 function Bar:GetButtonGrid()
flickerstreak@122 164 local cfg = self.config
flickerstreak@122 165 local r = cfg.btnRows or 1
flickerstreak@122 166 local c = cfg.btnColumns or 1
flickerstreak@122 167 local s = cfg.spacing or 4
flickerstreak@122 168 return r,c,s
flickerstreak@122 169 end
flickerstreak@122 170
flickerstreak@122 171 function Bar:GetNumButtons()
flickerstreak@122 172 local r,c = self:GetButtonGrid()
flickerstreak@122 173 return r*c
flickerstreak@122 174 end
flickerstreak@122 175
flickerstreak@122 176 function Bar:SetButtonGrid(r,c,s)
flickerstreak@122 177 if r > 0 and c > 0 and s > 0 then
flickerstreak@122 178 local cfg = self.config
flickerstreak@122 179 cfg.btnRows = r
flickerstreak@122 180 cfg.btnColumns = c
flickerstreak@122 181 cfg.spacing = s
flickerstreak@122 182 end
flickerstreak@122 183 ReAction:RefreshBar(self)
flickerstreak@122 184 end
flickerstreak@122 185
flickerstreak@122 186 function Bar:ClipNButtons( n )
flickerstreak@122 187 local cfg = self.config
flickerstreak@122 188 local r = cfg.btnRows or 1
flickerstreak@122 189 local c = cfg.btnColumns or 1
flickerstreak@122 190
flickerstreak@122 191 cfg.btnRows = ceil(n/c)
flickerstreak@122 192 cfg.btnColumns = min(n,c)
flickerstreak@122 193 end
flickerstreak@122 194
flickerstreak@122 195 function Bar:GetName()
flickerstreak@122 196 return self.name
flickerstreak@122 197 end
flickerstreak@122 198
flickerstreak@122 199 function Bar:GetFrame()
flickerstreak@122 200 -- this method is included for documentation purposes. It is overridden
flickerstreak@122 201 -- for each object in the :New() method.
flickerstreak@122 202 error("Invalid Bar object: used without initialization")
flickerstreak@122 203 end
flickerstreak@122 204
flickerstreak@122 205 -- only ReAction:RenameBar() should call this function. Calling from any other
flickerstreak@122 206 -- context will desync the bar list in the ReAction class.
flickerstreak@122 207 function Bar:SetName(name)
flickerstreak@122 208 self.name = name
flickerstreak@122 209 self:SetLabel(self.name) -- Bar:SetLabel() defined in Overlay.lua
flickerstreak@122 210 end
flickerstreak@122 211
flickerstreak@122 212 function Bar:GetAlpha()
flickerstreak@122 213 return self.config.alpha or 1.0
flickerstreak@122 214 end
flickerstreak@122 215
flickerstreak@122 216 function Bar:SetAlpha(value)
flickerstreak@122 217 self.config.alpha = value
flickerstreak@122 218 self:GetFrame():SetAlpha(value or 1.0)
flickerstreak@122 219 ReAction:RefreshBar(self)
flickerstreak@122 220 end
flickerstreak@122 221
flickerstreak@122 222 function Bar:AddButton(idx, button)
flickerstreak@122 223 local f = self:GetFrame()
flickerstreak@122 224
flickerstreak@122 225 -- store in a weak reverse-index array
flickerstreak@122 226 self.buttons[button] = idx
flickerstreak@122 227
flickerstreak@122 228 -- Store a properly wrapped reference to the child frame as an attribute
flickerstreak@122 229 -- (accessible via "frameref-btn#")
flickerstreak@122 230 f:SetFrameRef(format("btn%d",idx), button:GetFrame())
flickerstreak@122 231 end
flickerstreak@122 232
flickerstreak@122 233 function Bar:RemoveButton(button)
flickerstreak@122 234 local idx = self.buttons[button]
flickerstreak@122 235 if idx then
flickerstreak@122 236 self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil)
flickerstreak@122 237 self.buttons[button] = nil
flickerstreak@122 238 end
flickerstreak@122 239 end
flickerstreak@122 240
flickerstreak@122 241 -- iterator returns button, idx and does NOT iterate in index order
flickerstreak@122 242 function Bar:IterateButtons()
flickerstreak@122 243 return pairs(self.buttons)
flickerstreak@122 244 end
flickerstreak@122 245
flickerstreak@122 246 function Bar:PlaceButton(button, baseW, baseH)
flickerstreak@122 247 local idx = self.buttons[button]
flickerstreak@122 248 if idx then
flickerstreak@122 249 local r, c, s = self:GetButtonGrid()
flickerstreak@122 250 local bh, bw = self:GetButtonSize()
flickerstreak@122 251 local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based
flickerstreak@122 252 local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s)
flickerstreak@122 253 local scale = bw/baseW
flickerstreak@122 254 local b = button:GetFrame()
flickerstreak@122 255
flickerstreak@122 256 b:ClearAllPoints()
flickerstreak@122 257 b:SetPoint("TOPLEFT",x/scale,y/scale)
flickerstreak@122 258 b:SetScale(scale)
flickerstreak@122 259 end
flickerstreak@122 260 end
flickerstreak@122 261
flickerstreak@122 262 function Bar:SkinButton()
flickerstreak@122 263 -- does nothing by default
flickerstreak@122 264 end