bf33acba43bf1dce3e4af4d0215bf26fe9547223
[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->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 }
488
489 EditLabelbutton::~EditLabelbutton()
490 {
491 }
492 int EditLabelbutton::keypress_event()
493 {
494         if( get_keypress() == 'l' && !alt_down() )
495                 return handle_event();
496         return 0;
497 }
498 int EditLabelbutton::handle_event()
499 {
500         panel->panel_toggle_label();
501         return 1;
502 }
503
504 //next_label
505 EditNextLabel::EditNextLabel(MWindow *mwindow,
506         EditPanel *panel, int x, int y)
507  : BC_Button(x, y, mwindow->theme->get_image_set("nextlabel"))
508 {
509         this->mwindow = mwindow;
510         this->panel = panel;
511         set_tooltip(_("Next label ( ctrl -> )"));
512 }
513 EditNextLabel::~EditNextLabel()
514 {
515 }
516 int EditNextLabel::keypress_event()
517 {
518         if( ctrl_down() ) {
519                 int key = get_keypress();
520                 if( (key == RIGHT || key == '.') && !alt_down() ) {
521                         panel->panel_next_label(0);
522                         return 1;
523                 }
524                 if( key == '>' && alt_down() ) {
525                         panel->panel_next_label(1);
526                         return 1;
527                 }
528         }
529         return 0;
530 }
531 int EditNextLabel::handle_event()
532 {
533         int cut = ctrl_down() && alt_down();
534         panel->panel_next_label(cut);
535         return 1;
536 }
537
538 //prev_label
539 EditPrevLabel::EditPrevLabel(MWindow *mwindow,
540         EditPanel *panel, int x, int y)
541  : BC_Button(x, y, mwindow->theme->get_image_set("prevlabel"))
542 {
543         this->mwindow = mwindow;
544         this->panel = panel;
545         set_tooltip(_("Previous label ( ctrl <- )"));
546 }
547 EditPrevLabel::~EditPrevLabel()
548 {
549 }
550 int EditPrevLabel::keypress_event()
551 {
552         if( ctrl_down() ) {
553                 int key = get_keypress();
554                 if( (key == LEFT || key == ',') && !alt_down() ) {
555                         panel->panel_prev_label(0);
556                         return 1;
557                 }
558                 if( key == '<' && alt_down() ) {
559                         panel->panel_prev_label(1);
560                         return 1;
561                 }
562         }
563         return 0;
564 }
565 int EditPrevLabel::handle_event()
566 {
567         int cut = ctrl_down() && alt_down();
568         panel->panel_prev_label(cut);
569         return 1;
570 }
571
572 //prev_edit
573 EditPrevEdit::EditPrevEdit(MWindow *mwindow,
574         EditPanel *panel, int x, int y)
575  : BC_Button(x, y, mwindow->theme->get_image_set("prevedit"))
576 {
577         this->mwindow = mwindow;
578         this->panel = panel;
579         set_tooltip(_("Previous edit (alt <- )"));
580 }
581 EditPrevEdit::~EditPrevEdit()
582 {
583 }
584 int EditPrevEdit::keypress_event()
585 {
586         if( alt_down() ) {
587                 int key = get_keypress();
588                 if( (key == LEFT || key == ',') && !ctrl_down() ) {
589                         panel->panel_prev_edit(0);
590                         return 1;
591                 }
592                 if( key == ',' && ctrl_down() ) {
593                         panel->panel_prev_edit(1);
594                         return 1;
595                 }
596         }
597         return 0;
598 }
599 int EditPrevEdit::handle_event()
600 {
601         int cut = ctrl_down() && alt_down();
602         panel->panel_prev_edit(cut);
603         return 1;
604 }
605
606 //next_edit
607 EditNextEdit::EditNextEdit(MWindow *mwindow,
608         EditPanel *panel, int x, int y)
609  : BC_Button(x, y, mwindow->theme->get_image_set("nextedit"))
610 {
611         this->mwindow = mwindow;
612         this->panel = panel;
613         set_tooltip(_("Next edit ( alt -> )"));
614 }
615 EditNextEdit::~EditNextEdit()
616 {
617 }
618 int EditNextEdit::keypress_event()
619 {
620         if( alt_down() ) {
621                 int key = get_keypress();
622                 if( (key == RIGHT || key == '.') && !ctrl_down() ) {
623                         panel->panel_next_edit(0);
624                         return 1;
625                 }
626                 if( key == '.' && ctrl_down() ) {
627                         panel->panel_next_edit(1);
628                         return 1;
629                 }
630         }
631         return 0;
632 }
633 int EditNextEdit::handle_event()
634 {
635         int cut = ctrl_down() && alt_down();
636         panel->panel_next_edit(cut);
637         return 1;
638 }
639
640 //copy_selection
641 EditCopy::EditCopy(MWindow *mwindow, EditPanel *panel, int x, int y)
642  : BC_Button(x, y, mwindow->theme->get_image_set("copy"))
643 {
644         this->mwindow = mwindow;
645         this->panel = panel;
646         set_tooltip(_("Copy ( c )"));
647 }
648 EditCopy::~EditCopy()
649 {
650 }
651
652 int EditCopy::keypress_event()
653 {
654         if( alt_down() ) return 0;
655         if( (get_keypress() == 'c' && !ctrl_down()) ||
656             (panel->is_vwindow() && get_keypress() == 'C') ) {
657                 return handle_event();
658         }
659         return 0;
660 }
661 int EditCopy::handle_event()
662 {
663         panel->panel_copy_selection();
664         return 1;
665 }
666
667 //overwrite_selection
668 EditOverwrite::EditOverwrite(MWindow *mwindow, EditPanel *panel, int x, int y)
669  : BC_Button(x, y, mwindow->theme->overwrite_data)
670 {
671         this->mwindow = mwindow;
672         this->panel = panel;
673         set_tooltip(_("Overwrite ( b )"));
674 }
675 EditOverwrite::~EditOverwrite()
676 {
677 }
678 int EditOverwrite::handle_event()
679 {
680         panel->panel_overwrite_selection();
681         return 1;
682 }
683 int EditOverwrite::keypress_event()
684 {
685         if( alt_down() ) return 0;
686         if( get_keypress() == 'b' ||
687             (panel->is_vwindow() && get_keypress() == 'B') ) {
688                 handle_event();
689                 return 1;
690         }
691         return 0;
692 }
693
694 //set_inpoint
695 //unset_inoutpoint
696 EditInPoint::EditInPoint(MWindow *mwindow, EditPanel *panel, int x, int y)
697  : BC_Button(x, y, mwindow->theme->get_image_set("inbutton"))
698 {
699         this->mwindow = mwindow;
700         this->panel = panel;
701         set_tooltip(_("In point ( [ or < )"));
702 }
703 EditInPoint::~EditInPoint()
704 {
705 }
706 int EditInPoint::handle_event()
707 {
708         panel->panel_set_inpoint();
709         return 1;
710 }
711 int EditInPoint::keypress_event()
712 {
713         int key = get_keypress();
714         if( ctrl_down() ) {
715                 if( key == 't' ) {
716                         panel->panel_unset_inoutpoint();
717                         return 1;
718                 }
719         }
720         else if( !alt_down() ) {
721                 if( key == '[' || key == '<' ) {
722                         panel->panel_set_inpoint();
723                         return 1;
724                 }
725         }
726         return 0;
727 }
728
729 //set_outpoint
730 //unset_inoutpoint
731 EditOutPoint::EditOutPoint(MWindow *mwindow, EditPanel *panel, int x, int y)
732  : BC_Button(x, y, mwindow->theme->get_image_set("outbutton"))
733 {
734         this->mwindow = mwindow;
735         this->panel = panel;
736         set_tooltip(_("Out point ( ] or > )"));
737 }
738 EditOutPoint::~EditOutPoint()
739 {
740 }
741 int EditOutPoint::handle_event()
742 {
743         panel->panel_set_outpoint();
744         return 1;
745 }
746 int EditOutPoint::keypress_event()
747 {
748         int key = get_keypress();
749         if( ctrl_down() ) {
750                 if(  key == 't' ) {
751                         panel->panel_unset_inoutpoint();
752                         return 1;
753                 }
754         }
755         else if( !alt_down() ) {
756                 if( key == ']' || key == '>' ) {
757                         panel->panel_set_outpoint();
758                         return 1;
759                 }
760         }
761         return 0;
762 }
763
764 //splice_selection
765 EditSplice::EditSplice(MWindow *mwindow, EditPanel *panel, int x, int y)
766  : BC_Button(x, y, mwindow->theme->splice_data)
767 {
768         this->mwindow = mwindow;
769         this->panel = panel;
770         set_tooltip(_("Splice ( v )"));
771 }
772 EditSplice::~EditSplice()
773 {
774 }
775 int EditSplice::handle_event()
776 {
777         panel->panel_splice_selection();
778         return 1;
779 }
780 int EditSplice::keypress_event()
781 {
782         if( alt_down() ) return 0;
783         if( (get_keypress() == 'v' && !ctrl_down()) ||
784             (panel->is_vwindow() && get_keypress() == 'V') ) {
785                 handle_event();
786                 return 1;
787         }
788         return 0;
789 }
790
791 //to_clip
792 EditToClip::EditToClip(MWindow *mwindow, EditPanel *panel, int x, int y)
793  : BC_Button(x, y, mwindow->theme->get_image_set("toclip"))
794 {
795         this->mwindow = mwindow;
796         this->panel = panel;
797         set_tooltip(_("To clip ( i )"));
798 }
799 EditToClip::~EditToClip()
800 {
801 }
802 int EditToClip::handle_event()
803 {
804         panel->panel_to_clip();
805         return 1;
806 }
807
808 int EditToClip::keypress_event()
809 {
810         if( alt_down() ) return 0;
811         if( get_keypress() == 'i' ||
812             (panel->is_vwindow() && get_keypress() == 'I') ) {
813                 handle_event();
814                 return 1;
815         }
816         return 0;
817 }
818
819 //cut
820 EditCut::EditCut(MWindow *mwindow, EditPanel *panel, int x, int y)
821  : BC_Button(x, y, mwindow->theme->get_image_set("cut"))
822 {
823         this->mwindow = mwindow;
824         this->panel = panel;
825         set_tooltip(_("Split | Cut ( x )"));
826 }
827 EditCut::~EditCut()
828 {
829 }
830 int EditCut::keypress_event()
831 {
832         if( ctrl_down() || shift_down() || alt_down() )
833                 return 0;
834         if( get_keypress() == 'x' )
835                 return handle_event();
836         return 0;
837 }
838
839 int EditCut::handle_event()
840 {
841         panel->panel_cut();
842         return 1;
843 }
844
845 //paste
846 EditPaste::EditPaste(MWindow *mwindow, EditPanel *panel, int x, int y)
847  : BC_Button(x, y, mwindow->theme->get_image_set("paste"))
848 {
849         this->mwindow = mwindow;
850         this->panel = panel;
851         set_tooltip(_("Paste ( v )"));
852 }
853 EditPaste::~EditPaste()
854 {
855 }
856
857 int EditPaste::keypress_event()
858 {
859         if( get_keypress() == 'v' && !ctrl_down() )
860                 return handle_event();
861         return 0;
862 }
863 int EditPaste::handle_event()
864 {
865         panel->panel_paste();
866         return 1;
867 }
868
869 //fit_selection
870 EditFit::EditFit(MWindow *mwindow, EditPanel *panel, int x, int y)
871  : BC_Button(x, y, mwindow->theme->get_image_set("fit"))
872 {
873         this->mwindow = mwindow;
874         this->panel = panel;
875         set_tooltip(_("Fit selection to display ( f )"));
876 }
877 EditFit::~EditFit()
878 {
879 }
880 int EditFit::keypress_event()
881 {
882         if( !alt_down() && get_keypress() == 'f' ) {
883                 handle_event();
884                 return 1;
885         }
886         return 0;
887 }
888 int EditFit::handle_event()
889 {
890         panel->panel_fit_selection();
891         return 1;
892 }
893
894 //fit_autos
895 EditFitAutos::EditFitAutos(MWindow *mwindow, EditPanel *panel, int x, int y)
896  : BC_Button(x, y, mwindow->theme->get_image_set("fitautos"))
897 {
898         this->mwindow = mwindow;
899         this->panel = panel;
900         set_tooltip(_("Fit all autos to display ( Alt + f )"));
901 }
902 EditFitAutos::~EditFitAutos()
903 {
904 }
905 int EditFitAutos::keypress_event()
906 {
907         if( get_keypress() == 'f' && alt_down() ) {
908                 panel->panel_fit_autos(!ctrl_down() ? 1 : 0);
909                 return 1;
910         }
911         return 0;
912 }
913 int EditFitAutos::handle_event()
914 {
915         panel->panel_fit_autos(1);
916         return 1;
917 }
918
919 //set_editing_mode
920 ArrowButton::ArrowButton(MWindow *mwindow, EditPanel *panel, int x, int y)
921  : BC_Toggle(x, y,
922         mwindow->theme->get_image_set("arrow"),
923         mwindow->edl->session->editing_mode == EDITING_ARROW,
924         "", 0, 0, 0)
925 {
926         this->mwindow = mwindow;
927         this->panel = panel;
928         set_tooltip(_("Drag and drop editing mode"));
929 }
930
931 int ArrowButton::handle_event()
932 {
933         update(1);
934         panel->ibeam->update(0);
935         panel->panel_set_editing_mode(EDITING_ARROW);
936 // Nothing after this
937         return 1;
938 }
939
940 IBeamButton::IBeamButton(MWindow *mwindow, EditPanel *panel, int x, int y)
941  : BC_Toggle(x, y,
942         mwindow->theme->get_image_set("ibeam"),
943         mwindow->edl->session->editing_mode == EDITING_IBEAM,
944         "", 0, 0, 0)
945 {
946         this->mwindow = mwindow;
947         this->panel = panel;
948         set_tooltip(_("Cut and paste editing mode"));
949 }
950
951 int IBeamButton::handle_event()
952 {
953         update(1);
954         panel->arrow->update(0);
955         panel->panel_set_editing_mode(EDITING_IBEAM);
956 // Nothing after this
957         return 1;
958 }
959
960 //set_auto_keyframes
961 KeyFrameButton::KeyFrameButton(MWindow *mwindow, EditPanel *panel, int x, int y)
962  : BC_Toggle(x, y,
963         mwindow->theme->get_image_set("autokeyframe"),
964         mwindow->edl->session->auto_keyframes,
965         "", 0, 0, 0)
966 {
967         this->mwindow = mwindow;
968         this->panel = panel;
969         set_tooltip(_("Generate keyframes while tweeking (j)"));
970 }
971
972 int KeyFrameButton::handle_event()
973 {
974         panel->panel_set_auto_keyframes(get_value());
975         return 1;
976 }
977
978 int KeyFrameButton::keypress_event()
979 {
980         int key = get_keypress();
981         if( key == 'j' && !ctrl_down() && !shift_down() && !alt_down() ) {
982                 int value = get_value() ? 0 : 1;
983                 update(value);
984                 panel->panel_set_auto_keyframes(value);
985                 return 1;
986         }
987         return 0;
988 }
989
990 //set_span_keyframes
991 SpanKeyFrameButton::SpanKeyFrameButton(MWindow *mwindow, EditPanel *panel, int x, int y)
992  : BC_Toggle(x, y,
993         mwindow->theme->get_image_set("spankeyframe"),
994         mwindow->edl->session->span_keyframes,
995         "", 0, 0, 0)
996 {
997         this->mwindow = mwindow;
998         this->panel = panel;
999         set_tooltip(_("Allow keyframe spanning"));
1000 }
1001
1002 int SpanKeyFrameButton::handle_event()
1003 {
1004         panel->panel_set_span_keyframes(get_value());
1005         return 1;
1006 }
1007
1008 //set_labels_follow_edits
1009 LockLabelsButton::LockLabelsButton(MWindow *mwindow, EditPanel *panel, int x, int y)
1010  : BC_Toggle(x, y,
1011         mwindow->theme->get_image_set("locklabels"),
1012         mwindow->edl->session->labels_follow_edits,
1013         "", 0, 0, 0)
1014 {
1015         this->mwindow = mwindow;
1016         this->panel = panel;
1017         set_tooltip(_("Lock labels from moving with edits"));
1018 }
1019
1020 int LockLabelsButton::handle_event()
1021 {
1022         panel->panel_set_labels_follow_edits(get_value());
1023         return 1;
1024 }
1025
1026
1027
1028 EditManualGoto::EditManualGoto(MWindow *mwindow, EditPanel *panel, int x, int y)
1029  : BC_Button(x, y, mwindow->theme->get_image_set("goto"))
1030 {
1031         this->mwindow = mwindow;
1032         this->panel = panel;
1033         mangoto = new ManualGoto(mwindow, panel);
1034         set_tooltip(_("Manual goto ( g )"));
1035 }
1036 EditManualGoto::~EditManualGoto()
1037 {
1038         delete mangoto;
1039 }
1040 int EditManualGoto::handle_event()
1041 {
1042         mangoto->start();
1043         return 1;
1044 }
1045
1046 int EditManualGoto::keypress_event()
1047 {
1048         if( get_keypress() == 'g' ) {
1049                 handle_event();
1050                 return 1;
1051         }
1052         return 0;
1053 }
1054
1055
1056 EditClick2Play::EditClick2Play(MWindow *mwindow, EditPanel *panel, int x, int y)
1057  : BC_Toggle(x, y, mwindow->theme->get_image_set("playpatch_data"),
1058     !panel->is_vwindow() ?
1059         mwindow->edl->session->cwindow_click2play :
1060         mwindow->edl->session->vwindow_click2play)
1061 {
1062         this->mwindow = mwindow;
1063         this->panel = panel;
1064         set_tooltip(_("Click to play (p)"));
1065 }
1066 int EditClick2Play::handle_event()
1067 {
1068         int value = get_value();
1069         panel->set_click_to_play(value);
1070         return 1;
1071 }
1072 int EditClick2Play::keypress_event()
1073 {
1074         int key = get_keypress();
1075         if( key == 'p' && !ctrl_down() && !shift_down() && !alt_down() ) {
1076                 int value = get_value() ? 0 : 1;
1077                 update(value);
1078                 panel->set_click_to_play(value);
1079                 return 1;
1080         }
1081         return 0;
1082 }
1083
1084
1085 EditCommercial::EditCommercial(MWindow *mwindow, EditPanel *panel, int x, int y)
1086  : BC_Button(x, y, mwindow->theme->get_image_set("commercial"))
1087 {
1088         this->mwindow = mwindow;
1089         this->panel = panel;
1090         set_tooltip(_("Commercial ( shift A )"));
1091 }
1092 EditCommercial::~EditCommercial()
1093 {
1094 }
1095 int EditCommercial::keypress_event()
1096 {
1097         if( ctrl_down() || !shift_down() || alt_down() )
1098                 return 0;
1099         if( get_keypress() == 'A' )
1100                 return handle_event();
1101         return 0;
1102 }
1103
1104 int EditCommercial::handle_event()
1105 {
1106         int have_mwindow_lock = mwindow->gui->get_window_lock();
1107         if( have_mwindow_lock )
1108                 mwindow->gui->unlock_window();
1109         mwindow->commit_commercial();
1110         if( !mwindow->put_commercial() ) {
1111                 mwindow->gui->lock_window("EditCommercial::handle_event 1");
1112                 mwindow->cut();
1113                 if( !have_mwindow_lock )
1114                         mwindow->gui->unlock_window();
1115                 mwindow->activate_commercial();
1116                 return 1;
1117         }
1118         mwindow->undo_commercial();
1119         if( have_mwindow_lock )
1120                 mwindow->gui->lock_window("EditCommercial::handle_event 2");
1121         return 1;
1122 }
1123
1124
1125 EditUndo::EditUndo(MWindow *mwindow, EditPanel *panel, int x, int y)
1126  : BC_Button(x, y, mwindow->theme->get_image_set("undo"))
1127 {
1128         this->mwindow = mwindow;
1129         this->panel = panel;
1130         set_tooltip(_("Undo ( z or Ctrl-z)"));
1131 }
1132 EditUndo::~EditUndo()
1133 {
1134 }
1135 int EditUndo::keypress_event()
1136 {
1137         if( ctrl_down() || shift_down() || alt_down() )
1138                 return 0;
1139         if( get_keypress() == 'z' )
1140                 return handle_event();
1141         return 0;
1142 }
1143 int EditUndo::handle_event()
1144 {
1145         mwindow->undo_entry(panel->subwindow);
1146         return 1;
1147 }
1148
1149 EditRedo::EditRedo(MWindow *mwindow, EditPanel *panel, int x, int y)
1150  : BC_Button(x, y, mwindow->theme->get_image_set("redo"))
1151 {
1152         this->mwindow = mwindow;
1153         this->panel = panel;
1154         set_tooltip(_("Redo ( shift Z )"));
1155 }
1156 EditRedo::~EditRedo()
1157 {
1158 }
1159 int EditRedo::keypress_event()
1160 {
1161         if( ctrl_down() || !shift_down() || alt_down() )
1162                 return 0;
1163         if( get_keypress() == 'Z' )
1164                 return handle_event();
1165         return 0;
1166 }
1167 int EditRedo::handle_event()
1168 {
1169         mwindow->redo_entry(panel->subwindow);
1170         return 1;
1171 }
1172
1173
1174 EditPanelScopeDialog::EditPanelScopeDialog(MWindow *mwindow, EditPanel *panel)
1175  : BC_DialogThread()
1176 {
1177         this->mwindow = mwindow;
1178         this->panel = panel;
1179         scope_gui = 0;
1180         gui_lock = new Mutex("EditPanelScopeDialog::gui_lock");
1181 }
1182
1183 EditPanelScopeDialog::~EditPanelScopeDialog()
1184 {
1185         close_window();
1186         delete gui_lock;
1187 }
1188
1189 void EditPanelScopeDialog::handle_close_event(int result)
1190 {
1191         scope_gui = 0;
1192 }
1193 void EditPanelScopeDialog::handle_done_event(int result)
1194 {
1195         gui_lock->lock("EditPanelScopeDialog::handle_done_event");
1196         scope_gui = 0;
1197         gui_lock->unlock();
1198
1199         panel->subwindow->lock_window("EditPanelScopeDialog::handle_done_event");
1200         panel->scope->update(0);
1201         panel->subwindow->unlock_window();
1202 }
1203
1204 BC_Window* EditPanelScopeDialog::new_gui()
1205 {
1206         EditPanelScopeGUI *gui = new EditPanelScopeGUI(mwindow, this);
1207         gui->create_objects();
1208         scope_gui = gui;
1209         return gui;
1210 }
1211
1212 void EditPanelScopeDialog::process(VFrame *output_frame)
1213 {
1214         if( panel->scope_dialog ) {
1215                 panel->scope_dialog->gui_lock->lock("EditPanelScopeDialog::process");
1216                 if( panel->scope_dialog->scope_gui ) {
1217                         EditPanelScopeGUI *gui = panel->scope_dialog->scope_gui;
1218                         gui->process(output_frame);
1219                 }
1220                 panel->scope_dialog->gui_lock->unlock();
1221         }
1222 }
1223
1224 EditPanelScopeGUI::EditPanelScopeGUI(MWindow *mwindow, EditPanelScopeDialog *dialog)
1225  : ScopeGUI(mwindow->theme,
1226         mwindow->session->scope_x, mwindow->session->scope_y,
1227         mwindow->session->scope_w, mwindow->session->scope_h,
1228         mwindow->get_cpus())
1229 {
1230         this->mwindow = mwindow;
1231         this->dialog = dialog;
1232 }
1233
1234 EditPanelScopeGUI::~EditPanelScopeGUI()
1235 {
1236 }
1237
1238 void EditPanelScopeGUI::create_objects()
1239 {
1240         MainSession *session = mwindow->session;
1241         use_hist = session->use_hist;
1242         use_wave = session->use_wave;
1243         use_vector = session->use_vector;
1244         use_hist_parade = session->use_hist_parade;
1245         use_wave_parade = session->use_wave_parade;
1246         use_wave_gain = session->use_wave_gain;
1247         use_vect_gain = session->use_vect_gain;
1248         use_smooth = session->use_smooth;
1249         use_refresh = session->use_refresh;
1250         use_release = session->use_release;
1251         use_graticule = session->use_graticule;
1252         ScopeGUI::create_objects();
1253 }
1254
1255 void EditPanelScopeGUI::toggle_event()
1256 {
1257         MainSession *session = mwindow->session;
1258         session->use_hist = use_hist;
1259         session->use_wave = use_wave;
1260         session->use_vector = use_vector;
1261         session->use_hist_parade = use_hist_parade;
1262         session->use_wave_parade = use_wave_parade;
1263         session->use_wave_gain = use_wave_gain;
1264         session->use_vect_gain = use_vect_gain;
1265         session->use_smooth = use_smooth;
1266         session->use_refresh = use_refresh;
1267         session->use_release = use_release;
1268         session->use_graticule = use_graticule;
1269 }
1270
1271 int EditPanelScopeGUI::translation_event()
1272 {
1273         ScopeGUI::translation_event();
1274         MainSession *session = mwindow->session;
1275         session->scope_x = get_x();
1276         session->scope_y = get_y();
1277         return 0;
1278 }
1279
1280 int EditPanelScopeGUI::resize_event(int w, int h)
1281 {
1282         ScopeGUI::resize_event(w, h);
1283         MainSession *session = mwindow->session;
1284         session->scope_w = w;
1285         session->scope_h = h;
1286         return 0;
1287 }
1288
1289 EditPanelScope::EditPanelScope(MWindow *mwindow, EditPanel *panel, int x, int y)
1290  : BC_Toggle(x, y, mwindow->theme ?
1291                 mwindow->theme->get_image_set("scope_toggle") : 0, 0)
1292 {
1293         this->mwindow = mwindow;
1294         this->panel = panel;
1295         set_tooltip(_("View scope"));
1296 }
1297
1298 EditPanelScope::~EditPanelScope()
1299 {
1300 }
1301
1302 void EditPanelScopeGUI::update_scope()
1303 {
1304         Canvas *canvas = 0;
1305         if( dialog->panel->is_cwindow() ) {
1306                 CWindowGUI *cgui = (CWindowGUI *)dialog->panel->subwindow;
1307                 canvas = cgui->canvas;
1308         }
1309         else if( dialog->panel->is_vwindow() ) {
1310                 VWindowGUI *vgui = (VWindowGUI *)dialog->panel->subwindow;
1311                 canvas = vgui->canvas;
1312         }
1313         if( canvas && canvas->refresh_frame )
1314                 process(canvas->refresh_frame);
1315 }
1316
1317 int EditPanelScope::handle_event()
1318 {
1319         unlock_window();
1320         int v = get_value();
1321         if( v )
1322                 panel->scope_dialog->start();
1323         else
1324                 panel->scope_dialog->close_window();
1325         lock_window("EditPanelScope::handle_event");
1326         return 1;
1327 }
1328
1329 const char *EditPanelGangTracks::gang_tips[TOTAL_GANGS] = {
1330         N_("Currently: Gang None\n  Click to: Gang Channels"),
1331         N_("Currently: Gang Channels\n  Click to: Gang Media"),
1332         N_("Currently: Gang Media\n  Click to: Gang None"),
1333 };
1334
1335 EditPanelGangTracks::EditPanelGangTracks(MWindow *mwindow, EditPanel *panel,
1336                 int x, int y)
1337  : BC_Button(x, y, get_images(mwindow))
1338 {
1339         this->mwindow = mwindow;
1340         this->panel = panel;
1341         int gang = mwindow->edl->session->gang_tracks;
1342         set_tooltip(_(gang_tips[gang]));
1343 }
1344
1345 EditPanelGangTracks::~EditPanelGangTracks()
1346 {
1347 }
1348
1349 VFrame **EditPanelGangTracks::gang_images[TOTAL_GANGS];
1350
1351 VFrame **EditPanelGangTracks::get_images(MWindow *mwindow)
1352 {
1353         gang_images[GANG_NONE] = mwindow->theme->get_image_set("gang0");
1354         gang_images[GANG_MEDIA] = mwindow->theme->get_image_set("gang1");
1355         gang_images[GANG_CHANNELS] = mwindow->theme->get_image_set("gang2");
1356         int gang = mwindow->edl->session->gang_tracks;
1357         return gang_images[gang];
1358 }
1359
1360 void EditPanelGangTracks::update(int gang)
1361 {
1362         set_images(gang_images[gang]);
1363         draw_face();
1364         set_tooltip(_(gang_tips[gang]));
1365 }
1366
1367 int EditPanelGangTracks::handle_event()
1368 {
1369         int gang = mwindow->edl->session->gang_tracks;
1370         if( !shift_down() ) {
1371                 if( ++gang > GANG_MEDIA ) gang = GANG_NONE;
1372         }
1373         else {
1374                 if( --gang < GANG_NONE ) gang = GANG_MEDIA;
1375         }
1376         update(gang);
1377         panel->panel_set_gang_tracks(gang);
1378         return 1;
1379 }
1380
1381
1382 EditPanelTimecode::EditPanelTimecode(MWindow *mwindow,
1383         EditPanel *panel, int x, int y)
1384  : BC_Button(x, y, mwindow->theme->get_image_set("clapperbutton"))
1385 {
1386         this->mwindow = mwindow;
1387         this->panel = panel;
1388         tc_dialog = 0;
1389         set_tooltip(_("Set Timecode"));
1390 }
1391
1392 EditPanelTimecode::~EditPanelTimecode()
1393 {
1394         delete tc_dialog;
1395 }
1396
1397 int EditPanelTimecode::handle_event()
1398 {
1399         if( !tc_dialog )
1400                 tc_dialog = new EditPanelTcDialog(mwindow, panel);
1401         int px, py;
1402         get_pop_cursor(px, py, 0);
1403         tc_dialog->start_dialog(px, py);
1404         return 1;
1405 }
1406
1407 EditPanelTcDialog::EditPanelTcDialog(MWindow *mwindow, EditPanel *panel)
1408  : BC_DialogThread()
1409 {
1410         this->mwindow = mwindow;
1411         this->panel = panel;
1412         tc_gui = 0;
1413         px = py = 0;
1414 }
1415
1416 EditPanelTcDialog::~EditPanelTcDialog()
1417 {
1418         close_window();
1419 }
1420
1421 #define TCW_W xS(200)
1422 #define TCW_H yS(120)
1423
1424 void EditPanelTcDialog::start_dialog(int px, int py)
1425 {
1426         this->px = px - TCW_W/2;
1427         this->py = py - TCW_H/2;
1428         start();
1429 }
1430
1431 BC_Window *EditPanelTcDialog::new_gui()
1432 {
1433         tc_gui = new EditPanelTcWindow(this, px, py);
1434         tc_gui->create_objects();
1435         double timecode = mwindow->get_timecode_offset();
1436         tc_gui->update(timecode);
1437         tc_gui->show_window();
1438         return tc_gui;
1439 }
1440
1441 void EditPanelTcDialog::handle_done_event(int result)
1442 {
1443         if( result ) return;
1444         double ofs = tc_gui->get_timecode();
1445         mwindow->set_timecode_offset(ofs);
1446 }
1447
1448 EditPanelTcWindow::EditPanelTcWindow(EditPanelTcDialog *tc_dialog, int x, int y)
1449  : BC_Window(_(PROGRAM_NAME ": Timecode"), x, y,
1450         TCW_W, TCW_H, TCW_W, TCW_H, 0, 0, 1)
1451 {
1452         this->tc_dialog = tc_dialog;
1453 }
1454
1455 EditPanelTcWindow::~EditPanelTcWindow()
1456 {
1457 }
1458
1459 double EditPanelTcWindow::get_timecode()
1460 {
1461         int hrs = atoi(hours->get_text());
1462         int mins = atoi(minutes->get_text());
1463         int secs = atoi(seconds->get_text());
1464         int frms = atoi(frames->get_text());
1465         double frame_rate = tc_dialog->mwindow->edl->session->frame_rate;
1466         double timecode = hrs*3600 + mins*60 + secs + frms/frame_rate;
1467         return timecode;
1468 }
1469
1470 void EditPanelTcWindow::update(double timecode)
1471 {
1472         if( timecode < 0 ) timecode = 0;
1473         int64_t pos = timecode;
1474         int hrs = pos/3600;
1475         int mins = pos/60 - hrs*60;
1476         int secs = pos - hrs*3600 - mins*60;
1477         double frame_rate = tc_dialog->mwindow->edl->session->frame_rate;
1478         int frms = (timecode-pos) * frame_rate;
1479         hours->update(hrs);
1480         minutes->update(mins);
1481         seconds->update(secs);
1482         frames->update(frms);
1483 }
1484
1485 void EditPanelTcWindow::create_objects()
1486 {
1487         lock_window("EditPanelTcWindow::create_objects");
1488         int x = xS(20), y = yS(5);
1489         BC_Title *title = new BC_Title(x - 2, y, _("hour  min   sec   frms"), SMALLFONT);
1490         add_subwindow(title);  y += title->get_h() + xS(3);
1491         hours = new EditPanelTcInt(this, x, y, xS(26), 99, "%02i");
1492         add_subwindow(hours);    x += hours->get_w() + xS(4);
1493         minutes = new EditPanelTcInt(this, x, y, xS(26), 59, "%02i");
1494         add_subwindow(minutes);  x += minutes->get_w() + xS(4);
1495         seconds = new EditPanelTcInt(this, x, y, xS(26), 60, "%02i");
1496         add_subwindow(seconds);  x += seconds->get_w() + xS(4);
1497         frames = new EditPanelTcInt(this, x, y, xS(34), 999, "%03i");
1498         add_subwindow(frames);   x += frames->get_w() + xS(16);
1499         add_subwindow(new EditPanelTcReset(this, x, y));
1500         double timecode = tc_dialog->mwindow->get_timecode_offset();
1501         update(timecode);
1502         add_subwindow(new BC_OKButton(this));
1503         add_subwindow(new BC_CancelButton(this));
1504         unlock_window();
1505 }
1506
1507 EditPanelTcReset::EditPanelTcReset(EditPanelTcWindow *window, int x, int y)
1508  : BC_Button(x, y, window->tc_dialog->mwindow->theme->get_image_set("reset_button"))
1509 {
1510         this->window = window;
1511 }
1512
1513 int EditPanelTcReset::handle_event()
1514 {
1515         window->update(0);
1516         return 1;
1517 }
1518
1519
1520 EditPanelTcInt::EditPanelTcInt(EditPanelTcWindow *window, int x, int y, int w,
1521         int max, const char *format)
1522  : BC_TextBox(x, y, w, 1, "")
1523 {
1524         this->window = window;
1525         this->max = max;
1526         this->format = format;
1527         digits = 1;
1528         for( int m=max; (m/=10)>0; ++digits );
1529 }
1530
1531 EditPanelTcInt::~EditPanelTcInt()
1532 {
1533 }
1534
1535 int EditPanelTcInt::handle_event()
1536 {
1537         int v = atoi(get_text());
1538         if( v > max ) {
1539                 v = v % (max+1);
1540                 char string[BCSTRLEN];
1541                 sprintf(string, format, v);
1542                 BC_TextBox::update(string);
1543         }
1544         return 1;
1545 }
1546
1547 void EditPanelTcInt::update(int v)
1548 {
1549         char text[BCTEXTLEN];
1550         if( v > max ) v = max;
1551         sprintf(text, format, v);
1552         BC_TextBox::update(text);
1553 }
1554
1555 int EditPanelTcInt::keypress_event()
1556 {
1557         if( (int)strlen(get_text()) >= digits )
1558                 BC_TextBox::update("");
1559         int key = get_keypress();
1560         switch( key ) {
1561         case TAB:   case LEFTTAB:
1562         case LEFT:  case RIGHT:
1563         case HOME:  case END:
1564         case BACKSPACE:
1565         case DELETE:
1566         case '0': case '1': case '2': case '3': case '4':
1567         case '5': case '6': case '7': case '8': case '9':
1568                 return BC_TextBox::keypress_event();
1569         }
1570         return 1;
1571 }
1572