374 lines
12 KiB
C
374 lines
12 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "Ui.h"
|
|
#include "render.h"
|
|
|
|
struct List *newList(struct Ui_Colors *colors) {
|
|
struct List *list = malloc(sizeof(struct List));
|
|
if (list == NULL) return NULL;
|
|
initList(list);
|
|
list->colors = colors;
|
|
return list;
|
|
}
|
|
int freeList(struct List *list) {
|
|
freeListItems(list);
|
|
free(list); // :)
|
|
return 0;
|
|
}
|
|
int initList(struct List *list) {
|
|
if (list == NULL) return 1;
|
|
list->box.x = list->box.y = list->box.w = list->box.h = 0;
|
|
list->page = list->items_per_page = list->count = list->selected = 0;
|
|
list->items = NULL;
|
|
return 0;
|
|
}
|
|
int remListIndex(struct List *list, int index) {
|
|
if (index > list->count || index < 0) {
|
|
return 1;
|
|
}
|
|
struct Button* r_hand[list->count-index+1];
|
|
memcpy(&r_hand, list->items+index+1, (list->count-(index+1))*sizeof(struct Button*));
|
|
list->items = realloc(list->items, (list->count-1)*(sizeof(struct Button*)));
|
|
memcpy(list->items+index, r_hand, (list->count-(index+1))*sizeof(struct Button*));
|
|
list->count--;
|
|
return 0;
|
|
}
|
|
int addListItem(struct List *list, struct Button *item) {
|
|
list->count++;
|
|
list->items = realloc(list->items, sizeof(struct Button*)*list->count);
|
|
list->items[list->count-1] = item;
|
|
return 0;
|
|
}
|
|
int remListItem(struct List *list, struct Button *item) {
|
|
int i;
|
|
for(i = 0; i < list->count; i++) {
|
|
if (list->items[i] == item) {
|
|
return remListIndex(list, i);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
int freeListItems(struct List *list) {
|
|
int i;
|
|
for(i = 0; i < list->count; i++) {
|
|
freeButton(list->items[i]);
|
|
}
|
|
free(list->items);
|
|
list->items = NULL;
|
|
list->count = 0;
|
|
return 0;
|
|
}
|
|
int prepList(struct List *list) {
|
|
int i;
|
|
int offset_y = 0;
|
|
for(i = 0; i < list->count; i++) {
|
|
list->items[i]->box.y = offset_y;
|
|
offset_y += list->items[i]->box.h;
|
|
}
|
|
return 0;
|
|
}
|
|
int renderList(struct List *list) {
|
|
if (list == NULL) return 1;
|
|
int i;
|
|
int base_x = list->box.x;
|
|
int base_y = list->box.y;
|
|
|
|
renderSQuad(base_x, base_y, list->box.w, list->box.h, list->colors->bg);
|
|
|
|
int offset_y = 0;
|
|
for(i = 0; i < list->count; i++) {
|
|
int x = base_x + (list->box.w/2) - (list->items[i]->box.w/2);
|
|
int y = base_y + offset_y + list->items[i]->box.y;
|
|
if (list->items[i]->flags & UI_ACTIVE) {
|
|
renderSQuad(base_x, base_y+offset_y, list->box.w, list->items[i]->box.h, list->items[i]->colors->fg);
|
|
renderGlyphString(list->items[i]->glyphs, list->items[i]->colors->bg, x, y, list->items[i]->text);
|
|
} else {
|
|
renderSQuad(base_x, base_y+offset_y, list->box.w, list->items[i]->box.h, list->items[i]->colors->bg);
|
|
renderGlyphString(list->items[i]->glyphs, list->items[i]->colors->fg, x, y, list->items[i]->text);
|
|
}
|
|
/*if (i%2 == 0) {
|
|
renderSQuad(base_x, base_y+offset_y, list->box.w, list->items[i]->box.h, list->colors->fg);
|
|
renderGlyphString(list->items[i]->glyphs, list->items[i]->colors->bg, x, y, list->items[i]->text);
|
|
} else {
|
|
renderSQuad(base_x, base_y+offset_y, list->box.w, list->items[i]->box.h, list->items[i]->colors->bg);
|
|
renderGlyphString(list->items[i]->glyphs, list->items[i]->colors->fg, x, y, list->items[i]->text);
|
|
}*/
|
|
//int x = base_x + list->items[i]->box.x;
|
|
offset_y += list->items[i]->box.h;
|
|
}
|
|
return 0;
|
|
}
|
|
struct Box getListItemBox(struct List *list, int i) {
|
|
struct Box box = { 0, 0, 0, 0 };
|
|
if (list == NULL) return box;
|
|
if (i < 0 || i > list->count) return box;
|
|
box.x = 0;
|
|
box.y = i * list->items[i]->box.h; // FIXME: list y should be homogenously referenced
|
|
box.w = list->items[i]->box.w;
|
|
box.h = list->items[i]->box.h;
|
|
return box;
|
|
}
|
|
struct Box getListItemBoxAbs(struct List *list, int i) {
|
|
struct Box box = { 0, 0, 0, 0 };
|
|
if (list == NULL) return box;
|
|
if (i < 0 || i > list->count) return box;
|
|
box.x = list->box.x;
|
|
box.y = list->box.y + i * list->items[i]->box.h; // FIXME: list y should be homogenously referenced
|
|
box.w = list->box.w;
|
|
box.h = list->items[i]->box.h;
|
|
return box;
|
|
}
|
|
|
|
struct Button *newButton(struct Glyphs *glyphs, struct Ui_Colors *colors, const char *string) {
|
|
if (glyphs == NULL) return NULL;
|
|
if (string == NULL) return NULL;
|
|
struct Button *button = malloc(sizeof(struct Button));
|
|
if (button == NULL) return NULL;
|
|
button->colors = colors;
|
|
button->text = NULL;
|
|
button->flags = 0;
|
|
button->p_flags = 0;
|
|
button->glyphs = glyphs;
|
|
button->box.x = button->box.y = button->box.w = button->box.h = 0;
|
|
if (setButtonText(button, string) != 0) return NULL;
|
|
return button;
|
|
}
|
|
int freeButton(struct Button *button) {
|
|
if (button == NULL) return 1;
|
|
free(button->text);
|
|
free(button);
|
|
return 0;
|
|
}
|
|
int setButtonText(struct Button *button, const char *string) {
|
|
if (button == NULL) return 1;
|
|
if (string == NULL) return 2;
|
|
if (button->glyphs == NULL) return 3;
|
|
|
|
int size = strlen(string)+1;
|
|
if ((button->text = realloc(button->text, size)) == NULL) {
|
|
return 4;
|
|
}
|
|
memcpy(button->text, string, size);
|
|
|
|
button->box.w = getGlyphStringW(button->glyphs, button->text)+4;
|
|
button->box.h = button->glyphs->h+2; // TODO: getGlyphStringH
|
|
return 0;
|
|
}
|
|
int renderButton(struct Button *button) {
|
|
if (button == NULL) return 1;
|
|
SDL_Color fg, bg;
|
|
if (button->flags & UI_ACTIVE) {
|
|
fg = button->colors->a_fg;
|
|
bg = button->colors->a_bg;
|
|
renderSQuad(button->box.x+2, button->box.y+2, button->box.w, button->box.h, bg);
|
|
int x = (button->box.w/2) - getGlyphStringW(button->glyphs, button->text)/2;
|
|
renderGlyphString(button->glyphs, button->colors->a_fg, button->box.x+x+2, button->box.y+2, button->text);
|
|
} else {
|
|
fg = button->colors->fg;
|
|
bg = button->colors->bg;
|
|
// draw shadow
|
|
renderSQuad(button->box.x+2, button->box.y+2, button->box.w, button->box.h, button->colors->a_bg);
|
|
renderSQuad(button->box.x, button->box.y, button->box.w, button->box.h, bg);
|
|
int x = (button->box.w/2) - getGlyphStringW(button->glyphs, button->text)/2;
|
|
renderGlyphString(button->glyphs, button->colors->fg, button->box.x+x, button->box.y, button->text);
|
|
}
|
|
if (button->p_flags & UI_BORDER) {
|
|
renderLQuad(button->box.x, button->box.y, button->box.w+2, button->box.h+2, fg);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct TextInput *newTextInput(struct Glyphs *glyphs, struct Ui_Colors *colors, int width) {
|
|
if (glyphs == NULL) return NULL;
|
|
if (colors == NULL) return NULL;
|
|
struct TextInput *input = malloc(sizeof(struct TextInput));
|
|
if (input == NULL) return NULL;
|
|
input->colors = colors;
|
|
input->text = malloc(1);
|
|
input->text[0] = '\0';
|
|
input->cursor = 0;
|
|
input->p_flags = 0;
|
|
input->flags = 0;
|
|
input->glyphs = glyphs;
|
|
input->box.x = input->box.y = input->box.w = input->box.h = 0;
|
|
input->box.w = width;
|
|
input->box.h = input->glyphs->h; // TODO: getGlyphStringH
|
|
return input;
|
|
}
|
|
int freeTextInput(struct TextInput *input) {
|
|
free(input->text);
|
|
free(input);
|
|
return 0;
|
|
}
|
|
int insertTextInput(struct TextInput *text_input, const char *string) {
|
|
int text_size = strlen(text_input->text)+1;
|
|
int string_size = strlen(string)+1;
|
|
// calculate insert position
|
|
int l_hand = text_input->cursor*sizeof(char);
|
|
int r_hand = (text_size - l_hand)*sizeof(char);
|
|
// create a copy of our current text
|
|
char temp[r_hand];
|
|
memcpy(&temp, text_input->text+l_hand, r_hand);
|
|
// reallocate our text to fit added string
|
|
text_input->text = realloc(text_input->text, text_size+string_size-1);
|
|
// insert string, minus \0
|
|
memcpy(text_input->text+l_hand, string, string_size-1);
|
|
// copy over right-hand side of the text
|
|
memcpy(text_input->text+l_hand+string_size-1, &temp, r_hand);
|
|
text_input->cursor += string_size-1;
|
|
// hopefully nothing exploded
|
|
return 0;
|
|
}
|
|
int deleteTextInput(struct TextInput *text_input, int start, int length) {
|
|
if (text_input == NULL) return 1;
|
|
int text_size = strlen(text_input->text)+1;
|
|
if (start < 0 || start > text_size) return 2;
|
|
if (length <= 0 || start+length > text_size) return 2;
|
|
|
|
char temp[text_size - (start+length)];
|
|
memcpy(&temp, text_input->text+start+length, text_size - (start+length));
|
|
text_input->text = realloc(text_input->text, text_size-length);
|
|
memcpy(text_input->text+start, temp, text_size-(start+length));
|
|
|
|
return 0;
|
|
}
|
|
int setTextInputText(struct TextInput *text_input, const char *string, ...) {
|
|
if (text_input == NULL) return 1;
|
|
if (string == NULL) return 2;
|
|
if (text_input->glyphs == NULL) return 3;
|
|
|
|
char buf[128];
|
|
char *buffer;
|
|
int overflow;
|
|
va_list args;
|
|
|
|
buffer = buf;
|
|
|
|
va_start(args, string);
|
|
overflow = vsnprintf(buffer, 128, string, args);
|
|
va_end(args);
|
|
// did we overflow?
|
|
if (overflow >= 128) {
|
|
buffer = (char*)malloc(overflow+1);
|
|
va_start(args, string);
|
|
overflow = vsnprintf(buffer, overflow+1, string, args);
|
|
va_end(args);
|
|
}
|
|
if ((text_input->text = realloc(text_input->text, overflow+1)) == NULL) {
|
|
return 4;
|
|
}
|
|
memcpy(text_input->text, buffer, overflow+1);
|
|
if (buffer != buf) {
|
|
free(buffer);
|
|
}
|
|
text_input->cursor = overflow;
|
|
//text_input->box.w = getGlyphStringW(text_input->glyphs, string);
|
|
//text_input->box.h = text_input->glyphs->h; // TODO: getGlyphStringH
|
|
return 0;
|
|
}
|
|
int renderTextInput(struct TextInput *input) {
|
|
if (input == NULL) return 1;
|
|
SDL_Color fg, bg;
|
|
if (input->flags & UI_ACTIVE) {
|
|
fg = input->colors->a_fg;
|
|
bg = input->colors->a_bg;
|
|
} else {
|
|
fg = input->colors->fg;
|
|
bg = input->colors->bg;
|
|
}
|
|
renderSQuad(input->box.x, input->box.y, input->box.w, input->box.h, bg);
|
|
renderGlyphString(input->glyphs, input->colors->fg, input->box.x+2, input->box.y, input->text);
|
|
if (input->p_flags & UI_BORDER) {
|
|
renderLQuad(input->box.x, input->box.y, input->box.w+2, input->box.h+2, fg);
|
|
}
|
|
// draw cursor
|
|
char cursor_offset[input->cursor+1];
|
|
memcpy(&cursor_offset, input->text, input->cursor);
|
|
cursor_offset[input->cursor] = '\0';
|
|
renderGlyph(input->glyphs, input->colors->fg, '|', input->box.x+getGlyphStringW(input->glyphs, cursor_offset)-3, input->box.y);
|
|
return 0;
|
|
}
|
|
|
|
|
|
struct Textt *newTextt(struct Glyphs *glyphs, struct Ui_Colors *colors, const char *string) {
|
|
if (glyphs == NULL) return NULL;
|
|
if (string == NULL) return NULL;
|
|
struct Textt *text = malloc(sizeof(struct Textt));
|
|
if (text == NULL) return NULL;
|
|
text->colors = colors;
|
|
text->text = NULL;
|
|
text->flags = 0;
|
|
text->p_flags = 0;
|
|
text->glyphs = glyphs;
|
|
text->box.x = text->box.y = text->box.w = text->box.h = 0;
|
|
if (setTextt(text, string) != 0) return NULL;
|
|
return text;
|
|
}
|
|
int freeTextt(struct Textt *text) {
|
|
if (text == NULL) return 1;
|
|
free(text->text);
|
|
free(text);
|
|
return 0;
|
|
}
|
|
int setTextt(struct Textt *text, const char *string, ...) {
|
|
char buf[128];
|
|
char *buffer;
|
|
int overflow;
|
|
va_list args;
|
|
|
|
buffer = buf;
|
|
|
|
va_start(args, string);
|
|
overflow = vsnprintf(buffer, 128, string, args);
|
|
va_end(args);
|
|
// did we overflow?
|
|
if (overflow >= 128) {
|
|
buffer = (char*)malloc(overflow+1);
|
|
va_start(args, string);
|
|
overflow = vsnprintf(buffer, overflow+1, string, args);
|
|
va_end(args);
|
|
}
|
|
if ((text->text = realloc(text->text, overflow+1)) == NULL) {
|
|
return 4;
|
|
}
|
|
memcpy(text->text, buffer, overflow+1);
|
|
if (buffer != buf) {
|
|
free(buffer);
|
|
}
|
|
text->box.w = getGlyphStringW(text->glyphs, text->text);
|
|
text->box.h = text->glyphs->h; // TODO: getGlyphStringH
|
|
return 0;
|
|
}
|
|
int addTexttChar(struct Textt *text, char ch) {
|
|
// eww
|
|
printf("old: %s\n", text->text);
|
|
int size = strlen(text->text)+1;
|
|
text->text = realloc(text->text, size+1);
|
|
text->text[size] = ch;
|
|
text->text[size+1] = '\0';
|
|
printf("added %c, string is now \"%s\"\n", ch, text->text);
|
|
return 0;
|
|
}
|
|
int renderTextt(struct Textt *text) {
|
|
if (text == NULL) return 1;
|
|
SDL_Color fg, bg;
|
|
if (text->flags & UI_ACTIVE) {
|
|
fg = text->colors->a_fg;
|
|
bg = text->colors->a_bg;
|
|
//renderSQuad(text->box.x+2, text->box.y+2, text->box.w, text->box.h, bg);
|
|
int x = (text->box.w/2) - getGlyphStringW(text->glyphs, text->text)/2;
|
|
renderGlyphString(text->glyphs, text->colors->a_fg, text->box.x+x+2, text->box.y+2, text->text);
|
|
} else {
|
|
fg = text->colors->fg;
|
|
bg = text->colors->bg;
|
|
// draw shadow
|
|
//renderSQuad(text->box.x, text->box.y, text->box.w, text->box.h, bg);
|
|
int x = (text->box.w/2) - getGlyphStringW(text->glyphs, text->text)/2;
|
|
renderGlyphString(text->glyphs, text->colors->fg, text->box.x+x, text->box.y, text->text);
|
|
}
|
|
if (text->p_flags & UI_BORDER) {
|
|
renderLQuad(text->box.x, text->box.y, text->box.w+2, text->box.h+2, fg);
|
|
}
|
|
return 0;
|
|
}
|