diff options
Diffstat (limited to 'src/FbTk')
-rw-r--r-- | src/FbTk/Menu.cc | 254 | ||||
-rw-r--r-- | src/FbTk/Menu.hh | 18 |
2 files changed, 163 insertions, 109 deletions
diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc index dad6159..ac8d651 100644 --- a/src/FbTk/Menu.cc +++ b/src/FbTk/Menu.cc | |||
@@ -22,7 +22,7 @@ | |||
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
23 | // DEALINGS IN THE SOFTWARE. | 23 | // DEALINGS IN THE SOFTWARE. |
24 | 24 | ||
25 | // $Id: Menu.cc,v 1.68 2004/06/14 16:09:48 fluxgen Exp $ | 25 | // $Id: Menu.cc,v 1.69 2004/06/27 13:50:24 fluxgen Exp $ |
26 | 26 | ||
27 | //use GNU extensions | 27 | //use GNU extensions |
28 | #ifndef _GNU_SOURCE | 28 | #ifndef _GNU_SOURCE |
@@ -89,6 +89,7 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl): | |||
89 | m_screen_width(DisplayWidth(FbTk::App::instance()->display(), tm.screenNum())), | 89 | m_screen_width(DisplayWidth(FbTk::App::instance()->display(), tm.screenNum())), |
90 | m_screen_height(DisplayHeight(FbTk::App::instance()->display(), tm.screenNum())), | 90 | m_screen_height(DisplayHeight(FbTk::App::instance()->display(), tm.screenNum())), |
91 | m_alignment(ALIGNDONTCARE), | 91 | m_alignment(ALIGNDONTCARE), |
92 | m_active_index(-1), | ||
92 | m_need_update(true) { | 93 | m_need_update(true) { |
93 | 94 | ||
94 | // setup timers | 95 | // setup timers |
@@ -198,9 +199,7 @@ Menu::~Menu() { | |||
198 | m_image_ctrl.removeImage(menu.sel_pixmap); | 199 | m_image_ctrl.removeImage(menu.sel_pixmap); |
199 | 200 | ||
200 | FbTk::EventManager &evm = *FbTk::EventManager::instance(); | 201 | FbTk::EventManager &evm = *FbTk::EventManager::instance(); |
201 | evm.remove(menu.title); | 202 | |
202 | evm.remove(menu.frame); | ||
203 | evm.remove(menu.window); | ||
204 | if (s_focused == this) | 203 | if (s_focused == this) |
205 | s_focused = 0; | 204 | s_focused = 0; |
206 | } | 205 | } |
@@ -261,7 +260,9 @@ int Menu::remove(unsigned int index) { | |||
261 | which_sub = -1; | 260 | which_sub = -1; |
262 | else if (static_cast<unsigned int>(which_sub) > index) | 261 | else if (static_cast<unsigned int>(which_sub) > index) |
263 | which_sub--; | 262 | which_sub--; |
263 | |||
264 | m_need_update = true; // we need to redraw the menu | 264 | m_need_update = true; // we need to redraw the menu |
265 | |||
265 | return menuitems.size(); | 266 | return menuitems.size(); |
266 | } | 267 | } |
267 | 268 | ||
@@ -283,30 +284,36 @@ void Menu::lower() { | |||
283 | void Menu::nextItem() { | 284 | void Menu::nextItem() { |
284 | int old_which_press = which_press; | 285 | int old_which_press = which_press; |
285 | 286 | ||
286 | if (old_which_press >= 0 && | 287 | if (validIndex(old_which_press) && |
287 | old_which_press < static_cast<signed>(menuitems.size()) && | ||
288 | menuitems[old_which_press] != 0) { | 288 | menuitems[old_which_press] != 0) { |
289 | if (menuitems[old_which_press]->submenu()) { | 289 | if (menuitems[old_which_press]->submenu()) { |
290 | // we need to do this explicitly on the menu.window | 290 | // we need to do this explicitly on the menu.window |
291 | // since it might hide the parent if we use Menu::hide | 291 | // since it might hide the parent if we use Menu::hide |
292 | menuitems[old_which_press]->submenu()->internal_hide(); | 292 | menuitems[old_which_press]->submenu()->internal_hide(); |
293 | } | 293 | } |
294 | drawItem(old_which_press, false, true, true); | 294 | drawItem(old_which_press, |
295 | true, // clear | ||
296 | true); // transp | ||
295 | } | 297 | } |
296 | 298 | ||
297 | // restore old in case we changed which_press | 299 | // restore old in case we changed which_press |
298 | which_press = old_which_press; | 300 | which_press = old_which_press; |
299 | if (which_press < 0 || which_press >= static_cast<signed>(menuitems.size() - 1)) | 301 | if (!validIndex(which_press)) |
300 | which_press = 0; | 302 | which_press = 0; |
301 | else | 303 | else |
302 | which_press++; | 304 | which_press++; |
303 | 305 | ||
304 | 306 | ||
305 | if (menuitems[which_press] == 0) | 307 | if (menuitems[which_press] == 0) { |
308 | m_active_index = -1; | ||
306 | return; | 309 | return; |
310 | } | ||
307 | 311 | ||
312 | m_active_index = which_press; | ||
308 | 313 | ||
309 | drawItem(which_press, true, true, true); | 314 | drawItem(which_press, |
315 | true, // clear | ||
316 | true); // transp | ||
310 | 317 | ||
311 | } | 318 | } |
312 | 319 | ||
@@ -314,32 +321,39 @@ void Menu::prevItem() { | |||
314 | 321 | ||
315 | int old_which_press = which_press; | 322 | int old_which_press = which_press; |
316 | 323 | ||
317 | if (old_which_press >= 0 && old_which_press < static_cast<signed>(menuitems.size())) { | 324 | if (validIndex(old_which_press)) { |
318 | if (menuitems[old_which_press]->submenu()) { | 325 | if (menuitems[old_which_press]->submenu()) { |
319 | // we need to do this explicitly on the menu.window | 326 | // we need to do this explicitly on the menu.window |
320 | // since it might hide the parent if we use Menu::hide | 327 | // since it might hide the parent if we use Menu::hide |
321 | menuitems[old_which_press]->submenu()->internal_hide(); | 328 | menuitems[old_which_press]->submenu()->internal_hide(); |
322 | } | 329 | } |
323 | drawItem(old_which_press, false, true, true); | 330 | drawItem(old_which_press, |
331 | true, // clear | ||
332 | true); // transp | ||
324 | } | 333 | } |
325 | // restore old in case we changed which_press | 334 | // restore old in case we changed which_press |
326 | which_press = old_which_press; | 335 | which_press = old_which_press; |
327 | 336 | ||
328 | if (which_press <= 0 || which_press >= static_cast<signed>(menuitems.size())) | 337 | if (!validIndex(which_press)) |
329 | which_press = menuitems.size() - 1; | 338 | which_press = menuitems.size() - 1; |
330 | else if (which_press - 1 >= 0) | 339 | else if (which_press - 1 >= 0) |
331 | which_press--; | 340 | which_press--; |
332 | 341 | ||
333 | if (menuitems[which_press] == 0) | 342 | if (menuitems[which_press] == 0) { |
343 | m_active_index = -1; | ||
334 | return; | 344 | return; |
345 | } | ||
335 | 346 | ||
347 | m_active_index = which_press; | ||
336 | 348 | ||
337 | drawItem(which_press, true, true, true); | 349 | drawItem(which_press, |
350 | true, // clear | ||
351 | true); // transp | ||
338 | 352 | ||
339 | } | 353 | } |
340 | 354 | ||
341 | void Menu::enterSubmenu() { | 355 | void Menu::enterSubmenu() { |
342 | if (which_press < 0 || which_press >= static_cast<signed>(menuitems.size())) | 356 | if (!validIndex(which_press)) |
343 | return; | 357 | return; |
344 | 358 | ||
345 | Menu *submenu = menuitems[which_press]->submenu(); | 359 | Menu *submenu = menuitems[which_press]->submenu(); |
@@ -356,14 +370,16 @@ void Menu::enterSubmenu() { | |||
356 | } | 370 | } |
357 | 371 | ||
358 | void Menu::enterParent() { | 372 | void Menu::enterParent() { |
359 | if (which_press < 0 || which_press >= static_cast<signed>(menuitems.size()) || parent() == 0) | 373 | if (!validIndex(which_press) || parent() == 0) |
360 | return; | 374 | return; |
361 | 375 | ||
362 | Menu *submenu = menuitems[which_press]->submenu(); | 376 | Menu *submenu = menuitems[which_press]->submenu(); |
363 | if (submenu) | 377 | if (submenu) |
364 | submenu->internal_hide(); | 378 | submenu->internal_hide(); |
365 | 379 | ||
366 | drawItem(which_press, false, true, true); | 380 | drawItem(which_press, |
381 | true, // clear | ||
382 | true); // transp | ||
367 | which_press = -1; // dont select any in this | 383 | which_press = -1; // dont select any in this |
368 | // hide self | 384 | // hide self |
369 | visible = false; | 385 | visible = false; |
@@ -422,7 +438,7 @@ void Menu::update(int active_index) { | |||
422 | int new_height = menu.frame_h; | 438 | int new_height = menu.frame_h; |
423 | 439 | ||
424 | if (title_vis) | 440 | if (title_vis) |
425 | new_height += theme().titleHeight() + ((menu.frame_h>0)?menu.title.borderWidth():0); | 441 | new_height += theme().titleHeight() + ((menu.frame_h > 0)?menu.title.borderWidth():0); |
426 | 442 | ||
427 | 443 | ||
428 | if (new_width < 1) | 444 | if (new_width < 1) |
@@ -588,18 +604,9 @@ void Menu::update(int active_index) { | |||
588 | renderTransp(0, 0, | 604 | renderTransp(0, 0, |
589 | m_real_frame_pm.width(), m_real_frame_pm.height()); | 605 | m_real_frame_pm.width(), m_real_frame_pm.height()); |
590 | for (unsigned int i = 0; i < menuitems.size(); i++) { | 606 | for (unsigned int i = 0; i < menuitems.size(); i++) { |
591 | if (i == (unsigned int)which_sub) { | 607 | drawItem(i, // index |
592 | drawItem(i, // index | 608 | true, // clear |
593 | true, // highlight | 609 | false); // render_trans |
594 | true, // clear | ||
595 | false); // render_trans | ||
596 | } else { | ||
597 | drawItem(i, // index | ||
598 | // highlight | ||
599 | (static_cast<signed>(i) == active_index && isItemEnabled(i)), | ||
600 | true, // clear | ||
601 | false); // render transparent | ||
602 | } | ||
603 | } | 610 | } |
604 | 611 | ||
605 | } | 612 | } |
@@ -609,6 +616,7 @@ void Menu::update(int active_index) { | |||
609 | 616 | ||
610 | 617 | ||
611 | void Menu::show() { | 618 | void Menu::show() { |
619 | |||
612 | if (m_need_update) | 620 | if (m_need_update) |
613 | update(); | 621 | update(); |
614 | 622 | ||
@@ -632,15 +640,18 @@ void Menu::hide() { | |||
632 | if (!isVisible()) | 640 | if (!isVisible()) |
633 | return; | 641 | return; |
634 | 642 | ||
635 | if ((! torn) && m_parent && m_parent->isVisible()) { | 643 | |
644 | // if not torn and parent is visible, go to first parent | ||
645 | // and hide it | ||
646 | if (!torn && m_parent && m_parent->isVisible()) { | ||
636 | Menu *p = m_parent; | 647 | Menu *p = m_parent; |
637 | 648 | ||
638 | while (p->isVisible() && (! p->torn) && p->m_parent) | 649 | while (p->isVisible() && (! p->torn) && p->m_parent) |
639 | p = p->m_parent; | 650 | p = p->m_parent; |
640 | p->internal_hide(); | 651 | p->internal_hide(); |
641 | } else | 652 | } else // if we dont have a parent then do hide here |
642 | internal_hide(); | 653 | internal_hide(); |
643 | 654 | ||
644 | } | 655 | } |
645 | 656 | ||
646 | void Menu::grabInputFocus() { | 657 | void Menu::grabInputFocus() { |
@@ -666,21 +677,24 @@ void Menu::clearWindow() { | |||
666 | } | 677 | } |
667 | 678 | ||
668 | void Menu::internal_hide() { | 679 | void Menu::internal_hide() { |
669 | if (which_sub >= 0) { | 680 | |
681 | if (validIndex(which_sub)) { | ||
670 | MenuItem *tmp = menuitems[which_sub]; | 682 | MenuItem *tmp = menuitems[which_sub]; |
671 | tmp->submenu()->internal_hide(); | 683 | tmp->submenu()->internal_hide(); |
672 | } | 684 | } |
673 | 685 | ||
674 | if (m_parent && (! torn)) { | 686 | if (shown && shown->menu.window == menu.window) |
675 | m_parent->drawItem(m_parent->which_sub, false, true); | ||
676 | |||
677 | m_parent->which_sub = -1; | ||
678 | } else if (shown && shown->menu.window == menu.window) | ||
679 | shown = (Menu *) 0; | 687 | shown = (Menu *) 0; |
680 | 688 | ||
681 | torn = visible = false; | 689 | torn = visible = false; |
682 | which_sub = which_press = which_sub = -1; | 690 | which_sub = which_press = which_sub = -1; |
683 | 691 | ||
692 | // if we have an active index we need to redraw it | ||
693 | // as non active | ||
694 | int old = m_active_index; | ||
695 | m_active_index = -1; | ||
696 | drawItem(old, true); // clear old area from highlight | ||
697 | |||
684 | menu.window.hide(); | 698 | menu.window.hide(); |
685 | } | 699 | } |
686 | 700 | ||
@@ -709,7 +723,7 @@ void Menu::move(int x, int y) { | |||
709 | renderTransp(0, 0, | 723 | renderTransp(0, 0, |
710 | m_real_frame_pm.width(), m_real_frame_pm.height()); | 724 | m_real_frame_pm.width(), m_real_frame_pm.height()); |
711 | for (size_t i=0; i < menuitems.size(); ++i) { | 725 | for (size_t i=0; i < menuitems.size(); ++i) { |
712 | drawItem(i, false, // highlight | 726 | drawItem(i, |
713 | true, // clear | 727 | true, // clear |
714 | false); // transparent | 728 | false); // transparent |
715 | } | 729 | } |
@@ -759,8 +773,7 @@ void Menu::redrawTitle() { | |||
759 | 773 | ||
760 | 774 | ||
761 | void Menu::drawSubmenu(unsigned int index) { | 775 | void Menu::drawSubmenu(unsigned int index) { |
762 | if (which_sub >= 0 && static_cast<unsigned int>(which_sub) != index && | 776 | if (validIndex(which_sub) && static_cast<unsigned int>(which_sub) != index) { |
763 | static_cast<unsigned int>(which_sub) < menuitems.size()) { | ||
764 | MenuItem *itmp = menuitems[which_sub]; | 777 | MenuItem *itmp = menuitems[which_sub]; |
765 | 778 | ||
766 | if (! itmp->submenu()->isTorn()) | 779 | if (! itmp->submenu()->isTorn()) |
@@ -822,7 +835,7 @@ void Menu::drawSubmenu(unsigned int index) { | |||
822 | 835 | ||
823 | item->submenu()->move(new_x, new_y); | 836 | item->submenu()->move(new_x, new_y); |
824 | if (! moving) | 837 | if (! moving) |
825 | drawItem(index, true); | 838 | drawItem(index); |
826 | 839 | ||
827 | if (! item->submenu()->isVisible()) { | 840 | if (! item->submenu()->isVisible()) { |
828 | item->submenu()->show(); | 841 | item->submenu()->show(); |
@@ -847,7 +860,7 @@ bool Menu::hasSubmenu(unsigned int index) const { | |||
847 | } | 860 | } |
848 | 861 | ||
849 | 862 | ||
850 | int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_trans, | 863 | int Menu::drawItem(unsigned int index, bool clear, bool render_trans, |
851 | int x, int y, unsigned int w, unsigned int h) { | 864 | int x, int y, unsigned int w, unsigned int h) { |
852 | if (index >= menuitems.size() || menuitems.size() == 0 || | 865 | if (index >= menuitems.size() || menuitems.size() == 0 || |
853 | menu.persub == 0) | 866 | menu.persub == 0) |
@@ -862,7 +875,7 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t | |||
862 | int sel_x = 0, sel_y = 0; | 875 | int sel_x = 0, sel_y = 0; |
863 | unsigned int hilite_w = menu.item_w, hilite_h = theme().itemHeight(); | 876 | unsigned int hilite_w = menu.item_w, hilite_h = theme().itemHeight(); |
864 | unsigned int half_w = theme().itemHeight() / 2, quarter_w = theme().itemHeight() / 4; | 877 | unsigned int half_w = theme().itemHeight() / 2, quarter_w = theme().itemHeight() / 4; |
865 | 878 | bool highlight = (index == m_active_index); | |
866 | GC gc = | 879 | GC gc = |
867 | ((highlight || item->isSelected()) ? theme().hiliteTextGC().gc() : | 880 | ((highlight || item->isSelected()) ? theme().hiliteTextGC().gc() : |
868 | theme().frameTextGC().gc()); | 881 | theme().frameTextGC().gc()); |
@@ -1044,7 +1057,7 @@ void Menu::buttonPressEvent(XButtonEvent &be) { | |||
1044 | int sbl = (be.x / menu.item_w), i = (be.y / theme().itemHeight()); | 1057 | int sbl = (be.x / menu.item_w), i = (be.y / theme().itemHeight()); |
1045 | int w = (sbl * menu.persub) + i; | 1058 | int w = (sbl * menu.persub) + i; |
1046 | 1059 | ||
1047 | if (w < static_cast<int>(menuitems.size()) && w >= 0) { | 1060 | if (validIndex(w)) { |
1048 | which_press = i; | 1061 | which_press = i; |
1049 | which_sbl = sbl; | 1062 | which_sbl = sbl; |
1050 | 1063 | ||
@@ -1054,7 +1067,9 @@ void Menu::buttonPressEvent(XButtonEvent &be) { | |||
1054 | if (!item->submenu()->isVisible()) | 1067 | if (!item->submenu()->isVisible()) |
1055 | drawSubmenu(w); | 1068 | drawSubmenu(w); |
1056 | } else | 1069 | } else |
1057 | drawItem(w, item->isEnabled(), true, true); | 1070 | drawItem(w, |
1071 | true, // clear | ||
1072 | true); // render transparency | ||
1058 | 1073 | ||
1059 | } | 1074 | } |
1060 | } else { | 1075 | } else { |
@@ -1078,7 +1093,7 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) { | |||
1078 | renderTransp(0, 0, | 1093 | renderTransp(0, 0, |
1079 | m_real_frame_pm.width(), m_real_frame_pm.height()); | 1094 | m_real_frame_pm.width(), m_real_frame_pm.height()); |
1080 | for (size_t i=0; i < menuitems.size(); ++i) { | 1095 | for (size_t i=0; i < menuitems.size(); ++i) { |
1081 | drawItem(i, false, // highlight | 1096 | drawItem(i, |
1082 | true, // clear | 1097 | true, // clear |
1083 | false); // transparent | 1098 | false); // transparent |
1084 | } | 1099 | } |
@@ -1100,20 +1115,28 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) { | |||
1100 | w = (sbl * menu.persub) + i, | 1115 | w = (sbl * menu.persub) + i, |
1101 | p = (which_sbl * menu.persub) + which_press; | 1116 | p = (which_sbl * menu.persub) + which_press; |
1102 | 1117 | ||
1103 | if (w < static_cast<int>(menuitems.size()) && w >= 0) { | 1118 | if (validIndex(w)) { |
1104 | if (p == w && isItemEnabled(w)) { | 1119 | if (p == w && isItemEnabled(w)) { |
1105 | if (re.x > ix && re.x < (signed) (ix + menu.item_w) && | 1120 | if (re.x > ix && re.x < (signed) (ix + menu.item_w) && |
1106 | re.y > iy && re.y < (signed) (iy + theme().itemHeight())) { | 1121 | re.y > iy && re.y < (signed) (iy + theme().itemHeight())) { |
1107 | menuitems[w]->click(re.button, re.time); | 1122 | menuitems[w]->click(re.button, re.time); |
1108 | itemSelected(re.button, w); | 1123 | itemSelected(re.button, w); |
1109 | // just redraw this item | 1124 | // just redraw this item |
1110 | drawItem(w, true, true, true); | 1125 | drawItem(w, |
1126 | true, // clear | ||
1127 | true); // transparent | ||
1111 | } | 1128 | } |
1112 | } else { | 1129 | } else { |
1113 | drawItem(p, isItemEnabled(p) && (p == which_sub), true, true); | 1130 | drawItem(p, |
1131 | true, // clear | ||
1132 | true); // transparent | ||
1114 | } | 1133 | } |
1115 | } else | 1134 | |
1116 | drawItem(p, false, true, true); | 1135 | } else { |
1136 | drawItem(p, | ||
1137 | true, // clear | ||
1138 | true); // transparent | ||
1139 | } | ||
1117 | } | 1140 | } |
1118 | } | 1141 | } |
1119 | 1142 | ||
@@ -1126,7 +1149,9 @@ void Menu::motionNotifyEvent(XMotionEvent &me) { | |||
1126 | if (! moving) { | 1149 | if (! moving) { |
1127 | // if not moving: start moving operation | 1150 | // if not moving: start moving operation |
1128 | if (m_parent && (! torn)) { | 1151 | if (m_parent && (! torn)) { |
1129 | m_parent->drawItem(m_parent->which_sub, false, true, true); | 1152 | m_parent->drawItem(m_parent->which_sub, |
1153 | true, // clear | ||
1154 | true); // render transparency | ||
1130 | m_parent->which_sub = -1; | 1155 | m_parent->which_sub = -1; |
1131 | } | 1156 | } |
1132 | 1157 | ||
@@ -1140,65 +1165,83 @@ void Menu::motionNotifyEvent(XMotionEvent &me) { | |||
1140 | menu.window.move(me.x_root - menu.x_move, me.y_root - menu.y_move); | 1165 | menu.window.move(me.x_root - menu.x_move, me.y_root - menu.y_move); |
1141 | } | 1166 | } |
1142 | 1167 | ||
1143 | } else if ((! (me.state & Button1Mask)) && me.window == menu.frame && | 1168 | } else if (!(me.state & Button1Mask) && me.window == menu.frame) { |
1144 | me.x >= 0 && me.x < (signed) width() && | ||
1145 | me.y >= 0 && me.y < (signed) menu.frame_h) { | ||
1146 | stopHide(); | 1169 | stopHide(); |
1147 | int sbl = (me.x / menu.item_w), i = (me.y / theme().itemHeight()), | 1170 | int sbl = (me.x / menu.item_w), |
1171 | i = (me.y / theme().itemHeight()), | ||
1148 | w = (sbl * menu.persub) + i; | 1172 | w = (sbl * menu.persub) + i; |
1173 | |||
1174 | if (validIndex(m_active_index) && w != m_active_index) { | ||
1149 | 1175 | ||
1150 | if ((i != which_press || sbl != which_sbl) && | 1176 | int old = m_active_index; |
1151 | (w < static_cast<int>(menuitems.size()) && w >= 0)) { | 1177 | m_active_index = -1; |
1178 | MenuItem *item = menuitems[old]; | ||
1152 | 1179 | ||
1153 | if (which_press != -1 && which_sbl != -1) { | 1180 | if (item != 0) { |
1154 | 1181 | ||
1155 | int p = which_sbl * menu.persub + which_press; | 1182 | drawItem(old, |
1156 | MenuItem *item = menuitems[p]; | 1183 | true, // clear |
1157 | // don't redraw disabled items on enter/leave | 1184 | true); // transparent |
1158 | if (item != 0 && item->isEnabled()) { | ||
1159 | 1185 | ||
1160 | drawItem(p, false, // highlight | 1186 | if (item->submenu()) { |
1161 | true, // clear | ||
1162 | true); // transparent | ||
1163 | 1187 | ||
1164 | if (item->submenu()) { | 1188 | if (item->submenu()->isVisible() && |
1165 | 1189 | !item->submenu()->isTorn()) { | |
1166 | if (item->submenu()->isVisible() && | 1190 | // setup hide timer for submenu |
1167 | !item->submenu()->isTorn()) { | 1191 | item->submenu()->startHide(); |
1168 | // setup hide timer for submenu | ||
1169 | item->submenu()->startHide(); | ||
1170 | } | ||
1171 | } | 1192 | } |
1172 | 1193 | } | |
1173 | } | ||
1174 | 1194 | ||
1175 | } | 1195 | } |
1176 | 1196 | ||
1177 | which_press = i; | 1197 | } |
1178 | which_sbl = sbl; | ||
1179 | 1198 | ||
1180 | MenuItem *itmp = menuitems[w]; | ||
1181 | 1199 | ||
1182 | if (itmp->submenu()) { | 1200 | which_press = i; |
1201 | which_sbl = sbl; | ||
1183 | 1202 | ||
1184 | drawItem(w, true, true); | 1203 | m_active_index = -1; |
1185 | 1204 | ||
1186 | if (theme().menuMode() == MenuTheme::DELAY_OPEN) { | 1205 | if (!validIndex(w)) |
1187 | // setup show menu timer | 1206 | return; |
1188 | timeval timeout; | ||
1189 | timeout.tv_sec = 0; | ||
1190 | timeout.tv_usec = theme().delayOpen() * 1000; // transformed to usec | ||
1191 | m_submenu_timer.setTimeout(timeout); | ||
1192 | m_submenu_timer.start(); | ||
1193 | 1207 | ||
1194 | } | ||
1195 | 1208 | ||
1196 | } else { | 1209 | MenuItem *itmp = menuitems[w]; |
1197 | m_submenu_timer.stop(); | 1210 | |
1198 | if (itmp->isEnabled()) | 1211 | m_active_index = w; |
1199 | drawItem(w, true, true, true); | 1212 | |
1213 | if (itmp == 0) | ||
1214 | return; | ||
1215 | |||
1216 | if (itmp->submenu()) { | ||
1217 | // if submenu, | ||
1218 | // draw item highlighted and | ||
1219 | // start submenu open delay | ||
1220 | |||
1221 | drawItem(w, | ||
1222 | true); // clear | ||
1223 | |||
1224 | if (theme().menuMode() == MenuTheme::DELAY_OPEN) { | ||
1225 | // setup show menu timer | ||
1226 | timeval timeout; | ||
1227 | timeout.tv_sec = 0; | ||
1228 | timeout.tv_usec = theme().delayOpen() * 1000; // transformed to usec | ||
1229 | m_submenu_timer.setTimeout(timeout); | ||
1230 | m_submenu_timer.start(); | ||
1231 | |||
1232 | } | ||
1233 | |||
1234 | } else { | ||
1235 | // else normal menu item | ||
1236 | // draw highlighted | ||
1237 | m_submenu_timer.stop(); | ||
1238 | if (itmp->isEnabled()) { | ||
1239 | drawItem(w, | ||
1240 | true, // clear | ||
1241 | true); // transp | ||
1200 | } | 1242 | } |
1201 | } | 1243 | } |
1244 | |||
1202 | } | 1245 | } |
1203 | } | 1246 | } |
1204 | 1247 | ||
@@ -1238,7 +1281,7 @@ void Menu::enterNotifyEvent(XCrossingEvent &ce) { | |||
1238 | if (shifted) | 1281 | if (shifted) |
1239 | menu.window.move(menu.x_shift, menu.y_shift); | 1282 | menu.window.move(menu.x_shift, menu.y_shift); |
1240 | 1283 | ||
1241 | if (which_sub >= 0 && static_cast<size_t>(which_sub) < menuitems.size()) { | 1284 | if (validIndex(which_sub)) { |
1242 | MenuItem *tmp = menuitems[which_sub]; | 1285 | MenuItem *tmp = menuitems[which_sub]; |
1243 | if (tmp->submenu()->isVisible()) { | 1286 | if (tmp->submenu()->isVisible()) { |
1244 | int sbl = (ce.x / menu.item_w), i = (ce.y / theme().itemHeight()), | 1287 | int sbl = (ce.x / menu.item_w), i = (ce.y / theme().itemHeight()), |
@@ -1247,7 +1290,9 @@ void Menu::enterNotifyEvent(XCrossingEvent &ce) { | |||
1247 | if (w != which_sub && (! tmp->submenu()->isTorn())) { | 1290 | if (w != which_sub && (! tmp->submenu()->isTorn())) { |
1248 | tmp->submenu()->internal_hide(); | 1291 | tmp->submenu()->internal_hide(); |
1249 | 1292 | ||
1250 | drawItem(which_sub, false, true, true); | 1293 | drawItem(which_sub, |
1294 | true, // clear | ||
1295 | true); // transp | ||
1251 | which_sub = -1; | 1296 | which_sub = -1; |
1252 | } | 1297 | } |
1253 | } | 1298 | } |
@@ -1261,7 +1306,9 @@ void Menu::leaveNotifyEvent(XCrossingEvent &ce) { | |||
1261 | if (which_press != -1 && which_sbl != -1 && menuitems.size() > 0) { | 1306 | if (which_press != -1 && which_sbl != -1 && menuitems.size() > 0) { |
1262 | int p = (which_sbl * menu.persub) + which_press; | 1307 | int p = (which_sbl * menu.persub) + which_press; |
1263 | 1308 | ||
1264 | drawItem(p, (p == which_sub), true, true); | 1309 | drawItem(p, |
1310 | true, // clear | ||
1311 | true); // transp | ||
1265 | 1312 | ||
1266 | which_sbl = which_press = -1; | 1313 | which_sbl = which_press = -1; |
1267 | } | 1314 | } |
@@ -1298,7 +1345,7 @@ void Menu::keyPressEvent(XKeyEvent &event) { | |||
1298 | break; | 1345 | break; |
1299 | case XK_Return: | 1346 | case XK_Return: |
1300 | // send fake button 1 click | 1347 | // send fake button 1 click |
1301 | if (which_press >= 0 && which_press < static_cast<signed>(menuitems.size()) && | 1348 | if (validIndex(which_press) && |
1302 | isItemEnabled(which_press)) { | 1349 | isItemEnabled(which_press)) { |
1303 | menuitems[which_press]->click(1, event.time); | 1350 | menuitems[which_press]->click(1, event.time); |
1304 | itemSelected(1, which_press); | 1351 | itemSelected(1, which_press); |
@@ -1345,15 +1392,16 @@ void Menu::reconfigure() { | |||
1345 | 1392 | ||
1346 | 1393 | ||
1347 | void Menu::openSubmenu() { | 1394 | void Menu::openSubmenu() { |
1348 | if (!isVisible() || which_press < 0 || which_press >= static_cast<signed>(menuitems.size()) || | 1395 | if (!isVisible() || ! validIndex(which_press) || |
1349 | which_sbl < 0 || which_sbl >= static_cast<signed>(menuitems.size())) | 1396 | ! validIndex(which_sbl)) |
1350 | return; | 1397 | return; |
1351 | 1398 | ||
1352 | int item = which_sbl * menu.persub + which_press; | 1399 | int item = which_sbl * menu.persub + which_press; |
1353 | if (item < 0 || item >= static_cast<signed>(menuitems.size())) | 1400 | if (!validIndex(item)) |
1354 | return; | 1401 | return; |
1355 | 1402 | ||
1356 | drawItem(item, true, true); | 1403 | drawItem(item, |
1404 | true); // clear | ||
1357 | if (menuitems[item]->submenu() != 0 && !menuitems[item]->submenu()->isVisible()) | 1405 | if (menuitems[item]->submenu() != 0 && !menuitems[item]->submenu()->isVisible()) |
1358 | drawSubmenu(item); | 1406 | drawSubmenu(item); |
1359 | 1407 | ||
diff --git a/src/FbTk/Menu.hh b/src/FbTk/Menu.hh index 625a7d7..8c6c738 100644 --- a/src/FbTk/Menu.hh +++ b/src/FbTk/Menu.hh | |||
@@ -22,7 +22,7 @@ | |||
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
23 | // DEALINGS IN THE SOFTWARE. | 23 | // DEALINGS IN THE SOFTWARE. |
24 | 24 | ||
25 | // $Id: Menu.hh,v 1.36 2004/06/14 12:23:57 fluxgen Exp $ | 25 | // $Id: Menu.hh,v 1.37 2004/06/27 13:51:24 fluxgen Exp $ |
26 | 26 | ||
27 | #ifndef FBTK_MENU_HH | 27 | #ifndef FBTK_MENU_HH |
28 | #define FBTK_MENU_HH | 28 | #define FBTK_MENU_HH |
@@ -125,12 +125,14 @@ public: | |||
125 | /// hide menu | 125 | /// hide menu |
126 | virtual void hide(); | 126 | virtual void hide(); |
127 | virtual void clearWindow(); | 127 | virtual void clearWindow(); |
128 | void setActiveIndex(int index) { m_active_index = index; } | ||
128 | /*@}*/ | 129 | /*@}*/ |
129 | 130 | ||
130 | /** | 131 | /** |
131 | @name accessors | 132 | @name accessors |
132 | */ | 133 | */ |
133 | //@{ | 134 | //@{ |
135 | inline int activeIndex() const { return m_active_index; } | ||
134 | inline bool isTorn() const { return torn; } | 136 | inline bool isTorn() const { return torn; } |
135 | inline bool isVisible() const { return visible; } | 137 | inline bool isVisible() const { return visible; } |
136 | inline int screenNumber() const { return menu.window.screenNumber(); } | 138 | inline int screenNumber() const { return menu.window.screenNumber(); } |
@@ -156,6 +158,8 @@ public: | |||
156 | inline const MenuItem *find(unsigned int index) const { return menuitems[index]; } | 158 | inline const MenuItem *find(unsigned int index) const { return menuitems[index]; } |
157 | inline MenuItem *find(unsigned int index) { return menuitems[index]; } | 159 | inline MenuItem *find(unsigned int index) { return menuitems[index]; } |
158 | //@} | 160 | //@} |
161 | /// @return true if index is valid | ||
162 | inline bool validIndex(int index) const { return (index < static_cast<int>(numberOfItems()) && index >= 0); } | ||
159 | 163 | ||
160 | protected: | 164 | protected: |
161 | 165 | ||
@@ -168,8 +172,8 @@ protected: | |||
168 | } | 172 | } |
169 | 173 | ||
170 | virtual void itemSelected(int button, unsigned int index) { } | 174 | virtual void itemSelected(int button, unsigned int index) { } |
171 | virtual int drawItem(unsigned int index, bool highlight = false, | 175 | virtual int drawItem(unsigned int index, |
172 | bool clear= false, bool render_trans = true, | 176 | bool clear = false, bool render_trans = true, |
173 | int x= -1, int y= -1, | 177 | int x= -1, int y= -1, |
174 | unsigned int width= 0, unsigned int height= 0); | 178 | unsigned int width= 0, unsigned int height= 0); |
175 | virtual void redrawTitle(); | 179 | virtual void redrawTitle(); |
@@ -178,7 +182,8 @@ protected: | |||
178 | inline const Menu *parent() const { return m_parent; } | 182 | inline const Menu *parent() const { return m_parent; } |
179 | 183 | ||
180 | void update(FbTk::Subject *); | 184 | void update(FbTk::Subject *); |
181 | 185 | void renderTransp(int x, int y, | |
186 | unsigned int width, unsigned int height); | ||
182 | private: | 187 | private: |
183 | 188 | ||
184 | void openSubmenu(); | 189 | void openSubmenu(); |
@@ -186,8 +191,7 @@ private: | |||
186 | void startHide(); | 191 | void startHide(); |
187 | void stopHide(); | 192 | void stopHide(); |
188 | 193 | ||
189 | void renderTransp(int x, int y, | 194 | |
190 | unsigned int width, unsigned int height); | ||
191 | typedef std::vector<MenuItem *> Menuitems; | 195 | typedef std::vector<MenuItem *> Menuitems; |
192 | const MenuTheme &m_theme; | 196 | const MenuTheme &m_theme; |
193 | Menu *m_parent; | 197 | Menu *m_parent; |
@@ -216,6 +220,8 @@ private: | |||
216 | unsigned int frame_h, item_w; | 220 | unsigned int frame_h, item_w; |
217 | } menu; | 221 | } menu; |
218 | 222 | ||
223 | int m_active_index; ///< current highlighted index | ||
224 | |||
219 | Drawable m_root_pm; | 225 | Drawable m_root_pm; |
220 | static Menu *s_focused; ///< holds current input focused menu, so one can determine if a menu is focused | 226 | static Menu *s_focused; ///< holds current input focused menu, so one can determine if a menu is focused |
221 | FbPixmap m_frame_pm, ///< buffer pixmap | 227 | FbPixmap m_frame_pm, ///< buffer pixmap |