Fix missing includes
[centerim5.git] / cppconsui / ScrollPane.cpp
blob2f13599045ffcbefa28ef675865eaf2150909eb5
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 * ScrollPane class implementation.
26 * @ingroup cppconsui
29 #include "ScrollPane.h"
31 namespace CppConsUI
34 ScrollPane::ScrollPane(int w, int h, int scrollw, int scrollh)
35 : Container(w, h), scroll_xpos(0), scroll_ypos(0), scroll_width(scrollw)
36 , scroll_height(scrollh), update_screen_area(false), screen_area(NULL)
38 update_area = true;
41 ScrollPane::~ScrollPane()
43 if (screen_area)
44 delete screen_area;
47 void ScrollPane::Draw()
49 DrawEx(true);
52 int ScrollPane::GetRealWidth() const
54 if (!screen_area)
55 return 0;
56 return screen_area->getmaxx();
59 int ScrollPane::GetRealHeight() const
61 if (!screen_area)
62 return 0;
63 return screen_area->getmaxy();
66 Point ScrollPane::GetRelativePosition(const Container& ref,
67 const Widget& child) const
69 g_assert(child.GetParent() == this);
71 if (!parent || this == &ref)
72 return Point(child.GetLeft() - scroll_xpos, child.GetTop() - scroll_ypos);
74 Point p = parent->GetRelativePosition(ref, *this);
75 return Point(p.GetX() + child.GetLeft() - scroll_xpos,
76 p.GetY() + child.GetTop() - scroll_ypos);
79 Point ScrollPane::GetAbsolutePosition(const Widget& child) const
81 g_assert(child.GetParent() == this);
83 if (!parent)
84 return Point(child.GetLeft() - scroll_xpos, child.GetTop() - scroll_ypos);
86 Point p = parent->GetAbsolutePosition(*this);
87 return Point(p.GetX() + child.GetLeft() - scroll_xpos,
88 p.GetY() + child.GetTop() - scroll_ypos);
91 void ScrollPane::SetScrollSize(int swidth, int sheight)
93 if (swidth == scroll_width && sheight == scroll_height)
94 return;
96 scroll_width = swidth;
97 scroll_height = sheight;
98 UpdateVirtualArea();
100 signal_scrollarea_resize(*this, Size(scroll_width, scroll_height));
103 void ScrollPane::AdjustScroll(int newx, int newy)
105 bool scrolled = false;
106 if (scroll_xpos != newx || scroll_ypos != newy)
107 scrolled = true;
109 if (screen_area) {
110 scroll_xpos = newx;
111 scroll_ypos = newy;
113 int real_width = screen_area->getmaxx();
114 int real_height = screen_area->getmaxy();
116 if (scroll_xpos + real_width > scroll_width) {
117 scroll_xpos = scroll_width - real_width;
118 scrolled = true;
120 if (scroll_xpos < 0) {
121 scroll_xpos = 0;
122 scrolled = true;
125 if (scroll_ypos + real_height > scroll_height) {
126 scroll_ypos = scroll_height - real_height;
127 scrolled = true;
129 if (scroll_ypos < 0) {
130 scroll_ypos = 0;
131 scrolled = true;
134 else {
135 if (!scroll_xpos && !scroll_ypos)
136 scrolled = true;
137 scroll_xpos = 0;
138 scroll_ypos = 0;
141 if (scrolled) {
142 Redraw();
143 signal_scrollarea_scroll(*this, Point(scroll_xpos, scroll_ypos));
147 void ScrollPane::MakeVisible(int x, int y)
149 if (!screen_area) {
150 AdjustScroll(0, 0);
151 return;
154 if (!MakePointVisible(x, y))
155 return;
157 Redraw();
158 signal_scrollarea_scroll(*this, Point(scroll_xpos, scroll_ypos));
161 void ScrollPane::MakeVisible(int x, int y, int w, int h)
163 if (!screen_area) {
164 AdjustScroll(0, 0);
165 return;
168 bool scrolled = false;
169 if (MakePointVisible(x + w - 1, y + h - 1))
170 scrolled = true;
171 if (MakePointVisible(x, y))
172 scrolled = true;
174 if (!scrolled)
175 return;
177 Redraw();
178 signal_scrollarea_scroll(*this, Point(scroll_xpos, scroll_ypos));
181 void ScrollPane::UpdateArea()
183 update_screen_area = true;
184 Redraw();
187 void ScrollPane::ProceedUpdateArea()
189 g_assert(parent);
191 if (update_screen_area) {
192 if (screen_area)
193 delete screen_area;
194 screen_area = parent->GetSubPad(*this, xpos, ypos, width, height);
196 // fix scroll position if necessary
197 AdjustScroll(scroll_xpos, scroll_ypos);
199 update_screen_area = false;
203 void ScrollPane::UpdateVirtualArea()
205 if (!update_area)
206 for (Children::iterator i = children.begin(); i != children.end(); i++)
207 i->widget->UpdateArea();
209 update_area = true;
212 void ScrollPane::ProceedUpdateVirtualArea()
214 if (update_area) {
215 if (area)
216 delete area;
217 area = Curses::Window::newpad(scroll_width, scroll_height);
219 update_area = false;
223 void ScrollPane::DrawEx(bool container_draw)
225 ProceedUpdateArea();
226 ProceedUpdateVirtualArea();
228 if (!area || !screen_area) {
229 if (screen_area)
230 screen_area->fill(GetColorPair("container", "background"));
231 return;
234 if (container_draw)
235 Container::Draw();
237 /* If the defined scrollable area is smaller than the widget, make sure
238 * the copy works. */
239 int copyw = MIN(scroll_width, screen_area->getmaxx()) - 1;
240 int copyh = MIN(scroll_height, screen_area->getmaxy()) - 1;
242 area->copyto(screen_area, scroll_xpos, scroll_ypos, 0, 0, copyw, copyh, 0);
245 bool ScrollPane::MakePointVisible(int x, int y)
247 // fix parameters
248 if (x < 0)
249 x = 0;
250 else if (x >= scroll_width)
251 x = scroll_width - 1;
252 if (y < 0)
253 y = 0;
254 else if (y >= scroll_height)
255 y = scroll_height - 1;
257 int real_width = screen_area->getmaxx();
258 int real_height = screen_area->getmaxy();
260 bool scrolled = false;
261 if (x > scroll_xpos + real_width - 1) {
262 scroll_xpos = x - real_width + 1;
263 scrolled = true;
265 else if (x < scroll_xpos) {
266 scroll_xpos = x;
267 scrolled = true;
270 if (y > scroll_ypos + real_height - 1) {
271 scroll_ypos = y - real_height + 1;
272 scrolled = true;
274 else if (y < scroll_ypos) {
275 scroll_ypos = y;
276 scrolled = true;
279 return scrolled;
282 } // namespace CppConsUI
284 /* vim: set tabstop=2 shiftwidth=2 textwidth=78 expandtab : */