Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.

This commit is contained in:
t-moe
2015-05-17 14:23:12 +02:00
parent e46314b760
commit 2d463366c1
9 changed files with 441 additions and 396 deletions

View File

@@ -3,187 +3,152 @@
#include "button.h"
#include <string.h>
#define BRIGHTNESS_VAL 3 //How much the Brightness is in/decreased for button shadows (3 -> Add 1/3 off Full Value)
/* The Idea is as follows:
* When the user add's a button we create a touch area for that region and wait for PEN_DOWN events.
* Once the user puts the pen down in this area we'll redraw the button with different shadows (feedback)
* and we'll now wait on PEN_UP or PEN_LEAVE events.
* If the user takes the pen away while in the area (PEN_UP), we call the provided user callback
* Otherwise (PEN_LEAVE) we only restore the initial shadows
*/
/* Possible improvements:
* Move the button by 1 pixel while he is pressed, to create a "full 3d" experience
* Add events for the case when the button is pressed for a long time, without release
*/
//Method to calculate the shadow colors used to create the "3d" effect
void calculate_shadows(uint16_t bgcolor, uint16_t* light_shadow, uint16_t* dark_shadow) {
#define BRIGHTNESS_VAL 3 //How much the Brightness is in/decreased for button shadows (3 -> Add/Subtract 1/3 off Full Value)
uint16_t c_light,c_dark; //c_light and c_dark will be filled with a lighter and a darker color as the background color (for the shadows)
uint8_t r,g,b;
//separate the channels of the 16-bit rgb565 color
r=(bgcolor&0xF800)>>11;
g=(bgcolor&0x07E0)>>5;
b=(bgcolor&0x001F)>>0;
//For the light shadow color:
if((r + 0x1F/BRIGHTNESS_VAL) > 0x1F) //Adding one third would exceed the maximum of the red channel
c_light=0xF800; //Use full red
else //adding one third to the red channel is fine
c_light=(r+0x1F/BRIGHTNESS_VAL)<<11; //Use same red as in the background, but add one third
if((g + 0x3F/BRIGHTNESS_VAL) > 0x3F) //same for the green channel
c_light|=0x07E0;
else
c_light|=(g+0x3F/BRIGHTNESS_VAL)<<5;
if((b + 0x1F/BRIGHTNESS_VAL) > 0x1F) //and the blue channel
c_light|=0x0018;
else
c_light|=(b+0x1F/BRIGHTNESS_VAL)<<0;
//For the dark shadow color
if(r > (0x1F/BRIGHTNESS_VAL)) //Subtracting one third would NOT exceed the minimum of the red channel
c_dark=(r-0x1F/BRIGHTNESS_VAL)<<11; //Use same red as in the background, but subtract one third
else //Subtracting one third would give us a number below zero
c_dark=0x0000; //use no red channel
if(g > (0x3F/BRIGHTNESS_VAL)) //Same for the green channel
c_dark|=(g-0x3F/BRIGHTNESS_VAL)<<5;
if(b > (0x1F/BRIGHTNESS_VAL)) //and the blue channel
c_dark|=(b-0x1F/BRIGHTNESS_VAL)<<0;
//Assign the calculated shadows to out parameters
if(light_shadow!=NULL) *light_shadow = c_light;
if(dark_shadow!=NULL) *dark_shadow = c_dark;
}
//Callback which is called when the user touches the touch-area we created for the button
void buttons_cb(void* touchArea, TOUCH_ACTION triggeredAction)
//Method shared between normal Buttons and Bitmap Buttons-> Look at comment in headerfile for explanation.
{
TOUCH_AREA_STRUCT * area = (TOUCH_AREA_STRUCT*)touchArea;
BUTTON_STRUCT* button = (BUTTON_STRUCT*)touchArea;
unsigned int c1,c2;
unsigned char r,g,b;
r=(button->bgcolor&0xF800)>>11;
g=(button->bgcolor&0x07E0)>>5;
b=(button->bgcolor&0x001F)>>0;
if((r + 0x1F/BRIGHTNESS_VAL) >0x1F)
c1=0xF800;
else
c1=(r+0x1F/BRIGHTNESS_VAL)<<11;
if((g + 0x3F/BRIGHTNESS_VAL) >0x3F)
c1|=0x07E0;
else
c1|=(g+0x3F/BRIGHTNESS_VAL)<<5;
if((b + 0x1F/BRIGHTNESS_VAL) >0x1F)
c1|=0x0018;
else
c1|=(b+0x1F/BRIGHTNESS_VAL)<<0;
if(r > (0x1F/BRIGHTNESS_VAL))
c2=(r-0x1F/BRIGHTNESS_VAL)<<11;
else
c2=0x0000;
if(g > (0x3F/BRIGHTNESS_VAL))
c2|=(g-0x3F/BRIGHTNESS_VAL)<<5;
if(b > (0x1F/BRIGHTNESS_VAL))
c2|=(b-0x1F/BRIGHTNESS_VAL)<<0;
uint16_t c_light,c_dark; //c_light and c_dark will be filled with a lighter and a darker color as the background color (for the shadows)
calculate_shadows(button->bgcolor,&c_light,&c_dark);
switch(triggeredAction)
{
case PEN_DOWN:
area->hookedActions=PEN_UP|PEN_LEAVE;
tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c2); //Nord
tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c2);//West
tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c1); //S<EFBFBD>d
tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c1); //Ost
case PEN_DOWN: //If the user touches the area for the "first time"
area->hookedActions=PEN_UP|PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events
//Draw shadows
tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c_dark); //North
tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c_dark);//West
tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c_light); //South
tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c_light); //East
break;
case PEN_UP:
case PEN_LEAVE:
area->hookedActions=PEN_DOWN;
tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c1); //Nord
tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c1);//West
tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c2); //S<EFBFBD>d
tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c2); //Ost
if(triggeredAction==PEN_UP && button->callback!=NULL)
button->callback(button);
case PEN_UP: //If the user took the pen away, while in the area (=button pressed!)
case PEN_LEAVE: //or the user "slided out" of the area
area->hookedActions=PEN_DOWN; //for the future we only want PEN_DOWN events
//Draw inverse shadows
tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c_light); //North
tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c_light);//West
tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c_dark); //South
tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c_dark); //East
if(triggeredAction==PEN_UP && button->callback!=NULL) //If the button got "pressed" instead of left, and the user provided a callback
button->callback(button); //execute the user callback
break;
default:break;
}
}
bool gui_button_add(BUTTON_STRUCT* button)//Registers a button (fill Struct first). Return false if no more Space in the Pointertable (-->Change NUM_AREAS).
bool gui_button_add(BUTTON_STRUCT* button)
{
if(touch_have_empty(1))
if(touch_have_empty(1)) //Check if the touch module can handle one additional area
{
//Calculate width and height of the button text
unsigned int strwidth=tft_font_width(button->font)*strlen(button->text);
unsigned char strheight=tft_font_height(button->font);
button->base.hookedActions=PEN_DOWN;
button->base.callback = buttons_cb;
if(button->base.x2==AUTO)
button->base.hookedActions=PEN_DOWN; //At first we are interested in PEN_DOWN events
button->base.callback = buttons_cb; //Use our own callback for the touch area events
if(button->base.x2==AUTO) { //The user wants us to calculate the button width automatically
//Use string width + half of a character width as button width
button->base.x2= button->base.x1 -1 + strwidth+(tft_font_width(button->font)/2);
else if((button->base.x2-button->base.x1+1)<(strwidth+2))
return false;
} else if((button->base.x2-button->base.x1+1)<(strwidth+2)) { //the provided width is too small to fit the entire text
return false; //report error
}
if(button->base.y2==AUTO)
if(button->base.y2==AUTO) { //The user wants us to calculate the button height automatically
//Use one and a half character heights as button height
button->base.y2=button->base.y1 -1 +strheight+(strheight/2);
else if((button->base.y2-button->base.y1+1)<(strheight+2))
} else if((button->base.y2-button->base.y1+1)<(strheight+2)) { //the provided height is too small to fit the text
return false;
gui_button_redraw(button);
return touch_register_area(&button->base);
}
gui_button_redraw(button); //call the redraw method, which will take care of drawing the entire button
return touch_register_area(&button->base); //Register the touch area and receive events for this button, from now on
}
return false;
return false; //no more touch areas left
}
void gui_button_redraw(BUTTON_STRUCT* button)
{
unsigned int strwidth=tft_font_width(button->font)*strlen(button->text);
unsigned char strheight=tft_font_height(button->font);
unsigned char r,g,b;
unsigned int c;
r=(button->bgcolor&0xF800)>>11;
g=(button->bgcolor&0x07E0)>>5;
b=(button->bgcolor&0x001F)>>0;
//Calculate text dimensions and shadow colors
unsigned int strwidth=tft_font_width(button->font)*strlen(button->text);
unsigned char strheight=tft_font_height(button->font);
uint16_t c_light,c_dark;
calculate_shadows(button->bgcolor,&c_light,&c_dark);
//Draw the background and the 4 lines (shadow colors)
tft_fill_rectangle(button->base.x1+1,button->base.y1+1,button->base.x2-1,button->base.y2-1,button->bgcolor);
if((r + 0x1F/BRIGHTNESS_VAL) >0x1F)
c=0xF800;
else
c=(r+0x1F/BRIGHTNESS_VAL)<<11;
if((g + 0x3F/BRIGHTNESS_VAL) >0x3F)
c|=0x07E0;
else
c|=(g+0x3F/BRIGHTNESS_VAL)<<5;
if((b + 0x1F/BRIGHTNESS_VAL) >0x1F)
c|=0x0018;
else
c|=(b+0x1F/BRIGHTNESS_VAL)<<0;
tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c); //Nord
tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c);//West
if(r > (0x1F/BRIGHTNESS_VAL))
c=(r-0x1F/BRIGHTNESS_VAL)<<11;
else
c=0x0000;
if(g > (0x3F/BRIGHTNESS_VAL))
c|=(g-0x3F/BRIGHTNESS_VAL)<<5;
if(b > (0x1F/BRIGHTNESS_VAL))
c|=(b-0x1F/BRIGHTNESS_VAL)<<0;
tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c); //S<>d
tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c); //Ost
tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c_light); //North
tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c_light);//West
tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c_dark); //South
tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c_dark); //East
//Draw the text
tft_print_line(button->base.x1+(button->base.x2-button->base.x1+1-strwidth)/2,button->base.y1+(button->base.y2-button->base.y1+1-strheight)/2,button->txtcolor,button->bgcolor,button->font,button->text);
}
void gui_button_remove(BUTTON_STRUCT* button)
{
//We only need to unregister the touch area, as we have not allocated anything else
touch_unregister_area((TOUCH_AREA_STRUCT*)button);
}
/*
bool guiAddBitmapButton (BITMAPBUTTON_STRUCT* button)
{
if(touchHaveEmpty(1))
{
button->base.hookedActions=PEN_DOWN;
button->base.callback = buttons_cb;
if(button->base.x2==AUTO)
button->base.x2= button->base.x1 -1 + button->imgwidth + button->imgwidth/4;
else if((button->base.x2-button->base.x1+1)<(button->imgwidth+2))
return false;
if(button->base.y2==AUTO)
button->base.y2=button->base.y1 -1 +button->imgheight + button->imgheight/4;
else if((button->base.y2-button->base.y1+1)<(button->imgheight+2))
return false;
guiRedrawBitmapButton(button);
return touchRegisterArea(&button->base);
}
return false;
}
void guiRedrawBitmapButton(BITMAPBUTTON_STRUCT* button)
{
unsigned char r,g,b;
unsigned int c;
r=(button->bgcolor&0xF800)>>11;
g=(button->bgcolor&0x07E0)>>5;
b=(button->bgcolor&0x001F)>>0;
tftFillRectangle(button->base.x1+1,button->base.y1+1,button->base.x2-1,button->base.y2-1,button->bgcolor);
if((r + 0x1F/BRIGHTNESS_VAL) >0x1F)
c=0xF800;
else
c=(r+0x1F/BRIGHTNESS_VAL)<<11;
if((g + 0x3F/BRIGHTNESS_VAL) >0x3F)
c|=0x07E0;
else
c|=(g+0x3F/BRIGHTNESS_VAL)<<5;
if((b + 0x1F/BRIGHTNESS_VAL) >0x1F)
c|=0x0018;
else
c|=(b+0x1F/BRIGHTNESS_VAL)<<0;
tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c); //Nord
tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c);//West
if(r > (0x1F/BRIGHTNESS_VAL))
c=(r-0x1F/BRIGHTNESS_VAL)<<11;
else
c=0x0000;
if(g > (0x3F/BRIGHTNESS_VAL))
c|=(g-0x3F/BRIGHTNESS_VAL)<<5;
if(b > (0x1F/BRIGHTNESS_VAL))
c|=(b-0x1F/BRIGHTNESS_VAL)<<0;
tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c); //S<>d
tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c); //Ost
tftDrawBitmapUnscaledStreamedRaw(button->base.x1+(button->base.x2-button->base.x1+1-button->imgwidth)/2,button->base.y1+(button->base.y2-button->base.y1+1-button->imgheight)/2,button->imgwidth,button->imgheight,button->filename);
}
void guiRemoveBitmapButton(BITMAPBUTTON_STRUCT* button)
{
touchUnregisterArea((TOUCH_AREA_STRUCT*)button);
}
*/