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"
26 #include "bcpopupmenu.h"
27 #include "bcresources.h"
28 #include "bcsignals.h"
37 #define TOTAL_IMAGES 3
40 #define TRIANGLE_W xS(10)
41 #define TRIANGLE_H yS(10)
44 BC_PopupMenu::BC_PopupMenu(int x, int y, int w, const char *text,
45 int use_title, VFrame **data, int margin)
46 : BC_SubWindow(x, y, 0, 0, -1)
48 highlighted = popup_down = 0;
51 this->margin = margin >= 0 ? margin :
52 BC_WindowBase::get_resources()->popupmenu_margin;
53 this->use_title = use_title;
54 strcpy(this->text, text);
55 for( int i=0; i<TOTAL_IMAGES; ++i ) images[i] = 0;
62 BC_PopupMenu::BC_PopupMenu(int x, int y, const char *text,
63 int use_title, VFrame **data)
64 : BC_SubWindow(x, y, 0, -1, -1)
66 highlighted = popup_down = 0;
69 this->margin = BC_WindowBase::get_resources()->popupmenu_margin;
70 this->use_title = use_title;
71 strcpy(this->text, text);
72 for( int i=0; i<TOTAL_IMAGES; ++i ) images[i] = 0;
74 this->w_argument = -1;
79 BC_PopupMenu::~BC_PopupMenu()
84 for( int i=0; i<TOTAL_IMAGES; ++i ) delete images[i];
87 char* BC_PopupMenu::get_text()
92 void BC_PopupMenu::set_text(const char *text)
95 strcpy(this->text, text);
100 void BC_PopupMenu::set_icon(BC_Pixmap *icon)
104 if( menu_popup ) draw_title(1);
108 int BC_PopupMenu::initialize()
114 if( BC_WindowBase::get_resources()->popupmenu_images )
115 set_images(BC_WindowBase::get_resources()->popupmenu_images);
117 set_images(BC_WindowBase::get_resources()->generic_button_images);
120 // Move outside window if no title
121 x = -TRIANGLE_W; y = -TRIANGLE_H;
122 w = TRIANGLE_W; h = TRIANGLE_H;
125 BC_SubWindow::initialize();
127 menu_popup = new BC_MenuPopup;
128 menu_popup->initialize(top_level, 0, 0, 0, this);
130 if( use_title ) draw_title(0);
135 int BC_PopupMenu::set_images(VFrame **data)
137 for( int i=0; i<3; ++i ) {
139 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
142 w = w_argument > 0 ? w_argument :
143 calculate_w(margin, get_text_width(MEDIUMFONT, text), use_title);
144 h = images[BUTTON_UP]->get_h();
148 int BC_PopupMenu::calculate_w(int margin, int text_width, int use_title)
150 BC_Resources *resources = get_resources();
151 int l = margin >= 0 ? margin : resources->popupmenu_margin;
152 int r = use_title < 0 ? l : l + resources->popupmenu_triangle_margin;
153 return l + text_width + r;
156 int BC_PopupMenu::calculate_w(int text_width)
158 return calculate_w(-1, text_width, 0);
161 int BC_PopupMenu::calculate_h(VFrame **data)
163 if( !data ) data = BC_WindowBase::get_resources()->popupmenu_images ?
164 BC_WindowBase::get_resources()->popupmenu_images :
165 BC_WindowBase::get_resources()->generic_button_images ;
167 return data[BUTTON_UP]->get_h();
170 int BC_PopupMenu::add_item(BC_MenuItem *item)
172 menu_popup->add_item(item);
176 int BC_PopupMenu::remove_item(BC_MenuItem *item)
178 menu_popup->remove_item(item);
182 int BC_PopupMenu::del_item(BC_MenuItem *item)
184 menu_popup->del_item(item);
188 int BC_PopupMenu::total_items()
190 return menu_popup->total_items();
193 BC_MenuItem* BC_PopupMenu::get_item(int i)
195 return menu_popup->menu_items.values[i];
198 int BC_PopupMenu::get_margin()
203 int BC_PopupMenu::draw_face(int dx, int color)
205 if( !use_title ) return 0;
208 draw_top_background(parent_window, 0, 0, w, h);
209 draw_3segmenth(0, 0, w, images[status]);
212 if( color < 0 ) color = get_resources()->popup_title_text;
215 int offset = status == BUTTON_DN ? 1 : 0;
216 int available_w = get_w() - calculate_w(margin, 0, use_title);
219 char *truncated = get_truncated_text(MEDIUMFONT, text, available_w);
220 set_font(MEDIUMFONT);
221 BC_WindowBase::draw_center_text(
222 dx + available_w/2 + margin + offset,
223 (int)((float)get_h()/2 + get_text_ascent(MEDIUMFONT)/2 - 2) + offset,
230 available_w/ 2 + margin + offset - icon->get_w()/2 ,
231 get_h()/2 - icon->get_h()/2 + offset);
234 if( use_title >= 0 ) {
235 int tx = get_w() - margin - get_resources()->popupmenu_triangle_margin;
236 int ty = get_h()/2 - TRIANGLE_H/2;
237 draw_triangle_down_flat(tx, ty, TRIANGLE_W, TRIANGLE_H);
242 int BC_PopupMenu::draw_title(int flush)
249 int BC_PopupMenu::deactivate()
252 top_level->active_popup_menu = 0;
254 menu_popup->deactivate_menu();
256 if( use_title ) draw_title(1); // draw the title
261 int BC_PopupMenu::activate_menu()
263 if( !get_button_down() || !BC_WindowBase::get_resources()->popupmenu_btnup )
264 return menu_activate();
265 top_level->active_popup_menu = this;
270 int BC_PopupMenu::menu_activate()
277 top_level->deactivate();
278 top_level->active_popup_menu = this;
280 x = top_level->get_abs_cursor_x(0) - get_w();
281 y = top_level->get_abs_cursor_y(0) - get_h();
282 button_press_x = top_level->cursor_x;
283 button_press_y = top_level->cursor_y;
289 XTranslateCoordinates(top_level->display,
290 win, top_level->rootwin,
291 0, 0, &new_x, &new_y, &tempwin);
292 menu_popup->activate_menu(new_x, new_y,
296 menu_popup->activate_menu(x+xS(3), y+yS(3), w, h, 0, 1);
298 if( use_title ) draw_title(1);
305 int BC_PopupMenu::deactivate_menu()
312 int BC_PopupMenu::reposition_window(int x, int y)
314 BC_WindowBase::reposition_window(x, y);
319 int BC_PopupMenu::focus_out_event()
321 if( popup_down && !get_button_down() &&
322 !cursor_inside() && !menu_popup->cursor_inside() )
328 int BC_PopupMenu::repeat_event(int64_t duration)
330 if( status == BUTTON_HI &&
331 tooltip_text && tooltip_text[0] != 0 &&
332 duration == top_level->get_resources()->tooltip_delay ) {
339 int BC_PopupMenu::button_press_event()
342 if( get_buttonpress() == 1 && is_event_win() && use_title ) {
343 top_level->hide_tooltip();
344 if( status == BUTTON_HI || status == BUTTON_UP ) status = BUTTON_DN;
352 && (get_buttonpress() == 4 || get_buttonpress() == 5)
353 && menu_popup->total_items() > 1 ) {
355 for( int i=0; i<menu_popup->total_items(); ++i ) {
356 if( !strcmp(menu_popup->menu_items.values[i]->get_text(),get_text()) ) {
362 if( theval == -1 ) theval = 0;
363 else if( get_buttonpress() == 4 ) --theval;
364 else if( get_buttonpress() == 5 ) ++theval;
368 else if( theval >= menu_popup->total_items() )
369 theval = menu_popup->total_items() - 1;
371 BC_MenuItem *tmp = menu_popup->menu_items.values[theval];
372 set_text(tmp->get_text());
373 result = tmp->handle_event();
375 result = this->handle_event();
378 // Menu is down so dispatch to popup.
379 menu_popup->dispatch_button_press();
386 int BC_PopupMenu::button_release_event()
391 if( is_event_win() && use_title ) {
393 if( status == BUTTON_DN ) {
400 return menu_activate();
402 if( !use_title && status == BUTTON_DN ) {
405 else if( popup_down && menu_popup->cursor_inside() ) {
406 // Menu is down so dispatch to popup.
407 result = menu_popup->dispatch_button_release();
409 // released outside popup
410 if( get_resources()->popupmenu_btnup && !result && popup_down ) {
419 int BC_PopupMenu::translation_event()
421 //printf("BC_PopupMenu::translation_event 1\n");
422 if( popup_down ) menu_popup->dispatch_translation_event();
426 int BC_PopupMenu::cursor_leave_event()
429 if( status == BUTTON_HI && use_title ) {
437 if( !get_button_down() && !menu_popup->cursor_inside() ) {
439 // deactivate_menu();
441 menu_popup->dispatch_cursor_leave();
448 int BC_PopupMenu::cursor_enter_event()
450 if( is_event_win() && use_title ) {
451 if( top_level->button_down ) {
455 if( status == BUTTON_UP )
463 int BC_PopupMenu::cursor_motion_event()
467 // This menu is down.
469 result = menu_popup->dispatch_motion_event();
472 if( !result && use_title && is_event_win() ) {
474 if( !cursor_inside() ) {
480 if( cursor_inside() ) {
491 int BC_PopupMenu::drag_start_event()
493 //printf("BC_PopupMenu::drag_start_event %d\n", popup_down);
494 if( popup_down ) return 1;
498 int BC_PopupMenu::drag_stop_event()
500 if( popup_down ) return 1;
504 int BC_PopupMenu::drag_motion_event()
506 if( popup_down ) return 1;