aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk
diff options
context:
space:
mode:
authorMathias Gumz <akira@fluxbox.org>2015-01-15 13:24:46 (GMT)
committerMathias Gumz <akira@fluxbox.org>2015-01-15 13:25:05 (GMT)
commit8387742c8860694777f7c2c62da0a90c9e836988 (patch)
treee5bd5a50c3e033ea73a9339474750287d06aeb3f /src/FbTk
parentb4cd45549013e8b45f95bf3e123cd14684948e91 (diff)
downloadfluxbox-8387742c8860694777f7c2c62da0a90c9e836988.zip
fluxbox-8387742c8860694777f7c2c62da0a90c9e836988.tar.bz2
Refactor menu code: be more explicit and compact
This commit is a preparation step for some menu cleanup ahead. To make it easier to understand which types of MenuItems are added where and when, I converted the overloaded FbTk::Menu::insert() functions into explicit ones (Menu::insertSubmenu(), Menu::insertItem(), etc. ). This makes it possible to just grep for 'insertSubmenu()'. Side effect this commit: it trims down the very verbose creation of menu items in regards to how the labels are created. Minor: FbTk::Menu::shown and FbTk::Menu::s_focused are moved out of the class.
Diffstat (limited to 'src/FbTk')
-rw-r--r--src/FbTk/Menu.cc212
-rw-r--r--src/FbTk/Menu.hh38
2 files changed, 117 insertions, 133 deletions
diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc
index cb58685..4dbb48c 100644
--- a/src/FbTk/Menu.cc
+++ b/src/FbTk/Menu.cc
@@ -85,9 +85,11 @@ void renderMenuPixmap(Pixmap& pm, FbTk::FbWindow* win, int width, int height, co
85 85
86namespace FbTk { 86namespace FbTk {
87 87
88Menu *Menu::shown = 0; 88Menu* s_shown = 0; // if there's a menu open at all
89Menu* s_focused = 0; // holds currently focused menu
89 90
90Menu *Menu::s_focused = 0; 91Menu* Menu::shownMenu() { return s_shown; }
92Menu* Menu::focused() { return s_focused; }
91 93
92Menu::Menu(FbTk::ThemeProxy<MenuTheme> &tm, ImageControl &imgctrl): 94Menu::Menu(FbTk::ThemeProxy<MenuTheme> &tm, ImageControl &imgctrl):
93 m_theme(tm), 95 m_theme(tm),
@@ -101,8 +103,8 @@ Menu::Menu(FbTk::ThemeProxy<MenuTheme> &tm, ImageControl &imgctrl):
101 m_active_index(-1), 103 m_active_index(-1),
102 m_shape(0), 104 m_shape(0),
103 m_need_update(true) { 105 m_need_update(true) {
104 // setup timers
105 106
107 // setup timers
106 RefCount<Command<void> > show_cmd(new SimpleCommand<Menu>(*this, &Menu::openSubmenu)); 108 RefCount<Command<void> > show_cmd(new SimpleCommand<Menu>(*this, &Menu::openSubmenu));
107 m_submenu_timer.setCommand(show_cmd); 109 m_submenu_timer.setCommand(show_cmd);
108 m_submenu_timer.fireOnce(true); 110 m_submenu_timer.fireOnce(true);
@@ -192,8 +194,8 @@ Menu::~Menu() {
192 194
193 m_window.hide(); 195 m_window.hide();
194 196
195 if (shown && shown->window() == window()) 197 if (s_shown && s_shown->window() == window())
196 shown = 0; 198 s_shown = 0;
197 199
198 removeAll(); 200 removeAll();
199 201
@@ -210,59 +212,61 @@ Menu::~Menu() {
210 s_focused = 0; 212 s_focused = 0;
211} 213}
212 214
213int Menu::insert(const FbString &label, RefCount<Command<void> > &cmd, int pos) { 215int Menu::insertCommand(const FbString &label, RefCount<Command<void> > &cmd, int pos) {
214 return insert(new MenuItem(label, cmd, this), pos); 216 return insertItem(new MenuItem(label, cmd, this), pos);
215} 217}
216 218
217int Menu::insert(const FbString &label, int pos) { 219int Menu::insert(const FbString &label, int pos) {
218 return insert(new MenuItem(label, *this), pos); 220 return insertItem(new MenuItem(label, *this), pos);
219} 221}
220 222
221int Menu::insert(const FbString &label, Menu *submenu, int pos) { 223int Menu::insertSubmenu(const FbString &label, Menu *submenu, int pos) {
222 return insert(new MenuItem(label, submenu, this), pos); 224 return insertItem(new MenuItem(label, submenu, this), pos);
223} 225}
224 226
225int Menu::insert(MenuItem *item, int pos) { 227int Menu::insertItem(MenuItem *item, int pos) {
226 if (item == 0) 228 if (item == 0)
227 return menuitems.size(); 229 return m_items.size();
228 if (pos == -1) { 230 if (pos == -1) {
229 item->setIndex(menuitems.size()); 231 item->setIndex(m_items.size());
230 menuitems.push_back(item); 232 m_items.push_back(item);
231 } else { 233 } else {
232 menuitems.insert(menuitems.begin() + pos, item); 234 m_items.insert(m_items.begin() + pos, item);
233 fixMenuItemIndices(); 235 fixMenuItemIndices();
234 if (m_active_index >= pos) 236 if (m_active_index >= pos)
235 m_active_index++; 237 m_active_index++;
236 } 238 }
237 m_need_update = true; // we need to redraw the menu 239 m_need_update = true; // we need to redraw the menu
238 return menuitems.size(); 240 return m_items.size();
239} 241}
240 242
241void Menu::fixMenuItemIndices() { 243void Menu::fixMenuItemIndices() {
242 for (size_t i = 0; i < menuitems.size(); i++) 244 for (size_t i = 0; i < m_items.size(); i++)
243 menuitems[i]->setIndex(i); 245 m_items[i]->setIndex(i);
244} 246}
245 247
246int Menu::remove(unsigned int index) { 248int Menu::remove(unsigned int index) {
247 if (index >= menuitems.size()) { 249 if (index >= m_items.size()) {
248#ifdef DEBUG 250#ifdef DEBUG
249 cerr << __FILE__ << "(" << __LINE__ << ") Bad index (" << index 251 cerr << __FILE__ << "(" << __LINE__ << ") Bad index (" << index
250 << ") given to Menu::remove()" 252 << ") given to Menu::remove()"
251 << " -- should be between 0 and " << menuitems.size()-1 253 << " -- should be between 0 and " << m_items.size()-1
252 << " inclusive." << endl; 254 << " inclusive." << endl;
253#endif // DEBUG 255#endif // DEBUG
254 return -1; 256 return -1;
255 } 257 }
256 258
257 Menuitems::iterator it = menuitems.begin() + index; 259 Menuitems::iterator it = m_items.begin() + index;
258 MenuItem *item = (*it); 260 MenuItem *item = (*it);
259 261
260 if (item) { 262 if (item) {
261 if (!m_matches.empty()) 263 if (!m_matches.empty())
262 resetTypeAhead(); 264 resetTypeAhead();
263 menuitems.erase(it); 265
266 m_items.erase(it);
267
264 // avoid O(n^2) algorithm with removeAll() 268 // avoid O(n^2) algorithm with removeAll()
265 if (index != menuitems.size()) 269 if (index != m_items.size())
266 fixMenuItemIndices(); 270 fixMenuItemIndices();
267 271
268 if (item->submenu() != 0) { 272 if (item->submenu() != 0) {
@@ -291,12 +295,12 @@ int Menu::remove(unsigned int index) {
291 295
292 m_need_update = true; // we need to redraw the menu 296 m_need_update = true; // we need to redraw the menu
293 297
294 return menuitems.size(); 298 return m_items.size();
295} 299}
296 300
297void Menu::removeAll() { 301void Menu::removeAll() {
298 while (!menuitems.empty()) 302 while (!m_items.empty())
299 remove(menuitems.size()-1); 303 remove(m_items.size()-1);
300} 304}
301 305
302void Menu::raise() { 306void Menu::raise() {
@@ -308,26 +312,24 @@ void Menu::lower() {
308} 312}
309 313
310void Menu::cycleItems(bool reverse) { 314void Menu::cycleItems(bool reverse) {
311 Menuitems vec; 315 Menuitems& items = m_items;
312 if (m_type_ahead.stringSize()) 316 if (m_type_ahead.stringSize())
313 vec = m_matches; 317 items = m_matches;
314 else
315 vec = menuitems;
316 318
317 if (vec.size() < 1) 319 if (items.empty())
318 return; 320 return;
319 321
320 // find the next item to select 322 // find the next item to select
321 // this algorithm assumes menuitems are sorted properly 323 // this algorithm assumes menuitems are sorted properly
322 int new_index = -1; 324 int new_index = -1;
323 bool passed = !validIndex(m_active_index); 325 bool passed = !validIndex(m_active_index);
324 for (size_t i = 0; i < vec.size(); i++) { 326 for (size_t i = 0; i < items.size(); i++) {
325 if (!isItemSelectable(vec[i]->getIndex()) || 327 if (!isItemSelectable(items[i]->getIndex()) ||
326 vec[i]->getIndex() == m_active_index) 328 items[i]->getIndex() == m_active_index)
327 continue; 329 continue;
328 330
329 // determine whether or not we've passed the active index 331 // determine whether or not we've passed the active index
330 if (!passed && vec[i]->getIndex() > m_active_index) { 332 if (!passed && items[i]->getIndex() > m_active_index) {
331 if (reverse && new_index != -1) 333 if (reverse && new_index != -1)
332 break; 334 break;
333 passed = true; 335 passed = true;
@@ -335,10 +337,10 @@ void Menu::cycleItems(bool reverse) {
335 337
336 // decide if we want to keep this item 338 // decide if we want to keep this item
337 if (passed && !reverse) { 339 if (passed && !reverse) {
338 new_index = vec[i]->getIndex(); 340 new_index = items[i]->getIndex();
339 break; 341 break;
340 } else if (reverse || new_index == -1) 342 } else if (reverse || new_index == -1)
341 new_index = vec[i]->getIndex(); 343 new_index = items[i]->getIndex();
342 } 344 }
343 345
344 if (new_index != -1) 346 if (new_index != -1)
@@ -350,11 +352,11 @@ void Menu::setActiveIndex(int new_index) {
350 int old_active_index = m_active_index; 352 int old_active_index = m_active_index;
351 m_active_index = new_index; 353 m_active_index = new_index;
352 if (validIndex(old_active_index) && 354 if (validIndex(old_active_index) &&
353 menuitems[old_active_index] != 0) { 355 m_items[old_active_index] != 0) {
354 if (menuitems[old_active_index]->submenu()) { 356 if (m_items[old_active_index]->submenu()) {
355 // we need to do this explicitly on the m_window 357 // we need to do this explicitly on the m_window
356 // since it might hide the parent if we use Menu::hide 358 // since it might hide the parent if we use Menu::hide
357 menuitems[old_active_index]->submenu()->internal_hide(); 359 m_items[old_active_index]->submenu()->internal_hide();
358 } 360 }
359 clearItem(old_active_index); 361 clearItem(old_active_index);
360 } 362 }
@@ -365,11 +367,11 @@ void Menu::enterSubmenu() {
365 if (!validIndex(m_active_index)) 367 if (!validIndex(m_active_index))
366 return; 368 return;
367 369
368 Menu *submenu = menuitems[m_active_index]->submenu(); 370 Menu *submenu = m_items[m_active_index]->submenu();
369 if (submenu == 0) 371 if (submenu == 0)
370 return; 372 return;
371 373
372 if (submenu->menuitems.empty()) 374 if (submenu->m_items.empty())
373 return; 375 return;
374 376
375 drawSubmenu(m_active_index); 377 drawSubmenu(m_active_index);
@@ -393,15 +395,15 @@ void Menu::updateMenu() {
393 } else 395 } else
394 m_item_w = 1; 396 m_item_w = 1;
395 397
396 if (validIndex(m_active_index) && !menuitems[m_active_index]->isEnabled()) { 398 if (validIndex(m_active_index) && !m_items[m_active_index]->isEnabled()) {
397 // find the nearest enabled menuitem and highlight it 399 // find the nearest enabled menuitem and highlight it
398 for (size_t i = 1; i < menuitems.size(); i++) { 400 for (size_t i = 1; i < m_items.size(); i++) {
399 if (validIndex(m_active_index + i) && 401 if (validIndex(m_active_index + i) &&
400 menuitems[m_active_index + i]->isEnabled()) { 402 m_items[m_active_index + i]->isEnabled()) {
401 m_active_index += i; 403 m_active_index += i;
402 break; 404 break;
403 } else if (validIndex(m_active_index - i) && 405 } else if (validIndex(m_active_index - i) &&
404 menuitems[m_active_index - i]->isEnabled()) { 406 m_items[m_active_index - i]->isEnabled()) {
405 m_active_index -= i; 407 m_active_index -= i;
406 break; 408 break;
407 } 409 }
@@ -409,8 +411,8 @@ void Menu::updateMenu() {
409 } 411 }
410 412
411 unsigned int ii = 0; 413 unsigned int ii = 0;
412 Menuitems::iterator it = menuitems.begin(); 414 Menuitems::iterator it = m_items.begin();
413 Menuitems::iterator it_end = menuitems.end(); 415 Menuitems::iterator it_end = m_items.end();
414 for (; it != it_end; ++it) { 416 for (; it != it_end; ++it) {
415 ii = (*it)->width(theme()); 417 ii = (*it)->width(theme());
416 m_item_w = (ii > m_item_w ? ii : m_item_w); 418 m_item_w = (ii > m_item_w ? ii : m_item_w);
@@ -419,10 +421,10 @@ void Menu::updateMenu() {
419 if (m_item_w < 1) 421 if (m_item_w < 1)
420 m_item_w = 1; 422 m_item_w = 1;
421 423
422 if (!menuitems.empty()) { 424 if (!m_items.empty()) {
423 m_columns = 1; 425 m_columns = 1;
424 426
425 while (theme()->itemHeight() * (menuitems.size() + 1) / m_columns + 427 while (theme()->itemHeight() * (m_items.size() + 1) / m_columns +
426 theme()->titleHeight() + theme()->borderWidth() > m_screen_height) { 428 theme()->titleHeight() + theme()->borderWidth() > m_screen_height) {
427 m_columns++; 429 m_columns++;
428 } 430 }
@@ -430,8 +432,8 @@ void Menu::updateMenu() {
430 if (m_columns < m_min_columns) 432 if (m_columns < m_min_columns)
431 m_columns = m_min_columns; 433 m_columns = m_min_columns;
432 434
433 m_rows_per_column = menuitems.size() / m_columns; 435 m_rows_per_column = m_items.size() / m_columns;
434 if (menuitems.size() % m_columns) m_rows_per_column++; 436 if (m_items.size() % m_columns) m_rows_per_column++;
435 } else { 437 } else {
436 m_columns = 0; 438 m_columns = 0;
437 m_rows_per_column = 0; 439 m_rows_per_column = 0;
@@ -522,7 +524,7 @@ void Menu::updateMenu() {
522 524
523void Menu::show() { 525void Menu::show() {
524 526
525 if (isVisible() || menuitems.empty()) 527 if (isVisible() || m_items.empty())
526 return; 528 return;
527 529
528 m_visible = true; 530 m_visible = true;
@@ -537,9 +539,9 @@ void Menu::show() {
537 m_window.show(); 539 m_window.show();
538 raise(); 540 raise();
539 541
540 if (shown && shown != this) 542 if (s_shown && s_shown != this)
541 shown->hide(); 543 s_shown->hide();
542 shown = this; 544 s_shown = this;
543 545
544} 546}
545 547
@@ -565,8 +567,8 @@ void Menu::hide(bool force) {
565void Menu::grabInputFocus() { 567void Menu::grabInputFocus() {
566 // if there's a submenu open, focus it instead 568 // if there's a submenu open, focus it instead
567 if (validIndex(m_which_sub) && 569 if (validIndex(m_which_sub) &&
568 menuitems[m_which_sub]->submenu()->isVisible()) { 570 m_items[m_which_sub]->submenu()->isVisible()) {
569 menuitems[m_which_sub]->submenu()->grabInputFocus(); 571 m_items[m_which_sub]->submenu()->grabInputFocus();
570 return; 572 return;
571 } 573 }
572 574
@@ -582,14 +584,14 @@ void Menu::clearWindow() {
582 m_frame.clear(); 584 m_frame.clear();
583 585
584 // clear foreground bits of frame items 586 // clear foreground bits of frame items
585 for (size_t i = 0; i < menuitems.size(); i++) { 587 for (size_t i = 0; i < m_items.size(); i++) {
586 clearItem(i, false); // no clear 588 clearItem(i, false); // no clear
587 } 589 }
588 m_shape->update(); 590 m_shape->update();
589} 591}
590 592
591void Menu::redrawFrame(FbDrawable &drawable) { 593void Menu::redrawFrame(FbDrawable &drawable) {
592 for (size_t i = 0; i < menuitems.size(); i++) { 594 for (size_t i = 0; i < m_items.size(); i++) {
593 drawItem(drawable, i); 595 drawItem(drawable, i);
594 } 596 }
595 597
@@ -598,7 +600,7 @@ void Menu::redrawFrame(FbDrawable &drawable) {
598void Menu::internal_hide(bool first) { 600void Menu::internal_hide(bool first) {
599 601
600 if (validIndex(m_which_sub)) { 602 if (validIndex(m_which_sub)) {
601 MenuItem *tmp = menuitems[m_which_sub]; 603 MenuItem *tmp = m_items[m_which_sub];
602 if (tmp && tmp->submenu() && tmp->submenu()->isVisible()) 604 if (tmp && tmp->submenu() && tmp->submenu()->isVisible())
603 tmp->submenu()->internal_hide(false); 605 tmp->submenu()->internal_hide(false);
604 } 606 }
@@ -609,11 +611,11 @@ void Menu::internal_hide(bool first) {
609 m_active_index = -1; 611 m_active_index = -1;
610 clearItem(old); // clear old area from highlight 612 clearItem(old); // clear old area from highlight
611 613
612 if (shown == this) { 614 if (s_shown == this) {
613 if (m_parent && m_parent->isVisible()) 615 if (m_parent && m_parent->isVisible())
614 shown = m_parent; 616 s_shown = m_parent;
615 else 617 else
616 shown = (Menu *) 0; 618 s_shown = 0;
617 } 619 }
618 620
619 m_torn = m_visible = m_closing = false; 621 m_torn = m_visible = m_closing = false;
@@ -644,7 +646,7 @@ void Menu::move(int x, int y) {
644 clearWindow(); 646 clearWindow();
645 647
646 if (validIndex(m_which_sub) && 648 if (validIndex(m_which_sub) &&
647 menuitems[m_which_sub]->submenu()->isVisible()) 649 m_items[m_which_sub]->submenu()->isVisible())
648 drawSubmenu(m_which_sub); 650 drawSubmenu(m_which_sub);
649} 651}
650 652
@@ -676,17 +678,17 @@ void Menu::redrawTitle(FbDrawable &drawable) {
676 678
677void Menu::drawSubmenu(unsigned int index) { 679void Menu::drawSubmenu(unsigned int index) {
678 if (validIndex(m_which_sub) && static_cast<unsigned int>(m_which_sub) != index) { 680 if (validIndex(m_which_sub) && static_cast<unsigned int>(m_which_sub) != index) {
679 MenuItem *itmp = menuitems[m_which_sub]; 681 MenuItem *itmp = m_items[m_which_sub];
680 682
681 if (! itmp->submenu()->isTorn()) 683 if (! itmp->submenu()->isTorn())
682 itmp->submenu()->internal_hide(); 684 itmp->submenu()->internal_hide();
683 } 685 }
684 686
685 if (index >= menuitems.size()) 687 if (index >= m_items.size())
686 return; 688 return;
687 689
688 690
689 MenuItem *item = menuitems[index]; 691 MenuItem *item = m_items[index];
690 if (item->submenu() && isVisible() && (! item->submenu()->isTorn()) && 692 if (item->submenu() && isVisible() && (! item->submenu()->isTorn()) &&
691 item->isEnabled()) { 693 item->isEnabled()) {
692 694
@@ -750,7 +752,7 @@ void Menu::drawSubmenu(unsigned int index) {
750 clearItem(index); 752 clearItem(index);
751 753
752 if (! item->submenu()->isVisible() && item->submenu()->numberOfItems() > 0) { 754 if (! item->submenu()->isVisible() && item->submenu()->numberOfItems() > 0) {
753 shown = item->submenu(); 755 s_shown = item->submenu();
754 item->showSubmenu(); 756 item->showSubmenu();
755 item->submenu()->raise(); 757 item->submenu()->raise();
756 } 758 }
@@ -764,11 +766,11 @@ void Menu::drawSubmenu(unsigned int index) {
764int Menu::drawItem(FbDrawable &drawable, unsigned int index, 766int Menu::drawItem(FbDrawable &drawable, unsigned int index,
765 bool highlight, bool exclusive_drawable) { 767 bool highlight, bool exclusive_drawable) {
766 768
767 if (index >= menuitems.size() || menuitems.empty() || 769 if (index >= m_items.size() || m_items.empty() ||
768 m_rows_per_column == 0) 770 m_rows_per_column == 0)
769 return 0; 771 return 0;
770 772
771 MenuItem *item = menuitems[index]; 773 MenuItem *item = m_items[index];
772 if (! item) return 0; 774 if (! item) return 0;
773 775
774 // ensure we do not divide by 0 and thus cause a SIGFPE 776 // ensure we do not divide by 0 and thus cause a SIGFPE
@@ -804,7 +806,7 @@ void Menu::setLabel(const FbTk::BiDiString &labelstr) {
804 806
805 807
806void Menu::setItemSelected(unsigned int index, bool sel) { 808void Menu::setItemSelected(unsigned int index, bool sel) {
807 if (index >= menuitems.size()) return; 809 if (index >= m_items.size()) return;
808 810
809 MenuItem *item = find(index); 811 MenuItem *item = find(index);
810 if (! item) return; 812 if (! item) return;
@@ -814,7 +816,7 @@ void Menu::setItemSelected(unsigned int index, bool sel) {
814 816
815 817
816bool Menu::isItemSelected(unsigned int index) const{ 818bool Menu::isItemSelected(unsigned int index) const{
817 if (index >= menuitems.size()) return false; 819 if (index >= m_items.size()) return false;
818 820
819 const MenuItem *item = find(index); 821 const MenuItem *item = find(index);
820 if (!item) 822 if (!item)
@@ -825,7 +827,7 @@ bool Menu::isItemSelected(unsigned int index) const{
825 827
826 828
827void Menu::setItemEnabled(unsigned int index, bool enable) { 829void Menu::setItemEnabled(unsigned int index, bool enable) {
828 if (index >= menuitems.size()) return; 830 if (index >= m_items.size()) return;
829 831
830 MenuItem *item = find(index); 832 MenuItem *item = find(index);
831 if (! item) return; 833 if (! item) return;
@@ -835,7 +837,7 @@ void Menu::setItemEnabled(unsigned int index, bool enable) {
835 837
836 838
837bool Menu::isItemEnabled(unsigned int index) const { 839bool Menu::isItemEnabled(unsigned int index) const {
838 if (index >= menuitems.size()) return false; 840 if (index >= m_items.size()) return false;
839 841
840 const MenuItem *item = find(index); 842 const MenuItem *item = find(index);
841 if (!item) 843 if (!item)
@@ -846,7 +848,7 @@ bool Menu::isItemEnabled(unsigned int index) const {
846 848
847bool Menu::isItemSelectable(unsigned int index) const { 849bool Menu::isItemSelectable(unsigned int index) const {
848 850
849 if (index >= menuitems.size()) return false; 851 if (index >= m_items.size()) return false;
850 852
851 const MenuItem *item = find(index); 853 const MenuItem *item = find(index);
852 return (!item || !item->isEnabled()) ? false : true; 854 return (!item || !item->isEnabled()) ? false : true;
@@ -864,8 +866,8 @@ void Menu::handleEvent(XEvent &event) {
864 s_focused = this; 866 s_focused = this;
865 // if there's a submenu open, focus it instead 867 // if there's a submenu open, focus it instead
866 if (validIndex(m_which_sub) && 868 if (validIndex(m_which_sub) &&
867 menuitems[m_which_sub]->submenu()->isVisible()) 869 m_items[m_which_sub]->submenu()->isVisible())
868 menuitems[m_which_sub]->submenu()->grabInputFocus(); 870 m_items[m_which_sub]->submenu()->grabInputFocus();
869 } 871 }
870} 872}
871 873
@@ -883,7 +885,7 @@ void Menu::buttonPressEvent(XButtonEvent &be) {
883 int w = (column * m_rows_per_column) + i; 885 int w = (column * m_rows_per_column) + i;
884 886
885 if (validIndex(w) && isItemSelectable(static_cast<unsigned int>(w))) { 887 if (validIndex(w) && isItemSelectable(static_cast<unsigned int>(w))) {
886 MenuItem *item = menuitems[w]; 888 MenuItem *item = m_items[w];
887 889
888 if (item->submenu()) { 890 if (item->submenu()) {
889 if (!item->submenu()->isVisible()) 891 if (!item->submenu()->isVisible())
@@ -903,7 +905,7 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
903 m_moving = false; 905 m_moving = false;
904 906
905 if (validIndex(m_which_sub) && 907 if (validIndex(m_which_sub) &&
906 menuitems[m_which_sub]->submenu()->isVisible()) 908 m_items[m_which_sub]->submenu()->isVisible())
907 drawSubmenu(m_which_sub); 909 drawSubmenu(m_which_sub);
908 910
909 if (alpha() < 255) { 911 if (alpha() < 255) {
@@ -929,7 +931,7 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
929 if (m_active_index == w && isItemEnabled(w) && 931 if (m_active_index == w && isItemEnabled(w) &&
930 re.x > ix && re.x < (signed) (ix + m_item_w) && 932 re.x > ix && re.x < (signed) (ix + m_item_w) &&
931 re.y > iy && re.y < (signed) (iy + theme()->itemHeight())) { 933 re.y > iy && re.y < (signed) (iy + theme()->itemHeight())) {
932 menuitems[w]->click(re.button, re.time, re.state); 934 m_items[w]->click(re.button, re.time, re.state);
933 } else { 935 } else {
934 int old = m_active_index; 936 int old = m_active_index;
935 m_active_index = w; 937 m_active_index = w;
@@ -955,7 +957,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
955 clearItem(m_active_index); 957 clearItem(m_active_index);
956 958
957 if (validIndex(m_which_sub) && 959 if (validIndex(m_which_sub) &&
958 menuitems[m_which_sub]->submenu()->isVisible()) 960 m_items[m_which_sub]->submenu()->isVisible())
959 drawSubmenu(m_which_sub); 961 drawSubmenu(m_which_sub);
960 } else { 962 } else {
961 // we dont call ::move here 'cause we dont want to update transparency 963 // we dont call ::move here 'cause we dont want to update transparency
@@ -977,7 +979,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
977 if (s_focused != this && s_focused != 0) 979 if (s_focused != this && s_focused != 0)
978 grabInputFocus(); 980 grabInputFocus();
979 981
980 MenuItem *itmp = menuitems[w]; 982 MenuItem *itmp = m_items[w];
981 if (itmp == 0) 983 if (itmp == 0)
982 return; 984 return;
983 985
@@ -987,7 +989,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
987 clearItem(w); 989 clearItem(w);
988 clearItem(old); 990 clearItem(old);
989 991
990 MenuItem *item = validIndex(m_which_sub) ? menuitems[m_which_sub] : 0; 992 MenuItem *item = validIndex(m_which_sub) ? m_items[m_which_sub] : 0;
991 if (item != 0 && item->submenu() && item->submenu()->isVisible() && 993 if (item != 0 && item->submenu() && item->submenu()->isVisible() &&
992 !item->submenu()->isTorn()) { 994 !item->submenu()->isTorn()) {
993 // setup hide timer for submenu 995 // setup hide timer for submenu
@@ -1045,9 +1047,9 @@ void Menu::exposeEvent(XExposeEvent &ee) {
1045 // set the iterator to the first item in the column needing redrawing 1047 // set the iterator to the first item in the column needing redrawing
1046 int index = id + i * m_rows_per_column; 1048 int index = id + i * m_rows_per_column;
1047 1049
1048 if (index < static_cast<int>(menuitems.size()) && index >= 0) { 1050 if (index < static_cast<int>(m_items.size()) && index >= 0) {
1049 Menuitems::iterator it = menuitems.begin() + index; 1051 Menuitems::iterator it = m_items.begin() + index;
1050 Menuitems::iterator it_end = menuitems.end(); 1052 Menuitems::iterator it_end = m_items.end();
1051 for (ii = id; ii <= id_d && it != it_end; ++it, ii++) { 1053 for (ii = id; ii <= id_d && it != it_end; ++it, ii++) {
1052 int index = ii + (i * m_rows_per_column); 1054 int index = ii + (i * m_rows_per_column);
1053 // redraw the item 1055 // redraw the item
@@ -1119,7 +1121,7 @@ void Menu::keyPressEvent(XKeyEvent &event) {
1119 isItemEnabled(m_active_index)) { 1121 isItemEnabled(m_active_index)) {
1120 // send fake button click 1122 // send fake button click
1121 int button = (event.state & ShiftMask) ? 3 : 1; 1123 int button = (event.state & ShiftMask) ? 3 : 1;
1122 if (menuitems[m_active_index]->submenu() != 0 && button == 1) 1124 if (m_items[m_active_index]->submenu() != 0 && button == 1)
1123 enterSubmenu(); 1125 enterSubmenu();
1124 else { 1126 else {
1125 find(m_active_index)->click(button, event.time, event.state); 1127 find(m_active_index)->click(button, event.time, event.state);
@@ -1131,7 +1133,7 @@ void Menu::keyPressEvent(XKeyEvent &event) {
1131 case XK_Tab: 1133 case XK_Tab:
1132 case XK_ISO_Left_Tab: 1134 case XK_ISO_Left_Tab:
1133 if (validIndex(m_active_index) && isItemEnabled(m_active_index) && 1135 if (validIndex(m_active_index) && isItemEnabled(m_active_index) &&
1134 menuitems[m_active_index]->submenu() && m_matches.size() == 1) { 1136 m_items[m_active_index]->submenu() && m_matches.size() == 1) {
1135 enterSubmenu(); 1137 enterSubmenu();
1136 m_type_ahead.reset(); 1138 m_type_ahead.reset();
1137 } else { 1139 } else {
@@ -1156,12 +1158,12 @@ void Menu::leaveNotifyEvent(XCrossingEvent &ce) {
1156 m_closing = false; 1158 m_closing = false;
1157 // if there's a submenu open, highlight its index and stop hide 1159 // if there's a submenu open, highlight its index and stop hide
1158 if (validIndex(m_which_sub) && m_active_index != m_which_sub && 1160 if (validIndex(m_which_sub) && m_active_index != m_which_sub &&
1159 menuitems[m_which_sub]->submenu()->isVisible()) { 1161 m_items[m_which_sub]->submenu()->isVisible()) {
1160 int old = m_active_index; 1162 int old = m_active_index;
1161 m_active_index = m_which_sub; 1163 m_active_index = m_which_sub;
1162 clearItem(m_active_index); 1164 clearItem(m_active_index);
1163 clearItem(old); 1165 clearItem(old);
1164 menuitems[m_which_sub]->submenu()->stopHide(); 1166 m_items[m_which_sub]->submenu()->stopHide();
1165 } 1167 }
1166} 1168}
1167 1169
@@ -1194,17 +1196,17 @@ void Menu::reconfigure() {
1194void Menu::openSubmenu() { 1196void Menu::openSubmenu() {
1195 1197
1196 int item = m_active_index; 1198 int item = m_active_index;
1197 if (!isVisible() || !validIndex(item) || !menuitems[item]->isEnabled() || 1199 if (!isVisible() || !validIndex(item) || !m_items[item]->isEnabled() ||
1198 (s_focused != this && s_focused && s_focused->isVisible())) 1200 (s_focused != this && s_focused && s_focused->isVisible()))
1199 return; 1201 return;
1200 1202
1201 clearItem(item); 1203 clearItem(item);
1202 1204
1203 if (menuitems[item]->submenu() != 0) { 1205 if (m_items[item]->submenu() != 0) {
1204 // stop hide timer, so it doesnt hides the menu if we 1206 // stop hide timer, so it doesnt hides the menu if we
1205 // have the same submenu as the last shown submenu 1207 // have the same submenu as the last shown submenu
1206 // (window menu for clients inside workspacemenu for example) 1208 // (window menu for clients inside workspacemenu for example)
1207 menuitems[item]->submenu()->m_hide_timer.stop(); 1209 m_items[item]->submenu()->m_hide_timer.stop();
1208 drawSubmenu(item); 1210 drawSubmenu(item);
1209 } 1211 }
1210 1212
@@ -1228,15 +1230,15 @@ void Menu::themeReconfigured() {
1228 1230
1229 m_need_update = true; 1231 m_need_update = true;
1230 1232
1231 Menuitems::iterator it = menuitems.begin(); 1233 Menuitems::iterator it = m_items.begin();
1232 Menuitems::iterator it_end = menuitems.end(); 1234 Menuitems::iterator it_end = m_items.end();
1233 for (; it != it_end; ++it) { 1235 for (; it != it_end; ++it) {
1234 (*it)->updateTheme(theme()); 1236 (*it)->updateTheme(theme());
1235 } 1237 }
1236 reconfigure(); 1238 reconfigure();
1237} 1239}
1238 1240
1239void Menu::setScreen(int x, int y, int w, int h) { 1241void Menu::setScreen(int x, int y, unsigned int w, unsigned int h) {
1240 m_screen_x = x; 1242 m_screen_x = x;
1241 m_screen_y = y; 1243 m_screen_y = y;
1242 m_screen_width = w; 1244 m_screen_width = w;
@@ -1277,28 +1279,28 @@ void Menu::clearItem(int index, bool clear, int search_index) {
1277 int item_y = (row * item_h); 1279 int item_y = (row * item_h);
1278 bool highlight = (index == m_active_index && isItemSelectable(index)); 1280 bool highlight = (index == m_active_index && isItemSelectable(index));
1279 1281
1280 if (search_index < 0) 1282 if (search_index < 0) // need to underline the item
1281 // find if we need to underline the item
1282 search_index = std::find(m_matches.begin(), m_matches.end(), 1283 search_index = std::find(m_matches.begin(), m_matches.end(),
1283 find(index)) - m_matches.begin(); 1284 find(index)) - m_matches.begin();
1284 1285
1285 // don't highlight if moving, doesn't work with alpha on 1286 // don't highlight if moving, doesn't work with alpha on
1286 if (highlight && !m_moving) { 1287 if (highlight && !m_moving) {
1287 highlightItem(index); 1288 highlightItem(index);
1288 if (search_index < (int)m_matches.size()) 1289 if (search_index < static_cast<int>(m_matches.size()))
1289 drawLine(index, m_type_ahead.stringSize()); 1290 drawLine(index, m_type_ahead.stringSize());
1290 return; 1291 return;
1291 } else if (clear) 1292 } else if (clear)
1292 m_frame.clearArea(item_x, item_y, item_w, item_h); 1293 m_frame.clearArea(item_x, item_y, item_w, item_h);
1293 1294
1294 MenuItem *item = menuitems[index]; 1295 MenuItem* item = m_items[index];
1295 if (! item) return; 1296 if (!item)
1297 return;
1296 1298
1297 item->draw(m_frame, theme(), highlight, 1299 item->draw(m_frame, theme(), highlight,
1298 true, false, item_x, item_y, 1300 true, false, item_x, item_y,
1299 item_w, item_h); 1301 item_w, item_h);
1300 1302
1301 if (search_index < (int)m_matches.size()) 1303 if (search_index < static_cast<int>(m_matches.size()))
1302 drawLine(index, m_type_ahead.stringSize()); 1304 drawLine(index, m_type_ahead.stringSize());
1303} 1305}
1304 1306
@@ -1390,8 +1392,8 @@ void Menu::drawLine(int index, int size){
1390} 1392}
1391 1393
1392void Menu::hideShownMenu() { 1394void Menu::hideShownMenu() {
1393 if (shown) 1395 if (s_shown)
1394 shown->hide(); 1396 s_shown->hide();
1395} 1397}
1396 1398
1397} // end namespace FbTk 1399} // end namespace FbTk
diff --git a/src/FbTk/Menu.hh b/src/FbTk/Menu.hh
index 5e1d98c..49893c1 100644
--- a/src/FbTk/Menu.hh
+++ b/src/FbTk/Menu.hh
@@ -60,28 +60,18 @@ public:
60 @name manipulators 60 @name manipulators
61 */ 61 */
62 //@{ 62 //@{
63 /// add a menu item with a label and a command 63 int insertCommand(const FbString &label, RefCount<Command<void> > &cmd, int pos=-1);
64 int insert(const FbString &label, RefCount<Command<void> > &cmd, int pos=-1);
65 /// add empty menu item
66 int insert(const FbString &label, int pos=-1); 64 int insert(const FbString &label, int pos=-1);
67 /// add submenu 65 int insertSubmenu(const FbString &label, Menu *submenu, int pos= -1);
68 int insert(const FbString &label, Menu *submenu, int pos= -1); 66 int insertItem(MenuItem *item, int pos=-1);
69 /// add menu item
70 int insert(MenuItem *item, int pos=-1);
71 /// remove an item
72 int remove(unsigned int item); 67 int remove(unsigned int item);
73 /// remove all items
74 void removeAll(); 68 void removeAll();
75 void setInternalMenu(bool val = true) { m_internal_menu = val; } 69 void setInternalMenu(bool val = true) { m_internal_menu = val; }
76 void setAlignment(Alignment a) { m_alignment = a; } 70 void setAlignment(Alignment a) { m_alignment = a; }
77 71
78 /// raise this window
79 virtual void raise(); 72 virtual void raise();
80 /// lower this window
81 virtual void lower(); 73 virtual void lower();
82 /// cycle through menuitems
83 void cycleItems(bool reverse); 74 void cycleItems(bool reverse);
84 /// set and highlight new active index
85 void setActiveIndex(int new_index); 75 void setActiveIndex(int new_index);
86 void enterSubmenu(); 76 void enterSubmenu();
87 77
@@ -89,7 +79,7 @@ public:
89 void enableTitle(); 79 void enableTitle();
90 bool isTitleVisible() const { return m_title_vis; } 80 bool isTitleVisible() const { return m_title_vis; }
91 81
92 void setScreen(int x, int y, int w, int h); 82 void setScreen(int x, int y, unsigned int w, unsigned int h);
93 83
94 /** 84 /**
95 @name event handlers 85 @name event handlers
@@ -103,21 +93,16 @@ public:
103 void keyPressEvent(XKeyEvent &ke); 93 void keyPressEvent(XKeyEvent &ke);
104 void leaveNotifyEvent(XCrossingEvent &ce); 94 void leaveNotifyEvent(XCrossingEvent &ce);
105 //@} 95 //@}
106 /// get input focus
107 void grabInputFocus(); 96 void grabInputFocus();
108 virtual void reconfigure(); 97 virtual void reconfigure();
109 /// set label string
110 void setLabel(const FbTk::BiDiString &labelstr); 98 void setLabel(const FbTk::BiDiString &labelstr);
111 /// move menu to x,y
112 virtual void move(int x, int y); 99 virtual void move(int x, int y);
113 virtual void updateMenu(); 100 virtual void updateMenu();
114 void setItemSelected(unsigned int index, bool val); 101 void setItemSelected(unsigned int index, bool val);
115 void setItemEnabled(unsigned int index, bool val); 102 void setItemEnabled(unsigned int index, bool val);
116 void setMinimumColumns(int columns) { m_min_columns = columns; } 103 void setMinimumColumns(int columns) { m_min_columns = columns; }
117 virtual void drawSubmenu(unsigned int index); 104 virtual void drawSubmenu(unsigned int index);
118 /// show menu
119 virtual void show(); 105 virtual void show();
120 /// hide menu
121 virtual void hide(bool force = false); 106 virtual void hide(bool force = false);
122 virtual void clearWindow(); 107 virtual void clearWindow();
123 /*@}*/ 108 /*@}*/
@@ -140,7 +125,7 @@ public:
140 int y() const { return m_window.y(); } 125 int y() const { return m_window.y(); }
141 unsigned int width() const { return m_window.width(); } 126 unsigned int width() const { return m_window.width(); }
142 unsigned int height() const { return m_window.height(); } 127 unsigned int height() const { return m_window.height(); }
143 size_t numberOfItems() const { return menuitems.size(); } 128 size_t numberOfItems() const { return m_items.size(); }
144 int currentSubmenu() const { return m_which_sub; } 129 int currentSubmenu() const { return m_which_sub; }
145 130
146 bool isItemSelected(unsigned int index) const; 131 bool isItemSelected(unsigned int index) const;
@@ -149,12 +134,11 @@ public:
149 FbTk::ThemeProxy<MenuTheme> &theme() { return m_theme; } 134 FbTk::ThemeProxy<MenuTheme> &theme() { return m_theme; }
150 const FbTk::ThemeProxy<MenuTheme> &theme() const { return m_theme; } 135 const FbTk::ThemeProxy<MenuTheme> &theme() const { return m_theme; }
151 unsigned char alpha() const { return theme()->alpha(); } 136 unsigned char alpha() const { return theme()->alpha(); }
152 static Menu *shownMenu() { return shown; } 137 static Menu* shownMenu();
153 static Menu *focused() { return s_focused; } 138 static Menu* focused();
154 static void hideShownMenu(); 139 static void hideShownMenu();
155 /// @return menuitem at index 140 const MenuItem *find(size_t i) const { return m_items[i]; }
156 const MenuItem *find(unsigned int index) const { return menuitems[index]; } 141 MenuItem *find(size_t i) { return m_items[i]; }
157 MenuItem *find(unsigned int index) { return menuitems[index]; }
158 //@} 142 //@}
159 /// @return true if index is valid 143 /// @return true if index is valid
160 bool validIndex(int index) const { return (index < static_cast<int>(numberOfItems()) && index >= 0); } 144 bool validIndex(int index) const { return (index < static_cast<int>(numberOfItems()) && index >= 0); }
@@ -198,7 +182,7 @@ private:
198 ImageControl &m_image_ctrl; 182 ImageControl &m_image_ctrl;
199 183
200 typedef std::vector<MenuItem *> Menuitems; 184 typedef std::vector<MenuItem *> Menuitems;
201 Menuitems menuitems; 185 Menuitems m_items;
202 TypeAhead<Menuitems, MenuItem *> m_type_ahead; 186 TypeAhead<Menuitems, MenuItem *> m_type_ahead;
203 Menuitems m_matches; 187 Menuitems m_matches;
204 188
@@ -250,8 +234,6 @@ private:
250 // the corners 234 // the corners
251 std::auto_ptr<FbTk::Shape> m_shape; 235 std::auto_ptr<FbTk::Shape> m_shape;
252 236
253 static Menu *shown; ///< used for determining if there's a menu open at all
254 static Menu *s_focused; ///< holds current input focused menu, so one can determine if a menu is focused
255 bool m_need_update; 237 bool m_need_update;
256 Timer m_submenu_timer; 238 Timer m_submenu_timer;
257 Timer m_hide_timer; 239 Timer m_hide_timer;