comparison main.lua @ 7:f920db5fc6b1

version 0.3
author Flick <flickerstreak@gmail.com>
date Tue, 20 Mar 2007 21:25:29 +0000
parents dfd829db3ad0
children c05fd3e18b4f
comparison
equal deleted inserted replaced
6:2da5089ab7ff 7:f920db5fc6b1
1 -- ReAction.lua 1 -- main.lua
2 -- 2 --
3 -- Top-level file for the ReAction Action Bar add-on 3 -- Top-level file for the ReAction Action Bar add-on
4 -- 4 --
5 -- ReAction is implemented in terms of the Ace 2 library: http://www.wowace.com 5 -- implemented in terms of the Ace 2 development framework library: http://www.wowace.com
6 -- 6 --
7 7
8 -- Ace Library local object initialization
9 local L = AceLibrary("AceLocale-2.2"):new("ReAction")
10 local dewdrop = AceLibrary("Dewdrop-2.0")
11 local tablet = AceLibrary("Tablet-2.0")
12
13 -- private functions
14 local function tcopy(t)
15 local r = { }
16 for k, v in pairs(t) do
17 r[k] = (type(v) == "table" and tcopy(v) or v)
18 end
19 return r
20 end
21
22 -- private constants
23 local EMPTY_BAR_SLOT = -1
24
8 -- key binding label constants 25 -- key binding label constants
9 BINDING_HEADER_REACTION = "ReAction" 26 BINDING_HEADER_REACTION = L["ReAction"]
10 BINDING_NAME_REACTION_TOGGLELOCK = "Lock/Unlock ReAction Bars" 27 BINDING_NAME_REACTION_TOGGLELOCK = L["Toggle ReAction Bar Lock"]
11 BINDING_NAME_REBINDER_TOGGLEBINDINGMODE = "Toggle ReAction keybinding mode" 28 BINDING_NAME_REBOUND_TOGGLEBINDINGMODE = L["Toggle ReBound Keybinding Mode"]
12 29
13 -- ReAction addon setup via Ace 2 30
14 ReAction = AceLibrary("AceAddon-2.0"):new( 31 -- main object
32 local main = AceLibrary("AceAddon-2.0"):new(
15 "AceConsole-2.0", 33 "AceConsole-2.0",
16 "AceEvent-2.0", 34 "AceEvent-2.0",
17 "AceDB-2.0", 35 "AceDB-2.0",
18 "FuBarPlugin-2.0" 36 "FuBarPlugin-2.0"
19 ) 37 )
20 38
21 local function tcopy(t) 39 -- initial non-persistent state
22 local r = { } 40 main.locked = true
23 for k, v in pairs(t) do 41
24 r[k] = (type(v) == "table" and tcopy(v) or v) 42 -- set a global variable for Bindings.xml
25 end 43 ReActionAddOn = main
26 return r 44
27 end
28 45
29 -- FuBar plugin setup 46 -- FuBar plugin setup
30 ReAction.hasIcon = false 47 -- Even if FuBar isn't installed, this gives us a nice minimap-button interface.
31 ReAction.hasNoColor = true 48 main.hasIcon = "Interface\\Icons\\INV_Qiraj_JewelEncased"
32 ReAction.hideMenuTitle = true 49 main.hasNoColor = true
33 ReAction.defaultPosition = "RIGHT" 50 main.hideMenuTitle = true
34 ReAction.defaultMinimapPosition = 240 -- degrees 51 main.defaultPosition = "LEFT"
35 ReAction.OnMenuRequest = tcopy(ReActionGlobalMenuOptions) 52 main.defaultMinimapPosition = 240 -- degrees
36 53 main.OnMenuRequest = tcopy(ReActionGlobalMenuOptions) -- use a copy, or bar menus will have FuBar inserted items
37 -- initial non-persistent state 54 main.independentProfile = true
38 ReAction.locked = true 55
39 56 -- set the handler for the global bar menu options
40 -- localization 57 -- have to do this after tcopy() above, otherwise it will try to copy the handler object (bad idea)
41 -- local L = AceLibrary("AceLocale-2.0"):new("ReAction") 58 ReActionGlobalMenuOptions.handler = main
59
42 60
43 61
44 62
45 -- Event handling 63 -- Event handling
46 function ReAction:OnInitialize() 64 function main:OnInitialize()
47 self:RegisterChatCommand( {"/reaction", "/rxn"}, ReActionConsoleOptions, "REACTION" ) 65 self:RegisterChatCommand( {L["/reaction"], L["/rxn"]}, ReActionConsoleOptions, "REACTION" )
48
49 self:RegisterDB("ReActionDB","ReActionDBPC") 66 self:RegisterDB("ReActionDB","ReActionDBPC")
50 self:RegisterDefaults("profile", ReActionProfileDefaults) 67 self:RegisterDefaults("profile", ReAction_DefaultProfile)
51 self:RegisterEvent("PLAYER_REGEN_DISABLED","CombatLockdown") 68 self:RegisterEvent("PLAYER_REGEN_DISABLED","CombatLockdown")
52 self:RegisterEvent("PLAYER_ENTERING_WORLD","HideDefaultBars") 69 self:RegisterEvent("PLAYER_ENTERING_WORLD","HideDefaultBars")
53 end 70 self:RegisterEvent("EVENT_REBOUND_KEYBINDING_MODE")
54 71 end
55 function ReAction:OnEnable() 72
73 function main:OnEnable()
74 -- this gets called at startup and when the profile is changed
56 if self.db.profile.firstRunDone ~= true then 75 if self.db.profile.firstRunDone ~= true then
57 -- Do some "first-run" setup 76 -- Do some "first-run" setup
77 self:StealKeyBindings()
58 self.db.profile.firstRunDone = true 78 self.db.profile.firstRunDone = true
59 elseif self.db.profile.disabled == true then 79 self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars)
60 -- print some kind of a warning 80 end
61 end 81 self:DestroyAllBars()
62 self:SetupBars() 82 self:SetupBars()
63 end 83 end
64 84
65 function ReAction:OnDisable() 85 function main:OnDisable()
66 self:Lock() 86 self:Lock()
67 end 87 end
68 88
69 function ReAction:OnProfileEnable() 89 function main:OnProfileEnable()
70 -- handle profile switching 90 -- for profile switching
71 self:Lock() 91 self:OnEnable()
72 self:SetupBars() 92 end
73 end 93
74 94 function main:CombatLockdown()
75 function ReAction:CombatLockdown()
76 if not self:IsLocked() then 95 if not self:IsLocked() then
77 self:Lock() 96 self:Lock()
78 UIErrorsFrame:AddMessage("ReAction bars locked when in combat") 97 ReBound:Disable()
79 end 98 UIErrorsFrame:AddMessage(L["ReAction bars locked when in combat"])
80 end 99 end
81 100 end
82 101
83 -- lock/unlock ReAction 102 function main:EVENT_REBOUND_KEYBINDING_MODE(enabled)
84 function ReAction:SetLocked( lock ) 103 for _, bar in pairs(self.bars) do
104 for __, button in pairs(bar.buttons) do
105 button:TempShow(enabled)
106 end
107 end
108 end
109
110
111 -- FuBar plugin methods
112 function main:OnTooltipUpdate()
113 local c = tablet:AddCategory("columns", 2)
114 c:AddLine("text", L["Bar lock"], "text2", self.locked and ("|cffff0000"..L["Locked"].."|r") or ("|cffffcc00"..L["Unlocked"].."|r"))
115 c:AddLine("text", L["Button lock"], "text2", LOCK_ACTIONBAR == "1" and ("|cffcc0000"..L["Locked"].."|r") or ("|cff00cc00"..L["Unlocked"].."|r"))
116 c:AddLine("text", L["Kebinding mode"], "text2", ReBound:IsEnabled() and ("|cff33ff33"..L["On"].."|r") or ("|cffffcc00"..L["Off"].."|r"))
117 tablet:SetHint(L["|cffffcc00Shift-Click for bar lock|n|cff33ff33Alt-Click|r for keybindings|nRight-click for menu"])
118 end
119
120 function main:OnClick(button)
121 if IsShiftKeyDown() then
122 self:ToggleLocked()
123 self:UpdateDisplay()
124 elseif IsAltKeyDown() then
125 ReBound:ToggleEnabled()
126 self:UpdateDisplay()
127 end
128 end
129
130
131 -- lock/unlock bars
132 function main:SetLocked( lock )
85 if lock ~= self.locked then 133 if lock ~= self.locked then
86 if not lock then
87 self:Print("Buttons disabled while unlocked")
88 end
89 if not lock and InCombatLockdown() then 134 if not lock and InCombatLockdown() then
90 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) 135 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
91 else 136 else
92 self.locked = lock and true or false -- force data integrity 137 self.locked = lock and true or false -- force data integrity
93 for _, bar in pairs(self.bars) do 138 for _, bar in pairs(self.bars) do
94 if self.locked then bar:HideControls() else bar:ShowControls() end 139 if bar ~= EMPTY_BAR_SLOT then
140 if self.locked then
141 bar:HideControls()
142 -- close any dewdrop menu owned by the bar
143 if bar:GetControlFrame() == dewdrop:GetOpenedParent() then
144 dewdrop:Close()
145 end
146 else
147 bar:ShowControls()
148 end
149 end
95 end 150 end
96 end 151 end
97 end 152 end
98 end 153 end
99 154
100 function ReAction:IsLocked() 155 function main:IsLocked()
101 return self.locked 156 return self.locked
102 end 157 end
103 158
104 function ReAction:Lock() 159 function main:Lock()
105 self:SetLocked(true) 160 self:SetLocked(true)
106 end 161 end
107 162
108 function ReAction:Unlock() 163 function main:Unlock()
109 self:SetLocked(false) 164 self:SetLocked(false)
110 end 165 end
111 166
112 function ReAction:ToggleLocked() 167 function main:ToggleLocked()
113 ReAction:SetLocked( not(self.locked) ) 168 main:SetLocked( not(self.locked) )
114 end 169 end
115 170
116 171
117 172
118 -- Hide the default Blizzard main bar artwork 173 -- Hide the default Blizzard main bar artwork
119 function ReAction:HideArt() 174 function main:HideArt()
120 if self.db.profile.hideArt then 175 if self.db.profile.hideArt then
176 -- the pet bar is a child of MainMenuBar, and can't be hidden. Need to reparent it
177 PetActionBarFrame:SetParent(UIParent)
121 MainMenuBar:Hide() -- this also hides the bags, xp bar, lag meter, and micro menu buttons. 178 MainMenuBar:Hide() -- this also hides the bags, xp bar, lag meter, and micro menu buttons.
122 else 179 -- these two are the pet bar background
180 -- unfortunately UIParent_ManageFramePositions() shows and hides these too
181 -- so they get reparented to MainMenuBar
182 SlidingActionBarTexture0:SetParent(MainMenuBar)
183 SlidingActionBarTexture1:SetParent(MainMenuBar)
184 else
185 SlidingActionBarTexture0:SetParent(PetActionBarFrame)
186 SlidingActionBarTexture1:SetParent(PetActionBarFrame)
123 MainMenuBar:Show() 187 MainMenuBar:Show()
124 end 188 end
125 end 189 end
126 190
127 function ReAction:IsArtHidden() 191 function main:IsArtHidden()
128 return self.db.profile.hideArt 192 return self.db.profile.hideArt
129 end 193 end
130 194
131 function ReAction:SetHideArt( hide ) 195 function main:SetHideArt( hide )
132 if InCombatLockdown() then 196 if InCombatLockdown() then
133 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) 197 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
134 else 198 else
135 self.db.profile.hideArt = hide and true or false -- force data integrity 199 self.db.profile.hideArt = hide and true or false -- force data integrity
136 self:HideArt() 200 self:HideArt()
137 end 201 end
138 end 202 end
139 203
140 function ReAction:ToggleHideArt() 204 function main:ToggleHideArt()
141 self:SetHideArt( not self:IsArtHidden() ) 205 self:SetHideArt( not self:IsArtHidden() )
142 end
143
144
145
146 -- Keybinding color coding
147 function ReAction:SetKeyColorCoding( cc )
148 self.db.profile.keyColorCode = cc
149 end
150
151 function ReAction:IsKeyColorCodeEnabled()
152 return self.db.profile.keyColorCode
153 end
154
155 function ReAction:ToggleKeyColorCoding()
156 self:SetKeyColorCoding(not self.db.profile.keyColorCode)
157 end 206 end
158 207
159 208
160 209
161 -- Hide default Blizzard bars 210 -- Hide default Blizzard bars
170 ActionButton8, 219 ActionButton8,
171 ActionButton9, 220 ActionButton9,
172 ActionButton10, 221 ActionButton10,
173 ActionButton11, 222 ActionButton11,
174 ActionButton12, 223 ActionButton12,
224 PetActionButton1,
225 PetActionButton2,
226 PetActionButton3,
227 PetActionButton4,
228 PetActionButton5,
229 PetActionButton6,
230 PetActionButton7,
231 PetActionButton8,
232 PetActionButton9,
233 PetActionButton10,
234 -- NOT the PetActionBarFrame, though - we need that to auto-hide/show our pet action bars
235 MainMenuBarPageNumber,
236 ActionBarUpButton,
237 ActionBarDownButton,
175 BonusActionBarFrame, 238 BonusActionBarFrame,
239 ShapeshiftBarFrame,
176 MultiBarLeft, 240 MultiBarLeft,
177 MultiBarRight, 241 MultiBarRight,
178 MultiBarBottomLeft, 242 MultiBarBottomLeft,
179 MultiBarBottomRight 243 MultiBarBottomRight,
180 } 244 }
181 245
182 function ReAction:HideDefaultBars() 246 function main:StealKeyBindings()
247 -- steal the keybindings of the main action bar and assign them to rebar 1, buttons 1-12
248 for i = 1, 12 do
249 -- TODO: when we convert to override bindings
250 end
251 end
252
253 local function disableUIOptions()
254 -- disable the buttons to hide/show the blizzard multiaction bars
255 -- see UIOptionsFrame.lua and .xml
256 -- This is called every time the options panel is shown, after it is set up
257 for _, idx in pairs( { 33, 34, 35, 36, 37, 40 } ) do
258 local f = getglobal("UIOptionsFrameCheckButton"..idx)
259 f.disabled = true
260 OptionsFrame_DisableCheckBox(f)
261 f:SetChecked(false)
262 end
263 end
264
265 function main:HideDefaultBars()
183 for _, f in pairs(blizzDefaultBars) do 266 for _, f in pairs(blizzDefaultBars) do
184 f:UnregisterAllEvents()
185 f:Hide() 267 f:Hide()
186 f:SetParent(ReActionButtonRecycler) -- I mean it! 268 f:ClearAllPoints()
187 f:ClearAllPoints() -- no, I really mean it! 269 f:SetParent(ReAction.recycler)
188 end 270 f:SetPoint("TOPLEFT")
189 end 271 end
190 272
191 273 MainMenuBar:SetFrameStrata("LOW") -- otherwise it appears on top of bars, if it isn't hidden
192 -- Reset bars to defaults 274 hooksecurefunc("UIOptionsFrame_Load",disableUIOptions)
193 function ReAction:ResetBars() 275 end
276
277
278 -- Reset bars to blizzard defaults
279 function main:ResetBars()
194 if InCombatLockdown() then 280 if InCombatLockdown() then
195 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) 281 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
196 else 282 else
197 self.db.profile.bars = ReActionProfileDefaults.bars 283 self:DestroyAllBars()
284 self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars)
198 self:SetupBars() 285 self:SetupBars()
199 end 286 end
200 end 287 end
201 288
202 289
203 -- re-sync action IDs 290 -- re-sync action IDs
204 function ReAction:ResyncActionIDs() 291 function main:ResyncActionIDs()
205 -- TODO 292 -- TODO
206 end 293 end
207 294
208 295
209 296
210 -- Bar manipulation 297 -- Bar manipulation
211 ReAction.bars = { } 298 main.bars = { }
212 299
213 function ReAction:SetupBars() 300 function main:DestroyAllBars()
301 -- destroy any existing bars
302 for id = 1, table.maxn(self.bars) do
303 self:DestroyBar(id)
304 end
305 end
306
307
308 function main:SetupBars()
214 -- hide the default Blizzard art, if configued 309 -- hide the default Blizzard art, if configued
215 self:HideArt() 310 self:HideArt()
216 -- hide the default Blizzard bars
217 self:HideDefaultBars()
218 311
219 -- set up the bars from the profile 312 -- set up the bars from the profile
220 -- note the use of table.maxn rather than # or ipairs: 313 -- note the use of table.maxn rather than # or ipairs:
221 -- our array of bars can in fact contain holes 314 -- our array of bars can in fact contain holes
222 for id = 1, table.maxn(self.db.profile.bars) do 315 for id = 1, table.maxn(self.db.profile.bars) do
223 local config = self.db.profile.bars[id] 316 local config = self.db.profile.bars[id]
224 if self.bars[id] then
225 self.bars[id]:Destroy() -- remove old version of bar if switching profiles
226 end
227 if config then 317 if config then
228 self.bars[id] = ReBar:new(config, id) 318 self:CreateBar(config, id)
229 end
230 end
231
232 -- remove excess bars
233 for id = table.maxn(self.db.profile.bars) + 1, table.maxn(self.bars) do
234 if self.bars[id] then
235 self.bars[id]:Destroy()
236 self.bars[id] = nil
237 end 319 end
238 end 320 end
239 321
240 -- anchor the bars, have to do this in a second pass because 322 -- anchor the bars, have to do this in a second pass because
241 -- they might be anchored to each other in a non-ordered way 323 -- they might be anchored to each other in a non-ordered way
242 for _, bar in pairs(self.bars) do 324 for _, bar in pairs(self.bars) do
243 bar:ApplyAnchor() 325 if bar ~= EMPTY_BAR_SLOT then
244 end 326 bar:ApplyAnchor()
245 end 327 end
246 328 end
247 329 end
248 function ReAction:NewBar() 330
331 function main:CreateBar( config, id )
332 local bar = ReBar:new(config, id)
333 local buttonType = ReAction:GetButtonType(config.btnConfig.subtype)
334
335 if buttonType then
336 self.bars[id] = bar
337 self.db.profile.bars[id] = config
338
339 -- initialize dewdrop menu
340 local cf = bar:GetControlFrame()
341 dewdrop:Register(cf,
342 'children',
343 function()
344 dewdrop:FeedAceOptionsTable(ReActionGlobalMenuOptions)
345 dewdrop:FeedAceOptionsTable(GenerateReActionBarOptions(bar,self))
346 dewdrop:FeedAceOptionsTable(buttonType:GenerateOptionsTable(config.btnConfig, function() return bar:GetButtonList() end))
347 end,
348 'cursorX', true,
349 'cursorY', true
350 )
351
352 bar:GetControlFrame():SetScript("OnClick",
353 function(btn)
354 if btn == "RightButton" then
355 dewdrop:Open(cf)
356 end
357 end
358 )
359
360 if not self.locked then
361 bar:ShowControls()
362 end
363 return bar
364 else
365 if bar then
366 bar:Destroy()
367 end
368 error(L["Tried to create a button of unknown type"])
369 end
370 end
371
372 function main:DestroyBar( id )
373 local bar = self.bars[id]
374 if bar and bar ~= EMPTY_BAR_SLOT then
375 local cf = bar:GetControlFrame()
376 if cf == dewdrop:GetOpenedParent() then
377 dewdrop:Close()
378 dewdrop:Unregister(cf)
379 end
380 bar:Destroy()
381 -- we can't do tremove because each bar ID is encoded into the
382 -- frame names as they're created. Need a blank entry in the table.
383 -- The nice thing is that table.insert in NewBar() will automatically
384 -- find the lowest numbered nil slot.
385 self.bars[id] = EMPTY_BAR_SLOT
386 end
387 end
388
389 function main:NewBar( type )
249 if InCombatLockdown() then 390 if InCombatLockdown() then
250 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) 391 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
251 else 392 else
252 local c = tcopy(ReActionBarConfigDefaults) 393 local t = ReAction:GetButtonType(type)
253 local bar = ReBar:new(c, #self.bars+1) 394 if t then
254 table.insert(self.bars, bar) 395 local c = tcopy(ReAction_DefaultBarConfig["ReAction"][type])
255 table.insert(self.db.profile.bars, c) 396 local id = nil
256 if not self.locked then 397 for i = 1, table.maxn(self.bars) + 1 do -- there may be holes, so #self.bars won't work
257 bar:ShowControls() 398 if self.bars[i] == nil or self.bars[i] == EMPTY_BAR_SLOT then
258 end 399 id = i
259 end 400 break
260 end 401 end
261 402 end
262 403 local bar = self:CreateBar(c, id)
263 function ReAction:DeleteBar(id) 404 bar:ApplyAnchor()
405 self:Unlock()
406 end
407 end
408 end
409
410
411 function main:DeleteBar(id)
264 if InCombatLockdown() then 412 if InCombatLockdown() then
265 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) 413 UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
266 else 414 else
267 if self.bars[id] then 415 if self.bars[id] then
268 -- we can't do tremove because each bar ID is encoded into the 416 self:DestroyBar(id)
269 -- frame names as they're created. Need a nil entry in the table.
270 -- The nice thing is that table.insert in NewBar() will automatically
271 -- find the first nil slot.
272 self.bars[id]:Destroy()
273 self.bars[id] = nil
274 self.db.profile.bars[id] = nil 417 self.db.profile.bars[id] = nil
275 end 418 end
276 end 419 end
277 end 420 end
278 421
279 function ReAction:ToggleActionID() 422 function main:ToggleIds()
280 if self.showActionIDs then 423 if self.showIds then
281 ReActionButton:HideAllActionIDs() 424 ReAction:HideAllIds()
282 else 425 else
283 ReActionButton:ShowAllActionIDs() 426 ReAction:ShowAllIds()
284 end 427 end
285 self.showActionIDs = not self.showActionIDs 428 self.showIds = not self.showIds
286 end 429 end
287 430
288 function ReAction:IsActionIDVisible() 431 function main:AreIdsVisible()
289 return self.showActionIDs 432 return self.showIds
290 end 433 end
291 434
292 435
293 436
294 -- FuBar plugin methods
295 local tablet = AceLibrary("Tablet-2.0")
296
297 function ReAction:OnTooltipUpdate()
298 local c = tablet:AddCategory("columns", 2)
299 c:AddLine("text", "Bar lock", "text2", self.locked and "|cffcc0000Locked|r" or "|cff00cc00Unlocked|r")
300 c:AddLine("text", "Button lock", "text2", LOCK_ACTIONBAR == "1" and "|cffcc0000Locked|r" or "|cff00cc00Unlocked|r")
301 c:AddLine("text", "Kebinding mode", "text2", ReBinder:IsEnabled() and "|cff33ff33On|r" or "|cffffcc00Off|r")
302 tablet:SetHint("|cffffcc00Shift-Click|r for bar lock|n"..
303 "|cff33ff33Alt-Click|r for keybindings|n"..
304 "Right-click for menu")
305 end
306
307 function ReAction:OnClick(button)
308 if IsShiftKeyDown() then
309 self:ToggleLocked()
310 self:UpdateDisplay()
311 elseif IsAltKeyDown() then
312 ReBinder:ToggleEnabled()
313 end
314 end