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;
31 int const Timeline::_track_height = 64;
33 Timeline::Timeline (wxWindow* parent, shared_ptr<Playlist> pl)
37 SetDoubleBuffered (true);
39 Connect (wxID_ANY, wxEVT_PAINT, wxPaintEventHandler (Timeline::paint), 0, this);
41 if (pl->audio_from() == Playlist::AUDIO_FFMPEG) {
42 SetMinSize (wxSize (640, _track_height * 2 + 96));
44 SetMinSize (wxSize (640, _track_height * (max (1UL, pl->audio().size()) + 1) + 96));
51 list<shared_ptr<const T> > content, wxGraphicsContext* gc, int x, int y, double pixels_per_second, int track_height, wxString type, bool consecutive
55 for (typename list<shared_ptr<const T> >::iterator i = content.begin(); i != content.end(); ++i) {
56 Time const len = (*i)->temporal_length ();
57 wxGraphicsPath path = gc->CreatePath ();
58 path.MoveToPoint (x + t * pixels_per_second, y);
59 path.AddLineToPoint (x + (t + len) * pixels_per_second, y);
60 path.AddLineToPoint (x + (t + len) * pixels_per_second, y + track_height);
61 path.AddLineToPoint (x + t * pixels_per_second, y + track_height);
62 path.AddLineToPoint (x + t * pixels_per_second, y);
63 gc->StrokePath (path);
66 wxString name = wxString::Format ("%s [%s]", std_to_wx ((*i)->file().filename().string()), type);
69 wxDouble name_descent;
70 wxDouble name_leading;
71 gc->GetTextExtent (name, &name_width, &name_height, &name_descent, &name_leading);
73 gc->Clip (wxRegion (x + t * pixels_per_second, y, len * pixels_per_second, track_height));
74 gc->DrawText (name, t * pixels_per_second + 12, y + track_height - name_height - 4);
92 Timeline::paint (wxPaintEvent &)
96 shared_ptr<Playlist> pl = _playlist.lock ();
101 wxGraphicsContext* gc = wxGraphicsContext::Create (dc);
106 int const x_offset = 8;
108 int const width = GetSize().GetWidth();
109 double const pixels_per_second = (width - x_offset * 2) / (pl->content_length() / pl->video_frame_rate());
111 gc->SetFont (gc->CreateFont (*wxNORMAL_FONT));
113 gc->SetPen (*wxBLACK_PEN);
114 #if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
115 gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 4, wxPENSTYLE_SOLID));
116 gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (wxColour (149, 121, 232, 255), wxBRUSHSTYLE_SOLID));
118 gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 4, SOLID));
119 gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (wxColour (149, 121, 232, 255), SOLID));
121 y = plot_content_list (pl->video (), gc, x_offset, y, pixels_per_second, _track_height, _("video"), true);
123 #if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
124 gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (wxColour (242, 92, 120, 255), wxBRUSHSTYLE_SOLID));
126 gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (wxColour (242, 92, 120, 255), SOLID));
128 y = plot_content_list (pl->audio (), gc, x_offset, y, pixels_per_second, _track_height, _("audio"), pl->audio_from() == Playlist::AUDIO_FFMPEG);
132 #if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
133 gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, wxPENSTYLE_SOLID));
135 gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, SOLID));
138 int mark_interval = rint (128 / pixels_per_second);
139 if (mark_interval > 5) {
140 mark_interval -= mark_interval % 5;
142 if (mark_interval > 10) {
143 mark_interval -= mark_interval % 10;
145 if (mark_interval > 60) {
146 mark_interval -= mark_interval % 60;
148 if (mark_interval > 3600) {
149 mark_interval -= mark_interval % 3600;
152 if (mark_interval < 1) {
156 wxGraphicsPath path = gc->CreatePath ();
157 path.MoveToPoint (x_offset, y + 40);
158 path.AddLineToPoint (width, y + 40);
159 gc->StrokePath (path);
162 while ((t * pixels_per_second) < width) {
163 wxGraphicsPath path = gc->CreatePath ();
164 path.MoveToPoint (x_offset + t * pixels_per_second, y + 36);
165 path.AddLineToPoint (x_offset + t * pixels_per_second, y + 44);
166 gc->StrokePath (path);
169 int const h = tc / 3600;
171 int const m = tc / 60;
175 wxString str = wxString::Format ("%02d:%02d:%02d", h, m, s);
178 wxDouble str_descent;
179 wxDouble str_leading;
180 gc->GetTextExtent (str, &str_width, &str_height, &str_descent, &str_leading);
182 int const tx = x_offset + t * pixels_per_second;
183 if ((tx + str_width) < width) {
184 gc->DrawText (str, x_offset + t * pixels_per_second, y + 60);