diff --git a/TimeLayout.cpp b/TimeLayout.cpp deleted file mode 100644 index a3a37b4..0000000 --- a/TimeLayout.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "TimeLayout.h" - -namespace toucan -{ - void ITimeWidget::_init( - const std::shared_ptr& context, - const OTIO_NS::TimeRange& timeRange, - const std::string& objectName, - const std::shared_ptr& parent) - { - dtk::IWidget::_init(context, objectName, parent); - _timeRange = timeRange; - } - - ITimeWidget::~ITimeWidget() - {} - - const OTIO_NS::TimeRange& ITimeWidget::getTimeRange() - { - return _timeRange; - } - - double ITimeWidget::getScale() const - { - return _scale; - } - - void ITimeWidget::setScale(double value) - { - if (value == _scale) - return; - _scale = value; - for (const auto& child : getChildren()) - { - if (auto item = std::dynamic_pointer_cast(child)) - { - item->setScale(value); - } - } - _setSizeUpdate(); - } - - int ITimeWidget::getMinWidth() const - { - return _minWidth; - } - - OTIO_NS::RationalTime ITimeWidget::posToTime(double value) const - { - OTIO_NS::RationalTime out; - const dtk::Box2I& g = getGeometry(); - if (g.w() > 0) - { - const double n = (value - g.min.x) / static_cast(g.w()); - out = OTIO_NS::RationalTime( - _timeRange.start_time() + - OTIO_NS::RationalTime( - _timeRange.duration().value() * n, - _timeRange.duration().rate())). - round(); - out = dtk::clamp( - out, - _timeRange.start_time(), - _timeRange.end_time_inclusive()); - } - return out; - } - - int ITimeWidget::timeToPos(const OTIO_NS::RationalTime& value) const - { - int out = 0; - const dtk::Box2I& g = getGeometry(); - if (_timeRange.duration().value() > 0.0) - { - const OTIO_NS::RationalTime t = value - _timeRange.start_time(); - const double n = t.value() / _timeRange.duration().rescaled_to(t).value(); - out = g.min.x + g.w() * n; - } - return out; - } - - void TimeLayout::_init( - const std::shared_ptr& context, - const OTIO_NS::TimeRange& timeRange, - const std::shared_ptr& parent) - { - ITimeWidget::_init(context, timeRange, "toucan::TimeLayout", parent); - } - - TimeLayout::~TimeLayout() - {} - - std::shared_ptr TimeLayout::create( - const std::shared_ptr& context, - const OTIO_NS::TimeRange& timeRange, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new TimeLayout); - out->_init(context, timeRange, parent); - return out; - } - - void TimeLayout::setGeometry(const dtk::Box2I& value) - { - ITimeWidget::setGeometry(value); - for (const auto& child : getChildren()) - { - if (auto timeWidget = std::dynamic_pointer_cast(child)) - { - const OTIO_NS::TimeRange& timeRange = timeWidget->getTimeRange(); - const int t0 = timeToPos(timeRange.start_time()); - const int t1 = timeToPos(timeRange.end_time_exclusive()); - const dtk::Size2I& childSizeHint = child->getSizeHint(); - child->setGeometry(dtk::Box2I( - t0, - value.min.y, - std::max(t1 - t0, timeWidget->getMinWidth()), - childSizeHint.h)); - } - } - } - - void TimeLayout::sizeHintEvent(const dtk::SizeHintEvent& event) - { - ITimeWidget::sizeHintEvent(event); - dtk::Size2I sizeHint; - for (const auto& child : getChildren()) - { - if (auto timeWidget = std::dynamic_pointer_cast(child)) - { - const dtk::Size2I& childSizeHint = timeWidget->getSizeHint(); - sizeHint.h = std::max(sizeHint.h, childSizeHint.h); - } - } - sizeHint.w = _timeRange.duration().rescaled_to(1.0).value() * _scale; - _setSizeHint(sizeHint); - } - - void TimeStackLayout::_init( - const std::shared_ptr& context, - const OTIO_NS::TimeRange& timeRange, - const std::shared_ptr& parent) - { - ITimeWidget::_init(context, timeRange, "toucan::TimeStackLayout", parent); - } - - TimeStackLayout::~TimeStackLayout() - {} - - std::shared_ptr TimeStackLayout::create( - const std::shared_ptr& context, - const OTIO_NS::TimeRange& timeRange, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new TimeStackLayout); - out->_init(context, timeRange, parent); - return out; - } - - void TimeStackLayout::setGeometry(const dtk::Box2I& value) - { - ITimeWidget::setGeometry(value); - int y = value.min.y; - for (const auto& child : getChildren()) - { - if (auto timeWidget = std::dynamic_pointer_cast(child)) - { - const OTIO_NS::TimeRange& timeRange = timeWidget->getTimeRange(); - const double t0 = timeToPos(timeRange.start_time()); - const double t1 = timeToPos(timeRange.end_time_exclusive()); - const dtk::Size2I& childSizeHint = child->getSizeHint(); - child->setGeometry(dtk::Box2I(t0, y, t1 - t0, childSizeHint.h)); - y += childSizeHint.h + _size.spacing; - }; - } - } - - void TimeStackLayout::sizeHintEvent(const dtk::SizeHintEvent& event) - { - ITimeWidget::sizeHintEvent(event); - const bool displayScaleChanged = event.displayScale != _size.displayScale; - if (_size.init || displayScaleChanged) - { - _size.init = false; - _size.displayScale = event.displayScale; - _size.spacing = event.style->getSizeRole(dtk::SizeRole::SpacingTool, event.displayScale); - } - - dtk::Size2I sizeHint; - const auto& children = getChildren(); - if (!children.empty()) - { - for (const auto& child : children) - { - if (auto timeWidget = std::dynamic_pointer_cast(child)) - { - const dtk::Size2I& childSizeHint = timeWidget->getSizeHint(); - sizeHint.h += childSizeHint.h; - } - } - sizeHint.h += (children.size() - 1) * _size.spacing; - } - sizeHint.w = _timeRange.duration().rescaled_to(1.0).value() * _scale; - _setSizeHint(sizeHint); - } -} diff --git a/TimelineItem.cpp b/TimelineItem.cpp deleted file mode 100644 index 5ddcc72..0000000 --- a/TimelineItem.cpp +++ /dev/null @@ -1,616 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "TimelineItem.h" - -#include "App.h" -#include "FilesModel.h" -#include "StackItem.h" -#include "WindowModel.h" - -#include - -namespace toucan -{ - void TimelineItem::_init( - const std::shared_ptr& context, - const ItemData& data, - const std::shared_ptr& parent) - { - IItem::_init( - context, - data, - nullptr, - data.file->getTimelineWrapper()->getTimeRange(), - "toucan::TimelineItem", - parent); - - _setMouseHoverEnabled(true); - _setMousePressEnabled( - true, - 0, - 0 | static_cast(dtk::KeyModifier::Shift) | static_cast(dtk::commandKeyModifier)); - - _timeline = data.file->getTimeline(); - _timeRange = data.file->getTimelineWrapper()->getTimeRange(); - _selectionModel = data.file->getSelectionModel(); - _thumbnailGenerator = data.thumbnailGenerator; - _thumbnailCache = data.thumbnailCache; - - StackItem::create( - context, - data, - _timeline->tracks(), - _timeline, - shared_from_this()); - - _selectionObserver = dtk::ListObserver::create( - _selectionModel->observeSelection(), - [this](const std::vector& selection) - { - _select(shared_from_this(), selection); - }); - - _thumbnailsObserver = dtk::ValueObserver::create( - data.app->getWindowModel()->observeThumbnails(), - [this](bool value) - { - _thumbnails = value; - _setSizeUpdate(); - _setDrawUpdate(); - }); - } - - TimelineItem::~TimelineItem() - {} - - std::shared_ptr TimelineItem::create( - const std::shared_ptr& context, - const ItemData& data, - const std::shared_ptr& parent) - { - auto out = std::make_shared(); - out->_init(context, data, parent); - return out; - } - - const OTIO_NS::RationalTime& TimelineItem::getCurrentTime() const - { - return _currentTime; - } - - void TimelineItem::setCurrentTime(const OTIO_NS::RationalTime& value) - { - if (value == _currentTime) - return; - _currentTime = value; - _setDrawUpdate(); - } - - void TimelineItem::setCurrentTimeCallback(const std::function& value) - { - _currentTimeCallback = value; - } - - void TimelineItem::setInOutRange(const OTIO_NS::TimeRange& value) - { - if (value == _inOutRange) - return; - _inOutRange = value; - _setDrawUpdate(); - } - - void TimelineItem::setGeometry(const dtk::Box2I& value) - { - IItem::setGeometry(value); - const dtk::Box2I& g = getGeometry(); - const int timeHeight = _size.fontMetrics.lineHeight + _size.margin * 2; - for (const auto& child : getChildren()) - { - const dtk::Size2I& sizeHint = child->getSizeHint(); - int h = timeHeight; - if (_thumbnails) - { - h += _size.thumbnailHeight; - } - child->setGeometry(dtk::Box2I( - g.min.x, - g.min.y + h, - sizeHint.w, - sizeHint.h)); - } - if (auto scrollArea = getParentT()) - { - _size.scrollPos = scrollArea->getScrollPos(); - } - } - - void TimelineItem::tickEvent( - bool parentsVisible, - bool parentsEnabled, - const dtk::TickEvent& event) - { - IItem::tickEvent(parentsVisible, parentsEnabled, event); - auto i = _thumbnailRequests.begin(); - while (i != _thumbnailRequests.end()) - { - if (i->future.valid() && - i->future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) - { - const auto image = i->future.get(); - _thumbnailCache->add(getThumbnailCacheKey(nullptr, i->time, _size.thumbnailHeight), image); - _setDrawUpdate(); - i = _thumbnailRequests.erase(i); - } - else - { - ++i; - } - } - } - - void TimelineItem::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IItem::sizeHintEvent(event); - const bool displayScaleChanged = event.displayScale != _size.displayScale; - if (_size.init || displayScaleChanged) - { - _size.init = false; - _size.displayScale = event.displayScale; - _size.margin = event.style->getSizeRole(dtk::SizeRole::MarginInside, event.displayScale); - _size.border = event.style->getSizeRole(dtk::SizeRole::Border, event.displayScale); - _size.handle = event.style->getSizeRole(dtk::SizeRole::Handle, event.displayScale); - _size.thumbnailHeight = 2 * event.style->getSizeRole(dtk::SizeRole::SwatchLarge, event.displayScale); - _size.fontInfo = event.style->getFontRole(dtk::FontRole::Mono, event.displayScale); - _size.fontMetrics = event.fontSystem->getMetrics(_size.fontInfo); - std::vector ids; - for (const auto& request : _thumbnailRequests) - { - ids.push_back(request.id); - } - _thumbnailRequests.clear(); - _thumbnailGenerator->cancelThumbnails(ids); - _thumbnailCache->clear(); - } - int childSizeHint = 0; - for (const auto& child : getChildren()) - { - childSizeHint = std::max(childSizeHint, child->getSizeHint().h); - } - dtk::Size2I sizeHint( - _timeRange.duration().rescaled_to(1.0).value() * _scale, - _size.fontMetrics.lineHeight + _size.margin * 2); - if (_thumbnails) - { - sizeHint.h += _size.thumbnailHeight; - } - sizeHint.h += childSizeHint; - _setSizeHint(sizeHint); - } - - void TimelineItem::drawEvent(const dtk::Box2I& drawRect, const dtk::DrawEvent& event) - { - IItem::drawEvent(drawRect, event); - - const dtk::Box2I& g = getGeometry(); - const int thumbnailWidth = _size.thumbnailHeight * _thumbnailGenerator->getAspect(); - const int y = g.min.y + _size.fontMetrics.lineHeight + _size.margin * 2; - if (_thumbnails) - { - for (int x = g.min.x; x < g.max.x && thumbnailWidth > 0; x += thumbnailWidth) - { - const dtk::Box2I g2(x, y, thumbnailWidth, _size.thumbnailHeight); - if (dtk::intersects(g2, drawRect)) - { - const OTIO_NS::RationalTime t = posToTime(x); - std::shared_ptr image; - if (_thumbnailCache->get(getThumbnailCacheKey(nullptr, t, _size.thumbnailHeight), image)) - { - if (image) - { - event.render->drawImage( - image, - dtk::Box2I(x, y, image->getWidth(), image->getHeight())); - } - } - else - { - const auto j = std::find_if( - _thumbnailRequests.begin(), - _thumbnailRequests.end(), - [this, t](const ThumbnailRequest& request) - { - return t == request.time && _size.thumbnailHeight == request.height; - }); - if (j == _thumbnailRequests.end()) - { - _thumbnailRequests.push_back( - _thumbnailGenerator->getThumbnail(t, _size.thumbnailHeight)); - } - } - } - } - } - - std::vector cancel; - auto i = _thumbnailRequests.begin(); - while (i != _thumbnailRequests.end()) - { - const int x = timeToPos(i->time); - const dtk::Box2I g2(x, y, thumbnailWidth, _size.thumbnailHeight); - if (!dtk::intersects(g2, drawRect)) - { - cancel.push_back(i->id); - i = _thumbnailRequests.erase(i); - } - else - { - ++i; - } - } - _thumbnailGenerator->cancelThumbnails(cancel); - } - - void TimelineItem::drawOverlayEvent(const dtk::Box2I& drawRect, const dtk::DrawEvent& event) - { - IItem::drawOverlayEvent(drawRect, event); - const dtk::Box2I& g = getGeometry(); - - const dtk::Box2I g2( - g.min.x, - g.min.y + _size.scrollPos.y, - g.w(), - _size.fontMetrics.lineHeight + _size.margin * 2); - event.render->drawRect(g2, event.style->getColorRole(dtk::ColorRole::Base)); - - if (_inOutRange != _timeRange) - { - const int x0 = timeToPos(_inOutRange.start_time()); - const int x1 = timeToPos(_inOutRange.end_time_exclusive()); - dtk::Color4F color = event.style->getColorRole(dtk::ColorRole::Yellow); - color.a = .5F; - event.render->drawRect( - dtk::Box2I( - x0, - g.min.y + _size.scrollPos.y, - x1 - x0, - _size.fontMetrics.lineHeight + _size.margin * 2), - color); - } - - _drawTimeTicks(drawRect, event); - _drawTimeLabels(drawRect, event); - - int pos = timeToPos(_currentTime); - event.render->drawRect( - dtk::Box2I(pos, g.min.y + _size.scrollPos.y, _size.border * 2, g.h()), - event.style->getColorRole(dtk::ColorRole::Red)); - - std::string s = toString(_currentTime, _timeUnits); - dtk::Size2I size = event.fontSystem->getSize(s, _size.fontInfo); - dtk::Box2I g3( - pos + _size.border * 2 + _size.margin, - g.min.y + _size.scrollPos.y + _size.margin, - size.w, - _size.fontMetrics.lineHeight); - if (g3.max.x > g.max.x) - { - g3.min.x -= size.w + _size.border * 2 + _size.margin; - g3.max.x -= size.w + _size.border * 2 + _size.margin; - } - event.render->drawText( - event.fontSystem->getGlyphs(s, _size.fontInfo), - _size.fontMetrics, - g3.min, - event.style->getColorRole(dtk::ColorRole::Text)); - } - - void TimelineItem::mouseMoveEvent(dtk::MouseMoveEvent& event) - { - IItem::mouseMoveEvent(event); - if (MouseMode::CurrentTime == _mouse.mode) - { - _currentTime = posToTime(_getMousePos().x); - if (_currentTimeCallback) - { - _currentTimeCallback(_currentTime); - } - _setDrawUpdate(); - } - } - - void TimelineItem::mousePressEvent(dtk::MouseClickEvent& event) - { - IItem::mousePressEvent(event); - if (0 == event.button && - (0 == event.modifiers || - static_cast(dtk::KeyModifier::Shift) == event.modifiers || - static_cast(dtk::commandKeyModifier) == event.modifiers)) - { - std::shared_ptr selection; - _select(shared_from_this(), event.pos, selection); - SelectionItem item; - if (selection) - { - item.object = selection->getObject(); - item.timeRange = selection->getTimeRange(); - } - if (selection && item.object) - { - event.accept = true; - takeKeyFocus(); - _mouse.mode = MouseMode::Select; - auto selectionPrev = _selectionModel->getSelection(); - std::vector selectionNew; - if (static_cast(dtk::KeyModifier::Shift) == event.modifiers) - { - selectionNew = selectionPrev; - selectionNew.insert(selectionNew.end(), item); - } - else if (static_cast(dtk::commandKeyModifier) == event.modifiers) - { - selectionNew = selectionPrev; - auto i = std::find(selectionNew.begin(), selectionNew.end(), item); - if (i != selectionNew.end()) - { - selectionNew.erase(i); - } - } - else if (!selection->isSelected()) - { - selectionNew.insert(selectionNew.end(), item); - } - _selectionModel->setSelection(selectionNew); - } - else if (0 == event.modifiers) - { - event.accept = true; - takeKeyFocus(); - _mouse.mode = MouseMode::CurrentTime; - _currentTime = posToTime(_getMousePos().x); - if (_currentTimeCallback) - { - _currentTimeCallback(_currentTime); - } - _setDrawUpdate(); - } - } - } - - void TimelineItem::mouseReleaseEvent(dtk::MouseClickEvent& event) - { - IItem::mouseReleaseEvent(event); - if (_mouse.mode != MouseMode::None) - { - event.accept = true; - _mouse.mode = MouseMode::None; - } - } - - void TimelineItem::_timeUnitsUpdate() - { - _setSizeUpdate(); - _setDrawUpdate(); - } - - dtk::Size2I TimelineItem::_getLabelMaxSize( - const std::shared_ptr& fontSystem) const - { - const std::string labelMax = toString(_timeRange.end_time_inclusive(), _timeUnits); - const dtk::Size2I labelMaxSize = fontSystem->getSize(labelMax, _size.fontInfo); - return labelMaxSize; - } - - void TimelineItem::_getTimeTicks( - const std::shared_ptr& fontSystem, - double& seconds, - int& tick) - { - const int w = getSizeHint().w; - const float duration = _timeRange.duration().rescaled_to(1.0).value(); - const int secondsTick = 1.0 / duration * w; - const int minutesTick = 60.0 / duration * w; - const int hoursTick = 3600.0 / duration * w; - const dtk::Size2I labelMaxSize = _getLabelMaxSize(fontSystem); - const int distanceMin = _size.border + _size.margin + labelMaxSize.w; - seconds = 0.0; - tick = 0; - if (secondsTick >= distanceMin) - { - seconds = 1.0; - tick = secondsTick; - } - else if (minutesTick >= distanceMin) - { - seconds = 60.0; - tick = minutesTick; - } - else if (hoursTick >= distanceMin) - { - seconds = 3600.0; - tick = hoursTick; - } - } - - void TimelineItem::_drawTimeTicks( - const dtk::Box2I& drawRect, - const dtk::DrawEvent& event) - { - if (_timeRange != OTIO_NS::TimeRange()) - { - const dtk::Box2I& g = getGeometry(); - const int w = getSizeHint().w; - const float duration = _timeRange.duration().rescaled_to(1.0).value(); - const int frameTick = 1.0 / _timeRange.duration().value() * w; - if (duration > 0.0 && frameTick >= _size.handle) - { - dtk::TriMesh2F mesh; - size_t i = 1; - const OTIO_NS::RationalTime t0 = posToTime(g.min.x) - _timeRange.start_time(); - const OTIO_NS::RationalTime t1 = posToTime(g.max.x) - _timeRange.start_time(); - const double inc = 1.0 / _timeRange.duration().rate(); - const double x0 = static_cast(t0.rescaled_to(1.0).value() / inc) * inc; - const double x1 = static_cast(t1.rescaled_to(1.0).value() / inc) * inc; - for (double t = x0; t <= x1; t += inc) - { - const dtk::Box2I box( - g.min.x + - t / duration * w, - _size.scrollPos.y + - g.min.y + - _size.fontMetrics.lineHeight, - _size.border, - _size.margin * 2); - if (intersects(box, drawRect)) - { - mesh.v.push_back(dtk::V2F(box.min.x, box.min.y)); - mesh.v.push_back(dtk::V2F(box.max.x + 1, box.min.y)); - mesh.v.push_back(dtk::V2F(box.max.x + 1, box.max.y + 1)); - mesh.v.push_back(dtk::V2F(box.min.x, box.max.y + 1)); - mesh.triangles.push_back({ i + 0, i + 1, i + 2 }); - mesh.triangles.push_back({ i + 2, i + 3, i + 0 }); - i += 4; - } - } - if (!mesh.v.empty()) - { - event.render->drawMesh( - mesh, - event.style->getColorRole(dtk::ColorRole::Button)); - } - } - - double seconds = 0; - int tick = 0; - _getTimeTicks(event.fontSystem, seconds, tick); - if (duration > 0.0 && seconds > 0.0 && tick > 0) - { - dtk::TriMesh2F mesh; - size_t i = 1; - const OTIO_NS::RationalTime t0 = posToTime(g.min.x) - _timeRange.start_time(); - const OTIO_NS::RationalTime t1 = posToTime(g.max.x) - _timeRange.start_time(); - const double inc = seconds; - const double x0 = static_cast(t0.rescaled_to(1.0).value() / inc) * inc; - const double x1 = static_cast(t1.rescaled_to(1.0).value() / inc) * inc; - for (double t = x0; t <= x1; t += inc) - { - const dtk::Box2I box( - g.min.x + - t / duration * w, - _size.scrollPos.y + - g.min.y, - _size.border, - _size.fontMetrics.lineHeight + - _size.margin * 2); - if (intersects(box, drawRect)) - { - mesh.v.push_back(dtk::V2F(box.min.x, box.min.y)); - mesh.v.push_back(dtk::V2F(box.max.x + 1, box.min.y)); - mesh.v.push_back(dtk::V2F(box.max.x + 1, box.max.y + 1)); - mesh.v.push_back(dtk::V2F(box.min.x, box.max.y + 1)); - mesh.triangles.push_back({ i + 0, i + 1, i + 2 }); - mesh.triangles.push_back({ i + 2, i + 3, i + 0 }); - i += 4; - } - } - if (!mesh.v.empty()) - { - event.render->drawMesh( - mesh, - event.style->getColorRole(dtk::ColorRole::Button)); - } - } - } - } - - void TimelineItem::_drawTimeLabels( - const dtk::Box2I& drawRect, - const dtk::DrawEvent& event) - { - if (_timeRange != OTIO_NS::TimeRange()) - { - const dtk::Box2I& g = getGeometry(); - const int w = getSizeHint().w; - const float duration = _timeRange.duration().rescaled_to(1.0).value(); - double seconds = 0; - int tick = 0; - _getTimeTicks(event.fontSystem, seconds, tick); - if (seconds > 0.0 && tick > 0) - { - const dtk::Size2I labelMaxSize = _getLabelMaxSize(event.fontSystem); - const OTIO_NS::RationalTime t0 = posToTime(g.min.x) - _timeRange.start_time(); - const OTIO_NS::RationalTime t1 = posToTime(g.max.x) - _timeRange.start_time(); - const double inc = seconds; - const double x0 = static_cast(t0.rescaled_to(1.0).value() / inc) * inc; - const double x1 = static_cast(t1.rescaled_to(1.0).value() / inc) * inc; - for (double t = x0; t <= x1; t += inc) - { - const OTIO_NS::RationalTime time = _timeRange.start_time() + - OTIO_NS::RationalTime(t, 1.0).rescaled_to(_timeRange.duration().rate()); - const dtk::Box2I box( - g.min.x + - t / duration * w + - _size.border + - _size.margin, - _size.scrollPos.y + - g.min.y + - _size.margin, - labelMaxSize.w, - _size.fontMetrics.lineHeight); - if (time != _currentTime && intersects(box, drawRect)) - { - const std::string label = toString(time, _timeUnits); - event.render->drawText( - event.fontSystem->getGlyphs(label, _size.fontInfo), - _size.fontMetrics, - box.min, - event.style->getColorRole(dtk::ColorRole::TextDisabled)); - } - } - } - } - } - - void TimelineItem::_select( - const std::shared_ptr& widget, - const dtk::V2I& pos, - std::shared_ptr& out) - { - if (auto iitem = std::dynamic_pointer_cast(widget)) - { - if (dtk::contains(iitem->getSelectionRect(), pos)) - { - out = iitem; - } - } - for (const auto& child : widget->getChildren()) - { - if (dtk::contains(child->getGeometry(), pos)) - { - _select(child, pos, out); - } - } - } - - void TimelineItem::_select( - const std::shared_ptr& widget, - const std::vector& selection) - { - if (auto iitem = std::dynamic_pointer_cast(widget)) - { - auto object = iitem->getObject(); - const auto i = std::find_if( - selection.begin(), - selection.end(), - [object](const SelectionItem& item) - { - return object.value == item.object.value; - }); - iitem->setSelected(i != selection.end()); - } - for (const auto& child : widget->getChildren()) - { - _select(child, selection); - } - } -} diff --git a/TimelineItem.h b/TimelineItem.h deleted file mode 100644 index 763d9fc..0000000 --- a/TimelineItem.h +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include -#include - -#include - -namespace toucan -{ - class SelectionModel; - - //! Timeline item. - class TimelineItem : public IItem - { - protected: - void _init( - const std::shared_ptr&, - const ItemData&, - const std::shared_ptr& parent); - - public: - virtual ~TimelineItem(); - - //! Create a new item. - static std::shared_ptr create( - const std::shared_ptr&, - const ItemData&, - const std::shared_ptr& parent = nullptr); - - //! Get the current time. - const OTIO_NS::RationalTime& getCurrentTime() const; - - //! Set the current time. - void setCurrentTime(const OTIO_NS::RationalTime&); - - //! Set the current time callback. - void setCurrentTimeCallback(const std::function&); - - //! Set the in/out range. - void setInOutRange(const OTIO_NS::TimeRange&); - - void setGeometry(const dtk::Box2I&) override; - void tickEvent( - bool parentsVisible, - bool parentsEnabled, - const dtk::TickEvent&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - void drawEvent(const dtk::Box2I&, const dtk::DrawEvent&) override; - void drawOverlayEvent(const dtk::Box2I&, const dtk::DrawEvent&) override; - void mouseMoveEvent(dtk::MouseMoveEvent&) override; - void mousePressEvent(dtk::MouseClickEvent&) override; - void mouseReleaseEvent(dtk::MouseClickEvent&) override; - - protected: - void _timeUnitsUpdate() override; - - private: - dtk::Size2I _getLabelMaxSize( - const std::shared_ptr&) const; - void _getTimeTicks( - const std::shared_ptr&, - double& seconds, - int& tick); - void _drawTimeTicks( - const dtk::Box2I&, - const dtk::DrawEvent&); - void _drawTimeLabels( - const dtk::Box2I&, - const dtk::DrawEvent&); - - void _select( - const std::shared_ptr&, - const dtk::V2I&, - std::shared_ptr&); - void _select( - const std::shared_ptr&, - const std::vector&); - - OTIO_NS::SerializableObject::Retainer _timeline; - OTIO_NS::TimeRange _timeRange; - OTIO_NS::RationalTime _currentTime = OTIO_NS::RationalTime(-1.0, -1.0); - std::function _currentTimeCallback; - OTIO_NS::TimeRange _inOutRange; - std::shared_ptr _selectionModel; - bool _thumbnails = true; - std::shared_ptr _thumbnailGenerator; - std::list _thumbnailRequests; - std::shared_ptr > > _thumbnailCache; - - struct SizeData - { - bool init = true; - float displayScale = 0.F; - int margin = 0; - int border = 0; - int handle = 0; - int thumbnailHeight = 0; - dtk::FontInfo fontInfo; - dtk::FontMetrics fontMetrics; - dtk::V2I scrollPos; - }; - SizeData _size; - - enum MouseMode - { - None, - CurrentTime, - Select - }; - struct MouseData - { - MouseMode mode = MouseMode::None; - }; - MouseData _mouse; - - std::shared_ptr > _selectionObserver; - std::shared_ptr > _thumbnailsObserver; - }; -} diff --git a/TimelineWidget.cpp b/TimelineWidget.cpp deleted file mode 100644 index e9c805c..0000000 --- a/TimelineWidget.cpp +++ /dev/null @@ -1,376 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "TimelineWidget.h" - -#include "App.h" -#include "FilesModel.h" -#include "TimelineItem.h" -#include "WindowModel.h" - -namespace toucan -{ - namespace - { - const float marginPercentage = .1F; - } - - void TimelineWidget::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& parent) - { - IWidget::_init(context, "toucan::TimelineWidget", parent); - - _setMouseHoverEnabled(true); - _setMousePressEnabled( - true, - 0, - static_cast(dtk::KeyModifier::Alt)); - - _frameView = dtk::ObservableValue::create(true); - - _scrollWidget = dtk::ScrollWidget::create(context, dtk::ScrollType::Both, shared_from_this()); - _scrollWidget->setScrollEventsEnabled(false); - _scrollWidget->setBorder(false); - - auto appWeak = std::weak_ptr(app); - _fileObserver = dtk::ValueObserver >::create( - app->getFilesModel()->observeCurrent(), - [this, appWeak](const std::shared_ptr& file) - { - if (_file) - { - TimelineViewState viewState; - viewState.pos = _scrollWidget->getScrollPos(); - viewState.scale = _scale; - viewState.frameView = _frameView->get(); - _file->getPlaybackModel()->setViewState(viewState); - } - _file = file; - if (file) - { - _timeRange = file->getPlaybackModel()->getTimeRange(); - _viewState = file->getPlaybackModel()->getViewState(); - if (_viewState.has_value()) - { - _scale = _viewState->scale; - } - else - { - _sizeInit = true; - } - - ItemData data; - data.app = appWeak.lock(); - data.file = file; - data.thumbnailGenerator = file->getThumbnailGenerator(); - data.thumbnailCache = std::make_shared > >(); - data.thumbnailCache->setMax(1000); - _timelineItem = TimelineItem::create(getContext(), data); - _timelineItem->setScale(_scale); - _timelineItem->setCurrentTimeCallback( - [this](const OTIO_NS::RationalTime& value) - { - if (_file) - { - _file->getPlaybackModel()->setCurrentTime(value, CurrentTime::Free); - } - }); - _scrollWidget->setWidget(_timelineItem); - - _currentTimeObserver = dtk::ValueObserver::create( - file->getPlaybackModel()->observeCurrentTime(), - [this](const OTIO_NS::RationalTime& value) - { - _currentTime = value; - if (_timelineItem) - { - _timelineItem->setCurrentTime(value); - } - _scrollUpdate(); - }); - - _inOutRangeObserver = dtk::ValueObserver::create( - file->getPlaybackModel()->observeInOutRange(), - [this](const OTIO_NS::TimeRange& value) - { - _inOutRange = value; - if (_timelineItem) - { - _timelineItem->setInOutRange(_inOutRange); - } - }); - } - else - { - _timeRange = OTIO_NS::TimeRange(); - _timelineItem.reset(); - _scrollWidget->setWidget(nullptr); - _currentTimeObserver.reset(); - } - - _setSizeUpdate(); - _setDrawUpdate(); - }); - } - - TimelineWidget::~TimelineWidget() - {} - - std::shared_ptr TimelineWidget::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new TimelineWidget); - out->_init(context, app, parent); - return out; - } - - void TimelineWidget::setViewZoom(double value) - { - const dtk::Box2I& g = getGeometry(); - setViewZoom(value, dtk::V2I(g.w() / 2, g.h() / 2)); - } - - void TimelineWidget::setViewZoom(double zoom, const dtk::V2I& focus) - { - _setViewZoom( - zoom, - _scale, - focus, - _scrollWidget->getScrollPos()); - } - - bool TimelineWidget::hasFrameView() const - { - return _frameView->get(); - } - - std::shared_ptr > TimelineWidget::observeFrameView() const - { - return _frameView; - } - - void TimelineWidget::setFrameView(bool value) - { - if (_frameView->setIfChanged(value)) - { - if (value) - { - frameView(); - } - } - } - - void TimelineWidget::frameView() - { - dtk::V2I pos = _scrollWidget->getScrollPos(); - pos.x = 0; - _scrollWidget->setScrollPos(pos); - _scale = _getTimelineScale(); - if (_timelineItem) - { - _timelineItem->setScale(_scale); - } - _setSizeUpdate(); - _setDrawUpdate(); - } - - void TimelineWidget::setGeometry(const dtk::Box2I& value) - { - const dtk::Box2I viewportPrev = _scrollWidget->getViewport(); - IWidget::setGeometry(value); - _scrollWidget->setGeometry(value); - const bool changed = _scrollWidget->getViewport() != viewportPrev; - if (_sizeInit) - { - _sizeInit = false; - frameView(); - } - else if (_viewState.has_value()) - { - _scrollWidget->setScrollPos(_viewState->pos); - setFrameView(_viewState->frameView); - _viewState.reset(); - } - else if (changed && _frameView->get()) - { - frameView(); - } - else if (_timelineItem && - _timelineItem->getSizeHint().w < - _scrollWidget->getViewport().w()) - { - setFrameView(true); - frameView(); - } - } - - void TimelineWidget::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IWidget::sizeHintEvent(event); - _setSizeHint(_scrollWidget->getSizeHint()); - } - - void TimelineWidget::mouseMoveEvent(dtk::MouseMoveEvent& event) - { - IWidget::mouseMoveEvent(event); - switch (_mouse.mode) - { - case MouseMode::Scroll: - { - const dtk::V2I d = event.pos - _getMousePressPos(); - _scrollWidget->setScrollPos(_mouse.scrollPos - d); - setFrameView(false); - break; - } - default: break; - } - } - - void TimelineWidget::mousePressEvent(dtk::MouseClickEvent& event) - { - IWidget::mousePressEvent(event); - if (0 == event.button && - static_cast(dtk::KeyModifier::Alt) == event.modifiers) - { - event.accept = true; - takeKeyFocus(); - _mouse.mode = MouseMode::Scroll; - _mouse.scrollPos = _scrollWidget->getScrollPos(); - } - else - { - _mouse.mode = MouseMode::None; - } - } - - void TimelineWidget::mouseReleaseEvent(dtk::MouseClickEvent& event) - { - IWidget::mouseReleaseEvent(event); - } - - void TimelineWidget::scrollEvent(dtk::ScrollEvent& event) - { - IWidget::scrollEvent(event); - event.accept = true; - if (event.value.y > 0) - { - const double zoom = _scale * 1.1; - setViewZoom(zoom, event.pos); - } - else - { - const double zoom = _scale / 1.1; - setViewZoom(zoom, event.pos); - } - } - - void TimelineWidget::keyPressEvent(dtk::KeyEvent& event) - { - if (0 == event.modifiers) - { - switch (event.key) - { - case dtk::Key::Equal: - event.accept = true; - setViewZoom(_scale * 2.0, event.pos); - break; - case dtk::Key::Minus: - event.accept = true; - setViewZoom(_scale / 2.0, event.pos); - break; - case dtk::Key::Backspace: - event.accept = true; - setFrameView(true); - break; - default: break; - } - } - } - - void TimelineWidget::keyReleaseEvent(dtk::KeyEvent& event) - { - event.accept = true; - } - - void TimelineWidget::_setViewZoom( - double zoomNew, - double zoomPrev, - const dtk::V2I& focus, - const dtk::V2I& scrollPos) - { - const int w = getGeometry().w(); - const double zoomMin = _getTimelineScale(); - const double zoomMax = _getTimelineScaleMax(); - const double zoomClamped = dtk::clamp(zoomNew, zoomMin, zoomMax); - if (zoomClamped != _scale) - { - _scale = zoomClamped; - if (_timelineItem) - { - _timelineItem->setScale(_scale); - } - const double s = zoomClamped / zoomPrev; - const dtk::V2I scrollPosNew( - (scrollPos.x + focus.x) * s - focus.x, - scrollPos.y); - _scrollWidget->setScrollPos(scrollPosNew, false); - - setFrameView(zoomNew <= zoomMin); - } - } - - double TimelineWidget::_getTimelineScale() const - { - double out = 1.0; - const double duration = _timeRange.duration().rescaled_to(1.0).value(); - if (duration > 0.0) - { - const dtk::Box2I scrollViewport = _scrollWidget->getViewport(); - out = scrollViewport.w() / duration; - } - return out; - } - - double TimelineWidget::_getTimelineScaleMax() const - { - double out = 1.0; - const dtk::Box2I scrollViewport = _scrollWidget->getViewport(); - const double duration = _timeRange.duration().rescaled_to(1.0).value(); - if (duration < 1.0) - { - if (duration > 0.0) - { - out = scrollViewport.w() / duration; - } - } - else - { - out = scrollViewport.w(); - } - return out; - } - - void TimelineWidget::_scrollUpdate() - { - if (_timelineItem && - MouseMode::None == _mouse.mode) - { - const int pos = _timelineItem->timeToPos(_currentTime); - const dtk::Box2I vp = _scrollWidget->getViewport(); - const int margin = vp.w() * marginPercentage; - if (pos < (vp.min.x + margin) || pos >(vp.max.x - margin)) - { - const int offset = pos < (vp.min.x + margin) ? (vp.min.x + margin) : (vp.max.x - margin); - const OTIO_NS::RationalTime t = _currentTime - _timeRange.start_time(); - dtk::V2I scrollPos = _scrollWidget->getScrollPos(); - const dtk::Box2I& g = getGeometry(); - scrollPos.x = g.min.x - offset + t.rescaled_to(1.0).value() * _scale; - _scrollWidget->setScrollPos(scrollPos); - } - } - } -} diff --git a/VideoClipItem.cpp b/VideoClipItem.cpp deleted file mode 100644 index d2f6194..0000000 --- a/VideoClipItem.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "VideoClipItem.h" - -#include "App.h" -#include "File.h" -#include "WindowModel.h" - -#include - -#include - -#include -#include - -namespace toucan -{ - void VideoClipItem::_init( - const std::shared_ptr& context, - const ItemData& data, - const OTIO_NS::SerializableObject::Retainer& clip, - const OTIO_NS::SerializableObject::Retainer& timeline, - const dtk::Color4F& color, - const std::shared_ptr& parent) - { - OTIO_NS::TimeRange timeRange = clip->transformed_time_range( - clip->trimmed_range(), - timeline->tracks()); - if (timeline->global_start_time().has_value()) - { - timeRange = OTIO_NS::TimeRange( - timeline->global_start_time().value() + timeRange.start_time(), - timeRange.duration()); - } - timeRange = OTIO_NS::TimeRange( - timeRange.start_time().round(), - timeRange.duration().round()); - IItem::_init( - context, - data, - OTIO_NS::dynamic_retainer_cast(clip), - timeRange, - "toucan::VideoClipItem", - parent); - - _clip = clip; - _text = !clip->name().empty() ? clip->name() : "Video Clip"; - _color = color; - - setTooltip(clip->schema_name() + ": " + _text); - - _layout = dtk::VerticalLayout::create(context, shared_from_this()); - _layout->setSpacingRole(dtk::SizeRole::SpacingTool); - - _label = ItemLabel::create(context, _layout); - _label->setName(_text); - - _thumbnailsWidget = ThumbnailsWidget::create( - context, - _clip->media_reference(), - data.thumbnailGenerator, - data.thumbnailCache, - timeRange, - _layout); - - const auto& markers = clip->markers(); - if (!markers.empty()) - { - _markerLayout = TimeLayout::create(context, timeRange, _layout); - for (const auto& marker : markers) - { - const OTIO_NS::TimeRange trimmedRange = clip->trimmed_range(); - OTIO_NS::TimeRange markerRange( - marker->marked_range().start_time() + trimmedRange.start_time(), - marker->marked_range().duration()); - markerRange = clip->transformed_time_range(markerRange, timeline->tracks()); - if (timeline->global_start_time().has_value()) - { - markerRange = OTIO_NS::TimeRange( - timeline->global_start_time().value() + markerRange.start_time(), - markerRange.duration()); - } - auto markerItem = MarkerItem::create( - context, - data, - marker, - markerRange, - _markerLayout); - _markerItems.push_back(markerItem); - } - } - - _textUpdate(); - - _thumbnailsObserver = dtk::ValueObserver::create( - data.app->getWindowModel()->observeThumbnails(), - [this](bool value) - { - _thumbnailsWidget->setVisible(value); - }); - } - - VideoClipItem::~VideoClipItem() - {} - - std::shared_ptr VideoClipItem::create( - const std::shared_ptr& context, - const ItemData& data, - const OTIO_NS::SerializableObject::Retainer& clip, - const OTIO_NS::SerializableObject::Retainer& timeline, - const dtk::Color4F& color, - const std::shared_ptr& parent) - { - auto out = std::make_shared(); - out->_init(context, data, clip, timeline, color, parent); - return out; - } - - void VideoClipItem::setScale(double value) - { - IItem::setScale(value); - if (_markerLayout) - { - _markerLayout->setScale(value); - } - } - - void VideoClipItem::setGeometry(const dtk::Box2I& value) - { - IItem::setGeometry(value); - _layout->setGeometry(value); - } - - dtk::Box2I VideoClipItem::getChildrenClipRect() const - { - return dtk::margin(getGeometry(), -_size.border, 0, -_size.border, 0); - } - - void VideoClipItem::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IItem::sizeHintEvent(event); - const bool displayScaleChanged = event.displayScale != _size.displayScale; - if (_size.init || displayScaleChanged) - { - _size.init = false; - _size.displayScale = event.displayScale; - _size.border = event.style->getSizeRole(dtk::SizeRole::Border, event.displayScale); - } - dtk::Size2I sizeHint = _layout->getSizeHint(); - _setSizeHint(sizeHint); - } - - void VideoClipItem::drawEvent( - const dtk::Box2I& drawRect, - const dtk::DrawEvent& event) - { - IItem::drawEvent(drawRect, event); - dtk::Box2I g = _label->getGeometry(); - if (_thumbnailsWidget->isVisible(true)) - { - const dtk::Box2I& g2 = _thumbnailsWidget->getGeometry(); - g = dtk::Box2I(g.min, g2.max); - } - event.render->drawRect( - dtk::margin(g, -_size.border, 0, -_size.border, 0), - _selected ? event.style->getColorRole(dtk::ColorRole::Yellow) : _color); - } - - void VideoClipItem::_timeUnitsUpdate() - { - _textUpdate(); - } - - void VideoClipItem::_buildMenu(const std::shared_ptr& menu) - { - if (auto externalReference = dynamic_cast(_clip->media_reference())) - { - auto action = std::make_shared( - "Open Media", - [this, externalReference] - { - auto file = _file.lock(); - const std::filesystem::path path = file->getTimelineWrapper()->getMediaPath(externalReference->target_url()); - auto app = _app.lock(); - app->open(path); - }); - menu->addItem(action); - menu->addDivider(); - } - else if (auto sequenceRef = dynamic_cast(_clip->media_reference())) - { - auto action = std::make_shared( - "Open Image Sequence", - [this, sequenceRef] - { - auto file = _file.lock(); - const std::string path = getSequenceFrame( - file->getTimelineWrapper()->getMediaPath(sequenceRef->target_url_base()), - sequenceRef->name_prefix(), - sequenceRef->start_frame(), - sequenceRef->frame_zero_padding(), - sequenceRef->name_suffix()); - auto app = _app.lock(); - app->open(path); - }); - menu->addItem(action); - menu->addDivider(); - } - IItem::_buildMenu(menu); - } - - void VideoClipItem::_textUpdate() - { - if (_label) - { - std::string text = toString(_timeRange.duration(), _timeUnits); - _label->setDuration(text); - } - } -} diff --git a/VideoClipItem.h b/VideoClipItem.h deleted file mode 100644 index 4e7ce3c..0000000 --- a/VideoClipItem.h +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include -#include -#include -#include - -#include - -#include - -namespace toucan -{ - //! Timeline video clip item. - class VideoClipItem : public IItem - { - protected: - void _init( - const std::shared_ptr&, - const ItemData&, - const OTIO_NS::SerializableObject::Retainer&, - const OTIO_NS::SerializableObject::Retainer&, - const dtk::Color4F&, - const std::shared_ptr& parent); - - public: - virtual ~VideoClipItem(); - - //! Create a new item. - static std::shared_ptr create( - const std::shared_ptr&, - const ItemData&, - const OTIO_NS::SerializableObject::Retainer&, - const OTIO_NS::SerializableObject::Retainer&, - const dtk::Color4F&, - const std::shared_ptr& parent = nullptr); - - void setScale(double) override; - - void setGeometry(const dtk::Box2I&) override; - dtk::Box2I getChildrenClipRect() const override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - void drawEvent(const dtk::Box2I&, const dtk::DrawEvent&) override; - - protected: - void _timeUnitsUpdate() override; - void _buildMenu(const std::shared_ptr&) override; - - private: - void _textUpdate(); - - OTIO_NS::SerializableObject::Retainer _clip; - std::string _text; - dtk::Color4F _color; - std::string _url; - - std::shared_ptr _layout; - std::shared_ptr _label; - std::shared_ptr _thumbnailsWidget; - std::shared_ptr _markerLayout; - std::vector > _markerItems; - - std::shared_ptr > _thumbnailsObserver; - - struct SizeData - { - bool init = true; - float displayScale = 0.F; - int border = 0; - }; - SizeData _size; - - struct GeomData - { - dtk::Box2I g2; - dtk::Box2I g3; - }; - GeomData _geom; - }; -} diff --git a/WindowMenu.cpp b/WindowMenu.cpp deleted file mode 100644 index ad8948a..0000000 --- a/WindowMenu.cpp +++ /dev/null @@ -1,273 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "WindowMenu.h" - -#include "App.h" -#include "FilesModel.h" -#include "MainWindow.h" -#include "SelectionModel.h" -#include "ViewModel.h" - -#include - -#include -#include -#include -#include - -namespace toucan -{ - void WindowMenu::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& window, - const std::shared_ptr& parent) - { - dtk::Menu::_init(context, parent); - - std::weak_ptr windowWeak(window); - _actions["Window/FullScreen"] = std::make_shared( - "Full Screen", - "WindowFullScreen", - dtk::Key::U, - static_cast(dtk::commandKeyModifier), - [windowWeak](bool value) - { - if (auto window = windowWeak.lock()) - { - window->setFullScreen(value); - } - }); - _actions["Window/FullScreen"]->toolTip = "Toggle full screen mode"; - addItem(_actions["Window/FullScreen"]); - - addDivider(); - - struct Component - { - WindowComponent component; - std::string action; - std::string text; - std::string icon; - std::string tooltip; - }; - const std::vector components = - { - { WindowComponent::ToolBar, "ToolBar", "Tool Bar", "", "" }, - { WindowComponent::Tools, "Tools", "Tools", "PanelRight", "Toggle the tools" }, - { WindowComponent::Playback, "Playback", "Playback", "PanelBottom", "Toggle the playback controls" }, - { WindowComponent::InfoBar, "InfoBar", "InfoBar", "", "Toggle the information bar" } - }; - std::weak_ptr appWeak(app); - for (const auto& component : components) - { - const std::string actionName = dtk::Format("Window/{0}").arg(component.action); - _actions[actionName] = std::make_shared( - component.text, - component.icon, - [appWeak, component](bool value) - { - if (auto app = appWeak.lock()) - { - app->getWindowModel()->setComponent(component.component, value); - } - }); - _actions[actionName]->toolTip = component.tooltip; - addItem(_actions[actionName]); - } - - addDivider(); - - _menus["Window/Resize"] = addSubMenu("Resize"); - - _actions["Window/Resize/1280x720"] = std::make_shared( - "1280x720", - [windowWeak] - { - if (auto window = windowWeak.lock()) - { - window->setSize(dtk::Size2I(1280, 720)); - } - }); - _menus["Window/Resize"]->addItem(_actions["Window/Resize/1280x720"]); - - _actions["Window/Resize/1920x1080"] = std::make_shared( - "1920x1080", - [windowWeak] - { - if (auto window = windowWeak.lock()) - { - window->setSize(dtk::Size2I(1920, 1080)); - } - }); - _menus["Window/Resize"]->addItem(_actions["Window/Resize/1920x1080"]); - - _actions["Window/Resize/3840x2160"] = std::make_shared( - "3840x2160", - [windowWeak] - { - if (auto window = windowWeak.lock()) - { - window->setSize(dtk::Size2I(3840, 2160)); - } - }); - _menus["Window/Resize"]->addItem(_actions["Window/Resize/3840x2160"]); - - _menus["Window/DisplayScale"] = addSubMenu("Display Scale"); - - _actions["Window/DisplayScale/Auto"] = std::make_shared( - "Automatic", - [windowWeak](bool value) - { - if (auto window = windowWeak.lock()) - { - window->setDisplayScale(0.F); - } - }); - _menus["Window/DisplayScale"]->addItem(_actions["Window/DisplayScale/Auto"]); - - _actions["Window/DisplayScale/1.0"] = std::make_shared( - "1.0", - [windowWeak](bool value) - { - if (auto window = windowWeak.lock()) - { - window->setDisplayScale(1.F); - } - }); - _menus["Window/DisplayScale"]->addItem(_actions["Window/DisplayScale/1.0"]); - - _actions["Window/DisplayScale/1.5"] = std::make_shared( - "1.5", - [windowWeak](bool value) - { - if (auto window = windowWeak.lock()) - { - window->setDisplayScale(1.5F); - } - }); - _menus["Window/DisplayScale"]->addItem(_actions["Window/DisplayScale/1.5"]); - - _actions["Window/DisplayScale/2.0"] = std::make_shared( - "2.0", - [windowWeak](bool value) - { - if (auto window = windowWeak.lock()) - { - window->setDisplayScale(2.F); - } - }); - _menus["Window/DisplayScale"]->addItem(_actions["Window/DisplayScale/2.0"]); - - _actions["Window/DisplayScale/2.5"] = std::make_shared( - "2.5", - [windowWeak](bool value) - { - if (auto window = windowWeak.lock()) - { - window->setDisplayScale(2.5F); - } - }); - _menus["Window/DisplayScale"]->addItem(_actions["Window/DisplayScale/2.5"]); - - _actions["Window/DisplayScale/3.0"] = std::make_shared( - "3.0", - [windowWeak](bool value) - { - if (auto window = windowWeak.lock()) - { - window->setDisplayScale(3.F); - } - }); - _menus["Window/DisplayScale"]->addItem(_actions["Window/DisplayScale/3.0"]); - - _actions["Window/Thumbnails"] = std::make_shared( - "Thumbnails", - [appWeak](bool value) - { - if (auto app = appWeak.lock()) - { - app->getWindowModel()->setThumbnails(value); - } - }); - addItem(_actions["Window/Thumbnails"]); - - _actions["Window/Tooltips"] = std::make_shared( - "Tooltips", - [appWeak](bool value) - { - if (auto app = appWeak.lock()) - { - app->getWindowModel()->setTooltips(value); - } - }); - addItem(_actions["Window/Tooltips"]); - - _fullScreenObserver = dtk::ValueObserver::create( - window->observeFullScreen(), - [this](bool value) - { - setItemChecked(_actions["Window/FullScreen"], value); - }); - - _componentsObserver = dtk::MapObserver::create( - app->getWindowModel()->observeComponents(), - [this](const std::map& value) - { - auto i = value.find(WindowComponent::ToolBar); - setItemChecked(_actions["Window/ToolBar"], i->second); - i = value.find(WindowComponent::Tools); - setItemChecked(_actions["Window/Tools"], i->second); - i = value.find(WindowComponent::Playback); - setItemChecked(_actions["Window/Playback"], i->second); - i = value.find(WindowComponent::InfoBar); - setItemChecked(_actions["Window/InfoBar"], i->second); - }); - - _displayScaleObserver = dtk::ValueObserver::create( - window->observeDisplayScale(), - [this](float value) - { - _menus["Window/DisplayScale"]->setItemChecked(_actions["Window/DisplayScale/Auto"], 0.F == value); - _menus["Window/DisplayScale"]->setItemChecked(_actions["Window/DisplayScale/1.0"], 1.F == value); - _menus["Window/DisplayScale"]->setItemChecked(_actions["Window/DisplayScale/1.5"], 1.5F == value); - _menus["Window/DisplayScale"]->setItemChecked(_actions["Window/DisplayScale/2.0"], 2.F == value); - _menus["Window/DisplayScale"]->setItemChecked(_actions["Window/DisplayScale/2.5"], 2.5F == value); - _menus["Window/DisplayScale"]->setItemChecked(_actions["Window/DisplayScale/3.0"], 3.F == value); - }); - - _thumbnailsObserver = dtk::ValueObserver::create( - app->getWindowModel()->observeThumbnails(), - [this](bool value) - { - setItemChecked(_actions["Window/Thumbnails"], value); - }); - - _tooltipsObserver = dtk::ValueObserver::create( - app->getWindowModel()->observeTooltips(), - [this](bool value) - { - setItemChecked(_actions["Window/Tooltips"], value); - }); - } - - WindowMenu::~WindowMenu() - {} - - std::shared_ptr WindowMenu::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& window, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new WindowMenu); - out->_init(context, app, window, parent); - return out; - } - - const std::map >& WindowMenu::getActions() const - { - return _actions; - } -} diff --git a/WindowMenu.h b/WindowMenu.h deleted file mode 100644 index 86804ef..0000000 --- a/WindowMenu.h +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include -#include -#include - -namespace toucan -{ - class App; - class MainWindow; - - //! Window menu. - class WindowMenu : public dtk::Menu - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~WindowMenu(); - - //! Create a new menu. - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - //! Get the actions. - const std::map >& getActions() const; - - private: - std::map > _menus; - std::map > _actions; - - std::shared_ptr > _fullScreenObserver; - std::shared_ptr > _componentsObserver; - std::shared_ptr > _displayScaleObserver; - std::shared_ptr > _thumbnailsObserver; - std::shared_ptr > _tooltipsObserver; - }; -} - diff --git a/WindowModel.cpp b/WindowModel.cpp deleted file mode 100644 index f25fbca..0000000 --- a/WindowModel.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "WindowModel.h" - -#include -#include -#include - -#include - -#include -#include - -namespace toucan -{ - DTK_ENUM_IMPL( - WindowComponent, - "ToolBar", - "Tools", - "Playback", - "InfoBar"); - - WindowModel::WindowModel(const std::shared_ptr& context) - { - _settings = context->getSystem(); - std::map components = - { - { WindowComponent::ToolBar, true }, - { WindowComponent::Tools, true }, - { WindowComponent::Playback, true }, - { WindowComponent::InfoBar, true } - }; - bool thumbnails = true; - bool tooltips = true; - try - { - const auto json = std::any_cast(_settings->get("WindowModel")); - for (auto& i : components) - { - std::stringstream ss; - ss << i.first; - auto j = json.find(ss.str()); - if (j != json.end() && j->is_boolean()) - { - i.second = j->get(); - } - } - auto i = json.find("Thumbnails"); - if (i != json.end() && i->is_boolean()) - { - thumbnails = i->get(); - } - i = json.find("Tooltips"); - if (i != json.end() && i->is_boolean()) - { - tooltips = i->get(); - } - } - catch (const std::exception&) - {} - - _components = dtk::ObservableMap::create(components); - _thumbnails = dtk::ObservableValue::create(thumbnails); - _tooltips = dtk::ObservableValue::create(tooltips); - } - - WindowModel::~WindowModel() - { - nlohmann::json json; - for (const auto i : _components->get()) - { - std::stringstream ss; - ss << i.first; - json[ss.str()] = i.second; - } - json["Thumbnails"] = _thumbnails->get(); - json["Tooltips"] = _tooltips->get(); - _settings->set("WindowModel", json); - } - - const std::map WindowModel::getComponents() const - { - return _components->get(); - } - - std::shared_ptr > WindowModel::observeComponents() const - { - return _components; - } - - void WindowModel::setComponents(const std::map& value) - { - _components->setIfChanged(value); - } - - bool WindowModel::getComponent(WindowComponent value) const - { - return _components->getItem(value); - } - - void WindowModel::setComponent(WindowComponent component, bool value) - { - _components->setItemOnlyIfChanged(component, value); - } - - bool WindowModel::getThumbnails() const - { - return _thumbnails->get(); - } - - std::shared_ptr > WindowModel::observeThumbnails() const - { - return _thumbnails; - } - - void WindowModel::setThumbnails(bool value) - { - _thumbnails->setIfChanged(value); - } - - bool WindowModel::getTooltips() const - { - return _tooltips->get(); - } - - std::shared_ptr > WindowModel::observeTooltips() const - { - return _tooltips; - } - - void WindowModel::setTooltips(bool value) - { - _tooltips->setIfChanged(value); - } -} diff --git a/WindowModel.h b/WindowModel.h deleted file mode 100644 index d41c8d1..0000000 --- a/WindowModel.h +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include -#include -#include -#include - -namespace toucan -{ - //! Window components. - enum class WindowComponent - { - ToolBar, - Tools, - Playback, - InfoBar, - - Count, - First = ToolBar - }; - DTK_ENUM(WindowComponent); - - //! Window model. - class WindowModel : public std::enable_shared_from_this - { - public: - WindowModel(const std::shared_ptr&); - - virtual ~WindowModel(); - - //! Get the window components. - const std::map getComponents() const; - - //! Observe the window components. - std::shared_ptr > observeComponents() const; - - //! Set the window components. - void setComponents(const std::map&); - - //! Get a window component. - bool getComponent(WindowComponent) const; - - //! Set a window component. - void setComponent(WindowComponent, bool); - - //! Get whether thumbnails are enabled. - bool getThumbnails() const; - - //! Observe whether thumbnails are enabled. - std::shared_ptr > observeThumbnails() const; - - //! Set whether thumbnails are enabled. - void setThumbnails(bool); - - //! Get whether tooltips are enabled. - bool getTooltips() const; - - //! Observe whether tooltips are enabled. - std::shared_ptr > observeTooltips() const; - - //! Set whether tooltips are enabled. - void setTooltips(bool); - - private: - std::shared_ptr _settings; - std::shared_ptr > _components; - std::shared_ptr > _thumbnails; - std::shared_ptr > _tooltips; - }; -}