2012-01-01 04:01:18 +01:00
local GetTime = QuestHelper_GetTime
2010-11-08 14:28:59 +01:00
QuestHelper_File [ " menu.lua " ] = " 4.0.1.$svnversion$ "
2010-10-24 23:17:33 +02:00
QuestHelper_Loadtime [ " menu.lua " ] = GetTime ( )
QuestHelper.active_menu = nil
local menuBorderInset = 4
local menuBackdrop = {
bgFile = " Interface/Tooltips/UI-Tooltip-Background " ,
edgeFile = " Interface/Tooltips/UI-Tooltip-Border " ,
edgeSize = 16 ,
tile = true ,
tileSize = 16 ,
insets = { left = menuBorderInset , right = menuBorderInset , top = menuBorderInset , bottom = menuBorderInset } }
local menuBackdropColor = { 0 , 0 , 0 , 0.65 }
local menuBackdropBorderColor = { 1 , 1 , 1 , 0.7 }
local function Menu_AddItem ( self , item )
item : ClearAllPoints ( )
item : SetParent ( self )
item : SetPoint ( " TOPLEFT " , self , " TOPLEFT " )
item.parent = self
table.insert ( self.items , item )
end
local function Menu_SetCloseFunction ( self , ... )
self.func_arg = { ... }
self.func = table.remove ( self.func_arg , 1 )
end
local function Menu_OnUpdate ( self , elapsed )
if self.showing then
self.show_phase = self.show_phase + elapsed * 5.0
if self.show_phase > 1 then
self.show_phase = 1
QH_Hook ( self , " OnUpdate " , nil )
end
else
self.show_phase = self.show_phase - elapsed * 3.0
if self.show_phase < 0 then
self.show_phase = 0
QH_Hook ( self , " OnUpdate " , nil )
self : Hide ( )
if self.func then
self.func ( unpack ( self.func_arg ) )
end
if self.auto_release then
QuestHelper : ReleaseMenu ( self )
return
end
end
end
self : SetAlpha ( self.show_phase )
end
local function Menu_DoShow ( self )
self.showing = true
local w , h = 0 , 0
for i , c in ipairs ( self.items ) do
local cw , ch = c : GetSize ( )
w = math.max ( w , cw )
h = h + ch
end
local y = menuBorderInset
self : SetWidth ( w + 2 * menuBorderInset )
self : SetHeight ( h + 2 * menuBorderInset )
self : Show ( )
QH_Hook ( self , " OnUpdate " , self.OnUpdate )
for i , c in ipairs ( self.items ) do
local cw , ch = c : GetSize ( )
c : ClearAllPoints ( )
c : SetSize ( w , ch )
c : SetPoint ( " TOPLEFT " , self , " TOPLEFT " , menuBorderInset , - y )
y = y + ch
end
if self.parent then
self.level = self.parent . parent.level + # self.parent . parent.items + 1
self : SetFrameStrata ( self.parent : GetFrameStrata ( ) ) -- It should be sufficient to just set all to "TOOLTIP", but this seemed more versatile...
else
-- When there's no world map, or the world map is in a window, the menus
-- are un-parented. So make sure they're at a sufficient strata to be seen.
self : SetFrameStrata ( " TOOLTIP " )
end
self : SetFrameLevel ( self.level )
for i , n in ipairs ( self.items ) do
n.level = self.level + i
n : SetFrameLevel ( n.level )
n : SetFrameStrata ( self : GetFrameStrata ( ) )
n : DoShow ( )
end
end
local function Menu_DoHide ( self )
self.showing = false
QH_Hook ( self , " OnUpdate " , self.OnUpdate )
if self.active_item then
self.active_item . highlighting = false
QH_Hook ( self.active_item , " OnUpdate " , self.active_item . OnUpdate )
end
for i , n in ipairs ( self.items ) do
n : DoHide ( )
end
end
local function Menu_ShowAtCursor ( self , auto_release )
auto_release = ( auto_release == nil ) and true or auto_release
self.auto_release = auto_release
-- Add a 'Close Menu' item to the end of the menu, if it's not there already
if not self.close_item then
self.close_item = QuestHelper : CreateMenuItem ( self , QHText ( " MENU_CLOSE " ) )
self.close_item : SetFunction ( function ( ) self : DoHide ( ) end )
end
-- Set up the menu position, parentage, etc
local x , y = GetCursorPosition ( )
local parent = not UIParent : IsVisible ( ) and QuestHelper.map_overlay_uncropped or UIParent
self : SetParent ( parent )
self.level = ( parent or UIParent ) : GetFrameLevel ( ) + 10
self : ClearAllPoints ( )
-- Need to call DoShow before setting the position so that the width and height will have been calculated.
self : DoShow ( )
-- I declare this math horrible and convoluted.
local scale = parent and parent : GetEffectiveScale ( ) or 1
x , y = math.max ( 0 , math.min ( x - self : GetWidth ( ) / 2 * scale , UIParent : GetRight ( ) * UIParent : GetEffectiveScale ( ) - self : GetWidth ( ) * scale ) ) / scale ,
math.min ( UIParent : GetTop ( ) * UIParent : GetEffectiveScale ( ) , math.max ( self : GetHeight ( ) , y + 5 ) ) / scale
self : SetPoint ( " TOPLEFT " , UIParent , " BOTTOMLEFT " , x , y )
if QuestHelper.active_menu and QuestHelper.active_menu ~= self then
QuestHelper.active_menu : DoHide ( )
end
QuestHelper.active_menu = self
end
function QuestHelper : CreateMenu ( )
local menu = self : CreateFrame ( UIParent )
menu : Hide ( )
menu.items = self : CreateTable ( )
menu : SetMovable ( true )
menu : SetFrameStrata ( " TOOLTIP " ) -- A good default, but we usually re-parent the menus, which clobbers this.
menu : SetBackdrop ( menuBackdrop )
menu : SetBackdropColor ( unpack ( menuBackdropColor ) )
menu : SetBackdropBorderColor ( unpack ( menuBackdropBorderColor ) )
menu.AddItem = Menu_AddItem
menu.SetCloseFunction = Menu_SetCloseFunction
menu.OnUpdate = Menu_OnUpdate
menu.DoShow = Menu_DoShow
menu.DoHide = Menu_DoHide
menu.ShowAtCursor = Menu_ShowAtCursor
menu.show_phase = 0
menu.showing = false
menu.level = 2
menu : SetFrameLevel ( menu.level )
return menu
end
function QuestHelper : ReleaseMenu ( menu )
while # menu.items > 0 do
local item = table.remove ( menu.items )
self : ReleaseMenuItem ( item )
end
if self.active_menu == menu then
self.active_menu = nil
end
self : ReleaseTable ( menu.items )
self : ReleaseFrame ( menu )
end
local function MenuItem_AddTexture ( self , tex , before )
if before then
table.insert ( self.lchildren , 1 , tex )
else
table.insert ( self.rchildren , tex )
end
end
local function MenuItem_DoShow ( self )
self.showing = true
QH_Hook ( self , " OnUpdate " , self.OnUpdate )
self : Show ( )
end
local function MenuItem_DoHide ( self )
if self.submenu then
self.submenu : DoHide ( )
end
self.showing = false
QH_Hook ( self , " OnUpdate " , self.OnUpdate )
end
local function MenuItem_OnUpdate ( self , elapsed )
local done_update = true
if self.highlighting then
self.highlight_phase = self.highlight_phase + elapsed * 3.0
if self.highlight_phase > 1 then
self.highlight_phase = 1
else
done_update = false
end
else
self.highlight_phase = self.highlight_phase - elapsed
if self.highlight_phase < 0 then
self.highlight_phase = 0
else
done_update = false
end
end
if self.showing then
self.show_phase = self.show_phase + elapsed * 5.0
if self.show_phase > 1 then
self.show_phase = 1
else
done_update = false
end
else
self.show_phase = self.show_phase - elapsed * 5.0
if self.show_phase < 0 then
self.show_phase = 0
self.highlight_phase = 0
self : Hide ( )
done_update = true
else
done_update = false
end
end
self : Shade ( self.show_phase , self.highlight_phase )
if done_update then
QH_Hook ( self , " OnUpdate " , nil )
end
end
local function MenuItem_Shade ( self , s , h )
local theme = QuestHelper : GetColourTheme ( )
local ih = 1 - h
self.text : SetTextColor ( ih * theme.menu_text [ 1 ] + h * theme.menu_text_highlight [ 1 ] ,
ih * theme.menu_text [ 2 ] + h * theme.menu_text_highlight [ 2 ] ,
ih * theme.menu_text [ 3 ] + h * theme.menu_text_highlight [ 3 ] , 1 )
self.text : SetShadowColor ( 0 , 0 , 0 , ih )
self.text : SetShadowOffset ( 1 , - 1 )
self.background : SetVertexColor ( ih * theme.menu [ 1 ] + h * theme.menu_highlight [ 1 ] ,
ih * theme.menu [ 2 ] + h * theme.menu_highlight [ 2 ] ,
ih * theme.menu [ 3 ] + h * theme.menu_highlight [ 3 ] , h * 0.3 + 0.4 )
self : SetAlpha ( s )
end
local function MenuItem_SetFunction ( self , ... )
self.func_arg = { ... }
self.func = table.remove ( self.func_arg , 1 )
end
local function MenuItem_SetSubmenu ( self , menu )
--[[ assert(not self.submenu and menu) ]]
menu : ClearAllPoints ( )
menu : SetParent ( self )
menu : SetPoint ( " TOPLEFT " , self , " TOPLEFT " )
menu.parent = self
self.submenu = menu
self : AddTexture ( QuestHelper : CreateIconTexture ( self , 9 ) )
end
local function MenuItem_OnEnter ( self )
self.highlighting = true
QH_Hook ( self , " OnUpdate " , self.OnUpdate )
if self.parent . active_item and self.parent . active_item ~= self then
self.parent . active_item.highlighting = false
QH_Hook ( self.parent . active_item , " OnUpdate " , self.parent . active_item.OnUpdate )
end
self.parent . active_item = self
if self.parent . submenu and self.parent . submenu ~= self.submenu then
self.parent . submenu : DoHide ( )
self.parent . submenu = nil
end
if self.submenu then
self.parent . submenu = self.submenu
self.submenu : ClearAllPoints ( )
local v , h1 , h2 = " TOP " , " LEFT " , " RIGHT "
self.submenu : DoShow ( )
if self : GetRight ( ) + self.submenu : GetWidth ( ) > UIParent : GetRight ( ) * UIParent : GetEffectiveScale ( ) then
h1 , h2 = h2 , h1
end
if self : GetBottom ( ) - self.submenu : GetHeight ( ) < 0 then
v = " BOTTOM "
end
self.submenu : SetPoint ( v .. h1 , self , v .. h2 )
self.submenu : DoShow ( )
end
end
local function MenuItem_GetSize ( self )
self.text : SetParent ( UIParent ) -- Remove the text's parent so that it doesn't inherit scaling and mess up the dimensions.
self.text : ClearAllPoints ( )
self.text : SetWidth ( 0 )
self.text : SetHeight ( 0 )
self.text_w = self.text : GetStringWidth ( ) + 20
if self.text_w >= 320 then
-- Clamp width to 320, then ballance the two rows (using a binary search)
self.text : SetWidth ( 320 )
self.text_h = self.text : GetHeight ( ) + 1
local mn , mx = 100 , 321
while mn ~= mx do
local w = math.floor ( ( mn + mx ) * 0.5 )
self.text : SetWidth ( w - 1 )
if self.text : GetHeight ( ) <= self.text_h then
mx = w
else
mn = w + 1
end
end
self.text_w = mn + 1
self.text : SetWidth ( self.text_w )
else
self.text : SetWidth ( self.text_w )
self.text_h = self.text : GetHeight ( ) + 1
end
self.text : SetParent ( self )
local w , h = self.text_w + 4 , self.text_h + 4
for i , f in ipairs ( self.lchildren ) do
w = w + f : GetWidth ( ) + 4
h = math.max ( h , f : GetHeight ( ) + 4 )
end
for i , f in ipairs ( self.rchildren ) do
w = w + f : GetWidth ( ) + 4
h = math.max ( h , f : GetHeight ( ) + 4 )
end
self.needed_width = w
return w , h
end
local function MenuItem_SetSize ( self , w , h )
self : SetWidth ( w )
self : SetHeight ( h )
local x = 0
for i , f in ipairs ( self.lchildren ) do
local cw , ch = f : GetWidth ( ) , f : GetHeight ( )
f : ClearAllPoints ( )
f : SetPoint ( " TOPLEFT " , self , " TOPLEFT " , x + 2 , - ( h - ch ) * 0.5 )
x = x + cw + 4
end
local x1 = x
x = w
for i , f in ipairs ( self.rchildren ) do
local cw , ch = f : GetWidth ( ) , f : GetHeight ( )
f : ClearAllPoints ( )
x = x - cw - 4
f : SetPoint ( " TOPLEFT " , self , " TOPLEFT " , x + 2 , - ( h - ch ) * 0.5 )
end
self.text : ClearAllPoints ( )
self.text : SetPoint ( " TOPLEFT " , self , " TOPLEFT " , x1 + ( ( x - x1 ) - self.text_w ) * 0.5 , - ( h - self.text_h ) * 0.5 )
end
local function MenuItem_OnClick ( self , btn )
if btn == " RightButton " then
local parent = self.parent
while parent.parent do
parent = parent.parent
end
parent : DoHide ( )
elseif btn == " LeftButton " and self.func then
self.func ( unpack ( self.func_arg ) )
local parent = self.parent
while parent.parent do
parent = parent.parent
end
parent : DoHide ( )
end
end
function QuestHelper : CreateMenuItem ( menu , text )
item = self : CreateFrame ( menu )
item : Hide ( )
item.lchildren = self : CreateTable ( )
item.rchildren = self : CreateTable ( )
item.text = self : CreateText ( item , text )
item.background = self : CreateTexture ( item , 1 , 1 , 1 , 1 )
item.background : SetDrawLayer ( " BACKGROUND " )
item.background : SetAllPoints ( )
item.background : SetVertexColor ( 0 , 0 , 0 , 0 )
item.showing = false
item.highlighting = false
item.show_phase = 0
item.highlight_phase = 0
item.AddTexture = MenuItem_AddTexture
item.DoShow = MenuItem_DoShow
item.DoHide = MenuItem_DoHide
item.OnUpdate = MenuItem_OnUpdate
item.Shade = MenuItem_Shade
item.SetFunction = MenuItem_SetFunction
item.SetSubmenu = MenuItem_SetSubmenu
item.OnEnter = MenuItem_OnEnter
item.GetSize = MenuItem_GetSize
item.SetSize = MenuItem_SetSize
item.OnClick = MenuItem_OnClick
item : RegisterForClicks ( " LeftButtonUp " , " RightButtonDown " )
QH_Hook ( item , " OnEnter " , item.OnEnter )
QH_Hook ( item , " OnClick " , item.OnClick )
menu : AddItem ( item )
return item
end
function QuestHelper : ReleaseMenuItem ( item )
item : Hide ( )
while # item.lchildren > 0 do
local child = table.remove ( item.lchildren )
self : ReleaseTexture ( child )
end
while # item.rchildren > 0 do
local child = table.remove ( item.rchildren )
self : ReleaseTexture ( child )
end
if item.submenu then
self : ReleaseMenu ( item.submenu )
item.submenu = nil
end
self : ReleaseTable ( item.lchildren )
self : ReleaseTable ( item.rchildren )
self : ReleaseText ( item.text )
self : ReleaseTexture ( item.background )
self : ReleaseFrame ( item )
end
local function MenuTitle_OnDragStart ( self )
local parent = self.parent
while parent.parent do
parent = parent.parent
end
parent : StartMoving ( )
end
local function MenuTitle_OnDragStop ( self )
local parent = self.parent
while parent.parent do
parent = parent.parent
end
parent : StopMovingOrSizing ( )
end
local function MenuTitle_Shade ( self , s , h )
local theme = QuestHelper : GetColourTheme ( )
local ih = 1 - h
self.text : SetTextColor ( ih * theme.menu_title_text [ 1 ] + h * theme.menu_title_text_highlight [ 1 ] ,
ih * theme.menu_title_text [ 2 ] + h * theme.menu_title_text_highlight [ 2 ] ,
ih * theme.menu_title_text [ 3 ] + h * theme.menu_title_text_highlight [ 3 ] , 1 )
self.background : SetVertexColor ( ih * theme.menu_title [ 1 ] + h * theme.menu_title_highlight [ 1 ] ,
ih * theme.menu_title [ 2 ] + h * theme.menu_title_highlight [ 2 ] ,
ih * theme.menu_title [ 3 ] + h * theme.menu_title_highlight [ 3 ] , h * 0.3 + 0.4 )
self.text : SetShadowColor ( 0 , 0 , 0 , 1 )
self.text : SetShadowOffset ( 1 , - 1 )
self : SetAlpha ( s )
end
local function MenuTitle_OnClick ( self )
local parent = self.parent
while parent.parent do
parent = parent.parent
end
parent : DoHide ( )
end
function QuestHelper : CreateMenuTitle ( menu , title )
local item = self : CreateMenuItem ( menu , title )
local f1 , f2 = self : CreateTexture ( item , " Interface \\ AddOns \\ QuestHelper \\ Art \\ Fluff.tga " ) ,
self : CreateTexture ( item , " Interface \\ AddOns \\ QuestHelper \\ Art \\ Fluff.tga " )
f1 : SetTexCoord ( 0 , 1 , 0 , .5 )
f1 : SetWidth ( 20 )
f1 : SetHeight ( 10 )
f2 : SetTexCoord ( 0 , 1 , .5 , 1 )
f2 : SetWidth ( 20 )
f2 : SetHeight ( 10 )
item : AddTexture ( f1 , true )
item : AddTexture ( f2 , false )
item.OnDragStart = MenuTitle_OnDragStart
item.OnDragStop = MenuTitle_OnDragStop
item.Shade = MenuTitle_Shade
item.OnClick = MenuTitle_OnClick
item : RegisterForClicks ( " RightButtonDown " )
QH_Hook ( item , " OnClick " , item.OnClick )
QH_Hook ( item , " OnDragStart " , item.OnDragStart )
QH_Hook ( item , " OnDragStop " , item.OnDragStop )
item : RegisterForDrag ( " LeftButton " )
item.text : SetFont ( QuestHelper.font . fancy , 11 )
end