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
44 BC_PopupMenu::BC_PopupMenu(int x,
51 : BC_SubWindow(x, y, 0, 0, -1)
53 highlighted = popup_down = 0;
57 this->margin = margin;
59 this->margin = BC_WindowBase::get_resources()->popupmenu_margin;
61 this->use_title = use_title;
62 strcpy(this->text, text);
63 for(int i = 0; i < TOTAL_IMAGES; i++)
72 BC_PopupMenu::BC_PopupMenu(int x,
77 : BC_SubWindow(x, y, 0, -1, -1)
79 highlighted = popup_down = 0;
82 this->use_title = use_title;
83 strcpy(this->text, text);
84 for(int i = 0; i < TOTAL_IMAGES; i++)
89 this->w_argument = -1;
93 BC_PopupMenu::~BC_PopupMenu()
95 if(menu_popup) delete menu_popup;
96 for(int i = 0; i < TOTAL_IMAGES; i++)
98 if(images[i]) delete images[i];
102 char* BC_PopupMenu::get_text()
107 void BC_PopupMenu::set_text(const char *text)
111 strcpy(this->text, text);
116 void BC_PopupMenu::set_icon(BC_Pixmap *icon)
121 if(menu_popup) draw_title(1);
125 int BC_PopupMenu::initialize()
132 if(BC_WindowBase::get_resources()->popupmenu_images)
133 set_images(BC_WindowBase::get_resources()->popupmenu_images);
135 set_images(BC_WindowBase::get_resources()->generic_button_images);
138 // Move outside window if no title
146 BC_SubWindow::initialize();
148 menu_popup = new BC_MenuPopup;
149 menu_popup->initialize(top_level,
155 if(use_title) draw_title(0);
160 int BC_PopupMenu::set_images(VFrame **data)
162 BC_Resources *resources = get_resources();
163 for(int i = 0; i < 3; i++)
165 if(images[i]) delete images[i];
166 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
172 resources->popupmenu_triangle_margin;
174 w = get_text_width(MEDIUMFONT, text) +
176 resources->popupmenu_triangle_margin;
178 h = images[BUTTON_UP]->get_h();
182 int BC_PopupMenu::calculate_w(int w_argument)
185 BC_WindowBase::get_resources()->popupmenu_margin +
186 BC_WindowBase::get_resources()->popupmenu_triangle_margin;
189 int BC_PopupMenu::calculate_h(VFrame **data)
194 if(BC_WindowBase::get_resources()->popupmenu_images)
195 data = BC_WindowBase::get_resources()->popupmenu_images;
197 data = BC_WindowBase::get_resources()->generic_button_images;
200 return data[BUTTON_UP]->get_h();
203 int BC_PopupMenu::add_item(BC_MenuItem *item)
205 menu_popup->add_item(item);
209 int BC_PopupMenu::remove_item(BC_MenuItem *item)
211 menu_popup->remove_item(item);
215 int BC_PopupMenu::del_item(BC_MenuItem *item)
217 menu_popup->del_item(item);
221 int BC_PopupMenu::total_items()
223 return menu_popup->total_menuitems();
227 BC_MenuItem* BC_PopupMenu::get_item(int i)
229 return menu_popup->menu_items.values[i];
232 int BC_PopupMenu::draw_title(int flush)
234 if(!use_title) return 0;
235 BC_Resources *resources = get_resources();
238 draw_top_background(parent_window, 0, 0, w, h);
239 draw_3segmenth(0, 0, w, images[status]);
242 set_color(get_resources()->popup_title_text);
244 if(status == BUTTON_DN)
248 set_font(MEDIUMFONT);
249 char truncated[BCTEXTLEN];
250 int available_w = get_w() - margin * 2 - resources->popupmenu_triangle_margin;
251 truncate_text(truncated, text, available_w);
253 BC_WindowBase::draw_center_text(
254 available_w / 2 + margin + offset,
255 (int)((float)get_h() / 2 + get_text_ascent(MEDIUMFONT) / 2 - 2) + offset,
262 (get_w() - margin * 2 - resources->popupmenu_triangle_margin) / 2 + margin + offset - icon->get_w() / 2 ,
263 get_h() / 2 - icon->get_h() / 2 + offset);
267 draw_triangle_down_flat(get_w() - margin - resources->popupmenu_triangle_margin,
268 get_h() / 2 - TRIANGLE_H / 2, TRIANGLE_W, TRIANGLE_H);
274 int BC_PopupMenu::deactivate()
278 top_level->active_popup_menu = 0;
280 menu_popup->deactivate_menu();
282 if(use_title) draw_title(1); // draw the title
287 int BC_PopupMenu::activate_menu()
294 top_level->deactivate();
295 top_level->active_popup_menu = this;
298 x = top_level->get_abs_cursor_x(0) - get_w();
299 y = top_level->get_abs_cursor_y(0) - get_h();
300 button_press_x = top_level->cursor_x;
301 button_press_y = top_level->cursor_y;
309 XTranslateCoordinates(top_level->display,
310 win, top_level->rootwin,
311 0, 0, &new_x, &new_y, &tempwin);
312 menu_popup->activate_menu(new_x, new_y,
316 // back off x,y just a bit so the menu doesnt deactivate without motion
317 menu_popup->activate_menu(x-10, y-10, w, h, 0, 1);
319 if(use_title) draw_title(1);
324 int BC_PopupMenu::deactivate_menu()
331 int BC_PopupMenu::reposition_window(int x, int y)
333 BC_WindowBase::reposition_window(x, y);
338 int BC_PopupMenu::focus_out_event()
340 if( popup_down && !get_button_down() &&
341 !cursor_inside() && !menu_popup->cursor_inside() )
347 int BC_PopupMenu::repeat_event(int64_t duration)
349 if( status == BUTTON_HI && !tooltip_done &&
350 tooltip_text && tooltip_text[0] != 0 &&
351 duration == top_level->get_resources()->tooltip_delay )
360 int BC_PopupMenu::button_press_event()
362 if(get_buttonpress() == 1 &&
366 top_level->hide_tooltip();
367 if(status == BUTTON_HI || status == BUTTON_UP) status = BUTTON_DN;
375 && (get_buttonpress() == 4 || get_buttonpress() == 5)
376 && menu_popup->total_menuitems() > 1 )
379 for (int i = 0; i < menu_popup->total_menuitems(); i++) {
380 if (!strcmp(menu_popup->menu_items.values[i]->get_text(),get_text())) {
386 if (theval == -1) theval=0;
387 else if (get_buttonpress() == 4) theval--;
388 else if (get_buttonpress() == 5) theval++;
392 if (theval >= menu_popup->total_menuitems())
393 theval = menu_popup->total_menuitems() - 1;
395 BC_MenuItem *tmp = menu_popup->menu_items.values[theval];
396 set_text(tmp->get_text());
397 if (!tmp->handle_event())
398 this->handle_event();
402 // Menu is down so dispatch to popup.
403 menu_popup->dispatch_button_press();
410 int BC_PopupMenu::button_release_event()
417 if(is_event_win() && use_title)
420 if(status == BUTTON_DN)
427 if( !use_title && status == BUTTON_DN ) {
432 // Menu is down so dispatch to popup.
433 result = menu_popup->dispatch_button_release();
436 if(popup_down && button_releases >= 2)
441 if(!result && use_title && cursor_inside() && is_event_win())
447 if(!result && !use_title && popup_down && button_releases < 2)
453 if(!result && popup_down)
455 // Button was released outside any menu.
473 // Menu is down so dispatch to popup.
474 result = menu_popup->dispatch_button_release();
477 if(!result && use_title && cursor_inside() && top_level->event_win == win)
480 if(button_releases >= 2)
488 if(!result && !use_title && button_releases < 2)
490 // First release outside a floating menu
491 // Released outside a fictitious title area
492 // if(top_level->cursor_x < button_press_x - 5 ||
493 // top_level->cursor_y < button_press_y - 5 ||
494 // top_level->cursor_x > button_press_x + 5 ||
495 // top_level->cursor_y > button_press_y + 5)
503 int BC_PopupMenu::translation_event()
505 //printf("BC_PopupMenu::translation_event 1\n");
506 if(popup_down) menu_popup->dispatch_translation_event();
510 int BC_PopupMenu::cursor_leave_event()
513 if(status == BUTTON_HI && use_title)
522 if( !get_button_down() && !menu_popup->cursor_inside() )
524 menu_popup->dispatch_cursor_leave();
531 int BC_PopupMenu::cursor_enter_event()
533 if(is_event_win() && use_title)
536 if(top_level->button_down)
541 if(status == BUTTON_UP)
549 int BC_PopupMenu::cursor_motion_event()
553 // This menu is down.
556 result = menu_popup->dispatch_motion_event();
559 if(!result && use_title && top_level->event_win == win)
583 int BC_PopupMenu::drag_start_event()
585 //printf("BC_PopupMenu::drag_start_event %d\n", popup_down);
586 if(popup_down) return 1;
590 int BC_PopupMenu::drag_stop_event()
592 if(popup_down) return 1;
596 int BC_PopupMenu::drag_motion_event()
598 if(popup_down) return 1;