1 #include "ardour/session.h"
2 #include "time_axis_view.h"
3 #include "streamview.h"
4 #include "editor_summary.h"
5 #include "gui_thread.h"
7 #include "region_view.h"
11 using namespace ARDOUR;
13 /** Construct an EditorSummary.
14 * @param e Editor to represent.
16 EditorSummary::EditorSummary (Editor* e)
20 _regions_dirty (true),
23 _pixels_per_frame (1),
36 EditorSummary::set_session (Session* s)
40 Region::RegionPropertyChanged.connect (sigc::hide (mem_fun (*this, &EditorSummary::set_dirty)));
42 _session->RegionRemoved.connect (sigc::hide (mem_fun (*this, &EditorSummary::set_dirty)));
43 _session->EndTimeChanged.connect (mem_fun (*this, &EditorSummary::set_dirty));
44 _session->StartTimeChanged.connect (mem_fun (*this, &EditorSummary::set_dirty));
50 EditorSummary::~EditorSummary ()
53 gdk_pixmap_unref (_pixmap);
57 /** Handle an expose event.
58 * @param event Event from GTK.
61 EditorSummary::on_expose_event (GdkEventExpose* event)
63 /* Render the regions pixmap */
65 Gdk::Rectangle const exposure (
66 event->area.x, event->area.y, event->area.width, event->area.height
69 Gdk::Rectangle r = exposure;
70 Gdk::Rectangle content (0, 0, _width, _height);
72 r.intersect (content, intersects);
76 GdkPixmap* p = get_pixmap (get_window()->gobj ());
80 get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(),
91 /* Render the view rectangle */
93 pair<double, double> x;
94 pair<double, double> y;
97 cairo_t* cr = gdk_cairo_create (get_window()->gobj());
99 cairo_set_source_rgba (cr, 0, 1, 0, 0.5);
101 cairo_move_to (cr, x.first, y.first);
102 cairo_line_to (cr, x.second, y.first);
103 cairo_line_to (cr, x.second, y.second);
104 cairo_line_to (cr, x.first, y.second);
105 cairo_line_to (cr, x.first, y.first);
113 /** @param drawable GDK drawable.
114 * @return pixmap for the regions.
117 EditorSummary::get_pixmap (GdkDrawable* drawable)
119 if (_regions_dirty) {
122 gdk_pixmap_unref (_pixmap);
124 _pixmap = gdk_pixmap_new (drawable, _width, _height, -1);
126 cairo_t* cr = gdk_cairo_create (_pixmap);
130 _regions_dirty = false;
136 /** Render the required regions to a cairo context.
140 EditorSummary::render (cairo_t* cr)
148 cairo_set_source_rgb (cr, 0, 0, 0);
149 cairo_rectangle (cr, 0, 0, _width, _height);
152 /* compute total height of all tracks */
155 for (PublicEditor::TrackViewList::const_iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
156 h += (*i)->effective_height ();
159 nframes_t const start = _session->current_start_frame ();
160 _pixels_per_frame = static_cast<double> (_width) / (_session->current_end_frame() - start);
161 _vertical_scale = static_cast<double> (_height) / h;
166 for (PublicEditor::TrackViewList::const_iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
167 StreamView* s = (*i)->view ();
170 double const h = (*i)->effective_height () * _vertical_scale;
171 cairo_set_line_width (cr, h);
173 Gdk::Color const c = (*i)->color ();
174 cairo_set_source_rgb (cr, c.get_red_p (), c.get_green_p(), c.get_blue_p());
176 s->foreach_regionview (bind (
177 mem_fun (*this, &EditorSummary::render_region),
188 /** Render a region for the summary.
189 * @param r Region view.
190 * @param cr Cairo context.
191 * @param start Frame offset that the summary starts at.
192 * @param y y coordinate to render at.
195 EditorSummary::render_region (RegionView* r, cairo_t* cr, nframes_t start, double y) const
197 cairo_move_to (cr, (r->region()->position() - start) * _pixels_per_frame, y);
198 cairo_line_to (cr, ((r->region()->position() - start + r->region()->length())) * _pixels_per_frame, y);
202 /** Set the summary so that the whole thing will be re-rendered next time it is required */
204 EditorSummary::set_dirty ()
206 ENSURE_GUI_THREAD (mem_fun (*this, &EditorSummary::set_dirty));
208 _regions_dirty = true;
212 /** Set the summary so that just the view boundary markers will be re-rendered */
214 EditorSummary::set_bounds_dirty ()
216 ENSURE_GUI_THREAD (mem_fun (*this, &EditorSummary::set_bounds_dirty));
220 /** Handle a size request.
221 * @param req GTK requisition
224 EditorSummary::on_size_request (Gtk::Requisition *req)
226 /* Use a dummy, small width and the actual height that we want */
231 /** Handle a size allocation.
232 * @param alloc GTK allocation.
235 EditorSummary::on_size_allocate (Gtk::Allocation& alloc)
237 Gtk::EventBox::on_size_allocate (alloc);
239 _width = alloc.get_width ();
240 _height = alloc.get_height ();
246 EditorSummary::centre_on_click (GdkEventButton* ev)
248 nframes_t x = (ev->x / _pixels_per_frame) + _session->current_start_frame();
249 nframes_t const xh = _editor->current_page_frames () / 2;
256 _editor->reset_x_origin (x);
258 double y = ev->y / _vertical_scale;
259 double const yh = _editor->canvas_height () / 2;
266 _editor->reset_y_origin (y);
269 /** Handle a button press.
270 * @param ev GTK event.
273 EditorSummary::on_button_press_event (GdkEventButton* ev)
275 if (ev->button == 1) {
277 pair<double, double> xr;
278 pair<double, double> yr;
279 editor_view (&xr, &yr);
281 if (xr.first <= ev->x && ev->x <= xr.second && yr.first <= ev->y && ev->y <= yr.second) {
283 /* click inside the view rectangle: drag it */
286 _x_offset = ev->x - xr.first;
287 _y_offset = ev->y - yr.first;
288 _editor->_dragging_playhead = true;
292 /* click outside the view rectangle: centre the view around the mouse click */
293 centre_on_click (ev);
301 EditorSummary::editor_view (pair<double, double>* x, pair<double, double>* y) const
303 x->first = (_editor->leftmost_position () - _session->current_start_frame ()) * _pixels_per_frame;
304 x->second = x->first + _editor->current_page_frames() * _pixels_per_frame;
306 y->first = _editor->get_trackview_group_vertical_offset () * _vertical_scale;
307 y->second = y->first + _editor->canvas_height () * _vertical_scale;
311 EditorSummary::on_motion_notify_event (GdkEventMotion* ev)
319 _editor->reset_x_origin (((ev->x - _x_offset) / _pixels_per_frame) + _session->current_start_frame ());
320 _editor->reset_y_origin ((ev->y - _y_offset) / _vertical_scale);
326 EditorSummary::on_button_release_event (GdkEventButton* ev)
328 if (_dragging && !_moved) {
329 centre_on_click (ev);
333 _editor->_dragging_playhead = false;