Fix missing includes
[centerim5.git] / cppconsui / ListBox.cpp
blob8863f0e29dc9a92579b2d20ed46ed9c7616fce30
1 /*
2 * Copyright (C) 2007 by Mark Pustjens <pustjens@dds.nl>
3 * Copyright (C) 2010-2012 by CenterIM developers
5 * This file is part of CenterIM.
7 * CenterIM is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * CenterIM is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /**
23 * @file
24 * ListBox class implementation.
26 * @ingroup cppconsui
29 #include "ListBox.h"
31 namespace CppConsUI
34 ListBox::ListBox(int w, int h)
35 : AbstractListBox(w, h), children_height(0), autosize_children(0)
36 , autosize_height(0), reposition_widgets(false)
38 // allow fast focus changing (paging) using PageUp/PageDown keys
39 page_focus = true;
42 void ListBox::Draw()
44 ProceedUpdateArea();
45 // set virtual scroll area width
46 if (screen_area)
47 SetScrollWidth(screen_area->getmaxx());
48 UpdateScrollHeight();
49 if (update_area)
50 reposition_widgets = true;
51 ProceedUpdateVirtualArea();
53 if (!area) {
54 // scrollpane will clear the screen (real) area
55 AbstractListBox::Draw();
56 return;
59 if (reposition_widgets) {
60 autosize_height = 1;
61 int autosize_height_extra = 0;
62 int realh = area->getmaxy();
63 if (autosize_children && children_height < realh) {
64 int space = realh - (children_height - autosize_children);
65 autosize_height = space / autosize_children;
66 autosize_height_extra = space % autosize_children;
68 autosize_extra.clear();
70 int y = 0;
71 for (Children::iterator i = children.begin(); i != children.end(); i++) {
72 Widget *widget = i->widget;
73 if (!widget->IsVisible())
74 continue;
76 int h = widget->GetHeight();
77 if (h == AUTOSIZE) {
78 h = autosize_height;
79 if (autosize_height_extra) {
80 autosize_extra.insert(widget);
81 autosize_height_extra--;
82 h++;
85 // make sure the area is updated
86 widget->UpdateArea();
89 widget->Move(0, y);
90 y += h;
92 reposition_widgets = false;
95 // make sure that currently focused widget is visible
96 if (focus_child) {
97 int h = focus_child->GetHeight();
98 if (h == AUTOSIZE) {
99 h = autosize_height;
100 if (autosize_extra.find(focus_child) != autosize_extra.end())
101 h++;
104 MakeVisible(focus_child->GetLeft(), focus_child->GetTop(), 1, h);
107 AbstractListBox::Draw();
110 HorizontalLine *ListBox::InsertSeparator(size_t pos)
112 HorizontalLine *l = new HorizontalLine(AUTOSIZE);
113 InsertWidget(pos, *l);
114 return l;
117 HorizontalLine *ListBox::AppendSeparator()
119 HorizontalLine *l = new HorizontalLine(AUTOSIZE);
120 AppendWidget(*l);
121 return l;
124 void ListBox::InsertWidget(size_t pos, Widget& widget)
126 if (widget.IsVisible()) {
127 int h = widget.GetHeight();
128 if (h == AUTOSIZE) {
129 h = 1;
130 autosize_children++;
132 children_height += h;
133 UpdateScrollHeight();
136 // note: widget is moved to a correct position in Draw() method
137 ScrollPane::InsertWidget(pos, widget, 0, 0);
138 reposition_widgets = true;
140 if (widget.IsVisible())
141 signal_children_height_change(*this, children_height);
144 void ListBox::AppendWidget(Widget& widget)
146 InsertWidget(children.size(), widget);
149 Curses::Window *ListBox::GetSubPad(const Widget& child, int begin_x,
150 int begin_y, int ncols, int nlines)
152 // autosize
153 if (nlines == AUTOSIZE) {
154 nlines = autosize_height;
155 if (autosize_extra.find(&child) != autosize_extra.end())
156 nlines++;
159 return AbstractListBox::GetSubPad(child, begin_x, begin_y, ncols, nlines);
162 void ListBox::OnChildMoveResize(Widget& /*activator*/, const Rect& oldsize,
163 const Rect& newsize)
165 int old_height = oldsize.GetHeight();
166 int new_height = newsize.GetHeight();
167 if (old_height != new_height) {
168 if (old_height == AUTOSIZE) {
169 old_height = 1;
170 autosize_children--;
172 if (new_height == AUTOSIZE) {
173 new_height = 1;
174 autosize_children++;
176 children_height += new_height - old_height;
177 reposition_widgets = true;
178 UpdateScrollHeight();
180 signal_children_height_change(*this, children_height);
184 void ListBox::OnChildVisible(Widget& activator, bool visible)
186 // the widget is being hidden or deleted
187 int height = activator.GetHeight();
188 int sign = visible ? 1 : -1;
189 if (height == AUTOSIZE) {
190 autosize_children += sign;
191 height = 1;
193 children_height += sign * height;
194 reposition_widgets = true;
195 UpdateScrollHeight();
197 signal_children_height_change(*this, children_height);
200 void ListBox::UpdateScrollHeight()
202 int realh = 0;
203 if (screen_area)
204 realh = screen_area->getmaxy();
206 SetScrollHeight(MAX(realh, children_height));
209 } // namespace CppConsUI
211 /* vim: set tabstop=2 shiftwidth=2 textwidth=78 expandtab : */