diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/inputwidget.c | 11 | ||||
-rw-r--r-- | src/ui/labelwidget.c | 20 | ||||
-rw-r--r-- | src/ui/labelwidget.h | 14 | ||||
-rw-r--r-- | src/ui/text.c | 80 | ||||
-rw-r--r-- | src/ui/text.h | 3 | ||||
-rw-r--r-- | src/ui/widget.h | 1 |
6 files changed, 87 insertions, 42 deletions
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index de633e3c..bfb71913 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -291,12 +291,13 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
291 | static const iChar sensitiveChar_ = 0x25cf; /* black circle */ | 291 | static const iChar sensitiveChar_ = 0x25cf; /* black circle */ |
292 | 292 | ||
293 | static void draw_InputWidget_(const iInputWidget *d) { | 293 | static void draw_InputWidget_(const iInputWidget *d) { |
294 | const iWidget *w = constAs_Widget(d); | ||
294 | const uint32_t time = frameTime_Window(get_Window()); | 295 | const uint32_t time = frameTime_Window(get_Window()); |
295 | const iInt2 padding = init_I2(gap_UI / 2, gap_UI / 2); | 296 | const iInt2 padding = init_I2(gap_UI / 2, gap_UI / 2); |
296 | iRect bounds = adjusted_Rect(bounds_Widget(constAs_Widget(d)), padding, neg_I2(padding)); | 297 | iRect bounds = adjusted_Rect(bounds_Widget(w), padding, neg_I2(padding)); |
297 | const iBool isFocused = isFocused_Widget(constAs_Widget(d)); | 298 | const iBool isFocused = isFocused_Widget(w); |
298 | const iBool isHover = isHover_Widget(constAs_Widget(d)) && | 299 | const iBool isHover = isHover_Widget(w) && |
299 | contains_Widget(constAs_Widget(d), mouseCoord_Window(get_Window())); | 300 | contains_Widget(w, mouseCoord_Window(get_Window())); |
300 | iPaint p; | 301 | iPaint p; |
301 | init_Paint(&p); | 302 | init_Paint(&p); |
302 | iString text; | 303 | iString text; |
@@ -314,7 +315,7 @@ static void draw_InputWidget_(const iInputWidget *d) { | |||
314 | adjusted_Rect(bounds, neg_I2(one_I2()), zero_I2()), | 315 | adjusted_Rect(bounds, neg_I2(one_I2()), zero_I2()), |
315 | isFocused ? orange_ColorId : isHover ? cyan_ColorId : gray50_ColorId); | 316 | isFocused ? orange_ColorId : isHover ? cyan_ColorId : gray50_ColorId); |
316 | setClip_Paint(&p, bounds); | 317 | setClip_Paint(&p, bounds); |
317 | shrink_Rect(&bounds, init_I2(gap_UI * 2, 0)); | 318 | shrink_Rect(&bounds, init_I2(gap_UI * (flags_Widget(w) & tight_WidgetFlag ? 1 : 2), 0)); |
318 | const iInt2 emSize = advance_Text(d->font, "M"); | 319 | const iInt2 emSize = advance_Text(d->font, "M"); |
319 | const int textWidth = advance_Text(d->font, cstr_String(&text)).x; | 320 | const int textWidth = advance_Text(d->font, cstr_String(&text)).x; |
320 | const int cursorX = advanceN_Text(d->font, cstr_String(&text), d->cursor).x; | 321 | const int cursorX = advanceN_Text(d->font, cstr_String(&text), d->cursor).x; |
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index d3eaed11..c246c0c4 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c | |||
@@ -5,7 +5,9 @@ | |||
5 | #include "app.h" | 5 | #include "app.h" |
6 | #include "util.h" | 6 | #include "util.h" |
7 | 7 | ||
8 | iLocalDef iInt2 padding_(void) { return init_I2(3 * gap_UI, gap_UI); } | 8 | iLocalDef iInt2 padding_(int flags) { |
9 | return init_I2(flags & tight_WidgetFlag ? 3 * gap_UI / 2 : (3 * gap_UI), gap_UI); | ||
10 | } | ||
9 | 11 | ||
10 | struct Impl_LabelWidget { | 12 | struct Impl_LabelWidget { |
11 | iWidget widget; | 13 | iWidget widget; |
@@ -14,6 +16,7 @@ struct Impl_LabelWidget { | |||
14 | int key; | 16 | int key; |
15 | int kmods; | 17 | int kmods; |
16 | iString command; | 18 | iString command; |
19 | iBool alignVisual; /* align according to visible bounds, not typography */ | ||
17 | iClick click; | 20 | iClick click; |
18 | }; | 21 | }; |
19 | 22 | ||
@@ -191,13 +194,13 @@ static void draw_LabelWidget_(const iLabelWidget *d) { | |||
191 | } | 194 | } |
192 | setClip_Paint(&p, rect); | 195 | setClip_Paint(&p, rect); |
193 | if (flags & alignLeft_WidgetFlag) { | 196 | if (flags & alignLeft_WidgetFlag) { |
194 | draw_Text(d->font, add_I2(bounds.pos, padding_()), fg, cstr_String(&d->label)); | 197 | draw_Text(d->font, add_I2(bounds.pos, padding_(flags)), fg, cstr_String(&d->label)); |
195 | if ((flags & drawKey_WidgetFlag) && d->key) { | 198 | if ((flags & drawKey_WidgetFlag) && d->key) { |
196 | iString str; | 199 | iString str; |
197 | init_String(&str); | 200 | init_String(&str); |
198 | keyStr_LabelWidget_(d, &str); | 201 | keyStr_LabelWidget_(d, &str); |
199 | drawAlign_Text(uiShortcuts_FontId, | 202 | drawAlign_Text(uiShortcuts_FontId, |
200 | add_I2(topRight_Rect(bounds), negX_I2(padding_())), | 203 | add_I2(topRight_Rect(bounds), negX_I2(padding_(flags))), |
201 | flags & pressed_WidgetFlag ? fg : cyan_ColorId, | 204 | flags & pressed_WidgetFlag ? fg : cyan_ColorId, |
202 | right_Alignment, | 205 | right_Alignment, |
203 | cstr_String(&str)); | 206 | cstr_String(&str)); |
@@ -207,13 +210,13 @@ static void draw_LabelWidget_(const iLabelWidget *d) { | |||
207 | else if (flags & alignRight_WidgetFlag) { | 210 | else if (flags & alignRight_WidgetFlag) { |
208 | drawAlign_Text( | 211 | drawAlign_Text( |
209 | d->font, | 212 | d->font, |
210 | add_I2(topRight_Rect(bounds), negX_I2(padding_())), | 213 | add_I2(topRight_Rect(bounds), negX_I2(padding_(flags))), |
211 | fg, | 214 | fg, |
212 | right_Alignment, | 215 | right_Alignment, |
213 | cstr_String(&d->label)); | 216 | cstr_String(&d->label)); |
214 | } | 217 | } |
215 | else { | 218 | else { |
216 | drawCentered_Text(d->font, bounds, fg, cstr_String(&d->label)); | 219 | drawCentered_Text(d->font, bounds, d->alignVisual, fg, cstr_String(&d->label)); |
217 | } | 220 | } |
218 | clearClip_Paint(&p); | 221 | clearClip_Paint(&p); |
219 | } | 222 | } |
@@ -221,7 +224,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) { | |||
221 | void updateSize_LabelWidget(iLabelWidget *d) { | 224 | void updateSize_LabelWidget(iLabelWidget *d) { |
222 | iWidget *w = as_Widget(d); | 225 | iWidget *w = as_Widget(d); |
223 | const int flags = flags_Widget(w); | 226 | const int flags = flags_Widget(w); |
224 | iInt2 size = add_I2(measure_Text(d->font, cstr_String(&d->label)), muli_I2(padding_(), 2)); | 227 | iInt2 size = add_I2(measure_Text(d->font, cstr_String(&d->label)), muli_I2(padding_(flags), 2)); |
225 | if ((flags & drawKey_WidgetFlag) && d->key) { | 228 | if ((flags & drawKey_WidgetFlag) && d->key) { |
226 | iString str; | 229 | iString str; |
227 | init_String(&str); | 230 | init_String(&str); |
@@ -251,6 +254,7 @@ void init_LabelWidget(iLabelWidget *d, const char *label, int key, int kmods, co | |||
251 | d->kmods = kmods; | 254 | d->kmods = kmods; |
252 | init_Click(&d->click, d, !isEmpty_String(&d->command) ? SDL_BUTTON_LEFT : 0); | 255 | init_Click(&d->click, d, !isEmpty_String(&d->command) ? SDL_BUTTON_LEFT : 0); |
253 | setFlags_Widget(&d->widget, hover_WidgetFlag, d->click.button != 0); | 256 | setFlags_Widget(&d->widget, hover_WidgetFlag, d->click.button != 0); |
257 | d->alignVisual = iFalse; | ||
254 | updateSize_LabelWidget(d); | 258 | updateSize_LabelWidget(d); |
255 | } | 259 | } |
256 | 260 | ||
@@ -269,6 +273,10 @@ void setText_LabelWidget(iLabelWidget *d, const iString *text) { | |||
269 | updateSize_LabelWidget(d); | 273 | updateSize_LabelWidget(d); |
270 | } | 274 | } |
271 | 275 | ||
276 | void setAlignVisually_LabelWidget(iLabelWidget *d, iBool alignVisual) { | ||
277 | d->alignVisual = alignVisual; | ||
278 | } | ||
279 | |||
272 | void updateText_LabelWidget(iLabelWidget *d, const iString *text) { | 280 | void updateText_LabelWidget(iLabelWidget *d, const iString *text) { |
273 | set_String(&d->label, text); | 281 | set_String(&d->label, text); |
274 | refresh_Widget(&d->widget); | 282 | refresh_Widget(&d->widget); |
diff --git a/src/ui/labelwidget.h b/src/ui/labelwidget.h index 0563728e..aee853a5 100644 --- a/src/ui/labelwidget.h +++ b/src/ui/labelwidget.h | |||
@@ -7,16 +7,22 @@ | |||
7 | iDeclareWidgetClass(LabelWidget) | 7 | iDeclareWidgetClass(LabelWidget) |
8 | iDeclareObjectConstructionArgs(LabelWidget, const char *label, int key, int kmods, const char *command) | 8 | iDeclareObjectConstructionArgs(LabelWidget, const char *label, int key, int kmods, const char *command) |
9 | 9 | ||
10 | iLocalDef iLabelWidget *newEmpty_LabelWidget(void) { | ||
11 | return new_LabelWidget("", 0, 0, NULL); | ||
12 | } | ||
13 | |||
14 | void setFont_LabelWidget (iLabelWidget *, int fontId); | 10 | void setFont_LabelWidget (iLabelWidget *, int fontId); |
15 | void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ | 11 | void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ |
16 | void setTextCStr_LabelWidget (iLabelWidget *, const char *text); | 12 | void setTextCStr_LabelWidget (iLabelWidget *, const char *text); |
13 | void setAlignVisually_LabelWidget(iLabelWidget *, iBool alignVisual); | ||
17 | 14 | ||
18 | void updateSize_LabelWidget (iLabelWidget *); | 15 | void updateSize_LabelWidget (iLabelWidget *); |
19 | void updateText_LabelWidget (iLabelWidget *, const iString *text); /* not resized */ | 16 | void updateText_LabelWidget (iLabelWidget *, const iString *text); /* not resized */ |
20 | void updateTextCStr_LabelWidget (iLabelWidget *, const char *text); /* not resized */ | 17 | void updateTextCStr_LabelWidget (iLabelWidget *, const char *text); /* not resized */ |
21 | 18 | ||
22 | const iString *command_LabelWidget (const iLabelWidget *); | 19 | const iString *command_LabelWidget (const iLabelWidget *); |
20 | |||
21 | iLocalDef iLabelWidget *newEmpty_LabelWidget(void) { | ||
22 | return new_LabelWidget("", 0, 0, NULL); | ||
23 | } | ||
24 | iLocalDef iLabelWidget *newIcon_LabelWidget(const char *label, int key, int kmods, const char *command) { | ||
25 | iLabelWidget *d = new_LabelWidget(label, key, kmods, command); | ||
26 | setAlignVisually_LabelWidget(d, iTrue); | ||
27 | return d; | ||
28 | } | ||
diff --git a/src/ui/text.c b/src/ui/text.c index 1b483952..50b3bbab 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -23,6 +23,8 @@ iDeclareType(Font) | |||
23 | iDeclareType(Glyph) | 23 | iDeclareType(Glyph) |
24 | iDeclareTypeConstructionArgs(Glyph, iChar ch) | 24 | iDeclareTypeConstructionArgs(Glyph, iChar ch) |
25 | 25 | ||
26 | int enableHalfPixelGlyphs_Text = iTrue; /* debug setting */ | ||
27 | |||
26 | struct Impl_Glyph { | 28 | struct Impl_Glyph { |
27 | iHashNode node; | 29 | iHashNode node; |
28 | const iFont *font; /* may come from symbols/emoji */ | 30 | const iFont *font; /* may come from symbols/emoji */ |
@@ -189,7 +191,7 @@ void deinit_Text(void) { | |||
189 | iRelease(d->ansiEscape); | 191 | iRelease(d->ansiEscape); |
190 | } | 192 | } |
191 | 193 | ||
192 | iFont *font_Text_(enum iFontId id) { | 194 | iLocalDef iFont *font_Text_(enum iFontId id) { |
193 | return &text_.fonts[id]; | 195 | return &text_.fonts[id]; |
194 | } | 196 | } |
195 | 197 | ||
@@ -306,7 +308,13 @@ static const iGlyph *glyph_Font_(iFont *d, iChar ch) { | |||
306 | return glyph; | 308 | return glyph; |
307 | } | 309 | } |
308 | 310 | ||
309 | enum iRunMode { measure_RunMode, measureNoWrap_RunMode, draw_RunMode, drawPermanentColor_RunMode }; | 311 | enum iRunMode { |
312 | measure_RunMode, | ||
313 | measureNoWrap_RunMode, | ||
314 | measureVisual_RunMode, /* actual visible bounding box of the glyph, e.g., for icons */ | ||
315 | draw_RunMode, | ||
316 | drawPermanentColor_RunMode | ||
317 | }; | ||
310 | 318 | ||
311 | static iChar nextChar_(const char **chPos, const char *end) { | 319 | static iChar nextChar_(const char **chPos, const char *end) { |
312 | if (*chPos == end) { | 320 | if (*chPos == end) { |
@@ -322,8 +330,6 @@ static iChar nextChar_(const char **chPos, const char *end) { | |||
322 | return ch; | 330 | return ch; |
323 | } | 331 | } |
324 | 332 | ||
325 | int enableHalfPixelGlyphs_Text = iTrue; | ||
326 | |||
327 | iLocalDef iBool isWrapBoundary_(iChar a, iChar b) { | 333 | iLocalDef iBool isWrapBoundary_(iChar a, iChar b) { |
328 | if (b == '/' || b == '-' || b == ',' || b == ';' || b == ':') { | 334 | if (b == '/' || b == '-' || b == ',' || b == ';' || b == ':') { |
329 | return iTrue; | 335 | return iTrue; |
@@ -331,13 +337,18 @@ iLocalDef iBool isWrapBoundary_(iChar a, iChar b) { | |||
331 | return !isSpace_Char(a) && isSpace_Char(b); | 337 | return !isSpace_Char(a) && isSpace_Char(b); |
332 | } | 338 | } |
333 | 339 | ||
334 | static iInt2 run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLen, iInt2 pos, | 340 | iLocalDef iBool isMeasuring_(enum iRunMode mode) { |
341 | return mode == measure_RunMode || mode == measureNoWrap_RunMode || | ||
342 | mode == measureVisual_RunMode; | ||
343 | } | ||
344 | |||
345 | static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLen, iInt2 pos, | ||
335 | int xposLimit, const char **continueFrom_out, int *runAdvance_out) { | 346 | int xposLimit, const char **continueFrom_out, int *runAdvance_out) { |
336 | iInt2 size = zero_I2(); | 347 | iRect bounds = zero_Rect(); |
337 | const iInt2 orig = pos; | 348 | const iInt2 orig = pos; |
338 | float xpos = pos.x; | 349 | float xpos = pos.x; |
339 | float xposMax = xpos; | 350 | float xposMax = xpos; |
340 | iAssert(xposLimit == 0 || mode == measure_RunMode || mode == measureNoWrap_RunMode); | 351 | iAssert(xposLimit == 0 || isMeasuring_(mode)); |
341 | const char *lastWordEnd = text.start; | 352 | const char *lastWordEnd = text.start; |
342 | if (continueFrom_out) { | 353 | if (continueFrom_out) { |
343 | *continueFrom_out = text.end; | 354 | *continueFrom_out = text.end; |
@@ -386,13 +397,24 @@ static iInt2 run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe | |||
386 | *continueFrom_out = lastWordEnd; | 397 | *continueFrom_out = lastWordEnd; |
387 | break; | 398 | break; |
388 | } | 399 | } |
389 | size.x = iMax(size.x, x2 - orig.x); | 400 | const SDL_Rect dst = { x1 + glyph->d[hoff].x, |
390 | size.y = iMax(size.y, pos.y + glyph->font->height - orig.y); | 401 | pos.y + glyph->font->baseline + glyph->d[hoff].y, |
391 | if (mode != measure_RunMode && mode != measureNoWrap_RunMode) { | 402 | glyph->rect[hoff].size.x, |
392 | SDL_Rect dst = { x1 + glyph->d[hoff].x, | 403 | glyph->rect[hoff].size.y }; |
393 | pos.y + glyph->font->baseline + glyph->d[hoff].y, | 404 | /* Update the bounding box. */ |
394 | glyph->rect[hoff].size.x, | 405 | if (mode == measureVisual_RunMode) { |
395 | glyph->rect[hoff].size.y }; | 406 | if (isEmpty_Rect(bounds)) { |
407 | bounds = init_Rect(dst.x, dst.y, dst.w, dst.h); | ||
408 | } | ||
409 | else { | ||
410 | bounds = union_Rect(bounds, init_Rect(dst.x, dst.y, dst.w, dst.h)); | ||
411 | } | ||
412 | } | ||
413 | else { | ||
414 | bounds.size.x = iMax(bounds.size.x, x2 - orig.x); | ||
415 | bounds.size.y = iMax(bounds.size.y, pos.y + glyph->font->height - orig.y); | ||
416 | } | ||
417 | if (!isMeasuring_(mode)) { | ||
396 | SDL_RenderCopy(text_.render, text_.cache, (const SDL_Rect *) &glyph->rect[hoff], &dst); | 418 | SDL_RenderCopy(text_.render, text_.cache, (const SDL_Rect *) &glyph->rect[hoff], &dst); |
397 | } | 419 | } |
398 | xpos += glyph->advance; | 420 | xpos += glyph->advance; |
@@ -421,7 +443,7 @@ static iInt2 run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe | |||
421 | if (runAdvance_out) { | 443 | if (runAdvance_out) { |
422 | *runAdvance_out = xposMax - orig.x; | 444 | *runAdvance_out = xposMax - orig.x; |
423 | } | 445 | } |
424 | return size; | 446 | return bounds; |
425 | } | 447 | } |
426 | 448 | ||
427 | int lineHeight_Text(int fontId) { | 449 | int lineHeight_Text(int fontId) { |
@@ -439,7 +461,12 @@ iInt2 measureRange_Text(int fontId, iRangecc text) { | |||
439 | zero_I2(), | 461 | zero_I2(), |
440 | 0, | 462 | 0, |
441 | NULL, | 463 | NULL, |
442 | NULL); | 464 | NULL).size; |
465 | } | ||
466 | |||
467 | iRect visualBounds_Text(int fontId, iRangecc text) { | ||
468 | return run_Font_( | ||
469 | font_Text_(fontId), measureVisual_RunMode, text, iInvalidSize, zero_I2(), 0, NULL, NULL); | ||
443 | } | 470 | } |
444 | 471 | ||
445 | iInt2 measure_Text(int fontId, const char *text) { | 472 | iInt2 measure_Text(int fontId, const char *text) { |
@@ -456,7 +483,7 @@ iInt2 advanceRange_Text(int fontId, iRangecc text) { | |||
456 | 0, | 483 | 0, |
457 | NULL, | 484 | NULL, |
458 | &advance) | 485 | &advance) |
459 | .y; | 486 | .size.y; |
460 | return init_I2(advance, height); | 487 | return init_I2(advance, height); |
461 | } | 488 | } |
462 | 489 | ||
@@ -470,7 +497,7 @@ iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) | |||
470 | width, | 497 | width, |
471 | endPos, | 498 | endPos, |
472 | &advance) | 499 | &advance) |
473 | .y; | 500 | .size.y; |
474 | return init_I2(advance, height); | 501 | return init_I2(advance, height); |
475 | } | 502 | } |
476 | 503 | ||
@@ -484,7 +511,7 @@ iInt2 tryAdvanceNoWrap_Text(int fontId, iRangecc text, int width, const char **e | |||
484 | width, | 511 | width, |
485 | endPos, | 512 | endPos, |
486 | &advance) | 513 | &advance) |
487 | .y; | 514 | .size.y; |
488 | return init_I2(advance, height); | 515 | return init_I2(advance, height); |
489 | } | 516 | } |
490 | 517 | ||
@@ -530,7 +557,7 @@ void drawAlign_Text(int fontId, iInt2 pos, int color, enum iAlignment align, con | |||
530 | else if (align == right_Alignment) { | 557 | else if (align == right_Alignment) { |
531 | pos.x -= measure_Text(fontId, cstr_Block(&chars)).x; | 558 | pos.x -= measure_Text(fontId, cstr_Block(&chars)).x; |
532 | } | 559 | } |
533 | draw_Text_(fontId, pos, color, (iRangecc){ constBegin_Block(&chars), constEnd_Block(&chars) }); | 560 | draw_Text_(fontId, pos, color, range_Block(&chars)); |
534 | deinit_Block(&chars); | 561 | deinit_Block(&chars); |
535 | } | 562 | } |
536 | 563 | ||
@@ -542,7 +569,7 @@ void draw_Text(int fontId, iInt2 pos, int color, const char *text, ...) { | |||
542 | vprintf_Block(&chars, text, args); | 569 | vprintf_Block(&chars, text, args); |
543 | va_end(args); | 570 | va_end(args); |
544 | } | 571 | } |
545 | draw_Text_(fontId, pos, color, (iRangecc){ constBegin_Block(&chars), constEnd_Block(&chars) }); | 572 | draw_Text_(fontId, pos, color, range_Block(&chars)); |
546 | deinit_Block(&chars); | 573 | deinit_Block(&chars); |
547 | } | 574 | } |
548 | 575 | ||
@@ -550,7 +577,7 @@ void drawString_Text(int fontId, iInt2 pos, int color, const iString *text) { | |||
550 | draw_Text_(fontId, pos, color, range_String(text)); | 577 | draw_Text_(fontId, pos, color, range_String(text)); |
551 | } | 578 | } |
552 | 579 | ||
553 | void drawCentered_Text(int fontId, iRect rect, int color, const char *format, ...) { | 580 | void drawCentered_Text(int fontId, iRect rect, iBool alignVisual, int color, const char *format, ...) { |
554 | iBlock chars; | 581 | iBlock chars; |
555 | init_Block(&chars, 0); { | 582 | init_Block(&chars, 0); { |
556 | va_list args; | 583 | va_list args; |
@@ -558,10 +585,11 @@ void drawCentered_Text(int fontId, iRect rect, int color, const char *format, .. | |||
558 | vprintf_Block(&chars, format, args); | 585 | vprintf_Block(&chars, format, args); |
559 | va_end(args); | 586 | va_end(args); |
560 | } | 587 | } |
561 | const char *text = cstr_Block(&chars); | 588 | const iRangecc text = range_Block(&chars); |
562 | iInt2 textSize = advance_Text(fontId, text); | 589 | iRect textBounds = alignVisual ? visualBounds_Text(fontId, text) |
563 | draw_Text_(fontId, sub_I2(mid_Rect(rect), divi_I2(textSize, 2)), color, | 590 | : (iRect){ zero_I2(), advanceRange_Text(fontId, text) }; |
564 | (iRangecc){ constBegin_Block(&chars), constEnd_Block(&chars) }); | 591 | textBounds.pos = sub_I2(mid_Rect(rect), mid_Rect(textBounds)); |
592 | draw_Text_(fontId, textBounds.pos, color, text); | ||
565 | deinit_Block(&chars); | 593 | deinit_Block(&chars); |
566 | } | 594 | } |
567 | 595 | ||
diff --git a/src/ui/text.h b/src/ui/text.h index 95d49fda..f165c5b4 100644 --- a/src/ui/text.h +++ b/src/ui/text.h | |||
@@ -50,6 +50,7 @@ void deinit_Text (void); | |||
50 | int lineHeight_Text (int fontId); | 50 | int lineHeight_Text (int fontId); |
51 | iInt2 measure_Text (int fontId, const char *text); | 51 | iInt2 measure_Text (int fontId, const char *text); |
52 | iInt2 measureRange_Text (int fontId, iRangecc text); | 52 | iInt2 measureRange_Text (int fontId, iRangecc text); |
53 | iRect visualBounds_Text (int fontId, iRangecc text); | ||
53 | iInt2 advance_Text (int fontId, const char *text); | 54 | iInt2 advance_Text (int fontId, const char *text); |
54 | iInt2 advanceN_Text (int fontId, const char *text, size_t n); /* `n` in characters */ | 55 | iInt2 advanceN_Text (int fontId, const char *text, size_t n); /* `n` in characters */ |
55 | iInt2 advanceRange_Text (int fontId, iRangecc text); | 56 | iInt2 advanceRange_Text (int fontId, iRangecc text); |
@@ -65,7 +66,7 @@ enum iAlignment { | |||
65 | 66 | ||
66 | void draw_Text (int fontId, iInt2 pos, int color, const char *text, ...); | 67 | void draw_Text (int fontId, iInt2 pos, int color, const char *text, ...); |
67 | void drawAlign_Text (int fontId, iInt2 pos, int color, enum iAlignment align, const char *text, ...); | 68 | void drawAlign_Text (int fontId, iInt2 pos, int color, enum iAlignment align, const char *text, ...); |
68 | void drawCentered_Text (int fontId, iRect rect, int color, const char *text, ...); | 69 | void drawCentered_Text (int fontId, iRect rect, iBool alignVisual, int color, const char *text, ...); |
69 | void drawString_Text (int fontId, iInt2 pos, int color, const iString *text); | 70 | void drawString_Text (int fontId, iInt2 pos, int color, const iString *text); |
70 | 71 | ||
71 | SDL_Texture * glyphCache_Text (void); | 72 | SDL_Texture * glyphCache_Text (void); |
diff --git a/src/ui/widget.h b/src/ui/widget.h index 10e24678..7208a755 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h | |||
@@ -32,6 +32,7 @@ enum iWidgetFlag { | |||
32 | frameless_WidgetFlag = iBit(8), | 32 | frameless_WidgetFlag = iBit(8), |
33 | drawKey_WidgetFlag = iBit(10), | 33 | drawKey_WidgetFlag = iBit(10), |
34 | focusable_WidgetFlag = iBit(11), | 34 | focusable_WidgetFlag = iBit(11), |
35 | tight_WidgetFlag = iBit(31), /* smaller padding */ | ||
35 | keepOnTop_WidgetFlag = iBit(12), /* gets events first; drawn last */ | 36 | keepOnTop_WidgetFlag = iBit(12), /* gets events first; drawn last */ |
36 | arrangeHorizontal_WidgetFlag = iBit(17), /* arrange children horizontally */ | 37 | arrangeHorizontal_WidgetFlag = iBit(17), /* arrange children horizontally */ |
37 | arrangeVertical_WidgetFlag = iBit(18), /* arrange children vertically */ | 38 | arrangeVertical_WidgetFlag = iBit(18), /* arrange children vertically */ |