Compare commits
2 commits
091bb0a57b
...
1d7c2c6f92
Author | SHA1 | Date | |
---|---|---|---|
|
1d7c2c6f92 | ||
|
7901afc47c |
7 changed files with 111 additions and 16 deletions
|
@ -13,6 +13,7 @@
|
||||||
#include "dispatcher-node.h"
|
#include "dispatcher-node.h"
|
||||||
#include "box-layout-node.h"
|
#include "box-layout-node.h"
|
||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
|
#include <string.h>
|
||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
|
|
||||||
typedef struct AppState {
|
typedef struct AppState {
|
||||||
|
@ -114,6 +115,8 @@ int app_handle(struct UINode *node, void *data, int event_type, size_t d, void *
|
||||||
text_input->node.rect.w = 120;
|
text_input->node.rect.w = 120;
|
||||||
text_input->node.rect.h = 32;
|
text_input->node.rect.h = 32;
|
||||||
text_input->text_node = text_node_new(&text_input->node, state->font, UINeutral50, NULL);
|
text_input->text_node = text_node_new(&text_input->node, state->font, UINeutral50, NULL);
|
||||||
|
text_input->text_node->node.width_policy = UI_SIZE_POLICY_GROW;
|
||||||
|
text_input->text_node->node.height_policy = UI_SIZE_POLICY_GROW;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a bunch of buttons */
|
/* a bunch of buttons */
|
||||||
|
@ -130,7 +133,7 @@ int app_handle(struct UINode *node, void *data, int event_type, size_t d, void *
|
||||||
|
|
||||||
box_layout_new(buttons, UI_DIRECTION_VERTICAL);
|
box_layout_new(buttons, UI_DIRECTION_VERTICAL);
|
||||||
|
|
||||||
for (int i = 0; i < 10000; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
UINode *button = node_new(buttons, "button");
|
UINode *button = node_new(buttons, "button");
|
||||||
state_background_node_new(button, UIPurple600, UIPurple700, UIPurple800, 6.0);
|
state_background_node_new(button, UIPurple600, UIPurple700, UIPurple800, 6.0);
|
||||||
text_node_new(button, state->font, UINeutral50, "button");
|
text_node_new(button, state->font, UINeutral50, "button");
|
||||||
|
|
31
src/str.c
Normal file
31
src/str.c
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "str.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int ui_string_insert(UIString *str, const size_t where, const char *d, const size_t dsize)
|
||||||
|
{
|
||||||
|
size_t required_capacity = str->size + dsize;
|
||||||
|
if (required_capacity > str->capacity) {
|
||||||
|
str->data = realloc(str->data, required_capacity + 1);
|
||||||
|
str->data[required_capacity] = '\0';
|
||||||
|
str->capacity = required_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(str->data + where + dsize, str->data + where, str->capacity - where - dsize);
|
||||||
|
memcpy(str->data + where, d, dsize);
|
||||||
|
str->size += dsize;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ui_string_delete(UIString *str, const size_t where, const size_t amount)
|
||||||
|
{
|
||||||
|
if (str->data + where + amount > str->data + str->capacity) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(str->data + where, str->data + where + amount, str->capacity - where - amount);
|
||||||
|
str->size -= amount;
|
||||||
|
str->data[str->size] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
15
src/str.h
Normal file
15
src/str.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef _UI__STR_H
|
||||||
|
#define _UI__STR_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct UIString {
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
char *data;
|
||||||
|
} UIString;
|
||||||
|
|
||||||
|
int ui_string_insert(UIString *str, const size_t where, const char *d, const size_t dsize);
|
||||||
|
int ui_string_delete(UIString *str, const size_t where, const size_t amount);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,9 +1,11 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "text-node.h"
|
#include "text-node.h"
|
||||||
#include "text-input-node.h"
|
#include "text-input-node.h"
|
||||||
|
#include "str.h"
|
||||||
|
|
||||||
UITextInputNode *text_input_new(UINode *parent)
|
UITextInputNode *text_input_new(UINode *parent)
|
||||||
{
|
{
|
||||||
|
@ -13,8 +15,7 @@ UITextInputNode *text_input_new(UINode *parent)
|
||||||
n->node.flags = UI_NODE_RETAINS_PRESS;
|
n->node.flags = UI_NODE_RETAINS_PRESS;
|
||||||
n->node.text = "text_input";
|
n->node.text = "text_input";
|
||||||
n->node.handle_proto = text_input_handle;
|
n->node.handle_proto = text_input_handle;
|
||||||
n->text = calloc(1, 1);
|
n->text = (UIString){0};
|
||||||
n->text_size = 1;
|
|
||||||
n->text_cursor_index = 0;
|
n->text_cursor_index = 0;
|
||||||
node_attach(parent, (UINode*)n);
|
node_attach(parent, (UINode*)n);
|
||||||
return n;
|
return n;
|
||||||
|
@ -36,26 +37,59 @@ int text_input_handle(UINode *node, enum UIEvent ev, size_t d, void *p)
|
||||||
|
|
||||||
switch (keysym) {
|
switch (keysym) {
|
||||||
case XKB_KEY_BackSpace: {
|
case XKB_KEY_BackSpace: {
|
||||||
if (n->text_cursor_index > 0 && n->text_size > 1) {
|
if (n->text_cursor_index > 0) {
|
||||||
n->text[--n->text_cursor_index] = '\0';
|
ui_string_delete(&n->text, --n->text_cursor_index, 1);
|
||||||
n->text = realloc(n->text, n->text_size--);
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XKB_KEY_Delete: {
|
||||||
|
if (n->text_cursor_index > 0 && n->text_cursor_index + 1 <= n->text.size) {
|
||||||
|
ui_string_delete(&n->text, n->text_cursor_index + 1, 1);
|
||||||
|
}
|
||||||
|
if (n->text_cursor_index > n->text.size) {
|
||||||
|
n->text_cursor_index = n->text.size - 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XKB_KEY_Home: {
|
||||||
|
n->text_cursor_index = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XKB_KEY_End: {
|
||||||
|
n->text_cursor_index = n->text.size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XKB_KEY_Left: {
|
||||||
|
if (n->text_cursor_index > 0) {
|
||||||
|
n->text_cursor_index--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XKB_KEY_Right: {
|
||||||
|
if (n->text_cursor_index < n->text.size) {
|
||||||
|
n->text_cursor_index++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
size_t key_size = xkb_state_key_get_utf8(xkb_state, keycode, NULL, 0);
|
size_t input_size = xkb_state_key_get_utf8(xkb_state, keycode, NULL, 0) + 1;
|
||||||
size_t new_text_size = n->text_size + key_size;
|
if (input_size <= 1) {
|
||||||
n->text = realloc(n->text, new_text_size);
|
break;
|
||||||
xkb_state_key_get_utf8(xkb_state, keycode, n->text + n->text_cursor_index, key_size + 1);
|
}
|
||||||
n->text_cursor_index += key_size;
|
|
||||||
n->text_size = new_text_size;
|
char *input_buf = calloc(1, input_size);
|
||||||
|
xkb_state_key_get_utf8(xkb_state, keycode, input_buf, input_size);
|
||||||
|
ui_string_insert(&n->text, n->text_cursor_index, input_buf, input_size - 1);
|
||||||
|
n->text_cursor_index++;
|
||||||
|
free(input_buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n->text_node) {
|
if (n->text_node) {
|
||||||
n->text_node->pending_text = n->text;
|
n->text_node->pending_text = n->text.data;
|
||||||
n->text_node->caret_index = n->text_cursor_index;
|
n->text_node->caret_index = n->text_cursor_index;
|
||||||
|
n->text_node->wrap = true;
|
||||||
node_request_relayout(&n->text_node->node);
|
node_request_relayout(&n->text_node->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "text-node.h"
|
#include "text-node.h"
|
||||||
|
#include "str.h"
|
||||||
|
|
||||||
typedef struct UITextInputNode {
|
typedef struct UITextInputNode {
|
||||||
UINode node;
|
UINode node;
|
||||||
UITextNode *text_node;
|
UITextNode *text_node;
|
||||||
char *text;
|
UIString text;
|
||||||
size_t text_size;
|
|
||||||
size_t text_cursor_index;
|
size_t text_cursor_index;
|
||||||
} UITextInputNode;
|
} UITextInputNode;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ UITextNode *text_node_new(UINode *parent, PangoFontDescription *desc, UIRGBA col
|
||||||
n->color = color;
|
n->color = color;
|
||||||
n->caret_index = -1;
|
n->caret_index = -1;
|
||||||
n->caret_node = NULL;
|
n->caret_node = NULL;
|
||||||
|
n->wrap = false;
|
||||||
n->node.text = "text";
|
n->node.text = "text";
|
||||||
n->node.handle_proto = text_node_handle;
|
n->node.handle_proto = text_node_handle;
|
||||||
node_attach(parent, (UINode*)n);
|
node_attach(parent, (UINode*)n);
|
||||||
|
@ -43,7 +44,11 @@ int text_node_handle(UINode *node, enum UIEvent ev, size_t d, void *p)
|
||||||
} else {
|
} else {
|
||||||
PangoLayout *layout = pango_cairo_create_layout(n->node.drw);
|
PangoLayout *layout = pango_cairo_create_layout(n->node.drw);
|
||||||
pango_layout_set_font_description(layout, n->desc);
|
pango_layout_set_font_description(layout, n->desc);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
if (n->wrap) {
|
||||||
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
||||||
|
} else {
|
||||||
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||||
|
}
|
||||||
pango_layout_set_text(layout, n->pending_text, -1);
|
pango_layout_set_text(layout, n->pending_text, -1);
|
||||||
n->layout = layout;
|
n->layout = layout;
|
||||||
n->pending_text = NULL;
|
n->pending_text = NULL;
|
||||||
|
@ -80,6 +85,12 @@ int text_node_handle(UINode *node, enum UIEvent ev, size_t d, void *p)
|
||||||
if (!n->layout) {
|
if (!n->layout) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (node->parent->width_policy != UI_SIZE_POLICY_COMPUTED) {
|
||||||
|
pango_layout_set_width(n->layout, pango_units_from_double(node->parent->rect.w));
|
||||||
|
}
|
||||||
|
if (node->parent->height_policy != UI_SIZE_POLICY_COMPUTED) {
|
||||||
|
pango_layout_set_height(n->layout, pango_units_from_double(node->parent->rect.h));
|
||||||
|
}
|
||||||
if (n->caret_index >= 0) {
|
if (n->caret_index >= 0) {
|
||||||
if (!n->caret_node) {
|
if (!n->caret_node) {
|
||||||
n->caret_node = node_new(&n->node, "caret");
|
n->caret_node = node_new(&n->node, "caret");
|
||||||
|
|
|
@ -15,6 +15,7 @@ typedef struct UITextNode {
|
||||||
UIRGBA color;
|
UIRGBA color;
|
||||||
ssize_t caret_index;
|
ssize_t caret_index;
|
||||||
UINode *caret_node;
|
UINode *caret_node;
|
||||||
|
bool wrap;
|
||||||
} UITextNode;
|
} UITextNode;
|
||||||
|
|
||||||
int text_node_handle(UINode *node, enum UIEvent ev, size_t d, void *p);
|
int text_node_handle(UINode *node, enum UIEvent ev, size_t d, void *p);
|
||||||
|
|
Loading…
Reference in a new issue