add deselect to editpopup menu, drag edit select/deselect
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / trackcanvas.C
index f37b1cd63c4d307873a64fdda3c71b2cd5cfc3c5..536fabc6325e5d31e07c9ea444680291fa997ae0 100644 (file)
@@ -188,6 +188,7 @@ int TrackCanvas::drag_motion(
                Track **over_track, Edit **over_edit,
                PluginSet **over_pluginset, Plugin **over_plugin)
 {
+       int update_scroll = 0;
        int cursor_x = get_relative_cursor_x();
        int cursor_y = get_relative_cursor_y();
        if( get_cursor_over_window() ) {
@@ -196,6 +197,28 @@ int TrackCanvas::drag_motion(
        }
        if( over_track && !*over_track )
                *over_track = pane->over_patchbay();
+
+       switch( mwindow->session->current_operation ) {
+       case DRAG_EDIT_SELECT: {
+               Edit *edit = over_edit ? *over_edit : 0;
+               double position = mwindow->edl->get_cursor_position(cursor_x, pane->number);
+               mwindow->session->drag_position = mwindow->edl->align_to_frame(position, 0);
+               drag_edit_select(edit, 0, 1);
+               update_scroll = 1;
+               break; }
+       }
+
+       if( update_scroll ) {
+               if( !drag_scroll &&
+                   (cursor_x >= get_w() || cursor_x < 0 ||
+                    cursor_y >= get_h() || cursor_y < 0))
+                       start_dragscroll();
+               else if( drag_scroll &&
+                        cursor_x < get_w() && cursor_x >= 0 &&
+                        cursor_y < get_h() && cursor_y >= 0 )
+                       stop_dragscroll();
+       }
+
        return 0;
 }
 
@@ -500,7 +523,7 @@ int TrackCanvas::drag_stop(int *redraw)
                                result = 1;
                        }
                        break;
-               case DRAG_GROUP:
+               case DRAG_GROUP: {
                        mwindow->session->current_operation = NO_OPERATION;
                        EDL *drag_group = mwindow->session->drag_group;
                        if( drag_group ) {
@@ -532,10 +555,21 @@ int TrackCanvas::drag_stop(int *redraw)
                                }
                        }
                        result = 1;
+                       break; }
+               case DRAG_EDIT_SELECT:
+                       int select = ctrl_down() ? -1 : 1;
+                       drag_edit_select(mwindow->session->edit_highlighted, select, 0);
                        break;
                }
        }
 
+       switch( mwindow->session->current_operation ) {
+       case DRAG_EDIT_SELECT:
+               mwindow->session->current_operation = NO_OPERATION;
+               result = 1;
+               break;
+       }
+
        return result;
 }
 
@@ -1967,7 +2001,8 @@ void TrackCanvas::draw_inout_points()
 void TrackCanvas::draw_drag_handle()
 {
        if( mwindow->session->current_operation != DRAG_EDITHANDLE2 &&
-           mwindow->session->current_operation != DRAG_PLUGINHANDLE2 ) return;
+           mwindow->session->current_operation != DRAG_PLUGINHANDLE2 &&
+           mwindow->session->current_operation != DRAG_TRANSNHANDLE2 ) return;
        int64_t pixel1 = Units::round(mwindow->session->drag_position *
                mwindow->edl->session->sample_rate /
                mwindow->edl->local_session->zoom_sample -
@@ -2050,6 +2085,7 @@ void TrackCanvas::draw_drag_handle()
 void TrackCanvas::draw_transitions()
 {
        int64_t x, y, w, h;
+       if( !mwindow->edl->session->auto_conf->transitions ) return;
 
        for(Track *track = mwindow->edl->tracks->first; track; track = track->next) {
                if( track->is_hidden() ) continue;
@@ -3846,14 +3882,8 @@ void TrackCanvas::update_drag_handle()
        double new_position;
        int cursor_x = get_cursor_x();
 
-       new_position =
-               (double)(cursor_x +
-               mwindow->edl->local_session->view_start[pane->number]) *
-               mwindow->edl->local_session->zoom_sample /
-               mwindow->edl->session->sample_rate;
-
-       new_position =
-               mwindow->edl->align_to_frame(new_position, 0);
+       new_position = mwindow->edl->get_cursor_position(cursor_x, pane->number);
+       new_position = mwindow->edl->align_to_frame(new_position, 0);
 
        if( ctrl_down() && alt_down() ) {
 #define snapper(v) do { \
@@ -4297,6 +4327,53 @@ void TrackCanvas::update_drag_caption()
 }
 
 
+void TrackCanvas::drag_edit_select(Edit *over_edit, int select, int draw)
+{
+       if( !over_edit ) return;
+       if( !mwindow->session->drag_edit ) return;
+       Track *drag_track = mwindow->session->drag_edit->track;
+       Track *over_track = over_edit->track;
+       if( !drag_track || !over_track ) return;
+       if( drag_track->number_of() > over_track->number_of() ) {
+               Track *trk = drag_track;
+               drag_track = over_track;
+               over_track = trk;
+       }
+       double start_pos = mwindow->session->drag_start;
+       double end_pos = mwindow->session->drag_position;
+       if( start_pos > end_pos ) {
+               double pos = start_pos;
+               start_pos = end_pos;
+               end_pos = pos;
+       }
+       int done = 0, do_flash = 0;
+       for( Track *track=drag_track; !done; track=track->next ) {
+               if( !track->is_armed() ) continue;
+               for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
+                       int64_t pos = edit->startproject;
+                       int64_t end = pos + edit->length;
+                       double edit_start = track->from_units(pos);
+                       double edit_end = track->from_units(end);
+                       if( start_pos >= edit_end ) continue;
+                       if( edit_start > end_pos ) continue;
+                       if( select > 0 )
+                               edit->is_selected = 1;
+                       else if( select < 0 )
+                               edit->is_selected = 0;
+                       if( draw ) {
+                               int64_t edit_x, edit_y, edit_w, edit_h;
+                               edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h);
+                               set_color(YELLOW);
+                               draw_rectangle(edit_x, edit_y, edit_w, edit_h);
+                               do_flash = 1;
+                       }
+               }
+               if( track == over_track ) done = 1;
+       }
+       if( do_flash )
+               flash();
+}
+
 
 int TrackCanvas::cursor_update(int in_motion)
 {
@@ -4310,7 +4387,7 @@ int TrackCanvas::cursor_update(int in_motion)
        int update_cursor = 0;
        int rerender = 0;
        double position = 0.;
-//printf("TrackCanvas::cursor_update %d\n", __LINE__);
+//printf("TrackCanvas::cursor_update %d %d,%d\n", __LINE__, get_cursor_x(), get_cursor_y());
 
 // Default cursor
        int new_cursor =
@@ -4321,42 +4398,46 @@ int TrackCanvas::cursor_update(int in_motion)
        {
                case DRAG_EDITHANDLE1:
 // Outside threshold.  Upgrade status
-                       if(active)
-                       {
-                               if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
-                               {
-                                       mwindow->session->current_operation = DRAG_EDITHANDLE2;
-                                       update_overlay = 1;
-                               }
+                       if( !active ) break;
+                       if( labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W ) {
+                               mwindow->session->current_operation = DRAG_EDITHANDLE2;
+                               update_overlay = 1;
                        }
                        break;
-
                case DRAG_EDITHANDLE2:
-                       if(active)
-                       {
-                               update_drag_handle();
-                               update_overlay = 1;
-                       }
+                       if( !active ) break;
+                       update_drag_handle();
+                       update_overlay = 1;
                        break;
 
                case DRAG_PLUGINHANDLE1:
-                       if(active)
-                       {
-                               if(labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W)
-                               {
-                                       mwindow->session->current_operation = DRAG_PLUGINHANDLE2;
-                                       update_overlay = 1;
-                               }
+                       if( !active ) break;
+                       if( labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W ) {
+                               mwindow->session->current_operation = DRAG_PLUGINHANDLE2;
+                               update_overlay = 1;
                        }
                        break;
-
                case DRAG_PLUGINHANDLE2:
-                       if(active)
-                       {
-                               update_drag_handle();
+                       if( !active ) break;
+                       update_drag_handle();
+                       update_overlay = 1;
+                       break;
+
+               case DRAG_TRANSNHANDLE1:
+                       if( !active ) break;
+                       if( labs(get_cursor_x() - mwindow->session->drag_origin_x) > HANDLE_W ) {
+                               mwindow->session->current_operation = DRAG_TRANSNHANDLE2;
                                update_overlay = 1;
                        }
                        break;
+               case DRAG_TRANSNHANDLE2: {
+                       if( !active ) break;
+                       position = mwindow->edl->get_cursor_position(get_cursor_x(), pane->number);
+                       position = mwindow->edl->align_to_frame(position, 1);
+                       drag_transition_handle(position);
+                       rerender = 1;
+                       update_overlay = 1;
+                       break; }
 
 // Rubber band curves
                case DRAG_FADE:
@@ -4479,6 +4560,8 @@ int TrackCanvas::cursor_update(int in_motion)
                                                0, new_cursor, update_cursor)) break;
                                if(do_keyframes(get_cursor_x(), get_cursor_y(),
                                        0, 0, new_cursor, update_cursor, rerender)) break;
+                               if(do_transition_handles(get_cursor_x(), get_cursor_y(),
+                                       0, rerender, update_overlay, new_cursor, update_cursor)) break;
                                if(do_edit_handles(get_cursor_x(), get_cursor_y(),
                                        0, rerender, update_overlay, new_cursor, update_cursor)) break;
 // Plugin boundaries
@@ -4575,6 +4658,7 @@ int TrackCanvas::repeat_event(int64_t duration)
        int result = 0;
 
        switch(mwindow->session->current_operation) {
+               case DRAG_EDIT_SELECT:
                case SELECT_REGION:
 //printf("TrackCanvas::repeat_event 1 %d\n", mwindow->edl->local_session->view_start);
                if(get_cursor_x() > get_w()) {
@@ -4678,6 +4762,20 @@ int TrackCanvas::button_release_event()
                        result = 1;
                        break;
 
+               case DRAG_TRANSNHANDLE2:
+                       mwindow->session->current_operation = NO_OPERATION;
+                       drag_scroll = 0;
+                       result = 1;
+
+                       end_transnhandle_selection();
+                       break;
+
+               case DRAG_TRANSNHANDLE1:
+                       mwindow->session->current_operation = NO_OPERATION;
+                       drag_scroll = 0;
+                       result = 1;
+                       break;
+
                case DRAG_SPEED:
                        redraw = FORCE_REDRAW;
                        load_flags |= LOAD_EDITS | LOAD_TIMEBAR;
@@ -4758,6 +4856,10 @@ int TrackCanvas::button_release_event()
                        drag_scroll = 0;
                        break; }
 
+               case DRAG_EDIT_SELECT:
+                       //result = 0;
+                       break;
+
                default:
                        if( mwindow->session->current_operation ) {
 //                             if(mwindow->session->current_operation == SELECT_REGION) {
@@ -5000,6 +5102,95 @@ int TrackCanvas::do_plugin_handles(int cursor_x,
        return result;
 }
 
+int TrackCanvas::do_transition_handles(int cursor_x, int cursor_y, int button_press,
+               int &rerender, int &update_overlay, int &new_cursor, int &update_cursor)
+{
+       Transition *trans_result = 0;
+       int result = 0;
+
+       Track *track = mwindow->edl->tracks->first;
+       for( ; track && !result; track=track->next) {
+               if( track->is_hidden() ) continue;
+               Edit *edit = track->edits->first;
+               for( ; edit && !result; edit=edit->next ) {
+                       Transition *trans = edit->transition;
+                       if( !trans ) continue;
+                       int64_t x, y, w, h;
+                       edit_dimensions(edit, x, y, w, h);
+                       int strip_x = x, edit_y = y;
+                       get_transition_coords(edit, x, y, w, h);
+                       VFrame *strip = mwindow->theme->get_image("plugin_bg_data");
+                       int strip_y = y - strip->get_h();
+                       if( track->show_assets() && track->show_titles() )
+                               edit_y += mwindow->theme->get_image("title_bg_data")->get_h();
+                       if( strip_y < edit_y ) strip_y = edit_y;
+                       int strip_w = Units::round(edit->track->from_units(edit->transition->length) *
+                               mwindow->edl->session->sample_rate / mwindow->edl->local_session->zoom_sample);
+                       int x1 = strip_x + strip_w - HANDLE_W/2, x2 = x1 + HANDLE_W;
+                       int y1 = strip_y + strip->get_h()/2 - HANDLE_H/2, y2 = y1 + HANDLE_W;
+                       if( cursor_x >= x1 && cursor_x < x2 &&
+                           cursor_y >= y1 && cursor_y < y2 ) {
+                               trans_result = trans;
+                               result = 1;
+                       }
+               }
+       }
+
+       if( result ) {
+               if( button_press ) {
+                       mwindow->session->drag_transition = trans_result;
+                       mwindow->session->drag_handle = 1;
+                       mwindow->session->drag_button = get_buttonpress() - 1;
+                       int64_t trans_end = trans_result->edit->startproject + trans_result->length;
+                       double position = trans_result->edit->track->from_units(trans_end);
+                       mwindow->session->drag_position = position;
+                       mwindow->session->drag_start = position;
+                       mwindow->session->current_operation = DRAG_TRANSNHANDLE1;
+                       mwindow->session->drag_origin_x = get_cursor_x();
+                       mwindow->session->drag_origin_y = get_cursor_y();
+                       update_cursor = 1;
+               }
+               new_cursor = RIGHT_CURSOR;
+               update_overlay = 1;
+       }
+
+       return result;
+}
+
+int TrackCanvas::drag_transition_handle(double position)
+{
+       Transition *transition = mwindow->session->drag_transition;
+       if( !transition ) return 1;
+       mwindow->session->drag_position = position;
+       mwindow->edl->local_session->set_selectionstart(position);
+       mwindow->edl->local_session->set_selectionend(position);
+       char string[BCSTRLEN];
+       int64_t length = transition->length;
+       Track *track = transition->edit->track;
+       int64_t start_pos = track->to_units(mwindow->session->drag_start, 0);
+       int64_t end_pos = track->to_units(mwindow->session->drag_position, 0);
+       length += end_pos - start_pos;
+       if( length < 0 ) length = 0;
+       double time = track->from_units(length);
+       Units::totext(string, time,
+               mwindow->edl->session->time_format,
+               mwindow->edl->session->sample_rate,
+               mwindow->edl->session->frame_rate,
+               mwindow->edl->session->frames_per_foot);
+       mwindow->gui->show_message(string);
+       if( mwindow->gui->transition_menu->length_thread->running() ) {
+               TransitionLengthDialog *dialog = (TransitionLengthDialog *)
+                        mwindow->gui->transition_menu->length_thread->get_gui();
+               if( dialog ) {
+                       dialog->lock_window("TrackCanvas::drag_transition_handle");
+                       dialog->update_text(time);
+                       dialog->thread->new_length = time;
+                       dialog->unlock_window();
+               }
+       }
+       return 0;
+}
+
 
 int TrackCanvas::do_tracks(int cursor_x, int cursor_y, int button_press)
 {
@@ -5080,8 +5271,15 @@ int TrackCanvas::do_edits(int cursor_x, int cursor_y, int button_press, int drag
                                        mwindow->session->drag_origin_x = cursor_x;
                                        mwindow->session->drag_origin_y = cursor_y;
 // Where the drag started, so we know relative position inside the edit later
-                                       mwindow->session->drag_position =
-                                               mwindow->edl->get_cursor_position(cursor_x, pane->number);
+                                       double position = mwindow->edl->get_cursor_position(cursor_x, pane->number);
+                                       mwindow->session->drag_position = mwindow->edl->align_to_frame(position, 1);
+                                       if( get_buttonpress() == LEFT_BUTTON && alt_down() ) {
+                                               mwindow->session->drag_start = mwindow->session->drag_position;
+                                               drag_edit_select(edit, 0, 1);
+                                               mwindow->session->current_operation = DRAG_EDIT_SELECT;
+                                               result = 1;
+                                               continue;
+                                       }
                                        drag_start = 0; // if unselected "fast" drag
                                        if( !edit->silence() && !edit->is_selected ) {
                                                mwindow->edl->tracks->clear_selected_edits();
@@ -5421,6 +5619,10 @@ int TrackCanvas::button_press_event()
                                        0, get_buttonpress(), new_cursor,
                                        update_cursor, rerender) ) break;
                                update_message = 1;
+
+                               if( do_transition_handles(cursor_x, cursor_y,
+                                       1, rerender, update_overlay, new_cursor,
+                                       update_cursor) ) break;
 // Test edit boundaries
                                if( do_edit_handles(cursor_x, cursor_y,
                                        1, rerender, update_overlay, new_cursor,
@@ -5457,6 +5659,8 @@ int TrackCanvas::button_press_event()
                                        break;
                                }
                                update_message = 1;
+                               if( do_transition_handles(cursor_x, cursor_y,
+                                       1, rerender, update_overlay, new_cursor, update_cursor) ) break;
 // Test edit boundaries
                                if( do_edit_handles(cursor_x, cursor_y,
                                        1, rerender, update_overlay, new_cursor, update_cursor) ) break;
@@ -5553,11 +5757,19 @@ int TrackCanvas::start_selection(double position)
 void TrackCanvas::end_edithandle_selection()
 {
        mwindow->modify_edithandles();
+       mwindow->session->drag_edit = 0;
 }
 
 void TrackCanvas::end_pluginhandle_selection()
 {
        mwindow->modify_pluginhandles();
+       mwindow->session->drag_plugin = 0;
+}
+
+void TrackCanvas::end_transnhandle_selection()
+{
+       mwindow->modify_transnhandles();
+       mwindow->session->drag_transition = 0;
 }