170 lines
7.1 KiB
C
170 lines
7.1 KiB
C
/**************************************************************************************************************************************
|
|
* Project: discoverpixy
|
|
* Website: https://github.com/t-moe/discoverpixy
|
|
* Authors: Aaron Schmocker, Timo Lang
|
|
* Institution: BFH Bern University of Applied Sciences
|
|
* File: common/gui/numupdown.c
|
|
*
|
|
* Version History:
|
|
* Date Autor Email SHA Changes
|
|
* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support.
|
|
* 2015-04-30 timolang@gmail.com b491b78 Made numupdown horizontal
|
|
* 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.
|
|
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
|
|
*
|
|
**************************************************************************************************************************************/
|
|
|
|
#include "tft.h"
|
|
#include "touch.h"
|
|
#include "button.h"
|
|
#include "numupdown.h"
|
|
#include <stdio.h> //for sprintf
|
|
#include <stddef.h> //for offsetof macro
|
|
#include <stdlib.h> //for abs
|
|
|
|
/* The idea is as follows:
|
|
* When the user add's a numupdown we create two buttons, one with a plus and one with a minus sign in it
|
|
* When the user presses one of the buttons we check and increase the value and execute the provided user callback
|
|
*/
|
|
|
|
|
|
#define BASE_COLOR RGB(90,90,90) //Background color for the whole element
|
|
|
|
//Callback which is called when the user presses the "plus" button
|
|
void button_up_cb(void* button)
|
|
{
|
|
//Get the pointer to the numupdown: subtract the offset of the buttonUp member in the struct from the button pointer
|
|
NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonUp);
|
|
|
|
if (element->value < element->max) { //old value lies below the maximum
|
|
element->value++; //let's increase the value
|
|
gui_numupdown_update(element); //and redraw everything
|
|
|
|
if (element->callback != NULL) { //the user provided a callback
|
|
element->callback(element, element->value); //Call the user callback with the new value
|
|
}
|
|
}
|
|
}
|
|
|
|
//Callback which is called when the user presses the "minus" button
|
|
void button_down_cb(void* button)
|
|
{
|
|
//Get the pointer to the numupdown: subtract the offset of the buttonDown member in the struct from the button pointer
|
|
NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonDown);
|
|
|
|
if (element->value > element->min) { //old value lies above the minimum
|
|
element->value--; //let's decrease the value
|
|
gui_numupdown_update(element); //and redraw everything
|
|
|
|
if (element->callback != NULL) { //the user provided a callback
|
|
element->callback(element, element->value); //Call the user callback with the new value
|
|
}
|
|
}
|
|
}
|
|
|
|
//Method to calculate the number of characters needed to print the provided number in decimal notation (with optional sign)
|
|
static uint8_t calc_text_width(int16_t val)
|
|
{
|
|
uint8_t width = 1 + (val < 0); //1 if positive, 2 if negative (to let space for sign)
|
|
val = abs(val); //Make the number positive
|
|
|
|
while (val >= 10) { //while we have two or more digits
|
|
val /= 10; //remove one digit
|
|
width++; //add one character
|
|
}
|
|
|
|
return width;
|
|
}
|
|
|
|
|
|
bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown)
|
|
{
|
|
if (touch_have_empty(2)) { //Check if the touch module can handle two additional areas
|
|
if (numupdown->min > numupdown->max) { //min is bigger than max?
|
|
return false; //invalid parameter
|
|
}
|
|
|
|
if (numupdown->value < numupdown->min) { //value is smaller than min?
|
|
numupdown->value = numupdown->min; //normalize value
|
|
} else if (numupdown->value > numupdown->max) { //value is bigger than max?
|
|
numupdown->value = numupdown->max; //normalize value
|
|
}
|
|
|
|
uint8_t tw1 = calc_text_width(numupdown->max); //Calculate character width to render maximum value
|
|
uint8_t tw2 = calc_text_width(numupdown->min); //Calculate character width to render minimum value
|
|
|
|
if (tw2 > tw1) {
|
|
tw1 = tw2; //ensure tw1 contains the larger number of the two
|
|
}
|
|
|
|
uint8_t width = tft_font_width(0) * (tw1 + 1); //Calculate width of the number area
|
|
|
|
//Add "minus" button to the left side of the number area
|
|
numupdown->buttonDown.base.x1 = numupdown->x;
|
|
numupdown->buttonDown.base.y1 = numupdown->y;
|
|
numupdown->buttonDown.base.x2 = AUTO;
|
|
numupdown->buttonDown.base.y2 = numupdown->y + tft_font_height(0) * 2;
|
|
numupdown->buttonDown.text = "-";
|
|
numupdown->buttonDown.font = 0;
|
|
numupdown->buttonDown.bgcolor = BASE_COLOR;
|
|
numupdown->buttonDown.txtcolor = WHITE;
|
|
numupdown->buttonDown.callback = button_down_cb;
|
|
gui_button_add(&numupdown->buttonDown);
|
|
|
|
//Add "plus" button to the right side of the number area
|
|
numupdown->buttonUp.base.x1 = numupdown->buttonDown.base.x2 + width + 2;
|
|
numupdown->buttonUp.base.y1 = numupdown->y;
|
|
numupdown->buttonUp.base.x2 = AUTO;
|
|
numupdown->buttonUp.base.y2 = numupdown->y + tft_font_height(0) * 2;
|
|
numupdown->buttonUp.text = "+";
|
|
numupdown->buttonUp.font = 0;
|
|
numupdown->buttonUp.bgcolor = BASE_COLOR;
|
|
numupdown->buttonUp.txtcolor = WHITE;
|
|
numupdown->buttonUp.callback = button_up_cb;
|
|
gui_button_add(&numupdown->buttonUp);
|
|
|
|
//Draw background and label of the number area
|
|
tft_fill_rectangle(numupdown->buttonDown.base.x2 + 2, numupdown->y, numupdown->buttonDown.base.x2 + width, numupdown->buttonUp.base.y2, BASE_COLOR);
|
|
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);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false; //not enough touch areas left
|
|
}
|
|
|
|
void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown)
|
|
{
|
|
//remove the two buttons, we have no other allocated resources
|
|
gui_button_remove(&numupdown->buttonUp);
|
|
gui_button_remove(&numupdown->buttonDown);
|
|
}
|
|
|
|
|
|
void gui_numupdown_redraw(NUMUPDOWN_STRUCT* numupdown)
|
|
{
|
|
//redraw the two buttons
|
|
gui_button_redraw(&numupdown->buttonUp);
|
|
gui_button_redraw(&numupdown->buttonDown);
|
|
|
|
//call update method which will take care of the number-area rendering
|
|
gui_numupdown_update(numupdown);
|
|
}
|
|
|
|
void gui_numupdown_update(NUMUPDOWN_STRUCT* numupdown)
|
|
{
|
|
//Calculate the number area width again (see above)
|
|
uint8_t tw1 = calc_text_width(numupdown->max);
|
|
uint8_t tw2 = calc_text_width(numupdown->min);
|
|
|
|
if (tw2 > tw1) {
|
|
tw1 = tw2;
|
|
}
|
|
|
|
uint8_t width = tft_font_width(0) * (tw1 + 1);
|
|
|
|
//Draw background and label of the number area
|
|
tft_fill_rectangle(numupdown->buttonDown.base.x2 + 2, numupdown->y, numupdown->buttonDown.base.x2 + width, numupdown->buttonUp.base.y2, BASE_COLOR);
|
|
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);
|
|
}
|