Mercurial > wow > reaction
comparison modules/ReAction_ConfigUI/ReAction_ConfigUI.lua @ 33:c54c481ad0ed
- Moved bar control frame from ConfigUI to Bar
- Added LICENSE.txt
- added profile management options
- other minor cleanup
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Thu, 03 Apr 2008 20:25:40 +0000 |
parents | 0d95ce7a9ec2 |
children | 11ddb9610770 |
comparison
equal
deleted
inserted
replaced
32:821b2b7edff1 | 33:c54c481ad0ed |
---|---|
1 --[[ | 1 --[[ |
2 ReAction Configuration UI module | 2 ReAction Configuration UI module |
3 | 3 |
4 This modules creates and manages ReAction configuration | 4 Hooks into Blizzard Interface Options AddOns panel |
5 elements, including: | |
6 | |
7 - Interface Options panel | |
8 - bar dragging and resizing control overlays | |
9 - contextual menus | |
10 | |
11 Individual modules are responsible for populating these | |
12 configuration elements via ReAction:RegisterOptions(). The | |
13 valid values of 'context' are: | |
14 | |
15 - 'global' : added to the Global Settings tab | |
16 - 'module' : added to the Module Settings tab | |
17 - 'bar' : added to the Bar Settings tab | |
18 - 'barMenu' : shown on the bar contextual menu | |
19 | |
20 --]] | 5 --]] |
21 | 6 |
22 -- local imports | 7 -- local imports |
23 local ReAction = ReAction | 8 local ReAction = ReAction |
24 local L = ReAction.L | 9 local L = ReAction.L |
25 local _G = _G | |
26 local InCombatLockdown = InCombatLockdown | |
27 | |
28 local Dewdrop = AceLibrary("Dewdrop-2.0") | |
29 | 10 |
30 -- module declaration | 11 -- module declaration |
31 local moduleID = "ConfigUI" | 12 local moduleID = "ConfigUI" |
32 local module = ReAction:NewModule( moduleID, | 13 local module = ReAction:NewModule( moduleID ) |
33 "AceEvent-3.0" | |
34 ) | |
35 | 14 |
15 -- options table basic layer | |
36 module.configOptions = { | 16 module.configOptions = { |
37 type = "group", | 17 type = "group", |
38 childGroups = "tab", | 18 childGroups = "tab", |
39 args = { | 19 args = { |
40 desc = { | 20 desc = { |
92 self.db = ReAction.db:RegisterNamespace( moduleID, | 72 self.db = ReAction.db:RegisterNamespace( moduleID, |
93 { | 73 { |
94 profile = { } | 74 profile = { } |
95 } | 75 } |
96 ) | 76 ) |
97 self:InitializeOptions() | |
98 LibStub("AceConfig-3.0"):RegisterOptionsTable("ReAction",self.configOptions) | |
99 LibStub("AceConfigDialog-3.0"):AddToBlizOptions("ReAction", "ReAction") | |
100 self:RegisterEvent("PLAYER_REGEN_DISABLED") | |
101 end | |
102 | 77 |
103 function module:InitializeOptions() | |
104 for _, m in pairs(ReAction:GetOptions("global")) do | 78 for _, m in pairs(ReAction:GetOptions("global")) do |
105 for k, v in pairs(m) do | 79 for k, v in pairs(m) do |
106 self.configOptions.args.global.args[k] = v | 80 self.configOptions.args.global.args[k] = v |
107 end | 81 end |
108 end | 82 end |
83 | |
84 self.configOptions.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ReAction.db) | |
85 self.configOptions.args.profile.order = -2 | |
86 | |
87 LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("ReAction",self.configOptions) | |
88 LibStub("AceConfigDialog-3.0"):AddToBlizOptions("ReAction", "ReAction") | |
109 ReAction.RegisterCallback(self,"OnOptionsRegistered") | 89 ReAction.RegisterCallback(self,"OnOptionsRegistered") |
90 ReAction.RegisterCallback(self,"OnOptionsRefreshed") | |
110 end | 91 end |
111 | 92 |
112 function module:OnOptionsRegistered(evt, context, module, opts) | 93 function module:OnOptionsRegistered(evt, context, module, opts) |
113 if context == "global" then | 94 if context == "global" then |
114 for k, v in pairs(opts) do | 95 for k, v in pairs(opts) do |
123 elseif context == "barMenu" then | 104 elseif context == "barMenu" then |
124 | 105 |
125 end | 106 end |
126 end | 107 end |
127 | 108 |
128 function module:PLAYER_REGEN_DISABLED() | 109 function module:OnOptionsRefreshed(evt) |
129 if self.configMode == true then | 110 -- TODO: refresh options frame (just OpenConfig again?) |
130 UIErrorsFrame:AddMessage(L["ReAction config mode disabled during combat."]) | |
131 self:SetConfigMode(false) | |
132 end | |
133 end | |
134 | |
135 function module:SetConfigMode( mode ) | |
136 ReAction:CallMethodOnAllBars("ShowControls",mode) | |
137 ReAction:CallMethodOnAllModules("ApplyConfigMode",mode,ReAction.bars) | |
138 self.configMode = mode | |
139 end | |
140 | |
141 function module:ApplyConfigMode( mode, bars ) | |
142 if not(mode) then | |
143 -- close open dewdrop menu | |
144 local p = Dewdrop:GetOpenedParent() | |
145 if p then | |
146 for _, bar in pairs(bars) do | |
147 if bar then | |
148 if p == bar.controlFrame then | |
149 Dewdrop:Close() | |
150 end | |
151 end | |
152 end | |
153 end | |
154 end | |
155 end | |
156 | |
157 local function safecall(module, method, ...) | |
158 if module and type(module[method]) == "function" then | |
159 return module[method](method, ...) | |
160 end | |
161 end | 111 end |
162 | 112 |
163 function module:OpenConfig(bar) | 113 function module:OpenConfig(bar) |
164 Dewdrop:Close() | |
165 InterfaceOptionsFrame_OpenToFrame("ReAction") | 114 InterfaceOptionsFrame_OpenToFrame("ReAction") |
166 end | 115 if bar then |
167 | 116 -- TODO: select the correct bar pane |
168 function module:ApplyToBar(bar) | |
169 if self.configMode then | |
170 bar:ShowControls(self.configMode) | |
171 end | 117 end |
172 end | 118 end |
173 | |
174 function module:RemoveFromBar(bar) | |
175 if bar.controlFrame then | |
176 bar.controlFrame:SetParent(UIParent) | |
177 bar.controlFrame:ClearAllPoints() | |
178 bar.controlFrame:Hide() | |
179 bar.controlFrame = nil | |
180 end | |
181 end | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 -- | |
188 -- Bar config overlay | |
189 -- | |
190 -- import some of these for small OnUpdate performance boost | |
191 local Bar = ReAction.Bar.prototype | |
192 local GetSize = Bar.GetSize | |
193 local GetButtonSize = Bar.GetButtonSize | |
194 local GetButtonGrid = Bar.GetButtonGrid | |
195 local SetSize = Bar.SetSize | |
196 local SetButtonSize = Bar.SetButtonSize | |
197 local SetButtonGrid = Bar.SetButtonGrid | |
198 local ApplyAnchor = Bar.ApplyAnchor | |
199 local floor = math.floor | |
200 local min = math.min | |
201 local format = string.format | |
202 local GameTooltip = GameTooltip | |
203 | |
204 local function StoreExtents(bar) | |
205 local f = bar.frame | |
206 local point, relativeTo, relativePoint, x, y = f:GetPoint(1) | |
207 relativeTo = relativeTo or f:GetParent() | |
208 local anchorTo | |
209 for name, b in pairs(ReAction.bars) do | |
210 if b then | |
211 if b:GetFrame() == relativeTo then | |
212 anchorTo = name | |
213 break | |
214 end | |
215 end | |
216 end | |
217 anchorTo = anchorTo or relativeTo:GetName() | |
218 local c = bar.config | |
219 c.anchor = point | |
220 c.anchorTo = anchorTo | |
221 c.relativePoint = relativePoint | |
222 c.x = x | |
223 c.y = y | |
224 c.width, c.height = f:GetWidth(), f:GetHeight() | |
225 end | |
226 | |
227 local function RecomputeButtonSize(bar) | |
228 local w, h = GetSize(bar) | |
229 local bw, bh = GetButtonSize(bar) | |
230 local r, c, s = GetButtonGrid(bar) | |
231 | |
232 local scaleW = (floor(w/c) - s) / bw | |
233 local scaleH = (floor(h/r) - s) / bh | |
234 local scale = min(scaleW, scaleH) | |
235 | |
236 SetButtonSize(bar, scale * bw, scale * bh, s) | |
237 end | |
238 | |
239 local function RecomputeButtonSpacing(bar) | |
240 local w, h = GetSize(bar) | |
241 local bw, bh = GetButtonSize(bar) | |
242 local r, c, s = GetButtonGrid(bar) | |
243 | |
244 SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh)) | |
245 end | |
246 | |
247 local function RecomputeGrid(bar) | |
248 local w, h = GetSize(bar) | |
249 local bw, bh = GetButtonSize(bar) | |
250 local r, c, s = GetButtonGrid(bar) | |
251 | |
252 SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s) | |
253 end | |
254 | |
255 local function ClampToButtons(bar) | |
256 local bw, bh = GetButtonSize(bar) | |
257 local r, c, s = GetButtonGrid(bar) | |
258 SetSize(bar, (bw+s)*c, (bh+s)*r ) | |
259 end | |
260 | |
261 local function HideGameTooltip() | |
262 GameTooltip:Hide() | |
263 end | |
264 | |
265 local function CreateControls(bar) | |
266 local f = bar.frame | |
267 | |
268 f:SetMovable(true) | |
269 f:SetResizable(true) | |
270 f:SetClampedToScreen(true) | |
271 | |
272 -- buttons on the bar should be direct children of the bar frame. | |
273 -- The control elements need to float on top of this, which we could | |
274 -- do with SetFrameLevel() or Raise(), but it's more reliable to do it | |
275 -- via frame nesting, hence good old foo's appearance here. | |
276 local foo = CreateFrame("Frame",nil,f) | |
277 foo:SetAllPoints() | |
278 | |
279 local control = CreateFrame("Button", nil, foo) | |
280 control:EnableMouse(true) | |
281 control:SetToplevel(true) | |
282 control:SetPoint("TOPLEFT", -4, 4) | |
283 control:SetPoint("BOTTOMRIGHT", 4, -4) | |
284 control:SetBackdrop({ | |
285 edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", | |
286 tile = true, | |
287 tileSize = 16, | |
288 edgeSize = 16, | |
289 insets = { left = 0, right = 0, top = 0, bottom = 0 }, | |
290 }) | |
291 | |
292 -- textures | |
293 local bgTex = control:CreateTexture(nil,"BACKGROUND") | |
294 bgTex:SetTexture(0.7,0.7,1.0,0.2) | |
295 bgTex:SetPoint("TOPLEFT",4,-4) | |
296 bgTex:SetPoint("BOTTOMRIGHT",-4,4) | |
297 local hTex = control:CreateTexture(nil,"HIGHLIGHT") | |
298 hTex:SetTexture(0.7,0.7,1.0,0.2) | |
299 hTex:SetPoint("TOPLEFT",4,-4) | |
300 hTex:SetPoint("BOTTOMRIGHT",-4,4) | |
301 hTex:SetBlendMode("ADD") | |
302 | |
303 -- label | |
304 local label = control:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") | |
305 label:SetAllPoints() | |
306 label:SetJustifyH("CENTER") | |
307 label:SetShadowColor(0,0,0,1) | |
308 label:SetShadowOffset(2,-2) | |
309 label:SetTextColor(1,1,1,1) | |
310 label:SetText(bar:GetName()) | |
311 label:Show() | |
312 bar.controlLabelString = label -- so that bar:SetName() can update it | |
313 | |
314 local StopResize = function() | |
315 f:StopMovingOrSizing() | |
316 f.isMoving = false | |
317 f:SetScript("OnUpdate",nil) | |
318 StoreExtents(bar) | |
319 ClampToButtons(bar) | |
320 ApplyAnchor(bar) | |
321 end | |
322 | |
323 -- edge drag handles | |
324 for _, point in pairs({"LEFT","TOP","RIGHT","BOTTOM"}) do | |
325 local edge = CreateFrame("Frame",nil,control) | |
326 edge:EnableMouse(true) | |
327 edge:SetWidth(8) | |
328 edge:SetHeight(8) | |
329 if point == "TOP" or point == "BOTTOM" then | |
330 edge:SetPoint(point.."LEFT") | |
331 edge:SetPoint(point.."RIGHT") | |
332 else | |
333 edge:SetPoint("TOP"..point) | |
334 edge:SetPoint("BOTTOM"..point) | |
335 end | |
336 local tex = edge:CreateTexture(nil,"HIGHLIGHT") | |
337 tex:SetTexture(1.0,0.82,0,0.7) | |
338 tex:SetBlendMode("ADD") | |
339 tex:SetAllPoints() | |
340 edge:RegisterForDrag("LeftButton") | |
341 edge:SetScript("OnMouseDown", | |
342 function() | |
343 local bw, bh = GetButtonSize(bar) | |
344 local r, c, s = GetButtonGrid(bar) | |
345 f:SetMinResize( bw+s+1, bh+s+1 ) | |
346 f:StartSizing(point) | |
347 f:SetScript("OnUpdate", | |
348 function() | |
349 RecomputeGrid(bar) | |
350 bar:RefreshLayout() | |
351 end | |
352 ) | |
353 end | |
354 ) | |
355 edge:SetScript("OnMouseUp", StopResize) | |
356 edge:SetScript("OnEnter", | |
357 function() | |
358 GameTooltip:SetOwner(f, "ANCHOR_"..point) | |
359 GameTooltip:AddLine(L["Drag to add/remove buttons"]) | |
360 GameTooltip:Show() | |
361 end | |
362 ) | |
363 edge:SetScript("OnLeave", HideGameTooltip) | |
364 edge:Show() | |
365 end | |
366 | |
367 -- corner drag handles, again nested in an anonymous frame so that they are on top | |
368 local foo2 = CreateFrame("Frame",nil,control) | |
369 foo2:SetAllPoints(true) | |
370 for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do | |
371 local corner = CreateFrame("Frame",nil,foo2) | |
372 corner:EnableMouse(true) | |
373 corner:SetWidth(12) | |
374 corner:SetHeight(12) | |
375 corner:SetPoint(point) | |
376 local tex = corner:CreateTexture(nil,"HIGHLIGHT") | |
377 tex:SetTexture(1.0,0.82,0,0.7) | |
378 tex:SetBlendMode("ADD") | |
379 tex:SetAllPoints() | |
380 corner:RegisterForDrag("LeftButton","RightButton") | |
381 local updateTooltip = function() | |
382 local size, size2 = bar:GetButtonSize() | |
383 local rows, cols, spacing = bar:GetButtonGrid() | |
384 size = (size == size2) and tostring(size) or format("%dx%d",size,size2) | |
385 GameTooltipTextRight4:SetText(size) | |
386 GameTooltipTextRight5:SetText(tostring(spacing)) | |
387 end | |
388 corner:SetScript("OnMouseDown", | |
389 function(_,btn) | |
390 local bw, bh = GetButtonSize(bar) | |
391 local r, c, s = GetButtonGrid(bar) | |
392 if btn == "LeftButton" then -- button resize | |
393 f:SetMinResize( (s+12)*c+1, (s+12)*r+1 ) | |
394 f:SetScript("OnUpdate", | |
395 function() | |
396 RecomputeButtonSize(bar) | |
397 bar:RefreshLayout() | |
398 updateTooltip() | |
399 end | |
400 ) | |
401 elseif btn == "RightButton" then -- spacing resize | |
402 f:SetMinResize( bw*c, bh*r ) | |
403 f:SetScript("OnUpdate", | |
404 function() | |
405 RecomputeButtonSpacing(bar) | |
406 bar:RefreshLayout() | |
407 updateTooltip() | |
408 end | |
409 ) | |
410 end | |
411 f:StartSizing(point) | |
412 end | |
413 ) | |
414 corner:SetScript("OnMouseUp",StopResize) | |
415 corner:SetScript("OnEnter", | |
416 function() | |
417 GameTooltip:SetOwner(f, "ANCHOR_"..point) | |
418 GameTooltip:AddLine(L["Drag to resize buttons"]) | |
419 GameTooltip:AddLine(L["Right-click-drag"]) | |
420 GameTooltip:AddLine(L["to change spacing"]) | |
421 local size, size2 = bar:GetButtonSize() | |
422 local rows, cols, spacing = bar:GetButtonGrid() | |
423 size = (size == size2) and tostring(size) or format("%dx%d",size,size2) | |
424 GameTooltip:AddDoubleLine(L["Size:"], size) | |
425 GameTooltip:AddDoubleLine(L["Spacing:"], tostring(spacing)) | |
426 GameTooltip:Show() | |
427 end | |
428 ) | |
429 corner:SetScript("OnLeave", | |
430 function() | |
431 GameTooltip:Hide() | |
432 f:SetScript("OnUpdate",nil) | |
433 end | |
434 ) | |
435 | |
436 end | |
437 | |
438 control:RegisterForDrag("LeftButton") | |
439 control:RegisterForClicks("RightButtonDown") | |
440 | |
441 control:SetScript("OnDragStart", | |
442 function() | |
443 f:StartMoving() | |
444 f.isMoving = true | |
445 -- TODO: snap indicator update install | |
446 end | |
447 ) | |
448 | |
449 control:SetScript("OnDragStop", | |
450 function() | |
451 f:StopMovingOrSizing() | |
452 f.isMoving = false | |
453 f:SetScript("OnUpdate",nil) | |
454 -- TODO: snap frame here | |
455 StoreExtents(bar) | |
456 end | |
457 ) | |
458 | |
459 control:SetScript("OnEnter", | |
460 function() | |
461 -- add bar type and status information to name | |
462 local name = bar.name | |
463 for _, m in ReAction:IterateModules() do | |
464 local suffix = safecall(m,"GetBarNameModifier",bar) | |
465 if suffix then | |
466 name = ("%s %s"):format(name,suffix) | |
467 end | |
468 end | |
469 | |
470 GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT") | |
471 GameTooltip:AddLine(name) | |
472 GameTooltip:AddLine(L["Drag to move"]) | |
473 --GameTooltip:AddLine(L["Shift-drag for sticky mode"]) | |
474 GameTooltip:AddLine(L["Right-click for options"]) | |
475 GameTooltip:Show() | |
476 end | |
477 ) | |
478 | |
479 control:SetScript("OnLeave", HideGameTooltip) | |
480 | |
481 control:SetScript("OnClick", | |
482 function() | |
483 bar:ShowMenu() | |
484 end | |
485 ) | |
486 | |
487 return control | |
488 end | |
489 | |
490 function Bar:ShowControls(show) | |
491 if show then | |
492 if not self.controlFrame then | |
493 self.controlFrame = CreateControls(self) | |
494 end | |
495 self.controlFrame:Show() | |
496 elseif self.controlFrame then | |
497 self.controlFrame:Hide() | |
498 end | |
499 end | |
500 | |
501 function Bar:ShowMenu() | |
502 if not self.menuOpts then | |
503 self.menuOpts = { | |
504 type = "group", | |
505 args = { | |
506 openConfig = { | |
507 type = "execute", | |
508 name = L["Configure..."], | |
509 desc = L["Open the configuration dialogue for this bar"], | |
510 func = function() module:OpenConfig(self) end, | |
511 disabled = InCombatLockdown, | |
512 order = 1 | |
513 }, | |
514 delete = { | |
515 type = "execute", | |
516 name = L["Delete Bar"], | |
517 desc = L["Remove the bar from the current profile"], | |
518 func = function() ReAction:EraseBar(self) end, | |
519 order = 2 | |
520 }, | |
521 } | |
522 } | |
523 end | |
524 if self.modMenuOpts == nil then | |
525 self.modMenuOpts = { } | |
526 end | |
527 for _, m in ReAction:IterateModules() do | |
528 local opts = safecall(m,"GetBarMenuOptions",self,module) | |
529 if opts then | |
530 for k, v in pairs(opts) do | |
531 self.menuOpts.args[k] = v | |
532 end | |
533 end | |
534 end | |
535 Dewdrop:Open(self.controlFrame, "children", self.menuOpts, "cursorX", true, "cursorY", true) | |
536 end | |
537 | |
538 local Bar_SuperSetName = Bar.SetName | |
539 function Bar:SetName(name) | |
540 Bar_SuperSetName(self,name) | |
541 if self.controlLabelString then | |
542 self.controlLabelString:SetText(self.name) | |
543 end | |
544 end |