From 7500732976fd24dc96d24defe3978b604c3eb2fa Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 2 Jan 2011 10:40:17 +0100 Subject: [PATCH] Move Clips for ClipTracks to the GUI model. --- src/gui/model/clip-track.cpp | 43 ++++-- src/gui/model/clip-track.hpp | 44 ++++-- src/gui/widgets/timeline-widget.cpp | 2 +- src/gui/widgets/timeline-widget.hpp | 4 +- .../widgets/timeline/timeline-clip-track.cpp | 134 +++++++++++++----- .../widgets/timeline/timeline-clip-track.hpp | 69 +++++++-- .../widgets/timeline/timeline-group-track.cpp | 2 +- 7 files changed, 222 insertions(+), 76 deletions(-) diff --git a/src/gui/model/clip-track.cpp b/src/gui/model/clip-track.cpp index 30407a1f8..bc691993f 100644 --- a/src/gui/model/clip-track.cpp +++ b/src/gui/model/clip-track.cpp @@ -22,22 +22,39 @@ #include "clip-track.hpp" +#include "clip.hpp" + +#include + namespace gui { namespace model { - -ClipTrack::ClipTrack() -{ -} -std::string -ClipTrack::print_track() -{ - std::ostringstream os; - - os << "ClipTrack\t\"" << get_name() << "\""; - - return os.str(); -} + ClipTrack::ClipTrack() + { + // TEST CODE: add a clip to the track + + boost::shared_ptr model_clip(new model::Clip()); + model_clip->setName("Clip Name"); + clips.push_back(model_clip); + + // END TEST CODE + } + + std::string + ClipTrack::print_track() + { + std::ostringstream os; + + os << "ClipTrack\t\"" << get_name() << "\""; + + return os.str(); + } + + lumiera::observable_list< boost::shared_ptr >& + ClipTrack::getClipList() + { + return clips; + } } // namespace model } // namespace gui diff --git a/src/gui/model/clip-track.hpp b/src/gui/model/clip-track.hpp index 1fa86f7f1..ed4957581 100644 --- a/src/gui/model/clip-track.hpp +++ b/src/gui/model/clip-track.hpp @@ -29,24 +29,38 @@ #define CLIP_TRACK_HPP #include "track.hpp" +#include "lib/observable-list.hpp" namespace gui { namespace model { - -class Clip; - -class ClipTrack : public Track -{ -public: - ClipTrack(); - - std::string print_track(); - -private: - - std::vector clips; - -}; + + class Clip; + + class ClipTrack : public Track + { + public: + /** + * Constructor + **/ + ClipTrack(); + + /** + * Gets a string representation of the track that is suitable for debugging + **/ + std::string + print_track(); + + /** + * Gets the list of clips associated with this track. + **/ + lumiera::observable_list< boost::shared_ptr >& + getClipList(void); + + private: + + lumiera::observable_list< boost::shared_ptr > clips; + + }; } // namespace timeline } // namespace gui diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 1eb0c19cb..0f44402af 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -315,7 +315,7 @@ TimelineWidget::create_timeline_track_from_model_track( // class if(typeid(*model_track) == typeid(model::ClipTrack)) return shared_ptr(new timeline::ClipTrack( - *this, model_track)); + *this, dynamic_pointer_cast(model_track))); else if(typeid(*model_track) == typeid(model::GroupTrack)) return shared_ptr(new timeline::GroupTrack( *this, dynamic_pointer_cast(model_track))); diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index ee9cd184a..3bfa76593 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -241,9 +241,9 @@ protected: /** * The trackMap maps model tracks to timeline widget tracks which are * responsible for the UI representation of a track. - * @remarks The tree structure is maintianed by the model, and as the + * @remarks The tree structure is maintained by the model, and as the * widget is updated with update_tracks, timeline tracks are added and - * removed from the map in correspondance with the tree. + * removed from the map in correspondence with the tree. **/ std::map, boost::shared_ptr > diff --git a/src/gui/widgets/timeline/timeline-clip-track.cpp b/src/gui/widgets/timeline/timeline-clip-track.cpp index cf02f1bab..beddafc62 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.cpp +++ b/src/gui/widgets/timeline/timeline-clip-track.cpp @@ -27,47 +27,117 @@ #include "timeline-view-window.hpp" using namespace Gtk; +using boost::dynamic_pointer_cast; +using boost::shared_ptr; +using util::contains; namespace gui { namespace widgets { namespace timeline { -ClipTrack::ClipTrack(TimelineWidget &timelineWidget, - boost::shared_ptr track) : - Track(timelineWidget, track) -{ - // TEST CODE: add a clip to the track - boost::shared_ptr model_clip(new model::Clip()); - model_clip->setName("Clip Name"); - boost::shared_ptr timeline_clip(new timeline::Clip(model_clip)); - clips.push_back(timeline_clip); - // END TEST CODE -} + ClipTrack::ClipTrack (TimelineWidget &timelineWidget, + shared_ptr track) : + Track(timelineWidget, track) + { + REQUIRE (track); -void -ClipTrack::draw_track(Cairo::RefPtr cairo, + // Connect signals + track->getClipList().signal_changed().connect( + sigc::mem_fun(this, &ClipTrack::onClipListChanged)); + + updateClips(); + } + + void + ClipTrack::draw_track ( + Cairo::RefPtr cairo, TimelineViewWindow* const window) const -{ - REQUIRE(cairo); - REQUIRE(window); + { + REQUIRE (cairo); + REQUIRE (window); - // Draw a rectangle to let us know it works? :-) - cairo->rectangle(window->time_to_x(0), 1, - window->time_to_x(500000) - window->time_to_x(0), - get_height() - 2); - - cairo->set_source_rgb(0.5, 0.5, 0.5); - cairo->fill_preserve(); - - cairo->set_source_rgb(0.25, 0.25, 0.25); - cairo->stroke(); + // Draw a rectangle to let us know it works? :-) + cairo->rectangle(window->time_to_x(0), 1, + window->time_to_x(500000) - window->time_to_x(0), + get_height() - 2); - // Draw all clips - BOOST_FOREACH(boost::shared_ptr c, clips) - { - c->draw_clip(cairo, window); - } -} + cairo->set_source_rgb(0.5, 0.5, 0.5); + cairo->fill_preserve(); + + cairo->set_source_rgb(0.25, 0.25, 0.25); + cairo->stroke(); + + // Draw all clips + std::pair, shared_ptr > + pair; + BOOST_FOREACH (pair, clipMap) + { + pair.second->draw_clip(cairo, window); + } + } + + //// private methods + + void + ClipTrack::createTimelineClips() + { + BOOST_FOREACH (shared_ptr modelClip, getModelTrack()->getClipList()) + { + // Is a timeline UI clip present in the map already? + if (!contains (clipMap, modelClip)) + { + // The timeline UI clip is not present + // We will need to create one + clipMap[modelClip] = shared_ptr( + new timeline::Clip (modelClip)); + } + } + } + + shared_ptr + ClipTrack::getModelTrack () + { + return dynamic_pointer_cast(model_track); + } + + void + ClipTrack::onClipListChanged () + { + updateClips (); + } + + void + ClipTrack::removeOrphanedClips () + { + std::map< shared_ptr, + shared_ptr > + orphanClipMap (clipMap); + + // Remove all clips which are still present in the sequence + BOOST_FOREACH (shared_ptr modelClip, getModelTrack()->getClipList()) + if (contains (orphanClipMap, modelClip)) + orphanClipMap.erase(modelClip); + + // orphanClipMap now contains all the orphaned clips + // Remove them + std::pair< shared_ptr, shared_ptr > + pair; + BOOST_FOREACH (pair, orphanClipMap) + { + ENSURE (pair.first); + clipMap.erase (pair.first); + } + } + + void + ClipTrack::updateClips() + { + // Remove any clips which are no longer present in the model + removeOrphanedClips (); + + // Create timeline clips from all the model clips + createTimelineClips (); + } } // namespace timeline } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-clip-track.hpp b/src/gui/widgets/timeline/timeline-clip-track.hpp index cd71e44f1..49a29bb19 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.hpp +++ b/src/gui/widgets/timeline/timeline-clip-track.hpp @@ -37,21 +37,66 @@ namespace gui { namespace widgets { namespace timeline { -class Clip; -class TimelineViewWindow; + class Clip; + class TimelineViewWindow; -class ClipTrack : public timeline::Track -{ -public: - ClipTrack(TimelineWidget &timelineWidget, - boost::shared_ptr track); + class ClipTrack : public timeline::Track + { + public: + /** + * Constructor. + **/ + ClipTrack(TimelineWidget &timelineWidget, + boost::shared_ptr track); - void draw_track(Cairo::RefPtr cairo, - TimelineViewWindow* const window) const; + /** + * + **/ + void draw_track(Cairo::RefPtr cairo, + TimelineViewWindow* const window) const; -private: - std::vector > clips; -}; + private: + + /** + * Ensures timeline UI clips have been created for every model clip in track. + **/ + void + createTimelineClips(); + + /** + * Gets the modelTrack as a ClipTrack. + **/ + boost::shared_ptr + getModelTrack (); + + /** + * An event handler that receives notifications for when the models clip list has been + * changed. + **/ + void + onClipListChanged(); + + /** + * Removes any UI clips which no longer have corresponding model clips present in the + * sequence. + **/ + void + removeOrphanedClips(); + + /** + * Update the attached timeline clips. + **/ + void + updateClips(); + + /** + * The clipMap maps model clips to timeline widget clips which are responsible for the + * UI representation of a clip. + **/ + std::map, + boost::shared_ptr > + clipMap; + }; } // namespace timeline } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-group-track.cpp b/src/gui/widgets/timeline/timeline-group-track.cpp index 9407a41da..aa43e1970 100644 --- a/src/gui/widgets/timeline/timeline-group-track.cpp +++ b/src/gui/widgets/timeline/timeline-group-track.cpp @@ -35,7 +35,7 @@ GroupTrack::GroupTrack(TimelineWidget &timeline_widget, shared_ptr track) : Track(timeline_widget, track) { - REQUIRE(track); + REQUIRE (track); // Receive notifications of changes to the tracks track->get_child_track_list().signal_changed().connect(