6da2d0da5b1be51be9109b47a9782b8e1ebfd0ef
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / editpanel.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * Copyright (C) 2003-2016 Cinelerra CV contributors
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include "awindow.h"
24 #include "awindowgui.h"
25 #include "bcsignals.h"
26 #include "clipedit.h"
27 #include "cplayback.h"
28 #include "cwindow.h"
29 #include "cwindowgui.h"
30 #include "editpanel.h"
31 #include "edl.h"
32 #include "edlsession.h"
33 #include "filexml.h"
34 #include "keys.h"
35 #include "language.h"
36 #include "localsession.h"
37 #include "mainclock.h"
38 #include "mainsession.h"
39 #include "mainundo.h"
40 #include "manualgoto.h"
41 #include "mbuttons.h"
42 #include "meterpanel.h"
43 #include "mwindow.h"
44 #include "mwindowgui.h"
45 #include "playbackengine.h"
46 #include "preferences.h"
47 #include "scopewindow.h"
48 #include "theme.h"
49 #include "timebar.h"
50 #include "trackcanvas.h"
51 #include "transportque.h"
52 #include "vwindowgui.h"
53 #include "zoombar.h"
54
55
56
57 EditPanel::EditPanel(MWindow *mwindow,
58         BC_WindowBase *subwindow,
59         int window_id,
60         int x,
61         int y,
62         int editing_mode,
63         int use_editing_mode,
64         int use_keyframe,
65         int use_splice,   // Extra buttons
66         int use_overwrite,
67         int use_copy,
68         int use_paste,
69         int use_undo,
70         int use_fit,
71         int use_locklabels,
72         int use_labels,
73         int use_toclip,
74         int use_meters,
75         int use_cut,
76         int use_commercial,
77         int use_goto,
78         int use_clk2play,
79         int use_scope,
80         int use_gang_tracks,
81         int use_timecode)
82 {
83         this->window_id = window_id;
84         this->editing_mode = editing_mode;
85         this->use_editing_mode = use_editing_mode;
86         this->use_keyframe = use_keyframe;
87         this->use_splice = use_splice;
88         this->use_overwrite = use_overwrite;
89         this->use_copy = use_copy;
90         this->use_paste = use_paste;
91         this->use_undo = use_undo;
92         this->mwindow = mwindow;
93         this->subwindow = subwindow;
94         this->use_fit = use_fit;
95         this->use_labels = use_labels;
96         this->use_locklabels = use_locklabels;
97         this->use_toclip = use_toclip;
98         this->use_meters = use_meters;
99         this->use_cut = use_cut;
100         this->use_commercial = use_commercial;
101         this->use_goto = use_goto;
102         this->use_clk2play = use_clk2play;
103         this->use_scope = use_scope;
104         this->use_gang_tracks = use_gang_tracks;
105         this->use_timecode = use_timecode;
106
107         this->x = x;
108         this->y = y;
109         this->fit = 0;
110         this->fit_autos = 0;
111         this->inpoint = 0;
112         this->outpoint = 0;
113         this->splice = 0;
114         this->overwrite = 0;
115         this->clip = 0;
116         this->cut = 0;
117         this->commercial = 0;
118         this->copy = 0;
119         this->paste = 0;
120         this->labelbutton = 0;
121         this->prevlabel = 0;
122         this->nextlabel = 0;
123         this->prevedit = 0;
124         this->nextedit = 0;
125         this->gang_tracks = 0;
126         this->undo = 0;
127         this->redo = 0;
128         this->meter_panel = 0;
129         this->meters = 0;
130         this->arrow = 0;
131         this->ibeam = 0;
132         this->keyframe = 0;
133         this->span_keyframe = 0;
134         this->mangoto = 0;
135         this->click2play = 0;
136         this->scope = 0;
137         this->scope_dialog = 0;
138         locklabels = 0;
139 }
140
141 EditPanel::~EditPanel()
142 {
143         delete scope_dialog;
144 }
145
146 void EditPanel::set_meters(MeterPanel *meter_panel)
147 {
148         this->meter_panel = meter_panel;
149 }
150
151
152 void EditPanel::update()
153 {
154         int new_editing_mode = mwindow->edl->session->editing_mode;
155         if( arrow ) arrow->update(new_editing_mode == EDITING_ARROW);
156         if( ibeam ) ibeam->update(new_editing_mode == EDITING_IBEAM);
157         if( keyframe ) keyframe->update(mwindow->edl->session->auto_keyframes);
158         if( span_keyframe ) span_keyframe->update(mwindow->edl->session->span_keyframes);
159         if( locklabels ) locklabels->set_value(mwindow->edl->session->labels_follow_edits);
160         if( click2play ) {
161                 int value = !is_vwindow() ?
162                         mwindow->edl->session->cwindow_click2play :
163                         mwindow->edl->session->vwindow_click2play ;
164                 click2play->set_value(value);
165         }
166         if( gang_tracks ) gang_tracks->update(mwindow->edl->local_session->gang_tracks);
167         if( meters ) {
168                 if( is_cwindow() ) {
169                         meters->update(mwindow->edl->session->cwindow_meter);
170                         mwindow->cwindow->gui->update_meters();
171                 }
172                 else {
173                         meters->update(mwindow->edl->session->vwindow_meter);
174                 }
175         }
176         subwindow->flush();
177 }
178
179 int EditPanel::calculate_w(MWindow *mwindow, int use_keyframe, int total_buttons)
180 {
181         int button_w = xS(24); // mwindow->theme->get_image_set("meters")[0]->get_w();
182         int result = button_w * total_buttons;
183         if( use_keyframe )
184                 result += 2*(button_w + mwindow->theme->toggle_margin);
185         return result;
186 }
187
188 int EditPanel::calculate_h(MWindow *mwindow)
189 {
190         return mwindow->theme->get_image_set("meters")[0]->get_h();
191 }
192
193 void EditPanel::create_buttons()
194 {
195         x1 = x, y1 = y;
196
197         if( use_editing_mode ) {
198                 arrow = new ArrowButton(mwindow, this, x1, y1);
199                 subwindow->add_subwindow(arrow);
200                 x1 += arrow->get_w();
201                 ibeam = new IBeamButton(mwindow, this, x1, y1);
202                 subwindow->add_subwindow(ibeam);
203                 x1 += ibeam->get_w();
204                 x1 += mwindow->theme->toggle_margin;
205         }
206
207         if( use_keyframe ) {
208                 keyframe = new KeyFrameButton(mwindow, this, x1, y1);
209                 subwindow->add_subwindow(keyframe);
210                 x1 += keyframe->get_w();
211                 span_keyframe = new SpanKeyFrameButton(mwindow, this, x1, y1);
212                 subwindow->add_subwindow(span_keyframe);
213                 x1 += span_keyframe->get_w();
214         }
215
216         if( use_locklabels ) {
217                 locklabels = new LockLabelsButton(mwindow, this, x1, y1);
218                 subwindow->add_subwindow(locklabels);
219                 x1 += locklabels->get_w();
220         }
221
222         if( use_keyframe || use_locklabels )
223                 x1 += mwindow->theme->toggle_margin;
224
225 // Mandatory
226         inpoint = new EditInPoint(mwindow, this, x1, y1);
227         subwindow->add_subwindow(inpoint);
228         x1 += inpoint->get_w();
229         outpoint = new EditOutPoint(mwindow, this, x1, y1);
230         subwindow->add_subwindow(outpoint);
231         x1 += outpoint->get_w();
232
233         if( use_splice ) {
234                 splice = new EditSplice(mwindow, this, x1, y1);
235                 subwindow->add_subwindow(splice);
236                 x1 += splice->get_w();
237         }
238
239         if( use_overwrite ) {
240                 overwrite = new EditOverwrite(mwindow, this, x1, y1);
241                 subwindow->add_subwindow(overwrite);
242                 x1 += overwrite->get_w();
243         }
244
245         if( use_toclip ) {
246                 clip = new EditToClip(mwindow, this, x1, y1);
247                 subwindow->add_subwindow(clip);
248                 x1 += clip->get_w();
249         }
250
251         if( use_cut ) {
252                 cut = new EditCut(mwindow, this, x1, y1);
253                 subwindow->add_subwindow(cut);
254                 x1 += cut->get_w();
255         }
256
257         if( use_copy ) {
258                 copy = new EditCopy(mwindow, this, x1, y1);
259                 subwindow->add_subwindow(copy);
260                 x1 += copy->get_w();
261         }
262
263         if( use_paste ) {
264                 paste = new EditPaste(mwindow, this, x1, y1);
265                 subwindow->add_subwindow(paste);
266                 x1 += paste->get_w();
267         }
268
269         if( use_labels ) {
270                 labelbutton = new EditLabelbutton(mwindow, this, x1, y1);
271                 subwindow->add_subwindow(labelbutton);
272                 x1 += labelbutton->get_w();
273                 prevlabel = new EditPrevLabel(mwindow, this, x1, y1);
274                 subwindow->add_subwindow(prevlabel);
275                 x1 += prevlabel->get_w();
276                 nextlabel = new EditNextLabel(mwindow, this, x1, y1);
277                 subwindow->add_subwindow(nextlabel);
278                 x1 += nextlabel->get_w();
279         }
280
281 // all windows except VWindow since it's only implemented in MWindow.
282         if( use_cut ) {
283                 prevedit = new EditPrevEdit(mwindow, this, x1, y1);
284                 subwindow->add_subwindow(prevedit);
285                 x1 += prevedit->get_w();
286                 nextedit = new EditNextEdit(mwindow, this, x1, y1);
287                 subwindow->add_subwindow(nextedit);
288                 x1 += nextedit->get_w();
289         }
290
291         if( use_fit ) {
292                 fit = new EditFit(mwindow, this, x1, y1);
293                 subwindow->add_subwindow(fit);
294                 x1 += fit->get_w();
295                 fit_autos = new EditFitAutos(mwindow, this, x1, y1);
296                 subwindow->add_subwindow(fit_autos);
297                 x1 += fit_autos->get_w();
298         }
299
300         if( use_undo ) {
301                 undo = new EditUndo(mwindow, this, x1, y1);
302                 subwindow->add_subwindow(undo);
303                 x1 += undo->get_w();
304                 redo = new EditRedo(mwindow, this, x1, y1);
305                 subwindow->add_subwindow(redo);
306                 x1 += redo->get_w();
307         }
308
309         if( use_goto ) {
310                 mangoto = new EditManualGoto(mwindow, this, x1, y1);
311                 subwindow->add_subwindow(mangoto);
312                 x1 += mangoto->get_w();
313         }
314
315         if( use_clk2play ) {
316                 click2play = new EditClick2Play(mwindow, this, x1, y1+yS(3));
317                 subwindow->add_subwindow(click2play);
318                 x1 += click2play->get_w();
319         }
320
321         if( use_scope ) {
322                 scope = new EditPanelScope(mwindow, this, x1, y1-yS(1));
323                 subwindow->add_subwindow(scope);
324                 x1 += scope->get_w();
325                 scope_dialog = new EditPanelScopeDialog(mwindow, this);
326         }
327
328         if( use_timecode ) {
329                 timecode = new EditPanelTimecode(mwindow, this, x1, y1);
330                 subwindow->add_subwindow(timecode);
331                 x1 += timecode->get_w();
332         }
333
334         if( use_gang_tracks ) {
335                 gang_tracks = new EditPanelGangTracks(mwindow, this, x1, y1-yS(1));
336                 subwindow->add_subwindow(gang_tracks);
337                 x1 += gang_tracks->get_w();
338         }
339
340         if( use_meters ) {
341                 if( meter_panel ) {
342                         meters = new MeterShow(mwindow, meter_panel, x1, y1);
343                         subwindow->add_subwindow(meters);
344                         x1 += meters->get_w();
345                 }
346                 else
347                         printf("EditPanel::create_objects: meter_panel == 0\n");
348         }
349
350         if( use_commercial ) {
351                 commercial = new EditCommercial(mwindow, this, x1, y1);
352                 subwindow->add_subwindow(commercial);
353                 x1 += commercial->get_w();
354         }
355 }
356
357 void EditPanel::reposition_buttons(int x, int y)
358 {
359         this->x = x;
360         this->y = y;
361         x1 = x, y1 = y;
362
363         if( use_editing_mode ) {
364                 arrow->reposition_window(x1, y1);
365                 x1 += arrow->get_w();
366                 ibeam->reposition_window(x1, y1);
367                 x1 += ibeam->get_w();
368                 x1 += mwindow->theme->toggle_margin;
369         }
370
371         if( use_keyframe ) {
372                 keyframe->reposition_window(x1, y1);
373                 x1 += keyframe->get_w();
374                 span_keyframe->reposition_window(x1, y1);
375                 x1 += span_keyframe->get_w();
376         }
377
378         if( use_locklabels ) {
379                 locklabels->reposition_window(x1,y1);
380                 x1 += locklabels->get_w();
381         }
382
383         if( use_keyframe || use_locklabels )
384                 x1 += mwindow->theme->toggle_margin;
385
386         inpoint->reposition_window(x1, y1);
387         x1 += inpoint->get_w();
388         outpoint->reposition_window(x1, y1);
389         x1 += outpoint->get_w();
390         if( use_splice ) {
391                 splice->reposition_window(x1, y1);
392                 x1 += splice->get_w();
393         }
394         if( use_overwrite ) {
395                 overwrite->reposition_window(x1, y1);
396                 x1 += overwrite->get_w();
397         }
398         if( use_toclip ) {
399                 clip->reposition_window(x1, y1);
400                 x1 += clip->get_w();
401         }
402         if( use_cut ) {
403                 cut->reposition_window(x1, y1);
404                 x1 += cut->get_w();
405         }
406         if( use_copy ) {
407                 copy->reposition_window(x1, y1);
408                 x1 += copy->get_w();
409         }
410         if( use_paste ) {
411                 paste->reposition_window(x1, y1);
412                 x1 += paste->get_w();
413         }
414
415         if( use_labels ) {
416                 labelbutton->reposition_window(x1, y1);
417                 x1 += labelbutton->get_w();
418                 prevlabel->reposition_window(x1, y1);
419                 x1 += prevlabel->get_w();
420                 nextlabel->reposition_window(x1, y1);
421                 x1 += nextlabel->get_w();
422         }
423
424         if( prevedit ) {
425                 prevedit->reposition_window(x1, y1);
426                 x1 += prevedit->get_w();
427         }
428
429         if( nextedit ) {
430                 nextedit->reposition_window(x1, y1);
431                 x1 += nextedit->get_w();
432         }
433
434         if( use_fit ) {
435                 fit->reposition_window(x1, y1);
436                 x1 += fit->get_w();
437                 fit_autos->reposition_window(x1, y1);
438                 x1 += fit_autos->get_w();
439         }
440
441         if( use_undo ) {
442                 undo->reposition_window(x1, y1);
443                 x1 += undo->get_w();
444                 redo->reposition_window(x1, y1);
445                 x1 += redo->get_w();
446         }
447
448         if( use_goto ) {
449                 mangoto->reposition_window(x1, y1);
450                 x1 += mangoto->get_w();
451         }
452         if( use_clk2play ) {
453                 click2play->reposition_window(x1, y1+yS(3));
454                 x1 += click2play->get_w();
455         }
456         if( use_scope ) {
457                 scope->reposition_window(x1, y1-yS(1));
458                 x1 += scope->get_w();
459         }
460         if( use_timecode ) {
461                 timecode->reposition_window(x1, y1);
462                 x1 += timecode->get_w();
463         }
464
465         if( use_meters ) {
466                 meters->reposition_window(x1, y1);
467                 x1 += meters->get_w();
468         }
469 }
470
471 void EditPanel::create_objects()
472 {
473         create_buttons();
474 }
475
476 int EditPanel::get_w()
477 {
478         return x1 - x;
479 }
480
481 // toggle_label
482 EditLabelbutton::EditLabelbutton(MWindow *mwindow, EditPanel *panel, int x, int y)
483  : BC_Button(x, y, mwindow->theme->get_image_set("labelbutton"))
484 {
485         this->mwindow = mwindow;
486         this->panel = panel;
487         set_tooltip(_("Toggle label at current position ( l )"));
488 // *** CONTEXT_HELP ***
489         context_help_set_keyword("Labels");
490 }
491
492 EditLabelbutton::~EditLabelbutton()
493 {
494 }
495 int EditLabelbutton::keypress_event()
496 {
497         if( get_keypress() == 'l' && !alt_down() )
498                 return handle_event();
499         return context_help_check_and_show();
500 }
501 int EditLabelbutton::handle_event()
502 {
503         panel->panel_toggle_label();
504         return 1;
505 }
506
507 //next_label
508 EditNextLabel::EditNextLabel(MWindow *mwindow,
509         EditPanel *panel, int x, int y)
510  : BC_Button(x, y, mwindow->theme->get_image_set("nextlabel"))
511 {
512         this->mwindow = mwindow;
513         this->panel = panel;
514         set_tooltip(_("Next label ( ctrl -> )"));
515 // *** CONTEXT_HELP ***
516         context_help_set_keyword("Labels");
517 }
518 EditNextLabel::~EditNextLabel()
519 {
520 }
521 int EditNextLabel::keypress_event()
522 {
523         if( ctrl_down() ) {
524                 int key = get_keypress();
525                 if( (key == RIGHT || key == '.') && !alt_down() ) {
526                         panel->panel_next_label(0);
527                         return 1;
528                 }
529                 if( key == '>' && alt_down() ) {
530                         panel->panel_next_label(1);
531                         return 1;
532                 }
533         }
534         return context_help_check_and_show();
535 }
536 int EditNextLabel::handle_event()
537 {
538         int cut = ctrl_down() && alt_down();
539         panel->panel_next_label(cut);
540         return 1;
541 }
542
543 //prev_label
544 EditPrevLabel::EditPrevLabel(MWindow *mwindow,
545         EditPanel *panel, int x, int y)
546  : BC_Button(x, y, mwindow->theme->get_image_set("prevlabel"))
547 {
548         this->mwindow = mwindow;
549         this->panel = panel;
550         set_tooltip(_("Previous label ( ctrl <- )"));
551 // *** CONTEXT_HELP ***
552         context_help_set_keyword("Labels");
553 }
554 EditPrevLabel::~EditPrevLabel()
555 {
556 }
557 int EditPrevLabel::keypress_event()
558 {
559         if( ctrl_down() ) {
560                 int key = get_keypress();
561                 if( (key == LEFT || key == ',') && !alt_down() ) {
562                         panel->panel_prev_label(0);
563                         return 1;
564                 }
565                 if( key == '<' && alt_down() ) {
566                         panel->panel_prev_label(1);
567                         return 1;
568                 }
569         }
570         return context_help_check_and_show();
571 }
572 int EditPrevLabel::handle_event()
573 {
574         int cut = ctrl_down() && alt_down();
575         panel->panel_prev_label(cut);
576         return 1;
577 }
578
579 //prev_edit
580 EditPrevEdit::EditPrevEdit(MWindow *mwindow,
581         EditPanel *panel, int x, int y)
582  : BC_Button(x, y, mwindow->theme->get_image_set("prevedit"))
583 {
584         this->mwindow = mwindow;
585         this->panel = panel;
586         set_tooltip(_("Previous edit (alt <- )"));
587 // *** CONTEXT_HELP ***
588         context_help_set_keyword("Snapping while Cutting and Dragging");
589 }
590 EditPrevEdit::~EditPrevEdit()
591 {
592 }
593 int EditPrevEdit::keypress_event()
594 {
595         if( alt_down() ) {
596                 int key = get_keypress();
597                 if( (key == LEFT || key == ',') && !ctrl_down() ) {
598                         panel->panel_prev_edit(0);
599                         return 1;
600                 }
601                 if( key == ',' && ctrl_down() ) {
602                         panel->panel_prev_edit(1);
603                         return 1;
604                 }
605         }
606         return context_help_check_and_show();
607 }
608 int EditPrevEdit::handle_event()
609 {
610         int cut = ctrl_down() && alt_down();
611         panel->panel_prev_edit(cut);
612         return 1;
613 }
614
615 //next_edit
616 EditNextEdit::EditNextEdit(MWindow *mwindow,
617         EditPanel *panel, int x, int y)
618  : BC_Button(x, y, mwindow->theme->get_image_set("nextedit"))
619 {
620         this->mwindow = mwindow;
621         this->panel = panel;
622         set_tooltip(_("Next edit ( alt -> )"));
623 // *** CONTEXT_HELP ***
624         context_help_set_keyword("Snapping while Cutting and Dragging");
625 }
626 EditNextEdit::~EditNextEdit()
627 {
628 }
629 int EditNextEdit::keypress_event()
630 {
631         if( alt_down() ) {
632                 int key = get_keypress();
633                 if( (key == RIGHT || key == '.') && !ctrl_down() ) {
634                         panel->panel_next_edit(0);
635                         return 1;
636                 }
637                 if( key == '.' && ctrl_down() ) {
638                         panel->panel_next_edit(1);
639                         return 1;
640                 }
641         }
642         return context_help_check_and_show();
643 }
644 int EditNextEdit::handle_event()
645 {
646         int cut = ctrl_down() && alt_down();
647         panel->panel_next_edit(cut);
648         return 1;
649 }
650
651 //copy_selection
652 EditCopy::EditCopy(MWindow *mwindow, EditPanel *panel, int x, int y)
653  : BC_Button(x, y, mwindow->theme->get_image_set("copy"))
654 {
655         this->mwindow = mwindow;
656         this->panel = panel;
657         set_tooltip(_("Copy ( c )"));
658 // *** CONTEXT_HELP ***
659         context_help_set_keyword("Cut and Paste Editing");
660 }
661 EditCopy::~EditCopy()
662 {
663 }
664
665 int EditCopy::keypress_event()
666 {
667         if( alt_down() ) return context_help_check_and_show();
668         if( (get_keypress() == 'c' && !ctrl_down()) ||
669             (panel->is_vwindow() && get_keypress() == 'C') ) {
670                 return handle_event();
671         }
672         return context_help_check_and_show();
673 }
674 int EditCopy::handle_event()
675 {
676         panel->panel_copy_selection();
677         return 1;
678 }
679
680 //overwrite_selection
681 EditOverwrite::EditOverwrite(MWindow *mwindow, EditPanel *panel, int x, int y)
682  : BC_Button(x, y, mwindow->theme->overwrite_data)
683 {
684         this->mwindow = mwindow;
685         this->panel = panel;
686         set_tooltip(_("Overwrite ( b )"));
687 // *** CONTEXT_HELP ***
688         context_help_set_keyword("Two Screen Editing");
689 }
690 EditOverwrite::~EditOverwrite()
691 {
692 }
693 int EditOverwrite::handle_event()
694 {
695         panel->panel_overwrite_selection();
696         return 1;
697 }
698 int EditOverwrite::keypress_event()
699 {
700         if( alt_down() ) return context_help_check_and_show();
701         if( get_keypress() == 'b' ||
702             (panel->is_vwindow() && get_keypress() == 'B') ) {
703                 handle_event();
704                 return 1;
705         }
706         return context_help_check_and_show();
707 }
708
709 //set_inpoint
710 //unset_inoutpoint
711 EditInPoint::EditInPoint(MWindow *mwindow, EditPanel *panel, int x, int y)
712  : BC_Button(x, y, mwindow->theme->get_image_set("inbutton"))
713 {
714         this->mwindow = mwindow;
715         this->panel = panel;
716         set_tooltip(_("In point ( [ or < )"));
717 // *** CONTEXT_HELP ***
718         context_help_set_keyword("In\\/Out Points");
719 }
720 EditInPoint::~EditInPoint()
721 {
722 }
723 int EditInPoint::handle_event()
724 {
725         panel->panel_set_inpoint();
726         return 1;
727 }
728 int EditInPoint::keypress_event()
729 {
730         int key = get_keypress();
731         if( ctrl_down() ) {
732                 if( key == 't' ) {
733                         panel->panel_unset_inoutpoint();
734                         return 1;
735                 }
736         }
737         else if( !alt_down() ) {
738                 if( key == '[' || key == '<' ) {
739                         panel->panel_set_inpoint();
740                         return 1;
741                 }
742         }
743         return context_help_check_and_show();
744 }
745
746 //set_outpoint
747 //unset_inoutpoint
748 EditOutPoint::EditOutPoint(MWindow *mwindow, EditPanel *panel, int x, int y)
749  : BC_Button(x, y, mwindow->theme->get_image_set("outbutton"))
750 {
751         this->mwindow = mwindow;
752         this->panel = panel;
753         set_tooltip(_("Out point ( ] or > )"));
754 // *** CONTEXT_HELP ***
755         context_help_set_keyword("In\\/Out Points");
756 }
757 EditOutPoint::~EditOutPoint()
758 {
759 }
760 int EditOutPoint::handle_event()
761 {
762         panel->panel_set_outpoint();
763         return 1;
764 }
765 int EditOutPoint::keypress_event()
766 {
767         int key = get_keypress();
768         if( ctrl_down() ) {
769                 if(  key == 't' ) {
770                         panel->panel_unset_inoutpoint();
771                         return 1;
772                 }
773         }
774         else if( !alt_down() ) {
775                 if( key == ']' || key == '>' ) {
776                         panel->panel_set_outpoint();
777                         return 1;
778                 }
779         }
780         return context_help_check_and_show();
781 }
782
783 //splice_selection
784 EditSplice::EditSplice(MWindow *mwindow, EditPanel *panel, int x, int y)
785  : BC_Button(x, y, mwindow->theme->splice_data)
786 {
787         this->mwindow = mwindow;
788         this->panel = panel;
789         set_tooltip(_("Splice ( v )"));
790 // *** CONTEXT_HELP ***
791         context_help_set_keyword("Two Screen Editing");
792 }
793 EditSplice::~EditSplice()
794 {
795 }
796 int EditSplice::handle_event()
797 {
798         panel->panel_splice_selection();
799         return 1;
800 }
801 int EditSplice::keypress_event()
802 {
803         if( alt_down() ) return context_help_check_and_show();
804         if( (get_keypress() == 'v' && !ctrl_down()) ||
805             (panel->is_vwindow() && get_keypress() == 'V') ) {
806                 handle_event();
807                 return 1;
808         }
809         return context_help_check_and_show();
810 }
811
812 //to_clip
813 EditToClip::EditToClip(MWindow *mwindow, EditPanel *panel, int x, int y)
814  : BC_Button(x, y, mwindow->theme->get_image_set("toclip"))
815 {
816         this->mwindow = mwindow;
817         this->panel = panel;
818         set_tooltip(_("To clip ( i )"));
819 // *** CONTEXT_HELP ***
820         context_help_set_keyword("Two Screen Editing");
821 }
822 EditToClip::~EditToClip()
823 {
824 }
825 int EditToClip::handle_event()
826 {
827         panel->panel_to_clip();
828         return 1;
829 }
830
831 int EditToClip::keypress_event()
832 {
833         if( alt_down() ) return context_help_check_and_show();
834         if( get_keypress() == 'i' ||
835             (panel->is_vwindow() && get_keypress() == 'I') ) {
836                 handle_event();
837                 return 1;
838         }
839         return context_help_check_and_show();
840 }
841
842 //cut
843 EditCut::EditCut(MWindow *mwindow, EditPanel *panel, int x, int y)
844  : BC_Button(x, y, mwindow->theme->get_image_set("cut"))
845 {
846         this->mwindow = mwindow;
847         this->panel = panel;
848         set_tooltip(_("Split | Cut ( x )"));
849 // *** CONTEXT_HELP ***
850         context_help_set_keyword("Cut and Paste Editing");
851 }
852 EditCut::~EditCut()
853 {
854 }
855 int EditCut::keypress_event()
856 {
857         if( ctrl_down() || shift_down() || alt_down() )
858                 return context_help_check_and_show();
859         if( get_keypress() == 'x' )
860                 return handle_event();
861         return context_help_check_and_show();
862 }
863
864 int EditCut::handle_event()
865 {
866         panel->panel_cut();
867         return 1;
868 }
869
870 //paste
871 EditPaste::EditPaste(MWindow *mwindow, EditPanel *panel, int x, int y)
872  : BC_Button(x, y, mwindow->theme->get_image_set("paste"))
873 {
874         this->mwindow = mwindow;
875         this->panel = panel;
876         set_tooltip(_("Paste ( v )"));
877 // *** CONTEXT_HELP ***
878         context_help_set_keyword("Cut and Paste Editing");
879 }
880 EditPaste::~EditPaste()
881 {
882 }
883
884 int EditPaste::keypress_event()
885 {
886         if( get_keypress() == 'v' && !ctrl_down() )
887                 return handle_event();
888         return context_help_check_and_show();
889 }
890 int EditPaste::handle_event()
891 {
892         panel->panel_paste();
893         return 1;
894 }
895
896 //fit_selection
897 EditFit::EditFit(MWindow *mwindow, EditPanel *panel, int x, int y)
898  : BC_Button(x, y, mwindow->theme->get_image_set("fit"))
899 {
900         this->mwindow = mwindow;
901         this->panel = panel;
902         set_tooltip(_("Fit selection to display ( f )"));
903 // *** CONTEXT_HELP ***
904         context_help_set_keyword("Transport and Buttons Bar");
905 }
906 EditFit::~EditFit()
907 {
908 }
909 int EditFit::keypress_event()
910 {
911         if( !alt_down() && get_keypress() == 'f' ) {
912                 handle_event();
913                 return 1;
914         }
915         return context_help_check_and_show();
916 }
917 int EditFit::handle_event()
918 {
919         panel->panel_fit_selection();
920         return 1;
921 }
922
923 //fit_autos
924 EditFitAutos::EditFitAutos(MWindow *mwindow, EditPanel *panel, int x, int y)
925  : BC_Button(x, y, mwindow->theme->get_image_set("fitautos"))
926 {
927         this->mwindow = mwindow;
928         this->panel = panel;
929         set_tooltip(_("Fit all autos to display ( Alt + f )"));
930 // *** CONTEXT_HELP ***
931         context_help_set_keyword("Using Autos");
932 }
933 EditFitAutos::~EditFitAutos()
934 {
935 }
936 int EditFitAutos::keypress_event()
937 {
938         if( get_keypress() == 'f' && alt_down() ) {
939                 panel->panel_fit_autos(!ctrl_down() ? 1 : 0);
940                 return 1;
941         }
942         return context_help_check_and_show();
943 }
944 int EditFitAutos::handle_event()
945 {
946         panel->panel_fit_autos(1);
947         return 1;
948 }
949
950 //set_editing_mode
951 ArrowButton::ArrowButton(MWindow *mwindow, EditPanel *panel, int x, int y)
952  : BC_Toggle(x, y,
953         mwindow->theme->get_image_set("arrow"),
954         mwindow->edl->session->editing_mode == EDITING_ARROW,
955         "", 0, 0, 0)
956 {
957         this->mwindow = mwindow;
958         this->panel = panel;
959         set_tooltip(_("Drag and drop editing mode"));
960 // *** CONTEXT_HELP ***
961         context_help_set_keyword("Drag and Drop Editing");
962 }
963
964 int ArrowButton::handle_event()
965 {
966         update(1);
967         panel->ibeam->update(0);
968         panel->panel_set_editing_mode(EDITING_ARROW);
969 // Nothing after this
970         return 1;
971 }
972
973 IBeamButton::IBeamButton(MWindow *mwindow, EditPanel *panel, int x, int y)
974  : BC_Toggle(x, y,
975         mwindow->theme->get_image_set("ibeam"),
976         mwindow->edl->session->editing_mode == EDITING_IBEAM,
977         "", 0, 0, 0)
978 {
979         this->mwindow = mwindow;
980         this->panel = panel;
981         set_tooltip(_("Cut and paste editing mode"));
982 // *** CONTEXT_HELP ***
983         context_help_set_keyword("Cut and Paste Editing");
984 }
985
986 int IBeamButton::handle_event()
987 {
988         update(1);
989         panel->arrow->update(0);
990         panel->panel_set_editing_mode(EDITING_IBEAM);
991 // Nothing after this
992         return 1;
993 }
994
995 //set_auto_keyframes
996 KeyFrameButton::KeyFrameButton(MWindow *mwindow, EditPanel *panel, int x, int y)
997  : BC_Toggle(x, y,
998         mwindow->theme->get_image_set("autokeyframe"),
999         mwindow->edl->session->auto_keyframes,
1000         "", 0, 0, 0)
1001 {
1002         this->mwindow = mwindow;
1003         this->panel = panel;
1004         set_tooltip(_("Generate keyframes while tweeking (j)"));
1005 // *** CONTEXT_HELP ***
1006         context_help_set_keyword("Generate Keyframes while Tweaking");
1007 }
1008
1009 int KeyFrameButton::handle_event()
1010 {
1011         panel->panel_set_auto_keyframes(get_value());
1012         return 1;
1013 }
1014
1015 int KeyFrameButton::keypress_event()
1016 {
1017         int key = get_keypress();
1018         if( key == 'j' && !ctrl_down() && !shift_down() && !alt_down() ) {
1019                 int value = get_value() ? 0 : 1;
1020                 update(value);
1021                 panel->panel_set_auto_keyframes(value);
1022                 return 1;
1023         }
1024         return context_help_check_and_show();
1025 }
1026
1027 //set_span_keyframes
1028 SpanKeyFrameButton::SpanKeyFrameButton(MWindow *mwindow, EditPanel *panel, int x, int y)
1029  : BC_Toggle(x, y,
1030         mwindow->theme->get_image_set("spankeyframe"),
1031         mwindow->edl->session->span_keyframes,
1032         "", 0, 0, 0)
1033 {
1034         this->mwindow = mwindow;
1035         this->panel = panel;
1036         set_tooltip(_("Allow keyframe spanning"));
1037 // *** CONTEXT_HELP ***
1038         context_help_set_keyword("Allow Keyframe Spanning");
1039 }
1040
1041 int SpanKeyFrameButton::handle_event()
1042 {
1043         panel->panel_set_span_keyframes(get_value());
1044         return 1;
1045 }
1046
1047 //set_labels_follow_edits
1048 LockLabelsButton::LockLabelsButton(MWindow *mwindow, EditPanel *panel, int x, int y)
1049  : BC_Toggle(x, y,
1050         mwindow->theme->get_image_set("locklabels"),
1051         mwindow->edl->session->labels_follow_edits,
1052         "", 0, 0, 0)
1053 {
1054         this->mwindow = mwindow;
1055         this->panel = panel;
1056         set_tooltip(_("Lock labels from moving with edits"));
1057 // *** CONTEXT_HELP ***
1058         context_help_set_keyword("Labels");
1059 }
1060
1061 int LockLabelsButton::handle_event()
1062 {
1063         panel->panel_set_labels_follow_edits(get_value());
1064         return 1;
1065 }
1066
1067
1068
1069 EditManualGoto::EditManualGoto(MWindow *mwindow, EditPanel *panel, int x, int y)
1070  : BC_Button(x, y, mwindow->theme->get_image_set("goto"))
1071 {
1072         this->mwindow = mwindow;
1073         this->panel = panel;
1074         mangoto = new ManualGoto(mwindow, panel);
1075         set_tooltip(_("Manual goto ( g )"));
1076 // *** CONTEXT_HELP ***
1077         context_help_set_keyword("Transport and Buttons Bar");
1078 }
1079 EditManualGoto::~EditManualGoto()
1080 {
1081         delete mangoto;
1082 }
1083 int EditManualGoto::handle_event()
1084 {
1085         mangoto->start();
1086         return 1;
1087 }
1088
1089 int EditManualGoto::keypress_event()
1090 {
1091         if( get_keypress() == 'g' ) {
1092                 handle_event();
1093                 return 1;
1094         }
1095         return context_help_check_and_show();
1096 }
1097
1098
1099 EditClick2Play::EditClick2Play(MWindow *mwindow, EditPanel *panel, int x, int y)
1100  : BC_Toggle(x, y, mwindow->theme->get_image_set("playpatch_data"),
1101     !panel->is_vwindow() ?
1102         mwindow->edl->session->cwindow_click2play :
1103         mwindow->edl->session->vwindow_click2play)
1104 {
1105         this->mwindow = mwindow;
1106         this->panel = panel;
1107         set_tooltip(_("Click to play (p)"));
1108 // *** CONTEXT_HELP ***
1109         context_help_set_keyword("Click to Play in Viewer and Compositor");
1110 }
1111 int EditClick2Play::handle_event()
1112 {
1113         int value = get_value();
1114         panel->set_click_to_play(value);
1115         return 1;
1116 }
1117 int EditClick2Play::keypress_event()
1118 {
1119         int key = get_keypress();
1120         if( key == 'p' && !ctrl_down() && !shift_down() && !alt_down() ) {
1121                 int value = get_value() ? 0 : 1;
1122                 update(value);
1123                 panel->set_click_to_play(value);
1124                 return 1;
1125         }
1126         return context_help_check_and_show();
1127 }
1128
1129
1130 EditCommercial::EditCommercial(MWindow *mwindow, EditPanel *panel, int x, int y)
1131  : BC_Button(x, y, mwindow->theme->get_image_set("commercial"))
1132 {
1133         this->mwindow = mwindow;
1134         this->panel = panel;
1135         set_tooltip(_("Commercial ( shift A )"));
1136 // *** CONTEXT_HELP ***
1137         context_help_set_keyword("The commercial DB");
1138 }
1139 EditCommercial::~EditCommercial()
1140 {
1141 }
1142 int EditCommercial::keypress_event()
1143 {
1144         if( ctrl_down() || !shift_down() || alt_down() )
1145                 return context_help_check_and_show();
1146         if( get_keypress() == 'A' )
1147                 return handle_event();
1148         return context_help_check_and_show();
1149 }
1150
1151 int EditCommercial::handle_event()
1152 {
1153         int have_mwindow_lock = mwindow->gui->get_window_lock();
1154         if( have_mwindow_lock )
1155                 mwindow->gui->unlock_window();
1156         mwindow->commit_commercial();
1157         if( !mwindow->put_commercial() ) {
1158                 mwindow->gui->lock_window("EditCommercial::handle_event 1");
1159                 mwindow->cut();
1160                 if( !have_mwindow_lock )
1161                         mwindow->gui->unlock_window();
1162                 mwindow->activate_commercial();
1163                 return 1;
1164         }
1165         mwindow->undo_commercial();
1166         if( have_mwindow_lock )
1167                 mwindow->gui->lock_window("EditCommercial::handle_event 2");
1168         return 1;
1169 }
1170
1171
1172 EditUndo::EditUndo(MWindow *mwindow, EditPanel *panel, int x, int y)
1173  : BC_Button(x, y, mwindow->theme->get_image_set("undo"))
1174 {
1175         this->mwindow = mwindow;
1176         this->panel = panel;
1177         set_tooltip(_("Undo ( z or Ctrl-z)"));
1178 // *** CONTEXT_HELP ***
1179         context_help_set_keyword("Transport and Buttons Bar");
1180 }
1181 EditUndo::~EditUndo()
1182 {
1183 }
1184 int EditUndo::keypress_event()
1185 {
1186         if( ctrl_down() || shift_down() || alt_down() )
1187                 return context_help_check_and_show();
1188         if( get_keypress() == 'z' )
1189                 return handle_event();
1190         return context_help_check_and_show();
1191 }
1192 int EditUndo::handle_event()
1193 {
1194         mwindow->undo_entry(panel->subwindow);
1195         return 1;
1196 }
1197
1198 EditRedo::EditRedo(MWindow *mwindow, EditPanel *panel, int x, int y)
1199  : BC_Button(x, y, mwindow->theme->get_image_set("redo"))
1200 {
1201         this->mwindow = mwindow;
1202         this->panel = panel;
1203         set_tooltip(_("Redo ( shift Z )"));
1204 // *** CONTEXT_HELP ***
1205         context_help_set_keyword("Transport and Buttons Bar");
1206 }
1207 EditRedo::~EditRedo()
1208 {
1209 }
1210 int EditRedo::keypress_event()
1211 {
1212         if( ctrl_down() || !shift_down() || alt_down() )
1213                 return context_help_check_and_show();
1214         if( get_keypress() == 'Z' )
1215                 return handle_event();
1216         return context_help_check_and_show();
1217 }
1218 int EditRedo::handle_event()
1219 {
1220         mwindow->redo_entry(panel->subwindow);
1221         return 1;
1222 }
1223
1224
1225 EditPanelScopeDialog::EditPanelScopeDialog(MWindow *mwindow, EditPanel *panel)
1226  : BC_DialogThread()
1227 {
1228         this->mwindow = mwindow;
1229         this->panel = panel;
1230         scope_gui = 0;
1231         gui_lock = new Mutex("EditPanelScopeDialog::gui_lock");
1232 }
1233
1234 EditPanelScopeDialog::~EditPanelScopeDialog()
1235 {
1236         close_window();
1237         delete gui_lock;
1238 }
1239
1240 void EditPanelScopeDialog::handle_close_event(int result)
1241 {
1242         scope_gui = 0;
1243 }
1244 void EditPanelScopeDialog::handle_done_event(int result)
1245 {
1246         gui_lock->lock("EditPanelScopeDialog::handle_done_event");
1247         scope_gui = 0;
1248         gui_lock->unlock();
1249
1250         panel->subwindow->lock_window("EditPanelScopeDialog::handle_done_event");
1251         panel->scope->update(0);
1252         panel->subwindow->unlock_window();
1253 }
1254
1255 BC_Window* EditPanelScopeDialog::new_gui()
1256 {
1257         EditPanelScopeGUI *gui = new EditPanelScopeGUI(mwindow, this);
1258         gui->create_objects();
1259         scope_gui = gui;
1260         return gui;
1261 }
1262
1263 void EditPanelScopeDialog::process(VFrame *output_frame)
1264 {
1265         if( panel->scope_dialog ) {
1266                 panel->scope_dialog->gui_lock->lock("EditPanelScopeDialog::process");
1267                 if( panel->scope_dialog->scope_gui ) {
1268                         EditPanelScopeGUI *gui = panel->scope_dialog->scope_gui;
1269                         gui->process(output_frame);
1270                 }
1271                 panel->scope_dialog->gui_lock->unlock();
1272         }
1273 }
1274
1275 EditPanelScopeGUI::EditPanelScopeGUI(MWindow *mwindow, EditPanelScopeDialog *dialog)
1276  : ScopeGUI(mwindow->theme,
1277         mwindow->session->scope_x, mwindow->session->scope_y,
1278         mwindow->session->scope_w, mwindow->session->scope_h,
1279         mwindow->get_cpus())
1280 {
1281         this->mwindow = mwindow;
1282         this->dialog = dialog;
1283 }
1284
1285 EditPanelScopeGUI::~EditPanelScopeGUI()
1286 {
1287 }
1288
1289 void EditPanelScopeGUI::create_objects()
1290 {
1291         MainSession *session = mwindow->session;
1292         use_hist = session->use_hist;
1293         use_wave = session->use_wave;
1294         use_vector = session->use_vector;
1295         use_hist_parade = session->use_hist_parade;
1296         use_wave_parade = session->use_wave_parade;
1297         use_wave_gain = session->use_wave_gain;
1298         use_vect_gain = session->use_vect_gain;
1299         use_smooth = session->use_smooth;
1300         use_refresh = session->use_refresh;
1301         use_release = session->use_release;
1302         use_graticule = session->use_graticule;
1303         ScopeGUI::create_objects();
1304 }
1305
1306 void EditPanelScopeGUI::toggle_event()
1307 {
1308         MainSession *session = mwindow->session;
1309         session->use_hist = use_hist;
1310         session->use_wave = use_wave;
1311         session->use_vector = use_vector;
1312         session->use_hist_parade = use_hist_parade;
1313         session->use_wave_parade = use_wave_parade;
1314         session->use_wave_gain = use_wave_gain;
1315         session->use_vect_gain = use_vect_gain;
1316         session->use_smooth = use_smooth;
1317         session->use_refresh = use_refresh;
1318         session->use_release = use_release;
1319         session->use_graticule = use_graticule;
1320 }
1321
1322 int EditPanelScopeGUI::translation_event()
1323 {
1324         ScopeGUI::translation_event();
1325         MainSession *session = mwindow->session;
1326         session->scope_x = get_x();
1327         session->scope_y = get_y();
1328         return 0;
1329 }
1330
1331 int EditPanelScopeGUI::resize_event(int w, int h)
1332 {
1333         ScopeGUI::resize_event(w, h);
1334         MainSession *session = mwindow->session;
1335         session->scope_w = w;
1336         session->scope_h = h;
1337         return 0;
1338 }
1339
1340 EditPanelScope::EditPanelScope(MWindow *mwindow, EditPanel *panel, int x, int y)
1341  : BC_Toggle(x, y, mwindow->theme ?
1342                 mwindow->theme->get_image_set("scope_toggle") : 0, 0)
1343 {
1344         this->mwindow = mwindow;
1345         this->panel = panel;
1346         set_tooltip(_("View scope"));
1347 // *** CONTEXT_HELP ***
1348         context_help_set_keyword("Videoscope");
1349 }
1350
1351 EditPanelScope::~EditPanelScope()
1352 {
1353 }
1354
1355 void EditPanelScopeGUI::update_scope()
1356 {
1357         Canvas *canvas = 0;
1358         if( dialog->panel->is_cwindow() ) {
1359                 CWindowGUI *cgui = (CWindowGUI *)dialog->panel->subwindow;
1360                 canvas = cgui->canvas;
1361         }
1362         else if( dialog->panel->is_vwindow() ) {
1363                 VWindowGUI *vgui = (VWindowGUI *)dialog->panel->subwindow;
1364                 canvas = vgui->canvas;
1365         }
1366         if( canvas && canvas->refresh_frame )
1367                 process(canvas->refresh_frame);
1368 }
1369
1370 int EditPanelScope::handle_event()
1371 {
1372         unlock_window();
1373         int v = get_value();
1374         if( v )
1375                 panel->scope_dialog->start();
1376         else
1377                 panel->scope_dialog->close_window();
1378         lock_window("EditPanelScope::handle_event");
1379         return 1;
1380 }
1381
1382 const char *EditPanelGangTracks::gang_tips[TOTAL_GANGS] = {
1383         N_("Currently: Gang None\n  Click to: Gang Channels"),
1384         N_("Currently: Gang Channels\n  Click to: Gang Media"),
1385         N_("Currently: Gang Media\n  Click to: Gang None"),
1386 };
1387
1388 EditPanelGangTracks::EditPanelGangTracks(MWindow *mwindow, EditPanel *panel,
1389                 int x, int y)
1390  : BC_Button(x, y, get_images(mwindow))
1391 {
1392         this->mwindow = mwindow;
1393         this->panel = panel;
1394         int gang = mwindow->edl->local_session->gang_tracks;
1395         set_tooltip(_(gang_tips[gang]));
1396 // *** CONTEXT_HELP ***
1397         context_help_set_keyword("Displaying tracks: Ganged mode");
1398 }
1399
1400 EditPanelGangTracks::~EditPanelGangTracks()
1401 {
1402 }
1403
1404 VFrame **EditPanelGangTracks::gang_images[TOTAL_GANGS];
1405
1406 VFrame **EditPanelGangTracks::get_images(MWindow *mwindow)
1407 {
1408         gang_images[GANG_NONE] = mwindow->theme->get_image_set("gang0");
1409         gang_images[GANG_MEDIA] = mwindow->theme->get_image_set("gang1");
1410         gang_images[GANG_CHANNELS] = mwindow->theme->get_image_set("gang2");
1411         int gang = mwindow->edl->local_session->gang_tracks;
1412         return gang_images[gang];
1413 }
1414
1415 void EditPanelGangTracks::update(int gang)
1416 {
1417         set_images(gang_images[gang]);
1418         draw_face();
1419         set_tooltip(_(gang_tips[gang]));
1420 }
1421
1422 int EditPanelGangTracks::handle_event()
1423 {
1424         int gang = mwindow->edl->local_session->gang_tracks;
1425         if( !shift_down() ) {
1426                 if( ++gang > GANG_MEDIA ) gang = GANG_NONE;
1427         }
1428         else {
1429                 if( --gang < GANG_NONE ) gang = GANG_MEDIA;
1430         }
1431         update(gang);
1432         panel->panel_set_gang_tracks(gang);
1433         return 1;
1434 }
1435
1436
1437 EditPanelTimecode::EditPanelTimecode(MWindow *mwindow,
1438         EditPanel *panel, int x, int y)
1439  : BC_Button(x, y, mwindow->theme->get_image_set("clapperbutton"))
1440 {
1441         this->mwindow = mwindow;
1442         this->panel = panel;
1443         tc_dialog = 0;
1444         set_tooltip(_("Set Timecode"));
1445 // *** CONTEXT_HELP ***
1446         context_help_set_keyword("Align Timecodes");
1447 }
1448
1449 EditPanelTimecode::~EditPanelTimecode()
1450 {
1451         delete tc_dialog;
1452 }
1453
1454 int EditPanelTimecode::handle_event()
1455 {
1456         if( !tc_dialog )
1457                 tc_dialog = new EditPanelTcDialog(mwindow, panel);
1458         int px, py;
1459         get_pop_cursor(px, py, 0);
1460         tc_dialog->start_dialog(px, py);
1461         return 1;
1462 }
1463
1464 EditPanelTcDialog::EditPanelTcDialog(MWindow *mwindow, EditPanel *panel)
1465  : BC_DialogThread()
1466 {
1467         this->mwindow = mwindow;
1468         this->panel = panel;
1469         tc_gui = 0;
1470         px = py = 0;
1471 }
1472
1473 EditPanelTcDialog::~EditPanelTcDialog()
1474 {
1475         close_window();
1476 }
1477
1478 #define TCW_W xS(200)
1479 #define TCW_H yS(120)
1480
1481 void EditPanelTcDialog::start_dialog(int px, int py)
1482 {
1483         this->px = px - TCW_W/2;
1484         this->py = py - TCW_H/2;
1485         start();
1486 }
1487
1488 BC_Window *EditPanelTcDialog::new_gui()
1489 {
1490         tc_gui = new EditPanelTcWindow(this, px, py);
1491         tc_gui->create_objects();
1492         double timecode = mwindow->get_timecode_offset();
1493         tc_gui->update(timecode);
1494         tc_gui->show_window();
1495         return tc_gui;
1496 }
1497
1498 void EditPanelTcDialog::handle_done_event(int result)
1499 {
1500         if( result ) return;
1501         double ofs = tc_gui->get_timecode();
1502         mwindow->set_timecode_offset(ofs);
1503 }
1504
1505 EditPanelTcWindow::EditPanelTcWindow(EditPanelTcDialog *tc_dialog, int x, int y)
1506  : BC_Window(_(PROGRAM_NAME ": Timecode"), x, y,
1507         TCW_W, TCW_H, TCW_W, TCW_H, 0, 0, 1)
1508 {
1509         this->tc_dialog = tc_dialog;
1510 // *** CONTEXT_HELP ***
1511         context_help_set_keyword("Align Timecodes");
1512 }
1513
1514 EditPanelTcWindow::~EditPanelTcWindow()
1515 {
1516 }
1517
1518 double EditPanelTcWindow::get_timecode()
1519 {
1520         int hrs = atoi(hours->get_text());
1521         int mins = atoi(minutes->get_text());
1522         int secs = atoi(seconds->get_text());
1523         int frms = atoi(frames->get_text());
1524         double frame_rate = tc_dialog->mwindow->edl->session->frame_rate;
1525         double timecode = hrs*3600 + mins*60 + secs + frms/frame_rate;
1526         return timecode;
1527 }
1528
1529 void EditPanelTcWindow::update(double timecode)
1530 {
1531         if( timecode < 0 ) timecode = 0;
1532         int64_t pos = timecode;
1533         int hrs = pos/3600;
1534         int mins = pos/60 - hrs*60;
1535         int secs = pos - hrs*3600 - mins*60;
1536         double frame_rate = tc_dialog->mwindow->edl->session->frame_rate;
1537         int frms = (timecode-pos) * frame_rate;
1538         hours->update(hrs);
1539         minutes->update(mins);
1540         seconds->update(secs);
1541         frames->update(frms);
1542 }
1543
1544 void EditPanelTcWindow::create_objects()
1545 {
1546         lock_window("EditPanelTcWindow::create_objects");
1547         int x = xS(20), y = yS(5);
1548         BC_Title *title = new BC_Title(x - 2, y, _("hour  min   sec   frms"), SMALLFONT);
1549         add_subwindow(title);  y += title->get_h() + xS(3);
1550         hours = new EditPanelTcInt(this, x, y, xS(26), 99, "%02i");
1551         add_subwindow(hours);    x += hours->get_w() + xS(4);
1552         minutes = new EditPanelTcInt(this, x, y, xS(26), 59, "%02i");
1553         add_subwindow(minutes);  x += minutes->get_w() + xS(4);
1554         seconds = new EditPanelTcInt(this, x, y, xS(26), 60, "%02i");
1555         add_subwindow(seconds);  x += seconds->get_w() + xS(4);
1556         frames = new EditPanelTcInt(this, x, y, xS(34), 999, "%03i");
1557         add_subwindow(frames);   x += frames->get_w() + xS(16);
1558         add_subwindow(new EditPanelTcReset(this, x, y));
1559         double timecode = tc_dialog->mwindow->get_timecode_offset();
1560         update(timecode);
1561         add_subwindow(new BC_OKButton(this));
1562         add_subwindow(new BC_CancelButton(this));
1563         unlock_window();
1564 }
1565
1566 EditPanelTcReset::EditPanelTcReset(EditPanelTcWindow *window, int x, int y)
1567  : BC_Button(x, y, window->tc_dialog->mwindow->theme->get_image_set("reset_button"))
1568 {
1569         this->window = window;
1570 }
1571
1572 int EditPanelTcReset::handle_event()
1573 {
1574         window->update(0);
1575         return 1;
1576 }
1577
1578
1579 EditPanelTcInt::EditPanelTcInt(EditPanelTcWindow *window, int x, int y, int w,
1580         int max, const char *format)
1581  : BC_TextBox(x, y, w, 1, "")
1582 {
1583         this->window = window;
1584         this->max = max;
1585         this->format = format;
1586         digits = 1;
1587         for( int m=max; (m/=10)>0; ++digits );
1588 }
1589
1590 EditPanelTcInt::~EditPanelTcInt()
1591 {
1592 }
1593
1594 int EditPanelTcInt::handle_event()
1595 {
1596         int v = atoi(get_text());
1597         if( v > max ) {
1598                 v = v % (max+1);
1599                 char string[BCSTRLEN];
1600                 sprintf(string, format, v);
1601                 BC_TextBox::update(string);
1602         }
1603         return 1;
1604 }
1605
1606 void EditPanelTcInt::update(int v)
1607 {
1608         char text[BCTEXTLEN];
1609         if( v > max ) v = max;
1610         sprintf(text, format, v);
1611         BC_TextBox::update(text);
1612 }
1613
1614 int EditPanelTcInt::keypress_event()
1615 {
1616         if( get_keypress() == 'h' && alt_down() ) {
1617                 context_help_show("Align Timecodes");
1618                 return 1;
1619         }
1620
1621         if( (int)strlen(get_text()) >= digits )
1622                 BC_TextBox::update("");
1623         int key = get_keypress();
1624         switch( key ) {
1625         case TAB:   case LEFTTAB:
1626         case LEFT:  case RIGHT:
1627         case HOME:  case END:
1628         case BACKSPACE:
1629         case DELETE:
1630         case '0': case '1': case '2': case '3': case '4':
1631         case '5': case '6': case '7': case '8': case '9':
1632                 return BC_TextBox::keypress_event();
1633         }
1634         return 1;
1635 }
1636