Add remove option; resize timeline after drags.
authorCarl Hetherington <cth@carlh.net>
Fri, 19 Jul 2013 14:22:26 +0000 (15:22 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 19 Jul 2013 14:22:26 +0000 (15:22 +0100)
src/lib/film.cc
src/lib/film.h
src/lib/player.cc
src/lib/playlist.cc
src/lib/playlist.h
src/lib/types.h
src/wx/film_editor.cc
src/wx/timeline.cc
src/wx/timeline.h

index 172fd20abaf4ea561d9379fb168ad009a47bde2f..d5a5abae4fe17daa9bbc7b3957af7798d3479e4d 100644 (file)
@@ -728,7 +728,7 @@ Film::playlist () const
        return _playlist;
 }
 
-Playlist::ContentList
+ContentList
 Film::content () const
 {
        return _playlist->content ();
index 497320c5e0bbb9c3cb8f218fff1fabc791138eab..51db8ce00729219c44e4f98077efaeedd6d34596 100644 (file)
@@ -106,7 +106,7 @@ public:
 
        /* Proxies for some Playlist methods */
 
-       Playlist::ContentList content () const;
+       ContentList content () const;
 
        Time length () const;
        bool has_subtitles () const;
index ec20892effe9ec571d89e3c6cbb33bb2a68c70cd..d3d5d0f6bb2415b4ae458761e80aa13f0d3124f9 100644 (file)
@@ -401,10 +401,10 @@ Player::setup_pieces ()
 
        _pieces.clear ();
 
-       Playlist::ContentList content = _playlist->content ();
+       ContentList content = _playlist->content ();
        sort (content.begin(), content.end(), ContentSorter ());
 
-       for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
+       for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
 
                shared_ptr<Piece> piece (new Piece (*i));
 
index e4494acb052b74f6ef545dcf8568a290a1918137..c9d05b0495465507210a28f462f63e0fb4804bc2 100644 (file)
@@ -158,6 +158,23 @@ Playlist::remove (shared_ptr<Content> c)
        }
 }
 
+void
+Playlist::remove (ContentList c)
+{
+       for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
+               ContentList::iterator j = _content.begin ();
+               while (j != _content.end() && *j != *i) {
+                       ++j;
+               }
+       
+               if (j != _content.end ()) {
+                       _content.erase (j);
+               }
+       }
+
+       Changed ();
+}
+
 bool
 Playlist::has_subtitles () const
 {
@@ -285,17 +302,17 @@ ContentSorter::operator() (shared_ptr<Content> a, shared_ptr<Content> b)
 }
 
 /** @return content in an undefined order */
-Playlist::ContentList
+ContentList
 Playlist::content () const
 {
        return _content;
 }
 
 void
-Playlist::repeat (list<shared_ptr<Content> > c, int n)
+Playlist::repeat (ContentList c, int n)
 {
        pair<Time, Time> range (TIME_MAX, 0);
-       for (list<shared_ptr<Content> >::iterator i = c.begin(); i != c.end(); ++i) {
+       for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
                range.first = min (range.first, (*i)->start ());
                range.second = max (range.second, (*i)->start ());
                range.first = min (range.first, (*i)->end ());
@@ -304,7 +321,7 @@ Playlist::repeat (list<shared_ptr<Content> > c, int n)
 
        Time pos = range.second;
        for (int i = 0; i < n; ++i) {
-               for (list<shared_ptr<Content> >::iterator i = c.begin(); i != c.end(); ++i) {
+               for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
                        shared_ptr<Content> copy = (*i)->clone ();
                        copy->set_start (pos + copy->start() - range.first);
                        _content.push_back (copy);
index 1d69c34baee71bde82ee950cf9f5854e88f0fbf9..e39e9f51f96aa13148a4c4b48c8066ca9c135904 100644 (file)
@@ -60,11 +60,10 @@ public:
 
        void add (boost::shared_ptr<Content>);
        void remove (boost::shared_ptr<Content>);
+       void remove (ContentList);
 
        bool has_subtitles () const;
 
-       typedef std::vector<boost::shared_ptr<Content> > ContentList;
-
        ContentList content () const;
 
        std::string video_identifier () const;
@@ -77,7 +76,7 @@ public:
        void set_sequence_video (bool);
        void maybe_sequence_video ();
 
-       void repeat (std::list<boost::shared_ptr<Content> >, int);
+       void repeat (ContentList, int);
 
        mutable boost::signals2::signal<void ()> Changed;
        /** Third parameter is true if signals are currently being emitted frequently */
index aeaa82ec6225cfd90b77d46f02ce98a819b37e0d..458a2ecf3a21377b1bc4e3f91cb5186416741360 100644 (file)
@@ -32,6 +32,7 @@ typedef int64_t Time;
 #define TIME_HZ         ((Time) 96000)
 typedef int64_t OutputAudioFrame;
 typedef int    OutputVideoFrame;
+typedef std::vector<boost::shared_ptr<Content> > ContentList;
 
 /** @struct Crop
  *  @brief A description of the crop of an image or video.
index f087bf84cf2887f393e2eeaccc321e9f031b047e..bfef303a8600d4bd77af26e734cc451265a50b59 100644 (file)
@@ -1132,8 +1132,8 @@ FilmEditor::setup_content ()
        
        _content->DeleteAllItems ();
 
-       Playlist::ContentList content = _film->content ();
-       for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
+       ContentList content = _film->content ();
+       for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
                int const t = _content->GetItemCount ();
                _content->InsertItem (t, std_to_wx ((*i)->summary ()));
                if ((*i)->summary() == selected_summary) {
@@ -1240,7 +1240,7 @@ FilmEditor::selected_content ()
                return shared_ptr<Content> ();
        }
 
-       Playlist::ContentList c = _film->content ();
+       ContentList c = _film->content ();
        if (s < 0 || size_t (s) >= c.size ()) {
                return shared_ptr<Content> ();
        }
@@ -1466,7 +1466,7 @@ FilmEditor::length_changed ()
 void
 FilmEditor::set_selection (weak_ptr<Content> wc)
 {
-       Playlist::ContentList content = _film->content ();
+       ContentList content = _film->content ();
        for (size_t i = 0; i < content.size(); ++i) {
                if (content[i] == wc.lock ()) {
                        _content->SetItemState (i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
index 7d0ce660c3e3f88437eb69b621ba992ba60c5738..116ff81913a45ba701596a06e0abc95996c96b69 100644 (file)
@@ -81,7 +81,7 @@ public:
                , _track (t)
                , _selected (false)
        {
-               _content_connection = c->Changed.connect (bind (&ContentView::content_changed, this, _2));
+               _content_connection = c->Changed.connect (bind (&ContentView::content_changed, this, _2, _3));
        }
 
        dcpomatic::Rect<int> bbox () const
@@ -174,11 +174,16 @@ private:
                return _timeline.tracks_position().y + t * _timeline.track_height();
        }
 
-       void content_changed (int p)
+       void content_changed (int p, bool frequent)
        {
                if (p == ContentProperty::START || p == ContentProperty::LENGTH) {
                        force_redraw ();
                }
+
+               if (!frequent) {
+                       _timeline.setup_pixels_per_time_unit ();
+                       _timeline.Refresh ();
+               }
        }
 
        boost::weak_ptr<Content> _content;
@@ -314,7 +319,8 @@ private:
 };
 
 enum {
-       ID_repeat
+       ID_repeat,
+       ID_remove
 };
 
 Timeline::Timeline (wxWindow* parent, FilmEditor* ed, shared_ptr<Film> film)
@@ -339,7 +345,9 @@ Timeline::Timeline (wxWindow* parent, FilmEditor* ed, shared_ptr<Film> film)
        Connect (wxID_ANY, wxEVT_RIGHT_DOWN, wxMouseEventHandler (Timeline::right_down), 0, this);
        Connect (wxID_ANY, wxEVT_MOTION, wxMouseEventHandler (Timeline::mouse_moved), 0, this);
        Connect (wxID_ANY, wxEVT_SIZE, wxSizeEventHandler (Timeline::resized), 0, this);
+
        Connect (ID_repeat, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Timeline::repeat), 0, this);
+       Connect (ID_remove, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Timeline::remove), 0, this);
 
        playlist_changed ();
 
@@ -360,7 +368,7 @@ Timeline::paint (wxPaintEvent &)
 
        gc->SetFont (gc->CreateFont (*wxNORMAL_FONT));
 
-       for (list<shared_ptr<View> >::iterator i = _views.begin(); i != _views.end(); ++i) {
+       for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) {
                (*i)->paint (gc);
        }
 
@@ -378,9 +386,9 @@ Timeline::playlist_changed ()
        _views.clear ();
        _views.push_back (_time_axis_view);
 
-       Playlist::ContentList content = fl->playlist()->content ();
+       ContentList content = fl->playlist()->content ();
 
-       for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
+       for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
                if (dynamic_pointer_cast<VideoContent> (*i)) {
                        _views.push_back (shared_ptr<View> (new VideoContentView (*this, *i, 0)));
                }
@@ -397,7 +405,7 @@ Timeline::playlist_changed ()
 void
 Timeline::assign_tracks ()
 {
-       for (list<shared_ptr<View> >::iterator i = _views.begin(); i != _views.end(); ++i) {
+       for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) {
                shared_ptr<ContentView> cv = dynamic_pointer_cast<ContentView> (*i);
                if (cv) {
                        cv->set_track (0);
@@ -405,7 +413,7 @@ Timeline::assign_tracks ()
                }
        }
 
-       for (list<shared_ptr<View> >::iterator i = _views.begin(); i != _views.end(); ++i) {
+       for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) {
                shared_ptr<AudioContentView> acv = dynamic_pointer_cast<AudioContentView> (*i);
                if (!acv) {
                        continue;
@@ -415,7 +423,7 @@ Timeline::assign_tracks ()
                
                int t = 1;
                while (1) {
-                       list<shared_ptr<View> >::iterator j = _views.begin();
+                       ViewList::iterator j = _views.begin();
                        while (j != _views.end()) {
                                shared_ptr<AudioContentView> test = dynamic_pointer_cast<AudioContentView> (*j);
                                if (!test) {
@@ -470,7 +478,7 @@ Timeline::setup_pixels_per_time_unit ()
 shared_ptr<View>
 Timeline::event_to_view (wxMouseEvent& ev)
 {
-       list<shared_ptr<View> >::iterator i = _views.begin();
+       ViewList::iterator i = _views.begin();
        Position<int> const p (ev.GetX(), ev.GetY());
        while (i != _views.end() && !(*i)->bbox().contains (p)) {
                ++i;
@@ -496,7 +504,7 @@ Timeline::left_down (wxMouseEvent& ev)
                _down_view_start = content_view->content()->start ();
        }
 
-       for (list<shared_ptr<View> >::iterator i = _views.begin(); i != _views.end(); ++i) {
+       for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) {
                shared_ptr<ContentView> cv = dynamic_pointer_cast<ContentView> (*i);
                if (!cv) {
                        continue;
@@ -563,6 +571,8 @@ Timeline::right_down (wxMouseEvent& ev)
        if (!_menu) {
                _menu = new wxMenu;
                _menu->Append (ID_repeat, _("Repeat..."));
+               _menu->AppendSeparator ();
+               _menu->Append (ID_remove, _("Remove"));
        }
 
        PopupMenu (_menu, ev.GetPosition ());
@@ -612,7 +622,7 @@ Timeline::resized (wxSizeEvent &)
 void
 Timeline::clear_selection ()
 {
-       for (list<shared_ptr<View> >::iterator i = _views.begin(); i != _views.end(); ++i) {
+       for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) {
                shared_ptr<ContentView> cv = dynamic_pointer_cast<ContentView> (*i);
                if (cv) {
                        cv->set_selected (false);
@@ -623,7 +633,7 @@ Timeline::clear_selection ()
 void
 Timeline::repeat (wxCommandEvent &)
 {
-       list<shared_ptr<ContentView> > sel = selected ();
+       ContentList sel = selected_content ();
        if (sel.empty ()) {
                return;
        }
@@ -636,21 +646,32 @@ Timeline::repeat (wxCommandEvent &)
                return;
        }
 
-       list<shared_ptr<Content> > content;
-       for (list<shared_ptr<ContentView> >::iterator i = sel.begin(); i != sel.end(); ++i) {
-               content.push_back ((*i)->content ());
+       film->playlist()->repeat (sel, d.number ());
+       d.Destroy ();
+}
+
+void
+Timeline::remove (wxCommandEvent &)
+{
+       ContentList sel = selected_content ();
+       if (sel.empty ()) {
+               return;
        }
 
-       film->playlist()->repeat (content, d.number ());
-       d.Destroy ();
+       shared_ptr<const Film> film = _film.lock ();
+       if (!film) {
+               return;
+       }
+
+       film->playlist()->remove (sel);
 }
 
-list<shared_ptr<ContentView> >
-Timeline::selected () const
+Timeline::ContentViewList
+Timeline::selected_views () const
 {
-       list<shared_ptr<ContentView> > sel;
+       ContentViewList sel;
        
-       for (list<shared_ptr<View> >::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+       for (ViewList::const_iterator i = _views.begin(); i != _views.end(); ++i) {
                shared_ptr<ContentView> cv = dynamic_pointer_cast<ContentView> (*i);
                if (cv && cv->selected()) {
                        sel.push_back (cv);
@@ -659,4 +680,16 @@ Timeline::selected () const
 
        return sel;
 }
-               
+
+ContentList
+Timeline::selected_content () const
+{
+       ContentList sel;
+       ContentViewList views = selected_views ();
+       
+       for (ContentViewList::const_iterator i = views.begin(); i != views.end(); ++i) {
+               sel.push_back ((*i)->content ());
+       }
+
+       return sel;
+}
index 99094788f1aded6593143e12113be47f3c7d3282..48eaa9d762250bbde17d12797f6b4147f679c9f2 100644 (file)
@@ -61,6 +61,8 @@ public:
 
        int tracks () const;
 
+       void setup_pixels_per_time_unit ();
+
 private:
        void paint (wxPaintEvent &);
        void left_down (wxMouseEvent &);
@@ -68,19 +70,24 @@ private:
        void right_down (wxMouseEvent &);
        void mouse_moved (wxMouseEvent &);
        void playlist_changed ();
-       void setup_pixels_per_time_unit ();
        void resized (wxSizeEvent &);
        void assign_tracks ();
        void set_start_from_event (wxMouseEvent &);
        void clear_selection ();
+
        void repeat (wxCommandEvent &);
+       void remove (wxCommandEvent &);
+
+       typedef std::vector<boost::shared_ptr<View> > ViewList;
+       typedef std::vector<boost::shared_ptr<ContentView> > ContentViewList;
 
        boost::shared_ptr<View> event_to_view (wxMouseEvent &);
-       std::list<boost::shared_ptr<ContentView> > selected () const;
+       ContentViewList selected_views () const;
+       ContentList selected_content () const;
 
        FilmEditor* _film_editor;
        boost::weak_ptr<Film> _film;
-       std::list<boost::shared_ptr<View> > _views;
+       ViewList _views;
        boost::shared_ptr<TimeAxisView> _time_axis_view;
        int _tracks;
        double _pixels_per_time_unit;