diff options
author | David Walter Seikel | 2016-03-28 22:28:34 +1000 |
---|---|---|
committer | David Walter Seikel | 2016-03-28 22:28:34 +1000 |
commit | 7028cbe09c688437910a25623098762bf0fa592d (patch) | |
tree | 10b5af58277d9880380c2251f109325542c4e6eb /src/others/irrlicht-1.8.1/source/Irrlicht/CGUIContextMenu.cpp | |
parent | Move lemon to the src/others directory. (diff) | |
download | SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.zip SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.gz SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.bz2 SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.xz |
Move Irrlicht to src/others.
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CGUIContextMenu.cpp')
-rw-r--r-- | src/others/irrlicht-1.8.1/source/Irrlicht/CGUIContextMenu.cpp | 869 |
1 files changed, 869 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CGUIContextMenu.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CGUIContextMenu.cpp new file mode 100644 index 0000000..67631e7 --- /dev/null +++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CGUIContextMenu.cpp | |||
@@ -0,0 +1,869 @@ | |||
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 "CGUIContextMenu.h" | ||
6 | |||
7 | #ifdef _IRR_COMPILE_WITH_GUI_ | ||
8 | |||
9 | #include "IGUISkin.h" | ||
10 | #include "IGUIEnvironment.h" | ||
11 | #include "IVideoDriver.h" | ||
12 | #include "IGUIFont.h" | ||
13 | #include "IGUISpriteBank.h" | ||
14 | #include "os.h" | ||
15 | |||
16 | namespace irr | ||
17 | { | ||
18 | namespace gui | ||
19 | { | ||
20 | |||
21 | |||
22 | //! constructor | ||
23 | CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment, | ||
24 | IGUIElement* parent, s32 id, | ||
25 | core::rect<s32> rectangle, bool getFocus, bool allowFocus) | ||
26 | : IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0), | ||
27 | CloseHandling(ECMC_REMOVE), HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus) | ||
28 | { | ||
29 | #ifdef _DEBUG | ||
30 | setDebugName("CGUIContextMenu"); | ||
31 | #endif | ||
32 | |||
33 | Pos = rectangle.UpperLeftCorner; | ||
34 | recalculateSize(); | ||
35 | |||
36 | if (getFocus) | ||
37 | Environment->setFocus(this); | ||
38 | |||
39 | setNotClipped(true); | ||
40 | } | ||
41 | |||
42 | |||
43 | //! destructor | ||
44 | CGUIContextMenu::~CGUIContextMenu() | ||
45 | { | ||
46 | for (u32 i=0; i<Items.size(); ++i) | ||
47 | if (Items[i].SubMenu) | ||
48 | Items[i].SubMenu->drop(); | ||
49 | |||
50 | if (LastFont) | ||
51 | LastFont->drop(); | ||
52 | } | ||
53 | |||
54 | //! set behavior when menus are closed | ||
55 | void CGUIContextMenu::setCloseHandling(ECONTEXT_MENU_CLOSE onClose) | ||
56 | { | ||
57 | CloseHandling = onClose; | ||
58 | } | ||
59 | |||
60 | //! get current behavior when the menue will be closed | ||
61 | ECONTEXT_MENU_CLOSE CGUIContextMenu::getCloseHandling() const | ||
62 | { | ||
63 | return CloseHandling; | ||
64 | } | ||
65 | |||
66 | //! Returns amount of menu items | ||
67 | u32 CGUIContextMenu::getItemCount() const | ||
68 | { | ||
69 | return Items.size(); | ||
70 | } | ||
71 | |||
72 | |||
73 | //! Adds a menu item. | ||
74 | u32 CGUIContextMenu::addItem(const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking) | ||
75 | { | ||
76 | return insertItem(Items.size(), text, commandId, enabled, hasSubMenu, checked, autoChecking); | ||
77 | } | ||
78 | |||
79 | //! Insert a menu item at specified position. | ||
80 | u32 CGUIContextMenu::insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled, | ||
81 | bool hasSubMenu, bool checked, bool autoChecking) | ||
82 | { | ||
83 | SItem s; | ||
84 | s.Enabled = enabled; | ||
85 | s.Checked = checked; | ||
86 | s.AutoChecking = autoChecking; | ||
87 | s.Text = text; | ||
88 | s.IsSeparator = (text == 0); | ||
89 | s.SubMenu = 0; | ||
90 | s.CommandId = commandId; | ||
91 | |||
92 | if (hasSubMenu) | ||
93 | { | ||
94 | s.SubMenu = new CGUIContextMenu(Environment, this, commandId, | ||
95 | core::rect<s32>(0,0,100,100), false, false); | ||
96 | s.SubMenu->setVisible(false); | ||
97 | } | ||
98 | |||
99 | u32 result = idx; | ||
100 | if ( idx < Items.size() ) | ||
101 | { | ||
102 | Items.insert(s, idx); | ||
103 | } | ||
104 | else | ||
105 | { | ||
106 | Items.push_back(s); | ||
107 | result = Items.size() - 1; | ||
108 | } | ||
109 | |||
110 | recalculateSize(); | ||
111 | return result; | ||
112 | } | ||
113 | |||
114 | s32 CGUIContextMenu::findItemWithCommandId(s32 commandId, u32 idxStartSearch) const | ||
115 | { | ||
116 | for ( u32 i=idxStartSearch; i<Items.size(); ++i ) | ||
117 | { | ||
118 | if ( Items[i].CommandId == commandId ) | ||
119 | { | ||
120 | return (s32)i; | ||
121 | } | ||
122 | } | ||
123 | return -1; | ||
124 | } | ||
125 | |||
126 | //! Adds a sub menu from an element that already exists. | ||
127 | void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu) | ||
128 | { | ||
129 | if (index >= Items.size()) | ||
130 | return; | ||
131 | |||
132 | if (menu) | ||
133 | menu->grab(); | ||
134 | if (Items[index].SubMenu) | ||
135 | Items[index].SubMenu->drop(); | ||
136 | |||
137 | Items[index].SubMenu = menu; | ||
138 | menu->setVisible(false); | ||
139 | |||
140 | if (Items[index].SubMenu) | ||
141 | { | ||
142 | menu->AllowFocus = false; | ||
143 | if ( Environment->getFocus() == menu ) | ||
144 | { | ||
145 | Environment->setFocus( this ); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | recalculateSize(); | ||
150 | } | ||
151 | |||
152 | |||
153 | //! Adds a separator item to the menu | ||
154 | void CGUIContextMenu::addSeparator() | ||
155 | { | ||
156 | addItem(0, -1, true, false, false, false); | ||
157 | } | ||
158 | |||
159 | |||
160 | //! Returns text of the menu item. | ||
161 | const wchar_t* CGUIContextMenu::getItemText(u32 idx) const | ||
162 | { | ||
163 | if (idx >= Items.size()) | ||
164 | return 0; | ||
165 | |||
166 | return Items[idx].Text.c_str(); | ||
167 | } | ||
168 | |||
169 | |||
170 | //! Sets text of the menu item. | ||
171 | void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text) | ||
172 | { | ||
173 | if (idx >= Items.size()) | ||
174 | return; | ||
175 | |||
176 | Items[idx].Text = text; | ||
177 | recalculateSize(); | ||
178 | } | ||
179 | |||
180 | //! should the element change the checked status on clicking | ||
181 | void CGUIContextMenu::setItemAutoChecking(u32 idx, bool autoChecking) | ||
182 | { | ||
183 | if ( idx >= Items.size()) | ||
184 | return; | ||
185 | |||
186 | Items[idx].AutoChecking = autoChecking; | ||
187 | } | ||
188 | |||
189 | //! does the element change the checked status on clicking | ||
190 | bool CGUIContextMenu::getItemAutoChecking(u32 idx) const | ||
191 | { | ||
192 | if (idx >= Items.size()) | ||
193 | return false; | ||
194 | |||
195 | return Items[idx].AutoChecking; | ||
196 | } | ||
197 | |||
198 | |||
199 | //! Returns if a menu item is enabled | ||
200 | bool CGUIContextMenu::isItemEnabled(u32 idx) const | ||
201 | { | ||
202 | if (idx >= Items.size()) | ||
203 | { | ||
204 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
205 | return false; | ||
206 | } | ||
207 | |||
208 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
209 | return Items[idx].Enabled; | ||
210 | } | ||
211 | |||
212 | |||
213 | //! Returns if a menu item is checked | ||
214 | bool CGUIContextMenu::isItemChecked(u32 idx) const | ||
215 | { | ||
216 | if (idx >= Items.size()) | ||
217 | { | ||
218 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
219 | return false; | ||
220 | } | ||
221 | |||
222 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
223 | return Items[idx].Checked; | ||
224 | } | ||
225 | |||
226 | |||
227 | //! Sets if the menu item should be enabled. | ||
228 | void CGUIContextMenu::setItemEnabled(u32 idx, bool enabled) | ||
229 | { | ||
230 | if (idx >= Items.size()) | ||
231 | return; | ||
232 | |||
233 | Items[idx].Enabled = enabled; | ||
234 | } | ||
235 | |||
236 | |||
237 | //! Sets if the menu item should be checked. | ||
238 | void CGUIContextMenu::setItemChecked(u32 idx, bool checked ) | ||
239 | { | ||
240 | if (idx >= Items.size()) | ||
241 | return; | ||
242 | |||
243 | Items[idx].Checked = checked; | ||
244 | } | ||
245 | |||
246 | |||
247 | //! Removes a menu item | ||
248 | void CGUIContextMenu::removeItem(u32 idx) | ||
249 | { | ||
250 | if (idx >= Items.size()) | ||
251 | return; | ||
252 | |||
253 | if (Items[idx].SubMenu) | ||
254 | { | ||
255 | Items[idx].SubMenu->drop(); | ||
256 | Items[idx].SubMenu = 0; | ||
257 | } | ||
258 | |||
259 | Items.erase(idx); | ||
260 | recalculateSize(); | ||
261 | } | ||
262 | |||
263 | |||
264 | //! Removes all menu items | ||
265 | void CGUIContextMenu::removeAllItems() | ||
266 | { | ||
267 | for (u32 i=0; i<Items.size(); ++i) | ||
268 | if (Items[i].SubMenu) | ||
269 | Items[i].SubMenu->drop(); | ||
270 | |||
271 | Items.clear(); | ||
272 | recalculateSize(); | ||
273 | } | ||
274 | |||
275 | |||
276 | //! called if an event happened. | ||
277 | bool CGUIContextMenu::OnEvent(const SEvent& event) | ||
278 | { | ||
279 | if (isEnabled()) | ||
280 | { | ||
281 | |||
282 | switch(event.EventType) | ||
283 | { | ||
284 | case EET_GUI_EVENT: | ||
285 | switch(event.GUIEvent.EventType) | ||
286 | { | ||
287 | case EGET_ELEMENT_FOCUS_LOST: | ||
288 | if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus) | ||
289 | { | ||
290 | // set event parent of submenus | ||
291 | IGUIElement * p = EventParent ? EventParent : Parent; | ||
292 | setEventParent(p); | ||
293 | |||
294 | SEvent event; | ||
295 | event.EventType = EET_GUI_EVENT; | ||
296 | event.GUIEvent.Caller = this; | ||
297 | event.GUIEvent.Element = 0; | ||
298 | event.GUIEvent.EventType = EGET_ELEMENT_CLOSED; | ||
299 | if ( !p->OnEvent(event) ) | ||
300 | { | ||
301 | if ( CloseHandling & ECMC_HIDE ) | ||
302 | { | ||
303 | setVisible(false); | ||
304 | } | ||
305 | if ( CloseHandling & ECMC_REMOVE ) | ||
306 | { | ||
307 | remove(); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | return false; | ||
312 | } | ||
313 | break; | ||
314 | case EGET_ELEMENT_FOCUSED: | ||
315 | if (event.GUIEvent.Caller == this && !AllowFocus) | ||
316 | { | ||
317 | return true; | ||
318 | } | ||
319 | break; | ||
320 | default: | ||
321 | break; | ||
322 | } | ||
323 | break; | ||
324 | case EET_MOUSE_INPUT_EVENT: | ||
325 | switch(event.MouseInput.Event) | ||
326 | { | ||
327 | case EMIE_LMOUSE_LEFT_UP: | ||
328 | { | ||
329 | // menu might be removed if it loses focus in sendClick, so grab a reference | ||
330 | grab(); | ||
331 | const u32 t = sendClick(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)); | ||
332 | if ((t==0 || t==1) && Environment->hasFocus(this)) | ||
333 | Environment->removeFocus(this); | ||
334 | drop(); | ||
335 | } | ||
336 | return true; | ||
337 | case EMIE_LMOUSE_PRESSED_DOWN: | ||
338 | return true; | ||
339 | case EMIE_MOUSE_MOVED: | ||
340 | if (Environment->hasFocus(this)) | ||
341 | highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true); | ||
342 | return true; | ||
343 | default: | ||
344 | break; | ||
345 | } | ||
346 | break; | ||
347 | default: | ||
348 | break; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | return IGUIElement::OnEvent(event); | ||
353 | } | ||
354 | |||
355 | |||
356 | //! Sets the visible state of this element. | ||
357 | void CGUIContextMenu::setVisible(bool visible) | ||
358 | { | ||
359 | HighLighted = -1; | ||
360 | ChangeTime = os::Timer::getTime(); | ||
361 | for (u32 j=0; j<Items.size(); ++j) | ||
362 | if (Items[j].SubMenu) | ||
363 | Items[j].SubMenu->setVisible(false); | ||
364 | |||
365 | IGUIElement::setVisible(visible); | ||
366 | } | ||
367 | |||
368 | |||
369 | //! sends a click Returns: | ||
370 | //! 0 if click went outside of the element, | ||
371 | //! 1 if a valid button was clicked, | ||
372 | //! 2 if a nonclickable element was clicked | ||
373 | u32 CGUIContextMenu::sendClick(const core::position2d<s32>& p) | ||
374 | { | ||
375 | u32 t = 0; | ||
376 | |||
377 | // get number of open submenu | ||
378 | s32 openmenu = -1; | ||
379 | s32 j; | ||
380 | for (j=0; j<(s32)Items.size(); ++j) | ||
381 | if (Items[j].SubMenu && Items[j].SubMenu->isVisible()) | ||
382 | { | ||
383 | openmenu = j; | ||
384 | break; | ||
385 | } | ||
386 | |||
387 | // delegate click operation to submenu | ||
388 | if (openmenu != -1) | ||
389 | { | ||
390 | t = Items[j].SubMenu->sendClick(p); | ||
391 | if (t != 0) | ||
392 | return t; // clicked something | ||
393 | } | ||
394 | |||
395 | // check click on myself | ||
396 | if (isPointInside(p) && | ||
397 | (u32)HighLighted < Items.size()) | ||
398 | { | ||
399 | if (!Items[HighLighted].Enabled || | ||
400 | Items[HighLighted].IsSeparator || | ||
401 | Items[HighLighted].SubMenu) | ||
402 | return 2; | ||
403 | |||
404 | if ( Items[HighLighted].AutoChecking ) | ||
405 | { | ||
406 | Items[HighLighted].Checked = Items[HighLighted].Checked ? false : true; | ||
407 | } | ||
408 | |||
409 | SEvent event; | ||
410 | event.EventType = EET_GUI_EVENT; | ||
411 | event.GUIEvent.Caller = this; | ||
412 | event.GUIEvent.Element = 0; | ||
413 | event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED; | ||
414 | if (EventParent) | ||
415 | EventParent->OnEvent(event); | ||
416 | else if (Parent) | ||
417 | Parent->OnEvent(event); | ||
418 | |||
419 | return 1; | ||
420 | } | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | |||
426 | //! returns true, if an element was highligted | ||
427 | bool CGUIContextMenu::highlight(const core::position2d<s32>& p, bool canOpenSubMenu) | ||
428 | { | ||
429 | if (!isEnabled()) | ||
430 | { | ||
431 | return false; | ||
432 | } | ||
433 | |||
434 | // get number of open submenu | ||
435 | s32 openmenu = -1; | ||
436 | s32 i; | ||
437 | for (i=0; i<(s32)Items.size(); ++i) | ||
438 | if (Items[i].Enabled && Items[i].SubMenu && Items[i].SubMenu->isVisible()) | ||
439 | { | ||
440 | openmenu = i; | ||
441 | break; | ||
442 | } | ||
443 | |||
444 | // delegate highlight operation to submenu | ||
445 | if (openmenu != -1) | ||
446 | { | ||
447 | if (Items[openmenu].Enabled && Items[openmenu].SubMenu->highlight(p, canOpenSubMenu)) | ||
448 | { | ||
449 | HighLighted = openmenu; | ||
450 | ChangeTime = os::Timer::getTime(); | ||
451 | return true; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | // highlight myself | ||
456 | for (i=0; i<(s32)Items.size(); ++i) | ||
457 | { | ||
458 | if (Items[i].Enabled && getHRect(Items[i], AbsoluteRect).isPointInside(p)) | ||
459 | { | ||
460 | HighLighted = i; | ||
461 | ChangeTime = os::Timer::getTime(); | ||
462 | |||
463 | // make submenus visible/invisible | ||
464 | for (s32 j=0; j<(s32)Items.size(); ++j) | ||
465 | if (Items[j].SubMenu) | ||
466 | { | ||
467 | if ( j == i && canOpenSubMenu && Items[j].Enabled ) | ||
468 | Items[j].SubMenu->setVisible(true); | ||
469 | else if ( j != i ) | ||
470 | Items[j].SubMenu->setVisible(false); | ||
471 | } | ||
472 | return true; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | HighLighted = openmenu; | ||
477 | return false; | ||
478 | } | ||
479 | |||
480 | |||
481 | //! returns the item highlight-area | ||
482 | core::rect<s32> CGUIContextMenu::getHRect(const SItem& i, const core::rect<s32>& absolute) const | ||
483 | { | ||
484 | core::rect<s32> r = absolute; | ||
485 | r.UpperLeftCorner.Y += i.PosY; | ||
486 | r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height; | ||
487 | return r; | ||
488 | } | ||
489 | |||
490 | |||
491 | //! Gets drawing rect of Item | ||
492 | core::rect<s32> CGUIContextMenu::getRect(const SItem& i, const core::rect<s32>& absolute) const | ||
493 | { | ||
494 | core::rect<s32> r = absolute; | ||
495 | r.UpperLeftCorner.Y += i.PosY; | ||
496 | r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height; | ||
497 | r.UpperLeftCorner.X += 20; | ||
498 | return r; | ||
499 | } | ||
500 | |||
501 | |||
502 | //! draws the element and its children | ||
503 | void CGUIContextMenu::draw() | ||
504 | { | ||
505 | if (!IsVisible) | ||
506 | return; | ||
507 | |||
508 | IGUISkin* skin = Environment->getSkin(); | ||
509 | |||
510 | if (!skin) | ||
511 | return; | ||
512 | |||
513 | IGUIFont* font = skin->getFont(EGDF_MENU); | ||
514 | if (font != LastFont) | ||
515 | { | ||
516 | if (LastFont) | ||
517 | LastFont->drop(); | ||
518 | LastFont = font; | ||
519 | if (LastFont) | ||
520 | LastFont->grab(); | ||
521 | |||
522 | recalculateSize(); | ||
523 | } | ||
524 | |||
525 | IGUISpriteBank* sprites = skin->getSpriteBank(); | ||
526 | |||
527 | core::rect<s32> rect = AbsoluteRect; | ||
528 | core::rect<s32>* clip = 0; | ||
529 | |||
530 | // draw frame | ||
531 | skin->draw3DMenuPane(this, AbsoluteRect, clip); | ||
532 | |||
533 | // loop through all menu items | ||
534 | |||
535 | rect = AbsoluteRect; | ||
536 | s32 y = AbsoluteRect.UpperLeftCorner.Y; | ||
537 | |||
538 | for (s32 i=0; i<(s32)Items.size(); ++i) | ||
539 | { | ||
540 | if (Items[i].IsSeparator) | ||
541 | { | ||
542 | // draw separator | ||
543 | rect = AbsoluteRect; | ||
544 | rect.UpperLeftCorner.Y += Items[i].PosY + 3; | ||
545 | rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; | ||
546 | rect.UpperLeftCorner.X += 5; | ||
547 | rect.LowerRightCorner.X -= 5; | ||
548 | skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), rect, clip); | ||
549 | |||
550 | rect.LowerRightCorner.Y += 1; | ||
551 | rect.UpperLeftCorner.Y += 1; | ||
552 | skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), rect, clip); | ||
553 | |||
554 | y += 10; | ||
555 | } | ||
556 | else | ||
557 | { | ||
558 | rect = getRect(Items[i], AbsoluteRect); | ||
559 | |||
560 | // draw highlighted | ||
561 | |||
562 | if (i == HighLighted && Items[i].Enabled) | ||
563 | { | ||
564 | core::rect<s32> r = AbsoluteRect; | ||
565 | r.LowerRightCorner.Y = rect.LowerRightCorner.Y; | ||
566 | r.UpperLeftCorner.Y = rect.UpperLeftCorner.Y; | ||
567 | r.LowerRightCorner.X -= 5; | ||
568 | r.UpperLeftCorner.X += 5; | ||
569 | skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), r, clip); | ||
570 | } | ||
571 | |||
572 | // draw text | ||
573 | |||
574 | EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT; | ||
575 | |||
576 | if (i == HighLighted) | ||
577 | c = EGDC_HIGH_LIGHT_TEXT; | ||
578 | |||
579 | if (!Items[i].Enabled) | ||
580 | c = EGDC_GRAY_TEXT; | ||
581 | |||
582 | if (font) | ||
583 | font->draw(Items[i].Text.c_str(), rect, | ||
584 | skin->getColor(c), false, true, clip); | ||
585 | |||
586 | // draw submenu symbol | ||
587 | if (Items[i].SubMenu && sprites) | ||
588 | { | ||
589 | core::rect<s32> r = rect; | ||
590 | r.UpperLeftCorner.X = r.LowerRightCorner.X - 15; | ||
591 | |||
592 | sprites->draw2DSprite(skin->getIcon(EGDI_CURSOR_RIGHT), | ||
593 | r.getCenter(), clip, skin->getColor(c), | ||
594 | (i == HighLighted) ? ChangeTime : 0, | ||
595 | (i == HighLighted) ? os::Timer::getTime() : 0, | ||
596 | (i == HighLighted), true); | ||
597 | } | ||
598 | |||
599 | // draw checked symbol | ||
600 | if (Items[i].Checked && sprites) | ||
601 | { | ||
602 | core::rect<s32> r = rect; | ||
603 | r.LowerRightCorner.X = r.UpperLeftCorner.X - 15; | ||
604 | r.UpperLeftCorner.X = r.LowerRightCorner.X + 15; | ||
605 | sprites->draw2DSprite(skin->getIcon(EGDI_CHECK_BOX_CHECKED), | ||
606 | r.getCenter(), clip, skin->getColor(c), | ||
607 | (i == HighLighted) ? ChangeTime : 0, | ||
608 | (i == HighLighted) ? os::Timer::getTime() : 0, | ||
609 | (i == HighLighted), true); | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | IGUIElement::draw(); | ||
615 | } | ||
616 | |||
617 | |||
618 | void CGUIContextMenu::recalculateSize() | ||
619 | { | ||
620 | IGUIFont* font = Environment->getSkin()->getFont(EGDF_MENU); | ||
621 | |||
622 | if (!font) | ||
623 | return; | ||
624 | |||
625 | core::rect<s32> rect; | ||
626 | rect.UpperLeftCorner = RelativeRect.UpperLeftCorner; | ||
627 | u32 width = 100; | ||
628 | u32 height = 3; | ||
629 | |||
630 | u32 i; | ||
631 | for (i=0; i<Items.size(); ++i) | ||
632 | { | ||
633 | if (Items[i].IsSeparator) | ||
634 | { | ||
635 | Items[i].Dim.Width = 100; | ||
636 | Items[i].Dim.Height = 10; | ||
637 | } | ||
638 | else | ||
639 | { | ||
640 | Items[i].Dim = font->getDimension(Items[i].Text.c_str()); | ||
641 | Items[i].Dim.Width += 40; | ||
642 | |||
643 | if (Items[i].Dim.Width > width) | ||
644 | width = Items[i].Dim.Width; | ||
645 | } | ||
646 | |||
647 | Items[i].PosY = height; | ||
648 | height += Items[i].Dim.Height; | ||
649 | } | ||
650 | |||
651 | height += 5; | ||
652 | |||
653 | if (height < 10) | ||
654 | height = 10; | ||
655 | |||
656 | rect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + width; | ||
657 | rect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + height; | ||
658 | |||
659 | setRelativePosition(rect); | ||
660 | |||
661 | // recalculate submenus | ||
662 | for (i=0; i<Items.size(); ++i) | ||
663 | { | ||
664 | if (Items[i].SubMenu) | ||
665 | { | ||
666 | // move submenu | ||
667 | const s32 w = Items[i].SubMenu->getAbsolutePosition().getWidth(); | ||
668 | const s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight(); | ||
669 | |||
670 | core::rect<s32> subRect(width-5, Items[i].PosY, width+w-5, Items[i].PosY+h); | ||
671 | |||
672 | // if it would be drawn beyond the right border, then add it to the left side | ||
673 | gui::IGUIElement * root = Environment->getRootGUIElement(); | ||
674 | if ( root ) | ||
675 | { | ||
676 | core::rect<s32> rectRoot( root->getAbsolutePosition() ); | ||
677 | if ( getAbsolutePosition().UpperLeftCorner.X+subRect.LowerRightCorner.X > rectRoot.LowerRightCorner.X ) | ||
678 | { | ||
679 | subRect.UpperLeftCorner.X = -w; | ||
680 | subRect.LowerRightCorner.X = 0; | ||
681 | } | ||
682 | } | ||
683 | |||
684 | Items[i].SubMenu->setRelativePosition(subRect); | ||
685 | } | ||
686 | } | ||
687 | } | ||
688 | |||
689 | |||
690 | //! Returns the selected item in the menu | ||
691 | s32 CGUIContextMenu::getSelectedItem() const | ||
692 | { | ||
693 | return HighLighted; | ||
694 | } | ||
695 | |||
696 | |||
697 | //! \return Returns a pointer to the submenu of an item. | ||
698 | IGUIContextMenu* CGUIContextMenu::getSubMenu(u32 idx) const | ||
699 | { | ||
700 | if (idx >= Items.size()) | ||
701 | return 0; | ||
702 | |||
703 | return Items[idx].SubMenu; | ||
704 | } | ||
705 | |||
706 | |||
707 | //! Returns command id of a menu item | ||
708 | s32 CGUIContextMenu::getItemCommandId(u32 idx) const | ||
709 | { | ||
710 | if (idx >= Items.size()) | ||
711 | return -1; | ||
712 | |||
713 | return Items[idx].CommandId; | ||
714 | } | ||
715 | |||
716 | |||
717 | //! Sets the command id of a menu item | ||
718 | void CGUIContextMenu::setItemCommandId(u32 idx, s32 id) | ||
719 | { | ||
720 | if (idx >= Items.size()) | ||
721 | return; | ||
722 | |||
723 | Items[idx].CommandId = id; | ||
724 | } | ||
725 | |||
726 | |||
727 | //! Writes attributes of the element. | ||
728 | void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const | ||
729 | { | ||
730 | IGUIElement::serializeAttributes(out,options); | ||
731 | out->addPosition2d("Position", Pos); | ||
732 | |||
733 | if (Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) | ||
734 | { | ||
735 | const IGUIContextMenu* const ptr = (const IGUIContextMenu*)Parent; | ||
736 | // find the position of this item in its parent's list | ||
737 | u32 i; | ||
738 | // VC6 needs the cast for this | ||
739 | for (i=0; (i<ptr->getItemCount()) && (ptr->getSubMenu(i) != (const IGUIContextMenu*)this); ++i) | ||
740 | ; // do nothing | ||
741 | |||
742 | out->addInt("ParentItem", i); | ||
743 | } | ||
744 | |||
745 | out->addInt("CloseHandling", (s32)CloseHandling); | ||
746 | |||
747 | // write out the item list | ||
748 | out->addInt("ItemCount", Items.size()); | ||
749 | |||
750 | core::stringc tmp; | ||
751 | |||
752 | for (u32 i=0; i < Items.size(); ++i) | ||
753 | { | ||
754 | tmp = "IsSeparator"; tmp += i; | ||
755 | out->addBool(tmp.c_str(), Items[i].IsSeparator); | ||
756 | |||
757 | if (!Items[i].IsSeparator) | ||
758 | { | ||
759 | tmp = "Text"; tmp += i; | ||
760 | out->addString(tmp.c_str(), Items[i].Text.c_str()); | ||
761 | tmp = "CommandID"; tmp += i; | ||
762 | out->addInt(tmp.c_str(), Items[i].CommandId); | ||
763 | tmp = "Enabled"; tmp += i; | ||
764 | out->addBool(tmp.c_str(), Items[i].Enabled); | ||
765 | tmp = "Checked"; tmp += i; | ||
766 | out->addBool(tmp.c_str(), Items[i].Checked); | ||
767 | tmp = "AutoChecking"; tmp += i; | ||
768 | out->addBool(tmp.c_str(), Items[i].AutoChecking); | ||
769 | } | ||
770 | } | ||
771 | } | ||
772 | |||
773 | |||
774 | //! Reads attributes of the element | ||
775 | void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) | ||
776 | { | ||
777 | IGUIElement::deserializeAttributes(in,options); | ||
778 | |||
779 | Pos = in->getAttributeAsPosition2d("Position"); | ||
780 | |||
781 | // link to this item's parent | ||
782 | if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) ) | ||
783 | ((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this); | ||
784 | |||
785 | CloseHandling = (ECONTEXT_MENU_CLOSE)in->getAttributeAsInt("CloseHandling"); | ||
786 | |||
787 | removeAllItems(); | ||
788 | |||
789 | // read the item list | ||
790 | const s32 count = in->getAttributeAsInt("ItemCount"); | ||
791 | |||
792 | for (s32 i=0; i<count; ++i) | ||
793 | { | ||
794 | core::stringc tmp; | ||
795 | core::stringw txt; | ||
796 | s32 commandid=-1; | ||
797 | bool enabled=true; | ||
798 | bool checked=false; | ||
799 | bool autochecking=false; | ||
800 | |||
801 | tmp = "IsSeparator"; tmp += i; | ||
802 | if ( in->existsAttribute(tmp.c_str()) && in->getAttributeAsBool(tmp.c_str()) ) | ||
803 | addSeparator(); | ||
804 | else | ||
805 | { | ||
806 | tmp = "Text"; tmp += i; | ||
807 | if ( in->existsAttribute(tmp.c_str()) ) | ||
808 | txt = in->getAttributeAsStringW(tmp.c_str()); | ||
809 | |||
810 | tmp = "CommandID"; tmp += i; | ||
811 | if ( in->existsAttribute(tmp.c_str()) ) | ||
812 | commandid = in->getAttributeAsInt(tmp.c_str()); | ||
813 | |||
814 | tmp = "Enabled"; tmp += i; | ||
815 | if ( in->existsAttribute(tmp.c_str()) ) | ||
816 | enabled = in->getAttributeAsBool(tmp.c_str()); | ||
817 | |||
818 | tmp = "Checked"; tmp += i; | ||
819 | if ( in->existsAttribute(tmp.c_str()) ) | ||
820 | checked = in->getAttributeAsBool(tmp.c_str()); | ||
821 | |||
822 | tmp = "AutoChecking"; tmp += i; | ||
823 | if ( in->existsAttribute(tmp.c_str()) ) | ||
824 | autochecking = in->getAttributeAsBool(tmp.c_str()); | ||
825 | |||
826 | addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked, autochecking); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | recalculateSize(); | ||
831 | } | ||
832 | |||
833 | |||
834 | // because sometimes the element has no parent at click time | ||
835 | void CGUIContextMenu::setEventParent(IGUIElement *parent) | ||
836 | { | ||
837 | EventParent = parent; | ||
838 | |||
839 | for (u32 i=0; i<Items.size(); ++i) | ||
840 | if (Items[i].SubMenu) | ||
841 | Items[i].SubMenu->setEventParent(parent); | ||
842 | } | ||
843 | |||
844 | |||
845 | bool CGUIContextMenu::hasOpenSubMenu() const | ||
846 | { | ||
847 | for (u32 i=0; i<Items.size(); ++i) | ||
848 | if (Items[i].SubMenu && Items[i].SubMenu->isVisible()) | ||
849 | return true; | ||
850 | |||
851 | return false; | ||
852 | } | ||
853 | |||
854 | |||
855 | void CGUIContextMenu::closeAllSubMenus() | ||
856 | { | ||
857 | for (u32 i=0; i<Items.size(); ++i) | ||
858 | if (Items[i].SubMenu) | ||
859 | Items[i].SubMenu->setVisible(false); | ||
860 | |||
861 | //HighLighted = -1; | ||
862 | } | ||
863 | |||
864 | |||
865 | } // end namespace | ||
866 | } // end namespace | ||
867 | |||
868 | #endif // _IRR_COMPILE_WITH_GUI_ | ||
869 | |||