fix ruler, cwdw info popup updates, reset camera/projector shortcuts, findobj tweak...
[goodguy/history.git] / cinelerra-5.1 / cinelerra / cwindowtool.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 #include <stdio.h>
22 #include <stdint.h>
23
24 #include "automation.h"
25 #include "bccolors.h"
26 #include "clip.h"
27 #include "condition.h"
28 #include "cpanel.h"
29 #include "cplayback.h"
30 #include "cwindow.h"
31 #include "cwindowgui.h"
32 #include "cwindowtool.h"
33 #include "edl.h"
34 #include "edlsession.h"
35 #include "floatauto.h"
36 #include "floatautos.h"
37 #include "keys.h"
38 #include "language.h"
39 #include "localsession.h"
40 #include "mainsession.h"
41 #include "mainundo.h"
42 #include "maskauto.h"
43 #include "maskautos.h"
44 #include "mutex.h"
45 #include "mwindow.h"
46 #include "mwindowgui.h"
47 #include "theme.h"
48 #include "track.h"
49 #include "trackcanvas.h"
50 #include "transportque.h"
51
52
53 CWindowTool::CWindowTool(MWindow *mwindow, CWindowGUI *gui)
54  : Thread(1, 0, 0)
55 {
56         this->mwindow = mwindow;
57         this->gui = gui;
58         tool_gui = 0;
59         done = 0;
60         current_tool = CWINDOW_NONE;
61         set_synchronous(1);
62         input_lock = new Condition(0, "CWindowTool::input_lock");
63         output_lock = new Condition(1, "CWindowTool::output_lock");
64         tool_gui_lock = new Mutex("CWindowTool::tool_gui_lock");
65 }
66
67 CWindowTool::~CWindowTool()
68 {
69         done = 1;
70         stop_tool();
71         input_lock->unlock();
72         Thread::join();
73         delete input_lock;
74         delete output_lock;
75         delete tool_gui_lock;
76 }
77
78 void CWindowTool::start_tool(int operation)
79 {
80         CWindowToolGUI *new_gui = 0;
81         int result = 0;
82
83 //printf("CWindowTool::start_tool 1\n");
84         if(current_tool != operation)
85         {
86                 int previous_tool = current_tool;
87                 current_tool = operation;
88                 switch(operation)
89                 {
90                         case CWINDOW_EYEDROP:
91                                 new_gui = new CWindowEyedropGUI(mwindow, this);
92                                 break;
93                         case CWINDOW_CROP:
94                                 new_gui = new CWindowCropGUI(mwindow, this);
95                                 break;
96                         case CWINDOW_CAMERA:
97                                 new_gui = new CWindowCameraGUI(mwindow, this);
98                                 break;
99                         case CWINDOW_PROJECTOR:
100                                 new_gui = new CWindowProjectorGUI(mwindow, this);
101                                 break;
102                         case CWINDOW_MASK:
103                                 new_gui = new CWindowMaskGUI(mwindow, this);
104                                 break;
105                         case CWINDOW_RULER:
106                                 new_gui = new CWindowRulerGUI(mwindow, this);
107                                 break;
108                         case CWINDOW_PROTECT:
109                                 mwindow->edl->session->tool_window = 0;
110                                 gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]->update(0);
111                                 // fall thru
112                         default:
113                                 result = 1;
114                                 stop_tool();
115                                 break;
116                 }
117
118 //printf("CWindowTool::start_tool 1\n");
119
120
121                 if(!result)
122                 {
123                         stop_tool();
124 // Wait for previous tool GUI to finish
125                         output_lock->lock("CWindowTool::start_tool");
126                         this->tool_gui = new_gui;
127                         tool_gui->create_objects();
128                         if( previous_tool == CWINDOW_PROTECT || previous_tool == CWINDOW_NONE ) {
129                                 mwindow->edl->session->tool_window = 1;
130                                 gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]->update(1);
131                         }
132                         update_show_window();
133
134 // Signal thread to run next tool GUI
135                         input_lock->unlock();
136                 }
137 //printf("CWindowTool::start_tool 1\n");
138         }
139         else
140         if(tool_gui)
141         {
142                 tool_gui->lock_window("CWindowTool::start_tool");
143                 tool_gui->update();
144                 tool_gui->unlock_window();
145         }
146
147 //printf("CWindowTool::start_tool 2\n");
148
149 }
150
151
152 void CWindowTool::stop_tool()
153 {
154         if(tool_gui)
155         {
156                 tool_gui->lock_window("CWindowTool::stop_tool");
157                 tool_gui->set_done(0);
158                 tool_gui->unlock_window();
159         }
160 }
161
162 void CWindowTool::show_tool()
163 {
164         if(tool_gui && mwindow->edl->session->tool_window)
165         {
166                 tool_gui->lock_window("CWindowTool::show_tool");
167                 tool_gui->show_window();
168                 tool_gui->unlock_window();
169         }
170 }
171
172 void CWindowTool::hide_tool()
173 {
174         if(tool_gui && mwindow->edl->session->tool_window)
175         {
176                 tool_gui->lock_window("CWindowTool::show_tool");
177                 tool_gui->hide_window();
178                 tool_gui->unlock_window();
179         }
180 }
181
182
183 void CWindowTool::run()
184 {
185         while(!done)
186         {
187                 input_lock->lock("CWindowTool::run");
188                 if(!done)
189                 {
190                         tool_gui->run_window();
191                         tool_gui_lock->lock("CWindowTool::run");
192                         delete tool_gui;
193                         tool_gui = 0;
194                         tool_gui_lock->unlock();
195                 }
196                 output_lock->unlock();
197         }
198 }
199
200 void CWindowTool::update_show_window()
201 {
202         if(tool_gui)
203         {
204                 tool_gui->lock_window("CWindowTool::update_show_window");
205
206                 if(mwindow->edl->session->tool_window)
207                 {
208                         tool_gui->update();
209                         tool_gui->show_window();
210                 }
211                 else
212                         tool_gui->hide_window();
213                 tool_gui->flush();
214
215                 tool_gui->unlock_window();
216         }
217 }
218
219 void CWindowTool::raise_window()
220 {
221         if(tool_gui)
222         {
223                 gui->unlock_window();
224                 tool_gui->lock_window("CWindowTool::raise_window");
225                 tool_gui->raise_window();
226                 tool_gui->unlock_window();
227                 gui->lock_window("CWindowTool::raise_window");
228         }
229 }
230
231 void CWindowTool::update_values()
232 {
233         tool_gui_lock->lock("CWindowTool::update_values");
234         if(tool_gui)
235         {
236                 tool_gui->lock_window("CWindowTool::update_values");
237                 tool_gui->update();
238                 tool_gui->flush();
239                 tool_gui->unlock_window();
240         }
241         tool_gui_lock->unlock();
242 }
243
244
245
246
247
248
249
250 CWindowToolGUI::CWindowToolGUI(MWindow *mwindow,
251         CWindowTool *thread,
252         const char *title,
253         int w,
254         int h)
255  : BC_Window(title,
256         mwindow->session->ctool_x,
257         mwindow->session->ctool_y,
258         w,
259         h,
260         w,
261         h,
262         0,
263         0,
264         1)
265 {
266         this->mwindow = mwindow;
267         this->thread = thread;
268         current_operation = 0;
269 }
270
271 CWindowToolGUI::~CWindowToolGUI()
272 {
273 }
274
275 int CWindowToolGUI::close_event()
276 {
277         hide_window();
278         flush();
279         mwindow->edl->session->tool_window = 0;
280         unlock_window();
281
282
283
284         thread->gui->lock_window("CWindowToolGUI::close_event");
285         thread->gui->composite_panel->set_operation(mwindow->edl->session->cwindow_operation);
286         thread->gui->flush();
287         thread->gui->unlock_window();
288
289         lock_window("CWindowToolGUI::close_event");
290         return 1;
291 ;}
292
293 int CWindowToolGUI::keypress_event()
294 {
295         int result = 0;
296
297         switch( get_keypress() ) {
298         case 'w':
299         case 'W':
300                 return close_event();
301         case KEY_F1:
302         case KEY_F2:
303         case KEY_F3:
304         case KEY_F4:
305         case KEY_F5:
306         case KEY_F6:
307         case KEY_F7:
308         case KEY_F8:
309         case KEY_F9:
310         case KEY_F10:
311         case KEY_F11:
312         case KEY_F12:
313                 resend_event(thread->gui);
314                 result = 1;
315         }
316
317         return result;
318 }
319
320 int CWindowToolGUI::translation_event()
321 {
322         mwindow->session->ctool_x = get_x();
323         mwindow->session->ctool_y = get_y();
324         return 0;
325 }
326
327
328
329
330
331
332 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, float value, int log_increment = 0)
333  : BC_TumbleTextBox(gui, (float)value, (float)-65536, (float)65536, x, y, 100)
334 {
335         this->gui = gui;
336         set_log_floatincrement(log_increment);
337 }
338
339 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, int value)
340  : BC_TumbleTextBox(gui, (int64_t)value, (int64_t)-65536, (int64_t)65536, x, y, 100)
341 {
342         this->gui = gui;
343 }
344 int CWindowCoord::handle_event()
345 {
346         gui->event_caller = this;
347         gui->handle_event();
348         return 1;
349 }
350
351
352 CWindowCropOK::CWindowCropOK(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
353  : BC_GenericButton(x, y, _("Do it"))
354 {
355         this->mwindow = mwindow;
356         this->gui = gui;
357 }
358 int CWindowCropOK::handle_event()
359 {
360         mwindow->crop_video();
361         return 1;
362 }
363
364
365 int CWindowCropOK::keypress_event()
366 {
367         if(get_keypress() == 0xd)
368         {
369                 handle_event();
370                 return 1;
371         }
372         return 0;
373 }
374
375
376
377
378
379
380
381 CWindowCropGUI::CWindowCropGUI(MWindow *mwindow, CWindowTool *thread)
382  : CWindowToolGUI(mwindow,
383         thread,
384         _(PROGRAM_NAME ": Crop"),
385         330,
386         100)
387 {
388 }
389
390
391 CWindowCropGUI::~CWindowCropGUI()
392 {
393 }
394
395 void CWindowCropGUI::create_objects()
396 {
397         int x = 10, y = 10;
398         BC_Title *title;
399
400         lock_window("CWindowCropGUI::create_objects");
401         int column1 = 0;
402         int pad = MAX(BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1),
403                 BC_Title::calculate_h(this, "X")) + 5;
404         add_subwindow(title = new BC_Title(x, y, "X1:"));
405         column1 = MAX(column1, title->get_w());
406         y += pad;
407         add_subwindow(title = new BC_Title(x, y, _("W:")));
408         column1 = MAX(column1, title->get_w());
409         y += pad;
410         add_subwindow(new CWindowCropOK(mwindow, thread->tool_gui, x, y));
411
412         x += column1 + 5;
413         y = 10;
414         x1 = new CWindowCoord(thread->tool_gui, x, y,
415                 mwindow->edl->session->crop_x1);
416         x1->create_objects();
417         y += pad;
418         width = new CWindowCoord(thread->tool_gui, x, y,
419                 mwindow->edl->session->crop_x2 - mwindow->edl->session->crop_x1);
420         width->create_objects();
421
422
423         x += x1->get_w() + 10;
424         y = 10;
425         int column2 = 0;
426         add_subwindow(title = new BC_Title(x, y, "Y1:"));
427         column2 = MAX(column2, title->get_w());
428         y += pad;
429         add_subwindow(title = new BC_Title(x, y, _("H:")));
430         column2 = MAX(column2, title->get_w());
431         y += pad;
432
433         y = 10;
434         x += column2 + 5;
435         y1 = new CWindowCoord(thread->tool_gui, x, y,
436                 mwindow->edl->session->crop_y1);
437         y1->create_objects();
438         y += pad;
439         height = new CWindowCoord(thread->tool_gui, x, y,
440                 mwindow->edl->session->crop_y2 - mwindow->edl->session->crop_y1);
441         height->create_objects();
442         unlock_window();
443 }
444
445 void CWindowCropGUI::handle_event()
446 {
447         int new_x1, new_y1;
448         new_x1 = atol(x1->get_text());
449         new_y1 = atol(y1->get_text());
450         if(new_x1 != mwindow->edl->session->crop_x1)
451         {
452                 mwindow->edl->session->crop_x2 = new_x1 +
453                         mwindow->edl->session->crop_x2 -
454                         mwindow->edl->session->crop_x1;
455                 mwindow->edl->session->crop_x1 = new_x1;
456         }
457         if(new_y1 != mwindow->edl->session->crop_y1)
458         {
459                 mwindow->edl->session->crop_y2 = new_y1 +
460                         mwindow->edl->session->crop_y2 -
461                         mwindow->edl->session->crop_y1;
462                 mwindow->edl->session->crop_y1 = atol(y1->get_text());
463         }
464         mwindow->edl->session->crop_x2 = atol(width->get_text()) +
465                 mwindow->edl->session->crop_x1;
466         mwindow->edl->session->crop_y2 = atol(height->get_text()) +
467                 mwindow->edl->session->crop_y1;
468         update();
469         mwindow->cwindow->gui->lock_window("CWindowCropGUI::handle_event");
470         mwindow->cwindow->gui->canvas->draw_refresh();
471         mwindow->cwindow->gui->unlock_window();
472 }
473
474 void CWindowCropGUI::update()
475 {
476         x1->update((int64_t)mwindow->edl->session->crop_x1);
477         y1->update((int64_t)mwindow->edl->session->crop_y1);
478         width->update((int64_t)mwindow->edl->session->crop_x2 -
479                 mwindow->edl->session->crop_x1);
480         height->update((int64_t)mwindow->edl->session->crop_y2 -
481                 mwindow->edl->session->crop_y1);
482 }
483
484
485 CWindowEyedropGUI::CWindowEyedropGUI(MWindow *mwindow, CWindowTool *thread)
486  : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Color"), 220, 290)
487 {
488 }
489
490 CWindowEyedropGUI::~CWindowEyedropGUI()
491 {
492 }
493
494 void CWindowEyedropGUI::create_objects()
495 {
496         int margin = mwindow->theme->widget_border;
497         int x = 10 + margin;
498         int y = 10 + margin;
499         int x2 = 70, x3 = x2 + 60;
500         lock_window("CWindowEyedropGUI::create_objects");
501         BC_Title *title0, *title1, *title2, *title3, *title4, *title5, *title6, *title7;
502         add_subwindow(title0 = new BC_Title(x, y,_("X,Y:")));
503         y += title0->get_h() + margin;
504         add_subwindow(title7 = new BC_Title(x, y, _("Radius:")));
505         y += BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1) + margin;
506
507         add_subwindow(title1 = new BC_Title(x, y, _("Red:")));
508         y += title1->get_h() + margin;
509         add_subwindow(title2 = new BC_Title(x, y, _("Green:")));
510         y += title2->get_h() + margin;
511         add_subwindow(title3 = new BC_Title(x, y, _("Blue:")));
512         y += title3->get_h() + margin;
513
514         add_subwindow(title4 = new BC_Title(x, y, "Y:"));
515         y += title4->get_h() + margin;
516         add_subwindow(title5 = new BC_Title(x, y, "U:"));
517         y += title5->get_h() + margin;
518         add_subwindow(title6 = new BC_Title(x, y, "V:"));
519
520         add_subwindow(current = new BC_Title(x2, title0->get_y(), ""));
521
522         radius = new CWindowCoord(this, x2, title7->get_y(),
523                 mwindow->edl->session->eyedrop_radius);
524         radius->create_objects();
525         radius->set_boundaries((int64_t)0, (int64_t)255);
526
527         add_subwindow(red = new BC_Title(x2, title1->get_y(), "0"));
528         add_subwindow(green = new BC_Title(x2, title2->get_y(), "0"));
529         add_subwindow(blue = new BC_Title(x2, title3->get_y(), "0"));
530         add_subwindow(rgb_hex = new BC_Title(x3, red->get_y(), "#000000"));
531
532         add_subwindow(this->y = new BC_Title(x2, title4->get_y(), "0"));
533         add_subwindow(this->u = new BC_Title(x2, title5->get_y(), "0"));
534         add_subwindow(this->v = new BC_Title(x2, title6->get_y(), "0"));
535         add_subwindow(yuv_hex = new BC_Title(x3, this->y->get_y(), "#000000"));
536
537         y = title6->get_y() + this->v->get_h() + 2*margin;
538         add_subwindow(sample = new BC_SubWindow(x, y, 50, 50));
539         y += sample->get_h() + margin;
540         add_subwindow(use_max = new CWindowEyedropCheckBox(mwindow, this, x, y));
541         update();
542         unlock_window();
543 }
544
545 void CWindowEyedropGUI::update()
546 {
547         char string[BCTEXTLEN];
548         sprintf(string, "%d, %d",
549                 thread->gui->eyedrop_x,
550                 thread->gui->eyedrop_y);
551         current->update(string);
552
553         radius->update((int64_t)mwindow->edl->session->eyedrop_radius);
554
555         LocalSession *local_session = mwindow->edl->local_session;
556         int use_max = local_session->use_max;
557         float r = use_max ? local_session->red_max : local_session->red;
558         float g = use_max ? local_session->green_max : local_session->green;
559         float b = use_max ? local_session->blue_max : local_session->blue;
560         this->red->update(r);
561         this->green->update(g);
562         this->blue->update(b);
563
564         int rx = 255*r + 0.5;  bclamp(rx,0,255);
565         int gx = 255*g + 0.5;  bclamp(gx,0,255);
566         int bx = 255*b + 0.5;  bclamp(bx,0,255);
567         char rgb_text[BCSTRLEN];
568         sprintf(rgb_text, "#%02x%02x%02x", rx, gx, bx);
569         rgb_hex->update(rgb_text);
570         
571         float y, u, v;
572         YUV::yuv.rgb_to_yuv_f(r, g, b, y, u, v);
573         this->y->update(y);
574         this->u->update(u);  u += 0.5;
575         this->v->update(v);  v += 0.5;
576
577         int yx = 255*y + 0.5;  bclamp(yx,0,255);
578         int ux = 255*u + 0.5;  bclamp(ux,0,255);
579         int vx = 255*v + 0.5;  bclamp(vx,0,255);
580         char yuv_text[BCSTRLEN];
581         sprintf(yuv_text, "#%02x%02x%02x", yx, ux, vx);
582         yuv_hex->update(yuv_text);
583
584         int rgb = (rx << 16) | (gx << 8) | (bx << 0);
585         sample->set_color(rgb);
586         sample->draw_box(0, 0, sample->get_w(), sample->get_h());
587         sample->set_color(BLACK);
588         sample->draw_rectangle(0, 0, sample->get_w(), sample->get_h());
589         sample->flash();
590 }
591
592 void CWindowEyedropGUI::handle_event()
593 {
594         int new_radius = atoi(radius->get_text());
595         if(new_radius != mwindow->edl->session->eyedrop_radius)
596         {
597                 CWindowGUI *gui = mwindow->cwindow->gui;
598                 if(gui->eyedrop_visible)
599                 {
600                         gui->lock_window("CWindowEyedropGUI::handle_event");
601 // hide it
602                         int rerender;
603                         gui->canvas->do_eyedrop(rerender, 0, 1);
604                 }
605
606                 mwindow->edl->session->eyedrop_radius = new_radius;
607
608                 if(gui->eyedrop_visible)
609                 {
610 // draw it
611                         int rerender;
612                         gui->canvas->do_eyedrop(rerender, 0, 1);
613                         gui->unlock_window();
614                 }
615         }
616 }
617
618
619
620 /* Buttons to control Keyframe-Curve-Mode for Projector or Camera */
621
622 // Configuration for all possible Keyframe Curve Mode toggles
623 struct _CVD {
624         FloatAuto::t_mode mode;
625         bool use_camera;
626         const char* icon_id;
627         const char* tooltip;
628 };
629
630 const _CVD Camera_Crv_Smooth =
631         {       FloatAuto::SMOOTH,
632                 true,
633                 "tan_smooth",
634                 N_("\"smooth\" Curve on current Camera Keyframes")
635         };
636 const _CVD Camera_Crv_Linear =
637         {       FloatAuto::LINEAR,
638                 true,
639                 "tan_linear",
640                 N_("\"linear\" Curve on current Camera Keyframes")
641         };
642 const _CVD Projector_Crv_Smooth =
643         {       FloatAuto::SMOOTH,
644                 false,
645                 "tan_smooth",
646                 N_("\"smooth\" Curve on current Projector Keyframes")
647         };
648 const _CVD Projector_Crv_Linear =
649         {       FloatAuto::LINEAR,
650                 false,
651                 "tan_linear",
652                 N_("\"linear\" Curve on current Projector Keyframes")
653         };
654
655 // Implementation Class für Keyframe Curve Mode buttons
656 //
657 // This button reflects the state of the "current" keyframe
658 // (the nearest keyframe on the left) for all three automation
659 // lines together. Clicking on this button (re)sets the curve
660 // mode for the three "current" keyframes simultanously, but
661 // never creates a new keyframe.
662 //
663 class CWindowCurveToggle : public BC_Toggle
664 {
665 public:
666         CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y);
667         void check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z);
668         int handle_event();
669 private:
670         _CVD cfg;
671         MWindow *mwindow;
672         CWindowToolGUI *gui;
673 };
674
675
676 CWindowCurveToggle::CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
677  : BC_Toggle(x, y, mwindow->theme->get_image_set(mode.icon_id), false),
678    cfg(mode)
679 {
680         this->gui = gui;
681         this->mwindow = mwindow;
682         set_tooltip(_(cfg.tooltip));
683 }
684
685 void CWindowCurveToggle::check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z)
686 {
687 // the toggle state is only set to ON if all
688 // three automation lines have the same curve mode.
689 // For mixed states the toggle stays off.
690         set_value( x->curve_mode == this->cfg.mode &&
691                    y->curve_mode == this->cfg.mode &&
692                    z->curve_mode == this->cfg.mode
693                  ,true // redraw to show new state
694                  );
695 }
696
697 int CWindowCurveToggle::handle_event()
698 {
699         FloatAuto *x=0, *y=0, *z=0;
700         Track *track = mwindow->cwindow->calculate_affected_track();
701
702         if(track)
703         {       mwindow->cwindow->calculate_affected_autos(&x, &y, &z,
704                         track, cfg.use_camera, 0,0,0); // don't create new keyframe
705
706                 if(x)   x->change_curve_mode(cfg.mode);
707                 if(y)   y->change_curve_mode(cfg.mode);
708                 if(z)   z->change_curve_mode(cfg.mode);
709
710                 gui->update();
711                 gui->update_preview();
712         }
713
714         return 1;
715 }
716
717
718 CWindowEyedropCheckBox::CWindowEyedropCheckBox(MWindow *mwindow, 
719         CWindowEyedropGUI *gui, int x, int y)
720  : BC_CheckBox(x, y, mwindow->edl->local_session->use_max, _("Use maximum"))
721 {
722         this->mwindow = mwindow;
723         this->gui = gui;
724 }
725
726 int CWindowEyedropCheckBox::handle_event()
727 {
728         mwindow->edl->local_session->use_max = get_value();
729         
730         gui->update();
731         return 1;
732 }
733
734
735 CWindowCameraGUI::CWindowCameraGUI(MWindow *mwindow, CWindowTool *thread)
736  : CWindowToolGUI(mwindow,
737         thread,
738         _(PROGRAM_NAME ": Camera"),
739         170,
740         170)
741 {
742 }
743 CWindowCameraGUI::~CWindowCameraGUI()
744 {
745 }
746
747 void CWindowCameraGUI::create_objects()
748 {
749         int x = 10, y = 10, x1;
750         Track *track = mwindow->cwindow->calculate_affected_track();
751         FloatAuto *x_auto = 0;
752         FloatAuto *y_auto = 0;
753         FloatAuto *z_auto = 0;
754         BC_Title *title;
755         BC_Button *button;
756
757         lock_window("CWindowCameraGUI::create_objects");
758         if(track)
759         {
760                 mwindow->cwindow->calculate_affected_autos(&x_auto,
761                         &y_auto, &z_auto, track, 1, 0, 0, 0);
762         }
763
764         add_subwindow(title = new BC_Title(x, y, "X:"));
765         x += title->get_w();
766         this->x = new CWindowCoord(this, x, y,
767                 x_auto ? x_auto->get_value() : (float)0);
768         this->x->create_objects();
769
770
771         y += 30;
772         x = 10;
773         add_subwindow(title = new BC_Title(x, y, "Y:"));
774         x += title->get_w();
775         this->y = new CWindowCoord(this, x, y,
776                 y_auto ? y_auto->get_value() : (float)0);
777         this->y->create_objects();
778         y += 30;
779         x = 10;
780         add_subwindow(title = new BC_Title(x, y, "Z:"));
781         x += title->get_w();
782         this->z = new CWindowCoord(this, x, y,
783                 z_auto ? z_auto->get_value() : (float)1);
784         this->z->create_objects();
785         this->z->set_increment(0.01);
786
787         y += 30;
788         x1 = 10;
789         add_subwindow(button = new CWindowCameraLeft(mwindow, this, x1, y));
790         x1 += button->get_w();
791         add_subwindow(button = new CWindowCameraCenter(mwindow, this, x1, y));
792         x1 += button->get_w();
793         add_subwindow(button = new CWindowCameraRight(mwindow, this, x1, y));
794
795         y += button->get_h();
796         x1 = 10;
797         add_subwindow(button = new CWindowCameraTop(mwindow, this, x1, y));
798         x1 += button->get_w();
799         add_subwindow(button = new CWindowCameraMiddle(mwindow, this, x1, y));
800         x1 += button->get_w();
801         add_subwindow(button = new CWindowCameraBottom(mwindow, this, x1, y));
802 // additional Buttons to control the curve mode of the "current" keyframe
803         x1 += button->get_w() + 15;
804         add_subwindow(this->t_smooth = new CWindowCurveToggle(Camera_Crv_Smooth, mwindow, this, x1, y));
805         x1 += button->get_w();
806         add_subwindow(this->t_linear = new CWindowCurveToggle(Camera_Crv_Linear, mwindow, this, x1, y));
807
808 // fill in current auto keyframe values, set toggle states.
809         this->update();
810         unlock_window();
811 }
812
813 void CWindowCameraGUI::update_preview()
814 {
815         mwindow->gui->lock_window("CWindowCameraGUI::update_preview");
816         mwindow->restart_brender();
817         mwindow->gui->draw_overlays(1);
818         mwindow->sync_parameters(CHANGE_PARAMS);
819         mwindow->gui->unlock_window();
820         mwindow->cwindow->refresh_frame(CHANGE_NONE);
821         mwindow->cwindow->gui->lock_window("CWindowCameraGUI::update_preview");
822         mwindow->cwindow->gui->canvas->draw_refresh();
823         mwindow->cwindow->gui->unlock_window();
824 }
825
826
827 void CWindowCameraGUI::handle_event()
828 {
829         FloatAuto *x_auto = 0;
830         FloatAuto *y_auto = 0;
831         FloatAuto *z_auto = 0;
832         Track *track = mwindow->cwindow->calculate_affected_track();
833         if(track)
834         {
835                 mwindow->undo->update_undo_before(_("camera"), this);
836                 if(event_caller == x)
837                 {
838                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
839                                 track->automation->autos[AUTOMATION_CAMERA_X],
840                                 1);
841                         if(x_auto)
842                         {
843                                 x_auto->set_value(atof(x->get_text()));
844                                 update();
845                                 update_preview();
846                         }
847                 }
848                 else
849                 if(event_caller == y)
850                 {
851                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
852                                 track->automation->autos[AUTOMATION_CAMERA_Y],
853                                 1);
854                         if(y_auto)
855                         {
856                                 y_auto->set_value(atof(y->get_text()));
857                                 update();
858                                 update_preview();
859                         }
860                 }
861                 else
862                 if(event_caller == z)
863                 {
864                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
865                                 track->automation->autos[AUTOMATION_CAMERA_Z],
866                                 1);
867                         if(z_auto)
868                         {
869                                 float zoom = atof(z->get_text());
870                                 if(zoom > 100.) zoom = 100.;
871                                 else
872                                 if(zoom < 0.01) zoom = 0.01;
873         // Doesn't allow user to enter from scratch
874         //              if(zoom != atof(z->get_text()))
875         //                      z->update(zoom);
876
877                                 z_auto->set_value(zoom);
878                                 mwindow->gui->lock_window("CWindowCameraGUI::handle_event");
879                                 mwindow->gui->draw_overlays(1);
880                                 mwindow->gui->unlock_window();
881                                 update();
882                                 update_preview();
883                         }
884                 }
885
886                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
887         }
888 }
889
890 void CWindowCameraGUI::update()
891 {
892         FloatAuto *x_auto = 0;
893         FloatAuto *y_auto = 0;
894         FloatAuto *z_auto = 0;
895         Track *track = mwindow->cwindow->calculate_affected_track();
896
897         if(track)
898         {
899                 mwindow->cwindow->calculate_affected_autos(&x_auto,
900                         &y_auto,
901                         &z_auto,
902                         track,
903                         1,
904                         0,
905                         0,
906                         0);
907         }
908
909         if(x_auto)
910                 x->update(x_auto->get_value());
911         if(y_auto)
912                 y->update(y_auto->get_value());
913         if(z_auto) {
914                 float value = z_auto->get_value();
915                 z->update(value);
916                 thread->gui->composite_panel->cpanel_zoom->update(value);
917         }
918
919         if( x_auto && y_auto && z_auto )
920         {
921                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
922                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
923         }
924 }
925
926
927
928
929 CWindowCameraLeft::CWindowCameraLeft(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
930  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
931 {
932         this->gui = gui;
933         this->mwindow = mwindow;
934         set_tooltip(_("Left justify"));
935 }
936 int CWindowCameraLeft::handle_event()
937 {
938         FloatAuto *x_auto = 0;
939         FloatAuto *z_auto = 0;
940         Track *track = mwindow->cwindow->calculate_affected_track();
941         if(track)
942         {
943                 mwindow->cwindow->calculate_affected_autos(&x_auto,
944                         0,
945                         &z_auto,
946                         track,
947                         1,
948                         1,
949                         0,
950                         0);
951         }
952
953         if(x_auto && z_auto)
954         {
955                 int w = 0, h = 0;
956                 track->get_source_dimensions(
957                         mwindow->edl->local_session->get_selectionstart(1),
958                         w,
959                         h);
960
961                 if(w && h)
962                 {
963                         mwindow->undo->update_undo_before(_("camera"), 0);
964                         x_auto->set_value(
965                                 (double)track->track_w / z_auto->get_value() / 2 -
966                                 (double)w / 2);
967                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
968                         gui->update();
969                         gui->update_preview();
970                 }
971         }
972
973         return 1;
974 }
975
976
977 CWindowCameraCenter::CWindowCameraCenter(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
978  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
979 {
980         this->gui = gui;
981         this->mwindow = mwindow;
982         set_tooltip(_("Center horizontal"));
983 }
984 int CWindowCameraCenter::handle_event()
985 {
986         FloatAuto *x_auto = 0;
987         Track *track = mwindow->cwindow->calculate_affected_track();
988         if(track)
989                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
990                         track->automation->autos[AUTOMATION_CAMERA_X],
991                         1);
992
993         if(x_auto)
994         {
995                 mwindow->undo->update_undo_before(_("camera"), 0);
996                 x_auto->set_value(0);
997                 gui->update();
998                 gui->update_preview();
999                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1000         }
1001
1002         return 1;
1003 }
1004
1005
1006 CWindowCameraRight::CWindowCameraRight(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1007  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1008 {
1009         this->gui = gui;
1010         this->mwindow = mwindow;
1011         set_tooltip(_("Right justify"));
1012 }
1013 int CWindowCameraRight::handle_event()
1014 {
1015         FloatAuto *x_auto = 0;
1016         FloatAuto *z_auto = 0;
1017         Track *track = mwindow->cwindow->calculate_affected_track();
1018         if(track)
1019         {
1020                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1021                         0,
1022                         &z_auto,
1023                         track,
1024                         1,
1025                         1,
1026                         0,
1027                         0);
1028         }
1029
1030         if(x_auto && z_auto)
1031         {
1032                 int w = 0, h = 0;
1033                 track->get_source_dimensions(
1034                         mwindow->edl->local_session->get_selectionstart(1),
1035                         w,
1036                         h);
1037
1038                 if(w && h)
1039                 {
1040                         mwindow->undo->update_undo_before(_("camera"), 0);
1041                         x_auto->set_value( -((double)track->track_w / z_auto->get_value() / 2 -
1042                                 (double)w / 2));
1043                         gui->update();
1044                         gui->update_preview();
1045                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1046                 }
1047         }
1048
1049         return 1;
1050 }
1051
1052
1053 CWindowCameraTop::CWindowCameraTop(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1054  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1055 {
1056         this->gui = gui;
1057         this->mwindow = mwindow;
1058         set_tooltip(_("Top justify"));
1059 }
1060 int CWindowCameraTop::handle_event()
1061 {
1062         FloatAuto *y_auto = 0;
1063         FloatAuto *z_auto = 0;
1064         Track *track = mwindow->cwindow->calculate_affected_track();
1065         if(track)
1066         {
1067                 mwindow->cwindow->calculate_affected_autos(0,
1068                         &y_auto,
1069                         &z_auto,
1070                         track,
1071                         1,
1072                         0,
1073                         1,
1074                         0);
1075         }
1076
1077         if(y_auto && z_auto)
1078         {
1079                 int w = 0, h = 0;
1080                 track->get_source_dimensions(
1081                         mwindow->edl->local_session->get_selectionstart(1),
1082                         w,
1083                         h);
1084
1085                 if(w && h)
1086                 {
1087                         mwindow->undo->update_undo_before(_("camera"), 0);
1088                         y_auto->set_value((double)track->track_h / z_auto->get_value() / 2 -
1089                                 (double)h / 2);
1090                         gui->update();
1091                         gui->update_preview();
1092                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1093                 }
1094         }
1095
1096         return 1;
1097 }
1098
1099
1100 CWindowCameraMiddle::CWindowCameraMiddle(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1101  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1102 {
1103         this->gui = gui;
1104         this->mwindow = mwindow;
1105         set_tooltip(_("Center vertical"));
1106 }
1107 int CWindowCameraMiddle::handle_event()
1108 {
1109         FloatAuto *y_auto = 0;
1110         Track *track = mwindow->cwindow->calculate_affected_track();
1111         if(track)
1112                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1113                         track->automation->autos[AUTOMATION_CAMERA_Y], 1);
1114
1115         if(y_auto)
1116         {
1117                 mwindow->undo->update_undo_before(_("camera"), 0);
1118                 y_auto->set_value(0);
1119                 gui->update();
1120                 gui->update_preview();
1121                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1122         }
1123
1124         return 1;
1125 }
1126
1127
1128 CWindowCameraBottom::CWindowCameraBottom(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1129  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1130 {
1131         this->gui = gui;
1132         this->mwindow = mwindow;
1133         set_tooltip(_("Bottom justify"));
1134 }
1135 int CWindowCameraBottom::handle_event()
1136 {
1137         FloatAuto *y_auto = 0;
1138         FloatAuto *z_auto = 0;
1139         Track *track = mwindow->cwindow->calculate_affected_track();
1140         if(track)
1141         {
1142                 mwindow->cwindow->calculate_affected_autos(0,
1143                         &y_auto,
1144                         &z_auto,
1145                         track,
1146                         1,
1147                         0,
1148                         1,
1149                         0);
1150         }
1151
1152         if(y_auto && z_auto)
1153         {
1154                 int w = 0, h = 0;
1155                 track->get_source_dimensions(
1156                         mwindow->edl->local_session->get_selectionstart(1),
1157                         w,
1158                         h);
1159
1160                 if(w && h)
1161                 {
1162                         mwindow->undo->update_undo_before(_("camera"), 0);
1163                         y_auto->set_value(-((double)track->track_h / z_auto->get_value() / 2 -
1164                                 (double)h / 2));
1165                         gui->update();
1166                         gui->update_preview();
1167                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1168                 }
1169         }
1170
1171         return 1;
1172 }
1173
1174
1175 CWindowProjectorGUI::CWindowProjectorGUI(MWindow *mwindow, CWindowTool *thread)
1176  : CWindowToolGUI(mwindow,
1177         thread,
1178         _(PROGRAM_NAME ": Projector"),
1179         170,
1180         170)
1181 {
1182 }
1183 CWindowProjectorGUI::~CWindowProjectorGUI()
1184 {
1185 }
1186 void CWindowProjectorGUI::create_objects()
1187 {
1188         int x = 10, y = 10, x1;
1189         Track *track = mwindow->cwindow->calculate_affected_track();
1190         FloatAuto *x_auto = 0;
1191         FloatAuto *y_auto = 0;
1192         FloatAuto *z_auto = 0;
1193         BC_Title *title;
1194         BC_Button *button;
1195
1196         lock_window("CWindowProjectorGUI::create_objects");
1197         if(track)
1198         {
1199                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1200                         &y_auto,
1201                         &z_auto,
1202                         track,
1203                         0,
1204                         0,
1205                         0,
1206                         0);
1207         }
1208
1209         add_subwindow(title = new BC_Title(x, y, "X:"));
1210         x += title->get_w();
1211         this->x = new CWindowCoord(this, x, y,
1212                 x_auto ? x_auto->get_value() : (float)0);
1213         this->x->create_objects();
1214         y += 30;
1215         x = 10;
1216         add_subwindow(title = new BC_Title(x, y, "Y:"));
1217         x += title->get_w();
1218         this->y = new CWindowCoord(this, x, y,
1219                 y_auto ? y_auto->get_value() : (float)0);
1220         this->y->create_objects();
1221         y += 30;
1222         x = 10;
1223         add_subwindow(title = new BC_Title(x, y, "Z:"));
1224         x += title->get_w();
1225         this->z = new CWindowCoord(this, x, y,
1226                 z_auto ? z_auto->get_value() : (float)1);
1227         this->z->create_objects();
1228         this->z->set_increment(0.01);
1229
1230         y += 30;
1231         x1 = 10;
1232         add_subwindow(button = new CWindowProjectorLeft(mwindow, this, x1, y));
1233         x1 += button->get_w();
1234         add_subwindow(button = new CWindowProjectorCenter(mwindow, this, x1, y));
1235         x1 += button->get_w();
1236         add_subwindow(button = new CWindowProjectorRight(mwindow, this, x1, y));
1237
1238         y += button->get_h();
1239         x1 = 10;
1240         add_subwindow(button = new CWindowProjectorTop(mwindow, this, x1, y));
1241         x1 += button->get_w();
1242         add_subwindow(button = new CWindowProjectorMiddle(mwindow, this, x1, y));
1243         x1 += button->get_w();
1244         add_subwindow(button = new CWindowProjectorBottom(mwindow, this, x1, y));
1245
1246 // additional Buttons to control the curve mode of the "current" keyframe
1247         x1 += button->get_w() + 15;
1248         add_subwindow(this->t_smooth = new CWindowCurveToggle(Projector_Crv_Smooth, mwindow, this, x1, y));
1249         x1 += button->get_w();
1250         add_subwindow(this->t_linear = new CWindowCurveToggle(Projector_Crv_Linear, mwindow, this, x1, y));
1251
1252 // fill in current auto keyframe values, set toggle states.
1253         this->update();
1254         unlock_window();
1255 }
1256
1257 void CWindowProjectorGUI::update_preview()
1258 {
1259         mwindow->gui->lock_window("CWindowProjectorGUI::update_preview");
1260         mwindow->restart_brender();
1261         mwindow->sync_parameters(CHANGE_PARAMS);
1262         mwindow->gui->draw_overlays(1);
1263         mwindow->gui->unlock_window();
1264         mwindow->cwindow->refresh_frame(CHANGE_NONE);
1265         mwindow->cwindow->gui->lock_window("CWindowProjectorGUI::update_preview");
1266         mwindow->cwindow->gui->canvas->draw_refresh();
1267         mwindow->cwindow->gui->unlock_window();
1268 }
1269
1270 void CWindowProjectorGUI::handle_event()
1271 {
1272         FloatAuto *x_auto = 0;
1273         FloatAuto *y_auto = 0;
1274         FloatAuto *z_auto = 0;
1275         Track *track = mwindow->cwindow->calculate_affected_track();
1276
1277         if(track)
1278         {
1279                 mwindow->undo->update_undo_before(_("projector"), this);
1280                 if(event_caller == x)
1281                 {
1282                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1283                                 track->automation->autos[AUTOMATION_PROJECTOR_X],
1284                                 1);
1285                         if(x_auto)
1286                         {
1287                                 x_auto->set_value(atof(x->get_text()));
1288                                 update();
1289                                 update_preview();
1290                         }
1291                 }
1292                 else
1293                 if(event_caller == y)
1294                 {
1295                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1296                                 track->automation->autos[AUTOMATION_PROJECTOR_Y],
1297                                 1);
1298                         if(y_auto)
1299                         {
1300                                 y_auto->set_value(atof(y->get_text()));
1301                                 update();
1302                                 update_preview();
1303                         }
1304                 }
1305                 else
1306                 if(event_caller == z)
1307                 {
1308                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1309                                 track->automation->autos[AUTOMATION_PROJECTOR_Z],
1310                                 1);
1311                         if(z_auto)
1312                         {
1313                                 float zoom = atof(z->get_text());
1314                                 if(zoom > 100.) zoom = 100.;
1315                                 else if(zoom < 0.01) zoom = 0.01;
1316 //                      if (zoom != atof(z->get_text()))
1317 //                              z->update(zoom);
1318                                 z_auto->set_value(zoom);
1319
1320                                 mwindow->gui->lock_window("CWindowProjectorGUI::handle_event");
1321                                 mwindow->gui->draw_overlays(1);
1322                                 mwindow->gui->unlock_window();
1323
1324                                 update();
1325                                 update_preview();
1326                         }
1327                 }
1328                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1329         }
1330 }
1331
1332 void CWindowProjectorGUI::update()
1333 {
1334         FloatAuto *x_auto = 0;
1335         FloatAuto *y_auto = 0;
1336         FloatAuto *z_auto = 0;
1337         Track *track = mwindow->cwindow->calculate_affected_track();
1338
1339         if(track)
1340         {
1341                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1342                         &y_auto,
1343                         &z_auto,
1344                         track,
1345                         0,
1346                         0,
1347                         0,
1348                         0);
1349         }
1350
1351         if(x_auto)
1352                 x->update(x_auto->get_value());
1353         if(y_auto)
1354                 y->update(y_auto->get_value());
1355         if(z_auto) {
1356                 float value = z_auto->get_value();
1357                 z->update(value);
1358                 thread->gui->composite_panel->cpanel_zoom->update(value);
1359         }
1360
1361         if( x_auto && y_auto && z_auto )
1362         {
1363                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
1364                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
1365         }
1366 }
1367
1368 CWindowProjectorLeft::CWindowProjectorLeft(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1369  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
1370 {
1371         this->gui = gui;
1372         this->mwindow = mwindow;
1373         set_tooltip(_("Left justify"));
1374 }
1375 int CWindowProjectorLeft::handle_event()
1376 {
1377         FloatAuto *x_auto = 0;
1378         FloatAuto *z_auto = 0;
1379         Track *track = mwindow->cwindow->calculate_affected_track();
1380         if(track)
1381         {
1382                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1383                         0,
1384                         &z_auto,
1385                         track,
1386                         0,
1387                         1,
1388                         0,
1389                         0);
1390         }
1391         if(x_auto && z_auto)
1392         {
1393                 mwindow->undo->update_undo_before(_("projector"), 0);
1394                 x_auto->set_value( (double)track->track_w * z_auto->get_value() / 2 -
1395                         (double)mwindow->edl->session->output_w / 2 );
1396                 gui->update();
1397                 gui->update_preview();
1398                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1399         }
1400
1401         return 1;
1402 }
1403
1404
1405 CWindowProjectorCenter::CWindowProjectorCenter(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1406  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
1407 {
1408         this->gui = gui;
1409         this->mwindow = mwindow;
1410         set_tooltip(_("Center horizontal"));
1411 }
1412 int CWindowProjectorCenter::handle_event()
1413 {
1414         FloatAuto *x_auto = 0;
1415         Track *track = mwindow->cwindow->calculate_affected_track();
1416         if(track)
1417                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1418                         track->automation->autos[AUTOMATION_PROJECTOR_X],
1419                         1);
1420
1421         if(x_auto)
1422         {
1423                 mwindow->undo->update_undo_before(_("projector"), 0);
1424                 x_auto->set_value(0);
1425                 gui->update();
1426                 gui->update_preview();
1427                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1428         }
1429
1430         return 1;
1431 }
1432
1433
1434 CWindowProjectorRight::CWindowProjectorRight(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1435  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1436 {
1437         this->gui = gui;
1438         this->mwindow = mwindow;
1439         set_tooltip(_("Right justify"));
1440 }
1441 int CWindowProjectorRight::handle_event()
1442 {
1443         FloatAuto *x_auto = 0;
1444         FloatAuto *z_auto = 0;
1445         Track *track = mwindow->cwindow->calculate_affected_track();
1446         if(track)
1447         {
1448                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1449                         0,
1450                         &z_auto,
1451                         track,
1452                         0,
1453                         1,
1454                         0,
1455                         0);
1456         }
1457
1458         if(x_auto && z_auto)
1459         {
1460                 mwindow->undo->update_undo_before(_("projector"), 0);
1461                 x_auto->set_value( -((double)track->track_w * z_auto->get_value() / 2 -
1462                         (double)mwindow->edl->session->output_w / 2));
1463                 gui->update();
1464                 gui->update_preview();
1465                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1466         }
1467
1468         return 1;
1469 }
1470
1471
1472 CWindowProjectorTop::CWindowProjectorTop(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1473  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1474 {
1475         this->gui = gui;
1476         this->mwindow = mwindow;
1477         set_tooltip(_("Top justify"));
1478 }
1479 int CWindowProjectorTop::handle_event()
1480 {
1481         FloatAuto *y_auto = 0;
1482         FloatAuto *z_auto = 0;
1483         Track *track = mwindow->cwindow->calculate_affected_track();
1484         if(track)
1485         {
1486                 mwindow->cwindow->calculate_affected_autos(0,
1487                         &y_auto,
1488                         &z_auto,
1489                         track,
1490                         0,
1491                         0,
1492                         1,
1493                         0);
1494         }
1495
1496         if(y_auto && z_auto)
1497         {
1498                 mwindow->undo->update_undo_before(_("projector"), 0);
1499                 y_auto->set_value( (double)track->track_h * z_auto->get_value() / 2 -
1500                         (double)mwindow->edl->session->output_h / 2 );
1501                 gui->update();
1502                 gui->update_preview();
1503                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1504         }
1505
1506         return 1;
1507 }
1508
1509
1510 CWindowProjectorMiddle::CWindowProjectorMiddle(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1511  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1512 {
1513         this->gui = gui;
1514         this->mwindow = mwindow;
1515         set_tooltip(_("Center vertical"));
1516 }
1517 int CWindowProjectorMiddle::handle_event()
1518 {
1519         FloatAuto *y_auto = 0;
1520         Track *track = mwindow->cwindow->calculate_affected_track();
1521         if(track)
1522                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1523                         track->automation->autos[AUTOMATION_PROJECTOR_Y], 1);
1524
1525         if(y_auto)
1526         {
1527                 mwindow->undo->update_undo_before(_("projector"), 0);
1528                 y_auto->set_value(0);
1529                 gui->update();
1530                 gui->update_preview();
1531                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1532         }
1533
1534         return 1;
1535 }
1536
1537
1538 CWindowProjectorBottom::CWindowProjectorBottom(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1539  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1540 {
1541         this->gui = gui;
1542         this->mwindow = mwindow;
1543         set_tooltip(_("Bottom justify"));
1544 }
1545 int CWindowProjectorBottom::handle_event()
1546 {
1547         FloatAuto *y_auto = 0;
1548         FloatAuto *z_auto = 0;
1549         Track *track = mwindow->cwindow->calculate_affected_track();
1550         if(track)
1551         {
1552                 mwindow->cwindow->calculate_affected_autos(0,
1553                         &y_auto,
1554                         &z_auto,
1555                         track,
1556                         0,
1557                         0,
1558                         1,
1559                         0);
1560         }
1561
1562         if(y_auto && z_auto)
1563         {
1564                 mwindow->undo->update_undo_before(_("projector"), 0);
1565                 y_auto->set_value( -((double)track->track_h * z_auto->get_value() / 2 -
1566                         (double)mwindow->edl->session->output_h / 2));
1567                 gui->update();
1568                 gui->update_preview();
1569                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1570         }
1571
1572         return 1;
1573 }
1574
1575
1576 CWindowMaskMode::CWindowMaskMode(MWindow *mwindow,
1577         CWindowToolGUI *gui, int x, int y, const char *text)
1578  : BC_PopupMenu(x, y, 220, text, 1)
1579 {
1580         this->mwindow = mwindow;
1581         this->gui = gui;
1582 }
1583
1584 void CWindowMaskMode::create_objects()
1585 {
1586         add_item(new BC_MenuItem(mode_to_text(MASK_MULTIPLY_ALPHA)));
1587         add_item(new BC_MenuItem(mode_to_text(MASK_SUBTRACT_ALPHA)));
1588 }
1589
1590 char* CWindowMaskMode::mode_to_text(int mode)
1591 {
1592         switch(mode)
1593         {
1594                 case MASK_MULTIPLY_ALPHA:
1595                         return _("Multiply alpha");
1596                         break;
1597
1598                 case MASK_SUBTRACT_ALPHA:
1599                         return _("Subtract alpha");
1600                         break;
1601         }
1602
1603         return _("Subtract alpha");
1604 }
1605
1606 int CWindowMaskMode::text_to_mode(char *text)
1607 {
1608         if(!strcasecmp(text, _("Multiply alpha")))
1609                 return MASK_MULTIPLY_ALPHA;
1610         else
1611         if(!strcasecmp(text, _("Subtract alpha")))
1612                 return MASK_SUBTRACT_ALPHA;
1613
1614         return MASK_SUBTRACT_ALPHA;
1615 }
1616
1617 int CWindowMaskMode::handle_event()
1618 {
1619         MaskAutos *autos;
1620         MaskAuto *keyframe;
1621         Track *track;
1622         MaskPoint *point;
1623         SubMask *mask;
1624 // Get existing keyframe
1625         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1626         if(track)
1627         {
1628                 mwindow->undo->update_undo_before(_("mask mode"), 0);
1629 #ifdef USE_KEYFRAME_SPANNING
1630 // Create temp keyframe
1631                 MaskAuto temp_keyframe(mwindow->edl, autos);
1632                 temp_keyframe.copy_data(keyframe);
1633 // Update parameter
1634                 temp_keyframe.mode = text_to_mode(get_text());
1635 // Commit change to span of keyframes
1636                 autos->update_parameter(&temp_keyframe);
1637 #else
1638                 ((MaskAuto*)autos->default_auto)->mode =
1639                         text_to_mode(get_text());
1640 #endif
1641                 mwindow->undo->update_undo_after(_("mask mode"), LOAD_AUTOMATION);
1642         }
1643
1644 //printf("CWindowMaskMode::handle_event 1\n");
1645         gui->update_preview();
1646         return 1;
1647 }
1648
1649
1650
1651
1652
1653
1654
1655
1656 CWindowMaskDelete::CWindowMaskDelete(MWindow *mwindow,
1657         CWindowToolGUI *gui,
1658         int x,
1659         int y)
1660  : BC_GenericButton(x, y, _("Delete"))
1661 {
1662         this->mwindow = mwindow;
1663         this->gui = gui;
1664 }
1665
1666 int CWindowMaskDelete::handle_event()
1667 {
1668         MaskAutos *autos;
1669         MaskAuto *keyframe;
1670         Track *track;
1671         MaskPoint *point;
1672         SubMask *mask;
1673         int total_points = 0;
1674
1675 // Get existing keyframe
1676         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1677
1678         if(track)
1679         {
1680                 mwindow->undo->update_undo_before(_("mask delete"), 0);
1681
1682 #ifdef USE_KEYFRAME_SPANNING
1683 // Create temp keyframe
1684                 MaskAuto temp_keyframe(mwindow->edl, autos);
1685                 temp_keyframe.copy_data(keyframe);
1686 // Update parameter
1687                 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
1688                 if( shift_down() )
1689                         submask->points.remove_all_objects();
1690
1691                 for(int i = mwindow->cwindow->gui->affected_point;
1692                         i < submask->points.total - 1;
1693                         i++)
1694                 {
1695                         *submask->points.values[i] = *submask->points.values[i + 1];
1696                 }
1697
1698                 if(submask->points.total)
1699                 {
1700                         submask->points.remove_object(
1701                                 submask->points.values[submask->points.total - 1]);
1702                 }
1703                 total_points = submask->points.total;
1704
1705 // Commit change to span of keyframes
1706                 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
1707 #else
1708                 for(MaskAuto *current = (MaskAuto*)autos->default_auto;
1709                         current; )
1710                 {
1711                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1712                         if( shift_down() )
1713                                 submask->points.remove_all_objects();
1714
1715                         for(int i = mwindow->cwindow->gui->affected_point;
1716                                 i < submask->points.total - 1;
1717                                 i++)
1718                         {
1719                                 *submask->points.values[i] = *submask->points.values[i + 1];
1720                         }
1721
1722                         if(submask->points.total)
1723                         {
1724                                 submask->points.remove_object(
1725                                         submask->points.values[submask->points.total - 1]);
1726                         }
1727                         total_points = submask->points.total;
1728
1729                         if(current == (MaskAuto*)autos->default_auto)
1730                                 current = (MaskAuto*)autos->first;
1731                         else
1732                                 current = (MaskAuto*)NEXT;
1733                 }
1734 #endif
1735                 if( mwindow->cwindow->gui->affected_point >= total_points )
1736                         mwindow->cwindow->gui->affected_point =
1737                                 total_points > 0 ? total_points-1 : 0;
1738
1739                 gui->update();
1740                 gui->update_preview();
1741                 mwindow->undo->update_undo_after(_("mask delete"), LOAD_AUTOMATION);
1742         }
1743
1744
1745         return 1;
1746 }
1747
1748 int CWindowMaskDelete::keypress_event()
1749 {
1750         if(get_keypress() == BACKSPACE ||
1751                 get_keypress() == DELETE)
1752                 return handle_event();
1753         return 0;
1754 }
1755
1756
1757 // CWindowMaskCycleNext::CWindowMaskCycleNext(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1758 //  : BC_GenericButton(x, y, _("Cycle next"))
1759 // {
1760 //      this->mwindow = mwindow;
1761 //      this->gui = gui;
1762 // }
1763 // int CWindowMaskCycleNext::handle_event()
1764 // {
1765 //      MaskAuto *keyframe;
1766 //      MaskAutos *autos;
1767 //      Track *track;
1768 //      MaskPoint *point;
1769 //      SubMask *mask;
1770 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1771 //
1772 //      MaskPoint *temp;
1773 //
1774 // // Should apply to all keyframes
1775 //      if(keyframe && mask->points.total)
1776 //      {
1777 //              temp = mask->points.values[0];
1778 //
1779 //              for(int i = 0; i < mask->points.total - 1; i++)
1780 //              {
1781 //                      mask->points.values[i] = mask->points.values[i + 1];
1782 //              }
1783 //              mask->points.values[mask->points.total - 1] = temp;
1784 //
1785 //              mwindow->cwindow->gui->affected_point--;
1786 //              if(mwindow->cwindow->gui->affected_point < 0)
1787 //                      mwindow->cwindow->gui->affected_point = mask->points.total - 1;
1788 //
1789 //              gui->update();
1790 //              gui->update_preview();
1791 //      }
1792 //
1793 //      return 1;
1794 // }
1795 //
1796 // CWindowMaskCyclePrev::CWindowMaskCyclePrev(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1797 //  : BC_GenericButton(x, y, _("Cycle prev"))
1798 // {
1799 //      this->mwindow = mwindow;
1800 //      this->gui = gui;
1801 // }
1802 // int CWindowMaskCyclePrev::handle_event()
1803 // {
1804 //      MaskAuto *keyframe;
1805 //      MaskAutos *autos;
1806 //      Track *track;
1807 //      MaskPoint *point;
1808 //      SubMask *mask;
1809 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1810 //
1811 // // Should apply to all keyframes
1812 //      MaskPoint *temp;
1813 //      if(keyframe && mask->points.total)
1814 //      {
1815 //              temp = mask->points.values[mask->points.total - 1];
1816 //
1817 //              for(int i = mask->points.total - 1; i > 0; i--)
1818 //              {
1819 //                      mask->points.values[i] = mask->points.values[i - 1];
1820 //              }
1821 //              mask->points.values[0] = temp;
1822 //
1823 //              mwindow->cwindow->gui->affected_point++;
1824 //              if(mwindow->cwindow->gui->affected_point >= mask->points.total)
1825 //                      mwindow->cwindow->gui->affected_point = 0;
1826 //
1827 //              gui->update();
1828 //              gui->update_preview();
1829 //      }
1830 //      return 1;
1831 // }
1832
1833
1834 CWindowMaskNumber::CWindowMaskNumber(MWindow *mwindow,
1835         CWindowToolGUI *gui,
1836         int x,
1837         int y)
1838  : BC_TumbleTextBox(gui,
1839                 (int64_t)mwindow->edl->session->cwindow_mask,
1840                 (int64_t)0,
1841                 (int64_t)SUBMASKS - 1,
1842                 x,
1843                 y,
1844                 100)
1845 {
1846         this->mwindow = mwindow;
1847         this->gui = gui;
1848 }
1849
1850 CWindowMaskNumber::~CWindowMaskNumber()
1851 {
1852 }
1853
1854 int CWindowMaskNumber::handle_event()
1855 {
1856         mwindow->edl->session->cwindow_mask = atol(get_text());
1857         gui->update();
1858         gui->update_preview();
1859         return 1;
1860 }
1861
1862
1863 CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow,
1864         CWindowToolGUI *gui, int x, int y)
1865  : BC_TumbleTextBox(gui,
1866                 (int64_t)mwindow->cwindow->gui->affected_point,
1867                 (int64_t)0, INT64_MAX, x, y, 100)
1868 {
1869         this->mwindow = mwindow;
1870         this->gui = gui;
1871 }
1872
1873 CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint()
1874 {
1875 }
1876
1877 int CWindowMaskAffectedPoint::handle_event()
1878 {
1879         int total_points = 0;
1880         int affected_point = atol(get_text());
1881         Track *track = mwindow->cwindow->calculate_affected_track();
1882         if(track) {
1883                 MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1884                 MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0);
1885                 if( keyframe ) {
1886                         SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1887                         total_points = mask->points.size();
1888                 }
1889         }
1890         int active_point = affected_point;
1891         if( affected_point >= total_points )
1892                 affected_point = total_points - 1;
1893         else if( affected_point < 0 )
1894                 affected_point = 0;
1895         if( active_point != affected_point )
1896                 update((int64_t)affected_point);
1897         mwindow->cwindow->gui->affected_point = affected_point;
1898         gui->update();
1899         gui->update_preview();
1900         return 1;
1901 }
1902
1903
1904
1905
1906
1907 CWindowMaskFeather::CWindowMaskFeather(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1908  : BC_TumbleTextBox(gui,
1909                 (int64_t)0,
1910                 (int64_t)0,
1911                 (int64_t)0xff,
1912                 x,
1913                 y,
1914                 100)
1915 {
1916         this->mwindow = mwindow;
1917         this->gui = gui;
1918 }
1919 CWindowMaskFeather::~CWindowMaskFeather()
1920 {
1921 }
1922 int CWindowMaskFeather::handle_event()
1923 {
1924         MaskAutos *autos;
1925         MaskAuto *keyframe;
1926         Track *track;
1927         MaskPoint *point;
1928         SubMask *mask;
1929 #ifdef USE_KEYFRAME_SPANNING
1930         int create_it = 0;
1931 #else
1932         int create_it = 1;
1933 #endif
1934
1935         mwindow->undo->update_undo_before(_("mask feather"), this);
1936
1937 // Get existing keyframe
1938         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1939                         mask, point, create_it);
1940
1941         if(track)
1942         {
1943 #ifdef USE_KEYFRAME_SPANNING
1944 // Create temp keyframe
1945                 MaskAuto temp_keyframe(mwindow->edl, autos);
1946                 temp_keyframe.copy_data(keyframe);
1947 // Update parameter
1948                 temp_keyframe.feather = atof(get_text());
1949 // Commit change to span of keyframes
1950                 autos->update_parameter(&temp_keyframe);
1951 #else
1952                 keyframe->feather = atof(get_text());
1953 #endif
1954
1955                 gui->update_preview();
1956         }
1957
1958         mwindow->undo->update_undo_after(_("mask feather"), LOAD_AUTOMATION);
1959         return 1;
1960 }
1961
1962
1963 CWindowMaskValue::CWindowMaskValue(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1964  : BC_ISlider(x,
1965                         y,
1966                         0,
1967                         200,
1968                         200,
1969                         0,
1970                         100,
1971                         0)
1972 {
1973         this->mwindow = mwindow;
1974         this->gui = gui;
1975 }
1976
1977 CWindowMaskValue::~CWindowMaskValue()
1978 {
1979 }
1980
1981 int CWindowMaskValue::handle_event()
1982 {
1983         MaskAutos *autos;
1984         MaskAuto *keyframe;
1985         Track *track;
1986         MaskPoint *point;
1987         SubMask *mask;
1988 #ifdef USE_KEYFRAME_SPANNING
1989         int create_it = 0;
1990 #else
1991         int create_it = 1;
1992 #endif
1993
1994         mwindow->undo->update_undo_before(_("mask value"), this);
1995         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1996                 mask, point, create_it);
1997
1998         if(track)
1999         {
2000 #ifdef USE_KEYFRAME_SPANNING
2001 // Create temp keyframe
2002                 MaskAuto temp_keyframe(mwindow->edl, autos);
2003                 temp_keyframe.copy_data(keyframe);
2004 // Update parameter
2005                 temp_keyframe.value = get_value();
2006 // Commit change to span of keyframes
2007                 autos->update_parameter(&temp_keyframe);
2008 #else
2009                 keyframe->value = get_value();
2010 #endif
2011         }
2012
2013         gui->update_preview();
2014         mwindow->undo->update_undo_after(_("mask value"), LOAD_AUTOMATION);
2015         return 1;
2016 }
2017
2018
2019 CWindowMaskBeforePlugins::CWindowMaskBeforePlugins(CWindowToolGUI *gui, int x, int y)
2020  : BC_CheckBox(x,
2021         y,
2022         1,
2023         _("Apply mask before plugins"))
2024 {
2025         this->gui = gui;
2026 }
2027
2028 int CWindowMaskBeforePlugins::handle_event()
2029 {
2030         Track *track;
2031         MaskAutos *autos;
2032         MaskAuto *keyframe;
2033         SubMask *mask;
2034         MaskPoint *point;
2035         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
2036
2037         if (keyframe) {
2038                 keyframe->apply_before_plugins = get_value();
2039                 gui->update_preview();
2040         }
2041         return 1;
2042 }
2043
2044
2045 CWindowDisableOpenGLMasking::CWindowDisableOpenGLMasking(CWindowToolGUI *gui, int x, int y)
2046  : BC_CheckBox(x, y, 1, _("Disable OpenGL masking"))
2047 {
2048         this->gui = gui;
2049 }
2050
2051 int CWindowDisableOpenGLMasking::handle_event()
2052 {
2053         Track *track;
2054         MaskAutos *autos;
2055         MaskAuto *keyframe;
2056         SubMask *mask;
2057         MaskPoint *point;
2058         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
2059
2060         if (keyframe) {
2061                 keyframe->disable_opengl_masking = get_value();
2062                 gui->update_preview();
2063         }
2064         return 1;
2065 }
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075 CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread)
2076  : CWindowToolGUI(mwindow, thread,
2077         _(PROGRAM_NAME ": Mask"), 330, 320)
2078 {
2079         this->mwindow = mwindow;
2080         this->thread = thread;
2081         number = 0;
2082         active_point = 0;
2083         feather = 0;
2084 }
2085 CWindowMaskGUI::~CWindowMaskGUI()
2086 {
2087         lock_window("CWindowMaskGUI::~CWindowMaskGUI");
2088         delete number;
2089         delete active_point;
2090         delete feather;
2091         unlock_window();
2092 }
2093
2094 void CWindowMaskGUI::create_objects()
2095 {
2096         int x = 10, y = 10, margin = mwindow->theme->widget_border;
2097         //MaskAuto *keyframe = 0;
2098         //Track *track = mwindow->cwindow->calculate_affected_track();
2099         //if(track)
2100         //      keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(track->automation->autos[AUTOMATION_MASK], 0);
2101
2102         lock_window("CWindowMaskGUI::create_objects");
2103         BC_Title *title;
2104         add_subwindow(title = new BC_Title(x, y, _("Mode:")));
2105         add_subwindow(mode = new CWindowMaskMode(mwindow,
2106                 this, x + title->get_w() + margin, y, ""));
2107         mode->create_objects();
2108         y += mode->get_h() + margin;
2109         add_subwindow(title = new BC_Title(x, y, _("Value:")));
2110         add_subwindow(value = new CWindowMaskValue(mwindow, this, x + title->get_w() + margin, y));
2111         y += value->get_h() + margin;
2112         add_subwindow(delete_point = new CWindowMaskDelete(mwindow, this, x, y));
2113         int x1 = x + delete_point->get_w() + 2*margin;
2114         add_subwindow(title = new BC_Title(x1, y, _("Point:")));
2115         x1 += title->get_w() + margin;
2116         active_point = new CWindowMaskAffectedPoint(mwindow, this, x1, y);
2117         active_point->create_objects();
2118         y += delete_point->get_h() + margin;
2119         add_subwindow(title = new BC_Title(x, y, _("Mask number:")));
2120         number = new CWindowMaskNumber(mwindow,
2121                 this, x + title->get_w() + margin, y);
2122         number->create_objects();
2123         y += number->get_h() + margin;
2124         add_subwindow(title = new BC_Title(x, y, _("Feather:")));
2125         feather = new CWindowMaskFeather(mwindow,
2126                 this, x + title->get_w() + margin, y);
2127         feather->create_objects();
2128         y += feather->get_h() + margin;
2129         add_subwindow(title = new BC_Title(x, y, "X:"));
2130         x += title->get_w() + margin;
2131         this->x = new CWindowCoord(this, x, y, (float)0.0);
2132         this->x->create_objects();
2133         x += this->x->get_w() + margin;
2134         add_subwindow(title = new BC_Title(x, y, "Y:"));
2135         x += title->get_w() + margin;
2136         this->y = new CWindowCoord(this, x, y, (float)0.0);
2137         this->y->create_objects();
2138
2139         x = 10;
2140         y += this->y->get_h() + margin;
2141         add_subwindow(title = new BC_Title(x, y, _("Press Shift to move an end point")));
2142         y += title->get_h() + margin;
2143         add_subwindow(title = new BC_Title(x, y, _("Press Ctrl to move a control point")));
2144         y += title->get_h() + margin;
2145         add_subwindow(title = new BC_Title(x, y, _("Shift+click Delete to delete the mask")));
2146         y += title->get_h() + margin;
2147         add_subwindow(title = new BC_Title(x, y, _("Press Alt to translate the mask")));
2148         y += 30;
2149
2150         add_subwindow(this->apply_before_plugins = new CWindowMaskBeforePlugins(this, 10, y));
2151         y += this->apply_before_plugins->get_h() + margin;
2152         add_subwindow(this->disable_opengl_masking = new CWindowDisableOpenGLMasking(this, 10, y));
2153
2154         update();
2155         unlock_window();
2156 }
2157
2158 void CWindowMaskGUI::get_keyframe(Track* &track,
2159         MaskAutos* &autos,
2160         MaskAuto* &keyframe,
2161         SubMask* &mask,
2162         MaskPoint* &point,
2163         int create_it)
2164 {
2165         autos = 0;
2166         keyframe = 0;
2167
2168         track = mwindow->cwindow->calculate_affected_track();
2169         if(track)
2170         {
2171                 autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
2172                 keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(
2173                         autos,
2174                         create_it);
2175         }
2176
2177         if(keyframe)
2178                 mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
2179         else
2180                 mask = 0;
2181
2182         point = 0;
2183         if(keyframe)
2184         {
2185                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2186                         mwindow->cwindow->gui->affected_point >= 0)
2187                 {
2188                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2189                 }
2190         }
2191 }
2192
2193 void CWindowMaskGUI::update()
2194 {
2195         Track *track;
2196         MaskAutos *autos;
2197         MaskAuto *keyframe;
2198         SubMask *mask;
2199         MaskPoint *point;
2200 //printf("CWindowMaskGUI::update 1\n");
2201         get_keyframe(track, autos, keyframe, mask, point, 0);
2202
2203         double position = mwindow->edl->local_session->get_selectionstart(1);
2204         position = mwindow->edl->align_to_frame(position, 0);
2205         if(track)
2206         {
2207                 int64_t position_i = track->to_units(position, 0);
2208
2209                 if(point)
2210                 {
2211                         x->update(point->x);
2212                         y->update(point->y);
2213                 }
2214
2215                 if(mask)
2216                 {
2217                         feather->update((int64_t)autos->get_feather(position_i, PLAY_FORWARD));
2218                         value->update((int64_t)autos->get_value(position_i, PLAY_FORWARD));
2219                         apply_before_plugins->update((int64_t)keyframe->apply_before_plugins);
2220                         disable_opengl_masking->update((int64_t)keyframe->disable_opengl_masking);
2221                 }
2222         }
2223
2224 //printf("CWindowMaskGUI::update 1\n");
2225         active_point->update((int64_t)mwindow->cwindow->gui->affected_point);
2226         number->update((int64_t)mwindow->edl->session->cwindow_mask);
2227
2228 //printf("CWindowMaskGUI::update 1\n");
2229         if(track)
2230         {
2231 #ifdef USE_KEYFRAME_SPANNING
2232                 mode->set_text(
2233                         CWindowMaskMode::mode_to_text(keyframe->mode));
2234 #else
2235                 mode->set_text(
2236                         CWindowMaskMode::mode_to_text(((MaskAuto*)autos->default_auto)->mode));
2237 #endif
2238         }
2239 //printf("CWindowMaskGUI::update 2\n");
2240 }
2241
2242 void CWindowMaskGUI::handle_event()
2243 {
2244         Track *track;
2245         MaskAuto *keyframe;
2246         MaskAutos *autos;
2247         SubMask *mask;
2248         MaskPoint *point;
2249         get_keyframe(track, autos, keyframe, mask, point, 0);
2250
2251         mwindow->undo->update_undo_before(_("mask point"), this);
2252
2253         if(point)
2254         {
2255 #ifdef USE_KEYFRAME_SPANNING
2256 // Create temp keyframe
2257                 MaskAuto temp_keyframe(mwindow->edl, autos);
2258                 temp_keyframe.copy_data(keyframe);
2259 // Get affected point in temp keyframe
2260                 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2261                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2262                         mwindow->cwindow->gui->affected_point >= 0)
2263                 {
2264                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2265                 }
2266
2267                 if(point)
2268                 {
2269                         point->x = atof(x->get_text());
2270                         point->y = atof(y->get_text());
2271 // Commit to spanned keyframes
2272                         autos->update_parameter(&temp_keyframe);
2273                 }
2274 #else
2275                 point->x = atof(x->get_text());
2276                 point->y = atof(y->get_text());
2277 #endif
2278         }
2279
2280         update_preview();
2281         mwindow->undo->update_undo_after(_("mask point"), LOAD_AUTOMATION);
2282 }
2283
2284 void CWindowMaskGUI::update_preview()
2285 {
2286         mwindow->gui->lock_window("CWindowMaskGUI::update_preview");
2287         mwindow->restart_brender();
2288         mwindow->sync_parameters(CHANGE_PARAMS);
2289         mwindow->gui->draw_overlays(1);
2290         mwindow->gui->unlock_window();
2291         mwindow->cwindow->refresh_frame(CHANGE_NONE);
2292         mwindow->cwindow->gui->lock_window("CWindowMaskGUI::update_preview");
2293         mwindow->cwindow->gui->canvas->draw_refresh();
2294         mwindow->cwindow->gui->unlock_window();
2295 }
2296
2297
2298 CWindowRulerGUI::CWindowRulerGUI(MWindow *mwindow, CWindowTool *thread)
2299  : CWindowToolGUI(mwindow,
2300         thread,
2301         _(PROGRAM_NAME ": Ruler"),
2302         320,
2303         240)
2304 {
2305 }
2306
2307 CWindowRulerGUI::~CWindowRulerGUI()
2308 {
2309 }
2310
2311 void CWindowRulerGUI::create_objects()
2312 {
2313         int x = 10, y = 10, x1 = 100;
2314         BC_Title *title;
2315
2316         lock_window("CWindowRulerGUI::create_objects");
2317         add_subwindow(title = new BC_Title(x, y, _("Current:")));
2318         add_subwindow(current = new BC_TextBox(x1, y, 200, 1, ""));
2319         y += title->get_h() + 5;
2320         add_subwindow(title = new BC_Title(x, y, _("Point 1:")));
2321         add_subwindow(point1 = new BC_TextBox(x1, y, 200, 1, ""));
2322         y += title->get_h() + 5;
2323         add_subwindow(title = new BC_Title(x, y, _("Point 2:")));
2324         add_subwindow(point2 = new BC_TextBox(x1, y, 200, 1, ""));
2325         y += title->get_h() + 5;
2326         add_subwindow(title = new BC_Title(x, y, _("Deltas:")));
2327         add_subwindow(deltas = new BC_TextBox(x1, y, 200, 1, ""));
2328         y += title->get_h() + 5;
2329         add_subwindow(title = new BC_Title(x, y, _("Distance:")));
2330         add_subwindow(distance = new BC_TextBox(x1, y, 200, 1, ""));
2331         y += title->get_h() + 5;
2332         add_subwindow(title = new BC_Title(x, y, _("Angle:")));
2333         add_subwindow(angle = new BC_TextBox(x1, y, 200, 1, ""));
2334         y += title->get_h() + 10;
2335         char string[BCTEXTLEN];
2336         sprintf(string,
2337                  _("Press Ctrl to lock ruler to the\nnearest 45%c%c angle."),
2338                 0xc2, 0xb0); // degrees utf
2339         add_subwindow(title = new BC_Title(x,
2340                 y,
2341                 string));
2342         y += title->get_h() + 10;
2343         sprintf(string, _("Press Alt to translate the ruler."));
2344         add_subwindow(title = new BC_Title(x,
2345                 y,
2346                 string));
2347         update();
2348         unlock_window();
2349 }
2350
2351 void CWindowRulerGUI::update()
2352 {
2353         char string[BCTEXTLEN];
2354         int cx = mwindow->session->cwindow_output_x;
2355         int cy = mwindow->session->cwindow_output_y;
2356         sprintf(string, "%d, %d", cx, cy);
2357         current->update(string);
2358         double x1 = mwindow->edl->session->ruler_x1;
2359         double y1 = mwindow->edl->session->ruler_y1;
2360         sprintf(string, "%.0f, %.0f", x1, y1);
2361         point1->update(string);
2362         double x2 = mwindow->edl->session->ruler_x2;
2363         double y2 = mwindow->edl->session->ruler_y2;
2364         sprintf(string, "%.0f, %.0f", x2, y2);
2365         point2->update(string);
2366         double dx = x2 - x1, dy = y2 - y1;
2367         sprintf(string, "%s%.0f, %s%.0f", (dx>=0? "+":""), dx, (dy>=0? "+":""), dy);
2368         deltas->update(string);
2369         double d = sqrt(dx*dx + dy*dy);
2370         sprintf(string, _("%0.01f pixels"), d);
2371         distance->update(string);
2372         double a = d > 0 ? (atan2(-dy, dx) * 180/M_PI) : 0.;
2373         sprintf(string, "%0.02f %c%c", a, 0xc2, 0xb0);
2374         angle->update(string);
2375 }
2376
2377 void CWindowRulerGUI::handle_event()
2378 {
2379 }
2380
2381
2382
2383