discoverpixy
checkbox.c
Go to the documentation of this file.
1 /**************************************************************************************************************************************
2 * Project: discoverpixy
3 * Website: https://github.com/t-moe/discoverpixy
4 * Authors: Aaron Schmocker, Timo Lang
5 * Institution: BFH Bern University of Applied Sciences
6 * File: common/gui/checkbox.c
7 *
8 * Version History:
9 * Date Autor Email SHA Changes
10 * 2015-04-27 timolang@gmail.com b300ac5 Added Checkbox support
11 * 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
12 *
13 **************************************************************************************************************************************/
14 
15 #include "tft.h"
16 #include "touch.h"
17 #include "checkbox.h"
18 #include <stdio.h>
19 
20 /* The idea is as follows:
21  * When the user creates a checkbox we create a touch area for that region and wait for PEN_DOWN events.
22  * Once the user puts the pen down in this area we'll redraw the checkbox with different shadows (feedback)
23  * and we'll now wait on PEN_UP or PEN_LEAVE events.
24  * If the user takes the pen away while in the area (PEN_UP), we toggle the checkbox and we call the provided user callback
25  * Otherwise (PEN_LEAVE) we only restore the initial shadows
26  */
27 
28 
29 #define ACTIVE_COLOR RGB(251,208,123) //shadow color (inside of border)
30 #define BORDER_COLOR RGB(29,82,129) //1px border color
31 #define BACKGROUND_COLOR WHITE //Background color
32 
33 //Callback which is called when the user touches the touch-area we created for the checkbox
34 void checkboxes_cb(void* touchArea, TOUCH_ACTION triggeredAction)
35 {
36  TOUCH_AREA_STRUCT* area = (TOUCH_AREA_STRUCT*)touchArea;
37  CHECKBOX_STRUCT* checkbox = (CHECKBOX_STRUCT*)touchArea;
38 
39  switch (triggeredAction) {
40  case PEN_DOWN: //If the user touches the area for the "first time"
41  area->hookedActions = PEN_UP | PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events
42 
43  //Draw active shadows
44  tft_draw_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, ACTIVE_COLOR);
45  tft_draw_rectangle(checkbox->base.x1 + 2, checkbox->base.y1 + 2, checkbox->base.x2 - 2, checkbox->base.y2 - 2, ACTIVE_COLOR);
46  break;
47 
48  case PEN_UP: //If the user took the pen away, while in the area (=toggle checkbox!)
49  checkbox->checked = !checkbox->checked; //Toggle checkbox state
50  gui_checkbox_update(checkbox); //redraw/overdraw tickmark
51 
52  if (checkbox->callback != NULL) { //The user provided a callback
53  checkbox->callback(checkbox, checkbox->checked); //Call the provided callback with the new checked state
54  }
55 
56  // no break statement here!
57  case PEN_LEAVE: //if the user "slided out" of the area
58  area->hookedActions = PEN_DOWN; //for the future we only want PEN_DOWN events
59 
60  //Draw inactive shadows
61  tft_draw_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, BACKGROUND_COLOR);
62  tft_draw_rectangle(checkbox->base.x1 + 2, checkbox->base.y1 + 2, checkbox->base.x2 - 2, checkbox->base.y2 - 2, BACKGROUND_COLOR);
63  break;
64 
65  default:
66  break;
67  }
68 }
69 
71 {
72  if (touch_have_empty(1)) { //Check if the touch module can handle one additional area
73  unsigned char size = 0;
74  checkbox->base.hookedActions = PEN_DOWN; //At first we are interested in PEN_DOWN events
75  checkbox->base.callback = checkboxes_cb; //Use our own callback for the touch area events
76 
77  //Check the size of the checkbox
78  if (checkbox->base.x2 > checkbox->base.x1) {
79  size = checkbox->base.x2 - checkbox->base.x1; //use width a as size
80  }
81 
82  if (checkbox->base.y2 > checkbox->base.y1) {
83  if ((checkbox->base.y2 - checkbox->base.y1) > size) { //height is larger than size
84  size = checkbox->base.y2 - checkbox->base.y1; //use height as size
85  }
86  }
87 
88  if (size == 0) { //no size found (maybe swap x2 and x1 or y2 and y1 ?)
89  return false; //signal error
90  }
91 
92  if ((size & 0x01)) { //the size is an odd number
93  size++; //make size an even number
94  }
95 
96  //Correct x2,y2 so that the checkbox is quadratic
97  checkbox->base.x2 = checkbox->base.x1 + size;
98  checkbox->base.y2 = checkbox->base.y1 + size;
99 
100  gui_checkbox_redraw(checkbox);//Call redraw method, which will take care of the drawing of the entire checkbox
101 
102  return touch_register_area(&checkbox->base); //Register the touch area and receive events for this checkbox, from now on
103  }
104 
105  return false; //no more touch areas left
106 }
107 
109 {
110  //Draw background and border
111  tft_fill_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, BACKGROUND_COLOR);
112  tft_draw_rectangle(checkbox->base.x1, checkbox->base.y1, checkbox->base.x2, checkbox->base.y2, BORDER_COLOR);
113 
114  if (checkbox->checked) { //checkbox is currently checked
115  gui_checkbox_update(checkbox); //Call update method which will draw the tickmark
116  }
117 }
118 
120 {
121  //We only need to unregister the touch area, as we have not allocated anything else
123 }
124 
126 {
127  unsigned int c = (checkbox->checked) ? checkbox->fgcolor : BACKGROUND_COLOR; //color to use for the tickmark
128 
129  //helper points inside the checkbox
130  unsigned int xcent = checkbox->base.x1 + (checkbox->base.x2 - checkbox->base.x1) * 6 / 14;
131  unsigned int yleft = checkbox->base.y2 - (xcent - checkbox->base.x1) - 1 ;
132  unsigned int yright = checkbox->base.y2 - (checkbox->base.x2 - xcent) - 1 ;
133  unsigned int ybot = checkbox->base.y2 - 4;
134 
135  //Draw tickmark as a 3pixel wide line
136  tft_draw_line(checkbox->base.x1 + 3, yleft - 1, xcent, ybot - 1, c);
137  tft_draw_line(checkbox->base.x1 + 3, yleft, xcent, ybot , c);
138  tft_draw_line(checkbox->base.x1 + 3, yleft + 1, xcent, ybot + 1, c);
139  xcent++;
140  ybot--;
141  tft_draw_line(xcent, ybot - 1, checkbox->base.x2 - 3, yright - 1, c);
142  tft_draw_line(xcent, ybot, checkbox->base.x2 - 3, yright + 0, c);
143  tft_draw_line(xcent, ybot + 1, checkbox->base.x2 - 3, yright + 1, c);
144 }
TOUCH_ACTION
Definition: touch.h:52
bool touch_register_area(TOUCH_AREA_STRUCT *area)
Definition: touch.c:181
Receive an event when the pen goes down inside the region.
Definition: touch.h:54
Receive an event when the pen goes up inside the region.
Definition: touch.h:55
bool gui_checkbox_add(CHECKBOX_STRUCT *checkbox)
Definition: checkbox.c:70
void tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Definition: tft.c:50
#define ACTIVE_COLOR
Definition: checkbox.c:29
uint16_t y1
Top Left Y-Coordinate of Area.
Definition: touch.h:75
void gui_checkbox_update(CHECKBOX_STRUCT *checkbox)
Definition: checkbox.c:125
#define BACKGROUND_COLOR
Definition: checkbox.c:31
void gui_checkbox_remove(CHECKBOX_STRUCT *checkbox)
Definition: checkbox.c:119
uint16_t x1
Top Left X-Coordinate of Area.
Definition: touch.h:74
bool checked
A boolean which indicates whether or not the checkbox is currently checked.
Definition: checkbox.h:53
void touch_unregister_area(TOUCH_AREA_STRUCT *area)
Definition: touch.c:195
uint16_t y2
Bottom Right Y-Coordinate of Area.
Definition: touch.h:77
TOUCH_CALLBACK callback
Callback which is executed when an event occurred in this Area.
Definition: touch.h:78
uint16_t x2
Bottom Right X-Coordinate of Area.
Definition: touch.h:76
void tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Definition: tft.c:67
TOUCH_ACTION hookedActions
Actions to listen to.
Definition: touch.h:73
void tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Definition: tft.c:61
#define BORDER_COLOR
Definition: checkbox.c:30
TOUCH_AREA_STRUCT base
Basic geometry of the Checkbox. You only need to set the x1, y1, x2, y2 members of this struct...
Definition: checkbox.h:51
uint16_t fgcolor
The 16-bit color of the tickmark.
Definition: checkbox.h:52
bool touch_have_empty(unsigned char num)
Definition: touch.c:165
void gui_checkbox_redraw(CHECKBOX_STRUCT *checkbox)
Definition: checkbox.c:108
void checkboxes_cb(void *touchArea, TOUCH_ACTION triggeredAction)
Definition: checkbox.c:34
CHECKBOX_CALLBACK callback
Callback which is executed when the checkbox changes state.
Definition: checkbox.h:54
Receive an event when the pen leaves the region (pen was inside region before)
Definition: touch.h:57