_trackview_group = new ArdourCanvas::Group (hv_scroll_group);
CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews");
+ // used to show zoom mode active zooming
+ zoom_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
+ zoom_rect->hide();
+ zoom_rect->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_zoom_rect_event), (ArdourCanvas::Item*) 0));
+
+ // used as rubberband rect
+ rubberband_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
+ rubberband_rect->hide();
+
+ /* a group to hold stuff while it gets dragged around. Must be the
+ * uppermost (last) group with hv_scroll_group as a parent
+ */
+ _drag_motion_group = new ArdourCanvas::Group (hv_scroll_group);
+ CANVAS_DEBUG_NAME (_drag_motion_group, "Canvas Drag Motion");
+
/* TIME BAR CANVAS */
_time_markers_group = new ArdourCanvas::Group (h_scroll_group);
transport_punchout_line->set_y1 (ArdourCanvas::COORD_MAX);
transport_punchout_line->hide();
- // used to show zoom mode active zooming
- zoom_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
- zoom_rect->hide();
- zoom_rect->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_zoom_rect_event), (ArdourCanvas::Item*) 0));
-
- // used as rubberband rect
- rubberband_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
- rubberband_rect->hide();
-
tempo_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_tempo_bar_event), tempo_bar));
meter_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_meter_bar_event), meter_bar));
marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_marker_bar_event), marker_bar));
}
- _canvas_bottom_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, 20));
+ _canvas_drop_zone = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, 0.0));
/* this thing is transparent */
- _canvas_bottom_rect->set_fill (false);
- _canvas_bottom_rect->set_outline (false);
- _canvas_bottom_rect->Event.connect (sigc::mem_fun (*this, &Editor::canvas_bottom_rect_event));
+ _canvas_drop_zone->set_fill (false);
+ _canvas_drop_zone->set_outline (false);
+ _canvas_drop_zone->Event.connect (sigc::mem_fun (*this, &Editor::canvas_drop_zone_event));
/* these signals will initially be delivered to the canvas itself, but if they end up remaining unhandled, they are passed to Editor-level
handlers.
*/
- _track_canvas->signal_scroll_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_scroll_event));
+ _track_canvas->signal_scroll_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_scroll_event), true));
_track_canvas->signal_motion_notify_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_motion_notify_event));
_track_canvas->signal_button_press_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_button_press_event));
_track_canvas->signal_button_release_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_button_release_event));
_track_canvas_viewport->signal_size_allocate().connect (sigc::mem_fun(*this, &Editor::track_canvas_viewport_allocate));
+ initialize_rulers ();
+
ColorsChanged.connect (sigc::mem_fun (*this, &Editor::color_handler));
color_handler();
_visible_canvas_width = _canvas_viewport_allocation.get_width ();
_visible_canvas_height = _canvas_viewport_allocation.get_height ();
+ _canvas_drop_zone->set_y1 (_canvas_drop_zone->y0() + (_visible_canvas_height - 20.0));
+
// SHOWTRACKS
if (height_changed) {
* (the drag-n-drop zone) is, in fact, at the bottom.
*/
- _canvas_bottom_rect->set_position (ArdourCanvas::Duple (0, h));
+ _canvas_drop_zone->set_position (ArdourCanvas::Duple (0, h));
/* track controls layout must span the full height of "h" (all tracks)
* plus the bottom rect.
*/
- h += _canvas_bottom_rect->height ();
+ h += _canvas_drop_zone->height ();
/* set the height of the scrollable area (i.e. the sum of all contained widgets)
* for the controls layout. The size request is set elsewhere.
void
Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
{
- if (!Config->get_autoscroll_editor ()) {
+ if (!Config->get_autoscroll_editor () || autoscroll_active ()) {
return;
}
+ /* define a rectangular boundary for scrolling. If the mouse moves
+ * outside of this area and/or continue to be outside of this area,
+ * then we will continuously auto-scroll the canvas in the appropriate
+ * direction(s)
+ *
+ * the boundary is defined in coordinates relative to the toplevel
+ * window since that is what we're going to call ::get_pointer() on
+ * during autoscrolling to determine if we're still outside the
+ * boundary or not.
+ */
+
ArdourCanvas::Rect scrolling_boundary;
Gtk::Allocation alloc;
-
+ int cx, cy;
+
if (from_headers) {
alloc = controls_layout.get_allocation ();
- } else {
+ } else {
alloc = _track_canvas_viewport->get_allocation ();
+ cx = alloc.get_x();
+ cy = alloc.get_y();
+
+ /* reduce height by the height of the timebars, which happens
+ to correspond to the position of the hv_scroll_group.
+ */
+ alloc.set_height (alloc.get_height() - hv_scroll_group->position().y);
+ alloc.set_y (alloc.get_y() + hv_scroll_group->position().y);
+
+ /* now reduce it again so that we start autoscrolling before we
+ * move off the top or bottom of the canvas
+ */
+
+ alloc.set_height (alloc.get_height() - 20);
+ alloc.set_y (alloc.get_y() + 10);
+
/* the effective width of the autoscroll boundary so
that we start scrolling before we hit the edge.
alloc.set_width (alloc.get_width() - 20);
alloc.set_x (alloc.get_x() + 10);
}
+
}
- scrolling_boundary = ArdourCanvas::Rect (alloc.get_x(), alloc.get_y(),
- alloc.get_x() + alloc.get_width(),
- alloc.get_y() + alloc.get_height());
+ scrolling_boundary = ArdourCanvas::Rect (alloc.get_x(), alloc.get_y(), alloc.get_x() + alloc.get_width(), alloc.get_y() + alloc.get_height());
int x, y;
Gdk::ModifierType mask;
get_window()->get_pointer (x, y, mask);
- if ((allow_horiz && (x < scrolling_boundary.x0 || x >= scrolling_boundary.x1)) ||
- (allow_vert && (y < scrolling_boundary.y0 || y >= scrolling_boundary.y1))) {
+ if ((allow_horiz && ((x < scrolling_boundary.x0 && leftmost_frame > 0) || x >= scrolling_boundary.x1)) ||
+ (allow_vert && ((y < scrolling_boundary.y0 && vertical_adjustment.get_value() > 0)|| y >= scrolling_boundary.y1))) {
start_canvas_autoscroll (allow_horiz, allow_vert, scrolling_boundary);
}
}
get_window()->get_pointer (x, y, mask);
VisualChange vc;
+ bool vertical_motion = false;
if (autoscroll_horizontal_allowed) {
if (autoscroll_vertical_allowed) {
- const double vertical_pos = vertical_adjustment.get_value();
- const int speed_factor = 20;
+ // const double vertical_pos = vertical_adjustment.get_value();
+ const int speed_factor = 10;
/* vertical */
if (autoscroll_cnt && (autoscroll_cnt % speed_factor == 0)) {
y_motion = scroll_up_one_track ();
+ vertical_motion = true;
}
} else if (y > autoscroll_boundary.y1) {
if (autoscroll_cnt && (autoscroll_cnt % speed_factor == 0)) {
y_motion = scroll_down_one_track ();
-
+ vertical_motion = true;
}
}
no_stop = true;
}
- if (vc.pending) {
+ if (vc.pending || vertical_motion) {
/* change horizontal first */
/* the motion handler expects events in canvas coordinate space */
- /* first convert from Editor window coordinates to canvas
- * window coordinates
+ /* we asked for the mouse position above (::get_pointer()) via
+ * our own top level window (we being the Editor). Convert into
+ * coordinates within the canvas window.
*/
int cx;
int cy;
- /* clamp x and y to remain within the visible area */
+ translate_coordinates (*_track_canvas, x, y, cx, cy);
- x = min (max ((ArdourCanvas::Coord) x, autoscroll_boundary.x0), autoscroll_boundary.x1);
- y = min (max ((ArdourCanvas::Coord) y, autoscroll_boundary.y0), autoscroll_boundary.y1);
+ /* clamp x and y to remain within the autoscroll boundary,
+ * which is defined in window coordinates
+ */
- translate_coordinates (*_track_canvas_viewport, x, y, cx, cy);
+ x = min (max ((ArdourCanvas::Coord) cx, autoscroll_boundary.x0), autoscroll_boundary.x1);
+ y = min (max ((ArdourCanvas::Coord) cy, autoscroll_boundary.y0), autoscroll_boundary.y1);
+
+ /* now convert from Editor window coordinates to canvas
+ * window coordinates
+ */
ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy));
ev.x = d.x;
ev.y = d.y;
motion_handler (0, (GdkEvent*) &ev, true);
-
+
} else if (no_stop) {
/* not changing visual state but pointer is outside the scrolling boundary
ev.y = d.y;
motion_handler (0, (GdkEvent*) &ev, true);
-
+
} else {
stop_canvas_autoscroll ();
return false;
void
Editor::color_handler()
{
+ ArdourCanvas::Color base = ARDOUR_UI::config()->get_canvasvar_RulerBase();
+ ArdourCanvas::Color text = ARDOUR_UI::config()->get_canvasvar_RulerText();
+ timecode_ruler->set_fill_color (base);
+ timecode_ruler->set_outline_color (text);
+ minsec_ruler->set_fill_color (base);
+ minsec_ruler->set_outline_color (text);
+ samples_ruler->set_fill_color (base);
+ samples_ruler->set_outline_color (text);
+ bbt_ruler->set_fill_color (base);
+ bbt_ruler->set_outline_color (text);
+
playhead_cursor->set_color (ARDOUR_UI::config()->get_canvasvar_PlayHead());
_verbose_cursor->set_color (ARDOUR_UI::config()->get_canvasvar_VerboseCanvasCursor());
}
}
+void
+Editor::push_canvas_cursor (Gdk::Cursor* cursor)
+{
+ if (cursor) {
+ _cursor_stack.push (cursor);
+ set_canvas_cursor (cursor, false);
+ }
+}
+
+void
+Editor::pop_canvas_cursor ()
+{
+ if (!_cursor_stack.empty()) {
+ Gdk::Cursor* cursor = _cursor_stack.top ();
+ _cursor_stack.pop ();
+ set_canvas_cursor (cursor, false);
+ }
+}
+
bool
Editor::track_canvas_key_press (GdkEventKey*)
{