r1024: Add optional graduations to waveform.
[cinelerra_cv.git] / guicast / bcpopupmenu.C
blob7074b1a7af88b2eb8f4ac0a520e5f678d87ae871
1 #include "bcmenubar.h"
2 #include "bcmenuitem.h"
3 #include "bcmenupopup.h"
4 #include "bcpixmap.h"
5 #include "bcpopupmenu.h"
6 #include "bcresources.h"
7 #include "bcsignals.h"
8 #include "colors.h"
9 #include "fonts.h"
10 #include <string.h>
11 #include "vframe.h"
13 #define BUTTON_UP 0
14 #define BUTTON_HI 1
15 #define BUTTON_DN 2
16 #define TOTAL_IMAGES 3
19 #define TRIANGLE_W 10
20 #define TRIANGLE_H 10
23 BC_PopupMenu::BC_PopupMenu(int x, 
24                 int y, 
25                 int w, 
26                 char *text, 
27                 int use_title,
28                 VFrame **data,
29                 int margin)
30  : BC_SubWindow(x, y, 0, 0, -1)
32         highlighted = popup_down = 0;
33         menu_popup = 0;
34         icon = 0;
35         if(margin >= 0)
36                 this->margin = margin;
37         else
38                 this->margin = BC_WindowBase::get_resources()->popupmenu_margin;
40         this->use_title = use_title;
41         strcpy(this->text, text);
42         for(int i = 0; i < TOTAL_IMAGES; i++)
43         {
44                 images[i] = 0;
45         }
46         this->data = data;
47         this->w_argument = w;
48         status = BUTTON_UP;
51 BC_PopupMenu::BC_PopupMenu(int x, 
52                 int y, 
53                 char *text, 
54                 int use_title,
55                 VFrame **data)
56  : BC_SubWindow(x, y, w, -1, -1)
58         highlighted = popup_down = 0;
59         menu_popup = 0;
60         icon = 0;
61         this->use_title = use_title;
62         strcpy(this->text, text);
63         for(int i = 0; i < TOTAL_IMAGES; i++)
64         {
65                 images[i] = 0;
66         }
67         this->data = data;
68         this->w_argument = 0;
69         status = BUTTON_UP;
72 BC_PopupMenu::~BC_PopupMenu()
74         if(menu_popup) delete menu_popup;
75         for(int i = 0; i < TOTAL_IMAGES; i++)
76         {
77                 if(images[i]) delete images[i];
78         }
81 char* BC_PopupMenu::get_text()
83         return text;
86 void BC_PopupMenu::set_text(char *text)
88         if(use_title)
89         {
90                 strcpy(this->text, text);
91                 draw_title();
92         }
95 void BC_PopupMenu::set_icon(BC_Pixmap *icon)
97         if(use_title)
98         {
99                 this->icon = icon;
100                 if(menu_popup) draw_title();
101         }
104 int BC_PopupMenu::initialize()
106         if(use_title)
107         {
108                 if(data)
109                         set_images(data);
110                 else
111                 if(BC_WindowBase::get_resources()->popupmenu_images)
112                         set_images(BC_WindowBase::get_resources()->popupmenu_images);
113                 else
114                         set_images(BC_WindowBase::get_resources()->generic_button_images);
115         }
116         else
117 // Move outside window if no title
118         {
119                 x = -10;
120                 y = -10;
121                 w = 10;
122                 h = 10;
123         }
125         BC_SubWindow::initialize();
127         menu_popup = new BC_MenuPopup;
128         menu_popup->initialize(top_level, 
129                 0, 
130                 0, 
131                 0, 
132                 this);
134         if(use_title) draw_title();
136         return 0;
139 int BC_PopupMenu::set_images(VFrame **data)
141         BC_Resources *resources = get_resources();
142         for(int i = 0; i < 3; i++)
143         {
144                 if(images[i]) delete images[i];
145                 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
146         }
148         if(w_argument > 0)
149                 w = w_argument + 
150                         margin +
151                         resources->popupmenu_triangle_margin;
152         else
153                 w = get_text_width(MEDIUMFONT, text) + 
154                         margin +
155                         resources->popupmenu_triangle_margin;
157         h = images[BUTTON_UP]->get_h();
158         return 0;
161 int BC_PopupMenu::calculate_h(VFrame **data)
163         if(data)
164                 ;
165         else
166         if(BC_WindowBase::get_resources()->popupmenu_images)
167                 data = BC_WindowBase::get_resources()->popupmenu_images;
168         else
169                 data = BC_WindowBase::get_resources()->generic_button_images;
171         
172         return data[BUTTON_UP]->get_h();
175 int BC_PopupMenu::add_item(BC_MenuItem *item)
177         menu_popup->add_item(item);
178         return 0;
181 int BC_PopupMenu::remove_item(BC_MenuItem *item)
183         menu_popup->remove_item(item);
184         return 0;
187 int BC_PopupMenu::total_items()
189         return menu_popup->total_menuitems();
190         return 0;
193 BC_MenuItem* BC_PopupMenu::get_item(int i)
195         return menu_popup->menu_items.values[i];
198 int BC_PopupMenu::draw_title()
200         if(!use_title) return 0;
201         BC_Resources *resources = get_resources();
203 // Background
204         draw_top_background(parent_window, 0, 0, w, h);
205         draw_3segmenth(0, 0, w, images[status]);
207 // Overlay text
208         set_color(get_resources()->popup_title_text);
209         int offset = 0;
210         if(status == BUTTON_DN)
211                 offset = 1;
212         if(!icon)
213         {
214                 set_font(MEDIUMFONT);
215                 BC_WindowBase::draw_center_text(
216                         (get_w() - margin * 2 - resources->popupmenu_triangle_margin) / 2 + margin + offset, 
217                         (int)((float)get_h() / 2 + get_text_ascent(MEDIUMFONT) / 2 - 2) + offset, 
218                         text);
219         }
221         if(icon)
222         {
223                 draw_pixmap(icon,
224                         (get_w() - margin * 2 - resources->popupmenu_triangle_margin) / 2 + margin + offset - icon->get_w() / 2 ,
225                         get_h() / 2 - icon->get_h() / 2 + offset);
226         }
228         draw_triangle_down_flat(get_w() - margin - resources->popupmenu_triangle_margin, 
229                 get_h() / 2 - TRIANGLE_H / 2, 
230                 TRIANGLE_W, TRIANGLE_H);
232         flash();
233         return 0;
236 int BC_PopupMenu::deactivate()
238         if(popup_down)
239         {
240                 top_level->active_popup_menu = 0;
241                 popup_down = 0;
242                 menu_popup->deactivate_menu();
244                 if(use_title) draw_title();    // draw the title
245         }
246         return 0;
249 int BC_PopupMenu::activate_menu()
251         if(!popup_down)
252         {
253                 int x = this->x;
254                 int y = this->y;
256                 top_level->deactivate();
257                 top_level->active_popup_menu = this;
258                 if(!use_title)
259                 {
260                         x = top_level->get_abs_cursor_x(0) - get_w();
261                         y = top_level->get_abs_cursor_y(0) - get_h();
262                         button_press_x = top_level->cursor_x;
263                         button_press_y = top_level->cursor_y;
264                 }
266                 button_releases = 0;
267                 if(use_title)
268                 {
269                         Window tempwin;
270                         int new_x, new_y, top_w, top_h;
271                         XTranslateCoordinates(top_level->display, 
272                                 win, 
273                                 top_level->rootwin, 
274                                 0, 
275                                 0, 
276                                 &new_x, 
277                                 &new_y, 
278                                 &tempwin);
279                         menu_popup->activate_menu(new_x, 
280                                 new_y, 
281                                 w, 
282                                 h, 
283                                 0, 
284                                 1);
285                 }
286                 else
287                         menu_popup->activate_menu(x, y, w, h, 0, 1);
288                 popup_down = 1;
289                 if(use_title) draw_title();
290         }
291         return 0;
294 int BC_PopupMenu::deactivate_menu()
296         deactivate();
297         return 0;
301 int BC_PopupMenu::reposition_window(int x, int y)
303         BC_WindowBase::reposition_window(x, y);
304         draw_title();
305         return 0;
308 int BC_PopupMenu::focus_out_event()
310         deactivate();
311         return 0;
315 int BC_PopupMenu::repeat_event(int64_t duration)
317         if(duration == top_level->get_resources()->tooltip_delay &&
318                 tooltip_text[0] != 0 &&
319                 status == BUTTON_HI &&
320                 !tooltip_done)
321         {
322                 show_tooltip();
323                 tooltip_done = 1;
324                 return 1;
325         }
326         return 0;
329 int BC_PopupMenu::button_press_event()
331         int result = 0;
333         if(get_buttonpress() == 1 &&
334                 is_event_win() && 
335                 use_title)
336         {
337                 top_level->hide_tooltip();
338                 if(status == BUTTON_HI || status == BUTTON_UP) status = BUTTON_DN;
339                 activate_menu();
340                 draw_title();
341                 return 1;
342         }
344         // Scrolling section
345         if (is_event_win() 
346                 && (get_buttonpress() == 4 || get_buttonpress() == 5) 
347                 && menu_popup->total_menuitems() > 1
348         ) 
349         { 
350                 int theval = -1;
351                 for (int i = 0; i < menu_popup->total_menuitems(); i++) {
352                         if (!strcmp(menu_popup->menu_items.values[i]->get_text(),get_text())) {
353                                 theval=i; 
354                                 break;
355                         }
356                 }
358                 if (theval == -1)                  theval=0;
359                 else if (get_buttonpress() == 4)   theval--;
360                 else if (get_buttonpress() == 5)   theval++;
362                 if (theval < 0)
363                         theval=0;
364                 if (theval >= menu_popup->total_menuitems()) 
365                         theval = menu_popup->total_menuitems() - 1;
367                 BC_MenuItem *tmp = menu_popup->menu_items.values[theval];
368                 set_text(tmp->get_text());
369                 if (!tmp->handle_event())
370                         this->handle_event();
371         }
374         if(popup_down)
375         {
376 // Menu is down so dispatch to popup.
377                 menu_popup->dispatch_button_press();
378                 return 1;
379         }
381         return 0;
384 int BC_PopupMenu::button_release_event()
386 // try the title
387         int result = 0;
389         button_releases++;
391         if(is_event_win() && use_title)
392         {
393                 hide_tooltip();
394                 if(status == BUTTON_DN)
395                 {
396                         status = BUTTON_HI;
397                         draw_title();
398                 }
399         }
401         if(popup_down)
402         {
403 // Menu is down so dispatch to popup.
404                 result = menu_popup->dispatch_button_release();
405         }
407         if(popup_down && button_releases >= 2)
408         {
409                 deactivate();
410         }
412         if(!result && use_title && cursor_inside() && is_event_win())
413         {
414                 hide_tooltip();
415                 result = 1;
416         }
417         else
418         if(!result && !use_title && popup_down && button_releases < 2)
419         {
420                 result = 1;
421         }
424         if(!result && popup_down)
425         {
426 // Button was released outside any menu.
427                 deactivate();
428                 result = 1;
429         }
431         return result;
442         if(popup_down)
443         {
444 // Menu is down so dispatch to popup.
445                 result = menu_popup->dispatch_button_release();
446         }
448         if(!result && use_title && cursor_inside() && top_level->event_win == win)
449         {
450 // Inside title
451                 if(button_releases >= 2)
452                 {
453                         highlighted = 1;
454                         deactivate();
455                 }
456                 result = 1;
457         }
458         else
459         if(!result && !use_title && button_releases < 2)
460         {
461 // First release outside a floating menu
462 // Released outside a fictitious title area
463 //              if(top_level->cursor_x < button_press_x - 5 ||
464 //                      top_level->cursor_y < button_press_y - 5 ||
465 //                      top_level->cursor_x > button_press_x + 5 ||
466 //                      top_level->cursor_y > button_press_y + 5)       
467                         deactivate();
468                 result = 1;
469         }
471         return result;
474 int BC_PopupMenu::translation_event()
476 //printf("BC_PopupMenu::translation_event 1\n");
477         if(popup_down) menu_popup->dispatch_translation_event();
478         return 0;
481 int BC_PopupMenu::cursor_leave_event()
484         if(status == BUTTON_HI && use_title)
485         {
486                 status = BUTTON_UP;
487                 draw_title();
488                 hide_tooltip();
489         }
491 // dispatch to popup
492         if(popup_down)
493         {
494                 menu_popup->dispatch_cursor_leave();
495         }
497         return 0;
501 int BC_PopupMenu::cursor_enter_event()
503         if(is_event_win() && use_title)
504         {
505                 tooltip_done = 0;
506                 if(top_level->button_down)
507                 {
508                         status = BUTTON_DN;
509                 }
510                 else
511                 if(status == BUTTON_UP) 
512                         status = BUTTON_HI;
513                 draw_title();
514         }
516         return 0;
519 int BC_PopupMenu::cursor_motion_event()
521         int result = 0;
523 // This menu is down.
524         if(popup_down)
525         {
526                 result = menu_popup->dispatch_motion_event();
527         }
529         if(!result && use_title && top_level->event_win == win)
530         {
531                 if(highlighted)
532                 {
533                         if(cursor_inside())
534                         {
535                                 highlighted = 0;
536                                 draw_title();
537                         }
538                 }
539                 else
540                 {
541                         if(cursor_inside())
542                         {
543                                 highlighted = 1;
544                                 draw_title();
545                                 result = 1;
546                         }
547                 }
548         }
550         return result;
553 int BC_PopupMenu::drag_start_event()
555 //printf("BC_PopupMenu::drag_start_event %d\n", popup_down);
556         if(popup_down) return 1;
557         return 0;
560 int BC_PopupMenu::drag_stop_event()
562         if(popup_down) return 1;
563         return 0;
566 int BC_PopupMenu::drag_motion_event()
568         if(popup_down) return 1;
569         return 0;