diff options
-rw-r--r-- | src/FbTk/Menu.cc | 144 |
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 | ||
397 | void Menu::updateMenu() { | 392 | void 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 | } |