NXWidgets  1.19
cstickybuttonarray.cxx
Go to the documentation of this file.
1 /****************************************************************************
2  * NxWidgets/libnxwidgets/include/cstickybuttonarray.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 /****************************************************************************
37  * Included Files
38  ****************************************************************************/
39 
40 #include <nuttx/config.h>
41 
42 #include <stdint.h>
43 #include <stdbool.h>
44 
45 #include <nuttx/nx/nxglib.h>
46 
47 #include "cstickybuttonarray.hxx"
48 #include "cgraphicsport.hxx"
49 #include "cwidgetstyle.hxx"
50 
51 /****************************************************************************
52  * Pre-Processor Definitions
53  ****************************************************************************/
54 
55 /****************************************************************************
56  * CStickyButtonArray Method Implementations
57  ****************************************************************************/
58 
59 using namespace NXWidgets;
60 
61 /**
62  * Constructor for an array of sticky buttons.
63  *
64  * @param pWidgetControl The widget control for the display.
65  * @param x The x coordinate of the button array, relative to its parent.
66  * @param y The y coordinate of the button array, relative to its parent.
67  * @param buttonColumns The number of buttons in one row of the button array
68  * @param buttonRows The number of buttons in one column of the button array
69  * @param buttonWidth The width of one button
70  * @param buttonHeight The height of one button
71  * @param style The style that the button should use. If this is not
72  * specified, the button will use the global default widget
73  * style.
74  */
75 
77  nxgl_coord_t x, nxgl_coord_t y,
78  uint8_t buttonColumns, uint8_t buttonRows,
79  nxgl_coord_t buttonWidth, nxgl_coord_t buttonHeight,
80  CWidgetStyle *style)
81 : CButtonArray(pWidgetControl, x, y, buttonColumns, buttonRows, buttonWidth, buttonHeight, style)
82 {
83  // Initialize state
84 
85  m_isStuckDown = false;
86  m_stickDown = false;
87 }
88 
89 /**
90  * Check if any button in the array is stuck down and, if so,
91  * return the indices of the stuck down button.
92  *
93  * @param column The location to return the column index of the button
94  * of interest
95  * @param row The location to return the row index of the button of
96  * interest
97  * @return True if a button in the array is clicked
98  */
99 
100 bool CStickyButtonArray::isAnyButtonStuckDown(int &column, int &row) const
101 {
102  // Return the indices of the last stuck button
103 
104  column = m_stickyColumn;
105  row = m_stickyRow;
106 
107  // Return true if the button is currently stuck
108 
109  return m_isStuckDown;
110 }
111 
112 /**
113  * Check if this specific button in the array is stuck down
114  *
115  * @param column The column of the button to check.
116  * @param row The row of the button to check.
117  * @return True if this button is stuck down
118  */
119 
120 bool CStickyButtonArray::isThisButtonStuckDown(int column, int row) const
121 {
122  // Does this match the index of the last stuck button?
123 
124  if (column == m_stickyColumn && row == m_stickyRow)
125  {
126  // Yes.. return true if it is still stuck
127 
128  return m_isStuckDown;
129  }
130  else
131  {
132  // This button is definitely not stuck down
133 
134  return false;
135  }
136 }
137 
138 /**
139  * Force the button at this position into the stuck down state
140  *
141  * @param column The column containing the button to stick down
142  * @param row The rowtcontaining the button to stick down
143  * @return False(0) is returned if the indices are out of range.
144  */
145 
146 bool CStickyButtonArray::stickDown(int column, int row)
147 {
148  // Verify that the cursor position is within range
149 
150  if ((unsigned)column < m_buttonColumns && (unsigned)row < m_buttonRows)
151  {
152  // First, unstick any currently stuck buttons
153 
154  unstick();
155 
156  // Then stick this button down
157 
158  m_stickyColumn = column;
159  m_stickyRow = row;
160  m_isStuckDown = true;
161 
162  // We only want to update the stuck down buttons
163 
164  m_stickDown = true;
165  redraw();
166  m_stickDown = false;
167  return true;
168  }
169 
170  return false;
171 }
172 
173 /**
174  * Unstick all buttons.
175  */
176 
178 {
179  // Is any button stuck down?
180 
181  if (m_isStuckDown)
182  {
183  // Yes.. unstick it and update the button display
184 
185  m_isStuckDown = false;
186 
187  // We only want to update the stuck down buttons
188 
189  m_stickDown = true;
190  redraw();
191  m_stickDown = false;
192  }
193 }
194 
195 /**
196  * Draw the area of this widget that falls within the clipping region.
197  * Called by the redraw() function to draw all visible regions.
198  *
199  * @param port The CGraphicsPort to draw to.
200  * @see redraw()
201  */
202 
204 {
205  // Are we just updating the stuck down button?
206 
207  if (m_stickDown)
208  {
209  // There are two cases: (1) A sticky button was unstuck, or (2) a new
210  // button is stuck down. m_isStuckDown will distinguish these
211  //
212  // Draw the button using the clicked style if either (1) it is
213  // stuck down OR (2) it is currently clicked. Draw the button in
214  // the normal style if is is un-stuck and not clicked.
215  //
216  // NOTE: If usedClicked is false, the button may revert to either
217  // (1) the "normal" button state, or (2) the "highlighted" button
218  // stated. drawButton() will handle that.
219 
221  drawButton(port, m_stickyColumn, m_stickyRow, useClicked);
222  }
223 
224  // Do we draw just one button (due to click or release)?
225 
226  else if (m_redrawButton)
227  {
228  // Just one. Get the row/column indices from the last click
229 
230  int column;
231  int row;
232  bool useClicked = isButtonClicked(column, row);
233 
234  // If this is a press or release on the stuck down button, then don't
235  // redraw the button. Drawing of stuck down and unstuck buttons is
236  // controlled entirely by the m_stickDown case.
237 
238  if (!isThisButtonStuckDown(column, row))
239  {
240  // Not a stuck down button. Re-draw that button
241 
242  drawButton(port, column, row, useClicked);
243  }
244  }
245 
246  // Do we just draw the hightlighted button?
247 
248  else if (m_cursorChange)
249  {
250  // Do nothing if the highlighted button is also the stuck down button
251  // or the clicked button
252 
255  {
256  drawButton(port, m_cursorColumn, m_cursorRow, false);
257  }
258  }
259 
260  // Draw all buttons
261 
262  else
263  {
264  // Visit each column
265 
266  for (int column = 0; column < m_buttonColumns; column++)
267  {
268  // Visit each row
269 
270  for (int row = 0; row < m_buttonRows; row++)
271  {
272  // Is the button clicked?
273 
274  bool useClicked = isThisButtonClicked(column, row);
275 
276  // If the button is not clicked but it is the stuck button,
277  // then draw it as clicked anyway.
278 
279  if (!useClicked)
280  {
281  useClicked = isThisButtonStuckDown(column, row);
282  }
283 
284  // Draw each button. If useClicked is false, then drawButton
285  // will do the right thing if the button is highlighted.
286 
287  drawButton(port, column, row, useClicked);
288  }
289  }
290  }
291 }
292 
virtual bool isButtonClicked(int &column, int &row) const
virtual bool isThisButtonClicked(int column, int row) const
CStickyButtonArray(const CStickyButtonArray &button)
virtual bool stickDown(int column, int row)
virtual void drawButton(CGraphicsPort *port, int column, int row, bool useClicked)
virtual void drawContents(CGraphicsPort *port)
virtual bool isAnyButtonStuckDown(int &column, int &row) const
virtual bool isThisButtonStuckDown(int column, int row) const