Update list of wide characters
[centerim5.git] / cppconsui / HorizontalListBox.cpp
blob25482074b8b86bffb2c1cfe312c28d3d7b6e279c
1 // Copyright (C) 2007 Mark Pustjens <pustjens@dds.nl>
2 // Copyright (C) 2010-2015 Petr Pavlu <setup@dagobah.cz>
3 //
4 // This file is part of CenterIM.
5 //
6 // CenterIM is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // CenterIM is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with CenterIM. If not, see <http://www.gnu.org/licenses/>.
19 /// @file
20 /// HorizontalListBox class implementation.
21 ///
22 /// @ingroup cppconsui
24 #include "HorizontalListBox.h"
26 #include <algorithm>
27 #include <cassert>
29 namespace CppConsUI {
31 HorizontalListBox::HorizontalListBox(int w, int h)
32 : AbstractListBox(w, h), children_width_(0), autosize_children_count_(0)
36 VerticalLine *HorizontalListBox::insertSeparator(std::size_t pos)
38 auto l = new VerticalLine(AUTOSIZE);
39 insertWidget(pos, *l);
40 return l;
43 VerticalLine *HorizontalListBox::appendSeparator()
45 auto l = new VerticalLine(AUTOSIZE);
46 appendWidget(*l);
47 return l;
50 void HorizontalListBox::insertWidget(std::size_t pos, Widget &widget)
52 Container::insertWidget(pos, widget, UNSETPOS, UNSETPOS);
54 if (!widget.isVisible())
55 return;
57 // Calculate the expected width by the widget.
58 int w = widget.getWidth();
59 int autosize_change = 0;
60 if (w == AUTOSIZE) {
61 w = widget.getWishWidth();
62 if (w == AUTOSIZE) {
63 w = 1;
64 autosize_change = 1;
68 updateChildren(w, autosize_change);
71 void HorizontalListBox::appendWidget(Widget &widget)
73 insertWidget(children_.size(), widget);
76 void HorizontalListBox::updateArea()
78 int autosize_width = 1;
79 int autosize_width_extra = 0;
80 if (autosize_children_count_ && children_width_ < real_width_) {
81 int space = real_width_ - (children_width_ - autosize_children_count_);
82 autosize_width = space / autosize_children_count_;
83 autosize_width_extra = space % autosize_children_count_;
86 int x = 0;
87 for (Widget *widget : children_) {
88 bool is_visible = widget->isVisible();
90 // Position the widget correctly.
91 widget->setRealPosition(x, 0);
93 // Calculate the real width.
94 int w = widget->getWidth();
95 if (w == AUTOSIZE) {
96 w = widget->getWishWidth();
97 if (w == AUTOSIZE) {
98 w = autosize_width;
99 if (is_visible && autosize_width_extra > 0) {
100 --autosize_width_extra;
101 ++w;
106 // Calculate the real height.
107 int h = widget->getHeight();
108 if (h == AUTOSIZE) {
109 h = widget->getWishHeight();
110 if (h == AUTOSIZE)
111 h = real_height_;
113 if (h > real_height_)
114 h = real_height_;
116 widget->setRealSize(w, h);
118 if (is_visible)
119 x += w;
122 // Make sure that the currently focused widget is visible.
123 updateScroll();
126 void HorizontalListBox::onChildMoveResize(
127 Widget &activator, const Rect &oldsize, const Rect &newsize)
129 // Sanity check.
130 assert(newsize.getLeft() == UNSETPOS && newsize.getTop() == UNSETPOS);
132 if (!activator.isVisible())
133 return;
135 int old_width = oldsize.getWidth();
136 int new_width = newsize.getWidth();
138 if (old_width == new_width)
139 return;
141 int autosize_change = 0;
142 if (old_width == AUTOSIZE) {
143 old_width = activator.getWishWidth();
144 if (old_width == AUTOSIZE) {
145 old_width = 1;
146 --autosize_change;
149 if (new_width == AUTOSIZE) {
150 new_width = activator.getWishWidth();
151 if (new_width == AUTOSIZE) {
152 new_width = 1;
153 ++autosize_change;
157 updateChildren(new_width - old_width, autosize_change);
160 void HorizontalListBox::onChildWishSizeChange(
161 Widget &activator, const Size &oldsize, const Size &newsize)
163 if (!activator.isVisible() || activator.getWidth() != AUTOSIZE)
164 return;
166 // The widget is visible and is autosized.
167 int old_width = oldsize.getWidth();
168 int new_width = newsize.getWidth();
170 if (old_width == new_width)
171 return;
173 updateChildren(new_width - old_width, 0);
176 void HorizontalListBox::onChildVisible(Widget &activator, bool visible)
178 // The widget is being hidden or deleted.
179 int w = activator.getWidth();
180 int sign = visible ? 1 : -1;
181 int autosize_change = 0;
182 if (w == AUTOSIZE) {
183 w = activator.getWishWidth();
184 if (w == AUTOSIZE) {
185 w = 1;
186 autosize_change = sign;
189 updateChildren(sign * w, autosize_change);
192 void HorizontalListBox::moveWidget(Widget &widget, Widget &position, bool after)
194 Container::moveWidget(widget, position, after);
196 // Reposition all child widgets.
197 updateArea();
200 void HorizontalListBox::updateChildren(
201 int children_width_change, int autosize_children_count_change)
203 // Set new children data.
204 children_width_ += children_width_change;
205 assert(children_width_ >= 0);
206 autosize_children_count_ += autosize_children_count_change;
207 assert(autosize_children_count_ >= 0);
209 // Reposition all child widgets.
210 updateArea();
211 signal_children_width_change(*this, children_width_);
214 } // namespace CppConsUI
216 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: