#include "lib/film.h"
#include "lib/image_content.h"
#include "lib/playlist.h"
+#include "lib/scope_guard.h"
#include "lib/text_content.h"
#include "lib/timer.h"
#include "lib/video_content.h"
+#include <dcp/warnings.h>
+LIBDCP_DISABLE_WARNINGS
#include <wx/graphics.h>
+LIBDCP_ENABLE_WARNINGS
#include <iterator>
#include <list>
int const Timeline::_minimum_pixels_per_track = 16;
-Timeline::Timeline (wxWindow* parent, ContentPanel* cp, shared_ptr<Film> film, weak_ptr<FilmViewer> viewer)
+Timeline::Timeline(wxWindow* parent, ContentPanel* cp, shared_ptr<Film> film, FilmViewer& viewer)
: wxPanel (parent, wxID_ANY)
, _labels_canvas (new wxScrolledCanvas (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE))
, _main_canvas (new wxScrolledCanvas (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE))
, _left_down (false)
, _down_view_position (0)
, _first_move (false)
- , _menu (this)
+ , _menu (this, viewer)
, _snap (true)
, _tool (SELECT)
, _x_scroll_rate (16)
{
wxPaintDC dc (_labels_canvas);
+ auto film = _film.lock();
+ if (film->content().empty()) {
+ return;
+ }
+
auto gc = wxGraphicsContext::Create (dc);
if (!gc) {
return;
}
+ ScopeGuard sg = [gc]() { delete gc; };
+
int vsx, vsy;
_labels_canvas->GetViewStart (&vsx, &vsy);
gc->Translate (-vsx * _x_scroll_rate, -vsy * _y_scroll_rate + tracks_y_offset());
- _labels_view->paint (gc, list<dcpomatic::Rect<int> >());
-
- delete gc;
+ _labels_view->paint (gc, {});
}
Timeline::paint_main ()
{
wxPaintDC dc (_main_canvas);
+
+ auto film = _film.lock();
+ if (film->content().empty()) {
+ return;
+ }
+
_main_canvas->DoPrepareDC (dc);
auto gc = wxGraphicsContext::Create (dc);
return;
}
- int vsx, vsy;
- _main_canvas->GetViewStart (&vsx, &vsy);
- gc->Translate (-vsx * _x_scroll_rate, -vsy * _y_scroll_rate);
+ ScopeGuard sg = [gc]() { delete gc; };
gc->SetAntialiasMode (wxANTIALIAS_DEFAULT);
}
if (_zoom_point) {
- /* Translate back as _down_point and _zoom_point do not take scroll into account */
- gc->Translate (vsx * _x_scroll_rate, vsy * _y_scroll_rate);
- gc->SetPen (*wxBLACK_PEN);
+ gc->SetPen(gui_is_dark() ? *wxWHITE_PEN : *wxBLACK_PEN);
gc->SetBrush (*wxTRANSPARENT_BRUSH);
gc->DrawRectangle (
min (_down_point.x, _zoom_point->x),
/* Playhead */
- auto vp = _viewer.lock ();
- DCPOMATIC_ASSERT (vp);
-
gc->SetPen (*wxRED_PEN);
auto path = gc->CreatePath ();
- double const ph = vp->position().seconds() * pixels_per_second().get_value_or(0);
+ double const ph = _viewer.position().seconds() * pixels_per_second().get_value_or(0);
path.MoveToPoint (ph, 0);
path.AddLineToPoint (ph, pixels_per_track() * _tracks + 32);
gc->StrokePath (path);
-
- delete gc;
}
int t = base;
auto content = cv->content();
- DCPTimePeriod const content_period (content->position(), content->end(film));
+ DCPTimePeriod const content_period = content->period(film);
while (true) {
auto j = views.begin();
auto test_content = test->content();
if (
test->track() && test->track().get() == t &&
- content_period.overlap(DCPTimePeriod(test_content->position(), test_content->end(film)))) {
+ content_period.overlap(test_content->period(film))
+ ) {
/* we have an overlap on track `t' */
++t;
break;
Position<int> const p (ev.GetX() + vsx * _x_scroll_rate, ev.GetY() + vsy * _y_scroll_rate);
while (i != _views.rend() && !(*i)->bbox().contains (p)) {
- auto cv = dynamic_pointer_cast<TimelineContentView>(*i);
++i;
}
_down_view_position = content_view->content()->position ();
}
+ if (dynamic_pointer_cast<TimelineTimeAxisView>(view)) {
+ int vsx, vsy;
+ _main_canvas->GetViewStart(&vsx, &vsy);
+ _viewer.seek(DCPTime::from_seconds((ev.GetPosition().x + vsx * _x_scroll_rate) / _pixels_per_second.get_value_or(1)), true);
+ }
+
for (auto i: _views) {
auto cv = dynamic_pointer_cast<TimelineContentView>(i);
if (!cv) {
_labels_canvas->Scroll (0, 0);
Refresh ();
}
+
+
+void
+Timeline::keypress(wxKeyEvent const& event)
+{
+ if (event.GetKeyCode() == WXK_DELETE) {
+ auto film = _film.lock();
+ DCPOMATIC_ASSERT(film);
+ film->remove_content(selected_content());
+ } else {
+ switch (event.GetRawKeyCode()) {
+ case '+':
+ set_pixels_per_second(_pixels_per_second.get_value_or(1) * 2);
+ break;
+ case '-':
+ set_pixels_per_second(_pixels_per_second.get_value_or(1) / 2);
+ break;
+ }
+ }
+}
+