discoverpixy
numupdown.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/numupdown.c
7 *
8 * Version History:
9 * Date Autor Email SHA Changes
10 * 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support.
11 * 2015-04-30 timolang@gmail.com b491b78 Made numupdown horizontal
12 * 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
13 * 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
14 *
15 **************************************************************************************************************************************/
16 
17 #include "tft.h"
18 #include "touch.h"
19 #include "button.h"
20 #include "numupdown.h"
21 #include <stdio.h> //for sprintf
22 #include <stddef.h> //for offsetof macro
23 #include <stdlib.h> //for abs
24 
25 /* The idea is as follows:
26  * When the user add's a numupdown we create two buttons, one with a plus and one with a minus sign in it
27  * When the user presses one of the buttons we check and increase the value and execute the provided user callback
28  */
29 
30 
31 #define BASE_COLOR RGB(90,90,90) //Background color for the whole element
32 
33 //Callback which is called when the user presses the "plus" button
34 void button_up_cb(void* button)
35 {
36  //Get the pointer to the numupdown: subtract the offset of the buttonUp member in the struct from the button pointer
37  NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonUp);
38 
39  if (element->value < element->max) { //old value lies below the maximum
40  element->value++; //let's increase the value
41  gui_numupdown_update(element); //and redraw everything
42 
43  if (element->callback != NULL) { //the user provided a callback
44  element->callback(element, element->value); //Call the user callback with the new value
45  }
46  }
47 }
48 
49 //Callback which is called when the user presses the "minus" button
50 void button_down_cb(void* button)
51 {
52  //Get the pointer to the numupdown: subtract the offset of the buttonDown member in the struct from the button pointer
53  NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonDown);
54 
55  if (element->value > element->min) { //old value lies above the minimum
56  element->value--; //let's decrease the value
57  gui_numupdown_update(element); //and redraw everything
58 
59  if (element->callback != NULL) { //the user provided a callback
60  element->callback(element, element->value); //Call the user callback with the new value
61  }
62  }
63 }
64 
65 //Method to calculate the number of characters needed to print the provided number in decimal notation (with optional sign)
66 static uint8_t calc_text_width(int16_t val)
67 {
68  uint8_t width = 1 + (val < 0); //1 if positive, 2 if negative (to let space for sign)
69  val = abs(val); //Make the number positive
70 
71  while (val >= 10) { //while we have two or more digits
72  val /= 10; //remove one digit
73  width++; //add one character
74  }
75 
76  return width;
77 }
78 
79 
81 {
82  if (touch_have_empty(2)) { //Check if the touch module can handle two additional areas
83  if (numupdown->min > numupdown->max) { //min is bigger than max?
84  return false; //invalid parameter
85  }
86 
87  if (numupdown->value < numupdown->min) { //value is smaller than min?
88  numupdown->value = numupdown->min; //normalize value
89  } else if (numupdown->value > numupdown->max) { //value is bigger than max?
90  numupdown->value = numupdown->max; //normalize value
91  }
92 
93  uint8_t tw1 = calc_text_width(numupdown->max); //Calculate character width to render maximum value
94  uint8_t tw2 = calc_text_width(numupdown->min); //Calculate character width to render minimum value
95 
96  if (tw2 > tw1) {
97  tw1 = tw2; //ensure tw1 contains the larger number of the two
98  }
99 
100  uint8_t width = tft_font_width(0) * (tw1 + 1); //Calculate width of the number area
101 
102  //Add "minus" button to the left side of the number area
103  numupdown->buttonDown.base.x1 = numupdown->x;
104  numupdown->buttonDown.base.y1 = numupdown->y;
105  numupdown->buttonDown.base.x2 = AUTO;
106  numupdown->buttonDown.base.y2 = numupdown->y + tft_font_height(0) * 2;
107  numupdown->buttonDown.text = "-";
108  numupdown->buttonDown.font = 0;
109  numupdown->buttonDown.bgcolor = BASE_COLOR;
110  numupdown->buttonDown.txtcolor = WHITE;
111  numupdown->buttonDown.callback = button_down_cb;
112  gui_button_add(&numupdown->buttonDown);
113 
114  //Add "plus" button to the right side of the number area
115  numupdown->buttonUp.base.x1 = numupdown->buttonDown.base.x2 + width + 2;
116  numupdown->buttonUp.base.y1 = numupdown->y;
117  numupdown->buttonUp.base.x2 = AUTO;
118  numupdown->buttonUp.base.y2 = numupdown->y + tft_font_height(0) * 2;
119  numupdown->buttonUp.text = "+";
120  numupdown->buttonUp.font = 0;
121  numupdown->buttonUp.bgcolor = BASE_COLOR;
122  numupdown->buttonUp.txtcolor = WHITE;
123  numupdown->buttonUp.callback = button_up_cb;
124  gui_button_add(&numupdown->buttonUp);
125 
126  //Draw background and label of the number area
127  tft_fill_rectangle(numupdown->buttonDown.base.x2 + 2, numupdown->y, numupdown->buttonDown.base.x2 + width, numupdown->buttonUp.base.y2, BASE_COLOR);
128  tft_print_formatted(numupdown->buttonDown.base.x2 + 2 + tft_font_width(0) / 2, numupdown->y + tft_font_height(0) / 2, numupdown->fgcolor, BASE_COLOR, 0, "%*d", tw1, numupdown->value);
129 
130  return true;
131  }
132 
133  return false; //not enough touch areas left
134 }
135 
137 {
138  //remove the two buttons, we have no other allocated resources
139  gui_button_remove(&numupdown->buttonUp);
140  gui_button_remove(&numupdown->buttonDown);
141 }
142 
143 
145 {
146  //redraw the two buttons
147  gui_button_redraw(&numupdown->buttonUp);
148  gui_button_redraw(&numupdown->buttonDown);
149 
150  //call update method which will take care of the number-area rendering
151  gui_numupdown_update(numupdown);
152 }
153 
155 {
156  //Calculate the number area width again (see above)
157  uint8_t tw1 = calc_text_width(numupdown->max);
158  uint8_t tw2 = calc_text_width(numupdown->min);
159 
160  if (tw2 > tw1) {
161  tw1 = tw2;
162  }
163 
164  uint8_t width = tft_font_width(0) * (tw1 + 1);
165 
166  //Draw background and label of the number area
167  tft_fill_rectangle(numupdown->buttonDown.base.x2 + 2, numupdown->y, numupdown->buttonDown.base.x2 + width, numupdown->buttonUp.base.y2, BASE_COLOR);
168  tft_print_formatted(numupdown->buttonDown.base.x2 + 2 + tft_font_width(0) / 2, numupdown->y + tft_font_height(0) / 2, numupdown->fgcolor, BASE_COLOR, 0, "%*d", tw1, numupdown->value);
169 }
uint8_t tft_font_height(uint8_t fontnum)
Definition: tft.c:87
const char * text
The label of the button.
Definition: button.h:61
uint8_t tft_font_width(uint8_t fontnum)
Definition: tft.c:92
void gui_button_redraw(BUTTON_STRUCT *button)
Definition: button.c:164
uint16_t txtcolor
The 16-bit text color.
Definition: button.h:59
#define AUTO
Use this value instead of x2, y2 in the BUTTON_STRUCT to autocalculate the button width/height...
Definition: button.h:65
uint16_t x
The x-Coordinate of the Top-Left Starting Point.
Definition: numupdown.h:49
uint16_t y1
Top Left Y-Coordinate of Area.
Definition: touch.h:75
void tft_print_formatted(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char *format,...)
Definition: tft.c:111
bool gui_button_add(BUTTON_STRUCT *button)
Definition: button.c:133
uint16_t x1
Top Left X-Coordinate of Area.
Definition: touch.h:74
uint16_t bgcolor
The 16-bit background color of the button.
Definition: button.h:57
TOUCH_AREA_STRUCT base
Basic geometry of the button. You only need to set the x1, y1, x2, y2 members of this struct...
Definition: button.h:56
NUMUPDOWN_CALLBACK callback
Callback which is executed when the value changes.
Definition: numupdown.h:55
uint16_t y2
Bottom Right Y-Coordinate of Area.
Definition: touch.h:77
void button_down_cb(void *button)
Definition: numupdown.c:50
static uint8_t calc_text_width(int16_t val)
Definition: numupdown.c:66
uint16_t y
The y-Coordinate of the Top-Left Starting Point.
Definition: numupdown.h:50
int16_t max
The maximum possible value (inclusive)
Definition: numupdown.h:54
void gui_numupdown_remove(NUMUPDOWN_STRUCT *numupdown)
Definition: numupdown.c:136
uint16_t x2
Bottom Right X-Coordinate of Area.
Definition: touch.h:76
void gui_button_remove(BUTTON_STRUCT *button)
Definition: button.c:184
int16_t min
The minimum possible value (inclusive)
Definition: numupdown.h:53
#define WHITE
Definition: tft.h:53
void tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Definition: tft.c:67
void gui_numupdown_redraw(NUMUPDOWN_STRUCT *numupdown)
Definition: numupdown.c:144
uint16_t fgcolor
The 16-bit color of the value-text.
Definition: numupdown.h:51
BUTTON_STRUCT buttonDown
For internal use, don't change, don't initialize.
Definition: numupdown.h:58
void button_up_cb(void *button)
Definition: numupdown.c:34
void gui_numupdown_update(NUMUPDOWN_STRUCT *numupdown)
Definition: numupdown.c:154
int16_t value
The current/default value.
Definition: numupdown.h:52
BUTTON_CALLBACK callback
Callback which is executed when the button is pressed.
Definition: button.h:58
bool touch_have_empty(unsigned char num)
Definition: touch.c:165
uint8_t font
The number of the font to use.
Definition: button.h:60
#define BASE_COLOR
Definition: numupdown.c:31
BUTTON_STRUCT buttonUp
For internal use, don't change, don't initialize.
Definition: numupdown.h:57
bool gui_numupdown_add(NUMUPDOWN_STRUCT *numupdown)
Definition: numupdown.c:80