From f4a485919cd6dbaf2e4a078898a4caeba3e3a2ff Mon Sep 17 00:00:00 2001 From: Darby Johnston Date: Wed, 3 Jul 2024 18:36:17 -0700 Subject: [PATCH] Refactoring --- lib/tlPlay/CMakeLists.txt | 5 +- lib/tlPlay/Viewport.cpp | 164 ++++++++++++++++++++++++-- lib/tlPlay/Viewport.h | 8 +- lib/tlPlay/ViewportColorWidget.cpp | 158 +++++++++++++++++++++++++ lib/tlPlay/ViewportPrivate.h | 44 +++++++ lib/tlPlayApp/CMakeLists.txt | 2 - lib/tlPlayApp/ColorPickerTool.cpp | 116 ------------------ lib/tlPlayApp/ColorPickerTool.h | 47 -------- lib/tlPlayApp/SeparateAudioWidget.cpp | 4 +- lib/tlPlayApp/Tools.cpp | 7 +- lib/tlPlayApp/Tools.h | 1 - lib/tlPlayApp/ToolsWidget.cpp | 13 -- lib/tlPlayApp/ToolsWidget.h | 2 - lib/tlPlayQtApp/AudioTool.cpp | 2 +- lib/tlPlayQtApp/CMakeLists.txt | 2 - lib/tlPlayQtApp/ColorPickerTool.cpp | 112 ------------------ lib/tlPlayQtApp/ColorPickerTool.h | 42 ------- lib/tlPlayQtApp/DevicesTool.cpp | 2 +- lib/tlPlayQtApp/InfoTool.cpp | 2 +- lib/tlPlayQtApp/MainWindow.cpp | 9 -- lib/tlPlayQtApp/MessagesTool.cpp | 2 +- lib/tlPlayQtApp/SystemLogTool.cpp | 2 +- lib/tlTimelineUI/TimelineViewport.cpp | 64 +++++----- lib/tlTimelineUI/TimelineViewport.h | 7 +- lib/tlUI/FileBrowserWidget.cpp | 2 +- lib/tlUI/Spacer.cpp | 10 +- lib/tlUI/Spacer.h | 4 +- 27 files changed, 420 insertions(+), 413 deletions(-) create mode 100644 lib/tlPlay/ViewportColorWidget.cpp create mode 100644 lib/tlPlay/ViewportPrivate.h delete mode 100644 lib/tlPlayApp/ColorPickerTool.cpp delete mode 100644 lib/tlPlayApp/ColorPickerTool.h delete mode 100644 lib/tlPlayQtApp/ColorPickerTool.cpp delete mode 100644 lib/tlPlayQtApp/ColorPickerTool.h diff --git a/lib/tlPlay/CMakeLists.txt b/lib/tlPlay/CMakeLists.txt index f04af1f3a..0fdc70e30 100644 --- a/lib/tlPlay/CMakeLists.txt +++ b/lib/tlPlay/CMakeLists.txt @@ -12,6 +12,8 @@ set(HEADERS Util.h Viewport.h ViewportModel.h) +set(PRIVATE_HEADERS + ViewportPrivate.h) set(SOURCE App.cpp @@ -25,9 +27,10 @@ set(SOURCE Settings.cpp Util.cpp Viewport.cpp + ViewportColorWidget.cpp ViewportModel.cpp) -add_library(tlPlay ${HEADERS} ${SOURCE}) +add_library(tlPlay ${HEADERS} ${PRIVATE_HEADERS} ${SOURCE}) target_link_libraries(tlPlay tlTimelineUI tlDevice) set_target_properties(tlPlay PROPERTIES FOLDER lib) set_target_properties(tlPlay PROPERTIES PUBLIC_HEADER "${HEADERS}") diff --git a/lib/tlPlay/Viewport.cpp b/lib/tlPlay/Viewport.cpp index 6d834ed61..22992cfa1 100644 --- a/lib/tlPlay/Viewport.cpp +++ b/lib/tlPlay/Viewport.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2021-2024 Darby Johnston // All rights reserved. -#include +#include #include #include @@ -20,12 +20,32 @@ namespace tl size_t droppedFrames = 0; std::shared_ptr fpsLabel; - std::shared_ptr colorPickerLabel; std::shared_ptr hudLayout; + struct ColorPicker + { + image::Color4f color; + math::Vector2i pos; + std::shared_ptr widget; + }; + std::vector colorPickers; + + enum class MouseMode + { + None, + ColorPicker, + DragWidget + }; + struct MouseData + { + MouseMode mode = MouseMode::None; + size_t index = 0; + math::Vector2i offset; + }; + MouseData mouse; std::shared_ptr > fpsObserver; std::shared_ptr > droppedFramesObserver; - std::shared_ptr > colorPickerObserver; + std::shared_ptr > colorPickersObserver; }; void Viewport::_init( @@ -38,11 +58,10 @@ namespace tl p.hud = observer::Value::create(false); p.fpsLabel = ui::Label::create(context); + p.fpsLabel->setFontRole(ui::FontRole::Mono); p.fpsLabel->setMarginRole(ui::SizeRole::MarginInside); p.fpsLabel->setBackgroundRole(ui::ColorRole::Base); - p.colorPickerLabel = ui::Label::create(context); - p.hudLayout = ui::GridLayout::create(context, shared_from_this()); p.hudLayout->setMarginRole(ui::SizeRole::MarginSmall); p.fpsLabel->setParent(p.hudLayout); @@ -54,19 +73,24 @@ namespace tl [this](double value) { _p->fps = value; - _textUpdate(); + _hudUpdate(); }); p.droppedFramesObserver = observer::ValueObserver::create( observeDroppedFrames(), [this](size_t value) { _p->droppedFrames = value; - _textUpdate(); + _hudUpdate(); }); - p.colorPickerObserver = observer::ValueObserver::create( - observeColorPicker(), - [this](const image::Color4f& value) + p.colorPickersObserver = observer::ListObserver::create( + observeColorPickers(), + [this](const std::vector& value) { + for (size_t i = 0; i < value.size() && i < _p->colorPickers.size(); ++i) + { + _p->colorPickers[i].color = value[i]; + } + _colorWidgetsUpdate(); }); } @@ -110,6 +134,33 @@ namespace tl TimelineViewport::setGeometry(value); TLRENDER_P(); p.hudLayout->setGeometry(value); + for (const auto& colorPicker : p.colorPickers) + { + math::Size2i sizeHint = colorPicker.widget->getSizeHint(); + colorPicker.widget->setGeometry(math::Box2i( + colorPicker.pos.x, + colorPicker.pos.y, + sizeHint.w, + sizeHint.h)); + } + } + + void Viewport::childRemovedEvent(const ui::ChildEvent& event) + { + TimelineViewport::childRemovedEvent(event); + TLRENDER_P(); + const auto i = std::find_if( + p.colorPickers.begin(), + p.colorPickers.end(), + [event](const Private::ColorPicker& value) + { + return event.child == value.widget; + }); + if (i != p.colorPickers.end()) + { + p.colorPickers.erase(i); + _colorPickersUpdate(); + } } void Viewport::sizeHintEvent(const ui::SizeHintEvent& event) @@ -119,7 +170,78 @@ namespace tl _sizeHint = p.hudLayout->getSizeHint(); } - void Viewport::_textUpdate() + void Viewport::mouseMoveEvent(ui::MouseMoveEvent& event) + { + TimelineViewport::mouseMoveEvent(event); + TLRENDER_P(); + switch (p.mouse.mode) + { + case Private::MouseMode::ColorPicker: + if (!p.colorPickers.empty()) + { + p.colorPickers.back().pos = event.pos; + _colorPickersUpdate(); + _updates |= ui::Update::Size; + _updates |= ui::Update::Draw; + } + break; + case Private::MouseMode::DragWidget: + if (p.mouse.index < p.colorPickers.size()) + { + p.colorPickers[p.mouse.index].pos = event.pos - p.mouse.offset; + _colorPickersUpdate(); + _updates |= ui::Update::Size; + _updates |= ui::Update::Draw; + } + break; + default: break; + } + } + + void Viewport::mousePressEvent(ui::MouseClickEvent& event) + { + TimelineViewport::mousePressEvent(event); + TLRENDER_P(); + takeKeyFocus(); + if (0 == event.button) + { + for (size_t i = 0; i < p.colorPickers.size(); ++i) + { + if (p.colorPickers[i].widget->getGeometry().contains(event.pos)) + { + p.mouse.mode = Private::MouseMode::DragWidget; + p.mouse.index = i; + p.mouse.offset = event.pos - p.colorPickers[i].widget->getGeometry().min; + } + } + } + if (Private::MouseMode::None == p.mouse.mode && + 0 == event.button && + event.modifiers & static_cast(ui::KeyModifier::Shift)) + { + if (auto context = _context.lock()) + { + p.mouse.mode = Private::MouseMode::ColorPicker; + p.colorPickers.push_back({ + image::Color4f(), + event.pos, + ViewportColorWidget::create(context, shared_from_this()) }); + _colorPickersUpdate(); + _colorWidgetsUpdate(); + _updates |= ui::Update::Size; + _updates |= ui::Update::Draw; + } + } + } + + void Viewport::mouseReleaseEvent(ui::MouseClickEvent& event) + { + TimelineViewport::mouseReleaseEvent(event); + TLRENDER_P(); + p.mouse = Private::MouseData(); + } + + void Viewport::_hudUpdate() { TLRENDER_P(); p.fpsLabel->setText( @@ -127,5 +249,25 @@ namespace tl arg(p.fps, 2, 4). arg(p.droppedFrames)); } + + void Viewport::_colorPickersUpdate() + { + TLRENDER_P(); + std::vector colorPickers; + for (const auto& colorPicker : p.colorPickers) + { + colorPickers.push_back(colorPicker.pos); + } + setColorPickers(colorPickers); + } + + void Viewport::_colorWidgetsUpdate() + { + TLRENDER_P(); + for (const auto& colorPicker : p.colorPickers) + { + colorPicker.widget->setColor(colorPicker.color); + } + } } } diff --git a/lib/tlPlay/Viewport.h b/lib/tlPlay/Viewport.h index e321276b8..766f3f888 100644 --- a/lib/tlPlay/Viewport.h +++ b/lib/tlPlay/Viewport.h @@ -38,10 +38,16 @@ namespace tl void setHUD(bool); void setGeometry(const math::Box2i&) override; + void childRemovedEvent(const ui::ChildEvent&) override; void sizeHintEvent(const ui::SizeHintEvent&) override; + void mouseMoveEvent(ui::MouseMoveEvent&) override; + void mousePressEvent(ui::MouseClickEvent&) override; + void mouseReleaseEvent(ui::MouseClickEvent&) override; private: - void _textUpdate(); + void _hudUpdate(); + void _colorPickersUpdate(); + void _colorWidgetsUpdate(); TLRENDER_PRIVATE(); }; diff --git a/lib/tlPlay/ViewportColorWidget.cpp b/lib/tlPlay/ViewportColorWidget.cpp new file mode 100644 index 000000000..f387b4c5e --- /dev/null +++ b/lib/tlPlay/ViewportColorWidget.cpp @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2021-2024 Darby Johnston +// All rights reserved. + +#include + +#include +#include +#include +#include +#include + +#include + +namespace tl +{ + namespace play + { + struct ViewportColorWidget::Private + { + image::Color4f color; + + std::shared_ptr closeButton; + std::shared_ptr swatch; + std::shared_ptr label; + std::shared_ptr layout; + + struct SizeData + { + int margin = 0; + int border = 0; + }; + SizeData size; + }; + + void ViewportColorWidget::_init( + const std::shared_ptr& context, + const std::shared_ptr& parent) + { + IWidget::_init("tl::play::ViewportColorWidget", context, parent); + TLRENDER_P(); + + setBackgroundRole(ui::ColorRole::Window); + + p.closeButton = ui::ToolButton::create(context); + p.closeButton->setIcon("Close"); + + p.swatch = ui::ColorSwatch::create(context); + + p.label = ui::Label::create(context, shared_from_this()); + p.label->setFontRole(ui::FontRole::Mono); + + p.layout = ui::HorizontalLayout::create(context, shared_from_this()); + p.layout->setSpacingRole(ui::SizeRole::None); + auto hLayout = ui::HorizontalLayout::create(context, p.layout); + hLayout->setMarginRole(ui::SizeRole::MarginInside); + hLayout->setSpacingRole(ui::SizeRole::SpacingTool); + p.swatch->setParent(hLayout); + p.label->setParent(hLayout); + auto vLayout = ui::VerticalLayout::create(context, p.layout); + vLayout->setSpacingRole(ui::SizeRole::None); + p.closeButton->setParent(vLayout); + + _colorUpdate(); + + auto weak = std::weak_ptr( + std::dynamic_pointer_cast(shared_from_this())); + p.closeButton->setClickedCallback( + [weak] + { + if (auto widget = weak.lock()) + { + widget->setParent(nullptr); + } + }); + } + + ViewportColorWidget::ViewportColorWidget() : + _p(new Private) + {} + + ViewportColorWidget::~ViewportColorWidget() + {} + + std::shared_ptr ViewportColorWidget::create( + const std::shared_ptr& context, + const std::shared_ptr& parent) + { + auto out = std::shared_ptr(new ViewportColorWidget); + out->_init(context, parent); + return out; + } + + void ViewportColorWidget::setColor(const image::Color4f& value) + { + TLRENDER_P(); + if (value == p.color) + return; + p.color = value; + _colorUpdate(); + } + + void ViewportColorWidget::setGeometry(const math::Box2i& value) + { + IWidget::setGeometry(value); + TLRENDER_P(); + p.layout->setGeometry(value.margin(-p.size.border)); + } + + void ViewportColorWidget::sizeHintEvent(const ui::SizeHintEvent& event) + { + IWidget::sizeHintEvent(event); + TLRENDER_P(); + p.size.margin = event.style->getSizeRole(ui::SizeRole::MarginSmall, event.displayScale); + p.size.border = event.style->getSizeRole(ui::SizeRole::Border, event.displayScale); + _sizeHint = p.layout->getSizeHint() + p.size.border * 2; + } + + void ViewportColorWidget::drawEvent(const math::Box2i& drawRect, const ui::DrawEvent& event) + { + IWidget::drawEvent(drawRect, event); + TLRENDER_P(); + + const math::Box2i& g = getGeometry(); + event.render->drawMesh( + ui::border(g, p.size.border), + math::Vector2i(), + event.style->getColorRole(ui::ColorRole::Border)); + + const math::Box2i g2 = g.margin(-p.size.border); + geom::TriangleMesh2 mesh; + mesh.v.push_back(math::Vector2f(g2.min.x, g2.min.y)); + mesh.v.push_back(math::Vector2f(g2.min.x + p.size.margin, g2.min.y)); + mesh.v.push_back(math::Vector2f(g2.min.x, g2.min.y + p.size.margin)); + mesh.triangles.push_back({ 1, 2, 3 }); + event.render->drawMesh( + mesh, + math::Vector2i(), + event.style->getColorRole(ui::ColorRole::Text)); + } + + void ViewportColorWidget::_colorUpdate() + { + TLRENDER_P(); + p.swatch->setColor(p.color); + p.label->setText( + string::Format( + "R:{0}\n" + "G:{1}\n" + "B:{2}\n" + "A:{3}"). + arg(p.color.r, 2). + arg(p.color.g, 2). + arg(p.color.b, 2). + arg(p.color.a, 2)); + } + } +} diff --git a/lib/tlPlay/ViewportPrivate.h b/lib/tlPlay/ViewportPrivate.h new file mode 100644 index 000000000..d5250bdce --- /dev/null +++ b/lib/tlPlay/ViewportPrivate.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2021-2024 Darby Johnston +// All rights reserved. + +#pragma once + +#include + +namespace tl +{ + namespace play + { + class ViewportColorWidget : public ui::IWidget + { + TLRENDER_NON_COPYABLE(ViewportColorWidget); + + protected: + void _init( + const std::shared_ptr&, + const std::shared_ptr& parent); + + ViewportColorWidget(); + + public: + virtual ~ViewportColorWidget(); + + static std::shared_ptr create( + const std::shared_ptr&, + const std::shared_ptr& parent = nullptr); + + void setColor(const image::Color4f&); + + void setGeometry(const math::Box2i&) override; + void sizeHintEvent(const ui::SizeHintEvent&) override; + void drawEvent(const math::Box2i&, const ui::DrawEvent&) override; + + private: + void _colorUpdate(); + + TLRENDER_PRIVATE(); + }; + } +} + diff --git a/lib/tlPlayApp/CMakeLists.txt b/lib/tlPlayApp/CMakeLists.txt index ae40f8e48..18b78e411 100644 --- a/lib/tlPlayApp/CMakeLists.txt +++ b/lib/tlPlayApp/CMakeLists.txt @@ -4,7 +4,6 @@ set(HEADERS AudioMenu.h AudioPopup.h AudioTool.h - ColorPickerTool.h ColorTool.h CompareActions.h CompareMenu.h @@ -57,7 +56,6 @@ set(SOURCE AudioMenu.cpp AudioPopup.cpp AudioTool.cpp - ColorPickerTool.cpp ColorTool.cpp CompareActions.cpp CompareMenu.cpp diff --git a/lib/tlPlayApp/ColorPickerTool.cpp b/lib/tlPlayApp/ColorPickerTool.cpp deleted file mode 100644 index 51a648426..000000000 --- a/lib/tlPlayApp/ColorPickerTool.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2021-2024 Darby Johnston -// All rights reserved. - -#include - -#include - -#include - -#include -#include -#include -#include - -#include - -namespace tl -{ - namespace play_app - { - struct ColorPickerTool::Private - { - image::Color4f color; - std::shared_ptr swatch; - std::vector > labels; - std::shared_ptr layout; - std::shared_ptr > colorPickerObserver; - }; - - void ColorPickerTool::_init( - const std::shared_ptr& mainWindow, - const std::shared_ptr& app, - const std::shared_ptr& context, - const std::shared_ptr& parent) - { - IToolWidget::_init( - Tool::ColorPicker, - "tl::play_app::ColorPickerTool", - app, - context, - parent); - TLRENDER_P(); - - p.swatch = ui::ColorSwatch::create(context); - p.swatch->setSizeRole(ui::SizeRole::SwatchLarge); - - p.labels.push_back(ui::Label::create(context)); - p.labels.push_back(ui::Label::create(context)); - p.labels.push_back(ui::Label::create(context)); - p.labels.push_back(ui::Label::create(context)); - - p.layout = ui::VerticalLayout::create(context); - p.layout->setMarginRole(ui::SizeRole::MarginSmall); - p.layout->setSpacingRole(ui::SizeRole::SpacingSmall); - p.swatch->setParent(p.layout); - auto gridLayout = ui::GridLayout::create(context, p.layout); - gridLayout->setSpacingRole(ui::SizeRole::SpacingSmall); - auto label = ui::Label::create("Red:", context, gridLayout); - gridLayout->setGridPos(label, 0, 0); - p.labels[0]->setParent(gridLayout); - gridLayout->setGridPos(p.labels[0], 0, 1); - label = ui::Label::create("Green:", context, gridLayout); - gridLayout->setGridPos(label, 1, 0); - p.labels[1]->setParent(gridLayout); - gridLayout->setGridPos(p.labels[1], 1, 1); - label = ui::Label::create("Blue:", context, gridLayout); - gridLayout->setGridPos(label, 2, 0); - p.labels[2]->setParent(gridLayout); - gridLayout->setGridPos(p.labels[2], 2, 1); - label = ui::Label::create("Alpha:", context, gridLayout); - gridLayout->setGridPos(label, 3, 0); - p.labels[3]->setParent(gridLayout); - gridLayout->setGridPos(p.labels[3], 3, 1); - _setWidget(p.layout); - - _widgetUpdate(); - - p.colorPickerObserver = observer::ValueObserver::create( - mainWindow->getViewport()->observeColorPicker(), - [this](const image::Color4f& value) - { - _p->color = value; - _widgetUpdate(); - }); - } - - ColorPickerTool::ColorPickerTool() : - _p(new Private) - {} - - ColorPickerTool::~ColorPickerTool() - {} - - std::shared_ptr ColorPickerTool::create( - const std::shared_ptr& mainWindow, - const std::shared_ptr& app, - const std::shared_ptr& context, - const std::shared_ptr& parent) - { - auto out = std::shared_ptr(new ColorPickerTool); - out->_init(mainWindow, app, context, parent); - return out; - } - - void ColorPickerTool::_widgetUpdate() - { - TLRENDER_P(); - p.swatch->setColor(p.color); - p.labels[0]->setText(string::Format("{0}").arg(p.color.r)); - p.labels[1]->setText(string::Format("{0}").arg(p.color.g)); - p.labels[2]->setText(string::Format("{0}").arg(p.color.b)); - p.labels[3]->setText(string::Format("{0}").arg(p.color.a)); - } - } -} diff --git a/lib/tlPlayApp/ColorPickerTool.h b/lib/tlPlayApp/ColorPickerTool.h deleted file mode 100644 index 293440bae..000000000 --- a/lib/tlPlayApp/ColorPickerTool.h +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2021-2024 Darby Johnston -// All rights reserved. - -#pragma once - -#include - -#include - -namespace tl -{ - namespace play_app - { - class App; - class MainWindow; - - //! Color picker tool. - class ColorPickerTool : public IToolWidget - { - TLRENDER_NON_COPYABLE(ColorPickerTool); - - protected: - void _init( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent); - - ColorPickerTool(); - - public: - virtual ~ColorPickerTool(); - - static std::shared_ptr create( - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr&, - const std::shared_ptr& parent = nullptr); - - private: - void _widgetUpdate(); - - TLRENDER_PRIVATE(); - }; - } -} diff --git a/lib/tlPlayApp/SeparateAudioWidget.cpp b/lib/tlPlayApp/SeparateAudioWidget.cpp index 6b113bd93..c4dfeea15 100644 --- a/lib/tlPlayApp/SeparateAudioWidget.cpp +++ b/lib/tlPlayApp/SeparateAudioWidget.cpp @@ -63,14 +63,14 @@ namespace tl groupBox = ui::GroupBox::create("Audio", context, vLayout); p.audioFileEdit->setParent(groupBox); auto spacer = ui::Spacer::create(ui::Orientation::Vertical, context, vLayout); - spacer->setSpacingRole(ui::SizeRole::None); + spacer->setSizeRole(ui::SizeRole::None); spacer->setVStretch(ui::Stretch::Expanding); ui::Divider::create(ui::Orientation::Vertical, context, p.layout); auto hLayout = ui::HorizontalLayout::create(context, p.layout); hLayout->setMarginRole(ui::SizeRole::MarginSmall); hLayout->setSpacingRole(ui::SizeRole::SpacingSmall); spacer = ui::Spacer::create(ui::Orientation::Horizontal, context, hLayout); - spacer->setSpacingRole(ui::SizeRole::None); + spacer->setSizeRole(ui::SizeRole::None); spacer->setHStretch(ui::Stretch::Expanding); p.okButton->setParent(hLayout); p.cancelButton->setParent(hLayout); diff --git a/lib/tlPlayApp/Tools.cpp b/lib/tlPlayApp/Tools.cpp index 9b8a3570e..a0a97b075 100644 --- a/lib/tlPlayApp/Tools.cpp +++ b/lib/tlPlayApp/Tools.cpp @@ -19,7 +19,6 @@ namespace tl "Files", "View", "Color", - "ColorPicker", "Info", "Audio", "Devices", @@ -35,7 +34,6 @@ namespace tl "Files", "View", "Color", - "Color Picker", "Information", "Audio", "Devices", @@ -53,7 +51,6 @@ namespace tl "Files", "View", "Color", - "ColorPicker", "Info", "Audio", "Devices", @@ -76,8 +73,7 @@ namespace tl ui::Key::F6, ui::Key::F7, ui::Key::F8, - ui::Key::F9, - ui::Key::F10 + ui::Key::F9 }; return data[static_cast(value)]; } @@ -89,7 +85,6 @@ namespace tl Tool::Files, Tool::View, Tool::Color, - Tool::ColorPicker, Tool::Info, Tool::Audio, Tool::Devices, diff --git a/lib/tlPlayApp/Tools.h b/lib/tlPlayApp/Tools.h index dee0c4f84..8ff0a4120 100644 --- a/lib/tlPlayApp/Tools.h +++ b/lib/tlPlayApp/Tools.h @@ -20,7 +20,6 @@ namespace tl Files, View, Color, - ColorPicker, Info, Audio, Devices, diff --git a/lib/tlPlayApp/ToolsWidget.cpp b/lib/tlPlayApp/ToolsWidget.cpp index 387042b53..16dac4d33 100644 --- a/lib/tlPlayApp/ToolsWidget.cpp +++ b/lib/tlPlayApp/ToolsWidget.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -44,7 +43,6 @@ namespace tl p.toolWidgets[Tool::Audio] = AudioTool::create(app, context); p.toolWidgets[Tool::Color] = ColorTool::create(app, context); - p.toolWidgets[Tool::ColorPicker] = ColorPickerTool::create(mainWindow, app, context); p.toolWidgets[Tool::Devices] = DevicesTool::create(app, context); p.toolWidgets[Tool::Files] = FilesTool::create(app, context); p.toolWidgets[Tool::Info] = InfoTool::create(app, context); @@ -97,16 +95,5 @@ namespace tl IWidget::sizeHintEvent(event); _sizeHint = _p->layout->getSizeHint(); } - - std::map ToolsWidget::_getToolsVisible() const - { - TLRENDER_P(); - std::map out; - for (const auto& i : p.toolWidgets) - { - out[i.first] = i.second->isVisible(false); - } - return out; - } } } diff --git a/lib/tlPlayApp/ToolsWidget.h b/lib/tlPlayApp/ToolsWidget.h index 4212359d2..6af730a4e 100644 --- a/lib/tlPlayApp/ToolsWidget.h +++ b/lib/tlPlayApp/ToolsWidget.h @@ -43,8 +43,6 @@ namespace tl void sizeHintEvent(const ui::SizeHintEvent&) override; private: - std::map _getToolsVisible() const; - TLRENDER_PRIVATE(); }; } diff --git a/lib/tlPlayQtApp/AudioTool.cpp b/lib/tlPlayQtApp/AudioTool.cpp index 758ff3010..d2393e6a3 100644 --- a/lib/tlPlayQtApp/AudioTool.cpp +++ b/lib/tlPlayQtApp/AudioTool.cpp @@ -97,7 +97,7 @@ namespace tl setWidget(audioTool); toggleViewAction()->setIcon(QIcon(":/Icons/Audio.svg")); - toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F6)); + toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F5)); toggleViewAction()->setToolTip(tr("Show audio controls")); } } diff --git a/lib/tlPlayQtApp/CMakeLists.txt b/lib/tlPlayQtApp/CMakeLists.txt index 3adf477bd..9bfca8a60 100644 --- a/lib/tlPlayQtApp/CMakeLists.txt +++ b/lib/tlPlayQtApp/CMakeLists.txt @@ -2,7 +2,6 @@ set(HEADERS App.h AudioActions.h AudioTool.h - ColorPickerTool.h ColorTool.h CompareActions.h DevicesTool.h @@ -33,7 +32,6 @@ set(SOURCE App.cpp AudioActions.cpp AudioTool.cpp - ColorPickerTool.cpp ColorTool.cpp CompareActions.cpp DevicesTool.cpp diff --git a/lib/tlPlayQtApp/ColorPickerTool.cpp b/lib/tlPlayQtApp/ColorPickerTool.cpp deleted file mode 100644 index a6ca6cdc2..000000000 --- a/lib/tlPlayQtApp/ColorPickerTool.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2021-2024 Darby Johnston -// All rights reserved. - -#include - -#include -#include -#include - -#include - -#include - -#include - -#include -#include -#include -#include - -namespace tl -{ - namespace play_qt - { - struct ColorPickerTool::Private - { - image::Color4f color; - qtwidget::ColorSwatch* colorSwatch = nullptr; - std::vector labels; - std::shared_ptr > observer; - }; - - ColorPickerTool::ColorPickerTool(MainWindow* mainWindow, App* app, QWidget* parent) : - IToolWidget(app, parent), - _p(new Private) - { - TLRENDER_P(); - - p.colorSwatch = new qtwidget::ColorSwatch; - p.colorSwatch->setSwatchSize(40); - - p.labels.push_back(new QLabel); - p.labels.push_back(new QLabel); - p.labels.push_back(new QLabel); - p.labels.push_back(new QLabel); - - auto widget = new QWidget; - auto layout = new QVBoxLayout; - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(p.colorSwatch); - auto formLayout = new QFormLayout; - layout->addLayout(formLayout); - formLayout->addRow("Red:", p.labels[0]); - formLayout->addRow("Green:", p.labels[1]); - formLayout->addRow("Blue:", p.labels[2]); - formLayout->addRow("Alpha:", p.labels[3]); - widget->setLayout(layout); - addWidget(widget); - - addStretch(); - - _widgetUpdate(); - - p.observer = observer::ValueObserver::create( - mainWindow->viewport()->observeColorPicker(), - [this](const image::Color4f& value) - { - _p->color = value; - _widgetUpdate(); - }); - } - - ColorPickerTool::~ColorPickerTool() - {} - - void ColorPickerTool::_widgetUpdate() - { - TLRENDER_P(); - p.colorSwatch->setColor(p.color); - p.labels[0]->setText(QString::fromUtf8( - std::string(string::Format("{0}").arg(p.color.r)).c_str())); - p.labels[1]->setText(QString::fromUtf8( - std::string(string::Format("{0}").arg(p.color.g)).c_str())); - p.labels[2]->setText(QString::fromUtf8( - std::string(string::Format("{0}").arg(p.color.b)).c_str())); - p.labels[3]->setText(QString::fromUtf8( - std::string(string::Format("{0}").arg(p.color.a)).c_str())); - } - - ColorPickerDockWidget::ColorPickerDockWidget( - ColorPickerTool* colorPickerTool, - QWidget* parent) - { - setObjectName("ColorPickerTool"); - setWindowTitle(tr("Color Picker")); - setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - - auto dockTitleBar = new DockTitleBar; - dockTitleBar->setText(tr("Color Picker")); - dockTitleBar->setIcon(QIcon(":/Icons/ColorPicker.svg")); - auto dockWidget = new QDockWidget; - setTitleBarWidget(dockTitleBar); - - setWidget(colorPickerTool); - - toggleViewAction()->setIcon(QIcon(":/Icons/ColorPicker.svg")); - toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F4)); - toggleViewAction()->setToolTip(tr("Show color picker")); - } - } -} diff --git a/lib/tlPlayQtApp/ColorPickerTool.h b/lib/tlPlayQtApp/ColorPickerTool.h deleted file mode 100644 index f75aac943..000000000 --- a/lib/tlPlayQtApp/ColorPickerTool.h +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2021-2024 Darby Johnston -// All rights reserved. - -#pragma once - -#include - -#include - -namespace tl -{ - namespace play_qt - { - class MainWindow; - - //! Color picker tool. - class ColorPickerTool : public IToolWidget - { - Q_OBJECT - - public: - ColorPickerTool(MainWindow*, App*, QWidget* parent = nullptr); - - virtual ~ColorPickerTool(); - - private: - void _widgetUpdate(); - - TLRENDER_PRIVATE(); - }; - - //! Color picker tool dock widget. - class ColorPickerDockWidget : public QDockWidget - { - Q_OBJECT - - public: - ColorPickerDockWidget(ColorPickerTool*, QWidget* parent = nullptr); - }; - } -} diff --git a/lib/tlPlayQtApp/DevicesTool.cpp b/lib/tlPlayQtApp/DevicesTool.cpp index 190a81eef..00142f540 100644 --- a/lib/tlPlayQtApp/DevicesTool.cpp +++ b/lib/tlPlayQtApp/DevicesTool.cpp @@ -368,7 +368,7 @@ namespace tl setWidget(devicesTool); toggleViewAction()->setIcon(QIcon(":/Icons/Devices.svg")); - toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F7)); + toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F6)); toggleViewAction()->setToolTip(tr("Show devices")); } } diff --git a/lib/tlPlayQtApp/InfoTool.cpp b/lib/tlPlayQtApp/InfoTool.cpp index c0f1b6be9..61a467f8c 100644 --- a/lib/tlPlayQtApp/InfoTool.cpp +++ b/lib/tlPlayQtApp/InfoTool.cpp @@ -99,7 +99,7 @@ namespace tl setWidget(infoTool); toggleViewAction()->setIcon(QIcon(":/Icons/Info.svg")); - toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F5)); + toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F4)); toggleViewAction()->setToolTip(tr("Show information")); } } diff --git a/lib/tlPlayQtApp/MainWindow.cpp b/lib/tlPlayQtApp/MainWindow.cpp index 070f989e7..213cd65d5 100644 --- a/lib/tlPlayQtApp/MainWindow.cpp +++ b/lib/tlPlayQtApp/MainWindow.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -107,7 +106,6 @@ namespace tl FilesTool* filesTool = nullptr; ViewTool* viewTool = nullptr; ColorTool* colorTool = nullptr; - ColorPickerTool* colorPickerTool = nullptr; InfoTool* infoTool = nullptr; AudioTool* audioTool = nullptr; DevicesTool* devicesTool = nullptr; @@ -377,13 +375,6 @@ namespace tl toolsToolBar->addAction(colorDockWidget->toggleViewAction()); addDockWidget(Qt::RightDockWidgetArea, colorDockWidget); - p.colorPickerTool = new ColorPickerTool(this, app); - auto colorPickerDockWidget = new ColorPickerDockWidget(p.colorPickerTool); - colorPickerDockWidget->hide(); - p.toolActions->menu()->addAction(colorPickerDockWidget->toggleViewAction()); - toolsToolBar->addAction(colorPickerDockWidget->toggleViewAction()); - addDockWidget(Qt::RightDockWidgetArea, colorPickerDockWidget); - p.infoTool = new InfoTool(app); auto infoDockWidget = new InfoDockWidget(p.infoTool); infoDockWidget->hide(); diff --git a/lib/tlPlayQtApp/MessagesTool.cpp b/lib/tlPlayQtApp/MessagesTool.cpp index 358e3f800..f2499e983 100644 --- a/lib/tlPlayQtApp/MessagesTool.cpp +++ b/lib/tlPlayQtApp/MessagesTool.cpp @@ -126,7 +126,7 @@ namespace tl setWidget(messagesTool); toggleViewAction()->setIcon(QIcon(":/Icons/Messages.svg")); - toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F9)); + toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F8)); toggleViewAction()->setToolTip(tr("Show messages")); } } diff --git a/lib/tlPlayQtApp/SystemLogTool.cpp b/lib/tlPlayQtApp/SystemLogTool.cpp index f10d756a8..9253d5930 100644 --- a/lib/tlPlayQtApp/SystemLogTool.cpp +++ b/lib/tlPlayQtApp/SystemLogTool.cpp @@ -125,7 +125,7 @@ namespace tl setWidget(systemLogTool); - toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F10)); + toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F9)); toggleViewAction()->setToolTip(tr("Show system log")); } } diff --git a/lib/tlTimelineUI/TimelineViewport.cpp b/lib/tlTimelineUI/TimelineViewport.cpp index a6ed630d6..bb850acdc 100644 --- a/lib/tlTimelineUI/TimelineViewport.cpp +++ b/lib/tlTimelineUI/TimelineViewport.cpp @@ -51,7 +51,8 @@ namespace tl double frame = 0.0; }; DroppedFramesData droppedFramesData; - std::shared_ptr > colorPicker; + std::vector colorPickers; + std::shared_ptr > colorPickerValues; bool doRender = false; std::shared_ptr buffer; @@ -60,8 +61,7 @@ namespace tl { None, View, - Wipe, - ColorPicker + Wipe }; struct MouseData { @@ -90,7 +90,7 @@ namespace tl p.frameView = observer::Value::create(true); p.fps = observer::Value::create(0.0); p.droppedFrames = observer::Value::create(0); - p.colorPicker = observer::Value::create(); + p.colorPickerValues = observer::List::create(); } TimelineViewport::TimelineViewport() : @@ -358,9 +358,18 @@ namespace tl return _p->droppedFrames; } - std::shared_ptr > TimelineViewport::observeColorPicker() const + void TimelineViewport::setColorPickers(const std::vector& value) { - return _p->colorPicker; + TLRENDER_P(); + if (value == p.colorPickers) + return; + p.colorPickers = value; + _updates |= ui::Update::Draw; + } + + std::shared_ptr > TimelineViewport::observeColorPickers() const + { + return _p->colorPickerValues; } void TimelineViewport::setGeometry(const math::Box2i& value) @@ -473,24 +482,26 @@ namespace tl event.render->drawTexture(id, g); } - if (p.buffer && Private::MouseMode::ColorPicker == p.mouse.mode) + if (p.buffer && !p.colorPickers.empty()) { gl::OffscreenBufferBinding binding(p.buffer); - const math::Vector2i samplePos( - _mouse.pos.x - _geometry.min.x, - _mouse.pos.y - _geometry.min.y); - std::vector sample(4); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels( - samplePos.x, - samplePos.y, - 1, - 1, - GL_RGBA, - GL_FLOAT, - sample.data()); - const image::Color4f color(sample[0], sample[1], sample[2], sample[3]); - p.colorPicker->setIfChanged(color); + std::vector colors; + for (const auto& colorPicker : p.colorPickers) + { + const math::Vector2i pos = colorPicker - _geometry.min; + std::vector sample(4); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels( + pos.x, + pos.y, + 1, + 1, + GL_RGBA, + GL_FLOAT, + sample.data()); + colors.push_back(image::Color4f(sample[0], sample[1], sample[2], sample[3])); + } + p.colorPickerValues->setIfChanged(colors); } } @@ -533,9 +544,6 @@ namespace tl } break; } - case Private::MouseMode::ColorPicker: - _updates |= ui::Update::Draw; - break; default: break; } } @@ -556,12 +564,6 @@ namespace tl { p.mouse.mode = Private::MouseMode::Wipe; } - else if (0 == event.button && - event.modifiers & static_cast(ui::KeyModifier::Shift)) - { - p.mouse.mode = Private::MouseMode::ColorPicker; - _updates |= ui::Update::Draw; - } } void TimelineViewport::mouseReleaseEvent(ui::MouseClickEvent& event) diff --git a/lib/tlTimelineUI/TimelineViewport.h b/lib/tlTimelineUI/TimelineViewport.h index 2b155c492..bb616278f 100644 --- a/lib/tlTimelineUI/TimelineViewport.h +++ b/lib/tlTimelineUI/TimelineViewport.h @@ -112,8 +112,11 @@ namespace tl //! Observe the number of dropped frames during playback. std::shared_ptr > observeDroppedFrames() const; - //! Observe the color picker. - std::shared_ptr > observeColorPicker() const; + //! Set the color pickers. + void setColorPickers(const std::vector&); + + //! Observe the color pickers. + std::shared_ptr > observeColorPickers() const; void setGeometry(const math::Box2i&) override; void sizeHintEvent(const ui::SizeHintEvent&) override; diff --git a/lib/tlUI/FileBrowserWidget.cpp b/lib/tlUI/FileBrowserWidget.cpp index 82f104c72..88be7154c 100644 --- a/lib/tlUI/FileBrowserWidget.cpp +++ b/lib/tlUI/FileBrowserWidget.cpp @@ -169,7 +169,7 @@ namespace tl p.reverseSortCheckBox->setParent(hLayout); p.sequenceCheckBox->setParent(hLayout); auto spacer = Spacer::create(Orientation::Horizontal, context, hLayout); - spacer->setSpacingRole(SizeRole::None); + spacer->setSizeRole(SizeRole::None); spacer->setHStretch(Stretch::Expanding); p.okButton->setParent(hLayout); p.cancelButton->setParent(hLayout); diff --git a/lib/tlUI/Spacer.cpp b/lib/tlUI/Spacer.cpp index 686e47854..c8de484c7 100644 --- a/lib/tlUI/Spacer.cpp +++ b/lib/tlUI/Spacer.cpp @@ -11,7 +11,7 @@ namespace tl struct Spacer::Private { Orientation orientation = Orientation::Horizontal; - SizeRole spacingRole = SizeRole::Spacing; + SizeRole sizeRole = SizeRole::Spacing; struct SizeData { @@ -48,12 +48,12 @@ namespace tl return out; } - void Spacer::setSpacingRole(SizeRole value) + void Spacer::setSizeRole(SizeRole value) { TLRENDER_P(); - if (value == p.spacingRole) + if (value == p.sizeRole) return; - p.spacingRole = value; + p.sizeRole = value; p.size.sizeInit = true; _updates |= Update::Size; } @@ -66,7 +66,7 @@ namespace tl if (displayScaleChanged || p.size.sizeInit) { - p.size.size = event.style->getSizeRole(p.spacingRole, _displayScale); + p.size.size = event.style->getSizeRole(p.sizeRole, _displayScale); } p.size.sizeInit = false; diff --git a/lib/tlUI/Spacer.h b/lib/tlUI/Spacer.h index ca73b9cb9..82ebe6dbf 100644 --- a/lib/tlUI/Spacer.h +++ b/lib/tlUI/Spacer.h @@ -32,8 +32,8 @@ namespace tl const std::shared_ptr&, const std::shared_ptr& parent = nullptr); - //! Set the spacing role. - void setSpacingRole(SizeRole); + //! Set the size role. + void setSizeRole(SizeRole); void sizeHintEvent(const SizeHintEvent&) override;