1 QuestHelper_File
["menu.lua"] = "Development Version"
3 QuestHelper
.active_menu
= nil
5 local menuBorderInset
= 4
7 bgFile
= "Interface/Tooltips/UI-Tooltip-Background",
8 edgeFile
= "Interface/Tooltips/UI-Tooltip-Border",
12 insets
= { left
= menuBorderInset
, right
= menuBorderInset
, top
= menuBorderInset
, bottom
= menuBorderInset
}}
13 local menuBackdropColor
= { 0, 0, 0, 0.65 }
14 local menuBackdropBorderColor
= { 1, 1, 1, 0.7 }
16 local function Menu_AddItem(self
, item
)
19 item
:SetPoint("TOPLEFT", self
, "TOPLEFT")
21 table.insert(self
.items
, item
)
24 local function Menu_SetCloseFunction(self
, ...)
26 self
.func
= table.remove(self
.func_arg
, 1)
29 local function Menu_OnUpdate(self
, elapsed
)
31 self
.show_phase
= self
.show_phase
+ elapsed
* 5.0
32 if self
.show_phase
> 1 then
34 self
:SetScript("OnUpdate", nil)
37 self
.show_phase
= self
.show_phase
- elapsed
* 3.0
38 if self
.show_phase
< 0 then
40 self
:SetScript("OnUpdate", nil)
43 self
.func(unpack(self
.func_arg
))
45 if self
.auto_release
then
46 QuestHelper
:ReleaseMenu(self
)
52 self
:SetAlpha(self
.show_phase
)
55 local function Menu_DoShow(self
)
60 for i
, c
in ipairs(self
.items
) do
61 local cw
, ch
= c
:GetSize()
66 local y
= menuBorderInset
68 self
:SetWidth(w
+2*menuBorderInset
)
69 self
:SetHeight(h
+2*menuBorderInset
)
71 self
:SetScript("OnUpdate", self
.OnUpdate
)
73 for i
, c
in ipairs(self
.items
) do
74 local cw
, ch
= c
:GetSize()
77 c
:SetPoint("TOPLEFT", self
, "TOPLEFT", menuBorderInset
, -y
)
82 self
.level
= self
.parent
.parent
.level
+ #self
.parent
.parent
.items
+ 1
83 self
:SetFrameStrata(self
.parent
:GetFrameStrata()) -- It should be sufficient to just set all to "TOOLTIP", but this seemed more versatile...
85 -- When there's no world map, or the world map is in a window, the menus
86 -- are un-parented. So make sure they're at a sufficient strata to be seen.
87 self
:SetFrameStrata("TOOLTIP")
90 self
:SetFrameLevel(self
.level
)
92 for i
, n
in ipairs(self
.items
) do
93 n
.level
= self
.level
+i
94 n
:SetFrameLevel(n
.level
)
95 n
:SetFrameStrata(self
:GetFrameStrata())
100 local function Menu_DoHide(self
)
102 self
:SetScript("OnUpdate", self
.OnUpdate
)
104 if self
.active_item
then
105 self
.active_item
.highlighting
= false
106 self
.active_item
:SetScript("OnUpdate", self
.active_item
.OnUpdate
)
109 for i
, n
in ipairs(self
.items
) do
114 local function Menu_ShowAtCursor(self
, auto_release
)
115 auto_release
= auto_release
== nil and true or auto_release
116 self
.auto_release
= auto_release
118 -- Add a 'Close Menu' item to the end of the menu, if it's not there already
119 if not self
.close_item
then
120 self
.close_item
= QuestHelper
:CreateMenuItem(self
, QHText("MENU_CLOSE"))
121 self
.close_item
:SetFunction( function() self
:DoHide() end )
124 -- Set up the menu position, parentage, etc
125 local x
, y
= GetCursorPosition()
127 local parent
= not UIParent
:IsVisible() and QuestHelper
.map_overlay
or UIParent
128 self
:SetParent(parent
)
129 self
.level
= (parent
or UIParent
):GetFrameLevel()+10
130 self
:ClearAllPoints()
132 -- Need to call DoShow before setting the position so that the width and height will have been calculated.
135 -- I declare this math horrible and convoluted.
136 local scale
= parent
and parent
:GetEffectiveScale() or 1
137 x
, y
= math
.max(0, math
.min(x
-self
:GetWidth()/2*scale
, UIParent
:GetRight()*UIParent
:GetEffectiveScale()-self
:GetWidth()*scale
)) / scale
,
138 math
.min(UIParent
:GetTop()*UIParent
:GetEffectiveScale(), math
.max(self
:GetHeight(), y
+5)) / scale
140 self
:SetPoint("TOPLEFT", UIParent
, "BOTTOMLEFT", x
, y
)
142 if QuestHelper
.active_menu
and QuestHelper
.active_menu
~= self
then
143 QuestHelper
.active_menu
:DoHide()
146 QuestHelper
.active_menu
= self
150 function QuestHelper
:CreateMenu()
151 local menu
= self
:CreateFrame(UIParent
)
154 menu
.items
= self
:CreateTable()
155 menu
:SetMovable(true)
156 menu
:SetFrameStrata("TOOLTIP") -- A good default, but we usually re-parent the menus, which clobbers this.
157 menu
:SetBackdrop(menuBackdrop
)
158 menu
:SetBackdropColor(unpack(menuBackdropColor
))
159 menu
:SetBackdropBorderColor(unpack(menuBackdropBorderColor
))
161 menu
.AddItem
= Menu_AddItem
162 menu
.SetCloseFunction
= Menu_SetCloseFunction
163 menu
.OnUpdate
= Menu_OnUpdate
164 menu
.DoShow
= Menu_DoShow
165 menu
.DoHide
= Menu_DoHide
166 menu
.ShowAtCursor
= Menu_ShowAtCursor
171 menu
:SetFrameLevel(menu
.level
)
176 function QuestHelper
:ReleaseMenu(menu
)
177 while #menu
.items
> 0 do
178 local item
= table.remove(menu
.items
)
179 self
:ReleaseMenuItem(item
)
182 if self
.active_menu
== menu
then
183 self
.active_menu
= nil
186 self
:ReleaseTable(menu
.items
)
187 self
:ReleaseFrame(menu
)
190 local function MenuItem_AddTexture(self
, tex
, before
)
192 table.insert(self
.lchildren
, 1, tex
)
194 table.insert(self
.rchildren
, tex
)
198 local function MenuItem_DoShow(self
)
200 self
:SetScript("OnUpdate", self
.OnUpdate
)
204 local function MenuItem_DoHide(self
)
206 self
.submenu
:DoHide()
210 self
:SetScript("OnUpdate", self
.OnUpdate
)
213 local function MenuItem_OnUpdate(self
, elapsed
)
214 local done_update
= true
216 if self
.highlighting
then
217 self
.highlight_phase
= self
.highlight_phase
+ elapsed
* 3.0
218 if self
.highlight_phase
> 1 then
219 self
.highlight_phase
= 1
224 self
.highlight_phase
= self
.highlight_phase
- elapsed
225 if self
.highlight_phase
< 0 then
226 self
.highlight_phase
= 0
233 self
.show_phase
= self
.show_phase
+ elapsed
* 5.0
234 if self
.show_phase
> 1 then
240 self
.show_phase
= self
.show_phase
- elapsed
* 5.0
241 if self
.show_phase
< 0 then
243 self
.highlight_phase
= 0
251 self
:Shade(self
.show_phase
, self
.highlight_phase
)
254 self
:SetScript("OnUpdate", nil)
258 local function MenuItem_Shade(self
, s
, h
)
259 local theme
= QuestHelper
:GetColourTheme()
263 self
.text
:SetTextColor(ih
*theme
.menu_text
[1]+h
*theme
.menu_text_highlight
[1],
264 ih
*theme
.menu_text
[2]+h
*theme
.menu_text_highlight
[2],
265 ih
*theme
.menu_text
[3]+h
*theme
.menu_text_highlight
[3], 1)
267 self
.text
:SetShadowColor(0, 0, 0, ih
)
268 self
.text
:SetShadowOffset(1, -1)
270 self
.background
:SetVertexColor(ih
*theme
.menu
[1]+h
*theme
.menu_highlight
[1],
271 ih
*theme
.menu
[2]+h
*theme
.menu_highlight
[2],
272 ih
*theme
.menu
[3]+h
*theme
.menu_highlight
[3], h
*0.3+0.4)
277 local function MenuItem_SetFunction(self
, ...)
278 self
.func_arg
= {...}
279 self
.func
= table.remove(self
.func_arg
, 1)
282 local function MenuItem_SetSubmenu(self
, menu
)
283 assert(not self
.submenu
and menu
)
284 menu
:ClearAllPoints()
286 menu
:SetPoint("TOPLEFT", self
, "TOPLEFT")
289 self
:AddTexture(QuestHelper
:CreateIconTexture(self
, 9))
292 local function MenuItem_OnEnter(self
)
293 self
.highlighting
= true
294 self
:SetScript("OnUpdate", self
.OnUpdate
)
296 if self
.parent
.active_item
and self
.parent
.active_item
~= self
then
297 self
.parent
.active_item
.highlighting
= false
298 self
.parent
.active_item
:SetScript("OnUpdate", self
.parent
.active_item
.OnUpdate
)
301 self
.parent
.active_item
= self
303 if self
.parent
.submenu
and self
.parent
.submenu
~= self
.submenu
then
304 self
.parent
.submenu
:DoHide()
305 self
.parent
.submenu
= nil
309 self
.parent
.submenu
= self
.submenu
310 self
.submenu
:ClearAllPoints()
312 local v
, h1
, h2
= "TOP", "LEFT", "RIGHT"
314 self
.submenu
:DoShow()
316 if self
:GetRight()+self
.submenu
:GetWidth() > UIParent
:GetRight()*UIParent
:GetEffectiveScale() then
320 if self
:GetBottom()-self
.submenu
:GetHeight() < 0 then
324 self
.submenu
:SetPoint(v
..h1
, self
, v
..h2
)
325 self
.submenu
:DoShow()
329 local function MenuItem_GetSize(self
)
330 self
.text
:SetParent(nil) -- Remove the text's parent so that it doesn't inherit scaling and mess up the dimensions.
331 self
.text
:ClearAllPoints()
332 self
.text
:SetWidth(0)
333 self
.text
:SetHeight(0)
335 self
.text_w
= self
.text
:GetStringWidth()+20
336 if self
.text_w
>= 320 then
337 -- Clamp width to 320, then ballance the two rows (using a binary search)
338 self
.text
:SetWidth(320)
339 self
.text_h
= self
.text
:GetHeight()+1
340 local mn
, mx
= 100, 321
342 local w
= math
.floor((mn
+mx
)*0.5)
343 self
.text
:SetWidth(w
-1)
344 if self
.text
:GetHeight() <= self
.text_h
then
352 self
.text
:SetWidth(self
.text_w
)
354 self
.text
:SetWidth(self
.text_w
)
355 self
.text_h
= self
.text
:GetHeight()+1
358 self
.text
:SetParent(self
)
360 local w
, h
= self
.text_w
+4, self
.text_h
+4
362 for i
, f
in ipairs(self
.lchildren
) do
363 w
= w
+ f
:GetWidth() + 4
364 h
= math
.max(h
, f
:GetHeight() + 4)
367 for i
, f
in ipairs(self
.rchildren
) do
368 w
= w
+ f
:GetWidth() + 4
369 h
= math
.max(h
, f
:GetHeight() + 4)
372 self
.needed_width
= w
377 local function MenuItem_SetSize(self
, w
, h
)
383 for i
, f
in ipairs(self
.lchildren
) do
384 local cw
, ch
= f
:GetWidth(), f
:GetHeight()
387 f
:SetPoint("TOPLEFT", self
, "TOPLEFT", x
+2, -(h
-ch
)*0.5)
394 for i
, f
in ipairs(self
.rchildren
) do
395 local cw
, ch
= f
:GetWidth(), f
:GetHeight()
398 f
:SetPoint("TOPLEFT", self
, "TOPLEFT", x
+2, -(h
-ch
)*0.5)
401 self
.text
:ClearAllPoints()
402 self
.text
:SetPoint("TOPLEFT", self
, "TOPLEFT", x1
+((x
-x1
)-self
.text_w
)*0.5, -(h
-self
.text_h
)*0.5)
405 local function MenuItem_OnClick(self
, btn
)
406 if btn
== "RightButton" then
407 local parent
= self
.parent
408 while parent
.parent
do
409 parent
= parent
.parent
412 elseif btn
== "LeftButton" and self
.func
then
413 self
.func(unpack(self
.func_arg
))
414 local parent
= self
.parent
415 while parent
.parent
do
416 parent
= parent
.parent
422 function QuestHelper
:CreateMenuItem(menu
, text
)
423 item
= self
:CreateFrame(menu
)
426 item
.lchildren
= self
:CreateTable()
427 item
.rchildren
= self
:CreateTable()
428 item
.text
= self
:CreateText(item
, text
)
429 item
.background
= self
:CreateTexture(item
, 1, 1, 1, 1)
430 item
.background
:SetDrawLayer("BACKGROUND")
431 item
.background
:SetAllPoints()
432 item
.background
:SetVertexColor(0, 0, 0, 0)
435 item
.highlighting
= false
437 item
.highlight_phase
= 0
439 item
.AddTexture
= MenuItem_AddTexture
440 item
.DoShow
= MenuItem_DoShow
441 item
.DoHide
= MenuItem_DoHide
442 item
.OnUpdate
= MenuItem_OnUpdate
443 item
.Shade
= MenuItem_Shade
444 item
.SetFunction
= MenuItem_SetFunction
445 item
.SetSubmenu
= MenuItem_SetSubmenu
446 item
.OnEnter
= MenuItem_OnEnter
447 item
.GetSize
= MenuItem_GetSize
448 item
.SetSize
= MenuItem_SetSize
449 item
.OnClick
= MenuItem_OnClick
451 item
:RegisterForClicks("LeftButtonUp", "RightButtonDown")
452 item
:SetScript("OnEnter", item
.OnEnter
)
453 item
:SetScript("OnClick", item
.OnClick
)
460 function QuestHelper
:ReleaseMenuItem(item
)
463 while #item
.lchildren
> 0 do
464 local child
= table.remove(item
.lchildren
)
465 self
:ReleaseTexture(child
)
468 while #item
.rchildren
> 0 do
469 local child
= table.remove(item
.rchildren
)
470 self
:ReleaseTexture(child
)
474 self
:ReleaseMenu(item
.submenu
)
478 self
:ReleaseTable(item
.lchildren
)
479 self
:ReleaseTable(item
.rchildren
)
480 self
:ReleaseText(item
.text
)
481 self
:ReleaseTexture(item
.background
)
482 self
:ReleaseFrame(item
)
485 local function MenuTitle_OnDragStart(self
)
486 local parent
= self
.parent
488 while parent
.parent
do
489 parent
= parent
.parent
495 local function MenuTitle_OnDragStop(self
)
496 local parent
= self
.parent
498 while parent
.parent
do
499 parent
= parent
.parent
502 parent
:StopMovingOrSizing()
505 local function MenuTitle_Shade(self
, s
, h
)
506 local theme
= QuestHelper
:GetColourTheme()
510 self
.text
:SetTextColor(ih
*theme
.menu_title_text
[1]+h
*theme
.menu_title_text_highlight
[1],
511 ih
*theme
.menu_title_text
[2]+h
*theme
.menu_title_text_highlight
[2],
512 ih
*theme
.menu_title_text
[3]+h
*theme
.menu_title_text_highlight
[3], 1)
514 self
.background
:SetVertexColor(ih
*theme
.menu_title
[1]+h
*theme
.menu_title_highlight
[1],
515 ih
*theme
.menu_title
[2]+h
*theme
.menu_title_highlight
[2],
516 ih
*theme
.menu_title
[3]+h
*theme
.menu_title_highlight
[3], h
*0.3+0.4)
518 self
.text
:SetShadowColor(0, 0, 0, 1)
519 self
.text
:SetShadowOffset(1, -1)
524 local function MenuTitle_OnClick(self
)
525 local parent
= self
.parent
527 while parent
.parent
do
528 parent
= parent
.parent
534 function QuestHelper
:CreateMenuTitle(menu
, title
)
535 local item
= self
:CreateMenuItem(menu
, title
)
537 local f1
, f2
= self
:CreateTexture(item
, "Interface\\AddOns\\QuestHelper\\Art\\Fluff.tga"),
538 self
:CreateTexture(item
, "Interface\\AddOns\\QuestHelper\\Art\\Fluff.tga")
540 f1
:SetTexCoord(0, 1, 0, .5)
543 f2
:SetTexCoord(0, 1, .5, 1)
547 item
:AddTexture(f1
, true)
548 item
:AddTexture(f2
, false)
550 item
.OnDragStart
= MenuTitle_OnDragStart
551 item
.OnDragStop
= MenuTitle_OnDragStop
552 item
.Shade
= MenuTitle_Shade
553 item
.OnClick
= MenuTitle_OnClick
555 item
:RegisterForClicks("RightButtonDown")
556 item
:SetScript("OnClick", item
.OnClick
)
557 item
:SetScript("OnDragStart", item
.OnDragStart
)
558 item
:SetScript("OnDragStop", item
.OnDragStop
)
559 item
:RegisterForDrag("LeftButton")
561 item
.text
:SetFont(QuestHelper
.font
.fancy
, 11)