version update
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcmenuitem.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 "bcpopup.h"
27 #include "bcpopupmenu.h"
28 #include "bcresources.h"
29 #include "bcsignals.h"
30 #include "bcwindowbase.h"
31 #include "bccolors.h"
32 #include "cstrdup.h"
33
34 #include <string.h>
35
36
37 #define MENUITEM_UP 0
38 #define MENUITEM_HI 1
39 #define MENUITEM_DN 2
40
41
42 #define MENUITEM_MARGIN 2
43
44 // ================================ Menu Item ==================================
45
46 BC_MenuItem::BC_MenuItem(const char *text, const char *hotkey_text, int hotkey)
47 {
48         this->text = 0;
49         this->hotkey_text = 0;
50         reset();
51
52         if(text) set_text(text);
53         if(hotkey_text) set_hotkey_text(hotkey_text);
54
55         this->hotkey = hotkey;
56         checked = 0;
57         highlighted = 0;
58         down = 0;
59         submenu = 0;
60         shift_hotkey = 0;
61         alt_hotkey = 0;
62         ctrl_hotkey = 0;
63         menu_popup = 0;
64         enabled = 1;
65 }
66
67 BC_MenuItem::~BC_MenuItem()
68 {
69         if(text) delete [] text;
70         text = 0;
71         if(hotkey_text) delete [] hotkey_text;
72         hotkey_text = 0;
73         if(submenu) delete submenu;
74         submenu = 0;
75         if(menu_popup)
76                 menu_popup->remove_item(this);
77 }
78
79 void BC_MenuItem::reset()
80 {
81         set_text("");
82         set_hotkey_text("");
83         icon = 0;
84 }
85
86 int BC_MenuItem::initialize(BC_WindowBase *top_level, BC_MenuBar *menu_bar, BC_MenuPopup *menu_popup)
87 {
88         this->top_level = top_level;
89         this->menu_popup = menu_popup;
90         this->menu_bar = menu_bar;
91         return 0;
92 }
93
94 int BC_MenuItem::set_checked(int value)
95 {
96         this->checked = value;
97         return 0;
98 }
99
100 int BC_MenuItem::get_checked()
101 {
102         return checked;
103 }
104
105 void BC_MenuItem::set_icon(BC_Pixmap *icon)
106 {
107         this->icon = icon;
108 }
109
110 BC_Pixmap* BC_MenuItem::get_icon()
111 {
112         return icon;
113 }
114
115 void BC_MenuItem::set_text(const char *text)
116 {
117         delete [] this->text;
118         this->text = cstrdup(text);
119 }
120
121 void BC_MenuItem::set_hotkey_text(const char *text)
122 {
123         delete [] this->hotkey_text;
124         this->hotkey_text = cstrdup(text);
125 }
126
127 int BC_MenuItem::deactivate_submenus(BC_MenuPopup *exclude)
128 {
129         if(submenu && submenu != exclude)
130         {
131                 submenu->deactivate_submenus(exclude);
132                 submenu->deactivate_menu();
133                 submenu->popup_menu = 0;
134                 highlighted = 0;
135         }
136         return 0;
137 }
138
139 int BC_MenuItem::get_enabled()
140 {
141         return enabled;
142 }
143 void BC_MenuItem::set_enabled(int v)
144 {
145         enabled = v;
146 }
147
148
149 int BC_MenuItem::activate_submenu()
150 {
151         int new_x, new_y;
152         if(menu_popup->popup && submenu && !submenu->popup)
153         {
154                 Window tempwin;
155                 XTranslateCoordinates(top_level->display,
156                         menu_popup->get_popup()->win,
157                         top_level->rootwin,
158                         0,
159                         y,
160                         &new_x,
161                         &new_y,
162                         &tempwin);
163                 submenu->popup_menu = menu_popup->popup_menu;
164                 submenu->activate_menu(new_x + xS(5), new_y, menu_popup->w - xS(10), h, 0, 0);
165                 highlighted = 1;
166         }
167         return 0;
168 }
169
170
171 int BC_MenuItem::dispatch_button_press()
172 {
173         int result = 0;
174
175         if(submenu)
176         {
177                 result = submenu->dispatch_button_press();
178         }
179
180         if(!result && menu_popup->get_popup()->is_event_win())
181         {
182                 if(top_level->cursor_x >= 0 && top_level->cursor_x < menu_popup->get_w() &&
183                         top_level->cursor_y >= y && top_level->cursor_y < y + h)
184                 {
185                         if(!highlighted)
186                         {
187                                 highlighted = 1;
188                         }
189                         result = 1;
190                 }
191                 else
192                 if(highlighted)
193                 {
194                         highlighted = 0;
195                         result = 1;
196                 }
197         }
198
199         return result;
200 }
201
202 int BC_MenuItem::dispatch_button_release(int &redraw)
203 {
204         int len = strlen(text);
205         if( len > 0 && text[0] == '-' && text[len-1] == '-' ) return 0;
206
207         int result = 0;
208         if(submenu)
209         {
210                 result = submenu->dispatch_button_release();
211         }
212
213         if( !result && menu_popup->cursor_inside() ) {
214                 int cursor_x, cursor_y;
215                 menu_popup->get_popup()->get_relative_cursor(cursor_x, cursor_y);
216                 if( cursor_x >= 0 && cursor_x < menu_popup->get_w() &&
217                         cursor_y >= y && cursor_y < y + h ) {
218                         if(menu_bar)
219                                 menu_bar->deactivate();
220                         else
221                                 menu_popup->popup_menu->deactivate();
222
223                         if(!handle_event() && menu_popup && menu_popup->popup_menu)
224                         {
225                                 menu_popup->popup_menu->set_text(text);
226                                 menu_popup->popup_menu->handle_event();
227                         }
228                         return 1;
229                 }
230         }
231         return 0;
232 }
233
234 int BC_MenuItem::dispatch_motion_event(int &redraw)
235 {
236         int result = 0;
237
238         if(submenu)
239         {
240                 result = submenu->dispatch_motion_event();
241         }
242
243         if( !result && menu_popup->cursor_inside() ) {
244                 int cursor_x, cursor_y;
245                 menu_popup->get_popup()->get_relative_cursor(cursor_x, cursor_y);
246                 if( cursor_x >= 0 && cursor_x < menu_popup->get_w() &&
247                         cursor_y >= y && cursor_y < y + h) {
248 // Highlight the item
249                         if(!highlighted)
250                         {
251 // Deactivate submenus in the parent menu excluding this one.
252                                 menu_popup->deactivate_submenus(submenu);
253                                 highlighted = 1;
254                                 if(submenu) activate_submenu();
255                                 redraw = 1;
256                         }
257                         result = 1;
258                 }
259                 else
260                 if(highlighted)
261                 {
262                         highlighted = 0;
263                         result = 1;
264                         redraw = 1;
265                 }
266         }
267         return result;
268 }
269
270 int BC_MenuItem::dispatch_translation_event()
271 {
272         if(submenu)
273                 submenu->dispatch_translation_event();
274         return 0;
275 }
276
277 int BC_MenuItem::dispatch_cursor_leave()
278 {
279         int result = 0;
280         if(submenu)
281         {
282                 result = submenu->dispatch_cursor_leave();
283         }
284
285         if(!result && highlighted && menu_popup->get_popup()->is_event_win())
286         {
287                 highlighted = 0;
288                 return 1;
289         }
290         return 0;
291 }
292
293 int BC_MenuItem::dispatch_key_press()
294 {
295         int result = 0;
296         if(submenu)
297         {
298                 result = submenu->dispatch_key_press();
299         }
300
301         if(!result)
302         {
303
304                 if(top_level->get_keypress() == hotkey &&
305                         shift_hotkey == top_level->shift_down() &&
306                         alt_hotkey == top_level->alt_down() &&
307                         ctrl_hotkey == top_level->ctrl_down())
308                 {
309                         result = 1;
310                         handle_event();
311                 }
312         }
313         return result;
314 }
315
316
317 int BC_MenuItem::draw()
318 {
319         int text_line = top_level->get_text_descent(MEDIUMFONT);
320         BC_Resources *resources = top_level->get_resources();
321
322         if(!strcmp(text, "-")) {
323                 int bx = xS(5), by = y+h/2, bw = menu_popup->get_w()-xS(10);
324                 draw_bar(bx, by, bw);
325         }
326         else if( text[0] == '-' && text[strlen(text)-1] == '-' ) {
327                 draw_title_bar();
328         }
329         else {
330                 int xoffset = 0, yoffset = 0;
331                 if(highlighted)
332                 {
333                         int y = this->y;
334                         //int w = menu_popup->get_w() - 4;
335                         int h = this->h;
336
337 // Button down
338                         if(top_level->get_button_down() && !submenu)
339                         {
340                                 if(menu_popup->item_bg[MENUITEM_DN])
341                                 {
342 //                                      menu_popup->get_popup()->draw_9segment(MENUITEM_MARGIN,
343 //                                              y,
344 //                                              menu_popup->get_w() - MENUITEM_MARGIN * 2,
345 //                                              h,
346 //                                              menu_popup->item_bg[MENUITEM_DN]);
347                                         menu_popup->get_popup()->draw_3segmenth(MENUITEM_MARGIN,
348                                                 y,
349                                                 menu_popup->get_w() - MENUITEM_MARGIN * 2,
350                                                 menu_popup->item_bg[MENUITEM_DN]);
351                                 }
352                                 else
353                                 {
354                                         menu_popup->get_popup()->draw_3d_box(MENUITEM_MARGIN,
355                                                 y,
356                                                 menu_popup->get_w() - MENUITEM_MARGIN * 2,
357                                                 h,
358                                                 resources->menu_shadow,
359                                                 BLACK,
360                                                 resources->menu_down,
361                                                 resources->menu_down,
362                                                 resources->menu_light);
363                                 }
364                                 xoffset = xS(1);  yoffset = yS(1);
365                         }
366                         else
367 // Highlighted
368                         {
369                                 if(menu_popup->item_bg[MENUITEM_HI])
370                                 {
371 //                                      menu_popup->get_popup()->draw_9segment(MENUITEM_MARGIN,
372 //                                              y,
373 //                                              menu_popup->get_w() - MENUITEM_MARGIN * 2,
374 //                                              h,
375 //                                              menu_popup->item_bg[MENUITEM_HI]);
376                                         menu_popup->get_popup()->draw_3segmenth(MENUITEM_MARGIN,
377                                                 y,
378                                                 menu_popup->get_w() - MENUITEM_MARGIN * 2,
379                                                 menu_popup->item_bg[MENUITEM_HI]);
380                                 }
381                                 else
382                                 {
383                                         menu_popup->get_popup()->set_color(resources->menu_highlighted);
384                                         menu_popup->get_popup()->draw_box(MENUITEM_MARGIN,
385                                                 y,
386                                                 menu_popup->get_w() - MENUITEM_MARGIN * 2,
387                                                 h);
388                                 }
389                         }
390                         menu_popup->get_popup()->set_color(resources->menu_highlighted_fontcolor);
391                 }
392                 else
393                   {
394                 menu_popup->get_popup()->set_color(resources->menu_item_text);
395                   }
396                 if(checked)
397                 {
398 //                      menu_popup->get_popup()->draw_check(xS(10) + xoffset, y + 2 + yoffset);
399                         menu_popup->get_popup()->draw_pixmap(menu_popup->check,
400                                 xoffset,
401                                 y + (this->h - menu_popup->check->get_h()) / 2 + yoffset);
402                         menu_popup->get_popup()->set_font(MEDIUMFONT);
403                         menu_popup->get_popup()->draw_text(menu_popup->check->get_w() + xoffset,
404                                 y + h - text_line - 2 + yoffset,
405                                 text);
406                         menu_popup->get_popup()->draw_text(menu_popup->get_key_x() + xoffset,
407                                 y + h - text_line - 2 + yoffset,
408                                 hotkey_text);
409                 }
410                 else
411                 {
412                         menu_popup->get_popup()->set_font(MEDIUMFONT);
413                         menu_popup->get_popup()->draw_text(xS(10) + xoffset, y + h - text_line - 2 + yoffset, text);
414                         menu_popup->get_popup()->draw_text(menu_popup->get_key_x() + xoffset, y + h - text_line - 2 + yoffset, hotkey_text);
415                 }
416         }
417         return 0;
418 }
419
420 void BC_MenuItem::draw_bar(int bx, int by, int bw)
421 {
422         BC_Popup *popup = menu_popup->get_popup();
423         popup->set_color(DKGREY);
424         popup->draw_line(bx, by, bx+bw, by);
425         popup->set_color(LTGREY);  ++by;
426         popup->draw_line(bx, by, bx+bw, by);
427 }
428
429 void BC_MenuItem::draw_title_bar()
430 {
431         BC_Popup *popup = menu_popup->get_popup();
432         int len = strlen(text)-2;
433         if( len <= 0 ) return;
434         int tw = popup->get_text_width(MEDIUMFONT, text+1, len);
435         int th = popup->get_text_ascent(MEDIUMFONT);
436         int mw = menu_popup->get_w(), lw = mw - tw;
437         int x1 = xS(5), y1 = y+h/2;
438         int tx = lw/4, ty = y1 + th/2;
439         int w1 = tx - x1 - xS(5);
440         if( w1 > 0 ) draw_bar(x1, y1, w1);
441         BC_Resources *resources = top_level->get_resources();
442         popup->set_color(resources->text_background_hi);
443         popup->draw_text(tx, ty, text+1, len);
444         int x2 = tx + tw + xS(5), w2 = mw - xS(5) - x2;
445         if( w2 > 0 ) draw_bar(x2, y1, w2);
446 }
447
448 int BC_MenuItem::add_submenu(BC_SubMenu *submenu)
449 {
450         this->submenu = submenu;
451         submenu->initialize(top_level, menu_bar, 0, this, 0);
452         return 0;
453 }
454
455 BC_SubMenu* BC_MenuItem::get_submenu()
456 {
457         return submenu;
458 }
459
460 char* BC_MenuItem::get_text()
461 {
462         return text;
463 }
464
465 BC_WindowBase* BC_MenuItem::get_top_level()
466 {
467         return top_level;
468 }
469
470 BC_PopupMenu* BC_MenuItem::get_popup_menu()
471 {
472         return menu_popup->popup_menu;
473 }
474
475 int BC_MenuItem::set_shift(int value)
476 {
477         shift_hotkey = value;
478         return 0;
479 }
480
481 int BC_MenuItem::set_alt(int value)
482 {
483         alt_hotkey = value;
484         return 0;
485 }
486
487 void BC_MenuItem::set_ctrl(int value)
488 {
489         ctrl_hotkey = value;
490 }
491