commit 700df2e2739b914fa2738404f949f791814cf7d4
parent 2845e91cce752793dfebfac761c4b1ae7c25b023
Author: lumidify <nobody@lumidify.org>
Date: Wed, 6 Jan 2021 21:54:20 +0100
Add label widget
Diffstat:
15 files changed, 246 insertions(+), 12 deletions(-)
diff --git a/.ltk/theme.ini b/.ltk/theme.ini
@@ -17,3 +17,7 @@ border_active = #FFFFFF
fill_active = #738194
border_disabled = #FFFFFF
fill_disabled = #292929
+
+[label]
+text_color = #FFFFFF
+pad = 5
diff --git a/LICENSE b/LICENSE
@@ -4,7 +4,7 @@ See khash.h, ini.*, stb_truetype.*, and strtonum.c for third-party licenses.
MIT/X Consortium License
The Lumidify ToolKit (LTK)
-Copyright (c) 2016, 2017, 2018, 2019, 2020 lumidify <nobody@lumidify.org>
+Copyright (c) 2016-2021 lumidify <nobody@lumidify.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Makefile b/Makefile
@@ -1,6 +1,6 @@
include config.mk
-OBJ += color.o util.o ltkd.o ini.o grid.o button.o draw.o
+OBJ += color.o util.o ltkd.o ini.o grid.o button.o label.o draw.o
all: ltkd ltkc
diff --git a/TODO b/TODO
@@ -1,3 +1,5 @@
+Double-buffering; general improvements to rendering...
+
Convert points to pixels for stb rendering (currently, the size between
pango and stb is completely different).
diff --git a/button.c b/button.c
@@ -30,6 +30,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include "color.h"
#include "ltk.h"
#include "util.h"
#include "text.h"
diff --git a/color.h b/color.h
@@ -1,5 +1,8 @@
#include "defs.h"
+#ifndef _LTK_COLOR_H_
+#define _LTK_COLOR_H_
+
#ifdef USE_XFT
#include <X11/Xft/Xft.h>
#endif
@@ -10,3 +13,5 @@ typedef struct {
XftColor xftcolor;
#endif
} LtkColor;
+
+#endif /* _LTK_COLOR_H_ */
diff --git a/draw.c b/draw.c
@@ -29,6 +29,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include "color.h"
#include "ltk.h"
#include "util.h"
#include "draw.h"
diff --git a/grid.c b/grid.c
@@ -31,6 +31,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include "color.h"
#include "ltk.h"
#include "util.h"
#include "grid.h"
diff --git a/label.c b/label.c
@@ -0,0 +1,155 @@
+/*
+ * This file is part of the Lumidify ToolKit (LTK)
+ * Copyright (c) 2021 lumidify <nobody@lumidify.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "color.h"
+#include "ltk.h"
+#include "util.h"
+#include "text.h"
+#include "label.h"
+
+static void ltk_label_draw(ltk_label *label);
+static ltk_label *ltk_label_create(ltk_window *window,
+ const char *id, const char *text);
+static void ltk_label_destroy(ltk_label *label, int shallow);
+
+static struct {
+ LtkColor text_color;
+ int pad;
+} theme;
+
+void
+ltk_label_setup_theme_defaults(ltk_window *window) {
+ theme.pad = 5;
+ ltk_color_create(window->dpy, window->screen, window->cm,
+ "#FFFFFF", &theme.text_color);
+}
+
+void
+ltk_label_ini_handler(ltk_window *window, const char *prop, const char *value) {
+ if (strcmp(prop, "pad") == 0) {
+ theme.pad = atoi(value);
+ } else if (strcmp(prop, "text_color") == 0) {
+ ltk_color_create(window->dpy, window->screen, window->cm,
+ value, &theme.text_color);
+ } else {
+ ltk_warn("Unknown property \"%s\" for label style.\n", prop);
+ }
+}
+
+static void
+ltk_label_draw(ltk_label *label) {
+ ltk_window *window = label->widget.window;
+ ltk_rect rect = label->widget.rect;
+
+ int text_w, text_h;
+ ltk_text_line_get_size(label->tl, &text_w, &text_h);
+ int text_x = rect.x + (rect.w - text_w) / 2;
+ int text_y = rect.y + (rect.h - text_h) / 2;
+ ltk_text_line_draw(label->tl, window->gc, text_x, text_y);
+}
+
+static ltk_label *
+ltk_label_create(ltk_window *window, const char *id, const char *text) {
+ char *text_copy;
+ ltk_label *label = malloc(sizeof(ltk_label));
+ if (!label) ltk_fatal_errno("Unable to allocate memory for ltk_label.\n");
+
+ ltk_fill_widget_defaults(&label->widget, id, window,
+ <k_label_draw, NULL, <k_label_destroy, 1, LTK_LABEL);
+ uint16_t font_size = window->theme.font_size;
+ text_copy = strdup(text);
+ if (!text_copy)
+ ltk_fatal_errno("Unable to allocate label text.\n");
+ label->tl = ltk_text_line_create(window->xwindow, font_size, text_copy, -1);
+ int text_w, text_h;
+ ltk_text_line_get_size(label->tl, &text_w, &text_h);
+ label->widget.rect.w = text_w + theme.pad * 2;
+ label->widget.rect.h = text_h + theme.pad * 2;
+ ltk_text_line_render(label->tl, &window->theme.bg, &theme.text_color);
+
+ return label;
+}
+
+static void
+ltk_label_destroy(ltk_label *label, int shallow) {
+ if (!label) {
+ ltk_warn("Tried to destroy NULL label.\n");
+ return;
+ }
+ ltk_text_line_destroy(label->tl);
+ ltk_remove_widget(label->widget.window, label->widget.id);
+ free(label->widget.id);
+ free(label);
+}
+
+/* label <label id> create <text> */
+static int
+ltk_label_cmd_create(
+ ltk_window *window,
+ char **tokens,
+ size_t num_tokens,
+ char **errstr) {
+ ltk_label *label;
+ if (num_tokens != 4) {
+ *errstr = "Invalid number of arguments.\n";
+ return 1;
+ }
+ if (!ltk_widget_id_free(tokens[1])) {
+ *errstr = "Widget ID already taken.\n";
+ return 1;
+ }
+ label = ltk_label_create(window, tokens[1], tokens[3]);
+ ltk_set_widget(label, tokens[1]);
+
+ return 0;
+}
+
+/* label <button id> <command> ... */
+int
+ltk_label_cmd(
+ ltk_window *window,
+ char **tokens,
+ size_t num_tokens,
+ char **errstr) {
+ if (num_tokens < 3) {
+ *errstr = "Invalid number of arguments.\n";
+ return 1;
+ }
+ if (strcmp(tokens[2], "create") == 0) {
+ return ltk_label_cmd_create(window, tokens, num_tokens, errstr);
+ } else {
+ *errstr = "Invalid command.\n";
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/label.h b/label.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the Lumidify ToolKit (LTK)
+ * Copyright (c) 2021 lumidify <nobody@lumidify.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _LTK_LABEL_H_
+#define _LTK_LABEL_H_
+
+/* Requires the following includes: <X11/Xlib.h>, "ltk.h", "color.h", "text.h" */
+
+typedef struct {
+ ltk_widget widget;
+ LtkTextLine *tl;
+ Pixmap text_pixmap;
+} ltk_label;
+
+void ltk_label_setup_theme_defaults(ltk_window *window);
+void ltk_label_ini_handler(ltk_window *window, const char *prop, const char *value);
+
+int ltk_label_cmd(
+ ltk_window *window,
+ char **tokens,
+ size_t num_tokens,
+ char **errstr);
+
+#endif /* _LTK_LABEL_H_ */
diff --git a/ltk.h b/ltk.h
@@ -57,6 +57,7 @@ typedef enum {
LTK_GRID,
LTK_BUTTON,
LTK_DRAW,
+ LTK_LABEL,
LTK_WIDGET
} ltk_widget_type;
@@ -96,8 +97,8 @@ typedef struct {
int border_width;
uint16_t font_size;
char *font;
- XColor fg;
- XColor bg;
+ LtkColor fg;
+ LtkColor bg;
} ltk_window_theme;
struct ltk_event_queue {
diff --git a/ltkd.c b/ltkd.c
@@ -1,6 +1,8 @@
+/* FIXME: error checking in tokenizer (is this necessary?) */
+/* FIXME: parsing doesn't work properly with bs? */
/*
* This file is part of the Lumidify ToolKit (LTK)
- * Copyright (c) 2016, 2017, 2018, 2020 lumidify <nobody@lumidify.org>
+ * Copyright (c) 2016, 2017, 2018, 2020, 2021 lumidify <nobody@lumidify.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -42,12 +44,14 @@
#include "ini.h"
#include "khash.h"
+#include "color.h"
#include "ltk.h"
#include "util.h"
#include "text.h"
#include "grid.h"
#include "draw.h"
#include "button.h"
+#include "label.h"
#define MAX_SOCK_CONNS 20
#define READ_BLK_SIZE 128
@@ -579,10 +583,10 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int
window->xwindow =
XCreateSimpleWindow(window->dpy, DefaultRootWindow(window->dpy), x, y,
w, h, window->theme.border_width,
- window->theme.fg.pixel, window->theme.bg.pixel);
+ window->theme.fg.xcolor.pixel, window->theme.bg.xcolor.pixel);
window->gc = XCreateGC(window->dpy, window->xwindow, 0, 0);
- XSetForeground(window->dpy, window->gc, window->theme.fg.pixel);
- XSetBackground(window->dpy, window->gc, window->theme.bg.pixel);
+ XSetForeground(window->dpy, window->gc, window->theme.fg.xcolor.pixel);
+ XSetBackground(window->dpy, window->gc, window->theme.bg.xcolor.pixel);
XSetStandardProperties(window->dpy, window->xwindow, title, NULL, None,
NULL, 0, NULL);
XSetWMProtocols(window->dpy, window->xwindow, &window->wm_delete_msg, 1);
@@ -639,9 +643,11 @@ ltk_window_ini_handler(ltk_window *window, const char *prop, const char *value)
if (strcmp(prop, "border_width") == 0) {
window->theme.border_width = atoi(value);
} else if (strcmp(prop, "bg") == 0) {
- ltk_create_xcolor(window, value, &window->theme.bg);
+ ltk_color_create(window->dpy, window->screen,
+ window->cm, value, &window->theme.bg);
} else if (strcmp(prop, "fg") == 0) {
- ltk_create_xcolor(window, value, &window->theme.fg);
+ ltk_color_create(window->dpy, window->screen,
+ window->cm, value, &window->theme.fg);
} else if (strcmp(prop, "font") == 0) {
window->theme.font = strdup(value);
if (!window->theme.font)
@@ -657,6 +663,8 @@ ltk_ini_handler(void *window, const char *widget, const char *prop, const char *
ltk_window_ini_handler(window, prop, value);
} else if (strcmp(widget, "button") == 0) {
ltk_button_ini_handler(window, prop, value);
+ } else if (strcmp(widget, "label") == 0) {
+ ltk_label_ini_handler(window, prop, value);
} else {
return 0;
}
@@ -668,8 +676,10 @@ ltk_window_setup_theme_defaults(ltk_window *window) {
window->theme.border_width = 0;
window->theme.font_size = 15;
window->theme.font = "Liberation Mono";
- ltk_create_xcolor(window, "#000000", &window->theme.bg);
- ltk_create_xcolor(window, "#FFFFFF", &window->theme.fg);
+ ltk_color_create(window->dpy, window->screen,
+ window->cm, "#000000", &window->theme.bg);
+ ltk_color_create(window->dpy, window->screen,
+ window->cm, "#FFFFFF", &window->theme.fg);
}
static void
@@ -677,6 +687,7 @@ ltk_load_theme(ltk_window *window, const char *path) {
/* FIXME: Error checking, especially when creating colors! */
ltk_window_setup_theme_defaults(window);
ltk_button_setup_theme_defaults(window);
+ ltk_label_setup_theme_defaults(window);
if (ini_parse(path, ltk_ini_handler, window) < 0) {
ltk_warn("Can't load theme.\n");
}
@@ -1132,6 +1143,8 @@ process_commands(ltk_window *window, struct ltk_sock_info *sock) {
err = ltk_grid_cmd(window, tokens, num_tokens, &errstr);
} else if (strcmp(tokens[0], "button") == 0) {
err = ltk_button_cmd(window, tokens, num_tokens, &errstr);
+ } else if (strcmp(tokens[0], "label") == 0) {
+ err = ltk_label_cmd(window, tokens, num_tokens, &errstr);
} else if (strcmp(tokens[0], "set-root-widget") == 0) {
err = ltk_set_root_widget_cmd(window, tokens, num_tokens, &errstr);
} else if (strcmp(tokens[0], "draw") == 0) {
diff --git a/strtonum.c b/strtonum.c
@@ -63,4 +63,5 @@ strtonum(const char *numstr, long long minval, long long maxval,
return (ll);
}
+/* FIXME: What does this do? - lumidify */
DEF_WEAK(strtonum);
diff --git a/text.h b/text.h
@@ -1,6 +1,9 @@
#include "defs.h"
#include "color.h"
+#ifndef _LTK_TEXT_H_
+#define _LTK_TEXT_H_
+
typedef struct LtkTextLine LtkTextLine;
void ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm);
@@ -15,3 +18,5 @@ void ltk_text_line_destroy(LtkTextLine *tl);
#ifdef USE_PANGO
#include <pango/pangoxft.h>
#endif
+
+#endif /* _LTK_TEXT_H_ */
diff --git a/text_stb.c b/text_stb.c
@@ -35,6 +35,7 @@
#include "khash.h"
#include "stb_truetype.h" /* http://nothings.org/stb/stb_truetype.h */
+#include "color.h"
#include "ltk.h"
#include "util.h"
#include "text.h"