- Added function to read out the display_buffer via USB-Serial - Added basic structure and files for later complete firmware (still in progress) - Added Doc folder with schematic in it - Added Python script and batch file to read out the display buffer and open the image in gimp
1483 lines
46 KiB
C
1483 lines
46 KiB
C
/*
|
|
* Display_Objects.c
|
|
*
|
|
* Created: Fri Apr 02 2021 13:58:23
|
|
* Author Chris
|
|
*/
|
|
#include "Display.h"
|
|
#include "Display_Font.h"
|
|
#include "Display_Image.h"
|
|
#include "Display_Objects.h"
|
|
#include "Display_Message_Box_Icons.h"
|
|
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
|
|
// ============================================================================================
|
|
// Defines
|
|
#define DEG2RAD (float)(M_PI / 180)
|
|
|
|
|
|
// ============================================================================================
|
|
// Variables
|
|
volatile Display_Color _Background_Color;
|
|
|
|
struct
|
|
{
|
|
Display_Object *Array;
|
|
size_t Used;
|
|
size_t Size;
|
|
} _Objects;
|
|
|
|
struct
|
|
{
|
|
Style *Array;
|
|
size_t Used;
|
|
size_t Size;
|
|
} _Styles;
|
|
|
|
struct
|
|
{
|
|
Animation *Array;
|
|
size_t Used;
|
|
size_t Size;
|
|
} _Animations;
|
|
|
|
struct
|
|
{
|
|
Font *Array;
|
|
size_t Used;
|
|
size_t Size;
|
|
} _Fonts;
|
|
|
|
|
|
// ============================================================================================
|
|
// Function Declarations
|
|
Object_ID Display_Objects_Add(Object_Type type, Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, void *data, Style_ID style_id, Animation_ID animation_id);
|
|
Style* Display_Objects_Style_From_ID(Style_ID style_id);
|
|
Animation* Display_Objects_Animation_From_ID(Animation_ID animation_id);
|
|
Font* Display_Objects_Font_From_ID(Font_ID font_id);
|
|
|
|
void Display_Objects_Update_Coordinates_Offset_And_Dimension(Display_Object *object, Anchor_Point anchor_point, Coordinates_Type coordinates_type);
|
|
void Display_Objects_Convert_Coordinates(Coordinates_Type coordinates_type, Coordinates* coordinates);
|
|
Dimension Display_Objects_Get_Content_Size(Display_Object *object);
|
|
Dimension Display_Objects_Get_Content_Size_From_Shape(Display_Object *object);
|
|
|
|
|
|
/*******************************************************************
|
|
Functions
|
|
*******************************************************************/
|
|
void Display_Objects_Init(Display_Color background_color)
|
|
{
|
|
_Objects.Array = NULL;
|
|
_Objects.Used = _Objects.Size = 0;
|
|
|
|
_Styles.Array = NULL;
|
|
_Styles.Used = _Styles.Size = 0;
|
|
|
|
Display_Objects_Background_Color_Set(background_color);
|
|
}
|
|
|
|
void Display_Objects_Background_Color_Set(Display_Color color)
|
|
{
|
|
_Background_Color = color;
|
|
}
|
|
|
|
Display_Color Display_Objects_Background_Color_Get(void)
|
|
{
|
|
return _Background_Color;
|
|
}
|
|
|
|
void Display_Objects_Clear(void)
|
|
{
|
|
Object_Value_Bar_Arc *VA;
|
|
Object_Menu_Ring *MR;
|
|
Object_Canvas *C;
|
|
|
|
for (uint i = 0; i < _Objects.Size; i++)
|
|
{
|
|
Display_Object* O = Display_Objects_Get_By_ID(i);
|
|
switch (O->Type)
|
|
{
|
|
case FLOAT:
|
|
free((Object_Float*)(O->Data));
|
|
break;
|
|
case INTEGER:
|
|
free((Object_Integer*)(O->Data));
|
|
break;
|
|
case TEXT:
|
|
free((Object_Text*)(O->Data));
|
|
break;
|
|
case VALUE_BAR_RECT:
|
|
free((Object_Value_Bar_Rect*)(O->Data));
|
|
break;
|
|
case VALUE_BAR_ARC:
|
|
VA = (Object_Value_Bar_Arc*)(O->Data);
|
|
free((Object_Shape*)(VA->Arc));
|
|
free(VA);
|
|
break;
|
|
case GRAPH:
|
|
free((Object_Graph*)(O->Data));
|
|
break;
|
|
case BUTTON:
|
|
free((Object_Button*)(O->Data));
|
|
break;
|
|
case IMAGE:
|
|
free((Object_Image_Color*)(O->Data));
|
|
break;
|
|
case BOOLEAN:
|
|
free((Object_Bool*)(O->Data));
|
|
break;
|
|
case SHAPE:
|
|
free((Object_Shape*)(O->Data));
|
|
break;
|
|
case CANVAS:
|
|
C = (Object_Canvas*)(O->Data);
|
|
free(C->Data);
|
|
free(C);
|
|
case MESSAGE_BOX:
|
|
free((Object_Message_Box*)(O->Data));
|
|
break;
|
|
case MENU_SELECT:
|
|
free((Object_Menu_Select*)(O->Data));
|
|
break;
|
|
case MENU_ICON_ROW:
|
|
free((Object_Menu_Icon_Row*)(O->Data));
|
|
break;
|
|
case MENU_RING:
|
|
MR = (Object_Menu_Ring*)(O->Data);
|
|
free(MR->Items);
|
|
free(MR->Item_Scales);
|
|
free(MR->Item_Glow_Intensity);
|
|
if (MR->Appear_Animation != NULL) {
|
|
free(MR->Appear_Animation);
|
|
}
|
|
free(MR);
|
|
break;
|
|
case SELECT_YESNO:
|
|
free((Object_Select_YesNo*)(O->Data));
|
|
break;
|
|
case SELECT_LIST:
|
|
free((Object_Select_List*)(O->Data));
|
|
break;
|
|
case SELECT_VALUE:
|
|
free((Object_Select_Value*)(O->Data));
|
|
break;
|
|
case SELECT_RGB:
|
|
free((Object_Select_RGB*)(O->Data));
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
O->Data = NULL;
|
|
|
|
if (O->Animation_Status != NULL)
|
|
{
|
|
free(O->Animation_Status);
|
|
O->Animation_Status = NULL;
|
|
}
|
|
}
|
|
|
|
free(_Objects.Array);
|
|
_Objects.Array = NULL;
|
|
_Objects.Used = _Objects.Size = 0;
|
|
|
|
free(_Styles.Array);
|
|
_Styles.Array = NULL;
|
|
_Styles.Used = _Styles.Size = 0;
|
|
|
|
free(_Animations.Array);
|
|
_Animations.Array = NULL;
|
|
_Animations.Used = _Animations.Size = 0;
|
|
|
|
free(_Fonts.Array);
|
|
_Fonts.Array = NULL;
|
|
_Fonts.Used = _Fonts.Size = 0;
|
|
|
|
Display_Unselect_Object();
|
|
}
|
|
|
|
Style_ID Display_Objects_Add_Style(Display_Color background_color, Display_Color border_color, uint border_thickness, uint border_radius, uint padding_top, uint padding_right, uint padding_bottom, uint padding_left, float width_height_ratio)
|
|
{
|
|
Style Style;
|
|
Style.Background_Color = background_color;
|
|
Style.Border_Color = border_color;
|
|
Style.Border_Thickness = border_thickness;
|
|
Style.Border_Radius = border_radius;
|
|
Style.Padding[PADDING_TOP] = padding_top;
|
|
Style.Padding[PADDING_LEFT] = padding_left;
|
|
Style.Padding[PADDING_BOTTOM] = padding_bottom;
|
|
Style.Padding[PADDING_RIGHT] = padding_right;
|
|
Style.Width_Height_Ratio = width_height_ratio;
|
|
|
|
if (_Styles.Used == _Styles.Size)
|
|
{
|
|
_Styles.Size++;
|
|
_Styles.Array = realloc(_Styles.Array, _Styles.Size * sizeof(Style));
|
|
}
|
|
|
|
_Styles.Array[_Styles.Used++] = Style;
|
|
|
|
return (Style_ID)(_Styles.Used - 1);
|
|
}
|
|
|
|
Animation_ID Display_Objects_Add_Animation(int offset_x, int offset_y, uint tick_delay, uint tick_duration, Animation_Order start_condition)
|
|
{
|
|
Animation Animation;
|
|
Animation.Offset.X = offset_x;
|
|
Animation.Offset.Y = offset_y;
|
|
Animation.Tick_Delay = tick_delay;
|
|
Animation.Tick_Duration = tick_duration;
|
|
Animation.Animation_Start = start_condition;
|
|
|
|
if (_Animations.Used == _Animations.Size)
|
|
{
|
|
_Animations.Size++;
|
|
_Animations.Array = realloc(_Animations.Array, _Animations.Size * sizeof(Animation));
|
|
}
|
|
|
|
_Animations.Array[_Animations.Used++] = Animation;
|
|
|
|
return (Animation_ID)(_Animations.Used - 1);
|
|
}
|
|
|
|
Font_ID Display_Objects_Add_Font(const unsigned char *font, uint8_t character_spacing)
|
|
{
|
|
Font Font;
|
|
Font.Font = font;
|
|
Font.Character_Spacing = character_spacing;
|
|
|
|
if (_Fonts.Used == _Fonts.Size)
|
|
{
|
|
_Fonts.Size++;
|
|
_Fonts.Array = realloc(_Fonts.Array, _Fonts.Size * sizeof(Font));
|
|
}
|
|
|
|
_Fonts.Array[_Fonts.Used++] = Font;
|
|
|
|
return (Font_ID)(_Fonts.Used - 1);
|
|
}
|
|
|
|
size_t Display_Objects_Count(void)
|
|
{
|
|
return _Objects.Size;
|
|
}
|
|
|
|
Display_Object *Display_Objects_Get_By_ID(Object_ID id)
|
|
{
|
|
if (id < _Objects.Size)
|
|
{
|
|
return &(_Objects.Array[id]);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
size_t Display_Objects_Get_Count_Canvas(void)
|
|
{
|
|
size_t Canvas_Count = 0;
|
|
|
|
for(uint i=0;i<Display_Objects_Count();i++)
|
|
{
|
|
if(Display_Objects_Get_By_ID(i)->Type == CANVAS)
|
|
{
|
|
Canvas_Count++;
|
|
}
|
|
}
|
|
|
|
return Canvas_Count;
|
|
}
|
|
|
|
Object_ID Display_Objects_Get_ID_From_Canvas_Number(uint canvas_number)
|
|
{
|
|
for(uint i=0;i<Display_Objects_Count();i++)
|
|
{
|
|
if(Display_Objects_Get_By_ID(i)->Type == CANVAS)
|
|
{
|
|
if(canvas_number == 0)
|
|
{
|
|
return i;
|
|
}
|
|
else
|
|
{
|
|
canvas_number--;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Float(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, float *value, char *format, Font_ID font, Display_Color color, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Float *Number = malloc(sizeof(Object_Float));
|
|
Number->Font = Display_Objects_Font_From_ID(font);
|
|
Number->Color = color;
|
|
Number->Value = value;
|
|
sprintf(Number->Format, "%s", format);
|
|
|
|
return Display_Objects_Add(FLOAT, anchor_point, coordinates_type, x, y, selectable, (void *)Number, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Integer(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, int *value, char *format, Font_ID font, Display_Color color, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Integer *Number = malloc(sizeof(Object_Integer));
|
|
Number->Font = Display_Objects_Font_From_ID(font);
|
|
Number->Color = color;
|
|
Number->Value = value;
|
|
sprintf(Number->Format, "%s", format);
|
|
|
|
return Display_Objects_Add(INTEGER, anchor_point, coordinates_type, x, y, selectable, (void *)Number, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Text(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, char *text, Font_ID font, Display_Color color, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Text *Text = malloc(sizeof(Object_Text));
|
|
Text->Font = Display_Objects_Font_From_ID(font);
|
|
Text->Color = color;
|
|
Text->Length = sprintf(Text->Text, "%s", text);
|
|
|
|
return Display_Objects_Add(TEXT, anchor_point, coordinates_type, x, y, selectable, (void *)Text, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Value_Bar_Rect(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, uint32_t *value, uint32_t max, uint32_t min, Orientation orientation, Display_Color color, uint32_t width, uint32_t height, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Value_Bar_Rect *Bar = malloc(sizeof(Object_Value_Bar_Rect));
|
|
Bar->Value = value;
|
|
Bar->Max = max;
|
|
Bar->Min = min;
|
|
Bar->Orientation = orientation;
|
|
Bar->Color = color;
|
|
Bar->Dimension.Width = width;
|
|
Bar->Dimension.Height = height;
|
|
|
|
return Display_Objects_Add(VALUE_BAR_RECT, anchor_point, coordinates_type, x, y, selectable, (void *)Bar, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Value_Bar_Arc(Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, uint32_t* value, uint32_t max, uint32_t min, uint32_t delta_inc, uint32_t delta_dec, Display_Color color, uint16_t radius, uint16_t thickness, uint16_t steps, int16_t angle_start, int16_t angle_end, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Arc = malloc(sizeof(Object_Shape));
|
|
Arc->Type = ARC;
|
|
Arc->Color = color;
|
|
Arc->Dimension.Width = 0;
|
|
Arc->Dimension.Height = 0;
|
|
Arc->Radius_Start = radius;
|
|
Arc->Radius_End = radius;
|
|
Arc->Thickness = thickness;
|
|
Arc->Draw_Steps = steps;
|
|
Arc->Angle_Start = angle_start;
|
|
Arc->Angle_End = angle_end;
|
|
|
|
Object_Value_Bar_Arc *Value_Bar = malloc(sizeof(Object_Value_Bar_Arc));
|
|
Value_Bar->Value = value;
|
|
Value_Bar->Max = max;
|
|
Value_Bar->Min = min;
|
|
Value_Bar->Current = *value;
|
|
Value_Bar->Delta_Inc = delta_inc;
|
|
Value_Bar->Delta_Dec = delta_dec;
|
|
Value_Bar->Arc = Arc;
|
|
Value_Bar->Angle_End = angle_end;
|
|
|
|
return Display_Objects_Add(VALUE_BAR_ARC, LEFT_TOP, coordinates_type, x, y, selectable, (void *)Value_Bar, style_id, NO_ANIMATION);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Graph(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, uint16_t *data, uint16_t data_length, uint max, uint min, Display_Color color, uint height, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Graph *Graph = malloc(sizeof(Object_Graph));
|
|
Graph->Data = data;
|
|
Graph->Data_Length = data_length;
|
|
Graph->Max = max;
|
|
Graph->Min = min;
|
|
Graph->Color = color;
|
|
Graph->Dimension.Width = data_length;
|
|
Graph->Dimension.Height = height;
|
|
|
|
return Display_Objects_Add(GRAPH, anchor_point, coordinates_type, x, y, selectable, (void *)Graph, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Button(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, char *text, Font_ID font, uint return_value, Display_Color color, uint width, uint height, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Button *Button = malloc(sizeof(Object_Button));
|
|
Button->Font = Display_Objects_Font_From_ID(font);
|
|
Button->Return_Value = return_value;
|
|
Button->Color = color;
|
|
Button->Length = sprintf(Button->Text, "%s", text);
|
|
Button->Dimension.Height = height;
|
|
Button->Dimension.Width = width;
|
|
|
|
return Display_Objects_Add(BUTTON, anchor_point, coordinates_type, x, y, selectable, (void *)Button, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Image(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Image_Color* image, uint16_t Rotation_Angle, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Image_Color *Image = malloc(sizeof(Object_Image_Color));
|
|
|
|
Image->Image = image;
|
|
Image->Rotation_Angle = Rotation_Angle;
|
|
Image->Alpha = UINT8_MAX;
|
|
|
|
return Display_Objects_Add(IMAGE, anchor_point, coordinates_type, x, y, selectable, (void *)Image, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Bool(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, bool* value, char* text_true, Display_Color color_true, char* text_false, Display_Color color_false, Font_ID font , Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Bool *Bool = malloc(sizeof(Object_Bool));
|
|
Bool->Value = value;
|
|
Bool->Length_True = sprintf(Bool->Text_True , "%s", text_true);
|
|
Bool->Length_False = sprintf(Bool->Text_False , "%s", text_false);
|
|
Bool->Color_True = color_true;
|
|
Bool->Color_False = color_false;
|
|
Bool->Font = Display_Objects_Font_From_ID(font);
|
|
|
|
return Display_Objects_Add(BOOLEAN, anchor_point, coordinates_type, x, y, selectable, (void *)Bool, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Rectangle_Filled(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint32_t width, uint32_t height, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Shape = malloc(sizeof(Object_Shape));
|
|
Shape->Type = RECTANGLE_FILLED;
|
|
Shape->Color = color;
|
|
Shape->Dimension.Width = width;
|
|
Shape->Dimension.Height = height;
|
|
Shape->Radius_Start = 0;
|
|
Shape->Radius_End = 0;
|
|
Shape->Thickness = 0;
|
|
Shape->Draw_Steps = 0;
|
|
Shape->Angle_Start = 0;
|
|
Shape->Angle_End = 0;
|
|
|
|
return Display_Objects_Add(SHAPE, anchor_point, coordinates_type, x, y, selectable, (void *)Shape, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Rectangle_Frame(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint32_t width, uint32_t height, uint16_t border_thickness, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Shape = malloc(sizeof(Object_Shape));
|
|
Shape->Type = RECTANGLE_FRAME;
|
|
Shape->Color = color;
|
|
Shape->Dimension.Width = width;
|
|
Shape->Dimension.Height = height;
|
|
Shape->Radius_Start = 0;
|
|
Shape->Radius_End = 0;
|
|
Shape->Thickness = border_thickness;
|
|
Shape->Draw_Steps = 0;
|
|
Shape->Angle_Start = 0;
|
|
Shape->Angle_End = 0;
|
|
|
|
return Display_Objects_Add(SHAPE, anchor_point, coordinates_type, x, y, selectable, (void *)Shape, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Rounded_Rectangle_Filled(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint32_t width, uint32_t height, uint16_t radius, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Shape = malloc(sizeof(Object_Shape));
|
|
Shape->Type = ROUNDED_RECTANGLE_FILLED;
|
|
Shape->Color = color;
|
|
Shape->Dimension.Width = width;
|
|
Shape->Dimension.Height = height;
|
|
Shape->Radius_Start = radius;
|
|
Shape->Radius_End = radius;
|
|
Shape->Thickness = 0;
|
|
Shape->Draw_Steps = 0;
|
|
Shape->Angle_Start = 0;
|
|
Shape->Angle_End = 0;
|
|
|
|
return Display_Objects_Add(SHAPE, anchor_point, coordinates_type, x, y, selectable, (void *)Shape, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Rounded_Rectangle_Frame(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint32_t width, uint32_t height, uint16_t radius, uint16_t border_thickness, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Shape = malloc(sizeof(Object_Shape));
|
|
Shape->Type = ROUNDED_RECTANGLE_FRAME;
|
|
Shape->Color = color;
|
|
Shape->Dimension.Width = width;
|
|
Shape->Dimension.Height = height;
|
|
Shape->Radius_Start = radius;
|
|
Shape->Radius_End = radius;
|
|
Shape->Thickness = border_thickness;
|
|
Shape->Draw_Steps = 0;
|
|
Shape->Angle_Start = 0;
|
|
Shape->Angle_End = 0;
|
|
|
|
return Display_Objects_Add(SHAPE, anchor_point, coordinates_type, x, y, selectable, (void *)Shape, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Circle_Filled(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint16_t radius, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Shape = malloc(sizeof(Object_Shape));
|
|
Shape->Type = CIRCLE_FILLED;
|
|
Shape->Color = color;
|
|
Shape->Dimension.Width = 0;
|
|
Shape->Dimension.Height = 0;
|
|
Shape->Radius_Start = radius;
|
|
Shape->Radius_End = radius;
|
|
Shape->Thickness = 0;
|
|
Shape->Draw_Steps = 0;
|
|
Shape->Angle_Start = 0;
|
|
Shape->Angle_End = 0;
|
|
|
|
Coordinates Coordinates_In_Px = { .X = x, .Y = y };
|
|
Display_Objects_Convert_Coordinates(coordinates_type, &Coordinates_In_Px);
|
|
|
|
return Display_Objects_Add(SHAPE, anchor_point, BOTH_IN_PIXEL, Coordinates_In_Px.X + radius, Coordinates_In_Px.Y + radius, selectable, (void *)Shape, style_id, animation_id);
|
|
}
|
|
|
|
|
|
Object_ID Display_Objects_Add_Circle_Frame(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint16_t radius, uint16_t thickness, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Shape = malloc(sizeof(Object_Shape));
|
|
Shape->Type = CIRCLE_FRAME;
|
|
Shape->Color = color;
|
|
Shape->Dimension.Width = 0;
|
|
Shape->Dimension.Height = 0;
|
|
Shape->Radius_Start = radius;
|
|
Shape->Radius_End = radius;
|
|
Shape->Thickness = thickness;
|
|
Shape->Draw_Steps = 0;
|
|
Shape->Angle_Start = 0;
|
|
Shape->Angle_End = 0;
|
|
|
|
Coordinates Coordinates_In_Px = { .X = x, .Y = y };
|
|
Display_Objects_Convert_Coordinates(coordinates_type, &Coordinates_In_Px);
|
|
|
|
return Display_Objects_Add(SHAPE, anchor_point, BOTH_IN_PIXEL, Coordinates_In_Px.X + radius, Coordinates_In_Px.Y + radius, selectable, (void *)Shape, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Arc_Frame(Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint16_t radius, uint16_t thickness, uint16_t steps, int16_t angle_start, int16_t angle_end, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Shape = malloc(sizeof(Object_Shape));
|
|
Shape->Type = ARC;
|
|
Shape->Color = color;
|
|
Shape->Dimension.Width = 0;
|
|
Shape->Dimension.Height = 0;
|
|
Shape->Radius_Start = radius;
|
|
Shape->Radius_End = radius;
|
|
Shape->Thickness = thickness;
|
|
Shape->Draw_Steps = steps;
|
|
Shape->Angle_Start = angle_start;
|
|
Shape->Angle_End = angle_end;
|
|
|
|
return Display_Objects_Add(SHAPE, LEFT_TOP, coordinates_type, x, y, selectable, (void *)Shape, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Dispaly_Objects_Add_Line_XY(Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, int16_t x2, int16_t y2, uint16_t thickness, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Shape = malloc(sizeof(Object_Shape));
|
|
Shape->Type = LINE_XY;
|
|
Shape->Color = color;
|
|
Shape->Dimension.Width = 0;
|
|
Shape->Dimension.Height = 0;
|
|
Shape->Radius_Start = 0;
|
|
Shape->Radius_End = 0;
|
|
Shape->Thickness = thickness;
|
|
Shape->Draw_Steps = 0;
|
|
Shape->Angle_Start = x2;
|
|
Shape->Angle_End = y2;
|
|
|
|
return Display_Objects_Add(SHAPE, LEFT_TOP, coordinates_type, x, y, selectable, (void *)Shape, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Dispaly_Objects_Add_Line_Rad(Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint16_t radius_start, uint16_t radius_end, uint16_t thickness, int16_t angle, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Shape *Shape = malloc(sizeof(Object_Shape));
|
|
Shape->Type = LINE_RAD;
|
|
Shape->Color = color;
|
|
Shape->Dimension.Width = 0;
|
|
Shape->Dimension.Height = 0;
|
|
Shape->Radius_Start = radius_start;
|
|
Shape->Radius_End = radius_end;
|
|
Shape->Thickness = thickness;
|
|
Shape->Draw_Steps = 0;
|
|
Shape->Angle_Start = angle;
|
|
Shape->Angle_End = 0;
|
|
|
|
return Display_Objects_Add(SHAPE, LEFT_TOP, coordinates_type, x, y, selectable, (void *)Shape, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Canvas(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint width, uint height, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Object_Canvas *Canvas = malloc(sizeof(Object_Canvas));
|
|
Canvas->Dimension.Width = width;
|
|
Canvas->Dimension.Height = height;
|
|
Canvas->Data = (uint16_t*) malloc(width * height * sizeof(uint16_t));
|
|
|
|
for(uint y=0;y<height;y++)
|
|
{
|
|
for(uint x=0;x<width;x++)
|
|
{
|
|
Canvas->Data[y * width + x] = color;
|
|
}
|
|
}
|
|
|
|
return Display_Objects_Add(CANVAS, anchor_point, coordinates_type, x, y, selectable, (void *)Canvas, style_id, animation_id);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Message_Box(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, char* text, Font_ID font, Object_Message_Box_Icon icon, Display_Color color, Style_ID style_id)
|
|
{
|
|
Object_Message_Box *Message_Box = malloc(sizeof(Object_Message_Box));
|
|
Message_Box->Length = sprintf(Message_Box->Text, "%s", text);
|
|
Message_Box->Font = Display_Objects_Font_From_ID(font);
|
|
Message_Box->Color = color;
|
|
Message_Box->Icon = icon;
|
|
Message_Box->Show_Ticks_Left = 0;
|
|
|
|
return Display_Objects_Add(MESSAGE_BOX, anchor_point, coordinates_type, x, y, NOT_SELECTABLE, (void *)Message_Box, style_id, NO_ANIMATION);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Menu_Select(char* menu_titles, uint32_t menu_entry_count, uint32_t title_char_length, uint32_t* selected_entry, Configuration_Menu_Select* config)
|
|
{
|
|
Object_Menu_Select* Menu_Select = malloc(sizeof(Object_Menu_Select));
|
|
Menu_Select->Menu_Titles = menu_titles;
|
|
Menu_Select->Menu_Entry_Count = menu_entry_count;
|
|
Menu_Select->Title_Char_Length = title_char_length;
|
|
Menu_Select->Selected_Entry = selected_entry;
|
|
Menu_Select->Config = config;
|
|
|
|
return Display_Objects_Add(MENU_SELECT, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, NOT_SELECTABLE, (void *)Menu_Select, NO_STYLE, NO_ANIMATION);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Menu_Icon_Row(Icon_Row_Item* items, uint32_t item_count, uint32_t* selected_item, Configuration_Menu_Icon_Row* config)
|
|
{
|
|
Object_Menu_Icon_Row* Icon_Row = malloc(sizeof(Object_Menu_Icon_Row));
|
|
Icon_Row->Items = items;
|
|
Icon_Row->Item_Count = item_count;
|
|
Icon_Row->Selected_Item = selected_item;
|
|
Icon_Row->Config = config;
|
|
|
|
return Display_Objects_Add(MENU_ICON_ROW, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, NOT_SELECTABLE, (void *)Icon_Row, NO_STYLE, NO_ANIMATION);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Menu_Ring(Menu_Ring_Item_Config* items, uint32_t item_count, uint32_t* selected_item, Configuration_Menu_Ring* config)
|
|
{
|
|
if (item_count == 0 || item_count > 16) { // Reasonable limits
|
|
return -1; // Invalid item count
|
|
}
|
|
|
|
Object_Menu_Ring* Menu_Ring = malloc(sizeof(Object_Menu_Ring));
|
|
|
|
// Allocate dynamic arrays
|
|
Menu_Ring->Items = malloc(sizeof(Menu_Ring_Item_Config) * item_count);
|
|
Menu_Ring->Item_Scales = malloc(sizeof(float) * item_count);
|
|
Menu_Ring->Item_Glow_Intensity = malloc(sizeof(uint8_t) * item_count);
|
|
|
|
// Copy item configurations and initialize states
|
|
for (uint32_t i = 0; i < item_count; i++) {
|
|
Menu_Ring->Items[i] = items[i];
|
|
Menu_Ring->Item_Scales[i] = (i == *selected_item) ? config->Selection_Scale : 1.0f;
|
|
Menu_Ring->Item_Glow_Intensity[i] = (i == *selected_item) ? 255 : 0;
|
|
}
|
|
|
|
Menu_Ring->Item_Count = item_count;
|
|
Menu_Ring->Selected_Item = selected_item;
|
|
Menu_Ring->Config = config;
|
|
|
|
// Initialize animation state
|
|
Menu_Ring->Animation_Counter = 0;
|
|
Menu_Ring->Idle_Rotation_Angle = 0.0f;
|
|
Menu_Ring->Selection_Animation_Progress = 0;
|
|
Menu_Ring->Animation_Target = *selected_item;
|
|
|
|
// Initialize appear animation
|
|
Menu_Ring->Appear_Animation = malloc(sizeof(Menu_Ring_Appear_Animation));
|
|
Menu_Ring->Appear_Animation->State = MENU_RING_APPEAR_STATE_IDLE;
|
|
Menu_Ring->Appear_Animation->Ring_Draw_Angle = 0.0f;
|
|
Menu_Ring->Appear_Animation->Center_Scale = 0.0f;
|
|
Menu_Ring->Appear_Animation->Ring_Draw_Counter = 0;
|
|
Menu_Ring->Appear_Animation->Center_Grow_Counter = 0;
|
|
Menu_Ring->Appear_Animation->Current_Item_Appearing = 0;
|
|
Menu_Ring->Appear_Animation->Current_Item_Scale = 0.0f;
|
|
Menu_Ring->Appear_Animation->Item_Pop_Counter = 0;
|
|
Menu_Ring->Appear_Animation->Item_Delay_Counter = 0;
|
|
|
|
// Calculate animation timing
|
|
Menu_Ring->Appear_Animation->Total_Ring_Draw_Frames = 360 / MENU_RING_APPEAR_CIRCLE_DRAW_SPEED;
|
|
Menu_Ring->Appear_Animation->Total_Center_Grow_Frames = MENU_RING_APPEAR_CIRCLE_GROW_SPEED;
|
|
Menu_Ring->Appear_Animation->Total_Item_Pop_Frames = MENU_RING_APPEAR_ITEM_POP_SPEED;
|
|
Menu_Ring->Appear_Animation->Total_Item_Delay_Frames = MENU_RING_APPEAR_ITEM_DELAY;
|
|
|
|
Menu_Ring->Appear_Animation_Active = false;
|
|
|
|
return Display_Objects_Add(MENU_RING, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, SELECTABLE, (void *)Menu_Ring, NO_STYLE, NO_ANIMATION);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Select_YesNo(char* title, uint32_t title_length, bool* value, Configuration_Select_YesNo* config)
|
|
{
|
|
Object_Select_YesNo* Select_YesNo = malloc(sizeof(Object_Select_YesNo));
|
|
Select_YesNo->Title = title;
|
|
Select_YesNo->Title_Length = title_length;
|
|
Select_YesNo->Value = value;
|
|
Select_YesNo->Config = config;
|
|
|
|
return Display_Objects_Add(SELECT_YESNO, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, NOT_SELECTABLE, (void *)Select_YesNo, NO_STYLE, NO_ANIMATION);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Select_List(char* list_titles, uint32_t list_entry_count, uint32_t list_char_length, uint32_t* selected_entry, Configuration_Select_List* config)
|
|
{
|
|
Object_Select_List* Select_List = malloc(sizeof(Object_Select_List));
|
|
Select_List->List_Titles = list_titles;
|
|
Select_List->List_Entry_Count = list_entry_count;
|
|
Select_List->List_Char_Length = list_char_length;
|
|
Select_List->Selected_Entry = selected_entry;
|
|
Select_List->Config = config;
|
|
|
|
return Display_Objects_Add(SELECT_LIST, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, NOT_SELECTABLE, (void *)Select_List, NO_STYLE, NO_ANIMATION);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Select_Value(char* title, uint32_t title_length, int32_t* value, int32_t max, int32_t min, char* format, Configuration_Select_Value* config)
|
|
{
|
|
Object_Select_Value* Select_Value = malloc(sizeof(Object_Select_Value));
|
|
Select_Value->Title = title;
|
|
Select_Value->Title_Length = title_length;
|
|
Select_Value->Value = value;
|
|
Select_Value->Max = max;
|
|
Select_Value->Min = min;
|
|
sprintf(Select_Value->Format, "%s", format);
|
|
Select_Value->Config = config;
|
|
|
|
return Display_Objects_Add(SELECT_VALUE, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, NOT_SELECTABLE, (void *)Select_Value, NO_STYLE, NO_ANIMATION);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Select_RGB(RGB_Color* color_value, uint8_t* current_component, Configuration_Select_RGB* config)
|
|
{
|
|
if (color_value == NULL || config == NULL) {
|
|
return -1; // Invalid parameters
|
|
}
|
|
|
|
// Allocate memory for the RGB selector object
|
|
Object_Select_RGB* Select_RGB = malloc(sizeof(Object_Select_RGB));
|
|
if (Select_RGB == NULL) {
|
|
return -1; // Memory allocation failed
|
|
}
|
|
|
|
// Initialize RGB value pointer
|
|
Select_RGB->Color_Value = color_value;
|
|
|
|
// Set current state
|
|
Select_RGB->Current_Component = current_component;
|
|
|
|
// Initialize component labels
|
|
sprintf((char*)Select_RGB->Component_Labels[0], "RED");
|
|
sprintf((char*)Select_RGB->Component_Labels[1], "GREEN");
|
|
sprintf((char*)Select_RGB->Component_Labels[2], "BLUE");
|
|
|
|
// Initialize animation state
|
|
Select_RGB->Target_Value = Select_RGB->Color_Value->Array[*current_component]; // Array is R,G,B,A so: R=Array[0], G=Array[1], B=Array[2]
|
|
Select_RGB->Display_Value = Select_RGB->Target_Value;
|
|
Select_RGB->Animation_Counter = 0;
|
|
|
|
// UI Geometry
|
|
Select_RGB->Progress_Start_Angle = 270.0f; // 12 o'clock position
|
|
|
|
// Store configuration reference
|
|
Select_RGB->Config = config;
|
|
|
|
// Add to display objects system
|
|
// RGB selector is typically a full-screen interface, so use center positioning
|
|
return Display_Objects_Add(
|
|
SELECT_RGB, // Object type
|
|
LEFT_TOP, // Anchor point
|
|
BOTH_IN_PIXEL, // Coordinate type
|
|
0, //Select_RGB->Center_Position.X, // X position
|
|
0, //Select_RGB->Center_Position.Y, // Y position
|
|
SELECTABLE, // Not selectable for encoder input
|
|
(void*)Select_RGB, // Object data
|
|
NO_STYLE, // No style needed (custom rendering)
|
|
NO_ANIMATION // No standard animation (custom smooth transitions)
|
|
);
|
|
}
|
|
|
|
Object_ID Display_Objects_Add_Entry_Indicator(uint32_t entry_count, int32_t* entry_value, Configuration_Entry_Indicator* config)
|
|
{
|
|
Object_Entry_Indicator* Entry_Indicator = malloc(sizeof(Object_Entry_Indicator));
|
|
Entry_Indicator->Entry_Count = entry_count;
|
|
Entry_Indicator->Entry_Value = entry_value;
|
|
Entry_Indicator->Config = config;
|
|
|
|
return Display_Objects_Add(ENTRY_INDICATOR, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, NOT_SELECTABLE, (void *)Entry_Indicator, NO_STYLE, NO_ANIMATION);
|
|
}
|
|
|
|
void Display_Objects_Update_Coordinates(Object_ID id, Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
Object->Coordinates.X = x;
|
|
Object->Coordinates.Y = y;
|
|
Display_Objects_Update_Coordinates_Offset_And_Dimension(Object, anchor_point, coordinates_type);
|
|
}
|
|
|
|
void Display_Objects_Update_Enabled(Object_ID id, bool is_enabled)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
Object->Enabled = is_enabled;
|
|
}
|
|
|
|
void Display_Objects_Update_Color(Object_ID id, Display_Color color)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
switch(Object->Type)
|
|
{
|
|
case FLOAT:
|
|
((Object_Float*)(Object->Data))->Color = color;
|
|
break;
|
|
|
|
case INTEGER:
|
|
((Object_Integer*)(Object->Data))->Color = color;
|
|
break;
|
|
|
|
case TEXT:
|
|
((Object_Text*)(Object->Data))->Color = color;
|
|
break;
|
|
|
|
case VALUE_BAR_RECT:
|
|
((Object_Value_Bar_Rect*)(Object->Data))->Color = color;
|
|
break;
|
|
|
|
case BUTTON:
|
|
((Object_Button*)(Object->Data))->Color = color;
|
|
break;
|
|
|
|
case SHAPE:
|
|
((Object_Shape*)(Object->Data))->Color = color;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Display_Objects_Update_Text(Object_ID id, char* text)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
Object_Text* Text;
|
|
Object_Button* Button;
|
|
|
|
switch(Object->Type)
|
|
{
|
|
case TEXT:
|
|
Text = (Object_Text*)(Object->Data);
|
|
Text->Length = sprintf(Text->Text, "%s", text);
|
|
break;
|
|
|
|
case BUTTON:
|
|
Button = (Object_Button*)(Object->Data);
|
|
Button->Length = sprintf(Button->Text, "%s", text);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Display_Objects_Update_Image(Object_ID id, Image_Color* new_image)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL || new_image == NULL) {
|
|
return;
|
|
}
|
|
|
|
if(Object->Type != IMAGE) {
|
|
return;
|
|
}
|
|
|
|
Object_Image_Color* IM = (Object_Image_Color*)(Object->Data);
|
|
|
|
IM->Image = new_image;
|
|
}
|
|
|
|
void Display_Objects_Update_Alpha(Object_ID id, uint8_t new_alpha)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
if(Object->Type != IMAGE) {
|
|
return;
|
|
}
|
|
|
|
Object_Image_Color* IM = (Object_Image_Color*)(Object->Data);
|
|
|
|
IM->Alpha = new_alpha;
|
|
}
|
|
|
|
void Display_Objects_Update_Max_Min(Object_ID id, uint max, uint min)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
switch(Object->Type)
|
|
{
|
|
case VALUE_BAR_RECT:
|
|
((Object_Value_Bar_Rect*)Object->Data)->Max = max;
|
|
((Object_Value_Bar_Rect*)Object->Data)->Min = min;
|
|
break;
|
|
|
|
case GRAPH:
|
|
((Object_Graph*)Object->Data)->Max = max;
|
|
((Object_Graph*)Object->Data)->Min = min;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int Display_Objects_Update_Pixel(Object_ID id, int16_t x, int16_t y, Display_Color color)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return OBJECT_NOT_FOUND;
|
|
}
|
|
|
|
Object_Canvas* C;
|
|
|
|
switch(Object->Type)
|
|
{
|
|
case CANVAS:
|
|
C = (Object_Canvas*)(Object->Data);
|
|
|
|
if(x<0 || x>=C->Dimension.Width) { return X_OUT_OF_RANGE; }
|
|
if(y<0 || y>=C->Dimension.Height) { return Y_OUT_OF_RANGE; }
|
|
|
|
C->Data[y * C->Dimension.Width + x] = color;
|
|
|
|
return CANVAS_UPDATE_OK;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return OBJECT_WRONG_TYPE;
|
|
}
|
|
|
|
void Display_Objects_Show_Message_Box(Object_ID id, uint32_t ticks)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (Object->Type != MESSAGE_BOX) {
|
|
return;
|
|
}
|
|
|
|
Object_Message_Box* M = (Object_Message_Box*)(Object->Data);
|
|
M->Show_Ticks_Max = ticks;
|
|
M->Show_Ticks_Left = ticks;
|
|
}
|
|
|
|
void Display_Objects_Update_Angles_Rel(Object_ID id, int16_t angle_delta)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (Object->Type == SHAPE)
|
|
{
|
|
Object_Shape* S = (Object_Shape*)(Object->Data);
|
|
if(S->Type != ARC && S->Type != LINE_RAD) {
|
|
return;
|
|
}
|
|
|
|
S->Angle_Start += angle_delta;
|
|
S->Angle_Start %= 360;
|
|
if(S->Angle_Start < 0) {
|
|
S->Angle_Start += 360;
|
|
}
|
|
|
|
S->Angle_End += angle_delta;
|
|
S->Angle_End %= 360;
|
|
if(S->Angle_End < 0) {
|
|
S->Angle_End += 360;
|
|
}
|
|
}
|
|
else if(Object->Type == IMAGE) {
|
|
Object_Image_Color* IM = (Object_Image_Color*)(Object->Data);
|
|
IM->Rotation_Angle += angle_delta;
|
|
|
|
IM->Rotation_Angle %= 360;
|
|
if(IM->Rotation_Angle < 0) {
|
|
IM->Rotation_Angle += 360;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Display_Objects_Update_Angle_Start(Object_ID id, int16_t angle)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (Object->Type != SHAPE) {
|
|
return;
|
|
}
|
|
|
|
Object_Shape* S = (Object_Shape*)(Object->Data);
|
|
if(S->Type != ARC) {
|
|
return;
|
|
}
|
|
|
|
S->Angle_Start = angle;
|
|
S->Angle_Start %= 360;
|
|
if(S->Angle_Start < 0) {
|
|
S->Angle_Start += 360;
|
|
}
|
|
}
|
|
|
|
void Display_Objects_Update_Angle_End(Object_ID id, int16_t angle)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(id);
|
|
|
|
if(Object == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (Object->Type != SHAPE) {
|
|
return;
|
|
}
|
|
|
|
Object_Shape* S = (Object_Shape*)(Object->Data);
|
|
if(S->Type != ARC) {
|
|
return;
|
|
}
|
|
|
|
S->Angle_End = angle;
|
|
S->Angle_End %= 360;
|
|
if(S->Angle_End < 0) {
|
|
S->Angle_End += 360;
|
|
}
|
|
}
|
|
|
|
void Display_Objects_Menu_Ring_Start_Appear_Animation(Object_ID menu_ring_id)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(menu_ring_id);
|
|
if (Object == NULL || Object->Type != MENU_RING) {
|
|
return;
|
|
}
|
|
|
|
Object_Menu_Ring* Menu_Ring = (Object_Menu_Ring*)Object->Data;
|
|
if(Menu_Ring->Config == NULL) {
|
|
return;
|
|
}
|
|
|
|
Menu_Ring->Config->Enable_Appear_Animation = true;
|
|
|
|
if (Menu_Ring->Appear_Animation != NULL) {
|
|
// Reset animation state
|
|
Menu_Ring->Appear_Animation->State = MENU_RING_APPEAR_STATE_DRAWING_RING;
|
|
Menu_Ring->Appear_Animation->Ring_Draw_Angle = 0.0f;
|
|
Menu_Ring->Appear_Animation->Center_Scale = 0.0f;
|
|
Menu_Ring->Appear_Animation->Ring_Draw_Counter = 0;
|
|
Menu_Ring->Appear_Animation->Center_Grow_Counter = 0;
|
|
Menu_Ring->Appear_Animation->Current_Item_Appearing = 0;
|
|
Menu_Ring->Appear_Animation->Current_Item_Scale = 0.0f;
|
|
Menu_Ring->Appear_Animation->Item_Pop_Counter = 0;
|
|
Menu_Ring->Appear_Animation->Item_Delay_Counter = 0;
|
|
|
|
Menu_Ring->Appear_Animation_Active = true;
|
|
|
|
// Hide all items initially during animation
|
|
for (uint32_t i = 0; i < Menu_Ring->Item_Count; i++) {
|
|
Menu_Ring->Item_Scales[i] = 0.0f;
|
|
Menu_Ring->Item_Glow_Intensity[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Display_Objects_Menu_Ring_Is_Appear_Animation_Active(Object_ID menu_ring_id)
|
|
{
|
|
Display_Object* Object = Display_Objects_Get_By_ID(menu_ring_id);
|
|
if (Object == NULL || Object->Type != MENU_RING) {
|
|
return false;
|
|
}
|
|
|
|
Object_Menu_Ring* Menu_Ring = (Object_Menu_Ring*)Object->Data;
|
|
return Menu_Ring->Appear_Animation_Active;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
Internal Functions
|
|
*******************************************************************/
|
|
Object_ID Display_Objects_Add(Object_Type type, Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, void *data, Style_ID style_id, Animation_ID animation_id)
|
|
{
|
|
Display_Object Object;
|
|
Object.Type = type;
|
|
Object.Coordinates.X = x;
|
|
Object.Coordinates.Y = y;
|
|
Object.Content_Offset.X = 0;
|
|
Object.Content_Offset.Y = 0;
|
|
Object.Dimension.Height = 0;
|
|
Object.Dimension.Width = 0;
|
|
Object.Enabled = true;
|
|
Object.Selectable = selectable;
|
|
Object.Focused = false;
|
|
Object.Data = data;
|
|
Object.Style = Display_Objects_Style_From_ID(style_id);
|
|
Object.Animation = Display_Objects_Animation_From_ID(animation_id);
|
|
Object.Animation_Status = NULL;
|
|
|
|
Display_Objects_Update_Coordinates_Offset_And_Dimension(&Object, anchor_point, coordinates_type);
|
|
|
|
if (Object.Animation != NULL)
|
|
{
|
|
Object.Animation_Status = malloc(sizeof(Animation_Status));
|
|
Object.Animation_Status->State = NO_STARTED;
|
|
}
|
|
|
|
// _Objects->used is the number of used entries, because _Objects->array[_Objects->used++] updates _Objects->used only *after* the array has been accessed.
|
|
// Therefore a->used can go up to a->size
|
|
if (_Objects.Used == _Objects.Size)
|
|
{
|
|
_Objects.Size++;
|
|
_Objects.Array = realloc(_Objects.Array, _Objects.Size * sizeof(Display_Object));
|
|
}
|
|
|
|
_Objects.Array[_Objects.Used++] = Object;
|
|
|
|
return Display_Objects_Count() - 1;
|
|
}
|
|
|
|
Style *Display_Objects_Style_From_ID(Style_ID style_id)
|
|
{
|
|
if (style_id >= 0 && style_id < _Styles.Used)
|
|
{
|
|
return &_Styles.Array[style_id];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
Animation *Display_Objects_Animation_From_ID(Animation_ID animation_id)
|
|
{
|
|
if (animation_id >= 0 && animation_id < _Animations.Used)
|
|
{
|
|
return &_Animations.Array[animation_id];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
Font* Display_Objects_Font_From_ID(Font_ID font_id)
|
|
{
|
|
if (font_id >= 0 && font_id < _Fonts.Used)
|
|
{
|
|
return &_Fonts.Array[font_id];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void Display_Objects_Update_Coordinates_Offset_And_Dimension(Display_Object *object, Anchor_Point anchor_point, Coordinates_Type coordinates_type)
|
|
{
|
|
if (object == NULL) {
|
|
return;
|
|
}
|
|
|
|
///////////////////////////////////////
|
|
// Coordinated from Percent to Pixel //
|
|
///////////////////////////////////////
|
|
Coordinates Coordinates_In_Px = { .X = object->Coordinates.X, .Y = object->Coordinates.Y };
|
|
Display_Objects_Convert_Coordinates(coordinates_type, &Coordinates_In_Px);
|
|
|
|
if(object->Type == SHAPE && ((Object_Shape*)object->Data)->Type == LINE_XY) {
|
|
Object_Shape* Shape = (Object_Shape*)object->Data;
|
|
Coordinates Coordinates_Line_X2Y2 = { .X = Shape->Angle_Start, .Y = Shape->Angle_End };
|
|
Display_Objects_Convert_Coordinates(coordinates_type, &Coordinates_Line_X2Y2);
|
|
|
|
Shape->Angle_Start = Coordinates_Line_X2Y2.X;
|
|
Shape->Angle_End = Coordinates_Line_X2Y2.Y;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////
|
|
// Get Coordinated of Top-Left corner //
|
|
////////////////////////////////////////
|
|
Dimension Content_Size = Display_Objects_Get_Content_Size(object);
|
|
|
|
Coordinates Coordinates_Content_Top_Left = Coordinates_In_Px;
|
|
|
|
// Horizontal
|
|
switch (anchor_point & 0x0F)
|
|
{
|
|
case CENTER:
|
|
Coordinates_Content_Top_Left.X = Coordinates_In_Px.X - (Content_Size.Width >> 1);
|
|
break;
|
|
|
|
case LEFT:
|
|
// Already assigned via default value
|
|
// Coordinates_Content_Top_Left.X = Coordinates_In_Px.X;
|
|
break;
|
|
|
|
case RIGHT:
|
|
Coordinates_Content_Top_Left.X = Coordinates_In_Px.X - Content_Size.Width;
|
|
break;
|
|
}
|
|
|
|
// Vertical
|
|
switch (anchor_point & 0xF0)
|
|
{
|
|
case MIDDLE:
|
|
Coordinates_Content_Top_Left.Y = Coordinates_In_Px.Y - (Content_Size.Height >> 1);
|
|
break;
|
|
|
|
case TOP:
|
|
// Already assigned via default value
|
|
// Coordinates_Content_Top_Left.Y = Coordinates_In_Px.Y;
|
|
break;
|
|
|
|
case BOTTOM:
|
|
Coordinates_Content_Top_Left.Y = Coordinates_In_Px.Y - Content_Size.Height;
|
|
break;
|
|
}
|
|
|
|
Coordinates Offset_Content_Style = { .X = 0, .Y = 0 };
|
|
Dimension Object_Dimension = Content_Size;
|
|
|
|
if(object->Style != NULL)
|
|
{
|
|
Style* Style = object->Style;
|
|
|
|
//////////////////////////////////////////////////////////
|
|
// !!! HEIGHT and WIDTH of Style not yet considered !!! //
|
|
//////////////////////////////////////////////////////////
|
|
|
|
Offset_Content_Style.X = Style->Border_Thickness + Style->Padding[PADDING_LEFT];
|
|
Offset_Content_Style.Y = Style->Border_Thickness + Style->Padding[PADDING_TOP];
|
|
|
|
Object_Dimension.Height += (Style->Border_Thickness << 1) + Style->Padding[PADDING_TOP] + Style->Padding[PADDING_BOTTOM];
|
|
Object_Dimension.Width += (Style->Border_Thickness << 1) + Style->Padding[PADDING_LEFT] + Style->Padding[PADDING_RIGHT];
|
|
|
|
if(Style->Width_Height_Ratio != STYLE_WIDTH_HEIGHT_RATIO_AUTO)
|
|
{
|
|
uint16_t Ratio_Height = Object_Dimension.Width * Style->Width_Height_Ratio;
|
|
int16_t Height_Difference = Ratio_Height - Object_Dimension.Height;
|
|
|
|
Object_Dimension.Height = Ratio_Height;
|
|
Offset_Content_Style.Y += (Height_Difference >> 1);
|
|
}
|
|
}
|
|
|
|
object->Content_Offset = Offset_Content_Style;
|
|
object->Coordinates.X = Coordinates_Content_Top_Left.X - Offset_Content_Style.X;
|
|
object->Coordinates.Y = Coordinates_Content_Top_Left.Y - Offset_Content_Style.Y;
|
|
object->Dimension = Object_Dimension;
|
|
}
|
|
|
|
void Display_Objects_Convert_Coordinates(Coordinates_Type coordinates_type, Coordinates* coordinates)
|
|
{
|
|
switch (coordinates_type)
|
|
{
|
|
case BOTH_IN_PIXEL:
|
|
break;
|
|
|
|
case X_IN_PIXEL_Y_IN_PERCENT:
|
|
coordinates->Y = (DISPLAY_HEIGHT * coordinates->Y) / 100;
|
|
break;
|
|
|
|
case X_IN_PERCENT_Y_IN_PIXEL:
|
|
coordinates->X = (DISPLAY_WIDTH * coordinates->X) / 100;
|
|
break;
|
|
|
|
case BOTH_IN_PERCENT:
|
|
coordinates->X = (DISPLAY_WIDTH * coordinates->X) / 100;
|
|
coordinates->Y = (DISPLAY_HEIGHT * coordinates->Y) / 100;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
Dimension Display_Objects_Get_Content_Size(Display_Object *object)
|
|
{
|
|
Dimension Dimension = { .Width = 0, .Height = 0 };
|
|
|
|
if (object == NULL)
|
|
{
|
|
return Dimension;
|
|
}
|
|
|
|
void *Data = object->Data;
|
|
char String[64];
|
|
uint String_Char_Count;
|
|
|
|
switch (object->Type)
|
|
{
|
|
case FLOAT:
|
|
Display_Font_Set_Font(((Object_Float *)Data)->Font->Font);
|
|
String_Char_Count = sprintf(String, ((Object_Float *)Data)->Format, *(((Object_Float *)Data)->Value));
|
|
Dimension.Height = Display_Font_Get_Font_Height();
|
|
Dimension.Width = Display_Font_Width_String(String, String_Char_Count, ((Object_Float *)Data)->Font->Character_Spacing);
|
|
break;
|
|
|
|
case INTEGER:
|
|
Display_Font_Set_Font(((Object_Integer *)Data)->Font->Font);
|
|
String_Char_Count = sprintf(String, ((Object_Integer *)Data)->Format, *(((Object_Integer *)Data)->Value));
|
|
Dimension.Height = Display_Font_Get_Font_Height();
|
|
Dimension.Width = Display_Font_Width_String(String, String_Char_Count, ((Object_Integer *)Data)->Font->Character_Spacing);
|
|
break;
|
|
|
|
case TEXT:
|
|
Display_Font_Set_Font(((Object_Text *)Data)->Font->Font);
|
|
Dimension.Height = Display_Font_Get_Font_Height();
|
|
Dimension.Width = Display_Font_Width_String((((Object_Text *)Data)->Text), ((Object_Text *)Data)->Length, ((Object_Text *)Data)->Font->Character_Spacing);
|
|
break;
|
|
|
|
case VALUE_BAR_RECT:
|
|
Dimension.Height = ((Object_Value_Bar_Rect *)Data)->Dimension.Height;
|
|
Dimension.Width = ((Object_Value_Bar_Rect *)Data)->Dimension.Width;
|
|
break;
|
|
|
|
case GRAPH:
|
|
Dimension.Height = ((Object_Graph *)Data)->Dimension.Height;
|
|
Dimension.Width = ((Object_Graph *)Data)->Dimension.Width;
|
|
break;
|
|
|
|
case BUTTON:
|
|
Dimension.Height = ((Object_Button *)Data)->Dimension.Height;
|
|
Dimension.Width = ((Object_Button *)Data)->Dimension.Width;
|
|
break;
|
|
|
|
case IMAGE:
|
|
Dimension.Height = Display_Image_Get_Height(((Object_Image_Color*)Data)->Image);
|
|
Dimension.Width = Display_Image_Get_Width(((Object_Image_Color*)Data)->Image);
|
|
break;
|
|
|
|
case BOOLEAN:
|
|
Display_Font_Set_Font(((Object_Bool *)Data)->Font->Font);
|
|
Dimension.Height = Display_Font_Get_Font_Height();
|
|
if(((Object_Bool *)Data)->Length_True >= ((Object_Bool *)Data)->Length_False)
|
|
{
|
|
Dimension.Width = Display_Font_Width_String((((Object_Bool *)Data)->Text_True), ((Object_Bool *)Data)->Length_True, ((Object_Bool *)Data)->Font->Character_Spacing);
|
|
}
|
|
else
|
|
{
|
|
Dimension.Width = Display_Font_Width_String((((Object_Bool *)Data)->Text_False), ((Object_Bool *)Data)->Length_False, ((Object_Bool *)Data)->Font->Character_Spacing);
|
|
}
|
|
break;
|
|
|
|
case SHAPE:
|
|
Dimension = Display_Objects_Get_Content_Size_From_Shape(object);
|
|
break;
|
|
|
|
case CANVAS:
|
|
Dimension.Height = ((Object_Canvas *)Data)->Dimension.Height;
|
|
Dimension.Width = ((Object_Canvas *)Data)->Dimension.Width;
|
|
break;
|
|
|
|
case MESSAGE_BOX:
|
|
Display_Font_Set_Font(((Object_Message_Box *)Data)->Font->Font);
|
|
Dimension.Height = Display_Font_Get_Font_Height() + MESSAGE_BOX_TEXT_BAR_DISTANCE + MESSAGE_BOX_BAR_HEIGHT;
|
|
Dimension.Width = Display_Font_Width_String((((Object_Message_Box *)Data)->Text), ((Object_Message_Box *)Data)->Length, ((Object_Message_Box *)Data)->Font->Character_Spacing);
|
|
|
|
if((((Object_Message_Box *)Data)->Icon) != MESSAGE_BOX_ICON_NONE) {
|
|
Dimension.Width += MESSAGE_BOX_TEXT_ICON_DISTANCE + Display_Message_Box_Icons_Get_Icon_Width(((Object_Message_Box *)Data)->Icon);
|
|
|
|
if(Display_Message_Box_Icons_Get_Icon_Height(((Object_Message_Box *)Data)->Icon) > Display_Font_Get_Font_Height()) {
|
|
Dimension.Height = Display_Message_Box_Icons_Get_Icon_Height(((Object_Message_Box *)Data)->Icon) + MESSAGE_BOX_TEXT_BAR_DISTANCE + MESSAGE_BOX_BAR_HEIGHT;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MENU_SELECT:
|
|
case MENU_ICON_ROW:
|
|
case SELECT_YESNO:
|
|
case SELECT_LIST:
|
|
case SELECT_VALUE:
|
|
case SELECT_RGB:
|
|
Dimension.Height = 0;
|
|
Dimension.Width = 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return Dimension;
|
|
}
|
|
|
|
Dimension Display_Objects_Get_Content_Size_From_Shape(Display_Object *object)
|
|
{
|
|
Dimension Dimension = { .Width = 0, .Height = 0 };
|
|
|
|
if(object->Type != SHAPE) {
|
|
return Dimension;
|
|
}
|
|
|
|
Object_Shape* Shape = (Object_Shape *)object->Data;
|
|
|
|
int16_t X1, X2, Y1, Y2;
|
|
|
|
switch(Shape->Type)
|
|
{
|
|
case RECTANGLE_FILLED:
|
|
case RECTANGLE_FRAME:
|
|
case ROUNDED_RECTANGLE_FILLED:
|
|
case ROUNDED_RECTANGLE_FRAME:
|
|
Dimension.Width = Shape->Dimension.Width;
|
|
Dimension.Height = Shape->Dimension.Height;
|
|
break;
|
|
|
|
case CIRCLE_FILLED:
|
|
case CIRCLE_FRAME:
|
|
Dimension.Width = Shape->Radius_Start * 2;
|
|
Dimension.Height = Shape->Radius_Start * 2;
|
|
break;
|
|
|
|
case ARC:
|
|
// This is still a ToDo
|
|
break;
|
|
|
|
case LINE_XY:
|
|
Dimension.Width = abs(object->Coordinates.X - Shape->Angle_Start); // Angle_Start contains x2
|
|
Dimension.Height = abs(object->Coordinates.Y - Shape->Angle_End); // Angle_End contains y2
|
|
break;
|
|
|
|
case LINE_RAD:
|
|
X1 = object->Coordinates.X + cos(Shape->Angle_Start * DEG2RAD) * Shape->Radius_Start;
|
|
Y1 = object->Coordinates.Y + sin(Shape->Angle_Start * DEG2RAD) * Shape->Radius_Start;
|
|
|
|
X2 = object->Coordinates.X + cos(Shape->Angle_Start * DEG2RAD) * Shape->Radius_End;
|
|
Y2 = object->Coordinates.Y + sin(Shape->Angle_Start * DEG2RAD) * Shape->Radius_End;
|
|
|
|
Dimension.Width = abs(X1 - X2);
|
|
Dimension.Height = abs(Y1 - Y2);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return Dimension;
|
|
} |