diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index af2a7a5c2..2dd5b4fc0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -300,7 +300,7 @@ add_library(aseprite-library widgets/fileview.cpp widgets/groupbut.cpp widgets/hex_color_entry.cpp - widgets/menuitem.cpp + widgets/menuitem2.cpp widgets/palette_view.cpp widgets/popup_frame_pin.cpp widgets/statebar.cpp diff --git a/src/app.cpp b/src/app.cpp index c3d29158f..33962d950 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -54,7 +54,7 @@ #include "widgets/color_bar.h" #include "widgets/editor/editor.h" #include "widgets/editor/editor_view.h" -#include "widgets/menuitem.h" +#include "widgets/menuitem2.h" #include "widgets/statebar.h" #include "widgets/tabs.h" #include "widgets/toolbar.h" @@ -101,7 +101,7 @@ static Widget* box_colorbar = NULL; /* box where the color bar is */ static Widget* box_toolbar = NULL; /* box where the tools bar is */ static Widget* box_statusbar = NULL; /* box where the status bar is */ static Widget* box_tabsbar = NULL; /* box where the tabs bar is */ -static Widget* menubar = NULL; /* the menu bar widget */ +static MenuBar* menubar = NULL; /* the menu bar widget */ static StatusBar* statusbar = NULL; /* the status bar widget */ static ColorBar* colorbar = NULL; /* the color bar widget */ static Widget* toolbar = NULL; /* the tool bar widget */ @@ -180,7 +180,7 @@ int App::run() box_statusbar = top_window->findChild("statusbar"); box_tabsbar = top_window->findChild("tabsbar"); - menubar = jmenubar_new(); + menubar = new MenuBar(); statusbar = new StatusBar(); colorbar = new ColorBar(box_colorbar->getAlign()); toolbar = toolbar_new(); @@ -200,7 +200,7 @@ int App::run() view->attachToView(editor); /* setup the menus */ - jmenubar_set_menu(menubar, get_root_menu()); + menubar->setMenu(get_root_menu()); /* start text of status bar */ app_default_statusbar_message(); @@ -288,7 +288,7 @@ int App::run() // Remove the root-menu from the menu-bar (because the rootmenu // module should destroy it). - jmenubar_set_menu(menubar, NULL); + menubar->setMenu(NULL); // Destroy the top-window jwidget_free(top_window); @@ -402,25 +402,25 @@ void app_update_document_tab(const Document* document) */ bool app_realloc_recent_list() { - Widget* list_menuitem = get_recent_list_menuitem(); - Widget* menuitem; + MenuItem* list_menuitem = get_recent_list_menuitem(); + MenuItem* menuitem; /* update the recent file list menu item */ if (list_menuitem) { - if (jmenuitem_has_submenu_opened(list_menuitem)) + if (list_menuitem->hasSubmenuOpened()) return false; Command* cmd_open_file = CommandsModule::instance()->getCommandByName(CommandId::OpenFile); - Widget* submenu = jmenuitem_get_submenu(list_menuitem); + Menu* submenu = list_menuitem->getSubmenu(); if (submenu) { - jmenuitem_set_submenu(list_menuitem, NULL); + list_menuitem->setSubmenu(NULL); jwidget_free(submenu); } // Build the menu of recent files - submenu = jmenu_new(); - jmenuitem_set_submenu(list_menuitem, submenu); + submenu = new Menu(); + list_menuitem->setSubmenu(submenu); RecentFiles::const_iterator it = App::instance()->getRecentFiles()->begin(); RecentFiles::const_iterator end = App::instance()->getRecentFiles()->end(); @@ -433,12 +433,12 @@ bool app_realloc_recent_list() params.set("filename", filename); - menuitem = menuitem_new(get_filename(filename), cmd_open_file, ¶ms); + menuitem = new MenuItem2(get_filename(filename), cmd_open_file, ¶ms); submenu->addChild(menuitem); } } else { - menuitem = menuitem_new("Nothing", NULL, NULL); + menuitem = new MenuItem2("Nothing", NULL, NULL); menuitem->setEnabled(false); submenu->addChild(menuitem); } @@ -462,7 +462,7 @@ int app_get_current_image_type() } Frame* app_get_top_window() { return top_window; } -Widget* app_get_menubar() { return menubar; } +MenuBar* app_get_menubar() { return menubar; } StatusBar* app_get_statusbar() { return statusbar; } ColorBar* app_get_colorbar() { return colorbar; } Widget* app_get_toolbar() { return toolbar; } diff --git a/src/app.h b/src/app.h index 47979982f..2e0bc05ff 100644 --- a/src/app.h +++ b/src/app.h @@ -34,6 +34,7 @@ class Frame; class Layer; class LegacyModules; class LoggerModule; +class MenuBar; class Params; class RecentFiles; class StatusBar; @@ -96,7 +97,7 @@ bool app_realloc_recent_list(); int app_get_current_image_type(); Frame* app_get_top_window(); -Widget* app_get_menubar(); +MenuBar* app_get_menubar(); StatusBar* app_get_statusbar(); ColorBar* app_get_colorbar(); Widget* app_get_toolbar(); diff --git a/src/dialogs/aniedit.cpp b/src/dialogs/aniedit.cpp index 23194ff74..2f20f27b0 100644 --- a/src/dialogs/aniedit.cpp +++ b/src/dialogs/aniedit.cpp @@ -529,9 +529,9 @@ bool AnimationEditor::onProcessMessage(Message* msg) // Show the frame pop-up menu. if (msg->mouse.right) { if (m_clk_frame == m_hot_frame) { - JWidget popup_menu = get_frame_popup_menu(); + Menu* popup_menu = get_frame_popup_menu(); if (popup_menu != NULL) { - jmenu_popup(popup_menu, msg->mouse.x, msg->mouse.y); + popup_menu->showPopup(msg->mouse.x, msg->mouse.y); destroy_thumbnails(); invalidate(); @@ -571,9 +571,9 @@ bool AnimationEditor::onProcessMessage(Message* msg) // Show the layer pop-up menu. if (msg->mouse.right) { if (m_clk_layer == m_hot_layer) { - JWidget popup_menu = get_layer_popup_menu(); + Menu* popup_menu = get_layer_popup_menu(); if (popup_menu != NULL) { - jmenu_popup(popup_menu, msg->mouse.x, msg->mouse.y); + popup_menu->showPopup(msg->mouse.x, msg->mouse.y); destroy_thumbnails(); invalidate(); @@ -654,10 +654,10 @@ bool AnimationEditor::onProcessMessage(Message* msg) // Show the cel pop-up menu. if (msg->mouse.right) { - JWidget popup_menu = movement ? get_cel_movement_popup_menu(): - get_cel_popup_menu(); + Menu* popup_menu = movement ? get_cel_movement_popup_menu(): + get_cel_popup_menu(); if (popup_menu != NULL) { - jmenu_popup(popup_menu, msg->mouse.x, msg->mouse.y); + popup_menu->showPopup(msg->mouse.x, msg->mouse.y); destroy_thumbnails(); regenerateLayers(); diff --git a/src/gui/menu.cpp b/src/gui/menu.cpp index 5262734f6..8f3959751 100644 --- a/src/gui/menu.cpp +++ b/src/gui/menu.cpp @@ -44,28 +44,8 @@ JM_MESSAGE(exe_menuitem); #define JM_EXE_MENUITEM jm_exe_menuitem() -////////////////////////////////////////////////////////////////////// -// Some auxiliar matros - -#define MOUSE_IN(pos) \ - ((jmouse_x(0) >= pos->x1) && (jmouse_x(0) < pos->x2) && \ - (jmouse_y(0) >= pos->y1) && (jmouse_y(0) < pos->y2)) - -#define MBOX(widget) \ - ((MenuBox*)jwidget_get_data((widget), JI_MENUBOX)) - -#define MENU(widget) \ - ((Menu*)jwidget_get_data((widget), JI_MENU)) - -#define MITEM(widget) \ - ((MenuItem*)jwidget_get_data((widget), JI_MENUITEM)) - -#define HAS_SUBMENU(menuitem) \ - ((MITEM(menuitem)->submenu) && \ - (!jlist_empty(MITEM(menuitem)->submenu->children))) - // Data for the main jmenubar or the first popuped-jmenubox -struct Base +struct MenuBaseData { // True when the menu-items must be opened with the cursor movement bool was_clicked : 1; @@ -79,200 +59,145 @@ struct Base bool is_filtering : 1; bool close_all : 1; + + MenuBaseData() + { + was_clicked = false; + is_filtering = false; + is_processing = false; + close_all = false; + } + }; -// Data for a jmenu -struct Menu -{ - Widget* menuitem; // From where the menu was open -}; +static MenuBox* get_base_menubox(Widget* widget); +static MenuBaseData* get_base(Widget* widget); -// Data for a jmenubox -struct MenuBox -{ - Base *base; -}; - -// Data for a jmenuitem -struct MenuItem -{ - JAccel accel; // Hot-key - bool highlight : 1; // Is it highlighted? - Widget* submenu; // The sub-menu - Widget* submenu_menubox; // The opened menubox for this menu-item - int submenu_timer; // Timer to open the submenu -}; - -static bool menu_msg_proc(Widget* widget, Message* msg); -static void menu_request_size(Widget* widget, int *w, int *h); -static void menu_set_position(Widget* widget, JRect rect); - -static bool menubox_msg_proc(Widget* widget, Message* msg); -static void menubox_request_size(Widget* widget, int *w, int *h); -static void menubox_set_position(Widget* widget, JRect rect); - -static bool menuitem_msg_proc(Widget* widget, Message* msg); -static void menuitem_request_size(Widget* widget, int *w, int *h); - -static Widget* get_base_menubox(Widget* widget); -static Base *get_base(Widget* widget); -static Base *create_base(Widget* widget); - -static Widget* get_highlight(Widget* menu); -static void set_highlight(Widget* menu, Widget* menuitem, bool click, bool open_submenu, bool select_first_child); -static void unhighlight(Widget* menu); - -static void open_menuitem(Widget* menuitem, bool select_first); -static void close_menuitem(Widget* menuitem, bool last_of_close_chain); -static void close_popup(Widget* menubox); -static void close_all(Widget* menu); -static void exe_menuitem(Widget* menuitem); static bool window_msg_proc(Widget* widget, Message* msg); -static Widget* check_for_letter(Widget* menu, int ascii); -static Widget* check_for_accel(Widget* menu, Message* msg); +static MenuItem* check_for_letter(Menu* menu, int ascii); +static MenuItem* check_for_accel(Menu* menu, Message* msg); -static Widget* find_nextitem(Widget* menu, Widget* menuitem); -static Widget* find_previtem(Widget* menu, Widget* menuitem); +static MenuItem* find_nextitem(Menu* menu, MenuItem* menuitem); +static MenuItem* find_previtem(Menu* menu, MenuItem* menuitem); -Widget* jmenu_new() +Menu::Menu() + : Widget(JI_MENU) + , m_menuitem(NULL) { - Widget* widget = new Widget(JI_MENU); - Menu* menu = new Menu; - - menu->menuitem = NULL; - - jwidget_add_hook(widget, JI_MENU, menu_msg_proc, menu); - widget->initTheme(); - - return widget; + initTheme(); } -Widget* jmenubar_new() +Menu::~Menu() { - Widget* widget = jmenubox_new(); - - create_base(widget); - - widget->type = JI_MENUBAR; - widget->initTheme(); - - return widget; -} - -Widget* jmenubox_new() -{ - Widget* widget = new Widget(JI_MENUBOX); - MenuBox* menubox = new MenuBox; - - menubox->base = NULL; - - jwidget_add_hook(widget, JI_MENUBOX, menubox_msg_proc, menubox); - jwidget_focusrest(widget, true); - widget->initTheme(); - - return widget; -} - -Widget* jmenuitem_new(const char *text) -{ - Widget* widget = new Widget(JI_MENUITEM); - MenuItem* menuitem = new MenuItem; - - menuitem->accel = NULL; - menuitem->highlight = false; - menuitem->submenu = NULL; - menuitem->submenu_menubox = NULL; - menuitem->submenu_timer = -1; - - jwidget_add_hook(widget, JI_MENUITEM, menuitem_msg_proc, menuitem); - widget->setText(text); - widget->initTheme(); - - return widget; -} - -Widget* jmenubox_get_menu(Widget* widget) -{ - ASSERT_VALID_WIDGET(widget); - - if (jlist_empty(widget->children)) - return NULL; - else - return (Widget*)jlist_first(widget->children)->data; -} - -Widget* jmenubar_get_menu(Widget* widget) -{ - ASSERT_VALID_WIDGET(widget); - - return jmenubox_get_menu(widget); -} - -Widget* jmenuitem_get_submenu(Widget* widget) -{ - MenuItem *menuitem; - - ASSERT_VALID_WIDGET(widget); - - menuitem = MITEM(widget); - - return menuitem->submenu ? menuitem->submenu: NULL; -} - -JAccel jmenuitem_get_accel(Widget* widget) -{ - ASSERT_VALID_WIDGET(widget); - - return MITEM(widget)->accel; -} - -bool jmenuitem_has_submenu_opened(Widget* widget) -{ - ASSERT_VALID_WIDGET(widget); - - return MITEM(widget)->submenu_menubox != NULL; -} - -void jmenubox_set_menu(Widget* widget, Widget* widget_menu) -{ - Widget* old_menu; - - ASSERT_VALID_WIDGET(widget); - - old_menu = jmenubox_get_menu(widget); - if (old_menu) - widget->removeChild(old_menu); - - if (widget_menu) { - ASSERT_VALID_WIDGET(widget_menu); - widget->addChild(widget_menu); + if (m_menuitem) { + if (m_menuitem->getSubmenu() == this) { + m_menuitem->setSubmenu(NULL); + } + else { + ASSERT(m_menuitem->getSubmenu() == NULL); + } } } -void jmenubar_set_menu(Widget* widget, Widget* widget_menu) +MenuBox::MenuBox(int type) + : Widget(type) + , m_base(NULL) { - ASSERT_VALID_WIDGET(widget); - - jmenubox_set_menu(widget, widget_menu); + jwidget_focusrest(this, true); + initTheme(); } -void jmenuitem_set_submenu(Widget* widget, Widget* widget_menu) +MenuBox::~MenuBox() { - MenuItem *menuitem; + if (m_base && m_base->is_filtering) { + m_base->is_filtering = false; + jmanager_remove_msg_filter(JM_BUTTONPRESSED, this); + } - ASSERT_VALID_WIDGET(widget); + delete m_base; +} - menuitem = MITEM(widget); +MenuBar::MenuBar() + : MenuBox(JI_MENUBAR) +{ + createBase(); +} - if (menuitem->submenu) - MENU(menuitem->submenu)->menuitem = NULL; +MenuItem::MenuItem(const char *text) + : Widget(JI_MENUITEM) +{ + m_accel = NULL; + m_highlighted = false; + m_submenu = NULL; + m_submenu_menubox = NULL; + m_submenu_timer = -1; - menuitem->submenu = widget_menu; + setText(text); + initTheme(); +} - if (menuitem->submenu) { - ASSERT_VALID_WIDGET(widget_menu); - MENU(menuitem->submenu)->menuitem = widget; +MenuItem::~MenuItem() +{ + if (m_accel) + jaccel_free(m_accel); + + if (m_submenu) + jwidget_free(m_submenu); + + // Stop timer to open the popup + if (m_submenu_timer >= 0) { + jmanager_remove_timer(m_submenu_timer); + m_submenu_timer = -1; + } +} + +Menu* MenuBox::getMenu() +{ + if (jlist_empty(children)) + return NULL; + else + return static_cast(jlist_first(children)->data); +} + +MenuBaseData* MenuBox::createBase() +{ + delete m_base; + m_base = new MenuBaseData(); + return m_base; +} + +Menu* MenuItem::getSubmenu() +{ + return m_submenu; +} + +JAccel MenuItem::getAccel() +{ + return m_accel; +} + +void MenuBox::setMenu(Menu* menu) +{ + if (Menu* oldMenu = getMenu()) + removeChild(oldMenu); + + if (menu) { + ASSERT_VALID_WIDGET(menu); + addChild(menu); + } +} + +void MenuItem::setSubmenu(Menu* menu) +{ + if (m_submenu) + m_submenu->setOwnerMenuItem(NULL); + + m_submenu = menu; + + if (m_submenu) { + ASSERT_VALID_WIDGET(m_submenu); + m_submenu->setOwnerMenuItem(this); } } @@ -283,39 +208,39 @@ void jmenuitem_set_submenu(Widget* widget, Widget* widget_menu) * @warning The specified @a accel will be freed automatically when * the menu-item'll receive JM_DESTROY message. */ -void jmenuitem_set_accel(Widget* widget, JAccel accel) +void MenuItem::setAccel(JAccel accel) { - MenuItem *menuitem; + if (m_accel) + jaccel_free(m_accel); - ASSERT_VALID_WIDGET(widget); - - menuitem = MITEM(widget); - if (menuitem->accel) - jaccel_free(menuitem->accel); - - menuitem->accel = accel; + m_accel = accel; } -int jmenuitem_is_highlight(Widget* widget) +bool MenuItem::isHighlighted() const { - ASSERT_VALID_WIDGET(widget); - - return MITEM(widget)->highlight; + return m_highlighted; } -void jmenu_popup(Widget* menu, int x, int y) +void MenuItem::setHighlighted(bool state) { - Base *base; + m_highlighted = state; +} +bool MenuItem::hasSubmenu() const +{ + return (m_submenu && !jlist_empty(m_submenu->children)); +} + +void Menu::showPopup(int x, int y) +{ do { jmouse_poll(); } while (jmouse_b(0)); // New window and new menu-box Frame* window = new Frame(false, NULL); - Widget* menubox = jmenubox_new(); - - base = create_base(menubox); + MenuBox* menubox = new MenuBox(); + MenuBaseData* base = menubox->createBase(); base->was_clicked = true; base->is_filtering = true; jmanager_add_msg_filter(JM_BUTTONPRESSED, menubox); @@ -323,7 +248,7 @@ void jmenu_popup(Widget* menu, int x, int y) window->set_moveable(false); // Can't move the window // Set children - jmenubox_set_menu(menubox, menu); + menubox->setMenu(this); window->addChild(menubox); window->remap_window(); @@ -343,99 +268,82 @@ void jmenu_popup(Widget* menu, int x, int y) jmanager_free_focus(); // Fetch the "menu" so it isn't destroyed - jmenubox_set_menu(menubox, NULL); + menubox->setMenu(NULL); // Destroy the window jwidget_free(window); } -static bool menu_msg_proc(Widget* widget, Message* msg) +bool Menu::onProcessMessage(Message* msg) { switch (msg->type) { - case JM_DESTROY: { - Menu *menu = MENU(widget); - ASSERT(menu != NULL); - - if (menu->menuitem) { - if (MITEM(menu->menuitem)->submenu == widget) { - MITEM(menu->menuitem)->submenu = NULL; - } - else { - ASSERT(MITEM(menu->menuitem)->submenu == NULL); - } - } - - delete menu; - break; - } - case JM_REQSIZE: - menu_request_size(widget, &msg->reqsize.w, &msg->reqsize.h); + requestSize(&msg->reqsize.w, &msg->reqsize.h); return true; case JM_SETPOS: - menu_set_position(widget, &msg->setpos.rect); + set_position(&msg->setpos.rect); return true; case JM_DRAW: - widget->getTheme()->draw_menu(widget, &msg->draw.rect); + getTheme()->draw_menu(this, &msg->draw.rect); return true; } - return false; + return Widget::onProcessMessage(msg); } -static void menu_request_size(Widget* widget, int *w, int *h) +void Menu::requestSize(int *w, int *h) { Size reqSize; JLink link; *w = *h = 0; - JI_LIST_FOR_EACH(widget->children, link) { + JI_LIST_FOR_EACH(this->children, link) { reqSize = ((Widget*)link->data)->getPreferredSize(); - if (widget->parent->type == JI_MENUBAR) { - *w += reqSize.w + ((link->next != widget->children->end) ? - widget->child_spacing: 0); + if (this->parent->type == JI_MENUBAR) { + *w += reqSize.w + ((link->next != this->children->end) ? + this->child_spacing: 0); *h = MAX(*h, reqSize.h); } else { *w = MAX(*w, reqSize.w); - *h += reqSize.h + ((link->next != widget->children->end) ? - widget->child_spacing: 0); + *h += reqSize.h + ((link->next != this->children->end) ? + this->child_spacing: 0); } } - *w += widget->border_width.l + widget->border_width.r; - *h += widget->border_width.t + widget->border_width.b; + *w += this->border_width.l + this->border_width.r; + *h += this->border_width.t + this->border_width.b; } -static void menu_set_position(Widget* widget, JRect rect) +void Menu::set_position(JRect rect) { Size reqSize; Widget* child; JRect cpos; JLink link; - jrect_copy(widget->rc, rect); - cpos = jwidget_get_child_rect(widget); + jrect_copy(this->rc, rect); + cpos = jwidget_get_child_rect(this); - JI_LIST_FOR_EACH(widget->children, link) { + JI_LIST_FOR_EACH(this->children, link) { child = (Widget*)link->data; reqSize = child->getPreferredSize(); - if (widget->parent->type == JI_MENUBAR) + if (this->parent->type == JI_MENUBAR) cpos->x2 = cpos->x1+reqSize.w; else cpos->y2 = cpos->y1+reqSize.h; jwidget_set_rect(child, cpos); - if (widget->parent->type == JI_MENUBAR) + if (this->parent->type == JI_MENUBAR) cpos->x1 += jrect_w(cpos); else cpos->y1 += jrect_h(cpos); @@ -444,109 +352,87 @@ static void menu_set_position(Widget* widget, JRect rect) jrect_free(cpos); } -static bool menubox_msg_proc(Widget* widget, Message* msg) +bool MenuBox::onProcessMessage(Message* msg) { - Widget* menu = jmenubox_get_menu(widget); + Menu* menu = MenuBox::getMenu(); switch (msg->type) { - case JM_DESTROY: { - MenuBox* menubox = reinterpret_cast(jwidget_get_data(widget, JI_MENUBOX)); - ASSERT(menubox != NULL); - - if (menubox->base != NULL && - menubox->base->is_filtering) { - menubox->base->is_filtering = false; - jmanager_remove_msg_filter(JM_BUTTONPRESSED, widget); - } - - delete menubox->base; - delete menubox; - break; - } - case JM_REQSIZE: - menubox_request_size(widget, &msg->reqsize.w, &msg->reqsize.h); + requestSize(&msg->reqsize.w, &msg->reqsize.h); return true; case JM_SETPOS: - menubox_set_position(widget, &msg->setpos.rect); + set_position(&msg->setpos.rect); return true; case JM_MOTION: /* isn't pressing a button? */ - if (!msg->mouse.flags && !get_base(widget)->was_clicked) + if (!msg->mouse.flags && !get_base(this)->was_clicked) break; // Fall though case JM_BUTTONPRESSED: if (menu) { - Widget* picked; - - if (get_base(widget)->is_processing) + if (get_base(this)->is_processing) break; // Here we catch the filtered messages (menu-bar or the // popuped menu-box) to detect if the user press outside of // the widget - if (msg->type == JM_BUTTONPRESSED - && MBOX(widget)->base != NULL) { + if (msg->type == JM_BUTTONPRESSED && m_base != NULL) { Widget* picked = ji_get_default_manager()->pick(msg->mouse.x, msg->mouse.y); // If one of these conditions are accomplished we have to // close all menus (back to menu-bar or close the popuped // menubox), this is the place where we control if... if (picked == NULL || // If the button was clicked nowhere - picked == widget || // If the button was clicked in this menubox + picked == this || // If the button was clicked in this menubox // The picked widget isn't menu-related (picked->type != JI_MENUBOX && picked->type != JI_MENUBAR && picked->type != JI_MENUITEM) || // The picked widget (that is menu-related) isn't from // the same tree of menus - (get_base_menubox(picked) != widget)) { + (get_base_menubox(picked) != this)) { // The user click outside all the menu-box/menu-items, close all - close_all(menu); + menu->closeAll(); return true; } } // Get the widget below the mouse cursor - picked = menu->pick(msg->mouse.x, msg->mouse.y); + Widget* picked = menu->pick(msg->mouse.x, msg->mouse.y); if (picked) { if ((picked->type == JI_MENUITEM) && !(picked->flags & JI_DISABLED)) { // If the picked menu-item is not highlighted... - if (!MITEM(picked)->highlight) { + if (!static_cast(picked)->isHighlighted()) { // In menu-bar always open the submenu, in other popup-menus // open the submenu only if the user does click bool open_submenu = - (widget->type == JI_MENUBAR) || + (this->type == JI_MENUBAR) || (msg->type == JM_BUTTONPRESSED); - set_highlight(menu, picked, false, open_submenu, false); + menu->highlightItem(static_cast(picked), false, open_submenu, false); } // If the user pressed in a highlighted menu-item (maybe // the user was waiting for the timer to open the // submenu...) else if (msg->type == JM_BUTTONPRESSED && - HAS_SUBMENU(picked)) { - // Stop timer to open the popup - if (MITEM(picked)->submenu_timer >= 0) { - jmanager_remove_timer(MITEM(picked)->submenu_timer); - MITEM(picked)->submenu_timer = -1; - } + static_cast(picked)->hasSubmenu()) { + static_cast(picked)->stopTimer(); // If the submenu is closed, open it - if (MITEM(picked)->submenu_menubox == NULL) - open_menuitem(picked, false); + if (!static_cast(picked)->hasSubmenuOpened()) + static_cast(picked)->openSubmenu(false); } } - else if (!get_base(widget)->was_clicked) { - unhighlight(menu); + else if (!get_base(this)->was_clicked) { + menu->unhighlightItem(); } } } @@ -554,83 +440,65 @@ static bool menubox_msg_proc(Widget* widget, Message* msg) case JM_MOUSELEAVE: if (menu) { - Widget* highlight; - - if (get_base(widget)->is_processing) + if (get_base(this)->is_processing) break; - highlight = get_highlight(menu); - if ((highlight) && (!MITEM(highlight)->submenu_menubox)) - unhighlight(menu); + MenuItem* highlight = menu->getHighlightedItem(); + if (highlight && !highlight->hasSubmenuOpened()) + menu->unhighlightItem(); } break; case JM_BUTTONRELEASED: if (menu) { - Widget* highlight = get_highlight(menu); - - if (get_base(widget)->is_processing) + if (get_base(this)->is_processing) break; // The item is highlighted and not opened (and the timer to open the submenu is stopped) - if ((highlight) && - (!MITEM(highlight)->submenu_menubox) && - (MITEM(highlight)->submenu_timer < 0)) { - close_all(menu); - exe_menuitem(highlight); + MenuItem* highlight = menu->getHighlightedItem(); + if (highlight && + !highlight->hasSubmenuOpened() && + highlight->m_submenu_timer < 0) { + menu->closeAll(); + highlight->executeClick(); } } break; case JM_KEYPRESSED: if (menu) { - Widget* selected; + MenuItem* selected; - if (get_base(widget)->is_processing) + if (get_base(this)->is_processing) break; - get_base(widget)->was_clicked = false; + get_base(this)->was_clicked = false; // Check for ALT+some letter in menubar and some letter in menuboxes - if (((widget->type == JI_MENUBOX) && (!msg->any.shifts)) || - ((widget->type == JI_MENUBAR) && (msg->any.shifts & KB_ALT_FLAG))) { + if (((this->type == JI_MENUBOX) && (!msg->any.shifts)) || + ((this->type == JI_MENUBAR) && (msg->any.shifts & KB_ALT_FLAG))) { selected = check_for_letter(menu, scancode_to_ascii(msg->key.scancode)); if (selected) { - set_highlight(menu, selected, true, true, true); + menu->highlightItem(selected, true, true, true); return true; } } -#if 0 // TODO check this for jinete-tests - // Only in menu-bars... - if (widget->type == JI_MENUBAR) { - // ...check for accelerators - selected = check_for_accel(menubox->menu, msg); - if (selected) { - close_all(menu); - exe_menuitem(selected); - return true; - } - } -#endif - // Highlight movement with keyboard - if (widget->hasFocus()) { - Widget* highlight = get_highlight(menu); - Widget* child; - Widget* child_with_submenu_opened = NULL; + if (this->hasFocus()) { + MenuItem* highlight = menu->getHighlightedItem(); + MenuItem* child_with_submenu_opened = NULL; JLink link; bool used = false; /* search a child with highlight or the submenu opened */ JI_LIST_FOR_EACH(menu->children, link) { - child = (Widget*)link->data; - + Widget* child = (Widget*)link->data; if (child->type != JI_MENUITEM) continue; - if (MITEM(child)->submenu_menubox) - child_with_submenu_opened = child; + if (static_cast(child)->hasSubmenuOpened()) + child_with_submenu_opened = static_cast(child); } if (!highlight && child_with_submenu_opened) @@ -640,9 +508,9 @@ static bool menubox_msg_proc(Widget* widget, Message* msg) case KEY_ESC: /* in menu-bar */ - if (widget->type == JI_MENUBAR) { + if (this->type == JI_MENUBAR) { if (highlight) { - close_all(menu); + menu->closeAll(); /* fetch the focus */ jmanager_free_focus(); @@ -652,13 +520,13 @@ static bool menubox_msg_proc(Widget* widget, Message* msg) /* in menu-boxes */ else { if (child_with_submenu_opened) { - close_menuitem(child_with_submenu_opened, true); + child_with_submenu_opened->closeSubmenu(true); used = true; } /* go to parent */ - else if (MENU(menu)->menuitem) { + else if (menu->m_menuitem) { /* just retrogress one parent-level */ - close_menuitem(MENU(menu)->menuitem, true); + menu->m_menuitem->closeSubmenu(true); used = true; } } @@ -666,62 +534,61 @@ static bool menubox_msg_proc(Widget* widget, Message* msg) case KEY_UP: /* in menu-bar */ - if (widget->type == JI_MENUBAR) { + if (this->type == JI_MENUBAR) { if (child_with_submenu_opened) - close_menuitem(child_with_submenu_opened, true); + child_with_submenu_opened->closeSubmenu(true); } /* in menu-boxes */ else { /* go to previous */ highlight = find_previtem(menu, highlight); - set_highlight(menu, highlight, false, false, false); + menu->highlightItem(highlight, false, false, false); } used = true; break; case KEY_DOWN: /* in menu-bar */ - if (widget->type == JI_MENUBAR) { + if (this->type == JI_MENUBAR) { /* select the active menu */ - set_highlight(menu, highlight, true, true, true); + menu->highlightItem(highlight, true, true, true); } /* in menu-boxes */ else { /* go to next */ highlight = find_nextitem(menu, highlight); - set_highlight(menu, highlight, false, false, false); + menu->highlightItem(highlight, false, false, false); } used = true; break; case KEY_LEFT: /* in menu-bar */ - if (widget->type == JI_MENUBAR) { + if (this->type == JI_MENUBAR) { /* go to previous */ highlight = find_previtem(menu, highlight); - set_highlight(menu, highlight, false, false, false); + menu->highlightItem(highlight, false, false, false); } /* in menu-boxes */ else { /* go to parent */ - if (MENU(menu)->menuitem) { - Widget* menuitem; - Widget* parent = MENU(menu)->menuitem->parent->parent; + if (menu->m_menuitem) { + Widget* parent = menu->m_menuitem->parent->parent; /* go to the previous item in the parent */ /* if the parent is the menu-bar */ if (parent->type == JI_MENUBAR) { - menu = jmenubox_get_menu(parent); - menuitem = find_previtem(menu, get_highlight(menu)); + menu = static_cast(parent)->getMenu(); + MenuItem* menuitem = find_previtem(menu, menu->getHighlightedItem()); /* go to previous item in the parent */ - set_highlight(menu, menuitem, false, true, true); + menu->highlightItem(menuitem, false, true, true); } /* if the parent isn't the menu-bar */ else { /* just retrogress one parent-level */ - close_menuitem(MENU(menu)->menuitem, true); + menu->m_menuitem->closeSubmenu(true); } } } @@ -730,30 +597,28 @@ static bool menubox_msg_proc(Widget* widget, Message* msg) case KEY_RIGHT: /* in menu-bar */ - if (widget->type == JI_MENUBAR) { + if (this->type == JI_MENUBAR) { /* go to next */ highlight = find_nextitem(menu, highlight); - set_highlight(menu, highlight, false, false, false); + menu->highlightItem(highlight, false, false, false); } /* in menu-boxes */ else { /* enter in sub-menu */ - if ((highlight) && HAS_SUBMENU(highlight)) { - set_highlight(menu, highlight, true, true, true); + if ((highlight) && highlight->hasSubmenu()) { + menu->highlightItem(highlight, true, true, true); } - /* go to parent */ - else if (MENU(menu)->menuitem) { - Widget* root, *menuitem; + // Go to parent + else if (menu->m_menuitem) { + // Get the root menu + MenuBox* root = get_base_menubox(this); + menu = root->getMenu(); - /* get the root menu */ - root = get_base_menubox(widget); - menu = jmenubox_get_menu(root); + // Go to the next item in the root + MenuItem* menuitem = find_nextitem(menu, menu->getHighlightedItem()); - /* go to the next item in the root */ - menuitem = find_nextitem(menu, get_highlight(menu)); - - /* open the sub-menu */ - set_highlight(menu, menuitem, false, true, true); + // Open the sub-menu + menu->highlightItem(menuitem, false, true, true); } } used = true; @@ -762,7 +627,7 @@ static bool menubox_msg_proc(Widget* widget, Message* msg) case KEY_ENTER: case KEY_ENTER_PAD: if (highlight) - set_highlight(menu, highlight, true, true, true); + menu->highlightItem(highlight, true, true, true); used = true; break; } @@ -774,21 +639,19 @@ static bool menubox_msg_proc(Widget* widget, Message* msg) default: if (msg->type == JM_CLOSE_POPUP) { - _jmanager_close_window(widget->getManager(), - static_cast(widget->getRoot()), true); + _jmanager_close_window(this->getManager(), + static_cast(this->getRoot()), true); } break; } - return false; + return Widget::onProcessMessage(msg); } -static void menubox_request_size(Widget* widget, int *w, int *h) +void MenuBox::requestSize(int* w, int* h) { - Widget* menu = jmenubox_get_menu(widget); - - if (menu) { + if (Menu* menu = getMenu()) { Size reqSize = menu->getPreferredSize(); *w = reqSize.w; *h = reqSize.h; @@ -796,105 +659,78 @@ static void menubox_request_size(Widget* widget, int *w, int *h) else *w = *h = 0; - *w += widget->border_width.l + widget->border_width.r; - *h += widget->border_width.t + widget->border_width.b; + *w += this->border_width.l + this->border_width.r; + *h += this->border_width.t + this->border_width.b; } -static void menubox_set_position(Widget* widget, JRect rect) +void MenuBox::set_position(JRect rect) { - Widget* menu = jmenubox_get_menu(widget); + jrect_copy(this->rc, rect); - jrect_copy(widget->rc, rect); - - if (menu) { - JRect cpos = jwidget_get_child_rect(widget); + if (Menu* menu = getMenu()) { + JRect cpos = jwidget_get_child_rect(this); jwidget_set_rect(menu, cpos); jrect_free(cpos); } } -static bool menuitem_msg_proc(Widget* widget, Message* msg) +bool MenuItem::onProcessMessage(Message* msg) { - MenuItem *menuitem = MITEM(widget); - switch (msg->type) { - case JM_DESTROY: - ASSERT(menuitem != NULL); - - if (menuitem->accel) - jaccel_free(menuitem->accel); - - if (menuitem->submenu) - jwidget_free(menuitem->submenu); - - // Stop timer to open the popup - if (menuitem->submenu_timer >= 0) { - jmanager_remove_timer(menuitem->submenu_timer); - menuitem->submenu_timer = -1; - } - - delete menuitem; - break; - case JM_REQSIZE: - menuitem_request_size(widget, &msg->reqsize.w, &msg->reqsize.h); + requestSize(&msg->reqsize.w, &msg->reqsize.h); return true; case JM_DRAW: - widget->getTheme()->draw_menuitem(widget, &msg->draw.rect); + getTheme()->draw_menuitem(this, &msg->draw.rect); return true; case JM_MOUSEENTER: // TODO theme specific!! - widget->invalidate(); + invalidate(); // When a menu item receives the mouse, start a timer to open the submenu... - if (widget->isEnabled() && HAS_SUBMENU(widget)) { + if (isEnabled() && hasSubmenu()) { // Start the timer to open the submenu... - if (menuitem->submenu_timer < 0) - menuitem->submenu_timer = jmanager_add_timer(widget, TIMEOUT_TO_OPEN_SUBMENU); - jmanager_start_timer(menuitem->submenu_timer); + startTimer(); } break; case JM_MOUSELEAVE: // TODO theme specific!! - widget->invalidate(); + invalidate(); // Stop timer to open the popup - if (menuitem->submenu_timer >= 0) { - jmanager_remove_timer(menuitem->submenu_timer); - menuitem->submenu_timer = -1; + if (m_submenu_timer >= 0) { + jmanager_remove_timer(m_submenu_timer); + m_submenu_timer = -1; } break; default: if (msg->type == JM_OPEN_MENUITEM) { - Base* base = get_base(widget); - Frame* window; - Widget* menubox; - JRect pos, old_pos; + MenuBaseData* base = get_base(this); + JRect pos; bool select_first = msg->user.a ? true: false; ASSERT(base != NULL); ASSERT(base->is_processing); - ASSERT(HAS_SUBMENU(widget)); + ASSERT(hasSubmenu()); - old_pos = jwidget_get_rect(widget->parent->parent); + JRect old_pos = jwidget_get_rect(this->parent->parent); // New window and new menu-box - window = new Frame(false, NULL); + Frame* window = new Frame(false, NULL); jwidget_add_hook(window, -1, window_msg_proc, NULL); - menubox = jmenubox_new(); - - menuitem->submenu_menubox = menubox; + MenuBox* menubox = new MenuBox(); + m_submenu_menubox = menubox; window->set_moveable(false); // Can't move the window // Set children - jmenubox_set_menu(menubox, menuitem->submenu); + menubox->setMenu(m_submenu); window->addChild(menubox); window->remap_window(); @@ -902,15 +738,15 @@ static bool menuitem_msg_proc(Widget* widget, Message* msg) // Menubox position pos = jwidget_get_rect(window); - if (widget->parent->parent->type == JI_MENUBAR) { + if (this->parent->parent->type == JI_MENUBAR) { jrect_moveto(pos, - MID(0, widget->rc->x1, JI_SCREEN_W-jrect_w(pos)), - MID(0, widget->rc->y2, JI_SCREEN_H-jrect_h(pos))); + MID(0, this->rc->x1, JI_SCREEN_W-jrect_w(pos)), + MID(0, this->rc->y2, JI_SCREEN_H-jrect_h(pos))); } else { - int x_left = widget->rc->x1-jrect_w(pos); - int x_right = widget->rc->x2; - int x, y = widget->rc->y1; + int x_left = this->rc->x1-jrect_w(pos); + int x_right = this->rc->x2; + int x, y = this->rc->y1; struct jrect r1, r2; int s1, s2; @@ -929,7 +765,7 @@ static bool menuitem_msg_proc(Widget* widget, Message* msg) s2 = jrect_intersect(&r2, old_pos); if (!s2) - x = x_right; // Use the right because there aren't intersection with it + x = x_right; // Use the right because there aren't intersection with it else if (!s1) x = x_left; // Use the left because there are not intersection else if (jrect_w(&r2)*jrect_h(&r2) <= jrect_w(&r1)*jrect_h(&r1)) @@ -949,28 +785,29 @@ static bool menuitem_msg_proc(Widget* widget, Message* msg) // Setup the highlight of the new menubox if (select_first) { // Select the first child - Widget* child, *first_child = NULL; + Widget* child; + MenuItem* first_child = NULL; JLink link; - JI_LIST_FOR_EACH(menuitem->submenu->children, link) { + JI_LIST_FOR_EACH(m_submenu->children, link) { child = (Widget*)link->data; if (child->type != JI_MENUITEM) continue; if (child->isEnabled()) { - first_child = child; + first_child = static_cast(child); break; } } if (first_child) - set_highlight(menuitem->submenu, first_child, false, false, false); + m_submenu->highlightItem(first_child, false, false, false); else - unhighlight(menuitem->submenu); + m_submenu->unhighlightItem(); } else - unhighlight(menuitem->submenu); + m_submenu->unhighlightItem(); // Run in background window->open_window_bg(); @@ -981,16 +818,15 @@ static bool menuitem_msg_proc(Widget* widget, Message* msg) return true; } else if (msg->type == JM_CLOSE_MENUITEM) { - Base* base = get_base(widget); + MenuBaseData* base = get_base(this); Frame* window; - Widget* menubox; - bool last_of_close_chain = msg->user.a ? true: false; + bool last_of_close_chain = (msg->user.a ? true: false); ASSERT(base != NULL); ASSERT(base->is_processing); - menubox = menuitem->submenu_menubox; - menuitem->submenu_menubox = NULL; + MenuBox* menubox = m_submenu_menubox; + m_submenu_menubox = NULL; ASSERT(menubox != NULL); @@ -998,7 +834,7 @@ static bool menuitem_msg_proc(Widget* widget, Message* msg) ASSERT(window && window->type == JI_FRAME); // Fetch the "menu" to avoid free it with 'jwidget_free()' - jmenubox_set_menu(menubox, NULL); + menubox->setMenu(NULL); // Destroy the window window->closeWindow(NULL); @@ -1007,7 +843,7 @@ static bool menuitem_msg_proc(Widget* widget, Message* msg) if (base->close_all) jmanager_free_focus(); else - jmanager_set_focus(widget->parent->parent); + jmanager_set_focus(this->parent->parent); // Is not necessary to free this window because it's // automatically destroyed by the manager @@ -1018,62 +854,65 @@ static bool menuitem_msg_proc(Widget* widget, Message* msg) base->is_processing = false; } - // Stop timer to open the popup - if (menuitem->submenu_timer >= 0) { - jmanager_remove_timer(menuitem->submenu_timer); - menuitem->submenu_timer = -1; - } - + // Stop timer to open the popup + stopTimer(); return true; } else if (msg->type == JM_EXE_MENUITEM) { - jwidget_emit_signal(widget, JI_SIGNAL_MENUITEM_SELECT); + onClick(); return true; } break; case JM_TIMER: - if (msg->timer.timer_id == menuitem->submenu_timer) { - Base* base = get_base(widget); + if (msg->timer.timer_id == m_submenu_timer) { + MenuBaseData* base = get_base(this); - ASSERT(HAS_SUBMENU(widget)); + ASSERT(hasSubmenu()); // Stop timer to open the popup - jmanager_remove_timer(menuitem->submenu_timer); - menuitem->submenu_timer = -1; + stopTimer(); // If the submenu is closed, and we are not processing messages, open it - if (menuitem->submenu_menubox == NULL && !base->is_processing) - open_menuitem(widget, false); + if (m_submenu_menubox == NULL && !base->is_processing) + openSubmenu(false); } break; } - return false; + return Widget::onProcessMessage(msg); } -static void menuitem_request_size(Widget* widget, int *w, int *h) +void MenuItem::onClick() { - MenuItem *menuitem = MITEM(widget); - int bar = widget->parent->parent->type == JI_MENUBAR; + // Fire old JI_SIGNAL_MENUITEM_SELECT signal + jwidget_emit_signal(this, JI_SIGNAL_MENUITEM_SELECT); - if (widget->hasText()) { + // Fire new Click() signal. + Click(); +} + +void MenuItem::requestSize(int *w, int *h) +{ + int bar = (this->parent->parent->type == JI_MENUBAR); + + if (this->hasText()) { *w = - + widget->border_width.l - + jwidget_get_text_length(widget) - + ((bar) ? widget->child_spacing/4: widget->child_spacing) - + widget->border_width.r; + + this->border_width.l + + jwidget_get_text_length(this) + + ((bar) ? this->child_spacing/4: this->child_spacing) + + this->border_width.r; *h = - + widget->border_width.t - + jwidget_get_text_height(widget) - + widget->border_width.b; + + this->border_width.t + + jwidget_get_text_height(this) + + this->border_width.b; - if (menuitem->accel) { + if (m_accel) { char buf[256]; - jaccel_to_string(menuitem->accel, buf); - *w += ji_font_text_len(widget->getFont(), buf); + jaccel_to_string(m_accel, buf); + *w += ji_font_text_len(this->getFont(), buf); } } else { @@ -1082,23 +921,23 @@ static void menuitem_request_size(Widget* widget, int *w, int *h) } // Climbs the hierarchy of menus to get the most-top menubox. -static Widget* get_base_menubox(Widget* widget) +static MenuBox* get_base_menubox(Widget* widget) { while (widget != NULL) { ASSERT_VALID_WIDGET(widget); // We are in a menubox if (widget->type == JI_MENUBOX || widget->type == JI_MENUBAR) { - if (MBOX(widget)->base != NULL) { - return widget; + if (static_cast(widget)->getBase()) { + return static_cast(widget); } else { - Widget* menu = jmenubox_get_menu(widget); + Menu* menu = static_cast(widget)->getMenu(); ASSERT(menu != NULL); - ASSERT(MENU(menu)->menuitem != NULL); + ASSERT(menu->getOwnerMenuItem() != NULL); - widget = MENU(menu)->menuitem; + widget = menu->getOwnerMenuItem(); } } // We are in a menuitem @@ -1115,83 +954,66 @@ static Widget* get_base_menubox(Widget* widget) return NULL; } -static Base *get_base(Widget* widget) +static MenuBaseData* get_base(Widget* widget) { - widget = get_base_menubox(widget); - return MBOX(widget)->base; + MenuBox* menubox = get_base_menubox(widget); + return menubox->getBase(); } -static Base *create_base(Widget* widget) +MenuItem* Menu::getHighlightedItem() { - Base* base = new Base; - - base->was_clicked = false; - base->is_filtering = false; - base->is_processing = false; - base->close_all = false; - - MBOX(widget)->base = base; - - return base; -} - -static Widget* get_highlight(Widget* menu) -{ - Widget* child; JLink link; - - JI_LIST_FOR_EACH(menu->children, link) { - child = (Widget*)link->data; - + JI_LIST_FOR_EACH(this->children, link) { + Widget* child = (Widget*)link->data; if (child->type != JI_MENUITEM) continue; - if (MITEM(child)->highlight) - return child; + MenuItem* menuitem = static_cast(child); + if (menuitem->isHighlighted()) + return menuitem; } - return NULL; } -static void set_highlight(Widget* menu, Widget* menuitem, bool click, bool open_submenu, bool select_first_child) +void Menu::highlightItem(MenuItem* menuitem, bool click, bool open_submenu, bool select_first_child) { + Menu* menu = this; Widget* child; JLink link; // Find the menuitem with the highlight JI_LIST_FOR_EACH(menu->children, link) { child = (Widget*)link->data; - if (child->type != JI_MENUITEM) continue; if (child != menuitem) { // Is it? - if (MITEM(child)->highlight) { - MITEM(child)->highlight = false; + if (static_cast(child)->isHighlighted()) { + static_cast(child)->setHighlighted(false); child->invalidate(); } } } if (menuitem) { - if (!MITEM(menuitem)->highlight) { - MITEM(menuitem)->highlight = true; + if (!menuitem->isHighlighted()) { + menuitem->setHighlighted(true); menuitem->invalidate(); } // Highlight parents - if (MENU(menu)->menuitem != NULL) { - set_highlight(MENU(menu)->menuitem->parent, - MENU(menu)->menuitem, false, false, false); + if (menu->getOwnerMenuItem() != NULL) { + static_cast(menu->getOwnerMenuItem()->parent) + ->highlightItem(menu->getOwnerMenuItem(), false, false, false); } // Open submenu of the menitem - if (HAS_SUBMENU(menuitem)) { + if (menuitem->hasSubmenu()) { if (open_submenu) { // If the submenu is closed, open it - if (MITEM(menuitem)->submenu_menubox == NULL) - open_menuitem(menuitem, select_first_child); + if (!menuitem->hasSubmenuOpened()) + menuitem->openSubmenu(select_first_child); // The mouse was clicked get_base(menuitem)->was_clicked = true; @@ -1199,32 +1021,30 @@ static void set_highlight(Widget* menu, Widget* menuitem, bool click, bool open_ } // Execute menuitem action else if (click) { - close_all(menu); - exe_menuitem(menuitem); + menu->closeAll(); + menuitem->executeClick(); } } } -static void unhighlight(Widget* menu) +void Menu::unhighlightItem() { - set_highlight(menu, NULL, false, false, false); + highlightItem(NULL, false, false, false); } -static void open_menuitem(Widget* menuitem, bool select_first) +void MenuItem::openSubmenu(bool select_first) { Widget* menu; Widget* child; Message* msg; JLink link; - Base *base; - ASSERT_VALID_WIDGET(menuitem); - ASSERT(HAS_SUBMENU(menuitem)); + ASSERT(hasSubmenu()); - menu = menuitem->parent; + menu = this->parent; // The menu item is already opened? - ASSERT(MITEM(menuitem)->submenu_menubox == NULL); + ASSERT(m_submenu_menubox == NULL); ASSERT_VALID_WIDGET(menu); @@ -1232,23 +1052,23 @@ static void open_menuitem(Widget* menuitem, bool select_first) if (menu->parent) { JI_LIST_FOR_EACH(menu->children, link) { child = reinterpret_cast(link->data); - if (child->type != JI_MENUITEM) continue; - if (child != menuitem && MITEM(child)->submenu_menubox) { - close_menuitem(child, false); + MenuItem* childMenuItem = static_cast(child); + if (childMenuItem != this && childMenuItem->hasSubmenuOpened()) { + childMenuItem->closeSubmenu(false); } } } msg = jmessage_new(JM_OPEN_MENUITEM); msg->user.a = select_first; - jmessage_add_dest(msg, menuitem); + jmessage_add_dest(msg, this); jmanager_enqueue_message(msg); // Get the 'base' - base = get_base(menuitem); + MenuBaseData* base = get_base(this); ASSERT(base != NULL); ASSERT(base->is_processing == false); @@ -1262,46 +1082,43 @@ static void open_menuitem(Widget* menuitem, bool select_first) // popuped menu-box if (!base->is_filtering) { base->is_filtering = true; - jmanager_add_msg_filter(JM_BUTTONPRESSED, get_base_menubox(menuitem)); + jmanager_add_msg_filter(JM_BUTTONPRESSED, get_base_menubox(this)); } } -static void close_menuitem(Widget* menuitem, bool last_of_close_chain) +void MenuItem::closeSubmenu(bool last_of_close_chain) { Widget* menu, *child; Message* msg; JLink link; - Base *base; + MenuBaseData* base; - ASSERT_VALID_WIDGET(menuitem); - ASSERT(MITEM(menuitem)->submenu_menubox != NULL); + ASSERT(m_submenu_menubox != NULL); // First: recursively close the children - menu = jmenubox_get_menu(MITEM(menuitem)->submenu_menubox); + menu = m_submenu_menubox->getMenu(); ASSERT(menu != NULL); JI_LIST_FOR_EACH(menu->children, link) { child = reinterpret_cast(link->data); - if (child->type != JI_MENUITEM) continue; - if (MITEM(child)->submenu_menubox) { - close_menuitem(reinterpret_cast(link->data), false); - } + if (static_cast(child)->hasSubmenuOpened()) + static_cast(child)->closeSubmenu(false); } // Second: now we can close the 'menuitem' msg = jmessage_new(JM_CLOSE_MENUITEM); msg->user.a = last_of_close_chain; - jmessage_add_dest(msg, menuitem); + jmessage_add_dest(msg, this); jmanager_enqueue_message(msg); // If this is the last message of the chain, here we have the // responsibility to set is_processing flag to true. if (last_of_close_chain) { // Get the 'base' - base = get_base(menuitem); + base = get_base(this); ASSERT(base != NULL); ASSERT(base->is_processing == false); @@ -1310,29 +1127,33 @@ static void close_menuitem(Widget* menuitem, bool last_of_close_chain) } } -static void close_popup(Widget* menubox) +void MenuItem::startTimer() { - Message* msg = jmessage_new(JM_CLOSE_POPUP); - jmessage_add_dest(msg, menubox); - jmanager_enqueue_message(msg); + if (m_submenu_timer < 0) + m_submenu_timer = jmanager_add_timer(this, TIMEOUT_TO_OPEN_SUBMENU); + jmanager_start_timer(m_submenu_timer); } -static void close_all(Widget* menu) +void MenuItem::stopTimer() { - Widget* base_menubox = NULL; - Widget* menuitem = NULL; - JLink link; - Base *base; + // Stop timer to open the popup + if (m_submenu_timer >= 0) { + jmanager_remove_timer(m_submenu_timer); + m_submenu_timer = -1; + } +} - ASSERT(menu != NULL); - - while (MENU(menu)->menuitem != NULL) { - menuitem = MENU(menu)->menuitem; - menu = menuitem->parent; +void Menu::closeAll() +{ + Menu* menu = this; + MenuItem* menuitem = NULL; + while (menu->m_menuitem) { + menuitem = menu->m_menuitem; + menu = static_cast(menuitem->parent); } - base_menubox = get_base_menubox(menu->parent); - base = MBOX(base_menubox)->base; + MenuBox* base_menubox = get_base_menubox(menu->parent); + MenuBaseData* base = base_menubox->getBase(); base->close_all = true; base->was_clicked = false; if (base->is_filtering) { @@ -1340,35 +1161,42 @@ static void close_all(Widget* menu) jmanager_remove_msg_filter(JM_BUTTONPRESSED, base_menubox); } - unhighlight(menu); + menu->unhighlightItem(); if (menuitem != NULL) { - if (MITEM(menuitem)->submenu_menubox != NULL) - close_menuitem(menuitem, true); + if (menuitem->hasSubmenuOpened()) + menuitem->closeSubmenu(true); } else { + JLink link; JI_LIST_FOR_EACH(menu->children, link) { - menuitem = reinterpret_cast(link->data); - - if (menuitem->type != JI_MENUITEM) + Widget* child = reinterpret_cast(link->data); + if (child->type != JI_MENUITEM) continue; - if (MITEM(menuitem)->submenu_menubox != NULL) - close_menuitem(menuitem, true); + menuitem = static_cast(child); + if (menuitem->hasSubmenuOpened()) + menuitem->closeSubmenu(true); } } // For popuped menus - if (base_menubox->type == JI_MENUBOX) { - close_popup(base_menubox); - } + if (base_menubox->type == JI_MENUBOX) + base_menubox->closePopup(); } -static void exe_menuitem(Widget* menuitem) +void MenuBox::closePopup() +{ + Message* msg = jmessage_new(JM_CLOSE_POPUP); + jmessage_add_dest(msg, this); + jmanager_enqueue_message(msg); +} + +void MenuItem::executeClick() { // Send the message Message* msg = jmessage_new(JM_EXE_MENUITEM); - jmessage_add_dest(msg, menuitem); + jmessage_add_dest(msg, this); jmanager_enqueue_message(msg); } @@ -1381,63 +1209,57 @@ static bool window_msg_proc(Widget* widget, Message* msg) break; } - return false; } -static Widget* check_for_letter(Widget* menu, int ascii) +static MenuItem* check_for_letter(Menu* menu, int ascii) { - Widget* menuitem; JLink link; - int c; - JI_LIST_FOR_EACH(menu->children, link) { - menuitem = (Widget*)link->data; - - if (menuitem->type != JI_MENUITEM) + Widget* child = (Widget*)link->data; + if (child->type != JI_MENUITEM) continue; + MenuItem* menuitem = static_cast(child); + if (menuitem->hasText()) - for (c=0; menuitem->getText()[c]; c++) + for (int c=0; menuitem->getText()[c]; c++) if ((menuitem->getText()[c] == '&') && (menuitem->getText()[c+1] != '&')) if (tolower(ascii) == tolower(menuitem->getText()[c+1])) return menuitem; } - return NULL; } -static Widget* check_for_accel(Widget* menu, Message* msg) +static MenuItem* check_for_accel(Menu* menu, Message* msg) { - Widget* menuitem; JLink link; - JI_LIST_FOR_EACH(menu->children, link) { - menuitem = (Widget*)link->data; - - if (menuitem->type != JI_MENUITEM) + Widget* child = (Widget*)link->data; + if (child->type != JI_MENUITEM) continue; - if (MITEM(menuitem)->submenu) { - if ((menuitem = check_for_accel(MITEM(menuitem)->submenu, msg))) + MenuItem* menuitem = static_cast(child); + + if (menuitem->getSubmenu()) { + if ((menuitem = check_for_accel(menuitem->getSubmenu(), msg))) return menuitem; } - else if (MITEM(menuitem)->accel) { + else if (menuitem->getAccel()) { if ((menuitem->isEnabled()) && - (jaccel_check(MITEM(menuitem)->accel, - msg->any.shifts, - msg->key.ascii, - msg->key.scancode))) + (jaccel_check(menuitem->getAccel(), + msg->any.shifts, + msg->key.ascii, + msg->key.scancode))) return menuitem; } } - return NULL; } // Finds the next item of `menuitem', if `menuitem' is NULL searchs // from the first item in `menu' -static Widget* find_nextitem(Widget* menu, Widget* menuitem) +static MenuItem* find_nextitem(Menu* menu, MenuItem* menuitem) { Widget* nextitem; JLink link; @@ -1450,7 +1272,7 @@ static Widget* find_nextitem(Widget* menu, Widget* menuitem) for (; link != menu->children->end; link=link->next) { nextitem = (Widget*)link->data; if ((nextitem->type == JI_MENUITEM) && nextitem->isEnabled()) - return nextitem; + return static_cast(nextitem); } if (menuitem) @@ -1459,7 +1281,7 @@ static Widget* find_nextitem(Widget* menu, Widget* menuitem) return NULL; } -static Widget* find_previtem(Widget* menu, Widget* menuitem) +static MenuItem* find_previtem(Menu* menu, MenuItem* menuitem) { Widget* nextitem; JLink link; @@ -1472,7 +1294,7 @@ static Widget* find_previtem(Widget* menu, Widget* menuitem) for (; link != menu->children->end; link=link->prev) { nextitem = (Widget*)link->data; if ((nextitem->type == JI_MENUITEM) && nextitem->isEnabled()) - return nextitem; + return static_cast(nextitem); } if (menuitem) diff --git a/src/gui/menu.h b/src/gui/menu.h index 8c899f89d..572b1cb80 100644 --- a/src/gui/menu.h +++ b/src/gui/menu.h @@ -7,27 +7,134 @@ #ifndef GUI_MENU_H_INCLUDED #define GUI_MENU_H_INCLUDED -#include "gui/base.h" +#include "base/compiler_specific.h" +#include "base/signal.h" +#include "gui/widget.h" -Widget* jmenu_new(); -Widget* jmenubar_new(); -Widget* jmenubox_new(); -Widget* jmenuitem_new(const char *text); +class MenuItem; +struct MenuBaseData; -Widget* jmenubox_get_menu(Widget* menubox); -Widget* jmenubar_get_menu(Widget* menubar); -Widget* jmenuitem_get_submenu(Widget* menuitem); -JAccel jmenuitem_get_accel(Widget* menuitem); -bool jmenuitem_has_submenu_opened(Widget* menuitem); +class Menu : public Widget +{ +public: + Menu(); + ~Menu(); -void jmenubox_set_menu(Widget* menubox, Widget* menu); -void jmenubar_set_menu(Widget* menubar, Widget* menu); -void jmenuitem_set_submenu(Widget* menuitem, Widget* menu); -void jmenuitem_set_accel(Widget* menuitem, JAccel accel); + void showPopup(int x, int y); -int jmenuitem_is_highlight(Widget* menuitem); + // Returns the MenuItem that has as submenu this menu. + MenuItem* getOwnerMenuItem() { + return m_menuitem; + } -void jmenu_popup(Widget* menu, int x, int y); +protected: + virtual bool onProcessMessage(Message* msg) OVERRIDE; + +private: + void setOwnerMenuItem(MenuItem* ownerMenuItem) { + m_menuitem = ownerMenuItem; + } + + void requestSize(int* w, int* h); + void set_position(JRect rect); + void closeAll(); + + MenuItem* getHighlightedItem(); + void highlightItem(MenuItem* menuitem, bool click, bool open_submenu, bool select_first_child); + void unhighlightItem(); + + MenuItem* m_menuitem; // From where the menu was open + + friend class MenuBox; + friend class MenuItem; +}; + +class MenuBox : public Widget +{ +public: + MenuBox(int type = JI_MENUBOX); + ~MenuBox(); + + Menu* getMenu(); + void setMenu(Menu* menu); + + MenuBaseData* getBase() { + return m_base; + } + +protected: + virtual bool onProcessMessage(Message* msg) OVERRIDE; + MenuBaseData* createBase(); + +private: + void requestSize(int* w, int* h); + void set_position(JRect rect); + void closePopup(); + + MenuBaseData* m_base; + + friend class Menu; +}; + +class MenuBar : public MenuBox +{ +public: + MenuBar(); +}; + +class MenuItem : public Widget +{ +public: + MenuItem(const char *text); + ~MenuItem(); + + Menu* getSubmenu(); + void setSubmenu(Menu* submenu); + + JAccel getAccel(); + void setAccel(JAccel accel); + + bool isHighlighted() const; + void setHighlighted(bool state); + + // Returns true if the MenuItem has a submenu. + bool hasSubmenu() const; + + // Returns true if the submenu is opened. + bool hasSubmenuOpened() const { + return (m_submenu_menubox != NULL); + } + + // Returns the menu-box where the sub-menu has been opened, or just + // NULL if the sub-menu is closed. + MenuBox* getSubmenuContainer() const { + return m_submenu_menubox; + } + + // Fired when the menu item is clicked. + Signal0 Click; + +protected: + virtual bool onProcessMessage(Message* msg) OVERRIDE; + virtual void onClick(); + +private: + void requestSize(int* w, int* h); + void openSubmenu(bool select_first); + void closeSubmenu(bool last_of_close_chain); + void startTimer(); + void stopTimer(); + void executeClick(); + + JAccel m_accel; // Hot-key + bool m_highlighted; // Is it highlighted? + Menu* m_submenu; // The sub-menu + MenuBox* m_submenu_menubox; // The opened menubox for this menu-item + int m_submenu_timer; // Timer to open the submenu + + friend class Menu; + friend class MenuBox; +}; int jm_open_menuitem(); int jm_close_menuitem(); diff --git a/src/gui/theme.h b/src/gui/theme.h index 7e939f3ff..947aad231 100644 --- a/src/gui/theme.h +++ b/src/gui/theme.h @@ -14,6 +14,8 @@ struct FONT; class ButtonBase; class Entry; +class Menu; +class MenuItem; class PaintEvent; class Theme @@ -53,8 +55,8 @@ public: virtual void paintLinkLabel(PaintEvent& ev) = 0; virtual void draw_listbox(JWidget widget, JRect clip) = 0; virtual void draw_listitem(JWidget widget, JRect clip) = 0; - virtual void draw_menu(JWidget widget, JRect clip) = 0; - virtual void draw_menuitem(JWidget widget, JRect clip) = 0; + virtual void draw_menu(Menu* menu, JRect clip) = 0; + virtual void draw_menuitem(MenuItem* menuitem, JRect clip) = 0; virtual void draw_panel(JWidget widget, JRect clip) = 0; virtual void paintRadioButton(PaintEvent& ev) = 0; virtual void draw_separator(JWidget widget, JRect clip) = 0; diff --git a/src/modules/rootmenu.cpp b/src/modules/rootmenu.cpp index 7918cc2de..bedb7528c 100644 --- a/src/modules/rootmenu.cpp +++ b/src/modules/rootmenu.cpp @@ -35,23 +35,23 @@ #include "modules/rootmenu.h" #include "tools/tool_box.h" #include "util/filetoks.h" -#include "widgets/menuitem.h" +#include "widgets/menuitem2.h" #include "tinyxml.h" -static JWidget root_menu; +static Menu* root_menu; -static JWidget recent_list_menuitem; -static JWidget layer_popup_menu; -static JWidget frame_popup_menu; -static JWidget cel_popup_menu; -static JWidget cel_movement_popup_menu; +static MenuItem* recent_list_menuitem; +static Menu* layer_popup_menu; +static Menu* frame_popup_menu; +static Menu* cel_popup_menu; +static Menu* cel_movement_popup_menu; static int load_root_menu(); -static JWidget load_menu_by_id(TiXmlHandle& handle, const char *id); -static JWidget convert_xmlelem_to_menu(TiXmlElement* elem); -static JWidget convert_xmlelem_to_menuitem(TiXmlElement* elem); -static void apply_shortcut_to_menuitems_with_command(JWidget menu, Command* command, Params* params, JAccel accel); +static Menu* load_menu_by_id(TiXmlHandle& handle, const char *id); +static Menu* convert_xmlelem_to_menu(TiXmlElement* elem); +static Widget* convert_xmlelem_to_menuitem(TiXmlElement* elem); +static void apply_shortcut_to_menuitems_with_command(Menu* menu, Command* command, Params* params, JAccel accel); int init_module_rootmenu() { @@ -74,18 +74,18 @@ void exit_module_rootmenu() delete cel_movement_popup_menu; } -JWidget get_root_menu() { return root_menu; } +Menu* get_root_menu() { return root_menu; } -JWidget get_recent_list_menuitem() { return recent_list_menuitem; } -JWidget get_layer_popup_menu() { return layer_popup_menu; } -JWidget get_frame_popup_menu() { return frame_popup_menu; } -JWidget get_cel_popup_menu() { return cel_popup_menu; } -JWidget get_cel_movement_popup_menu() { return cel_movement_popup_menu; } +MenuItem* get_recent_list_menuitem() { return recent_list_menuitem; } +Menu* get_layer_popup_menu() { return layer_popup_menu; } +Menu* get_frame_popup_menu() { return frame_popup_menu; } +Menu* get_cel_popup_menu() { return cel_popup_menu; } +Menu* get_cel_movement_popup_menu() { return cel_movement_popup_menu; } static int load_root_menu() { if (app_get_menubar()) - jmenubar_set_menu(app_get_menubar(), NULL); + app_get_menubar()->setMenu(NULL); // destroy `root-menu' delete root_menu; // widget @@ -229,7 +229,7 @@ static int load_root_menu() // Sets the "menu" of the "menu-bar" to the new "root-menu" if (app_get_menubar()) { - jmenubar_set_menu(app_get_menubar(), root_menu); + app_get_menubar()->setMenu(root_menu); app_get_top_window()->remap_window(); app_get_top_window()->invalidate(); } @@ -237,7 +237,7 @@ static int load_root_menu() return 0; } -static JWidget load_menu_by_id(TiXmlHandle& handle, const char* id) +static Menu* load_menu_by_id(TiXmlHandle& handle, const char* id) { ASSERT(id != NULL); @@ -261,15 +261,15 @@ static JWidget load_menu_by_id(TiXmlHandle& handle, const char* id) return NULL; } -static JWidget convert_xmlelem_to_menu(TiXmlElement* elem) +static Menu* convert_xmlelem_to_menu(TiXmlElement* elem) { - JWidget menu = jmenu_new(); + Menu* menu = new Menu(); //PRINTF("convert_xmlelem_to_menu(%s, %s, %s)\n", elem->Value(), elem->Attribute("id"), elem->Attribute("text")); TiXmlElement* child = elem->FirstChildElement(); while (child) { - JWidget menuitem = convert_xmlelem_to_menuitem(child); + Widget* menuitem = convert_xmlelem_to_menuitem(child); if (menuitem) menu->addChild(menuitem); else @@ -282,7 +282,7 @@ static JWidget convert_xmlelem_to_menu(TiXmlElement* elem) return menu; } -static JWidget convert_xmlelem_to_menuitem(TiXmlElement* elem) +static Widget* convert_xmlelem_to_menuitem(TiXmlElement* elem) { // is it a ? if (strcmp(elem->Value(), "separator") == 0) @@ -309,8 +309,8 @@ static JWidget convert_xmlelem_to_menuitem(TiXmlElement* elem) } /* create the item */ - JWidget menuitem = menuitem_new(elem->Attribute("text"), - command, command ? ¶ms: NULL); + MenuItem2* menuitem = new MenuItem2(elem->Attribute("text"), + command, command ? ¶ms: NULL); if (!menuitem) return NULL; @@ -323,42 +323,43 @@ static JWidget convert_xmlelem_to_menuitem(TiXmlElement* elem) } } - /* has it a sub-menu ()? */ + // Has it a sub-menu ()? if (strcmp(elem->Value(), "menu") == 0) { - /* create the sub-menu */ - JWidget sub_menu = convert_xmlelem_to_menu(elem); - if (!sub_menu) + // Create the sub-menu + Menu* subMenu = convert_xmlelem_to_menu(elem); + if (!subMenu) throw base::Exception("Error reading the sub-menu\n"); - jmenuitem_set_submenu(menuitem, sub_menu); + menuitem->setSubmenu(subMenu); } return menuitem; } -static void apply_shortcut_to_menuitems_with_command(JWidget menu, Command *command, Params* params, JAccel accel) +static void apply_shortcut_to_menuitems_with_command(Menu* menu, Command *command, Params* params, JAccel accel) { JList children = menu->getChildren(); - JWidget menuitem, submenu; JLink link; JI_LIST_FOR_EACH(children, link) { - menuitem = (JWidget)link->data; + Widget* child = (Widget*)link->data; - if (menuitem->getType() == JI_MENUITEM) { - Command* mi_command = menuitem_get_command(menuitem); - Params* mi_params = menuitem_get_params(menuitem); + if (child->getType() == JI_MENUITEM) { + ASSERT(dynamic_cast(child) != NULL); + + MenuItem2* menuitem = static_cast(child); + Command* mi_command = menuitem->getCommand(); + Params* mi_params = menuitem->getParams(); if (mi_command && ustricmp(mi_command->short_name(), command->short_name()) == 0 && ((mi_params && *mi_params == *params) || (Params() == *params))) { // Set the accelerator to be shown in this menu-item - jmenuitem_set_accel(menuitem, jaccel_new_copy(accel)); + menuitem->setAccel(jaccel_new_copy(accel)); } - submenu = jmenuitem_get_submenu(menuitem); - if (submenu) + if (Menu* submenu = menuitem->getSubmenu()) apply_shortcut_to_menuitems_with_command(submenu, command, params, accel); } } diff --git a/src/modules/rootmenu.h b/src/modules/rootmenu.h index 16efdd8c7..a48be9998 100644 --- a/src/modules/rootmenu.h +++ b/src/modules/rootmenu.h @@ -21,6 +21,9 @@ #include "gui/base.h" +class Menu; +class MenuItem; + enum { ACCEL_FOR_UNDO, ACCEL_FOR_REDO, @@ -32,14 +35,12 @@ enum { int init_module_rootmenu(); void exit_module_rootmenu(); -JWidget get_root_menu(); +Menu* get_root_menu(); -JWidget get_recent_list_menuitem(); -JWidget get_layer_popup_menu(); -JWidget get_frame_popup_menu(); -JWidget get_cel_popup_menu(); -JWidget get_cel_movement_popup_menu(); - -/* void show_fx_popup_menu(); */ +MenuItem* get_recent_list_menuitem(); +Menu* get_layer_popup_menu(); +Menu* get_frame_popup_menu(); +Menu* get_cel_popup_menu(); +Menu* get_cel_movement_popup_menu(); #endif diff --git a/src/skin/skin_theme.cpp b/src/skin/skin_theme.cpp index 1749b1844..29b231f9f 100644 --- a/src/skin/skin_theme.cpp +++ b/src/skin/skin_theme.cpp @@ -1017,12 +1017,12 @@ void SkinTheme::draw_listitem(JWidget widget, JRect clip) } } -void SkinTheme::draw_menu(JWidget widget, JRect clip) +void SkinTheme::draw_menu(Menu* widget, JRect clip) { jdraw_rectfill(widget->rc, BGCOLOR); } -void SkinTheme::draw_menuitem(JWidget widget, JRect clip) +void SkinTheme::draw_menuitem(MenuItem* widget, JRect clip) { int c, bg, fg, bar; int x1, y1, x2, y2; @@ -1040,7 +1040,7 @@ void SkinTheme::draw_menuitem(JWidget widget, JRect clip) bg = get_menuitem_normal_face_color(); } else { - if (jmenuitem_is_highlight(widget)) { + if (widget->isHighlighted()) { fg = get_menuitem_highlight_text_color(); bg = get_menuitem_highlight_face_color(); } @@ -1090,7 +1090,7 @@ void SkinTheme::draw_menuitem(JWidget widget, JRect clip) /* for menu-box */ if (!bar) { /* draw the arrown (to indicate which this menu has a sub-menu) */ - if (jmenuitem_get_submenu(widget)) { + if (widget->getSubmenu()) { int scale = jguiscale(); /* enabled */ @@ -1116,14 +1116,14 @@ void SkinTheme::draw_menuitem(JWidget widget, JRect clip) } } /* draw the keyboard shortcut */ - else if (jmenuitem_get_accel(widget)) { + else if (widget->getAccel()) { int old_align = widget->getAlign(); char buf[256]; pos = jwidget_get_rect(widget); pos->x2 -= widget->child_spacing/4; - jaccel_to_string(jmenuitem_get_accel(widget), buf); + jaccel_to_string(widget->getAccel(), buf); widget->setAlign(JI_RIGHT | JI_MIDDLE); draw_textstring(buf, fg, bg, false, widget, pos, 0); diff --git a/src/skin/skin_theme.h b/src/skin/skin_theme.h index f15041827..c33d6535c 100644 --- a/src/skin/skin_theme.h +++ b/src/skin/skin_theme.h @@ -74,8 +74,8 @@ public: void paintLinkLabel(PaintEvent& ev); void draw_listbox(JWidget widget, JRect clip); void draw_listitem(JWidget widget, JRect clip); - void draw_menu(JWidget widget, JRect clip); - void draw_menuitem(JWidget widget, JRect clip); + void draw_menu(Menu* menu, JRect clip); + void draw_menuitem(MenuItem* menuitem, JRect clip); void draw_panel(JWidget widget, JRect clip); void paintRadioButton(PaintEvent& ev); void draw_separator(JWidget widget, JRect clip); diff --git a/src/widgets/menuitem.cpp b/src/widgets/menuitem.cpp deleted file mode 100644 index d3f54fcc9..000000000 --- a/src/widgets/menuitem.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* ASE - Allegro Sprite Editor - * Copyright (C) 2001-2011 David Capello - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include -#include -#include - -#include "commands/command.h" -#include "commands/params.h" -#include "gui/hook.h" -#include "gui/menu.h" -#include "gui/message.h" -#include "gui/widget.h" -#include "modules/gui.h" -#include "ui_context.h" - -struct MenuItem -{ - Command *m_command; - Params *m_params; - - MenuItem(Command *command, Params* params) - : m_command(command) - , m_params(params ? params->clone(): NULL) - { - } - - ~MenuItem() - { - delete m_params; - } - -}; - -static int menuitem_type(); -static bool menuitem_msg_proc(JWidget widget, Message* msg); - -/** - * A widget that represent a menu item of the application. - * - * It's like a jmenuitem, but it has a extra properties: the name of - * the command to be executed when it's clicked (also that command is - * used to check the availability of the command). - * - * @see jmenuitem_new - */ -JWidget menuitem_new(const char* text, Command* command, Params* params) -{ - JWidget widget = jmenuitem_new(text); - MenuItem* menuitem = new MenuItem(command, params); - - jwidget_add_hook(widget, - menuitem_type(), - menuitem_msg_proc, - menuitem); - - return widget; -} - -Command* menuitem_get_command(JWidget widget) -{ - MenuItem* menuitem = reinterpret_cast(jwidget_get_data(widget, menuitem_type())); - return menuitem->m_command; -} - -Params* menuitem_get_params(JWidget widget) -{ - MenuItem* menuitem = reinterpret_cast(jwidget_get_data(widget, menuitem_type())); - return menuitem->m_params; -} - -static int menuitem_type() -{ - static int type = 0; - if (!type) - type = ji_register_widget_type(); - return type; -} - -static bool menuitem_msg_proc(JWidget widget, Message* msg) -{ - switch (msg->type) { - - case JM_DESTROY: { - MenuItem* menuitem = reinterpret_cast(jwidget_get_data(widget, menuitem_type())); - delete menuitem; - break; - } - - case JM_OPEN: { - MenuItem* menuitem = reinterpret_cast(jwidget_get_data(widget, menuitem_type())); - UIContext* context = UIContext::instance(); - - if (menuitem->m_command) { - if (menuitem->m_params) - menuitem->m_command->loadParams(menuitem->m_params); - - widget->setEnabled(menuitem->m_command->isEnabled(context)); - widget->setSelected(menuitem->m_command->isChecked(context)); - } - break; - } - - case JM_CLOSE: - // disable the menu (the keyboard shortcuts are processed by "manager_msg_proc") - widget->setEnabled(false); - break; - - case JM_SIGNAL: - if (msg->signal.num == JI_SIGNAL_MENUITEM_SELECT) { - MenuItem* menuitem = reinterpret_cast(jwidget_get_data(widget, menuitem_type())); - UIContext* context = UIContext::instance(); - - if (menuitem->m_command) { - if (menuitem->m_params) - menuitem->m_command->loadParams(menuitem->m_params); - - if (menuitem->m_command->isEnabled(context)) { - context->executeCommand(menuitem->m_command); - return true; - } - } - } - break; - - default: - if (msg->type == jm_open_menuitem()) { - // Update the context flags after opening the menuitem's - // submenu to update the "enabled" flag of each command - // correctly. - Context* context = UIContext::instance(); - context->updateFlags(); - } - break; - } - - return false; -} diff --git a/src/widgets/menuitem2.cpp b/src/widgets/menuitem2.cpp new file mode 100644 index 000000000..7bff21afe --- /dev/null +++ b/src/widgets/menuitem2.cpp @@ -0,0 +1,98 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "widgets/menuitem2.h" + +#include "commands/command.h" +#include "commands/params.h" +#include "gui/hook.h" +#include "gui/menu.h" +#include "gui/message.h" +#include "gui/widget.h" +#include "modules/gui.h" +#include "ui_context.h" + +#include +#include +#include + +MenuItem2::MenuItem2(const char* text, Command* command, Params* params) + : MenuItem(text) + , m_command(command) + , m_params(params ? params->clone(): NULL) +{ +} + +MenuItem2::~MenuItem2() +{ + delete m_params; +} + +bool MenuItem2::onProcessMessage(Message* msg) +{ + switch (msg->type) { + + case JM_OPEN: { + UIContext* context = UIContext::instance(); + + if (m_command) { + if (m_params) + m_command->loadParams(m_params); + + setEnabled(m_command->isEnabled(context)); + setSelected(m_command->isChecked(context)); + } + break; + } + + case JM_CLOSE: + // disable the menu (the keyboard shortcuts are processed by "manager_msg_proc") + setEnabled(false); + break; + + case JM_SIGNAL: + if (msg->signal.num == JI_SIGNAL_MENUITEM_SELECT) { + UIContext* context = UIContext::instance(); + + if (m_command) { + if (m_params) + m_command->loadParams(m_params); + + if (m_command->isEnabled(context)) { + context->executeCommand(m_command); + return true; + } + } + } + break; + + default: + if (msg->type == jm_open_menuitem()) { + // Update the context flags after opening the menuitem's + // submenu to update the "enabled" flag of each command + // correctly. + Context* context = UIContext::instance(); + context->updateFlags(); + } + break; + } + + return MenuItem::onProcessMessage(msg); +} diff --git a/src/widgets/menuitem.h b/src/widgets/menuitem2.h similarity index 60% rename from src/widgets/menuitem.h rename to src/widgets/menuitem2.h index cab6ffd4b..85e44f4e5 100644 --- a/src/widgets/menuitem.h +++ b/src/widgets/menuitem2.h @@ -19,14 +19,31 @@ #ifndef WIDGETS_MENUITEM_H_INCLUDED #define WIDGETS_MENUITEM_H_INCLUDED -#include "gui/base.h" +#include "gui/menu.h" class Command; class Params; -JWidget menuitem_new(const char* text, Command* command, Params* params); +// A widget that represent a menu item of the application. +// +// It's like a MenuItme, but it has a extra properties: the name of +// the command to be executed when it's clicked (also that command is +// used to check the availability of the command). +class MenuItem2 : public MenuItem +{ +public: + MenuItem2(const char* text, Command* command, Params* params); + ~MenuItem2(); -Command* menuitem_get_command(JWidget menuitem); -Params* menuitem_get_params(JWidget menuitem); + Command* getCommand() { return m_command; } + Params* getParams() { return m_params; } + +protected: + bool onProcessMessage(Message* msg) OVERRIDE; + +private: + Command* m_command; + Params* m_params; +}; #endif