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 }