r878: This is Cinelerra 2.1.
[cinelerra_cv/ct.git] / guicast / bcpopupmenu.C
blob74902c9ec6d5c45dbc28ff27738f7519577818b0
1 #include "bcmenubar.h"
2 #include "bcmenupopup.h"
3 #include "bcpixmap.h"
4 #include "bcpopupmenu.h"
5 #include "bcresources.h"
6 #include "bcsignals.h"
7 #include "colors.h"
8 #include "fonts.h"
9 #include <string.h>
10 #include "vframe.h"
12 #define BUTTON_UP 0
13 #define BUTTON_HI 1
14 #define BUTTON_DN 2
15 #define TOTAL_IMAGES 3
18 #define TRIANGLE_W 10
19 #define TRIANGLE_H 10
22 BC_PopupMenu::BC_PopupMenu(int x, 
23                 int y, 
24                 int w, 
25                 char *text, 
26                 int use_title,
27                 VFrame **data,
28                 int margin)
29  : BC_SubWindow(x, y, 0, 0, -1)
31         highlighted = popup_down = 0;
32         menu_popup = 0;
33         icon = 0;
34         if(margin >= 0)
35                 this->margin = margin;
36         else
37                 this->margin = BC_WindowBase::get_resources()->popupmenu_margin;
39         this->use_title = use_title;
40         strcpy(this->text, text);
41         for(int i = 0; i < TOTAL_IMAGES; i++)
42         {
43                 images[i] = 0;
44         }
45         this->data = data;
46         this->w_argument = w;
47         status = BUTTON_UP;
50 BC_PopupMenu::BC_PopupMenu(int x, 
51                 int y, 
52                 char *text, 
53                 int use_title,
54                 VFrame **data)
55  : BC_SubWindow(x, y, w, -1, -1)
57         highlighted = popup_down = 0;
58         menu_popup = 0;
59         icon = 0;
60         this->use_title = use_title;
61         strcpy(this->text, text);
62         for(int i = 0; i < TOTAL_IMAGES; i++)
63         {
64                 images[i] = 0;
65         }
66         this->data = data;
67         this->w_argument = 0;
68         status = BUTTON_UP;
71 BC_PopupMenu::~BC_PopupMenu()
73         if(menu_popup) delete menu_popup;
74         for(int i = 0; i < TOTAL_IMAGES; i++)
75         {
76                 if(images[i]) delete images[i];
77         }
80 char* BC_PopupMenu::get_text()
82         return text;
85 void BC_PopupMenu::set_text(char *text)
87         if(use_title)
88         {
89                 strcpy(this->text, text);
90                 draw_title();
91         }
94 void BC_PopupMenu::set_icon(BC_Pixmap *icon)
96         if(use_title)
97         {
98                 this->icon = icon;
99                 if(menu_popup) draw_title();
100         }
103 int BC_PopupMenu::initialize()
105         if(use_title)
106         {
107                 if(data)
108                         set_images(data);
109                 else
110                 if(BC_WindowBase::get_resources()->popupmenu_images)
111                         set_images(BC_WindowBase::get_resources()->popupmenu_images);
112                 else
113                         set_images(BC_WindowBase::get_resources()->generic_button_images);
114         }
115         else
116 // Move outside window if no title
117         {
118                 x = -10;
119                 y = -10;
120                 w = 10;
121                 h = 10;
122         }
124         BC_SubWindow::initialize();
126         menu_popup = new BC_MenuPopup;
127         menu_popup->initialize(top_level, 
128                 0, 
129                 0, 
130                 0, 
131                 this);
133         if(use_title) draw_title();
135         return 0;
138 int BC_PopupMenu::set_images(VFrame **data)
140         BC_Resources *resources = get_resources();
141         for(int i = 0; i < 3; i++)
142         {
143                 if(images[i]) delete images[i];
144                 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
145         }
147         if(w_argument > 0)
148                 w = w_argument + 
149                         margin +
150                         resources->popupmenu_triangle_margin;
151         else
152                 w = get_text_width(MEDIUMFONT, text) + 
153                         margin +
154                         resources->popupmenu_triangle_margin;
156         h = images[BUTTON_UP]->get_h();
157         return 0;
160 int BC_PopupMenu::calculate_h(VFrame **data)
162         if(data)
163                 ;
164         else
165         if(BC_WindowBase::get_resources()->popupmenu_images)
166                 data = BC_WindowBase::get_resources()->popupmenu_images;
167         else
168                 data = BC_WindowBase::get_resources()->generic_button_images;
170         
171         return data[BUTTON_UP]->get_h();
174 int BC_PopupMenu::add_item(BC_MenuItem *item)
176         menu_popup->add_item(item);
177         return 0;
180 int BC_PopupMenu::remove_item(BC_MenuItem *item)
182         menu_popup->remove_item(item);
183         return 0;
186 int BC_PopupMenu::total_items()
188         return menu_popup->total_menuitems();
189         return 0;
192 BC_MenuItem* BC_PopupMenu::get_item(int i)
194         return menu_popup->menu_items.values[i];
197 int BC_PopupMenu::draw_title()
199         if(!use_title) return 0;
200         BC_Resources *resources = get_resources();
202 // Background
203         draw_top_background(parent_window, 0, 0, w, h);
204         draw_3segmenth(0, 0, w, images[status]);
206 // Overlay text
207         set_color(get_resources()->popup_title_text);
208         int offset = 0;
209         if(status == BUTTON_DN)
210                 offset = 1;
211         if(!icon)
212         {
213                 set_font(MEDIUMFONT);
214                 BC_WindowBase::draw_center_text(
215                         (get_w() - margin * 2 - resources->popupmenu_triangle_margin) / 2 + margin + offset, 
216                         (int)((float)get_h() / 2 + get_text_ascent(MEDIUMFONT) / 2 - 2) + offset, 
217                         text);
218         }
220         if(icon)
221         {
222                 draw_pixmap(icon,
223                         (get_w() - margin * 2 - resources->popupmenu_triangle_margin) / 2 + margin + offset - icon->get_w() / 2 ,
224                         get_h() / 2 - icon->get_h() / 2 + offset);
225         }
227         draw_triangle_down_flat(get_w() - margin - resources->popupmenu_triangle_margin, 
228                 get_h() / 2 - TRIANGLE_H / 2, 
229                 TRIANGLE_W, TRIANGLE_H);
231         flash();
232         return 0;
235 int BC_PopupMenu::deactivate()
237         if(popup_down)
238         {
239                 top_level->active_popup_menu = 0;
240                 popup_down = 0;
241                 menu_popup->deactivate_menu();
243                 if(use_title) draw_title();    // draw the title
244         }
245         return 0;
248 int BC_PopupMenu::activate_menu()
250         if(!popup_down)
251         {
252                 int x = this->x;
253                 int y = this->y;
255                 top_level->deactivate();
256                 top_level->active_popup_menu = this;
257                 if(!use_title)
258                 {
259                         x = top_level->get_abs_cursor_x(0) - get_w();
260                         y = top_level->get_abs_cursor_y(0) - get_h();
261                         button_press_x = top_level->cursor_x;
262                         button_press_y = top_level->cursor_y;
263                 }
265                 button_releases = 0;
266                 if(use_title)
267                 {
268                         Window tempwin;
269                         int new_x, new_y, top_w, top_h;
270                         XTranslateCoordinates(top_level->display, 
271                                 win, 
272                                 top_level->rootwin, 
273                                 0, 
274                                 0, 
275                                 &new_x, 
276                                 &new_y, 
277                                 &tempwin);
278                         menu_popup->activate_menu(new_x, 
279                                 new_y, 
280                                 w, 
281                                 h, 
282                                 0, 
283                                 1);
284                 }
285                 else
286                         menu_popup->activate_menu(x, y, w, h, 0, 1);
287                 popup_down = 1;
288                 if(use_title) draw_title();
289         }
290         return 0;
293 int BC_PopupMenu::deactivate_menu()
295         deactivate();
296         return 0;
300 int BC_PopupMenu::reposition_window(int x, int y)
302         BC_WindowBase::reposition_window(x, y);
303         draw_title();
304         return 0;
307 int BC_PopupMenu::focus_out_event()
309         deactivate();
310         return 0;
314 int BC_PopupMenu::repeat_event(int64_t duration)
316         if(duration == top_level->get_resources()->tooltip_delay &&
317                 tooltip_text[0] != 0 &&
318                 status == BUTTON_HI &&
319                 !tooltip_done)
320         {
321                 show_tooltip();
322                 tooltip_done = 1;
323                 return 1;
324         }
325         return 0;
328 int BC_PopupMenu::button_press_event()
330         int result = 0;
332         if(get_buttonpress() == 1 &&
333                 is_event_win() && 
334                 use_title)
335         {
336                 top_level->hide_tooltip();
337                 if(status == BUTTON_HI || status == BUTTON_UP) status = BUTTON_DN;
338                 activate_menu();
339                 draw_title();
340                 return 1;
341         }
343         if(popup_down)
344         {
345 // Menu is down so dispatch to popup.
346                 menu_popup->dispatch_button_press();
347                 return 1;
348         }
350         return 0;
353 int BC_PopupMenu::button_release_event()
355 // try the title
356         int result = 0;
358         button_releases++;
360         if(is_event_win() && use_title)
361         {
362                 hide_tooltip();
363                 if(status == BUTTON_DN)
364                 {
365                         status = BUTTON_HI;
366                         draw_title();
367                 }
368         }
370         if(popup_down)
371         {
372 // Menu is down so dispatch to popup.
373                 result = menu_popup->dispatch_button_release();
374         }
376         if(popup_down && button_releases >= 2)
377         {
378                 deactivate();
379         }
381         if(!result && use_title && cursor_inside() && is_event_win())
382         {
383                 hide_tooltip();
384                 result = 1;
385         }
386         else
387         if(!result && !use_title && popup_down && button_releases < 2)
388         {
389                 result = 1;
390         }
393         if(!result && popup_down)
394         {
395 // Button was released outside any menu.
396                 deactivate();
397                 result = 1;
398         }
400         return result;
411         if(popup_down)
412         {
413 // Menu is down so dispatch to popup.
414                 result = menu_popup->dispatch_button_release();
415         }
417         if(!result && use_title && cursor_inside() && top_level->event_win == win)
418         {
419 // Inside title
420                 if(button_releases >= 2)
421                 {
422                         highlighted = 1;
423                         deactivate();
424                 }
425                 result = 1;
426         }
427         else
428         if(!result && !use_title && button_releases < 2)
429         {
430 // First release outside a floating menu
431 // Released outside a fictitious title area
432 //              if(top_level->cursor_x < button_press_x - 5 ||
433 //                      top_level->cursor_y < button_press_y - 5 ||
434 //                      top_level->cursor_x > button_press_x + 5 ||
435 //                      top_level->cursor_y > button_press_y + 5)       
436                         deactivate();
437                 result = 1;
438         }
440         return result;
443 int BC_PopupMenu::translation_event()
445 //printf("BC_PopupMenu::translation_event 1\n");
446         if(popup_down) menu_popup->dispatch_translation_event();
447         return 0;
450 int BC_PopupMenu::cursor_leave_event()
453         if(status == BUTTON_HI && use_title)
454         {
455                 status = BUTTON_UP;
456                 draw_title();
457                 hide_tooltip();
458         }
460 // dispatch to popup
461         if(popup_down)
462         {
463                 menu_popup->dispatch_cursor_leave();
464         }
466         return 0;
470 int BC_PopupMenu::cursor_enter_event()
472         if(is_event_win() && use_title)
473         {
474                 tooltip_done = 0;
475                 if(top_level->button_down)
476                 {
477                         status = BUTTON_DN;
478                 }
479                 else
480                 if(status == BUTTON_UP) 
481                         status = BUTTON_HI;
482                 draw_title();
483         }
485         return 0;
488 int BC_PopupMenu::cursor_motion_event()
490         int result = 0;
492 // This menu is down.
493         if(popup_down)
494         {
495                 result = menu_popup->dispatch_motion_event();
496         }
498         if(!result && use_title && top_level->event_win == win)
499         {
500                 if(highlighted)
501                 {
502                         if(cursor_inside())
503                         {
504                                 highlighted = 0;
505                                 draw_title();
506                         }
507                 }
508                 else
509                 {
510                         if(cursor_inside())
511                         {
512                                 highlighted = 1;
513                                 draw_title();
514                                 result = 1;
515                         }
516                 }
517         }
519         return result;
522 int BC_PopupMenu::drag_start_event()
524 //printf("BC_PopupMenu::drag_start_event %d\n", popup_down);
525         if(popup_down) return 1;
526         return 0;
529 int BC_PopupMenu::drag_stop_event()
531         if(popup_down) return 1;
532         return 0;
535 int BC_PopupMenu::drag_motion_event()
537         if(popup_down) return 1;
538         return 0;