2 Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <wx/graphics.h>
29 using boost::shared_ptr;
32 int const Timeline::_track_height = 64;
34 Timeline::Timeline (wxWindow* parent, shared_ptr<Playlist> pl)
38 SetDoubleBuffered (true);
40 Connect (wxID_ANY, wxEVT_PAINT, wxPaintEventHandler (Timeline::paint), 0, this);
42 if (pl->audio_from() == Playlist::AUDIO_FFMPEG) {
43 SetMinSize (wxSize (640, _track_height * 2 + 96));
45 SetMinSize (wxSize (640, _track_height * (max (size_t (1), pl->audio().size()) + 1) + 96));
48 pl->Changed.connect (bind (&Timeline::playlist_changed, this));
49 pl->ContentChanged.connect (bind (&Timeline::playlist_changed, this));
55 list<shared_ptr<const T> > content, wxGraphicsContext* gc, int x, int y, double pixels_per_second, int track_height, wxString type, bool consecutive
59 for (typename list<shared_ptr<const T> >::iterator i = content.begin(); i != content.end(); ++i) {
60 Time const len = (*i)->temporal_length ();
61 wxGraphicsPath path = gc->CreatePath ();
62 path.MoveToPoint (x + t * pixels_per_second, y);
63 path.AddLineToPoint (x + (t + len) * pixels_per_second, y);
64 path.AddLineToPoint (x + (t + len) * pixels_per_second, y + track_height);
65 path.AddLineToPoint (x + t * pixels_per_second, y + track_height);
66 path.AddLineToPoint (x + t * pixels_per_second, y);
67 gc->StrokePath (path);
70 wxString name = wxString::Format ("%s [%s]", std_to_wx ((*i)->file().filename().string()), type);
73 wxDouble name_descent;
74 wxDouble name_leading;
75 gc->GetTextExtent (name, &name_width, &name_height, &name_descent, &name_leading);
77 gc->Clip (wxRegion (x + t * pixels_per_second, y, len * pixels_per_second, track_height));
78 gc->DrawText (name, t * pixels_per_second + 12, y + track_height - name_height - 4);
96 Timeline::paint (wxPaintEvent &)
100 shared_ptr<Playlist> pl = _playlist.lock ();
105 wxGraphicsContext* gc = wxGraphicsContext::Create (dc);
110 int const x_offset = 8;
112 int const width = GetSize().GetWidth();
113 double const pixels_per_second = (width - x_offset * 2) / (pl->content_length() / pl->video_frame_rate());
115 gc->SetFont (gc->CreateFont (*wxNORMAL_FONT));
117 gc->SetPen (*wxBLACK_PEN);
118 #if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
119 gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 4, wxPENSTYLE_SOLID));
120 gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (wxColour (149, 121, 232, 255), wxBRUSHSTYLE_SOLID));
122 gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 4, SOLID));
123 gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (wxColour (149, 121, 232, 255), SOLID));
125 y = plot_content_list (pl->video (), gc, x_offset, y, pixels_per_second, _track_height, _("video"), true);
127 #if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
128 gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (wxColour (242, 92, 120, 255), wxBRUSHSTYLE_SOLID));
130 gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (wxColour (242, 92, 120, 255), SOLID));
132 y = plot_content_list (pl->audio (), gc, x_offset, y, pixels_per_second, _track_height, _("audio"), pl->audio_from() == Playlist::AUDIO_FFMPEG);
136 #if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
137 gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, wxPENSTYLE_SOLID));
139 gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, SOLID));
142 int mark_interval = rint (128 / pixels_per_second);
143 if (mark_interval > 5) {
144 mark_interval -= mark_interval % 5;
146 if (mark_interval > 10) {
147 mark_interval -= mark_interval % 10;
149 if (mark_interval > 60) {
150 mark_interval -= mark_interval % 60;
152 if (mark_interval > 3600) {
153 mark_interval -= mark_interval % 3600;
156 if (mark_interval < 1) {
160 wxGraphicsPath path = gc->CreatePath ();
161 path.MoveToPoint (x_offset, y + 40);
162 path.AddLineToPoint (width, y + 40);
163 gc->StrokePath (path);
166 while ((t * pixels_per_second) < width) {
167 wxGraphicsPath path = gc->CreatePath ();
168 path.MoveToPoint (x_offset + t * pixels_per_second, y + 36);
169 path.AddLineToPoint (x_offset + t * pixels_per_second, y + 44);
170 gc->StrokePath (path);
173 int const h = tc / 3600;
175 int const m = tc / 60;
179 wxString str = wxString::Format ("%02d:%02d:%02d", h, m, s);
182 wxDouble str_descent;
183 wxDouble str_leading;
184 gc->GetTextExtent (str, &str_width, &str_height, &str_descent, &str_leading);
186 int const tx = x_offset + t * pixels_per_second;
187 if ((tx + str_width) < width) {
188 gc->DrawText (str, x_offset + t * pixels_per_second, y + 60);
197 Timeline::playlist_changed ()