Fix dialog w/scrollbar wrong size in a particular case (fix #5396)#5481
Fix dialog w/scrollbar wrong size in a particular case (fix #5396)#5481Gasparoken wants to merge 1 commit into
Conversation
aseprite-bot
left a comment
There was a problem hiding this comment.
clang-tidy made some suggestions
| View* view = static_cast<View*>(dlg->grid.parent()->parent()); | ||
| if (newBounds.size().w > workarea.w) { | ||
| newBounds.w = std::min(newBounds.size().w, workarea.w); | ||
| if (newBounds.size().h < workarea.h && view->horizontalBar()) |
There was a problem hiding this comment.
warning: implicit conversion 'ScrollBar *' -> 'bool' [readability-implicit-bool-conversion]
| if (newBounds.size().h < workarea.h && view->horizontalBar()) | |
| if (newBounds.size().h < workarea.h && (view->horizontalBar() != nullptr)) |
| } | ||
| if (newBounds.size().h > workarea.h) { | ||
| newBounds.h = std::min(newBounds.size().h, workarea.h); | ||
| if (newBounds.size().w < workarea.w && view->verticalBar()) |
There was a problem hiding this comment.
warning: implicit conversion 'ScrollBar *' -> 'bool' [readability-implicit-bool-conversion]
| if (newBounds.size().w < workarea.w && view->verticalBar()) | |
| if (newBounds.size().w < workarea.w && (view->verticalBar() != nullptr)) |
| void Viewport::onSizeHint(SizeHintEvent& ev) | ||
| { | ||
| ev.setSizeHint(gfx::Size(1 + border().width(), 1 + border().height())); | ||
| for (auto child : children()) { |
There was a problem hiding this comment.
warning: 'auto child' can be declared as 'auto *child' [readability-qualified-auto]
| for (auto child : children()) { | |
| for (auto *child : children()) { |
dabfd00 to
fd2865d
Compare
martincapello
left a comment
There was a problem hiding this comment.
Tested this and it seems to work. I'm just not sure how the expected UX should be, but this fixes the issue it claims to fix.
dacap
left a comment
There was a problem hiding this comment.
Some comments to work on, I'll be testing a little more tomorrow with multiple monitors.
| ev.setSizeHint(gfx::Size(1 + border().width(), 1 + border().height())); | ||
| gfx::Size sz = ev.sizeHint(); | ||
| for (auto child : children()) { | ||
| sz += child->sizeHint(); | ||
| ev.setSizeHint(sz); | ||
| } |
There was a problem hiding this comment.
I'm not quite sure if we should change the viewport size here (as it affects all viewports in the app), and have make this change explicit so the user must change the minimum size of the parent View to specify a minimum size (check that several elements in .xml widgets change the minwidth/height fields).
I'd prefer if we revert this change and in someway change the minimum size of the view explicitly (the view could be stored in a field of the Dialog class).
Just in case we need this change, we could do something like:
gfx::Size sz(1, 1);
for (auto* child : children())
sz |= child->sizeHint();
ev.setSizeHint(sz);
But I'm not sure to apply this change to main directly (as it might break something else)
| const bool allowVResize = bool(dlg->autofit & ui::TOP) ^ bool(dlg->autofit & ui::BOTTOM); | ||
| const bool allowHResize = bool(dlg->autofit & ui::LEFT) ^ bool(dlg->autofit & ui::RIGHT); |
There was a problem hiding this comment.
Is this right? This logic looks confusing, like it wants to say "allow vertical resize if top or bottom, but not both are enabled", but probably you want to specify it (a comment might help in these cases).
Should be this change to?
| const bool allowVResize = bool(dlg->autofit & ui::TOP) ^ bool(dlg->autofit & ui::BOTTOM); | |
| const bool allowHResize = bool(dlg->autofit & ui::LEFT) ^ bool(dlg->autofit & ui::RIGHT); | |
| const bool allowVResize = bool(dlg->autofit & ui::TOP) | bool(dlg->autofit & ui::BOTTOM); | |
| const bool allowHResize = bool(dlg->autofit & ui::LEFT) | bool(dlg->autofit & ui::RIGHT); |
There was a problem hiding this comment.
Maybe I'm confused in interpreting the API documentation that says: "...(eg. when autofitting with Align.LEFT | Align.TOP, the dialog bounds will shrink to the minimum size anchored at the top left of the dialog)". Therefore, I assume that if we anchor, for example, TOP and BOTTOM, the size would remain fixed given the anchoring concept. I'll need your confirmation this the behavior I'm describing is correct.
On the other hand, but following the logic of anchoring, how should a dialogue behave without Align?
There was a problem hiding this comment.
It's as the API says, but never thought about the possibility of having TOP|BOTTOM or LEFT|RIGHT as anchors. The anchor should be one corner/edge (0, TOP|LEFT, TOP, TOP|RIGHT, LEFT, RIGHT, BOTTOM|LEFT, BOTTOM, BOTTOM|RIGHT), but probably we can support the case you say too.
Without autofit the default is TOP|LEFT (just changing the size without changing the origin).
| allowHResize ? dlg->window.sizeHint().w : oldBounds.w, | ||
| allowVResize ? dlg->window.sizeHint().h : oldBounds.h); | ||
|
|
||
| if (auto* view = dynamic_cast<View*>(View::getView(&dlg->grid))) { |
There was a problem hiding this comment.
Probably it'd be better to have the view pointer directly in the Dialog class and doing something like:
| if (auto* view = dynamic_cast<View*>(View::getView(&dlg->grid))) { | |
| if (View* view = dlg->view) { |
| if (newBounds.size().w > workarea.w && allowHResize) { | ||
| newBounds.w = std::min(newBounds.size().w, workarea.w); | ||
| if (newBounds.size().h < workarea.h && view->horizontalBar() && allowVResize) | ||
| newBounds.h += view->horizontalBar()->getBarWidth(); | ||
| } | ||
| if (newBounds.size().h > workarea.h && allowVResize) { | ||
| newBounds.h = std::min(newBounds.size().h, workarea.h); | ||
| if (newBounds.size().w < workarea.w && view->verticalBar() && allowHResize) | ||
| newBounds.w += view->verticalBar()->getBarWidth(); | ||
| } | ||
| if ((dlg->autofit & ui::BOTTOM) && allowVResize) | ||
| newBounds.y = oldBounds.y2() - newBounds.h; | ||
| if ((dlg->autofit & ui::RIGHT) && allowHResize) | ||
| newBounds.x = oldBounds.x2() - newBounds.w; | ||
|
|
||
| // Trim of dialog areas outside the workarea | ||
| if (newBounds.x2() > workarea.x2()) | ||
| newBounds.w -= (newBounds.x2() - workarea.x2()); | ||
| if (newBounds.y2() > workarea.y2()) | ||
| newBounds.h -= (newBounds.y2() - workarea.y2()); | ||
| if (newBounds.x < workarea.x) { | ||
| newBounds.w = oldBounds.x2() - workarea.x; | ||
| newBounds.x = workarea.x; | ||
| } | ||
| if (newBounds.y < workarea.y) { | ||
| newBounds.h = oldBounds.y2() - workarea.y; | ||
| newBounds.y = workarea.y; | ||
| } | ||
|
|
||
| // Restore newBounds refered to the mainWindows | ||
| if (get_multiple_displays()) | ||
| newBounds.offset(-mainWindowBounds.origin()); | ||
| } | ||
| dlg->setWindowBounds(newBounds); |
There was a problem hiding this comment.
I'll test this tomorrow, I've detected that with multiples monitors it doesn't work as expected. Wouldn't be possible to use fit_bounds() function in this case?
23769c7 to
ca090e2
Compare
|
clang-tidy review says "All clean, LGTM! 👍" |
1 similar comment
|
clang-tidy review says "All clean, LGTM! 👍" |
…5396) Prior to this fix, changing the visibility of a widget in an autoscrolling dialog would collapse the size of the dialog.
ca090e2 to
d8daa8b
Compare
|
clang-tidy review says "All clean, LGTM! 👍" |
|
I have to test this a little more this, but I'm not sure if we should modify the dialog size when it has a view/autoscrollbars, as the user might have changed the dialog size to something preferred, and modifying that size is just making things worse (changing the user preference / viewport size). |
|
I've cherry-picked the commit in 71dd383 (as laf has conflicts), and I'll continue from there. |
|
There are a couple of issues I'm trying to fix of this patch (now merged in main): 1) |
Fixed some regressions introduced in #5481 / 71dd383 * Replaced Dialog::getCurrentWorkarea() with ui::fit_bounds() (getCurrentWorkarea() wasn't returning a valid rectangle for all cases) * Fixed accessing a nullptr Dialog::view pointer * Use View::makeVisibleAllScrollableArea() instead of setMinSize() directly
fix #5396