#include <set>
#include <string>
#include <algorithm>
+#include <bitset>
#include "pbd/error.h"
#include "pbd/enumwriter.h"
#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/tearoff.h"
+#include "canvas/canvas.h"
+
+#include "ardour/audioregion.h"
+#include "ardour/operations.h"
+#include "ardour/playlist.h"
+#include "ardour/profile.h"
+#include "ardour/region_factory.h"
+#include "ardour/route.h"
+#include "ardour/session.h"
+#include "ardour/types.h"
+
#include "ardour_ui.h"
#include "actions.h"
-#include "canvas-note.h"
#include "editor.h"
#include "time_axis_view.h"
#include "audio_time_axis.h"
#include "mouse_cursors.h"
#include "editor_cursors.h"
#include "verbose_cursor.h"
-
-#include "ardour/audioregion.h"
-#include "ardour/operations.h"
-#include "ardour/playlist.h"
-#include "ardour/profile.h"
-#include "ardour/region_factory.h"
-#include "ardour/route.h"
-#include "ardour/session.h"
-#include "ardour/types.h"
-
-#include <bitset>
+#include "note.h"
#include "i18n.h"
}
int x, y;
- double wx, wy;
- Gdk::ModifierType mask;
- Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->track_canvas->get_window();
- Glib::RefPtr<const Gdk::Window> pointer_window;
+ Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->_track_canvas->get_window();
if (!canvas_window) {
return false;
}
- pointer_window = canvas_window->get_pointer (x, y, mask);
+ Glib::RefPtr<const Gdk::Window> pointer_window = Gdk::Display::get_default()->get_window_at_pointer (x, y);
- if (pointer_window == track_canvas->get_bin_window()) {
- wx = x;
- wy = y;
- in_track_canvas = true;
+ if (!pointer_window) {
+ return false;
+ }
- } else {
+ if (pointer_window != canvas_window && pointer_window != _time_bars_canvas->get_window()) {
in_track_canvas = false;
- return false;
+ return false;
}
+ in_track_canvas = true;
+
GdkEvent event;
event.type = GDK_BUTTON_RELEASE;
- event.button.x = wx;
- event.button.y = wy;
+ event.button.x = x;
+ event.button.y = y;
+
+ where = window_event_sample (&event, 0, 0);
- where = event_frame (&event, 0, 0);
return true;
}
framepos_t
-Editor::event_frame (GdkEvent const * event, double* pcx, double* pcy) const
+Editor::window_event_sample (GdkEvent const * event, double* pcx, double* pcy) const
{
- double cx, cy;
+ double x;
+ double y;
- if (pcx == 0) {
- pcx = &cx;
+ if (!gdk_event_get_coords (event, &x, &y)) {
+ return 0;
}
- if (pcy == 0) {
- pcy = &cy;
+
+ /* event coordinates are in window units, so convert to canvas
+ * (i.e. account for scrolling)
+ */
+
+ ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (x, y));
+
+ if (pcx) {
+ *pcx = d.x;
}
- *pcx = 0;
- *pcy = 0;
+ if (pcy) {
+ *pcy = d.y;
+ }
- switch (event->type) {
- case GDK_BUTTON_RELEASE:
- 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);
- break;
- case GDK_ENTER_NOTIFY:
- case GDK_LEAVE_NOTIFY:
- track_canvas->w2c(event->crossing.x, event->crossing.y, *pcx, *pcy);
- break;
- case GDK_KEY_PRESS:
- case GDK_KEY_RELEASE:
- // track_canvas->w2c(event->key.x, event->key.y, *pcx, *pcy);
- break;
- default:
- warning << string_compose (_("Editor::event_frame() used on unhandled event type %1"), event->type) << endmsg;
- break;
+ return pixel_to_sample (d.x);
+}
+
+framepos_t
+Editor::canvas_event_sample (GdkEvent const * event, double* pcx, double* pcy) const
+{
+ double x;
+ double y;
+
+ /* event coordinates are already in canvas units */
+
+ if (!gdk_event_get_coords (event, &x, &y)) {
+ cerr << "!NO c COORDS for event type " << event->type << endl;
+ return 0;
}
- /* note that pixel_to_frame() never returns less than zero, so even if the pixel
+ if (pcx) {
+ *pcx = x;
+ }
+
+ if (pcy) {
+ *pcy = y;
+ }
+
+ /* note that pixel_to_sample_from_event() never returns less than zero, so even if the pixel
position is negative (as can be the case with motion events in particular),
the frame location is always positive.
*/
- return pixel_to_frame (*pcx);
+ return pixel_to_sample_from_event (x);
}
Gdk::Cursor*
/* up-down cursor as a cue that automation can be dragged up and down when in join object/range mode */
if (!_internal_editing && get_smart_mode() ) {
+
double x, y;
get_pointer_position (x, y);
- ArdourCanvas::Item* i = track_canvas->get_item_at (x, y);
- if (i && i->property_parent() && (*i->property_parent()).get_data (X_("timeselection"))) {
- pair<TimeAxisView*, int> tvp = trackview_by_y_position (_last_motion_y + vertical_adjustment.get_value() - canvas_timebars_vsize);
- if (dynamic_cast<AutomationTimeAxisView*> (tvp.first)) {
- current_canvas_cursor = _cursors->up_down;
+
+ if (x >= 0 && y >= 0) {
+
+ vector<ArdourCanvas::Item const *> items;
+
+ _track_canvas->root()->add_items_at_point (ArdourCanvas::Duple (x,y), items);
+
+ // first item will be the upper most
+
+ if (!items.empty()) {
+ const ArdourCanvas::Item* i = items.front();
+
+ if (i && i->parent() && i->parent()->get_data (X_("timeselection"))) {
+ pair<TimeAxisView*, int> tvp = trackview_by_y_position (_last_motion_y);
+ if (dynamic_cast<AutomationTimeAxisView*> (tvp.first)) {
+ current_canvas_cursor = _cursors->up_down;
+ }
+ }
}
}
}
assert (act);
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
assert (tact);
- if (tact->get_active())
+
+ if (tact->get_active()) {
m = MouseObject; //Smart mode turned to ON, force editing to Object mode
-
+ }
+
set_mouse_mode(m, true); //call this so the button styles can get updated
}
set_canvas_cursor ();
set_gain_envelope_visibility ();
+
+ update_time_selection_display ();
MouseModeChanged (); /* EMIT SIGNAL */
}
+void
+Editor::update_time_selection_display ()
+{
+ if (smart_mode_action->get_active()) {
+ /* not sure what to do here */
+ if (mouse_mode == MouseObject) {
+ } else {
+ }
+ } else {
+ switch (mouse_mode) {
+ case MouseRange:
+ selection->clear_objects ();
+ break;
+ default:
+ selection->clear_time ();
+ break;
+ }
+ }
+}
+
void
Editor::step_mouse_mode (bool next)
{
to cut notes or regions.
*/
+ MouseMode eff_mouse_mode = mouse_mode;
+
+ if (get_smart_mode() && eff_mouse_mode == MouseRange && event->button.button == 3 && item_type == RegionItem) {
+ /* context clicks are always about object properties, even if
+ we're in range mode within smart mode.
+ */
+ eff_mouse_mode = MouseObject;
+ }
+
if (((mouse_mode != MouseObject) &&
(mouse_mode != MouseAudition || item_type != RegionItem) &&
(mouse_mode != MouseTimeFX || item_type != RegionItem) &&
switch (item_type) {
case RegionItem:
- if (!get_smart_mode() || (_join_object_range_state != JOIN_OBJECT_RANGE_RANGE)) {
- if (press) {
- if (mouse_mode != MouseRange) {
- set_selected_regionview_from_click (press, op);
- } else {
- /* don't change the selection unless the
- clicked track is not currently selected. if
- so, "collapse" the selection to just this
- track
- */
- if (!selection->selected (clicked_axisview)) {
- set_selected_track_as_side_effect (Selection::Set);
- }
- }
+ if (press) {
+ if (eff_mouse_mode != MouseRange) {
+ set_selected_regionview_from_click (press, op);
} else {
- if (mouse_mode != MouseRange) {
- set_selected_regionview_from_click (press, op);
+ /* don't change the selection unless the
+ clicked track is not currently selected. if
+ so, "collapse" the selection to just this
+ track
+ */
+ if (!selection->selected (clicked_axisview)) {
+ set_selected_track_as_side_effect (Selection::Set);
}
}
+ } else {
+ if (eff_mouse_mode != MouseRange) {
+ set_selected_regionview_from_click (press, op);
+ }
}
break;
case RegionViewName:
case LeftFrameHandle:
case RightFrameHandle:
- if ( mouse_mode != MouseRange ) {
+ if (eff_mouse_mode != MouseRange) {
set_selected_regionview_from_click (press, op);
} else if (event->type == GDK_BUTTON_PRESS) {
set_selected_track_as_side_effect (op);
case FadeOutItem:
case StartCrossFadeItem:
case EndCrossFadeItem:
- if ( mouse_mode != MouseRange ) {
+ if (eff_mouse_mode != MouseRange) {
+ cerr << "Should be setting selected regionview\n";
set_selected_regionview_from_click (press, op);
} else if (event->type == GDK_BUTTON_PRESS) {
set_selected_track_as_side_effect (op);
case ControlPointItem:
set_selected_track_as_side_effect (op);
- if ( mouse_mode != MouseRange ) {
+ if (eff_mouse_mode != MouseRange) {
set_selected_control_point_from_click (press, op);
}
break;
switch (item_type) {
case PlayheadCursorItem:
- _drags->set (new CursorDrag (this, item, true), event);
+ _drags->set (new CursorDrag (this, *playhead_cursor, true), event);
return true;
case MarkerItem:
{
TempoMarker* m = reinterpret_cast<TempoMarker*> (item->get_data ("marker"));
assert (m);
- if (m->tempo().movable ()) {
- _drags->set (
- new TempoMarkerDrag (
- this,
- item,
- Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
- ),
- event
- );
- return true;
- } else {
- return false;
- }
+ _drags->set (
+ new TempoMarkerDrag (
+ this,
+ item,
+ Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
+ ),
+ event
+ );
+ return true;
}
case MeterMarkerItem:
{
MeterMarker* m = reinterpret_cast<MeterMarker*> (item->get_data ("marker"));
assert (m);
- if (m->meter().movable ()) {
- _drags->set (
- new MeterMarkerDrag (
- this,
- item,
- Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
- ),
- event
- );
- return true;
- } else {
- return false;
- }
+ _drags->set (
+ new MeterMarkerDrag (
+ this,
+ item,
+ Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
+ ),
+ event
+ );
+ return true;
}
case VideoBarItem:
case TempoBarItem:
case MeterBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
- _drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event);
+ _drags->set (new CursorDrag (this, *playhead_cursor, false), event);
}
return true;
break;
case RangeMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
- _drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event);
+ _drags->set (new CursorDrag (this, *playhead_cursor, false), event);
} else {
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateRangeMarker), event);
}
case CdMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
- _drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event);
+ _drags->set (new CursorDrag (this, *playhead_cursor, false), event);
} else {
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateCDMarker), event);
}
case TransportMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
- _drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event);
+ _drags->set (new CursorDrag (this, *playhead_cursor, false), event);
} else {
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateTransportMarker), event);
}
case SelectionItem:
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
start_selection_grab (item, event);
+ return true;
} else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::SecondaryModifier)) {
/* grab selection for moving */
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionMove), event);
} else {
- double const y = event->button.y + vertical_adjustment.get_value() - canvas_timebars_vsize;
+ double const y = event->button.y;
pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
if (tvp.first) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
case MouseDraw:
switch (item_type) {
case NoteItem:
+ /* Existing note: allow trimming/motion */
if (internal_editing()) {
/* trim notes if we're in internal edit mode and near the ends of the note */
- ArdourCanvas::CanvasNote* cn = dynamic_cast<ArdourCanvas::CanvasNote*> (item);
- if (cn && cn->big_enough_to_trim() && cn->mouse_near_ends()) {
+ NoteBase* cn = reinterpret_cast<NoteBase*>(item->get_data ("notebase"));
+ assert (cn);
+ if (cn->big_enough_to_trim() && cn->mouse_near_ends()) {
_drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor);
} else {
_drags->set (new NoteDrag (this, item), event);
}
return true;
- }
+ }
break;
case StreamItem:
if (internal_editing()) {
case MouseObject:
switch (item_type) {
case NoteItem:
+ /* Existing note: allow trimming/motion */
if (internal_editing()) {
- ArdourCanvas::CanvasNoteEvent* cn = dynamic_cast<ArdourCanvas::CanvasNoteEvent*> (item);
- if (cn->mouse_near_ends()) {
+ NoteBase* cn = reinterpret_cast<NoteBase*> (item->get_data ("notebase"));
+ assert (cn);
+ if (cn->big_enough_to_trim() && cn->mouse_near_ends()) {
_drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor);
} else {
_drags->set (new NoteDrag (this, item), event);
// }
_drags->start_grab (event);
+ return true;
break;
case RegionViewNameHighlight:
_drags->set (new RegionCreateDrag (this, item, parent), event);
} else {
/* See if there's a region before the click that we can extend, and extend it if so */
- framepos_t const t = event_frame (event);
+ framepos_t const t = canvas_event_sample (event);
boost::shared_ptr<Region> prev = pl->find_next_region (t, End, -1);
if (!prev) {
_drags->set (new RegionCreateDrag (this, item, parent), event);
{
if ( get_smart_mode() ) {
/* we're in "smart" joined mode, and we've clicked on a Selection */
- double const y = event->button.y + vertical_adjustment.get_value() - canvas_timebars_vsize;
+ double const y = event->button.y;
pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
if (tvp.first) {
/* if we're over an automation track, start a drag of its data */
boost::shared_ptr<Playlist> pl = t->playlist ();
if (pl) {
- boost::shared_ptr<Region> r = pl->top_region_at (event_frame (event));
+ boost::shared_ptr<Region> r = pl->top_region_at (canvas_event_sample (event));
if (r) {
RegionView* rv = rtv->view()->find_view (r);
clicked_selection = select_range (rv->region()->position(),
rvs.push_back (rv);
_drags->add (new RegionMoveDrag (this, item, rv, rvs, false, false));
_drags->start_grab (event);
+ return true;
}
}
}
break;
case MouseTimeFX:
- if (internal_editing() && item_type == NoteItem) {
+ if (internal_editing() && item_type == NoteItem ) {
/* drag notes if we're in internal edit mode */
- _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor);
+ NoteBase* cn = reinterpret_cast<NoteBase*>(item->get_data ("notebase"));
+ assert (cn);
+ if (cn->big_enough_to_trim()) {
+ _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor);
+ }
return true;
} else if (clicked_regionview) {
/* do time-FX */
case MouseZoom:
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
- temporal_zoom_to_frame (false, event_frame (event));
+ temporal_zoom_to_frame (false, canvas_event_sample (event));
} else {
- temporal_zoom_to_frame (true, event_frame(event));
+ temporal_zoom_to_frame (true, canvas_event_sample(event));
}
return true;
break;
bool
Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
+ if (event->type == GDK_2BUTTON_PRESS) {
+ _drags->mark_double_click ();
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ return true;
+ }
+
if (event->type != GDK_BUTTON_PRESS) {
- if (event->type == GDK_2BUTTON_PRESS) {
- gdk_pointer_ungrab (GDK_CURRENT_TIME);
- return button_double_click_handler (item, event, item_type);
- }
return false;
}
- Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->track_canvas->get_window();
+ Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->_track_canvas_viewport->get_window();
if (canvas_window) {
Glib::RefPtr<const Gdk::Window> pointer_window;
pointer_window = canvas_window->get_pointer (x, y, mask);
- if (pointer_window == track_canvas->get_bin_window()) {
- track_canvas->window_to_world (x, y, wx, wy);
+ if (pointer_window == _track_canvas->get_window()) {
+ _track_canvas->window_to_canvas (x, y, wx, wy);
}
}
pre_press_cursor = current_canvas_cursor;
-
- track_canvas->grab_focus();
+
+ _track_canvas->grab_focus();
if (_session && _session->actively_recording()) {
return true;
//not rolling, range mode click + join_play_range : locate the PH here
if ( !_drags->active () && !_session->transport_rolling() && ( effective_mouse_mode() == MouseRange ) && Config->get_always_play_range() ) {
- framepos_t where = event_frame (event, 0, 0);
+ framepos_t where = canvas_event_sample (event);
snap_to(where);
_session->request_locate (where, false);
}
return button_bindings->activate (b, Gtkmm2ext::Bindings::Release);
}
-bool
-Editor::button_double_click_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) {
-
- if (event->button.button != 1) {
- return false;
- }
-
- switch (item_type) {
- case RegionItem:
- case NoteItem:
- case PlayheadCursorItem:
- case MarkerItem:
- case RangeMarkerBarItem:
- case CdMarkerBarItem:
- case TempoMarkerItem:
- case MeterMarkerItem:
- case MarkerBarItem:
- case TempoBarItem:
- case MeterBarItem:
- case TransportMarkerBarItem:
- case StreamItem:
- break;
-
- default:
- break;
- }
- return false;
-}
-
-
-
bool
Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
- framepos_t where = event_frame (event, 0, 0);
+ framepos_t where = canvas_event_sample (event);
AutomationTimeAxisView* atv = 0;
if (pre_press_cursor) {
were_dragging = true;
}
- update_region_layering_order_editor ();
+ update_region_layering_order_editor ();
/* edit events get handled here */
show_region_properties ();
break;
- case TempoMarkerItem:
- edit_tempo_marker (item);
+ case TempoMarkerItem: {
+ Marker* marker;
+ TempoMarker* tempo_marker;
+
+ if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
+ fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if ((tempo_marker = dynamic_cast<TempoMarker*> (marker)) == 0) {
+ fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ edit_tempo_marker (*tempo_marker);
break;
+ }
- case MeterMarkerItem:
- edit_meter_marker (item);
+ case MeterMarkerItem: {
+ Marker* marker;
+ MeterMarker* meter_marker;
+
+ if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
+ fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if ((meter_marker = dynamic_cast<MeterMarker*> (marker)) == 0) {
+ fatal << _("programming error: marker for meter is not a meter marker!") << endmsg;
+ /*NOTREACHED*/
+ }
+ edit_meter_marker (*meter_marker);
break;
+ }
case RegionViewName:
if (clicked_regionview->name_active()) {
case MeterBarItem:
if (!_dragging_playhead) {
- mouse_add_new_meter_event (pixel_to_frame (event->button.x));
+ mouse_add_new_meter_event (pixel_to_sample (event->button.x));
}
return true;
break;
case AutomationTrackItem:
atv = dynamic_cast<AutomationTimeAxisView*>(clicked_axisview);
if (atv) {
- atv->add_automation_event (event, where, event->button.y);
+ bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+ atv->add_automation_event (event, where, event->button.y, with_guard_points);
}
return true;
break;
*/
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (clicked_regionview);
if (!were_dragging && arv) {
- arv->add_gain_point_event (item, event);
+ bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+ arv->add_gain_point_event (item, event, with_guard_points);
}
return true;
break;
}
- case AutomationTrackItem:
+ case AutomationTrackItem: {
+ bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
dynamic_cast<AutomationTimeAxisView*>(clicked_axisview)->
- add_automation_event (event, where, event->button.y);
+ add_automation_event (event, where, event->button.y, with_guard_points);
return true;
break;
+ }
default:
break;
}
case ControlPointItem:
if (mouse_mode == MouseGain || mouse_mode == MouseObject) {
cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
- cp->set_visible (true);
+ cp->show ();
double at_x, at_y;
at_x = cp->get_x();
case GainLineItem:
if (mouse_mode == MouseGain) {
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
- if (line)
- line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredGainLine.get();
+ if (line) {
+ line->set_outline_color (ARDOUR_UI::config()->get_canvasvar_EnteredGainLine());
+ }
if (is_drawable()) {
set_canvas_cursor (_cursors->fader);
}
if (mouse_mode == MouseGain || mouse_mode == MouseObject) {
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
if (line) {
- line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredAutomationLine.get();
+ line->set_outline_color (ARDOUR_UI::config()->get_canvasvar_EnteredAutomationLine());
}
if (is_drawable()) {
set_canvas_cursor (_cursors->fader);
}
break;
+ case RegionItem:
+ switch (effective_mouse_mode()) {
+ case MouseRange:
+ set_canvas_cursor (_cursors->selector);
+ break;
+ default:
+ set_canvas_cursor (which_grabber_cursor());
+ break;
+ }
+ break;
+
case StartSelectionTrimItem:
if (is_drawable()) {
set_canvas_cursor (_cursors->left_side_trim);
}
break;
+
case RegionViewName:
/* when the name is not an active item, the entire name highlight is for trimming */
break;
}
entered_marker = marker;
- marker->set_color_rgba (ARDOUR_UI::config()->canvasvar_EnteredMarker.get());
+ marker->set_color_rgba (ARDOUR_UI::config()->get_canvasvar_EnteredMarker());
// fall through
case MeterMarkerItem:
case TempoMarkerItem:
case FadeInHandleItem:
if (mouse_mode == MouseObject && !internal_editing()) {
- ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item);
+ ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
if (rect) {
- rect->property_fill_color_rgba() = 0xBBBBBBAA;
+ RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
+ rect->set_fill_color (rv->get_fill_color());
+ set_canvas_cursor (_cursors->fade_in);
}
- set_canvas_cursor (_cursors->fade_in);
}
break;
case FadeOutHandleItem:
if (mouse_mode == MouseObject && !internal_editing()) {
- ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item);
+ ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
if (rect) {
- rect->property_fill_color_rgba() = 0xBBBBBBAA;
+ RegionView* rv = static_cast<RegionView*>(item->get_data ("regionview"));
+ rect->set_fill_color (rv->get_fill_color ());
+ set_canvas_cursor (_cursors->fade_out);
}
- set_canvas_cursor (_cursors->fade_out);
}
break;
case FeatureLineItem:
- {
- ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
- line->property_fill_color_rgba() = 0xFF0000FF;
- }
- break;
+ {
+ ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
+ line->set_outline_color (0xFF0000FF);
+ }
+ break;
+
case SelectionItem:
if ( get_smart_mode() ) {
set_canvas_cursor ();
Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type)
{
AutomationLine* al;
- ControlPoint* cp;
Marker *marker;
Location *loc;
RegionView* rv;
switch (item_type) {
case ControlPointItem:
- cp = reinterpret_cast<ControlPoint*>(item->get_data ("control_point"));
- if (cp->line().the_list()->interpolation() != AutomationList::Discrete) {
- if (cp->line().npoints() > 1 && !cp->get_selected()) {
- cp->set_visible (false);
- }
- }
-
if (is_drawable()) {
set_canvas_cursor (current_canvas_cursor);
}
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
- if (line)
- line->property_fill_color_rgba() = al->get_line_color();
+ if (line) {
+ line->set_outline_color (al->get_line_color());
+ }
}
if (is_drawable()) {
set_canvas_cursor (current_canvas_cursor);
case FadeOutHandleItem:
rv = static_cast<RegionView*>(item->get_data ("regionview"));
{
- ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item);
+ ArdourCanvas::Rectangle *rect = dynamic_cast<ArdourCanvas::Rectangle *> (item);
if (rect) {
- rect->property_fill_color_rgba() = rv->get_fill_color();
+ rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_InactiveFadeHandle());
}
}
set_canvas_cursor (current_canvas_cursor);
case FeatureLineItem:
{
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
- line->property_fill_color_rgba() = (guint) ARDOUR_UI::config()->canvasvar_ZeroLine.get();;
+ line->set_outline_color (ARDOUR_UI::config()->get_canvasvar_ZeroLine());
}
break;
event might do, its a good tradeoff.
*/
- track_canvas->get_pointer (x, y);
+ _track_canvas->get_pointer (x, y);
}
if (current_stepping_trackview) {
void
Editor::reposition_zoom_rect (framepos_t start, framepos_t end)
{
- double x1 = frame_to_pixel (start);
- double x2 = frame_to_pixel (end);
- double y2 = full_canvas_height - 1.0;
-
- zoom_rect->property_x1() = x1;
- zoom_rect->property_y1() = 1.0;
- zoom_rect->property_x2() = x2;
- zoom_rect->property_y2() = y2;
+ double x1 = sample_to_pixel (start);
+ double x2 = sample_to_pixel (end);
+ double y2 = _full_canvas_height - 1.0;
+
+ zoom_rect->set (ArdourCanvas::Rect (x1, 1.0, x2, y2));
}
} else {
_drags->add (new RegionMoveDrag (this, item, region_view, selection->regions.by_layer(), false, false));
}
-
- /* sync the canvas to what we think is its current state */
- update_canvas_now();
}
void
}
/* XXX: maybe we should make entered_track work in all cases, rather than resorting to this */
- pair<TimeAxisView*, int> tvp = trackview_by_y_position (y + vertical_adjustment.get_value() - canvas_timebars_vsize);
+ pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
if (tvp.first) {
double cx = 0;
double cy = y;
- rtv->canvas_display()->w2i (cx, cy);
+ rtv->canvas_display()->canvas_to_item (cx, cy);
double const c = cy / (rtv->view()->child_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE);
void
Editor::remove_midi_note (ArdourCanvas::Item* item, GdkEvent *)
{
- ArdourCanvas::CanvasNoteEvent* e = dynamic_cast<ArdourCanvas::CanvasNoteEvent*> (item);
+ NoteBase* e = reinterpret_cast<NoteBase*> (item->get_data ("notebase"));
assert (e);
e->region_view().delete_note (e->note ());
void
Editor::set_canvas_cursor_for_region_view (double x, RegionView* rv)
{
- assert (rv);
+ /* XXX: this check should not be necessary */
+ if (rv == 0) {
+ return;
+ }
ArdourCanvas::Group* g = rv->get_canvas_group ();
- ArdourCanvas::Group* p = g->get_parent_group ();
+ ArdourCanvas::Group* p = g->parent ();
/* Compute x in region view parent coordinates */
double dy = 0;
- p->w2i (x, dy);
+ p->canvas_to_item (x, dy);
- double x1, x2, y1, y2;
- g->get_bounds (x1, y1, x2, y2);
+ boost::optional<ArdourCanvas::Rect> item_bbox = g->bounding_box ();
+ assert (item_bbox);
+ ArdourCanvas::Rect parent_bbox = g->item_to_parent (item_bbox.get ());
- /* Halfway across the region */
- double const h = (x1 + x2) / 2;
+ /* First or last 10% of region is used for trimming, if the whole
+ region is wider than 20 pixels at the current zoom level.
+ */
- Trimmable::CanTrim ct = rv->region()->can_trim ();
- if (x <= h) {
- if (ct & Trimmable::FrontTrimEarlier) {
- set_canvas_cursor (_cursors->left_side_trim);
- } else {
- set_canvas_cursor (_cursors->left_side_trim_right_only);
- }
- } else {
- if (ct & Trimmable::EndTrimLater) {
- set_canvas_cursor (_cursors->right_side_trim);
- } else {
- set_canvas_cursor (_cursors->right_side_trim_left_only);
+ double const w = parent_bbox.width();
+
+ if (w > 20.0 && x >= parent_bbox.x0 && x < parent_bbox.x1) {
+
+ Trimmable::CanTrim ct = rv->region()->can_trim ();
+
+ if (((x - parent_bbox.x0) / w) < 0.10) {
+ if (ct & Trimmable::FrontTrimEarlier) {
+ set_canvas_cursor (_cursors->left_side_trim, true);
+ } else {
+ set_canvas_cursor (_cursors->left_side_trim_right_only, true);
+ }
+ } else if (((parent_bbox.x1 - x) / w) < 0.10) {
+ if (ct & Trimmable::EndTrimLater) {
+ set_canvas_cursor (_cursors->right_side_trim, true);
+ } else {
+ set_canvas_cursor (_cursors->right_side_trim_left_only, true);
+ }
}
}
}
-/** Obtain the pointer position in world coordinates */
+/** Obtain the pointer position in canvas coordinates */
void
Editor::get_pointer_position (double& x, double& y) const
{
int px, py;
- track_canvas->get_pointer (px, py);
- track_canvas->window_to_world (px, py, x, y);
+ _track_canvas->get_pointer (px, py);
+ _track_canvas->window_to_canvas (px, py, x, y);
}