diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | src/FbTk/Menu.cc | 219 | ||||
-rw-r--r-- | src/FbTk/Menu.hh | 11 |
3 files changed, 85 insertions, 148 deletions
@@ -1,5 +1,8 @@ | |||
1 | (Format: Year/Month/Day) | 1 | (Format: Year/Month/Day) |
2 | Changes for 1.0rc3: | 2 | Changes for 1.0rc3: |
3 | *07/02/28: | ||
4 | * Fixed some strange menu behaviors (Mark) | ||
5 | FbTk/Menu.cc/hh | ||
3 | *07/02/27: | 6 | *07/02/27: |
4 | * Respect external tabs in ArrangeWindows (thanks to Tomas Janousek <tomi | 7 | * Respect external tabs in ArrangeWindows (thanks to Tomas Janousek <tomi |
5 | at nomi dot cz> | 8 | at nomi dot cz> |
diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc index 138eaf4..cb401fa 100644 --- a/src/FbTk/Menu.cc +++ b/src/FbTk/Menu.cc | |||
@@ -114,9 +114,7 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl): | |||
114 | menu.x_move = | 114 | menu.x_move = |
115 | menu.y_move = 0; | 115 | menu.y_move = 0; |
116 | 116 | ||
117 | m_which_sub = | 117 | m_which_sub = -1; |
118 | m_which_press = | ||
119 | m_which_sbl = -1; | ||
120 | 118 | ||
121 | menu.frame_pixmap = | 119 | menu.frame_pixmap = |
122 | menu.title_pixmap = | 120 | menu.title_pixmap = |
@@ -273,94 +271,91 @@ void Menu::lower() { | |||
273 | menu.window.lower(); | 271 | menu.window.lower(); |
274 | } | 272 | } |
275 | 273 | ||
276 | void Menu::nextItem() { | 274 | void Menu::nextItem(int failsafe) { |
277 | if (menuitems.empty()) | 275 | if (menuitems.empty()) |
278 | return; | 276 | return; |
279 | 277 | ||
280 | int old_which_press = m_which_press; | 278 | if (failsafe == -1) |
281 | m_active_index = -1; | 279 | failsafe = m_active_index; |
282 | if (validIndex(old_which_press) && | 280 | |
283 | menuitems[old_which_press] != 0) { | 281 | int old_active_index = m_active_index; |
284 | if (menuitems[old_which_press]->submenu()) { | 282 | m_active_index += 1; |
283 | if (!validIndex(m_active_index)) | ||
284 | m_active_index = 0; | ||
285 | |||
286 | if (validIndex(old_active_index) && | ||
287 | menuitems[old_active_index] != 0) { | ||
288 | if (menuitems[old_active_index]->submenu()) { | ||
285 | // we need to do this explicitly on the menu.window | 289 | // we need to do this explicitly on the menu.window |
286 | // since it might hide the parent if we use Menu::hide | 290 | // since it might hide the parent if we use Menu::hide |
287 | menuitems[old_which_press]->submenu()->internal_hide(); | 291 | menuitems[old_active_index]->submenu()->internal_hide(); |
288 | } | 292 | } |
289 | clearItem(old_which_press); | 293 | clearItem(old_active_index); |
290 | } | 294 | } |
291 | 295 | ||
292 | // restore old in case we changed m_which_press | 296 | if (menuitems[m_active_index] == 0) { |
293 | m_which_press = old_which_press + 1; | ||
294 | if (!validIndex(m_which_press)) | ||
295 | m_which_press = 0; | ||
296 | |||
297 | |||
298 | if (menuitems[m_which_press] == 0) { | ||
299 | m_active_index = -1; | 297 | m_active_index = -1; |
300 | return; | 298 | return; |
301 | } | 299 | } |
302 | 300 | ||
303 | if (!isItemSelectable(m_which_press)) { | 301 | if (!isItemSelectable(m_active_index) && m_active_index != failsafe) { |
304 | nextItem(); | 302 | nextItem(failsafe); |
305 | return; | 303 | return; |
306 | } | 304 | } |
307 | 305 | ||
308 | m_active_index = m_which_press; | 306 | clearItem(m_active_index); |
309 | |||
310 | clearItem(m_which_press); | ||
311 | 307 | ||
312 | } | 308 | } |
313 | 309 | ||
314 | void Menu::prevItem() { | 310 | void Menu::prevItem(int failsafe) { |
315 | if (menuitems.empty()) | 311 | if (menuitems.empty()) |
316 | return; | 312 | return; |
317 | 313 | ||
318 | int old_which_press = m_which_press; | 314 | if (failsafe == -1) |
319 | m_active_index = -1; | 315 | failsafe = m_active_index; |
320 | if (validIndex(old_which_press)) { | 316 | |
321 | if (menuitems[old_which_press]->submenu()) { | 317 | int old_active_index = m_active_index; |
318 | m_active_index -= 1; | ||
319 | if (!validIndex(m_active_index)) | ||
320 | m_active_index = menuitems.size() - 1; | ||
321 | |||
322 | if (validIndex(old_active_index)) { | ||
323 | if (menuitems[old_active_index]->submenu()) { | ||
322 | // we need to do this explicitly on the menu.window | 324 | // we need to do this explicitly on the menu.window |
323 | // since it might hide the parent if we use Menu::hide | 325 | // since it might hide the parent if we use Menu::hide |
324 | menuitems[old_which_press]->submenu()->internal_hide(); | 326 | menuitems[old_active_index]->submenu()->internal_hide(); |
325 | } | 327 | } |
326 | clearItem(old_which_press); | 328 | clearItem(old_active_index); |
327 | } | 329 | } |
328 | // restore old in case we changed m_which_press | ||
329 | m_which_press = old_which_press - 1; | ||
330 | 330 | ||
331 | if (!validIndex(m_which_press)) | 331 | if (menuitems[m_active_index] == 0) { |
332 | m_which_press = menuitems.size() - 1; | ||
333 | |||
334 | if (menuitems[m_which_press] == 0) { | ||
335 | m_active_index = -1; | 332 | m_active_index = -1; |
336 | return; | 333 | return; |
337 | } | 334 | } |
338 | 335 | ||
339 | if (!isItemSelectable(m_which_press)) { | 336 | if (!isItemSelectable(m_active_index) && m_active_index != failsafe) { |
340 | prevItem(); | 337 | prevItem(failsafe); |
341 | return; | 338 | return; |
342 | } | 339 | } |
343 | 340 | ||
344 | m_active_index = m_which_press; | 341 | clearItem(m_active_index); |
345 | |||
346 | clearItem(m_which_press); | ||
347 | 342 | ||
348 | } | 343 | } |
349 | 344 | ||
350 | void Menu::enterSubmenu() { | 345 | void Menu::enterSubmenu() { |
351 | if (!validIndex(m_which_press)) | 346 | if (!validIndex(m_active_index)) |
352 | return; | 347 | return; |
353 | 348 | ||
354 | Menu *submenu = menuitems[m_which_press]->submenu(); | 349 | Menu *submenu = menuitems[m_active_index]->submenu(); |
355 | if (submenu == 0) | 350 | if (submenu == 0) |
356 | return; | 351 | return; |
357 | 352 | ||
358 | if (submenu->menuitems.size() == 0) | 353 | if (submenu->menuitems.size() == 0) |
359 | return; | 354 | return; |
360 | 355 | ||
361 | drawSubmenu(m_which_press); | 356 | drawSubmenu(m_active_index); |
362 | submenu->grabInputFocus(); | 357 | submenu->grabInputFocus(); |
363 | submenu->m_which_press = -1; // so we land on 0 after nextItem() | 358 | submenu->m_active_index = -1; // so we land on 0 after nextItem() |
364 | submenu->nextItem(); | 359 | submenu->nextItem(); |
365 | } | 360 | } |
366 | 361 | ||
@@ -368,15 +363,13 @@ void Menu::enterParent() { | |||
368 | if (parent() == 0) | 363 | if (parent() == 0) |
369 | return; | 364 | return; |
370 | 365 | ||
371 | if (validIndex(m_which_press)) { | 366 | if (validIndex(m_active_index)) { |
372 | Menu *submenu = menuitems[m_which_press]->submenu(); | 367 | Menu *submenu = menuitems[m_active_index]->submenu(); |
373 | if (submenu) | 368 | if (submenu) |
374 | submenu->internal_hide(); | 369 | submenu->internal_hide(); |
375 | } | 370 | } |
376 | 371 | ||
377 | m_active_index = -1; | 372 | m_active_index = -1; |
378 | //clearItem(m_which_press); | ||
379 | m_which_press = -1; // dont select any in this | ||
380 | // hide self | 373 | // hide self |
381 | m_visible = false; | 374 | m_visible = false; |
382 | menu.window.hide(); | 375 | menu.window.hide(); |
@@ -619,7 +612,7 @@ void Menu::internal_hide() { | |||
619 | shown = (Menu *) 0; | 612 | shown = (Menu *) 0; |
620 | 613 | ||
621 | m_torn = m_visible = false; | 614 | m_torn = m_visible = false; |
622 | m_which_sub = m_which_press = m_which_sub = -1; | 615 | m_which_sub = -1; |
623 | 616 | ||
624 | menu.window.hide(); | 617 | menu.window.hide(); |
625 | } | 618 | } |
@@ -751,18 +744,6 @@ void Menu::drawSubmenu(unsigned int index) { | |||
751 | 744 | ||
752 | } | 745 | } |
753 | 746 | ||
754 | #ifdef NOT_USED | ||
755 | bool Menu::hasSubmenu(unsigned int index) const { | ||
756 | if (index >= menuitems.size()) //boundary check | ||
757 | return false; | ||
758 | |||
759 | if (!menuitems[index]->submenu()) //has submenu? | ||
760 | return false; | ||
761 | |||
762 | return true; | ||
763 | } | ||
764 | #endif // NOT_USED | ||
765 | |||
766 | int Menu::drawItem(FbDrawable &drawable, unsigned int index, | 747 | int Menu::drawItem(FbDrawable &drawable, unsigned int index, |
767 | bool highlight, bool exclusive_drawable) { | 748 | bool highlight, bool exclusive_drawable) { |
768 | 749 | ||
@@ -872,9 +853,6 @@ void Menu::buttonPressEvent(XButtonEvent &be) { | |||
872 | int w = (sbl * menu.persub) + i; | 853 | int w = (sbl * menu.persub) + i; |
873 | 854 | ||
874 | if (validIndex(w) && isItemSelectable(static_cast<unsigned int>(w))) { | 855 | if (validIndex(w) && isItemSelectable(static_cast<unsigned int>(w))) { |
875 | m_which_press = i; | ||
876 | m_which_sbl = sbl; | ||
877 | |||
878 | MenuItem *item = menuitems[w]; | 856 | MenuItem *item = menuitems[w]; |
879 | 857 | ||
880 | if (item->submenu()) { | 858 | if (item->submenu()) { |
@@ -913,19 +891,19 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) { | |||
913 | 891 | ||
914 | int sbl = (re.x / menu.item_w), i = (re.y / theme().itemHeight()), | 892 | int sbl = (re.x / menu.item_w), i = (re.y / theme().itemHeight()), |
915 | ix = sbl * menu.item_w, iy = i * theme().itemHeight(), | 893 | ix = sbl * menu.item_w, iy = i * theme().itemHeight(), |
916 | w = (sbl * menu.persub) + i, | 894 | w = (sbl * menu.persub) + i; |
917 | p = (m_which_sbl * menu.persub) + m_which_press; | ||
918 | 895 | ||
919 | if (validIndex(w) && isItemSelectable(static_cast<unsigned int>(w))) { | 896 | if (validIndex(w) && isItemSelectable(static_cast<unsigned int>(w))) { |
920 | if (p == w && isItemEnabled(w)) { | 897 | if (m_active_index == w && isItemEnabled(w) && |
921 | if (re.x > ix && re.x < (signed) (ix + menu.item_w) && | 898 | re.x > ix && re.x < (signed) (ix + menu.item_w) && |
922 | re.y > iy && re.y < (signed) (iy + theme().itemHeight())) { | 899 | re.y > iy && re.y < (signed) (iy + theme().itemHeight())) { |
923 | menuitems[w]->click(re.button, re.time); | 900 | menuitems[w]->click(re.button, re.time); |
924 | itemSelected(re.button, w); | ||
925 | } | ||
926 | } | 901 | } |
927 | 902 | ||
928 | clearItem(p); | 903 | int old = m_active_index; |
904 | m_active_index = w; | ||
905 | clearItem(old); | ||
906 | clearItem(w); | ||
929 | } | 907 | } |
930 | } | 908 | } |
931 | } | 909 | } |
@@ -938,11 +916,6 @@ void Menu::motionNotifyEvent(XMotionEvent &me) { | |||
938 | 916 | ||
939 | if (! m_moving) { | 917 | if (! m_moving) { |
940 | // if not m_moving: start m_moving operation | 918 | // if not m_moving: start m_moving operation |
941 | if (m_parent && (! m_torn)) { | ||
942 | m_parent->m_which_sub = -1; | ||
943 | m_parent->clearItem(m_parent->m_which_sub); // clear | ||
944 | } | ||
945 | |||
946 | m_moving = m_torn = true; | 919 | m_moving = m_torn = true; |
947 | // clear current highlighted item | 920 | // clear current highlighted item |
948 | clearItem(m_active_index); | 921 | clearItem(m_active_index); |
@@ -962,7 +935,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) { | |||
962 | i = (me.y / theme().itemHeight()), | 935 | i = (me.y / theme().itemHeight()), |
963 | w = (sbl * menu.persub) + i; | 936 | w = (sbl * menu.persub) + i; |
964 | 937 | ||
965 | if (w == m_active_index) | 938 | if (w == m_active_index || !validIndex(w)) |
966 | return; | 939 | return; |
967 | 940 | ||
968 | // if another menu is focused, change focus to this one, so arrow keys | 941 | // if another menu is focused, change focus to this one, so arrow keys |
@@ -970,68 +943,36 @@ void Menu::motionNotifyEvent(XMotionEvent &me) { | |||
970 | if (s_focused != this && s_focused != 0) | 943 | if (s_focused != this && s_focused != 0) |
971 | grabInputFocus(); | 944 | grabInputFocus(); |
972 | 945 | ||
973 | if (validIndex(m_active_index) && w != m_active_index) { | ||
974 | int old_active_index = m_active_index; | ||
975 | m_active_index = -1; | ||
976 | MenuItem *item = menuitems[old_active_index]; | ||
977 | |||
978 | if (item != 0) { | ||
979 | |||
980 | clearItem(old_active_index); | ||
981 | |||
982 | if (item->submenu()) { | ||
983 | if (item->submenu()->isVisible() && | ||
984 | !item->submenu()->isTorn()) { | ||
985 | // setup hide timer for submenu | ||
986 | item->submenu()->startHide(); | ||
987 | m_which_sub = -1; | ||
988 | } | ||
989 | } | ||
990 | |||
991 | } | ||
992 | |||
993 | } | ||
994 | |||
995 | |||
996 | m_which_press = i; | ||
997 | m_which_sbl = sbl; | ||
998 | |||
999 | m_active_index = -1; | ||
1000 | |||
1001 | if (!validIndex(w)) | ||
1002 | return; | ||
1003 | |||
1004 | |||
1005 | MenuItem *itmp = menuitems[w]; | 946 | MenuItem *itmp = menuitems[w]; |
1006 | |||
1007 | m_active_index = w; | ||
1008 | |||
1009 | if (itmp == 0) | 947 | if (itmp == 0) |
1010 | return; | 948 | return; |
1011 | 949 | ||
1012 | if (itmp->submenu()) { | 950 | if (itmp->isEnabled()) { |
1013 | // if submenu, | 951 | int old = m_active_index; |
1014 | // draw item highlighted and | 952 | m_active_index = w; |
1015 | // start submenu open delay | ||
1016 | |||
1017 | clearItem(w); | 953 | clearItem(w); |
954 | clearItem(old); | ||
1018 | 955 | ||
1019 | if (theme().menuMode() == MenuTheme::DELAY_OPEN) { | 956 | MenuItem *item = validIndex(m_which_sub) ? menuitems[m_which_sub] : 0; |
1020 | // setup show menu timer | 957 | if (item != 0 && item->submenu() && item->submenu()->isVisible() && |
1021 | timeval timeout; | 958 | !item->submenu()->isTorn()) { |
1022 | timeout.tv_sec = 0; | 959 | // setup hide timer for submenu |
1023 | timeout.tv_usec = theme().delayOpen() * 1000; // transformed to usec | 960 | item->submenu()->startHide(); |
1024 | m_submenu_timer.setTimeout(timeout); | ||
1025 | m_submenu_timer.start(); | ||
1026 | } | 961 | } |
1027 | 962 | ||
963 | } | ||
964 | |||
965 | if (itmp->submenu() && theme().menuMode() == MenuTheme::DELAY_OPEN) { | ||
966 | // start submenu open delay | ||
967 | timeval timeout; | ||
968 | timeout.tv_sec = 0; | ||
969 | timeout.tv_usec = theme().delayOpen() * 1000; // transformed to usec | ||
970 | m_submenu_timer.setTimeout(timeout); | ||
971 | m_submenu_timer.start(); | ||
1028 | } else if (isItemSelectable(w)){ | 972 | } else if (isItemSelectable(w)){ |
1029 | // else normal menu item | 973 | // else normal menu item |
1030 | // draw highlighted | 974 | // draw highlighted |
1031 | m_submenu_timer.stop(); | 975 | m_submenu_timer.stop(); |
1032 | if (itmp->isEnabled()) { | ||
1033 | clearItem(w); | ||
1034 | } | ||
1035 | } | 976 | } |
1036 | 977 | ||
1037 | } | 978 | } |
@@ -1099,13 +1040,12 @@ void Menu::keyPressEvent(XKeyEvent &event) { | |||
1099 | break; | 1040 | break; |
1100 | case XK_Return: | 1041 | case XK_Return: |
1101 | // send fake button 1 click | 1042 | // send fake button 1 click |
1102 | if (validIndex(m_which_press) && | 1043 | if (validIndex(m_active_index) && |
1103 | isItemEnabled(m_which_press)) { | 1044 | isItemEnabled(m_active_index)) { |
1104 | if (event.state & ShiftMask) | 1045 | if (event.state & ShiftMask) |
1105 | menuitems[m_which_press]->click(3, event.time); | 1046 | menuitems[m_active_index]->click(3, event.time); |
1106 | else | 1047 | else |
1107 | menuitems[m_which_press]->click(1, event.time); | 1048 | menuitems[m_active_index]->click(1, event.time); |
1108 | itemSelected(1, m_which_press); | ||
1109 | m_need_update = true; | 1049 | m_need_update = true; |
1110 | updateMenu(); | 1050 | updateMenu(); |
1111 | } | 1051 | } |
@@ -1143,12 +1083,9 @@ void Menu::reconfigure() { | |||
1143 | 1083 | ||
1144 | void Menu::openSubmenu() { | 1084 | void Menu::openSubmenu() { |
1145 | 1085 | ||
1146 | if (!isVisible() || ! validIndex(m_which_press) || | 1086 | int item = m_active_index; |
1147 | ! validIndex(m_which_sbl)) | 1087 | if (!isVisible() || !validIndex(item) || !menuitems[item]->isEnabled() || |
1148 | return; | 1088 | s_focused != this && s_focused && s_focused->isVisible()) |
1149 | |||
1150 | int item = m_which_sbl * menu.persub + m_which_press; | ||
1151 | if (!validIndex(item) || !menuitems[item]->isEnabled()) | ||
1152 | return; | 1089 | return; |
1153 | 1090 | ||
1154 | clearItem(item); | 1091 | clearItem(item); |
diff --git a/src/FbTk/Menu.hh b/src/FbTk/Menu.hh index 94a1e6f..43b77a1 100644 --- a/src/FbTk/Menu.hh +++ b/src/FbTk/Menu.hh | |||
@@ -88,9 +88,9 @@ public: | |||
88 | /// lower this window | 88 | /// lower this window |
89 | virtual void lower(); | 89 | virtual void lower(); |
90 | /// select next item | 90 | /// select next item |
91 | void nextItem(); | 91 | void nextItem(int failsafe = -1); |
92 | /// select previous item | 92 | /// select previous item |
93 | void prevItem(); | 93 | void prevItem(int failsafe = -1); |
94 | void enterSubmenu(); | 94 | void enterSubmenu(); |
95 | void enterParent(); | 95 | void enterParent(); |
96 | 96 | ||
@@ -152,9 +152,7 @@ public: | |||
152 | inline unsigned int height() const { return menu.window.height(); } | 152 | inline unsigned int height() const { return menu.window.height(); } |
153 | inline size_t numberOfItems() const { return menuitems.size(); } | 153 | inline size_t numberOfItems() const { return menuitems.size(); } |
154 | inline int currentSubmenu() const { return m_which_sub; } | 154 | inline int currentSubmenu() const { return m_which_sub; } |
155 | #ifdef NOT_USED | 155 | |
156 | bool hasSubmenu(unsigned int index) const; | ||
157 | #endif | ||
158 | bool isItemSelected(unsigned int index) const; | 156 | bool isItemSelected(unsigned int index) const; |
159 | bool isItemEnabled(unsigned int index) const; | 157 | bool isItemEnabled(unsigned int index) const; |
160 | bool isItemSelectable(unsigned int index) const; | 158 | bool isItemSelectable(unsigned int index) const; |
@@ -184,7 +182,6 @@ protected: | |||
184 | titleWindow().raise(); | 182 | titleWindow().raise(); |
185 | } | 183 | } |
186 | 184 | ||
187 | virtual void itemSelected(int button, unsigned int index) { } | ||
188 | // renders item onto pm | 185 | // renders item onto pm |
189 | int drawItem(FbDrawable &pm, unsigned int index, | 186 | int drawItem(FbDrawable &pm, unsigned int index, |
190 | bool highlight = false, | 187 | bool highlight = false, |
@@ -220,7 +217,7 @@ private: | |||
220 | bool m_internal_menu; ///< whether we should destroy this menu or if it's managed somewhere else | 217 | bool m_internal_menu; ///< whether we should destroy this menu or if it's managed somewhere else |
221 | bool m_title_vis; ///< title visibility | 218 | bool m_title_vis; ///< title visibility |
222 | 219 | ||
223 | int m_which_sub, m_which_press, m_which_sbl; | 220 | int m_which_sub; |
224 | Alignment m_alignment; | 221 | Alignment m_alignment; |
225 | 222 | ||
226 | struct _menu { | 223 | struct _menu { |