olaf neophyte and de.po updates, valgrind tweaks, delete green lady, inkscape dpi=96
[goodguy/history.git] / cinelerra-5.1 / guicast / bcpopupmenu.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "bcmenubar.h"
23 #include "bcmenuitem.h"
24 #include "bcmenupopup.h"
25 #include "bcpixmap.h"
26 #include "bcpopupmenu.h"
27 #include "bcresources.h"
28 #include "bcsignals.h"
29 #include "bccolors.h"
30 #include "fonts.h"
31 #include <string.h>
32 #include "vframe.h"
33
34 #define BUTTON_UP 0
35 #define BUTTON_HI 1
36 #define BUTTON_DN 2
37 #define TOTAL_IMAGES 3
38
39
40 #define TRIANGLE_W 10
41 #define TRIANGLE_H 10
42
43
44 BC_PopupMenu::BC_PopupMenu(int x,
45                 int y,
46                 int w,
47                 const char *text,
48                 int use_title,
49                 VFrame **data,
50                 int margin)
51  : BC_SubWindow(x, y, 0, 0, -1)
52 {
53         highlighted = popup_down = 0;
54         menu_popup = 0;
55         icon = 0;
56         if(margin >= 0)
57                 this->margin = margin;
58         else
59                 this->margin = BC_WindowBase::get_resources()->popupmenu_margin;
60
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 = w;
69         status = BUTTON_UP;
70         pending = 0;
71 }
72
73 BC_PopupMenu::BC_PopupMenu(int x,
74                 int y,
75                 const char *text,
76                 int use_title,
77                 VFrame **data)
78  : BC_SubWindow(x, y, 0, -1, -1)
79 {
80         highlighted = popup_down = 0;
81         menu_popup = 0;
82         icon = 0;
83         this->use_title = use_title;
84         strcpy(this->text, text);
85         for(int i = 0; i < TOTAL_IMAGES; i++)
86         {
87                 images[i] = 0;
88         }
89         this->data = data;
90         this->w_argument = -1;
91         status = BUTTON_UP;
92         pending = 0;
93 }
94
95 BC_PopupMenu::~BC_PopupMenu()
96 {
97         use_title = 0;
98         deactivate();
99         delete menu_popup;
100         for(int i = 0; i < TOTAL_IMAGES; i++)
101         {
102                 if(images[i]) delete images[i];
103         }
104 }
105
106 char* BC_PopupMenu::get_text()
107 {
108         return text;
109 }
110
111 void BC_PopupMenu::set_text(const char *text)
112 {
113         if(use_title)
114         {
115                 strcpy(this->text, text);
116                 draw_title(1);
117         }
118 }
119
120 void BC_PopupMenu::set_icon(BC_Pixmap *icon)
121 {
122         if(use_title)
123         {
124                 this->icon = icon;
125                 if(menu_popup) draw_title(1);
126         }
127 }
128
129 int BC_PopupMenu::initialize()
130 {
131         if(use_title)
132         {
133                 if(data)
134                         set_images(data);
135                 else
136                 if(BC_WindowBase::get_resources()->popupmenu_images)
137                         set_images(BC_WindowBase::get_resources()->popupmenu_images);
138                 else
139                         set_images(BC_WindowBase::get_resources()->generic_button_images);
140         }
141         else
142 // Move outside window if no title
143         {
144                 x = -10;
145                 y = -10;
146                 w = 10;
147                 h = 10;
148         }
149
150         BC_SubWindow::initialize();
151
152         menu_popup = new BC_MenuPopup;
153         menu_popup->initialize(top_level,
154                 0,
155                 0,
156                 0,
157                 this);
158
159         if(use_title) draw_title(0);
160
161         return 0;
162 }
163
164 int BC_PopupMenu::set_images(VFrame **data)
165 {
166         BC_Resources *resources = get_resources();
167         for(int i = 0; i < 3; i++)
168         {
169                 if(images[i]) delete images[i];
170                 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
171         }
172
173         if(w_argument >= 0)
174                 w = w_argument +
175                         margin +
176                         resources->popupmenu_triangle_margin;
177         else
178                 w = get_text_width(MEDIUMFONT, text) +
179                         margin +
180                         resources->popupmenu_triangle_margin;
181
182         h = images[BUTTON_UP]->get_h();
183         return 0;
184 }
185
186 int BC_PopupMenu::calculate_w(int w_argument)
187 {
188         return w_argument +
189                 BC_WindowBase::get_resources()->popupmenu_margin +
190                 BC_WindowBase::get_resources()->popupmenu_triangle_margin;
191 }
192
193 int BC_PopupMenu::calculate_h(VFrame **data)
194 {
195         if(data)
196                 ;
197         else
198         if(BC_WindowBase::get_resources()->popupmenu_images)
199                 data = BC_WindowBase::get_resources()->popupmenu_images;
200         else
201                 data = BC_WindowBase::get_resources()->generic_button_images;
202
203
204         return data[BUTTON_UP]->get_h();
205 }
206
207 int BC_PopupMenu::add_item(BC_MenuItem *item)
208 {
209         menu_popup->add_item(item);
210         return 0;
211 }
212
213 int BC_PopupMenu::remove_item(BC_MenuItem *item)
214 {
215         menu_popup->remove_item(item);
216         return 0;
217 }
218
219 int BC_PopupMenu::del_item(BC_MenuItem *item)
220 {
221         menu_popup->del_item(item);
222         return 0;
223 }
224
225 int BC_PopupMenu::total_items()
226 {
227         return menu_popup->total_items();
228 }
229
230 BC_MenuItem* BC_PopupMenu::get_item(int i)
231 {
232         return menu_popup->menu_items.values[i];
233 }
234
235 int BC_PopupMenu::draw_title(int flush)
236 {
237         if(!use_title) return 0;
238         BC_Resources *resources = get_resources();
239
240 // Background
241         draw_top_background(parent_window, 0, 0, w, h);
242         draw_3segmenth(0, 0, w, images[status]);
243
244 // Overlay text
245         set_color(get_resources()->popup_title_text);
246         int offset = 0;
247         if(status == BUTTON_DN)
248                 offset = 1;
249         if(!icon)
250         {
251                 set_font(MEDIUMFONT);
252                 char truncated[BCTEXTLEN];
253                 int available_w = get_w() - margin * 2 - resources->popupmenu_triangle_margin;
254                 truncate_text(truncated, text, available_w);
255
256                 BC_WindowBase::draw_center_text(
257                         available_w / 2 + margin + offset,
258                         (int)((float)get_h() / 2 + get_text_ascent(MEDIUMFONT) / 2 - 2) + offset,
259                         truncated);
260         }
261
262         if(icon)
263         {
264                 draw_pixmap(icon,
265                         (get_w() - margin * 2 - resources->popupmenu_triangle_margin) / 2 + margin + offset - icon->get_w() / 2 ,
266                         get_h() / 2 - icon->get_h() / 2 + offset);
267         }
268
269         if( use_title >= 0 )
270                 draw_triangle_down_flat(get_w() - margin - resources->popupmenu_triangle_margin,
271                         get_h() / 2 - TRIANGLE_H / 2, TRIANGLE_W, TRIANGLE_H);
272
273         flash(flush);
274         return 0;
275 }
276
277 int BC_PopupMenu::deactivate()
278 {
279         if(popup_down)
280         {
281                 top_level->active_popup_menu = 0;
282                 popup_down = 0;
283                 menu_popup->deactivate_menu();
284
285                 if(use_title) draw_title(1);    // draw the title
286         }
287         return 0;
288 }
289
290 int BC_PopupMenu::activate_menu()
291 {
292         if( !get_button_down() || !BC_WindowBase::get_resources()->popupmenu_btnup )
293                 return menu_activate();
294         top_level->active_popup_menu = this;
295         pending = 1;
296         return 0;
297 }
298
299 int BC_PopupMenu::menu_activate()
300 {
301         pending = 0;
302         if( !popup_down )
303         {
304                 int x = this->x;
305                 int y = this->y;
306
307                 top_level->deactivate();
308                 top_level->active_popup_menu = this;
309                 if(!use_title)
310                 {
311                         x = top_level->get_abs_cursor_x(0) - get_w();
312                         y = top_level->get_abs_cursor_y(0) - get_h();
313                         button_press_x = top_level->cursor_x;
314                         button_press_y = top_level->cursor_y;
315                 }
316
317                 if(use_title)
318                 {
319                         Window tempwin;
320                         int new_x, new_y;
321                         XTranslateCoordinates(top_level->display,
322                                 win, top_level->rootwin,
323                                 0, 0, &new_x, &new_y, &tempwin);
324                         menu_popup->activate_menu(new_x, new_y,
325                                 w, h, 0, 1);
326                 }
327                 else
328                         menu_popup->activate_menu(x+3, y+3, w, h, 0, 1);
329                 popup_down = 1;
330                 if(use_title) draw_title(1);
331         }
332         return 1;
333 }
334
335 int BC_PopupMenu::deactivate_menu()
336 {
337         deactivate();
338         return 0;
339 }
340
341
342 int BC_PopupMenu::reposition_window(int x, int y)
343 {
344         BC_WindowBase::reposition_window(x, y);
345         draw_title(0);
346         return 0;
347 }
348
349 int BC_PopupMenu::focus_out_event()
350 {
351         if( popup_down && !get_button_down() &&
352             !cursor_inside() && !menu_popup->cursor_inside() )
353                 deactivate();
354         return 0;
355 }
356
357
358 int BC_PopupMenu::repeat_event(int64_t duration)
359 {
360         if( status == BUTTON_HI &&
361                 tooltip_text && tooltip_text[0] != 0 &&
362                 duration == top_level->get_resources()->tooltip_delay )
363         {
364                 show_tooltip();
365                 return 1;
366         }
367         return 0;
368 }
369
370 int BC_PopupMenu::button_press_event()
371 {
372         int result = 0;
373         if(get_buttonpress() == 1 &&
374                 is_event_win() &&
375                 use_title)
376         {
377                 top_level->hide_tooltip();
378                 if(status == BUTTON_HI || status == BUTTON_UP) status = BUTTON_DN;
379                 activate_menu();
380                 draw_title(1);
381                 return 1;
382         }
383
384         // Scrolling section
385         if (is_event_win()
386                 && (get_buttonpress() == 4 || get_buttonpress() == 5)
387                 && menu_popup->total_items() > 1 )
388         {
389                 int theval = -1;
390                 for (int i = 0; i < menu_popup->total_items(); i++) {
391                         if (!strcmp(menu_popup->menu_items.values[i]->get_text(),get_text())) {
392                                 theval=i;
393                                 break;
394                         }
395                 }
396
397                 if (theval == -1)                  theval=0;
398                 else if (get_buttonpress() == 4)   theval--;
399                 else if (get_buttonpress() == 5)   theval++;
400
401                 if (theval < 0)
402                         theval=0;
403                 if (theval >= menu_popup->total_items())
404                         theval = menu_popup->total_items() - 1;
405
406                 BC_MenuItem *tmp = menu_popup->menu_items.values[theval];
407                 set_text(tmp->get_text());
408                 result = tmp->handle_event();
409                 if( !result )
410                         result = this->handle_event();
411         }
412         if(popup_down)
413         {
414 // Menu is down so dispatch to popup.
415                 menu_popup->dispatch_button_press();
416                 result = 1;
417         }
418
419         return result;
420 }
421
422 int BC_PopupMenu::button_release_event()
423 {
424 // try the title
425         int result = 0;
426
427         if(is_event_win() && use_title)
428         {
429                 hide_tooltip();
430                 if(status == BUTTON_DN)
431                 {
432                         status = BUTTON_HI;
433                         draw_title(1);
434                 }
435         }
436
437         if( pending )
438                 return menu_activate();
439
440         if( !use_title && status == BUTTON_DN ) {
441                 result = 1;
442         }
443         else if( popup_down && menu_popup->cursor_inside() ) {
444 // Menu is down so dispatch to popup.
445                 result = menu_popup->dispatch_button_release();
446         }
447 // released outside popup
448         if( get_resources()->popupmenu_btnup && !result && popup_down ) {
449                 deactivate();
450                 result = 1;
451         }
452         hide_tooltip();
453
454         return result;
455 }
456
457 int BC_PopupMenu::translation_event()
458 {
459 //printf("BC_PopupMenu::translation_event 1\n");
460         if(popup_down) menu_popup->dispatch_translation_event();
461         return 0;
462 }
463
464 int BC_PopupMenu::cursor_leave_event()
465 {
466
467         if(status == BUTTON_HI && use_title)
468         {
469                 status = BUTTON_UP;
470                 draw_title(1);
471                 hide_tooltip();
472         }
473
474 // dispatch to popup
475         if( popup_down ) {
476                 if( !get_button_down() && !menu_popup->cursor_inside() ) {
477                         status = BUTTON_UP;
478 //                      deactivate_menu();
479                 }
480                 menu_popup->dispatch_cursor_leave();
481         }
482
483         return 0;
484 }
485
486
487 int BC_PopupMenu::cursor_enter_event()
488 {
489         if(is_event_win() && use_title)
490         {
491                 if(top_level->button_down)
492                 {
493                         status = BUTTON_DN;
494                 }
495                 else
496                 if(status == BUTTON_UP)
497                         status = BUTTON_HI;
498                 draw_title(1);
499         }
500
501         return 0;
502 }
503
504 int BC_PopupMenu::cursor_motion_event()
505 {
506         int result = 0;
507
508 // This menu is down.
509         if(popup_down) {
510                 result = menu_popup->dispatch_motion_event();
511         }
512
513         if(!result && use_title && is_event_win()) {
514                 if(highlighted) {
515                         if(!cursor_inside()) {
516                                 highlighted = 0;
517                                 draw_title(1);
518                         }
519                 }
520                 else {
521                         if(cursor_inside()) {
522                                 highlighted = 1;
523                                 draw_title(1);
524                                 result = 1;
525                         }
526                 }
527         }
528
529         return result;
530 }
531
532 int BC_PopupMenu::drag_start_event()
533 {
534 //printf("BC_PopupMenu::drag_start_event %d\n", popup_down);
535         if(popup_down) return 1;
536         return 0;
537 }
538
539 int BC_PopupMenu::drag_stop_event()
540 {
541         if(popup_down) return 1;
542         return 0;
543 }
544
545 int BC_PopupMenu::drag_motion_event()
546 {
547         if(popup_down) return 1;
548         return 0;
549 }
550
551
552
553
554
555
556