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