annotate classes/Bar.lua @ 154:df67685b340e

Fixed some bar/overlay encapsulation
author Flick <flickerstreak@gmail.com>
date Fri, 08 May 2009 17:30:22 +0000
parents d5e11e924053
children 806a61b331a0
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@147 11 local KB = LibStub("LibKeyBound-1.0")
flickerstreak@147 12
flickerstreak@147 13 ---- Bar class ----
flickerstreak@122 14 local Bar = { }
flickerstreak@122 15 local weak = { __mode = "k" }
flickerstreak@147 16 local frameList = { }
flickerstreak@122 17
flickerstreak@122 18 ReAction.Bar = Bar -- export to ReAction
flickerstreak@122 19
flickerstreak@122 20 function Bar:New( name, config )
flickerstreak@122 21 if type(config) ~= "table" then
flickerstreak@122 22 error("ReAction.Bar: config table required")
flickerstreak@122 23 end
flickerstreak@122 24
flickerstreak@122 25 -- create new self
flickerstreak@122 26 self = setmetatable(
flickerstreak@122 27 {
flickerstreak@122 28 config = config,
flickerstreak@122 29 name = name,
flickerstreak@122 30 buttons = setmetatable( { }, weak ),
flickerstreak@122 31 width = config.width or 480,
flickerstreak@147 32 height = config.height or 40,
flickerstreak@122 33 },
flickerstreak@147 34 {__index = self} )
flickerstreak@122 35
flickerstreak@122 36 -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is
flickerstreak@122 37 -- not mouse-clickable by the user.
flickerstreak@122 38 local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent
flickerstreak@147 39 name = name and "ReAction-"..name
flickerstreak@147 40 local f = name and frameList[name]
flickerstreak@147 41 if not f then
flickerstreak@147 42 f = CreateFrame("Button", name, parent, "SecureHandlerStateTemplate, SecureHandlerClickTemplate")
flickerstreak@147 43 if name then
flickerstreak@147 44 frameList[name] = f
flickerstreak@147 45 end
flickerstreak@147 46 end
flickerstreak@122 47 f:SetFrameStrata("MEDIUM")
flickerstreak@122 48 f:SetWidth(self.width)
flickerstreak@146 49 f:SetHeight(self.height)
flickerstreak@122 50 f:SetAlpha(config.alpha or 1.0)
flickerstreak@122 51 f:Show()
flickerstreak@122 52 f:EnableMouse(false)
flickerstreak@122 53 f:SetClampedToScreen(true)
flickerstreak@122 54
flickerstreak@122 55 f:SetAttribute("_onstate-showgrid",
flickerstreak@122 56 -- function(self,stateid,newstate)
flickerstreak@122 57 [[
flickerstreak@122 58 control:ChildUpdate(stateid,newstate)
flickerstreak@122 59 control:CallMethod("UpdateShowGrid")
flickerstreak@122 60 ]])
flickerstreak@122 61 f.UpdateShowGrid = function(frame)
flickerstreak@122 62 for button in self:IterateButtons() do
flickerstreak@122 63 button:UpdateShowGrid()
flickerstreak@122 64 end
flickerstreak@122 65 end
flickerstreak@122 66 ReAction.gridProxy:AddFrame(f)
flickerstreak@122 67
flickerstreak@122 68 -- Override the default frame accessor to provide strict read-only access
flickerstreak@122 69 function self:GetFrame()
flickerstreak@122 70 return f
flickerstreak@122 71 end
flickerstreak@122 72
flickerstreak@122 73 self:ApplyAnchor()
flickerstreak@147 74 self:SetConfigMode(ReAction:GetConfigMode())
flickerstreak@147 75 self:SetKeybindMode(ReAction:GetKeybindMode())
flickerstreak@147 76
flickerstreak@122 77 ReAction.RegisterCallback(self, "OnConfigModeChanged")
flickerstreak@147 78 KB.RegisterCallback(self, "LIBKEYBOUND_ENABLED")
flickerstreak@147 79 KB.RegisterCallback(self, "LIBKEYBOUND_DISABLED")
flickerstreak@147 80 KB.RegisterCallback(self, "LIBKEYBOUND_MODE_COLOR_CHANGED","LIBKEYBOUND_ENABLED")
flickerstreak@122 81
flickerstreak@122 82 return self
flickerstreak@122 83 end
flickerstreak@122 84
flickerstreak@122 85 function Bar:Destroy()
flickerstreak@122 86 local f = self:GetFrame()
flickerstreak@122 87 f:UnregisterAllEvents()
flickerstreak@125 88 self:ShowControls(false)
flickerstreak@122 89 ReAction.UnregisterAllCallbacks(self)
flickerstreak@147 90 KB.UnregisterAllCallbacks(self)
flickerstreak@122 91 ReAction.gridProxy:RemoveFrame(f)
flickerstreak@122 92 f:SetParent(UIParent)
flickerstreak@122 93 f:ClearAllPoints()
flickerstreak@147 94 f:Hide()
flickerstreak@122 95 end
flickerstreak@122 96
flickerstreak@147 97 --
flickerstreak@147 98 -- Events
flickerstreak@147 99 --
flickerstreak@147 100
flickerstreak@147 101 function Bar:OnConfigModeChanged(event, mode)
flickerstreak@147 102 self:SetConfigMode(mode)
flickerstreak@123 103 end
flickerstreak@123 104
flickerstreak@147 105 function Bar:LIBKEYBOUND_ENABLED(evt)
flickerstreak@147 106 self:SetKeybindMode(true)
flickerstreak@147 107 end
flickerstreak@147 108
flickerstreak@147 109 function Bar:LIBKEYBOUND_DISABLED(evt)
flickerstreak@147 110 self:SetKeybindMode(false)
flickerstreak@122 111 end
flickerstreak@122 112
flickerstreak@153 113 --
flickerstreak@153 114 -- Accessors
flickerstreak@153 115 --
flickerstreak@153 116
flickerstreak@153 117 function Bar:GetName()
flickerstreak@153 118 return self.name
flickerstreak@153 119 end
flickerstreak@153 120
flickerstreak@153 121 -- only ReAction:RenameBar() should call this function. Calling from any other
flickerstreak@153 122 -- context will desync the bar list in the ReAction class.
flickerstreak@153 123 function Bar:SetName(name)
flickerstreak@153 124 self.name = name
flickerstreak@154 125 if self.overlay then
flickerstreak@154 126 self.overlay:SetLabel(self.name)
flickerstreak@154 127 end
flickerstreak@153 128 end
flickerstreak@153 129
flickerstreak@153 130 function Bar:GetFrame()
flickerstreak@153 131 -- this method is included for documentation purposes. It is overridden
flickerstreak@153 132 -- for each object in the :New() method.
flickerstreak@153 133 error("Invalid Bar object: used without initialization")
flickerstreak@153 134 end
flickerstreak@153 135
flickerstreak@153 136 function Bar:GetConfig()
flickerstreak@153 137 return self.config
flickerstreak@153 138 end
flickerstreak@153 139
flickerstreak@153 140 function Bar:GetAnchor()
flickerstreak@122 141 local c = self.config
flickerstreak@153 142 return (c.point or "CENTER"),
flickerstreak@153 143 (c.anchor or self:GetFrame():GetParent():GetName()),
flickerstreak@153 144 (c.relpoint or c.point or "CENTER"),
flickerstreak@153 145 (c.x or 0),
flickerstreak@153 146 (c.y or 0)
flickerstreak@122 147 end
flickerstreak@122 148
flickerstreak@122 149 function Bar:SetAnchor(point, frame, relativePoint, x, y)
flickerstreak@122 150 local c = self.config
flickerstreak@122 151 c.point = point or c.point
flickerstreak@122 152 c.anchor = frame or c.anchor
flickerstreak@122 153 c.relpoint = relativePoint or c.relpoint
flickerstreak@122 154 c.x = x or c.x
flickerstreak@122 155 c.y = y or c.y
flickerstreak@122 156 self:ApplyAnchor()
flickerstreak@122 157 ReAction:RefreshBar(self)
flickerstreak@122 158 end
flickerstreak@122 159
flickerstreak@122 160 function Bar:GetSize()
flickerstreak@122 161 local f = self:GetFrame()
flickerstreak@122 162 return f:GetWidth(), f:GetHeight()
flickerstreak@122 163 end
flickerstreak@122 164
flickerstreak@122 165 function Bar:SetSize(w,h)
flickerstreak@122 166 local f = self:GetFrame()
flickerstreak@122 167 self.config.width = w
flickerstreak@122 168 self.config.height = h
flickerstreak@122 169 f:SetWidth(w)
flickerstreak@122 170 f:SetHeight(h)
flickerstreak@122 171 end
flickerstreak@122 172
flickerstreak@122 173 function Bar:GetButtonSize()
flickerstreak@122 174 local w = self.config.btnWidth or 32
flickerstreak@122 175 local h = self.config.btnHeight or 32
flickerstreak@122 176 -- TODO: get from modules?
flickerstreak@122 177 return w,h
flickerstreak@122 178 end
flickerstreak@122 179
flickerstreak@122 180 function Bar:SetButtonSize(w,h)
flickerstreak@122 181 if w > 0 and h > 0 then
flickerstreak@122 182 self.config.btnWidth = w
flickerstreak@122 183 self.config.btnHeight = h
flickerstreak@122 184 end
flickerstreak@122 185 ReAction:RefreshBar(self)
flickerstreak@122 186 end
flickerstreak@122 187
flickerstreak@153 188 function Bar:GetNumButtons()
flickerstreak@153 189 local r,c = self:GetButtonGrid()
flickerstreak@153 190 return r*c
flickerstreak@153 191 end
flickerstreak@153 192
flickerstreak@122 193 function Bar:GetButtonGrid()
flickerstreak@122 194 local cfg = self.config
flickerstreak@122 195 local r = cfg.btnRows or 1
flickerstreak@122 196 local c = cfg.btnColumns or 1
flickerstreak@122 197 local s = cfg.spacing or 4
flickerstreak@122 198 return r,c,s
flickerstreak@122 199 end
flickerstreak@122 200
flickerstreak@122 201 function Bar:SetButtonGrid(r,c,s)
flickerstreak@122 202 if r > 0 and c > 0 and s > 0 then
flickerstreak@122 203 local cfg = self.config
flickerstreak@122 204 cfg.btnRows = r
flickerstreak@122 205 cfg.btnColumns = c
flickerstreak@122 206 cfg.spacing = s
flickerstreak@122 207 end
flickerstreak@122 208 ReAction:RefreshBar(self)
flickerstreak@122 209 end
flickerstreak@122 210
flickerstreak@122 211 function Bar:GetAlpha()
flickerstreak@122 212 return self.config.alpha or 1.0
flickerstreak@122 213 end
flickerstreak@122 214
flickerstreak@122 215 function Bar:SetAlpha(value)
flickerstreak@122 216 self.config.alpha = value
flickerstreak@122 217 self:GetFrame():SetAlpha(value or 1.0)
flickerstreak@122 218 ReAction:RefreshBar(self)
flickerstreak@122 219 end
flickerstreak@122 220
flickerstreak@122 221 -- iterator returns button, idx and does NOT iterate in index order
flickerstreak@122 222 function Bar:IterateButtons()
flickerstreak@122 223 return pairs(self.buttons)
flickerstreak@122 224 end
flickerstreak@122 225
flickerstreak@153 226 --
flickerstreak@153 227 -- Methods
flickerstreak@153 228 --
flickerstreak@153 229
flickerstreak@147 230 function Bar:SetConfigMode(mode)
flickerstreak@147 231 self:ShowControls(mode)
flickerstreak@148 232 if self.unitwatch then
flickerstreak@148 233 if mode then
flickerstreak@148 234 UnregisterUnitWatch(self:GetFrame())
flickerstreak@148 235 self:GetFrame():Show()
flickerstreak@148 236 else
flickerstreak@148 237 RegisterUnitWatch(self:GetFrame())
flickerstreak@148 238 end
flickerstreak@148 239 end
flickerstreak@147 240 for b in self:IterateButtons() do
flickerstreak@147 241 b:ShowGridTemp(mode)
flickerstreak@147 242 b:UpdateActionIDLabel(mode)
flickerstreak@147 243 end
flickerstreak@147 244 end
flickerstreak@147 245
flickerstreak@147 246 function Bar:SetKeybindMode(mode)
flickerstreak@148 247 if self.unitwatch then
flickerstreak@148 248 if mode then
flickerstreak@148 249 UnregisterUnitWatch(self:GetFrame())
flickerstreak@148 250 self:GetFrame():Show()
flickerstreak@148 251 else
flickerstreak@148 252 RegisterUnitWatch(self:GetFrame())
flickerstreak@148 253 end
flickerstreak@148 254 end
flickerstreak@147 255 for b in self:IterateButtons() do
flickerstreak@147 256 b:SetKeybindMode(mode)
flickerstreak@147 257 end
flickerstreak@147 258 end
flickerstreak@147 259
flickerstreak@153 260 function Bar:ApplyAnchor()
flickerstreak@153 261 local f = self:GetFrame()
flickerstreak@153 262 local c = self.config
flickerstreak@153 263 local p = c.point
flickerstreak@153 264
flickerstreak@153 265 f:SetWidth(c.width)
flickerstreak@153 266 f:SetHeight(c.height)
flickerstreak@153 267 f:ClearAllPoints()
flickerstreak@153 268
flickerstreak@153 269 if p then
flickerstreak@153 270 local a = f:GetParent()
flickerstreak@153 271 if c.anchor then
flickerstreak@153 272 local bar = ReAction:GetBar(c.anchor)
flickerstreak@153 273 if bar then
flickerstreak@153 274 a = bar:GetFrame()
flickerstreak@153 275 else
flickerstreak@153 276 a = _G[c.anchor]
flickerstreak@153 277 end
flickerstreak@153 278 end
flickerstreak@153 279 local fr = a or f:GetParent()
flickerstreak@153 280 f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0)
flickerstreak@153 281 else
flickerstreak@153 282 f:SetPoint("CENTER")
flickerstreak@153 283 end
flickerstreak@153 284 end
flickerstreak@153 285
flickerstreak@153 286 function Bar:ClipNButtons( n )
flickerstreak@153 287 local cfg = self.config
flickerstreak@153 288 local r = cfg.btnRows or 1
flickerstreak@153 289 local c = cfg.btnColumns or 1
flickerstreak@153 290
flickerstreak@153 291 cfg.btnRows = ceil(n/c)
flickerstreak@153 292 cfg.btnColumns = min(n,c)
flickerstreak@153 293 end
flickerstreak@153 294
flickerstreak@153 295 function Bar:AddButton(idx, button)
flickerstreak@153 296 local f = self:GetFrame()
flickerstreak@153 297
flickerstreak@153 298 -- store in a weak reverse-index array
flickerstreak@153 299 self.buttons[button] = idx
flickerstreak@153 300
flickerstreak@153 301 -- Store a properly wrapped reference to the child frame as an attribute
flickerstreak@153 302 -- (accessible via "frameref-btn#")
flickerstreak@153 303 f:SetFrameRef(format("btn%d",idx), button:GetFrame())
flickerstreak@153 304 end
flickerstreak@153 305
flickerstreak@153 306 function Bar:RemoveButton(button)
flickerstreak@153 307 local idx = self.buttons[button]
flickerstreak@153 308 if idx then
flickerstreak@153 309 self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil)
flickerstreak@153 310 self.buttons[button] = nil
flickerstreak@153 311 end
flickerstreak@153 312 end
flickerstreak@153 313
flickerstreak@122 314 function Bar:PlaceButton(button, baseW, baseH)
flickerstreak@122 315 local idx = self.buttons[button]
flickerstreak@122 316 if idx then
flickerstreak@122 317 local r, c, s = self:GetButtonGrid()
flickerstreak@122 318 local bh, bw = self:GetButtonSize()
flickerstreak@122 319 local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based
flickerstreak@122 320 local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s)
flickerstreak@122 321 local scale = bw/baseW
flickerstreak@122 322 local b = button:GetFrame()
flickerstreak@122 323
flickerstreak@122 324 b:ClearAllPoints()
flickerstreak@122 325 b:SetPoint("TOPLEFT",x/scale,y/scale)
flickerstreak@122 326 b:SetScale(scale)
flickerstreak@122 327 end
flickerstreak@122 328 end
flickerstreak@122 329
flickerstreak@122 330 function Bar:SkinButton()
flickerstreak@122 331 -- does nothing by default
flickerstreak@147 332 end
flickerstreak@148 333
flickerstreak@154 334 function Bar:ShowControls(show)
flickerstreak@154 335 local f = self.overlay
flickerstreak@154 336 if show then
flickerstreak@154 337 if not f then
flickerstreak@154 338 f = Bar.Overlay:New(self) -- see Overlay.lua
flickerstreak@154 339 self.overlay = f
flickerstreak@154 340 end
flickerstreak@154 341 f:Show()
flickerstreak@154 342 elseif f then
flickerstreak@154 343 f:Hide()
flickerstreak@154 344 end
flickerstreak@154 345 end
flickerstreak@154 346
flickerstreak@154 347 function Bar:RefreshControls()
flickerstreak@154 348 if self.overlay and self.overlay:IsShown() then
flickerstreak@154 349 self.overlay:RefreshControls()
flickerstreak@154 350 end
flickerstreak@154 351 end
flickerstreak@154 352
flickerstreak@154 353 function Bar:SetLabelSubtext(text)
flickerstreak@154 354 if self.overlay then
flickerstreak@154 355 self.overlay:SetLabelSubtext(text)
flickerstreak@154 356 end
flickerstreak@154 357 end
flickerstreak@154 358
flickerstreak@154 359 --
flickerstreak@154 360 -- Secure state functions
flickerstreak@154 361 --
flickerstreak@154 362
flickerstreak@148 363 -- pass unit=nil to set up the unit elsewhere, if you want something more complex
flickerstreak@148 364 function Bar:RegisterUnitWatch( unit, enable )
flickerstreak@148 365 local f = self:GetFrame()
flickerstreak@148 366 if unit then
flickerstreak@148 367 f:SetAttribute("unit",unit)
flickerstreak@148 368 end
flickerstreak@148 369 if not ReAction:GetConfigMode() then
flickerstreak@148 370 if enable then
flickerstreak@148 371 RegisterUnitWatch(f)
flickerstreak@148 372 elseif self.unitwatch then
flickerstreak@148 373 UnregisterUnitWatch(f)
flickerstreak@148 374 end
flickerstreak@148 375 end
flickerstreak@148 376 self.unitwatch = enable
flickerstreak@148 377 end
flickerstreak@148 378