component* textinput_create(const text_settings *tconf, const char *text, const char *initialvalue) { component *c = widget_create(); textinput *tb = malloc(sizeof(textinput)); memset(tb, 0, sizeof(textinput)); tb->text = strdup(text); memcpy(&tb->tconf, tconf, sizeof(text_settings)); tb->pos = &tb->pos_; // Background for field int tsize = text_char_width(&tb->tconf); image img; image_create(&img, 15*tsize+2, tsize+3); image_clear(&img, COLOR_MENU_BG); image_rect(&img, 0, 0, 15*tsize+1, tsize+2, COLOR_MENU_BORDER); surface_create_from_image(&tb->sur, &img); image_free(&img); // Copy over the initial value memcpy(tb->buf, initialvalue, strlen(initialvalue)+1); // Widget stuff widget_set_obj(c, tb); widget_set_render_cb(c, textinput_render); widget_set_event_cb(c, textinput_event); widget_set_tick_cb(c, textinput_tick); widget_set_free_cb(c, textinput_free); return c; }
void textbutton_set_border(component *c, color col) { textbutton *tb = widget_get_obj(c); tb->border_enabled = 1; tb->border_color = col; if(tb->border_created) { // destroy the old border first surface_free(&tb->border); } // create new border int chars = strlen(tb->text); int fsize = text_char_width(&tb->tconf); int width = chars * fsize; menu_background_border_create(&tb->border, width+6, fsize+3); tb->border_created = 1; }
void text_render(const text_settings *settings, int x, int y, int w, int h, const char *text) { int len = strlen(text); int size = text_char_width(settings); int xspace = w - settings->padding.left - settings->padding.right; int yspace = h - settings->padding.top - settings->padding.bottom; int charw = size + settings->cspacing; int charh = size + settings->lspacing; int rows = (yspace + settings->lspacing) / charh; int cols = (xspace + settings->cspacing) / charw; int fit_lines = text_find_line_count(settings->direction, cols, rows, len, text); int start_x = x + settings->padding.left; int start_y = y + settings->padding.top; int tmp_s = 0; // Initial alignment for whole text block switch(settings->direction) { case TEXT_VERTICAL: tmp_s = fit_lines * charw - settings->cspacing; // Total W minus last spacing switch(settings->halign) { case TEXT_CENTER: start_x += ceil((xspace - tmp_s) / 2.0f); break; case TEXT_RIGHT: start_x += (xspace - tmp_s); break; default: break; } break; case TEXT_HORIZONTAL: tmp_s = fit_lines * charh - settings->lspacing; // Total H minus last spacing switch(settings->valign) { case TEXT_MIDDLE: start_y += floor((yspace - tmp_s) / 2.0f); break; case TEXT_BOTTOM: start_y += (yspace - tmp_s); break; default: break; } break; } int ptr = 0; int line = 0; while(ptr < len-1 && line < fit_lines) { int line_len; int real_len; int mx = 0; int my = 0; int line_pw; int line_ph; // Find out how many characters for this row/col if(settings->direction == TEXT_HORIZONTAL) line_len = text_find_max_strlen(cols, text + ptr); else line_len = text_find_max_strlen(rows, text + ptr); real_len = line_len; // Skip spaces int k = 0; for(; k < line_len; k++) { if(text[ptr+k] != ' ') break; real_len--; } // Find total size of this line and set newline start coords switch(settings->direction) { case TEXT_HORIZONTAL: line_pw = real_len * charw - settings->cspacing; my += charh * line; // Horizontal alignment for this line switch(settings->halign) { case TEXT_CENTER: mx += floor((xspace - line_pw) / 2.0f); break; case TEXT_RIGHT: mx += (xspace - line_pw); break; default: break; } break; case TEXT_VERTICAL: line_ph = real_len * charh - settings->lspacing; mx += charw * line; // Vertical alignment for this line switch(settings->valign) { case TEXT_MIDDLE: my += ceil((yspace - line_ph) / 2.0f); break; case TEXT_BOTTOM: my += (yspace - line_ph); break; default: break; } break; } // Render characters for(; k < line_len; k++) { // Skip line endings. if(text[ptr+k] == '\n') continue; // Render character text_render_char(settings, mx + start_x, my + start_y, text[ptr+k]); // Render to the right direction if(settings->direction == TEXT_HORIZONTAL) { mx += charw; } else { my += charh; } } ptr += line_len; line++; } }