diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CGUIMenu.cpp | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CGUIMenu.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CGUIMenu.cpp new file mode 100644 index 0000000..6987df8 --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/CGUIMenu.cpp | |||
@@ -0,0 +1,294 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #include "CGUIMenu.h" | ||
6 | #ifdef _IRR_COMPILE_WITH_GUI_ | ||
7 | |||
8 | #include "IGUISkin.h" | ||
9 | #include "IGUIEnvironment.h" | ||
10 | #include "IVideoDriver.h" | ||
11 | #include "IGUIFont.h" | ||
12 | #include "IGUIWindow.h" | ||
13 | |||
14 | #include "os.h" | ||
15 | |||
16 | namespace irr | ||
17 | { | ||
18 | namespace gui | ||
19 | { | ||
20 | |||
21 | //! constructor | ||
22 | CGUIMenu::CGUIMenu(IGUIEnvironment* environment, IGUIElement* parent, | ||
23 | s32 id, core::rect<s32> rectangle) | ||
24 | : CGUIContextMenu(environment, parent, id, rectangle, false, true) | ||
25 | { | ||
26 | #ifdef _DEBUG | ||
27 | setDebugName("CGUIMenu"); | ||
28 | #endif | ||
29 | |||
30 | Type = EGUIET_MENU; | ||
31 | |||
32 | setNotClipped(false); | ||
33 | |||
34 | recalculateSize(); | ||
35 | } | ||
36 | |||
37 | |||
38 | //! draws the element and its children | ||
39 | void CGUIMenu::draw() | ||
40 | { | ||
41 | if (!IsVisible) | ||
42 | return; | ||
43 | |||
44 | IGUISkin* skin = Environment->getSkin(); | ||
45 | IGUIFont* font = skin->getFont(EGDF_MENU); | ||
46 | |||
47 | if (font != LastFont) | ||
48 | { | ||
49 | if (LastFont) | ||
50 | LastFont->drop(); | ||
51 | LastFont = font; | ||
52 | if (LastFont) | ||
53 | LastFont->grab(); | ||
54 | |||
55 | recalculateSize(); | ||
56 | } | ||
57 | |||
58 | core::rect<s32> rect = AbsoluteRect; | ||
59 | |||
60 | // draw frame | ||
61 | |||
62 | skin->draw3DToolBar(this, rect, &AbsoluteClippingRect); | ||
63 | |||
64 | // loop through all menu items | ||
65 | |||
66 | rect = AbsoluteRect; | ||
67 | |||
68 | for (s32 i=0; i<(s32)Items.size(); ++i) | ||
69 | { | ||
70 | if (!Items[i].IsSeparator) | ||
71 | { | ||
72 | rect = getRect(Items[i], AbsoluteRect); | ||
73 | |||
74 | // draw highlighted | ||
75 | if (i == HighLighted && Items[i].Enabled) | ||
76 | { | ||
77 | skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_DARK_SHADOW), | ||
78 | true, true, rect, &AbsoluteClippingRect); | ||
79 | } | ||
80 | // draw text | ||
81 | |||
82 | EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT; | ||
83 | |||
84 | if (i == HighLighted) | ||
85 | c = EGDC_HIGH_LIGHT_TEXT; | ||
86 | |||
87 | if (!Items[i].Enabled) | ||
88 | c = EGDC_GRAY_TEXT; | ||
89 | |||
90 | if (font) | ||
91 | font->draw(Items[i].Text.c_str(), rect, | ||
92 | skin->getColor(c), true, true, &AbsoluteClippingRect); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | IGUIElement::draw(); | ||
97 | } | ||
98 | |||
99 | |||
100 | //! called if an event happened. | ||
101 | bool CGUIMenu::OnEvent(const SEvent& event) | ||
102 | { | ||
103 | if (isEnabled()) | ||
104 | { | ||
105 | |||
106 | switch(event.EventType) | ||
107 | { | ||
108 | case EET_GUI_EVENT: | ||
109 | switch(event.GUIEvent.EventType) | ||
110 | { | ||
111 | case gui::EGET_ELEMENT_FOCUS_LOST: | ||
112 | if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element)) | ||
113 | { | ||
114 | closeAllSubMenus(); | ||
115 | HighLighted = -1; | ||
116 | } | ||
117 | break; | ||
118 | case gui::EGET_ELEMENT_FOCUSED: | ||
119 | if (event.GUIEvent.Caller == this && Parent) | ||
120 | { | ||
121 | Parent->bringToFront(this); | ||
122 | } | ||
123 | break; | ||
124 | default: | ||
125 | break; | ||
126 | } | ||
127 | break; | ||
128 | case EET_MOUSE_INPUT_EVENT: | ||
129 | switch(event.MouseInput.Event) | ||
130 | { | ||
131 | case EMIE_LMOUSE_PRESSED_DOWN: | ||
132 | { | ||
133 | if (!Environment->hasFocus(this)) | ||
134 | { | ||
135 | Environment->setFocus(this); | ||
136 | } | ||
137 | |||
138 | if (Parent) | ||
139 | Parent->bringToFront(this); | ||
140 | |||
141 | core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y); | ||
142 | bool shouldCloseSubMenu = hasOpenSubMenu(); | ||
143 | if (!AbsoluteClippingRect.isPointInside(p)) | ||
144 | { | ||
145 | shouldCloseSubMenu = false; | ||
146 | } | ||
147 | highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true); | ||
148 | if ( shouldCloseSubMenu ) | ||
149 | { | ||
150 | Environment->removeFocus(this); | ||
151 | } | ||
152 | |||
153 | return true; | ||
154 | } | ||
155 | case EMIE_LMOUSE_LEFT_UP: | ||
156 | { | ||
157 | core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y); | ||
158 | if (!AbsoluteClippingRect.isPointInside(p)) | ||
159 | { | ||
160 | s32 t = sendClick(p); | ||
161 | if ((t==0 || t==1) && Environment->hasFocus(this)) | ||
162 | Environment->removeFocus(this); | ||
163 | } | ||
164 | |||
165 | return true; | ||
166 | } | ||
167 | case EMIE_MOUSE_MOVED: | ||
168 | if (Environment->hasFocus(this) && HighLighted >= 0) | ||
169 | { | ||
170 | s32 oldHighLighted = HighLighted; | ||
171 | highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true); | ||
172 | if ( HighLighted < 0 ) | ||
173 | HighLighted = oldHighLighted; // keep last hightlight active when moving outside the area | ||
174 | } | ||
175 | return true; | ||
176 | default: | ||
177 | break; | ||
178 | } | ||
179 | break; | ||
180 | default: | ||
181 | break; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | return IGUIElement::OnEvent(event); | ||
186 | } | ||
187 | |||
188 | void CGUIMenu::recalculateSize() | ||
189 | { | ||
190 | core::rect<s32> clientRect; // client rect of parent | ||
191 | if ( Parent && Parent->hasType(EGUIET_WINDOW) ) | ||
192 | { | ||
193 | clientRect = static_cast<IGUIWindow*>(Parent)->getClientRect(); | ||
194 | } | ||
195 | else if ( Parent ) | ||
196 | { | ||
197 | clientRect = core::rect<s32>(0,0, Parent->getAbsolutePosition().getWidth(), | ||
198 | Parent->getAbsolutePosition().getHeight()); | ||
199 | } | ||
200 | else | ||
201 | { | ||
202 | clientRect = RelativeRect; | ||
203 | } | ||
204 | |||
205 | |||
206 | IGUISkin* skin = Environment->getSkin(); | ||
207 | IGUIFont* font = skin->getFont(EGDF_MENU); | ||
208 | |||
209 | if (!font) | ||
210 | { | ||
211 | if (Parent && skin) | ||
212 | RelativeRect = core::rect<s32>(clientRect.UpperLeftCorner.X, clientRect.UpperLeftCorner.Y, | ||
213 | clientRect.LowerRightCorner.X, clientRect.UpperLeftCorner.Y+skin->getSize(EGDS_MENU_HEIGHT)); | ||
214 | return; | ||
215 | } | ||
216 | |||
217 | core::rect<s32> rect; | ||
218 | rect.UpperLeftCorner = clientRect.UpperLeftCorner; | ||
219 | s32 height = font->getDimension(L"A").Height + 5; | ||
220 | //if (skin && height < skin->getSize ( EGDS_MENU_HEIGHT )) | ||
221 | // height = skin->getSize(EGDS_MENU_HEIGHT); | ||
222 | s32 width = rect.UpperLeftCorner.X; | ||
223 | s32 i; | ||
224 | |||
225 | for (i=0; i<(s32)Items.size(); ++i) | ||
226 | { | ||
227 | if (Items[i].IsSeparator) | ||
228 | { | ||
229 | Items[i].Dim.Width = 0; | ||
230 | Items[i].Dim.Height = height; | ||
231 | } | ||
232 | else | ||
233 | { | ||
234 | Items[i].Dim = font->getDimension(Items[i].Text.c_str()); | ||
235 | Items[i].Dim.Width += 20; | ||
236 | } | ||
237 | |||
238 | Items[i].PosY = width; | ||
239 | width += Items[i].Dim.Width; | ||
240 | } | ||
241 | |||
242 | width = clientRect.getWidth(); | ||
243 | |||
244 | rect.LowerRightCorner.X = rect.UpperLeftCorner.X + width; | ||
245 | rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + height; | ||
246 | |||
247 | setRelativePosition(rect); | ||
248 | |||
249 | // recalculate submenus | ||
250 | for (i=0; i<(s32)Items.size(); ++i) | ||
251 | if (Items[i].SubMenu) | ||
252 | { | ||
253 | // move submenu | ||
254 | s32 w = Items[i].SubMenu->getAbsolutePosition().getWidth(); | ||
255 | s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight(); | ||
256 | |||
257 | Items[i].SubMenu->setRelativePosition( | ||
258 | core::rect<s32>(Items[i].PosY, height , | ||
259 | Items[i].PosY+w-5, height+h)); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | |||
264 | //! returns the item highlight-area | ||
265 | core::rect<s32> CGUIMenu::getHRect(const SItem& i, const core::rect<s32>& absolute) const | ||
266 | { | ||
267 | core::rect<s32> r = absolute; | ||
268 | r.UpperLeftCorner.X += i.PosY; | ||
269 | r.LowerRightCorner.X = r.UpperLeftCorner.X + i.Dim.Width; | ||
270 | return r; | ||
271 | } | ||
272 | |||
273 | |||
274 | //! Gets drawing rect of Item | ||
275 | core::rect<s32> CGUIMenu::getRect(const SItem& i, const core::rect<s32>& absolute) const | ||
276 | { | ||
277 | return getHRect(i, absolute); | ||
278 | } | ||
279 | |||
280 | |||
281 | void CGUIMenu::updateAbsolutePosition() | ||
282 | { | ||
283 | if (Parent) | ||
284 | DesiredRect.LowerRightCorner.X = Parent->getAbsolutePosition().getWidth(); | ||
285 | |||
286 | IGUIElement::updateAbsolutePosition(); | ||
287 | } | ||
288 | |||
289 | |||
290 | } // end namespace | ||
291 | } // end namespace | ||
292 | |||
293 | #endif // _IRR_COMPILE_WITH_GUI_ | ||
294 | |||