From 56506a1993f402fe889a650faa3de2e265632498 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 19 Jul 2013 15:22:26 +0100 Subject: [PATCH] Add remove option; resize timeline after drags. --- src/lib/film.cc | 2 +- src/lib/film.h | 2 +- src/lib/player.cc | 4 +-- src/lib/playlist.cc | 25 +++++++++++--- src/lib/playlist.h | 5 ++- src/lib/types.h | 1 + src/wx/film_editor.cc | 8 ++--- src/wx/timeline.cc | 79 ++++++++++++++++++++++++++++++------------- src/wx/timeline.h | 13 +++++-- 9 files changed, 98 insertions(+), 41 deletions(-) diff --git a/src/lib/film.cc b/src/lib/film.cc index 172fd20ab..d5a5abae4 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -728,7 +728,7 @@ Film::playlist () const return _playlist; } -Playlist::ContentList +ContentList Film::content () const { return _playlist->content (); diff --git a/src/lib/film.h b/src/lib/film.h index 497320c5e..51db8ce00 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -106,7 +106,7 @@ public: /* Proxies for some Playlist methods */ - Playlist::ContentList content () const; + ContentList content () const; Time length () const; bool has_subtitles () const; diff --git a/src/lib/player.cc b/src/lib/player.cc index ec20892ef..d3d5d0f6b 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -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 (new Piece (*i)); diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index e4494acb0..c9d05b049 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -158,6 +158,23 @@ Playlist::remove (shared_ptr 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 a, shared_ptr b) } /** @return content in an undefined order */ -Playlist::ContentList +ContentList Playlist::content () const { return _content; } void -Playlist::repeat (list > c, int n) +Playlist::repeat (ContentList c, int n) { pair range (TIME_MAX, 0); - for (list >::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 > c, int n) Time pos = range.second; for (int i = 0; i < n; ++i) { - for (list >::iterator i = c.begin(); i != c.end(); ++i) { + for (ContentList::iterator i = c.begin(); i != c.end(); ++i) { shared_ptr copy = (*i)->clone (); copy->set_start (pos + copy->start() - range.first); _content.push_back (copy); diff --git a/src/lib/playlist.h b/src/lib/playlist.h index 1d69c34ba..e39e9f51f 100644 --- a/src/lib/playlist.h +++ b/src/lib/playlist.h @@ -60,11 +60,10 @@ public: void add (boost::shared_ptr); void remove (boost::shared_ptr); + void remove (ContentList); bool has_subtitles () const; - typedef std::vector > 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 >, int); + void repeat (ContentList, int); mutable boost::signals2::signal Changed; /** Third parameter is true if signals are currently being emitted frequently */ diff --git a/src/lib/types.h b/src/lib/types.h index aeaa82ec6..458a2ecf3 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -32,6 +32,7 @@ typedef int64_t Time; #define TIME_HZ ((Time) 96000) typedef int64_t OutputAudioFrame; typedef int OutputVideoFrame; +typedef std::vector > ContentList; /** @struct Crop * @brief A description of the crop of an image or video. diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index f087bf84c..bfef303a8 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -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 (); } - Playlist::ContentList c = _film->content (); + ContentList c = _film->content (); if (s < 0 || size_t (s) >= c.size ()) { return shared_ptr (); } @@ -1466,7 +1466,7 @@ FilmEditor::length_changed () void FilmEditor::set_selection (weak_ptr 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); diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index 7d0ce660c..116ff8191 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -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 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; @@ -314,7 +319,8 @@ private: }; enum { - ID_repeat + ID_repeat, + ID_remove }; Timeline::Timeline (wxWindow* parent, FilmEditor* ed, shared_ptr film) @@ -339,7 +345,9 @@ Timeline::Timeline (wxWindow* parent, FilmEditor* ed, shared_ptr 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 >::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 (*i)) { _views.push_back (shared_ptr (new VideoContentView (*this, *i, 0))); } @@ -397,7 +405,7 @@ Timeline::playlist_changed () void Timeline::assign_tracks () { - for (list >::iterator i = _views.begin(); i != _views.end(); ++i) { + for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) { shared_ptr cv = dynamic_pointer_cast (*i); if (cv) { cv->set_track (0); @@ -405,7 +413,7 @@ Timeline::assign_tracks () } } - for (list >::iterator i = _views.begin(); i != _views.end(); ++i) { + for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) { shared_ptr acv = dynamic_pointer_cast (*i); if (!acv) { continue; @@ -415,7 +423,7 @@ Timeline::assign_tracks () int t = 1; while (1) { - list >::iterator j = _views.begin(); + ViewList::iterator j = _views.begin(); while (j != _views.end()) { shared_ptr test = dynamic_pointer_cast (*j); if (!test) { @@ -470,7 +478,7 @@ Timeline::setup_pixels_per_time_unit () shared_ptr Timeline::event_to_view (wxMouseEvent& ev) { - list >::iterator i = _views.begin(); + ViewList::iterator i = _views.begin(); Position 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 >::iterator i = _views.begin(); i != _views.end(); ++i) { + for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) { shared_ptr cv = dynamic_pointer_cast (*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 >::iterator i = _views.begin(); i != _views.end(); ++i) { + for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) { shared_ptr cv = dynamic_pointer_cast (*i); if (cv) { cv->set_selected (false); @@ -623,7 +633,7 @@ Timeline::clear_selection () void Timeline::repeat (wxCommandEvent &) { - list > sel = selected (); + ContentList sel = selected_content (); if (sel.empty ()) { return; } @@ -636,21 +646,32 @@ Timeline::repeat (wxCommandEvent &) return; } - list > content; - for (list >::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 film = _film.lock (); + if (!film) { + return; + } + + film->playlist()->remove (sel); } -list > -Timeline::selected () const +Timeline::ContentViewList +Timeline::selected_views () const { - list > sel; + ContentViewList sel; - for (list >::const_iterator i = _views.begin(); i != _views.end(); ++i) { + for (ViewList::const_iterator i = _views.begin(); i != _views.end(); ++i) { shared_ptr cv = dynamic_pointer_cast (*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; +} diff --git a/src/wx/timeline.h b/src/wx/timeline.h index 99094788f..48eaa9d76 100644 --- a/src/wx/timeline.h +++ b/src/wx/timeline.h @@ -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 > ViewList; + typedef std::vector > ContentViewList; boost::shared_ptr event_to_view (wxMouseEvent &); - std::list > selected () const; + ContentViewList selected_views () const; + ContentList selected_content () const; FilmEditor* _film_editor; boost::weak_ptr _film; - std::list > _views; + ViewList _views; boost::shared_ptr _time_axis_view; int _tracks; double _pixels_per_time_unit; -- 2.30.2