From 7f615d734f0380447be3868c93c9c234825dbb2e Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 2 Jan 2011 16:57:14 +0100 Subject: [PATCH] WIP: make clips selectable in timeline --- src/gui/model/clip.cpp | 6 ++ src/gui/model/clip.hpp | 8 ++ src/gui/widgets/timeline-widget.cpp | 2 +- src/gui/widgets/timeline-widget.hpp | 3 +- .../widgets/timeline/timeline-arrow-tool.cpp | 92 +++++++++++++------ .../widgets/timeline/timeline-arrow-tool.hpp | 75 ++++++++------- src/gui/widgets/timeline/timeline-body.cpp | 6 ++ src/gui/widgets/timeline/timeline-body.hpp | 3 + .../widgets/timeline/timeline-clip-track.cpp | 15 +++ .../widgets/timeline/timeline-clip-track.hpp | 15 ++- src/gui/widgets/timeline/timeline-clip.cpp | 82 +++++++++-------- src/gui/widgets/timeline/timeline-clip.hpp | 34 +++---- .../timeline/timeline-header-widget.cpp | 2 +- .../timeline/timeline-layout-helper.cpp | 2 +- src/gui/widgets/timeline/timeline-track.cpp | 9 +- src/gui/widgets/timeline/timeline-track.hpp | 21 +++-- 16 files changed, 246 insertions(+), 129 deletions(-) diff --git a/src/gui/model/clip.cpp b/src/gui/model/clip.cpp index 95233b20f..1dc0f2e00 100644 --- a/src/gui/model/clip.cpp +++ b/src/gui/model/clip.cpp @@ -48,6 +48,12 @@ namespace model { return name; } + bool + Clip::isPlayingAt(lumiera::Time position) const + { + return (begin <= position && end >= position); + } + void Clip::setBegin(gavl_time_t begin) { diff --git a/src/gui/model/clip.hpp b/src/gui/model/clip.hpp index a024cfb67..2c8fd5add 100644 --- a/src/gui/model/clip.hpp +++ b/src/gui/model/clip.hpp @@ -26,6 +26,8 @@ #include #include "gui/gtk-lumiera.hpp" +#include "lib/lumitime.hpp" + // TODO: Remove once we get real measure of duration. // This is here *only* for purposes of testing the GUI. extern "C" { @@ -67,6 +69,12 @@ namespace model { const std::string getName() const; + /** + * Check whether or not the clip will be playing during the given time. + **/ + bool + isPlayingAt(lumiera::Time position) const; + /** * Sets the begin time of this clip. * @param[in] begin The new begin time to set this clip to. diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 89c098783..0e1b975a9 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -326,7 +326,7 @@ TimelineWidget::create_timeline_track_from_modelTrack( void TimelineWidget::remove_orphaned_tracks() -{ +{ std::map, boost::shared_ptr > orphan_track_map(trackMap); diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index b409d7fe1..7f45c0e17 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -102,7 +102,8 @@ public: */ void set_tool(timeline::ToolType tool_type); - boost::shared_ptr get_hovering_track() const; + boost::shared_ptr + get_hovering_track() const; public: /* ===== Signals ===== */ diff --git a/src/gui/widgets/timeline/timeline-arrow-tool.cpp b/src/gui/widgets/timeline/timeline-arrow-tool.cpp index 67765288f..f0c109189 100644 --- a/src/gui/widgets/timeline/timeline-arrow-tool.cpp +++ b/src/gui/widgets/timeline/timeline-arrow-tool.cpp @@ -26,41 +26,75 @@ namespace gui { namespace widgets { namespace timeline { -ArrowTool::ArrowTool(TimelineBody &timeline_body) : - Tool(timeline_body) -{ + ArrowTool::ArrowTool(TimelineBody &timelineBody) : + Tool(timelineBody) + { -} + } -ToolType -ArrowTool::get_type() const -{ - return Arrow; -} + ToolType + ArrowTool::get_type() const + { + return Arrow; + } -Gdk::Cursor -ArrowTool::get_cursor() const -{ - return Gdk::Cursor(Gdk::LEFT_PTR); -} + Gdk::Cursor + ArrowTool::get_cursor() const + { + return Gdk::Cursor(Gdk::LEFT_PTR); + } -void -ArrowTool::on_button_press_event(GdkEventButton* event) -{ - Tool::on_button_press_event(event); -} + void + ArrowTool::on_button_press_event(GdkEventButton* event) + { + REQUIRE (event != NULL); + Tool::on_button_press_event(event); -void -ArrowTool::on_button_release_event(GdkEventButton* event) -{ - Tool::on_button_release_event(event); -} + // Convert the mouse click position to a Time + boost::shared_ptr state = timelineBody.getTimelineWidget().get_state(); + REQUIRE(state); + const TimelineViewWindow &window = state->get_view_window(); + lumiera::Time tpoint = window.x_to_time(mousePoint.get_x()); -void -ArrowTool::on_motion_notify_event(GdkEventMotion *event) -{ - Tool::on_motion_notify_event(event); -} + // Get the clip, if any + boost::shared_ptr track = getHoveringTrack(); + boost::shared_ptr clip = track->getClipAt(tpoint); + + // Nothing to do if there is no clip + if (clip == boost::shared_ptr()) + return; + + clip->setSelected(true); + } + + void + ArrowTool::on_button_release_event(GdkEventButton* event) + { + REQUIRE (event != NULL); + Tool::on_button_release_event(event); + + boost::shared_ptr track = + getHoveringTrack(); + } + + void + ArrowTool::on_motion_notify_event(GdkEventMotion *event) + { + REQUIRE (event != NULL); + Tool::on_motion_notify_event(event); + + // We do not need to do anything if we are not dragging + if (!isDragging) + return; + } + + boost::shared_ptr + ArrowTool::getHoveringTrack () + { + boost::shared_ptr track( + timelineBody.getTimelineWidget().get_hovering_track()); + return track; + } } // namespace timeline } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-arrow-tool.hpp b/src/gui/widgets/timeline/timeline-arrow-tool.hpp index be21b19c5..c9b7decab 100644 --- a/src/gui/widgets/timeline/timeline-arrow-tool.hpp +++ b/src/gui/widgets/timeline/timeline-arrow-tool.hpp @@ -27,52 +27,63 @@ #define TIMELINE_ARROW_TOOL_HPP #include + #include "timeline-tool.hpp" +#include "gui/widgets/timeline-widget.hpp" +#include "timeline-body.hpp" +#include "timeline-track.hpp" + namespace gui { namespace widgets { namespace timeline { -/** - * A helper class to implement the timeline i-beam tool - */ -class ArrowTool : public Tool -{ -public: /** - * Constructor - * @param timeline_body The owner timeline body object + * A helper class to implement the timeline arrow tool */ - ArrowTool(TimelineBody &timeline_body); + class ArrowTool : public Tool + { + public: + /** + * Constructor + * @param timelineBody The owner timeline body object + */ + ArrowTool(TimelineBody &timelineBody); - /** - * Gets the type of tool represented by this class - */ - ToolType get_type() const; + /** + * Gets the type of tool represented by this class + */ + ToolType get_type() const; -protected: + protected: - /** - * Gets the cursor to display for this tool at this moment. - */ - Gdk::Cursor get_cursor() const; + /** + * Gets the cursor to display for this tool at this moment. + */ + Gdk::Cursor get_cursor() const; -protected: - /** - * The event handler for button press events. - */ - void on_button_press_event(GdkEventButton* event); + /** + * The event handler for button press events. + */ + void on_button_press_event(GdkEventButton* event); - /** - * The event handler for button release events. - */ - void on_button_release_event(GdkEventButton* event); + /** + * The event handler for button release events. + */ + void on_button_release_event(GdkEventButton* event); - /** - * The event handler for mouse move events. - */ - void on_motion_notify_event(GdkEventMotion *event); -}; + /** + * The event handler for mouse move events. + */ + void on_motion_notify_event(GdkEventMotion *event); + + private: + + boost::shared_ptr + getHoveringTrack (); + + bool selectionRectangleActive; + }; } // namespace timeline } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp index f78f99ec1..7d5873f34 100644 --- a/src/gui/widgets/timeline/timeline-body.cpp +++ b/src/gui/widgets/timeline/timeline-body.cpp @@ -69,6 +69,12 @@ TimelineBody::~TimelineBody() WARN_IF(!tool, gui, "An invalid tool pointer is unexpected here"); } +TimelineWidget& +TimelineBody::getTimelineWidget () const +{ + return timelineWidget; +} + ToolType TimelineBody::get_tool() const { diff --git a/src/gui/widgets/timeline/timeline-body.hpp b/src/gui/widgets/timeline/timeline-body.hpp index b6e6a3c29..9f6162beb 100644 --- a/src/gui/widgets/timeline/timeline-body.hpp +++ b/src/gui/widgets/timeline/timeline-body.hpp @@ -65,6 +65,9 @@ public: */ ~TimelineBody(); + TimelineWidget& + getTimelineWidget () const; + /** * Returns the type of the currently selected timeline tool. */ diff --git a/src/gui/widgets/timeline/timeline-clip-track.cpp b/src/gui/widgets/timeline/timeline-clip-track.cpp index 55b7169b8..6c41ddf83 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.cpp +++ b/src/gui/widgets/timeline/timeline-clip-track.cpp @@ -76,6 +76,21 @@ namespace timeline { } } + boost::shared_ptr + ClipTrack::getClipAt(lumiera::Time position) const + { + std::pair, shared_ptr > + pair; + BOOST_FOREACH (pair, clipMap) + { + if (pair.first->isPlayingAt(position)) + return pair.second; + } + + // Nothing found + return boost::shared_ptr(); + } + //// private methods void diff --git a/src/gui/widgets/timeline/timeline-clip-track.hpp b/src/gui/widgets/timeline/timeline-clip-track.hpp index 49a29bb19..72f0f4040 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.hpp +++ b/src/gui/widgets/timeline/timeline-clip-track.hpp @@ -50,10 +50,19 @@ namespace timeline { boost::shared_ptr track); /** - * + * Draw the track in the timeline. **/ - void draw_track(Cairo::RefPtr cairo, - TimelineViewWindow* const window) const; + void + draw_track(Cairo::RefPtr cairo, + TimelineViewWindow* const window) const; + + /** + * Gets the clip that is occupying the given time. If there is no track, return a NULL + * pointer. + * @param the given time + **/ + boost::shared_ptr + getClipAt(lumiera::Time position) const; private: diff --git a/src/gui/widgets/timeline/timeline-clip.cpp b/src/gui/widgets/timeline/timeline-clip.cpp index b09dd7b1b..a3f847cc8 100644 --- a/src/gui/widgets/timeline/timeline-clip.cpp +++ b/src/gui/widgets/timeline/timeline-clip.cpp @@ -26,54 +26,60 @@ namespace gui { namespace widgets { namespace timeline { -Clip::Clip(boost::shared_ptr clip) - : modelClip(clip), - selected(false) -{ - REQUIRE(modelClip); + Clip::Clip(boost::shared_ptr clip) + : modelClip(clip), + selected(false) + { + REQUIRE(modelClip); - // TODO: Connect signals - //modelClip->signalNameChanged().connect(mem_fun(this, - // &Clip::onNameChanged); -} + // TODO: Connect signals + //modelClip->signalNameChanged().connect(mem_fun(this, + // &Clip::onNameChanged); + } -void -Clip::draw_clip(Cairo::RefPtr cr, - TimelineViewWindow* const window) const -{ - REQUIRE(cr); - REQUIRE(window); - REQUIRE(modelClip); + void + Clip::draw_clip(Cairo::RefPtr cr, + TimelineViewWindow* const window) const + { + REQUIRE(cr); + REQUIRE(window); + REQUIRE(modelClip); - int x = window->time_to_x(modelClip->getBegin()); - int width = window->time_to_x( - modelClip->getEnd()) - window->time_to_x(modelClip->getBegin()); + int x = window->time_to_x(modelClip->getBegin()); + int width = window->time_to_x( + modelClip->getEnd()) - window->time_to_x(modelClip->getBegin()); - // Draw a rectangle for the clip - cr->rectangle(x, 1, width, 100-2); - // TODO: get height from the Timeline::Track + // Draw a rectangle for the clip + cr->rectangle(x, 1, width, 100-2); + // TODO: get height from the Timeline::Track - if (selected) - cr->set_source(Cairo::SolidPattern::create_rgb (0.3, 0.3, 0.3)); - else - cr->set_source(Cairo::SolidPattern::create_rgb (0.4, 0.4, 0.4)); - cr->fill_preserve(); + if (selected) + cr->set_source(Cairo::SolidPattern::create_rgb (0.4, 0.4, 0.8)); + else + cr->set_source(Cairo::SolidPattern::create_rgb (0.4, 0.4, 0.4)); + cr->fill_preserve(); - cr->set_source_rgb(0.25, 0.25, 0.25); - cr->stroke(); + cr->set_source_rgb(0.25, 0.25, 0.25); + cr->stroke(); - // Show the clip name - cr->rectangle(x, 1, width, 100-2); - cr->clip(); + // Show the clip name + cr->rectangle(x, 1, width, 100-2); + cr->clip(); - cr->move_to (x + 3, 12); - cr->set_source_rgb (1.0, 1.0, 1.0); + cr->move_to (x + 3, 12); + cr->set_source_rgb (1.0, 1.0, 1.0); - cr->set_font_size (9); - cr->show_text (modelClip->getName()); + cr->set_font_size (9); + cr->show_text (modelClip->getName()); - // TODO: Show thumbnails for clip -} + // TODO: Show thumbnails for clip + } + + void + Clip::setSelected(bool selected) + { + this->selected = selected; + } } // namespace timeline } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-clip.hpp b/src/gui/widgets/timeline/timeline-clip.hpp index 6ac571d06..4937e38bc 100644 --- a/src/gui/widgets/timeline/timeline-clip.hpp +++ b/src/gui/widgets/timeline/timeline-clip.hpp @@ -37,27 +37,29 @@ namespace gui { namespace widgets { namespace timeline { -class Clip : public model::Clip -{ -public: - Clip(boost::shared_ptr clip); + class Clip : public model::Clip + { + public: + Clip(boost::shared_ptr clip); - void draw_clip(Cairo::RefPtr cairo, - TimelineViewWindow* const window) const; + void draw_clip(Cairo::RefPtr cairo, + TimelineViewWindow* const window) const; - void - setSelected(bool state); + /** + * Sets the selected status of the clip. + **/ + void + setSelected (bool state); -private: + private: - boost::shared_ptr modelClip; + boost::shared_ptr modelClip; - /** - * True when this clip is selected in the GUI. - */ - bool selected; - -}; + /** + * True when this clip is selected in the GUI. + */ + bool selected; + }; } // namespace timeline } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-header-widget.cpp b/src/gui/widgets/timeline/timeline-header-widget.cpp index 1eac796d0..734e42dfd 100644 --- a/src/gui/widgets/timeline/timeline-header-widget.cpp +++ b/src/gui/widgets/timeline/timeline-header-widget.cpp @@ -160,7 +160,7 @@ TimelineHeaderWidget::on_expose_event(GdkEventExpose *event) REQUIRE(style); REQUIRE(gdkWindow); - shared_ptr modelTrack = track.get_modelTrack(); + shared_ptr modelTrack = track.getModelTrack(); REQUIRE(modelTrack); // Get the header box diff --git a/src/gui/widgets/timeline/timeline-layout-helper.cpp b/src/gui/widgets/timeline/timeline-layout-helper.cpp index ec653ad81..0e311cd7d 100644 --- a/src/gui/widgets/timeline/timeline-layout-helper.cpp +++ b/src/gui/widgets/timeline/timeline-layout-helper.cpp @@ -150,7 +150,7 @@ TimelineLayoutHelper::begin_dragging_track( dragPoint.get_y() - rect.get_y()); const shared_ptr modelTrack = - dragging_track->get_modelTrack(); + dragging_track->getModelTrack(); draggingTrackIter = iterator_from_track(modelTrack); dragBranchHeight = measure_branch_height(draggingTrackIter); diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index e2b22ce2e..2ac324f1f 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -103,7 +103,7 @@ Track::get_header_widget() } shared_ptr -Track::get_modelTrack() const +Track::getModelTrack() const { return modelTrack; } @@ -120,6 +120,13 @@ Track::get_expanded() const return expanded; } +boost::shared_ptr +Track::getClipAt(lumiera::Time) const +{ + // Default implementation returns empty pointer + return boost::shared_ptr(); +} + void Track::expand_collapse(ExpandDirection direction) { diff --git a/src/gui/widgets/timeline/timeline-track.hpp b/src/gui/widgets/timeline/timeline-track.hpp index 7e0668f31..663327494 100644 --- a/src/gui/widgets/timeline/timeline-track.hpp +++ b/src/gui/widgets/timeline/timeline-track.hpp @@ -28,6 +28,7 @@ #include "gui/widgets/menu-button.hpp" #include "gui/widgets/mini-button.hpp" #include "gui/widgets/button-bar.hpp" +#include "timeline-clip.hpp" #include "timeline-header-container.hpp" #include "timeline-header-widget.hpp" @@ -75,7 +76,7 @@ public: Gtk::Widget& get_header_widget(); boost::shared_ptr - get_modelTrack() const; + getModelTrack() const; /** * Return the visual height of the track in pixels. @@ -109,24 +110,24 @@ public: * @see tick_expand_animation **/ float get_expand_animation_state() const; - + /** * Gets whether the branch is animation. * @return Returns true if the branch is animating, false if not. **/ bool is_expand_animating() const; - + /** * When this track is being animated, tick_expand_animation must be * called repeatedly to cause the animation to progress. - **/ + **/ void tick_expand_animation(); - + /** * Calculates the expander style, given the animation state. **/ Gtk::ExpanderStyle get_expander_style() const; - + /** * **/ @@ -139,6 +140,14 @@ public: TimelineViewWindow* const window) const = 0; + /** + * Gets the clip that is occupying the given time. + * The default implementation simply returns an empty pointer. + * @param the given time + **/ + virtual boost::shared_ptr + getClipAt(lumiera::Time position) const; + private: /**