13
0
livetrax/gtk2_ardour/editor_summary.cc
Carl Hetherington c6c10f1e7f Add some comments.
git-svn-id: svn://localhost/ardour2/branches/3.0@5169 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-06-11 14:49:20 +00:00

266 lines
5.7 KiB
C++

#include "ardour/session.h"
#include "time_axis_view.h"
#include "streamview.h"
#include "editor_summary.h"
#include "gui_thread.h"
#include "editor.h"
#include "region_view.h"
using namespace std;
using namespace sigc;
using namespace ARDOUR;
/** Construct an EditorSummary.
* @param e Editor to represent.
*/
EditorSummary::EditorSummary (Editor* e)
: _editor (e),
_session (0),
_pixmap (0),
_regions_dirty (true),
_width (512),
_height (64),
_pixels_per_frame (1)
{
}
/** Set the session.
* @param s Session.
*/
void
EditorSummary::set_session (Session* s)
{
_session = s;
Region::RegionPropertyChanged.connect (sigc::hide (mem_fun (*this, &EditorSummary::set_dirty)));
_session->RegionRemoved.connect (sigc::hide (mem_fun (*this, &EditorSummary::set_dirty)));
_session->EndTimeChanged.connect (mem_fun (*this, &EditorSummary::set_dirty));
_session->StartTimeChanged.connect (mem_fun (*this, &EditorSummary::set_dirty));
set_dirty ();
}
/** Destroy */
EditorSummary::~EditorSummary ()
{
if (_pixmap) {
gdk_pixmap_unref (_pixmap);
}
}
/** Handle an expose event.
* @param event Event from GTK.
*/
bool
EditorSummary::on_expose_event (GdkEventExpose* event)
{
/* Render the regions pixmap */
Gdk::Rectangle const exposure (
event->area.x, event->area.y, event->area.width, event->area.height
);
Gdk::Rectangle r = exposure;
Gdk::Rectangle content (0, 0, _width, _height);
bool intersects;
r.intersect (content, intersects);
if (intersects) {
GdkPixmap* p = get_pixmap (get_window()->gobj ());
gdk_draw_drawable (
get_window()->gobj(),
get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(),
p,
r.get_x(),
r.get_y(),
r.get_x(),
r.get_y(),
r.get_width(),
r.get_height()
);
}
/* Render the view beginning and end markers */
cairo_t* cr = gdk_cairo_create (get_window()->gobj());
cairo_set_source_rgb (cr, 0, 1, 0);
cairo_set_line_width (cr, 2);
double const s = (_editor->leftmost_position () - _session->current_start_frame ()) * _pixels_per_frame;
cairo_move_to (cr, s, 0);
cairo_line_to (cr, s, _height);
cairo_stroke (cr);
double const e = s + _editor->current_page_frames() * _pixels_per_frame;
cairo_move_to (cr, e, 0);
cairo_line_to (cr, e, _height);
cairo_stroke (cr);
cairo_destroy (cr);
return true;
}
/** @param drawable GDK drawable.
* @return pixmap for the regions.
*/
GdkPixmap *
EditorSummary::get_pixmap (GdkDrawable* drawable)
{
if (_regions_dirty) {
if (_pixmap) {
gdk_pixmap_unref (_pixmap);
}
_pixmap = gdk_pixmap_new (drawable, _width, _height, -1);
cairo_t* cr = gdk_cairo_create (_pixmap);
render (cr);
cairo_destroy (cr);
_regions_dirty = false;
}
return _pixmap;
}
/** Render the required regions to a cairo context.
* @param cr Context.
*/
void
EditorSummary::render (cairo_t* cr)
{
if (_session == 0) {
return;
}
/* background */
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_rectangle (cr, 0, 0, _width, _height);
cairo_fill (cr);
int N = 0;
/* count tracks to render */
for (PublicEditor::TrackViewList::const_iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
if ((*i)->view()) {
++N;
}
}
nframes_t const start = _session->current_start_frame ();
_pixels_per_frame = static_cast<double> (_width) / (_session->current_end_frame() - start);
double const track_height = static_cast<double> (_height) / N;
cairo_set_line_width (cr, track_height);
/* render regions */
int n = 0;
for (PublicEditor::TrackViewList::const_iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
StreamView* s = (*i)->view ();
if (s) {
double const v = ((n % 2) == 0) ? 1 : 0.5;
cairo_set_source_rgb (cr, v, v, v);
s->foreach_regionview (bind (
mem_fun (*this, &EditorSummary::render_region),
cr,
start,
track_height * (n + 0.5)
));
++n;
}
}
}
/** Render a region for the summary.
* @param r Region view.
* @param cr Cairo context.
* @param start Frame offset that the summary starts at.
* @param y y coordinate to render at.
*/
void
EditorSummary::render_region (RegionView* r, cairo_t* cr, nframes_t start, double y) const
{
cairo_move_to (cr, (r->region()->position() - start) * _pixels_per_frame, y);
cairo_line_to (cr, (r->region()->position() - start + r->region()->length()) * _pixels_per_frame, y);
cairo_stroke (cr);
}
/** Set the summary so that the whole thing will be re-rendered next time it is required */
void
EditorSummary::set_dirty ()
{
ENSURE_GUI_THREAD (mem_fun (*this, &EditorSummary::set_dirty));
_regions_dirty = true;
queue_draw ();
}
/** Set the summary so that just the view boundary markers will be re-rendered */
void
EditorSummary::set_bounds_dirty ()
{
ENSURE_GUI_THREAD (mem_fun (*this, &EditorSummary::set_bounds_dirty));
queue_draw ();
}
/** Handle a size request.
* @param req GTK requisition
*/
void
EditorSummary::on_size_request (Gtk::Requisition *req)
{
/* Use a dummy, small width and the actual height that we want */
req->width = 64;
req->height = 64;
}
/** Handle a size allocation.
* @param alloc GTK allocation.
*/
void
EditorSummary::on_size_allocate (Gtk::Allocation& alloc)
{
Gtk::EventBox::on_size_allocate (alloc);
_width = alloc.get_width ();
_height = alloc.get_height ();
set_dirty ();
}
/** Handle a button press.
* @param ev GTK event.
*/
bool
EditorSummary::on_button_press_event (GdkEventButton* ev)
{
if (ev->button == 1) {
/* centre the editor view around the mouse click */
nframes_t f = (ev->x / _pixels_per_frame) + _session->current_start_frame();
nframes_t const h = _editor->current_page_frames () / 2;
if (f > h) {
f -= h;
} else {
f = 0;
}
_editor->reset_x_origin (f);
}
return true;
}