Mercurial > wow > reaction
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 |