vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 FUBAR_VERSION = tonumber((string.gsub("$Revision: 9716 $", "^.-(%d+).-$", "%1")))
2  
3 local AceOO = AceLibrary("AceOO-2.0")
4 local Jostle = AceLibrary("Jostle-2.0")
5 local AceEvent = AceLibrary("AceEvent-2.0")
6  
7 local SPACING_FROM_SIDES = 5
8  
9 local bgFile = "Interface\\AddOns\\FuBar\\background"
10  
11 local function getsecond(_, value)
12 return value
13 end
14  
15 local L = AceLibrary("AceLocale-2.0"):new("FuBar")
16  
17 local _G = getfenv(0)
18  
19 FuBar_Panel = AceOO.Class()
20 local FuBar_Panel = FuBar_Panel
21 FuBar_Panel.id = 0
22 FuBar_Panel.instances = {}
23 FuBar_Panel.sealed = true
24  
25 function FuBar_Panel:ToString()
26 return "FuBar_Panel"
27 end
28  
29 function FuBar_Panel:SetBackground(bg)
30 if bgFile ~= bg then
31 bgFile = bg
32 for _,v in ipairs(self.instances) do
33 v:UpdateTexture()
34 end
35 end
36 end
37  
38 function FuBar_Panel:IsBackground(bg)
39 return bgFile == bg
40 end
41  
42 local frame_OnMouseUp = function()
43 if arg1 == "RightButton" then
44 this.panel:OpenMenu()
45 elseif arg1 == "LeftButton" then
46 this.panel:StopDrag()
47 HideDropDownMenu(1)
48 end
49 end
50 local frame_OnMouseDown = function()
51 if arg1 == "LeftButton" then
52 this.panel:StartDrag()
53 end
54 end
55 local frame_OnDragStart = function()
56 this.panel:StartDrag()
57 end
58 local frame_OnDragStop = function()
59 this.panel:StopDrag()
60 end
61 local frame_OnEnter = function()
62 FuBar:Panel_OnEnter(this.panel:GetAttachPoint())
63 end
64 local frame_OnLeave = function()
65 FuBar:Panel_OnLeave(this.panel:GetAttachPoint())
66 end
67 local frame_OnSizeChanged = function()
68 local panel = this.panel
69 if this.lastWidth == GetScreenWidth() then
70 panel.data.widthPercent = panel.frame:GetWidth() / GetScreenWidth()
71 else
72 this.lastWidth = GetScreenWidth()
73 end
74 panel:UpdateCenteredPosition()
75 panel:UpdateTexture()
76 end
77 local left_OnEnter = function()
78 if not this.panel:IsLocked() then
79 SetCursor("ATTACK_ERROR_CURSOR")
80 end
81 end
82 local left_OnLeave = ResetCursor
83 local right_OnEnter = left_OnEnter
84 local right_OnLeave = left_OnLeave
85 local left_OnMouseDown = function()
86 if arg1 == "LeftButton" then
87 this.panel:StartSizing('LEFT')
88 end
89 end
90 local left_OnMouseUp = function()
91 if arg1 == "RightButton" then
92 this.panel:OpenMenu()
93 elseif arg1 == "LeftButton" then
94 this.panel:StopDrag()
95 end
96 end
97 local right_OnMouseDown = function()
98 if arg1 == "LeftButton" then
99 this.panel:StartSizing('RIGHT')
100 end
101 end
102 local right_OnMouseUp = left_OnMouseUp
103  
104 local backdropsPerPanel = ceil(GetScreenWidth() / 256)
105  
106 local topTexture
107 local bottomTexture
108  
109 function FuBar_Panel.prototype:init(attachPoint)
110 self.class.super.prototype.init(self)
111 self.class.id = self.class.id + 1
112  
113 if not FuBar.db.profile.panels then
114 FuBar.db.profile.panels = {}
115 end
116 if not FuBar.db.profile.panels[self.class.id] then
117 table.insert(FuBar.db.profile.panels, {})
118 end
119 if not FuBar.db.profile.detached then
120 FuBar.db.profile.detached = {}
121 end
122  
123 self.data = FuBar.db.profile.panels[self.class.id]
124 if not self.data then
125 FuBar.db.profile.panels[self.class.id] = {}
126 self.data = FuBar.db.profile.panels[self.class.id]
127 end
128 self.id = self.class.id
129 self.plugins = {
130 left = {},
131 center = {},
132 right = {},
133 }
134  
135 self.frame = _G["FuBarFrame" .. self.id]
136 if not self.frame then
137 local frame = CreateFrame("Frame", "FuBarFrame" .. self.id, UIParent)
138 self.frame = frame
139  
140 if not topTexture then
141 topTexture = frame:CreateTexture("FuBarFrameTopTexture", "ARTWORK")
142 bottomTexture = frame:CreateTexture("FuBarFrameBottomTexture", "ARTWORK")
143 topTexture:SetTexture(1, 1, 1)
144 topTexture:SetGradientAlpha("VERTICAL", 1, 1, 1, 0, 1, 1, 1, 0.5 * FuBar:GetTransparency())
145 bottomTexture:SetTexture(1, 1, 1)
146 bottomTexture:SetGradientAlpha("VERTICAL", 1, 1, 1, 0.5 * FuBar:GetTransparency(), 1, 1, 1, 0)
147 topTexture:Hide()
148 bottomTexture:Hide()
149 end
150  
151 frame:SetFrameStrata("HIGH")
152 frame:SetFrameLevel(6)
153 frame:EnableMouse(true)
154 frame:SetMovable(true)
155 frame:SetResizable(true)
156 frame:SetWidth(500)
157 frame:SetHeight(24)
158 frame:SetPoint('TOP', UIParent, 'TOP')
159 local left = CreateFrame("Frame", frame:GetName() .. 'LEFT', frame)
160 left:SetPoint('TOPLEFT', frame, 'TOPLEFT')
161 left:SetPoint('BOTTOMRIGHT', frame, 'BOTTOMLEFT', 5, 0)
162 left:EnableMouse(true)
163 left:Show()
164 local right = CreateFrame("Frame", frame:GetName() .. 'RIGHT', frame)
165 right:SetPoint('TOPRIGHT', frame, 'TOPRIGHT')
166 right:SetPoint('BOTTOMLEFT', frame, 'BOTTOMRIGHT', -5, 0)
167 right:EnableMouse(true)
168 right:Show()
169 frame.left = left
170 frame.right = right
171 frame.lastWidth = GetScreenWidth()
172 frame:SetScript("OnMouseUp", frame_OnMouseUp)
173 frame:SetScript("OnMouseDown", frame_OnMouseDown)
174 frame:SetScript("OnDragStart", frame_OnDragStart)
175 frame:SetScript("OnDragStop", frame_OnDragStop)
176 frame:SetScript("OnEnter", frame_OnEnter)
177 frame:SetScript("OnLeave", frame_OnLeave)
178 frame:SetScript("OnSizeChanged", frame_OnSizeChanged)
179 left:SetScript("OnEnter", left_OnEnter)
180 left:SetScript("OnLeave", left_OnLeave)
181 right:SetScript("OnEnter", right_OnEnter)
182 right:SetScript("OnLeave", right_OnLeave)
183 left:SetScript("OnMouseDown", left_OnMouseDown)
184 left:SetScript("OnMouseUp", left_OnMouseUp)
185 right:SetScript("OnMouseDown", right_OnMouseDown)
186 right:SetScript("OnMouseUp", right_OnMouseUp)
187  
188 frame.bgTextures = {}
189 local lastTexture
190 for i = 1, backdropsPerPanel do
191 local texture = frame:CreateTexture(frame:GetName() .. "Texture" .. i, "BACKGROUND")
192 texture:SetWidth(256)
193 texture:SetHeight(256)
194 if not lastTexture then
195 texture:SetPoint('TOPLEFT', frame, 'TOPLEFT')
196 else
197 texture:SetPoint('LEFT', lastTexture, 'RIGHT')
198 end
199 texture:SetTexture(bgFile)
200 table.insert(frame.bgTextures, texture)
201 lastTexture = texture
202 end
203 end
204  
205 self.bgTextures = self.frame.bgTextures
206 self.frame.panel = self
207 self.frame.left.panel = self
208 self.frame.right.panel = self
209  
210 if not self.class.instances[self.id] then
211 table.insert(self.class.instances, self)
212 else
213 self.class.instances[self.id] = self
214 end
215  
216 if not self.data.attachPoint then
217 self.data.attachPoint = attachPoint or 'TOP'
218 end
219  
220 if not self.data.plugins then
221 self.data.plugins = {
222 left = {},
223 right = {},
224 center = {},
225 }
226 end
227  
228 if not self.frame:IsShown() then
229 self.frame:Show()
230 end
231  
232 self.stopUpdates = {}
233  
234 for _,v in ipairs(self.class.instances) do
235 v:Update()
236 v:UpdateTexture()
237 end
238 if self.data.attachPoint == 'TOP' then
239 Jostle:RegisterTop(self.frame)
240 self.frame:SetFrameStrata("HIGH")
241 self.frame:SetFrameLevel(6)
242 elseif self.data.attachPoint == 'BOTTOM' then
243 Jostle:RegisterBottom(self.frame)
244 self.frame:SetFrameStrata("HIGH")
245 self.frame:SetFrameLevel(6)
246 else
247 self.frame:SetFrameStrata("MEDIUM")
248 self.frame:SetFrameLevel(1)
249 end
250 AceEvent:TriggerEvent("FuBar_ChangedPanels")
251 Jostle:Refresh()
252 end
253  
254 function FuBar_Panel.prototype:del(force)
255 assert(force or self.class.id > 1, "Cannot destroy only panel.")
256  
257 if topTexture.attachedTo == self then
258 topTexture:ClearAllPoints()
259 topTexture:Hide()
260 topTexture.attachedTo = nil
261 end
262 if bottomTexture.attachedTo == self then
263 bottomTexture:ClearAllPoints()
264 bottomTexture:Hide()
265 bottomTexture.attachedTo = nil
266 end
267  
268 for h = 1, 3 do
269 local t, position
270 if h == 1 then
271 t = self.plugins.left
272 position = 'LEFT'
273 elseif h == 2 then
274 t = self.plugins.center
275 position = 'CENTER'
276 else
277 t = self.plugins.right
278 position = 'RIGHT'
279 end
280 for i = table.getn(t), 1, -1 do
281 local plugin = t[i]
282 self:RemovePlugin(i, position)
283 plugin:Hide()
284 end
285 end
286  
287 for i = self.id + 1, self.class.id do
288 if self.class.instances[i]:GetAttachPoint() == self.data.attachPoint then
289 self:SwitchWithPanel(i)
290 end
291 end
292  
293 Jostle:Unregister(self.frame)
294 if not force then
295 self:SetAttachPoint('NONE')
296 end
297 self.frame:Hide()
298  
299 if not force then
300 table.remove(FuBar.db.profile.panels, self.id)
301 end
302 self.data = nil
303 self.plugins = nil
304 table.remove(self.class.instances, self.id)
305  
306 self.class.id = self.class.id - 1
307 AceEvent:TriggerEvent("FuBar_ChangedPanels")
308 for i = 1, self.class.id do
309 local panel = self.class.instances[i]
310 panel.id = i
311 panel:UpdateTexture()
312 panel:Update()
313 end
314  
315 Jostle:Refresh()
316 end
317  
318 function FuBar_Panel.prototype:WarnDestroy()
319 if self:GetNumPlugins('LEFT') + self:GetNumPlugins('CENTER') + self:GetNumPlugins('RIGHT') == 0 then
320 self:del()
321 else
322 if not StaticPopupDialogs["FUBAR_DESTROY_PANEL"] then
323 StaticPopupDialogs["FUBAR_DESTROY_PANEL"] = {
324 text = L["Are you sure you want to remove this panel?"],
325 button1 = L["Remove panel"],
326 button2 = CANCEL,
327 timeout = 0,
328 whileDead = 1,
329 hideOnEscape = 1,
330 }
331 end
332 StaticPopupDialogs["FUBAR_DESTROY_PANEL"].OnAccept = function()
333 self:del()
334 end
335 StaticPopup_Show("FUBAR_DESTROY_PANEL")
336 end
337 end
338  
339 function FuBar_Panel.prototype:SwitchWithPanel(id, preventUpdate)
340 local other = self.class.instances[id]
341 if not other or self.data.attachPoint ~= other.data.attachPoint then
342 return
343 end
344 other.id, self.id = self.id, other.id
345 other.frame, self.frame = self.frame, other.frame
346 self.frame.panel = self
347 other.frame.panel = other
348 self.frame.left.panel = self
349 other.frame.right.panel = other
350 self.class.instances[other.id] = other
351 self.class.instances[self.id] = self
352 FuBar.db.profile.panels[other.id], FuBar.db.profile.panels[self.id] = FuBar.db.profile.panels[self.id], FuBar.db.profile.panels[other.id]
353 self.bgTextures, other.bgTextures = other.bgTextures, self.bgTextures
354 if not preventUpdate then
355 other:Update()
356 self:Update()
357 end
358 for i = 1, self.class.id do
359 self.class.instances[i]:UpdateTexture()
360 end
361 AceEvent:TriggerEvent("FuBar_ChangedPanels")
362 Jostle:Refresh()
363 end
364  
365 function FuBar_Panel.prototype:GetAttachPoint()
366 if not self.data then
367 ReloadUI()
368 return
369 end
370 return self.data.attachPoint
371 end
372  
373 function FuBar_Panel.prototype:SetAttachPoint(point)
374 if self.data.attachPoint == point then
375 return
376 end
377 Jostle:Unregister(self.frame)
378 if point == 'NONE' then
379 self.data.yPercent = 0.5 - (FuBarFrame1:GetHeight()/2 / GetScreenHeight())
380 self.frame:SetFrameStrata("MEDIUM")
381 self.frame:SetFrameLevel(1)
382 elseif point == 'TOP' or point == 'BOTTOM' then
383 self.data.yPercent = nil
384 self.frame:SetFrameStrata("HIGH")
385 self.frame:SetFrameLevel(6)
386 else
387 assert(false, "Improper attach point given: " .. point)
388 end
389  
390 local previous = self.data.attachPoint
391 self.data.attachPoint = point
392 for i = self.id, self.class.id do
393 local panel = self.class.instances[i]
394 if previous == panel:GetAttachPoint() or point == panel:GetAttachPoint() then
395 panel:Update()
396 end
397 end
398 self:Update()
399  
400 Jostle:Refresh()
401  
402 if self:IsLocked() then
403 self:ToggleLocked()
404 end
405  
406 if self.data.attachPoint == 'TOP' then
407 Jostle:RegisterTop(self.frame)
408 elseif self.data.attachPoint == 'BOTTOM' then
409 Jostle:RegisterBottom(self.frame)
410 end
411  
412 for i = 1, self.class.id do
413 self.class.instances[i]:UpdateTexture()
414 end
415  
416 AceEvent:TriggerEvent("FuBar_ChangedPanels")
417 Jostle:Refresh()
418 end
419  
420 function FuBar_Panel.prototype:IsLocked()
421 return self.data and self.data.lock
422 end
423  
424 function FuBar_Panel.prototype:ToggleLocked()
425 if self.data then
426 self.data.lock = not self.data.lock
427 return self.data.lock
428 end
429 end
430  
431 function FuBar_Panel.prototype:GetPositionFromEdge()
432 local num = 1
433 local set = 0
434 if self.data.attachPoint == 'TOP' then
435 for i = 1, self.class.id do
436 local panel = self.class.instances[i]
437 if panel == self then
438 set = num
439 num = num + 1
440 elseif panel and panel:GetAttachPoint() == 'TOP' then
441 num = num + 1
442 end
443 end
444 elseif self.data.attachPoint == 'BOTTOM' then
445 for i = 1, self.class.id do
446 local panel = self.class.instances[i]
447 if panel == self then
448 set = num
449 num = num + 1
450 elseif panel and panel:GetAttachPoint() == 'BOTTOM' then
451 num = num + 1
452 end
453 end
454 else
455 return
456 end
457 return num - set
458 end
459  
460 function FuBar_Panel.prototype:UpdateTexture()
461 if topTexture.attachedTo == self then
462 topTexture:ClearAllPoints()
463 topTexture:Hide()
464 topTexture.attachedTo = nil
465 end
466 if bottomTexture.attachedTo == self then
467 bottomTexture:ClearAllPoints()
468 bottomTexture:Hide()
469 bottomTexture.attachedTo = nil
470 end
471 local point = self:GetAttachPoint()
472 local height = FuBar:GetFontSize() + FuBar:GetThickness()
473 self.frame:SetHeight(height)
474  
475 local uiscale = 768 / GetScreenHeight()
476 local texsize = 256 / uiscale
477 local realLeft = self.frame:GetLeft() or 0
478 local left = mod(self.frame:GetLeft() or 0, texsize)
479 local width = self.frame:GetWidth() or 0
480 local fromEdge = self:GetPositionFromEdge()
481 if fromEdge and self.bgTextures then
482 local y1, y2
483 if self.data.attachPoint == 'TOP' then
484 y1, y2 = 1-((height) / texsize) * fromEdge, 1-(height / 256) * (fromEdge - 1)
485 else
486 y1, y2 = ((height + 2) / texsize) * (fromEdge - 1), ((height+2) / 256) * fromEdge
487 end
488 for i,texture in ipairs(self.bgTextures) do
489 texture:SetTexture(bgFile)
490 local x = (i - 1) * texsize
491 local xr = i * texsize
492 texture:Show()
493 texture:SetHeight(height)
494 local x1, x2 = 0, 1
495 local changed = false
496 if i == 1 then
497 x1 = left / texsize
498 texture:SetWidth(texsize - left)
499 changed = true
500 end
501 if width + left < xr then
502 if i == 1 then
503 texture:SetWidth(width)
504 x2 = mod(width + left - x, texsize) / texsize
505 else
506 texture:SetWidth(mod(width + left - x, texsize))
507 x2 = mod(width + left - x, texsize) / texsize
508 end
509 elseif not changed then
510 texture:SetWidth(texsize)
511 end
512 texture:SetPoint('TOPLEFT', self.frame, 'TOPLEFT', x + x1*texsize - left, 0)
513 texture:SetTexCoord(x1, x2, y1, y2)
514 texture:SetVertexColor(1, 1, 1, FuBar:GetTransparency())
515 end
516 elseif self.bgTextures then
517 local y1, y2 = 0.5 - height / texsize / 2, 0.5 + height / texsize / 2
518 for i,texture in ipairs(self.bgTextures) do
519 texture:SetTexture(bgFile)
520 local x = (i - 1) * texsize
521 local xr = i * texsize
522 texture:Show()
523 texture:SetHeight(height)
524 local changed = false
525 local x1, x2 = 0, 1
526 if width < xr then
527 texture:SetWidth(mod(width - x, texsize))
528 x2 = mod(width - x, texsize) / texsize
529 else
530 texture:SetWidth(texsize)
531 end
532 texture:SetTexCoord(x1, x2, y1, y2)
533 texture:SetVertexColor(1, 1, 1, FuBar:GetTransparency())
534 end
535 end
536 end
537  
538 function FuBar_Panel.prototype:AddPlugin(plugin, index, side, isDefaultSide)
539 if FuBar:IsChangingProfile() then
540 return
541 end
542 if plugin:GetPanel() then
543 plugin:GetPanel():RemovePlugin(plugin)
544 end
545 plugin:SetPanel(self)
546 if FuBar.db.profile.detached then
547 FuBar.db.profile.detached[plugin:GetTitle()] = nil
548 end
549 plugin:GetFrame():SetParent(self.frame)
550  
551 if not FuBar.db.profile.places then
552 FuBar.db.profile.places = {}
553 end
554 if FuBar.db.profile.places.left and FuBar.db.profile.places.left[plugin:GetTitle()] then
555 FuBar.db.profile.places.left[plugin:GetTitle()] = nil
556 if not side or isDefaultSide then
557 side = 'LEFT'
558 end
559 end
560 if FuBar.db.profile.places.center and FuBar.db.profile.places.center[plugin:GetTitle()] then
561 FuBar.db.profile.places.center[plugin:GetTitle()] = nil
562 if not side or isDefaultSide then
563 side = 'CENTER'
564 end
565 end
566 if FuBar.db.profile.places.right and FuBar.db.profile.places.right[plugin:GetTitle()] then
567 FuBar.db.profile.places.right[plugin:GetTitle()] = nil
568 if not side or isDefaultSide then
569 side = 'RIGHT'
570 end
571 end
572 if not side then
573 side = 'LEFT'
574 end
575 local positioned = false
576 for h = 1, 3 do
577 local t, dt
578 if h == 1 then
579 t = self.plugins.left
580 dt = self.data.plugins.left
581 elseif h == 2 then
582 t = self.plugins.center
583 dt = self.data.plugins.center
584 else
585 t = self.plugins.right
586 dt = self.data.plugins.right
587 end
588 for i, value in ipairs(dt) do
589 if value == plugin:GetTitle() then
590 for j = i - 1, 1, -1 do
591 local otherName = dt[j]
592 for k, p in ipairs(t) do
593 if p:GetTitle() == otherName then
594 table.insert(t, k + 1, plugin)
595 positioned = true
596 break
597 end
598 end
599 if positioned then
600 break
601 end
602 end
603 if not positioned then
604 table.insert(t, 1, plugin)
605 positioned = true
606 end
607 break
608 end
609 end
610 if positioned then
611 break
612 end
613 end
614  
615 if not positioned then
616 local t, dt
617 if side == 'RIGHT' then
618 t, dt = self.plugins.right, self.data.plugins.right
619 elseif side == 'CENTER' then
620 t, dt = self.plugins.center, self.data.plugins.center
621 else
622 t, dt = self.plugins.left, self.data.plugins.left
623 end
624 if not index then
625 table.insert(t, plugin)
626 table.insert(dt, plugin:GetTitle())
627 else
628 if index == 1 then
629 table.insert(t, index, plugin)
630 table.insert(dt, 1, plugin:GetTitle())
631 else
632 table.insert(t, index, plugin)
633 local name = t[index - 1]:GetTitle()
634 local done = false
635 for k, v in ipairs(dt) do
636 if name == v then
637 table.insert(dt, k + 1, plugin:GetTitle())
638 done = true
639 break
640 end
641 end
642 if not done then
643 table.insert(dt, plugin:GetTitle())
644 end
645 end
646 end
647 end
648 plugin:GetFrame():Show()
649 if plugin.minimapFrame then
650 plugin.minimapFrame:Hide()
651 end
652 if not positioned then
653 assert(self:GetPluginSide(plugin) == side)
654 end
655 self:Update()
656 return true
657 end
658  
659 function FuBar_Panel.prototype:RemovePlugin(index, side)
660 if FuBar:IsChangingProfile() then
661 return
662 end
663 if type(index) == "table" then
664 index, side = self:IndexOfPlugin(index)
665 if not index then
666 return
667 end
668 end
669  
670 local t, dt
671 if not FuBar.db.profile.places then
672 FuBar.db.profile.places = {}
673 end
674 if side == 'RIGHT' then
675 if not FuBar.db.profile.places.right then
676 FuBar.db.profile.places.right = {}
677 end
678 t, dt = self.plugins.right, self.data.plugins.right
679 FuBar.db.profile.places.right[t[index]:GetTitle()] = true
680 elseif side == 'CENTER' then
681 if not FuBar.db.profile.places.center then
682 FuBar.db.profile.places.center = {}
683 end
684 t, dt = self.plugins.center, self.data.plugins.center
685 FuBar.db.profile.places.center[t[index]:GetTitle()] = true
686 else
687 if not FuBar.db.profile.places.left then
688 FuBar.db.profile.places.left = {}
689 end
690 t, dt = self.plugins.left, self.data.plugins.left
691 FuBar.db.profile.places.left[t[index]:GetTitle()] = true
692 end
693  
694 local plugin = t[index]
695 assert(plugin:GetPanel() == self, "Plugin has improper panel field")
696 plugin:SetPanel(nil)
697 if not self.class.stopUpdates then
698 plugin:GetFrame():Hide()
699 if plugin.minimapFrame then
700 plugin.minimapFrame:Hide()
701 end
702 end
703 for i = 1, table.getn(dt) do
704 if dt[i] == plugin:GetTitle() then
705 table.remove(dt, i)
706 end
707 end
708 table.remove(t, index)
709 FuBar.db.profile.detached[plugin:GetTitle()] = true
710 self:Update()
711 end
712  
713 function FuBar_Panel.prototype:GetPlugin(index, side)
714 if not self.plugins then
715 ReloadUI()
716 return
717 end
718 if side == 'RIGHT' then
719 return self.plugins.right[index]
720 elseif side == 'CENTER' then
721 return self.plugins.center[index]
722 else
723 return self.plugins.left[index]
724 end
725 end
726  
727 function FuBar_Panel.prototype:GetNumPlugins(side)
728 if side == 'RIGHT' then
729 return table.getn(self.plugins.right)
730 elseif side == 'CENTER' then
731 return table.getn(self.plugins.center)
732 else
733 return table.getn(self.plugins.left)
734 end
735 end
736  
737 function FuBar_Panel.prototype:IndexOfPlugin(plugin)
738 for i = 1, self:GetNumPlugins('LEFT') do
739 if self.plugins.left[i] == plugin then
740 return i, 'LEFT'
741 end
742 end
743 for i = 1, self:GetNumPlugins('CENTER') do
744 if self.plugins.center[i] == plugin then
745 return i, 'CENTER'
746 end
747 end
748 for i = 1, self:GetNumPlugins('RIGHT') do
749 if self.plugins.right[i] == plugin then
750 return i, 'RIGHT'
751 end
752 end
753 end
754  
755 function FuBar_Panel.prototype:HasPlugin(plugin)
756 return self:IndexOfPlugin(plugin) ~= nil
757 end
758  
759 function FuBar_Panel.prototype:GetPluginSide(plugin)
760 local index, side = self:IndexOfPlugin(plugin)
761 assert(index, "Plugin not in panel")
762 return side
763 end
764  
765 function FuBar_Panel.prototype:SetPluginSide(plugin, side)
766 local oldSide = self:GetPluginSide(plugin)
767 if oldSide ~= side then
768 self:RemovePlugin(plugin)
769 self:AddPlugin(plugin, nil, side)
770 self:Update()
771 end
772 end
773  
774 function FuBar_Panel:PreventUpdate()
775 self.stopUpdates = true
776 end
777  
778 function FuBar_Panel:StopPreventUpdate(code)
779 self.stopUpdates = false
780 end
781  
782 function FuBar_Panel.prototype:Update()
783 if self.class.stopUpdates then
784 return
785 end
786 if not self.data.widthPercent or self.data.widthPercent > 1 then
787 self.data.widthPercent = 1
788 end
789 local width = self.data.widthPercent * GetScreenWidth()
790 self.frame:SetWidth(width)
791  
792 if not self.data.xPercent or not self.data.yPercent then
793 self.data.xPercent = 0.5 - self.data.widthPercent / 2
794 self.data.yPercent = 0.5
795 end
796 if self:GetAttachPoint() == 'TOP' then
797 self.frame:ClearAllPoints()
798 local hasTop = nil
799 for i = self.id - 1, 1, -1 do
800 if self.class.instances[i] and self.class.instances[i]:GetAttachPoint() == 'TOP' then
801 hasTop = self.class.instances[i]
802 break
803 end
804 end
805  
806 if not hasTop then
807 self.frame:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', self.data.xPercent * GetScreenWidth(), 1)
808 else
809 self.frame:SetPoint('TOPLEFT', hasTop.frame, 'BOTTOMLEFT', self.data.xPercent * GetScreenWidth() - (hasTop.frame:GetLeft() or 0), 0)
810 end
811 elseif self:GetAttachPoint(panelId) == 'BOTTOM' then
812 self.frame:ClearAllPoints()
813 local hasBottom = nil
814 for i = self.id - 1, 1, -1 do
815 if self.class.instances[i] and self.class.instances[i]:GetAttachPoint() == 'BOTTOM' then
816 hasBottom = self.class.instances[i]
817 break
818 end
819 end
820 if not hasBottom then
821 self.frame:SetPoint('BOTTOMLEFT', UIParent, 'BOTTOMLEFT', self.data.xPercent * GetScreenWidth(), -1)
822 else
823 self.frame:SetPoint('BOTTOMLEFT', hasBottom.frame, 'TOPLEFT', self.data.xPercent * GetScreenWidth() - hasBottom.frame:GetLeft(), 0)
824 end
825 else
826 self.frame:ClearAllPoints()
827 self.frame:SetPoint('BOTTOMLEFT', UIParent, 'BOTTOMLEFT', self.data.xPercent * GetScreenWidth(), self.data.yPercent * GetScreenHeight())
828 end
829  
830 local num = 0
831  
832 for h = 1, 3 do
833 local t, side
834 if h == 1 then
835 t = self.plugins.left
836 side = 'LEFT'
837 elseif h == 2 then
838 t = self.plugins.center
839 side = 'CENTER'
840 else
841 t = self.plugins.right
842 side = 'RIGHT'
843 end
844 local i = 1
845 while i <= self:GetNumPlugins(side) do
846 assert(t[i], "nil plugin spot")
847 if type(t[i].IsDisabled) == "function" and t[i]:IsDisabled() then
848 self:RemovePlugin(i, side)
849 i = i - 1
850 end
851 i = i + 1
852 end
853 end
854  
855 for h = 1, 3 do
856 local t, side
857 if h == 1 then
858 t = self.plugins.left
859 side = 'LEFT'
860 elseif h == 2 then
861 t = self.plugins.center
862 side = 'CENTER'
863 else
864 t = self.plugins.right
865 side = 'RIGHT'
866 end
867 for i = 1, self:GetNumPlugins(side) do
868 t[i]:CheckWidth()
869 t[i].frame:SetParent(self.frame)
870 t[i].frame:ClearAllPoints()
871 end
872 end
873  
874 for h = 1, 3 do
875 local t, side, alpha, bravo, sideSpacing, spacing
876 if h == 1 then
877 t = self.plugins.left
878 side = 'LEFT'
879 alpha, bravo = 'LEFT', 'RIGHT'
880 sideSpacing = SPACING_FROM_SIDES
881 spacing = FuBar:GetLeftSpacing()
882 elseif h == 2 then
883 t = self.plugins.center
884 side = 'CENTER'
885 alpha, bravo = 'LEFT', 'RIGHT'
886 sideSpacing = SPACING_FROM_SIDES
887 spacing = FuBar:GetCenterSpacing()
888 else
889 t = self.plugins.right
890 side = 'RIGHT'
891 alpha, bravo = 'RIGHT', 'LEFT'
892 sideSpacing = -SPACING_FROM_SIDES
893 spacing = -FuBar:GetRightSpacing()
894 end
895 for i = 1, self:GetNumPlugins(side) do
896 t[i].frame:Show()
897 if i == 1 then
898 t[i].frame:SetPoint(alpha, self.frame, alpha, sideSpacing, 0)
899 else
900 t[i].frame:SetPoint(alpha, t[i-1].frame, bravo, spacing, 0)
901 end
902 end
903 end
904  
905 self:UpdateCenteredPosition()
906 self:CheckForOverlap()
907 end
908  
909 function FuBar_Panel.prototype:UpdateCenteredPosition()
910 if self:GetPlugin(1, 'CENTER') then
911 local num = self:GetNumPlugins('CENTER')
912 local width = num * FuBar:GetCenterSpacing()
913 for i = 1, num do
914 width = width + self.plugins.center[i].frame:GetWidth()
915 end
916  
917 local frame = self:GetPlugin(1, 'CENTER').frame
918 frame:ClearAllPoints()
919 frame:SetPoint('LEFT', self.frame, 'LEFT', (self.data.widthPercent * GetScreenWidth() - width) / 2, 0)
920 end
921 end
922  
923 function FuBar_Panel.prototype:GetSavedOrder(side)
924 if side == 'RIGHT' then
925 return self.data.plugins.right
926 elseif side == 'CENTER' then
927 return self.data.plugins.center
928 else
929 return self.data.plugins.left
930 end
931 end
932  
933 function FuBar_Panel.prototype:ResetSavedOrder(side)
934 local t
935 if side == 'RIGHT' then
936 t = self.data.plugins.right
937 elseif side == 'CENTER' then
938 t = self.data.plugins.center
939 else
940 t = self.data.plugins.left
941 end
942 for key in pairs(t) do
943 t[key] = nil
944 end
945 end
946  
947 local Dewdrop = AceLibrary("Dewdrop-2.0")
948 function FuBar_Panel.prototype:OpenMenu()
949 if Dewdrop:IsOpen(self.frame) then
950 Dewdrop:Close()
951 return
952 end
953 self.class.selectedPanel = self.id
954 if not Dewdrop:IsRegistered(self.class.instances[1].frame) then
955 Dewdrop:Register(self.class.instances[1].frame,
956 'children', FuBar.menu,
957 'point', function(parent)
958 if parent:GetTop() < GetScreenHeight() / 2 then
959 return 'BOTTOM', 'TOP'
960 else
961 return 'TOP', 'BOTTOM'
962 end
963 end,
964 'cursorX', true,
965 'dontHook', true
966 )
967 end
968 Dewdrop:Open(self.frame, self.class.instances[1].frame)
969 end
970  
971 local closePanel
972 function FuBar_Panel.prototype:StartSizing(direction)
973 DropDownList1:Hide()
974 if not self:IsLocked() then
975 local x, y = FuBar:GetScaledCursorPosition()
976 local left, right = self.frame:GetLeft(), self.frame:GetRight()
977 if self:GetAttachPoint() ~= 'NONE' then
978 self.lastWidth = self.frame:GetWidth()
979 end
980 self.frame:StartSizing(direction)
981 self.sizeFrom = direction
982 closePanel = nil
983 for i = self.id + 1, self.class.id do
984 local panel = self.class.instances[i]
985 if panel:GetAttachPoint() == self:GetAttachPoint() then
986 closePanel = panel
987 local x, y = closePanel.frame:GetLeft(), closePanel.frame:GetBottom()
988 closePanel.frame:ClearAllPoints()
989 closePanel.frame:SetPoint('BOTTOMLEFT', UIParent, 'BOTTOMLEFT', x, y)
990 break
991 end
992 end
993 end
994 end
995  
996 local lastX, lastY
997  
998 function FuBar_Panel.prototype:StartDrag()
999 if not self:IsLocked() and self:GetAttachPoint() == 'NONE' then
1000 self.frame:StartMoving()
1001 elseif not self:IsLocked() then
1002 self.frame:StartMoving()
1003 closePanel = nil
1004 for i = self.id + 1, self.class.id do
1005 local panel = self.class.instances[i]
1006 if panel and panel:GetAttachPoint() == self:GetAttachPoint() then
1007 closePanel = panel
1008 local x, y = closePanel.frame:GetLeft(), closePanel.frame:GetBottom()
1009 closePanel.frame:ClearAllPoints()
1010 closePanel.frame:SetPoint('BOTTOMLEFT', UIParent, 'BOTTOMLEFT', x, y)
1011 break
1012 end
1013 end
1014 lastX, lastY = self.frame:GetCenter()
1015 end
1016 end
1017  
1018 function FuBar_Panel.prototype:StopDrag()
1019 self.frame:StopMovingOrSizing()
1020 local x, y = self.frame:GetCenter()
1021 local offsetX = 0
1022 if self.frame:GetWidth() < 50 then
1023 if self.sizeFrom == 'LEFT' then
1024 offsetX = self.frame:GetWidth() - 50
1025 end
1026 self.frame:SetWidth(50)
1027 elseif self.frame:GetWidth() > GetScreenWidth() then
1028 if self.sizeFrom == 'RIGHT' then
1029 offsetX = self.frame:GetWidth() - self.frame:GetRight()
1030 else
1031 offsetX = -self.frame:GetLeft()
1032 end
1033 self.frame:SetWidth(GetScreenWidth())
1034 end
1035 self.sizeFrom = nil
1036 self.data.xPercent = (self.frame:GetLeft() + offsetX) / GetScreenWidth()
1037 self.data.yPercent = self.frame:GetBottom() / GetScreenHeight()
1038 self.data.widthPercent = self.frame:GetWidth() / GetScreenWidth()
1039 if self.data.xPercent < 0 then
1040 self.data.xPercent = 0
1041 elseif self.data.xPercent + self.data.widthPercent > 1 then
1042 self.data.xPercent = 1 - self.data.widthPercent
1043 end
1044 self:Update()
1045 if closePanel then
1046 closePanel:Update()
1047 closePanel = nil
1048 end
1049 if lastY then
1050 if self:GetAttachPoint() == 'TOP' then
1051 if y < GetScreenHeight() / 2 then
1052 self:SetAttachPoint('BOTTOM')
1053 end
1054 else
1055 if y > GetScreenHeight() /2 then
1056 self:SetAttachPoint('TOP')
1057 end
1058 end
1059 if self:GetAttachPoint() == 'TOP' then
1060 local position = 0
1061 for i = 1, self.class.id do
1062 if i ~= self.id then
1063 local other = self.class.instances[i]
1064 if other:GetAttachPoint() == 'TOP' then
1065 if y <= getsecond(other.frame:GetCenter()) then
1066 position = i
1067 end
1068 end
1069 else
1070 if y <= lastY then
1071 position = i
1072 end
1073 end
1074 end
1075 lastY = nil
1076 if position < self.id then
1077 position = position + 1
1078 end
1079 local shift = position - self.id
1080 local num = 0
1081 if shift < 0 then
1082 for i = 1, -shift do
1083 num = num + 1
1084 if self.class.instances[self.id - num]:GetAttachPoint() == 'TOP' then
1085 self:SwitchWithPanel(self.id - num)
1086 num = 0
1087 end
1088 end
1089 elseif shift > 0 then
1090 for i = 1, shift do
1091 num = num + 1
1092 if self.class.instances[self.id + num]:GetAttachPoint() == 'TOP' then
1093 self:SwitchWithPanel(self.id + num)
1094 num = 0
1095 end
1096 end
1097 end
1098 elseif self:GetAttachPoint() == 'BOTTOM' then
1099 local position = 0
1100 for i = 1, self.class.id do
1101 if i ~= self.id then
1102 local other = self.class.instances[i]
1103 if other:GetAttachPoint() == 'BOTTOM' then
1104 if y >= getsecond(other.frame:GetCenter()) then
1105 position = i
1106 end
1107 end
1108 else
1109 if y >= lastY then
1110 position = i
1111 end
1112 end
1113 end
1114 lastY = nil
1115 if position < self.id then
1116 position = position + 1
1117 end
1118 local shift = position - self.id
1119 local num = 0
1120 if shift < 0 then
1121 for i = 1, -shift do
1122 num = num + 1
1123 if self.class.instances[self.id - num]:GetAttachPoint() == 'BOTTOM' then
1124 self:SwitchWithPanel(self.id - num)
1125 num = 0
1126 end
1127 end
1128 elseif shift > 0 then
1129 for i = 1, shift do
1130 num = num + 1
1131 if self.class.instances[self.id + num]:GetAttachPoint() == 'BOTTOM' then
1132 self:SwitchWithPanel(self.id + num)
1133 num = 0
1134 end
1135 end
1136 end
1137 end
1138 end
1139 self:UpdateTexture()
1140 end
1141  
1142 function FuBar_Panel.prototype:HasOverlap()
1143 local leftNum, centerNum, rightNum = self:GetNumPlugins('LEFT'), self:GetNumPlugins('CENTER'), self:GetNumPlugins('RIGHT')
1144 local left = self:GetPlugin(leftNum, 'LEFT')
1145 local right = self:GetPlugin(rightNum, 'RIGHT')
1146 local centerLeft = self:GetPlugin(1, 'CENTER')
1147 local centerRight = self:GetPlugin(centerNum, 'CENTER')
1148  
1149 if centerLeft then
1150 if left and left.frame:GetRight() and centerLeft.frame:GetLeft() then
1151 if left and left.frame:GetRight() >= centerLeft.frame:GetLeft() - 5 then
1152 return true
1153 end
1154 end
1155 return right and right.frame:GetLeft() and centerRight.frame:GetRight() and right.frame:GetLeft() <= centerRight.frame:GetRight() + 5
1156 elseif left and right then
1157 if left.frame:GetRight() and right.frame:GetLeft() then
1158 return left.frame:GetRight() >= right.frame:GetLeft() - 5
1159 end
1160 elseif left then
1161 if left.frame:GetRight() and self.frame:GetRight() then
1162 return left.frame:GetRight() > self.frame:GetRight() - 5
1163 end
1164 elseif right then
1165 if right.frame:GetLeft() and self.frame:GetLeft() then
1166 return right.frame:GetLeft() < self.frame:GetLeft() + 5
1167 end
1168 end
1169  
1170 return false
1171 end
1172  
1173 function FuBar_Panel.prototype:CheckForOverlap()
1174 if FuBar:IsOverflowing() and self:HasOverlap() then
1175 local side = 'CENTER'
1176 local plugin = self:GetPlugin(self:GetNumPlugins(side), side)
1177 if not plugin then
1178 side = 'LEFT'
1179 plugin = self:GetPlugin(self:GetNumPlugins(side), side)
1180 if not plugin then
1181 side = 'RIGHT'
1182 plugin = self:GetPlugin(self:GetNumPlugins(side), side)
1183 end
1184 end
1185 local panel
1186 for i = self.id + 1, self.class.id do
1187 if self.class.instances[i]:GetAttachPoint() == self:GetAttachPoint() then
1188 panel = self.class.instances[i]
1189 end
1190 end
1191 if not panel then
1192 panel = FuBar_Panel:new(self:GetAttachPoint())
1193 end
1194 FuBar_Panel:PreventUpdate()
1195 self:RemovePlugin(plugin)
1196 panel:AddPlugin(plugin, 1, side)
1197 FuBar_Panel:StopPreventUpdate()
1198 panel:Update()
1199 self:Update()
1200 end
1201 end