diff options
-rw-r--r-- | src/FbTk/Menu.cc | 171 |
1 files changed, 67 insertions, 104 deletions
diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc index 2a91ee4..7869376 100644 --- a/src/FbTk/Menu.cc +++ b/src/FbTk/Menu.cc | |||
@@ -22,7 +22,7 @@ | |||
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
23 | // DEALINGS IN THE SOFTWARE. | 23 | // DEALINGS IN THE SOFTWARE. |
24 | 24 | ||
25 | // $Id: Menu.cc,v 1.66 2004/06/13 12:01:52 fluxgen Exp $ | 25 | // $Id: Menu.cc,v 1.67 2004/06/14 12:24:23 fluxgen Exp $ |
26 | 26 | ||
27 | //use GNU extensions | 27 | //use GNU extensions |
28 | #ifndef _GNU_SOURCE | 28 | #ifndef _GNU_SOURCE |
@@ -381,7 +381,6 @@ void Menu::enableTitle() { | |||
381 | } | 381 | } |
382 | 382 | ||
383 | void Menu::update(int active_index) { | 383 | void Menu::update(int active_index) { |
384 | |||
385 | if (title_vis) { | 384 | if (title_vis) { |
386 | menu.item_w = theme().titleFont().textWidth(menu.label.c_str(), | 385 | menu.item_w = theme().titleFont().textWidth(menu.label.c_str(), |
387 | menu.label.size()); | 386 | menu.label.size()); |
@@ -485,7 +484,7 @@ void Menu::update(int active_index) { | |||
485 | m_title_pm.width(), m_title_pm.height()); | 484 | m_title_pm.width(), m_title_pm.height()); |
486 | 485 | ||
487 | } | 486 | } |
488 | 487 | ||
489 | } | 488 | } |
490 | } | 489 | } |
491 | 490 | ||
@@ -536,8 +535,8 @@ void Menu::update(int active_index) { | |||
536 | width(), menu.frame_h); | 535 | width(), menu.frame_h); |
537 | 536 | ||
538 | 537 | ||
539 | if (m_need_update && (m_frame_pm.width() != menu.frame.width() || | 538 | if (m_need_update || m_frame_pm.width() != menu.frame.width() || |
540 | m_frame_pm.height() != menu.frame.height() )){ | 539 | m_frame_pm.height() != menu.frame.height()){ |
541 | 540 | ||
542 | m_frame_pm = FbTk::FbPixmap(menu.frame.window(), | 541 | m_frame_pm = FbTk::FbPixmap(menu.frame.window(), |
543 | menu.frame.width(), menu.frame.height(), | 542 | menu.frame.width(), menu.frame.height(), |
@@ -548,82 +547,61 @@ void Menu::update(int active_index) { | |||
548 | menu.frame.depth()); | 547 | menu.frame.depth()); |
549 | 548 | ||
550 | menu.frame.setBackgroundPixmap(m_real_frame_pm.drawable()); | 549 | menu.frame.setBackgroundPixmap(m_real_frame_pm.drawable()); |
551 | 550 | GContext def_gc(menu.frame); | |
552 | if (m_frame_pm.drawable() == 0) { | 551 | if (m_frame_pm.drawable() == 0) { |
553 | _FB_USES_NLS; | 552 | _FB_USES_NLS; |
554 | cerr<<"FbTk::Menu: "<<_FBTKTEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<<" ("<< | 553 | cerr<<"FbTk::Menu: "<<_FBTKTEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<<" ("<< |
555 | menu.frame.window()<<", "<<menu.frame.width()<<", "<< | 554 | menu.frame.window()<<", "<<menu.frame.width()<<", "<< |
556 | menu.frame.height()<< | 555 | menu.frame.height()<< |
557 | ", "<<menu.frame.depth()<<") !"<<endl; | 556 | ", "<<menu.frame.depth()<<") !"<<endl; |
558 | } else if (menu.sublevels > 0 && menu.persub * menu.sublevels != (int)menuitems.size()) { | 557 | } else { |
559 | 558 | ||
560 | // TODO: fill only that part of the menuframe with the | ||
561 | // pixmap/color, that has actually NO buttons on it | ||
562 | // ??? did I made this comment ? (fluxgen) | ||
563 | // if so, what am I talking about? | ||
564 | GContext def_gc(menu.frame); | ||
565 | if (menu.frame_pixmap == 0) { | 559 | if (menu.frame_pixmap == 0) { |
566 | def_gc.setForeground(theme().frameTexture().color()); | 560 | def_gc.setForeground(theme().frameTexture().color()); |
567 | m_frame_pm.fillRectangle(def_gc.gc(), | 561 | m_frame_pm.fillRectangle(def_gc.gc(), |
568 | 0, 0, | 562 | 0, 0, |
569 | width(), menu.frame_h); | 563 | width(), menu.frame_h); |
570 | m_real_frame_pm.fillRectangle(def_gc.gc(), | ||
571 | 0, 0, | ||
572 | width(), menu.frame_h); | ||
573 | } else { | 564 | } else { |
574 | m_frame_pm.copyArea(menu.frame_pixmap, def_gc.gc(), | 565 | m_frame_pm.copyArea(menu.frame_pixmap, def_gc.gc(), |
575 | 0, 0, | 566 | 0, 0, |
576 | 0, 0, | 567 | 0, 0, |
577 | width(), menu.frame_h); | 568 | width(), menu.frame_h); |
578 | |||
579 | m_real_frame_pm.copyArea(menu.frame_pixmap, | ||
580 | def_gc.gc(), | ||
581 | 0, 0, | ||
582 | 0, 0, | ||
583 | width(), menu.frame_h); | ||
584 | } | 569 | } |
570 | |||
585 | 571 | ||
586 | } | 572 | } |
587 | 573 | ||
574 | m_real_frame_pm.copyArea(m_frame_pm.drawable(), | ||
575 | def_gc.gc(), | ||
576 | 0, 0, | ||
577 | 0, 0, | ||
578 | m_frame_pm.width(), m_frame_pm.height()); | ||
579 | |||
588 | } | 580 | } |
589 | 581 | ||
590 | // if menu visible and title visible | 582 | // if menu visible and title visible |
591 | if (title_vis && visible) | 583 | if (title_vis && visible) |
592 | redrawTitle(); | 584 | redrawTitle(); |
593 | 585 | ||
594 | if (active_index >= 0 && isVisible()) { | 586 | if (active_index >= 0 || m_need_update) { |
595 | move(x(), y()); | 587 | |
596 | renderTransp(0, 0, | 588 | renderTransp(0, 0, |
597 | m_real_frame_pm.width(), m_real_frame_pm.height()); | 589 | m_real_frame_pm.width(), m_real_frame_pm.height()); |
598 | for (unsigned int i = 0; i < menuitems.size(); i++) { | 590 | for (unsigned int i = 0; i < menuitems.size(); i++) { |
599 | if (i == (unsigned int)which_sub) { | 591 | if (i == (unsigned int)which_sub) { |
600 | drawItem(i, true, // highlight | 592 | drawItem(i, // index |
601 | true, // clear | 593 | true, // highlight |
594 | true, // clear | ||
602 | false); // render_trans | 595 | false); // render_trans |
603 | } else | 596 | } else { |
604 | drawItem(i, | 597 | drawItem(i, // index |
605 | // high light | 598 | // highlight |
606 | (static_cast<signed>(i) == active_index && isItemEnabled(i)), | 599 | (static_cast<signed>(i) == active_index && isItemEnabled(i)), |
607 | true, // clear | 600 | true, // clear |
608 | false); // render transparent | 601 | false); // render transparent |
602 | } | ||
609 | } | 603 | } |
610 | 604 | ||
611 | // if (m_parent) | ||
612 | // m_parent->drawSubmenu(m_parent->which_sub); | ||
613 | /* | ||
614 | renderTransp(0, active_index*menu.item_h, | ||
615 | width(), menu.item_h); | ||
616 | */ | ||
617 | |||
618 | } | ||
619 | |||
620 | if (m_need_update) { | ||
621 | for (unsigned int i = 0; i < menuitems.size(); i++) { | ||
622 | if (i == (unsigned int)which_sub) { | ||
623 | drawItem(i, true, true, false); | ||
624 | } else | ||
625 | drawItem(i, (static_cast<signed>(i) == active_index && isItemEnabled(i)), true, true); | ||
626 | } | ||
627 | } | 605 | } |
628 | 606 | ||
629 | m_need_update = false; | 607 | m_need_update = false; |
@@ -633,6 +611,7 @@ void Menu::update(int active_index) { | |||
633 | void Menu::show() { | 611 | void Menu::show() { |
634 | if (m_need_update) | 612 | if (m_need_update) |
635 | update(); | 613 | update(); |
614 | |||
636 | menu.window.showSubwindows(); | 615 | menu.window.showSubwindows(); |
637 | menu.window.show(); | 616 | menu.window.show(); |
638 | raise(); | 617 | raise(); |
@@ -644,7 +623,7 @@ void Menu::show() { | |||
644 | 623 | ||
645 | shown = this; | 624 | shown = this; |
646 | } | 625 | } |
647 | 626 | ||
648 | } | 627 | } |
649 | 628 | ||
650 | 629 | ||
@@ -707,6 +686,15 @@ void Menu::internal_hide() { | |||
707 | 686 | ||
708 | 687 | ||
709 | void Menu::move(int x, int y) { | 688 | void Menu::move(int x, int y) { |
689 | if (x == this->x() && y == this->y()) | ||
690 | return; | ||
691 | |||
692 | // if we're not visible and we do transparency | ||
693 | // we need to update transparency when we call | ||
694 | // show() next time | ||
695 | if (alpha() < 255) | ||
696 | m_need_update = true; | ||
697 | |||
710 | menu.window.move(x, y); | 698 | menu.window.move(x, y); |
711 | 699 | ||
712 | if (!isVisible()) | 700 | if (!isVisible()) |
@@ -725,7 +713,7 @@ void Menu::move(int x, int y) { | |||
725 | true, // clear | 713 | true, // clear |
726 | false); // transparent | 714 | false); // transparent |
727 | } | 715 | } |
728 | 716 | m_need_update = false; | |
729 | } | 717 | } |
730 | 718 | ||
731 | } | 719 | } |
@@ -962,18 +950,20 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t | |||
962 | 950 | ||
963 | } | 951 | } |
964 | 952 | ||
965 | if (render_trans) | 953 | if (render_trans) { |
966 | renderTransp(item_x, item_y, | 954 | renderTransp(item_x, item_y, |
967 | width(), theme().itemHeight()); | 955 | width(), theme().itemHeight()); |
956 | } | ||
968 | 957 | ||
969 | item->draw(m_real_frame_pm, theme(), highlight, | 958 | item->draw(m_real_frame_pm, theme(), highlight, |
970 | item_x, item_y, | 959 | item_x, item_y, |
971 | menu.item_w, theme().itemHeight()); | 960 | menu.item_w, theme().itemHeight()); |
972 | 961 | ||
973 | 962 | ||
974 | if (clear) | 963 | if (clear) { |
975 | menu.frame.clearArea(item_x, item_y, | 964 | menu.frame.clearArea(item_x, item_y, |
976 | menu.item_w, theme().itemHeight(), False); | 965 | menu.item_w, theme().itemHeight(), False); |
966 | } | ||
977 | 967 | ||
978 | 968 | ||
979 | return item_y; | 969 | return item_y; |
@@ -1072,7 +1062,22 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) { | |||
1072 | if (re.window == menu.title) { | 1062 | if (re.window == menu.title) { |
1073 | if (moving) { | 1063 | if (moving) { |
1074 | moving = false; | 1064 | moving = false; |
1075 | move(x(), y()); | 1065 | |
1066 | if (which_sub != -1) | ||
1067 | drawSubmenu(which_sub); | ||
1068 | |||
1069 | if (alpha() < 255) { | ||
1070 | redrawTitle(); | ||
1071 | menu.title.clear(); | ||
1072 | renderTransp(0, 0, | ||
1073 | m_real_frame_pm.width(), m_real_frame_pm.height()); | ||
1074 | for (size_t i=0; i < menuitems.size(); ++i) { | ||
1075 | drawItem(i, false, // highlight | ||
1076 | true, // clear | ||
1077 | false); // transparent | ||
1078 | } | ||
1079 | |||
1080 | } | ||
1076 | } | 1081 | } |
1077 | 1082 | ||
1078 | if (re.x >= 0 && re.x <= (signed) width() && | 1083 | if (re.x >= 0 && re.x <= (signed) width() && |
@@ -1196,54 +1201,8 @@ void Menu::exposeEvent(XExposeEvent &ee) { | |||
1196 | if (ee.window == menu.title) { | 1201 | if (ee.window == menu.title) { |
1197 | redrawTitle(); | 1202 | redrawTitle(); |
1198 | menu.title.clearArea(ee.x, ee.y, ee.width, ee.height); | 1203 | menu.title.clearArea(ee.x, ee.y, ee.width, ee.height); |
1199 | } else if (ee.window == menu.frame) { | 1204 | } else if (ee.window == menu.frame) |
1200 | |||
1201 | if (moving) { | ||
1202 | menu.frame.clearArea(ee.x, ee.y, ee.width, ee.height); | ||
1203 | return; | ||
1204 | } | ||
1205 | |||
1206 | // this is a compilicated algorithm... lets do it step by step... | ||
1207 | // first... we see in which sub level the expose starts... and how many | ||
1208 | // items down in that sublevel | ||
1209 | |||
1210 | // Simon was here :-) I think this all makes much more sense when | ||
1211 | // we rename sbl to "start_col", sbl_d to "end_col", ditto id -> row | ||
1212 | // a "sublevel" is basically a column in a multi-column menu (e.g. placement) | ||
1213 | |||
1214 | if (menu.item_w == 0) | ||
1215 | menu.item_w = 1; | ||
1216 | |||
1217 | unsigned int | ||
1218 | start_column = (ee.x / menu.item_w), | ||
1219 | end_column = ((ee.x + ee.width) / menu.item_w), | ||
1220 | start_row = (ee.y / theme().itemHeight()), | ||
1221 | end_row = ((ee.y + ee.height) / theme().itemHeight()); | ||
1222 | if (static_cast<signed>(end_row) > menu.persub) | ||
1223 | end_row = menu.persub; | ||
1224 | |||
1225 | // draw the sublevels and the number of items the exposure spans | ||
1226 | unsigned int col, row; | ||
1227 | int max_y = 0; | ||
1228 | for (col = start_column; col <= end_column; col++) { | ||
1229 | // set the iterator to the first item in the column needing redrawing | ||
1230 | unsigned int index = start_row + col * menu.persub; | ||
1231 | if (index < menuitems.size()) { | ||
1232 | Menuitems::iterator it = menuitems.begin() + index; | ||
1233 | Menuitems::iterator it_end = menuitems.end(); | ||
1234 | for (row = start_row; row <= end_row && it != it_end; ++it, row++) { | ||
1235 | unsigned int index = row + (col * menu.persub); | ||
1236 | max_y = max(drawItem(index, | ||
1237 | (which_sub == static_cast<signed>(index)), // highlight | ||
1238 | false, // clear | ||
1239 | true), max_y); // render trans | ||
1240 | } | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | menu.frame.clearArea(ee.x, ee.y, ee.width, ee.height); | 1205 | menu.frame.clearArea(ee.x, ee.y, ee.width, ee.height); |
1245 | |||
1246 | } | ||
1247 | } | 1206 | } |
1248 | 1207 | ||
1249 | 1208 | ||
@@ -1375,6 +1334,7 @@ void Menu::reconfigure() { | |||
1375 | 1334 | ||
1376 | 1335 | ||
1377 | update(); | 1336 | update(); |
1337 | |||
1378 | } | 1338 | } |
1379 | 1339 | ||
1380 | 1340 | ||
@@ -1424,10 +1384,8 @@ void Menu::update(FbTk::Subject *subj) { | |||
1424 | 1384 | ||
1425 | void Menu::renderTransp(int x, int y, | 1385 | void Menu::renderTransp(int x, int y, |
1426 | unsigned int width, unsigned int height) { | 1386 | unsigned int width, unsigned int height) { |
1427 | // no need to render transparent unless visible | 1387 | // even though we dont render transparency |
1428 | if (!isVisible()) | 1388 | // we do need to copy the style background |
1429 | return; | ||
1430 | |||
1431 | GContext def_gc(menu.frame); | 1389 | GContext def_gc(menu.frame); |
1432 | m_real_frame_pm.copyArea(m_frame_pm.drawable(), | 1390 | m_real_frame_pm.copyArea(m_frame_pm.drawable(), |
1433 | def_gc.gc(), | 1391 | def_gc.gc(), |
@@ -1435,9 +1393,14 @@ void Menu::renderTransp(int x, int y, | |||
1435 | x, y, | 1393 | x, y, |
1436 | width, height); | 1394 | width, height); |
1437 | 1395 | ||
1438 | if (m_transp.get() == 0) | 1396 | // no need to render transparent unless visible |
1397 | // but we do need to render it if we marked it as | ||
1398 | // need update | ||
1399 | if (!isVisible() && !m_need_update || m_transp.get() == 0) | ||
1439 | return; | 1400 | return; |
1440 | 1401 | ||
1402 | |||
1403 | // render the root background | ||
1441 | #ifdef HAVE_XRENDER | 1404 | #ifdef HAVE_XRENDER |
1442 | 1405 | ||
1443 | Pixmap root = getRootPixmap(screenNumber()); | 1406 | Pixmap root = getRootPixmap(screenNumber()); |