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