/* * CINELERRA * Copyright (C) 2008 Adam Williams * * 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 "bcdisplayinfo.h" #include "bcmenubar.h" #include "bcmenuitem.h" #include "bcmenupopup.h" #include "bcpixmap.h" #include "bcpopup.h" #include "bcresources.h" #include "bcwindowbase.h" #include "clip.h" #include // ==================================== Menu Popup ============================= // Types of menu popups #define MENUPOPUP_MENUBAR 0 #define MENUPOPUP_SUBMENU 1 #define MENUPOPUP_POPUP 2 BC_MenuPopup::BC_MenuPopup() { window_bg = 0; item_bg[0] = 0; item_bg[1] = 0; item_bg[2] = 0; check = 0; } BC_MenuPopup::~BC_MenuPopup() { while(menu_items.size()) { // Each menuitem recursively removes itself from the arraylist delete menu_items.get(0); } delete window_bg; delete item_bg[0]; delete item_bg[1]; delete item_bg[2]; delete check; } int BC_MenuPopup::initialize(BC_WindowBase *top_level, BC_MenuBar *menu_bar, BC_Menu *menu, BC_MenuItem *menu_item, BC_PopupMenu *popup_menu) { popup = 0; active = 0; this->menu = menu; this->menu_bar = menu_bar; this->menu_item = menu_item; this->popup_menu = popup_menu; this->top_level = top_level; if(menu_item) this->type = MENUPOPUP_SUBMENU; else if(menu) this->type = MENUPOPUP_MENUBAR; else if(popup_menu) this->type = MENUPOPUP_POPUP; BC_Resources *resources = top_level->get_resources(); if(resources->menu_popup_bg) { window_bg = new BC_Pixmap(top_level, resources->menu_popup_bg); } if(resources->menu_item_bg) { item_bg[0] = new BC_Pixmap(top_level, resources->menu_item_bg[0], PIXMAP_ALPHA); item_bg[1] = new BC_Pixmap(top_level, resources->menu_item_bg[1], PIXMAP_ALPHA); item_bg[2] = new BC_Pixmap(top_level, resources->menu_item_bg[2], PIXMAP_ALPHA); } if(resources->check) { check = new BC_Pixmap(top_level, resources->check, PIXMAP_ALPHA); } return 0; } int BC_MenuPopup::add_item(BC_MenuItem *item) { menu_items.append(item); item->initialize(top_level, menu_bar, this); return 0; } int BC_MenuPopup::remove_item(BC_MenuItem *item) { menu_items.remove(item); return 0; } int BC_MenuPopup::del_item(BC_MenuItem *item) { if(!item && menu_items.size() > 0) { item = menu_items.get(menu_items.size() - 1); } if(item) { remove_item(item); item->menu_popup = 0; delete item; } return 0; } BC_MenuItem *BC_MenuPopup::get_item(int i) { return menu_items[i]; } int BC_MenuPopup::total_items() { return menu_items.size(); } int BC_MenuPopup::dispatch_button_press() { int result = 0; if(popup) { for(int i = 0; i < menu_items.total && !result && popup; i++) { result = menu_items.values[i]->dispatch_button_press(); } if(result) draw_items(); } return 0; } int BC_MenuPopup::dispatch_button_release() { int result = 0, redraw = 0; if(popup) { for(int i = 0; i < menu_items.total && !result && popup; i++) { result = menu_items.values[i]->dispatch_button_release(redraw); } if(redraw) draw_items(); } return result; } int BC_MenuPopup::dispatch_key_press() { int result = 0; for(int i = 0; i < menu_items.total && !result; i++) { result = menu_items.values[i]->dispatch_key_press(); } return result; } int BC_MenuPopup::dispatch_motion_event() { int i, result = 0, redraw = 0; if(popup) { // Try submenus and items for(i = 0; i < menu_items.total; i++) { result |= menu_items.values[i]->dispatch_motion_event(redraw); } if(redraw) draw_items(); } return result; } int BC_MenuPopup::dispatch_translation_event() { if(popup) { int new_x = x + (top_level->last_translate_x - top_level->prev_x - BC_DisplayInfo::get_left_border()); int new_y = y + (top_level->last_translate_y - top_level->prev_y - BC_DisplayInfo::get_top_border()); // printf("BC_MenuPopup::dispatch_translation_event %d %d %d %d\n", // top_level->prev_x, // top_level->last_translate_x, // top_level->prev_y, // top_level->last_translate_y); popup->reposition_window(new_x, new_y, popup->get_w(), popup->get_h()); top_level->flush(); this->x = new_x; this->y = new_y; for(int i = 0; i < menu_items.total; i++) { menu_items.values[i]->dispatch_translation_event(); } } return 0; } int BC_MenuPopup::dispatch_cursor_leave() { int result = 0; if(popup) { for(int i = 0; i < menu_items.total; i++) { result |= menu_items.values[i]->dispatch_cursor_leave(); } if(result) draw_items(); } return 0; } int BC_MenuPopup::activate_menu(int x, int y, int w, int h, int top_window_coords, int vertical_justify) { Window tempwin; int new_x, new_y; int top_x0 = top_level->get_screen_x(0, -1); int top_y0 = top_level->get_screen_y(0, -1); int top_x1 = top_x0 + top_level->get_screen_w(0, -1); int top_y1 = top_y0 + top_level->get_screen_h(0, -1); get_dimensions(); // Coords are relative to the main window if(top_window_coords) XTranslateCoordinates(top_level->display, top_level->win, top_level->rootwin, x, y, &new_x, &new_y, &tempwin); else // Coords are absolute { new_x = x; new_y = y; } // All coords are now relative to root window. if(vertical_justify) { this->x = new_x; this->y = new_y + h; if( this->x < top_x0 ) this->x = top_x0; if( this->y < top_y0 ) this->y = top_y0; if(this->x + this->w > top_x1) this->x -= this->x + this->w - top_x1; // Right justify if(this->y + this->h > top_y1) this->y -= this->h + h; // Bottom justify // Avoid top of menu going out of screen if(this->y < 0) this->y = 2; } else { this->x = new_x + w; this->y = new_y; if( this->x < top_x0 ) this->x = top_x0; if( this->y < top_y0 ) this->y = top_y0; if(this->x + this->w > top_x1) this->x = new_x - this->w; if(this->y + this->h > top_y1) this->y = new_y + h - this->h; } top_x0 += 2; top_y0 += 2; if( this->x < top_x0 ) this->x = top_x0; if( this->y < top_y0 ) this->y = top_y0; active = 1; if(menu_bar) { popup = new BC_Popup(menu_bar, this->x, this->y, this->w, this->h, top_level->get_resources()->menu_up, 1, menu_bar->bg_pixmap); } else { popup = new BC_Popup(top_level, this->x, this->y, this->w, this->h, top_level->get_resources()->menu_up, 1, 0); // popup->set_background(top_level->get_resources()->menu_bg); } draw_items(); popup->show_window(); return 0; } int BC_MenuPopup::deactivate_submenus(BC_MenuPopup *exclude) { for(int i = 0; i < menu_items.total; i++) { menu_items.values[i]->deactivate_submenus(exclude); } return 0; } int BC_MenuPopup::deactivate_menu() { deactivate_submenus(0); if(popup) delete popup; popup = 0; active = 0; return 0; } int BC_MenuPopup::draw_items() { if(menu_bar) popup->draw_top_tiles(menu_bar, 0, 0, w, h); else popup->draw_top_tiles(popup, 0, 0, w, h); if(window_bg) { popup->draw_9segment(0, 0, w, h, window_bg); } else { popup->draw_3d_border(0, 0, w, h, top_level->get_resources()->menu_light, top_level->get_resources()->menu_up, top_level->get_resources()->menu_shadow, BLACK); } for(int i = 0; i < menu_items.total; i++) { menu_items.values[i]->draw(); } popup->flash(); return 0; } int BC_MenuPopup::get_dimensions() { int widest_text = 10, widest_key = 10; int text_w, key_w; int i = 0; // pad for border h = 2; // Set up parameters in each item and get total h. for(i = 0; i < menu_items.total; i++) { text_w = 10 + top_level->get_text_width(MEDIUMFONT, menu_items.values[i]->text); if(menu_items.values[i]->checked) text_w += check->get_w() + 1; key_w = 10 + top_level->get_text_width(MEDIUMFONT, menu_items.values[i]->hotkey_text); if(text_w > widest_text) widest_text = text_w; if(key_w > widest_key) widest_key = key_w; if(!strcmp(menu_items.values[i]->text, "-")) menu_items.values[i]->h = 5; else { menu_items.values[i]->h = item_bg[0] ? item_bg[0]->get_h() : top_level->get_text_height(MEDIUMFONT) + 4; } menu_items.values[i]->y = h; menu_items.values[i]->highlighted = 0; menu_items.values[i]->down = 0; h += menu_items.values[i]->h; } w = widest_text + widest_key + 10; w = MAX(w, top_level->get_resources()->min_menu_w); // pad for division key_x = widest_text + 5; // pad for border h += 2; return 0; } int BC_MenuPopup::get_key_x() { return key_x; } BC_Popup* BC_MenuPopup::get_popup() { return popup; } int BC_MenuPopup::cursor_inside() { if( !popup ) return 0; if( popup->cursor_above() ) return 1; for( int i=0; isubmenu ) continue; if( menu_items[i]->submenu->cursor_inside() ) return 1; } return 0; } int BC_MenuPopup::get_w() { return w; } // ================================= Sub Menu ================================== BC_SubMenu::BC_SubMenu() : BC_MenuPopup() { } BC_SubMenu::~BC_SubMenu() { } int BC_SubMenu::add_submenuitem(BC_MenuItem *item) { add_item(item); return 0; }