7 #include "SDL_gfxPrimitives.h"
9 #include "../graphics.h"
10 #include "../memory.h"
16 static void free_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
17 static void reposition_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
18 static void rescale_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
19 static void paint_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
20 static void update_text_label(struct xuni_t
*xuni
, struct widget_t
*widget
);
22 static void get_label_image_pos(enum label_type_t type
, const SDL_Rect
*real
,
23 const SDL_Surface
*image
, int *x
, int *y
);
24 static int label_pos_to_width(struct widget_edit_t
*edit
,
25 struct widget_t
*font
);
26 static void paint_label_clip(SDL_Surface
*image
, SDL_Surface
*screen
,
27 int x
, int y
, struct clip_pos_t
*clip
);
28 static void paint_edit_label(struct smode_t
*smode
,
29 struct widget_edit_t
*edit
, struct widget_t
*font
, int x
, int y
);
31 void label_widget_event(struct xuni_t
*xuni
, struct widget_t
*widget
,
32 enum widget_event_t event
) {
34 static void (*function
[])(struct xuni_t
*xuni
, struct widget_t
*widget
)
44 call_widget_event_func(xuni
, widget
, event
, function
,
45 sizeof(function
) / sizeof(*function
));
48 void init_label(struct widget_t
*widget
, size_t font
, const char *data
,
49 enum label_type_t type
, Uint8 r
, Uint8 g
, Uint8 b
) {
51 widget
->type
= WIDGET_LABEL
;
52 widget
->p
.label
= xuni_memory_allocate(sizeof(*widget
->p
.label
));
54 widget
->p
.label
->type
= type
;
55 xuni_memory_increment((void *)data
);
56 widget
->p
.label
->text
= data
;
57 widget
->p
.label
->font
= font
;
58 widget
->p
.label
->label
= 0;
59 widget
->p
.label
->scroll
= 0;
61 widget
->p
.label
->col
.r
= r
;
62 widget
->p
.label
->col
.g
= g
;
63 widget
->p
.label
->col
.b
= b
;
66 static void free_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
67 if(xuni_memory_decrement(widget
->p
.label
)) {
68 free_surface(widget
->p
.label
->label
);
70 xuni_memory_free((void *)widget
->p
.label
->text
);
72 free(widget
->p
.label
);
76 static void get_label_image_pos(enum label_type_t type
, const SDL_Rect
*real
,
77 const SDL_Surface
*image
, int *x
, int *y
) {
80 case LABEL_ALIGN_LEFT
:
81 *y
+= (real
->h
- image
->h
) / 2;
83 case LABEL_ALIGN_CENTRE
:
84 *x
+= (real
->w
- image
->w
) / 2;
85 *y
+= (real
->h
- image
->h
) / 2;
87 case LABEL_ALIGN_RIGHT
:
88 *x
+= real
->w
- image
->w
;
89 *y
+= (real
->h
- image
->h
) / 2;
92 printf("*** Unknown label type: %i\n", (int)type
);
97 static void paint_label_clip(SDL_Surface
*image
, SDL_Surface
*screen
,
98 int x
, int y
, struct clip_pos_t
*clip
) {
101 blit_surface(screen
, image
, x
, y
);
104 blit_surface_area(screen
, image
,
114 static int label_pos_to_width(struct widget_edit_t
*edit
,
115 struct widget_t
*font
) {
120 if(!edit
->data
->text
|| !*edit
->data
->text
) return 0;
122 if(edit
->pos
!= edit
->len
) swap
= 1;
125 temp
= edit
->data
->text
[edit
->pos
];
126 ((char *)edit
->data
->text
)[edit
->pos
] = 0;
129 /* !!! if pos->real.w is set by reposition_label(), it could be used here
130 when edit->pos == edit->len
132 w
= font_string_width(font
, edit
->data
->text
);
135 ((char *)edit
->data
->text
)[edit
->pos
] = temp
;
141 /* !!! very inefficient */
142 size_t width_to_label_pos(int pos
, struct widget_t
*font
, char *data
) {
145 size_t len
= strlen(data
), x
= len
+ 1;
153 w
= font_string_width(font
, data
);
155 /*printf("is %i>%i for \"%s\"?\n", w, pos, data);*/
158 } while(w
> pos
&& x
);
160 /*printf("%i<=%i<=%i: %i %i (%i)\n", prevw, pos, w,
161 abs(pos - prevw), abs(pos - w), (int)x);*/
163 /* Because <= is used instead of <, it opts to move the cursor to the
164 right when the exact centre of a character is clicked on. This only
165 matters for characters that are an odd number of pixels wide. */
166 if(prevw
- pos
<= pos
- w
) x
++;
168 if(x
== len
+ 1) x
--;
173 static void paint_edit_label(struct smode_t
*smode
,
174 struct widget_edit_t
*edit
, struct widget_t
*font
, int x
, int y
) {
178 width
= label_pos_to_width(edit
, font
);
179 height
= font_height(font
);
180 /*vlineRGBA(smode->screen, x + widget->pos->real.w + 1,
181 y, y + widget->pos->real.h, 255, 255, 255, 255);*/
182 /*printf("width=%i, height=%i, pos=(%i,%i)\n", width, height, x, y);*/
183 vlineRGBA(smode
->screen
, x
+ width
,
184 y
, y
+ height
, 255, 255, 255, 255);
187 static void paint_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
190 if(!widget
->p
.label
->label
) {
195 SDL_FillRect(xuni->smode->screen, &widget->pos->real,
196 SDL_MapRGB(xuni->smode->screen->format, 0, 0, 128));
199 get_label_image_pos(widget
->p
.label
->type
, &widget
->pos
->real
,
200 widget
->p
.label
->label
, &x
, &y
);
202 x
+= widget
->pos
->real
.x
;
203 y
+= widget
->pos
->real
.y
;
205 paint_label_clip(widget
->p
.label
->label
, xuni
->smode
->screen
,
206 x
, y
, widget
->pos
->clip
);
208 /* use xuni->gui->edit.datawidget instead of xuni->gui->active.widget? */
209 if(widget
->base
&& widget
->base
->type
== WIDGET_TEXTBOX
210 && xuni
->gui
->active
.widget
== widget
->base
) {
212 if(widget
->pos
->clip
) {
213 x
-= widget
->pos
->clip
->xclip
;
214 x
+= widget
->pos
->clip
->xoff
;
215 y
+= widget
->pos
->clip
->yoff
;
218 paint_edit_label(xuni
->smode
, &xuni
->gui
->edit
,
219 get_theme_widget(xuni
, widget
->p
.label
->font
), x
, y
);
223 void reposition_label_data(struct xuni_t
*xuni
, struct label_t
*label
,
224 struct widget_edit_t
*edit
, size_t pos
) {
226 int poswidth
= label_pos_to_width(edit
,
227 get_theme_widget(xuni
, label
->font
));
228 double boxwidth
= get_box_width(xuni
, xuni
->theme
->current
) / 100.0
229 * xuni
->smode
->width
;
230 int labelw
, offset
, newleft
, basewidth
;
232 /* !!! would use widget->p.label->label->w, but the label is not resized, nor pos->real.w set */
234 labelw
= font_string_width(
235 get_theme_widget(xuni
, label
->font
), label
->text
);
239 offset
= labelw
- edit
->datawidget
->base
->pos
->real
.w
+ boxwidth
* 2;
241 /*printf("reposition_label_data() offset=%i, poswidth=%i, labelw=%i\n",
242 offset, poswidth, labelw);*/
245 if(poswidth
< offset
) newleft
= poswidth
;
246 else newleft
= offset
;
249 /* all of the text in the textbox fits into one view */
253 basewidth
= edit
->datawidget
->base
->pos
->real
.w
- boxwidth
* 2;
255 /* If the new left position is out of range of the displayed one, set the
256 displayed left position so that newleft is visible.
258 if(poswidth
< edit
->datawidget
->base
->p
.textbox
->leftpos
) {
259 edit
->datawidget
->base
->p
.textbox
->leftpos
= poswidth
;
261 else if(poswidth
> edit
->datawidget
->base
->p
.textbox
->leftpos
264 edit
->datawidget
->base
->p
.textbox
->leftpos
= poswidth
- basewidth
;
267 /*poswidth = edit->leftpos;*/
269 if(offset
> edit
->datawidget
->base
->p
.textbox
->leftpos
) {
270 /*printf("offset by %i\n", offset - poswidth);*/
271 add_widget_clip(xuni
, edit
->datawidget
, 0, 0,
272 -(offset
- edit
->datawidget
->base
->p
.textbox
->leftpos
), 0, 0, 0);
276 add_widget_clip(xuni, edit->datawidget, 0, 0, offset, 0, 0, 0);
279 /*add_widget_clip(widget, width, 0, 0, 0, -width * 2, 0);*/
282 static void reposition_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
285 /* !!! hack to allow textbox scrolling */
286 if(/*widget->p.label->label &&*/ widget
->base
&& widget
->base
->pos
287 && (widget
->base
->type
== WIDGET_TEXTBOX
288 || widget
->base
->type
== WIDGET_PANEL
)) {
290 double width
= get_box_width(xuni
, xuni
->theme
->current
) / 100.0
291 * xuni
->smode
->width
;
294 /* !!! would use widget->p.label->label->w, but the label is not resized, nor pos->real.w set */
295 if(widget
->p
.label
->text
) {
296 labelw
= font_string_width(
297 get_theme_widget(xuni
, widget
->p
.label
->font
),
298 widget
->p
.label
->text
);
302 offset
= labelw
- widget
->base
->pos
->real
.w
+ width
* 2;
303 /*printf("base width: %i\n", widget->base->pos->real.w);
304 print_inline_widget_backtrace(widget);*/
305 if(widget
->base
->type
== WIDGET_TEXTBOX
) {
307 add_widget_clip(xuni
, widget
, 0, 0, offset
, 0, 0, 0);
310 add_widget_clip(xuni
, widget
, width
, 0, 0, 0, -width
* 2, 0);
313 if(offset
< 0) widget
->pos
->real
.w
= labelw
;
315 widget
->pos
->real
.w
= widget
->base
->pos
->real
.w
- width
* 2;
318 /*if(widget->base->type == WIDGET_TEXTBOX) {*/
319 if(widget
== xuni
->gui
->edit
.datawidget
) {
320 reposition_label_data(xuni
, xuni
->gui
->edit
.data
,
321 &xuni
->gui
->edit
, xuni
->gui
->edit
.pos
);
324 add_widget_clip(xuni, widget, 0, 0,
325 -widget->base->p.textbox->leftpos, 0, 0, 0);
329 /* !!! too small most likely */
330 /*widget->pos->real.h = font_height(widget->p.label->font);*/
334 static void rescale_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
336 static int count = 0;
338 printf("rescale_label() #%3i \"%s\"\n", ++count,
339 widget->p.label->text);
342 /*if(widget->p.label->font) {*/
344 free_surface(widget
->p
.label
->label
);
345 widget
->p
.label
->label
346 = render_text(get_theme_widget(xuni
, widget
->p
.label
->font
),
347 widget
->p
.label
->text
,
348 widget
->p
.label
->col
.r
,
349 widget
->p
.label
->col
.g
,
350 widget
->p
.label
->col
.b
);
352 /*widget->pos->scale.w
353 = widget->p.label->label->w * 100.0 / smode->width;
355 = widget->p.label->label->h * 100.0 / smode->height;*/
357 if(!widget
->pos
->scale
.w
&& !widget
->pos
->scale
.h
358 && widget
->p
.label
->label
) {
360 widget
->pos
->real
.w
= widget
->p
.label
->label
->w
;
361 widget
->pos
->real
.h
= widget
->p
.label
->label
->h
;
365 static void update_text_label(struct xuni_t
*xuni
, struct widget_t
*widget
) {
366 rescale_label(xuni
, widget
);