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