4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bcmenubar.h"
23 #include "bcmenuitem.h"
24 #include "bcmenupopup.h"
27 #include "bcresources.h"
28 #include "bcwindowbase.h"
35 // ==================================== Menu Popup =============================
37 // Types of menu popups
38 #define MENUPOPUP_MENUBAR 0
39 #define MENUPOPUP_SUBMENU 1
40 #define MENUPOPUP_POPUP 2
42 BC_MenuPopup::BC_MenuPopup()
51 BC_MenuPopup::~BC_MenuPopup()
53 while(menu_items.size())
55 // Each menuitem recursively removes itself from the arraylist
56 delete menu_items.get(0);
66 int BC_MenuPopup::initialize(BC_WindowBase *top_level,
69 BC_MenuItem *menu_item,
70 BC_PopupMenu *popup_menu)
75 this->menu_bar = menu_bar;
76 this->menu_item = menu_item;
77 this->popup_menu = popup_menu;
78 this->top_level = top_level;
80 if(menu_item) this->type = MENUPOPUP_SUBMENU;
82 if(menu) this->type = MENUPOPUP_MENUBAR;
84 if(popup_menu) this->type = MENUPOPUP_POPUP;
86 BC_Resources *resources = top_level->get_resources();
87 if(resources->menu_popup_bg)
89 window_bg = new BC_Pixmap(top_level, resources->menu_popup_bg);
92 if(resources->menu_item_bg)
94 item_bg[0] = new BC_Pixmap(top_level, resources->menu_item_bg[0], PIXMAP_ALPHA);
95 item_bg[1] = new BC_Pixmap(top_level, resources->menu_item_bg[1], PIXMAP_ALPHA);
96 item_bg[2] = new BC_Pixmap(top_level, resources->menu_item_bg[2], PIXMAP_ALPHA);
101 check = new BC_Pixmap(top_level, resources->check, PIXMAP_ALPHA);
107 int BC_MenuPopup::add_item(BC_MenuItem *item)
109 menu_items.append(item);
110 item->initialize(top_level, menu_bar, this);
114 int BC_MenuPopup::remove_item(BC_MenuItem *item, int recursive)
116 if(!item && menu_items.size() > 0)
118 item = menu_items.get(menu_items.size() - 1);
123 menu_items.remove(item);
124 item->menu_popup = 0;
125 if(!recursive) delete item;
130 int BC_MenuPopup::total_menuitems()
132 return menu_items.total;
135 int BC_MenuPopup::dispatch_button_press()
140 for(int i = 0; i < menu_items.total && !result; i++)
142 result = menu_items.values[i]->dispatch_button_press();
144 if(result) draw_items();
149 int BC_MenuPopup::dispatch_button_release()
151 int result = 0, redraw = 0;
154 for(int i = 0; i < menu_items.total && !result; i++)
156 result = menu_items.values[i]->dispatch_button_release(redraw);
158 if(redraw) draw_items();
163 int BC_MenuPopup::dispatch_key_press()
166 for(int i = 0; i < menu_items.total && !result; i++)
168 result = menu_items.values[i]->dispatch_key_press();
173 int BC_MenuPopup::dispatch_motion_event()
175 int i, result = 0, redraw = 0;
179 // Try submenus and items
180 for(i = 0; i < menu_items.total; i++)
182 result |= menu_items.values[i]->dispatch_motion_event(redraw);
185 if(redraw) draw_items();
191 int BC_MenuPopup::dispatch_translation_event()
196 (top_level->last_translate_x -
198 top_level->get_resources()->get_left_border());
200 (top_level->last_translate_y -
202 top_level->get_resources()->get_top_border());
204 // printf("BC_MenuPopup::dispatch_translation_event %d %d %d %d\n",
205 // top_level->prev_x,
206 // top_level->last_translate_x,
207 // top_level->prev_y,
208 // top_level->last_translate_y);
209 popup->reposition_window(new_x, new_y, popup->get_w(), popup->get_h());
214 for(int i = 0; i < menu_items.total; i++)
216 menu_items.values[i]->dispatch_translation_event();
223 int BC_MenuPopup::dispatch_cursor_leave()
229 for(int i = 0; i < menu_items.total; i++)
231 result |= menu_items.values[i]->dispatch_cursor_leave();
233 if(result) draw_items();
238 int BC_MenuPopup::activate_menu(int x,
242 int top_window_coords,
243 int vertical_justify)
247 int top_x0 = top_level->get_screen_x(0, -1);
248 int top_y0 = top_level->get_screen_y(0, -1);
249 int top_x1 = top_x0 + top_level->get_screen_w(0, -1);
250 int top_y1 = top_y0 + top_level->get_screen_h(0, -1);
254 // Coords are relative to the main window
255 if(top_window_coords)
256 XTranslateCoordinates(top_level->display,
265 // Coords are absolute
271 // All coords are now relative to root window.
276 if( this->x < top_x0 ) this->x = top_x0;
277 if( this->y < top_y0 ) this->y = top_y0;
278 if(this->x + this->w > top_x1) this->x -= this->x + this->w - top_x1; // Right justify
279 if(this->y + this->h > top_y1) this->y -= this->h + h; // Bottom justify
280 // Avoid top of menu going out of screen
288 if( this->x < top_x0 ) this->x = top_x0;
289 if( this->y < top_y0 ) this->y = top_y0;
290 if(this->x + this->w > top_x1) this->x = new_x - this->w;
291 if(this->y + this->h > top_y1) this->y = new_y + h - this->h;
293 top_x0 += 2; top_y0 += 2;
294 if( this->x < top_x0 ) this->x = top_x0;
295 if( this->y < top_y0 ) this->y = top_y0;
300 popup = new BC_Popup(menu_bar, this->x, this->y, this->w, this->h,
301 top_level->get_resources()->menu_up,
303 menu_bar->bg_pixmap);
307 popup = new BC_Popup(top_level, this->x, this->y, this->w, this->h,
308 top_level->get_resources()->menu_up,
311 // popup->set_background(top_level->get_resources()->menu_bg);
314 popup->show_window();
318 int BC_MenuPopup::deactivate_submenus(BC_MenuPopup *exclude)
320 for(int i = 0; i < menu_items.total; i++)
322 menu_items.values[i]->deactivate_submenus(exclude);
327 int BC_MenuPopup::deactivate_menu()
329 deactivate_submenus(0);
331 if(popup) delete popup;
338 int BC_MenuPopup::draw_items()
341 popup->draw_top_tiles(menu_bar, 0, 0, w, h);
343 popup->draw_top_tiles(popup, 0, 0, w, h);
347 popup->draw_9segment(0, 0, w, h, window_bg);
351 popup->draw_3d_border(0, 0, w, h,
352 top_level->get_resources()->menu_light,
353 top_level->get_resources()->menu_up,
354 top_level->get_resources()->menu_shadow,
358 for(int i = 0; i < menu_items.total; i++)
360 menu_items.values[i]->draw();
368 int BC_MenuPopup::get_dimensions()
370 int widest_text = 10, widest_key = 10;
376 // Set up parameters in each item and get total h.
377 for(i = 0; i < menu_items.total; i++)
379 text_w = 10 + top_level->get_text_width(MEDIUMFONT, menu_items.values[i]->text);
380 if(menu_items.values[i]->checked) text_w += check->get_w() + 1;
382 key_w = 10 + top_level->get_text_width(MEDIUMFONT, menu_items.values[i]->hotkey_text);
383 if(text_w > widest_text) widest_text = text_w;
384 if(key_w > widest_key) widest_key = key_w;
386 if(!strcmp(menu_items.values[i]->text, "-"))
387 menu_items.values[i]->h = 5;
390 // menu_items.values[i]->h = top_level->get_text_height(MEDIUMFONT) + 4;
391 menu_items.values[i]->h = item_bg[0]->get_h();
394 menu_items.values[i]->y = h;
395 menu_items.values[i]->highlighted = 0;
396 menu_items.values[i]->down = 0;
397 h += menu_items.values[i]->h;
399 w = widest_text + widest_key + 10;
401 w = MAX(w, top_level->get_resources()->min_menu_w);
403 key_x = widest_text + 5;
409 int BC_MenuPopup::get_key_x()
414 BC_Popup* BC_MenuPopup::get_popup()
419 int BC_MenuPopup::cursor_inside()
421 if( !popup ) return 0;
422 int x = popup->get_relative_cursor_x();
423 if( x < 0 || x > popup->get_w() ) return 0;
424 int y = popup->get_relative_cursor_y();
425 if( y < 0 || y > popup->get_h() ) return 0;
429 int BC_MenuPopup::get_w()
438 // ================================= Sub Menu ==================================
440 BC_SubMenu::BC_SubMenu() : BC_MenuPopup()
444 BC_SubMenu::~BC_SubMenu()
448 int BC_SubMenu::add_submenuitem(BC_MenuItem *item)