18 new shapewipe transitions from rafa, rework savefile/confirm for nested edl edits
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / timebar.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "awindow.h"
23 #include "awindowgui.h"
24 #include "bcsignals.h"
25 #include "clip.h"
26 #include "cplayback.h"
27 #include "cursors.h"
28 #include "cwindow.h"
29 #include "cwindowgui.h"
30 #include "edl.h"
31 #include "edlsession.h"
32 #include "filexml.h"
33 #include "fonts.h"
34 #include "labels.h"
35 #include "labeledit.h"
36 #include "localsession.h"
37 #include "maincursor.h"
38 #include "mainundo.h"
39 #include "mbuttons.h"
40 #include "mwindow.h"
41 #include "mwindowgui.h"
42 #include "patchbay.h"
43 #include "preferences.h"
44 #include "recordlabel.h"
45 #include "localsession.h"
46 #include "mainsession.h"
47 #include "theme.h"
48 #include "timebar.h"
49 #include "timelinepane.h"
50 #include "trackcanvas.h"
51 #include "tracks.h"
52 #include "transportque.h"
53 #include "units.h"
54 #include "vframe.h"
55 #include "vwindow.h"
56 #include "vwindowgui.h"
57 #include "zoombar.h"
58
59
60 LabelGUI::LabelGUI(MWindow *mwindow, TimeBar *timebar,
61         int64_t pixel, int y,
62         double position, VFrame **data)
63  : BC_Toggle(translate_pixel(mwindow, pixel), y,
64                 data ? data : mwindow->theme->label_toggle, 0)
65 {
66         this->mwindow = mwindow;
67         this->timebar = timebar;
68         this->gui = 0;
69         this->pixel = pixel;
70         this->position = position;
71         this->label = 0;
72 }
73
74 LabelGUI::~LabelGUI()
75 {
76         if( timebar->drag_label == this )
77                 timebar->drag_label = 0;
78 }
79
80 int LabelGUI::get_y(MWindow *mwindow, TimeBar *timebar)
81 {
82         return timebar->get_h() -
83                 mwindow->theme->label_toggle[0]->get_h();
84 }
85
86 int LabelGUI::translate_pixel(MWindow *mwindow, int pixel)
87 {
88         int result = pixel - mwindow->theme->label_toggle[0]->get_w() / 2;
89         return result;
90 }
91
92 void LabelGUI::reposition(int flush)
93 {
94         reposition_window(translate_pixel(mwindow, pixel),
95                 BC_Toggle::get_y());
96 }
97
98 int LabelGUI::button_press_event()
99 {
100         int result = test_drag_label(1);
101
102         if( this->is_event_win() && get_buttonpress() == 3 ) {
103                 if( label ) {
104                         int cur_x, cur_y;
105                         get_abs_cursor(cur_x, cur_y, 0);
106                         timebar->label_edit->start(label, cur_x, cur_y);
107                 }
108                 result = 1;
109         } else {
110                 result = BC_Toggle::button_press_event();
111         }
112         if( label )
113                 set_tooltip(this->label->textstr);
114         return result;
115 }
116
117 int LabelGUI::button_release_event()
118 {
119         int ret = BC_Toggle::button_release_event();
120         test_drag_label(0);
121         return ret;
122 }
123
124 int LabelGUI::test_drag_label(int press)
125 {
126         if( is_event_win() && get_buttonpress() == 1 ) {
127                 switch( timebar->current_operation ) {
128                 case TIMEBAR_NONE:
129                         if( press && get_value() ) {
130                                 timebar->current_operation = TIMEBAR_DRAG_LABEL;
131                                 timebar->drag_label = this;
132                                 set_cursor(HSEPARATE_CURSOR, 0, 0);
133                                 mwindow->undo->update_undo_before(_("drag label"), this);
134                                 return 1;
135                         }
136                         break;
137                 case TIMEBAR_DRAG_LABEL:
138                         if( !press ) {
139                                 timebar->current_operation = TIMEBAR_NONE;
140                                 timebar->drag_label = 0;
141                                 set_cursor(ARROW_CURSOR, 0, 0);
142                                 mwindow->undo->update_undo_after(_("drag label"), LOAD_TIMEBAR);
143                                 mwindow->awindow->gui->async_update_assets(); // labels folder
144                         }
145                         break;
146                 }
147         }
148         return 0;
149 }
150
151 int LabelGUI::handle_event()
152 {
153         timebar->select_label(position);
154         return 1;
155 }
156
157 void LabelGUI::update_value()
158 {
159         EDL *edl = timebar->get_edl();
160         double start = edl->local_session->get_selectionstart(1);
161         double end = edl->local_session->get_selectionend(1);
162         int v = ( label->position >= start && end >= label->position ) ||
163             edl->equivalent(label->position, start) ||
164             edl->equivalent(label->position, end) ||
165             timebar->drag_label == this ? 1 : 0;
166         update(v);
167 }
168
169
170 InPointGUI::InPointGUI(MWindow *mwindow, TimeBar *timebar,
171         int64_t pixel, double position)
172  : LabelGUI(mwindow, timebar,
173         pixel, get_y(mwindow, timebar),
174         position, mwindow->theme->in_point)
175 {
176 //printf("InPointGUI::InPointGUI %d %d\n", pixel, get_y(mwindow, timebar));
177 }
178 InPointGUI::~InPointGUI()
179 {
180 }
181 int InPointGUI::get_y(MWindow *mwindow, TimeBar *timebar)
182 {
183         int result;
184         result = timebar->get_h() -
185                 mwindow->theme->in_point[0]->get_h();
186         return result;
187 }
188
189
190 OutPointGUI::OutPointGUI(MWindow *mwindow, TimeBar *timebar,
191         int64_t pixel, double position)
192  : LabelGUI(mwindow, timebar,
193         pixel, get_y(mwindow, timebar),
194         position, mwindow->theme->out_point)
195 {
196 //printf("OutPointGUI::OutPointGUI %d %d\n", pixel, get_y(mwindow, timebar));
197 }
198 OutPointGUI::~OutPointGUI()
199 {
200 }
201 int OutPointGUI::get_y(MWindow *mwindow, TimeBar *timebar)
202 {
203         return timebar->get_h() -
204                 mwindow->theme->out_point[0]->get_h();
205 }
206
207
208 PresentationGUI::PresentationGUI(MWindow *mwindow, TimeBar *timebar,
209         int64_t pixel, double position)
210  : LabelGUI(mwindow, timebar, pixel, get_y(mwindow, timebar), position)
211 {
212 }
213 PresentationGUI::~PresentationGUI()
214 {
215 }
216
217 TimeBar::TimeBar(MWindow *mwindow, BC_WindowBase *gui,
218         int x, int y, int w, int h)
219  : BC_SubWindow(x, y, w, h)
220 {
221 //printf("TimeBar::TimeBar %d %d %d %d\n", x, y, w, h);
222         this->gui = gui;
223         this->mwindow = mwindow;
224         this->drag_label = 0;
225         label_edit = new LabelEdit(mwindow, mwindow->awindow, 0);
226         pane = 0;
227         highlighted = 0;
228 }
229
230 TimeBar::~TimeBar()
231 {
232         delete in_point;
233         delete out_point;
234         delete label_edit;
235         labels.remove_all_objects();
236         presentations.remove_all_objects();
237 }
238
239 void TimeBar::create_objects()
240 {
241         in_point = 0;
242         out_point = 0;
243 //printf("TimeBar::create_objects %d\n", __LINE__);
244         current_operation = TIMEBAR_NONE;
245         set_cursor(UPRIGHT_ARROW_CURSOR, 0, 0);
246         update(0);
247 }
248
249
250 int64_t TimeBar::position_to_pixel(double position)
251 {
252         get_edl_length();
253         return (int64_t)(position / time_per_pixel);
254 }
255
256
257 double TimeBar::pixel_to_position(int pixel)
258 {
259         if( pane ) {
260                 pixel += get_edl()->local_session->view_start[pane->number];
261         }
262
263         return (double)pixel *
264                 get_edl()->local_session->zoom_sample /
265                 get_edl()->session->sample_rate;
266 }
267
268 void TimeBar::update_labels()
269 {
270         int output = 0;
271         EDL *edl = get_edl();
272
273         if( edl ) {
274                 for( Label *current=edl->labels->first; current; current=NEXT ) {
275                         int64_t pixel = position_to_pixel(current->position);
276                         if( pixel >= 0 && pixel < get_w()  ) {
277 // Create new label
278                                 if( output >= labels.total ) {
279                                         LabelGUI *new_label;
280                                         add_subwindow(new_label = new LabelGUI(mwindow, this,
281                                                         pixel, LabelGUI::get_y(mwindow, this),
282                                                         current->position));
283                                         new_label->set_cursor(INHERIT_CURSOR, 0, 0);
284                                         new_label->set_tooltip(current->textstr);
285                                         new_label->label = current;
286                                         labels.append(new_label);
287                                 }
288 // Reposition old label
289                                 else {
290                                         LabelGUI *gui = labels.values[output];
291                                         if( gui->pixel != pixel ) {
292                                                 gui->pixel = pixel;
293                                                 gui->reposition(0);
294                                         }
295 //                                      else {
296 //                                              gui->draw_face(1,0);
297 //                                      }
298
299                                         labels.values[output]->position = current->position;
300                                         labels.values[output]->set_tooltip(current->textstr);
301                                         labels.values[output]->label = current;
302                                 }
303
304                                 labels.values[output++]->update_value();
305                         }
306                 }
307         }
308
309 // Delete excess labels
310         while(labels.total > output)
311         {
312                 labels.remove_object();
313         }
314
315 // Get the labels to show
316         show_window(0);
317 }
318
319 void TimeBar::update_highlights()
320 {
321         EDL *edl = get_edl();
322         if( !edl ) return;
323         for( int i = 0; i < labels.total; i++ ) {
324                 labels.values[i]->update_value();
325         }
326
327         if( edl->equivalent(edl->local_session->get_inpoint(),
328                         edl->local_session->get_selectionstart(1)) ||
329                 edl->equivalent(edl->local_session->get_inpoint(),
330                         edl->local_session->get_selectionend(1)) ) {
331                 if( in_point ) in_point->update(1);
332         }
333         else
334                 if( in_point ) in_point->update(0);
335
336         if( edl->equivalent(edl->local_session->get_outpoint(),
337                         edl->local_session->get_selectionstart(1)) ||
338                 edl->equivalent(edl->local_session->get_outpoint(),
339                         edl->local_session->get_selectionend(1)) ) {
340                 if( out_point ) out_point->update(1);
341         }
342         else
343                 if( out_point ) out_point->update(0);
344
345         draw_inout_highlight();
346 }
347
348 void TimeBar::draw_inout_highlight()
349 {
350         EDL *edl = get_edl();
351         if( !edl->local_session->inpoint_valid() ) return;
352         if( !edl->local_session->outpoint_valid() ) return;
353         double in_position = edl->local_session->get_inpoint();
354         double out_position = edl->local_session->get_outpoint();
355         if( in_position >= out_position ) return;
356         int in_x = position_to_pixel(in_position);
357         int out_x = position_to_pixel(out_position);
358         CLAMP(in_x, 0, get_w());
359         CLAMP(out_x, 0, get_w());
360         set_color(mwindow->theme->inout_highlight_color);
361         int lw = xS(5);
362         set_line_width(lw);
363         set_inverse();
364         draw_line(in_x, get_h()-2*lw, out_x, get_h()-2*lw);
365         set_opaque();
366         set_line_width(1);
367 }
368
369 void TimeBar::update_points()
370 {
371         EDL *edl = get_edl();
372         int64_t pixel = !edl ? 0 :
373                 position_to_pixel(edl->local_session->get_inpoint());
374
375         if( in_point ) {
376                 if( edl && edl->local_session->inpoint_valid() &&
377                     pixel >= 0 && pixel < get_w() ) {
378                         if( !EQUIV(edl->local_session->get_inpoint(), in_point->position) ||
379                             in_point->pixel != pixel ) {
380                                 in_point->pixel = pixel;
381                                 in_point->position = edl->local_session->get_inpoint();
382                                 in_point->reposition(0);
383                         }
384                         else {
385                                 in_point->draw_face(1, 0);
386                         }
387                 }
388                 else {
389                         delete in_point;
390                         in_point = 0;
391                 }
392         }
393         else
394         if( edl && edl->local_session->inpoint_valid() &&
395             pixel >= 0 && pixel < get_w() ) {
396                 add_subwindow(in_point = new InPointGUI(mwindow,
397                         this, pixel, edl->local_session->get_inpoint()));
398                 in_point->set_cursor(ARROW_CURSOR, 0, 0);
399         }
400
401         pixel = !edl ? 0 :
402                  position_to_pixel(edl->local_session->get_outpoint());
403
404         if( out_point ) {
405                 if( edl && edl->local_session->outpoint_valid() &&
406                     pixel >= 0 && pixel < get_w()) {
407                         if( !EQUIV(edl->local_session->get_outpoint(), out_point->position) ||
408                             out_point->pixel != pixel ) {
409                                 out_point->pixel = pixel;
410                                 out_point->position = edl->local_session->get_outpoint();
411                                 out_point->reposition(0);
412                         }
413                         else {
414                                 out_point->draw_face(1, 0);
415                         }
416                 }
417                 else {
418                         delete out_point;
419                         out_point = 0;
420                 }
421         }
422         else
423         if( edl && edl->local_session->outpoint_valid() &&
424             pixel >= 0 && pixel < get_w() ) {
425                 add_subwindow(out_point = new OutPointGUI(mwindow,
426                         this, pixel, edl->local_session->get_outpoint()));
427                 out_point->set_cursor(ARROW_CURSOR, 0, 0);
428         }
429
430 //      flush();
431 }
432
433 void TimeBar::update_clock(double position)
434 {
435 }
436
437 void TimeBar::update(int flush)
438 {
439         draw_time();
440 // Need to redo these when range is drawn to get the background updated.
441         update_labels();
442         update_points();
443
444
445         EDL *edl = get_edl();
446         int64_t pixel = -1;
447         int x = get_relative_cursor_x();
448 // Draw highlight position
449         if( edl && (highlighted || current_operation == TIMEBAR_DRAG) &&
450             x >= 0 && x < get_w() ) {
451 //printf("TimeBar::update %d %d\n", __LINE__, x);
452                 double position = pixel_to_position(x);
453
454                 position = mwindow->edl->align_to_frame(position, 0);
455                 pixel = position_to_pixel(position);
456                 update_clock(position);
457         }
458
459         if( pixel < 0 ) {
460                 double position = test_highlight();
461                 if( position >= 0 ) pixel = position_to_pixel(position);
462         }
463
464
465         if( pixel >= 0 && pixel < get_w() ) {
466                 set_color(mwindow->theme->timebar_cursor_color);
467                 set_line_dashes(1);
468 //printf("TimeBar::update %d pane=%d pixel=%jd\n", __LINE__, pane->number, pixel);
469                 draw_line(pixel, 0, pixel, get_h());
470                 set_line_dashes(0);
471         }
472
473
474         if( edl ) {
475                 double playback_start = edl->local_session->playback_start;
476                 if( playback_start >= 0 ) {
477                         int64_t pixel = position_to_pixel(playback_start);
478                         set_color(mwindow->theme->timebar_cursor_color ^ 0x0000ff);
479                         draw_line(pixel, 0, pixel, get_h());
480                         double playback_end = edl->local_session->playback_end;
481                         if( playback_end > playback_start ) {
482                                 pixel = position_to_pixel(playback_end);
483                                 set_color(mwindow->theme->timebar_cursor_color ^ 0x00ff00);
484                                 draw_line(pixel, 0, pixel, get_h());
485                         }
486                 }
487
488                 double position = edl->local_session->get_selectionstart(1);
489                 int64_t pixel = position_to_pixel(position);
490 // Draw insertion point position.
491                 int color = mwindow->theme->timebar_cursor_color;
492                 if( mwindow->preferences->forward_render_displacement )
493                         color ^= 0x00ffff;
494                 set_color(color);
495                 draw_line(pixel, 0, pixel, get_h());
496         }
497
498         update_highlights();
499
500 // Get the labels to show
501         show_window(0);
502         flash(flush);
503 //printf("TimeBar::update %d this=%p %d\n", __LINE__, this, current_operation);
504 }
505
506
507
508 int TimeBar::delete_project()
509 {
510 //      labels->delete_all();
511         return 0;
512 }
513
514 int TimeBar::save(FileXML *xml)
515 {
516 //      labels->save(xml);
517         return 0;
518 }
519
520
521
522
523 void TimeBar::draw_time()
524 {
525 }
526
527 EDL* TimeBar::get_edl()
528 {
529         return mwindow->edl;
530 }
531
532
533
534 void TimeBar::draw_range()
535 {
536 //printf("TimeBar::draw_range %d %p\n", __LINE__, get_edl());
537         if( has_preview() && get_edl() ) {
538                 int x1, x2;
539                 get_preview_pixels(x1, x2);
540                 draw_3segmenth(0, 0, x1, mwindow->theme->timebar_view_data);
541                 draw_top_background(get_parent(), x1, 0, x2 - x1, get_h());
542                 draw_3segmenth(x2, 0, get_w() - x2, mwindow->theme->timebar_view_data);
543
544                 set_color(BLACK);
545                 draw_line(x1, 0, x1, get_h());
546                 draw_line(x2, 0, x2, get_h());
547
548
549                 EDL *edl = get_edl();
550                 if( edl ) {
551                         int64_t pixel = position_to_pixel(
552                                 edl->local_session->get_selectionstart(1));
553 // Draw insertion point position if this timebar belongs to a window which
554 // has something other than the master EDL.
555                         set_color(mwindow->theme->timebar_cursor_color);
556                         draw_line(pixel, 0, pixel, get_h());
557                 }
558         }
559         else
560                 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
561 }
562
563 void TimeBar::select_label(double position)
564 {
565 }
566
567
568
569 int TimeBar::draw()
570 {
571         return 0;
572 }
573
574 double TimeBar::get_edl_length()
575 {
576         edl_length = get_edl() ? get_edl()->tracks->total_length() : 0;
577         int w1 = get_w()-1;
578         time_per_pixel = !EQUIV(edl_length, 0) ? edl_length/w1 : w1;
579         return edl_length;
580 }
581
582 int TimeBar::get_preview_pixels(int &x1, int &x2)
583 {
584         x1 = 0;  x2 = get_w();
585         get_edl_length();
586         EDL *edl = get_edl();
587         if( edl && !EQUIV(edl_length, 0) ) {
588                 double preview_start = edl->local_session->preview_start;
589                 double preview_end = edl->local_session->preview_end;
590                 if( preview_end < 0 || preview_end > edl_length )
591                         preview_end = edl_length;
592                 if( preview_end >= preview_start ) {
593                         x1 = (int)(preview_start / time_per_pixel);
594                         x2 = (int)(preview_end / time_per_pixel);
595                 }
596         }
597         return 0;
598 }
599
600
601 int TimeBar::test_preview(int buttonpress)
602 {
603         int result = 0;
604
605
606         if( get_edl() && cursor_inside() && buttonpress >= 0 ) {
607                 int x1, x2, x = get_relative_cursor_x();
608                 get_preview_pixels(x1, x2);
609 //printf("TimeBar::test_preview %d %d %d\n", x1, x2, x);
610 // Inside left handle
611                 if( x >= x1 - HANDLE_W && x < x1 + HANDLE_W &&
612 // Ignore left handle if both handles are up against the left side
613                     x2 > HANDLE_W ) {
614                         if( buttonpress ) {
615                                 current_operation = TIMEBAR_DRAG_LEFT;
616                                 start_position = get_edl()->local_session->preview_start;
617                                 start_cursor_x = x;
618                         }
619                         else if( get_cursor() != LEFT_CURSOR )
620                                 set_cursor(LEFT_CURSOR, 0, 1);
621                         result = 1;
622                 }
623 // Inside right handle
624                 else if( x >= x2 - HANDLE_W && x < x2 + HANDLE_W &&
625 // Ignore right handle if both handles are up against the right side
626                     x1 < get_w() - HANDLE_W ) {
627                         if( buttonpress ) {
628                                 current_operation = TIMEBAR_DRAG_RIGHT;
629                                 start_position = get_edl()->local_session->preview_end;
630                                 if( start_position < 0 || start_position > edl_length )
631                                         start_position = edl_length;
632                                 start_cursor_x = x;
633                         }
634                         else if( get_cursor() != RIGHT_CURSOR )
635                                 set_cursor(RIGHT_CURSOR, 0, 1);
636                         result = 1;
637                 }
638 // Inside preview
639                 else if( get_button_down() && get_buttonpress() == 3 &&
640                     x >= x1 && x < x2 ) {
641                         if( buttonpress ) {
642                                 current_operation = TIMEBAR_DRAG_CENTER;
643                                 starting_start_position = get_edl()->local_session->preview_start;
644                                 starting_end_position = get_edl()->local_session->preview_end;
645                                 if( starting_end_position < 0 || starting_end_position > edl_length )
646                                         starting_end_position = edl_length;
647                                 start_cursor_x = x;
648                         }
649                         if( get_cursor() != HSEPARATE_CURSOR )
650                                 set_cursor(HSEPARATE_CURSOR, 0, 1);
651                         result = 1;
652                 }
653         }
654
655         if( !result && get_cursor() != ARROW_CURSOR )
656                 set_cursor(ARROW_CURSOR, 0, 1);
657
658
659         return result;
660 }
661
662 int TimeBar::move_preview(int &redraw)
663 {
664         int result = 0, x = get_relative_cursor_x();
665         switch( current_operation ) {
666         case TIMEBAR_DRAG_LEFT: {
667                 get_edl()->local_session->preview_start =
668                         start_position + time_per_pixel * (x - start_cursor_x);
669                 double preview_end = get_edl()->local_session->preview_end;
670                 if( preview_end < 0 || preview_end > edl_length )
671                         preview_end = get_edl()->local_session->preview_end = edl_length;
672                 CLAMP(get_edl()->local_session->preview_start, 0, preview_end);
673                 result = 1;
674                 break; }
675         case TIMEBAR_DRAG_RIGHT: {
676                 double preview_end = get_edl()->local_session->preview_end =
677                         start_position + time_per_pixel * (x - start_cursor_x);
678                 double preview_start = get_edl()->local_session->preview_start;
679                 if( preview_end >= edl_length && !preview_start ) {
680                         get_edl()->local_session->preview_end = -1;
681                         if( preview_start > preview_end )
682                                 preview_start = get_edl()->local_session->preview_start = preview_end;
683                 }
684                 else
685                         CLAMP(get_edl()->local_session->preview_end, preview_start, edl_length);
686                 result = 1;
687                 break; }
688         case TIMEBAR_DRAG_CENTER: {
689                 double dt = time_per_pixel * (x - start_cursor_x);
690                 get_edl()->local_session->preview_start = starting_start_position + dt;
691                 get_edl()->local_session->preview_end = starting_end_position + dt;
692                 if( get_edl()->local_session->preview_start < 0 ) {
693                         get_edl()->local_session->preview_end -= get_edl()->local_session->preview_start;
694                         get_edl()->local_session->preview_start = 0;
695                 }
696                 else
697                 if( get_edl()->local_session->preview_end > edl_length ) {
698                         get_edl()->local_session->preview_start -= get_edl()->local_session->preview_end - edl_length;
699                         get_edl()->local_session->preview_end = edl_length;
700                 }
701                 result = 1;
702                 break; }
703         }
704
705 //printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation);
706
707         if( result ) {
708                 update_preview();
709                 redraw = 1;
710         }
711 //printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation);
712
713         return result;
714 }
715
716 void TimeBar::update_preview()
717 {
718 }
719
720 int TimeBar::samplemovement()
721 {
722         return 0;
723 }
724
725 void TimeBar::stop_playback()
726 {
727 }
728
729 int TimeBar::button_press_event()
730 {
731         int result = 0;
732         if( is_event_win() && cursor_above() ) {
733                 if( has_preview() && get_buttonpress() == 3 ) {
734                         result = test_preview(1);
735                 }
736 // Change time format
737                 else if( !is_vwindow() && ctrl_down() ) {
738                         if( get_buttonpress() == 1 )
739                                 mwindow->next_time_format();
740                         else
741                         if( get_buttonpress() == 2 )
742                                 mwindow->prev_time_format();
743                         result = 1;
744                 }
745                 else if( get_buttonpress() == 1 ) {
746                         stop_playback();
747
748 // Select region between two labels
749                         if( !is_vwindow() && get_double_click() &&
750                             get_edl()->labels->first ) {
751                                 int x = get_relative_cursor_x();
752                                 double position = pixel_to_position(x);
753 // Test labels
754                                 select_region(position);
755                         }
756                         else {
757
758 // Reposition highlight cursor
759                                 update_cursor();
760                                 current_operation = TIMEBAR_DRAG;
761                                 activate_timeline();
762                         }
763                         result = 1;
764                 }
765         }
766         return result;
767 }
768
769 void TimeBar::activate_timeline()
770 {
771         mwindow->gui->activate_timeline();
772 }
773
774 int TimeBar::cursor_motion_event()
775 {
776         int result = 0;
777         int redraw = 0;
778
779         switch( current_operation ) {
780         case TIMEBAR_DRAG_LEFT:
781         case TIMEBAR_DRAG_RIGHT:
782         case TIMEBAR_DRAG_CENTER:
783                 if( has_preview() )
784                         result = move_preview(redraw);
785                 break;
786
787         case TIMEBAR_DRAG_LABEL:
788                 if( drag_label ) {
789                         EDL *edl = get_edl();
790                         int pixel = get_relative_cursor_x();
791                         double position = pixel_to_position(pixel);
792                         if( drag_label->label )
793                                 drag_label->label->position = position;
794                         else if( drag_label == in_point ) {
795                                 if( out_point && edl->local_session->outpoint_valid() ) {
796                                         double out_pos = edl->local_session->get_outpoint();
797                                         if( position > out_pos ) {
798                                                 edl->local_session->set_outpoint(position);
799                                                 drag_label = out_point;
800                                                 position = out_pos;
801                                         }
802                                 }
803                                 edl->local_session->set_inpoint(position);
804                         }
805                         else if( drag_label == out_point ) {
806                                 if( in_point && edl->local_session->inpoint_valid() ) {
807                                         double in_pos = edl->local_session->get_inpoint();
808                                         if( position < in_pos ) {
809                                                 edl->local_session->set_inpoint(position);
810                                                 drag_label = in_point;
811                                                 position = in_pos;
812                                         }
813                                 }
814                                 edl->local_session->set_outpoint(position);
815                         }
816                 }
817         // fall thru
818         case TIMEBAR_DRAG:
819                 update_cursor();
820                 handle_mwindow_drag();
821                 result = 1;
822                 break;
823
824         default:
825                 if( has_preview() )
826                         result = test_preview(0);
827                 break;
828         }
829
830
831         if( redraw ) {
832                 update(1);
833         }
834
835         return result;
836 }
837
838 int TimeBar::cursor_leave_event()
839 {
840         if( highlighted ) {
841                 highlighted = 0;
842                 update(1);
843         }
844         return 0;
845 }
846
847 int TimeBar::button_release_event()
848 {
849 //printf("TimeBar::button_release_event %d %d\n", __LINE__, current_operation);
850         int result = 0;
851         int need_redraw = 0;
852         switch( current_operation )
853         {
854                 case TIMEBAR_DRAG:
855                         mwindow->gui->get_focused_pane()->canvas->stop_dragscroll();
856                         current_operation = TIMEBAR_NONE;
857                         need_redraw = 1;
858                         result = 1;
859                         break;
860
861                 default:
862                         if( current_operation != TIMEBAR_NONE ) {
863                                 current_operation = TIMEBAR_NONE;
864                                 result = 1;
865                         }
866                         break;
867         }
868
869         if( (!cursor_above() && highlighted) || need_redraw ) {
870                 highlighted = 0;
871                 update(1);
872         }
873
874         return result;
875 }
876
877 // Update the selection cursor during a dragging operation
878 void TimeBar::update_cursor()
879 {
880 }
881
882 void TimeBar::handle_mwindow_drag()
883 {
884 }
885
886 int TimeBar::select_region(double position)
887 {
888         Label *start = 0, *end = 0, *current;
889         for( current = get_edl()->labels->first; current; current = NEXT ) {
890                 if( current->position > position ) {
891                         end = current;
892                         break;
893                 }
894         }
895
896         for( current = get_edl()->labels->last ; current; current = PREVIOUS ) {
897                 if( current->position <= position ) {
898                         start = current;
899                         break;
900                 }
901         }
902
903 // Select region
904         if( end != start ) {
905                 if( !start )
906                         get_edl()->local_session->set_selectionstart(0);
907                 else
908                         get_edl()->local_session->set_selectionstart(start->position);
909
910                 if( !end )
911                         get_edl()->local_session->set_selectionend(get_edl()->tracks->total_length());
912                 else
913                         get_edl()->local_session->set_selectionend(end->position);
914         }
915         else
916         if( end || start ) {
917                 get_edl()->local_session->set_selectionstart(start->position);
918                 get_edl()->local_session->set_selectionend(start->position);
919         }
920
921 // Que the CWindow
922         unlock_window();
923         mwindow->cwindow->update(1, 0, 0);
924         mwindow->gui->lock_window("TimeBar::select_region 3");
925         mwindow->gui->hide_cursor(0);
926         mwindow->gui->draw_cursor(1);
927         mwindow->gui->flash_canvas(0);
928         mwindow->gui->activate_timeline();
929         mwindow->gui->zoombar->update();
930         mwindow->gui->unlock_window();
931         lock_window("TimeBar::select_region 4");
932         update_highlights();
933         return 0;
934 }
935
936
937 int TimeBar::delete_arrows()
938 {
939         return 0;
940 }
941
942 double TimeBar::test_highlight()
943 {
944         return -1;
945 }
946
947