8 #include "SDL_gfxPrimitives.h"
10 #include "../graphics.h"
11 #include "../memory.h"
17 static void free_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
18 static void reposition_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
19 static void rescale_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
20 static void paint_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
21 static void update_text_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
23 static void get_label_image_pos(struct xuni_t
*xuni
, struct widget_t
*widget
,
25 static int label_pos_to_width(struct xuni_t
*xuni
, struct widget_edit_t
*edit
,
26 struct widget_t
*font
);
27 static void paint_label_clip(SDL_Surface
*image
, SDL_Surface
*screen
,
28 int x
, int y
, struct clip_pos_t
*clip
);
29 static void paint_edit_label(struct xuni_t
*xuni
, struct widget_edit_t
*edit
,
30 struct widget_t
*font
, int x
, int y
);
32 void label_widget_event(struct xuni_t
*xuni
, struct widget_t
*widget
,
33 enum widget_event_t event
) {
35 static void (*function
[])(struct xuni_t
*xuni
, struct widget_t
*widget
)
45 call_widget_event_func(xuni
, widget
, event
, function
,
46 sizeof(function
) / sizeof(*function
));
49 void init_label(struct widget_t
*widget
, size_t font
, const char *data
,
50 enum label_type_t type
, Uint8 r
, Uint8 g
, Uint8 b
) {
52 widget
->type
= WIDGET_LABEL
;
53 widget
->p
.label
= xuni_memory_allocate(sizeof(*widget
->p
.label
));
55 widget
->p
.label
->type
= type
;
56 xuni_memory_increment((void *)data
);
57 widget
->p
.label
->text
= data
;
58 widget
->p
.label
->font
= font
;
59 widget
->p
.label
->label
= 0;
60 widget
->p
.label
->scroll
= 0;
62 widget
->p
.label
->col
.r
= r
;
63 widget
->p
.label
->col
.g
= g
;
64 widget
->p
.label
->col
.b
= b
;
67 static void free_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
68 if(xuni_memory_decrement(widget
->p
.label
)) {
69 free_surface(widget
->p
.label
->label
);
71 xuni_memory_free((void *)widget
->p
.label
->text
);
73 free(widget
->p
.label
);
77 static void get_label_image_pos(struct xuni_t
*xuni
, struct widget_t
*widget
,
80 const SDL_Rect
*real
= &widget
->pos
->real
;
82 = font_height(xuni
, get_theme_widget(xuni
, widget
->p
.label
->font
));
85 if(widget
->p
.label
->label
) {
86 width
= widget
->p
.label
->label
->w
;
89 switch(widget
->p
.label
->type
) {
90 case LABEL_ALIGN_LEFT
:
91 *y
+= (real
->h
- height
) / 2;
93 case LABEL_ALIGN_CENTRE
:
94 *x
+= (real
->w
- width
) / 2;
95 *y
+= (real
->h
- height
) / 2;
97 case LABEL_ALIGN_RIGHT
:
98 *x
+= real
->w
- width
;
99 *y
+= (real
->h
- height
) / 2;
102 printf("*** Unknown label type: %i\n", (int)widget
->p
.label
->type
);
107 static void paint_label_clip(SDL_Surface
*image
, SDL_Surface
*screen
,
108 int x
, int y
, struct clip_pos_t
*clip
) {
113 blit_surface(screen
, image
, x
, y
);
116 blit_surface_area(screen
, image
,
126 static int label_pos_to_width(struct xuni_t
*xuni
, struct widget_edit_t
*edit
,
127 struct widget_t
*font
) {
132 if(!edit
->data
->text
|| !*edit
->data
->text
) return 0;
134 if(edit
->pos
!= edit
->len
) swap
= 1;
137 temp
= edit
->data
->text
[edit
->pos
];
138 ((char *)edit
->data
->text
)[edit
->pos
] = 0;
141 /* !!! if pos->real.w is set by reposition_label(), it could be used here
142 when edit->pos == edit->len
144 w
= font_string_width(xuni
, font
, edit
->data
->text
);
147 ((char *)edit
->data
->text
)[edit
->pos
] = temp
;
153 /* !!! very inefficient */
154 size_t width_to_label_pos(struct xuni_t
*xuni
, int pos
, struct widget_t
*font
,
159 size_t len
= strlen(data
), x
= len
+ 1;
167 w
= font_string_width(xuni
, font
, data
);
169 /*printf("is %i>%i for \"%s\"?\n", w, pos, data);*/
172 } while(w
> pos
&& x
);
174 /*printf("%i<=%i<=%i: %i %i (%i)\n", prevw, pos, w,
175 abs(pos - prevw), abs(pos - w), (int)x);*/
177 /* Because <= is used instead of <, it opts to move the cursor to the
178 right when the exact centre of a character is clicked on. This only
179 matters for characters that are an odd number of pixels wide. */
180 if(prevw
- pos
<= pos
- w
) x
++;
182 if(x
== len
+ 1) x
--;
187 static void paint_edit_label(struct xuni_t
*xuni
, struct widget_edit_t
*edit
,
188 struct widget_t
*font
, int x
, int y
) {
192 width
= label_pos_to_width(xuni
, edit
, font
);
193 height
= font_height(xuni
, font
);
194 /*vlineRGBA(smode->screen, x + widget->pos->real.w + 1,
195 y, y + widget->pos->real.h, 255, 255, 255, 255);*/
196 /*printf("width=%i, height=%i, pos=(%i,%i)\n", width, height, x, y);*/
197 vlineRGBA(xuni
->smode
->screen
, x
+ width
, y
, y
+ height
,
201 static void paint_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
205 SDL_FillRect(xuni->smode->screen, &widget->pos->real,
206 SDL_MapRGB(xuni->smode->screen->format, 0, 0, 128));
209 /*if(widget->p.label->label->h !=
210 font_height(xuni, get_theme_widget(xuni, widget->p.label->font))) {
212 printf("Not equal!\n");
215 get_label_image_pos(xuni
, widget
, &x
, &y
);
217 x
+= widget
->pos
->real
.x
;
218 y
+= widget
->pos
->real
.y
;
220 paint_label_clip(widget
->p
.label
->label
, xuni
->smode
->screen
,
221 x
, y
, widget
->pos
->clip
);
223 /* use xuni->gui->edit.datawidget instead of xuni->gui->active.widget? */
224 if(widget
->base
&& widget
->base
->type
== WIDGET_TEXTBOX
225 && xuni
->gui
->active
.widget
== widget
->base
) {
227 if(widget
->pos
->clip
) {
228 x
-= widget
->pos
->clip
->xclip
;
229 x
+= widget
->pos
->clip
->xoff
;
230 y
+= widget
->pos
->clip
->yoff
;
233 paint_edit_label(xuni
, &xuni
->gui
->edit
,
234 get_theme_widget(xuni
, widget
->p
.label
->font
), x
, y
);
238 void reposition_label_data(struct xuni_t
*xuni
, struct label_t
*label
,
239 struct widget_edit_t
*edit
, size_t pos
) {
241 int poswidth
= label_pos_to_width(xuni
, edit
,
242 get_theme_widget(xuni
, label
->font
));
243 double boxwidth
= get_box_width(xuni
, xuni
->theme
->current
) / 100.0
244 * xuni
->smode
->width
;
245 int labelw
, offset
, newleft
, basewidth
;
247 /* !!! would use widget->p.label->label->w, but the label is not resized, nor pos->real.w set */
249 labelw
= font_string_width(xuni
,
250 get_theme_widget(xuni
, label
->font
), label
->text
);
254 offset
= labelw
- edit
->datawidget
->base
->pos
->real
.w
+ boxwidth
* 2;
256 /*printf("reposition_label_data() offset=%i, poswidth=%i, labelw=%i\n",
257 offset, poswidth, labelw);*/
260 if(poswidth
< offset
) newleft
= poswidth
;
261 else newleft
= offset
;
264 /* all of the text in the textbox fits into one view */
268 basewidth
= edit
->datawidget
->base
->pos
->real
.w
- boxwidth
* 2;
270 /* If the new left position is out of range of the displayed one, set the
271 displayed left position so that newleft is visible.
273 if(poswidth
< edit
->datawidget
->base
->p
.textbox
->leftpos
) {
274 edit
->datawidget
->base
->p
.textbox
->leftpos
= poswidth
;
276 else if(poswidth
> edit
->datawidget
->base
->p
.textbox
->leftpos
279 edit
->datawidget
->base
->p
.textbox
->leftpos
= poswidth
- basewidth
;
282 /*poswidth = edit->leftpos;*/
284 if(offset
> edit
->datawidget
->base
->p
.textbox
->leftpos
) {
285 /*printf("offset by %i\n", offset - poswidth);*/
286 add_widget_clip(xuni
, edit
->datawidget
, 0, 0,
287 -(offset
- edit
->datawidget
->base
->p
.textbox
->leftpos
), 0, 0, 0);
291 add_widget_clip(xuni, edit->datawidget, 0, 0, offset, 0, 0, 0);
294 /*add_widget_clip(widget, width, 0, 0, 0, -width * 2, 0);*/
297 static void reposition_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
301 /* !!! hack to allow textbox scrolling */
302 if(/*widget->p.label->label &&*/ widget
->base
&& widget
->base
->pos
) {
303 if(widget
->base
->type
== WIDGET_TEXTBOX
) scroll
= 1;
305 if(widget
->base
->type
== WIDGET_PANEL
&& widget
->base
->base
306 && widget
->base
->base
->type
== WIDGET_LISTBOX
) {
313 double width
= get_box_width(xuni
, xuni
->theme
->current
) / 100.0
314 * xuni
->smode
->width
;
317 /* !!! would use widget->p.label->label->w, but the label is not resized, nor pos->real.w set */
318 if(widget
->p
.label
->text
) {
319 labelw
= font_string_width(xuni
,
320 get_theme_widget(xuni
, widget
->p
.label
->font
),
321 widget
->p
.label
->text
);
325 offset
= labelw
- widget
->base
->pos
->real
.w
+ width
* 2;
326 /*printf("base width: %i\n", widget->base->pos->real.w);
327 print_inline_widget_backtrace(widget);*/
330 add_widget_clip(xuni
, widget
, 0, 0, offset
, 0, 0, 0);
333 add_widget_clip(xuni
, widget
, width
, 0, 0, 0, -width
* 2, 0);
335 if(offset
< 0) widget
->pos
->real
.w
= labelw
;
337 widget
->pos
->real
.w
= widget
->base
->pos
->real
.w
- width
* 2;
340 if(widget
== xuni
->gui
->edit
.datawidget
) {
341 reposition_label_data(xuni
, xuni
->gui
->edit
.data
,
342 &xuni
->gui
->edit
, xuni
->gui
->edit
.pos
);
345 add_widget_clip(xuni, widget, 0, 0,
346 -widget->base->p.textbox->leftpos, 0, 0, 0);
349 /* !!! too small most likely */
350 /*widget->pos->real.h = font_height(widget->p.label->font);*/
354 static void rescale_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
356 static int count = 0;
358 printf("rescale_label() #%3i \"%s\"\n", ++count,
359 widget->p.label->text);
362 /*if(widget->p.label->font) {*/
364 free_surface(widget
->p
.label
->label
);
365 widget
->p
.label
->label
367 get_theme_widget(xuni
, widget
->p
.label
->font
),
368 widget
->p
.label
->text
,
369 widget
->p
.label
->col
.r
,
370 widget
->p
.label
->col
.g
,
371 widget
->p
.label
->col
.b
);
374 /* it's better to do this in font.c */
375 if(widget
->p
.label
->label
) {
376 SDL_Surface
*temp
= widget
->p
.label
->label
;
377 double ratio
, xratio
, yratio
;
379 ratio
= (xuni
->smode
->screen
->w
/ (double)xuni
->smode
->screen
->h
)
380 / get_font_ratio(xuni
);
381 xratio
= (ratio
> 1.0) ? ratio
: 1.0;
382 yratio
= (ratio
< 1.0) ? 1.0 / ratio
: 1.0;
384 widget
->p
.label
->label
= zoomSurface(temp
,
385 /*widget->pos->scale.w / 100.0
386 / ((double)xuni->smode->screen->w / widget->base->pos->real.w)
387 * xuni->smode->screen->w / temp->w*/ xratio
,
388 /*widget->pos->scale.h / 100.0
389 / ((double)xuni->smode->screen->h / widget->base->pos->real.h)
390 * xuni->smode->screen->h / temp->h*/ yratio
,
393 SDL_FreeSurface(temp
);
397 /*widget->pos->scale.w
398 = widget->p.label->label->w * 100.0 / smode->width;
400 = widget->p.label->label->h * 100.0 / smode->height;*/
402 if(!widget
->pos
->scale
.w
&& !widget
->pos
->scale
.h
403 && widget
->p
.label
->label
) {
405 widget
->pos
->real
.w
= widget
->p
.label
->label
->w
;
406 widget
->pos
->real
.h
= widget
->p
.label
->label
->h
;
410 static void update_text_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
411 rescale_label(xuni
, widget
);