comparison Button.lua @ 245:65f2805957a0

No real reason to store some of the code in a subdirectory.
author Flick
date Sat, 26 Mar 2011 12:35:08 -0700
parents classes/Button.lua@dcdc0235d489
children 46b59a9ded76
comparison
equal deleted inserted replaced
244:f255cd69e890 245:65f2805957a0
1 --[[
2 ReAction Button base class
3 --]]
4
5 -- local imports
6 local addonName, addonTable = ...
7 local ReAction = addonTable.ReAction
8 local L = ReAction.L
9 local LKB = ReAction.LKB
10 local _G = _G
11 local CreateFrame = CreateFrame
12 local GetBindingKey = GetBindingKey
13 local format = string.format
14
15 -- private
16 local trash = CreateFrame("Frame")
17 local frameList = { }
18 local idPools = { }
19
20 local function kb_onEnter( frame )
21 LKB:Set(frame)
22 end
23
24 -- Button class
25 local buttonTypeID = "Button"
26 local Button = {
27 defaultBarConfig = {
28 type = buttonTypeID,
29 btnWidth = 36,
30 btnHeight = 36,
31 btnRows = 1,
32 btnColumns = 12,
33 spacing = 3
34 },
35 barType = L["Button Bar"]
36 }
37
38 ReAction.Button = Button -- export to ReAction
39
40 function Button:New( name, config, bar, idx, inherits, buttonType )
41 buttonType = buttonType or "CheckButton"
42
43 -- create new self
44 self = setmetatable(
45 {
46 bar = bar,
47 idx = idx,
48 config = config,
49 name = name,
50 },
51 { __index = self } )
52
53 -- have to recycle frames with the same name: CreateFrame() doesn't overwrite
54 -- existing globals. Can't set to nil in the global because it's then tainted.
55 -- Caller is responsible for ensuring global uniqueness of names.
56 local f = name and frameList[name]
57 if f then
58 f:SetParent(bar:GetFrame())
59 else
60 f = CreateFrame(buttonType, name, bar:GetFrame(), inherits)
61 if name then
62 frameList[name] = f
63 end
64 end
65
66 self.frame = f
67
68 local frames = { }
69 self.frames = frames
70 frames.icon = _G[name.."Icon"]
71 frames.flash = _G[name.."Flash"]
72 frames.hotkey = _G[name.."HotKey"]
73 frames.count = _G[name.."Count"]
74 frames.name = _G[name.."Name"]
75 frames.border = _G[name.."Border"]
76 frames.cooldown = _G[name.."Cooldown"]
77 frames.normalTexture = _G[name.."NormalTexture"]
78
79 if config then
80 config.name = name
81 end
82
83 -- install LibKeyBound handlers onto frame
84 function f:GetActionName()
85 return format("%s:%s", bar:GetName(), idx)
86 end
87
88 local clickBinding = format("CLICK %s:LeftButton", name)
89 function f:GetHotkey()
90 return LKB:ToShortKey(GetBindingKey(clickBinding))
91 end
92
93 return self
94 end
95
96 function Button:Destroy()
97 local f = self:GetFrame()
98 f:UnregisterAllEvents()
99 self:ReleaseActionID(self:GetActionID())
100 if f then
101 f:Hide()
102 f:SetParent(trash)
103 f:ClearAllPoints()
104 end
105 end
106
107 function Button:GetBar()
108 return self.bar
109 end
110
111 function Button:GetFrame()
112 return self.frame
113 end
114
115 function Button:GetIndex()
116 return self.idx
117 end
118
119 function Button:GetName()
120 return self.name
121 end
122
123 function Button:GetDefaultBarConfig()
124 return self.defaultBarConfig
125 end
126
127 function Button:GetBarType()
128 return self.barType
129 end
130
131 function Button:GetButtonTypeID()
132 return self.buttonTypeID
133 end
134
135 function Button:GetConfig()
136 return self.config
137 end
138
139 function Button:GetActionID()
140 -- derived classes should override this
141 return nil
142 end
143
144 function Button:SetActionIDPool( poolID, maxID )
145 self.actionPoolID = poolID
146 self.actionMaxID = maxID
147 end
148
149 function Button:SetupBar( bar )
150 local config = bar:GetConfig()
151 if not config.buttons then
152 config.buttons = { }
153 end
154 local btnCfg = config.buttons
155
156 local r, c = bar:GetButtonGrid()
157 local n = r*c
158 local cfgN = n
159
160 local hint = nil
161 local i = 1
162 repeat
163 local b = bar:GetButton(i)
164 if b then
165 if i > n then
166 bar:RemoveButton(b)
167 b:Destroy()
168 if i > cfgN then
169 btnCfg[i] = nil
170 end
171 else
172 b:Refresh()
173 hint = b:GetActionID()
174 end
175 elseif i <= n then
176 local cfg = btnCfg[i] or { }
177 local success, r = pcall(self.New, self, cfg, bar, i, hint) -- note call semantics for derived class constructors
178 if success and r then
179 b = r
180 bar:AddButton(i,b)
181 btnCfg[i] = cfg
182 b:Refresh()
183 hint = b:GetActionID()
184 else
185 n = i - 1
186 if not success then
187 bar:ClipNButtons(n)
188 cfgN = n
189 geterrorhandler()(r)
190 end
191 end
192 end
193 i = i + 1
194 until b == nil
195 end
196
197 function Button:AcquireActionID( id, hint, unique )
198 local poolID = self.actionPoolID
199 local maxID = self.actionMaxID
200 if not poolID or not maxID then
201 error("AcquireActionID: must setup pool first with SetActionIDPool")
202 end
203 local pool = idPools[poolID]
204 if not pool then
205 pool = { nWraps = 0, useCount = { } }
206 for i = 1, maxID do
207 pool.useCount[i] = 0
208 end
209 idPools[poolID] = pool
210 end
211 local useCount = pool.useCount
212 if id == nil then
213 repeat
214 local nWraps = pool.nWraps or 0
215 if hint and (useCount[hint] == nil or useCount[hint] == nWraps) then
216 id = hint
217 else
218 local start = hint or 1
219 for i = start, maxID do
220 if useCount[i] == nil or useCount[i] == nWraps then
221 id = i
222 break
223 end
224 end
225 if not id then
226 for i = 1, start do
227 if useCount[i] == nil or useCount[i] == nWraps then
228 id = i
229 break
230 end
231 end
232 end
233 end
234 if id == nil then
235 if unique then
236 return nil
237 end
238 pool.nWraps = nWraps + 1
239 end
240 until id ~= nil
241 end
242 useCount[id] = (useCount[id] or 0) + 1
243 return id
244 end
245
246 function Button:ReleaseActionID( id )
247 local poolID = self.actionPoolID
248 if not poolID then
249 error("ReleaseActionID: must setup pool first with SetActionIDPool")
250 end
251 local pool = idPools[poolID]
252 if pool and id and pool.useCount[id] then
253 pool.useCount[id] = pool.useCount[id] - 1
254 pool.nWraps = min(pool.useCount[id], pool.nWraps)
255 end
256 end
257
258 function Button:Refresh()
259 local f = self:GetFrame()
260 self.bar:PlaceButton( self, f:GetWidth(), f:GetHeight() )
261 end
262
263 function Button:SetKeybindMode( mode )
264 local f = self.frame
265 if mode then
266 self.oldOnEnter = f:GetScript("OnEnter")
267 f:SetScript("OnEnter", kb_onEnter)
268 elseif self.oldOnEnter then
269 f:SetScript("OnEnter", self.oldOnEnter)
270 self.oldOnEnter = nil
271 end
272 self:ShowGridTemp(mode)
273 self:UpdateKeybindModeDisplay( mode )
274 end
275
276 function Button:UpdateKeybindModeDisplay( mode )
277 local border = self.frames.border or _G[format("%sBorder",tostring(self:GetName()))]
278 if border then
279 if mode then
280 border:SetVertexColor(LKB:GetColorKeyBoundMode())
281 border:Show()
282 else
283 border:Hide()
284 end
285 end
286 end
287
288 function Button:UpdateHotkey( hotkey )
289 hotkey = hotkey or self.frames.hotkey
290 if not hotkey then
291 hotkey = _G[self:GetName().."HotKey"]
292 self.frames.hotkey = hotkey
293 end
294 if hotkey then
295 local txt = self.frame:GetHotkey()
296 hotkey:SetText( txt )
297 if txt == nil or txt == "" then
298 hotkey:Hide()
299 else
300 hotkey:Show()
301 end
302 end
303 end
304
305 function Button:GetActionIDLabel( create )
306 local f = self:GetFrame()
307 if not f.actionIDLabel and create then
308 local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
309 label:SetAllPoints()
310 label:SetJustifyH("CENTER")
311 label:SetShadowColor(0,0,0,1)
312 label:SetShadowOffset(2,-2)
313 f.actionIDLabel = label -- store the label with the frame for recycling
314 end
315 return f.actionIDLabel
316 end
317
318 function Button:UpdateActionIDLabel( show )
319 local label = self:GetActionIDLabel( show )
320 if label then
321 if show then
322 local id = self:GetActionID()
323 if id then
324 label:SetText(tostring(id))
325 label:Show()
326 return
327 end
328 end
329 label:Hide()
330 end
331 end
332
333 function Button:SetNormalVertexColor( r, g, b, a )
334 if ReAction.LBF then
335 ReAction.LBF:SetNormalVertexColor(self:GetFrame(), r, g, b, a)
336 else
337 self:GetFrame():GetNormalTexture():SetVertexColor(r,g,b,a)
338 end
339 end
340
341 function Button:GetNormalVertexColor()
342 if ReAction.LBF then
343 return ReAction.LBF:GetNormalVertexColor(self:GetFrame())
344 else
345 return self:GetFrame():GetNormalTexture():GetVertexColor()
346 end
347 end
348
349 function Button:UpdateShowGrid()
350 -- does nothing by default
351 end
352
353 function Button:ShowGridTemp(show)
354 -- does nothing by default
355 end
356
357 function Button:ShowGrid(show)
358 -- does nothing by default
359 end