Reimplement Box resize algorithm

This commit is contained in:
David Capello 2015-06-23 22:46:05 -03:00
parent a2538628c7
commit e6d22e7e38
2 changed files with 76 additions and 117 deletions

View File

@ -70,7 +70,6 @@ of the following projects created by third-parties:
* [Allegro 4](http://alleg.sourceforge.net/) - [allegro4 license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/allegro4-LICENSE.txt) * [Allegro 4](http://alleg.sourceforge.net/) - [allegro4 license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/allegro4-LICENSE.txt)
* [FreeType](http://www.freetype.org/) - [FTL license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/FTL.txt) * [FreeType](http://www.freetype.org/) - [FTL license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/FTL.txt)
* [GTK+](http://www.gtk.org/) - [LGPL license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/LGPL-2.1.txt)
* [Google Test](http://code.google.com/p/googletest/) - [gtest license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/gtest-LICENSE.txt) * [Google Test](http://code.google.com/p/googletest/) - [gtest license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/gtest-LICENSE.txt)
* [XFree86](http://www.x.org/) - [XFree86 license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/XFree86-LICENSE.txt) * [XFree86](http://www.x.org/) - [XFree86 license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/XFree86-LICENSE.txt)
* [curl](http://curl.haxx.se/) - [curl license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/curl-LICENSE.txt) * [curl](http://curl.haxx.se/) - [curl license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/curl-LICENSE.txt)

View File

@ -4,8 +4,6 @@
// This file is released under the terms of the MIT license. // This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information. // Read LICENSE.txt for more information.
/* Based on code from GTK+ 2.1.2 (gtk+/gtk/gtkhbox.c) */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -30,162 +28,124 @@ Box::Box(int align)
void Box::onPreferredSize(PreferredSizeEvent& ev) void Box::onPreferredSize(PreferredSizeEvent& ev)
{ {
#define GET_CHILD_SIZE(w, h) \ #define ADD_CHILD_SIZE(w, h) { \
{ \ if (getAlign() & HOMOGENEOUS) \
if (getAlign() & HOMOGENEOUS) \ prefSize.w = MAX(prefSize.w, childSize.w); \
w = MAX(w, reqSize.w); \ else \
else \ prefSize.w += childSize.w; \
w += reqSize.w; \ prefSize.h = MAX(prefSize.h, childSize.h); \
\
h = MAX(h, reqSize.h); \
} }
#define FINAL_SIZE(w) \ #define FINAL_ADJUSTMENT(w) { \
{ \ if (getAlign() & HOMOGENEOUS) \
if (getAlign() & HOMOGENEOUS) \ prefSize.w *= visibleChildren; \
w *= nvis_children; \ prefSize.w += childSpacing() * (visibleChildren-1); \
\
w += childSpacing() * (nvis_children-1); \
} }
int w, h, nvis_children; int visibleChildren = 0;
for (Widget* child : getChildren()) {
nvis_children = 0;
UI_FOREACH_WIDGET(getChildren(), it) {
Widget* child = *it;
if (!child->hasFlags(HIDDEN)) if (!child->hasFlags(HIDDEN))
nvis_children++; ++visibleChildren;
} }
w = h = 0; Size prefSize(0, 0);
for (Widget* child : getChildren()) {
UI_FOREACH_WIDGET(getChildren(), it) {
Widget* child = *it;
if (child->hasFlags(HIDDEN)) if (child->hasFlags(HIDDEN))
continue; continue;
Size reqSize = child->getPreferredSize(); Size childSize = child->getPreferredSize();
if (getAlign() & HORIZONTAL) {
if (this->getAlign() & HORIZONTAL) { ADD_CHILD_SIZE(w, h);
GET_CHILD_SIZE(w, h);
} }
else { else {
GET_CHILD_SIZE(h, w); ADD_CHILD_SIZE(h, w);
} }
} }
if (nvis_children > 0) { if (visibleChildren > 0) {
if (this->getAlign() & HORIZONTAL) { if (getAlign() & HORIZONTAL) {
FINAL_SIZE(w); FINAL_ADJUSTMENT(w);
} }
else { else {
FINAL_SIZE(h); FINAL_ADJUSTMENT(h);
} }
} }
w += border().width(); prefSize.w += border().width();
h += border().height(); prefSize.h += border().height();
ev.setPreferredSize(Size(w, h)); ev.setPreferredSize(prefSize);
} }
void Box::onResize(ResizeEvent& ev) void Box::onResize(ResizeEvent& ev)
{ {
#define FIXUP(x, y, w, h, left, top, width, height) \ #define LAYOUT_CHILDREN(x, w) { \
{ \ availExtraSize = availSize.w - prefSize.w; \
int width; \ availSize.w -= childSpacing() * (visibleChildren-1); \
if (nvis_children > 0) { \ if (getAlign() & HOMOGENEOUS) \
homogeneousSize = availSize.w / visibleChildren; \
\
Rect childPos(getChildrenBounds()); \
int i = 0, j = 0; \
for (Widget* child : getChildren()) { \
if (child->hasFlags(HIDDEN)) \
continue; \
\
int size = 0; \
\
if (getAlign() & HOMOGENEOUS) { \ if (getAlign() & HOMOGENEOUS) { \
width = (getBounds().w \ if (i < visibleChildren-1) \
- this->border().width() \ size = homogeneousSize; \
- this->childSpacing() * (nvis_children - 1)); \ else \
extra = width / nvis_children; \ size = availSize.w; \
} \
else if (nexpand_children > 0) { \
width = getBounds().w - reqSize.w; \
extra = width / nexpand_children; \
} \ } \
else { \ else { \
width = 0; \ size = child->getPreferredSize().w; \
extra = 0; \
} \
\ \
x = getBounds().x + border().left(); \ if (child->isExpansive()) { \
y = getBounds().y + border().top(); \ int extraSize = (availExtraSize / (expansiveChildren-j)); \
h = MAX(1, getBounds().h - border().height()); \ size += extraSize; \
\ availExtraSize -= extraSize; \
UI_FOREACH_WIDGET(getChildren(), it) { \ if (++j == expansiveChildren) \
child = *it; \ size += availExtraSize; \
\
if (!child->hasFlags(HIDDEN)) { \
if (this->getAlign() & HOMOGENEOUS) { \
if (nvis_children == 1) \
child_width = width; \
else \
child_width = extra; \
\
--nvis_children; \
width -= extra; \
} \
else { \
reqSize = child->getPreferredSize(); \
\
child_width = reqSize.w; \
\
if (child->isExpansive()) { \
if (nexpand_children == 1) \
child_width += width; \
else \
child_width += extra; \
\
--nexpand_children; \
width -= extra; \
} \
} \
\
w = MAX(1, child_width); \
\
gfx::Rect cpos; \
if (getAlign() & HORIZONTAL) \
cpos = gfx::Rect(x, y, w, h); \
else \
cpos = gfx::Rect(y, x, h, w); \
\
child->setBounds(cpos); \
\
x += child_width + this->childSpacing(); \
} \ } \
} \ } \
\
childPos.w = MAX(1, size); \
child->setBounds(childPos); \
childPos.x += size + childSpacing(); \
availSize.w -= size; \
++i; \
} \ } \
} }
Widget* child;
int nvis_children = 0;
int nexpand_children = 0;
int child_width;
int extra;
int x, y, w, h;
setBoundsQuietly(ev.getBounds()); setBoundsQuietly(ev.getBounds());
UI_FOREACH_WIDGET(getChildren(), it) { int visibleChildren = 0;
child = *it; int expansiveChildren = 0;
for (Widget* child : getChildren()) {
if (!child->hasFlags(HIDDEN)) { if (!child->hasFlags(HIDDEN)) {
nvis_children++; ++visibleChildren;
if (child->isExpansive()) if (child->isExpansive())
nexpand_children++; ++expansiveChildren;
} }
} }
Size reqSize = getPreferredSize(); if (visibleChildren > 0) {
Size prefSize(getPreferredSize());
Size availSize(getChildrenBounds().getSize());
int homogeneousSize = 0;
int availExtraSize = 0;
if (this->getAlign() & HORIZONTAL) { prefSize.w -= border().width();
FIXUP(x, y, w, h, left, top, width, height); prefSize.h -= border().height();
}
else { if (getAlign() & HORIZONTAL) {
FIXUP(y, x, h, w, top, left, height, width); LAYOUT_CHILDREN(x, w);
}
else {
LAYOUT_CHILDREN(y, h);
}
} }
} }