Skip to content

Add layouts + dockable UI#3485

Merged
dacap merged 35 commits into
aseprite:betafrom
dacap:dock
Aug 5, 2025
Merged

Add layouts + dockable UI#3485
dacap merged 35 commits into
aseprite:betafrom
dacap:dock

Conversation

@dacap

@dacap dacap commented Aug 23, 2022

Copy link
Copy Markdown
Member

This is a work-in-progress. We want to add multiple ways to customize the layout/workspace #518

@dacap dacap mentioned this pull request Aug 23, 2022
@dacap dacap linked an issue Aug 23, 2022 that may be closed by this pull request
5 tasks
@dacap dacap changed the title Dock Add layouts + dockable UI Aug 23, 2022
@dacap dacap self-assigned this Sep 19, 2022
@dacap dacap force-pushed the dock branch 2 times, most recently from 0b3acea to b595aae Compare January 11, 2024 19:59

@aseprite-bot aseprite-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 79. Check the log or trigger a new build to see more.

{
}

bool ToggleWorkspaceLayoutCommand::onChecked(Context* ctx)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'ctx' is unused [misc-unused-parameters]

Suggested change
bool ToggleWorkspaceLayoutCommand::onChecked(Context* ctx)
bool ToggleWorkspaceLayoutCommand::onChecked(Context* /*ctx*/)

->isSelectorVisible();
}

void ToggleWorkspaceLayoutCommand::onExecute(Context* ctx)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'ctx' is unused [misc-unused-parameters]

Suggested change
void ToggleWorkspaceLayoutCommand::onExecute(Context* ctx)
void ToggleWorkspaceLayoutCommand::onExecute(Context* /*ctx*/)

Comment thread src/app/ui/configure_timeline_popup.cpp Outdated

int selITem = m_box->position()->selectedItem();
switch (selITem) {
int selItem = option;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'selItem' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int selItem = option;
int const selItem = option;

Comment thread src/app/ui/dock.cpp Outdated

InitTheme.connect(
[this]{
if (auto p = parent())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto p' can be declared as 'auto *p' [readability-qualified-auto]

Suggested change
if (auto p = parent())
if (auto *p = parent())

Comment thread src/app/ui/dock.cpp
initTheme();
}

void Dock::resetDocks()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'resetDocks' is within a recursive call chain [misc-no-recursion]

void Dock::resetDocks()
           ^
Additional context

src/app/ui/dock.cpp:108: example recursive call chain, starting from function 'resetDocks'

void Dock::resetDocks()
           ^

src/app/ui/dock.cpp:115: Frame #1: function 'resetDocks' calls function 'resetDocks' here:

      subdock->resetDocks();
      ^

src/app/ui/dock.cpp:115: ... which was the starting point of the recursive call chain; there may be other cycles

      subdock->resetDocks();
      ^

Comment thread src/app/ui/dock.cpp
int i = side_index(side);
// Only EXPANSIVE sides can be user-defined (has a splitter so the
// user can expand or shrink it)
if (m_aligns[i] & EXPANSIVE)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: implicit conversion 'unsigned int' -> bool [readability-implicit-bool-conversion]

Suggested change
if (m_aligns[i] & EXPANSIVE)
if ((m_aligns[i] & EXPANSIVE) != 0u)

Comment thread src/app/ui/dock.cpp Outdated
Comment on lines +239 to +249
else
return gfx::Size();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not use 'else' after 'return' [readability-else-after-return]

Suggested change
else
return gfx::Size();
return gfx::Size();

Comment thread src/app/ui/dock.cpp

Dock* Dock::subdock(int side)
{
int i = side_index(side);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'i' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int i = side_index(side);
int const i = side_index(side);

Comment thread src/app/ui/dock.cpp Outdated
Dock* Dock::subdock(int side)
{
int i = side_index(side);
if (auto subdock = dynamic_cast<Dock*>(m_sides[i]))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto subdock' can be declared as 'auto *subdock' [readability-qualified-auto]

Suggested change
if (auto subdock = dynamic_cast<Dock*>(m_sides[i]))
if (auto *subdock = dynamic_cast<Dock*>(m_sides[i]))

Comment thread src/app/ui/dock.cpp Outdated
if (auto subdock = dynamic_cast<Dock*>(m_sides[i]))
return subdock;

auto oldWidget = m_sides[i];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto oldWidget' can be declared as 'auto *oldWidget' [readability-qualified-auto]

Suggested change
auto oldWidget = m_sides[i];
auto *oldWidget = m_sides[i];

@aseprite-bot aseprite-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 54. Check the log or trigger a new build to see more.

Comment thread src/app/ui/dock.cpp Outdated
return subdock;

auto oldWidget = m_sides[i];
auto newSubdock = new Dock;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto newSubdock' can be declared as 'auto *newSubdock' [readability-qualified-auto]

Suggested change
auto newSubdock = new Dock;
auto *newSubdock = new Dock;

Comment thread src/app/ui/dock.cpp Outdated
forEachSide(bounds,
[bounds](ui::Widget* widget,
const gfx::Rect& widgetBounds,
const gfx::Rect& separator,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'separator' is unused [misc-unused-parameters]

Suggested change
const gfx::Rect& separator,
const gfx::Rect& /*separator*/,

Comment thread src/app/ui/dock.cpp Outdated
[bounds](ui::Widget* widget,
const gfx::Rect& widgetBounds,
const gfx::Rect& separator,
const int index) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'index' is unused [misc-unused-parameters]

Suggested change
const int index) {
const int /*index*/) {

Comment thread src/app/ui/dock.cpp Outdated
m_capturedSide = -1;
forEachSide(childrenBounds(),
[this, pos](ui::Widget* widget,
const gfx::Rect& widgetBounds,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'widgetBounds' is unused [misc-unused-parameters]

Suggested change
const gfx::Rect& widgetBounds,
const gfx::Rect& /*widgetBounds*/,

Comment thread src/app/ui/dock.cpp Outdated
const gfx::Point pos = static_cast<MouseMessage*>(msg)->position();
ui::CursorType cursor = ui::kArrowCursor;
forEachSide(childrenBounds(),
[pos, &cursor](ui::Widget* widget,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'widget' is unused [misc-unused-parameters]

Suggested change
[pos, &cursor](ui::Widget* widget,
[pos, &cursor](ui::Widget* /*widget*/,

Comment thread src/app/ui/dock.cpp Outdated
(m_aligns[i] & EXPANSIVE ? childSpacing(): 0);

const gfx::Size sz =
(m_aligns[i] & EXPANSIVE ? m_sizes[i]: widget->sizeHint());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: implicit conversion 'unsigned int' -> bool [readability-implicit-bool-conversion]

Suggested change
(m_aligns[i] & EXPANSIVE ? m_sizes[i]: widget->sizeHint());
((m_aligns[i] & EXPANSIVE) != 0u ? m_sizes[i]: widget->sizeHint());

Comment thread src/app/ui/dock.h
int whichSideChildIsDocked(const ui::Widget* widget) const;
gfx::Size getUserDefinedSizeAtSide(int side) const;

obs::signal<void()> Resize;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'Resize' has public visibility [misc-non-private-member-variables-in-classes]

  obs::signal<void()> Resize;
                      ^

Comment thread src/app/ui/dock.h
gfx::Size getUserDefinedSizeAtSide(int side) const;

obs::signal<void()> Resize;
obs::signal<void()> UserResizedDock;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'UserResizedDock' has public visibility [misc-non-private-member-variables-in-classes]

  obs::signal<void()> UserResizedDock;
                      ^

Comment thread src/app/ui/dock.h Outdated
void onUserResizedDock();

private:
void setSide(const int i, ui::Widget* newWidget);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'i' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
void setSide(const int i, ui::Widget* newWidget);
void setSide(int i, ui::Widget* newWidget);

Comment thread src/app/ui/dock.h Outdated

private:
void setSide(const int i, ui::Widget* newWidget);
int calcAlign(const int i);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'i' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
int calcAlign(const int i);
int calcAlign(int i);

@aseprite-bot aseprite-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 26. Check the log or trigger a new build to see more.

Comment thread src/app/ui/dock.h Outdated
const int index)> f);

bool hasVisibleSide(const int i) const {
return (m_sides[i] && m_sides[i]->isVisible());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: implicit conversion 'value_type' (aka 'ui::Widget *') -> bool [readability-implicit-bool-conversion]

Suggested change
return (m_sides[i] && m_sides[i]->isVisible());
return ((m_sides[i] != nullptr) && m_sides[i]->isVisible());

Comment thread src/app/ui/layout.cpp
}
}

static void load_dock_layout(const XMLElement* elem, Dock* dock)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'load_dock_layout' is within a recursive call chain [misc-no-recursion]

static void load_dock_layout(const XMLElement* elem, Dock* dock)
            ^
Additional context

src/app/ui/layout.cpp:71: example recursive call chain, starting from function 'load_dock_layout'

static void load_dock_layout(const XMLElement* elem, Dock* dock)
            ^

src/app/ui/layout.cpp:111: Frame #1: function 'load_dock_layout' calls function 'load_dock_layout' here:

      load_dock_layout(childElem, subdock);
      ^

src/app/ui/layout.cpp:111: ... which was the starting point of the recursive call chain; there may be other cycles

      load_dock_layout(childElem, subdock);
      ^

Comment thread src/app/ui/layout.cpp Outdated
Dock* subdock = nullptr;

int side = ui::CENTER;
if (auto sideStr = elem->Attribute("side")) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto sideStr' can be declared as 'const auto *sideStr' [readability-qualified-auto]

Suggested change
if (auto sideStr = elem->Attribute("side")) {
if (const auto *sideStr = elem->Attribute("side")) {

Comment thread src/app/ui/layout.cpp Outdated
else if (elemName == "dock") { subdock = dock->subdock(side); }

if (subdock) {
auto childElem = elem->FirstChildElement();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto childElem' can be declared as 'const auto *childElem' [readability-qualified-auto]

Suggested change
auto childElem = elem->FirstChildElement();
const auto *childElem = elem->FirstChildElement();

Comment thread src/app/ui/layout.cpp Outdated
LayoutPtr Layout::MakeFromXmlElement(const XMLElement* layoutElem)
{
auto layout = std::make_shared<Layout>();
if (auto name = layoutElem->Attribute("name")) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto name' can be declared as 'const auto *name' [readability-qualified-auto]

Suggested change
if (auto name = layoutElem->Attribute("name")) {
if (const auto *name = layoutElem->Attribute("name")) {

Comment thread src/app/ui/main_window.cpp Outdated
m_customizableDockPlaceholder = std::make_unique<Widget>();
m_customizableDockPlaceholder->addChild(m_customizableDock);
m_customizableDockPlaceholder->InitTheme.connect([this]{
auto theme = static_cast<skin::SkinTheme*>(this->theme());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto theme' can be declared as 'auto *theme' [readability-qualified-auto]

Suggested change
auto theme = static_cast<skin::SkinTheme*>(this->theme());
auto *theme = static_cast<skin::SkinTheme*>(this->theme());

Comment thread src/app/ui/main_window.cpp Outdated
align = HORIZONTAL;
invertWidgets = true;
side = ui::LEFT;
w = (workspaceBounds.w * (1.0-timelineSplitterPos)) / guiscale();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: narrowing conversion from 'double' to 'int' [bugprone-narrowing-conversions]

        w = (workspaceBounds.w * (1.0-timelineSplitterPos)) / guiscale();
            ^

Comment thread src/app/ui/main_window.cpp Outdated
case gen::TimelinePosition::RIGHT:
align = HORIZONTAL;
side = ui::RIGHT;
w = (workspaceBounds.w * (1.0-timelineSplitterPos)) / guiscale();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: narrowing conversion from 'double' to 'int' [bugprone-narrowing-conversions]

        w = (workspaceBounds.w * (1.0-timelineSplitterPos)) / guiscale();
            ^

Comment thread src/app/ui/main_window.cpp Outdated
break;
case gen::TimelinePosition::BOTTOM:
side = ui::BOTTOM;
h = (workspaceBounds.h * (1.0-timelineSplitterPos)) / guiscale();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: narrowing conversion from 'double' to 'int' [bugprone-narrowing-conversions]

        h = (workspaceBounds.h * (1.0-timelineSplitterPos)) / guiscale();
            ^

Comment thread src/app/ui/toolbar.cpp
Rect rc = getToolGroupBounds(group_index);
int w = 0;

int w = borderWidth;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'w' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int w = borderWidth;
int const w = borderWidth;

@aseprite-bot aseprite-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

Comment thread src/app/ui/toolbar.cpp Outdated
Point arrow = (tool ? getToolPositionInGroup(group_index, tool): Point(0, 0));
if (tool && m_popupWindow && m_popupWindow->isVisible())
toolrc.x += arrow.x - m_popupWindow->bounds().w;
Point arrow = (tool ? getToolPositionInGroup(tool): Point(0, 0));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'arrow' of type 'Point' (aka 'PointT') can be declared 'const' [misc-const-correctness]

Suggested change
Point arrow = (tool ? getToolPositionInGroup(tool): Point(0, 0));
Point const arrow = (tool ? getToolPositionInGroup(tool): Point(0, 0));

@aseprite-bot aseprite-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 83. Check the log or trigger a new build to see more.

{
}

bool ToggleWorkspaceLayoutCommand::onChecked(Context* ctx)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'ctx' is unused [misc-unused-parameters]

Suggested change
bool ToggleWorkspaceLayoutCommand::onChecked(Context* ctx)
bool ToggleWorkspaceLayoutCommand::onChecked(Context* /*ctx*/)

return App::instance()->mainWindow()->layoutSelector()->isSelectorVisible();
}

void ToggleWorkspaceLayoutCommand::onExecute(Context* ctx)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'ctx' is unused [misc-unused-parameters]

Suggested change
void ToggleWorkspaceLayoutCommand::onExecute(Context* ctx)
void ToggleWorkspaceLayoutCommand::onExecute(Context* /*ctx*/)

Comment thread src/app/ui/configure_timeline_popup.cpp Outdated

int selITem = m_box->position()->selectedItem();
switch (selITem) {
int selItem = option;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'selItem' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int selItem = option;
int const selItem = option;

Comment thread src/app/ui/configure_timeline_popup.cpp Outdated
int selITem = m_box->position()->selectedItem();
switch (selITem) {
int selItem = option;
switch (selItem) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: switching on non-enum value without default case may not cover all cases [bugprone-switch-missing-default-case]

  switch (selItem) {
  ^

Comment thread src/app/ui/dock.cpp

namespace {

enum { kTopIndex, kBottomIndex, kLeftIndex, kRightIndex, kCenterIndex };

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: enum '(unnamed enum at /github/workspace/src/app/ui/dock.cpp:31:1)' uses a larger base type ('unsigned int', size: 4 bytes) than necessary for its value set, consider using 'std::uint8_t' (1 byte) as the base type to reduce its size [performance-enum-size]

enum { kTopIndex, kBottomIndex, kLeftIndex, kRightIndex, kCenterIndex };
^

Comment thread src/app/ui/dock.cpp
}
}

void Dock::undock(Widget* widget)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'undock' is within a recursive call chain [misc-no-recursion]

void Dock::undock(Widget* widget)
           ^
Additional context

src/app/ui/dock.cpp:183: example recursive call chain, starting from function 'undock'

void Dock::undock(Widget* widget)
           ^

src/app/ui/dock.cpp:200: Frame #1: function 'undock' calls function 'undock' here:

      undock(parentDock);
      ^

src/app/ui/dock.cpp:200: ... which was the starting point of the recursive call chain; there may be other cycles

      undock(parentDock);
      ^

Comment thread src/app/ui/dock.cpp Outdated
if (!parent)
return; // Already undocked

if (auto parentDock = dynamic_cast<Dock*>(parent)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto parentDock' can be declared as 'auto *parentDock' [readability-qualified-auto]

Suggested change
if (auto parentDock = dynamic_cast<Dock*>(parent)) {
if (auto *parentDock = dynamic_cast<Dock*>(parent)) {

Comment thread src/app/ui/dock.cpp Outdated
undock(parentDock);
}
}
else if (auto parentTabs = dynamic_cast<DockTabs*>(parent)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto parentTabs' can be declared as 'auto *parentTabs' [readability-qualified-auto]

Suggested change
else if (auto parentTabs = dynamic_cast<DockTabs*>(parent)) {
else if (auto *parentTabs = dynamic_cast<DockTabs*>(parent)) {

Comment thread src/app/ui/dock.cpp

gfx::Size Dock::getUserDefinedSizeAtSide(int side) const
{
int i = side_index(side);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'i' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int i = side_index(side);
int const i = side_index(side);

Comment thread src/app/ui/dock.cpp
int i = side_index(side);
// Only EXPANSIVE sides can be user-defined (has a splitter so the
// user can expand or shrink it)
if (m_aligns[i] & EXPANSIVE)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: implicit conversion 'unsigned int' -> 'bool' [readability-implicit-bool-conversion]

Suggested change
if (m_aligns[i] & EXPANSIVE)
if ((m_aligns[i] & EXPANSIVE) != 0u)

@aseprite-bot aseprite-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 77. Check the log or trigger a new build to see more.

Comment thread src/app/ui/dock.cpp
initTheme();
}

void Dock::setCustomizing(bool enable, bool doLayout)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'setCustomizing' is within a recursive call chain [misc-no-recursion]

void Dock::setCustomizing(bool enable, bool doLayout)
           ^
Additional context

src/app/ui/dock.cpp:101: example recursive call chain, starting from function 'setCustomizing'

void Dock::setCustomizing(bool enable, bool doLayout)
           ^

src/app/ui/dock.cpp:110: Frame #1: function 'setCustomizing' calls function 'setCustomizing' here:

      subdock->setCustomizing(enable, false);
      ^

src/app/ui/dock.cpp:110: ... which was the starting point of the recursive call chain; there may be other cycles

      subdock->setCustomizing(enable, false);
      ^

Comment thread src/app/ui/dock.cpp Outdated
m_customizing = enable;

for (int i = 0; i < kSides; ++i) {
auto child = m_sides[i];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto child' can be declared as 'auto *child' [readability-qualified-auto]

Suggested change
auto child = m_sides[i];
auto *child = m_sides[i];

Comment thread src/app/ui/dock.cpp Outdated
auto child = m_sides[i];
if (!child)
continue;
else if (auto subdock = dynamic_cast<Dock*>(child))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto subdock' can be declared as 'auto *subdock' [readability-qualified-auto]

    else if (auto subdock = dynamic_cast<Dock*>(child))
             ^

this fix will not be applied because it overlaps with another fix

Comment thread src/app/ui/dock.cpp
if (!child)
continue;
else if (auto subdock = dynamic_cast<Dock*>(child))
subdock->setCustomizing(enable, false);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not use 'else' after 'continue' [readability-else-after-return]

Suggested change
subdock->setCustomizing(enable, false);
if (auto subdock = dynamic_cast<Dock*>(child))
subdock->setCustomizing(enable, false);

Comment thread src/app/ui/dock.cpp
layout();
}

void Dock::resetDocks()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'resetDocks' is within a recursive call chain [misc-no-recursion]

void Dock::resetDocks()
           ^
Additional context

src/app/ui/dock.cpp:117: example recursive call chain, starting from function 'resetDocks'

void Dock::resetDocks()
           ^

src/app/ui/dock.cpp:124: Frame #1: function 'resetDocks' calls function 'resetDocks' here:

      subdock->resetDocks();
      ^

src/app/ui/dock.cpp:124: ... which was the starting point of the recursive call chain; there may be other cycles

      subdock->resetDocks();
      ^

Comment thread src/app/ui/dock.cpp Outdated
auto rc = widgetBounds;
auto th = textHeight();
if (isCustomizing()) {
auto theme = SkinTheme::get(this);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto theme' can be declared as 'auto *theme' [readability-qualified-auto]

Suggested change
auto theme = SkinTheme::get(this);
auto *theme = SkinTheme::get(this);

Comment thread src/app/ui/dock.cpp Outdated
auto theme = SkinTheme::get(this);
auto color = theme->colors.workspaceText();
int handleSide = 0;
if (auto dockable = dynamic_cast<Dockable*>(widget))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto dockable' can be declared as 'auto *dockable' [readability-qualified-auto]

Suggested change
if (auto dockable = dynamic_cast<Dockable*>(widget))
if (auto *dockable = dynamic_cast<Dockable*>(widget))

Comment thread src/app/ui/dock.cpp
int handleSide = 0;
if (auto dockable = dynamic_cast<Dockable*>(widget))
handleSide = dockable->dockHandleSide();
switch (handleSide) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: switching on non-enum value without default case may not cover all cases [bugprone-switch-missing-default-case]

                    switch (handleSide) {
                    ^

Comment thread src/app/ui/dock.cpp
const gfx::Point pos = static_cast<MouseMessage*>(msg)->position();
gfx::Size& sz = m_sizes[m_hit.sideIndex];

switch (m_hit.sideIndex) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: switching on non-enum value without default case may not cover all cases [bugprone-switch-missing-default-case]

          switch (m_hit.sideIndex) {
          ^

Comment thread src/app/ui/dock.cpp
m_hit = calcHit(pos);

if (m_hit.sideIndex >= 0) {
switch (m_hit.sideIndex) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: switching on non-enum value without default case may not cover all cases [bugprone-switch-missing-default-case]

        switch (m_hit.sideIndex) {
        ^

@dacap dacap force-pushed the dock branch 2 times, most recently from 55590bd to ec60773 Compare May 7, 2025 20:04
@dacap dacap marked this pull request as ready for review May 8, 2025 02:38
@dacap

dacap commented May 8, 2025

Copy link
Copy Markdown
Member Author

The initial iteration of this feature is quite ready to be tested. Still some minor things to be fixed (and a lot of room of improvement to dock widgets in other parts, and sub-divide widgets like the ColorBar), but it's a good start for a first iteration.

@ckaiser ckaiser left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gave it a test and found an issue, when modifying the default theme, closing the app and re-opening it again, the modifications aren't applied, only when I open the dropdown and re-select "Default*" do my layout changes show up. The rest is looking good!

Had some minor string stuff in the comments and usability thoughts:

New icon looks good! I'm wondering if it should have some kind of toggle state beyond just the dropdown appearing?

Another thing that I was thinking about was if it'd be wise to automatically hide the dropdown & docking handles, because I can definitely see a user clicking on it and then just leaving it on for the rest of the session. It's not a big deal since it doesn't persist, but yeah maybe opening/closing a file, losing focus or switching tabs could hide it?

Comment thread data/strings/en.ini Outdated
modified = {} (Modified)
deleting_layout = Deleting Layout
deleting_layout_confirmation = Are you sure you want to delete the layout '{}'?
restoring_layout = "Restoring Layout"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
restoring_layout = "Restoring Layout"
restoring_layout = Restoring Layout

Comment thread data/strings/en.ini Outdated
deleting_layout = Deleting Layout
deleting_layout_confirmation = Are you sure you want to delete the layout '{}'?
restoring_layout = "Restoring Layout"
restoring_layout_confirmation = Are you sure you want to restore the {} layout?"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
restoring_layout_confirmation = Are you sure you want to restore the {} layout?"
restoring_layout_confirmation = Are you sure you want to restore the '{}' layout?

Comment thread data/widgets/new_layout.xml Outdated
<vbox>
<grid columns="2">
<label text="@.base" />
<combobox id="base" expansive="true">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this dialogue should probably have some kind of explainer/help text either in a tooltip or in a help button or something, just to make sure the concept of a "base" layout is understood since it's a pretty programmer-y thing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if the "base" field is even necessary. From the user point of view, creating a new layout will be based on the "actual look" of the UI (the actual layout). Not sure what effect has the "base" layout to the new user layout. Could we just remove this field?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah now that I think about it, it's a relic from when you had to make a new layout to modify the default ones - better off without it, simpler.

dacap and others added 20 commits August 4, 2025 19:41
This patch includes:

* The layout is updated immediately when docks are resized (before
  this the layout was like a snapshot of the configuration when the
  layout was created or overwritten with the "New Layout" option)
* Saving the active layout used in
  preferences.general.workspace_layout so we can restore it after
  restarting Aseprite
* Change "UI Layout" to "Workspace Layout"
* Some strings moved to en.ini file for i18n
* Fixed a crash on MainWindow::onActiveViewChange() when the
  application was being closed
This was a new issue with combination of
9b90159, probably we should close the
popup when the window is resized (instead of onSizeHint()).
@dacap's notes: A description of the included changes:

* Improve UX auto-saving layouts when docks are modified, and new 'X'
  icon to delete layouts (or reset the 'Default' layout).
* Remove old timeline position controls (Left/Right/Bottom buttons)
  from the Timeline configuration and from the layout selector
* Add support to drag and drop docks to other sides with real-time
  feedback using a semi-transparent UILayer
* Add a context menu w/right-click to dock the widget at the supported
  sides without drag-and-drop

Some review comments in #2
This improves the look of the flag as another icon above the tabs
bottom and at the right of the layout selector icon.
* Better support to load legacy timeline information: we have to
  estimate workspace bounds)
* Auto-save layouts after resizing a splitter/dock
* Fix resetting expansive widgets inside docks after switching tabs
* Load mirrored layout correctly if it was the last selected layout
With this patch we've also simplified some hacks handling the
populateComboBox() call, deferring the deletion of widgets/items when
we are inside an event generated by those items.
Without this, the combobox is still visible and clicking the button
again will crash the program.
We're going to keep this section for a couple of versions as old users
get used to the new Workspace Layout customization.

The "Position" section will contain the layout icon so we can switch
the Workspace Layout combobox from there too,
@dacap

dacap commented Aug 4, 2025

Copy link
Copy Markdown
Member Author

I've just updated beta branch and rebased dock to continue working on this.

@dacap dacap moved this to Todo in Aseprite v1.3 Aug 4, 2025
@dacap dacap merged commit 7434db6 into aseprite:beta Aug 5, 2025
12 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Aseprite v1.3 Aug 5, 2025
@dacap dacap deleted the dock branch August 5, 2025 19:31
@dacap dacap self-assigned this Aug 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Make all elements on screen dockable/movable/resizable

3 participants