1 QuestHelper_File
["menu.lua"] = "Development Version"
2 QuestHelper_Loadtime
["menu.lua"] = GetTime()
4 QuestHelper
.active_menu
= nil
6 local menuBorderInset
= 4
8 bgFile
= "Interface/Tooltips/UI-Tooltip-Background",
9 edgeFile
= "Interface/Tooltips/UI-Tooltip-Border",
13 insets
= { left
= menuBorderInset
, right
= menuBorderInset
, top
= menuBorderInset
, bottom
= menuBorderInset
}}
14 local menuBackdropColor
= { 0, 0, 0, 0.65 }
15 local menuBackdropBorderColor
= { 1, 1, 1, 0.7 }
17 local function Menu_AddItem(self
, item
)
20 item
:SetPoint("TOPLEFT", self
, "TOPLEFT")
22 table.insert(self
.items
, item
)
25 local function Menu_SetCloseFunction(self
, ...)
27 self
.func
= table.remove(self
.func_arg
, 1)
30 local function Menu_OnUpdate(self
, elapsed
)
32 self
.show_phase
= self
.show_phase
+ elapsed
* 5.0
33 if self
.show_phase
> 1 then
35 QH_Hook(self
, "OnUpdate", nil)
38 self
.show_phase
= self
.show_phase
- elapsed
* 3.0
39 if self
.show_phase
< 0 then
41 QH_Hook(self
, "OnUpdate", nil)
44 self
.func(unpack(self
.func_arg
))
46 if self
.auto_release
then
47 QuestHelper
:ReleaseMenu(self
)
53 self
:SetAlpha(self
.show_phase
)
56 local function Menu_DoShow(self
)
61 for i
, c
in ipairs(self
.items
) do
62 local cw
, ch
= c
:GetSize()
67 local y
= menuBorderInset
69 self
:SetWidth(w
+2*menuBorderInset
)
70 self
:SetHeight(h
+2*menuBorderInset
)
72 QH_Hook(self
, "OnUpdate", self
.OnUpdate
)
74 for i
, c
in ipairs(self
.items
) do
75 local cw
, ch
= c
:GetSize()
78 c
:SetPoint("TOPLEFT", self
, "TOPLEFT", menuBorderInset
, -y
)
83 self
.level
= self
.parent
.parent
.level
+ #self
.parent
.parent
.items
+ 1
84 self
:SetFrameStrata(self
.parent
:GetFrameStrata()) -- It should be sufficient to just set all to "TOOLTIP", but this seemed more versatile...
86 -- When there's no world map, or the world map is in a window, the menus
87 -- are un-parented. So make sure they're at a sufficient strata to be seen.
88 self
:SetFrameStrata("TOOLTIP")
91 self
:SetFrameLevel(self
.level
)
93 for i
, n
in ipairs(self
.items
) do
94 n
.level
= self
.level
+i
95 n
:SetFrameLevel(n
.level
)
96 n
:SetFrameStrata(self
:GetFrameStrata())
101 local function Menu_DoHide(self
)
103 QH_Hook(self
, "OnUpdate", self
.OnUpdate
)
105 if self
.active_item
then
106 self
.active_item
.highlighting
= false
107 QH_Hook(self
.active_item
, "OnUpdate", self
.active_item
.OnUpdate
)
110 for i
, n
in ipairs(self
.items
) do
115 local function Menu_ShowAtCursor(self
, auto_release
)
116 auto_release
= auto_release
== nil and true or auto_release
117 self
.auto_release
= auto_release
119 -- Add a 'Close Menu' item to the end of the menu, if it's not there already
120 if not self
.close_item
then
121 self
.close_item
= QuestHelper
:CreateMenuItem(self
, QHText("MENU_CLOSE"))
122 self
.close_item
:SetFunction( function() self
:DoHide() end )
125 -- Set up the menu position, parentage, etc
126 local x
, y
= GetCursorPosition()
128 local parent
= not UIParent
:IsVisible() and QuestHelper
.map_overlay
or UIParent
129 self
:SetParent(parent
)
130 self
.level
= (parent
or UIParent
):GetFrameLevel()+10
131 self
:ClearAllPoints()
133 -- Need to call DoShow before setting the position so that the width and height will have been calculated.
136 -- I declare this math horrible and convoluted.
137 local scale
= parent
and parent
:GetEffectiveScale() or 1
138 x
, y
= math
.max(0, math
.min(x
-self
:GetWidth()/2*scale
, UIParent
:GetRight()*UIParent
:GetEffectiveScale()-self
:GetWidth()*scale
)) / scale
,
139 math
.min(UIParent
:GetTop()*UIParent
:GetEffectiveScale(), math
.max(self
:GetHeight(), y
+5)) / scale
141 self
:SetPoint("TOPLEFT", UIParent
, "BOTTOMLEFT", x
, y
)
143 if QuestHelper
.active_menu
and QuestHelper
.active_menu
~= self
then
144 QuestHelper
.active_menu
:DoHide()
147 QuestHelper
.active_menu
= self
151 function QuestHelper
:CreateMenu()
152 local menu
= self
:CreateFrame(UIParent
)
155 menu
.items
= self
:CreateTable()
156 menu
:SetMovable(true)
157 menu
:SetFrameStrata("TOOLTIP") -- A good default, but we usually re-parent the menus, which clobbers this.
158 menu
:SetBackdrop(menuBackdrop
)
159 menu
:SetBackdropColor(unpack(menuBackdropColor
))
160 menu
:SetBackdropBorderColor(unpack(menuBackdropBorderColor
))
162 menu
.AddItem
= Menu_AddItem
163 menu
.SetCloseFunction
= Menu_SetCloseFunction
164 menu
.OnUpdate
= Menu_OnUpdate
165 menu
.DoShow
= Menu_DoShow
166 menu
.DoHide
= Menu_DoHide
167 menu
.ShowAtCursor
= Menu_ShowAtCursor
172 menu
:SetFrameLevel(menu
.level
)
177 function QuestHelper
:ReleaseMenu(menu
)
178 while #menu
.items
> 0 do
179 local item
= table.remove(menu
.items
)
180 self
:ReleaseMenuItem(item
)
183 if self
.active_menu
== menu
then
184 self
.active_menu
= nil
187 self
:ReleaseTable(menu
.items
)
188 self
:ReleaseFrame(menu
)
191 local function MenuItem_AddTexture(self
, tex
, before
)
193 table.insert(self
.lchildren
, 1, tex
)
195 table.insert(self
.rchildren
, tex
)
199 local function MenuItem_DoShow(self
)
201 QH_Hook(self
, "OnUpdate", self
.OnUpdate
)
205 local function MenuItem_DoHide(self
)
207 self
.submenu
:DoHide()
211 QH_Hook(self
, "OnUpdate", self
.OnUpdate
)
214 local function MenuItem_OnUpdate(self
, elapsed
)
215 local done_update
= true
217 if self
.highlighting
then
218 self
.highlight_phase
= self
.highlight_phase
+ elapsed
* 3.0
219 if self
.highlight_phase
> 1 then
220 self
.highlight_phase
= 1
225 self
.highlight_phase
= self
.highlight_phase
- elapsed
226 if self
.highlight_phase
< 0 then
227 self
.highlight_phase
= 0
234 self
.show_phase
= self
.show_phase
+ elapsed
* 5.0
235 if self
.show_phase
> 1 then
241 self
.show_phase
= self
.show_phase
- elapsed
* 5.0
242 if self
.show_phase
< 0 then
244 self
.highlight_phase
= 0
252 self
:Shade(self
.show_phase
, self
.highlight_phase
)
255 QH_Hook(self
, "OnUpdate", nil)
259 local function MenuItem_Shade(self
, s
, h
)
260 local theme
= QuestHelper
:GetColourTheme()
264 self
.text
:SetTextColor(ih
*theme
.menu_text
[1]+h
*theme
.menu_text_highlight
[1],
265 ih
*theme
.menu_text
[2]+h
*theme
.menu_text_highlight
[2],
266 ih
*theme
.menu_text
[3]+h
*theme
.menu_text_highlight
[3], 1)
268 self
.text
:SetShadowColor(0, 0, 0, ih
)
269 self
.text
:SetShadowOffset(1, -1)
271 self
.background
:SetVertexColor(ih
*theme
.menu
[1]+h
*theme
.menu_highlight
[1],
272 ih
*theme
.menu
[2]+h
*theme
.menu_highlight
[2],
273 ih
*theme
.menu
[3]+h
*theme
.menu_highlight
[3], h
*0.3+0.4)
278 local function MenuItem_SetFunction(self
, ...)
279 self
.func_arg
= {...}
280 self
.func
= table.remove(self
.func_arg
, 1)
283 local function MenuItem_SetSubmenu(self
, menu
)
284 assert(not self
.submenu
and menu
)
285 menu
:ClearAllPoints()
287 menu
:SetPoint("TOPLEFT", self
, "TOPLEFT")
290 self
:AddTexture(QuestHelper
:CreateIconTexture(self
, 9))
293 local function MenuItem_OnEnter(self
)
294 self
.highlighting
= true
295 QH_Hook(self
, "OnUpdate", self
.OnUpdate
)
297 if self
.parent
.active_item
and self
.parent
.active_item
~= self
then
298 self
.parent
.active_item
.highlighting
= false
299 QH_Hook(self
.parent
.active_item
, "OnUpdate", self
.parent
.active_item
.OnUpdate
)
302 self
.parent
.active_item
= self
304 if self
.parent
.submenu
and self
.parent
.submenu
~= self
.submenu
then
305 self
.parent
.submenu
:DoHide()
306 self
.parent
.submenu
= nil
310 self
.parent
.submenu
= self
.submenu
311 self
.submenu
:ClearAllPoints()
313 local v
, h1
, h2
= "TOP", "LEFT", "RIGHT"
315 self
.submenu
:DoShow()
317 if self
:GetRight()+self
.submenu
:GetWidth() > UIParent
:GetRight()*UIParent
:GetEffectiveScale() then
321 if self
:GetBottom()-self
.submenu
:GetHeight() < 0 then
325 self
.submenu
:SetPoint(v
..h1
, self
, v
..h2
)
326 self
.submenu
:DoShow()
330 local function MenuItem_GetSize(self
)
331 self
.text
:SetParent(UIParent
) -- Remove the text's parent so that it doesn't inherit scaling and mess up the dimensions.
332 self
.text
:ClearAllPoints()
333 self
.text
:SetWidth(0)
334 self
.text
:SetHeight(0)
336 self
.text_w
= self
.text
:GetStringWidth()+20
337 if self
.text_w
>= 320 then
338 -- Clamp width to 320, then ballance the two rows (using a binary search)
339 self
.text
:SetWidth(320)
340 self
.text_h
= self
.text
:GetHeight()+1
341 local mn
, mx
= 100, 321
343 local w
= math
.floor((mn
+mx
)*0.5)
344 self
.text
:SetWidth(w
-1)
345 if self
.text
:GetHeight() <= self
.text_h
then
353 self
.text
:SetWidth(self
.text_w
)
355 self
.text
:SetWidth(self
.text_w
)
356 self
.text_h
= self
.text
:GetHeight()+1
359 self
.text
:SetParent(self
)
361 local w
, h
= self
.text_w
+4, self
.text_h
+4
363 for i
, f
in ipairs(self
.lchildren
) do
364 w
= w
+ f
:GetWidth() + 4
365 h
= math
.max(h
, f
:GetHeight() + 4)
368 for i
, f
in ipairs(self
.rchildren
) do
369 w
= w
+ f
:GetWidth() + 4
370 h
= math
.max(h
, f
:GetHeight() + 4)
373 self
.needed_width
= w
378 local function MenuItem_SetSize(self
, w
, h
)
384 for i
, f
in ipairs(self
.lchildren
) do
385 local cw
, ch
= f
:GetWidth(), f
:GetHeight()
388 f
:SetPoint("TOPLEFT", self
, "TOPLEFT", x
+2, -(h
-ch
)*0.5)
395 for i
, f
in ipairs(self
.rchildren
) do
396 local cw
, ch
= f
:GetWidth(), f
:GetHeight()
399 f
:SetPoint("TOPLEFT", self
, "TOPLEFT", x
+2, -(h
-ch
)*0.5)
402 self
.text
:ClearAllPoints()
403 self
.text
:SetPoint("TOPLEFT", self
, "TOPLEFT", x1
+((x
-x1
)-self
.text_w
)*0.5, -(h
-self
.text_h
)*0.5)
406 local function MenuItem_OnClick(self
, btn
)
407 if btn
== "RightButton" then
408 local parent
= self
.parent
409 while parent
.parent
do
410 parent
= parent
.parent
413 elseif btn
== "LeftButton" and self
.func
then
414 self
.func(unpack(self
.func_arg
))
415 local parent
= self
.parent
416 while parent
.parent
do
417 parent
= parent
.parent
423 function QuestHelper
:CreateMenuItem(menu
, text
)
424 item
= self
:CreateFrame(menu
)
427 item
.lchildren
= self
:CreateTable()
428 item
.rchildren
= self
:CreateTable()
429 item
.text
= self
:CreateText(item
, text
)
430 item
.background
= self
:CreateTexture(item
, 1, 1, 1, 1)
431 item
.background
:SetDrawLayer("BACKGROUND")
432 item
.background
:SetAllPoints()
433 item
.background
:SetVertexColor(0, 0, 0, 0)
436 item
.highlighting
= false
438 item
.highlight_phase
= 0
440 item
.AddTexture
= MenuItem_AddTexture
441 item
.DoShow
= MenuItem_DoShow
442 item
.DoHide
= MenuItem_DoHide
443 item
.OnUpdate
= MenuItem_OnUpdate
444 item
.Shade
= MenuItem_Shade
445 item
.SetFunction
= MenuItem_SetFunction
446 item
.SetSubmenu
= MenuItem_SetSubmenu
447 item
.OnEnter
= MenuItem_OnEnter
448 item
.GetSize
= MenuItem_GetSize
449 item
.SetSize
= MenuItem_SetSize
450 item
.OnClick
= MenuItem_OnClick
452 item
:RegisterForClicks("LeftButtonUp", "RightButtonDown")
453 QH_Hook(item
, "OnEnter", item
.OnEnter
)
454 QH_Hook(item
, "OnClick", item
.OnClick
)
461 function QuestHelper
:ReleaseMenuItem(item
)
464 while #item
.lchildren
> 0 do
465 local child
= table.remove(item
.lchildren
)
466 self
:ReleaseTexture(child
)
469 while #item
.rchildren
> 0 do
470 local child
= table.remove(item
.rchildren
)
471 self
:ReleaseTexture(child
)
475 self
:ReleaseMenu(item
.submenu
)
479 self
:ReleaseTable(item
.lchildren
)
480 self
:ReleaseTable(item
.rchildren
)
481 self
:ReleaseText(item
.text
)
482 self
:ReleaseTexture(item
.background
)
483 self
:ReleaseFrame(item
)
486 local function MenuTitle_OnDragStart(self
)
487 local parent
= self
.parent
489 while parent
.parent
do
490 parent
= parent
.parent
496 local function MenuTitle_OnDragStop(self
)
497 local parent
= self
.parent
499 while parent
.parent
do
500 parent
= parent
.parent
503 parent
:StopMovingOrSizing()
506 local function MenuTitle_Shade(self
, s
, h
)
507 local theme
= QuestHelper
:GetColourTheme()
511 self
.text
:SetTextColor(ih
*theme
.menu_title_text
[1]+h
*theme
.menu_title_text_highlight
[1],
512 ih
*theme
.menu_title_text
[2]+h
*theme
.menu_title_text_highlight
[2],
513 ih
*theme
.menu_title_text
[3]+h
*theme
.menu_title_text_highlight
[3], 1)
515 self
.background
:SetVertexColor(ih
*theme
.menu_title
[1]+h
*theme
.menu_title_highlight
[1],
516 ih
*theme
.menu_title
[2]+h
*theme
.menu_title_highlight
[2],
517 ih
*theme
.menu_title
[3]+h
*theme
.menu_title_highlight
[3], h
*0.3+0.4)
519 self
.text
:SetShadowColor(0, 0, 0, 1)
520 self
.text
:SetShadowOffset(1, -1)
525 local function MenuTitle_OnClick(self
)
526 local parent
= self
.parent
528 while parent
.parent
do
529 parent
= parent
.parent
535 function QuestHelper
:CreateMenuTitle(menu
, title
)
536 local item
= self
:CreateMenuItem(menu
, title
)
538 local f1
, f2
= self
:CreateTexture(item
, "Interface\\AddOns\\QuestHelper\\Art\\Fluff.tga"),
539 self
:CreateTexture(item
, "Interface\\AddOns\\QuestHelper\\Art\\Fluff.tga")
541 f1
:SetTexCoord(0, 1, 0, .5)
544 f2
:SetTexCoord(0, 1, .5, 1)
548 item
:AddTexture(f1
, true)
549 item
:AddTexture(f2
, false)
551 item
.OnDragStart
= MenuTitle_OnDragStart
552 item
.OnDragStop
= MenuTitle_OnDragStop
553 item
.Shade
= MenuTitle_Shade
554 item
.OnClick
= MenuTitle_OnClick
556 item
:RegisterForClicks("RightButtonDown")
557 QH_Hook(item
, "OnClick", item
.OnClick
)
558 QH_Hook(item
, "OnDragStart", item
.OnDragStart
)
559 QH_Hook(item
, "OnDragStop", item
.OnDragStop
)
560 item
:RegisterForDrag("LeftButton")
562 item
.text
:SetFont(QuestHelper
.font
.fancy
, 11)