1 /*
2 	GWEN
3 	Copyright (c) 2010 Facepunch Studios
4 	See license in Gwen.h
5 */
6 
7 #include "Gwen/Gwen.h"
8 #include "Gwen/Controls/Menu.h"
9 #include "Gwen/Skin.h"
10 #include "Gwen/Utility.h"
11 
12 using namespace Gwen;
13 using namespace Gwen::Controls;
14 
GWEN_CONTROL_CONSTRUCTOR(Menu)15 GWEN_CONTROL_CONSTRUCTOR(Menu)
16 {
17 	SetBounds(0, 0, 10, 10);
18 	SetPadding(Padding(2, 2, 2, 2));
19 
20 	SetDisableIconMargin(false);
21 
22 	SetAutoHideBars(true);
23 	SetScroll(false, true);
24 }
25 
Render(Skin::Base * skin)26 void Menu::Render(Skin::Base* skin)
27 {
28 	skin->DrawMenu(this, IconMarginDisabled());
29 }
30 
RenderUnder(Skin::Base * skin)31 void Menu::RenderUnder(Skin::Base* skin)
32 {
33 	BaseClass::RenderUnder(skin);
34 	skin->DrawShadow(this);
35 }
36 
Layout(Skin::Base * skin)37 void Menu::Layout(Skin::Base* skin)
38 {
39 	int childrenHeight = 0;
40 	for (Base::List::iterator it = m_InnerPanel->Children.begin(); it != m_InnerPanel->Children.end(); ++it)
41 	{
42 		Base* pChild = (*it);
43 		if (!pChild)
44 			continue;
45 
46 		childrenHeight += pChild->Height();
47 	}
48 
49 	if (Y() + childrenHeight > GetCanvas()->Height())
50 		childrenHeight = GetCanvas()->Height() - Y();
51 
52 	SetSize(Width(), childrenHeight);
53 
54 	BaseClass::Layout(skin);
55 }
56 
AddItem(const Gwen::UnicodeString & strName,const UnicodeString & strIconName,Gwen::Event::Handler * pHandler,Gwen::Event::Handler::Function fn)57 MenuItem* Menu::AddItem(const Gwen::UnicodeString& strName, const UnicodeString& strIconName, Gwen::Event::Handler* pHandler, Gwen::Event::Handler::Function fn)
58 {
59 	MenuItem* pItem = new MenuItem(this);
60 	pItem->SetText(strName);
61 	pItem->SetImage(strIconName);
62 
63 	if (fn && pHandler)
64 	{
65 		pItem->onMenuItemSelected.Add(pHandler, fn);
66 	}
67 
68 	OnAddItem(pItem);
69 
70 	return pItem;
71 }
72 
OnAddItem(MenuItem * item)73 void Menu::OnAddItem(MenuItem* item)
74 {
75 	item->Dock(Pos::Top);
76 	item->SetTextPadding(Padding(IconMarginDisabled() ? 0 : 24, 0, 16, 0));
77 	item->SetPadding(Padding(4, 4, 4, 4));
78 	item->SizeToContents();
79 	item->SetAlignment(Pos::CenterV | Pos::Left);
80 	item->onHoverEnter.Add(this, &Menu::OnHoverItem);
81 
82 	// Do this here - after Top Docking these values mean nothing in layout
83 	int w = item->Width() + 10 + 32;
84 	if (w < Width()) w = Width();
85 	SetSize(w, Height());
86 }
87 
ClearItems()88 void Menu::ClearItems()
89 {
90 	for (Base::List::iterator it = m_InnerPanel->Children.begin(); it != m_InnerPanel->Children.end(); ++it)
91 	{
92 		Base* pChild = *it;
93 
94 		if (!pChild) continue;
95 		pChild->DelayedDelete();
96 	}
97 }
98 
AddItem(const Gwen::String & strName,const String & strIconName,Gwen::Event::Handler * pHandler,Gwen::Event::Handler::Function fn)99 MenuItem* Menu::AddItem(const Gwen::String& strName, const String& strIconName, Gwen::Event::Handler* pHandler, Gwen::Event::Handler::Function fn)
100 {
101 	return AddItem(Gwen::Utility::StringToUnicode(strName), Gwen::Utility::StringToUnicode(strIconName), pHandler, fn);
102 }
103 
CloseAll()104 void Menu::CloseAll()
105 {
106 	for (Base::List::iterator it = m_InnerPanel->Children.begin(); it != m_InnerPanel->Children.end(); ++it)
107 	{
108 		Base* pChild = *it;
109 		MenuItem* pItem = pChild->DynamicCastMenuItem();
110 		if (!pItem) continue;
111 
112 		pItem->CloseMenu();
113 	}
114 }
115 
IsMenuOpen()116 bool Menu::IsMenuOpen()
117 {
118 	for (Base::List::iterator it = m_InnerPanel->Children.begin(); it != m_InnerPanel->Children.end(); ++it)
119 	{
120 		Base* pChild = *it;
121 		MenuItem* pItem = pChild->DynamicCastMenuItem();
122 		if (!pItem) continue;
123 
124 		if (pItem->IsMenuOpen())
125 			return true;
126 	}
127 
128 	return false;
129 }
130 
OnHoverItem(Gwen::Controls::Base * pControl)131 void Menu::OnHoverItem(Gwen::Controls::Base* pControl)
132 {
133 	if (!ShouldHoverOpenMenu()) return;
134 
135 	MenuItem* pItem = pControl->DynamicCastMenuItem();
136 	if (!pItem) return;
137 	if (pItem->IsMenuOpen()) return;
138 
139 	CloseAll();
140 	pItem->OpenMenu();
141 }
142 
Close()143 void Menu::Close()
144 {
145 	SetHidden(true);
146 }
147 
CloseMenus()148 void Menu::CloseMenus()
149 {
150 	BaseClass::CloseMenus();
151 
152 	CloseAll();
153 	Close();
154 }
155 
AddDivider()156 void Menu::AddDivider()
157 {
158 	MenuDivider* divider = new MenuDivider(this);
159 	divider->Dock(Pos::Top);
160 	divider->SetMargin(Margin(IconMarginDisabled() ? 0 : 24, 0, 4, 0));
161 }
162 
Render(Gwen::Skin::Base * skin)163 void MenuDivider::Render(Gwen::Skin::Base* skin)
164 {
165 	skin->DrawMenuDivider(this);
166 }