static void a3d_textbox_printText(a3d_textbox_t* self, const char* string) { assert(self); assert(string); LOGD("debug string=%s", string); a3d_widget_t* widget = (a3d_widget_t*) self; a3d_text_t* text = a3d_text_new(widget->screen, 0, self->anchor, self->style_border, self->style_line, self->style_text, &(self->color_fill), &(self->color_line), &(self->color_text), self->max_len, NULL, NULL); if(text == NULL) { return; } a3d_text_wrapx(text, self->text_wrapx); a3d_listbox_t* listbox = (a3d_listbox_t*) self; if(a3d_list_enqueue(listbox->list, (const void*) text) == 0) { goto fail_enqueue; } a3d_text_printf(text, "%s", string); // success return; // failure fail_enqueue: a3d_text_delete(&text); }
void a3d_textbox_clear(a3d_textbox_t* self) { assert(self); LOGD("debug"); a3d_listbox_t* listbox = (a3d_listbox_t*) self; a3d_listitem_t* iter = a3d_list_head(listbox->list); while(iter) { a3d_text_t* text; text = (a3d_text_t*) a3d_list_remove(listbox->list, &iter); a3d_text_delete(&text); } iter = a3d_list_head(self->strings); while(iter) { void* string = (void*) a3d_list_remove(self->strings, &iter); free(string); } a3d_widget_t* widget = (a3d_widget_t*) self; a3d_screen_dirty(widget->screen); }
a3d_bulletbox_t* a3d_bulletbox_new(a3d_screen_t* screen, int wsize, int anchor, int style_border, int style_line, int style_text, a3d_vec4f_t* color_fill, a3d_vec4f_t* color_line, a3d_vec4f_t* color_text, a3d_vec4f_t* color_icon, int max_len, int count, a3d_widget_click_fn click_fn, a3d_widget_refresh_fn refresh_fn) { assert(screen); assert(color_fill); assert(color_line); assert(color_text); assert(color_icon); if(wsize == 0) { wsize = sizeof(a3d_bulletbox_t); } a3d_bulletbox_t* self; self = (a3d_bulletbox_t*) a3d_widget_new(screen, wsize, anchor, A3D_WIDGET_WRAP_SHRINK, A3D_WIDGET_WRAP_SHRINK, A3D_WIDGET_STRETCH_NA, 1.0f, style_border, style_line, color_line, color_fill, NULL, a3d_bulletbox_size, click_fn, a3d_bulletbox_layout, a3d_bulletbox_drag, a3d_bulletbox_draw, a3d_bulletbox_fade, refresh_fn); if(self == NULL) { return NULL; } a3d_vec4f_t clear = { .r = 0.0f, .g = 0.0f, .b = 0.0f, .a = 0.0f }; int wrap = A3D_WIDGET_WRAP_STRETCH_TEXT_MEDIUM; if(style_text == A3D_TEXT_STYLE_LARGE) { wrap = A3D_WIDGET_WRAP_STRETCH_TEXT_LARGE; } else if(style_text == A3D_TEXT_STYLE_SMALL) { wrap = A3D_WIDGET_WRAP_STRETCH_TEXT_SMALL; } self->icon = a3d_sprite_new(screen, 0, anchor, wrap, wrap, A3D_WIDGET_STRETCH_SQUARE, 1.0f, A3D_WIDGET_BORDER_NONE, A3D_WIDGET_LINE_NONE, &clear, &clear, color_icon, NULL, NULL, count); if(self->icon == NULL) { goto fail_icon; } self->text = a3d_text_new(screen, 0, anchor, A3D_WIDGET_BORDER_NONE, A3D_WIDGET_LINE_NONE, style_text, &clear, &clear, color_text, max_len, NULL, NULL); if(self->text == NULL) { goto fail_text; } // success return self; // failure fail_text: a3d_sprite_delete(&self->icon); fail_icon: a3d_widget_delete((a3d_widget_t**) &self); return NULL; } void a3d_bulletbox_delete(a3d_bulletbox_t** _self) { assert(_self); a3d_bulletbox_t* self = *_self; if(self) { LOGD("debug"); a3d_text_delete(&self->text); a3d_sprite_delete(&self->icon); a3d_widget_delete((a3d_widget_t**) _self); } }
static void a3d_textbox_reflow(a3d_widget_t* widget, float w, float h) { assert(widget); LOGD("debug w=%f, h=%f", w, h); a3d_textbox_t* self = (a3d_textbox_t*) widget; // reflow text when changes occur if((self->dirty == 0) && (self->last_w == w) && (self->last_h == h)) { return; } self->dirty = 0; self->last_w = w; self->last_h = h; // determine maxi a3d_font_t* font = a3d_screen_font(widget->screen); float aspect = a3d_font_aspectRatio(font); float size = a3d_screen_layoutText(widget->screen, self->style_text); int maxi = (int) (w/(aspect*size)) - 1; // maxi does not include null character // but max_len does // limit to max_len if((maxi >= self->max_len) || (maxi == 0)) { maxi = self->max_len - 1; } // clear the text a3d_listbox_t* listbox = (a3d_listbox_t*) self; a3d_listitem_t* iter = a3d_list_head(listbox->list); while(iter) { a3d_text_t* text; text = (a3d_text_t*) a3d_list_remove(listbox->list, &iter); a3d_text_delete(&text); } // initialize parser char tok[256]; char dst[256]; int srci = 0; int toki = 0; int dsti = 0; int type = A3D_TOKEN_END; // reflow the string(s) iter = a3d_list_head(self->strings); while(iter) { const char* src = (const char*) a3d_list_peekitem(iter); srci = 0; type = getToken(src, tok, &srci, &toki); while(type != A3D_TOKEN_END) { if(type == A3D_TOKEN_BREAK) { if(dsti > 0) { a3d_textbox_printText(self, dst); a3d_textbox_printText(self, ""); } else { a3d_textbox_printText(self, ""); } dsti = 0; break; } if(dsti == 0) { strncpy(dst, tok, 256); dst[255] = '\0'; dsti = toki; } else { if(dsti + toki + 1 <= maxi) { strcat(dst, " "); strcat(dst, tok); dst[255] = '\0'; dsti += toki + 1; } else { a3d_textbox_printText(self, dst); strncpy(dst, tok, 256); dst[255] = '\0'; dsti = toki; } } type = getToken(src, tok, &srci, &toki); } iter = a3d_list_next(iter); } if(dsti > 0) { a3d_textbox_printText(self, dst); } }