NXWidgets  1.19
cscrollingpanel.cxx
Go to the documentation of this file.
1 /****************************************************************************
2  * NxWidgets/libnxwidgets/src/cscrollingpanel.cxx
3  *
4  * Copyright (C) 2012 Gregory Nutt. All rights reserved.
5  * Author: Gregory Nutt <gnutt@nuttx.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  * 3. Neither the name NuttX, NxWidgets, nor the names of its contributors
18  * me be used to endorse or promote products derived from this software
19  * without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  ****************************************************************************
35  *
36  * Portions of this package derive from Woopsi (http://woopsi.org/) and
37  * portions are original efforts. It is difficult to determine at this
38  * point what parts are original efforts and which parts derive from Woopsi.
39  * However, in any event, the work of Antony Dzeryn will be acknowledged
40  * in most NxWidget files. Thanks Antony!
41  *
42  * Copyright (c) 2007-2011, Antony Dzeryn
43  * All rights reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions are met:
47  *
48  * * Redistributions of source code must retain the above copyright
49  * notice, this list of conditions and the following disclaimer.
50  * * Redistributions in binary form must reproduce the above copyright
51  * notice, this list of conditions and the following disclaimer in the
52  * documentation and/or other materials provided with the distribution.
53  * * Neither the names "Woopsi", "Simian Zombie" nor the
54  * names of its contributors may be used to endorse or promote products
55  * derived from this software without specific prior written permission.
56  *
57  * THIS SOFTWARE IS PROVIDED BY Antony Dzeryn ``AS IS'' AND ANY
58  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
59  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
60  * DISCLAIMED. IN NO EVENT SHALL Antony Dzeryn BE LIABLE FOR ANY
61  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
62  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
63  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
64  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
66  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67  *
68  ****************************************************************************/
69 
70 /****************************************************************************
71  * Included Files
72  ****************************************************************************/
73 
74 #include <nuttx/config.h>
75 
76 #include <stdint.h>
77 #include <stdbool.h>
78 #include <debug.h>
79 
80 #include "cwidgetcontrol.hxx"
81 #include "cscrollingpanel.hxx"
82 #include "cgraphicsport.hxx"
83 #include "singletons.hxx"
84 
85 /****************************************************************************
86  * Pre-Processor Definitions
87  ****************************************************************************/
88 
89 /****************************************************************************
90  * Method Implementations
91  ****************************************************************************/
92 
93 using namespace NXWidgets;
94 
95 /**
96  * Constructor.
97  *
98  * @param pWidgetControl The widget control for the display.
99  * @param x The x coordinate of the widget.
100  * @param y The y coordinate of the widget.
101  * @param width The width of the widget.
102  * @param height The height of the widget.
103  * @param flags The usual widget flags.
104  * @param style The style that the widget should use. If this is not
105  * specified, the widget will use the values stored in the global
106  * g_defaultWidgetStyle object. The widget will copy the properties of
107  * the style into its own internal style object.
108  */
109 
111  nxgl_coord_t x, nxgl_coord_t y,
112  nxgl_coord_t width, nxgl_coord_t height,
113  uint32_t flags, CWidgetStyle* style)
114 : CNxWidget(pWidgetControl, x, y, width, height, flags, style)
115 {
116  m_widgetControl = pWidgetControl;
117 
118  // NOTE: CScrollingPanel is temporarily borderless because there was no
119  // easy way to redraw only the required part of the border.
120 
121  m_flags.permeable = true;
122  m_flags.borderless = true;
123 
124  CRect rect;
125  getClientRect(rect);
126 
127  m_canvasWidth = rect.getWidth();
128  m_canvasHeight = rect.getHeight();
129  m_canvasX = 0;
130  m_canvasY = 0;
131 
134  setContentScrolled(true);
135 }
136 
137 /**
138  * Scroll the panel by the specified amounts.
139  *
140  * @param dx The horizontal distance to scroll.
141  * @param dy The vertical distance to scroll.
142  */
143 
144 void CScrollingPanel::scroll(int32_t dx, int32_t dy)
145 {
146  CRect rect;
147  getClientRect(rect);
148 
149  // Prevent scrolling outside boundaries
150 
151  if (m_canvasX + dx < -(m_canvasWidth - rect.getWidth()))
152  {
153  dx = -(m_canvasWidth - rect.getWidth()) - m_canvasX;
154  }
155  else if (m_canvasX + dx > 0)
156  {
157  dx = -m_canvasX;
158  }
159 
160  if (m_canvasY + dy < -(m_canvasHeight - rect.getHeight()))
161  {
162  dy = -(m_canvasHeight - rect.getHeight()) - m_canvasY;
163  }
164  else if (m_canvasY + dy > 0)
165  {
166  dy = -m_canvasY;
167  }
168 
169  // Prevent scrolling in disallowed planes
170 
171  if (!allowsVerticalScroll())
172  {
173  dy = 0;
174  }
175 
176  if (!allowsHorizontalScroll())
177  {
178  dx = 0;
179  }
180 
181  // Perform scroll if necessary
182 
183  if ((dx != 0) || (dy != 0))
184  {
185  // Only scroll if content scrolling is enabled
186 
188  {
189  // Perform scroll
190 
191  TNxArray<CRect> revealedRects;
193  port->move(getX(), getY(), dx, dy, rect.getWidth(), rect.getHeight());
194 
195  if (dx > 0)
196  {
197  revealedRects.push_back(CRect(getX(), getY(), dx, rect.getHeight()));
198  }
199  else if (dx < 0)
200  {
201  revealedRects.push_back(CRect(getX() + rect.getWidth() + dx, getY(), -dx, rect.getHeight()));
202  }
203 
204  if (dy > 0)
205  {
206  revealedRects.push_back(CRect(getX(), getY(), rect.getWidth(), dy));
207  }
208  else if (dy < 0)
209  {
210  revealedRects.push_back(CRect(getX(), getY() + rect.getHeight() + dy, rect.getWidth(), -dy));
211  }
212 
213  // Adjust the scroll values
214 
215  m_canvasY += dy;
216  m_canvasX += dx;
217 
218  // Move children but do not redraw.
219 
220  scrollChildren(dx, dy, false);
221 
222  if (revealedRects.size() > 0)
223  {
224  // Draw background to revealed sections
225 
226  for (int i = 0; i < revealedRects.size(); ++i)
227  {
228  CRect &rrect = revealedRects[i];
229 
230  ginfo("Redrawing %d,%d,%d,%d after scroll\n",
231  rrect.getX(), rrect.getY(),
232  rrect.getWidth(), rrect.getHeight());
233 
234  port->drawFilledRect(rrect.getX(), rrect.getY(),
235  rrect.getWidth(), rrect.getHeight(),
237 
238  // Check if any children intersect this region.
239  // If it does, it should be redrawn.
240 
241  for (int j = 0; j < m_children.size(); ++j)
242  {
243  CRect crect = m_children[j]->getBoundingBox();
244  if (crect.intersects(rrect))
245  {
246  m_children[j]->redraw();
247  }
248  }
249  }
250  }
251  }
252  else
253  {
254  // Adjust the scroll values
255 
256  m_canvasY += dy;
257  m_canvasX += dx;
258 
259  // Scroll all child widgets and redraw them
260 
261  scrollChildren(dx, dy, true);
262  }
263 
264  // Notify event handlers
265 
267  }
268 }
269 
270 /**
271  * Reposition the panel's scrolling region to the specified coordinates.
272  *
273  * @param x The new x coordinate of the scrolling region.
274  * @param y The new y coordinate of the scrolling region.
275  */
276 
277 void CScrollingPanel::jump(int32_t x, int32_t y)
278 {
279  // Calculate difference between jump value and current value and scroll
280 
281  scroll(x - m_canvasX, y - m_canvasY);
282 }
283 
284 /**
285  * Draw the area of this widget that falls within the clipping region.
286  * Called by the redraw() function to draw all visible regions.
287  *
288  * @param port The CGraphicsPort to draw to.
289  * @see redraw()
290  */
291 
293 {
294  port->drawFilledRect(getX(), getY(), getWidth(), getHeight(),
296 }
297 
298 /**
299  * Draw the area of this widget that falls within the clipping region.
300  * Called by the redraw() function to draw all visible regions.
301  *
302  * @param port The CGraphicsPort to draw to.
303  * @see redraw()
304  */
305 
307 {
308  // Stop drawing if the widget indicates it should not have an outline
309 
310  if (!isBorderless())
311  {
312  port->drawBevelledRect(getX(), getY(), getWidth(), getHeight(),
314  }
315 }
316 
317 /**
318  * Scrolls the panel to match the drag.
319  *
320  * @param x The x coordinate of the mouse.
321  * @param y The y coordinate of the mouse.
322  * @param vX The horizontal drag distance.
323  * @param vY The vertical drag distance.
324  */
325 
326 void CScrollingPanel::onDrag(nxgl_coord_t x, nxgl_coord_t y,
327  nxgl_coord_t vX, nxgl_coord_t vY)
328 {
329  scroll(vX, vY);
330 }
331 
332 /**
333  * Starts the dragging system.
334  *
335  * @param x The x coordinate of the click.
336  * @param y The y coordinate of the click.
337  */
338 
339 void CScrollingPanel::onClick(nxgl_coord_t x, nxgl_coord_t y)
340 {
341  startDragging(x, y);
342 }
343 
344 /**
345  * Scroll all child widgets by the specified amounts. Actually uses
346  * the widget's moveTo() function to reposition them.
347  *
348  * @param dx The horizontal distance to scroll.
349  * @param dy The vertical distance to scroll.
350  * @param do_redraw Redraw widgets after moving.
351  */
352 
353 void CScrollingPanel::scrollChildren(int32_t dx, int32_t dy, bool do_redraw)
354 {
355  nxgl_coord_t widgetX = 0;
356  nxgl_coord_t widgetY = 0;
357  nxgl_coord_t thisX = getX();
358  nxgl_coord_t thisY = getY();
359  CNxWidget *widget = (CNxWidget *)NULL;
360 
361  for (int32_t i = 0; i < m_children.size(); i++)
362  {
363  widget = m_children[i];
364  bool oldstate = widget->isDrawingEnabled();
365 
366  if (!do_redraw)
367  {
368  widget->disableDrawing();
369  }
370 
371  widgetX = (widget->getX() - thisX) + dx;
372  widgetY = (widget->getY() - thisY) + dy;
373  widget->moveTo(widgetX, widgetY);
374 
375  if (!do_redraw && oldstate)
376  {
377  widget->enableDrawing();
378  }
379  }
380 }
bool allowsVerticalScroll(void) const
virtual void drawBorder(CGraphicsPort *port)
bool isBorderless(void) const
Definition: cnxwidget.hxx:549
void raiseScrollEvent(nxgl_coord_t vX, nxgl_coord_t vY)
nxgl_mxpixel_t getShadowEdgeColor(void) const
Definition: cnxwidget.hxx:749
nxgl_coord_t getHeight(void) const
Definition: crect.hxx:204
CGraphicsPort * getGraphicsPort(void)
bool moveTo(nxgl_coord_t x, nxgl_coord_t y)
Definition: cnxwidget.cxx:990
void disableDrawing(void)
Definition: cnxwidget.hxx:908
nxgl_coord_t getWidth(void) const
Definition: crect.hxx:181
void drawBevelledRect(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height, nxgl_mxpixel_t shineColor, nxgl_mxpixel_t shadowColor)
nxgl_coord_t getX(void) const
Definition: crect.hxx:160
bool intersects(const CRect &rect) const
Definition: crect.cxx:318
virtual void onClick(nxgl_coord_t x, nxgl_coord_t y)
nxgl_mxpixel_t getBackgroundColor(void) const
Definition: cnxwidget.hxx:716
void setContentScrolled(bool scrolled)
CWidgetControl * m_widgetControl
bool allowsHorizontalScroll(void) const
nxgl_coord_t getHeight(void) const
Definition: cnxwidget.hxx:593
CScrollingPanel(const CScrollingPanel &scrollingPanel)
void getClientRect(CRect &rect) const
Definition: cnxwidget.cxx:421
virtual void drawContents(CGraphicsPort *port)
void drawFilledRect(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height, nxgl_mxpixel_t color)
void setAllowsHorizontalScroll(bool allow)
void scrollChildren(int32_t dx, int32_t dy, bool do_redraw)
nxgl_mxpixel_t getShineEdgeColor(void) const
Definition: cnxwidget.hxx:738
void push_back(const T &value)
Definition: tnxarray.hxx:267
void enableDrawing(void)
Definition: cnxwidget.hxx:917
CWidgetEventHandlerList * m_widgetEventHandlers
Definition: cnxwidget.hxx:191
virtual void scroll(int32_t dx, int32_t dy)
nxgl_coord_t getY(void) const
Definition: cnxwidget.cxx:261
void setAllowsVerticalScroll(bool allow)
nxgl_coord_t getWidth(void) const
Definition: cnxwidget.hxx:582
nxgl_coord_t getX(void) const
Definition: cnxwidget.cxx:245
void move(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t deltaX, nxgl_coord_t deltaY, nxgl_coord_t width, nxgl_coord_t height)
nxgl_coord_t getY(void) const
Definition: crect.hxx:170
const int size(void) const
Definition: tnxarray.hxx:261
TNxArray< CNxWidget * > m_children
Definition: cnxwidget.hxx:204
bool isDrawingEnabled(void) const
Definition: cnxwidget.cxx:325
void startDragging(nxgl_coord_t x, nxgl_coord_t y)
Definition: cnxwidget.cxx:1542
virtual void jump(int32_t x, int32_t y)
virtual void onDrag(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t vX, nxgl_coord_t vY)