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