1 /***********************************************************************
2 created: 5/4/2005
3 author: Tomas Lindquist Olsen (based on code by Paul D Turner)
4
5 purpose: Implementation of MenuBase widget base class
6 *************************************************************************/
7 /***************************************************************************
8 * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining
11 * a copy of this software and associated documentation files (the
12 * "Software"), to deal in the Software without restriction, including
13 * without limitation the rights to use, copy, modify, merge, publish,
14 * distribute, sublicense, and/or sell copies of the Software, and to
15 * permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 ***************************************************************************/
29 #include "CEGUI/widgets/MenuBase.h"
30 #include "CEGUI/widgets/PopupMenu.h"
31 #include "CEGUI/widgets/MenuItem.h"
32
33 // Start of CEGUI namespace section
34 namespace CEGUI
35 {
36
37 /*************************************************************************
38 Constants
39 *************************************************************************/
40 // event strings
41 const String MenuBase::EventNamespace("MenuBase");
42 const String MenuBase::EventPopupOpened("PopupOpened");
43 const String MenuBase::EventPopupClosed("PopupClosed");
44
45 /*************************************************************************
46 Constructor for MenuBase base class.
47 *************************************************************************/
MenuBase(const String & type,const String & name)48 MenuBase::MenuBase(const String& type, const String& name)
49 : ItemListBase(type, name),
50 d_itemSpacing(0.0f),
51 d_popupItem(0),
52 d_allowMultiplePopups(false),
53 d_autoCloseNestedPopups(false)
54 {
55 // add properties for MenuBase class
56 addMenuBaseProperties();
57 }
58
59 /*************************************************************************
60 Destructor for MenuBase base class.
61 *************************************************************************/
~MenuBase(void)62 MenuBase::~MenuBase(void)
63 {
64 }
65
66 /*************************************************************************
67 Change the currently open MenuItem PopupMenu
68 *************************************************************************/
changePopupMenuItem(MenuItem * item)69 void MenuBase::changePopupMenuItem(MenuItem* item)
70 {
71 if (!d_allowMultiplePopups && d_popupItem == item)
72 return;
73
74 if (!d_allowMultiplePopups && d_popupItem != 0)
75 {
76 WindowEventArgs we(d_popupItem->getPopupMenu());
77 d_popupItem->closePopupMenu(false);
78 d_popupItem = 0;
79 onPopupClosed(we);
80 }
81
82 if (item)
83 {
84 d_popupItem = item;
85 d_popupItem->openPopupMenu(false);
86 WindowEventArgs we(d_popupItem->getPopupMenu());
87 onPopupOpened(we);
88 }
89
90 }
91
92
93 /*************************************************************************
94 handler invoked internally when the a MenuItem attached to this
95 MenuBase opens its popup.
96 *************************************************************************/
onPopupOpened(WindowEventArgs & e)97 void MenuBase::onPopupOpened(WindowEventArgs& e)
98 {
99 fireEvent(EventPopupOpened, e, EventNamespace);
100 }
101
102
103 /*************************************************************************
104 handler invoked internally when the a MenuItem attached to this
105 MenuBase closes its popup.
106 *************************************************************************/
onPopupClosed(WindowEventArgs & e)107 void MenuBase::onPopupClosed(WindowEventArgs& e)
108 {
109 fireEvent(EventPopupClosed, e, EventNamespace);
110 }
111
112
113 /************************************************************************
114 Add properties for this widget
115 *************************************************************************/
addMenuBaseProperties(void)116 void MenuBase::addMenuBaseProperties(void)
117 {
118 const String propertyOrigin = "CEGUI/MenuBase";
119
120 CEGUI_DEFINE_PROPERTY(MenuBase, float,
121 "ItemSpacing", "Property to get/set the item spacing of the menu. Value is a float.",
122 &MenuBase::setItemSpacing, &MenuBase::getItemSpacing, 10.0f
123 );
124
125 CEGUI_DEFINE_PROPERTY(MenuBase, bool,
126 "AllowMultiplePopups", "Property to get/set the state of the allow multiple popups setting for the menu. Value is either \"true\" or \"false\".",
127 &MenuBase::setAllowMultiplePopups, &MenuBase::isMultiplePopupsAllowed, false /* TODO: Inconsistency and awful English */
128 );
129
130 CEGUI_DEFINE_PROPERTY(MenuBase, bool,
131 "AutoCloseNestedPopups", "Property to set if the menu should close all its open child popups, when it gets hidden. Value is either \"true\" or \"false\".",
132 &MenuBase::setAutoCloseNestedPopups, &MenuBase::getAutoCloseNestedPopups, false
133 );
134 }
135
136
137 /************************************************************************
138 Set if multiple child popup menus are allowed simultaneously
139 *************************************************************************/
setAllowMultiplePopups(bool setting)140 void MenuBase::setAllowMultiplePopups(bool setting)
141 {
142 if (d_allowMultiplePopups != setting)
143 {
144 // TODO :
145 // close all popups except perhaps the last one opened!
146 d_allowMultiplePopups = setting;
147 }
148 }
149
setPopupMenuItemClosing()150 void MenuBase::setPopupMenuItemClosing()
151 {
152 if (d_popupItem)
153 {
154 d_popupItem->startPopupClosing();
155 }
156 }
157
158 //----------------------------------------------------------------------------//
onChildRemoved(ElementEventArgs & e)159 void MenuBase::onChildRemoved(ElementEventArgs& e)
160 {
161 // if the removed window was our tracked popup item, zero ptr to it.
162 if (static_cast<Window*>(e.element) == d_popupItem)
163 d_popupItem = 0;
164
165 // base class version
166 ItemListBase::onChildRemoved(e);
167 }
168
onHidden(WindowEventArgs &)169 void MenuBase::onHidden(WindowEventArgs&)
170 {
171 if (!getAutoCloseNestedPopups())
172 return;
173
174 changePopupMenuItem(0);
175
176 if (d_allowMultiplePopups)
177 {
178 for (size_t i = 0; i < d_listItems.size(); ++i)
179 {
180 if (!d_listItems[i])
181 continue;
182
183 MenuItem* menuItem = dynamic_cast<MenuItem*>(d_listItems[i]);
184 if (!menuItem)
185 continue;
186
187 if (!menuItem->getPopupMenu())
188 continue;
189
190 WindowEventArgs we(menuItem->getPopupMenu());
191 menuItem->closePopupMenu(false);
192 onPopupClosed(we);
193 }
194 }
195 }
196 //----------------------------------------------------------------------------//
197
198 } // End of CEGUI namespace section
199