Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / guicast / bcmenupopup.C
blob7e01ca4b8c2f852a026069d2dd853e364098a841
1 #include "bcmenubar.h"
2 #include "bcmenuitem.h"
3 #include "bcmenupopup.h"
4 #include "bcpixmap.h"
5 #include "bcpopup.h"
6 #include "bcresources.h"
7 #include "bcwindowbase.h"
8 #include "clip.h"
10 #include <string.h>
14 // ==================================== Menu Popup =============================
16 // Types of menu popups
17 #define MENUPOPUP_MENUBAR 0
18 #define MENUPOPUP_SUBMENU 1
19 #define MENUPOPUP_POPUP   2
21 BC_MenuPopup::BC_MenuPopup()
23         window_bg = 0;
24         item_bg[0] = 0;
25         item_bg[1] = 0;
26         item_bg[2] = 0;
29 BC_MenuPopup::~BC_MenuPopup()
31         while(menu_items.total)
32         {
33 // Each menuitem recursively removes itself from the arraylist
34                 delete menu_items.values[0];
35         }
36         delete window_bg;
37         delete item_bg[0];
38         delete item_bg[1];
39         delete item_bg[2];
42 int BC_MenuPopup::initialize(BC_WindowBase *top_level, 
43                 BC_MenuBar *menu_bar, 
44                 BC_Menu *menu, 
45                 BC_MenuItem *menu_item, 
46                 BC_PopupMenu *popup_menu)
48         popup = 0;
49         active = 0;
50         this->menu = menu;
51         this->menu_bar = menu_bar;
52         this->menu_item = menu_item;
53         this->popup_menu = popup_menu;
54         this->top_level = top_level;
56         if(menu_item) this->type = MENUPOPUP_SUBMENU;
57         else
58         if(menu) this->type = MENUPOPUP_MENUBAR;
59         else
60         if(popup_menu) this->type = MENUPOPUP_POPUP;
62         BC_Resources *resources = top_level->get_resources();
63         if(resources->menu_popup_bg)
64         {
65                 window_bg = new BC_Pixmap(top_level, resources->menu_popup_bg);
66         }
67         if(resources->menu_item_bg)
68         {
69                 item_bg[0] = new BC_Pixmap(top_level, resources->menu_item_bg[0], PIXMAP_ALPHA);
70                 item_bg[1] = new BC_Pixmap(top_level, resources->menu_item_bg[1], PIXMAP_ALPHA);
71                 item_bg[2] = new BC_Pixmap(top_level, resources->menu_item_bg[2], PIXMAP_ALPHA);
72         }
74         return 0;
77 int BC_MenuPopup::add_item(BC_MenuItem *item)
79         menu_items.append(item);
80         item->initialize(top_level, menu_bar, this);
81         return 0;
84 int BC_MenuPopup::remove_item(BC_MenuItem *item)
86         if(!item)
87         {
88                 item = menu_items.values[menu_items.total - 1];
89                 delete item;
90         }
91         if(item) menu_items.remove(item);
92         return 0;
95 int BC_MenuPopup::total_menuitems()
97         return menu_items.total;
100 int BC_MenuPopup::dispatch_button_press()
102         int result = 0;
103         if(popup)
104         {
105                 for(int i = 0; i < menu_items.total && !result; i++)
106                 {
107                         result = menu_items.values[i]->dispatch_button_press();
108                 }
109                 if(result) draw_items();
110         }
111         return 0;
114 int BC_MenuPopup::dispatch_button_release()
116         int result = 0, redraw = 0;
117         if(popup)
118         {
119                 for(int i = 0; i < menu_items.total && !result; i++)
120                 {
121                         result = menu_items.values[i]->dispatch_button_release(redraw);
122                 }
123                 if(redraw) draw_items();
124         }
125         return result;
128 int BC_MenuPopup::dispatch_key_press()
130         int result = 0;
131         for(int i = 0; i < menu_items.total && !result; i++)
132         {
133                 result = menu_items.values[i]->dispatch_key_press();
134         }
135         return result;
138 int BC_MenuPopup::dispatch_motion_event()
140         int i, result = 0, redraw = 0;
141         Window tempwin;
143         if(popup)
144         {
145 // Try submenus and items
146                 for(i = 0; i < menu_items.total; i++)
147                 {
148                         result |= menu_items.values[i]->dispatch_motion_event(redraw);
149                 }
151                 if(redraw) draw_items();
152         }
154         return result;
157 int BC_MenuPopup::dispatch_translation_event()
159         if(popup)
160         {
161                 int new_x = x + 
162                         (top_level->last_translate_x - 
163                         top_level->prev_x - 
164                         top_level->get_resources()->get_left_border());
165                 int new_y = y + 
166                         (top_level->last_translate_y - 
167                         top_level->prev_y -
168                         top_level->get_resources()->get_top_border());
170 // printf("BC_MenuPopup::dispatch_translation_event %d %d %d %d\n", 
171 // top_level->prev_x, 
172 // top_level->last_translate_x, 
173 // top_level->prev_y, 
174 // top_level->last_translate_y);
175                 popup->reposition_window(new_x, new_y, popup->get_w(), popup->get_h());
176                 top_level->flush();
177                 this->x = new_x;
178                 this->y = new_y;
180                 for(int i = 0; i < menu_items.total; i++)
181                 {
182                         menu_items.values[i]->dispatch_translation_event();
183                 }
184         }
185         return 0;
189 int BC_MenuPopup::dispatch_cursor_leave()
191         int result = 0;
192         
193         if(popup)
194         {
195                 for(int i = 0; i < menu_items.total; i++)
196                 {
197                         result |= menu_items.values[i]->dispatch_cursor_leave();
198                 }
199                 if(result) draw_items();
200         }
201         return 0;
204 int BC_MenuPopup::activate_menu(int x, 
205         int y, 
206         int w, 
207         int h, 
208         int top_window_coords, 
209         int vertical_justify)
211         Window tempwin;
212         int new_x, new_y, top_w, top_h;
213         top_w = top_level->get_root_w(1, 0);
214         top_h = top_level->get_root_h(0);
216         get_dimensions();
218 // Coords are relative to the main window
219         if(top_window_coords)
220                 XTranslateCoordinates(top_level->display, 
221                         top_level->win, 
222                         top_level->rootwin, 
223                         x, 
224                         y, 
225                         &new_x, 
226                         &new_y, 
227                         &tempwin);
228         else
229 // Coords are absolute
230         {
231                 new_x = x; 
232                 new_y = y; 
233         }
235 // All coords are now relative to root window.
236         if(vertical_justify)
237         {
238                 this->x = new_x;
239                 this->y = new_y + h;
240                 if(this->x + this->w > top_w) this->x -= this->x + this->w - top_w; // Right justify
241                 if(this->y + this->h > top_h) this->y -= this->h + h; // Bottom justify
242         }
243         else
244         {
245                 this->x = new_x + w;
246                 this->y = new_y;
247                 if(this->x + this->w > top_w) this->x = new_x - this->w;
248                 if(this->y + this->h > top_h) this->y = new_y + h - this->h;
249         }
251         active = 1;
252         if(menu_bar)
253         {
254                 popup = new BC_Popup(menu_bar, 
255                                         this->x, 
256                                         this->y, 
257                                         this->w, 
258                                         this->h, 
259                                         top_level->get_resources()->menu_up,
260                                         1,
261                                         menu_bar->bg_pixmap);
262         }
263         else
264         {
265                 popup = new BC_Popup(top_level, 
266                                         this->x, 
267                                         this->y, 
268                                         this->w, 
269                                         this->h, 
270                                         top_level->get_resources()->menu_up,
271                                         1,
272                                         0);
273 //              popup->set_background(top_level->get_resources()->menu_bg);
274         }
275         draw_items();
276         popup->show_window();
277         return 0;
280 int BC_MenuPopup::deactivate_submenus(BC_MenuPopup *exclude)
282         for(int i = 0; i < menu_items.total; i++)
283         {
284                 menu_items.values[i]->deactivate_submenus(exclude);
285         }
286         return 0;
289 int BC_MenuPopup::deactivate_menu()
291         deactivate_submenus(0);
293         if(popup) delete popup;
294         popup = 0;
295         active = 0;
297         return 0;
300 int BC_MenuPopup::draw_items()
302         if(menu_bar)
303                 popup->draw_top_tiles(menu_bar, 0, 0, w, h);
304         else
305                 popup->draw_top_tiles(popup, 0, 0, w, h);
307         if(window_bg)
308         {
309                 popup->draw_9segment(0,
310                         0,
311                         w,
312                         h,
313                         window_bg);
314         }
315         else
316         {
317                 popup->draw_3d_border(0, 0, w, h, 
318                         top_level->get_resources()->menu_light,
319                         top_level->get_resources()->menu_up,
320                         top_level->get_resources()->menu_shadow,
321                         BLACK);
322         }
324         for(int i = 0; i < menu_items.total; i++)
325         {
326                 menu_items.values[i]->draw();
327         }
328         popup->flash();
331         return 0;
334 int BC_MenuPopup::get_dimensions()
336         int widest_text = 10, widest_key = 10;
337         int text_w, key_w;
338         int i = 0;
340 // pad for border
341         h = 2;
342 // Set up parameters in each item and get total h. 
343         for(i = 0; i < menu_items.total; i++)
344         {
345                 text_w = 10 + top_level->get_text_width(MEDIUMFONT, menu_items.values[i]->text);
346                 if(menu_items.values[i]->checked) text_w += 20;
348                 key_w = 10 + top_level->get_text_width(MEDIUMFONT, menu_items.values[i]->hotkey_text);
349                 if(text_w > widest_text) widest_text = text_w;
350                 if(key_w > widest_key) widest_key = key_w;
352                 if(!strcmp(menu_items.values[i]->text, "-")) 
353                         menu_items.values[i]->h = 5;
354                 else
355                         menu_items.values[i]->h = top_level->get_text_height(MEDIUMFONT) + 4;
357                 menu_items.values[i]->y = h;
358                 menu_items.values[i]->highlighted = 0;
359                 menu_items.values[i]->down = 0;
360                 h += menu_items.values[i]->h;
361         }
362         w = widest_text + widest_key + 10;
364         w = MAX(w, top_level->get_resources()->min_menu_w);
365 // pad for division
366         key_x = widest_text + 5;
367 // pad for border
368         h += 2;
369         return 0;
372 int BC_MenuPopup::get_key_x()
374         return key_x;
377 BC_Popup* BC_MenuPopup::get_popup()
379         return popup;
382 int BC_MenuPopup::get_w()
384         return w;
391 // ================================= Sub Menu ==================================
393 BC_SubMenu::BC_SubMenu() : BC_MenuPopup()
397 BC_SubMenu::~BC_SubMenu()
401 int BC_SubMenu::add_submenuitem(BC_MenuItem *item)
403         add_item(item);
404         return 0;
408 //      Local Variables:
409 //      mode: C++
410 //      c-file-style: "linux"
411 //      End: