aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/FbTk/Menu.cc144
1 files changed, 64 insertions, 80 deletions
diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc
index aceb7eb..c9220af 100644
--- a/src/FbTk/Menu.cc
+++ b/src/FbTk/Menu.cc
@@ -157,23 +157,18 @@ Menu::Menu(FbTk::ThemeProxy<MenuTheme> &tm, ImageControl &imgctrl):
157 event_mask ^= FocusChangeMask; 157 event_mask ^= FocusChangeMask;
158 event_mask |= EnterWindowMask | LeaveWindowMask; 158 event_mask |= EnterWindowMask | LeaveWindowMask;
159 159
160 int w = width();
161 int th = theme()->titleHeight();
162 int fh = std::max(m_frame.height, m_frame.height);
163
160 //create menu title 164 //create menu title
161 m_title.win = FbTk::FbWindow(m_window, 165 m_title.win = FbTk::FbWindow(m_window, 0, 0, w, th, event_mask, false, true);
162 0, 0, width(), theme()->titleHeight(),
163 event_mask,
164 false, // override redirect
165 true); // save under
166 166
167 evm.add(*this, m_title.win); 167 evm.add(*this, m_title.win);
168 m_title.win.setRenderer(*this); 168 m_title.win.setRenderer(*this);
169 169
170 event_mask |= PointerMotionMask; 170 event_mask |= PointerMotionMask;
171 m_frame.win = FbTk::FbWindow(m_window, 171 m_frame.win = FbTk::FbWindow(m_window, 0, th, w, fh, event_mask, false, true);
172 0, theme()->titleHeight(),
173 width(), m_frame.height ? m_frame.height : 1,
174 event_mask,
175 false, // override redirect
176 true); // save under
177 evm.add(*this, m_frame.win); 172 evm.add(*this, m_frame.win);
178 m_frame.win.setRenderer(*this); 173 m_frame.win.setRenderer(*this);
179 m_title.win.raise(); 174 m_title.win.raise();
@@ -395,15 +390,21 @@ void Menu::enableTitle() {
395} 390}
396 391
397void Menu::updateMenu() { 392void Menu::updateMenu() {
398 if (m_title.visible) {
399 m_item_w = theme()->titleFont().textWidth(m_title.label);
400 m_item_w += (theme()->bevelWidth() * 2);
401 } else
402 m_item_w = 1;
403 393
394 int bevel = theme()->bevelWidth();
395 int bw = theme()->borderWidth();
396 int ih = theme()->itemHeight();
397 unsigned int iw = 1;
398 int th = theme()->titleHeight();
399 int tbw = m_title.win.borderWidth();
400 int w = static_cast<int>(width());
401 size_t l = m_items.size();
402 size_t i;
403
404
405 // find the nearest enabled menuitem and highlight it
404 if (validIndex(m_active_index) && !m_items[m_active_index]->isEnabled()) { 406 if (validIndex(m_active_index) && !m_items[m_active_index]->isEnabled()) {
405 // find the nearest enabled menuitem and highlight it 407 for (i = 1; i < l; i++) {
406 for (size_t i = 1; i < m_items.size(); i++) {
407 if (validIndex(m_active_index + i) && 408 if (validIndex(m_active_index + i) &&
408 m_items[m_active_index + i]->isEnabled()) { 409 m_items[m_active_index + i]->isEnabled()) {
409 m_active_index += i; 410 m_active_index += i;
@@ -416,43 +417,44 @@ void Menu::updateMenu() {
416 } 417 }
417 } 418 }
418 419
419 unsigned int ii = 0; 420
420 size_t l = m_items.size(); 421 // calculate needed item width
421 size_t i; 422 m_item_w = 1;
423 if (m_title.visible) {
424 m_item_w = theme()->titleFont().textWidth(m_title.label);
425 m_item_w += bevel * 2;
426 }
427 m_item_w = std::max(iw, m_item_w);
422 for (i = 0; i < l; i++) { 428 for (i = 0; i < l; i++) {
423 ii = m_items[i]->width(theme()); 429 iw = m_items[i]->width(theme());
424 m_item_w = (ii > m_item_w ? ii : m_item_w); 430 m_item_w = std::max(iw, m_item_w);
425 } 431 }
426 432
427 if (m_item_w < 1)
428 m_item_w = 1;
429 433
434 // calculate needed columns
435 m_columns = 0;
436 m_rows_per_column = 0;
430 if (!m_items.empty()) { 437 if (!m_items.empty()) {
431 m_columns = 1; 438 m_columns = 1;
432 439
433 while (theme()->itemHeight() * (m_items.size() + 1) / m_columns + 440 while (ih * (l + 1) / m_columns + th + bw > m_screen.height) {
434 theme()->titleHeight() + theme()->borderWidth() > m_screen.height) {
435 m_columns++; 441 m_columns++;
436 } 442 }
437 443
438 if (m_columns < m_min_columns) 444 m_columns = std::max(m_min_columns, m_columns);
439 m_columns = m_min_columns;
440
441 m_rows_per_column = m_items.size() / m_columns; 445 m_rows_per_column = m_items.size() / m_columns;
442 if (m_items.size() % m_columns) m_rows_per_column++; 446 if (m_items.size() % m_columns)
443 } else { 447 m_rows_per_column++;
444 m_columns = 0;
445 m_rows_per_column = 0;
446 } 448 }
447 449
448 int itmp = (theme()->itemHeight() * m_rows_per_column); 450 int itmp = ih * m_rows_per_column;
449 m_frame.height = itmp < 1 ? 1 : itmp; 451 m_frame.height = std::max(1, itmp);
450 452
451 unsigned int new_width = (m_columns * m_item_w); 453 unsigned int new_width = (m_columns * m_item_w);
452 unsigned int new_height = m_frame.height; 454 unsigned int new_height = m_frame.height;
453 455
454 if (m_title.visible) 456 if (m_title.visible)
455 new_height += theme()->titleHeight() + ((m_frame.height > 0)?m_title.win.borderWidth():0); 457 new_height += th + ((m_frame.height > 0) ? tbw : 0);
456 458
457 459
458 if (new_width == 0) 460 if (new_width == 0)
@@ -474,52 +476,39 @@ void Menu::updateMenu() {
474 if (m_frame.win.alpha() != alpha()) 476 if (m_frame.win.alpha() != alpha())
475 m_frame.win.setAlpha(alpha()); 477 m_frame.win.setAlpha(alpha());
476 478
477 renderMenuPixmap(m_hilite_pixmap, NULL, 479 renderMenuPixmap(m_hilite_pixmap, NULL, m_item_w, ih, theme()->hiliteTexture(), m_image_ctrl);
478 m_item_w, theme()->itemHeight(),
479 theme()->hiliteTexture(), m_image_ctrl);
480 480
481 481
482 if (!theme()->selectedPixmap().pixmap().drawable()) { 482 if (!theme()->selectedPixmap().pixmap().drawable()) {
483 int hw = theme()->itemHeight() / 2; 483 int hw = ih / 2;
484 // render image, disable cache and let the theme remove the pixmap 484 // render image, disable cache and let the theme remove the pixmap
485 theme()->setSelectedPixmap(m_image_ctrl. 485 Pixmap pm = m_image_ctrl.renderImage(hw, hw, theme()->hiliteTexture(), ROT0, false);
486 renderImage(hw, hw, 486 theme()->setSelectedPixmap(pm, false); // the theme takes care of this pixmap
487 theme()->hiliteTexture(), ROT0,
488 false // no cache
489 ),
490 false); // the theme takes care of this pixmap
491 487
492 if (!theme()->highlightSelectedPixmap().pixmap().drawable()) { 488 if (!theme()->highlightSelectedPixmap().pixmap().drawable()) {
493 int hw = theme()->itemHeight() / 2; 489 hw = ih / 2;
494 // render image, disable cache and let the theme remove the pixmap 490 // render image, disable cache and let the theme remove the pixmap
495 theme()->setHighlightSelectedPixmap(m_image_ctrl. 491 pm = m_image_ctrl.renderImage(hw, hw, theme()->frameTexture(), ROT0, false);
496 renderImage(hw, hw, 492 theme()->setHighlightSelectedPixmap(pm, false); // theme takes care of this pixmap
497 theme()->frameTexture(), ROT0,
498 false // no cache
499 ),
500 false); // theme takes care of this pixmap
501 } 493 }
502 } 494 }
503 495
496 int y = 0;
504 if (m_title.visible) { 497 if (m_title.visible) {
505 m_title.win.moveResize(-m_title.win.borderWidth(), -m_title.win.borderWidth(), 498 m_title.win.moveResize(-tbw, -tbw, w + tbw, th);
506 width() + m_title.win.borderWidth(), theme()->titleHeight()); 499 y = m_title.win.y() + m_title.win.height() + 2 * tbw;
507 } 500 }
508 501
509 m_frame.win.moveResize(0, ((m_title.visible) ? m_title.win.y() + m_title.win.height() + 502 m_frame.win.moveResize(0, y, w, m_frame.height);
510 m_title.win.borderWidth()*2 : 0),
511 width(), m_frame.height);
512 503
513 if (m_title.visible && m_need_update) { 504 if (m_title.visible && m_need_update) {
514 renderMenuPixmap(m_title.pixmap, &m_title.win, 505 renderMenuPixmap(m_title.pixmap, &m_title.win,
515 width(), theme()->titleHeight(), 506 w, th, theme()->titleTexture(), m_image_ctrl);
516 theme()->titleTexture(), m_image_ctrl);
517 } 507 }
518 508
519 if (m_need_update) { 509 if (m_need_update) {
520 renderMenuPixmap(m_frame.pixmap, &m_frame.win, 510 renderMenuPixmap(m_frame.pixmap, &m_frame.win,
521 width(), m_frame.height, 511 w, m_frame.height, theme()->frameTexture(), m_image_ctrl);
522 theme()->frameTexture(), m_image_ctrl);
523 } 512 }
524 513
525 clearWindow(); 514 clearWindow();
@@ -534,7 +523,6 @@ void Menu::show() {
534 return; 523 return;
535 524
536 m_state.visible = true; 525 m_state.visible = true;
537
538 if (m_need_update) 526 if (m_need_update)
539 updateMenu(); 527 updateMenu();
540 528
@@ -662,7 +650,7 @@ void Menu::redrawTitle(FbDrawable &drawable) {
662 650
663 const FbTk::Font &font = theme()->titleFont(); 651 const FbTk::Font &font = theme()->titleFont();
664 int dx = theme()->bevelWidth(); 652 int dx = theme()->bevelWidth();
665 int l = static_cast<int>(font.textWidth(m_title.label) + theme()->bevelWidth()*2); 653 int l = static_cast<int>(font.textWidth(m_title.label) + dx*2);
666 654
667 switch (theme()->titleFontJustify()) { 655 switch (theme()->titleFontJustify()) {
668 case FbTk::RIGHT: 656 case FbTk::RIGHT:
@@ -677,9 +665,9 @@ void Menu::redrawTitle(FbDrawable &drawable) {
677 } 665 }
678 666
679 // difference between height based on font, and style-set height 667 // difference between height based on font, and style-set height
680 int height_offset = theme()->titleHeight() - (font.height() + 2*theme()->bevelWidth()); 668 int height_offset = theme()->titleHeight() - (font.height() + 2*dx);
681 font.drawText(drawable, screenNumber(), theme()->titleTextGC().gc(), m_title.label, 669 font.drawText(drawable, screenNumber(), theme()->titleTextGC().gc(), m_title.label,
682 dx, font.ascent() + theme()->bevelWidth() + height_offset/2); // position 670 dx, font.ascent() + dx + height_offset/2); // position
683} 671}
684 672
685 673
@@ -1310,25 +1298,21 @@ void Menu::clearItem(int index, bool clear, int search_index) {
1310#endif 1298#endif
1311 } 1299 }
1312 1300
1313 // don't highlight if moving, doesn't work with alpha on 1301 // highlight only if not if moving, doesn't work with alpha on
1314 if (highlight && !m_state.moving) { 1302 if (highlight && !m_state.moving) {
1315 highlightItem(index); 1303 highlightItem(index);
1316 if (start_idx != end_idx) { // need a underline (aka "matched item") 1304 } else {
1317 m_items[index]->drawLine(m_frame.win, theme(), 1305 if (clear) {
1318 end_idx - start_idx, item_x, item_y, m_item_w, start_idx); 1306 m_frame.win.clearArea(item_x, item_y, item_w, item_h);
1319 } 1307 }
1320 return;
1321 }
1322 1308
1323 if (clear) { 1309 m_items[index]->draw(m_frame.win, theme(), highlight,
1324 m_frame.win.clearArea(item_x, item_y, item_w, item_h); 1310 true, false, item_x, item_y,
1311 item_w, item_h);
1325 } 1312 }
1326 1313
1327 m_items[index]->draw(m_frame.win, theme(), highlight, 1314 // need a underline (aka "matched item")
1328 true, false, item_x, item_y, 1315 if (start_idx != end_idx) {
1329 item_w, item_h);
1330
1331 if (start_idx != end_idx) { // need a underline (aka "matched item")
1332 m_items[index]->drawLine(m_frame.win, theme(), 1316 m_items[index]->drawLine(m_frame.win, theme(),
1333 end_idx - start_idx, item_x, item_y, m_item_w, start_idx); 1317 end_idx - start_idx, item_x, item_y, m_item_w, start_idx);
1334 } 1318 }