From 2082f0843b8091e9218e4209010f319d76e02a87 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Thu, 7 Aug 2008 20:27:41 +0100 Subject: [PATCH] Initial implementation of I-Beam tool. Needs more work --- src/gui/widgets/timeline-widget.cpp | 108 ++++++++++------- src/gui/widgets/timeline-widget.hpp | 31 ++++- .../widgets/timeline/timeline-arrow-tool.cpp | 22 +++- .../widgets/timeline/timeline-arrow-tool.hpp | 7 +- src/gui/widgets/timeline/timeline-body.cpp | 112 +++++++++++++++++- src/gui/widgets/timeline/timeline-body.hpp | 18 ++- .../widgets/timeline/timeline-ibeam-tool.cpp | 54 ++++++++- .../widgets/timeline/timeline-ibeam-tool.hpp | 14 ++- src/gui/widgets/timeline/timeline-ruler.cpp | 106 +++++++++++------ src/gui/widgets/timeline/timeline-ruler.hpp | 35 +++--- src/gui/widgets/timeline/timeline-tool.cpp | 35 ++++-- src/gui/widgets/timeline/timeline-tool.hpp | 19 +-- 12 files changed, 428 insertions(+), 133 deletions(-) diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index faea874ff..867595ad3 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -21,8 +21,6 @@ * *****************************************************/ #include "timeline-widget.hpp" -#include "timeline/timeline-arrow-tool.hpp" -#include "timeline/timeline-ibeam-tool.hpp" #include @@ -46,14 +44,17 @@ TimelineWidget::TimelineWidget() : totalHeight(0), horizontalAdjustment(0, 0, 0), verticalAdjustment(0, 0, 0), + selectionStart(0), + selectionEnd(0), horizontalScroll(horizontalAdjustment), - verticalScroll(verticalAdjustment), - tool(NULL) + verticalScroll(verticalAdjustment) { body = new TimelineBody(this); ENSURE(body != NULL); headerContainer = new HeaderContainer(this); ENSURE(headerContainer != NULL); + ruler = new TimelineRuler(this); + ENSURE(ruler != NULL); horizontalAdjustment.signal_value_changed().connect( sigc::mem_fun( this, &TimelineWidget::on_scroll) ); @@ -63,9 +64,10 @@ TimelineWidget::TimelineWidget() : this, &TimelineWidget::on_motion_in_body_notify_event) ); set_time_scale(GAVL_TIME_SCALE / 200); + set_selection(2000000, 4000000); attach(*body, 1, 2, 1, 2, FILL|EXPAND, FILL|EXPAND); - attach(ruler, 1, 2, 0, 1, FILL|EXPAND, SHRINK); + attach(*ruler, 1, 2, 0, 1, FILL|EXPAND, SHRINK); attach(*headerContainer, 0, 1, 1, 2, SHRINK, FILL|EXPAND); attach(horizontalScroll, 1, 2, 2, 3, FILL|EXPAND, SHRINK); attach(verticalScroll, 2, 3, 1, 2, SHRINK, FILL|EXPAND); @@ -87,10 +89,10 @@ TimelineWidget::~TimelineWidget() REQUIRE(headerContainer != NULL); if(headerContainer != NULL) headerContainer->unreference(); - - REQUIRE(tool != NULL); - if(tool != NULL) - delete tool; + + REQUIRE(ruler != NULL); + if(ruler != NULL) + ruler->unreference(); } gavl_time_t @@ -102,9 +104,11 @@ TimelineWidget::get_time_offset() const void TimelineWidget::set_time_offset(gavl_time_t time_offset) { + REQUIRE(ruler != NULL); + timeOffset = time_offset; horizontalAdjustment.set_value(time_offset); - ruler.set_time_offset(time_offset); + ruler->update_view(); } int64_t @@ -116,11 +120,14 @@ TimelineWidget::get_time_scale() const void TimelineWidget::set_time_scale(int64_t time_scale) { + REQUIRE(ruler != NULL); + timeScale = time_scale; - ruler.set_time_scale(time_scale); const int view_width = body->get_allocation().get_width(); horizontalAdjustment.set_page_size(timeScale * view_width); + + ruler->update_view(); } void @@ -163,49 +170,56 @@ TimelineWidget::shift_view(int shift_size) shift_size * timeScale * view_width / 16); } +gavl_time_t +TimelineWidget::get_selection_start() const +{ + return selectionStart; +} + +gavl_time_t +TimelineWidget::get_selection_end() const +{ + return selectionEnd; +} + +void +TimelineWidget::set_selection(gavl_time_t start, gavl_time_t end) +{ + if(start < end) + { + selectionStart = start; + selectionEnd = end; + } + else + { + // The selection is back-to-front, flip it round + selectionStart = end; + selectionEnd = start; + } + + ruler->queue_draw(); + body->queue_draw(); +} + ToolType TimelineWidget::get_tool() const { - REQUIRE(tool != NULL); - if(tool != NULL) - return tool->get_type(); - return None; + REQUIRE(body != NULL); + return body->get_tool(); } void TimelineWidget::set_tool(ToolType tool_type) { - // Tidy up old tool - if(tool != NULL) - { - // Do we need to change tools? - if(tool->get_type() == tool_type) - return; - - delete tool; - } - - // Create the new tool - switch(tool_type) - { - case timeline::Arrow: - tool = new timeline::ArrowTool(this); - break; - - case timeline::IBeam: - tool = new timeline::IBeamTool(this); - break; - } - - // Apply the cursor if possible - tool->apply_cursor(); + REQUIRE(body != NULL); + body->set_tool(tool_type); } void TimelineWidget::on_scroll() { timeOffset = horizontalAdjustment.get_value(); - ruler.set_time_offset(timeOffset); + ruler->update_view(); } void @@ -216,6 +230,18 @@ TimelineWidget::on_size_allocate(Allocation& allocation) update_scroll(); } +int +TimelineWidget::time_to_x(gavl_time_t time) const +{ + return (int)((time - timeOffset) / timeScale); +} + +gavl_time_t +TimelineWidget::x_to_time(int x) const +{ + return (gavl_time_t)((int64_t)x * timeScale + timeOffset); +} + void TimelineWidget::update_tracks() { @@ -282,7 +308,7 @@ bool TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event) { REQUIRE(event != NULL); - ruler.set_mouse_chevron_offset(event->x); + ruler->set_mouse_chevron_offset(event->x); return true; } diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index e5e90fe92..ca6be76ec 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -31,6 +31,8 @@ #include "timeline/timeline-body.hpp" #include "timeline/timeline-ruler.hpp" #include "timeline/timeline-tool.hpp" +#include "timeline/timeline-arrow-tool.hpp" +#include "timeline/timeline-ibeam-tool.hpp" #include "timeline/track.hpp" namespace lumiera { @@ -96,18 +98,30 @@ public: **/ void shift_view(int shift_size); + gavl_time_t get_selection_start() const; + + gavl_time_t get_selection_end() const; + + void set_selection(gavl_time_t start, gavl_time_t end); + timeline::ToolType get_tool() const; void set_tool(timeline::ToolType tool_type); - + /* ===== Events ===== */ protected: void on_scroll(); void on_size_allocate(Gtk::Allocation& allocation); + + /* ===== Utilities ===== */ +protected: + int time_to_x(gavl_time_t time) const; + + gavl_time_t x_to_time(int x) const; /* ===== Internals ===== */ -protected: +private: void update_tracks(); @@ -118,8 +132,14 @@ protected: bool on_motion_in_body_notify_event(GdkEventMotion *event); protected: + + // View State gavl_time_t timeOffset; int64_t timeScale; + + // Selection State + gavl_time_t selectionStart; + gavl_time_t selectionEnd; int totalHeight; @@ -129,13 +149,11 @@ protected: timeline::HeaderContainer *headerContainer; timeline::TimelineBody *body; - timeline::TimelineRuler ruler; + timeline::TimelineRuler *ruler; Gtk::Adjustment horizontalAdjustment, verticalAdjustment; Gtk::HScrollbar horizontalScroll; Gtk::VScrollbar verticalScroll; - - timeline::Tool *tool; /* ===== Constants ===== */ public: @@ -148,7 +166,10 @@ protected: friend class timeline::TimelineBody; friend class timeline::HeaderContainer; + friend class timeline::TimelineRuler; friend class timeline::Tool; + friend class timeline::ArrowTool; + friend class timeline::IBeamTool; }; } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-arrow-tool.cpp b/src/gui/widgets/timeline/timeline-arrow-tool.cpp index 4e65165f5..109d6190e 100644 --- a/src/gui/widgets/timeline/timeline-arrow-tool.cpp +++ b/src/gui/widgets/timeline/timeline-arrow-tool.cpp @@ -27,8 +27,8 @@ namespace gui { namespace widgets { namespace timeline { -ArrowTool::ArrowTool(TimelineWidget *timeline_widget) : - Tool(timeline_widget) +ArrowTool::ArrowTool(TimelineBody *timeline_body) : + Tool(timeline_body) { } @@ -45,6 +45,24 @@ ArrowTool::get_cursor() const return Gdk::Cursor(Gdk::ARROW); } +void +ArrowTool::on_button_press_event(GdkEventButton* event) +{ + Tool::on_button_press_event(event); +} + +void +ArrowTool::on_button_release_event(GdkEventButton* event) +{ + Tool::on_button_release_event(event); +} + +void +ArrowTool::on_motion_notify_event(GdkEventMotion *event) +{ + Tool::on_motion_notify_event(event); +} + } // namespace timeline } // namespace widgets } // namespace gui diff --git a/src/gui/widgets/timeline/timeline-arrow-tool.hpp b/src/gui/widgets/timeline/timeline-arrow-tool.hpp index 05f4ef562..b7bfb6138 100644 --- a/src/gui/widgets/timeline/timeline-arrow-tool.hpp +++ b/src/gui/widgets/timeline/timeline-arrow-tool.hpp @@ -37,12 +37,17 @@ namespace timeline { class ArrowTool : public Tool { public: - ArrowTool(TimelineWidget *timeline_widget); + ArrowTool(TimelineBody *timeline_body); ToolType get_type() const; protected: Gdk::Cursor get_cursor() const; + +protected: + void on_button_press_event(GdkEventButton* event); + void on_button_release_event(GdkEventButton* event); + void on_motion_notify_event(GdkEventMotion *event); }; } // namespace timeline diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp index 63edb6a1a..50da41348 100644 --- a/src/gui/widgets/timeline/timeline-body.cpp +++ b/src/gui/widgets/timeline/timeline-body.cpp @@ -27,6 +27,9 @@ #include "../timeline-widget.hpp" #include "../../window-manager.hpp" +#include "timeline-arrow-tool.hpp" +#include "timeline-ibeam-tool.hpp" + using namespace Gtk; using namespace std; using namespace lumiera::gui; @@ -38,8 +41,10 @@ namespace gui { namespace widgets { namespace timeline { -TimelineBody::TimelineBody(lumiera::gui::widgets::TimelineWidget *timeline_widget) : +TimelineBody::TimelineBody(lumiera::gui::widgets::TimelineWidget + *timeline_widget) : Glib::ObjectBase("TimelineBody"), + tool(NULL), dragType(None), mouseDownX(0), mouseDownY(0), @@ -63,6 +68,51 @@ TimelineBody::TimelineBody(lumiera::gui::widgets::TimelineWidget *timeline_widge GDK_TYPE_COLOR, G_PARAM_READABLE)); } +TimelineBody::~TimelineBody() +{ + REQUIRE(tool != NULL); + if(tool != NULL) + delete tool; +} + +ToolType +TimelineBody::get_tool() const +{ + REQUIRE(tool != NULL); + if(tool != NULL) + return tool->get_type(); + return lumiera::gui::widgets::timeline::None; +} + +void +TimelineBody::set_tool(timeline::ToolType tool_type) +{ + // Tidy up old tool + if(tool != NULL) + { + // Do we need to change tools? + if(tool->get_type() == tool_type) + return; + + delete tool; + } + + // Create the new tool + switch(tool_type) + { + case timeline::Arrow: + tool = new ArrowTool(this); + break; + + case timeline::IBeam: + tool = new IBeamTool(this); + break; + } + + // Apply the cursor if possible + tool->apply_cursor(); +} + void TimelineBody::on_realize() { @@ -76,7 +126,7 @@ TimelineBody::on_realize() Gdk::BUTTON_RELEASE_MASK); // Apply the cursor if possible - timelineWidget->tool->apply_cursor(); + tool->apply_cursor(); } void @@ -138,7 +188,12 @@ TimelineBody::on_button_press_event(GdkEventButton* event) default: dragType = None; break; - } + } + + // Forward the event to the tool + tool->on_button_press_event(event); + + return true; } bool @@ -146,11 +201,16 @@ TimelineBody::on_button_release_event(GdkEventButton* event) { // Terminate any drags dragType = None; + + // Forward the event to the tool + tool->on_button_release_event(event); + + return true; } bool TimelineBody::on_motion_notify_event(GdkEventMotion *event) -{ +{ REQUIRE(event != NULL); switch(dragType) @@ -168,6 +228,9 @@ TimelineBody::on_motion_notify_event(GdkEventMotion *event) } } + // Forward the event to the tool + tool->on_motion_notify_event(event); + // false so that the message is passed up to the owner TimelineWidget return false; } @@ -175,6 +238,8 @@ TimelineBody::on_motion_notify_event(GdkEventMotion *event) bool TimelineBody::on_expose_event(GdkEventExpose* event) { + Cairo::Matrix view_matrix; + REQUIRE(event != NULL); REQUIRE(timelineWidget != NULL); @@ -196,6 +261,7 @@ TimelineBody::on_expose_event(GdkEventExpose* event) // Translate the view by the scroll distance cairo->translate(0, -get_vertical_offset()); + cairo->get_matrix(view_matrix); // Interate drawing each track BOOST_FOREACH( Track* track, timelineWidget->tracks ) @@ -217,8 +283,44 @@ TimelineBody::on_expose_event(GdkEventExpose* event) // Shift for the next track cairo->translate(0, height + TimelineWidget::TrackPadding); - } + } + + //----- Draw the selection -----// + const int start_x = timelineWidget->time_to_x( + timelineWidget->get_selection_start()); + const int end_x = timelineWidget->time_to_x( + timelineWidget->get_selection_end()); + cairo->set_matrix(view_matrix); + + // Draw the cover + if(end_x > 0 && start_x < allocation.get_width()) + { + cairo->set_source_rgba(1.0, 0, 0, 0.5); + cairo->rectangle(start_x + 0.5, 0, + end_x - start_x, allocation.get_height()); + cairo->fill(); + } + + cairo->set_source_rgb(1.0, 0, 0); + cairo->set_line_width(1); + + // Draw the start + if(start_x >= 0 && start_x < allocation.get_width()) + { + cairo->move_to(start_x + 0.5, 0); + cairo->line_to(start_x + 0.5, allocation.get_height()); + cairo->stroke_preserve(); + } + + // Draw the end + if(end_x >= 0 && end_x < allocation.get_width()) + { + cairo->move_to(end_x + 0.5, 0); + cairo->line_to(end_x + 0.5, allocation.get_height()); + cairo->stroke_preserve(); + } + return true; } diff --git a/src/gui/widgets/timeline/timeline-body.hpp b/src/gui/widgets/timeline/timeline-body.hpp index 86ce40a47..cebe4d5e1 100644 --- a/src/gui/widgets/timeline/timeline-body.hpp +++ b/src/gui/widgets/timeline/timeline-body.hpp @@ -27,6 +27,7 @@ #define TIMELINE_BODY_HPP #include "../../gtk-lumiera.hpp" +#include "timeline-tool.hpp" namespace lumiera { namespace gui { @@ -40,6 +41,12 @@ class TimelineBody : public Gtk::DrawingArea { public: TimelineBody(lumiera::gui::widgets::TimelineWidget *timeline_widget); + + ~TimelineBody(); + + ToolType get_tool() const; + + void set_tool(ToolType tool_type); /* ===== Events ===== */ protected: @@ -76,15 +83,20 @@ private: Shift }; - // UI State Data - DragType dragType; + timeline::Tool *tool; double mouseDownX, mouseDownY; + + // Scroll State + DragType dragType; gavl_time_t beginShiftTimeOffset; - int beginShiftVerticalOffset; + int beginShiftVerticalOffset; GdkColor background; lumiera::gui::widgets::TimelineWidget *timelineWidget; + + friend class ArrowTool; + friend class IBeamTool; }; } // namespace timeline diff --git a/src/gui/widgets/timeline/timeline-ibeam-tool.cpp b/src/gui/widgets/timeline/timeline-ibeam-tool.cpp index 8225ced80..1940a04b1 100644 --- a/src/gui/widgets/timeline/timeline-ibeam-tool.cpp +++ b/src/gui/widgets/timeline/timeline-ibeam-tool.cpp @@ -21,14 +21,15 @@ * *****************************************************/ #include "timeline-ibeam-tool.hpp" +#include "../timeline-widget.hpp" namespace lumiera { namespace gui { namespace widgets { namespace timeline { -IBeamTool::IBeamTool(TimelineWidget *timeline_widget) : - Tool(timeline_widget) +IBeamTool::IBeamTool(TimelineBody *timeline_body) : + Tool(timeline_body) { } @@ -44,6 +45,55 @@ IBeamTool::get_cursor() const return Gdk::Cursor(Gdk::XTERM); } +void +IBeamTool::on_button_press_event(GdkEventButton* event) +{ + Tool::on_button_press_event(event); + + REQUIRE(timelineBody != NULL); + lumiera::gui::widgets::TimelineWidget *timeline_widget = + timelineBody->timelineWidget; + REQUIRE(timeline_widget != NULL); + + if(event->button == 1) + { + drag_start_time = timeline_widget->x_to_time(event->x); + timeline_widget->set_selection(drag_start_time, drag_start_time); + } +} + +void +IBeamTool::on_button_release_event(GdkEventButton* event) +{ + Tool::on_button_release_event(event); + + if(event->button == 1) + set_leading_x(event->x); +} + +void +IBeamTool::on_motion_notify_event(GdkEventMotion *event) +{ + Tool::on_motion_notify_event(event); + + if(isDragging) + set_leading_x(event->x); +} + +void IBeamTool::set_leading_x(const int x) +{ + REQUIRE(timelineBody != NULL); + lumiera::gui::widgets::TimelineWidget *timeline_widget = + timelineBody->timelineWidget; + REQUIRE(timeline_widget != NULL); + + const gavl_time_t time = timeline_widget->x_to_time(x); + if(time > drag_start_time) + timeline_widget->set_selection(drag_start_time, time); + else + timeline_widget->set_selection(time, drag_start_time); +} + } // namespace timeline } // namespace widgets } // namespace gui diff --git a/src/gui/widgets/timeline/timeline-ibeam-tool.hpp b/src/gui/widgets/timeline/timeline-ibeam-tool.hpp index 79eb36c8c..fa0021ce1 100644 --- a/src/gui/widgets/timeline/timeline-ibeam-tool.hpp +++ b/src/gui/widgets/timeline/timeline-ibeam-tool.hpp @@ -38,12 +38,24 @@ namespace timeline { class IBeamTool : public Tool { public: - IBeamTool(TimelineWidget *timeline_widget); + IBeamTool(TimelineBody *timeline_body); ToolType get_type() const; protected: Gdk::Cursor get_cursor() const; + +protected: + void on_button_press_event(GdkEventButton* event); + void on_button_release_event(GdkEventButton* event); + void on_motion_notify_event(GdkEventMotion *event); + +private: + void set_leading_x(const int x); + +protected: + //----- Internals -----// + gavl_time_t drag_start_time; }; } // namespace timeline diff --git a/src/gui/widgets/timeline/timeline-ruler.cpp b/src/gui/widgets/timeline/timeline-ruler.cpp index 44cf4e307..0b28472b9 100644 --- a/src/gui/widgets/timeline/timeline-ruler.cpp +++ b/src/gui/widgets/timeline/timeline-ruler.cpp @@ -23,6 +23,7 @@ #include #include "timeline-ruler.hpp" +#include "../timeline-widget.hpp" #include "../../window-manager.hpp" extern "C" { @@ -41,39 +42,24 @@ namespace gui { namespace widgets { namespace timeline { -TimelineRuler::TimelineRuler() : +TimelineRuler::TimelineRuler( + lumiera::gui::widgets::TimelineWidget *timeline_widget) : Glib::ObjectBase("TimelineRuler"), - timeOffset(-1), - timeScale(1), mouseChevronOffset(0), annotationHorzMargin(0), annotationVertMargin(0), majorTickHeight(0), minorLongTickHeight(0), minorShortTickHeight(0), - minDivisionWidth(100) -{ + minDivisionWidth(100), + timelineWidget(timeline_widget) +{ + REQUIRE(timelineWidget != NULL); + // Install style properties register_styles(); } -void -TimelineRuler::set_time_offset(gavl_time_t time_offset) -{ - timeOffset = time_offset; - rulerImage.clear(); - queue_draw(); -} - -void -TimelineRuler::set_time_scale(int64_t time_scale) -{ - REQUIRE(time_scale > 0); - timeScale = time_scale; - rulerImage.clear(); - queue_draw(); -} - void TimelineRuler::set_mouse_chevron_offset(int offset) { @@ -81,6 +67,13 @@ TimelineRuler::set_mouse_chevron_offset(int offset) queue_draw(); } +void +TimelineRuler::update_view() +{ + rulerImage.clear(); + queue_draw(); +} + void TimelineRuler::on_realize() { @@ -132,8 +125,9 @@ TimelineRuler::on_expose_event(GdkEventExpose* event) cairo->set_source(rulerImage, 0, 0); cairo->paint(); - // Draw the mouse chevron + // Draw the overlays draw_mouse_chevron(cairo, allocation); + draw_selection(cairo, allocation); return true; } @@ -168,11 +162,15 @@ TimelineRuler::on_size_allocate(Gtk::Allocation& allocation) void TimelineRuler::draw_ruler(Cairo::RefPtr cairo, - Gdk::Rectangle ruler_rect) + const Gdk::Rectangle ruler_rect) { REQUIRE(cairo); REQUIRE(ruler_rect.get_width() > 0); REQUIRE(ruler_rect.get_height() > 0); + REQUIRE(timelineWidget != NULL); + + const gavl_time_t left_offset = timelineWidget->timeOffset; + const int64_t time_scale = timelineWidget->timeScale; // Preparation steps const int height = ruler_rect.get_height(); @@ -187,7 +185,7 @@ TimelineRuler::draw_ruler(Cairo::RefPtr cairo, cairo->clip(); // Make sure we don't have impossible zoom - if(timeScale <= 0) + if(time_scale <= 0) return; // Render ruler annotations @@ -196,16 +194,16 @@ TimelineRuler::draw_ruler(Cairo::RefPtr cairo, const gavl_time_t major_spacing = calculate_major_spacing(); const gavl_time_t minor_spacing = major_spacing / 10; - int64_t time_offset = timeOffset - timeOffset % major_spacing; - if(timeOffset < 0) + int64_t time_offset = left_offset - left_offset % major_spacing; + if(left_offset < 0) time_offset -= major_spacing; int x = 0; - const int64_t x_offset = timeOffset / timeScale; + const int64_t x_offset = left_offset / time_scale; do { - x = (int)(time_offset / timeScale - x_offset); + x = (int)(time_offset / time_scale - x_offset); cairo->set_line_width(1); @@ -241,7 +239,7 @@ TimelineRuler::draw_ruler(Cairo::RefPtr cairo, void TimelineRuler::draw_mouse_chevron(Cairo::RefPtr cairo, - Gdk::Rectangle ruler_rect) + const Gdk::Rectangle ruler_rect) { REQUIRE(cairo); REQUIRE(ruler_rect.get_width() > 0); @@ -258,19 +256,55 @@ TimelineRuler::draw_mouse_chevron(Cairo::RefPtr cairo, cairo->move_to(mouseChevronOffset + 0.5, ruler_rect.get_height()); - cairo->line_to(mouseChevronOffset + mouseChevronSize + 0.5, - ruler_rect.get_height() - mouseChevronSize); - cairo->line_to(mouseChevronOffset - mouseChevronSize + 0.5, - ruler_rect.get_height() - mouseChevronSize); + cairo->rel_line_to(-mouseChevronSize, -mouseChevronSize); + cairo->rel_line_to(2 * mouseChevronSize, 0); cairo->fill(); } +void +TimelineRuler::draw_selection(Cairo::RefPtr cairo, + const Gdk::Rectangle ruler_rect) +{ + REQUIRE(cairo); + REQUIRE(ruler_rect.get_width() > 0); + REQUIRE(ruler_rect.get_height() > 0); + REQUIRE(timelineWidget != NULL); + + Glib::RefPtr