home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / guicast / bcmenubar.C < prev    next >
C/C++ Source or Header  |  2000-11-29  |  21KB  |  1,147 lines

  1. #include "bcmenubar.h"
  2. #include "bcpopup.h"
  3. #include "bcpopupmenu.h"
  4. #include "bcresources.h"
  5. #include "colors.h"
  6. #include "fonts.h"
  7. #include <string.h>
  8.  
  9.  
  10. // ================================== Menu bar ==================================
  11.  
  12. BC_MenuBar::BC_MenuBar(int x, int y, int w)
  13.  : BC_SubWindow(x, y, w, 0, -1)
  14. {
  15. // Height is really determined by the font in create_tool_objects.
  16.     button_releases = 0;
  17.     active = 0;
  18. }
  19.  
  20.  
  21. BC_MenuBar::~BC_MenuBar()
  22. {
  23. // Delete all titles.
  24.     for(int i = 0; i < menu_titles.total; i++) delete menu_titles.values[i];
  25.     menu_titles.remove_all();
  26. }
  27.  
  28. int BC_MenuBar::initialize()
  29. {
  30. // Initialize dimensions
  31.     h = get_text_height(MEDIUMFONT) + 8;
  32.     bg_color = top_level->get_resources()->menu_up;
  33.     
  34.  
  35. // Create the subwindow
  36.     BC_SubWindow::initialize();
  37.  
  38.     if(top_level->get_resources()->menu_bg) 
  39.         set_background(top_level->get_resources()->menu_bg);
  40.     draw_face();
  41.     return 0;
  42. }
  43.  
  44. int BC_MenuBar::add_menu(BC_Menu* menu)
  45. {
  46.     int x, w;
  47.  
  48. // Get dimensions
  49.     if(menu_titles.total == 0)
  50.         x = 2;
  51.     else
  52.         x = menu_titles.values[menu_titles.total - 1]->x + 
  53.             menu_titles.values[menu_titles.total - 1]->w;
  54.  
  55.     w = get_text_width(MEDIUMFONT, menu->text) + 20;
  56. // get pointer
  57.     menu_titles.append(menu);
  58. // initialize and draw
  59.     menu->initialize(top_level, this, x, 2, w, get_h() - 4); 
  60.     return 0;
  61. }
  62.  
  63. int BC_MenuBar::button_press_event()
  64. {
  65.     int result = 0;
  66.  
  67.     for(int i = 0; i < menu_titles.total && !result; i++)
  68.     {
  69.         result = menu_titles.values[i]->dispatch_button_press();
  70.     }
  71.  
  72.     return result;
  73. }
  74.  
  75. int BC_MenuBar::button_release_event()
  76. {
  77.     int result = 0;
  78.  
  79.     button_down = 0;
  80.     button_releases++;
  81.     for(int i = 0; i < menu_titles.total; i++)
  82.     {
  83.         result += menu_titles.values[i]->dispatch_button_release();
  84.     }
  85.  
  86. // Button was released outside any menu.
  87.     if(!result)
  88.     {
  89.         deactivate();
  90.     }
  91.  
  92.     return result;
  93. }
  94.  
  95. int BC_MenuBar::resize_event(int w, int h)
  96. {
  97.     resize_window(w, get_h());
  98.     draw_face();
  99.     for(int i = 0; i < menu_titles.total; i++)
  100.     {
  101.         menu_titles.values[i]->draw_title();
  102.     }
  103.     return 0;
  104. }
  105.  
  106. int BC_MenuBar::keypress_event()
  107. {
  108.     int result = 0;
  109.     if(!top_level->active_subwindow || !top_level->active_subwindow->uses_text())
  110.     {
  111.         for(int i = 0; i < menu_titles.total && !result; i++)
  112.         {
  113.             result = menu_titles.values[i]->dispatch_keypress();
  114.         }
  115.     }
  116.     return result;
  117. }
  118.  
  119. int BC_MenuBar::cursor_motion_event()
  120. {
  121.     int result = 0;
  122.     for(int i = 0; i < menu_titles.total && !result; i++)
  123.     {
  124.         result = menu_titles.values[i]->dispatch_motion_event();
  125.     }
  126.     return result;
  127. }
  128.  
  129. int BC_MenuBar::cursor_leave_event()
  130. {
  131.     for(int i = 0; i < menu_titles.total; i++)
  132.     {
  133.         menu_titles.values[i]->dispatch_cursor_leave();
  134.     }
  135.     return 0;
  136. }
  137.  
  138. int BC_MenuBar::cursor_enter_event()
  139. {
  140.     if(active) return 1;
  141.     return 0;
  142. }
  143.  
  144. int BC_MenuBar::translation_event()
  145. {
  146.     if(active)
  147.     {
  148.         for(int i = 0; i < menu_titles.total; i++)
  149.         {
  150.             menu_titles.values[i]->dispatch_translation_event();
  151.         }
  152.     }
  153.     return 0;
  154. }
  155.  
  156. int BC_MenuBar::activate()
  157. {
  158.     top_level->deactivate();
  159.     top_level->active_menubar = this;
  160.     active = 1;
  161.     return 0;
  162. }
  163.  
  164. int BC_MenuBar::deactivate()
  165. {
  166.     for(int i = 0; i < menu_titles.total; i++)
  167.     {
  168.         menu_titles.values[i]->deactivate_menu();
  169.     }
  170.     top_level->active_menubar = 0;
  171.     active = 0;
  172.     return 0;
  173. }
  174.  
  175. int BC_MenuBar::unhighlight()
  176. {
  177.     for(int i = 0; i < menu_titles.total; i++)
  178.     {
  179.         menu_titles.values[i]->unhighlight();
  180.     }
  181.     return 0;
  182. }
  183.  
  184. int BC_MenuBar::draw_face()
  185. {
  186.     int lx,ly,ux,uy;
  187.     int h, w;
  188.     h = get_h();
  189.     w = get_w();
  190.     h--; 
  191.     w--;
  192.  
  193.     lx = 1;  ly = 1;
  194.     ux = w - 1;  uy = h - 1;
  195.  
  196.     set_color(top_level->get_resources()->menu_light);
  197.     draw_line(0, 0, 0, uy);
  198.     draw_line(0, 0, ux, 0);
  199.  
  200.     set_color(top_level->get_resources()->menu_shadow);
  201.     draw_line(ux, ly, ux, uy);
  202.     draw_line(lx, uy, ux, uy);
  203.     set_color(BLACK);
  204.     draw_line(w, 0, w, h);
  205.     draw_line(0, h, w, h);
  206.  
  207.     flash();
  208.     return 0;
  209. }
  210.  
  211. // ==================================== Menu ===================================
  212.  
  213. BC_Menu::BC_Menu(char *text)
  214. {
  215.     strcpy(this->text, text);
  216.     menu_bar = 0;
  217.     active = 0;
  218.     highlighted = 0;
  219. }
  220.  
  221. BC_Menu::~BC_Menu()
  222. {
  223.     delete menu_popup;
  224. }
  225.  
  226. int BC_Menu::initialize(BC_WindowBase *top_level, 
  227.         BC_MenuBar *menu_bar, 
  228.         int x, 
  229.         int y, 
  230.         int w, 
  231.         int h)
  232. {
  233.     this->x = x; 
  234.     this->y = y; 
  235.     this->w = w; 
  236.     this->h = h;
  237.     this->menu_bar = menu_bar;
  238.     this->top_level = top_level;
  239.     menu_popup = new BC_MenuPopup;
  240.     menu_popup->initialize(top_level, menu_bar, this, 0, 0);
  241.     draw_title();
  242.     return 0;
  243. }
  244.  
  245. int BC_Menu::add_item(BC_MenuItem* menuitem)
  246. {
  247.     menu_popup->add_item(menuitem);
  248.     return 0;
  249. }
  250.  
  251. int BC_Menu::remove_item(BC_MenuItem *item)
  252. {
  253.     menu_popup->remove_item(item);
  254.     return 0;
  255. }
  256.  
  257. int BC_Menu::total_menuitems()
  258. {
  259.     return menu_popup->total_menuitems();
  260. }
  261.  
  262. int BC_Menu::dispatch_button_press()
  263. {
  264.     int result = 0;
  265.  
  266. // Menu is down so dispatch to popup
  267.     if(active)
  268.     {
  269.         result = menu_popup->dispatch_button_press();
  270.     }
  271.  
  272. // Try title.
  273.     if(!result)
  274.     {
  275.         if(top_level->event_win == menu_bar->win &&
  276.             top_level->cursor_x >= x && top_level->cursor_x < x + w &&
  277.             top_level->cursor_y >= y && top_level->cursor_y < y + h)
  278.         {
  279.             if(!active)
  280.             {
  281.                 menu_bar->deactivate();
  282.                 menu_bar->unhighlight();
  283.                 menu_bar->button_releases = 0;
  284.                 menu_bar->activate();
  285.                 activate_menu();
  286.             }
  287.             result = 1;
  288.         }
  289.     }
  290.     return result;
  291. }
  292.  
  293. int BC_Menu::dispatch_button_release()
  294. {
  295. // try the title
  296.     int result = 0;
  297.     if(top_level->event_win == menu_bar->win &&
  298.         top_level->cursor_x >= x && top_level->cursor_y < x + w &&
  299.         top_level->cursor_y >= y && top_level->cursor_y < y + h)
  300.     {
  301.         if(menu_bar->button_releases >= 2)
  302.         {
  303.             highlighted = 1;
  304.             menu_bar->deactivate();
  305.         }
  306.         result = 1;
  307.     }
  308.     else
  309. // try the popup
  310.         result = menu_popup->dispatch_button_release();
  311.     return result;
  312. }
  313.  
  314. int BC_Menu::dispatch_keypress()
  315. {
  316.     return menu_popup->dispatch_key_press();
  317. }
  318.  
  319. int BC_Menu::dispatch_motion_event()
  320. {
  321.     int result = 0;
  322.     int cursor_x, cursor_y;
  323.     Window tempwin;
  324.  
  325. // try the popup
  326.     if(active)
  327.     {
  328.         result = menu_popup->dispatch_motion_event();
  329.     }
  330.  
  331.     if(!result)
  332.     {
  333.         XTranslateCoordinates(top_level->display, 
  334.             top_level->event_win, 
  335.             menu_bar->win, 
  336.             top_level->cursor_x, 
  337.             top_level->cursor_y, 
  338.             &cursor_x, 
  339.             &cursor_y, 
  340.             &tempwin);
  341.  
  342. // change focus from other menu
  343.         if(menu_bar->active && !active &&
  344.             cursor_x >= x && cursor_x < x + w &&
  345.             cursor_y >= y && cursor_y < y + h)
  346.         {
  347.             menu_bar->activate();
  348.             activate_menu();
  349.             result = 1;
  350.         }
  351.         else
  352. // control highlighting
  353.         if(highlighted)
  354.         {
  355.             if(cursor_x < x || cursor_x >= x + w ||
  356.                 cursor_y < y || cursor_y >= y + h)
  357.             {
  358.                 highlighted = 0;
  359.                 draw_title();
  360.             }
  361.         }
  362.         else
  363.         {
  364.             if(cursor_x >= x && cursor_x < x + w &&
  365.                 cursor_y >= y && cursor_y < y + h)
  366.             {
  367.                 menu_bar->unhighlight();
  368.                 highlighted = 1;
  369.                 draw_title();
  370.                 result = 1;
  371.             }
  372.         }
  373.     }
  374.     return result;
  375. }
  376.  
  377. int BC_Menu::dispatch_cursor_leave()
  378. {
  379.     if(active)
  380.     {
  381.         menu_popup->dispatch_cursor_leave();
  382.     }
  383.     unhighlight();
  384.     return 0;
  385. }
  386.  
  387. int BC_Menu::dispatch_translation_event()
  388. {
  389.     if(active)
  390.     {
  391.         menu_popup->dispatch_translation_event();
  392.     }
  393.     return 0;
  394. }
  395.  
  396. int BC_Menu::activate_menu()
  397. {
  398.     Window tempwin;
  399.     int new_x, new_y, top_w, top_h;
  400.     if(menu_bar)
  401.     {
  402.         XTranslateCoordinates(top_level->display, 
  403.             menu_bar->win, 
  404.             top_level->rootwin, 
  405.             x, 
  406.             y, 
  407.             &new_x, 
  408.             &new_y, 
  409.             &tempwin);
  410.         menu_popup->activate_menu(new_x, new_y, w, h, 0, 1);
  411.     }
  412.     else
  413.         menu_popup->activate_menu(x, y, w, h, 1, 1);
  414.  
  415.     active = 1;
  416.     draw_title();
  417.     return 0;
  418. }
  419.  
  420. int BC_Menu::set_text(char *text)
  421. {
  422.     strcpy(this->text, text);
  423.     draw_title();
  424.     return 0;
  425. }
  426.  
  427. int BC_Menu::draw_title()
  428. {
  429.     if(active && menu_popup)
  430.     {
  431. // Menu is pulled down and title is recessed.
  432.         menu_bar->draw_3d_box(x, y, w, h, 
  433.             top_level->get_resources()->menu_shadow, 
  434.             BLACK, 
  435.             top_level->get_resources()->menu_down,
  436.             top_level->get_resources()->menu_down,
  437.             top_level->get_resources()->menu_light);
  438.     }
  439.     else
  440. // Menu is not pulled down.
  441.     {
  442.         if(highlighted)
  443.         {
  444.             menu_bar->set_color(top_level->get_resources()->menu_highlighted);
  445.             menu_bar->draw_box(x, y, w, h);
  446.         }
  447.         else
  448.         {
  449.             menu_bar->draw_background(x, y, w, h);
  450.         }
  451.     
  452.     }
  453.  
  454.     menu_bar->set_color(BLACK);
  455.     menu_bar->set_font(MEDIUMFONT);
  456.     menu_bar->draw_text(x + 10, h - menu_bar->get_text_descent(MEDIUMFONT), text);
  457.     menu_bar->flash();
  458.     return 0;
  459. }
  460.  
  461. int BC_Menu::deactivate_menu()
  462. {
  463.     if(active)
  464.     {
  465.         menu_popup->deactivate_menu();
  466.         active = 0;
  467.         draw_title();
  468.     }
  469.     return 0;
  470. }
  471.  
  472. int BC_Menu::unhighlight()
  473. {
  474.     if(highlighted)
  475.     {
  476.         highlighted = 0;
  477.         draw_title();
  478.     }
  479.     return 0;
  480. }
  481.  
  482. // ==================================== Menu Popup =============================
  483.  
  484. // Types of menu popups
  485. #define MENUPOPUP_MENUBAR 0
  486. #define MENUPOPUP_SUBMENU 1
  487. #define MENUPOPUP_POPUP   2
  488.  
  489. BC_MenuPopup::BC_MenuPopup()
  490. {
  491. }
  492.  
  493. BC_MenuPopup::~BC_MenuPopup()
  494. {
  495.     while(menu_items.total)
  496.     {
  497. // Each menuitem recursively removes itself from the arraylist
  498.         delete menu_items.values[0];
  499.     }
  500. }
  501.  
  502. int BC_MenuPopup::initialize(BC_WindowBase *top_level, 
  503.         BC_MenuBar *menu_bar, 
  504.         BC_Menu *menu, 
  505.         BC_MenuItem *menu_item, 
  506.         BC_PopupMenu *popup_menu)
  507. {
  508.     popup = 0;
  509.     active = 0;
  510.     this->menu = menu;
  511.     this->menu_bar = menu_bar;
  512.     this->menu_item = menu_item;
  513.     this->popup_menu = popup_menu;
  514.     this->top_level = top_level;
  515.  
  516.     if(menu_item) this->type = MENUPOPUP_SUBMENU;
  517.     else
  518.     if(menu) this->type = MENUPOPUP_MENUBAR;
  519.     else
  520.     if(popup_menu) this->type = MENUPOPUP_POPUP;
  521.  
  522.     return 0;
  523. }
  524.  
  525. int BC_MenuPopup::add_item(BC_MenuItem *item)
  526. {
  527.     menu_items.append(item);
  528.     item->initialize(top_level, menu_bar, this);
  529.     return 0;
  530. }
  531.  
  532. int BC_MenuPopup::remove_item(BC_MenuItem *item)
  533. {
  534.     if(!item)
  535.     {
  536.         item = menu_items.values[menu_items.total - 1];
  537.         delete item;
  538.     }
  539.     if(item) menu_items.remove(item);
  540.     return 0;
  541. }
  542.  
  543. int BC_MenuPopup::total_menuitems()
  544. {
  545.     return menu_items.total;
  546. }
  547.  
  548. int BC_MenuPopup::dispatch_button_press()
  549. {
  550.     int result = 0;
  551.     if(popup)
  552.     {
  553.         for(int i = 0; i < menu_items.total && !result; i++)
  554.         {
  555.             result = menu_items.values[i]->dispatch_button_press();
  556.         }
  557.         if(result) draw_items();
  558.     }
  559.     return 0;
  560. }
  561.  
  562. int BC_MenuPopup::dispatch_button_release()
  563. {
  564.     int result = 0, redraw = 0;
  565.     if(popup)
  566.     {
  567.         for(int i = 0; i < menu_items.total && !result; i++)
  568.         {
  569.             result = menu_items.values[i]->dispatch_button_release(redraw);
  570.         }
  571.         if(redraw) draw_items();
  572.     }
  573.     return result;
  574. }
  575.  
  576. int BC_MenuPopup::dispatch_key_press()
  577. {
  578.     int result = 0;
  579.     for(int i = 0; i < menu_items.total && !result; i++)
  580.     {
  581.         result = menu_items.values[i]->dispatch_key_press();
  582.     }
  583.     return result;
  584. }
  585.  
  586. int BC_MenuPopup::dispatch_motion_event()
  587. {
  588.     int i, result = 0, redraw = 0;
  589.     Window tempwin;
  590.  
  591.     if(popup)
  592.     {
  593. // Try submenus and items
  594.         for(i = 0; i < menu_items.total; i++)
  595.         {
  596.             result |= menu_items.values[i]->dispatch_motion_event(redraw);
  597.         }
  598.  
  599.         if(redraw) draw_items();
  600.     }
  601.  
  602.     return result;
  603. }
  604.  
  605. int BC_MenuPopup::dispatch_translation_event()
  606. {
  607.     if(popup)
  608.     {
  609.         int new_x = x + (top_level->last_translate_x - top_level->x);
  610.         int new_y = y + (top_level->last_translate_y - top_level->y);
  611.  
  612.         popup->reposition_window(new_x, new_y, popup->get_w(), popup->get_h());
  613.         top_level->flush();
  614.         this->x = new_x;
  615.         this->y = new_y;
  616.  
  617.         for(int i = 0; i < menu_items.total; i++)
  618.         {
  619.             menu_items.values[i]->dispatch_translation_event();
  620.         }
  621.     }
  622.     return 0;
  623. }
  624.  
  625.  
  626. int BC_MenuPopup::dispatch_cursor_leave()
  627. {
  628.     int result = 0;
  629.     
  630.     if(popup)
  631.     {
  632.         for(int i = 0; i < menu_items.total; i++)
  633.         {
  634.             result |= menu_items.values[i]->dispatch_cursor_leave();
  635.         }
  636.         if(result) draw_items();
  637.     }
  638.     return 0;
  639. }
  640.  
  641. int BC_MenuPopup::activate_menu(int x, 
  642.     int y, 
  643.     int w, 
  644.     int h, 
  645.     int top_window_coords, 
  646.     int vertical_justify)
  647. {
  648.     Window tempwin;
  649.     int new_x, new_y, top_w, top_h;
  650.     top_w = top_level->get_root_w();
  651.     top_h = top_level->get_root_h();
  652.  
  653.     get_dimensions();
  654.  
  655. // Coords are relative to the main window
  656.     if(top_window_coords)
  657.         XTranslateCoordinates(top_level->display, 
  658.             top_level->win, 
  659.             top_level->rootwin, 
  660.             x, 
  661.             y, 
  662.             &new_x, 
  663.             &new_y, 
  664.             &tempwin);
  665.     else
  666. // Coords are absolute
  667.     {
  668.         new_x = x; 
  669.         new_y = y; 
  670.     }
  671.  
  672. // All coords are now relative to root window.
  673.     if(vertical_justify)
  674.     {
  675.         this->x = new_x;
  676.         this->y = new_y + h;
  677.         if(this->x + this->w > top_w) this->x -= this->x + this->w - top_w; // Right justify
  678.         if(this->y + this->h > top_h) this->y -= this->h + h; // Bottom justify
  679.     }
  680.     else
  681.     {
  682.         this->x = new_x + w;
  683.         this->y = new_y;
  684.         if(this->x + this->w > top_w) this->x = new_x - this->w;
  685.         if(this->y + this->h > top_h) this->y = new_y + h - this->h;
  686.     }
  687.  
  688.     active = 1;
  689.     if(menu_bar)
  690.     {
  691.         popup = new BC_Popup(menu_bar, 
  692.                     this->x, 
  693.                     this->y, 
  694.                     this->w, 
  695.                     this->h, 
  696.                     -1,
  697.                     1,
  698.                     menu_bar->bg_pixmap);
  699.     }
  700.     else
  701.     {
  702.         popup = new BC_Popup(top_level, 
  703.                     this->x, 
  704.                     this->y, 
  705.                     this->w, 
  706.                     this->h, 
  707.                     top_level->get_resources()->menu_light,
  708.                     1,
  709.                     0);
  710.         popup->set_background(top_level->get_resources()->menu_bg);
  711.     }
  712.     draw_items();
  713.     popup->show_window();
  714.     return 0;
  715. }
  716.  
  717. int BC_MenuPopup::deactivate_submenus(BC_MenuPopup *exclude)
  718. {
  719.     for(int i = 0; i < menu_items.total; i++)
  720.     {
  721.         menu_items.values[i]->deactivate_submenus(exclude);
  722.     }
  723.     return 0;
  724. }
  725.  
  726. int BC_MenuPopup::deactivate_menu()
  727. {
  728.     deactivate_submenus(0);
  729.  
  730.     if(popup) delete popup;
  731.     popup = 0;
  732.     active = 0;
  733.  
  734.     return 0;
  735. }
  736.  
  737. int BC_MenuPopup::draw_items()
  738. {
  739.     if(menu_bar)
  740.         popup->draw_top_tiles(menu_bar, 0, 0, w, h);
  741.     else
  742.         popup->draw_top_tiles(popup, 0, 0, w, h);
  743.  
  744.     popup->draw_3d_border(0, 0, w, h, 
  745.         top_level->get_resources()->menu_light,
  746.         top_level->get_resources()->menu_up,
  747.         top_level->get_resources()->menu_shadow,
  748.         BLACK);
  749.  
  750.     for(int i = 0; i < menu_items.total; i++)
  751.     {
  752.         menu_items.values[i]->draw();
  753.     }
  754.  
  755.     popup->flash();
  756.     return 0;
  757. }
  758.  
  759. int BC_MenuPopup::get_dimensions()
  760. {
  761.     int widest_text = 10, widest_key = 10;
  762.     int text_w, key_w;
  763.     int i = 0;
  764.  
  765. // pad for border
  766.     h = 2;
  767. // Set up parameters in each item and get total h. 
  768.     for(i = 0; i < menu_items.total; i++)
  769.     {
  770.         text_w = 10 + top_level->get_text_width(MEDIUMFONT, menu_items.values[i]->text);
  771.         if(menu_items.values[i]->checked) text_w += 20;
  772.  
  773.         key_w = 10 + top_level->get_text_width(MEDIUMFONT, menu_items.values[i]->hotkey_text);
  774.         if(text_w > widest_text) widest_text = text_w;
  775.         if(key_w > widest_key) widest_key = key_w;
  776.  
  777.         if(!strcmp(menu_items.values[i]->text, "-")) 
  778.             menu_items.values[i]->h = 5;
  779.         else
  780.             menu_items.values[i]->h = top_level->get_text_height(MEDIUMFONT) + 4;
  781.  
  782.         menu_items.values[i]->y = h;
  783.         menu_items.values[i]->highlighted = 0;
  784.         menu_items.values[i]->down = 0;
  785.         h += menu_items.values[i]->h;
  786.     }
  787.     w = widest_text + widest_key + 10;
  788. // pad for division
  789.     key_x = widest_text + 5;
  790. // pad for border
  791.     h += 2;
  792.     return 0;
  793. }
  794.  
  795. int BC_MenuPopup::get_key_x()
  796. {
  797.     return key_x;
  798. }
  799.  
  800. BC_Popup* BC_MenuPopup::get_popup()
  801. {
  802.     return popup;
  803. }
  804.  
  805. int BC_MenuPopup::get_w()
  806. {
  807.     return w;
  808. }
  809.  
  810.  
  811.  
  812.  
  813.  
  814. // ================================ Menu Item ==================================
  815.  
  816. BC_MenuItem::BC_MenuItem(char *text, char *hotkey_text, int hotkey)
  817. {
  818.     strcpy(this->text, text);
  819.     strcpy(this->hotkey_text, hotkey_text);
  820.     this->hotkey = hotkey;
  821.     checked = 0;
  822.     highlighted = 0;
  823.     down = 0;
  824.     submenu = 0;
  825.     shift_hotkey = 0;
  826. }
  827.  
  828. BC_MenuItem::~BC_MenuItem()
  829. {
  830.     if(submenu) delete submenu;
  831.     menu_popup->remove_item(this);
  832. }
  833.  
  834. int BC_MenuItem::initialize(BC_WindowBase *top_level, BC_MenuBar *menu_bar, BC_MenuPopup *menu_popup)
  835. {
  836.     this->top_level = top_level;
  837.     this->menu_popup = menu_popup;
  838.     this->menu_bar = menu_bar;
  839.     return 0;
  840. }
  841.  
  842. int BC_MenuItem::set_checked(int value)
  843. {
  844.     this->checked = value;
  845.     return 0;
  846. }
  847.  
  848. int BC_MenuItem::get_checked()
  849. {
  850.     return checked;
  851. }
  852.  
  853. int BC_MenuItem::set_text(char *text)
  854. {
  855.     strcpy(this->text, text);
  856.     return 0;
  857. }
  858.  
  859. int BC_MenuItem::deactivate_submenus(BC_MenuPopup *exclude)
  860. {
  861.     if(submenu && submenu != exclude)
  862.     {
  863.         submenu->deactivate_submenus(exclude);
  864.         submenu->deactivate_menu();
  865.         highlighted = 0;
  866.     }
  867.     return 0;
  868. }
  869.  
  870. int BC_MenuItem::activate_submenu()
  871. {
  872.     int new_x, new_y;
  873.     if(menu_popup->popup && submenu && !submenu->popup)
  874.     {
  875.         Window tempwin;
  876.         XTranslateCoordinates(top_level->display, 
  877.             menu_popup->get_popup()->win, 
  878.             top_level->rootwin, 
  879.             0, 
  880.             y, 
  881.             &new_x, 
  882.             &new_y, 
  883.             &tempwin);
  884.         submenu->activate_menu(new_x + 5, new_y, menu_popup->w - 10, h, 0, 0);
  885.         highlighted = 1;
  886.     }
  887.     return 0;
  888. }
  889.  
  890.  
  891. int BC_MenuItem::dispatch_button_press()
  892. {
  893.     int result = 0;
  894.  
  895.     if(submenu)
  896.     {
  897.         result = submenu->dispatch_button_press();
  898.     }
  899.  
  900.     if(!result && top_level->event_win == menu_popup->get_popup()->win)
  901.     {
  902.         if(top_level->cursor_x >= 0 && top_level->cursor_x < menu_popup->get_w() &&
  903.             top_level->cursor_y >= y && top_level->cursor_y < y + h)
  904.         {
  905.             if(!highlighted)
  906.             {
  907.                 highlighted = 1;
  908.             }
  909.             result = 1;
  910.         }
  911.         else
  912.         if(highlighted)
  913.         {
  914.             highlighted = 0;
  915.             result = 1;
  916.         }
  917.     }
  918.  
  919.     return result;
  920. }
  921.  
  922. int BC_MenuItem::dispatch_button_release(int &redraw)
  923. {
  924.     int result = 0;
  925.     int cursor_x, cursor_y;
  926.     Window tempwin;
  927.  
  928.     if(submenu)
  929.     {
  930.         result = submenu->dispatch_button_release();
  931.     }
  932.  
  933.     if(!result)
  934.     {
  935.         XTranslateCoordinates(top_level->display, 
  936.             top_level->event_win, 
  937.             menu_popup->get_popup()->win, 
  938.             top_level->cursor_x, 
  939.             top_level->cursor_y, 
  940.             &cursor_x, 
  941.             &cursor_y, 
  942.             &tempwin);
  943.  
  944.         if(cursor_x >= 0 && cursor_x < menu_popup->get_w() &&
  945.             cursor_y >= y && cursor_y < y + h)
  946.         {
  947.             if(menu_bar)
  948.                 menu_bar->deactivate();
  949.             else
  950.                 menu_popup->popup_menu->deactivate();
  951.  
  952.             handle_event();
  953.             return 1;
  954.         }
  955.     }
  956.     return 0;
  957. }
  958.  
  959. int BC_MenuItem::dispatch_motion_event(int &redraw)
  960. {
  961.     int result = 0;
  962.     int cursor_x, cursor_y;
  963.     Window tempwin;
  964.  
  965.     if(submenu)
  966.     {
  967.         result = submenu->dispatch_motion_event();
  968.     }
  969.  
  970.     XTranslateCoordinates(top_level->display, 
  971.         top_level->event_win, 
  972.         menu_popup->get_popup()->win, 
  973.         top_level->cursor_x, 
  974.         top_level->cursor_y, 
  975.         &cursor_x, 
  976.         &cursor_y, 
  977.         &tempwin);
  978.  
  979.     if(cursor_x >= 0 && cursor_x < menu_popup->get_w() &&
  980.         cursor_y >= y && cursor_y < y + h)
  981.     {
  982. // Highlight the item
  983.         if(!highlighted)
  984.         {
  985. // Deactivate submenus in the parent menu excluding this one.
  986.             menu_popup->deactivate_submenus(submenu);
  987.             highlighted = 1;
  988.             if(submenu) activate_submenu();
  989.             redraw = 1;
  990.         }
  991.         result = 1;
  992.     }
  993.     else
  994.     if(highlighted)
  995.     {
  996.         highlighted = 0;
  997.         result = 1;
  998.         redraw = 1;
  999.     }
  1000.     return result;
  1001. }
  1002.  
  1003. int BC_MenuItem::dispatch_translation_event()
  1004. {
  1005.     if(submenu)
  1006.         submenu->dispatch_translation_event();
  1007.     return 0;
  1008. }
  1009.  
  1010. int BC_MenuItem::dispatch_cursor_leave()
  1011. {
  1012.     int result = 0;
  1013.     if(submenu)
  1014.     {
  1015.         result = submenu->dispatch_cursor_leave();
  1016.     }
  1017.  
  1018.     if(!result && highlighted && top_level->event_win == menu_popup->get_popup()->win)
  1019.     {
  1020.         highlighted = 0;
  1021.         return 1;
  1022.     }
  1023.     return 0;
  1024. }
  1025.  
  1026. int BC_MenuItem::dispatch_key_press()
  1027. {
  1028.     int result = 0;
  1029.     if(submenu)
  1030.     {
  1031.         result = submenu->dispatch_key_press();
  1032.     }
  1033.     
  1034.     if(!result)
  1035.     {
  1036.         if(top_level->get_keypress() == hotkey && 
  1037.             shift_hotkey == top_level->shift_down())
  1038.         {
  1039.             result = 1;
  1040.             handle_event();
  1041.         }
  1042.     }
  1043.     return result;
  1044. }
  1045.  
  1046.  
  1047. int BC_MenuItem::draw()
  1048. {
  1049.     int text_line = top_level->get_text_descent(MEDIUMFONT);
  1050.     if(!strcmp(text, "-"))
  1051.     {
  1052.         menu_popup->get_popup()->set_color(DKGREY);
  1053.         menu_popup->get_popup()->draw_line(5, y + h / 2, menu_popup->get_w() - 5, y + h / 2);
  1054.         menu_popup->get_popup()->set_color(LTGREY);
  1055.         menu_popup->get_popup()->draw_line(5, y + h / 2 + 1, menu_popup->get_w() - 5, y + h / 2 + 1);
  1056.     }
  1057.     else
  1058.     {
  1059.         if(highlighted)
  1060.         {
  1061.             int y = this->y;
  1062.             int w = menu_popup->get_w() - 4;
  1063.             int h = this->h;
  1064.             
  1065.             if(top_level->get_button_down() && !submenu)
  1066.             {
  1067.                 menu_popup->get_popup()->draw_3d_box(2, y, menu_popup->get_w() - 4, h, 
  1068.                     top_level->get_resources()->menu_shadow,
  1069.                     BLACK,
  1070.                     top_level->get_resources()->menu_down,
  1071.                     top_level->get_resources()->menu_down,
  1072.                     top_level->get_resources()->menu_light);
  1073.             }
  1074.             else
  1075.             {
  1076.                 menu_popup->get_popup()->set_color(top_level->get_resources()->menu_highlighted);
  1077.                 menu_popup->get_popup()->draw_box(2, y, menu_popup->get_w() - 4, h);
  1078.             }
  1079.         }
  1080.  
  1081.         menu_popup->get_popup()->set_color(BLACK);
  1082.         if(checked)
  1083.         {
  1084.             menu_popup->get_popup()->draw_check(10, y + 2);
  1085.             menu_popup->get_popup()->set_font(MEDIUMFONT);
  1086.             menu_popup->get_popup()->draw_text(30, y + h - text_line - 2, text);
  1087.             menu_popup->get_popup()->draw_text(menu_popup->get_key_x(), y + h - text_line - 2, hotkey_text);
  1088.         }
  1089.         else
  1090.         {
  1091.             menu_popup->get_popup()->set_font(MEDIUMFONT);
  1092.             menu_popup->get_popup()->draw_text(10, y + h - text_line - 2, text);
  1093.             menu_popup->get_popup()->draw_text(menu_popup->get_key_x(), y + h - text_line - 2, hotkey_text);
  1094.         }
  1095.     }
  1096.     return 0;
  1097. }
  1098.  
  1099.  
  1100. int BC_MenuItem::add_submenu(BC_SubMenu *submenu)
  1101. {
  1102.     this->submenu = submenu;
  1103.     submenu->initialize(top_level, menu_bar, 0, this, 0);
  1104.     return 0;
  1105. }
  1106.  
  1107. char* BC_MenuItem::get_text()
  1108. {
  1109.     return text;
  1110. }
  1111.  
  1112. BC_WindowBase* BC_MenuItem::get_top_level()
  1113. {
  1114.     return top_level;
  1115. }
  1116.  
  1117. BC_PopupMenu* BC_MenuItem::get_popup_menu()
  1118. {
  1119.     return menu_popup->popup_menu;
  1120. }
  1121.  
  1122. int BC_MenuItem::set_shift(int value)
  1123. {
  1124.     shift_hotkey = value;
  1125.     return 0;
  1126. }
  1127.  
  1128. // ================================= Sub Menu ==================================
  1129.  
  1130. BC_SubMenu::BC_SubMenu() : BC_MenuPopup()
  1131. {
  1132. }
  1133.  
  1134. BC_SubMenu::~BC_SubMenu()
  1135. {
  1136. }
  1137.  
  1138. int BC_SubMenu::add_submenuitem(BC_MenuItem *item)
  1139. {
  1140.     add_item(item);
  1141.     return 0;
  1142. }
  1143.  
  1144.  
  1145.  
  1146.  
  1147.