label.c - ltk - GUI toolkit for X11 (WIP)
HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
HTML git clone https://lumidify.org/ltk.git (encrypted, but very slow)
HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
label.c (4690B)
---
1 /*
2 * Copyright (c) 2021-2024 lumidify <nobody@lumidify.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <stddef.h>
18
19 #include "config.h"
20 #include "memory.h"
21 #include "color.h"
22 #include "rect.h"
23 #include "widget.h"
24 #include "ltk.h"
25 #include "util.h"
26 #include "text.h"
27 #include "label.h"
28 #include "graphics.h"
29
30 #define MAX_LABEL_PADDING 50000
31
32 static void ltk_label_draw(ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk_rect clip);
33 static void ltk_label_destroy(ltk_widget *self, int shallow);
34 static void ltk_label_recalc_ideal_size(ltk_widget *self);
35
36 static struct ltk_widget_vtable vtable = {
37 .draw = <k_label_draw,
38 .destroy = <k_label_destroy,
39 .hide = NULL,
40 .resize = NULL,
41 .change_state = NULL,
42 .child_size_change = NULL,
43 .remove_child = NULL,
44 .get_child_at_pos = NULL,
45 .key_press = NULL,
46 .key_release = NULL,
47 .mouse_press = NULL,
48 .mouse_release = NULL,
49 .motion_notify = NULL,
50 .mouse_leave = NULL,
51 .mouse_enter = NULL,
52 .recalc_ideal_size = <k_label_recalc_ideal_size,
53 .type = LTK_WIDGET_LABEL,
54 .flags = LTK_NEEDS_REDRAW | LTK_ACTIVATABLE_SPECIAL,
55 .invalid_signal = LTK_LABEL_SIGNAL_INVALID
56 };
57
58 static struct {
59 ltk_color *text_color;
60 ltk_color *bg_color;
61 ltk_color *bg_color_active;
62 char *font;
63 ltk_size pad;
64 ltk_size font_size;
65 } theme;
66
67 static ltk_theme_parseinfo parseinfo[] = {
68 {"bg-color", THEME_COLOR, {.color = &theme.bg_color}, {.color = "#000000"}, 0, 0, 0},
69 {"bg-color-active", THEME_COLOR, {.color = &theme.bg_color_active}, {.color = "#222222"}, 0, 0, 0},
70 {"pad", THEME_SIZE, {.size = &theme.pad}, {.size = {.val = 100, .unit = LTK_UNIT_MM}}, 0, MAX_LABEL_PADDING, 0},
71 {"text-color", THEME_COLOR, {.color = &theme.text_color}, {.color = "#FFFFFF"}, 0, 0, 0},
72 {"font-size", THEME_SIZE, {.size = &theme.font_size}, {.size = {.val = 1200, .unit = LTK_UNIT_PT}}, 0, 20000, 0},
73 {"font", THEME_STRING, {.str = &theme.font}, {.str = "Monospace"}, 0, 0, 0},
74 };
75
76 void
77 ltk_label_get_theme_parseinfo(ltk_theme_parseinfo **p, size_t *len) {
78 *p = parseinfo;
79 *len = LENGTH(parseinfo);
80 }
81
82 static void
83 ltk_label_draw(ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk_rect clip) {
84 ltk_label *label = LTK_CAST_LABEL(self);
85 ltk_rect lrect = self->lrect;
86 ltk_rect clip_final = ltk_rect_intersect(clip, (ltk_rect){0, 0, lrect.w, lrect.h});
87 if (clip_final.w <= 0 || clip_final.h <= 0)
88 return;
89 ltk_rect draw_clip = {x + clip_final.x, y + clip_final.y, clip_final.w, clip_final.h};
90 ltk_surface_fill_rect(draw_surf, (self->state & LTK_ACTIVE) ? theme.bg_color_active : theme.bg_color, draw_clip);
91
92 int text_w, text_h;
93 ltk_text_line_get_size(label->tl, &text_w, &text_h);
94 int text_x = x + (lrect.w - text_w) / 2;
95 int text_y = y + (lrect.h - text_h) / 2;
96 ltk_text_line_draw_clipped(label->tl, draw_surf, theme.text_color, text_x, text_y, draw_clip);
97 }
98
99 static void
100 recalc_ideal_size(ltk_label *label) {
101 int text_w, text_h;
102 ltk_text_line_get_size(label->tl, &text_w, &text_h);
103 int pad = ltk_size_to_pixel(theme.pad, LTK_CAST_WIDGET(label)->last_dpi);
104 label->widget.ideal_w = text_w + pad * 2;
105 label->widget.ideal_h = text_h + pad * 2;
106 }
107
108 static void
109 ltk_label_recalc_ideal_size(ltk_widget *self) {
110 ltk_label *label = LTK_CAST_LABEL(self);
111 int font_size = ltk_size_to_pixel(theme.font_size, self->last_dpi);
112 ltk_text_line_set_font_size(label->tl, font_size);
113 recalc_ideal_size(label);
114 }
115
116 ltk_label *
117 ltk_label_create(ltk_window *window, const char *text) {
118 ltk_label *label = ltk_malloc(sizeof(ltk_label));
119
120 ltk_fill_widget_defaults(LTK_CAST_WIDGET(label), window, &vtable, 0, 0);
121 label->tl = ltk_text_line_create_const_text_default(
122 theme.font, ltk_size_to_pixel(theme.font_size, label->widget.last_dpi), text, -1
123 );
124 recalc_ideal_size(label);
125
126 return label;
127 }
128
129 static void
130 ltk_label_destroy(ltk_widget *self, int shallow) {
131 (void)shallow;
132 ltk_label *label = LTK_CAST_LABEL(self);
133 if (!label) {
134 ltk_warn("Tried to destroy NULL label.\n");
135 return;
136 }
137 ltk_text_line_destroy(label->tl);
138 ltk_free(label);
139 }