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/>.
24 * ScrollPane class implementation.
29 #include "ScrollPane.h"
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
)
41 ScrollPane::~ScrollPane()
47 void ScrollPane::Draw()
52 int ScrollPane::GetRealWidth() const
56 return screen_area
->getmaxx();
59 int ScrollPane::GetRealHeight() const
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);
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
)
96 scroll_width
= swidth
;
97 scroll_height
= sheight
;
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
)
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
;
120 if (scroll_xpos
< 0) {
125 if (scroll_ypos
+ real_height
> scroll_height
) {
126 scroll_ypos
= scroll_height
- real_height
;
129 if (scroll_ypos
< 0) {
135 if (!scroll_xpos
&& !scroll_ypos
)
143 signal_scrollarea_scroll(*this, Point(scroll_xpos
, scroll_ypos
));
147 void ScrollPane::MakeVisible(int x
, int y
)
154 if (!MakePointVisible(x
, y
))
158 signal_scrollarea_scroll(*this, Point(scroll_xpos
, scroll_ypos
));
161 void ScrollPane::MakeVisible(int x
, int y
, int w
, int h
)
168 bool scrolled
= false;
169 if (MakePointVisible(x
+ w
- 1, y
+ h
- 1))
171 if (MakePointVisible(x
, y
))
178 signal_scrollarea_scroll(*this, Point(scroll_xpos
, scroll_ypos
));
181 void ScrollPane::UpdateArea()
183 update_screen_area
= true;
187 void ScrollPane::ProceedUpdateArea()
191 if (update_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()
206 for (Children::iterator i
= children
.begin(); i
!= children
.end(); i
++)
207 i
->widget
->UpdateArea();
212 void ScrollPane::ProceedUpdateVirtualArea()
217 area
= Curses::Window::newpad(scroll_width
, scroll_height
);
223 void ScrollPane::DrawEx(bool container_draw
)
226 ProceedUpdateVirtualArea();
228 if (!area
|| !screen_area
) {
230 screen_area
->fill(GetColorPair("container", "background"));
237 /* If the defined scrollable area is smaller than the widget, make sure
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
)
250 else if (x
>= scroll_width
)
251 x
= scroll_width
- 1;
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;
265 else if (x
< scroll_xpos
) {
270 if (y
> scroll_ypos
+ real_height
- 1) {
271 scroll_ypos
= y
- real_height
+ 1;
274 else if (y
< scroll_ypos
) {
282 } // namespace CppConsUI
284 /* vim: set tabstop=2 shiftwidth=2 textwidth=78 expandtab : */