Improve stretching (RELATIVE) toolbar items

The available space is distributed reg. the preferred width
of items (spacers and the iconbar ;-) instead of evenly.

The preferred width of the iconbar is calculated from its buttons.

This allows to align the iconbar using spacers and makes better use of
the available space
This commit is contained in:
Thomas Lübking 2016-07-24 16:40:03 +02:00 committed by Mathias Gumz
parent 10e3f10b55
commit 3bde5c8aee
5 changed files with 45 additions and 20 deletions

View file

@ -292,7 +292,9 @@ void IconbarTool::move(int x, int y) {
void IconbarTool::resize(unsigned int width, unsigned int height) {
m_icon_container.resize(width, height);
m_icon_container.setMaxTotalSize(m_icon_container.orientation() == FbTk::ROT0 || m_icon_container.orientation() == FbTk::ROT180 ? width : height);
const unsigned int maxsize = (m_icon_container.orientation() & 1) ? height : width;
m_icon_container.setMaxTotalSize(maxsize);
m_icon_container.setMaxSizePerClient(maxsize/std::max(1, m_icon_container.size()));
renderTheme();
}
@ -300,7 +302,9 @@ void IconbarTool::moveResize(int x, int y,
unsigned int width, unsigned int height) {
m_icon_container.moveResize(x, y, width, height);
m_icon_container.setMaxTotalSize(m_icon_container.orientation() == FbTk::ROT0 || m_icon_container.orientation() == FbTk::ROT180 ? width : height);
const unsigned int maxsize = (m_icon_container.orientation() & 1) ? height : width;
m_icon_container.setMaxTotalSize(maxsize);
m_icon_container.setMaxSizePerClient(maxsize/std::max(1, m_icon_container.size()));
renderTheme();
}
@ -362,6 +366,18 @@ unsigned int IconbarTool::width() const {
return m_icon_container.width();
}
unsigned int IconbarTool::preferredWidth() const {
// border and paddings
unsigned int w = 2*borderWidth() + *m_rc_client_padding * m_icons.size();
// the buttons
for (IconMap::const_iterator it = m_icons.begin(), end = m_icons.end(); it != end; ++it) {
w += it->second->preferredWidth();
}
return w;
}
unsigned int IconbarTool::height() const {
return m_icon_container.height();
}
@ -384,9 +400,6 @@ void IconbarTool::update(UpdateReason reason, Focusable *win) {
m_icon_container.setAlignment(*m_rc_alignment);
*m_rc_client_width = FbTk::Util::clamp(*m_rc_client_width, 10, 400);
m_icon_container.setMaxSizePerClient(*m_rc_client_width);
// lock graphic update
m_icon_container.setUpdateLock(true);
@ -404,6 +417,11 @@ void IconbarTool::update(UpdateReason reason, Focusable *win) {
break;
}
resizeSig().emit();
const unsigned int maxsize = (m_icon_container.orientation() & 1) ? height() : width();
m_icon_container.setMaxTotalSize(maxsize);
m_icon_container.setMaxSizePerClient(maxsize/std::max(1, m_icon_container.size()));
// unlock container and update graphics
m_icon_container.setUpdateLock(false);
m_icon_container.update();
@ -441,6 +459,7 @@ void IconbarTool::insertWindow(Focusable &win, int pos) {
}
m_icon_container.insertItem(button, pos);
m_tracker.join(button->titleChanged(), FbTk::MemFun(resizeSig(), &FbTk::Signal<>::emit));
}
void IconbarTool::reset() {

View file

@ -60,6 +60,7 @@ public:
void parentMoved() { m_icon_container.parentMoved(); }
unsigned int width() const;
unsigned int preferredWidth() const;
unsigned int height() const;
unsigned int borderWidth() const;

View file

@ -868,6 +868,8 @@ void Toolbar::rearrangeItems() {
ItemList::iterator item_it_end = m_item_list.end();
int bevel_width = theme()->bevelWidth();
int fixed_width = bevel_width; // combined size of all fixed items
int relative_width = 0; // combined *desired* size of all relative items
int stretch_items = 0;
int relative_items = 0;
int last_bw = 0; // we show the largest border of adjoining items
bool first = true;
@ -895,7 +897,7 @@ void Toolbar::rearrangeItems() {
last_bw = borderW;
tmpw = (*item_it)->width();
tmpw = (*item_it)->preferredWidth();
tmph = (*item_it)->height();
FbTk::translateSize(orient, tmpw, tmph);
@ -906,18 +908,22 @@ void Toolbar::rearrangeItems() {
if (bevel_width)
fixed_width -= 2*(borderW + bevel_width);
} else {
relative_items++;
++relative_items;
relative_width += tmpw;
if (!tmpw)
++stretch_items;
}
}
// calculate what's going to be left over to the relative sized items
int relative_width = 0;
int rounding_error = 0;
if (relative_items == 0)
relative_width = 0;
else { // size left after fixed items / number of relative items
relative_width = (width - fixed_width) / relative_items;
rounding_error = width - fixed_width - relative_items * relative_width;
float stretch_factor = 1.0f;
if (relative_items) {
if (relative_width <= width - fixed_width && stretch_items) {
relative_width = int(width - fixed_width - relative_width)/stretch_items;
} else {
stretch_factor = float(width - fixed_width)/relative_width;
relative_width = 0;
}
}
// now move and resize the items
@ -952,12 +958,9 @@ void Toolbar::rearrangeItems() {
tmpy = offset;
if ((*item_it)->type() == ToolbarItem::RELATIVE) {
int extra = 0;
if (rounding_error != 0) { // distribute rounding error over all relatives
extra = 1;
--rounding_error;
}
tmpw = extra + relative_width;
unsigned int itemw = (*item_it)->preferredWidth(), itemh = (*item_it)->height();
FbTk::translateSize(orient, itemw, itemh);
tmpw = itemw ? std::floor(stretch_factor * itemw) : relative_width;
tmph = height - size_offset;
} else if ((*item_it)->type() == ToolbarItem::SQUARE) {
tmpw = tmph = height - size_offset;

View file

@ -47,6 +47,7 @@ public:
virtual void show() = 0;
virtual void hide() = 0;
virtual unsigned int width() const = 0;
virtual unsigned int preferredWidth() const { return width(); }
virtual unsigned int height() const = 0;
virtual unsigned int borderWidth() const = 0;
// some items might be there, but effectively empty, so shouldn't appear

View file

@ -2804,6 +2804,7 @@ void FluxboxWindow::setTitle(const std::string& title, Focusable &client) {
frame().setFocusTitle(title);
// relay title to others that display the focus title
titleSig().emit(title, *this);
frame().tabcontainer().repositionItems();
}
void FluxboxWindow::frameExtentChanged() {