aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk')
-rw-r--r--src/FbTk/Menu.cc219
-rw-r--r--src/FbTk/Menu.hh11
2 files changed, 82 insertions, 148 deletions
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
276void Menu::nextItem() { 274void 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
314void Menu::prevItem() { 310void 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
350void Menu::enterSubmenu() { 345void 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
755bool 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
766int Menu::drawItem(FbDrawable &drawable, unsigned int index, 747int 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
1144void Menu::openSubmenu() { 1084void 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 {