#include <jack/types.h>
#include <gtkmm2ext/utils.h>
-#include <ardour/audioregion.h>
-#include <ardour/profile.h>
+#include "ardour/profile.h"
#include "ardour_ui.h"
#include "editor.h"
#include "editing.h"
#include "rgb_macros.h"
#include "utils.h"
-#include "time_axis_view.h"
#include "audio_time_axis.h"
+#include "editor_drag.h"
+#include "region_view.h"
+#include "editor_group_tabs.h"
+#include "editor_routes.h"
#include "i18n.h"
_background_group = new ArdourCanvas::Group (*track_canvas->root());
_master_group = new ArdourCanvas::Group (*track_canvas->root());
- range_marker_drag_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, physical_screen_height);
- range_marker_drag_rect->hide ();
-
_trackview_group = new ArdourCanvas::Group (*_master_group);
_region_motion_group = new ArdourCanvas::Group (*_trackview_group);
marker_group = new ArdourCanvas::Group (*timebar_group, 0.0, timebar_height);
cd_marker_group = new ArdourCanvas::Group (*timebar_group, 0.0, 0.0);
- marker_drag_line_points.push_back(Gnome::Art::Point(0.0, 0.0));
- marker_drag_line_points.push_back(Gnome::Art::Point(0.0, physical_screen_height));
-
- marker_drag_line = new ArdourCanvas::Line (*timebar_group);
- marker_drag_line->property_width_pixels() = 1;
- marker_drag_line->property_points() = marker_drag_line_points;
- marker_drag_line->hide();
-
cd_marker_bar_drag_rect = new ArdourCanvas::SimpleRect (*cd_marker_group, 0.0, 0.0, 100, timebar_height);
cd_marker_bar_drag_rect->property_outline_pixels() = 0;
cd_marker_bar_drag_rect->hide ();
range_marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_range_marker_bar_event), range_marker_bar));
transport_marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_transport_marker_bar_event), transport_marker_bar));
- playhead_cursor = new Cursor (*this, &Editor::canvas_playhead_cursor_event);
+ playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event);
if (logo_item) {
logo_item->lower_to_bottom ();
track_canvas->signal_motion_notify_event().connect (mem_fun (*this, &Editor::track_canvas_motion_notify_event));
track_canvas->signal_button_press_event().connect (mem_fun (*this, &Editor::track_canvas_button_press_event));
track_canvas->signal_button_release_event().connect (mem_fun (*this, &Editor::track_canvas_button_release_event));
+ track_canvas->signal_drag_motion().connect (mem_fun (*this, &Editor::track_canvas_drag_motion));
track_canvas->set_name ("EditorMainCanvas");
track_canvas->add_events (Gdk::POINTER_MOTION_HINT_MASK|Gdk::SCROLL_MASK);
bool
Editor::track_canvas_size_allocated ()
{
- bool height_changed = canvas_height != canvas_allocation.get_height();
+ bool height_changed = _canvas_height != canvas_allocation.get_height();
- canvas_width = canvas_allocation.get_width();
- canvas_height = canvas_allocation.get_height();
+ _canvas_width = canvas_allocation.get_width();
+ _canvas_height = canvas_allocation.get_height();
if (session) {
TrackViewList::iterator i;
if (height_changed) {
if (playhead_cursor) {
- playhead_cursor->set_length (canvas_height);
+ playhead_cursor->set_length (_canvas_height);
}
for (MarkerSelection::iterator x = selection->markers.begin(); x != selection->markers.end(); ++x) {
- (*x)->set_line_vpos (0, canvas_height);
+ (*x)->set_line_vpos (0, _canvas_height);
}
- vertical_adjustment.set_page_size (canvas_height);
+ vertical_adjustment.set_page_size (_canvas_height);
last_trackview_group_vertical_offset = get_trackview_group_vertical_offset ();
- if ((vertical_adjustment.get_value() + canvas_height) >= vertical_adjustment.get_upper()) {
+ if ((vertical_adjustment.get_value() + _canvas_height) >= vertical_adjustment.get_upper()) {
/*
We're increasing the size of the canvas while the bottom is visible.
We scroll down to keep in step with the controls layout.
*/
- vertical_adjustment.set_value (full_canvas_height - canvas_height);
+ vertical_adjustment.set_value (full_canvas_height - _canvas_height);
}
}
reset_hscrollbar_stepping ();
update_fixed_rulers();
redisplay_tempo (false);
+ _summary->set_overlays_dirty ();
Resized (); /* EMIT_SIGNAL */
void
Editor::controls_layout_size_request (Requisition* req)
{
- TreeModel::Children rows = route_display_model->children();
- TreeModel::Children::iterator i;
- double pos;
- bool changed = false;
-
- for (pos = 0, i = rows.begin(); i != rows.end(); ++i) {
- TimeAxisView *tv = (*i)[route_display_columns.tv];
- if (tv != 0) {
- pos += tv->effective_height ();
- tv->clip_to_viewport ();
- }
+ double pos = 0;
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ pos += (*i)->effective_height ();
+ (*i)->clip_to_viewport ();
}
gint height = min ((gint) pos, (gint) (physical_screen_height - 600));
- gint width = max (edit_controls_vbox.get_width(), controls_layout.get_width());
+
+ bool changed = false;
+
+ gint w = edit_controls_vbox.get_width();
+ if (_group_tabs->is_mapped()) {
+ w += _group_tabs->get_width ();
+ }
+
+ gint width = max (w, controls_layout.get_width());
/* don't get too big. the fudge factors here are just guesses */
if (req->width != width) {
gint vbox_width = edit_controls_vbox.get_width();
+ if (_group_tabs->is_mapped()) {
+ vbox_width += _group_tabs->get_width();
+ }
req->width = width;
/* this one is important: it determines how big the layout thinks it really is, as
controls_layout.property_width () = vbox_width;
controls_layout.property_width_request () = vbox_width;
- time_button_event_box.property_width_request () = vbox_width;
- zoom_box.property_width_request () = vbox_width;
+ // time_button_event_box.property_width_request () = vbox_width;
+ // zoom_box.property_width_request () = vbox_width;
}
if (req->height != height) {
}
bool
-Editor::track_canvas_map_handler (GdkEventAny* ev)
+Editor::track_canvas_map_handler (GdkEventAny* /*ev*/)
{
- track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+ if (current_canvas_cursor) {
+ track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+ }
return false;
}
}
void
-Editor::drop_regions (const RefPtr<Gdk::DragContext>& context,
- int x, int y,
- const SelectionData& data,
- guint info, guint time)
+Editor::drop_regions (const RefPtr<Gdk::DragContext>& /*context*/,
+ int /*x*/, int /*y*/,
+ const SelectionData& /*data*/,
+ guint /*info*/, guint /*time*/)
{
- std::list<boost::shared_ptr<Region> > regions;
- region_list_display.get_object_drag_data (regions);
-
- for (list<boost::shared_ptr<Region> >::iterator r = regions.begin(); r != regions.end(); ++r) {
-
- boost::shared_ptr<AudioRegion> ar;
-
- if ((ar = boost::dynamic_pointer_cast<AudioRegion>(*r)) != 0) {
- insert_region_list_drag (ar, x, y);
- }
- }
-
- context->drag_finish (true, false, time);
+ assert (_drag);
+ _drag->end_grab (0);
+ delete _drag;
+ _drag = 0;
}
void
-Editor::maybe_autoscroll (GdkEventMotion* event)
+Editor::maybe_autoscroll (GdkEventMotion* event, bool allow_vert)
{
-
nframes64_t rightmost_frame = leftmost_frame + current_page_frames();
- nframes64_t frame = drag_info.current_pointer_frame;
+ nframes64_t frame = _drag->current_pointer_frame();
bool startit = false;
autoscroll_y = 0;
autoscroll_x = 0;
- if (event->y < canvas_timebars_vsize) {
+ if (event->y < canvas_timebars_vsize && allow_vert) {
autoscroll_y = -1;
startit = true;
- } else if (event->y > canvas_height) {
+ } else if (event->y > _canvas_height) {
autoscroll_y = 1;
startit = true;
}
last_autoscroll_y = autoscroll_y;
}
-void
-Editor::maybe_autoscroll_horizontally (GdkEventMotion* event)
-{
- nframes64_t rightmost_frame = leftmost_frame + current_page_frames();
- nframes64_t frame = drag_info.current_pointer_frame;
- bool startit = false;
-
- autoscroll_y = 0;
- autoscroll_x = 0;
-
- if (frame > rightmost_frame) {
-
- if (rightmost_frame < max_frames) {
- autoscroll_x = 1;
- startit = true;
- }
-
- } else if (frame < leftmost_frame) {
- if (leftmost_frame > 0) {
- autoscroll_x = -1;
- startit = true;
- }
-
- }
-
- if ((autoscroll_x != last_autoscroll_x) || (autoscroll_y != last_autoscroll_y) || (autoscroll_x == 0 && autoscroll_y == 0)) {
- stop_canvas_autoscroll ();
- }
-
- if (startit && autoscroll_timeout_tag < 0) {
- start_canvas_autoscroll (autoscroll_x, autoscroll_y);
- }
-
- last_autoscroll_x = autoscroll_x;
- last_autoscroll_y = autoscroll_y;
-}
-
gint
Editor::_autoscroll_canvas (void *arg)
{
double new_pixel;
double target_pixel;
+ assert (_drag);
+
if (autoscroll_x_distance != 0) {
if (autoscroll_x > 0) {
- autoscroll_x_distance = (unit_to_frame (drag_info.current_pointer_x) - (leftmost_frame + current_page_frames())) / 3;
+ autoscroll_x_distance = (unit_to_frame (_drag->current_pointer_x()) - (leftmost_frame + current_page_frames())) / 3;
} else if (autoscroll_x < 0) {
- autoscroll_x_distance = (leftmost_frame - unit_to_frame (drag_info.current_pointer_x)) / 3;
+ autoscroll_x_distance = (leftmost_frame - unit_to_frame (_drag->current_pointer_x())) / 3;
}
}
if (autoscroll_y_distance != 0) {
if (autoscroll_y > 0) {
- autoscroll_y_distance = (drag_info.current_pointer_y - (get_trackview_group_vertical_offset() + canvas_height)) / 3;
+ autoscroll_y_distance = (_drag->current_pointer_y() - (get_trackview_group_vertical_offset() + _canvas_height)) / 3;
} else if (autoscroll_y < 0) {
- autoscroll_y_distance = (vertical_adjustment.get_value () - drag_info.current_pointer_y) / 3;
+ autoscroll_y_distance = (vertical_adjustment.get_value () - _drag->current_pointer_y()) / 3;
}
}
new_pixel = vertical_pos - autoscroll_y_distance;
}
- target_pixel = drag_info.current_pointer_y - autoscroll_y_distance;
+ target_pixel = _drag->current_pointer_y() - autoscroll_y_distance;
target_pixel = max (target_pixel, 0.0);
} else if (autoscroll_y > 0) {
- double top_of_bottom_of_canvas = full_canvas_height - canvas_height;
+ double top_of_bottom_of_canvas = full_canvas_height - _canvas_height;
if (vertical_pos > full_canvas_height - autoscroll_y_distance) {
new_pixel = full_canvas_height;
new_pixel = min (top_of_bottom_of_canvas, new_pixel);
- target_pixel = drag_info.current_pointer_y + autoscroll_y_distance;
+ target_pixel = _drag->current_pointer_y() + autoscroll_y_distance;
/* don't move to the full canvas height because the item will be invisible
(its top edge will line up with the bottom of the visible canvas.
target_pixel = min (target_pixel, full_canvas_height - 10);
} else {
- target_pixel = drag_info.current_pointer_y;
+ target_pixel = _drag->current_pointer_y();
new_pixel = vertical_pos;
}
ev.x = x;
ev.y = y;
- motion_handler (drag_info.item, (GdkEvent*) &ev, drag_info.item_type, true);
+ motion_handler (_drag->item(), (GdkEvent*) &ev, true);
autoscroll_cnt++;
}
bool
-Editor::left_track_canvas (GdkEventCrossing *ev)
+Editor::left_track_canvas (GdkEventCrossing */*ev*/)
{
set_entered_track (0);
set_entered_regionview (0);
}
bool
-Editor::entered_track_canvas (GdkEventCrossing *ev)
+Editor::entered_track_canvas (GdkEventCrossing */*ev*/)
{
reset_canvas_action_sensitivity (true);
return FALSE;
/* this will do an immediate redraw */
controls_layout.get_vadjustment()->set_value (vertical_adjustment.get_value());
+
+ if (pending_visual_change.idle_handler_id < 0) {
+ _summary->set_overlays_dirty ();
+ }
}
void
Editor::scroll_canvas_horizontally ()
{
- nframes64_t time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
-
- if (time_origin != leftmost_frame) {
- canvas_scroll_to (time_origin);
- }
-
/* horizontal scrolling only */
- double x1, x2, y1, y2, x_delta;
+ double x1, y1, x2, y2, x_delta;
+ _master_group->get_bounds (x1, y1, x2, y2);
+
+ x_delta = - (x1 + horizontal_adjustment.get_value());
- _master_group->get_bounds(x1, y1, x2, y2);
- x_delta = x1 + horizontal_adjustment.get_value();
+ _master_group->move (x_delta, 0);
+ timebar_group->move (x_delta, 0);
+ time_line_group->move (x_delta, 0);
+ cursor_group->move (x_delta, 0);
- _master_group->move (-x_delta, 0);
- timebar_group->move (-x_delta, 0);
- time_line_group->move (-x_delta, 0);
- cursor_group->move (-x_delta, 0);
+ leftmost_frame = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
update_fixed_rulers ();
redisplay_tempo (true);
+ if (pending_visual_change.idle_handler_id < 0) {
+ _summary->set_overlays_dirty ();
+ }
+
#ifndef GTKOSX
if (!autoscroll_active) {
/* force rulers and canvas to move in lock step */
}
last_trackview_group_vertical_offset = get_trackview_group_vertical_offset ();
/* required to keep the controls_layout in lock step with the canvas group */
- track_canvas->update_now ();
-}
-
-void
-Editor::canvas_horizontally_scrolled ()
-{
- nframes64_t time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
-
- if (time_origin != leftmost_frame) {
- canvas_scroll_to (time_origin);
- }
- redisplay_tempo (true);
-}
-
-void
-Editor::canvas_scroll_to (nframes64_t time_origin)
-{
- leftmost_frame = time_origin;
+ update_canvas_now ();
}
void
transport_bar_drag_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TransportDragRect.get();
transport_bar_drag_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_TransportDragRect.get();
- marker_drag_line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerDragLine.get();
-
- range_marker_drag_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_RangeDragRect.get();
- range_marker_drag_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_RangeDragRect.get();
-
transport_loop_range_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TransportLoopRect.get();
transport_loop_range_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_TransportLoopRect.get();
Editor::flush_canvas ()
{
if (is_mapped()) {
- track_canvas->update_now ();
+ update_canvas_now ();
// gdk_window_process_updates (GTK_LAYOUT(track_canvas->gobj())->bin_window, true);
}
}
+void
+Editor::update_canvas_now ()
+{
+ /* GnomeCanvas has a bug whereby if its idle handler is not scheduled between
+ two calls to update_now, an assert will trip. This wrapper works around
+ that problem by only calling update_now if the assert will not trip.
+
+ I think the GC bug is due to the fact that its code will reset need_update
+ and need_redraw to FALSE without checking to see if an idle handler is scheduled.
+ If one is scheduled, GC should probably remove it.
+ */
+
+ GnomeCanvas* c = track_canvas->gobj ();
+ if (c->need_update || c->need_redraw) {
+ track_canvas->update_now ();
+ }
+}