summaryrefslogtreecommitdiff
path: root/gtk2_ardour/editor_mouse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gtk2_ardour/editor_mouse.cc')
-rw-r--r--gtk2_ardour/editor_mouse.cc171
1 files changed, 146 insertions, 25 deletions
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index 5fbd76ed49..1b91947d40 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -134,13 +134,11 @@ Editor::event_frame (GdkEvent const * event, double* pcx, double* pcy) const
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
-
*pcx = event->button.x;
*pcy = event->button.y;
_trackview_group->w2i(*pcx, *pcy);
break;
case GDK_MOTION_NOTIFY:
-
*pcx = event->motion.x;
*pcy = event->motion.y;
_trackview_group->w2i(*pcx, *pcy);
@@ -254,6 +252,17 @@ Editor::set_canvas_cursor ()
}
}
+ switch (_join_object_range_state) {
+ case JOIN_OBJECT_RANGE_NONE:
+ break;
+ case JOIN_OBJECT_RANGE_OBJECT:
+ current_canvas_cursor = which_grabber_cursor ();
+ break;
+ case JOIN_OBJECT_RANGE_RANGE:
+ current_canvas_cursor = selector_cursor;
+ break;
+ }
+
if (is_drawable()) {
track_canvas->get_window()->set_cursor(*current_canvas_cursor);
}
@@ -315,9 +324,9 @@ Editor::mouse_mode_toggled (MouseMode m)
instant_save ();
- if (mouse_mode != MouseRange) {
+ if (mouse_mode != MouseRange && _join_object_range_state == JOIN_OBJECT_RANGE_NONE) {
- /* in all modes except range, hide the range selection,
+ /* in all modes except range and joined object/range, hide the range selection,
show the object (region) selection.
*/
@@ -331,7 +340,7 @@ Editor::mouse_mode_toggled (MouseMode m)
} else {
/*
- in range mode, show the range selection.
+ in range or object/range mode, show the range selection.
*/
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
@@ -416,6 +425,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
*/
if (((mouse_mode != MouseObject) &&
+ (_join_object_range_state != JOIN_OBJECT_RANGE_OBJECT) &&
(mouse_mode != MouseAudition || item_type != RegionItem) &&
(mouse_mode != MouseTimeFX || item_type != RegionItem) &&
(mouse_mode != MouseGain) &&
@@ -445,16 +455,21 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
switch (item_type) {
case RegionItem:
- if (mouse_mode != MouseRange) {
+ if (mouse_mode != MouseRange || _join_object_range_state == JOIN_OBJECT_RANGE_OBJECT) {
set_selected_regionview_from_click (press, op, true);
} else if (event->type == GDK_BUTTON_PRESS) {
- set_selected_track_as_side_effect ();
+ selection->clear_tracks ();
+ set_selected_track_as_side_effect (true);
+ }
+ if (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT && !selection->regions.empty()) {
+ select_range_around_region (selection->regions.front());
}
+
break;
case RegionViewNameHighlight:
case RegionViewName:
- if (mouse_mode != MouseRange) {
+ if (mouse_mode != MouseRange || _join_object_range_state == JOIN_OBJECT_RANGE_OBJECT) {
set_selected_regionview_from_click (press, op, true);
} else if (event->type == GDK_BUTTON_PRESS) {
set_selected_track_as_side_effect ();
@@ -466,7 +481,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
case FadeInItem:
case FadeOutHandleItem:
case FadeOutItem:
- if (mouse_mode != MouseRange) {
+ if (mouse_mode != MouseRange || _join_object_range_state == JOIN_OBJECT_RANGE_OBJECT) {
set_selected_regionview_from_click (press, op, true);
} else if (event->type == GDK_BUTTON_PRESS) {
set_selected_track_as_side_effect ();
@@ -475,7 +490,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
case ControlPointItem:
set_selected_track_as_side_effect ();
- if (mouse_mode != MouseRange) {
+ if (mouse_mode != MouseRange || _join_object_range_state == JOIN_OBJECT_RANGE_OBJECT) {
set_selected_control_point_from_click (op, false);
}
break;
@@ -597,7 +612,9 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break;
}
- switch (mouse_mode) {
+ Editing::MouseMode eff = effective_mouse_mode ();
+
+ switch (eff) {
case MouseRange:
switch (item_type) {
case StartSelectionTrimItem:
@@ -623,11 +640,21 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
_drag = new SelectionDrag (this, item, SelectionDrag::SelectionMove);
_drag->start_grab (event);
} else {
- /* this was debated, but decided the more common action was to
- make a new selection */
- assert (_drag == 0);
- _drag = new SelectionDrag (this, item, SelectionDrag::CreateSelection);
- _drag->start_grab (event);
+ double const y = event->button.y + vertical_adjustment.get_value() - canvas_timebars_vsize;
+ pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
+ if (tvp.first) {
+ AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
+ assert (_drag == 0);
+ if (join_object_range_button.get_active() && atv) {
+ /* smart "join" mode: drag automation */
+ _drag = new AutomationRangeDrag (this, atv->base_item(), selection->time);
+ } else {
+ /* this was debated, but decided the more common action was to
+ make a new selection */
+ _drag = new SelectionDrag (this, item, SelectionDrag::CreateSelection);
+ }
+ _drag->start_grab (event);
+ }
}
break;
@@ -734,14 +761,46 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
_drag = new RegionCreateDrag (this, item, clicked_axisview);
_drag->start_grab (event);
return true;
+ } else {
+ assert (_drag == 0);
+ _drag = new RubberbandSelectDrag (this, item);
+ _drag->start_grab (event);
}
- /* fallthru */
+ break;
+
case AutomationTrackItem:
assert (_drag == 0);
- _drag = new RubberbandSelectDrag (this, item);
+
+ if (join_object_range_button.get_active()) {
+ /* smart "join" mode: drag automation */
+ _drag = new AutomationRangeDrag (this, item, selection->time);
+ } else {
+ /* otherwise: rubberband drag to select automation points */
+ _drag = new RubberbandSelectDrag (this, item);
+ }
+
_drag->start_grab (event);
break;
+ case SelectionItem:
+ {
+ if (join_object_range_button.get_active()) {
+ /* we're in "smart" joined mode, and we've clicked on a Selection; if we're
+ * over an automation track, start a drag of its data */
+ double const y = event->button.y + vertical_adjustment.get_value() - canvas_timebars_vsize;
+ pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
+ if (tvp.first) {
+ AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
+ if (atv) {
+ assert (_drag == 0);
+ _drag = new AutomationRangeDrag (this, atv->base_item(), selection->time);
+ _drag->start_grab (event);
+ }
+ }
+ }
+ break;
+ }
+
#ifdef WITH_CMT
case ImageFrameHandleStartItem:
imageframe_start_handle_op(item, event) ;
@@ -878,7 +937,8 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
bool
Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
- switch (mouse_mode) {
+ Editing::MouseMode const eff = effective_mouse_mode ();
+ switch (eff) {
case MouseObject:
switch (item_type) {
case RegionItem:
@@ -1152,6 +1212,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
/* delete events get handled here */
+ Editing::MouseMode const eff = effective_mouse_mode ();
+
if (_drag == 0 && Keyboard::is_delete_event (&event->button)) {
switch (item_type) {
@@ -1168,13 +1230,13 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break;
case RegionItem:
- if (mouse_mode == MouseObject) {
+ if (eff == MouseObject) {
remove_clicked_region ();
}
break;
case ControlPointItem:
- if (mouse_mode == MouseGain) {
+ if (eff == MouseGain) {
remove_gain_control_point (item, event);
} else {
remove_control_point (item, event);
@@ -1233,7 +1295,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break;
}
- switch (mouse_mode) {
+ switch (eff) {
case MouseObject:
switch (item_type) {
case AutomationTrackItem:
@@ -1305,7 +1367,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case 2:
- switch (mouse_mode) {
+ switch (eff) {
case MouseObject:
switch (item_type) {
@@ -1348,7 +1410,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
}
bool
-Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* /*event*/, ItemType item_type)
+Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
ControlPoint* cp;
Marker * marker;
@@ -1544,7 +1606,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* /*event*/, ItemType i
}
bool
-Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* /*event*/, ItemType item_type)
+Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
AutomationLine* al;
ControlPoint* cp;
@@ -1661,6 +1723,10 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* /*event*/, ItemType i
break;
}
+ if (item_type == RegionItem) {
+ update_join_object_range_location (event->crossing.x, event->crossing.y);
+ }
+
return false;
}
@@ -1782,6 +1848,12 @@ Editor::motion_handler (ArdourCanvas::Item* /*item*/, GdkEvent* event, bool from
return true;
}
+ JoinObjectRangeState const old = _join_object_range_state;
+ update_join_object_range_location (event->motion.x, event->motion.y);
+ if (_join_object_range_state != old) {
+ set_canvas_cursor ();
+ }
+
bool handled = false;
if (_drag) {
handled = _drag->motion_handler (event, from_autoscroll);
@@ -2598,3 +2670,52 @@ Editor::set_internal_edit (bool yn)
}
+
+/** Update _join_object_range_state which indicate whether we are over the top or bottom half of a region view,
+ * used by the `join object/range' tool mode.
+ */
+void
+Editor::update_join_object_range_location (double x, double y)
+{
+ if (join_object_range_button.get_active() == false || (mouse_mode != MouseRange && mouse_mode != MouseObject)) {
+ _join_object_range_state = JOIN_OBJECT_RANGE_NONE;
+ return;
+ }
+
+ if (entered_regionview) {
+
+ double cx = x;
+ double cy = y;
+ entered_regionview->get_canvas_group()->w2i (cx, cy);
+
+ double x1;
+ double y1;
+ double x2;
+ double y2;
+ entered_regionview->get_canvas_group()->get_bounds (x1, y1, x2, y2);
+
+ bool const top_half = cy < (y2 - y1) / 2;
+
+ _join_object_range_state = top_half ? JOIN_OBJECT_RANGE_RANGE : JOIN_OBJECT_RANGE_OBJECT;
+
+ } else {
+
+ if (mouse_mode == MouseObject) {
+ _join_object_range_state = JOIN_OBJECT_RANGE_OBJECT;
+ } else if (mouse_mode == MouseRange) {
+ _join_object_range_state = JOIN_OBJECT_RANGE_RANGE;
+ }
+ }
+}
+
+Editing::MouseMode
+Editor::effective_mouse_mode () const
+{
+ if (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT) {
+ return MouseObject;
+ } else if (_join_object_range_state == JOIN_OBJECT_RANGE_RANGE) {
+ return MouseRange;
+ }
+
+ return mouse_mode;
+}