confirm prefs update, fix bg_pixmap sz, plugin layout tweaks
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / gwindowgui.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 "autoconf.h"
23 #include "bchash.h"
24 #include "bcsignals.h"
25 #include "clip.h"
26 #include "condition.h"
27 #include "edl.h"
28 #include "edlsession.h"
29 #include "gwindowgui.h"
30 #include "keys.h"
31 #include "language.h"
32 #include "localsession.h"
33 #include "mainmenu.h"
34 #include "mainsession.h"
35 #include "mwindow.h"
36 #include "mwindowgui.h"
37 #include "theme.h"
38 #include "tracks.h"
39 #include "trackcanvas.h"
40 #include "zoombar.h"
41
42 #include <math.h>
43
44
45
46 GWindowGUI::GWindowGUI(MWindow *mwindow, int w, int h)
47  : BC_Window(_(PROGRAM_NAME ": Overlays"),
48         mwindow->session->gwindow_x, mwindow->session->gwindow_y,
49         w, h, w, h, 0, 0, 1)
50 {
51         this->mwindow = mwindow;
52         camera_xyz = 0;
53         projector_xyz = 0;
54 }
55
56 GWindowGUI::~GWindowGUI()
57 {
58 }
59
60 const char *GWindowGUI::non_auto_text[NON_AUTOMATION_TOTAL] =
61 {
62         N_("Assets"),
63         N_("Titles"),
64         N_("Transitions"),
65         N_("Plugin Keyframes"),
66         N_("Hard Edges"),
67 };
68
69 const char *GWindowGUI::auto_text[AUTOMATION_TOTAL] =
70 {
71         N_("Mute"),
72         N_("Camera X"),
73         N_("Camera Y"),
74         N_("Camera Z"),
75         N_("Projector X"),
76         N_("Projector Y"),
77         N_("Projector Z"),
78         N_("Fade"),
79         N_("Pan"),
80         N_("Mode"),
81         N_("Mask"),
82         N_("Speed")
83 };
84
85 int GWindowGUI::auto_colors[AUTOMATION_TOTAL] =
86 {
87         PINK,
88         RED,
89         GREEN,
90         BLUE,
91         LTPINK,
92         LTGREEN,
93         LTBLUE,
94         LTPURPLE,
95         -1,
96         -1,
97         -1,
98         ORANGE,
99 };
100
101 void GWindowGUI::load_defaults()
102 {
103         BC_Hash *defaults = mwindow->defaults;
104         auto_colors[AUTOMATION_MUTE] = defaults->get("AUTO_COLOR_MUTE", auto_colors[AUTOMATION_MUTE]);
105         auto_colors[AUTOMATION_CAMERA_X] = defaults->get("AUTO_COLOR_CAMERA_X", auto_colors[AUTOMATION_CAMERA_X]);
106         auto_colors[AUTOMATION_CAMERA_Y] = defaults->get("AUTO_COLOR_CAMERA_Y", auto_colors[AUTOMATION_CAMERA_Y]);
107         auto_colors[AUTOMATION_CAMERA_Z] = defaults->get("AUTO_COLOR_CAMERA_Z", auto_colors[AUTOMATION_CAMERA_Z]);
108         auto_colors[AUTOMATION_PROJECTOR_X] = defaults->get("AUTO_COLOR_PROJECTOR_X", auto_colors[AUTOMATION_PROJECTOR_X]);
109         auto_colors[AUTOMATION_PROJECTOR_Y] = defaults->get("AUTO_COLOR_PROJECTOR_Y", auto_colors[AUTOMATION_PROJECTOR_Y]);
110         auto_colors[AUTOMATION_PROJECTOR_Z] = defaults->get("AUTO_COLOR_PROJECTOR_Z", auto_colors[AUTOMATION_PROJECTOR_Z]);
111         auto_colors[AUTOMATION_FADE] = defaults->get("AUTO_COLOR_FADE", auto_colors[AUTOMATION_FADE]);
112         auto_colors[AUTOMATION_SPEED] = defaults->get("AUTO_COLOR_SPEED", auto_colors[AUTOMATION_SPEED]);
113 }
114
115 void GWindowGUI::save_defaults()
116 {
117         BC_Hash *defaults = mwindow->defaults;
118         defaults->update("AUTO_COLOR_MUTE", auto_colors[AUTOMATION_MUTE]);
119         defaults->update("AUTO_COLOR_CAMERA_X", auto_colors[AUTOMATION_CAMERA_X]);
120         defaults->update("AUTO_COLOR_CAMERA_Y", auto_colors[AUTOMATION_CAMERA_Y]);
121         defaults->update("AUTO_COLOR_CAMERA_Z", auto_colors[AUTOMATION_CAMERA_Z]);
122         defaults->update("AUTO_COLOR_PROJECTOR_X", auto_colors[AUTOMATION_PROJECTOR_X]);
123         defaults->update("AUTO_COLOR_PROJECTOR_Y", auto_colors[AUTOMATION_PROJECTOR_Y]);
124         defaults->update("AUTO_COLOR_PROJECTOR_Z", auto_colors[AUTOMATION_PROJECTOR_Z]);
125         defaults->update("AUTO_COLOR_FADE", auto_colors[AUTOMATION_FADE]);
126         defaults->update("AUTO_COLOR_SPEED", auto_colors[AUTOMATION_SPEED]);
127 }
128
129 static toggleinfo toggle_order[] =
130 {
131         {0, NON_AUTOMATION_ASSETS},
132         {0, NON_AUTOMATION_TITLES},
133         {0, NON_AUTOMATION_TRANSITIONS},
134         {0, NON_AUTOMATION_PLUGIN_AUTOS},
135         {0, -1}, // bar
136         {1, AUTOMATION_FADE},
137         {1, AUTOMATION_MUTE},
138         {1, AUTOMATION_SPEED},
139         {1, AUTOMATION_MODE},
140         {1, AUTOMATION_PAN},
141         {1, AUTOMATION_MASK},
142         {-1, NON_AUTOMATION_HARD_EDGES},
143         {0, -1}, // bar
144         {1, AUTOMATION_CAMERA_X},
145         {1, AUTOMATION_CAMERA_Y},
146         {1, AUTOMATION_CAMERA_Z},
147         {-1, NONAUTOTOGGLES_CAMERA_XYZ},
148         {0, -1}, // bar
149         {1, AUTOMATION_PROJECTOR_X},
150         {1, AUTOMATION_PROJECTOR_Y},
151         {1, AUTOMATION_PROJECTOR_Z},
152         {-1, NONAUTOTOGGLES_PROJECTOR_XYZ},
153 };
154
155 const char *GWindowGUI::toggle_text(toggleinfo *tp)
156 {
157         if( tp->isauto > 0 ) return _(auto_text[tp->ref]);
158         if( !tp->isauto ) return _(non_auto_text[tp->ref]);
159         switch( tp->ref ) {
160         case NONAUTOTOGGLES_CAMERA_XYZ:
161         case NONAUTOTOGGLES_PROJECTOR_XYZ:
162                 return _("XYZ");
163         case NON_AUTOMATION_HARD_EDGES:
164                 return _("Hard Edges");
165         }
166         return "()";
167 }
168
169 void GWindowGUI::calculate_extents(BC_WindowBase *gui, int *w, int *h)
170 {
171         int temp1, temp2, temp3, temp4, temp5, temp6, temp7;
172         int current_w, current_h;
173         int ys5 = yS(5), ys10 = yS(10);
174         *w = xS(10);
175         *h = ys10;
176
177         for( int i=0; i<(int)(sizeof(toggle_order)/sizeof(toggle_order[0])); ++i ) {
178                 toggleinfo *tp = &toggle_order[i];
179                 int ref = tp->ref;
180                 if( ref < 0 ) {
181                         *h += get_resources()->bar_data->get_h() + ys5;
182                         continue;
183                 }
184                 BC_Toggle::calculate_extents(gui,
185                         BC_WindowBase::get_resources()->checkbox_images,
186                         0, &temp1, &current_w, &current_h,
187                         &temp2, &temp3, &temp4, &temp5, &temp6, &temp7,
188                         toggle_text(tp), MEDIUMFONT);
189                 current_w += current_h;
190                 *w = MAX(current_w, *w);
191                 *h += current_h + ys5;
192         }
193
194         *h += ys10;
195         *w += xS(20);
196 }
197
198 GWindowColorButton::GWindowColorButton(GWindowToggle *auto_toggle,
199                 int x, int y, int w, int color)
200  : ColorCircleButton(auto_toggle->caption, x, y, w, w, color, -1, 1)
201 {
202         this->auto_toggle = auto_toggle;
203         this->color = color;
204 }
205
206 GWindowColorButton::~GWindowColorButton()
207 {
208 }
209
210 int GWindowColorButton::handle_new_color(int color, int alpha)
211 {
212         this->color = color;
213         return 1;
214 }
215
216 void GWindowColorButton::handle_done_event(int result)
217 {
218         ColorCircleButton::handle_done_event(result);
219         int ref = auto_toggle->info->ref;
220         GWindowGUI *gui = auto_toggle->gui;
221         gui->lock_window("GWindowColorThread::handle_done_event");
222         if( !result ) {
223                 GWindowGUI::auto_colors[ref] = color;
224                 auto_toggle->update_gui(color);
225                 gui->save_defaults();
226         }
227         else {
228                 color = GWindowGUI::auto_colors[ref];
229                 update_gui(color);
230         }
231         gui->unlock_window();
232         MWindowGUI *mwindow_gui = gui->mwindow->gui;
233         mwindow_gui->lock_window("GWindowColorUpdate::run");
234         mwindow_gui->draw_overlays(1);
235         mwindow_gui->unlock_window();
236 }
237
238
239 void GWindowGUI::create_objects()
240 {
241         int xs10 = xS(10);
242         int ys5 = yS(5), ys10 = yS(10);
243         int x = xs10, y = ys10;
244         lock_window("GWindowGUI::create_objects");
245
246         for( int i=0; i<(int)(sizeof(toggle_order)/sizeof(toggle_order[0])); ++i ) {
247                 toggleinfo *tp = &toggle_order[i];
248                 int ref = tp->ref;
249                 if( ref < 0 ) {
250                         BC_Bar *bar = new BC_Bar(x,y,get_w()-x-xs10);
251                         add_tool(bar);
252                         toggles[i] = 0;
253                         y += bar->get_h() + ys5;
254                         continue;
255                 }
256                 const char *label = toggle_text(tp);
257                 int color = tp->isauto > 0 ?
258                         auto_colors[tp->ref] :
259                         get_resources()->text_default ;
260                 GWindowToggle *toggle = new GWindowToggle(this, x, y, label, color, tp);
261                 add_tool(toggles[i] = toggle);
262                 if( tp->isauto > 0 ) {
263                         VFrame *vframe = 0;
264                         switch( ref ) {
265                         case AUTOMATION_MODE: vframe = mwindow->theme->modekeyframe_data;  break;
266                         case AUTOMATION_PAN:  vframe = mwindow->theme->pankeyframe_data;   break;
267                         case AUTOMATION_MASK: vframe = mwindow->theme->maskkeyframe_data;  break;
268                         }
269                         if( !vframe ) {
270                                 int wh = toggle->get_h() - yS(4);
271                                 if( wh < 1 ) wh = 1;
272                                 GWindowColorButton *color_button =
273                                         new GWindowColorButton(toggle, get_w()-wh-ys10, y+yS(2), wh, color);
274                                 add_tool(color_button);
275                                 color_button->create_objects();
276                         }
277                         else
278                                 draw_vframe(vframe, get_w()-vframe->get_w()-xs10, y);
279                 }
280                 else {
281                         const char *accel = 0;
282                         switch( ref ) {
283                         case NONAUTOTOGGLES_CAMERA_XYZ:
284                                 camera_xyz = toggle;
285                                 accel = _("Shift-F1");
286                                 break;
287                         case NONAUTOTOGGLES_PROJECTOR_XYZ:
288                                 projector_xyz = toggle;
289                                 accel = _("Shift-F2");
290                                 break;
291                         case NON_AUTOMATION_HARD_EDGES:
292                                 VFrame *vframe = mwindow->theme->hardedge_data;
293                                 draw_vframe(vframe, get_w()-vframe->get_w()-xs10, y);
294                                 hard_edges = toggle;
295                                 break;
296                         }
297                          if( accel ) {
298                                 int x1 = get_w() - BC_Title::calculate_w(this, accel) - xs10;
299                                 add_subwindow(new BC_Title(x1, y, accel));
300                         }
301                 }
302                 y += toggles[i]->get_h() + ys5;
303         }
304         update_toggles(0);
305         unlock_window();
306 }
307
308 void GWindowGUI::update_mwindow(int toggles, int overlays)
309 {
310         unlock_window();
311         mwindow->gui->lock_window("GWindowGUI::update_mwindow");
312         if( toggles )
313                 mwindow->gui->mainmenu->update_toggles(0);
314         if( overlays )
315                 mwindow->gui->draw_overlays(1);
316         mwindow->gui->unlock_window();
317         lock_window("GWindowGUI::update_mwindow");
318 }
319
320 void GWindowGUI::update_toggles(int use_lock)
321 {
322         if(use_lock) {
323                 lock_window("GWindowGUI::update_toggles");
324                 set_cool(0);
325         }
326
327         for( int i=0; i<(int)(sizeof(toggle_order)/sizeof(toggle_order[0])); ++i ) {
328                 if( toggles[i] ) toggles[i]->update();
329         }
330
331         camera_xyz->set_value(check_xyz(AUTOMATION_CAMERA_X) > 0 ? 1 : 0);
332         projector_xyz->set_value(check_xyz(AUTOMATION_PROJECTOR_X) > 0 ? 1 : 0);
333
334         if(use_lock) unlock_window();
335 }
336
337 void GWindowGUI::toggle_camera_xyz()
338 {
339         int v = camera_xyz->get_value() ? 0 : 1;
340         camera_xyz->set_value(v);
341         xyz_check(AUTOMATION_CAMERA_X, v);
342         update_toggles(0);
343         update_mwindow(1, 1);
344 }
345
346 void GWindowGUI::toggle_projector_xyz()
347 {
348         int v = projector_xyz->get_value() ? 0 : 1;
349         projector_xyz->set_value(v);
350         xyz_check(AUTOMATION_PROJECTOR_X, v);
351         update_toggles(0);
352         update_mwindow(1, 1);
353 }
354
355 int GWindowGUI::translation_event()
356 {
357         mwindow->session->gwindow_x = get_x();
358         mwindow->session->gwindow_y = get_y();
359         return 0;
360 }
361
362 int GWindowGUI::close_event()
363 {
364         hide_window();
365         mwindow->session->show_gwindow = 0;
366         unlock_window();
367
368         mwindow->gui->lock_window("GWindowGUI::close_event");
369         mwindow->gui->mainmenu->show_gwindow->set_checked(0);
370         mwindow->gui->unlock_window();
371
372         lock_window("GWindowGUI::close_event");
373         mwindow->save_defaults();
374         return 1;
375 }
376
377 int GWindowGUI::keypress_event()
378 {
379         if( ctrl_down() && shift_down() ) {
380                 switch(get_keypress()) {
381                 case KEY_F1:
382                 case KEY_F2:
383                 case KEY_F3:
384                 case KEY_F4:
385                         if( ctrl_down() && shift_down() ) {
386                                 resend_event(mwindow->gui);
387                                 return 1;
388                         }
389                 }
390         }
391         else if( !ctrl_down() && shift_down() ) {
392                 switch(get_keypress()) {
393                 case KEY_F1:
394                         toggle_camera_xyz();
395                         return 1;
396                 case KEY_F2:
397                         toggle_projector_xyz();
398                         return 1;
399                 }
400         }
401         switch(get_keypress()) {
402         case 'w':
403         case 'W':
404         case '0':
405                 if( ctrl_down() ) {
406                         close_event();
407                         return 1;
408                 }
409                 break;
410         }
411         return 0;
412 }
413
414 int GWindowGUI::check_xyz(int group)
415 {
416 // returns 1=all set, -1=all clear, 0=mixed
417         int *autos = mwindow->edl->session->auto_conf->autos;
418         int v = autos[group], ret = v ? 1 : -1;
419         if( autos[group+1] != v || autos[group+2] != v ) ret = 0;
420         return ret;
421 }
422 void GWindowGUI::xyz_check(int group, int v)
423 {
424         int *autos = mwindow->edl->session->auto_conf->autos;
425         autos[group+0] = v;
426         autos[group+1] = v;
427         autos[group+2] = v;
428 }
429
430 int* GWindowGUI::get_main_value(toggleinfo *info)
431 {
432         if( info->isauto > 0 )
433                 return &mwindow->edl->session->auto_conf->autos[info->ref];
434         switch( info->ref ) {
435         case NON_AUTOMATION_ASSETS: return &mwindow->edl->session->show_assets;
436         case NON_AUTOMATION_TITLES: return &mwindow->edl->session->show_titles;
437         case NON_AUTOMATION_TRANSITIONS: return &mwindow->edl->session->auto_conf->transitions;
438         case NON_AUTOMATION_PLUGIN_AUTOS: return &mwindow->edl->session->auto_conf->plugins;
439         case NON_AUTOMATION_HARD_EDGES: return &mwindow->edl->session->auto_conf->hard_edges;
440         }
441         return 0;
442 }
443
444
445 GWindowToggle::GWindowToggle(GWindowGUI *gui, int x, int y,
446         const char *text, int color, toggleinfo *info)
447  : BC_CheckBox(x, y, 0, text, MEDIUMFONT, color)
448 {
449         this->gui = gui;
450         this->info = info;
451         this->color = color;
452         this->color_button = 0;
453         hot = hot_value = 0;
454 }
455
456 GWindowToggle::~GWindowToggle()
457 {
458         delete color_button;
459 }
460
461 int GWindowToggle::handle_event()
462 {
463         int value = get_value();
464         if( shift_down() ) {
465                 if( !hot ) {
466                         gui->set_hot(this);
467                         value = 1;
468                 }
469                 else {
470                         gui->set_cool(1);
471                         value = hot_value;
472                 }
473         }
474         else
475                 gui->set_cool(0);
476         if( info->isauto >= 0 ) {
477                 *gui->get_main_value(info) = value;
478                 switch( info->ref ) {
479                 case AUTOMATION_CAMERA_X:
480                 case AUTOMATION_CAMERA_Y:
481                 case AUTOMATION_CAMERA_Z: {
482                         int v = gui->check_xyz(AUTOMATION_CAMERA_X);
483                         gui->camera_xyz->set_value(v > 0 ? 1 : 0);
484                         break; }
485                 case AUTOMATION_PROJECTOR_X:
486                 case AUTOMATION_PROJECTOR_Y:
487                 case AUTOMATION_PROJECTOR_Z: {
488                         int v = gui->check_xyz(AUTOMATION_PROJECTOR_X);
489                         gui->projector_xyz->set_value(v > 0 ? 1 : 0);
490                         break; }
491                 }
492         }
493         else {
494                 int group = -1;
495                 switch( info->ref ) {
496                 case NONAUTOTOGGLES_CAMERA_XYZ:     group = AUTOMATION_CAMERA_X;     break;
497                 case NONAUTOTOGGLES_PROJECTOR_XYZ:  group = AUTOMATION_PROJECTOR_X;  break;
498                 case NON_AUTOMATION_HARD_EDGES: *gui->get_main_value(info) = value;  break;
499                 }
500                 if( group >= 0 ) {
501                         gui->xyz_check(group, value);
502                         gui->update_toggles(0);
503                 }
504         }
505         gui->update_mwindow(1, 0);
506
507 // Update stuff in MWindow
508         unlock_window();
509         MWindow *mwindow = gui->mwindow;
510         mwindow->gui->lock_window("GWindowToggle::handle_event");
511
512         mwindow->gui->update(1, NORMAL_DRAW, 0, 0, 1, 0, 0);
513         mwindow->gui->draw_overlays(1);
514
515         if( value && info->isauto > 0 ) {
516                 int autogroup_type = -1;
517                 switch( info->ref ) {
518                 case AUTOMATION_FADE:
519                         autogroup_type = mwindow->edl->tracks->recordable_video_tracks() ?
520                                 AUTOGROUPTYPE_VIDEO_FADE : AUTOGROUPTYPE_AUDIO_FADE ;
521                         break;
522                 case AUTOMATION_SPEED:
523                         autogroup_type = AUTOGROUPTYPE_SPEED;
524                         break;
525                 case AUTOMATION_CAMERA_X:
526                 case AUTOMATION_PROJECTOR_X:
527                         autogroup_type = AUTOGROUPTYPE_X;
528                         break;
529                 case AUTOMATION_CAMERA_Y:
530                 case AUTOMATION_PROJECTOR_Y:
531                         autogroup_type = AUTOGROUPTYPE_Y;
532                         break;
533                 case AUTOMATION_CAMERA_Z:
534                 case AUTOMATION_PROJECTOR_Z:
535                         autogroup_type = AUTOGROUPTYPE_ZOOM;
536                         break;
537                 }
538                 if( autogroup_type >= 0 ) {
539                         mwindow->edl->local_session->zoombar_showautotype = autogroup_type;
540                         mwindow->gui->zoombar->update_autozoom();
541                 }
542         }
543
544         mwindow->gui->unlock_window();
545         lock_window("GWindowToggle::handle_event");
546
547         return 1;
548 }
549
550 void GWindowToggle::update()
551 {
552         int *vp = gui->get_main_value(info);
553         if( vp ) set_value(*vp);
554 }
555
556 void GWindowToggle::update_gui(int color)
557 {
558         BC_Toggle::color = color;
559         draw_face(1,0);
560 }
561
562 int GWindowToggle::draw_face(int flash, int flush)
563 {
564         int ret = BC_Toggle::draw_face(flash, flush);
565         if( hot ) {
566                 set_color(color);
567                 set_opaque();
568                 draw_rectangle(text_x-1, text_y-1, text_w+1, text_h+1);
569                 if( flash ) this->flash(0);
570                 if( flush ) this->flush();
571         }
572         return ret;
573 }
574
575 void GWindowGUI::set_cool(int reset, int all)
576 {
577         for( int i=0; i<(int)(sizeof(toggles)/sizeof(toggles[0])); ++i ) {
578                 GWindowToggle* toggle = toggles[i];
579                 if( !toggle ) continue;
580                 int *vp = get_main_value(toggle->info);
581                 if( !vp ) continue;
582                 if( toggle->hot ) {
583                         toggle->hot = 0;
584                         toggle->draw_face(1, 0);
585                 }
586                 if( reset > 0 )
587                         *vp = toggle->hot_value;
588                 else {
589                         toggle->hot_value = *vp;
590                         if( reset < 0 ) {
591                                 if ( all || toggle->info->isauto > 0 )
592                                         *vp = 0;
593                         }
594                 }
595         }
596         if( reset )
597                 update_toggles(0);
598 }
599
600 void GWindowGUI::set_hot(GWindowToggle *toggle)
601 {
602         int *vp = get_main_value(toggle->info);
603         if( !vp ) return;
604         set_cool(-1, !toggle->info->isauto ? 1 : 0);
605         toggle->hot = 1;
606         toggle->set_value(*vp = 1);
607 }
608