comparison ReAction.lua @ 257:920d17851a93 stable

Merge 1.1 beta 4 to stable
author Flick
date Tue, 12 Apr 2011 16:06:31 -0700
parents 47818b3938c9
children 9e708a155ab9
comparison
equal deleted inserted replaced
210:b2b105747466 257:920d17851a93
1 local addonName, addonTable = ... 1 local addonName, addonTable = ...
2 local pcall = pcall 2 local pcall = pcall
3 local pairs = pairs 3 local pairs = pairs
4 local type = type 4 local type = type
5 local geterrorhandler = geterrorhandler 5 local geterrorhandler = geterrorhandler
6 local LKB = LibStub("LibKeyBound-1.0")
7 local L = LibStub("AceLocale-3.0"):GetLocale("ReAction") 6 local L = LibStub("AceLocale-3.0"):GetLocale("ReAction")
7 local LKB = LibStub("LibKeyBound-1.0",true)
8 if not LKB then
9 LoadAddOn("LibKeyBound-1.0")
10 LKB = LibStub("LibKeyBound-1.0")
11 end
8 12
9 ------ Utility ------ 13 ------ Utility ------
10 local tcopy 14 -- make a deep copy of a table
11 do 15 local function tcopy(x)
12 function tcopy(x) 16 if type(x) ~= "table" then
13 if type(x) ~= "table" then 17 return x
14 return x 18 end
15 end 19 local r = {}
16 local r = {} 20 for k,v in pairs(x) do
17 for k,v in pairs(x) do 21 r[k] = tcopy(v)
18 r[k] = tcopy(v) 22 end
19 end 23 return r
20 return r 24 end
21 end 25
22 end 26 -- traverse a table tree by key list and fetch the result or first nil
27 local function tfetch(t, ...)
28 for i = 1, select('#', ...) do
29 t = t and t[select(i, ...)]
30 end
31 return t
32 end
33
34 -- traverse a table tree by key list and build tree as necessary
35 local function tbuild(t, ...)
36 for i = 1, select('#', ...) do
37 local key = select(i, ...)
38 if not t[key] then t[key] = { } end
39 t = t[key]
40 end
41 return t
42 end
43
44 -- return a new array of keys of table 't', sorted by comparing
45 -- sub-fields (obtained via tfetch) of the table values
46 local function fieldsort( t, ... )
47 local r = { }
48 for k in pairs(t) do
49 table.insert(r,k)
50 end
51 local path = { ... }
52 table.sort(r, function(lhs, rhs)
53 local olhs = tfetch(t[lhs], unpack(path)) or 0
54 local orhs = tfetch(t[rhs], unpack(path)) or 0
55 return olhs < orhs
56 end)
57 return r
58 end
59
60 -- store in the addon table
61 addonTable.tcopy = tcopy
62 addonTable.tfetch = tfetch
63 addonTable.tbuild = tbuild
64 addonTable.fieldsort = fieldsort
23 65
24 ------ Core ------ 66 ------ Core ------
25 local ReAction = LibStub("AceAddon-3.0"):NewAddon( "ReAction", 67 local ReAction = LibStub("AceAddon-3.0"):NewAddon( "ReAction",
26 "AceEvent-3.0" 68 "AceEvent-3.0"
27 ) 69 )
28 addonTable.ReAction = ReAction 70 addonTable.ReAction = ReAction
29 ReAction.version = "1.1" 71 ReAction.version = GetAddOnMetadata("ReAction","Version")
30 ReAction.L = L 72 ReAction.L = L
31 ReAction.LKB = LKB 73 ReAction.LKB = LKB
32 74
75
76 ReAction.barTypes = { }
33 77
34 ------ Handlers ------ 78 ------ Handlers ------
35 function ReAction:OnInitialize() 79 function ReAction:OnInitialize()
36 self.db = LibStub("AceDB-3.0"):New("ReAction_DB", 80 self.db = LibStub("AceDB-3.0"):New("ReAction_DB",
37 { 81 self.defaultProfile,
38 profile = {
39 bars = { },
40 defaultBar = { },
41 }
42 },
43 true -- use global 'Default' (locale-specific) 82 true -- use global 'Default' (locale-specific)
44 ) 83 )
45 84
85 self:UpgradeProfile()
86
46 self.bars = { } 87 self.bars = { }
47 self.defaultBarConfig = { } 88
89 self.LBF = LibStub("LibButtonFacade",true)
90 if self.LBF then
91 self.LBF:RegisterSkinCallback("ReAction", self.OnSkinChanged, self)
92 end
93
94 -- It's fairly normal to use the Blizzard vehicle bar, and to have
95 -- your regular buttons in the same location. If you do this, and don't
96 -- bother to hide your buttons, they'll obscure some parts of the vehicle bar.
97 VehicleMenuBar:SetFrameLevel(VehicleMenuBar:GetFrameLevel()+3)
48 98
49 self.callbacks = LibStub("CallbackHandler-1.0"):New(self) 99 self.callbacks = LibStub("CallbackHandler-1.0"):New(self)
100
50 LKB.RegisterCallback(self,"LIBKEYBOUND_ENABLED") 101 LKB.RegisterCallback(self,"LIBKEYBOUND_ENABLED")
51 LKB.RegisterCallback(self,"LIBKEYBOUND_DISABLED") 102 LKB.RegisterCallback(self,"LIBKEYBOUND_DISABLED")
52 LKB.RegisterCallback(self, "LIBKEYBOUND_MODE_COLOR_CHANGED","LIBKEYBOUND_ENABLED") 103 LKB.RegisterCallback(self, "LIBKEYBOUND_MODE_COLOR_CHANGED","LIBKEYBOUND_ENABLED")
104
105 -- see Profile.lua for these callback implementations
106 self.db.RegisterCallback(self,"OnProfileChanged")
107 self.db.RegisterCallback(self,"OnProfileCopied","OnProfileChanged")
108 self.db.RegisterCallback(self,"OnNewProfile")
109 self.db.RegisterCallback(self,"OnProfileReset", "OnNewProfile")
110
53 self:RegisterEvent("PLAYER_REGEN_DISABLED") 111 self:RegisterEvent("PLAYER_REGEN_DISABLED")
112 self:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
113
54 self:InitializeOptions() 114 self:InitializeOptions()
55 end 115 end
56 116
57 function ReAction:OnEnable() 117 function ReAction:OnEnable()
58 self:InitializeBars() 118 self:InitializeBars()
119 self:UPDATE_SHAPESHIFT_FORMS() -- it doesn't fire on a /reloadui
59 end 120 end
60 121
61 function ReAction:OnDisable() 122 function ReAction:OnDisable()
62 self:TearDownBars() 123 self:TearDownBars()
63 end 124 end
69 self:SetKeybindMode(false) 130 self:SetKeybindMode(false)
70 self:CloseEditor() 131 self:CloseEditor()
71 end 132 end
72 end 133 end
73 134
135 function ReAction:UPDATE_SHAPESHIFT_FORMS()
136 -- Re-parse the rules table according to the new form list.
137 -- This happens both at initial login (after PLAYER_ENTERING_WORLD)
138 -- as well as when gaining new abilities.
139 self.Bar:InitRuleFormats()
140 for _, bar in self:IterateBars() do
141 bar:ApplyStates()
142 end
143 end
144
74 function ReAction:LIBKEYBOUND_ENABLED( evt ) 145 function ReAction:LIBKEYBOUND_ENABLED( evt )
75 self:SetKeybindMode(true) 146 self:SetKeybindMode(true)
76 end 147 end
77 148
78 function ReAction:LIBKEYBOUND_DISABLED( evt ) 149 function ReAction:LIBKEYBOUND_DISABLED( evt )
79 return self:SetKeybindMode(false) 150 return self:SetKeybindMode(false)
151 end
152
153 function ReAction:OnSkinChanged( skinID, gloss, backdrop, group, button, colors )
154 if group == nil then
155 -- don't store global
156 else
157 -- 'group' is the bar-name
158 local bar = self:GetBar(group)
159 if bar then
160 local c = bar:GetConfig().ButtonFacade
161 if c then
162 c.skinID = skinID
163 c.gloss = gloss
164 c.backdrop = backdrop
165 c.colors = colors
166 end
167 end
168 end
80 end 169 end
81 170
82 171
83 ------ Methods ------ 172 ------ Methods ------
84 173
108 -- (1) ReAction:CreateBar(name, [cfgTable]) 197 -- (1) ReAction:CreateBar(name, [cfgTable])
109 -- (2) ReAction:CreateBar(name, "barType", [nRows], [nCols], [btnSize], [btnSpacing]) 198 -- (2) ReAction:CreateBar(name, "barType", [nRows], [nCols], [btnSize], [btnSpacing])
110 function ReAction:CreateBar(name, config, ...) 199 function ReAction:CreateBar(name, config, ...)
111 local profile = self.db.profile 200 local profile = self.db.profile
112 201
113 if name then 202 name = tostring(name)
114 if self.bars[name] then 203 if not name or name == "" then
115 self:UserError(format(L["ReAction: name '%s' already in use"],name)) 204 error("ReAction:CreateBar() - bar name string required")
116 return nil 205 elseif self.bars[name] then
117 end 206 self:UserError(format(L["ReAction: name '%s' already in use"],name))
118 else 207 return nil
119 local prefix = L["Bar "] 208 end
120 local i = 1 209
121 repeat 210 local class
122 name = prefix..i
123 i = i + 1
124 until self.bars[name] == nil
125 end
126
127 if type(config) == "string" then 211 if type(config) == "string" then
128 config = self.defaultBarConfig[config] 212 class = self.barTypes[config]
129 if not config then 213 if not class then
130 error(("ReAction:CreateBar() - unknown bar type '%s'"):format(tostring(select(1,...)))) 214 error(("ReAction:CreateBar() - unknown bar type '%s'"):format(config))
131 end 215 end
132 config = tcopy(config) 216 config = tcopy(class:GetDefaultBarConfig())
133 config.btnRows = select(1,...) or config.btnRows or 1 217 config.btnRows = select(1,...) or config.btnRows
134 config.btnColumns = select(2,...) or config.btnColumns or 12 218 config.btnColumns = select(2,...) or config.btnColumns
135 config.btnWidth = select(3,...) or config.btnWidth or 36 219 config.btnWidth = select(3,...) or config.btnWidth
136 config.btnHeight = select(3,...) or config.btnHeight or 36 220 config.btnHeight = select(3,...) or config.btnHeight
137 config.spacing = select(4,...) or config.spacing or 3 221 config.spacing = select(4,...) or config.spacing
138 config.width = config.width or config.btnColumns*(config.btnWidth + config.spacing) + 1 222 config.width = config.width or config.btnColumns*(config.btnWidth + config.spacing) + 1
139 config.height = config.height or config.btnRows*(config.btnHeight + config.spacing) + 1 223 config.height = config.height or config.btnRows*(config.btnHeight + config.spacing) + 1
140 config.anchor = config.anchor or "UIParent" 224 config.anchor = config.anchor or "UIParent"
141 config.point = config.point or "BOTTOM" 225 config.point = config.point or "BOTTOM"
142 config.relpoint = config.relpoint or "BOTTOM" 226 config.relpoint = config.relpoint or "BOTTOM"
143 config.y = config.y or 200 227 config.y = config.y or 200
144 config.x = config.x or 0 228 config.x = config.x or 0
145 end 229 else
146 config = config or profile.bars[name] or tcopy(profile.defaultBar) 230 config = config or profile.bars[name] or { }
231 if not config or not config.type or not self.barTypes[config.type] then
232 error(("ReAction: Unable to construct/fetch config table for bar '%s'"):format(name))
233 end
234 class = self.barTypes[config.type]
235 end
147 236
148 profile.bars[name] = config 237 profile.bars[name] = config
149 local bar = self.Bar:New( name, config ) -- ReAction.Bar defined in Bar.lua 238 local bar = self.Bar:New( name, config, class ) -- ReAction.Bar defined in Bar.lua
150 self.bars[name] = bar 239 self.bars[name] = bar
151 self.callbacks:Fire("OnCreateBar", bar, name) 240 self.callbacks:Fire("OnCreateBar", bar, name)
152 if self.configMode then 241 if self.configMode then
153 bar:ShowControls(true) 242 bar:ShowControls(true)
154 end 243 end
163 self.callbacks:Fire("OnDestroyBar", bar, name) 252 self.callbacks:Fire("OnDestroyBar", bar, name)
164 bar:Destroy() 253 bar:Destroy()
165 end 254 end
166 end 255 end
167 256
168 function ReAction:RefreshBar(x)
169 local bar, name = self:GetBar(x)
170 if bar and name then
171 self.callbacks:Fire("OnRefreshBar", bar, name)
172 end
173 end
174
175 function ReAction:InitializeBars() 257 function ReAction:InitializeBars()
176 if not self.barsInitialized then 258 if not self.barsInitialized then
259 self:ManageBlizzardBars()
260
177 for name, config in pairs(self.db.profile.bars) do 261 for name, config in pairs(self.db.profile.bars) do
178 if config then 262 if config then
179 self:CreateBar(name, config) 263 self:CreateBar(name, config)
180 end 264 end
181 end 265 end
182 -- re-anchor and refresh in case anchor order does not match init order 266 -- re-anchor in case anchor order does not match init order
183 for name, bar in pairs(self.bars) do 267 for name, bar in pairs(self.bars) do
184 bar:ApplyAnchor() 268 bar:ApplyAnchor()
185 self.callbacks:Fire("OnRefreshBar", bar, name)
186 end 269 end
187 self.barsInitialized = true 270 self.barsInitialized = true
188 end 271 end
189 end 272 end
190 273
224 end 307 end
225 308
226 function ReAction:EraseBar(x) 309 function ReAction:EraseBar(x)
227 local bar, name = self:GetBar(x) 310 local bar, name = self:GetBar(x)
228 if bar and name then 311 if bar and name then
229 self.callbacks:Fire("OnEraseBar", bar, name)
230 self:DestroyBar(bar) 312 self:DestroyBar(bar)
231 self.db.profile.bars[name] = nil 313 self.db.profile.bars[name] = nil
232 end 314 end
233 end 315 end
234 316
235 function ReAction:RegisterBarType( name, config, isDefaultChoice ) 317 local blizzFrames = {
236 self.defaultBarConfig[name] = config 318 MainMenuBar,
237 if isDefaultChoice then 319 MultiBarLeft,
238 self.defaultBarConfigChoice = name 320 MultiBarRight,
239 end 321 MultiBarBottomLeft,
240 self:RefreshEditor() 322 MultiBarBottomRight,
241 end 323 }
242 324
243 function ReAction:UnregisterBarType( name ) 325 local hideFrame = CreateFrame("Frame")
244 self.defaultBarConfig[name] = nil 326 hideFrame:Hide()
245 if self.defaultBarConfigChoice == name then 327 local hiddenParents = { }
246 self.defaultBarConfigChoice = nil 328 local function ManageBlizzFrame(f, hide)
247 end 329 if hide and not hiddenParents[f] then
248 self:RefreshEditor() 330 hiddenParents[f] = f:GetParent()
331 f:SetParent(hideFrame)
332 elseif not hide and hiddenParents[f] then
333 f:SetParent(hiddenParents[f])
334 hiddenParents[f] = nil
335 if f:IsShown() then
336 f:Show() -- refresh
337 end
338 end
339 end
340
341 function ReAction:ManageBlizzardBars()
342 for _, f in pairs(blizzFrames) do
343 ManageBlizzFrame(f, self.db.profile.options.hideBlizzardBars)
344 end
345 ManageBlizzFrame(VehicleMenuBar, self.db.profile.options.hideBlizzardVehicleBar)
346 end
347
348 function ReAction:RegisterBarType( class, isDefault )
349 local name = class:GetButtonTypeID()
350 self.barTypes[name] = class
351 if isDefault then
352 self.defaultBarType = name
353 end
249 end 354 end
250 355
251 function ReAction:IterateBarTypes() 356 function ReAction:IterateBarTypes()
252 return pairs(self.defaultBarConfig) 357 return pairs(self.barTypes)
253 end 358 end
254 359
255 function ReAction:GetBarTypeConfig(name) 360 function ReAction:GetDefaultBarConfig(barType)
256 if name then 361 if barType and self.barTypes[barType] then
257 return self.defaultBarConfig[name] 362 return self.barTypes[barType]:GetDefaultBarConfig()
258 end 363 end
259 end 364 end
260 365
261 function ReAction:GetBarTypeOptions( fill ) 366 function ReAction:GetBarTypeOptions( fill )
262 fill = fill or { } 367 fill = fill or { }
265 end 370 end
266 return fill 371 return fill
267 end 372 end
268 373
269 function ReAction:GetDefaultBarType() 374 function ReAction:GetDefaultBarType()
270 return self.defaultBarConfigChoice 375 return self.defaultBarType
271 end 376 end
272 377
273 function ReAction:SetConfigMode( mode ) 378 function ReAction:SetConfigMode( mode )
274 if mode ~= self.configMode then 379 if mode ~= self.configMode then
275 if mode then 380 if mode then
300 end 405 end
301 406
302 function ReAction:GetKeybindMode( mode ) 407 function ReAction:GetKeybindMode( mode )
303 return self.kbMode 408 return self.kbMode
304 end 409 end
410
411
412 -- ConfigMode support
413 CONFIGMODE_CALLBACKS = CONFIGMODE_CALLBACKS or {}
414
415 function CONFIGMODE_CALLBACKS.ReAction( action, mode )
416 if action == "ON" then
417 ReAction:SetConfigMode(true)
418 elseif action == "OFF" then
419 ReAction:SetConfigMode(false)
420 elseif action == "LISTMODES" then
421 -- no modes
422 end
423 end
424