commit f8162695f7e3ea7d517610987a5fbc614f515878
parent 0d6981b3dbd7dbfcc80fe517414fac3da70822b4
Author: lumidify <nobody@lumidify.org>
Date: Sun, 1 Jan 2017 18:48:28 +0100
Update event system
Diffstat:
15 files changed, 218 insertions(+), 177 deletions(-)
diff --git a/README.md b/README.md
@@ -6,6 +6,6 @@ Please do not attempt to actually use any of the code.
## Licenses of Other Libraries Used
-[uthash](https://troydhanson.github.io/uthash/): [BSD Revised](https://troydhanson.github.io/uthash/license.html)
+[uthash](https://troydhanson.github.io/uthash/) by Troy D. Hanson: [BSD Revised](https://troydhanson.github.io/uthash/license.html)
-[cJSON](https://github.com/DaveGamble/cJSON): [MIT/X](https://github.com/DaveGamble/cJSON/blob/master/LICENSE)
+[cJSON](https://github.com/DaveGamble/cJSON) by Dave Gamble: [MIT/X](https://github.com/DaveGamble/cJSON/blob/master/LICENSE)
diff --git a/button.c b/button.c
@@ -154,6 +154,7 @@ void ltk_draw_button(void *widget)
}
XSetForeground(ltk_global->display, window->gc, fill_color.pixel);
XFillRectangle(ltk_global->display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h);
+ if (border_width < 1) return;
XSetForeground(ltk_global->display, window->gc, border_color.pixel);
XSetLineAttributes(ltk_global->display, window->gc, border_width, LineSolid, CapButt, JoinMiter);
XDrawRectangle(ltk_global->display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h);
@@ -173,11 +174,15 @@ LtkButton *ltk_create_button(LtkWindow *window, const char *text, void (*callbac
button->widget.parent = NULL;
button->widget.active_widget = NULL;
button->widget.hover_widget = NULL;
- button->widget.key_func = <k_button_key_event;
- button->widget.mouse_func = <k_button_mouse_event;
- button->widget.update_function = NULL;
- button->widget.draw_function = <k_draw_button;
- button->widget.destroy_function = <k_destroy_button;
+ button->widget.key_press = NULL;
+ button->widget.key_release = NULL;
+ button->widget.mouse_press = NULL;
+ button->widget.mouse_release = <k_button_mouse_release;
+ button->widget.motion_notify = NULL;
+ button->widget.resize = NULL;
+ button->widget.draw = <k_draw_button;
+ button->widget.destroy = <k_destroy_button;
+ button->widget.redraw_state = 1;
button->widget.rect.x = 0;
button->widget.rect.y = 0;
/* For testing, will default to size of text once text is implemented */
@@ -206,52 +211,8 @@ void ltk_button_key_event(void *widget, XEvent event)
{
}
-void ltk_button_mouse_event(void *widget, XEvent event)
+
+void ltk_button_mouse_release(void *widget, XEvent event)
{
LtkButton *button = widget;
- if (button->widget.state == DISABLED)
- {
- return;
- }
- if (event.type == ButtonPress && event.xbutton.button == 1)
- {
- LtkWidget *parent = button->widget.parent;
- if (parent)
- {
- ltk_remove_active_widget(parent);
- parent->active_widget = button;
- }
- button->widget.state = PRESSED;
- ltk_draw_button(button);
- }
- else if (event.type == ButtonRelease)
- {
- if (button->widget.state == PRESSED)
- {
- button->widget.state = HOVERACTIVE;
- ltk_draw_button(button);
- }
- }
- else if (event.type == MotionNotify)
- {
- if (button->widget.state == NORMAL || button->widget.state == ACTIVE)
- {
- if (button->widget.state == ACTIVE)
- {
- button->widget.state = HOVERACTIVE;
- }
- else
- {
- button->widget.state = HOVER;
- }
- LtkWidget *parent = button->widget.parent;
- LtkWidget *hover_widget;
- if (parent)
- {
- ltk_remove_hover_widget(parent);
- parent->hover_widget = button;
- }
- ltk_draw_button(button);
- }
- }
}
diff --git a/button.h b/button.h
@@ -72,7 +72,6 @@ LtkButton *ltk_create_button(LtkWindow *window, const char *text, void (*callbac
void ltk_button_key_event(void *widget, XEvent event);
void ltk_button_mouse_event(void *widget, XEvent event);
void ltk_destroy_button(void *widget);
-void ltk_button_key_event(void *widget, XEvent event);
-void ltk_button_mouse_event(void *widget, XEvent event);
+void ltk_button_mouse_release(void *widget, XEvent event);
#endif
diff --git a/common.c b/common.c
@@ -56,7 +56,7 @@ void ltk_remove_active_widget(void *widget)
{
child = parent->active_widget;
child->state = NORMAL;
- child->draw_function(child);
+ child->draw(child);
parent->active_widget = NULL;
parent = child;
}
@@ -73,7 +73,7 @@ void ltk_remove_hover_widget(void *widget)
{
child = parent->hover_widget;
child->state = child->state == HOVERACTIVE ? ACTIVE : NORMAL;
- child->draw_function(child);
+ child->draw(child);
parent->hover_widget = NULL;
parent = child;
}
diff --git a/common.h b/common.h
@@ -24,6 +24,7 @@
#ifndef _LTK_COMMON_H_
#define _LTK_COMMON_H_
+typedef void (*LTK_VOID_FUNC)(void *);
typedef struct LtkWidget LtkWidget;
typedef enum
diff --git a/event.c b/event.c
@@ -26,17 +26,27 @@
void ltk_handle_event(XEvent event)
{
LtkWindow *window;
+ LtkWidget *root_widget;
HASH_FIND_INT(ltk_global->window_hash, &event.xany.window, window);
- if ((event.type == KeyPress || event.type == KeyRelease) && window->key_func)
+ root_widget = window->root_widget;
+ if (!root_widget) return;
+ switch (event.type)
{
- window->key_func(window, event);
- }
- else if ((event.type == ButtonPress || event.type == ButtonRelease || event.type == MotionNotify) && window->mouse_func)
- {
- window->mouse_func(window, event);
- }
- else if (window->other_func)
- {
- window->other_func(window, event);
+ case KeyPress:
+ break;
+ case KeyRelease:
+ break;
+ case ButtonPress:
+ ltk_mouse_press_event(root_widget, event);
+ break;
+ case ButtonRelease:
+ ltk_mouse_release_event(root_widget, event);
+ break;
+ case MotionNotify:
+ ltk_motion_notify_event(root_widget, event);
+ break;
+ default:
+ if (window->other_event)
+ window->other_event(window, event);
}
}
diff --git a/event.h b/event.h
@@ -26,6 +26,6 @@
#ifndef _LTK_EVENT_H_
#define _LTK_EVENT_H_
-typedef void (*LTK_EVENT_FUNC)(void *widget, XEvent event);
+typedef void (*LTK_EVENT_FUNC)(void *, XEvent);
#endif
diff --git a/grid.c b/grid.c
@@ -42,12 +42,9 @@ void ltk_draw_grid(LtkGrid *grid)
int i;
for (i = 0; i < grid->rows * grid->columns; i++)
{
- if (!grid->widget_grid[i])
- {
- continue;
- }
+ if (!grid->widget_grid[i]) continue;
LtkWidget *ptr = grid->widget_grid[i];
- ptr->draw_function(ptr);
+ ptr->draw(ptr);
}
}
@@ -57,11 +54,15 @@ LtkGrid *ltk_create_grid(LtkWindow *window, int rows, int columns)
grid->widget.window = window;
grid->widget.parent = NULL;
- grid->widget.key_func = <k_grid_key_event;
- grid->widget.mouse_func = <k_grid_mouse_event;
- grid->widget.update_function = <k_recalculate_grid;
- grid->widget.draw_function = <k_draw_grid;
- grid->widget.destroy_function = <k_destroy_grid;
+ grid->widget.mouse_press = <k_grid_mouse_press;
+ grid->widget.mouse_release = <k_grid_mouse_release;
+ grid->widget.motion_notify = <k_grid_motion_notify;
+ grid->widget.key_press = NULL;
+ grid->widget.key_release = NULL;
+ grid->widget.resize = <k_recalculate_grid;
+ grid->widget.draw = <k_draw_grid;
+ grid->widget.destroy = <k_destroy_grid;
+ grid->widget.redraw_state = 0;
grid->widget.rect.x = 0;
grid->widget.rect.y = 0;
grid->widget.rect.w = 0;
@@ -113,7 +114,7 @@ void ltk_destroy_grid(void *widget)
if (grid->widget_grid[i])
{
ptr = grid->widget_grid[i];
- ptr->destroy_function(ptr);
+ ptr->destroy(ptr);
}
}
free(grid->widget_grid);
@@ -203,9 +204,9 @@ void ltk_recalculate_grid(void *widget)
}
if (orig_width != ptr->rect.w || orig_height != ptr->rect.h)
{
- if (ptr->update_function)
+ if (ptr->resize)
{
- ptr->update_function(ptr);
+ ptr->resize(ptr);
}
}
@@ -246,10 +247,12 @@ void ltk_grid_widget(void *ptr, LtkGrid *grid, int row, int column, int row_span
widget->column = column;
widget->row_span = row_span;
widget->column_span = column_span;
- if (grid->column_weights[column] == 0 && widget->rect.w > grid->column_widths[column]) {
+ if (grid->column_weights[column] == 0 && widget->rect.w > grid->column_widths[column])
+ {
grid->column_widths[column] = widget->rect.w;
}
- if (grid->row_weights[row] == 0 && widget->rect.h > grid->row_heights[row]) {
+ if (grid->row_weights[row] == 0 && widget->rect.h > grid->row_heights[row])
+ {
grid->row_heights[row] = widget->rect.h;
}
grid->widget_grid[widget->row * grid->columns + widget->column] = widget;
@@ -257,57 +260,71 @@ void ltk_grid_widget(void *ptr, LtkGrid *grid, int row, int column, int row_span
ltk_recalculate_grid(grid);
}
-void ltk_grid_key_event(void *widget, XEvent event)
-{
- LtkGrid *grid = widget;
- LtkWidget *ptr = grid->widget.active_widget;
- if (ptr && ptr->key_func)
- {
- ptr->key_func(ptr, event);
- }
-}
-
-void ltk_grid_mouse_event(void *widget, XEvent event)
+int ltk_grid_find_nearest_column(LtkGrid *grid, int x)
{
- LtkGrid *grid = widget;
- LtkWidget *ptr;
int i;
- int x, y;
- int row, column;
- if (event.type == ButtonPress || event.type == ButtonRelease)
- {
- x = event.xbutton.x;
- y = event.xbutton.y;
- }
- else if (event.type == MotionNotify)
- {
- x = event.xmotion.x;
- y = event.xmotion.y;
- }
for (i = 0; i < grid->columns; i++)
{
if (grid->column_pos[i] <= x && grid->column_pos[i + 1] >= x)
{
- column = i;
+ return i;
}
}
+}
+
+int ltk_grid_find_nearest_row(LtkGrid *grid, int y)
+{
+ int i;
for (i = 0; i < grid->rows; i++)
{
if (grid->row_pos[i] <= y && grid->row_pos[i + 1] >= y)
{
- row = i;
+ return i;
}
}
- ptr = grid->widget_grid[row * grid->columns + column];
- if (ptr && ptr->mouse_func)
+}
+
+ltk_grid_mouse_press(void *widget, XEvent event)
+{
+ LtkGrid *grid = widget;
+ int x = event.xbutton.x;
+ int y = event.xbutton.y;
+ int row = ltk_grid_find_nearest_row(grid, y);
+ int column = ltk_grid_find_nearest_column(grid, x);
+ LtkWidget *ptr = grid->widget_grid[row * grid->columns + column];
+ if (ptr && ltk_collide_rect(ptr->rect, x, y))
+ {
+ ltk_mouse_press_event(ptr, event);
+ }
+}
+
+ltk_grid_mouse_release(void *widget, XEvent event)
+{
+ LtkGrid *grid = widget;
+ int x = event.xbutton.x;
+ int y = event.xbutton.y;
+ int row = ltk_grid_find_nearest_row(grid, y);
+ int column = ltk_grid_find_nearest_column(grid, x);
+ LtkWidget *ptr = grid->widget_grid[row * grid->columns + column];
+ if (ptr && ltk_collide_rect(ptr->rect, x, y))
+ {
+ ltk_mouse_release_event(ptr, event);
+ }
+}
+
+ltk_grid_motion_notify(void *widget, XEvent event)
+{
+ LtkGrid *grid = widget;
+ int x = event.xbutton.x;
+ int y = event.xbutton.y;
+ int row = ltk_grid_find_nearest_row(grid, y);
+ int column = ltk_grid_find_nearest_column(grid, x);
+ LtkWidget *ptr = grid->widget_grid[row * grid->columns + column];
+ if (ptr)
{
if (ltk_collide_rect(ptr->rect, x, y))
- {
- ptr->mouse_func(ptr, event);
- }
- else if (grid->widget.hover_widget)
- {
+ ltk_motion_notify_event(ptr, event);
+ else
ltk_remove_hover_widget(grid);
- }
}
}
diff --git a/grid.h b/grid.h
@@ -46,8 +46,9 @@ void ltk_draw_grid(LtkGrid *grid);
LtkGrid *ltk_create_grid(LtkWindow *window, int rows, int columns);
void ltk_destroy_grid(void *widget);
void ltk_recalculate_grid(void *widget);
-void ltk_grid_key_event(void *widget, XEvent event);
-void ltk_grid_mouse_event(void *widget, XEvent event);
void ltk_grid_widget(void *ptr, LtkGrid *grid, int row, int column, int rowspan, int columnspan, int sticky[4]);
+void ltk_grid_mouse_press(void *widget, XEvent event);
+void ltk_grid_mouse_release(void *widget, XEvent event);
+void ltk_grid_motion_notify(void *widget, XEvent event);
#endif
diff --git a/test1.c b/test1.c
@@ -1,21 +1,8 @@
#include "ltk.h"
-void bob(void *window, XEvent event)
+void bob1(void)
{
- KeySym key;
- char text[255];
- if (XLookupString(&event.xkey, text, 255, &key, 0) == 1)
- {
- if (text[0] == 'q')
- {
- ltk_quit();
- }
- }
-}
-
-void bob1(void *window, XEvent event)
-{
- printf("mouse\n");
+ printf("bob\n");
}
int main(int argc, char *argv[])
@@ -28,7 +15,7 @@ int main(int argc, char *argv[])
ltk_set_row_weight(grid1, 1, 1);
ltk_set_column_weight(grid1, 0, 1);
ltk_set_column_weight(grid1, 1, 1);
- LtkButton *button1 = ltk_create_button(window1, "I'm a button!", NULL);
+ LtkButton *button1 = ltk_create_button(window1, "I'm a button!", &bob1);
int sticky1[4] = {0, 1, 0, 1};
ltk_grid_widget(button1, grid1, 0, 0, 1, 1, sticky1);
LtkButton *button2 = ltk_create_button(window1, "I'm a button!", NULL);
diff --git a/themes/default.ini b/themes/default.ini
@@ -0,0 +1,21 @@
+[window]
+border_width = 0
+background = #000000
+foreground = #FFFFFF
+
+[button]
+border_width = 2
+font_size = 20
+border_color = #339999
+fill_color = #113355
+pad_left = 5
+pad_right = 5
+pad_top = 5
+pad_bottom = 5
+fill_color_hover = 738194
+border_color_pressed = #FFFFFF
+fill_color_pressed = 113355
+border_color_active = #FFFFFF
+fill_color_active = #113355
+border_color_disabled = #FFFFFF
+fill_color_disabled = #292929
diff --git a/widget.c b/widget.c
@@ -21,3 +21,60 @@
* SOFTWARE.
*/
+#include "ltk.h"
+
+void ltk_mouse_press_event(void *widget, XEvent event)
+{
+ LtkWidget *ptr = widget;
+ if (!ptr || ptr->state == DISABLED) return;
+ if (event.xbutton.button == 1)
+ {
+ LtkWidget *parent = ptr->parent;
+ if (parent)
+ {
+ ltk_remove_active_widget(parent);
+ parent->active_widget = ptr;
+ }
+ ptr->state = PRESSED;
+ if (ptr->redraw_state) ptr->draw(ptr);
+ }
+ if (ptr->mouse_press)
+ {
+ ptr->mouse_press(ptr, event);
+ }
+}
+
+void ltk_mouse_release_event(void *widget, XEvent event)
+{
+ LtkWidget *ptr = widget;
+ if (!ptr || ptr->state == DISABLED) return;
+ if (ptr->state == PRESSED)
+ {
+ ptr->state = HOVERACTIVE;
+ if (ptr->redraw_state) ptr->draw(ptr);
+ }
+ if (ptr->mouse_release)
+ {
+ ptr->mouse_release(ptr, event);
+ }
+}
+
+void ltk_motion_notify_event(void *widget, XEvent event)
+{
+ LtkWidget *ptr = widget;
+ if (!ptr || ptr->state == NORMAL || ptr->state == ACTIVE)
+ {
+ ptr->state = ptr->state == ACTIVE ? HOVERACTIVE : HOVER;
+ LtkWidget *parent = ptr->parent;
+ if (parent)
+ {
+ ltk_remove_hover_widget(parent);
+ parent->hover_widget = ptr;
+ }
+ if (ptr->redraw_state) ptr->draw(ptr);
+ }
+ if (ptr->motion_notify)
+ {
+ ptr->motion_notify(ptr, event);
+ }
+}
diff --git a/widget.h b/widget.h
@@ -38,18 +38,29 @@ typedef struct LtkWidget
void *hover_widget;
/* Parent widget */
void *parent;
- /* Function to be called on a KeyPress or KeyRelease event */
- LTK_EVENT_FUNC key_func;
- /* Function to be called on a ButtonPress, ButtonRelease, or MotionNotify event */
- LTK_EVENT_FUNC mouse_func;
- /* For container widgets; function to be called when the widget is resized */
- void (*update_function)(void *);
+
+ /* Called on KeyPress events */
+ void (*key_press)(void *, XEvent event);
+ /* Called on KeyRelease events */
+ void (*key_release)(void *, XEvent event);
+ /* Called on ButtonPress events */
+ void (*mouse_press)(void *, XEvent event);
+ /* Called on ButtonRelease event */
+ void (*mouse_release)(void *, XEvent event);
+ /* Called on MotionNotify events */
+ void (*motion_notify)(void *, XEvent event);
+
+ /* Function to update the widget after its LtkRect has been modified */
+ void (*resize)(void *);
/* Function to draw the widget */
- void (*draw_function)(void *);
- /* State of the widget; NORMAL, PRESSED, ACTIVE, HOVER, or DISABLED */
+ void (*draw)(void *);
+ /* Function to destroy the widget */
+ void (*destroy)(void *);
+
+ /* Specifies if the widget needs to be redrawn after a state change */
+ int redraw_state;
+ /* State of the widget */
LtkWidgetState state;
- /* Function to destroy the widget; used by containers to destroy child widgets */
- void (*destroy_function)(void *);
/* Position and size of the widget */
LtkRect rect;
/* Row of widget if gridded */
diff --git a/window.c b/window.c
@@ -49,7 +49,7 @@ void ltk_redraw_window(LtkWindow *window)
return;
}
ptr = window->root_widget;
- ptr->draw_function(ptr);
+ ptr->draw(ptr);
}
LtkWindow *ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int h)
@@ -65,9 +65,7 @@ LtkWindow *ltk_create_window(const char *title, int x, int y, unsigned int w, un
XSetStandardProperties(display, window->xwindow, title, NULL, None, NULL, 0, NULL);
window->root_widget = NULL;
- window->key_func = <k_window_key_event;
- window->mouse_func = <k_window_mouse_event;
- window->other_func = <k_window_other_event;
+ window->other_event = <k_window_other_event;
window->rect.w = 0;
window->rect.h = 0;
@@ -88,31 +86,11 @@ void ltk_destroy_window(LtkWindow *window)
LtkWidget *ptr = window->root_widget;
if (ptr)
{
- ptr->destroy_function(ptr);
+ ptr->destroy(ptr);
}
free(window);
}
-void ltk_window_key_event(void *widget, XEvent event)
-{
- LtkWindow *window = widget;
- LtkWidget *ptr = window->root_widget;
- if (ptr && ptr->key_func)
- {
- ptr->key_func(ptr, event);
- }
-}
-
-void ltk_window_mouse_event(void *widget, XEvent event)
-{
- LtkWindow *window = widget;
- LtkWidget *ptr = window->root_widget;
- if (ptr && ptr->mouse_func)
- {
- ptr->mouse_func(ptr, event);
- }
-}
-
void ltk_window_other_event(void *widget, XEvent event)
{
LtkWindow *window = widget;
@@ -122,13 +100,13 @@ void ltk_window_other_event(void *widget, XEvent event)
unsigned int w, h;
w = event.xconfigure.width;
h = event.xconfigure.height;
- if (ptr && ptr->update_function && (window->rect.w != w || window->rect.h != h))
+ if (ptr && ptr->resize && (window->rect.w != w || window->rect.h != h))
{
window->rect.w = w;
window->rect.h = h;
ptr->rect.w = w;
ptr->rect.h = h;
- ptr->update_function(ptr);
+ ptr->resize(ptr);
ltk_redraw_window(window);
}
}
@@ -155,7 +133,7 @@ void ltk_resize_window(Uint32 id, int w, int h)
}
ptr->rect.w = w;
ptr->rect.h = h;
- ptr->update_function(ptr);
+ ptr->resize(ptr);
}
void ltk_window_set_root_widget(LtkWindow *window, void *root_widget)
diff --git a/window.h b/window.h
@@ -32,9 +32,7 @@ typedef struct LtkWindow
Window xwindow;
GC gc;
void *root_widget;
- LTK_EVENT_FUNC key_func; /* Called on any keyboard event */
- LTK_EVENT_FUNC mouse_func; /* Called on any mouse event */
- LTK_EVENT_FUNC other_func; /* Called on any other event */
+ void (*other_event)(void *, XEvent event);
LtkRect rect;
UT_hash_handle hh;
} LtkWindow;