diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eda67d..88dc020 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,6 @@ project( LANGUAGES CXX C) set(toucan_VIEW ON CACHE BOOL "Build viewer application") -set(toucan_EDIT OFF CACHE BOOL "Build editor application") list(PREPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) @@ -31,9 +30,6 @@ if(APPLE) set(CMAKE_IGNORE_PREFIX_PATH /opt/homebrew) endif() set_property(GLOBAL PROPERTY USE_FOLDERS ON) -if(toucan_EDIT) - add_definitions(-Dtoucan_EDIT) -endif() set(TOUCAN_PLUGINS toucanColorSpace @@ -57,7 +53,7 @@ find_package(OpenColorIO) find_package(OpenImageIO) find_package(OTIO) find_package(OpenFX) -if(toucan_VIEW OR toucan_EDIT) +if(toucan_VIEW) find_package(lunasvg) find_package(dtk) endif() diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt index 0340266..588f766 100644 --- a/bin/CMakeLists.txt +++ b/bin/CMakeLists.txt @@ -2,6 +2,3 @@ add_subdirectory(toucan-render) if(toucan_VIEW) add_subdirectory(toucan-view) endif() -if(toucan_EDIT) - add_subdirectory(toucan-edit) -endif() diff --git a/bin/toucan-edit/CMakeLists.txt b/bin/toucan-edit/CMakeLists.txt deleted file mode 100644 index a54d44c..0000000 --- a/bin/toucan-edit/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_executable(toucan-edit main.cpp) -target_link_libraries(toucan-edit toucanEdit) -set_target_properties(toucan-edit PROPERTIES FOLDER bin) -add_dependencies(toucan-edit ${TOUCAN_PLUGINS}) - -install( - TARGETS toucan-edit - RUNTIME DESTINATION bin) diff --git a/bin/toucan-edit/main.cpp b/bin/toucan-edit/main.cpp deleted file mode 100644 index 63b5ff3..0000000 --- a/bin/toucan-edit/main.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include - -#include - -DTK_MAIN() -{ - try - { - auto context = dtk::Context::create(); - auto args = dtk::convert(argc, argv); - auto app = toucan::App::create(context, args); - if (app->getExit() != 0) - return app->getExit(); - app->run(); - } - catch (const std::exception& e) - { - std::cout << "ERROR: " << e.what() << std::endl; - return 1; - } - return 0; -} diff --git a/lib/toucanEdit/App.cpp b/lib/toucanEdit/App.cpp deleted file mode 100644 index a8cbc80..0000000 --- a/lib/toucanEdit/App.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "App.h" - -#include "DocumentsModel.h" -#include "TimeUnitsModel.h" -#include "Timeline.h" -#include "Window.h" - -#include -#include -#include - -namespace toucan -{ - void App::_init( - const std::shared_ptr& context, - std::vector& argv) - { - dtk::App::_init( - context, - argv, - "toucan-edit", - "Toucan editor", - { - dtk::CmdLineValueArg::create( - _path, - "input", - "Input timeline.", - true) - }); - - context->getSystem()->setNativeFileDialog(false); - - _messageLog = std::make_shared(); - - _timeUnitsModel = std::make_shared(); - - std::vector searchPath; - const std::filesystem::path parentPath = std::filesystem::path(argv[0]).parent_path(); - searchPath.push_back(parentPath); -#if defined(_WINDOWS) - searchPath.push_back(parentPath / ".." / ".." / ".."); -#else // _WINDOWS - searchPath.push_back(parentPath / ".." / ".."); -#endif // _WINDOWS - ImageEffectHostOptions hostOptions; - //hostOptions.log = _messageLog; - _host = std::make_shared(searchPath, hostOptions); - - _documentsModel = std::make_shared(context, _host); - - _window = Window::create( - context, - std::dynamic_pointer_cast(shared_from_this()), - "toucan-edit", - dtk::Size2I(1920, 1080)); - addWindow(_window); - - if (!_path.empty()) - { - try - { - _documentsModel->open(_path); - } - catch (const std::exception& e) - { - _context->getSystem()->message("ERROR", e.what(), _window); - } - } - - _window->show(); - } - - App::~App() - {} - - std::shared_ptr App::create( - const std::shared_ptr& context, - std::vector& argv) - { - auto out = std::shared_ptr(new App); - out->_init(context, argv); - return out; - } - - const std::shared_ptr& App::getTimeUnitsModel() const - { - return _timeUnitsModel; - } - - const std::shared_ptr& App::getHost() const - { - return _host; - } - - const std::shared_ptr& App::getDocumentsModel() const - { - return _documentsModel; - } -} diff --git a/lib/toucanEdit/App.h b/lib/toucanEdit/App.h deleted file mode 100644 index 84cb66f..0000000 --- a/lib/toucanEdit/App.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -namespace toucan -{ - class DocumentsModel; - class TimeUnitsModel; - class Window; - - class App : public dtk::App - { - protected: - void _init( - const std::shared_ptr&, - std::vector&); - - public: - virtual ~App(); - - static std::shared_ptr create( - const std::shared_ptr&, - std::vector&); - - const std::shared_ptr& getTimeUnitsModel() const; - const std::shared_ptr& getHost() const; - const std::shared_ptr& getDocumentsModel() const; - - private: - std::shared_ptr _messageLog; - std::string _path; - std::shared_ptr _timeUnitsModel; - std::shared_ptr _host; - std::shared_ptr _documentsModel; - std::shared_ptr _window; - }; -} - diff --git a/lib/toucanEdit/BottomBar.cpp b/lib/toucanEdit/BottomBar.cpp deleted file mode 100644 index 72e55df..0000000 --- a/lib/toucanEdit/BottomBar.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "BottomBar.h" - -#include "App.h" -#include "DocumentsModel.h" -#include "TimeWidgets.h" - -namespace toucan -{ - void BottomBar::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& parent) - { - dtk::IWidget::_init(context, "toucan::BottomBar", parent); - - _layout = dtk::HorizontalLayout::create(context, shared_from_this()); - _layout->setMarginRole(dtk::SizeRole::MarginInside); - _layout->setSpacingRole(dtk::SizeRole::SpacingSmall); - - _playbackButtons = PlaybackButtons::create(context, _layout); - - _frameButtons = FrameButtons::create(context, _layout); - - _timeEdit = TimeEdit::create(context, app->getTimeUnitsModel(), _layout); - _timeEdit->setTooltip("Current time"); - - _durationLabel = TimeLabel::create(context, app->getTimeUnitsModel(), _layout); - _durationLabel->setTooltip("Timeline duration"); - - _frameButtons->setCallback( - [this](FrameAction value) - { - if (_document) - { - _document->getPlaybackModel()->frameAction(value); - } - }); - - _playbackButtons->setCallback( - [this](Playback value) - { - if (_document) - { - _document->getPlaybackModel()->setPlayback(value); - } - }); - - _timeEdit->setCallback( - [this](const OTIO_NS::RationalTime& value) - { - if (_document) - { - _document->getPlaybackModel()->setCurrentTime(value); - } - }); - - _documentObserver = dtk::ValueObserver >::create( - app->getDocumentsModel()->observeCurrent(), - [this](const std::shared_ptr& document) - { - _document = document; - if (document) - { - _timeRangeObserver = dtk::ValueObserver::create( - document->getPlaybackModel()->observeTimeRange(), - [this](const OTIO_NS::TimeRange& value) - { - _timeRange = value; - _timeRangeUpdate(); - }); - - _currentTimeObserver = dtk::ValueObserver::create( - document->getPlaybackModel()->observeCurrentTime(), - [this](const OTIO_NS::RationalTime& value) - { - _currentTime = value; - _currentTimeUpdate(); - }); - - _playbackObserver = dtk::ValueObserver::create( - document->getPlaybackModel()->observePlayback(), - [this](Playback value) - { - _playback = value; - _playbackUpdate(); - }); - } - else - { - _timeRange = OTIO_NS::TimeRange(); - _currentTime = OTIO_NS::RationalTime(); - _playback = Playback::Stop; - - _timeRangeUpdate(); - _currentTimeUpdate(); - _playbackUpdate(); - - _timeRangeObserver.reset(); - _currentTimeObserver.reset(); - _playbackObserver.reset(); - } - - _frameButtons->setEnabled(document.get()); - _playbackButtons->setEnabled(document.get()); - _timeEdit->setEnabled(document.get()); - _durationLabel->setEnabled(document.get()); - }); - } - - BottomBar::~BottomBar() - {} - - std::shared_ptr BottomBar::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new BottomBar); - out->_init(context, app, parent); - return out; - } - - void BottomBar::setGeometry(const dtk::Box2I& value) - { - IWidget::setGeometry(value); - _layout->setGeometry(value); - } - - void BottomBar::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IWidget::sizeHintEvent(event); - _setSizeHint(_layout->getSizeHint()); - } - - void BottomBar::_timelineUpdate() - {} - - void BottomBar::_timeRangeUpdate() - { - _timeEdit->setTimeRange(_timeRange); - - _durationLabel->setTime(_timeRange.duration()); - } - - void BottomBar::_currentTimeUpdate() - { - _timeEdit->setTime(_currentTime); - } - - void BottomBar::_playbackUpdate() - { - _playbackButtons->setPlayback(_playback); - } -} diff --git a/lib/toucanEdit/BottomBar.h b/lib/toucanEdit/BottomBar.h deleted file mode 100644 index 7e80d71..0000000 --- a/lib/toucanEdit/BottomBar.h +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include -#include - -namespace toucan -{ - class App; - class Document; - class FrameButtons; - class PlaybackButtons; - class TimeEdit; - class TimeLabel; - - class BottomBar : public dtk::IWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~BottomBar(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - - private: - void _timelineUpdate(); - void _timeRangeUpdate(); - void _currentTimeUpdate(); - void _playbackUpdate(); - - std::shared_ptr _document; - OTIO_NS::TimeRange _timeRange; - OTIO_NS::RationalTime _currentTime; - Playback _playback = Playback::Stop; - - std::shared_ptr _layout; - std::shared_ptr _frameButtons; - std::shared_ptr _playbackButtons; - std::shared_ptr _timeEdit; - std::shared_ptr _durationLabel; - - std::shared_ptr > > _documentObserver; - std::shared_ptr > _timeRangeObserver; - std::shared_ptr > _currentTimeObserver; - std::shared_ptr > _playbackObserver; - }; -} - diff --git a/lib/toucanEdit/CMakeLists.txt b/lib/toucanEdit/CMakeLists.txt deleted file mode 100644 index abc9e18..0000000 --- a/lib/toucanEdit/CMakeLists.txt +++ /dev/null @@ -1,74 +0,0 @@ -set(HEADERS - App.h - BottomBar.h - Clip.h - ClipWidget.h - Document.h - DocumentsModel.h - DocumentTab.h - Effects.h - Gap.h - GapWidget.h - IContainer.h - IContainerInline.h - IItem.h - IItemWidget.h - ImageGraph.h - MediaReferences.h - MenuBar.h - PlaybackModel.h - SelectionModel.h - Stack.h - StackWidget.h - ThumbnailGenerator.h - Timeline.h - TimelineConvert.h - TimelineView.h - TimelineWidget.h - TimeUnitsModel.h - TimeWidgets.h - Track.h - TrackWidget.h - Transitions.h - Viewport.h - ViewModel.h - Window.h) - -set(SOURCE - App.cpp - BottomBar.cpp - Clip.cpp - ClipWidget.cpp - Document.cpp - DocumentsModel.cpp - DocumentTab.cpp - Effects.cpp - Gap.cpp - GapWidget.cpp - IContainer.cpp - IItem.cpp - IItemWidget.cpp - ImageGraph.cpp - MediaReferences.cpp - MenuBar.cpp - PlaybackModel.cpp - SelectionModel.cpp - Stack.cpp - StackWidget.cpp - ThumbnailGenerator.cpp - Timeline.cpp - TimelineConvert.cpp - TimelineView.cpp - TimelineWidget.cpp - TimeUnitsModel.cpp - TimeWidgets.cpp - Track.cpp - TrackWidget.cpp - Transitions.cpp - Viewport.cpp - ViewModel.cpp - Window.cpp) - -add_library(toucanEdit ${HEADERS} ${SOURCE}) -target_link_libraries(toucanEdit toucan dtk::dtkUI) -set_target_properties(toucanEdit PROPERTIES FOLDER lib) diff --git a/lib/toucanEdit/Clip.cpp b/lib/toucanEdit/Clip.cpp deleted file mode 100644 index ab58cc6..0000000 --- a/lib/toucanEdit/Clip.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Clip.h" - -#include "MediaReferences.h" - -namespace toucan -{ - Clip::Clip( - const std::string& name, - const OTIO_NS::TimeRange& range, - const OTIO_NS::AnyDictionary& metadata) : - IItem(name, range, metadata) - {} - - Clip::~Clip() - {} - - const Clip::MediaReferences& Clip::getMediaReferences() const - { - return _mediaReferences; - } - - std::shared_ptr Clip::getMediaReference() const - { - std::shared_ptr out; - auto i = _mediaReferences.find(_activeMediaReference); - return i != _mediaReferences.end() ? i->second : nullptr; - } - - void Clip::setMediaReferences(const MediaReferences& value) - { - _mediaReferences = value; - } - - const std::string Clip::defaultMediaKey = "DEFAULT_MEDIA"; - - const std::string& Clip::getActiveMediaReference() const - { - return _activeMediaReference; - } - - void Clip::setActiveMediaReference(const std::string& value) - { - _activeMediaReference = value; - } -} diff --git a/lib/toucanEdit/Clip.h b/lib/toucanEdit/Clip.h deleted file mode 100644 index 27727fb..0000000 --- a/lib/toucanEdit/Clip.h +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -namespace toucan -{ - class IMediaReference; - - class Clip : public IItem - { - public: - Clip( - const std::string& name = std::string(), - const OTIO_NS::TimeRange& range = OTIO_NS::TimeRange(), - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary()); - - virtual ~Clip(); - - using MediaReferences = std::map >; - - const MediaReferences& getMediaReferences() const; - std::shared_ptr getMediaReference() const; - void setMediaReferences(const MediaReferences&); - - static const std::string defaultMediaKey; - - const std::string& getActiveMediaReference() const; - void setActiveMediaReference(const std::string&); - - private: - MediaReferences _mediaReferences; - std::string _activeMediaReference = defaultMediaKey; - }; -} - diff --git a/lib/toucanEdit/ClipWidget.cpp b/lib/toucanEdit/ClipWidget.cpp deleted file mode 100644 index 7ffe5db..0000000 --- a/lib/toucanEdit/ClipWidget.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "ClipWidget.h" - -#include "Clip.h" - -#include -#include - -namespace toucan -{ - void ClipWidget::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& clip, - const dtk::Color4F& color, - const std::shared_ptr& parent) - { - IItemWidget::_init( - context, - app, - clip, - clip->getRange(), - "toucan::ClipWidget", - parent); - - _setMousePressEnabled(0, 0); - - _clip = clip; - _text = clip->getName(); - if (_text.empty()) - { - _text = "Clip"; - } - _color = color; - - setTooltip(_text); - } - - ClipWidget::~ClipWidget() - {} - - std::shared_ptr ClipWidget::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& clip, - const dtk::Color4F& color, - const std::shared_ptr& parent) - { - auto out = std::make_shared(); - out->_init(context, app, clip, color, parent); - return out; - } - - void ClipWidget::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IItemWidget::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.fontInfo = event.style->getFontRole(dtk::FontRole::Label , event.displayScale); - _size.fontMetrics = event.fontSystem->getMetrics(_size.fontInfo); - _size.textSize = event.fontSystem->getSize(_text, _size.fontInfo); - _draw.glyphs.clear(); - } - dtk::Size2I sizeHint( - _timeRange.duration().rescaled_to(1.0).value() * _scale, - _size.textSize.h + _size.margin * 2 + _size.border * 2); - _setSizeHint(sizeHint); - } - - void ClipWidget::clipEvent(const dtk::Box2I& clipRect, bool clipped) - { - IItemWidget::clipEvent(clipRect, clipped); - if (clipped) - { - _draw.glyphs.clear(); - } - } - - void ClipWidget::drawEvent( - const dtk::Box2I& drawRect, - const dtk::DrawEvent& event) - { - IItemWidget::drawEvent(drawRect, event); - const dtk::Box2I& g = getGeometry(); - - const dtk::Box2I g2 = dtk::margin(g, -_size.border, 0, -_size.border, 0); - event.render->drawRect( - g2, - _selected ? event.style->getColorRole(dtk::ColorRole::Yellow) : _color); - - const dtk::Box2I g3 = dtk::margin(g2, -_size.margin); - if (!_text.empty() && _draw.glyphs.empty()) - { - _draw.glyphs = event.fontSystem->getGlyphs(_text, _size.fontInfo); - } - dtk::ClipRectEnabledState clipRectEnabledState(event.render); - dtk::ClipRectState clipRectState(event.render); - event.render->setClipRectEnabled(true); - event.render->setClipRect(intersect(g3, drawRect)); - event.render->drawText( - _draw.glyphs, - _size.fontMetrics, - dtk::V2I(g3.min.x, g3.min.y + g3.h() / 2 - _size.fontMetrics.lineHeight / 2), - event.style->getColorRole(dtk::ColorRole::Text)); - } -} diff --git a/lib/toucanEdit/ClipWidget.h b/lib/toucanEdit/ClipWidget.h deleted file mode 100644 index 0860bd5..0000000 --- a/lib/toucanEdit/ClipWidget.h +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - class Clip; - - class ClipWidget : public IItemWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const dtk::Color4F&, - const std::shared_ptr& parent); - - public: - virtual ~ClipWidget(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const dtk::Color4F&, - const std::shared_ptr& parent = nullptr); - - void sizeHintEvent(const dtk::SizeHintEvent&) override; - void clipEvent(const dtk::Box2I&, bool) override; - void drawEvent(const dtk::Box2I&, const dtk::DrawEvent&) override; - - private: - std::shared_ptr _clip; - std::string _text; - dtk::Color4F _color; - - struct SizeData - { - bool init = true; - float displayScale = 0.F; - int margin = 0; - int border = 0; - dtk::FontInfo fontInfo; - dtk::FontMetrics fontMetrics; - dtk::Size2I textSize; - }; - SizeData _size; - - struct DrawData - { - std::vector > glyphs; - }; - DrawData _draw; - }; -} diff --git a/lib/toucanEdit/Document.cpp b/lib/toucanEdit/Document.cpp deleted file mode 100644 index 91a4b94..0000000 --- a/lib/toucanEdit/Document.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Document.h" - -#include "ImageGraph.h" -#include "PlaybackModel.h" -#include "SelectionModel.h" -#include "Timeline.h" -#include "ThumbnailGenerator.h" -#include "ViewModel.h" - -#include - -namespace toucan -{ - Document::Document( - const std::shared_ptr& context, - const std::shared_ptr& host, - const std::filesystem::path& path) : - _host(host), - _path(path) - { - OTIO_NS::ErrorStatus errorStatus; - auto otioTimeline = OTIO_NS::SerializableObject::Retainer( - dynamic_cast(OTIO_NS::Timeline::from_json_file(path.string(), &errorStatus))); - if (!otioTimeline) - { - throw std::runtime_error(errorStatus.full_description); - } - _timeline = convertFrom(path, otioTimeline); - - const auto& globalStartTime = otioTimeline->global_start_time(); - const OTIO_NS::RationalTime& duration = otioTimeline->duration(); - const OTIO_NS::RationalTime startTime = globalStartTime.has_value() ? - globalStartTime.value() : - OTIO_NS::RationalTime(0.0, duration.rate()); - - _playbackModel = std::make_shared(context); - _playbackModel->setTimeRange(OTIO_NS::TimeRange(startTime, duration)); - _playbackModel->setCurrentTime(startTime); - - _viewModel = std::make_shared(); - - _selectionModel = std::make_shared(); - - _thumbnailGenerator = std::make_shared(_timeline, _host); - - _currentImage = dtk::ObservableValue >::create(); - - _rootNode = dtk::ObservableValue >::create(); - - ImageGraphOptions graphOptions; - _graph = std::make_shared(_timeline, graphOptions); - - _currentTimeObserver = dtk::ValueObserver::create( - _playbackModel->observeCurrentTime(), - [this](const OTIO_NS::RationalTime& value) - { - _currentTime = value; - auto node = _graph->exec(_host, _currentTime); - _rootNode->setAlways(node); - _render(); - }); - } - - Document::~Document() - {} - - const std::filesystem::path& Document::getPath() const - { - return _path; - } - - const std::shared_ptr& Document::getTimeline() const - { - return _timeline; - } - - const std::shared_ptr& Document::getPlaybackModel() const - { - return _playbackModel; - } - - const std::shared_ptr& Document::getViewModel() const - { - return _viewModel; - } - - const std::shared_ptr& Document::getSelectionModel() const - { - return _selectionModel; - } - - const std::shared_ptr& Document::getThumbnailGenerator() const - { - return _thumbnailGenerator; - } - - std::shared_ptr > > Document::observeCurrentImage() const - { - return _currentImage; - } - - void Document::_render() - { - std::shared_ptr image; - if (_rootNode->get()) - { - //! \todo Can we remove this time arg? - const OTIO_NS::TimeRange& timeRange = _playbackModel->getTimeRange(); - _imageBuf = _rootNode->get()->exec(_currentTime - timeRange.start_time()); - - const auto& spec = _imageBuf.spec(); - dtk::ImageType imageType = dtk::ImageType::None; - if (OIIO::TypeDesc::UINT8 == spec.format) - { - switch (spec.nchannels) - { - case 1: imageType = dtk::ImageType::L_U8; break; - case 2: imageType = dtk::ImageType::LA_U8; break; - case 3: imageType = dtk::ImageType::RGB_U8; break; - case 4: imageType = dtk::ImageType::RGBA_U8; break; - default: break; - } - } - else if (OIIO::TypeDesc::UINT16 == spec.format) - { - switch (spec.nchannels) - { - case 1: imageType = dtk::ImageType::L_U16; break; - case 2: imageType = dtk::ImageType::LA_U16; break; - case 3: imageType = dtk::ImageType::RGB_U16; break; - case 4: imageType = dtk::ImageType::RGBA_U16; break; - default: break; - } - } - else if (OIIO::TypeDesc::HALF == spec.format) - { - switch (spec.nchannels) - { - case 1: imageType = dtk::ImageType::L_F16; break; - case 2: imageType = dtk::ImageType::LA_F16; break; - case 3: imageType = dtk::ImageType::RGB_F16; break; - case 4: imageType = dtk::ImageType::RGBA_F16; break; - default: break; - } - } - else if (OIIO::TypeDesc::FLOAT == spec.format) - { - switch (spec.nchannels) - { - case 1: imageType = dtk::ImageType::L_F32; break; - case 2: imageType = dtk::ImageType::LA_F32; break; - case 3: imageType = dtk::ImageType::RGB_F32; break; - case 4: imageType = dtk::ImageType::RGBA_F32; break; - default: break; - } - } - dtk::ImageInfo info(spec.width, spec.height, imageType); - info.layout.mirror.y = true; - image = dtk::Image::create(info, reinterpret_cast(_imageBuf.localpixels())); - } - _currentImage->setIfChanged(image); - } -} diff --git a/lib/toucanEdit/Document.h b/lib/toucanEdit/Document.h deleted file mode 100644 index 48efb73..0000000 --- a/lib/toucanEdit/Document.h +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include -#include -#include - -#include - -namespace toucan -{ - class ImageGraph; - class PlaybackModel; - class SelectionModel; - class Timeline; - class ThumbnailGenerator; - class ViewModel; - - class Document : std::enable_shared_from_this - { - public: - Document( - const std::shared_ptr&, - const std::shared_ptr&, - const std::filesystem::path&); - - ~Document(); - - const std::filesystem::path& getPath() const; - - const std::shared_ptr& getTimeline() const; - - const std::shared_ptr& getPlaybackModel() const; - const std::shared_ptr& getViewModel() const; - const std::shared_ptr& getSelectionModel() const; - const std::shared_ptr& getThumbnailGenerator() const; - - std::shared_ptr > > observeCurrentImage() const; - - private: - void _render(); - - std::shared_ptr _host; - std::filesystem::path _path; - std::shared_ptr _timeline; - std::shared_ptr _playbackModel; - std::shared_ptr _viewModel; - std::shared_ptr _selectionModel; - std::shared_ptr _thumbnailGenerator; - std::shared_ptr > > _currentImage; - OTIO_NS::RationalTime _currentTime; - - std::shared_ptr _graph; - std::shared_ptr > > _rootNode; - OIIO::ImageBuf _imageBuf; - - std::shared_ptr > _currentTimeObserver; - }; -} diff --git a/lib/toucanEdit/DocumentTab.cpp b/lib/toucanEdit/DocumentTab.cpp deleted file mode 100644 index 857ada1..0000000 --- a/lib/toucanEdit/DocumentTab.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "DocumentTab.h" - -#include "App.h" -#include "BottomBar.h" -#include "TimelineView.h" -#include "Viewport.h" - -namespace toucan -{ - void DocumentTab::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& document, - const std::shared_ptr& parent) - { - dtk::IWidget::_init(context, "toucan::DocumentTab", parent); - - _vSplitter = dtk::Splitter::create(context, dtk::Orientation::Vertical, shared_from_this()); - _vSplitter->setSplit({ .7F, .3F }); - _vSplitter->setStretch(dtk::Stretch::Expanding); - _hSplitter = dtk::Splitter::create(context, dtk::Orientation::Horizontal, _vSplitter); - _hSplitter->setSplit({ .75F, .25F }); - - _viewport = Viewport::create(context, document, _hSplitter); - _viewport->setStretch(dtk::Stretch::Expanding); - - _bottomLayout = dtk::VerticalLayout::create(context, _vSplitter); - _bottomLayout->setSpacingRole(dtk::SizeRole::None); - _bottomBar = BottomBar::create(context, app, _bottomLayout); - _timelineView = TimelineView::create(context, app, document, _bottomLayout); - _timelineView->setVStretch(dtk::Stretch::Expanding); - } - - DocumentTab::~DocumentTab() - {} - - std::shared_ptr DocumentTab::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& document, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new DocumentTab); - out->_init(context, app, document, parent); - return out; - } - - void DocumentTab::setGeometry(const dtk::Box2I& value) - { - dtk::IWidget::setGeometry(value); - _vSplitter->setGeometry(value); - } - - void DocumentTab::sizeHintEvent(const dtk::SizeHintEvent& event) - { - dtk::IWidget::sizeHintEvent(event); - _setSizeHint(_vSplitter->getSizeHint()); - } -} diff --git a/lib/toucanEdit/DocumentTab.h b/lib/toucanEdit/DocumentTab.h deleted file mode 100644 index 87aed87..0000000 --- a/lib/toucanEdit/DocumentTab.h +++ /dev/null @@ -1,49 +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 BottomBar; - class Document; - class TimelineView; - class Viewport; - - class DocumentTab : public dtk::IWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~DocumentTab(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - - private: - std::shared_ptr _vSplitter; - std::shared_ptr _hSplitter; - std::shared_ptr _viewport; - std::shared_ptr _bottomLayout; - std::shared_ptr _bottomBar; - std::shared_ptr _timelineView; - }; -} - diff --git a/lib/toucanEdit/DocumentsModel.cpp b/lib/toucanEdit/DocumentsModel.cpp deleted file mode 100644 index c68230f..0000000 --- a/lib/toucanEdit/DocumentsModel.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "DocumentsModel.h" - -#include "PlaybackModel.h" - -#include - -namespace toucan -{ - DocumentsModel::DocumentsModel( - const std::shared_ptr& context, - const std::shared_ptr& host) : - _context(context), - _host(host) - { - _documents = dtk::ObservableList< std::shared_ptr >::create(); - _add = dtk::ObservableValue::create(-1); - _remove = dtk::ObservableValue::create(-1); - _current = dtk::ObservableValue< std::shared_ptr >::create(nullptr); - _currentIndex = dtk::ObservableValue::create(-1); - } - - DocumentsModel::~DocumentsModel() - {} - - void DocumentsModel::open(const std::filesystem::path& path) - { - if (auto context = _context.lock()) - { - auto documents = _documents->get(); - auto document = std::make_shared(context, _host, path); - documents.push_back(document); - _documents->setIfChanged(documents); - const int index = documents.size() - 1; - _add->setAlways(index); - _current->setIfChanged(documents[index]); - _currentIndex->setIfChanged(index); - } - } - - void DocumentsModel::close() - { - close(_currentIndex->get()); - } - - void DocumentsModel::close(int index) - { - auto documents = _documents->get(); - if (index >= 0 && index < documents.size()) - { - auto document = *(documents.begin() + index); - documents.erase(documents.begin() + index); - _remove->setAlways(index); - _documents->setIfChanged(documents); - int current = std::min(_currentIndex->get(), static_cast(documents.size()) - 1); - _current->setAlways( - (current >= 0 && current < documents.size()) ? - documents[current] : - nullptr); - _currentIndex->setAlways(current); - } - } - - void DocumentsModel::closeAll() - { - auto documents = _documents->get(); - for (size_t i = 0; i < documents.size(); ++i) - { - _remove->setAlways(i); - } - _documents->setIfChanged({}); - _current->setIfChanged(nullptr); - _currentIndex->setIfChanged(-1); - } - - std::shared_ptr > > DocumentsModel::observeDocuments() const - { - return _documents; - } - - std::shared_ptr > DocumentsModel::observeAdd() const - { - return _add; - } - - std::shared_ptr > DocumentsModel::observeRemove() const - { - return _remove; - } - - std::shared_ptr > > DocumentsModel::observeCurrent() const - { - return _current; - } - - std::shared_ptr > DocumentsModel::observeCurrentIndex() const - { - return _currentIndex; - } - - void DocumentsModel::setCurrentIndex(int value) - { - const auto& documents = _documents->get(); - const int index = dtk::clamp(value, 0, static_cast(documents.size()) - 1); - _current->setIfChanged(documents[index]); - _currentIndex->setIfChanged(index); - } - - void DocumentsModel::next() - { - const auto& documents = _documents->get(); - if (!documents.empty()) - { - int index = _currentIndex->get() + 1; - if (index >= documents.size()) - { - index = 0; - } - setCurrentIndex(index); - } - } - - void DocumentsModel::prev() - { - const auto& documents = _documents->get(); - if (!documents.empty()) - { - int index = _currentIndex->get() - 1; - if (index < 0) - { - index = static_cast(documents.size()) - 1; - } - setCurrentIndex(index); - } - } -} diff --git a/lib/toucanEdit/DocumentsModel.h b/lib/toucanEdit/DocumentsModel.h deleted file mode 100644 index 2a49ace..0000000 --- a/lib/toucanEdit/DocumentsModel.h +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -#include -#include -#include - -namespace toucan -{ - class DocumentsModel : public std::enable_shared_from_this - { - public: - DocumentsModel( - const std::shared_ptr&, - const std::shared_ptr&); - - virtual ~DocumentsModel(); - - void open(const std::filesystem::path&); - void close(); - void close(int); - void closeAll(); - - std::shared_ptr > > observeDocuments() const; - std::shared_ptr > observeAdd() const; - std::shared_ptr > observeRemove() const; - std::shared_ptr > > observeCurrent() const; - std::shared_ptr > observeCurrentIndex() const; - void setCurrentIndex(int); - void next(); - void prev(); - - private: - std::weak_ptr _context; - std::shared_ptr _host; - std::shared_ptr > > _documents; - std::shared_ptr > _add; - std::shared_ptr > _remove; - std::shared_ptr > > _current; - std::shared_ptr > _currentIndex; - }; -} - diff --git a/lib/toucanEdit/Effects.cpp b/lib/toucanEdit/Effects.cpp deleted file mode 100644 index 9dafae3..0000000 --- a/lib/toucanEdit/Effects.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Effects.h" - -namespace toucan -{ - Effect::Effect( - const std::string& name, - const std::string& effectName, - const OTIO_NS::AnyDictionary& metadata) : - _name(name), - _effectName(effectName), - _metadata(metadata) - {} - - Effect::~Effect() - {} - - const std::string& Effect::getName() const - { - return _name; - } - - void Effect::setName(const std::string& value) - { - _name = value; - } - - const std::string& Effect::getEffectName() const - { - return _effectName; - } - - void Effect::setEffectName(const std::string& value) - { - _effectName = value; - } - - const OTIO_NS::AnyDictionary& Effect::getMetadata() const - { - return _metadata; - } - - void Effect::setMetadata(const OTIO_NS::AnyDictionary& value) - { - _metadata = value; - } - - LinearTimeWarp::LinearTimeWarp( - const std::string & name, - const std::string & effectName, - const OTIO_NS::AnyDictionary & metadata) : - Effect(name, effectName, metadata) - {} - - LinearTimeWarp::~LinearTimeWarp() - {} - - double LinearTimeWarp::getTimeScalar() const - { - return _timeScalar; - } - - void LinearTimeWarp::setTimeScalar(double value) - { - _timeScalar = value; - } -} diff --git a/lib/toucanEdit/Effects.h b/lib/toucanEdit/Effects.h deleted file mode 100644 index f2e4db9..0000000 --- a/lib/toucanEdit/Effects.h +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -namespace toucan -{ - class Effect : public std::enable_shared_from_this - { - public: - Effect( - const std::string& name = std::string(), - const std::string& effectName = std::string(), - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary()); - - virtual ~Effect(); - - const std::string& getName() const; - void setName(const std::string&); - - const std::string& getEffectName() const; - void setEffectName(const std::string&); - - const OTIO_NS::AnyDictionary& getMetadata() const; - void setMetadata(const OTIO_NS::AnyDictionary&); - - private: - std::string _name; - std::string _effectName; - OTIO_NS::AnyDictionary _metadata; - }; - - class LinearTimeWarp : public Effect - { - public: - LinearTimeWarp( - const std::string& name = std::string(), - const std::string& effectName = std::string(), - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary()); - - virtual ~LinearTimeWarp(); - - double getTimeScalar() const; - void setTimeScalar(double); - - private: - double _timeScalar = 1.0; - }; -} - diff --git a/lib/toucanEdit/Gap.cpp b/lib/toucanEdit/Gap.cpp deleted file mode 100644 index 4c89929..0000000 --- a/lib/toucanEdit/Gap.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Gap.h" - -namespace toucan -{ - Gap::Gap( - const std::string& name, - const OTIO_NS::TimeRange& range, - const OTIO_NS::AnyDictionary& metadata) : - IItem(name, range, metadata) - {} - - Gap::~Gap() - {} -} diff --git a/lib/toucanEdit/Gap.h b/lib/toucanEdit/Gap.h deleted file mode 100644 index 61e40d3..0000000 --- a/lib/toucanEdit/Gap.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - class Gap : public IItem - { - public: - Gap( - const std::string& name = std::string(), - const OTIO_NS::TimeRange& range = OTIO_NS::TimeRange(), - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary()); - - virtual ~Gap(); - }; -} - diff --git a/lib/toucanEdit/GapWidget.cpp b/lib/toucanEdit/GapWidget.cpp deleted file mode 100644 index fef0ee8..0000000 --- a/lib/toucanEdit/GapWidget.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "GapWidget.h" - -#include "Gap.h" - -#include -#include -#include - -#include - -namespace toucan -{ - void GapWidget::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& gap, - const std::shared_ptr& parent) - { - IItemWidget::_init( - context, - app, - gap, - gap->getRange(), - "toucan::ClipItem", - parent); - - _gap = gap; - _text = gap->getName(); - if (_text.empty()) - { - _text = "Gap"; - } - _color = dtk::Color4F(.3F, .3F, .3F); - - setTooltip(_text); - } - - GapWidget::~GapWidget() - {} - - std::shared_ptr GapWidget::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& gap, - const std::shared_ptr& parent) - { - auto out = std::make_shared(); - out->_init(context, app, gap, parent); - return out; - } - - void GapWidget::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IItemWidget::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.fontInfo = event.style->getFontRole(dtk::FontRole::Label , event.displayScale); - _size.fontMetrics = event.fontSystem->getMetrics(_size.fontInfo); - _size.textSize = event.fontSystem->getSize(_text, _size.fontInfo); - _draw.glyphs.clear(); - } - dtk::Size2I sizeHint( - _timeRange.duration().rescaled_to(1.0).value() * _scale, - _size.textSize.h + _size.margin * 2 + _size.border * 2); - _setSizeHint(sizeHint); - } - - void GapWidget::clipEvent(const dtk::Box2I& clipRect, bool clipped) - { - IItemWidget::clipEvent(clipRect, clipped); - if (clipped) - { - _draw.glyphs.clear(); - } - } - - void GapWidget::drawEvent( - const dtk::Box2I& drawRect, - const dtk::DrawEvent& event) - { - IItemWidget::drawEvent(drawRect, event); - const dtk::Box2I& g = getGeometry(); - - const dtk::Box2I g2 = dtk::margin(g, -_size.border, 0, -_size.border, 0); - event.render->drawRect( - g2, - _selected ? event.style->getColorRole(dtk::ColorRole::Yellow) : _color); - - const dtk::Box2I g3 = dtk::margin(g2, -_size.margin); - if (!_text.empty() && _draw.glyphs.empty()) - { - _draw.glyphs = event.fontSystem->getGlyphs(_text, _size.fontInfo); - } - dtk::ClipRectEnabledState clipRectEnabledState(event.render); - dtk::ClipRectState clipRectState(event.render); - event.render->setClipRectEnabled(true); - event.render->setClipRect(intersect(g3, drawRect)); - event.render->drawText( - _draw.glyphs, - _size.fontMetrics, - dtk::V2I(g3.min.x, g3.min.y + g3.h() / 2 - _size.fontMetrics.lineHeight / 2), - event.style->getColorRole(dtk::ColorRole::Text)); - } -} diff --git a/lib/toucanEdit/GapWidget.h b/lib/toucanEdit/GapWidget.h deleted file mode 100644 index f1ae6bd..0000000 --- a/lib/toucanEdit/GapWidget.h +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - class Gap; - - class GapWidget : public IItemWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~GapWidget(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - void sizeHintEvent(const dtk::SizeHintEvent&) override; - void clipEvent(const dtk::Box2I&, bool) override; - void drawEvent(const dtk::Box2I&, const dtk::DrawEvent&) override; - - private: - std::shared_ptr _gap; - std::string _text; - dtk::Color4F _color; - - struct SizeData - { - bool init = true; - float displayScale = 0.F; - int margin = 0; - int border = 0; - dtk::FontInfo fontInfo; - dtk::FontMetrics fontMetrics; - dtk::Size2I textSize; - }; - SizeData _size; - - struct DrawData - { - std::vector > glyphs; - }; - DrawData _draw; - }; -} diff --git a/lib/toucanEdit/IContainer.cpp b/lib/toucanEdit/IContainer.cpp deleted file mode 100644 index 13b14a7..0000000 --- a/lib/toucanEdit/IContainer.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "IContainer.h" - -namespace toucan -{ - IContainer::IContainer( - const std::string& name, - const OTIO_NS::TimeRange& range, - const OTIO_NS::AnyDictionary& metadata) : - IItem(name, range, metadata) - {} - - IContainer::~IContainer() - {} - - const std::vector >& IContainer::getChildren() const - { - return _children; - } - - void IContainer::addChild(const std::shared_ptr& child) - { - if (auto prev = child->_parent.lock()) - { - const auto i = std::find(prev->_children.begin(), prev->_children.end(), child); - if (i != prev->_children.end()) - { - prev->_children.erase(i); - } - } - child->_parent = std::dynamic_pointer_cast(shared_from_this()); - _children.push_back(child); - } - - void IContainer::removeChild(const std::shared_ptr& child) - { - const auto i = std::find(_children.begin(), _children.end(), child); - if (i != _children.end()) - { - child->_parent.reset(); - _children.erase(i); - } - } - - OTIO_NS::TimeRange IContainer::getChildRange(const std::shared_ptr& item) - { - const OTIO_NS::TimeRange& range = getRange(); - OTIO_NS::RationalTime t = range.start_time(); - const auto& children = getChildren(); - auto i = children.begin(); - for (; i != children.end() && *i != item; ++i) - { - t += (*i)->getRange().duration(); - } - OTIO_NS::RationalTime d(0.0, t.rate()); - if (i != children.end()) - { - d = (*i)->getRange().duration(); - } - return OTIO_NS::TimeRange(t, d); - } -} diff --git a/lib/toucanEdit/IContainer.h b/lib/toucanEdit/IContainer.h deleted file mode 100644 index bea3190..0000000 --- a/lib/toucanEdit/IContainer.h +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - enum class Find - { - Recurse, - Shallow - }; - - class IContainer : public IItem - { - public: - IContainer( - const std::string& name = std::string(), - const OTIO_NS::TimeRange& range = OTIO_NS::TimeRange(), - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary()); - - virtual ~IContainer() = 0; - - const std::vector >& getChildren() const; - void addChild(const std::shared_ptr&); - void removeChild(const std::shared_ptr&); - - virtual OTIO_NS::TimeRange getChildRange(const std::shared_ptr&); - - template - std::shared_ptr find(Find find = Find::Recurse) const; - template - std::vector > findAll(Find find = Find::Recurse) const; - - private: - template - void _findAll(Find, std::vector >&) const; - - std::vector > _children; - }; -} - -#include "IContainerInline.h" - diff --git a/lib/toucanEdit/IContainerInline.h b/lib/toucanEdit/IContainerInline.h deleted file mode 100644 index fe4dc6c..0000000 --- a/lib/toucanEdit/IContainerInline.h +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -namespace toucan -{ - template - inline std::shared_ptr IContainer::find(Find find) const - { - std::shared_ptr out; - for (const auto& child : _children) - { - if ((out = std::dynamic_pointer_cast(child))) - { - break; - } - if (Find::Recurse == find) - { - if (auto container = std::dynamic_pointer_cast(child)) - { - out = container->find(); - } - } - } - return out; - } - - template - inline std::vector > IContainer::findAll(Find find) const - { - std::vector > out; - _findAll(find, out); - return out; - } - - template - inline void IContainer::_findAll(Find find, std::vector >& out) const - { - for (const auto& child : _children) - { - if (auto t = std::dynamic_pointer_cast(child)) - { - out.push_back(t); - } - if (Find::Recurse == find) - { - if (auto container = std::dynamic_pointer_cast(child)) - { - container->_findAll(find, out); - } - } - } - } -} diff --git a/lib/toucanEdit/IItem.cpp b/lib/toucanEdit/IItem.cpp deleted file mode 100644 index bcbf7b9..0000000 --- a/lib/toucanEdit/IItem.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "IItem.h" - -#include "IContainer.h" - -namespace toucan -{ - IItem::IItem( - const std::string& name, - const OTIO_NS::TimeRange& range, - const OTIO_NS::AnyDictionary& metadata) : - _name(name), - _range(range), - _metadata(metadata) - {} - - IItem::~IItem() - {} - - const std::string& IItem::getName() const - { - return _name; - } - - void IItem::setName(const std::string& name) - { - _name = name; - } - - const OTIO_NS::TimeRange& IItem::getRange() const - { - return _range; - } - - void IItem::setRange(const OTIO_NS::TimeRange& range) - { - _range = range; - } - - const OTIO_NS::AnyDictionary& IItem::getMetadata() const - { - return _metadata; - } - - void IItem::setMetadata(const OTIO_NS::AnyDictionary& value) - { - _metadata = value; - } - - std::shared_ptr IItem::getParent() const - { - return _parent.lock(); - } - - std::shared_ptr IItem::getRoot() - { - std::shared_ptr item = shared_from_this(); - for (; item->getParent(); item = item->getParent()) - ; - return std::dynamic_pointer_cast(item); - } - - const std::vector >& IItem::getEffects() const - { - return _effects; - } - - void IItem::setEffects(const std::vector >& value) - { - _effects = value; - } - - OTIO_NS::RationalTime IItem::transform( - const OTIO_NS::RationalTime& time, - const std::shared_ptr& toItem) - { - OTIO_NS::RationalTime out = time; - - auto root = getRoot(); - auto item = shared_from_this(); - while (item != toItem && item != root) - { - out -= item->getRange().start_time(); - auto parent = item->getParent(); - out += parent->getChildRange(item).start_time(); - item = parent; - } - - auto ancestor = item; - item = toItem; - while (item != ancestor && item != root) - { - out += item->getRange().start_time(); - auto parent = item->getParent(); - out -= parent->getChildRange(item).start_time(); - item = parent; - } - - return out; - } - - OTIO_NS::TimeRange IItem::transform( - const OTIO_NS::TimeRange& range, - const std::shared_ptr& toItem) - { - return OTIO_NS::TimeRange( - transform(range.start_time(), toItem), - range.duration()); - } -} diff --git a/lib/toucanEdit/IItem.h b/lib/toucanEdit/IItem.h deleted file mode 100644 index 90b66ed..0000000 --- a/lib/toucanEdit/IItem.h +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include -#include - -namespace toucan -{ - class Effect; - class IContainer; - - class IItem : public std::enable_shared_from_this - { - public: - IItem( - const std::string& name = std::string(), - const OTIO_NS::TimeRange& range = OTIO_NS::TimeRange(), - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary()); - - virtual ~IItem() = 0; - - const std::string& getName() const; - void setName(const std::string&); - - const OTIO_NS::TimeRange& getRange() const; - void setRange(const OTIO_NS::TimeRange&); - - const OTIO_NS::AnyDictionary& getMetadata() const; - void setMetadata(const OTIO_NS::AnyDictionary&); - - std::shared_ptr getParent() const; - std::shared_ptr getRoot(); - - const std::vector >& getEffects() const; - void setEffects(const std::vector >&); - - OTIO_NS::RationalTime transform( - const OTIO_NS::RationalTime&, - const std::shared_ptr&); - - OTIO_NS::TimeRange transform( - const OTIO_NS::TimeRange&, - const std::shared_ptr&); - - private: - std::string _name; - OTIO_NS::TimeRange _range; - OTIO_NS::AnyDictionary _metadata; - std::weak_ptr _parent; - std::vector > _effects; - - friend class IContainer; - }; -} - diff --git a/lib/toucanEdit/IItemWidget.cpp b/lib/toucanEdit/IItemWidget.cpp deleted file mode 100644 index 100801d..0000000 --- a/lib/toucanEdit/IItemWidget.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "IItemWidget.h" - -namespace toucan -{ - void IItemWidget::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& item, - const OTIO_NS::TimeRange& timeRange, - const std::string& name, - const std::shared_ptr& parent) - { - IWidget::_init(context, name, parent); - _item = item; - _timeRange = timeRange; - } - - IItemWidget::~IItemWidget() - {} - - const std::shared_ptr& IItemWidget::getItem() const - { - return _item; - } - - const OTIO_NS::TimeRange& IItemWidget::getTimeRange() - { - return _timeRange; - } - - void IItemWidget::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(); - } - - bool IItemWidget::isSelected() const - { - return _selected; - } - - void IItemWidget::setSelected(bool value) - { - if (value == _selected) - return; - _selected = value; - _setDrawUpdate(); - } -} diff --git a/lib/toucanEdit/IItemWidget.h b/lib/toucanEdit/IItemWidget.h deleted file mode 100644 index ef8cc70..0000000 --- a/lib/toucanEdit/IItemWidget.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -namespace toucan -{ - class App; - - class IItemWidget : public dtk::IWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const OTIO_NS::TimeRange&, - const std::string&, - const std::shared_ptr& parent); - - public: - virtual ~IItemWidget() = 0; - - const std::shared_ptr& getItem() const; - - const OTIO_NS::TimeRange& getTimeRange(); - - void setScale(double); - - bool isSelected() const; - void setSelected(bool); - - protected: - std::shared_ptr _item; - OTIO_NS::TimeRange _timeRange; - double _scale = 100.0; - bool _selected = false; - }; -} diff --git a/lib/toucanEdit/ImageGraph.cpp b/lib/toucanEdit/ImageGraph.cpp deleted file mode 100644 index 21a1e02..0000000 --- a/lib/toucanEdit/ImageGraph.cpp +++ /dev/null @@ -1,361 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "ImageGraph.h" - -#include "Clip.h" -#include "Effects.h" -#include "Gap.h" -#include "MediaReferences.h" -#include "Stack.h" -#include "Timeline.h" -#include "Track.h" -#include "Transitions.h" - -#include -#include -#include -#include - -namespace toucan -{ - ImageGraph::ImageGraph( - const std::shared_ptr& timeline, - const ImageGraphOptions& options) : - _timeline(timeline), - _options(options) - { - // Get the image size from the first clip. - for (const auto& clip : timeline->getStack()->findAll()) - { - if (auto ref = clip->getMediaReference()) - { - if (auto externalRef = std::dynamic_pointer_cast(ref)) - { - const std::filesystem::path path = getMediaPath( - timeline->getPath().parent_path(), - externalRef->getURL()); - const OIIO::ImageBuf buf(path.string()); - const auto& spec = buf.spec(); - if (spec.width > 0) - { - _imageSize.x = spec.width; - _imageSize.y = spec.height; - break; - } - } - else if (auto sequenceRef = std::dynamic_pointer_cast(ref)) - { - const std::filesystem::path path = getSequenceFrame( - getMediaPath(timeline->getPath().parent_path(), sequenceRef->getTargetURLBase()), - sequenceRef->getNamePrefix(), - sequenceRef->getStartFrame(), - sequenceRef->getFrameZeroPadding(), - sequenceRef->getNameSuffix()); - const OIIO::ImageBuf buf(path.string()); - const auto& spec = buf.spec(); - if (spec.width > 0) - { - _imageSize.x = spec.width; - _imageSize.y = spec.height; - break; - } - } - else if (auto generatorRef = std::dynamic_pointer_cast(ref)) - { - auto parameters = generatorRef->getParameters(); - auto i = parameters.find("size"); - if (i != parameters.end() && i->second.has_value()) - { - anyToVec(std::any_cast(i->second), _imageSize); - } - } - } - } - } - - ImageGraph::~ImageGraph() - {} - - const IMATH_NAMESPACE::V2i& ImageGraph::getImageSize() const - { - return _imageSize; - } - - std::shared_ptr ImageGraph::exec( - const std::shared_ptr& host, - const OTIO_NS::RationalTime& time) - { - // Set the background color. - OTIO_NS::AnyDictionary metaData; - metaData["size"] = vecToAny(_imageSize); - metaData["color"] = vecToAny(IMATH_NAMESPACE::V4f(0.F, 0.F, 0.F, 1.F)); - std::shared_ptr node = host->createNode("toucan:Fill", metaData); - - // Loop over the tracks. - auto stack = _timeline->getStack(); - for (const auto& track : stack->findAll(Find::Shallow)) - { - if (TrackKind::video == track->getKind()) - { - // Process this track. - const OTIO_NS::RationalTime trackTime = stack->transform(time, track); - auto trackNode = _track(host, trackTime, track); - - // Get the track effects. - const auto& effects = track->getEffects(); - if (!effects.empty()) - { - trackNode = _effects(host, effects, trackNode); - } - - // Composite this track over the previous track. - std::vector > nodes; - if (trackNode) - { - nodes.push_back(trackNode); - } - if (node) - { - nodes.push_back(node); - } - auto comp = std::make_shared(nodes); - comp->setPremult(true); - node = comp; - } - } - - - // Get the stack effects. - const auto& effects = stack->getEffects(); - if (!effects.empty()) - { - node = _effects(host, effects, node); - } - - return node; - } - - std::shared_ptr ImageGraph::_track( - const std::shared_ptr& host, - const OTIO_NS::RationalTime& time, - const std::shared_ptr& track) - { - std::shared_ptr out; - - // Find the items for the given time. - std::shared_ptr item; - std::shared_ptr prev; - std::shared_ptr prev2; - std::shared_ptr next; - std::shared_ptr next2; - const auto& children = track->getChildren(); - for (size_t i = 0; i < children.size(); ++i) - { - item = children[i]; - const OTIO_NS::RationalTime itemTime = track->transform(time, item); - const OTIO_NS::TimeRange& range = item->getRange(); - if (range.contains(itemTime)) - { - out = _item(host, itemTime, item); - if (i > 0) - { - prev = children[i - 1]; - } - if (i > 1) - { - prev2 = children[i - 2]; - } - if (i < (children.size() - 1)) - { - next = children[i + 1]; - } - if (children.size() > 1 && i < (children.size() - 2)) - { - next2 = children[i + 2]; - } - break; - } - } - - // Handle transitions. - if (item) - { - if (auto prevTransition = std::dynamic_pointer_cast(prev)) - { - OTIO_NS::TimeRange rangeInParent = prevTransition->transform( - OTIO_NS::TimeRange( - -prevTransition->getInOffset(), - prevTransition->getInOffset() + prevTransition->getOutOffset()), - track); - if (rangeInParent.contains(time) && prev2) - { - const double value = - (time - rangeInParent.start_time()).value() / - rangeInParent.duration().value(); - - auto metaData = prevTransition->getMetadata(); - metaData["value"] = value; - auto node = host->createNode( - prevTransition->getTransitionType(), - metaData); - if (!node) - { - node = host->createNode( - "toucan:Dissolve", - metaData); - } - if (node) - { - auto a = _item( - host, - track->transform(time, prev2), - prev2); - node->setInputs({ a, out }); - out = node; - } - } - } - if (auto nextTransition = std::dynamic_pointer_cast(next)) - { - OTIO_NS::TimeRange rangeInParent = nextTransition->transform( - OTIO_NS::TimeRange( - -nextTransition->getInOffset(), - nextTransition->getInOffset() + nextTransition->getOutOffset()), - track); - if (rangeInParent.contains(time) && next2) - { - const double value = - (time - rangeInParent.start_time()).value() / - rangeInParent.duration().value(); - - auto metaData = nextTransition->getMetadata(); - metaData["value"] = value; - auto node = host->createNode( - nextTransition->getTransitionType(), - metaData); - if (!node) - { - node = host->createNode( - "toucan:Dissolve", - metaData); - } - if (node) - { - auto b = _item( - host, - track->transform(time, next2), - next2); - node->setInputs({ out, b }); - out = node; - } - } - } - } - - return out; - } - - std::shared_ptr ImageGraph::_item( - const std::shared_ptr& host, - const OTIO_NS::RationalTime& time, - const std::shared_ptr& item) - { - std::shared_ptr out; - - if (auto clip = std::dynamic_pointer_cast(item)) - { - // Get the media reference. - auto ref = clip->getMediaReference(); - if (auto externalRef = std::dynamic_pointer_cast(ref)) - { - auto i = _loadCache.find(externalRef); - if (i != _loadCache.end()) - { - out = i->second; - } - else - { - const std::filesystem::path path = getMediaPath( - _timeline->getPath().parent_path(), - externalRef->getURL()); - auto read = std::make_shared(path); - out = read; - _loadCache[externalRef] = read; - } - } - else if (auto sequenceRef = std::dynamic_pointer_cast(ref)) - { - const std::filesystem::path path = getMediaPath( - _timeline->getPath().parent_path(), - sequenceRef->getTargetURLBase()); - auto read = std::make_shared( - path, - sequenceRef->getNamePrefix(), - sequenceRef->getNameSuffix(), - sequenceRef->getStartFrame(), - sequenceRef->getFrameStep(), - sequenceRef->getRate(), - sequenceRef->getFrameZeroPadding()); - out = read; - } - else if (auto generatorRef = std::dynamic_pointer_cast(ref)) - { - out = host->createNode( - generatorRef->getGeneratorKind(), - generatorRef->getParameters()); - } - } - else if (auto gap = std::dynamic_pointer_cast(item)) - { - OTIO_NS::AnyDictionary metaData; - metaData["size"] = vecToAny(_imageSize); - out = host->createNode("toucan:Fill", metaData); - } - - // Get the effects. - const auto& effects = item->getEffects(); - if (!effects.empty()) - { - out = _effects(host, effects, out); - } - if (out) - { - const OTIO_NS::RationalTime timeOffset = item->transform( - item->getRange().start_time(), - _timeline->getStack()); - out->setTimeOffset(timeOffset); - } - - return out; - } - - std::shared_ptr ImageGraph::_effects( - const std::shared_ptr& host, - const std::vector >& effects, - const std::shared_ptr& input) - { - std::shared_ptr out = input; - for (const auto& effect : effects) - { - if (auto linearTimeWarp = std::dynamic_pointer_cast(effect)) - { - auto linearTimeWarpNode = std::make_shared( - static_cast(linearTimeWarp->getTimeScalar()), - std::vector >{ out }); - out = linearTimeWarpNode; - } - else - { - if (auto imageEffect = host->createNode( - effect->getEffectName(), - effect->getMetadata(), - { out })) - { - out = imageEffect; - } - } - } - return out; - } -} diff --git a/lib/toucanEdit/ImageGraph.h b/lib/toucanEdit/ImageGraph.h deleted file mode 100644 index adb6445..0000000 --- a/lib/toucanEdit/ImageGraph.h +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include -#include -#include - -#include - -namespace toucan -{ - class Effect; - class IItem; - class IMediaReference; - class Timeline; - class Track; - - //! Image graph options. - struct ImageGraphOptions - { - std::shared_ptr log; - }; - - //! Create image graphs from a timeline. - class ImageGraph : public std::enable_shared_from_this - { - public: - ImageGraph( - const std::shared_ptr&, - const ImageGraphOptions & = ImageGraphOptions()); - - ~ImageGraph(); - - //! Get the timeline image size. - const IMATH_NAMESPACE::V2i& getImageSize() const; - - //! Get an image graph for the given time. - std::shared_ptr exec( - const std::shared_ptr&, - const OTIO_NS::RationalTime&); - - private: - std::shared_ptr _track( - const std::shared_ptr&, - const OTIO_NS::RationalTime&, - const std::shared_ptr&); - - std::shared_ptr _item( - const std::shared_ptr&, - const OTIO_NS::RationalTime&, - const std::shared_ptr&); - - std::shared_ptr _effects( - const std::shared_ptr&, - const std::vector >&, - const std::shared_ptr&); - - std::shared_ptr _timeline; - ImageGraphOptions _options; - IMATH_NAMESPACE::V2i _imageSize = IMATH_NAMESPACE::V2i(0, 0); - std::map, std::shared_ptr > _loadCache; - }; -} diff --git a/lib/toucanEdit/MediaReferences.cpp b/lib/toucanEdit/MediaReferences.cpp deleted file mode 100644 index 59755ca..0000000 --- a/lib/toucanEdit/MediaReferences.cpp +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "MediaReferences.h" - -#include - -namespace toucan -{ - IMediaReference::IMediaReference() - {} - - IMediaReference::~IMediaReference() - {} - - ExternalReference::ExternalReference(const std::string& url) : - _url(url) - {} - - ExternalReference::~ExternalReference() - {} - - const std::string& ExternalReference::getURL() const - { - return _url; - } - - void ExternalReference::setURL(const std::string& url) - { - _url = url; - } - - ImageSequenceReference::ImageSequenceReference( - const std::string& targetURLBase, - const std::string& namePrefix, - const std::string& nameSuffix, - int startFrame, - int frameStep, - double rate, - int frameZeroPadding) : - _targetURLBase(targetURLBase), - _namePrefix(namePrefix), - _nameSuffix(nameSuffix), - _startFrame(startFrame), - _frameStep(frameStep), - _rate(rate), - _frameZeroPadding(frameZeroPadding) - {} - - ImageSequenceReference::~ImageSequenceReference() - {} - - const std::string& ImageSequenceReference::getTargetURLBase() const - { - return _targetURLBase; - } - - void ImageSequenceReference::setTargetURLBase(const std::string& value) - { - _targetURLBase = value; - } - - const std::string& ImageSequenceReference::getNamePrefix() const - { - return _namePrefix; - } - - void ImageSequenceReference::setNamePrefix(const std::string& value) - { - _namePrefix = value; - } - - const std::string& ImageSequenceReference::getNameSuffix() const - { - return _nameSuffix; - } - - void ImageSequenceReference::setNameSuffix(const std::string& value) - { - _nameSuffix = value; - } - - int ImageSequenceReference::getStartFrame() const - { - return _startFrame; - } - - void ImageSequenceReference::setStartFrame(int value) - { - _startFrame = value; - } - - int ImageSequenceReference::getFrameStep() const - { - return _frameStep; - } - - void ImageSequenceReference::setFrameStep(int value) - { - _frameStep = value; - } - - double ImageSequenceReference::getRate() const - { - return _rate; - } - - void ImageSequenceReference::setRate(double value) - { - _rate = value; - } - - int ImageSequenceReference::getFrameZeroPadding() const - { - return _frameZeroPadding; - } - - void ImageSequenceReference::setFrameZeroPadding(int value) - { - _frameZeroPadding = value; - } - - GeneratorReference::GeneratorReference( - const std::string& generatorKind, - const OTIO_NS::AnyDictionary& parameters) : - _generatorKind(generatorKind), - _parameters(parameters) - {} - - GeneratorReference::~GeneratorReference() - {} - - const std::string& GeneratorReference::getGeneratorKind() const - { - return _generatorKind; - } - - void GeneratorReference::setGeneratorKind(const std::string& value) - { - _generatorKind = value; - } - - const OTIO_NS::AnyDictionary& GeneratorReference::getParameters() const - { - return _parameters; - } - - void GeneratorReference::setParameters(const OTIO_NS::AnyDictionary& value) - { - _parameters = value; - } - - std::filesystem::path getMediaPath( - const std::filesystem::path& timelinePath, - const std::string& url) - { - std::filesystem::path path = splitURLProtocol(url).second; - if (!path.is_absolute()) - { - path = timelinePath / path; - } - return path; - } -} diff --git a/lib/toucanEdit/MediaReferences.h b/lib/toucanEdit/MediaReferences.h deleted file mode 100644 index 6f855c8..0000000 --- a/lib/toucanEdit/MediaReferences.h +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include -#include -#include - -namespace toucan -{ - class IMediaReference : public std::enable_shared_from_this - { - public: - IMediaReference(); - - virtual ~IMediaReference() = 0; - }; - - class ExternalReference : public IMediaReference - { - public: - ExternalReference(const std::string& url = std::string()); - - ~ExternalReference(); - - const std::string& getURL() const; - void setURL(const std::string&); - - private: - std::string _url; - }; - - class ImageSequenceReference : public IMediaReference - { - public: - ImageSequenceReference( - const std::string& targetURLBase = std::string(), - const std::string& namePrefix = std::string(), - const std::string& nameSuffix = std::string(), - int startFrame = 1, - int frameStep = 1, - double rate = 1.0, - int frameZeroPadding = 0); - - ~ImageSequenceReference(); - - const std::string& getTargetURLBase() const; - void setTargetURLBase(const std::string&); - - const std::string& getNamePrefix() const; - void setNamePrefix(const std::string&); - - const std::string& getNameSuffix() const; - void setNameSuffix(const std::string&); - - int getStartFrame() const; - void setStartFrame(int); - - int getFrameStep() const; - void setFrameStep(int); - - double getRate() const; - void setRate(double); - - int getFrameZeroPadding() const; - void setFrameZeroPadding(int); - - private: - std::string _targetURLBase; - std::string _namePrefix; - std::string _nameSuffix; - int _startFrame = 1; - int _frameStep = 1; - double _rate = 1.0; - int _frameZeroPadding = 0; - }; - - class GeneratorReference : public IMediaReference - { - public: - GeneratorReference( - const std::string& generatorKind, - const OTIO_NS::AnyDictionary& parameters); - - ~GeneratorReference(); - - const std::string& getGeneratorKind() const; - void setGeneratorKind(const std::string&); - - const OTIO_NS::AnyDictionary& getParameters() const; - void setParameters(const OTIO_NS::AnyDictionary&); - - private: - std::string _generatorKind; - OTIO_NS::AnyDictionary _parameters; - }; - - std::filesystem::path getMediaPath( - const std::filesystem::path& timelinePath, - const std::string& url); -} - diff --git a/lib/toucanEdit/MenuBar.cpp b/lib/toucanEdit/MenuBar.cpp deleted file mode 100644 index 103512d..0000000 --- a/lib/toucanEdit/MenuBar.cpp +++ /dev/null @@ -1,684 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "MenuBar.h" - -#include "App.h" -#include "DocumentsModel.h" -#include "SelectionModel.h" -#include "ViewModel.h" -#include "Window.h" - -#include -#include -#include -#include - -namespace toucan -{ - void MenuBar::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& window, - const std::shared_ptr& parent) - { - dtk::MenuBar::_init(context, parent); - - _app = app; - _documentsModel = app->getDocumentsModel(); - - _fileMenuInit(context, app); - _editMenuInit(context, app); - _timeMenuInit(context, app); - _playbackMenuInit(context, app); - _viewMenuInit(context, app); - _windowMenuInit(context, app, window); - - _documentObserver = dtk::ValueObserver >::create( - _documentsModel->observeCurrent(), - [this](const std::shared_ptr& document) - { - _document = document; - _fileMenuUpdate(); - _editMenuUpdate(); - _timeMenuUpdate(); - _playbackMenuUpdate(); - _viewMenuUpdate(); - _windowMenuUpdate(); - }); - } - - MenuBar::~MenuBar() - {} - - std::shared_ptr MenuBar::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 MenuBar); - out->_init(context, app, window, parent); - return out; - } - - const std::map >& MenuBar::getActions() const - { - return _actions; - } - - void MenuBar::_fileMenuInit( - const std::shared_ptr& context, - const std::shared_ptr& app) - { - _menus["File"] = dtk::Menu::create(context); - addMenu("File", _menus["File"]); - - auto appWeak = std::weak_ptr(app); - _actions["File/Open"] = std::make_shared( - "Open", - "FileOpen", - dtk::Key::O, - static_cast(dtk::KeyModifier::Control), - [this] - { - if (auto context = _getContext().lock()) - { - if (auto fileBrowserSystem = context->getSystem()) - { - if (_document) - { - fileBrowserSystem->setPath(_document->getPath().parent_path()); - } - dtk::FileBrowserOptions options; - options.extensions.push_back(".otio"); - fileBrowserSystem->setOptions(options); - fileBrowserSystem->open( - getWindow(), - [this](const std::filesystem::path& path) - { - if (auto context = _getContext().lock()) - { - try - { - _documentsModel->open(path); - } - catch (const std::exception& e) - { - context->getSystem()->message("ERROR", e.what(), getWindow()); - } - } - }); - } - } - }); - _actions["File/Open"]->toolTip = "Open a file"; - _menus["File"]->addItem(_actions["File/Open"]); - - _actions["File/Close"] = std::make_shared( - "Close", - "FileClose", - dtk::Key::E, - static_cast(dtk::KeyModifier::Control), - [this] { _documentsModel->close(); }); - _actions["File/Close"]->toolTip = "Close the current file"; - _menus["File"]->addItem(_actions["File/Close"]); - - _actions["File/CloseAll"] = std::make_shared( - "Close All", - "FileCloseAll", - dtk::Key::E, - static_cast(dtk::KeyModifier::Shift) | static_cast(dtk::KeyModifier::Control), - [this] { _documentsModel->closeAll(); }); - _actions["File/CloseAll"]->toolTip = "Close all files"; - _menus["File"]->addItem(_actions["File/CloseAll"]); - - _menus["File"]->addDivider(); - - _menus["Files"] = _menus["File"]->addSubMenu("Files"); - - _actions["File/Next"] = std::make_shared( - "Next", - dtk::Key::PageUp, - 0, - [this] { _documentsModel->next(); }); - _actions["File/Next"]->toolTip = "Switch to the next file"; - _menus["File"]->addItem(_actions["File/Next"]); - - _actions["File/Prev"] = std::make_shared( - "Previous", - dtk::Key::PageDown, - 0, - [this] { _documentsModel->prev(); }); - _actions["File/Prev"]->toolTip = "Switch to the previous file"; - _menus["File"]->addItem(_actions["File/Prev"]); - - _menus["File"]->addDivider(); - - _actions["File/Exit"] = std::make_shared( - "Exit", - dtk::Key::Q, - static_cast(dtk::KeyModifier::Control), - [appWeak] - { - if (auto app = appWeak.lock()) - { - app->exit(); - } - }); - _menus["File"]->addItem(_actions["File/Exit"]); - - _documentsObserver = dtk::ListObserver >::create( - _documentsModel->observeDocuments(), - [this](const std::vector >& documents) - { - _menus["Files"]->clear(); - _filesActions.clear(); - for (int i = 0; i < documents.size(); ++i) - { - auto item = std::make_shared( - documents[i]->getPath().filename().string(), - [this, i] - { - _documentsModel->setCurrentIndex(i); - }); - _menus["Files"]->addItem(item); - _filesActions.push_back(item); - } - }); - - _documentIndexObserver = dtk::ValueObserver::create( - _documentsModel->observeCurrentIndex(), - [this](int index) - { - for (int i = 0; i < _filesActions.size(); ++i) - { - _menus["Files"]->setItemChecked(_filesActions[i], i == index); - } - }); - } - - void MenuBar::_editMenuInit( - const std::shared_ptr& context, - const std::shared_ptr& app) - { - _menus["Edit"] = dtk::Menu::create(context); - addMenu("Edit", _menus["Edit"]); - - _actions["Edit/SelectAll"] = std::make_shared( - "Select All", - dtk::Key::A, - static_cast(dtk::KeyModifier::Control), - [this] - { - if (_document) - { - _document->getSelectionModel()->selectAll(_document->getTimeline()); - } - }); - _menus["Edit"]->addItem(_actions["Edit/SelectAll"]); - - _actions["Edit/SelectNone"] = std::make_shared( - "Select None", - dtk::Key::A, - static_cast(dtk::KeyModifier::Shift) | - static_cast(dtk::KeyModifier::Control), - [this] - { - if (_document) - { - _document->getSelectionModel()->clearSelection(); - } - }); - _menus["Edit"]->addItem(_actions["Edit/SelectNone"]); - - _actions["Edit/SelectInvert"] = std::make_shared( - "Invert Selection", - dtk::Key::I, - static_cast(dtk::KeyModifier::Control), - [this] - { - if (_document) - { - _document->getSelectionModel()->invertSelection(_document->getTimeline()); - } - }); - _menus["Edit"]->addItem(_actions["Edit/SelectInvert"]); - } - - void MenuBar::_timeMenuInit( - const std::shared_ptr& context, - const std::shared_ptr& app) - { - _menus["Time"] = dtk::Menu::create(context); - addMenu("Time", _menus["Time"]); - - _actions["Time/Start"] = std::make_shared( - "Start Frame", - "FrameStart", - dtk::Key::Up, - 0, - [this] - { - if (_document) - { - _document->getPlaybackModel()->frameAction(FrameAction::Start); - } - }); - _menus["Time"]->addItem(_actions["Time/Start"]); - - _actions["Time/Prev"] = std::make_shared( - "Previous Frame", - "FramePrev", - dtk::Key::Left, - 0, - [this] - { - if (_document) - { - _document->getPlaybackModel()->frameAction(FrameAction::Prev); - } - }); - _menus["Time"]->addItem(_actions["Time/Prev"]); - - _actions["Time/Next"] = std::make_shared( - "Next Frame", - "FrameNext", - dtk::Key::Right, - 0, - [this] - { - if (_document) - { - _document->getPlaybackModel()->frameAction(FrameAction::Next); - } - }); - _menus["Time"]->addItem(_actions["Time/Next"]); - - _actions["Time/End"] = std::make_shared( - "End Frame", - "FrameEnd", - dtk::Key::Down, - 0, - [this] - { - if (_document) - { - _document->getPlaybackModel()->frameAction(FrameAction::End); - } - }); - _menus["Time"]->addItem(_actions["Time/End"]); - - _menus["Time"]->addDivider(); - - _menus["TimeUnits"] = _menus["Time"]->addSubMenu("Time Units"); - - _actions["TimeUnits/Timecode"] = std::make_shared( - "Timecode", - [this](bool value) - { - if (auto app = _app.lock()) - { - app->getTimeUnitsModel()->setTimeUnits(TimeUnits::Timecode); - } - }); - _menus["TimeUnits"]->addItem(_actions["TimeUnits/Timecode"]); - - _actions["TimeUnits/Frames"] = std::make_shared( - "Frames", - [this](bool value) - { - if (auto app = _app.lock()) - { - app->getTimeUnitsModel()->setTimeUnits(TimeUnits::Frames); - } - }); - _menus["TimeUnits"]->addItem(_actions["TimeUnits/Frames"]); - - _actions["TimeUnits/Seconds"] = std::make_shared( - "Seconds", - [this](bool value) - { - if (auto app = _app.lock()) - { - app->getTimeUnitsModel()->setTimeUnits(TimeUnits::Seconds); - } - }); - _menus["TimeUnits"]->addItem(_actions["TimeUnits/Seconds"]); - - _timeUnitsObserver = dtk::ValueObserver::create( - app->getTimeUnitsModel()->observeTimeUnits(), - [this](TimeUnits value) - { - _menus["TimeUnits"]->setItemChecked(_actions["TimeUnits/Timecode"], TimeUnits::Timecode == value); - _menus["TimeUnits"]->setItemChecked(_actions["TimeUnits/Frames"], TimeUnits::Frames == value); - _menus["TimeUnits"]->setItemChecked(_actions["TimeUnits/Seconds"], TimeUnits::Seconds == value); - }); - } - - void MenuBar::_playbackMenuInit( - const std::shared_ptr& context, - const std::shared_ptr& app) - { - _menus["Playback"] = dtk::Menu::create(context); - addMenu("Playback", _menus["Playback"]); - - _actions["Playback/Stop"] = std::make_shared( - "Stop", - "PlaybackStop", - dtk::Key::K, - 0, - [this] - { - if (_document) - { - _document->getPlaybackModel()->setPlayback(Playback::Stop); - } - }); - _menus["Playback"]->addItem(_actions["Playback/Stop"]); - - _actions["Playback/Forward"] = std::make_shared( - "Forward", - "PlaybackForward", - dtk::Key::L, - 0, - [this] - { - if (_document) - { - _document->getPlaybackModel()->setPlayback(Playback::Forward); - } - }); - _menus["Playback"]->addItem(_actions["Playback/Forward"]); - - _actions["Playback/Reverse"] = std::make_shared( - "Reverse", - "PlaybackReverse", - dtk::Key::J, - 0, - [this] - { - if (_document) - { - _document->getPlaybackModel()->setPlayback(Playback::Reverse); - } - }); - _menus["Playback"]->addItem(_actions["Playback/Reverse"]); - - _menus["Playback"]->addDivider(); - - _actions["Playback/Toggle"] = std::make_shared( - "Toggle Playback", - dtk::Key::Space, - 0, - [this] - { - if (_document) - { - _document->getPlaybackModel()->togglePlayback(); - } - }); - _menus["Playback"]->addItem(_actions["Playback/Toggle"]); - } - - void MenuBar::_viewMenuInit( - const std::shared_ptr& context, - const std::shared_ptr& app) - { - _menus["View"] = dtk::Menu::create(context); - addMenu("View", _menus["View"]); - - _actions["View/ZoomIn"] = std::make_shared( - "Zoom In", - dtk::Key::Equal, - 0, - [this] - { - if (_document) - { - _document->getViewModel()->zoomIn(); - } - }); - _menus["View"]->addItem(_actions["View/ZoomIn"]); - - _actions["View/ZoomOut"] = std::make_shared( - "Zoom Out", - dtk::Key::Minus, - 0, - [this] - { - if (_document) - { - _document->getViewModel()->zoomOut(); - } - }); - _menus["View"]->addItem(_actions["View/ZoomOut"]); - - _actions["View/ZoomReset"] = std::make_shared( - "Zoom Reset", - dtk::Key::_0, - 0, - [this] - { - if (_document) - { - _document->getViewModel()->zoomReset(); - } - }); - _menus["View"]->addItem(_actions["View/ZoomReset"]); - - _menus["View"]->addDivider(); - - _actions["View/FrameView"] = std::make_shared( - "Frame View", - dtk::Key::Backspace, - 0, - [this](bool value) - { - if (_document) - { - _document->getViewModel()->setFrame(value); - } - }); - _menus["View"]->addItem(_actions["View/FrameView"]); - } - - void MenuBar::_windowMenuInit( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& window) - { - _menus["Window"] = dtk::Menu::create(context); - addMenu("Window", _menus["Window"]); - - std::weak_ptr windowWeak(window); - _actions["Window/FullScreen"] = std::make_shared( - "Full Screen", - "WindowFullScreen", - dtk::Key::U, - static_cast(dtk::KeyModifier::Control), - [windowWeak](bool value) - { - if (auto window = windowWeak.lock()) - { - window->setFullScreen(value); - } - }); - _actions["Window/FullScreen"]->toolTip = "Toggle full screen mode"; - _menus["Window"]->addItem(_actions["Window/FullScreen"]); - - _menus["Window"]->addDivider(); - - _menus["Window/Resize"] = _menus["Window"]->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"] = _menus["Window"]->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/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/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"]); - - _fullScreenObserver = dtk::ValueObserver::create( - window->observeFullScreen(), - [this](bool value) - { - _menus["Window"]->setItemChecked(_actions["Window/FullScreen"], value); - }); - - _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/2.0"], 2.F == value); - _menus["Window/DisplayScale"]->setItemChecked(_actions["Window/DisplayScale/3.0"], 3.F == value); - }); - } - - void MenuBar::_fileMenuUpdate() - { - _menus["File"]->setItemEnabled(_actions["File/Close"], _document.get()); - _menus["File"]->setItemEnabled(_actions["File/CloseAll"], _document.get()); - _menus["File"]->setSubMenuEnabled(_menus["Files"], _document.get()); - _menus["File"]->setItemEnabled(_actions["File/Next"], _filesActions.size() > 1); - _menus["File"]->setItemEnabled(_actions["File/Prev"], _filesActions.size() > 1); - } - - void MenuBar::_editMenuUpdate() - { - _menus["Edit"]->setItemEnabled(_actions["Edit/SelectAll"], _document.get()); - _menus["Edit"]->setItemEnabled(_actions["Edit/SelectNone"], _document.get()); - _menus["Edit"]->setItemEnabled(_actions["Edit/SelectInvert"], _document.get()); - } - - void MenuBar::_timeMenuUpdate() - { - _menus["Time"]->setItemEnabled(_actions["Time/Start"], _document.get()); - _menus["Time"]->setItemEnabled(_actions["Time/Prev"], _document.get()); - _menus["Time"]->setItemEnabled(_actions["Time/Next"], _document.get()); - _menus["Time"]->setItemEnabled(_actions["Time/End"], _document.get()); - } - - void MenuBar::_playbackMenuUpdate() - { - if (_document) - { - _playbackObserver = dtk::ValueObserver::create( - _document->getPlaybackModel()->observePlayback(), - [this](Playback value) - { - _menus["Playback"]->setItemChecked(_actions["Playback/Stop"], Playback::Stop == value); - _menus["Playback"]->setItemChecked(_actions["Playback/Forward"], Playback::Forward == value); - _menus["Playback"]->setItemChecked(_actions["Playback/Reverse"], Playback::Reverse == value); - }); - } - else - { - _playbackObserver.reset(); - } - - _menus["Playback"]->setItemEnabled(_actions["Playback/Stop"], _document.get()); - _menus["Playback"]->setItemEnabled(_actions["Playback/Forward"], _document.get()); - _menus["Playback"]->setItemEnabled(_actions["Playback/Reverse"], _document.get()); - _menus["Playback"]->setItemEnabled(_actions["Playback/Toggle"], _document.get()); - } - - void MenuBar::_viewMenuUpdate() - { - if (_document) - { - _frameViewObserver = dtk::ValueObserver::create( - _document->getViewModel()->observeFrame(), - [this](bool value) - { - _menus["View"]->setItemChecked(_actions["View/FrameView"], value); - }); - } - else - { - _frameViewObserver.reset(); - } - - _menus["View"]->setItemEnabled(_actions["View/ZoomIn"], _document.get()); - _menus["View"]->setItemEnabled(_actions["View/ZoomOut"], _document.get()); - _menus["View"]->setItemEnabled(_actions["View/ZoomReset"], _document.get()); - _menus["View"]->setItemEnabled(_actions["View/FrameView"], _document.get()); - } - - void MenuBar::_windowMenuUpdate() - { - } -} diff --git a/lib/toucanEdit/MenuBar.h b/lib/toucanEdit/MenuBar.h deleted file mode 100644 index 5ee2a46..0000000 --- a/lib/toucanEdit/MenuBar.h +++ /dev/null @@ -1,85 +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 Document; - class DocumentsModel; - class Window; - - class MenuBar : public dtk::MenuBar - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~MenuBar(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - const std::map >& getActions() const; - - private: - void _fileMenuInit( - const std::shared_ptr&, - const std::shared_ptr&); - void _editMenuInit( - const std::shared_ptr&, - const std::shared_ptr&); - void _timeMenuInit( - const std::shared_ptr&, - const std::shared_ptr&); - void _playbackMenuInit( - const std::shared_ptr&, - const std::shared_ptr&); - void _viewMenuInit( - const std::shared_ptr&, - const std::shared_ptr&); - void _windowMenuInit( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&); - - void _fileMenuUpdate(); - void _editMenuUpdate(); - void _timeMenuUpdate(); - void _playbackMenuUpdate(); - void _viewMenuUpdate(); - void _windowMenuUpdate(); - - std::weak_ptr _app; - std::shared_ptr _documentsModel; - std::shared_ptr _document; - - std::map > _menus; - std::map > _actions; - std::vector > _filesActions; - - std::shared_ptr > > _documentsObserver; - std::shared_ptr > > _documentObserver; - std::shared_ptr > _documentIndexObserver; - std::shared_ptr > _playbackObserver; - std::shared_ptr > _frameViewObserver; - std::shared_ptr > _fullScreenObserver; - std::shared_ptr > _displayScaleObserver; - std::shared_ptr > _timeUnitsObserver; - }; -} - diff --git a/lib/toucanEdit/PlaybackModel.cpp b/lib/toucanEdit/PlaybackModel.cpp deleted file mode 100644 index 3cc35e3..0000000 --- a/lib/toucanEdit/PlaybackModel.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "PlaybackModel.h" - -namespace toucan -{ - PlaybackModel::PlaybackModel(const std::shared_ptr& context) - { - _timeRange = dtk::ObservableValue::create(); - _currentTime = dtk::ObservableValue::create(OTIO_NS::RationalTime(-1.0, -1.0)); - _playback = dtk::ObservableValue::create(Playback::Stop); - _timer = dtk::Timer::create(context); - _timer->setRepeating(true); - } - - PlaybackModel::~PlaybackModel() - {} - - const OTIO_NS::TimeRange& PlaybackModel::getTimeRange() const - { - return _timeRange->get(); - } - - std::shared_ptr > PlaybackModel::observeTimeRange() const - { - return _timeRange; - } - - void PlaybackModel::setTimeRange(const OTIO_NS::TimeRange& value) - { - if (_timeRange->setIfChanged(value)) - { - _currentTime->setIfChanged(value.start_time()); - } - } - - const OTIO_NS::RationalTime& PlaybackModel::getCurrentTime() const - { - return _currentTime->get(); - } - - std::shared_ptr > PlaybackModel::observeCurrentTime() const - { - return _currentTime; - } - - void PlaybackModel::setCurrentTime(const OTIO_NS::RationalTime& value) - { - OTIO_NS::RationalTime time = value; - if (!time.is_invalid_time()) - { - const OTIO_NS::TimeRange& range = _timeRange->get(); - if (time > range.end_time_inclusive()) - { - time = range.start_time(); - } - else if (time < range.start_time()) - { - time = range.end_time_inclusive(); - } - } - if (time != _currentTime->get()) - { - _playback->setIfChanged(Playback::Stop); - _currentTime->setIfChanged(time); - } - } - - void PlaybackModel::frameAction(FrameAction value) - { - const OTIO_NS::TimeRange& timeRange = _timeRange->get(); - const OTIO_NS::RationalTime& time = _currentTime->get(); - switch (value) - { - case FrameAction::Start: - setCurrentTime(timeRange.start_time()); - break; - case FrameAction::Prev: - setCurrentTime(time - OTIO_NS::RationalTime(1.0, time.rate())); - break; - case FrameAction::Next: - setCurrentTime(time + OTIO_NS::RationalTime(1.0, time.rate())); - break; - case FrameAction::End: - setCurrentTime(timeRange.end_time_inclusive()); - break; - default: break; - } - } - - Playback PlaybackModel::getPlayback() const - { - return _playback->get(); - } - - std::shared_ptr > PlaybackModel::observePlayback() const - { - return _playback; - } - - void PlaybackModel::setPlayback(Playback value) - { - const Playback prev = _playback->get(); - if (_playback->setIfChanged(value)) - { - switch (value) - { - case Playback::Stop: - _timer->stop(); - _playbackPrev = prev; - break; - case Playback::Forward: - case Playback::Reverse: - _timer->start( - std::chrono::microseconds(static_cast(1000 / _currentTime->get().rate())), - [this] - { - _timeUpdate(); - }); - break; - default: break; - } - } - } - - void PlaybackModel::togglePlayback() - { - setPlayback( - Playback::Stop == _playback->get() ? - _playbackPrev : - Playback::Stop); - } - - void PlaybackModel::_timeUpdate() - { - switch (_playback->get()) - { - case Playback::Forward: - { - auto time = _currentTime->get() + OTIO_NS::RationalTime(1.0, _currentTime->get().rate()); - if (time > _timeRange->get().end_time_inclusive()) - { - time = _timeRange->get().start_time(); - } - _currentTime->setIfChanged(time); - break; - } - case Playback::Reverse: - { - auto time = _currentTime->get() - OTIO_NS::RationalTime(1.0, _currentTime->get().rate()); - if (time < _timeRange->get().start_time()) - { - time = _timeRange->get().end_time_inclusive(); - } - _currentTime->setIfChanged(time); - break; - } - default: break; - } - } -} diff --git a/lib/toucanEdit/PlaybackModel.h b/lib/toucanEdit/PlaybackModel.h deleted file mode 100644 index c138d69..0000000 --- a/lib/toucanEdit/PlaybackModel.h +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include -#include - -#include - -namespace toucan -{ - enum FrameAction - { - Start, - Prev, - Next, - End - }; - - enum class Playback - { - Stop, - Forward, - Reverse - }; - - class PlaybackModel : public std::enable_shared_from_this - { - public: - PlaybackModel(const std::shared_ptr&); - - virtual ~PlaybackModel(); - - const OTIO_NS::TimeRange& getTimeRange() const; - std::shared_ptr > observeTimeRange() const; - void setTimeRange(const OTIO_NS::TimeRange&); - - const OTIO_NS::RationalTime& getCurrentTime() const; - std::shared_ptr > observeCurrentTime() const; - void setCurrentTime(const OTIO_NS::RationalTime&); - - void frameAction(FrameAction); - - Playback getPlayback() const; - std::shared_ptr > observePlayback() const; - void setPlayback(Playback); - void togglePlayback(); - - private: - void _timeUpdate(); - - std::shared_ptr > _timeRange; - std::shared_ptr > _currentTime; - std::shared_ptr > _playback; - Playback _playbackPrev = Playback::Forward; - std::shared_ptr _timer; - }; -} diff --git a/lib/toucanEdit/SelectionModel.cpp b/lib/toucanEdit/SelectionModel.cpp deleted file mode 100644 index 1d83a49..0000000 --- a/lib/toucanEdit/SelectionModel.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "SelectionModel.h" - -#include "Timeline.h" - -#include - -namespace toucan -{ - SelectionModel::SelectionModel() - { - _selection = dtk::ObservableList >::create(); - } - - SelectionModel::~SelectionModel() - {} - - const std::vector >& SelectionModel::getSelection() const - { - return _selection->get(); - } - - std::shared_ptr > > SelectionModel::observeSelection() const - { - return _selection; - } - - void SelectionModel::setSelection(const std::vector >& selection) - { - std::set > set; - set.insert(selection.begin(), selection.end()); - std::vector > tmp; - tmp.insert(tmp.end(), set.begin(), set.end()); - _selection->setIfChanged(tmp); - } - - void SelectionModel::selectAll(const std::shared_ptr& timeline) - { - std::vector > items; - //for (auto& item : timeline->find_children()) - //{ - // items.push_back(item); - //} - _selection->setIfChanged(items); - } - - void SelectionModel::clearSelection() - { - _selection->setIfChanged({}); - } - - void SelectionModel::invertSelection(const std::shared_ptr& timeline) - { - std::vector > items; - //for (auto& item : timeline->find_children()) - //{ - // items.push_back(item); - //} - const auto& selection = _selection->get(); - auto i = items.begin(); - while (i != items.end()) - { - auto j = std::find(selection.begin(), selection.end(), *i); - if (j != selection.end()) - { - i = items.erase(i); - } - else - { - ++i; - } - } - _selection->setIfChanged(items); - } -} diff --git a/lib/toucanEdit/SelectionModel.h b/lib/toucanEdit/SelectionModel.h deleted file mode 100644 index 67564aa..0000000 --- a/lib/toucanEdit/SelectionModel.h +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - class IItem; - class Timeline; - - class SelectionModel : public std::enable_shared_from_this - { - public: - SelectionModel(); - - virtual ~SelectionModel(); - - const std::vector >& getSelection() const; - std::shared_ptr > > observeSelection() const; - void setSelection(const std::vector >&); - - void selectAll(const std::shared_ptr&); - void clearSelection(); - void invertSelection(const std::shared_ptr&); - - private: - std::shared_ptr > > _selection; - }; -} diff --git a/lib/toucanEdit/Stack.cpp b/lib/toucanEdit/Stack.cpp deleted file mode 100644 index 5df9b1c..0000000 --- a/lib/toucanEdit/Stack.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Stack.h" - -#include - -namespace toucan -{ - Stack::Stack( - const std::string& name, - const OTIO_NS::TimeRange& range, - const OTIO_NS::AnyDictionary& metadata) : - IContainer(name, range, metadata) - {} - - Stack::~Stack() - {} - - OTIO_NS::TimeRange Stack::getChildRange(const std::shared_ptr& item) - { - OTIO_NS::TimeRange out; - const auto& children = getChildren(); - auto i = std::find(children.begin(), children.end(), item); - if (i != children.end()) - { - out = OTIO_NS::TimeRange( - getRange().start_time(), - (*i)->getRange().duration()); - } - return out; - } -} diff --git a/lib/toucanEdit/Stack.h b/lib/toucanEdit/Stack.h deleted file mode 100644 index cd7cb21..0000000 --- a/lib/toucanEdit/Stack.h +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - class Stack : public IContainer - { - public: - Stack( - const std::string& name = std::string(), - const OTIO_NS::TimeRange& range = OTIO_NS::TimeRange(), - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary()); - - virtual ~Stack(); - - OTIO_NS::TimeRange getChildRange(const std::shared_ptr&) override; - }; -} - diff --git a/lib/toucanEdit/StackWidget.cpp b/lib/toucanEdit/StackWidget.cpp deleted file mode 100644 index 76892ed..0000000 --- a/lib/toucanEdit/StackWidget.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "StackWidget.h" - -#include "Stack.h" - -#include -#include - -namespace toucan -{ - void StackWidget::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& stack, - const std::shared_ptr& parent) - { - IItemWidget::_init( - context, - app, - stack, - stack->getRange(), - "toucan::StackWidget", - parent); - - _stack = stack; - _text = stack->getName(); - if (_text.empty()) - { - _text = "Stack"; - } - _color = dtk::Color4F(.2F, .2F, .2F); - - setTooltip(_text); - } - - StackWidget::~StackWidget() - {} - - std::shared_ptr StackWidget::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& stack, - const std::shared_ptr& parent) - { - auto out = std::make_shared(); - out->_init(context, app, stack, parent); - return out; - } - - void StackWidget::setGeometry(const dtk::Box2I& value) - { - IItemWidget::setGeometry(value); - const dtk::Box2I& g = getGeometry(); - dtk::V2I pos = g.min; - pos.y += _size.fontMetrics.lineHeight + _size.margin * 2 + _size.border * 2; - for (const auto& child : getChildren()) - { - const dtk::Size2I& sizeHint = child->getSizeHint(); - child->setGeometry(dtk::Box2I(pos.x, pos.y, sizeHint.w, sizeHint.h)); - pos.y += sizeHint.h; - } - } - - void StackWidget::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IItemWidget::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.fontInfo = event.style->getFontRole(dtk::FontRole::Label, event.displayScale); - _size.fontMetrics = event.fontSystem->getMetrics(_size.fontInfo); - _size.textSize = event.fontSystem->getSize(_text, _size.fontInfo); - _draw.glyphs.clear(); - } - dtk::Size2I sizeHint( - _timeRange.duration().rescaled_to(1.0).value() * _scale, - 0); - const auto& children = getChildren(); - for (const auto& child : children) - { - const dtk::Size2I& childSizeHint = child->getSizeHint(); - sizeHint.h += childSizeHint.h; - } - sizeHint.h += _size.textSize.h + _size.margin * 2 + _size.border * 4; - _setSizeHint(sizeHint); - } - - void StackWidget::clipEvent(const dtk::Box2I& clipRect, bool clipped) - { - IItemWidget::clipEvent(clipRect, clipped); - if (clipped) - { - _draw.glyphs.clear(); - } - } - - void StackWidget::drawEvent( - const dtk::Box2I& drawRect, - const dtk::DrawEvent& event) - { - IItemWidget::drawEvent(drawRect, event); - const dtk::Box2I& g = getGeometry(); - - const dtk::Box2I g2( - g.min.x + _size.border, - g.min.y, - g.w() - _size.border * 2, - _size.fontMetrics.lineHeight + _size.margin * 2); - event.render->drawRect( - g2, - _selected ? event.style->getColorRole(dtk::ColorRole::Yellow) : _color); - - const dtk::Box2I g3 = dtk::margin(g2, -_size.margin); - if (!_text.empty() && _draw.glyphs.empty()) - { - _draw.glyphs = event.fontSystem->getGlyphs(_text, _size.fontInfo); - } - dtk::ClipRectEnabledState clipRectEnabledState(event.render); - dtk::ClipRectState clipRectState(event.render); - event.render->setClipRectEnabled(true); - event.render->setClipRect(intersect(g3, drawRect)); - event.render->drawText( - _draw.glyphs, - _size.fontMetrics, - g3.min, - event.style->getColorRole(dtk::ColorRole::Text)); - } -} diff --git a/lib/toucanEdit/StackWidget.h b/lib/toucanEdit/StackWidget.h deleted file mode 100644 index e3cf104..0000000 --- a/lib/toucanEdit/StackWidget.h +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - class Stack; - - class StackWidget : public IItemWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~StackWidget(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - void clipEvent(const dtk::Box2I&, bool) override; - void drawEvent(const dtk::Box2I&, const dtk::DrawEvent&) override; - - private: - std::shared_ptr _stack; - std::string _text; - dtk::Color4F _color; - - struct SizeData - { - bool init = true; - float displayScale = 0.F; - int margin = 0; - int border = 0; - dtk::FontInfo fontInfo; - dtk::FontMetrics fontMetrics; - dtk::Size2I textSize; - }; - SizeData _size; - - struct DrawData - { - std::vector > glyphs; - }; - DrawData _draw; - }; -} diff --git a/lib/toucanEdit/ThumbnailGenerator.cpp b/lib/toucanEdit/ThumbnailGenerator.cpp deleted file mode 100644 index b3cf7ec..0000000 --- a/lib/toucanEdit/ThumbnailGenerator.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "ThumbnailGenerator.h" - -#include "ImageGraph.h" -#include "Timeline.h" - -#include - -#include - -#include - -namespace toucan -{ - ThumbnailGenerator::ThumbnailGenerator( - const std::shared_ptr& timeline, - const std::shared_ptr& host) : - _timeline(timeline), - _host(host) - { - _graph = std::make_shared(_timeline); - const IMATH_NAMESPACE::V2i& imageSize = _graph->getImageSize(); - _aspect = imageSize.y > 0 ? - (imageSize.x / static_cast(imageSize.y)) : - 0.F; - } - - ThumbnailGenerator::~ThumbnailGenerator() - {} - - float ThumbnailGenerator::getAspect() const - { - return _aspect; - } - - std::future ThumbnailGenerator::getThumbnail( - const OTIO_NS::RationalTime& time, - int height) - { - auto graph = _graph->exec(_host, time); - return std::async( - std::launch::async, - [this, graph, time, height] - { - const auto sourceBuf = graph->exec(time); - const auto& sourceSpec = sourceBuf.spec(); - - const dtk::Size2I thumbnailSize(height * _aspect, height); - dtk::ImageInfo info; - info.size = thumbnailSize; - switch (sourceSpec.nchannels) - { - case 1: - switch (sourceSpec.format.basetype) - { - case OIIO::TypeDesc::UINT8: info.type = dtk::ImageType::L_U8; break; - case OIIO::TypeDesc::UINT16: info.type = dtk::ImageType::L_U16; break; - case OIIO::TypeDesc::HALF: info.type = dtk::ImageType::L_F16; break; - case OIIO::TypeDesc::FLOAT: info.type = dtk::ImageType::L_F32; break; - } - break; - case 2: - switch (sourceSpec.format.basetype) - { - case OIIO::TypeDesc::UINT8: info.type = dtk::ImageType::LA_U8; break; - case OIIO::TypeDesc::UINT16: info.type = dtk::ImageType::LA_U16; break; - case OIIO::TypeDesc::HALF: info.type = dtk::ImageType::LA_F16; break; - case OIIO::TypeDesc::FLOAT: info.type = dtk::ImageType::LA_F32; break; - } - break; - case 3: - switch (sourceSpec.format.basetype) - { - case OIIO::TypeDesc::UINT8: info.type = dtk::ImageType::RGB_U8; break; - case OIIO::TypeDesc::UINT16: info.type = dtk::ImageType::RGB_U16; break; - case OIIO::TypeDesc::HALF: info.type = dtk::ImageType::RGB_F16; break; - case OIIO::TypeDesc::FLOAT: info.type = dtk::ImageType::RGB_F32; break; - } - break; - default: - switch (sourceSpec.format.basetype) - { - case OIIO::TypeDesc::UINT8: info.type = dtk::ImageType::RGBA_U8; break; - case OIIO::TypeDesc::UINT16: info.type = dtk::ImageType::RGBA_U16; break; - case OIIO::TypeDesc::HALF: info.type = dtk::ImageType::RGBA_F16; break; - case OIIO::TypeDesc::FLOAT: info.type = dtk::ImageType::RGBA_F32; break; - } - break; - } - info.layout.mirror.y = true; - - std::shared_ptr thumbnail; - if (info.isValid()) - { - thumbnail = dtk::Image::create(info); - auto resizedBuf = OIIO::ImageBufAlgo::resize( - sourceBuf, - "", - 0.F, - OIIO::ROI( - 0, info.size.w, - 0, info.size.h, - 0, 1, - 0, std::min(4, sourceSpec.nchannels))); - memcpy( - thumbnail->getData(), - resizedBuf.localpixels(), - thumbnail->getByteCount()); - } - return Thumbnail{ time, thumbnail }; - }); - } -} diff --git a/lib/toucanEdit/ThumbnailGenerator.h b/lib/toucanEdit/ThumbnailGenerator.h deleted file mode 100644 index 3505bca..0000000 --- a/lib/toucanEdit/ThumbnailGenerator.h +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -#include - -namespace toucan -{ - class ImageEffectHost; - class ImageGraph; - class Timeline; - - struct Thumbnail - { - OTIO_NS::RationalTime time; - std::shared_ptr image; - }; - - class ThumbnailGenerator : public std::enable_shared_from_this - { - public: - ThumbnailGenerator( - const std::shared_ptr&, - const std::shared_ptr&); - - ~ThumbnailGenerator(); - - float getAspect() const; - - std::future getThumbnail( - const OTIO_NS::RationalTime&, - int height); - - private: - std::shared_ptr _timeline; - std::shared_ptr _host; - std::shared_ptr _graph; - float _aspect = 1.F; - }; -} diff --git a/lib/toucanEdit/TimeUnitsModel.cpp b/lib/toucanEdit/TimeUnitsModel.cpp deleted file mode 100644 index 8c8cac7..0000000 --- a/lib/toucanEdit/TimeUnitsModel.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "TimeUnitsModel.h" - -#include - -namespace toucan -{ - TimeUnitsModel::TimeUnitsModel() - { - _timeUnits = dtk::ObservableValue::create(TimeUnits::Timecode); - } - - TimeUnitsModel::~TimeUnitsModel() - {} - - TimeUnits TimeUnitsModel::getTimeUnits() const - { - return _timeUnits->get(); - } - - std::shared_ptr > TimeUnitsModel::observeTimeUnits() const - { - return _timeUnits; - } - - void TimeUnitsModel::setTimeUnits(TimeUnits value) - { - _timeUnits->setIfChanged(value); - } - - std::string TimeUnitsModel::getLabel(const OTIO_NS::RationalTime& time) const - { - std::string out; - switch (_timeUnits->get()) - { - case TimeUnits::Timecode: out = time.to_timecode(); break; - case TimeUnits::Frames: - { - std::stringstream ss; - ss << time.to_frames(); - out = ss.str(); - break; - } - case TimeUnits::Seconds: - { - std::stringstream ss; - ss.precision(2); - ss << std::fixed << time.to_seconds(); - out = ss.str(); - break; - } - default: break; - } - return out; - } -} diff --git a/lib/toucanEdit/TimeUnitsModel.h b/lib/toucanEdit/TimeUnitsModel.h deleted file mode 100644 index e9be279..0000000 --- a/lib/toucanEdit/TimeUnitsModel.h +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -namespace toucan -{ - enum class TimeUnits - { - Timecode, - Frames, - Seconds - }; - - class TimeUnitsModel : public std::enable_shared_from_this - { - public: - TimeUnitsModel(); - - virtual ~TimeUnitsModel(); - - TimeUnits getTimeUnits() const; - std::shared_ptr > observeTimeUnits() const; - void setTimeUnits(TimeUnits); - - std::string getLabel(const OTIO_NS::RationalTime&) const; - - private: - std::shared_ptr > _timeUnits; - }; -} diff --git a/lib/toucanEdit/TimeWidgets.cpp b/lib/toucanEdit/TimeWidgets.cpp deleted file mode 100644 index 2c36a31..0000000 --- a/lib/toucanEdit/TimeWidgets.cpp +++ /dev/null @@ -1,391 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "TimeWidgets.h" - -#include - -#include - -namespace toucan -{ - void FrameButtons::_init( - const std::shared_ptr& context, - const std::shared_ptr& parent) - { - IWidget::_init(context, "toucan::FrameButtons", parent); - - _layout = dtk::HorizontalLayout::create(context, shared_from_this()); - _layout->setSpacingRole(dtk::SizeRole::SpacingTool); - - auto startButton = dtk::ToolButton::create(context, _layout); - startButton->setIcon("FrameStart"); - startButton->setTooltip("Go to the start frame"); - - auto prevButton = dtk::ToolButton::create(context, _layout); - prevButton->setIcon("FramePrev"); - prevButton->setRepeatClick(true); - prevButton->setTooltip("Go to the previous frame"); - - auto nextButton = dtk::ToolButton::create(context, _layout); - nextButton->setIcon("FrameNext"); - nextButton->setRepeatClick(true); - nextButton->setTooltip("Go to the next frame"); - - auto endButton = dtk::ToolButton::create(context, _layout); - endButton->setIcon("FrameEnd"); - endButton->setTooltip("Go to the end frame"); - - _buttonGroup = dtk::ButtonGroup::create(context, dtk::ButtonGroupType::Click); - _buttonGroup->addButton(startButton); - _buttonGroup->addButton(prevButton); - _buttonGroup->addButton(nextButton); - _buttonGroup->addButton(endButton); - - _buttonGroup->setClickedCallback( - [this](int index) - { - if (_callback) - { - _callback(static_cast(index)); - } - }); - } - - FrameButtons::~FrameButtons() - {} - - std::shared_ptr FrameButtons::create( - const std::shared_ptr& context, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new FrameButtons); - out->_init(context, parent); - return out; - } - - void FrameButtons::setCallback(const std::function& value) - { - _callback = value; - } - - void FrameButtons::setGeometry(const dtk::Box2I& value) - { - IWidget::setGeometry(value); - _layout->setGeometry(value); - } - - void FrameButtons::sizeHintEvent(const dtk::SizeHintEvent& value) - { - IWidget::sizeHintEvent(value); - _setSizeHint(_layout->getSizeHint()); - } - - void PlaybackButtons::_init( - const std::shared_ptr& context, - const std::shared_ptr& parent) - { - IWidget::_init(context, "toucan::PlaybackButtons", parent); - - _layout = dtk::HorizontalLayout::create(context, shared_from_this()); - _layout->setSpacingRole(dtk::SizeRole::SpacingTool); - - auto reverseButton = dtk::ToolButton::create(context, _layout); - reverseButton->setIcon("PlaybackReverse"); - reverseButton->setTooltip("Reverse playback"); - - auto stopButton = dtk::ToolButton::create(context, _layout); - stopButton->setIcon("PlaybackStop"); - stopButton->setTooltip("Stop playback"); - - auto forwardButton = dtk::ToolButton::create(context, _layout); - forwardButton->setIcon("PlaybackForward"); - forwardButton->setTooltip("Forward playback"); - - _buttonGroup = dtk::ButtonGroup::create(context, dtk::ButtonGroupType::Radio); - _buttonGroup->addButton(stopButton); - _buttonGroup->addButton(forwardButton); - _buttonGroup->addButton(reverseButton); - - _playbackUpdate(); - - _buttonGroup->setCheckedCallback( - [this](int index, bool value) - { - if (value) - { - if (_callback) - { - _callback(static_cast(index)); - } - } - }); - } - - PlaybackButtons::~PlaybackButtons() - {} - - std::shared_ptr PlaybackButtons::create( - const std::shared_ptr& context, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new PlaybackButtons); - out->_init(context, parent); - return out; - } - - void PlaybackButtons::setPlayback(Playback value) - { - if (value == _playback) - return; - _playback = value; - _playbackUpdate(); - } - - void PlaybackButtons::setCallback(const std::function& value) - { - _callback = value; - } - - void PlaybackButtons::setGeometry(const dtk::Box2I& value) - { - IWidget::setGeometry(value); - _layout->setGeometry(value); - } - - void PlaybackButtons::sizeHintEvent(const dtk::SizeHintEvent& value) - { - IWidget::sizeHintEvent(value); - _setSizeHint(_layout->getSizeHint()); - } - - void PlaybackButtons::_playbackUpdate() - { - _buttonGroup->setChecked(static_cast(_playback), true); - } - - void TimeEdit::_init( - const std::shared_ptr& context, - const std::shared_ptr& timeUnitsModel, - const std::shared_ptr& parent) - { - IWidget::_init(context, "toucan::TimeEdit", parent); - - _timeUnitsModel = timeUnitsModel; - - _layout = dtk::HorizontalLayout::create(context, shared_from_this()); - _layout->setSpacingRole(dtk::SizeRole::SpacingTool); - - _lineEdit = dtk::LineEdit::create(context, _layout); - _lineEdit->setFormat("00:00:00:00"); - - _incButtons = dtk::IncButtons::create(context, _layout); - - _timeUpdate(); - - _lineEdit->setTextCallback( - [this](const std::string& text) - { - if (_callback) - { - const auto time = OTIO_NS::RationalTime::from_timecode(text, _time.rate()); - _callback(time); - } - }); - - _incButtons->setIncCallback( - [this] - { - _timeInc(); - }); - _incButtons->setDecCallback( - [this] - { - _timeDec(); - }); - - _timeUnitsObserver = dtk::ValueObserver::create( - timeUnitsModel->observeTimeUnits(), - [this](TimeUnits) - { - _timeUpdate(); - }); - } - - TimeEdit::~TimeEdit() - {} - - std::shared_ptr TimeEdit::create( - const std::shared_ptr& context, - const std::shared_ptr& timeUnitsModel, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new TimeEdit); - out->_init(context, timeUnitsModel, parent); - return out; - } - - void TimeEdit::setTime(const OTIO_NS::RationalTime& value) - { - if (value.strictly_equal(_time)) - return; - _time = value; - _timeUpdate(); - } - - void TimeEdit::setTimeRange(const OTIO_NS::TimeRange& value) - { - if (value.start_time().strictly_equal(_timeRange.start_time()) && - value.duration().strictly_equal(_timeRange.duration())) - return; - _timeRange = value; - _timeUpdate(); - } - - void TimeEdit::setCallback(const std::function& value) - { - _callback = value; - } - - void TimeEdit::setGeometry(const dtk::Box2I& value) - { - IWidget::setGeometry(value); - _layout->setGeometry(value); - } - - void TimeEdit::sizeHintEvent(const dtk::SizeHintEvent& value) - { - IWidget::sizeHintEvent(value); - _setSizeHint(_layout->getSizeHint()); - } - - void TimeEdit::keyPressEvent(dtk::KeyEvent& event) - { - if (_lineEdit->hasKeyFocus()) - { - if (0 == event.modifiers) - { - switch (event.key) - { - case dtk::Key::Up: - case dtk::Key::Right: - event.accept = true; - _timeInc(); - break; - case dtk::Key::Down: - case dtk::Key::Left: - event.accept = true; - _timeDec(); - break; - case dtk::Key::PageUp: - event.accept = true; - _timeInc(_time.rate()); - break; - case dtk::Key::PageDown: - event.accept = true; - _timeInc(-_time.rate()); - break; - default: break; - } - } - } - if (!event.accept) - { - IWidget::keyPressEvent(event); - } - } - - void TimeEdit::keyReleaseEvent(dtk::KeyEvent& event) - { - IWidget::keyReleaseEvent(event); - event.accept = true; - } - - void TimeEdit::_timeUpdate() - { - _lineEdit->setText(_timeUnitsModel->getLabel(_time)); - } - - void TimeEdit::_timeInc(int value) - { - if (_callback) - { - const auto time = _time + OTIO_NS::RationalTime(value, _time.rate()); - _callback(time); - } - } - - void TimeEdit::_timeDec(int value) - { - if (_callback) - { - const auto time = _time - OTIO_NS::RationalTime(value, _time.rate()); - _callback(time); - } - } - - void TimeLabel::_init( - const std::shared_ptr& context, - const std::shared_ptr& timeUnitsModel, - const std::shared_ptr& parent) - { - IWidget::_init(context, "toucan::TimeLabel", parent); - - _timeUnitsModel = timeUnitsModel; - - _label = dtk::Label::create(context, shared_from_this()); - _label->setMarginRole(dtk::SizeRole::MarginInside); - - _timeUpdate(); - - _timeUnitsObserver = dtk::ValueObserver::create( - timeUnitsModel->observeTimeUnits(), - [this](TimeUnits value) - { - _timeUpdate(); - }); - } - - TimeLabel::~TimeLabel() - {} - - std::shared_ptr TimeLabel::create( - const std::shared_ptr& context, - const std::shared_ptr& timeUnitsModel, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new TimeLabel); - out->_init(context, timeUnitsModel, parent); - return out; - } - - void TimeLabel::setTime(const OTIO_NS::RationalTime& value) - { - if (value.strictly_equal(_time)) - return; - _time = value; - _timeUpdate(); - } - - void TimeLabel::setMarginRole(dtk::SizeRole value) - { - _label->setMarginRole(value); - } - - void TimeLabel::setGeometry(const dtk::Box2I& value) - { - IWidget::setGeometry(value); - _label->setGeometry(value); - } - - void TimeLabel::sizeHintEvent(const dtk::SizeHintEvent& value) - { - IWidget::sizeHintEvent(value); - _setSizeHint(_label->getSizeHint()); - } - - void TimeLabel::_timeUpdate() - { - _label->setText(_timeUnitsModel->getLabel(_time)); - } -} diff --git a/lib/toucanEdit/TimeWidgets.h b/lib/toucanEdit/TimeWidgets.h deleted file mode 100644 index 236e628..0000000 --- a/lib/toucanEdit/TimeWidgets.h +++ /dev/null @@ -1,151 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include -#include - -#include -#include -#include -#include -#include - -#include - -namespace toucan -{ - class FrameButtons : public dtk::IWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~FrameButtons(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - void setCallback(const std::function&); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - - private: - std::function _callback; - std::shared_ptr _layout; - std::shared_ptr _buttonGroup; - }; - - class PlaybackButtons : public dtk::IWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~PlaybackButtons(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - void setPlayback(Playback); - - void setCallback(const std::function&); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - - private: - void _playbackUpdate(); - - Playback _playback = Playback::Stop; - std::function _callback; - std::shared_ptr _layout; - std::shared_ptr _buttonGroup; - }; - - class TimeEdit : public dtk::IWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~TimeEdit(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr& timeUnitsModel, - const std::shared_ptr& parent = nullptr); - - void setTime(const OTIO_NS::RationalTime&); - void setTimeRange(const OTIO_NS::TimeRange&); - - void setCallback(const std::function&); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - void keyPressEvent(dtk::KeyEvent&) override; - void keyReleaseEvent(dtk::KeyEvent&) override; - - private: - void _timeInc(int = 1); - void _timeDec(int = 1); - void _timeUpdate(); - - OTIO_NS::RationalTime _time; - OTIO_NS::TimeRange _timeRange; - std::shared_ptr _timeUnitsModel; - - std::shared_ptr _layout; - std::shared_ptr _lineEdit; - std::shared_ptr _incButtons; - std::function _callback; - - std::shared_ptr > _timeUnitsObserver; - }; - - class TimeLabel : public dtk::IWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~TimeLabel(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr& timeUnitsModel, - const std::shared_ptr& parent = nullptr); - - void setTime(const OTIO_NS::RationalTime&); - - void setMarginRole(dtk::SizeRole); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - - private: - void _timeUpdate(); - - OTIO_NS::RationalTime _time; - std::shared_ptr _timeUnitsModel; - - std::shared_ptr _label; - - std::shared_ptr > _timeUnitsObserver; - }; -} - diff --git a/lib/toucanEdit/Timeline.cpp b/lib/toucanEdit/Timeline.cpp deleted file mode 100644 index 61cfd54..0000000 --- a/lib/toucanEdit/Timeline.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Timeline.h" - -#include "Stack.h" - -namespace toucan -{ - Timeline::Timeline( - const std::filesystem::path& path, - const OTIO_NS::AnyDictionary& metadata) : - _path(path), - _metadata(metadata) - { - _range = dtk::ObservableValue::create(); - _stack = std::make_shared(); - _itemRanges = dtk::ObservableList >::create(); - } - - Timeline::~Timeline() - {} - - const std::filesystem::path& Timeline::getPath() const - { - return _path; - } - - const OTIO_NS::AnyDictionary& Timeline::getMetadata() const - { - return _metadata; - } - - void Timeline::setMetadata(const OTIO_NS::AnyDictionary& value) - { - _metadata = value; - } - - const OTIO_NS::TimeRange& Timeline::getRange() const - { - return _range->get(); - } - - std::shared_ptr > Timeline::observeRange() const - { - return _range; - } - - void Timeline::setRange(const OTIO_NS::TimeRange& range) - { - if (_range->setIfChanged(range)) - { - _stack->setRange(range); - } - } - - const std::shared_ptr& Timeline::getStack() const - { - return _stack; - } - - void Timeline::setItemDuration(const std::shared_ptr& item, const OTIO_NS::RationalTime& duration) - { - if (auto parent = item->getParent()) - { - std::vector > items; - - auto children = parent->getChildren(); - auto i = std::find(children.begin(), children.end(), item); - if (i != children.end()) - { - OTIO_NS::TimeRange range = (*i)->getRange(); - OTIO_NS::RationalTime diff = range.duration() - duration; - range = OTIO_NS::TimeRange(range.start_time(), duration); - (*i)->setRange(range); - items.push_back(*i); - ++i; - for (; i != children.end(); ++i) - { - range = (*i)->getRange(); - range = OTIO_NS::TimeRange(range.start_time() + diff, range.duration()); - (*i)->setRange(range); - items.push_back(*i); - } - } - - OTIO_NS::TimeRange range; - i = children.begin(); - if (i != children.end()) - { - range = (*i)->getRange(); - ++i; - for (; i != children.end(); ++i) - { - range = OTIO_NS::TimeRange( - range.start_time(), - range.duration() + (*i)->getRange().duration()); - } - } - if (range != parent->getRange()) - { - parent->setRange(range); - items.push_back(parent); - } - - range = OTIO_NS::TimeRange(); - children = _stack->getChildren(); - i = children.begin(); - if (i != children.end()) - { - range = (*i)->getRange(); - ++i; - for (; i != children.end(); ++i) - { - range = OTIO_NS::TimeRange( - range.start_time(), - range.duration() + (*i)->getRange().duration()); - } - } - if (range != _stack->getRange()) - { - _stack->setRange(range); - items.push_back(_stack); - } - - _range->setIfChanged(range); - _itemRanges->setAlways(items); - } - } - - std::shared_ptr > > Timeline::observeItemRanges() const - { - return _itemRanges; - } -} diff --git a/lib/toucanEdit/Timeline.h b/lib/toucanEdit/Timeline.h deleted file mode 100644 index 3d2eefc..0000000 --- a/lib/toucanEdit/Timeline.h +++ /dev/null @@ -1,57 +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 IItem; - class Stack; - - class Timeline : std::enable_shared_from_this - { - public: - Timeline( - const std::filesystem::path&, - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary()); - - ~Timeline(); - - const std::filesystem::path& getPath() const; - - const OTIO_NS::AnyDictionary& getMetadata() const; - void setMetadata(const OTIO_NS::AnyDictionary&); - - const OTIO_NS::TimeRange& getRange() const; - std::shared_ptr > observeRange() const; - void setRange(const OTIO_NS::TimeRange&); - - const std::shared_ptr& getStack() const; - - void setItemDuration(const std::shared_ptr&, const OTIO_NS::RationalTime&); - std::shared_ptr > > observeItemRanges() const; - - private: - std::filesystem::path _path; - OTIO_NS::AnyDictionary _metadata; - std::shared_ptr > _range; - std::shared_ptr _stack; - std::shared_ptr > > _itemRanges; - }; - - OTIO_NS::SerializableObject::Retainer convertTo( - const std::shared_ptr&); - - std::shared_ptr convertFrom( - const std::filesystem::path&, - const OTIO_NS::SerializableObject::Retainer&); -} - diff --git a/lib/toucanEdit/TimelineConvert.cpp b/lib/toucanEdit/TimelineConvert.cpp deleted file mode 100644 index fe04db5..0000000 --- a/lib/toucanEdit/TimelineConvert.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Timeline.h" - -#include "Clip.h" -#include "Effects.h" -#include "Gap.h" -#include "MediaReferences.h" -#include "Stack.h" -#include "Track.h" -#include "Transitions.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace toucan -{ - OTIO_NS::SerializableObject::Retainer convertTo( - const std::shared_ptr& timeline) - { - OTIO_NS::SerializableObject::Retainer out; - return out; - } - - namespace - { - void convertEffects( - const OTIO_NS::SerializableObject::Retainer& otioItem, - const std::shared_ptr& item) - { - std::vector > effects; - for (const auto& otioEffect : otioItem->effects()) - { - if (auto otioLinear= OTIO_NS::dynamic_retainer_cast(otioEffect)) - { - auto linear = std::make_shared( - otioLinear->name(), - otioLinear->effect_name(), - otioLinear->metadata()); - linear->setTimeScalar(otioLinear->time_scalar()); - effects.push_back(linear); - } - else - { - effects.push_back(std::make_shared( - otioEffect->name(), - otioEffect->effect_name(), - otioEffect->metadata())); - } - } - item->setEffects(effects); - } - - std::shared_ptr convertFrom( - const OTIO_NS::SerializableObject::Retainer& otioClip) - { - auto clip = std::make_shared( - otioClip->name(), - otioClip->trimmed_range(), - otioClip->metadata()); - - Clip::MediaReferences refs; - for (const auto& otioRef : otioClip->media_references()) - { - if (auto otioExternalRef = dynamic_cast(otioRef.second)) - { - refs[otioRef.first] = std::make_shared( - otioExternalRef->target_url()); - } - else if (auto otioImageSequenceRef = dynamic_cast(otioRef.second)) - { - refs[otioRef.first] = std::make_shared( - otioImageSequenceRef->target_url_base(), - otioImageSequenceRef->name_prefix(), - otioImageSequenceRef->name_suffix(), - otioImageSequenceRef->start_frame(), - otioImageSequenceRef->frame_step(), - otioImageSequenceRef->rate(), - otioImageSequenceRef->frame_zero_padding()); - } - else if (auto otioGeneratorRef = dynamic_cast(otioRef.second)) - { - refs[otioRef.first] = std::make_shared( - otioGeneratorRef->generator_kind(), - otioGeneratorRef->parameters()); - } - } - clip->setMediaReferences(refs); - clip->setActiveMediaReference(otioClip->active_media_reference_key()); - - convertEffects(OTIO_NS::dynamic_retainer_cast(otioClip), clip); - - return clip; - } - - std::shared_ptr convertFrom( - const OTIO_NS::SerializableObject::Retainer& otioGap) - { - auto out = std::make_shared( - otioGap->name(), - otioGap->trimmed_range(), - otioGap->metadata()); - return out; - } - - std::shared_ptr convertFrom( - const OTIO_NS::SerializableObject::Retainer& otioTransition) - { - auto out = std::make_shared( - otioTransition->name(), - OTIO_NS::TimeRange( - OTIO_NS::RationalTime(0.0, otioTransition->duration().rate()), - OTIO_NS::RationalTime(0.0, otioTransition->duration().rate())), - otioTransition->metadata(), - otioTransition->transition_type(), - otioTransition->in_offset(), - otioTransition->out_offset()); - return out; - } - - std::shared_ptr convertFrom( - const OTIO_NS::SerializableObject::Retainer& otioTrack) - { - auto track = std::make_shared( - otioTrack->name(), - otioTrack->trimmed_range(), - otioTrack->metadata(), - otioTrack->kind()); - - for (const auto& otioItem : otioTrack->children()) - { - if (auto otioClip = OTIO_NS::dynamic_retainer_cast(otioItem)) - { - auto clip = convertFrom(otioClip); - track->addChild(clip); - } - else if (auto otioGap = OTIO_NS::dynamic_retainer_cast(otioItem)) - { - auto gap = convertFrom(otioGap); - track->addChild(gap); - } - else if (auto otioTransition = OTIO_NS::dynamic_retainer_cast(otioItem)) - { - auto transition = convertFrom(otioTransition); - track->addChild(transition); - } - } - - convertEffects(OTIO_NS::dynamic_retainer_cast(otioTrack), track); - - return track; - } - } - - std::shared_ptr convertFrom( - const std::filesystem::path& path, - const OTIO_NS::SerializableObject::Retainer& otioTimeline) - { - auto out = std::make_shared(path, otioTimeline->metadata()); - - const OTIO_NS::RationalTime& duration = otioTimeline->duration(); - OTIO_NS::RationalTime startTime(0.0, duration.rate()); - auto opt = otioTimeline->global_start_time(); - if (opt.has_value()) - { - startTime = opt.value(); - } - out->setRange(OTIO_NS::TimeRange(startTime, duration)); - - auto stack = out->getStack(); - auto otioStack = otioTimeline->tracks(); - stack->setName(otioStack->name()); - stack->setRange(otioStack->trimmed_range()); - stack->setMetadata(otioStack->metadata()); - - for (const auto& otioItem : otioStack->children()) - { - if (auto otioTrack = OTIO_NS::dynamic_retainer_cast(otioItem)) - { - auto track = convertFrom(otioTrack); - out->getStack()->addChild(track); - } - } - - convertEffects(otioStack, stack); - - return out; - } -} diff --git a/lib/toucanEdit/TimelineConvert.h b/lib/toucanEdit/TimelineConvert.h deleted file mode 100644 index 8f1d354..0000000 --- a/lib/toucanEdit/TimelineConvert.h +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - struct TrackKind - { - static const std::string video; - static const std::string audio; - }; - - class Track : public IContainer - { - public: - Track(const std::string& kind); - - virtual ~Track(); - - const std::string& getKind() const; - - private: - std::string _kind; - }; -} - diff --git a/lib/toucanEdit/TimelineView.cpp b/lib/toucanEdit/TimelineView.cpp deleted file mode 100644 index 22d0db4..0000000 --- a/lib/toucanEdit/TimelineView.cpp +++ /dev/null @@ -1,311 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "TimelineView.h" - -#include "App.h" -#include "DocumentsModel.h" -#include "PlaybackModel.h" -#include "TimelineWidget.h" - -namespace toucan -{ - namespace - { - const float marginPercentage = .1F; - } - - void TimelineView::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& document, - const std::shared_ptr& parent) - { - IWidget::_init(context, "toucan::TimelineView", parent); - - _setMouseHoverEnabled(true); - _setMousePressEnabled(true, 0, static_cast(dtk::KeyModifier::Control)); - - _document = document; - _timeRange = document->getPlaybackModel()->getTimeRange(); - _frameView = dtk::ObservableValue::create(true); - - _scrollWidget = dtk::ScrollWidget::create(context, dtk::ScrollType::Both, shared_from_this()); - _scrollWidget->setScrollEventsEnabled(false); - _scrollWidget->setBorder(false); - - _timelineWidget = TimelineWidget::create( - context, - app, - document); - _scrollWidget->setWidget(_timelineWidget); - - _timelineWidget->setCurrentTimeCallback( - [this](const OTIO_NS::RationalTime& value) - { - _document->getPlaybackModel()->setCurrentTime(value); - }); - - _currentTimeObserver = dtk::ValueObserver::create( - document->getPlaybackModel()->observeCurrentTime(), - [this](const OTIO_NS::RationalTime& value) - { - _currentTime = value; - if (_timelineWidget) - { - _timelineWidget->setCurrentTime(value); - } - _scrollUpdate(); - }); - } - - TimelineView::~TimelineView() - {} - - std::shared_ptr TimelineView::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& document, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new TimelineView); - out->_init(context, app, document, parent); - return out; - } - - void TimelineView::setViewZoom(double value) - { - const dtk::Box2I& g = getGeometry(); - setViewZoom(value, dtk::V2I(g.w() / 2, g.h() / 2)); - } - - void TimelineView::setViewZoom(double zoom, const dtk::V2I& focus) - { - _setViewZoom( - zoom, - _scale, - focus, - _scrollWidget->getScrollPos()); - } - - void TimelineView::frameView() - { - _scrollWidget->setScrollPos(dtk::V2I()); - const double scale = _getTimelineScale(); - if (scale != _scale) - { - _scale = scale; - if (_timelineWidget) - { - _timelineWidget->setScale(_scale); - } - _setSizeUpdate(); - _setDrawUpdate(); - } - } - - bool TimelineView::hasFrameView() const - { - return _frameView->get(); - } - - std::shared_ptr > TimelineView::observeFrameView() const - { - return _frameView; - } - - void TimelineView::setFrameView(bool value) - { - if (_frameView->setIfChanged(value)) - { - if (value) - { - frameView(); - } - } - } - - void TimelineView::setGeometry(const dtk::Box2I& value) - { - const bool changed = value != getGeometry(); - IWidget::setGeometry(value); - _scrollWidget->setGeometry(value); - if (_sizeInit || (changed && _frameView->get())) - { - _sizeInit = false; - frameView(); - } - else if (_timelineWidget && - _timelineWidget->getSizeHint().w < - _scrollWidget->getViewport().w()) - { - setFrameView(true); - } - } - - void TimelineView::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IWidget::sizeHintEvent(event); - _setSizeHint(_scrollWidget->getSizeHint()); - } - - void TimelineView::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 TimelineView::mousePressEvent(dtk::MouseClickEvent& event) - { - IWidget::mousePressEvent(event); - if (0 == event.button && - static_cast(dtk::KeyModifier::Control) == event.modifiers) - { - event.accept = true; - takeKeyFocus(); - _mouse.mode = MouseMode::Scroll; - _mouse.scrollPos = _scrollWidget->getScrollPos(); - } - else - { - _mouse.mode = MouseMode::None; - } - } - - void TimelineView::mouseReleaseEvent(dtk::MouseClickEvent& event) - { - IWidget::mouseReleaseEvent(event); - } - - void TimelineView::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 TimelineView::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 TimelineView::keyReleaseEvent(dtk::KeyEvent& event) - { - event.accept = true; - } - - void TimelineView::_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 (_timelineWidget) - { - _timelineWidget->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 TimelineView::_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 TimelineView::_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 TimelineView::_scrollUpdate() - { - if (_timelineWidget && - MouseMode::None == _mouse.mode) - { - const int pos = _timelineWidget->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/lib/toucanEdit/TimelineView.h b/lib/toucanEdit/TimelineView.h deleted file mode 100644 index 1328561..0000000 --- a/lib/toucanEdit/TimelineView.h +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include -#include - -#include - -namespace toucan -{ - class App; - class Document; - class TimelineWidget; - - class TimelineView : public dtk::IWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~TimelineView(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - void setViewZoom(double); - void setViewZoom(double, const dtk::V2I& focus); - - bool hasFrameView() const; - void frameView(); - std::shared_ptr > observeFrameView() const; - void setFrameView(bool); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - void mouseMoveEvent(dtk::MouseMoveEvent&) override; - void mousePressEvent(dtk::MouseClickEvent&) override; - void mouseReleaseEvent(dtk::MouseClickEvent&) override; - void scrollEvent(dtk::ScrollEvent&) override; - void keyPressEvent(dtk::KeyEvent&) override; - void keyReleaseEvent(dtk::KeyEvent&) override; - - private: - void _setViewZoom( - double zoomNew, - double zoomPrev, - const dtk::V2I& focus, - const dtk::V2I& scrollPos); - - double _getTimelineScale() const; - double _getTimelineScaleMax() const; - - void _scrollUpdate(); - - std::shared_ptr _document; - OTIO_NS::TimeRange _timeRange; - OTIO_NS::RationalTime _currentTime; - double _scale = 100.0; - bool _sizeInit = true; - std::shared_ptr > _frameView; - - std::shared_ptr _scrollWidget; - std::shared_ptr _timelineWidget; - - enum class MouseMode - { - None, - Scroll - }; - struct MouseData - { - MouseMode mode = MouseMode::None; - dtk::V2I scrollPos; - std::chrono::steady_clock::time_point wheelTimer; - }; - MouseData _mouse; - - std::shared_ptr > _currentTimeObserver; - }; -} diff --git a/lib/toucanEdit/TimelineWidget.cpp b/lib/toucanEdit/TimelineWidget.cpp deleted file mode 100644 index a98ceb4..0000000 --- a/lib/toucanEdit/TimelineWidget.cpp +++ /dev/null @@ -1,578 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "TimelineWidget.h" - -#include "App.h" -#include "DocumentsModel.h" -#include "Clip.h" -#include "ClipWidget.h" -#include "Gap.h" -#include "GapWidget.h" -#include "Stack.h" -#include "StackWidget.h" -#include "Timeline.h" -#include "TrackWidget.h" -#include "Track.h" - -#include - -namespace toucan -{ - void TimelineWidget::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& document, - const std::shared_ptr& parent) - { - auto timeline = document->getTimeline(); - IItemWidget::_init( - context, - app, - nullptr, - timeline->getRange(), - "toucan::TimelineWidget", - parent); - - _setMouseHoverEnabled(true); - _setMousePressEnabled( - true, - 0, - 0 | static_cast(dtk::KeyModifier::Shift) | static_cast(dtk::KeyModifier::Control)); - - _timeline = timeline; - _timeUnitsModel = app->getTimeUnitsModel(); - _selectionModel = document->getSelectionModel(); - _thumbnailGenerator = document->getThumbnailGenerator(); - - auto stackWidget = StackWidget::create(context, app, _timeline->getStack(), shared_from_this()); - for (const auto& child : timeline->getStack()->getChildren()) - { - if (auto track = std::dynamic_pointer_cast(child)) - { - auto trackWidget = TrackWidget::create(context, app, track, stackWidget); - - for (const auto& child : track->getChildren()) - { - if (auto clip = std::dynamic_pointer_cast(child)) - { - auto clipWidget = ClipWidget::create( - context, - app, - clip, - dtk::Color4F(.4F, .5F, .7F), - trackWidget); - } - else if (auto gap = std::dynamic_pointer_cast(child)) - { - auto GapWidget = GapWidget::create( - context, - app, - gap, - trackWidget); - } - } - } - } - - _timeUnitsObserver = dtk::ValueObserver::create( - _timeUnitsModel->observeTimeUnits(), - [this](TimeUnits) - { - _setDrawUpdate(); - }); - - _selectionObserver = dtk::ListObserver >::create( - _selectionModel->observeSelection(), - [this](const std::vector >& selection) - { - _select(shared_from_this(), selection); - }); - - } - - TimelineWidget::~TimelineWidget() - {} - - std::shared_ptr TimelineWidget::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& document, - const std::shared_ptr& parent) - { - auto out = std::make_shared(); - out->_init(context, app, document, parent); - return out; - } - - const OTIO_NS::RationalTime& TimelineWidget::getCurrentTime() const - { - return _currentTime; - } - - void TimelineWidget::setCurrentTime(const OTIO_NS::RationalTime& value) - { - if (value == _currentTime) - return; - _currentTime = value; - _setDrawUpdate(); - } - - void TimelineWidget::setCurrentTimeCallback(const std::function& value) - { - _currentTimeCallback = value; - } - - OTIO_NS::RationalTime TimelineWidget::posToTime(double value) const - { - OTIO_NS::RationalTime out; - const dtk::Box2I& g = getGeometry(); - if (g.w() > 0) - { - const double normalized = (value - g.min.x) / - static_cast(_timeRange.duration().rescaled_to(1.0).value() * _scale); - out = OTIO_NS::RationalTime( - _timeRange.start_time() + - OTIO_NS::RationalTime( - _timeRange.duration().value() * normalized, - _timeRange.duration().rate())). - round(); - out = dtk::clamp( - out, - _timeRange.start_time(), - _timeRange.end_time_inclusive()); - } - return out; - } - - int TimelineWidget::timeToPos(const OTIO_NS::RationalTime& value) const - { - const dtk::Box2I& g = getGeometry(); - const OTIO_NS::RationalTime t = value - _timeRange.start_time(); - return g.min.x + t.rescaled_to(1.0).value() * _scale; - } - - void TimelineWidget::setGeometry(const dtk::Box2I& value) - { - IItemWidget::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(); - child->setGeometry(dtk::Box2I( - g.min.x, - g.min.y + timeHeight + _size.thumbnailSize.h, - sizeHint.w, - sizeHint.h)); - } - if (auto scrollArea = getParentT()) - { - _size.scrollPos = scrollArea->getScrollPos(); - } - } - - void TimelineWidget::tickEvent( - bool parentsVisible, - bool parentsEnabled, - const dtk::TickEvent& event) - { - IItemWidget::tickEvent(parentsVisible, parentsEnabled, event); - if (_thumbnailFuture.valid() && - _thumbnailFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready) - { - const auto thumbnail = _thumbnailFuture.get(); - _thumbnails[thumbnail.time] = thumbnail.image; - _setDrawUpdate(); - } - } - - void TimelineWidget::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IItemWidget::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.thumbnailSize.h = 2 * event.style->getSizeRole(dtk::SizeRole::SwatchLarge, event.displayScale); - _size.thumbnailSize.w = _size.thumbnailSize.h * _thumbnailGenerator->getAspect(); - _size.fontInfo = event.style->getFontRole(dtk::FontRole::Label, event.displayScale); - _size.fontMetrics = event.fontSystem->getMetrics(_size.fontInfo); - _thumbnailFuture = std::future(); - _thumbnails.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); - sizeHint.h += _size.thumbnailSize.h; - sizeHint.h += childSizeHint; - _setSizeHint(sizeHint); - } - - void TimelineWidget::drawEvent(const dtk::Box2I& drawRect, const dtk::DrawEvent& event) - { - IItemWidget::drawEvent(drawRect, event); - const dtk::Box2I& g = getGeometry(); - const int y = g.min.y + _size.fontMetrics.lineHeight + _size.margin * 2; - for (int x = g.min.x; x < g.max.x && _size.thumbnailSize.w > 0; x += _size.thumbnailSize.w) - { - const dtk::Box2I g2(x, y, _size.thumbnailSize.w, _size.thumbnailSize.h); - if (dtk::intersects(g2, drawRect)) - { - const OTIO_NS::RationalTime t = posToTime(x); - const auto i = _thumbnails.find(t); - if (i != _thumbnails.end()) - { - if (i->second) - { - event.render->drawImage( - i->second, - dtk::Box2I(x, y, i->second->getWidth(), i->second->getHeight())); - } - } - else if (!_thumbnailFuture.valid()) - { - _thumbnailFuture = _thumbnailGenerator->getThumbnail(t, _size.thumbnailSize.h); - } - } - } - } - - void TimelineWidget::drawOverlayEvent(const dtk::Box2I& drawRect, const dtk::DrawEvent& event) - { - IItemWidget::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)); - - _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 = _timeUnitsModel->getLabel(_currentTime); - 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 TimelineWidget::mouseMoveEvent(dtk::MouseMoveEvent& event) - { - IItemWidget::mouseMoveEvent(event); - if (MouseMode::CurrentTime == _mouse.mode) - { - _currentTime = posToTime(_getMousePos().x); - if (_currentTimeCallback) - { - _currentTimeCallback(_currentTime); - } - _setDrawUpdate(); - } - } - - void TimelineWidget::mousePressEvent(dtk::MouseClickEvent& event) - { - IItemWidget::mousePressEvent(event); - if (0 == event.button && - (0 == event.modifiers || - static_cast(dtk::KeyModifier::Shift) == event.modifiers || - static_cast(dtk::KeyModifier::Control) == event.modifiers)) - { - event.accept = true; - auto selection = _select(shared_from_this(), event.pos); - std::shared_ptr item; - if (selection) - { - item = selection->getItem(); - } - if (selection && item) - { - _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::KeyModifier::Control) == 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 - { - _mouse.mode = MouseMode::CurrentTime; - _currentTime = posToTime(_getMousePos().x); - if (_currentTimeCallback) - { - _currentTimeCallback(_currentTime); - } - _setDrawUpdate(); - } - } - } - - void TimelineWidget::mouseReleaseEvent(dtk::MouseClickEvent& event) - { - IItemWidget::mouseReleaseEvent(event); - if (_mouse.mode != MouseMode::None) - { - event.accept = true; - _mouse.mode = MouseMode::None; - } - } - - dtk::Size2I TimelineWidget::_getLabelMaxSize( - const std::shared_ptr& fontSystem) const - { - const std::string labelMax = _timeUnitsModel->getLabel(_timeRange.duration()); - const dtk::Size2I labelMaxSize = fontSystem->getSize(labelMax, _size.fontInfo); - return labelMaxSize; - } - - void TimelineWidget::_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 TimelineWidget::_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 TimelineWidget::_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 = _timeUnitsModel->getLabel(time); - event.render->drawText( - event.fontSystem->getGlyphs(label, _size.fontInfo), - _size.fontMetrics, - box.min, - event.style->getColorRole(dtk::ColorRole::TextDisabled)); - } - } - } - } - } - - std::shared_ptr TimelineWidget::_select( - const std::shared_ptr& widget, - const dtk::V2I& pos) - { - std::shared_ptr out; - if (auto itemWidget = std::dynamic_pointer_cast(widget)) - { - out = itemWidget; - } - for (const auto& child : widget->getChildren()) - { - if (dtk::contains(child->getGeometry(), pos)) - { - out = _select(child, pos); - break; - } - } - return out; - } - - void TimelineWidget::_select( - const std::shared_ptr& widget, - const std::vector >& selection) - { - if (auto itemWidget = std::dynamic_pointer_cast(widget)) - { - const auto i = std::find(selection.begin(), selection.end(), itemWidget->getItem()); - itemWidget->setSelected(i != selection.end()); - } - for (const auto& child : widget->getChildren()) - { - _select(child, selection); - } - } -} diff --git a/lib/toucanEdit/TimelineWidget.h b/lib/toucanEdit/TimelineWidget.h deleted file mode 100644 index 8c51a83..0000000 --- a/lib/toucanEdit/TimelineWidget.h +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include -#include -#include -#include - -namespace toucan -{ - class Document; - - class TimelineWidget : public IItemWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~TimelineWidget(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - const OTIO_NS::RationalTime& getCurrentTime() const; - void setCurrentTime(const OTIO_NS::RationalTime&); - void setCurrentTimeCallback(const std::function&); - - OTIO_NS::RationalTime posToTime(double) const; - int timeToPos(const OTIO_NS::RationalTime&) const; - - 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; - - 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&); - - std::shared_ptr _select( - const std::shared_ptr&, - const dtk::V2I&); - void _select( - const std::shared_ptr&, - const std::vector >&); - - std::shared_ptr _timeline; - OTIO_NS::RationalTime _currentTime = OTIO_NS::RationalTime(-1.0, -1.0); - std::function _currentTimeCallback; - std::shared_ptr _timeUnitsModel; - std::shared_ptr _selectionModel; - std::shared_ptr _thumbnailGenerator; - std::future _thumbnailFuture; - std::map > _thumbnails; - - struct SizeData - { - bool init = true; - float displayScale = 0.F; - int margin = 0; - int border = 0; - int handle = 0; - dtk::Size2I thumbnailSize; - 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 > _timeUnitsObserver; - std::shared_ptr > > _selectionObserver; - }; -} diff --git a/lib/toucanEdit/Track.cpp b/lib/toucanEdit/Track.cpp deleted file mode 100644 index 6fe24b0..0000000 --- a/lib/toucanEdit/Track.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Track.h" - -namespace toucan -{ - const std::string TrackKind::video = "Video"; - const std::string TrackKind::audio = "Audio"; - - Track::Track( - const std::string& name, - const OTIO_NS::TimeRange& range, - const OTIO_NS::AnyDictionary& metadata, - const std::string& kind) : - IContainer(name, range, metadata), - _kind(kind) - {} - - Track::~Track() - {} - - const std::string& Track::getKind() const - { - return _kind; - } -} diff --git a/lib/toucanEdit/Track.h b/lib/toucanEdit/Track.h deleted file mode 100644 index aee616c..0000000 --- a/lib/toucanEdit/Track.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - struct TrackKind - { - static const std::string video; - static const std::string audio; - }; - class Track : public IContainer - { - public: - Track( - const std::string& name = std::string(), - const OTIO_NS::TimeRange& range = OTIO_NS::TimeRange(), - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary(), - const std::string& kind = TrackKind::video); - - virtual ~Track(); - - const std::string& getKind() const; - - private: - std::string _kind; - }; -} - diff --git a/lib/toucanEdit/TrackWidget.cpp b/lib/toucanEdit/TrackWidget.cpp deleted file mode 100644 index 3794138..0000000 --- a/lib/toucanEdit/TrackWidget.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "TrackWidget.h" - -#include "Track.h" - -#include -#include - -namespace toucan -{ - void TrackWidget::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& track, - const std::shared_ptr& parent) - { - IItemWidget::_init( - context, - app, - track, - track->getRange(), - "toucan::TrackWidget", - parent); - - _track = track; - _text = track->getName(); - if (_text.empty()) - { - _text = track->getKind(); - } - _color = TrackKind::video == track->getKind() ? - dtk::Color4F(.2F, .2F, .3F) : - dtk::Color4F(.2F, .3F, .2F); - - setTooltip(_text); - } - - TrackWidget::~TrackWidget() - {} - - std::shared_ptr TrackWidget::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::shared_ptr& track, - const std::shared_ptr& parent) - { - auto out = std::make_shared(); - out->_init(context, app, track, parent); - return out; - } - - void TrackWidget::setGeometry(const dtk::Box2I& value) - { - IItemWidget::setGeometry(value); - const dtk::Box2I& g = getGeometry(); - dtk::V2I pos = g.min; - pos.y += _size.fontMetrics.lineHeight + _size.margin * 2 + _size.border * 2; - for (const auto& child : getChildren()) - { - const dtk::Size2I& sizeHint = child->getSizeHint(); - child->setGeometry(dtk::Box2I(pos.x, pos.y, sizeHint.w, sizeHint.h)); - pos.x += sizeHint.w; - } - } - - void TrackWidget::sizeHintEvent(const dtk::SizeHintEvent& event) - { - IItemWidget::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.fontInfo = event.style->getFontRole(dtk::FontRole::Label, event.displayScale); - _size.fontMetrics = event.fontSystem->getMetrics(_size.fontInfo); - _size.textSize = event.fontSystem->getSize(_text, _size.fontInfo); - _draw.glyphs.clear(); - } - dtk::Size2I sizeHint( - _timeRange.duration().rescaled_to(1.0).value() * _scale, - 0); - for (const auto& child : getChildren()) - { - const dtk::Size2I& childSizeHint = child->getSizeHint(); - sizeHint.h = std::max(sizeHint.h, childSizeHint.h); - } - sizeHint.h += _size.textSize.h + _size.margin * 2 + _size.border * 4; - _setSizeHint(sizeHint); - } - - void TrackWidget::clipEvent(const dtk::Box2I& clipRect, bool clipped) - { - IItemWidget::clipEvent(clipRect, clipped); - if (clipped) - { - _draw.glyphs.clear(); - } - } - - void TrackWidget::drawEvent( - const dtk::Box2I& drawRect, - const dtk::DrawEvent& event) - { - IItemWidget::drawEvent(drawRect, event); - const dtk::Box2I& g = getGeometry(); - - const dtk::Box2I g2( - g.min.x + _size.border, - g.min.y, - g.w() - _size.border * 2, - _size.fontMetrics.lineHeight + _size.margin * 2); - event.render->drawRect( - g2, - _selected ? event.style->getColorRole(dtk::ColorRole::Yellow) : _color); - - const dtk::Box2I g3 = dtk::margin(g2, -_size.margin); - if (!_text.empty() && _draw.glyphs.empty()) - { - _draw.glyphs = event.fontSystem->getGlyphs(_text, _size.fontInfo); - } - dtk::ClipRectEnabledState clipRectEnabledState(event.render); - dtk::ClipRectState clipRectState(event.render); - event.render->setClipRectEnabled(true); - event.render->setClipRect(intersect(g3, drawRect)); - event.render->drawText( - _draw.glyphs, - _size.fontMetrics, - g3.min, - event.style->getColorRole(dtk::ColorRole::Text)); - } -} diff --git a/lib/toucanEdit/TrackWidget.h b/lib/toucanEdit/TrackWidget.h deleted file mode 100644 index 7a91e1b..0000000 --- a/lib/toucanEdit/TrackWidget.h +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -namespace toucan -{ - class Track; - - class TrackWidget : public IItemWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~TrackWidget(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - void clipEvent(const dtk::Box2I&, bool) override; - void drawEvent(const dtk::Box2I&, const dtk::DrawEvent&) override; - - private: - std::shared_ptr _track; - std::string _text; - dtk::Color4F _color; - - struct SizeData - { - bool init = true; - float displayScale = 0.F; - int margin = 0; - int border = 0; - dtk::FontInfo fontInfo; - dtk::FontMetrics fontMetrics; - dtk::Size2I textSize; - }; - SizeData _size; - - struct DrawData - { - std::vector > glyphs; - }; - DrawData _draw; - }; -} diff --git a/lib/toucanEdit/Transitions.cpp b/lib/toucanEdit/Transitions.cpp deleted file mode 100644 index 6899a44..0000000 --- a/lib/toucanEdit/Transitions.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Transitions.h" - -namespace toucan -{ - Transition::Transition( - const std::string& name, - const OTIO_NS::TimeRange& range, - const OTIO_NS::AnyDictionary& metadata, - const std::string& transitionType, - const OTIO_NS::RationalTime& inOffset, - const OTIO_NS::RationalTime& outOffset) : - IItem(name, range, metadata), - _transitionType(transitionType), - _inOffset(inOffset), - _outOffset(outOffset) - {} - - Transition::~Transition() - {} - - const std::string& Transition::getTransitionType() const - { - return _transitionType; - } - - void Transition::setTransitionType(const std::string& value) - { - _transitionType = value; - } - - const OTIO_NS::RationalTime& Transition::getInOffset() const - { - return _inOffset; - } - - void Transition::setInOffset(const OTIO_NS::RationalTime& value) - { - _inOffset = value; - } - - const OTIO_NS::RationalTime& Transition::getOutOffset() const - { - return _outOffset; - } - - void Transition::setOutOffset(const OTIO_NS::RationalTime& value) - { - _outOffset = value; - } -} diff --git a/lib/toucanEdit/Transitions.h b/lib/toucanEdit/Transitions.h deleted file mode 100644 index 6248c2d..0000000 --- a/lib/toucanEdit/Transitions.h +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -namespace toucan -{ - class Transition : public IItem - { - public: - Transition( - const std::string& name = std::string(), - const OTIO_NS::TimeRange& range = OTIO_NS::TimeRange(), - const OTIO_NS::AnyDictionary& metadata = OTIO_NS::AnyDictionary(), - const std::string& transitionType = std::string(), - const OTIO_NS::RationalTime& inOffset = OTIO_NS::RationalTime(), - const OTIO_NS::RationalTime& outOffset = OTIO_NS::RationalTime()); - - virtual ~Transition(); - - const std::string& getTransitionType() const; - void setTransitionType(const std::string&); - - const OTIO_NS::RationalTime& getInOffset() const; - void setInOffset(const OTIO_NS::RationalTime&); - - const OTIO_NS::RationalTime& getOutOffset() const; - void setOutOffset(const OTIO_NS::RationalTime&); - - private: - std::string _transitionType; - OTIO_NS::RationalTime _inOffset; - OTIO_NS::RationalTime _outOffset; - }; -} - diff --git a/lib/toucanEdit/ViewModel.cpp b/lib/toucanEdit/ViewModel.cpp deleted file mode 100644 index 5f2e59d..0000000 --- a/lib/toucanEdit/ViewModel.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "ViewModel.h" - -#include - -namespace toucan -{ - ViewModel::ViewModel() - { - _zoomIn = dtk::ObservableValue::create(false); - _zoomOut = dtk::ObservableValue::create(false); - _zoomReset = dtk::ObservableValue::create(false); - _frame = dtk::ObservableValue::create(true); - } - - ViewModel::~ViewModel() - {} - - void ViewModel::zoomIn() - { - _zoomIn->setAlways(true); - } - - void ViewModel::zoomOut() - { - _zoomOut->setAlways(true); - } - - void ViewModel::zoomReset() - { - _zoomReset->setAlways(true); - } - - std::shared_ptr > ViewModel::observeZoomIn() const - { - return _zoomIn; - } - - std::shared_ptr > ViewModel::observeZoomOut() const - { - return _zoomOut; - } - - std::shared_ptr > ViewModel::observeZoomReset() const - { - return _zoomReset; - } - - bool ViewModel::getFrame() const - { - return _frame->get(); - } - - std::shared_ptr > ViewModel::observeFrame() const - { - return _frame; - } - - void ViewModel::setFrame(bool value) - { - _frame->setIfChanged(value); - } -} diff --git a/lib/toucanEdit/ViewModel.h b/lib/toucanEdit/ViewModel.h deleted file mode 100644 index eb9a2db..0000000 --- a/lib/toucanEdit/ViewModel.h +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -namespace toucan -{ - class ViewModel : public std::enable_shared_from_this - { - public: - ViewModel(); - - virtual ~ViewModel(); - - void zoomIn(); - void zoomOut(); - void zoomReset(); - std::shared_ptr > observeZoomIn() const; - std::shared_ptr > observeZoomOut() const; - std::shared_ptr > observeZoomReset() const; - - bool getFrame() const; - std::shared_ptr > observeFrame() const; - void setFrame(bool); - - private: - std::shared_ptr > _zoomIn; - std::shared_ptr > _zoomOut; - std::shared_ptr > _zoomReset; - std::shared_ptr > _frame; - }; -} diff --git a/lib/toucanEdit/Viewport.cpp b/lib/toucanEdit/Viewport.cpp deleted file mode 100644 index d4b5d48..0000000 --- a/lib/toucanEdit/Viewport.cpp +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Viewport.h" - -#include "App.h" -#include "Document.h" -#include "ViewModel.h" - -namespace toucan -{ - void Viewport::_init( - const std::shared_ptr& context, - const std::shared_ptr& document, - const std::shared_ptr& parent) - { - IWidget::_init(context, "toucan::Viewport", parent); - - _setMouseHoverEnabled(true); - _setMousePressEnabled(true); - - _viewModel = document->getViewModel(); - _pos = dtk::ObservableValue::create(); - _zoom = dtk::ObservableValue::create(1.F); - _frame = dtk::ObservableValue::create(true); - - _imageObserver = dtk::ValueObserver >::create( - document->observeCurrentImage(), - [this](const std::shared_ptr& value) - { - _image = value; - _setDrawUpdate(); - }); - - _zoomInObserver = dtk::ValueObserver::create( - _viewModel->observeZoomIn(), - [this](bool value) - { - if (value) - { - zoomIn(); - } - }); - - _zoomOutObserver = dtk::ValueObserver::create( - _viewModel->observeZoomOut(), - [this](bool value) - { - if (value) - { - zoomOut(); - } - }); - - _zoomResetObserver = dtk::ValueObserver::create( - _viewModel->observeZoomReset(), - [this](bool value) - { - if (value) - { - zoomReset(); - } - }); - - _frameObserver = dtk::ValueObserver::create( - _viewModel->observeFrame(), - [this](bool value) - { - setFrame(value); - }); - } - - Viewport::~Viewport() - {} - - std::shared_ptr Viewport::create( - const std::shared_ptr& context, - const std::shared_ptr& document, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new Viewport); - out->_init(context, document, parent); - return out; - } - - const dtk::V2I& Viewport::getPos() const - { - return _pos->get(); - } - - float Viewport::getZoom() const - { - return _zoom->get(); - } - - std::shared_ptr > Viewport::observePos() const - { - return _pos; - } - - std::shared_ptr > Viewport::observeZoom() const - { - return _zoom; - } - - void Viewport::setPosZoom(const dtk::V2I& pos, float zoom) - { - setFrame(false); - bool changed = _pos->setIfChanged(pos); - changed |= _zoom->setIfChanged(zoom); - if (changed) - { - _setDrawUpdate(); - } - } - - void Viewport::setZoom(float value) - { - const dtk::Box2I& g = getGeometry(); - const dtk::V2I viewportCenter(g.w() / 2, g.h() / 2); - setZoom(value, _isMouseInside() ? (_getMousePos() - g.min) : viewportCenter); - } - - void Viewport::setZoom(float zoom, const dtk::V2I& focus) - { - dtk::V2I pos = _pos->get(); - const float zoomPrev = _zoom->get(); - pos.x = focus.x + (pos.x - focus.x) * (zoom / zoomPrev); - pos.y = focus.y + (pos.y - focus.y) * (zoom / zoomPrev); - setPosZoom(pos, zoom); - } - - void Viewport::zoomIn(double amount) - { - setZoom(_zoom->get() * amount); - } - - void Viewport::zoomOut(double amount) - { - setZoom(_zoom->get() / amount); - } - - void Viewport::zoomReset() - { - setZoom(1.F); - } - - bool Viewport::getFrame() const - { - return _frame->get(); - } - - std::shared_ptr > Viewport::observeFrame() const - { - return _frame; - } - - void Viewport::setFrame(bool value) - { - if (_frame->setIfChanged(value)) - { - _viewModel->setFrame(value); - _setDrawUpdate(); - } - } - - void Viewport::drawEvent(const dtk::Box2I& drawRect, const dtk::DrawEvent& event) - { - IWidget::drawEvent(drawRect, event); - if (_image) - { - if (_frame->get()) - { - _frameUpdate(); - } - const dtk::Box2I& g = getGeometry(); - const dtk::Size2I& imageSize = _image->getSize(); - dtk::M44F vm; - vm = vm * dtk::translate(dtk::V3F(g.min.x, g.min.y, 0.F)); - vm = vm * dtk::translate(dtk::V3F(_pos->get().x, _pos->get().y, 0.F)); - vm = vm * dtk::scale(dtk::V3F(_zoom->get(), _zoom->get(), 1.F)); - const auto m = event.render->getTransform(); - event.render->setTransform(m * vm); - dtk::ImageOptions options; - options.imageFilters.magnify = dtk::ImageFilter::Nearest; - event.render->drawImage( - _image, - dtk::Box2F(0, 0, imageSize.w, imageSize.h), - dtk::Color4F(1.F, 1.F, 1.F), - options); - event.render->setTransform(m); - } - } - - void Viewport::mouseMoveEvent(dtk::MouseMoveEvent& event) - { - IWidget::mouseMoveEvent(event); - if (_isMousePressed()) - { - event.accept = true; - const dtk::V2I& mousePressPos = _getMousePressPos(); - _pos->setIfChanged(dtk::V2I( - _viewMousePress.x + (event.pos.x - mousePressPos.x), - _viewMousePress.y + (event.pos.y - mousePressPos.y))); - _setDrawUpdate(); - } - } - - void Viewport::mousePressEvent(dtk::MouseClickEvent& event) - { - IWidget::mousePressEvent(event); - if (0 == event.button && 0 == event.modifiers) - { - event.accept = true; - setFrame(false); - _viewMousePress = _pos->get(); - } - } - - void Viewport::mouseReleaseEvent(dtk::MouseClickEvent& event) - { - IWidget::mouseReleaseEvent(event); - event.accept = true; - } - - void Viewport::scrollEvent(dtk::ScrollEvent& event) - { - IWidget::scrollEvent(event); - if (0 == event.modifiers) - { - event.accept = true; - if (event.value.y > 0) - { - zoomOut(.9F); - } - else if (event.value.y < 0) - { - zoomIn(.9F); - } - } - } - - void Viewport::_frameUpdate() - { - if (_frame && _image) - { - const dtk::Box2I& g = getGeometry(); - const dtk::Size2I imageSize = _image->getSize(); - float zoom = g.w() / static_cast(imageSize.w); - if (zoom * imageSize.h > g.h()) - { - zoom = g.h() / static_cast(imageSize.h); - } - const dtk::V2I c(imageSize.w / 2, imageSize.h / 2); - const dtk::V2I pos = dtk::V2I( - g.w() / 2.F - c.x * zoom, - g.h() / 2.F - c.y * zoom); - - _pos->setIfChanged(pos); - _zoom->setIfChanged(zoom); - } - } -} diff --git a/lib/toucanEdit/Viewport.h b/lib/toucanEdit/Viewport.h deleted file mode 100644 index aa9846a..0000000 --- a/lib/toucanEdit/Viewport.h +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -#include - -#include - -namespace toucan -{ - class Document; - class ViewModel; - - class Viewport : public dtk::IWidget - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - public: - virtual ~Viewport(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - const dtk::V2I& getPos() const; - float getZoom() const; - std::shared_ptr > observePos() const; - std::shared_ptr > observeZoom() const; - void setPosZoom(const dtk::V2I&, float); - void setZoom(float); - void setZoom(float, const dtk::V2I& focus); - void zoomIn(double amount = 2.F); - void zoomOut(double amount = 2.F); - void zoomReset(); - - bool getFrame() const; - std::shared_ptr > observeFrame() const; - void setFrame(bool); - - void drawEvent(const dtk::Box2I&, const dtk::DrawEvent&) override; - void mouseMoveEvent(dtk::MouseMoveEvent&) override; - void mousePressEvent(dtk::MouseClickEvent&) override; - void mouseReleaseEvent(dtk::MouseClickEvent&) override; - void scrollEvent(dtk::ScrollEvent&) override; - - private: - void _frameUpdate(); - - std::shared_ptr _viewModel; - std::shared_ptr _image; - std::shared_ptr > _pos; - std::shared_ptr > _zoom; - std::shared_ptr > _frame; - dtk::V2I _viewMousePress; - - std::shared_ptr > > _imageObserver; - std::shared_ptr > _zoomInObserver; - std::shared_ptr > _zoomOutObserver; - std::shared_ptr > _zoomResetObserver; - std::shared_ptr > _frameObserver; - }; -} - diff --git a/lib/toucanEdit/Window.cpp b/lib/toucanEdit/Window.cpp deleted file mode 100644 index 0b19769..0000000 --- a/lib/toucanEdit/Window.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "Window.h" - -#include "App.h" -#include "DocumentTab.h" -#include "DocumentsModel.h" -#include "MenuBar.h" - -#include -#include -#include - -namespace toucan -{ - void Window::_init( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::string& name, - const dtk::Size2I& size) - { - dtk::Window::_init(context, name, size); - - _layout = dtk::VerticalLayout::create(context, shared_from_this()); - _layout->setSpacingRole(dtk::SizeRole::None); - - _menuBar = MenuBar::create( - context, - app, - std::dynamic_pointer_cast(shared_from_this()), - _layout); - dtk::Divider::create(context, dtk::Orientation::Vertical, _layout); - - _tabWidget = dtk::TabWidget::create(context, _layout); - _tabWidget->setTabsClosable(true); - _tabWidget->setVStretch(dtk::Stretch::Expanding); - - _app = app; - - std::weak_ptr appWeak(app); - _tabWidget->setCallback( - [appWeak](int index) - { - if (auto app = appWeak.lock()) - { - app->getDocumentsModel()->setCurrentIndex(index); - } - }); - _tabWidget->setTabCloseCallback( - [appWeak](int index) - { - if (auto app = appWeak.lock()) - { - app->getDocumentsModel()->close(index); - } - }); - - _documentsObserver = dtk::ListObserver >::create( - app->getDocumentsModel()->observeDocuments(), - [this](const std::vector >& documents) - { - _documents = documents; - }); - - _addObserver = dtk::ValueObserver::create( - app->getDocumentsModel()->observeAdd(), - [this, appWeak](int index) - { - if (index >= 0 && index < _documents.size()) - { - auto document = _documents[index]; - auto context = _getContext().lock(); - auto app = appWeak.lock(); - auto tab = DocumentTab::create(context, app, document); - _tabWidget->addTab( - dtk::elide(document->getPath().filename().string()), - tab, - document->getPath().string()); - _documentTabs[document] = tab; - } - }); - - _removeObserver = dtk::ValueObserver::create( - app->getDocumentsModel()->observeRemove(), - [this, appWeak](int index) - { - if (index >= 0 && index < _documents.size()) - { - auto document = _documents[index]; - const auto i = _documentTabs.find(document); - if (i != _documentTabs.end()) - { - _tabWidget->removeTab(i->second); - _documentTabs.erase(i); - } - } - }); - - _documentObserver = dtk::ValueObserver::create( - app->getDocumentsModel()->observeCurrentIndex(), - [this](int index) - { - _tabWidget->setCurrentTab(index); - }); - } - - Window::~Window() - {} - - std::shared_ptr Window::create( - const std::shared_ptr& context, - const std::shared_ptr& app, - const std::string& name, - const dtk::Size2I& size) - { - auto out = std::shared_ptr(new Window); - out->_init(context, app, name, size); - return out; - } - - void Window::setGeometry(const dtk::Box2I& value) - { - dtk::Window::setGeometry(value); - _layout->setGeometry(value); - } - - void Window::sizeHintEvent(const dtk::SizeHintEvent& event) - { - dtk::Window::sizeHintEvent(event); - _setSizeHint(_layout->getSizeHint()); - } - - void Window::keyPressEvent(dtk::KeyEvent& event) - { - event.accept = _menuBar->shortcut(event.key, event.modifiers); - } - - void Window::keyReleaseEvent(dtk::KeyEvent& event) - { - event.accept = true; - } - - void Window::_drop(const std::vector& value) - { - if (auto context = _getContext().lock()) - { - if (auto app = _app.lock()) - { - std::vector errors; - for (const auto& i : value) - { - try - { - app->getDocumentsModel()->open(i); - } - catch (const std::exception& e) - { - errors.push_back(e.what()); - } - } - if (!errors.empty()) - { - context->getSystem()->message( - "ERROR", - dtk::join(errors, '\n'), - getWindow()); - } - } - } - } -} diff --git a/lib/toucanEdit/Window.h b/lib/toucanEdit/Window.h deleted file mode 100644 index 5b848c7..0000000 --- a/lib/toucanEdit/Window.h +++ /dev/null @@ -1,59 +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 Document; - class DocumentTab; - class MenuBar; - - class Window : public dtk::Window - { - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::string& name, - const dtk::Size2I&); - - public: - virtual ~Window(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::string& name, - const dtk::Size2I&); - - void setGeometry(const dtk::Box2I&) override; - void sizeHintEvent(const dtk::SizeHintEvent&) override; - void keyPressEvent(dtk::KeyEvent&) override; - void keyReleaseEvent(dtk::KeyEvent&) override; - - protected: - void _drop(const std::vector&) override; - - private: - std::weak_ptr _app; - std::vector > _documents; - - std::shared_ptr _layout; - std::shared_ptr _menuBar; - std::shared_ptr _tabWidget; - std::map, std::shared_ptr > _documentTabs; - - std::shared_ptr > > _documentsObserver; - std::shared_ptr > _addObserver; - std::shared_ptr > _removeObserver; - std::shared_ptr > _documentObserver; - }; -} - diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2b875f1..9f39a36 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,2 @@ add_subdirectory(toucanTest) -if(toucan_EDIT) - add_subdirectory(toucanEditTest) -endif() add_subdirectory(toucan-test) diff --git a/tests/toucanEditTest/CMakeLists.txt b/tests/toucanEditTest/CMakeLists.txt deleted file mode 100644 index b8996b3..0000000 --- a/tests/toucanEditTest/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(HEADERS - StackTest.h) - -set(SOURCE - StackTest.cpp) - -add_library(toucanEditTest ${SOURCE} ${HEADERS}) -target_link_libraries(toucanEditTest toucanEdit) -set_target_properties(toucanEditTest PROPERTIES FOLDER tests) diff --git a/tests/toucanEditTest/StackTest.cpp b/tests/toucanEditTest/StackTest.cpp deleted file mode 100644 index 5d0dbe0..0000000 --- a/tests/toucanEditTest/StackTest.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#include "StackTest.h" - -#include -#include -#include - -#include - -namespace toucan -{ - void stackTest() - { - { - auto stack = std::make_shared(); - assert(stack == stack->getRoot()); - - auto track = std::make_shared(TrackKind::video); - stack->addChild(track); - assert(stack == track->getRoot()); - - auto clip = std::make_shared(); - assert(!clip->getRoot()); - track->addChild(clip); - assert(stack == clip->getRoot()); - } - { - auto track = std::make_shared(TrackKind::video); - track->setRange(OTIO_NS::TimeRange( - OTIO_NS::RationalTime(0.0, 24.0), - OTIO_NS::RationalTime(48.0, 24.0))); - - auto clip = std::make_shared(); - clip->setRange(OTIO_NS::TimeRange( - OTIO_NS::RationalTime(0.0, 24.0), - OTIO_NS::RationalTime(24.0, 24.0))); - track->addChild(clip); - - auto clip2 = std::make_shared(); - clip2->setRange(OTIO_NS::TimeRange( - OTIO_NS::RationalTime(0.0, 24.0), - OTIO_NS::RationalTime(24.0, 24.0))); - track->addChild(clip2); - - OTIO_NS::TimeRange range = track->getChildRange(clip); - assert(OTIO_NS::TimeRange( - OTIO_NS::RationalTime(0.0, 24.0), - OTIO_NS::RationalTime(24.0, 24.0)) == range); - - range = track->getChildRange(clip2); - assert(OTIO_NS::TimeRange( - OTIO_NS::RationalTime(24.0, 24.0), - OTIO_NS::RationalTime(24.0, 24.0)) == range); - } - { - auto track = std::make_shared(TrackKind::video); - track->setRange(OTIO_NS::TimeRange( - OTIO_NS::RationalTime(0.0, 24.0), - OTIO_NS::RationalTime(48.0, 24.0))); - - auto clip = std::make_shared(); - clip->setRange(OTIO_NS::TimeRange( - OTIO_NS::RationalTime(0.0, 24.0), - OTIO_NS::RationalTime(24.0, 24.0))); - track->addChild(clip); - - auto clip2 = std::make_shared(); - clip2->setRange(OTIO_NS::TimeRange( - OTIO_NS::RationalTime(0.0, 24.0), - OTIO_NS::RationalTime(24.0, 24.0))); - track->addChild(clip2); - - OTIO_NS::RationalTime t = track->transform( - OTIO_NS::RationalTime(0.0, 24.0), - clip); - assert(OTIO_NS::RationalTime(0.0, 24.0) == t); - - t = track->transform( - OTIO_NS::RationalTime(24.0, 24.0), - clip2); - assert(OTIO_NS::RationalTime(0.0, 24.0) == t); - - t = clip->transform( - OTIO_NS::RationalTime(0.0, 24.0), - track); - assert(OTIO_NS::RationalTime(0.0, 24.0) == t); - - t = clip2->transform( - OTIO_NS::RationalTime(0.0, 24.0), - track); - assert(OTIO_NS::RationalTime(24.0, 24.0) == t); - } - } -} diff --git a/tests/toucanEditTest/StackTest.h b/tests/toucanEditTest/StackTest.h deleted file mode 100644 index 4a121c6..0000000 --- a/tests/toucanEditTest/StackTest.h +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Contributors to the toucan project. - -#pragma once - -namespace toucan -{ - void stackTest(); -}