vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 Name: FuBarPlugin-2.0
3 Revision: $Rev: 7560 $
4 Author: Cameron Kenneth Knight (ckknight@gmail.com)
5 Website: http://wiki.wowace.com/index.php/FuBarPlugin-2.0
6 Documentation: http://wiki.wowace.com/index.php/FuBarPlugin-2.0
7 SVN: svn://svn.wowace.com/root/branches/FuBar/FuBarPlugin-2.0/FuBarPlugin-2.0/
8 Description: Plugin for FuBar.
9 Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0, Tablet-2.0, Dewdrop-2.0
10 ]]
11  
12 local MAJOR_VERSION = "FuBarPlugin-2.0"
13 local MINIMAPCONTAINER_MAJOR_VERSION = "FuBarPlugin-MinimapContainer-2.0"
14 local MINOR_VERSION = "$Revision: 7560 $"
15  
16 -- This ensures the code is only executed if the libary doesn't already exist, or is a newer version
17 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
18 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
19  
20 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0.") end
21  
22 local AceEvent = AceLibrary:HasInstance("AceEvent-2.0") and AceLibrary("AceEvent-2.0")
23 local Tablet = AceLibrary:HasInstance("Tablet-2.0") and AceLibrary("Tablet-2.0")
24 local Dewdrop = AceLibrary:HasInstance("Dewdrop-2.0") and AceLibrary("Dewdrop-2.0")
25  
26 local epsilon = 1e-5
27 local _G = getfenv(0)
28  
29 local FuBarPlugin = AceLibrary("AceOO-2.0").Mixin {
30 "GetTitle",
31 "GetName",
32 "GetCategory",
33 "SetFontSize",
34 "GetFrame",
35 "Show",
36 "Hide",
37 "GetPanel",
38 "IsTextColored",
39 "ToggleTextColored",
40 "IsMinimapAttached",
41 "ToggleMinimapAttached",
42 "Update",
43 "UpdateDisplay",
44 "UpdateData",
45 "UpdateText",
46 "UpdateTooltip",
47 "SetIcon",
48 "GetIcon",
49 "CheckWidth",
50 "SetText",
51 "GetText",
52 "IsIconShown",
53 "ToggleIconShown",
54 "ShowIcon",
55 "HideIcon",
56 "IsTextShown",
57 "ToggleTextShown",
58 "ShowText",
59 "HideText",
60 "IsTooltipDetached",
61 "ToggleTooltipDetached",
62 "DetachTooltip",
63 "ReattachTooltip",
64 "GetDefaultPosition",
65 "SetPanel",
66 "IsLoadOnDemand",
67 "IsDisabled",
68 "CreateBasicPluginFrame",
69 "CreatePluginChildFrame",
70 "OpenMenu",
71 "AddImpliedMenuOptions",
72 }
73  
74 local good = nil
75 local function CheckFuBar()
76 if not good then
77 good = FuBar and tonumber(string.sub(FuBar.version, 1, 3)) and tonumber(string.sub(FuBar.version, 1, 3)) >= 2 and true
78 end
79 return good
80 end
81  
82 function FuBarPlugin:GetTitle()
83 local name = self.title or self.name
84 FuBarPlugin:assert(name, "You must provide self.title or self.name")
85 local _,_,title = string.find(name, "FuBar %- (.+)")
86 if not title then
87 title = name
88 end
89 return (string.gsub(title, "|c%x%x%x%x%x%x%x%x(.-)|r", "%1"))
90 end
91  
92 function FuBarPlugin:GetName()
93 return self.name
94 end
95  
96 function FuBarPlugin:GetCategory()
97 return self.category or "Other"
98 end
99  
100 function FuBarPlugin:GetFrame()
101 return self.frame
102 end
103  
104 function FuBarPlugin:GetPanel()
105 return self.panel
106 end
107  
108 function FuBarPlugin:IsTextColored()
109 return not self.db or not self.db.profile or not self.db.profile.uncolored
110 end
111  
112 function FuBarPlugin:IsTextShown()
113 return not self.hasNoText and (not self.db or not self.db.profile or self.db.profile.showText ~= 0)
114 end
115  
116 function FuBarPlugin:ToggleTextColored()
117 self.db.profile.uncolored = not self.db.profile.uncolored or nil
118 self:UpdateText()
119 end
120  
121 function FuBarPlugin:ToggleMinimapAttached()
122 if CheckFuBar() and not self.cannotAttachToMinimap then
123 local value = self:IsMinimapAttached()
124 if value then
125 self.panel:RemovePlugin(self)
126 FuBar:GetPanel(1):AddPlugin(self, nil, self.defaultPosition)
127 else
128 self.panel:RemovePlugin(self)
129 AceLibrary(MINIMAPCONTAINER_MAJOR_VERSION):AddPlugin(self)
130 end
131 end
132 Dewdrop:Close()
133 end
134  
135 function FuBarPlugin:IsMinimapAttached()
136 if not CheckFuBar() then
137 return true
138 end
139 return self.panel == AceLibrary(MINIMAPCONTAINER_MAJOR_VERSION)
140 end
141  
142 function FuBarPlugin:Update()
143 self:UpdateData()
144 self:UpdateText()
145 self:UpdateTooltip()
146 end
147  
148 function FuBarPlugin:UpdateDisplay()
149 self:UpdateText()
150 self:UpdateTooltip()
151 end
152  
153 function FuBarPlugin:UpdateData()
154 if type(self.OnDataUpdate) == "function" then
155 if not self:IsDisabled() then
156 self:OnDataUpdate()
157 end
158 end
159 end
160  
161 function FuBarPlugin:UpdateText()
162 if type(self.OnTextUpdate) == "function" then
163 if not self:IsDisabled() then
164 self:OnTextUpdate()
165 end
166 elseif self:IsTextShown() then
167 self:SetText(self:GetTitle())
168 end
169 end
170  
171 function FuBarPlugin:RegisterTablet()
172 if not Tablet:IsRegistered(self.frame) then
173 if self.db and self.db.profile and not self.db.profile.detachedTooltip then
174 self.db.profile.detachedTooltip = {}
175 end
176 Tablet:Register(self.frame,
177 'children', function()
178 Tablet:SetTitle(self:GetTitle())
179 if type(self.OnTooltipUpdate) == "function" then
180 if not self:IsDisabled() then
181 self:OnTooltipUpdate()
182 end
183 end
184 end,
185 'clickable', self.clickableTooltip,
186 'data', CheckFuBar() and FuBar.db.profile.tooltip or self.db and self.db.profile.detachedTooltip or {},
187 'detachedData', self.db and self.db.profile.detachedTooltip or {},
188 'point', function(frame)
189 if frame:GetTop() > GetScreenHeight() / 2 then
190 local x = frame:GetCenter()
191 if x < GetScreenWidth() / 3 then
192 return "TOPLEFT", "BOTTOMLEFT"
193 elseif x < GetScreenWidth() * 2 / 3 then
194 return "TOP", "BOTTOM"
195 else
196 return "TOPRIGHT", "BOTTOMRIGHT"
197 end
198 else
199 local x = frame:GetCenter()
200 if x < GetScreenWidth() / 3 then
201 return "BOTTOMLEFT", "TOPLEFT"
202 elseif x < GetScreenWidth() * 2 / 3 then
203 return "BOTTOM", "TOP"
204 else
205 return "BOTTOMRIGHT", "TOPRIGHT"
206 end
207 end
208 end,
209 'menu', self.OnMenuRequest and function(level, value, valueN_1, valueN_2, valueN_3, valueN_4)
210 if level == 1 then
211 local name = tostring(self)
212 if not string.find(name, '^table:') then
213 name = string.gsub(name, "|c%x%x%x%x%x%x%x%x(.-)|r", "%1")
214 Dewdrop:AddLine(
215 'text', name,
216 'isTitle', true
217 )
218 end
219 end
220 if type(self.OnMenuRequest) == "function" then
221 self:OnMenuRequest(level, value, true, valueN_1, valueN_2, valueN_3, valueN_4)
222 elseif type(self.OnMenuRequest) == "table" then
223 Dewdrop:FeedAceOptionsTable(self.OnMenuRequest)
224 end
225 end
226 )
227 end
228 end
229  
230 function FuBarPlugin:UpdateTooltip()
231 FuBarPlugin.RegisterTablet(self)
232 if self:IsMinimapAttached() then
233 Tablet:Refresh(self.minimapFrame)
234 else
235 Tablet:Refresh(self.frame)
236 end
237 end
238  
239 function FuBarPlugin:OnProfileEnable()
240 self:Update()
241 end
242  
243 function FuBarPlugin:Show(panelId)
244 if self.frame:IsShown() or (self.minimapFrame and self.minimapFrame:IsShown()) then
245 return
246 end
247 if panelId ~= false then
248 if self.db then
249 self.db.profile.hidden = nil
250 end
251 end
252 if self.IsActive and not self:IsActive() then
253 self.panelIdTmp = panelId
254 self:ToggleActive()
255 self.panelIdTmp = nil
256 if self.db then
257 self.db.profile.disabled = nil
258 end
259 elseif not self.db or not self.db.profile.hidden then
260 if panelId == 0 or not CheckFuBar() then
261 AceLibrary(MINIMAPCONTAINER_MAJOR_VERSION):AddPlugin(self)
262 else
263 FuBar:ShowPlugin(self, panelId or self.panelIdTmp)
264 end
265 self:Update()
266 end
267 end
268  
269 function FuBarPlugin:Hide()
270 if not self.frame:IsShown() and (not self.minimapFrame or not self.minimapFrame:IsShown()) then
271 return
272 end
273 if self.hideWithoutStandby then
274 if self.db then
275 self.db.profile.hidden = true
276 end
277 end
278 if not self.hideWithoutStandby then
279 if self.db and not self.overrideTooltip and not self.cannotDetachTooltip and self:IsTooltipDetached() and self.db.profile.detachedTooltip and self.db.profile.detachedTooltip.detached then
280 self:ReattachTooltip()
281 self.db.profile.detachedTooltip.detached = true
282 end
283 if self.IsActive and self:IsActive() and self.ToggleActive and (not CheckFuBar() or not FuBar:IsChangingProfile()) then
284 self:ToggleActive()
285 end
286 end
287 if self.panel then
288 self.panel:RemovePlugin(self)
289 end
290 self.frame:Hide()
291 if self.minimapFrame then
292 self.minimapFrame:Hide()
293 end
294  
295 if Dewdrop:IsOpen(self.frame) or (self.minimapFrame and Dewdrop:IsOpen(self.minimapFrame)) then
296 Dewdrop:Close()
297 end
298 end
299  
300 function FuBarPlugin:SetIcon(path)
301 if not path then
302 return
303 end
304 FuBarPlugin:argCheck(path, 2, "string", "boolean")
305 FuBarPlugin:assert(self.hasIcon, "Cannot set icon unless self.hasIcon is set. (" .. self:GetTitle() .. ")")
306 if not self.iconFrame then
307 return
308 end
309 if type(path) ~= "string" then
310 path = format("Interface\\AddOns\\%s\\icon", self.folderName)
311 elseif not string.find(path, '^Interface[\\/]') then
312 path = format("Interface\\AddOns\\%s\\%s", self.folderName, path)
313 end
314 if string.sub(path, 1, 16) == "Interface\\Icons\\" then
315 self.iconFrame:SetTexCoord(0.05, 0.95, 0.05, 0.95)
316 else
317 self.iconFrame:SetTexCoord(0, 1, 0, 1)
318 end
319 self.iconFrame:SetTexture(path)
320 if self.minimapIcon then
321 if string.sub(path, 1, 16) == "Interface\\Icons\\" then
322 self.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
323 else
324 self.minimapIcon:SetTexCoord(0, 1, 0, 1)
325 end
326 self.minimapIcon:SetTexture(path)
327 end
328 end
329  
330 function FuBarPlugin:GetIcon()
331 if self.hasIcon then
332 return self.iconFrame:GetTexture()
333 end
334 end
335  
336 function FuBarPlugin:CheckWidth(force)
337 FuBarPlugin:argCheck(force, 2, "boolean", "nil")
338 if (self.iconFrame and self.iconFrame:IsShown()) or (self.textFrame and self.textFrame:IsShown()) then
339 if (self.db and self.db.profile and not self:IsIconShown()) or not self.hasIcon then
340 self.iconFrame:SetWidth(epsilon)
341 end
342 local width
343 if not self.hasNoText then
344 self.textFrame:SetHeight(0)
345 self.textFrame:SetWidth(500)
346 width = self.textFrame:GetStringWidth() + 1
347 self.textFrame:SetWidth(width)
348 self.textFrame:SetHeight(self.textFrame:GetHeight())
349 end
350 if self.hasNoText or not self.textFrame:IsShown() then
351 self.frame:SetWidth(self.iconFrame:GetWidth())
352 if self.panel and self.panel:GetPluginSide(self) == "CENTER" then
353 self.panel:UpdateCenteredPosition()
354 end
355 elseif force or not self.textWidth or self.textWidth < width or self.textWidth - 8 > width then
356 self.textWidth = width
357 self.textFrame:SetWidth(width)
358 if self.iconFrame and self.iconFrame:IsShown() then
359 self.frame:SetWidth(width + self.iconFrame:GetWidth())
360 else
361 self.frame:SetWidth(width)
362 end
363 if self.panel and self.panel:GetPluginSide(self) == "CENTER" then
364 self.panel:UpdateCenteredPosition()
365 end
366 end
367 end
368 end
369  
370 function FuBarPlugin:SetText(text)
371 if not self.textFrame then
372 return
373 end
374 FuBarPlugin:assert(not self.hasNoText, "Cannot set text if self.hasNoText has been set. (" .. self:GetTitle() .. ")")
375 FuBarPlugin:argCheck(text, 2, "string", "number")
376 if text == "" then
377 if self.hasIcon then
378 self:ShowIcon()
379 else
380 text = self:GetTitle()
381 end
382 end
383 if not self:IsTextColored() then
384 text = string.gsub(text, "|c%x%x%x%x%x%x%x%x(.-)|r", "%1")
385 end
386 self.textFrame:SetText(text)
387 self:CheckWidth()
388 end
389  
390 function FuBarPlugin:GetText()
391 FuBarPlugin:assert(self.textFrame, "Cannot get text without a self.textFrame (" .. self:GetTitle() .. ")")
392 if not self.hasNoText then
393 return self.textFrame:GetText() or ""
394 end
395 end
396  
397 function FuBarPlugin:IsIconShown()
398 if not self.hasIcon then
399 return false
400 elseif self.hasNoText then
401 return true
402 elseif not self.db then
403 return true
404 elseif not self.db.profile.showIcon then
405 return true
406 else
407 return (self.db.profile.showIcon == 1 or self.db.profile.showIcon == true) and true or false
408 end
409 end
410  
411 function FuBarPlugin:ToggleIconShown()
412 FuBarPlugin:assert(self.iconFrame, "Cannot toggle icon without a self.iconFrame (" .. self:GetTitle() .. ")")
413 FuBarPlugin:assert(self.hasIcon, "Cannot show icon unless self.hasIcon is set. (" .. self:GetTitle() .. ")")
414 FuBarPlugin:assert(not self.hasNoText, "Cannot hide icon if self.hasNoText is set. (" .. self:GetTitle() .. ")")
415 FuBarPlugin:assert(self.textFrame, "Cannot hide icon if self.textFrame is not set. (" .. self:GetTitle() .. ")")
416 FuBarPlugin:assert(self.iconFrame, "Cannot hide icon if self.iconFrame is not set. (" .. self:GetTitle() .. ")")
417 local value = not self:IsIconShown()
418 self.db.profile.showIcon = value and 1 or 0
419 if value then
420 if not self:IsTextShown() and self.textFrame:IsShown() and self.textFrame:GetText() == self:GetTitle() then
421 self.textFrame:Hide()
422 self.textFrame:SetText("")
423 end
424 self.iconFrame:Show()
425 self.iconFrame:SetWidth(self.iconFrame:GetHeight())
426 else
427 if not self.textFrame:IsShown() or not self.textFrame:GetText() then
428 self.textFrame:Show()
429 self.textFrame:SetText(self:GetTitle())
430 end
431 self.iconFrame:Hide()
432 self.iconFrame:SetWidth(epsilon)
433 end
434 self:CheckWidth(true)
435 return value
436 end
437  
438 function FuBarPlugin:ShowIcon()
439 if not self:IsIconShown() then
440 self:ToggleIconShown()
441 end
442 end
443  
444 function FuBarPlugin:HideIcon()
445 if self:IsIconShown() then
446 self:ToggleIconShown()
447 end
448 end
449  
450 function FuBarPlugin:IsTextShown()
451 if not self.hasIcon then
452 return false
453 elseif self.hasNoText then
454 return false
455 elseif not self.db then
456 return true
457 elseif not self.db.profile.showText then
458 return true
459 else
460 return (self.db.profile.showText == 1 or self.db.profile.showText == true) and true or false
461 end
462 end
463  
464 function FuBarPlugin:ToggleTextShown()
465 FuBarPlugin:assert(not self.cannotHideText, "Cannot hide text unless self.cannotHideText is unset. (" .. self:GetTitle() .. ")")
466 FuBarPlugin:assert(self.hasIcon, "Cannot show text unless self.hasIcon is set. (" .. self:GetTitle() .. ")")
467 FuBarPlugin:assert(not self.hasNoText, "Cannot hide text if self.hasNoText is set. (" .. self:GetTitle() .. ")")
468 FuBarPlugin:assert(self.textFrame, "Cannot hide text if self.textFrame is not set. (" .. self:GetTitle() .. ")")
469 FuBarPlugin:assert(self.iconFrame, "Cannot hide text if self.iconFrame is not set. (" .. self:GetTitle() .. ")")
470 local value = not self:IsTextShown()
471 self.db.profile.showText = value and 1 or 0
472 if value then
473 self.textFrame:Show()
474 self:UpdateText()
475 else
476 self.textFrame:SetText("")
477 self.textFrame:SetWidth(epsilon)
478 self.textFrame:Hide()
479 if not self:IsIconShown() then
480 DropDownList1:Hide()
481 end
482 self:ShowIcon()
483 end
484 self:CheckWidth(true)
485 return value
486 end
487  
488 function FuBarPlugin:ShowText()
489 if not self:IsTextShown() then
490 self:ToggleTextShown()
491 end
492 end
493  
494 function FuBarPlugin:HideText()
495 if self:IsTextShown() then
496 self:ToggleTextShown()
497 end
498 end
499  
500 function FuBarPlugin:IsTooltipDetached()
501 if not Tablet.registry[self.frame] then
502 self:UpdateTooltip()
503 end
504 return not Tablet:IsAttached(self.frame)
505 end
506  
507 function FuBarPlugin:ToggleTooltipDetached()
508 if self:IsTooltipDetached() then
509 Tablet:Attach(self.frame)
510 else
511 Tablet:Detach(self.frame)
512 end
513 end
514  
515 function FuBarPlugin:DetachTooltip()
516 Tablet:Detach(self.frame)
517 end
518  
519 function FuBarPlugin:ReattachTooltip()
520 Tablet:Attach(self.frame)
521 end
522  
523 function FuBarPlugin:GetDefaultPosition()
524 return self.defaultPosition or "LEFT"
525 end
526  
527 local function IsCorrectPanel(panel)
528 if type(panel) ~= "table" then
529 return false
530 elseif type(panel.AddPlugin) ~= "function" then
531 return false
532 elseif type(panel.RemovePlugin) ~= "function" then
533 return false
534 elseif type(panel.GetNumPlugins) ~= "function" then
535 return false
536 elseif type(panel:GetNumPlugins()) ~= "number" then
537 return false
538 elseif type(panel.GetPlugin) ~= "function" then
539 return false
540 elseif type(panel.HasPlugin) ~= "function" then
541 return false
542 elseif type(panel.GetPluginSide) ~= "function" then
543 return false
544 end
545 return true
546 end
547  
548 function FuBarPlugin:SetPanel(panel)
549 if panel then
550 FuBarPlugin:assert(IsCorrectPanel(panel), "Bad argument #2 to `SetPanel'. Panel does not have the correct API.")
551 end
552 self.panel = panel
553 end
554  
555 function FuBarPlugin:SetFontSize(size)
556 FuBarPlugin:assert(not self.userDefinedFrame, "You must provide a SetFontSize(size) method if you provide your own frame.")
557 if self.hasIcon then
558 FuBarPlugin:assert(self.iconFrame, (self.name and self.name .. ": " or "") .. "No iconFrame found")
559 self.iconFrame:SetWidth(size + 3)
560 self.iconFrame:SetHeight(size + 3)
561 end
562 if not self.hasNoText then
563 FuBarPlugin:assert(self.textFrame, (self.name and self.name .. ": " or "") .. "No textFrame found")
564 local font, _, flags = self.textFrame:GetFont()
565 self.textFrame:SetFont(font, size, flags)
566 end
567 self:CheckWidth()
568 end
569  
570 function FuBarPlugin:IsLoadOnDemand()
571 return IsAddOnLoadOnDemand(self.folderName)
572 end
573  
574 function FuBarPlugin:IsDisabled()
575 return self.IsActive and not self:IsActive() or false
576 end
577  
578 function FuBarPlugin:OnInstanceInit(target)
579 if not AceEvent then
580 self:error(MAJOR_VERSION .. " requires AceEvent-2.0.")
581 elseif not Tablet then
582 self:error(MAJOR_VERSION .. " requires Tablet-2.0.")
583 elseif not Dewdrop then
584 self:error(MAJOR_VERSION .. " requires Dewdrop-2.0.")
585 end
586 self.registry[target] = true
587  
588 local _,_,folderName = string.find(debugstack(6, 1, 0), "\\AddOns\\(.*)\\")
589 target.folderName = folderName
590 self.folderNames[target] = folderName
591  
592 -- self:ScheduleEvent(FuBarPlugin.RegisterForLoad, 0, target)
593 end
594  
595 function FuBarPlugin:CreateBasicPluginFrame(name)
596 local frame = CreateFrame("Button", name, UIParent)
597 frame:SetFrameStrata("HIGH")
598 frame:EnableMouse(true)
599 frame:EnableMouseWheel(true)
600 frame:SetMovable(true)
601 frame:SetWidth(150)
602 frame:SetHeight(24)
603 frame:SetPoint("CENTER", UIParent, "CENTER")
604  
605 frame:SetScript("OnClick", function()
606 if type(self.OnClick) == "function" then
607 self:OnClick(arg1)
608 end
609 end)
610 frame:SetScript("OnDoubleClick", function()
611 if type(self.OnDoubleClick) == "function" then
612 self:OnDoubleClick(arg1)
613 end
614 end)
615 frame:SetScript("OnMouseDown", function()
616 if arg1 == "RightButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then
617 self:OpenMenu()
618 return
619 else
620 HideDropDownMenu(1)
621 if type(self.OnMouseDown) == "function" then
622 self:OnMouseDown(arg1)
623 end
624 end
625 end)
626 frame:SetScript("OnMouseUp", function()
627 if type(self.OnMouseUp) == "function" then
628 self:OnMouseUp(arg1)
629 end
630 end)
631 frame:SetScript("OnReceiveDrag", function()
632 if type(self.OnReceiveDrag) == "function" then
633 self:OnReceiveDrag()
634 end
635 end)
636 return frame
637 end
638  
639 function FuBarPlugin:CreatePluginChildFrame(frameType, name, parent)
640 FuBarPlugin:assert(self.frame, "You must have self.frame declared in order to add child frames")
641 FuBarPlugin:argCheck(frameType, 1, "string")
642 local child = CreateFrame(frameType, name, parent)
643 if parent then
644 child:SetFrameLevel(parent:GetFrameLevel() + 2)
645 end
646 child:SetScript("OnEnter", function()
647 if self.frame:GetScript("OnEnter") then
648 self.frame:GetScript("OnEnter")()
649 end
650 end)
651 child:SetScript("OnLeave", function()
652 if self.frame:GetScript("OnLeave") then
653 self.frame:GetScript("OnLeave")()
654 end
655 end)
656 if child:HasScript("OnClick") then
657 child:SetScript("OnClick", function()
658 if self.frame:HasScript("OnClick") and self.frame:GetScript("OnClick") then
659 self.frame:GetScript("OnClick")()
660 end
661 end)
662 end
663 if child:HasScript("OnDoubleClick") then
664 child:SetScript("OnDoubleClick", function()
665 if self.frame:HasScript("OnDoubleClick") and self.frame:GetScript("OnDoubleClick") then
666 self.frame:GetScript("OnDoubleClick")()
667 end
668 end)
669 end
670 child:SetScript("OnMouseDown", function()
671 if self.frame:GetScript("OnMouseDown") then
672 self.frame:GetScript("OnMouseDown")()
673 end
674 end)
675 child:SetScript("OnMouseUp", function()
676 if self.frame:GetScript("OnMouseUp") then
677 self.frame:GetScript("OnMouseUp")()
678 end
679 end)
680 child:SetScript("OnReceiveDrag", function()
681 if self.frame:GetScript("OnReceiveDrag") then
682 self.frame:GetScript("OnReceiveDrag")()
683 end
684 end)
685 return child
686 end
687  
688 function FuBarPlugin:OpenMenu(frame)
689 if not frame then
690 frame = self:GetFrame()
691 end
692 if not frame or not self:GetFrame() or Dewdrop:IsOpen(frame) then
693 Dewdrop:Close()
694 return
695 end
696 Tablet:Close()
697  
698 if not Dewdrop:IsRegistered(self:GetFrame()) then
699 if type(self.OnMenuRequest) == "table" and (not self.OnMenuRequest.handler or self.OnMenuRequest.handler == self) and self.OnMenuRequest.type == "group" then
700 Dewdrop:InjectAceOptionsTable(self, self.OnMenuRequest)
701 if self.OnMenuRequest.args and CheckFuBar() then
702 self.OnMenuRequest.args.profile = nil
703 end
704 end
705 Dewdrop:Register(self:GetFrame(),
706 'children', type(self.OnMenuRequest) == "table" and self.OnMenuRequest or function(level, value, valueN_1, valueN_2, valueN_3, valueN_4)
707 if level == 1 then
708 Dewdrop:AddLine(
709 'text', self:GetTitle(),
710 'isTitle', true
711 )
712 end
713  
714 if level == 1 then
715 if self.OnMenuRequest then
716 self:OnMenuRequest(level, value, false, valueN_1, valueN_2, valueN_3, valueN_4)
717 end
718  
719 if not self.overrideMenu then
720 if self.MenuSettings then
721 Dewdrop:AddLine()
722 end
723 self:AddImpliedMenuOptions()
724 end
725 else
726 if not self.overrideMenu and self:AddImpliedMenuOptions() then
727 else
728 if self.OnMenuRequest then
729 self:OnMenuRequest(level, value, false, valueN_1, valueN_2, valueN_3, valueN_4)
730 end
731 end
732 end
733 if level == 1 then
734 Dewdrop:AddLine(
735 'text', CLOSE,
736 'func', Dewdrop.Close,
737 'arg1', Dewdrop
738 )
739 end
740 end,
741 'point', function(frame)
742 local x, y = frame:GetCenter()
743 local leftRight
744 if x < GetScreenWidth() / 2 then
745 leftRight = "LEFT"
746 else
747 leftRight = "RIGHT"
748 end
749 if y < GetScreenHeight() / 2 then
750 return "BOTTOM" .. leftRight, "TOP" .. leftRight
751 else
752 return "TOP" .. leftRight, "BOTTOM" .. leftRight
753 end
754 end,
755 'dontHook', true
756 )
757 end
758 if frame == self:GetFrame() then
759 Dewdrop:Open(self:GetFrame())
760 else
761 Dewdrop:Open(frame, self:GetFrame())
762 end
763 end
764  
765 local impliedMenuOptions
766 function FuBarPlugin:AddImpliedMenuOptions(level)
767 FuBarPlugin:argCheck(level, 2, "number", "nil")
768 if not impliedMenuOptions then
769 impliedMenuOptions = {}
770 end
771 if not impliedMenuOptions[self] then
772 impliedMenuOptions[self] = { type = 'group', args = {} }
773 Dewdrop:InjectAceOptionsTable(self, impliedMenuOptions[self])
774 if impliedMenuOptions[self].args and CheckFuBar() then
775 impliedMenuOptions[self].args.profile = nil
776 end
777 end
778 return Dewdrop:FeedAceOptionsTable(impliedMenuOptions[self], level and level - 1)
779 end
780  
781 function FuBarPlugin.OnEmbedInitialize(FuBarPlugin, self)
782 if not self.frame then
783 local name = "FuBarPlugin" .. self:GetTitle() .. "Frame"
784 local frame = _G[name]
785 if not frame or not _G[self.frame:GetName() .. "Text"] or not _G[self.frame:GetName() .. "Icon"] then
786 frame = self:CreateBasicPluginFrame(name)
787  
788 local icon = frame:CreateTexture(name .. "Icon", "ARTWORK")
789 icon:SetWidth(16)
790 icon:SetHeight(16)
791 icon:SetPoint("LEFT", frame, "LEFT")
792  
793 local text = frame:CreateFontString(name .. "Text", "ARTWORK")
794 text:SetWidth(134)
795 text:SetHeight(24)
796 text:SetPoint("LEFT", icon, "RIGHT", 0, 1)
797 text:SetFontObject(GameFontNormal)
798 end
799 self.frame = frame
800 self.textFrame = _G[self.frame:GetName() .. "Text"]
801 self.iconFrame = _G[self.frame:GetName() .. "Icon"]
802 else
803 self.userDefinedFrame = true
804 end
805  
806 self.frame.plugin = self
807 self.frame:SetParent(UIParent)
808 self.frame:SetPoint("RIGHT", UIParent, "LEFT", -5, 0)
809 self.frame:Hide()
810  
811 if self.hasIcon then
812 self:SetIcon(self.hasIcon)
813 end
814  
815 if CheckFuBar() then
816 FuBar:RegisterPlugin(self)
817 end
818 end
819  
820  
821 local recheckPlugins
822 function FuBarPlugin.OnEmbedEnable(FuBarPlugin, self)
823 if self:IsIconShown() then
824 self.iconFrame:Show()
825 else
826 self.iconFrame:Hide()
827 end
828 self:CheckWidth(true)
829  
830 if not self.hideWithoutStandby or not self.db.profile.hidden then
831 FuBarPlugin:ScheduleEvent(self.Show, 0, self)
832 end
833  
834 if not self.overrideTooltip and not self.cannotDetachTooltip and self.db and self.db.profile.detachedTooltip and self.db.profile.detachedTooltip.detached then
835 FuBarPlugin:ScheduleEvent(self.DetachTooltip, 0, self)
836 end
837  
838 if self:IsLoadOnDemand() and CheckFuBar() then
839 if not FuBar.db.profile.loadOnDemand then
840 FuBar.db.profile.loadOnDemand = {}
841 end
842 if not FuBar.db.profile.loadOnDemand[self.folderName] then
843 FuBar.db.profile.loadOnDemand[self.folderName] = {}
844 end
845 FuBar.db.profile.loadOnDemand[self.folderName].disabled = nil
846 end
847  
848 if CheckFuBar() and AceLibrary:HasInstance("AceConsole-2.0") then
849 if not recheckPlugins then
850 local AceConsole = AceLibrary("AceConsole-2.0")
851 local AceOO = AceLibrary("AceOO-2.0")
852 function recheckPlugins()
853 for k,v in pairs(AceConsole.registry) do
854 if type(v) == "table" and v.args and AceOO.inherits(v.handler, FuBarPlugin) then
855 v.args.profile = nil
856 end
857 end
858 end
859 end
860 FuBarPlugin:ScheduleEvent(recheckPlugins, 0)
861 end
862 end
863  
864 function FuBarPlugin.OnEmbedDisable(FuBarPlugin, self)
865 self:Hide()
866  
867 if self:IsLoadOnDemand() and CheckFuBar() then
868 if not FuBar.db.profile.loadOnDemand then
869 FuBar.db.profile.loadOnDemand = {}
870 end
871 if not FuBar.db.profile.loadOnDemand[self.folderName] then
872 FuBar.db.profile.loadOnDemand[self.folderName] = {}
873 end
874 FuBar.db.profile.loadOnDemand[self.folderName].disabled = true
875 end
876 end
877  
878 function FuBarPlugin.OnEmbedProfileEnable(FuBarPlugin, self)
879 self:Update()
880 if self.db and self.db.profile then
881 if not self.db.profile.detachedTooltip then
882 self.db.profile.detachedTooltip = {}
883 end
884 if Tablet.registry[self.frame] then
885 Tablet:UpdateDetachedData(self.frame, self.db.profile.detachedTooltip)
886 else
887 self:UpdateTooltip()
888 end
889 end
890 end
891  
892 function FuBarPlugin.GetAceOptionsDataTable(FuBarPlugin, self)
893 return {
894 icon = {
895 type = "toggle",
896 name = "Show icon",
897 desc = "Show icon",
898 set = "ToggleIconShown",
899 get = "IsIconShown",
900 hidden = function()
901 return not self.hasIcon or self.hasNoText or self:IsMinimapAttached()
902 end,
903 order = -13.7,
904 handler = self,
905 },
906 text = {
907 type = "toggle",
908 name = "Show text",
909 desc = "Show text",
910 set = "ToggleTextShown",
911 get = "IsTextShown",
912 hidden = function()
913 return self.cannotHideText or not self.hasIcon or self.hasNoText or self:IsMinimapAttached()
914 end,
915 order = -13.6,
916 handler = self,
917 },
918 colorText = {
919 type = "toggle",
920 name = "Show colored text",
921 desc = "Show colored text",
922 set = "ToggleTextColored",
923 get = "IsTextColored",
924 hidden = function()
925 return self.userDefinedFrame or self.hasNoText or self.hasNoColor or self:IsMinimapAttached()
926 end,
927 order = -13.5,
928 handler = self,
929 },
930 detachTooltip = {
931 type = "toggle",
932 name = "Detach tooltip",
933 desc = "Detach tooltip",
934 get = "IsTooltipDetached",
935 set = "ToggleTooltipDetached",
936 hidden = function()
937 return self.overrideTooltip or self.cannotDetachTooltip
938 end,
939 order = -13.4,
940 handler = self,
941 },
942 lockTooltip = {
943 type = "toggle",
944 name = "Lock tooltip",
945 desc = "Lock tooltip",
946 get = function()
947 return Tablet:IsLocked(self.frame)
948 end,
949 set = function()
950 return Tablet:ToggleLocked(self.frame)
951 end,
952 disabled = function()
953 return not self:IsTooltipDetached()
954 end,
955 hidden = function()
956 return self.overrideTooltip or self.cannotDetachTooltip
957 end,
958 order = -13.3,
959 handler = self,
960 },
961 position = {
962 type = "text",
963 name = "Position",
964 desc = "Position",
965 validate = {
966 LEFT = "Left",
967 CENTER = "Center",
968 RIGHT = "Right"
969 },
970 get = function()
971 return self.panel:GetPluginSide(self)
972 end,
973 set = function(value)
974 self.panel:SetPluginSide(self, value)
975 end,
976 hidden = "IsMinimapAttached",
977 order = -13.2,
978 handler = self,
979 },
980 minimapAttach = {
981 type = "toggle",
982 name = "Attach to minimap",
983 desc = "Attach to minimap",
984 get = "IsMinimapAttached",
985 set = "ToggleMinimapAttached",
986 hidden = function()
987 return (self.cannotAttachToMinimap and not self:IsMinimapAttached()) or not CheckFuBar()
988 end,
989 order = -13.1,
990 handler = self,
991 },
992 hide = {
993 type = "execute",
994 name = "Hide",
995 desc = "Hide",
996 func = "Hide",
997 hidden = function()
998 return not self.hideWithoutStandby
999 end,
1000 order = -13,
1001 handler = self,
1002 },
1003 }
1004 end
1005  
1006 local function activate(self, oldLib, oldDeactivate)
1007 FuBarPlugin = self
1008  
1009 if oldLib then
1010 self.registry = oldLib.registry
1011 self.folderNames = oldLib.folderNames
1012 end
1013  
1014 if not self.registry then
1015 self.registry = {}
1016 end
1017 if not self.folderNames then
1018 self.folderNames = {}
1019 end
1020  
1021 FuBarPlugin.activate(self, oldLib, oldDeactivate)
1022  
1023 if oldDeactivate then
1024 oldDeactivate(oldLib)
1025 end
1026 end
1027  
1028 local function external(self, major, instance)
1029 if major == "AceEvent-2.0" then
1030 AceEvent = instance
1031  
1032 AceEvent:embed(self)
1033 elseif major == "Tablet-2.0" then
1034 Tablet = instance
1035 elseif major == "Dewdrop-2.0" then
1036 Dewdrop = instance
1037 end
1038 end
1039  
1040 AceLibrary:Register(FuBarPlugin, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
1041  
1042 local MinimapContainer = {}
1043  
1044 function MinimapContainer:AddPlugin(plugin)
1045 if CheckFuBar() and FuBar:IsChangingProfile() then
1046 return
1047 end
1048 if plugin.panel ~= nil then
1049 plugin.panel:RemovePlugin(plugin)
1050 end
1051 plugin.panel = self
1052 if not plugin.minimapFrame then
1053 local frame = CreateFrame("Button", plugin.frame:GetName() .. "MinimapButton", Minimap)
1054 plugin.minimapFrame = frame
1055 AceLibrary(MAJOR_VERSION).RegisterTablet(plugin)
1056 Tablet:Register(frame, plugin.frame)
1057 frame.plugin = plugin
1058 frame:SetWidth(31)
1059 frame:SetHeight(31)
1060 frame:SetFrameStrata("BACKGROUND")
1061 frame:SetFrameLevel(4)
1062 frame:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
1063 local icon = frame:CreateTexture(frame:GetName() .. "Icon", "BACKGROUND")
1064 plugin.minimapIcon = icon
1065 local path = plugin:GetIcon() or (plugin.iconFrame and plugin.iconFrame:GetTexture()) or "Interface\\Icons\\INV_Misc_QuestionMark"
1066 icon:SetTexture(path)
1067 if string.sub(path, 1, 16) == "Interface\\Icons\\" then
1068 icon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
1069 else
1070 icon:SetTexCoord(0, 1, 0, 1)
1071 end
1072 icon:SetWidth(20)
1073 icon:SetHeight(20)
1074 icon:SetPoint("TOPLEFT", frame, "TOPLEFT", 7, -5)
1075 local overlay = frame:CreateTexture(frame:GetName() .. "Overlay","OVERLAY")
1076 overlay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder")
1077 overlay:SetWidth(53)
1078 overlay:SetHeight(53)
1079 overlay:SetPoint("TOPLEFT",frame,"TOPLEFT")
1080 frame:EnableMouse(true)
1081 frame:RegisterForClicks("LeftButtonUp")
1082 frame.plugin = plugin
1083 frame:SetScript("OnClick", function()
1084 if type(plugin.OnClick) == "function" then
1085 if not this.dragged then
1086 plugin:OnClick(arg1)
1087 end
1088 end
1089 end)
1090 frame:SetScript("OnDoubleClick", function()
1091 if type(plugin.OnDoubleClick) == "function" then
1092 plugin:OnDoubleClick(arg1)
1093 end
1094 end)
1095 frame:SetScript("OnReceiveDrag", function()
1096 if type(plugin.OnReceiveDrag) == "function" then
1097 if not this.dragged then
1098 plugin:OnReceiveDrag()
1099 end
1100 end
1101 end)
1102 frame:SetScript("OnMouseDown", function()
1103 this.dragged = false
1104 if arg1 == "LeftButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then
1105 HideDropDownMenu(1)
1106 if type(plugin.OnMouseDown) == "function" then
1107 plugin:OnMouseDown(arg1)
1108 end
1109 elseif arg1 == "RightButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then
1110 plugin:OpenMenu(frame)
1111 else
1112 HideDropDownMenu(1)
1113 if type(plugin.OnMouseDown) == "function" then
1114 plugin:OnMouseDown(arg1)
1115 end
1116 end
1117 if plugin.OnClick or plugin.OnMouseDown or plugin.OnMouseUp or plugin.OnDoubleClick then
1118 if string.sub(this.plugin.minimapIcon:GetTexture(), 1, 16) == "Interface\\Icons\\" then
1119 plugin.minimapIcon:SetTexCoord(0.14, 0.86, 0.14, 0.86)
1120 else
1121 plugin.minimapIcon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
1122 end
1123 end
1124 end)
1125 frame:SetScript("OnMouseUp", function()
1126 if not this.dragged and type(plugin.OnMouseUp) == "function" then
1127 plugin:OnMouseUp(arg1)
1128 end
1129 if string.sub(this.plugin.minimapIcon:GetTexture(), 1, 16) == "Interface\\Icons\\" then
1130 plugin.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
1131 else
1132 plugin.minimapIcon:SetTexCoord(0, 1, 0, 1)
1133 end
1134 end)
1135 frame:RegisterForDrag("LeftButton")
1136 frame:SetScript("OnDragStart", self.OnDragStart)
1137 frame:SetScript("OnDragStop", self.OnDragStop)
1138 end
1139 plugin.frame:Hide()
1140 plugin.minimapFrame:Show()
1141 self:ReadjustLocation(plugin)
1142 table.insert(self.plugins, plugin)
1143 local exists = false
1144 return true
1145 end
1146  
1147 function MinimapContainer:RemovePlugin(index)
1148 if CheckFuBar() and FuBar:IsChangingProfile() then
1149 return
1150 end
1151 if type(index) == "table" then
1152 index = self:IndexOfPlugin(index)
1153 if not index then
1154 return
1155 end
1156 end
1157 local t = self.plugins
1158 local plugin = t[index]
1159 assert(plugin.panel == self, "Plugin has improper panel field")
1160 plugin:SetPanel(nil)
1161 table.remove(t, index)
1162 return true
1163 end
1164  
1165 function MinimapContainer:ReadjustLocation(plugin)
1166 local frame = plugin.minimapFrame
1167 if not plugin.db.profile.minimapPositionWild then
1168 local position = plugin.db.profile.minimapPosition or plugin.defaultMinimapPosition or math.random(1, 360)
1169 local angle = math.rad(position or 0)
1170 local x = math.cos(angle) * 80
1171 local y = math.sin(angle) * 80
1172 frame:SetPoint("CENTER", Minimap, "CENTER", x, y)
1173 else
1174 frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", plugin.db.profile.minimapPositionX, plugin.db.profile.minimapPositionY)
1175 end
1176 end
1177  
1178 function MinimapContainer:GetPlugin(index)
1179 return self.plugins[index]
1180 end
1181  
1182 function MinimapContainer:GetNumPlugins()
1183 return table.getn(self.plugins)
1184 end
1185  
1186 function MinimapContainer:IndexOfPlugin(plugin)
1187 for i,p in ipairs(self.plugins) do
1188 if p == plugin then
1189 return i, "MINIMAP"
1190 end
1191 end
1192 end
1193  
1194 function MinimapContainer:HasPlugin(plugin)
1195 return self:IndexOfPlugin(plugin) ~= nil
1196 end
1197  
1198 function MinimapContainer:GetPluginSide(plugin)
1199 local index = self:IndexOfPlugin(plugin)
1200 assert(index, "Plugin not in panel")
1201 return "MINIMAP"
1202 end
1203  
1204 function MinimapContainer.OnDragStart()
1205 this.dragged = true
1206 this:LockHighlight()
1207 this:SetScript("OnUpdate", MinimapContainer.OnUpdate)
1208 if string.sub(this.plugin.minimapIcon:GetTexture(), 1, 16) == "Interface\\Icons\\" then
1209 this.plugin.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
1210 else
1211 this.plugin.minimapIcon:SetTexCoord(0, 1, 0, 1)
1212 end
1213 end
1214  
1215 function MinimapContainer.OnDragStop()
1216 this:SetScript("OnUpdate", nil)
1217 this:UnlockHighlight()
1218 end
1219  
1220 function MinimapContainer.OnUpdate()
1221 if not IsAltKeyDown() then
1222 local mx, my = Minimap:GetCenter()
1223 local px, py = GetCursorPosition()
1224 local scale = UIParent:GetEffectiveScale()
1225 px, py = px / scale, py / scale
1226 local lastPosition = this.plugin.db.profile.minimapPosition
1227 local position = math.deg(math.atan2(py - my, px - mx))
1228 if position <= 0 then
1229 position = position + 360
1230 elseif position > 360 then
1231 position = position - 360
1232 end
1233 this.plugin.db.profile.minimapPosition = position
1234 this.plugin.db.profile.minimapPositionX = nil
1235 this.plugin.db.profile.minimapPositionY = nil
1236 this.plugin.db.profile.minimapPositionWild = nil
1237 else
1238 local px, py = GetCursorPosition()
1239 local scale = UIParent:GetEffectiveScale()
1240 px, py = px / scale, py / scale
1241 this.plugin.db.profile.minimapPositionX = px
1242 this.plugin.db.profile.minimapPositionY = py
1243 this.plugin.db.profile.minimapPosition = nil
1244 this.plugin.db.profile.minimapPositionWild = true
1245 end
1246 MinimapContainer:ReadjustLocation(this.plugin)
1247 end
1248  
1249 local function activate(self, oldLib, oldDeactivate)
1250 MinimapContainer = self
1251  
1252 if oldLib then
1253 self.plugins = oldLib.plugins
1254 end
1255  
1256 if not self.plugins then
1257 self.plugins = {}
1258 end
1259  
1260 if oldDeactivate then
1261 oldDeactivate(oldLib)
1262 end
1263 end
1264  
1265 AceLibrary:Register(MinimapContainer, MINIMAPCONTAINER_MAJOR_VERSION, MINOR_VERSION, activate)