1 // Copyright (C) 2007 Mark Pustjens <pustjens@dds.nl>
2 // Copyright (C) 2010-2015 Petr Pavlu <setup@dagobah.cz>
4 // This file is part of CenterIM.
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/>.
20 /// ListBox class implementation.
22 /// @ingroup cppconsui
31 ListBox::ListBox(int w
, int h
)
32 : AbstractListBox(w
, h
), children_height_(0), autosize_children_count_(0)
34 // Allow fast focus changing (paging) using PageUp/PageDown keys.
38 HorizontalLine
*ListBox::insertSeparator(std::size_t pos
)
40 auto l
= new HorizontalLine(AUTOSIZE
);
41 insertWidget(pos
, *l
);
45 HorizontalLine
*ListBox::appendSeparator()
47 auto l
= new HorizontalLine(AUTOSIZE
);
52 void ListBox::insertWidget(std::size_t pos
, Widget
&widget
)
54 Container::insertWidget(pos
, widget
, UNSETPOS
, UNSETPOS
);
56 if (!widget
.isVisible())
59 // Calculate the expected height by the widget.
60 int h
= widget
.getHeight();
61 int autosize_change
= 0;
63 h
= widget
.getWishHeight();
70 updateChildren(h
, autosize_change
);
73 void ListBox::appendWidget(Widget
&widget
)
75 insertWidget(children_
.size(), widget
);
78 void ListBox::updateArea()
80 int autosize_height
= 1;
81 int autosize_height_extra
= 0;
82 if (autosize_children_count_
&& children_height_
< real_height_
) {
83 int space
= real_height_
- (children_height_
- autosize_children_count_
);
84 autosize_height
= space
/ autosize_children_count_
;
85 autosize_height_extra
= space
% autosize_children_count_
;
89 for (Widget
*widget
: children_
) {
90 bool is_visible
= widget
->isVisible();
92 // Position the widget correctly.
93 widget
->setRealPosition(0, y
);
95 // Calculate the real width.
96 int w
= widget
->getWidth();
98 w
= widget
->getWishWidth();
105 // Calculate the real height.
106 int h
= widget
->getHeight();
108 h
= widget
->getWishHeight();
111 if (is_visible
&& autosize_height_extra
> 0) {
112 --autosize_height_extra
;
118 widget
->setRealSize(w
, h
);
124 // Make sure that the currently focused widget is visible.
128 void ListBox::onChildMoveResize(
129 Widget
&activator
, const Rect
&oldsize
, const Rect
&newsize
)
132 assert(newsize
.getLeft() == UNSETPOS
&& newsize
.getTop() == UNSETPOS
);
134 if (!activator
.isVisible())
137 int old_height
= oldsize
.getHeight();
138 int new_height
= newsize
.getHeight();
140 if (old_height
== new_height
)
143 int autosize_change
= 0;
144 if (old_height
== AUTOSIZE
) {
145 old_height
= activator
.getWishHeight();
146 if (old_height
== AUTOSIZE
) {
151 if (new_height
== AUTOSIZE
) {
152 new_height
= activator
.getWishHeight();
153 if (new_height
== AUTOSIZE
) {
159 updateChildren(new_height
- old_height
, autosize_change
);
162 void ListBox::onChildWishSizeChange(
163 Widget
&activator
, const Size
&oldsize
, const Size
&newsize
)
165 if (!activator
.isVisible() || activator
.getHeight() != AUTOSIZE
)
168 // The widget is visible and is autosized.
169 int old_height
= oldsize
.getHeight();
170 int new_height
= newsize
.getHeight();
172 if (old_height
== new_height
)
175 updateChildren(new_height
- old_height
, 0);
178 void ListBox::onChildVisible(Widget
&activator
, bool visible
)
180 // The widget is being hidden or deleted.
181 int h
= activator
.getHeight();
182 int sign
= visible
? 1 : -1;
183 int autosize_change
= 0;
185 h
= activator
.getWishHeight();
188 autosize_change
= sign
;
191 updateChildren(sign
* h
, autosize_change
);
194 void ListBox::moveWidget(Widget
&widget
, Widget
&position
, bool after
)
196 Container::moveWidget(widget
, position
, after
);
198 // Reposition all child widgets.
202 void ListBox::updateChildren(
203 int children_height_change
, int autosize_children_count_change
)
205 // Set new children data.
206 children_height_
+= children_height_change
;
207 assert(children_height_
>= 0);
208 autosize_children_count_
+= autosize_children_count_change
;
209 assert(autosize_children_count_
>= 0);
211 // Reposition all child widgets.
213 signal_children_height_change(*this, children_height_
);
216 } // namespace CppConsUI
218 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: