ltk

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/ltk.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
Log | Files | Refs | README | 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 = &ltk_label_draw,
     38 	.destroy = &ltk_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 = &ltk_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 }