NXWidgets  1.19
cbuttonarray.cxx
Go to the documentation of this file.
1 /****************************************************************************
2  * NxWidgets/libnxwidgets/include/cbuttonarray.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 "cbuttonarray.hxx"
48 #include "cgraphicsport.hxx"
49 #include "cwidgetstyle.hxx"
50 
51 /****************************************************************************
52  * Pre-Processor Definitions
53  ****************************************************************************/
54 
55 /****************************************************************************
56  * CButtonArray Method Implementations
57  ****************************************************************************/
58 
59 using namespace NXWidgets;
60 
61 /**
62  * Constructor for an array of 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 : CNxWidget(pWidgetControl, x, y,
82  buttonColumns * buttonWidth + 2, buttonRows * buttonHeight + 2,
83  0, style)
84 {
85  // Save configuration
86 
87  m_buttonRows = buttonRows;
88  m_buttonColumns = buttonColumns;
89  m_buttonWidth = buttonWidth;
90  m_buttonHeight = buttonHeight;
91 
92  // Make sure the the positional data is valid.
93 
94  m_clickX = x;
95  m_clickY = y;
96  m_cursorColumn = 0;
97  m_cursorRow = 0;
98 
99  // Default behavior is to redraw the entire button array
100 
101  m_redrawButton = false;
102 
103  // No hightlighted buttons
104 
105  m_cursorOn = false;
106  m_cursorChange = false;
107 
108  // At present, There is no border on the array itself
109 
110  m_flags.borderless = true;
111 
112  // Make sure that the full size of the text array is allocated
113 
115 }
116 
117 /**
118  * CButtonArray Destructor.
119  */
120 
122 {
123  // Delete the array of CNxString instances
124 
125  delete [] m_buttonText;
126 }
127 
128 /**
129  * Returns the string shown in the label.
130  *
131  * @param column The column index of the button of interest
132 * @param row The row index of the button of interest
133  * @return The label's text.
134  */
135 
136 const CNxString &CButtonArray::getText(int column, int row) const
137 {
138  return m_buttonText[row * m_buttonColumns + column];
139 }
140 
141 /**
142  * Set the text displayed in the label.
143  *
144  * @param column The column index of the button to set
145  * @param row The row index of the button to set
146  * @param text String to display.
147  */
148 
149 void CButtonArray::setText(int column, int row, const CNxString &text)
150 {
151  m_buttonText[row * m_buttonColumns + column] = text;
152  onTextChange();
153 }
154 
155 /**
156  * Return the position of the last clicked button (0,0 will be returned
157  * the no button has every been clicked). The button at this position
158  * is currently clicked then, in addition, return true.
159  *
160  * @param column The location to return the column index of the button
161  * of interest
162  * @param row The location to return the row index of the button of
163  * interest
164  * @return True if a button in the array is clicked
165  */
166 
167 bool CButtonArray::isButtonClicked(int &column, int &row) const
168 {
169  // Return the last clicked position
170 
171  column = (m_clickX - getX()) / m_buttonWidth;
172 
173  // Calculate and return the button row index
174 
175  row = (m_clickY - getY()) / m_buttonHeight;
176 
177  // Return true if the button is currently clicked
178 
179  return isClicked();
180 }
181 
182 /**
183  * Check if this specific button in the array is clicked
184  *
185  * @param column The column of the button to check.
186  * @param row The row of the button to check.
187  * @return True if this button is clicked
188  */
189 
190 bool CButtonArray::isThisButtonClicked(int column, int row) const
191 {
192  // The upper left X/Y position of the button at these indices
193 
194  nxgl_coord_t x = getX() + column * m_buttonWidth;
195  nxgl_coord_t y = getY() + row * m_buttonHeight;
196 
197  // Was the last click on this button?
198 
199  if ((m_clickX >= x && m_clickX < x + m_buttonWidth) &&
200  (m_clickY >= y && m_clickY < y + m_buttonHeight))
201  {
202  // Yes.. return true if the button is clicked
203 
204  return isClicked();
205  }
206  else
207  {
208  // No.. then it can't be clicked
209 
210  return false;
211  }
212 }
213 
214 /**
215  * Control the cursor state.
216  *
217  * @param cursorOn True(1), the current cursor position will be highlighted
218  */
219 
220 void CButtonArray::cursor(bool cursorOn)
221 {
222  if (cursorOn != m_cursorOn)
223  {
224  // Set the state cursor state
225 
226  m_cursorOn = cursorOn;
227 
228  // Update only the effected button
229 
230  m_cursorChange = true;
231  redraw();
232  m_cursorChange = false;
233  }
234 }
235 
236 /**
237  * Return the current cursor position (button indices) and an indication
238  * if the button at the cursor is currently hightlighted.
239  *
240  * @param column The location to return the column index of the button
241  * of interest
242  * @param row The location to return the row index of the button of
243  * interest
244  * @return True if the cursor is enabled and the button is highlighted
245  */
246 
247 bool CButtonArray::getCursorPosition(int &column, int &row) const
248 {
249  column = m_cursorColumn;
250  row = m_cursorRow;
251  return m_cursorOn;
252 }
253 
254 /**
255  * Set the cursor position (button indices). Note that the cursor
256  * does not have to be enabled to set the position.
257  *
258  * @param column The column index of the button of interest
259  * @param row The row index of the button of interest
260  * @return True if the cursor position is valid
261  */
262 
263 bool CButtonArray::setCursorPosition(int column, int row)
264 {
265  // Verify that the cursor position is within range
266 
267  if ((unsigned)column < m_buttonColumns && (unsigned)row < m_buttonRows)
268  {
269  // Verify that the now position is different from the old position
270 
271  if (column != m_cursorColumn || row != m_cursorRow)
272  {
273  m_cursorChange = true;
274 
275  // Is the cursor on now?
276 
277  bool redrawCursor = m_cursorOn;
278  if (redrawCursor)
279  {
280  // Yes.. clear the old cursor highlight
281 
282  m_cursorOn = false;
283  redraw();
284  }
285 
286  // Set the new cursor position
287 
288  m_cursorColumn = column;
289  m_cursorRow = row;
290 
291  // Do we need to turn the cursor back on?
292 
293  if (redrawCursor)
294  {
295  // Yes.. Set the new cursor hightlight
296 
297  m_cursorOn = true;
298  redraw();
299  }
300 
301  m_cursorChange = false;
302  }
303 
304  return true;
305  }
306 
307  return false;
308 }
309 
310 /**
311  * Check if this specific button in the array is at the cursor position
312  * and highlighted.
313  *
314  * @param column The column of the button to check.
315  * @param row The row of the button to check.
316  * @return True if this button is at the cursor position and highlighted.
317  */
318 
319 bool CButtonArray::isCursorPosition(int column, int row) const
320 {
321  if (column == m_cursorColumn && row == m_cursorRow)
322  {
323  return m_cursorOn;
324  }
325 
326  return false;
327 }
328 
329 /**
330  * Insert the dimensions that this widget wants to have into the rect
331  * passed in as a parameter. All coordinates are relative to the
332  * widget's parent.
333  *
334  * @param rect Reference to a rect to populate with data.
335  */
336 
338 {
339  return getRect(rect);
340 }
341 
342 /**
343  * Sets the font.
344  *
345  * @param font A pointer to the font to use.
346  */
347 
349 {
350  m_style.font = font;
351  redraw();
352 }
353 
354 /**
355  * Draw the area of this widget that falls within the clipping region.
356  * Called by the redraw() function to draw all visible regions.
357  *
358  * @param port The CGraphicsPort to draw to.
359  * @see redraw()
360  */
361 
363 {
364  // Do we draw just the clicked/unclicked button?
365 
366  if (m_redrawButton)
367  {
368  int column;
369  int row;
370 
371  // Just one. Get the row/column indices from the last click
372 
373  (void)posToButton(m_clickX, m_clickY, column, row);
374 
375  // And draw that button
376 
377  drawButton(port, column, row, isClicked());
378  }
379 
380  // Do we just draw the hightlighted button?
381 
382  else if (m_cursorChange)
383  {
384  // Do nothing if the highlighted button is also the clicked button
385 
387  {
388  drawButton(port, m_cursorColumn, m_cursorRow, false);
389  }
390  }
391 
392  // Draw all buttons
393 
394  else
395  {
396  // Visit each column
397 
398  for (int column = 0; column < m_buttonColumns; column++)
399  {
400  // Visit each row
401 
402  for (int row = 0; row < m_buttonRows; row++)
403  {
404  // Draw each button
405 
406  drawButton(port, column, row, isThisButtonClicked(column, row));
407  }
408  }
409  }
410 }
411 
412 /**
413  * Draw the area of this widget that falls within the clipping region.
414  * Called by the redraw() function to draw all visible regions.
415  *
416  * @param port The CGraphicsPort to draw to.
417  * @see redraw()
418  */
419 
421 {
422  // This doesn't do anything anymore
423 }
424 
425 /**
426  * Redraw only one button
427  *
428  * @param port The CGraphicsPort to draw to.
429  * @param column The button column index
430  * @param row The button row index
431  * @param useClicked Draw the button using the 'clicked' button style,
432  * regardless of the actual button state.
433  * @see onClick() and onRelease()
434  */
435 
436 void CButtonArray::drawButton(CGraphicsPort *port, int column, int row, bool useClicked)
437 {
438  // The X/Y position of the button
439 
440  nxgl_coord_t x = getX() + column * m_buttonWidth;
441  nxgl_coord_t y = getY() + row * m_buttonHeight;
442 
443  // Determine which colors to use
444 
445  nxwidget_pixel_t borderColor1;
446  nxwidget_pixel_t borderColor2;
447  nxwidget_pixel_t backColor;
448  nxwidget_pixel_t textColor;
449 
450  // Pick the background and test colors. Should we use the 'clicked' backgound style?
451 
452  if (useClicked || isCursorPosition(column, row))
453  {
454  // "Selected" text color on unique "Selected" background color
455 
456  backColor = getSelectedBackgroundColor();
457  textColor = getSelectedTextColor();
458  }
459  else
460  {
461  // Normal background color and "Enabled" text color
462 
463  backColor = getBackgroundColor();
464  textColor = getEnabledTextColor();
465  }
466 
467  // Pick the border colors. Should we use the 'clicked' button style?
468 
469  if (useClicked)
470  {
471  // Yes.. Bevelled into the screen
472 
473  borderColor1 = getShadowEdgeColor();
474  borderColor2 = getShineEdgeColor();
475  }
476  else
477  {
478  // No.. Bevelled out of the screen
479 
480  borderColor1 = getShineEdgeColor();
481  borderColor2 = getShadowEdgeColor();
482  }
483 
484  // Use a special text color if the widget is not enabled
485 
486  if (!isEnabled())
487  {
488  textColor = getDisabledTextColor();
489  }
490 
491  // Draw the background
492 
493  port->drawFilledRect(x, y, m_buttonWidth, m_buttonHeight, backColor);
494 
495  // Draw the button outline
496 
497  port->drawBevelledRect(x, y, m_buttonWidth, m_buttonHeight, borderColor1, borderColor2);
498 
499  // Get the text for this button
500 
501  CNxString *text = &m_buttonText[row * m_buttonColumns + column];
502 
503  // Get the text drawing region
504 
505  CRect rect;
506  rect.setX(x + 1);
507  rect.setY(y + 1);
508  rect.setWidth(m_buttonWidth - 2);
509  rect.setHeight(m_buttonHeight - 2);
510 
511  // Get the centered text alignment
512 
513  nxgl_coord_t alignY = (m_buttonHeight - getFont()->getHeight() - 2) >> 1;
514  nxgl_coord_t alignX = (m_buttonWidth - getFont()->getStringWidth(*text) - 2) >> 1;
515 
516  // Get the text display position
517 
518  struct nxgl_point_s pos;
519  pos.x = x + alignX;
520  pos.y = y + alignY;
521 
522  // Set the CGraphicsControl background to match the selected background color.
523  // This is only necessary if we cannot read from the LCD. If we cannot read
524  // from then the font background is set to this background color.
525  // REVISIT: This begs for a more generalized solution.
526 
527 #ifdef CONFIG_NX_WRITEONLY
528  nxgl_mxpixel_t saveColor = port->getBackColor();
529  port->setBackColor(backColor);
530 #endif
531 
532  // And draw the button text.
533 
534  port->drawText(&pos, &rect, getFont(), *text, 0, text->getLength(), textColor);
535 
536  // Restore the default background color
537 
538 #ifdef CONFIG_NX_WRITEONLY
539  port->setBackColor(saveColor);
540 #endif
541 }
542 
543 /**
544  * Redraws the button.
545  *
546  * @param x The x coordinate of the click.
547  * @param y The y coordinate of the click.
548  */
549 
550 void CButtonArray::onClick(nxgl_coord_t x, nxgl_coord_t y)
551 {
552  // Click X,Y is in raw window coordinates
553 
554  m_clickX = x;
555  m_clickY = y;
556 
557  // Redraw only the button that was clicked
558 
559  m_redrawButton = true;
560  redraw();
561  m_redrawButton = false;
562 }
563 
564 /**
565  * Raises an action.
566  *
567  * @param x The x coordinate of the mouse.
568  * @param y The y coordinate of the mouse.
569  */
570 
571 void CButtonArray::onPreRelease(nxgl_coord_t x, nxgl_coord_t y)
572 {
574 }
575 
576 /**
577  * Redraws the button.
578  *
579  * @param x The x coordinate of the mouse.
580  * @param y The y coordinate of the mouse.
581  */
582 
583 void CButtonArray::onRelease(nxgl_coord_t x, nxgl_coord_t y)
584 {
585  // Redraw only the button that was released
586 
587  m_redrawButton = true;
588  redraw();
589  m_redrawButton = false;
590 }
591 
592 /**
593  * Redraws the button.
594  *
595  * @param x The x coordinate of the mouse.
596  * @param y The y coordinate of the mouse.
597  */
598 
599 void CButtonArray::onReleaseOutside(nxgl_coord_t x, nxgl_coord_t y)
600 {
601  redraw();
602 }
603 
604 /**
605  * Convert an X/Y position to a button column/row index
606  *
607  * @param x The x position
608  * @param y The y position
609  * @param column The location to return the column index of the button
610  * of interest
611  * @param row The location to return the row index of the button of
612  * interest
613  * @return false is the position is invalid
614  */
615 
616 bool CButtonArray::posToButton(nxgl_coord_t x, nxgl_coord_t y, int &column, int &row)
617 {
618  // Get the row/column indices matching the x/y position
619 
620  column = (x - getX()) / m_buttonWidth;
621  row = (y - getY()) / m_buttonHeight;
622  return ((unsigned)column < m_buttonColumns && (unsigned)row < m_buttonRows);
623 }
624 
625 /**
626  * Updates the GUI after the text has changed.
627  */
628 
630 {
631  redraw();
633 }
634 
nxgl_coord_t m_buttonHeight
bool isClicked(void) const
Definition: cnxwidget.hxx:560
nxgl_mxpixel_t getShadowEdgeColor(void) const
Definition: cnxwidget.hxx:749
void setBackColor(nxgl_mxpixel_t backColor)
virtual bool isButtonClicked(int &column, int &row) const
CButtonArray(const CButtonArray &button)
virtual bool isCursorPosition(int column, int row) const
virtual void onPreRelease(nxgl_coord_t x, nxgl_coord_t y)
void getRect(CRect &rect) const
Definition: cnxwidget.cxx:448
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)
virtual void onRelease(nxgl_coord_t x, nxgl_coord_t y)
virtual void getPreferredDimensions(CRect &rect) const
nxgl_coord_t m_buttonWidth
nxgl_mxpixel_t getBackgroundColor(void) const
Definition: cnxwidget.hxx:716
virtual bool isThisButtonClicked(int column, int row) const
virtual void onTextChange(void)
virtual void setText(int column, int row, const CNxString &text)
uint8_t nxwidget_pixel_t
Definition: nxconfig.hxx:442
bool isEnabled(void) const
Definition: cnxwidget.cxx:381
nxgl_coord_t getStringWidth(const CNxString &text) const
Definition: cnxfont.cxx:142
virtual const CNxString & getText(int column, int row) const
nxgl_mxpixel_t getEnabledTextColor(void) const
Definition: cnxwidget.hxx:782
virtual void drawContents(CGraphicsPort *port)
void setHeight(nxgl_coord_t height)
Definition: crect.hxx:261
virtual void setFont(CNxFont *font)
void setX(nxgl_coord_t x)
Definition: crect.hxx:229
nxgl_mxpixel_t getSelectedBackgroundColor(void) const
Definition: cnxwidget.hxx:727
void drawFilledRect(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height, nxgl_mxpixel_t color)
CNxFont * getFont(void) const
Definition: cnxwidget.hxx:705
virtual void cursor(bool cursorOn)
nxgl_mxpixel_t getShineEdgeColor(void) const
Definition: cnxwidget.hxx:738
nxgl_mxpixel_t getBackColor(void) const
const uint8_t getHeight(void) const
Definition: cnxfont.hxx:229
CWidgetEventHandlerList * m_widgetEventHandlers
Definition: cnxwidget.hxx:191
const unsigned int getLength(void) const
Definition: cnxstring.hxx:325
virtual bool setCursorPosition(int column, int row)
virtual bool posToButton(nxgl_coord_t x, nxgl_coord_t y, int &column, int &row)
virtual void drawButton(CGraphicsPort *port, int column, int row, bool useClicked)
nxgl_coord_t getY(void) const
Definition: cnxwidget.cxx:261
void setWidth(nxgl_coord_t width)
Definition: crect.hxx:250
nxgl_coord_t getX(void) const
Definition: cnxwidget.cxx:245
CWidgetStyle m_style
Definition: cnxwidget.hxx:183
nxgl_mxpixel_t getDisabledTextColor(void) const
Definition: cnxwidget.hxx:771
void setY(nxgl_coord_t y)
Definition: crect.hxx:240
virtual void drawBorder(CGraphicsPort *port)
void drawText(struct nxgl_point_s *pos, CRect *bound, CNxFont *font, const CNxString &string)
virtual void onReleaseOutside(nxgl_coord_t x, nxgl_coord_t y)
virtual void onClick(nxgl_coord_t x, nxgl_coord_t y)
nxgl_mxpixel_t getSelectedTextColor(void) const
Definition: cnxwidget.hxx:793
virtual bool getCursorPosition(int &column, int &row) const