Browse Source

add combo box

master
Alexandros Theodotou 3 years ago
parent
commit
2a13b3fc4a
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 3
      inc/ztoolkit/ztk.h
  2. 5
      inc/ztoolkit/ztk_app.h
  3. 130
      inc/ztoolkit/ztk_combo_box.h
  4. 8
      inc/ztoolkit/ztk_label.h
  5. 54
      inc/ztoolkit/ztk_widget.h
  6. 1
      src/meson.build
  7. 98
      src/ztk_app.c
  8. 1
      src/ztk_color.c
  9. 507
      src/ztk_combo_box.c
  10. 3
      src/ztk_drawing_area.c
  11. 2
      src/ztk_knob.c
  12. 3
      src/ztk_knob_with_label.c
  13. 2
      src/ztk_label.c
  14. 2
      src/ztk_widget.c
  15. 8
      tests/meson.build
  16. 62
      tests/ztk_app.c

3
inc/ztoolkit/ztk.h

@ -24,13 +24,14 @@ @@ -24,13 +24,14 @@
#include "log.h"
#include "types.h"
#include "rsvg.h"
#include "ztk_widget.h"
#include "ztk_app.h"
#include "ztk_color.h"
#include "ztk_combo_box.h"
#include "ztk_drawing_area.h"
#include "ztk_knob.h"
#include "ztk_knob_with_label.h"
#include "ztk_label.h"
#include "ztk_widget.h"
#ifndef MAX
# define MAX(x,y) (x > y ? x : y)

5
inc/ztoolkit/ztk_app.h

@ -90,6 +90,11 @@ ztk_app_remove_widget ( @@ -90,6 +90,11 @@ ztk_app_remove_widget (
ZtkApp * self,
ZtkWidget * widget);
int
ztk_app_contains_widget (
ZtkApp * self,
ZtkWidget * widget);
/**
* Draws each widget.
*/

130
inc/ztoolkit/ztk_combo_box.h

@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZToolkit
*
* ZToolkit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ZToolkit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with ZToolkit. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __Z_TOOLKIT_ZTK_COMBO_BOX_H__
#define __Z_TOOLKIT_ZTK_COMBO_BOX_H__
#include "ztk.h"
/**
* A combo box element.
*/
typedef struct ZtkComboBoxElement
{
/** 1 if this is a separator. */
int is_separator;
/** Label to display. */
char label[420];
/** Function to call when activated. */
ZtkWidgetActivateCallback activate_cb;
/** Data specific to this element. */
void * activate_cb_data;
} ZtkComboBoxElement;
/**
* Combobox widget.
*/
typedef struct ZtkComboBox
{
/** Base widget. */
ZtkWidget base;
/** Parent widget to spawn on. */
ZtkWidget * parent;
ZtkComboBoxElement elements[120];
int num_elements;
char font_name[180];
double font_size;
/** Text color. */
ZtkColor text_normal_color;
/** Text when hovered. */
ZtkColor text_hover_color;
/** Text when hovered. */
ZtkColor text_click_color;
/** Color of the frame around the combo box. */
ZtkColor frame_color;
/** Background color of the whole combobox. */
ZtkColor bg_color;
/** Color of separator elements. */
ZtkColor separator_color;
/** Background color of the hovered element. */
ZtkColor hover_color;
/** Background color of the clicked element. */
ZtkColor click_color;
/** 1 if it the combobox should spawn upwards
* instead of downards. */
int upwards;
/** 1 if it the combobox should spawn backwards
* (left) instead of forwards (right). */
int backwards;
/** Hovered index. */
int hovered_idx;
} ZtkComboBox;
/**
* Creates a new combobox.
*
* @param parent The parent widget to spawn on.
* @param spawn_upwards Spawn upwards instead of
* downards.
*/
ZtkComboBox *
ztk_combo_box_new (
ZtkWidget * parent,
int spawn_upwards,
int spawn_backwards);
/**
* @param data Data related to the current element
* to pass to the activate callback.
*/
void
ztk_combo_box_add_text_element (
ZtkComboBox * self,
const char * label,
ZtkWidgetActivateCallback activate_cb,
void * data);
void
ztk_combo_box_add_separator (
ZtkComboBox * self);
void
ztk_combo_box_clear (
ZtkComboBox * self);
#endif

8
inc/ztoolkit/ztk_label.h

@ -1,20 +1,20 @@ @@ -1,20 +1,20 @@
/*
* Copyright (C) 2019 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
* This file is part of ZToolkit
*
* ZPlugins is free software: you can redistribute it and/or modify
* ZToolkit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ZPlugins is distributed in the hope that it will be useful,
* ZToolkit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* along with ZToolkit. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __Z_TOOLKIT_ZTK_LABEL_H__

54
inc/ztoolkit/ztk_widget.h

@ -69,7 +69,9 @@ typedef enum ZtkWidgetType @@ -69,7 +69,9 @@ typedef enum ZtkWidgetType
ZTK_WIDGET_TYPE_NONE,
ZTK_WIDGET_TYPE_LABEL,
ZTK_WIDGET_TYPE_KNOB,
ZTK_WIDGET_TYPE_KNOB_WITH_LABEL,
ZTK_WIDGET_TYPE_DRAWING_AREA,
ZTK_WIDGET_TYPE_COMBO_BOX,
} ZtkWidgetType;
typedef struct ZtkWidget ZtkWidget;
@ -97,6 +99,44 @@ typedef void (*ZtkWidgetDrawCallback) ( @@ -97,6 +99,44 @@ typedef void (*ZtkWidgetDrawCallback) (
cairo_t * cr,
void * data);
/**
* Prototype for activate callbacks.
*
* This should be used on widgets that can be
* activated, like combobox elements or buttons.
*
* @param widget The ZtkWidget instance.
* @param data User data passed during
* instantiation.
*/
typedef void (*ZtkWidgetActivateCallback) (
ZtkWidget * widget,
void * data);
/**
* Button event callback prototype.
*
* @return If the next hit widget on the stack
* should receive the event (1) or if the chain
* should stop here (0).
*/
typedef int (*ZtkWidgetButtonEventCallback) (
ZtkWidget * widget,
const PuglEventButton * btn,
void * data);
/**
* Motion event callback prototype.
*
* @return If the next hit widget on the stack
* should receive the event (1) or if the chain
* should stop here (0).
*/
typedef int (*ZtkWidgetMotionEventCallback) (
ZtkWidget * widget,
const PuglEventMotion * event,
void * data);
/**
* Base widget.
*/
@ -129,15 +169,8 @@ typedef struct ZtkWidget @@ -129,15 +169,8 @@ typedef struct ZtkWidget
* (optional). */
ZtkWidgetGenericCallback dispose_cb;
/**
* Button event callback (optional).
*
* Returns if the
* next hit widget on the stack should receive
* the event (1) or if the chain should stop here
* (0).
*/
int (*button_event_cb) (ZtkWidget *, const PuglEventButton *);
/** Button event callback (optional). */
ZtkWidgetButtonEventCallback button_event_cb;
/** Button event callback (optional). */
int (*key_event_cb) (ZtkWidget *, const PuglEventKey *);
@ -146,7 +179,7 @@ typedef struct ZtkWidget @@ -146,7 +179,7 @@ typedef struct ZtkWidget
int (*crossing_event_cb) (ZtkWidget *, const PuglEventCrossing *);
/** Motion event callback (optional). */
int (*motion_event_cb) (ZtkWidget *, const PuglEventMotion *);
ZtkWidgetMotionEventCallback motion_event_cb;
/** Scroll event callback (optional). */
int (*scroll_event_cb) (ZtkWidget *, const PuglEventScroll *);
@ -187,6 +220,7 @@ typedef struct ZtkWidget @@ -187,6 +220,7 @@ typedef struct ZtkWidget
void
ztk_widget_init (
ZtkWidget * self,
ZtkWidgetType type,
ZtkRect * rect,
ZtkWidgetGenericCallback update_cb,
ZtkWidgetDrawCallback draw_cb,

1
src/meson.build

@ -20,6 +20,7 @@ ztoolkit_srcs = files([ @@ -20,6 +20,7 @@ ztoolkit_srcs = files([
'rsvg.c',
'ztk_app.c',
'ztk_color.c',
'ztk_combo_box.c',
'ztk_drawing_area.c',
'ztk_knob.c',
'ztk_knob_with_label.c',

98
src/ztk_app.c

@ -21,9 +21,7 @@ @@ -21,9 +21,7 @@
#include <stdio.h>
#include <string.h>
#include "ztoolkit/ztk_app.h"
#include "ztoolkit/ztk_cairo.h"
#include "ztoolkit/ztk_widget.h"
#include "ztoolkit/ztk.h"
#include <pugl/pugl.h>
#include <pugl/pugl_cairo.h>
@ -101,7 +99,28 @@ post_event_to_widgets ( @@ -101,7 +99,28 @@ post_event_to_widgets (
const PuglEvent * event)
{
ZtkWidget * w = NULL;
for (int i = 0; i < self->num_widgets; i++)
/* if any combo box is active and not
* hit, remove it */
if (event->type == PUGL_BUTTON_PRESS)
{
const PuglEventButton * ev =
(const PuglEventButton *) event;
for (int i = self->num_widgets - 1;
i >= 0; i--)
{
w = self->widgets[i];
if ((w->type ==
ZTK_WIDGET_TYPE_COMBO_BOX) &&
!ztk_widget_is_hit (
w, ev->x, ev->y))
{
ztk_app_remove_widget (self, w);
}
}
}
for (int i = self->num_widgets - 1; i >= 0; i--)
{
w = self->widgets[i];
switch (event->type)
@ -130,7 +149,8 @@ post_event_to_widgets ( @@ -130,7 +149,8 @@ post_event_to_widgets (
ZTK_WIDGET_STATE_SELECTED;
if (w->button_event_cb)
{
w->button_event_cb (w, ev);
w->button_event_cb (
w, ev, w->user_data);
}
}
else
@ -150,7 +170,8 @@ post_event_to_widgets ( @@ -150,7 +170,8 @@ post_event_to_widgets (
~ZTK_WIDGET_STATE_PRESSED;
if (w->button_event_cb)
{
w->button_event_cb (w, ev);
w->button_event_cb (
w, ev, w->user_data);
}
}
break;
@ -165,7 +186,8 @@ post_event_to_widgets ( @@ -165,7 +186,8 @@ post_event_to_widgets (
ZTK_WIDGET_STATE_HOVERED;
if (w->motion_event_cb)
{
w->motion_event_cb (w, ev);
w->motion_event_cb (
w, ev, w->user_data);
}
}
else
@ -324,6 +346,16 @@ ztk_app_new ( @@ -324,6 +346,16 @@ ztk_app_new (
return self;
}
static int
cmp_z (
const void * a,
const void * b)
{
return
(*(ZtkWidget **) a)->z -
(*(ZtkWidget **) b)->z;
}
/**
* Adds a widget with the given Z axis.
*/
@ -333,7 +365,27 @@ ztk_app_add_widget ( @@ -333,7 +365,27 @@ ztk_app_add_widget (
ZtkWidget * widget,
int z)
{
if (self->num_widgets == self->widgets_size)
/* skip if already in app */
if (ztk_app_contains_widget (self, widget))
{
ztk_warning (
"Attempted to add widget %p to ZtkApp, "
"but the widget is already in ZtkApp",
widget);
return;
}
if (self->widgets_size == 0)
{
self->widgets_size = 2;
self->widgets =
(ZtkWidget **)
realloc (
self->widgets,
(size_t) self->widgets_size *
sizeof (ZtkWidget *));
}
else if (self->num_widgets == self->widgets_size)
{
self->widgets_size = self->widgets_size * 2;
self->widgets =
@ -348,6 +400,9 @@ ztk_app_add_widget ( @@ -348,6 +400,9 @@ ztk_app_add_widget (
widget->z = z;
/* TODO sort by z */
qsort (
self->widgets, (size_t) self->num_widgets,
sizeof (ZtkWidget *), cmp_z);
}
/**
@ -358,23 +413,48 @@ ztk_app_remove_widget ( @@ -358,23 +413,48 @@ ztk_app_remove_widget (
ZtkApp * self,
ZtkWidget * widget)
{
int match = 0;
for (int i = self->num_widgets - 1;
i >= 0; i--)
{
ZtkWidget * w = self->widgets[i];
if (w == widget)
{
match = 1;
for (int j = i; j < self->num_widgets - 1;
j++)
{
self->widgets[j] = self->widgets[j + 1];
self->widgets[j] =
self->widgets[j + 1];
}
break;
}
}
if (!match)
{
ztk_warning (
"Tried to remove widget %p from ZtkApp but "
"it wasn't found", widget);
return;
}
self->num_widgets--;
}
int
ztk_app_contains_widget (
ZtkApp * self,
ZtkWidget * widget)
{
for (int i = 0; i < self->num_widgets; i++)
{
ZtkWidget * w = self->widgets[i];
if (w == widget)
return 1;
}
return 0;
}
/**
* Draws each widget.
*/

1
src/ztk_color.c

@ -58,4 +58,5 @@ ztk_color_parse_hex ( @@ -58,4 +58,5 @@ ztk_color_parse_hex (
str[2] = '\0';
num = strtol (str, NULL, 16);
color->blue = (double) num / 255;
color->alpha = 1;
}

507
src/ztk_combo_box.c

@ -0,0 +1,507 @@ @@ -0,0 +1,507 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZToolkit
*
* ZToolkit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ZToolkit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with ZToolkit. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include "ztoolkit/ztk.h"
/** Height of the separator, excluding padding. */
#define SEPARATOR_HEIGHT 2
/** Padding to leave left/right/bot/top of the
* text. */
#define PADDING 2
static double
get_height (
ZtkComboBox * self)
{
double height = PADDING * 2;
for (int i = 0; i < self->num_elements; i++)
{
ZtkComboBoxElement * el = &self->elements[i];
if (el->is_separator)
{
height += SEPARATOR_HEIGHT + PADDING * 2;
}
else
{
/* the app is not set until the widget gets
* added to the app */
ZtkWidget * widget = (ZtkWidget *) self;
if (!widget->app)
continue;
cairo_t* cr =
(cairo_t*) puglGetContext (
widget->app->view);
cairo_text_extents_t extents;
cairo_set_font_size (cr, self->font_size);
cairo_text_extents (cr, el->label, &extents);
height += (int) extents.height + PADDING * 2;
}
}
return height;
}
static double
get_width (
ZtkComboBox * self)
{
double width = 12;
for (int i = 0; i < self->num_elements; i++)
{
ZtkComboBoxElement * el = &self->elements[i];
if (el->is_separator)
continue;
/* the app is not set until the widget gets
* added to the app */
ZtkWidget * widget = (ZtkWidget *) self;
if (!widget->app)
continue;
cairo_t* cr =
(cairo_t*) puglGetContext (
widget->app->view);
cairo_text_extents_t extents;
cairo_set_font_size (cr, self->font_size);
cairo_text_extents (cr, el->label, &extents);
width =
/* *2 for the element, *2 for the frame */
MAX (width, extents.width + PADDING * 4);
}
return width;
}
static void
get_dimensions (
ZtkComboBox * self,
ZtkRect * rect)
{
double height = get_height (self);
double width = get_width (self);
rect->width = width;
rect->height = height;
if (self->upwards)
{
if (self->backwards)
{
rect->x =
(self->parent->rect.x +
self->parent->rect.width) - width;
rect->y = self->parent->rect.y - height;
}
else
{
rect->x = self->parent->rect.x;
rect->y = self->parent->rect.y - height;
}
}
else /* downwards */
{
if (self->backwards)
{
rect->x =
(self->parent->rect.x +
self->parent->rect.width) - width;
rect->y =
self->parent->rect.y +
self->parent->rect.height;
}
else
{
rect->x = self->parent->rect.x;
rect->y =
self->parent->rect.y +
self->parent->rect.height;
}
}
}
static void
draw_cb (
ZtkWidget * w,
cairo_t * cr,
void * data)
{
ZtkComboBox * self = (ZtkComboBox *) w;
ZtkRect rect;
get_dimensions (self, &rect);
/* draw bg and frame */
ztk_color_set_for_cairo (
&self->frame_color, cr);
cairo_rectangle (
cr, rect.x, rect.y, rect.width,
rect.height);
cairo_fill (cr);
ztk_color_set_for_cairo (
&self->bg_color, cr);
cairo_rectangle (
cr, rect.x + PADDING, rect.y + PADDING,
rect.width - PADDING * 2,
rect.height - PADDING * 2);
cairo_fill (cr);
double height = rect.y + PADDING;
double next_height;
/* find element hit */
for (int i = 0; i < self->num_elements; i++)
{
ZtkComboBoxElement * el = &self->elements[i];
if (el->is_separator)
{
next_height =
height + SEPARATOR_HEIGHT +
PADDING * 2;
/* draw the element bg */
if (self->hovered_idx == i)
{
if (w->state & ZTK_WIDGET_STATE_PRESSED)
{
ztk_color_set_for_cairo (
&self->click_color, cr);
}
else
{
ztk_color_set_for_cairo (
&self->hover_color, cr);
}
cairo_rectangle (
cr, rect.x + PADDING, height,
rect.width - PADDING * 2,
next_height - height);
cairo_fill (cr);
}
/* draw the separator */
ztk_color_set_for_cairo (
&self->separator_color, cr);
cairo_rectangle (
cr, rect.x + PADDING * 2,
height + PADDING,
rect.width - PADDING * 4,
SEPARATOR_HEIGHT);
cairo_fill (cr);
height = next_height;
}
else
{
cairo_text_extents_t extents;
cairo_set_font_size (cr, self->font_size);
cairo_text_extents (
cr, el->label, &extents);
next_height =
height + extents.height +
PADDING * 2;
/* draw the element bg */
if (self->hovered_idx == i)
{
if (w->state & ZTK_WIDGET_STATE_PRESSED)
{
ztk_color_set_for_cairo (
&self->click_color, cr);
}
else
{
ztk_color_set_for_cairo (
&self->hover_color, cr);
}
cairo_rectangle (
cr, rect.x + PADDING, height,
rect.width - PADDING * 2,
next_height - height);
cairo_fill (cr);
}
/* draw the text */
if (self->hovered_idx == i)
{
if (w->state & ZTK_WIDGET_STATE_PRESSED)
{
ztk_color_set_for_cairo (
&self->text_click_color, cr);
}
else
{
ztk_color_set_for_cairo (
&self->text_hover_color, cr);
}
}
else
{
ztk_color_set_for_cairo (
&self->text_normal_color, cr);
}
cairo_move_to (
cr, rect.x + PADDING * 2,
height + PADDING + extents.height);
cairo_show_text (
cr, el->label);
height = next_height;
}
}
}
static void
update_cb (
ZtkWidget * w,
void * data)
{
}
static int
motion_cb (
ZtkWidget * widget,
const PuglEventMotion * event,
void * data)
{
ztk_message ("%s", "combo box motion");
/* set hovered */
ZtkComboBox * self = (ZtkComboBox *) widget;
double y = event->y;
double height = widget->rect.y + PADDING;
double next_height;
/* find element hit */
for (int i = 0; i < self->num_elements; i++)
{
ZtkComboBoxElement * el = &self->elements[i];
if (el->is_separator)
{
next_height =
height + SEPARATOR_HEIGHT +
PADDING * 2;
if (y >= height && y < next_height)
{
self->hovered_idx = i;
return 0;
}
height = next_height;
}
else
{
cairo_t* cr =
(cairo_t*) puglGetContext (
((ZtkWidget *) self)->app->view);
cairo_text_extents_t extents;
cairo_set_font_size (
cr, self->font_size);
cairo_text_extents (
cr, el->label, &extents);
next_height =
height + extents.height +
PADDING * 2;
if (y >= height && y < next_height)
{
self->hovered_idx = i;
return 0;
}
height = next_height;
}
}
self->hovered_idx = -1;
return 0;
}
static void
free_cb (
ZtkWidget * w,
void * data)
{
ZtkComboBox * self = (ZtkComboBox *) w;
free (self);
}
static int
button_event_cb (
ZtkWidget * widget,
const PuglEventButton * btn,
void * data)
{
ZtkComboBox * self = (ZtkComboBox *) widget;
const PuglEvent * ev = (const PuglEvent *) btn;
if (ztk_widget_is_hit (widget, btn->x, btn->y))
{
/* skip if already removed */
if (!ztk_app_contains_widget (
widget->app, widget))
return 0;
/* skip if not release or no valid hover */
if (ev->type != PUGL_BUTTON_RELEASE ||
self->hovered_idx < 0)
return 0;
ZtkComboBoxElement * el =
&self->elements[self->hovered_idx];
if (!el->is_separator)
{
/* activate */
el->activate_cb (
widget, el->activate_cb_data);
/* remove from app to hide the
* combobox */
ztk_app_remove_widget (
widget->app, widget);
ztk_message ("%s", "removed");
return 0;
}
}
/* clicked outside */
else
{
/* remove widget */
ztk_app_remove_widget (
widget->app, widget);
}
return 0;
}
/**
* Initializes the defaults.
*/
static void
ztk_combo_box_init (
ZtkComboBox * self)
{
strcpy (self->font_name, "Cantarrel");
self->font_size = 12.0;
ztk_color_parse_hex (
&self->text_normal_color, "#DDDDDD");
ztk_color_parse_hex (
&self->text_hover_color, "#EEEEEE");
ztk_color_parse_hex (
&self->text_click_color, "#FFFFFF");
ztk_color_parse_hex (
&self->bg_color, "#323232");
ztk_color_parse_hex (
&self->frame_color, "#646464");
ztk_color_parse_hex (
&self->separator_color, "#AAAAAA");
ztk_color_parse_hex (
&self->hover_color, "#646464");
ztk_color_parse_hex (
&self->click_color, "#868686");
}
/**
* Creates a new combobox.
*
* @param parent The parent widget to spawn on.
* @param spawn_upwards Spawn upwards instead of
* downards.
*/
ZtkComboBox *
ztk_combo_box_new (
ZtkWidget * parent,
int spawn_upwards,
int spawn_backwards)
{
ZtkComboBox * self =
calloc (1, sizeof (ZtkComboBox));
ZtkRect rect = { 0, 0, 0, 0 };
ztk_widget_init (
(ZtkWidget *) self, ZTK_WIDGET_TYPE_COMBO_BOX,
&rect, update_cb, draw_cb,
free_cb);
ZtkWidget * widget = (ZtkWidget *) self;
/* catch button events */
widget->button_event_cb = button_event_cb;
widget->motion_event_cb = motion_cb;
self->parent = parent;
self->upwards = spawn_upwards;
self->backwards = spawn_backwards;
ztk_combo_box_init (self);
self->hovered_idx = -1;
/* update dimensions */
get_dimensions (self, &widget->rect);
return self;
}
/**
* @param data Data related to the current element
* to pass to the activate callback.
*/
void
ztk_combo_box_add_text_element (
ZtkComboBox * self,
const char * label,
ZtkWidgetActivateCallback activate_cb,
void * data)
{
ZtkComboBoxElement * el =
&self->elements[self->num_elements++];
strcpy (el->label, label);
el->is_separator = 0;
el->activate_cb = activate_cb;
el->activate_cb_data = data;
/* update dimensions */
ZtkWidget * widget = (ZtkWidget *) self;
get_dimensions (self, &widget->rect);
}
void
ztk_combo_box_add_separator (
ZtkComboBox * self)
{
ZtkComboBoxElement * el =
&self->elements[self->num_elements++];
el->is_separator = 1;
/* update dimensions */
ZtkWidget * widget = (ZtkWidget *) self;
get_dimensions (self, &widget->rect);
}
void
ztk_combo_box_clear (
ZtkComboBox * self)
{
self->num_elements = 0;
}

3
src/ztk_drawing_area.c

@ -69,7 +69,8 @@ ztk_drawing_area_new ( @@ -69,7 +69,8 @@ ztk_drawing_area_new (
ZtkDrawingArea * self =
calloc (1, sizeof (ZtkDrawingArea));
ztk_widget_init (
(ZtkWidget *) self, rect,
(ZtkWidget *) self,
ZTK_WIDGET_TYPE_DRAWING_AREA, rect,
update_cb ? update_cb : ztk_drawing_area_update,
draw_cb,
ztk_drawing_area_free);

2
src/ztk_knob.c

@ -258,7 +258,7 @@ ztk_knob_new ( @@ -258,7 +258,7 @@ ztk_knob_new (
{
ZtkKnob * self = calloc (1, sizeof (ZtkKnob));
ztk_widget_init (
(ZtkWidget *) self, rect,
(ZtkWidget *) self, ZTK_WIDGET_TYPE_KNOB, rect,
ztk_knob_update_cb, ztk_knob_draw_cb,
ztk_knob_free);

3
src/ztk_knob_with_label.c

@ -79,7 +79,8 @@ ztk_knob_with_label_new ( @@ -79,7 +79,8 @@ ztk_knob_with_label_new (
calloc (1, sizeof (ZtkKnobWithLabel));
ztk_widget_init (
(ZtkWidget *) self, rect,
(ZtkWidget *) self,
ZTK_WIDGET_TYPE_KNOB_WITH_LABEL, rect,
ztk_knob_with_label_update_cb,
ztk_knob_with_label_draw_cb,
ztk_knob_with_label_free);

2
src/ztk_label.c

@ -75,7 +75,7 @@ ztk_label_new ( @@ -75,7 +75,7 @@ ztk_label_new (
x, y, 0, 0,
};
ztk_widget_init (
(ZtkWidget *) self, &rect,
(ZtkWidget *) self, ZTK_WIDGET_TYPE_LABEL, &rect,
ztk_label_update_cb, ztk_label_draw_cb,
ztk_label_free);

2
src/ztk_widget.c

@ -27,12 +27,14 @@ @@ -27,12 +27,14 @@
void
ztk_widget_init (
ZtkWidget * self,
ZtkWidgetType type,
ZtkRect * rect,
ZtkWidgetGenericCallback update_cb,
ZtkWidgetDrawCallback draw_cb,
ZtkWidgetGenericCallback free_cb)
{
self->rect = *rect;
self->type = type;
self->update_cb = update_cb;
self->draw_cb = draw_cb;
self->free_cb = free_cb;

8
tests/meson.build

@ -30,6 +30,14 @@ e = executable ( @@ -30,6 +30,14 @@ e = executable (
)
test ('color_test', e)
e = executable (
'ztk_app', 'ztk_app.c',
include_directories: inc_dirs,
link_with: ztoolkit_lib,
dependencies: deps,
)
test ('ztk_app_test', e)
if get_option('enable_rsvg')
e = executable (
'rsvg', 'rsvg.c',

62
tests/ztk_app.c

@ -0,0 +1,62 @@ @@ -0,0 +1,62 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZToolkit
*
* ZToolkit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZToolkit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with ZToolkit. If not, see <https://www.gnu.org/licenses/>.
*/
#include "helper.h"
#include <ztoolkit/ztk.h>
int main (
int argc, const char* argv[])
{
ZtkApp * app = calloc (1, sizeof (ZtkApp));
for (int i = 0; i < 24; i++)
{
ZtkWidget * widget =
calloc (1, sizeof (ZtkWidget));
ztk_app_add_widget (app, widget, 23 - i);
ztk_assert (widget->z == 23 - i);
}
ztk_assert (app->num_widgets == 24);
/* check z coordinate */
int last_z = 0;
for (int i = 0; i < 24; i++)
{
ZtkWidget * widget = app->widgets[i];
ztk_assert (widget->z >= last_z);
last_z = widget->z;
}
/* remove widgets */
ztk_app_remove_widget (app, app->widgets[23]);
ztk_assert (app->num_widgets == 23);
ztk_assert (app->widgets[22]->z == 22);
ztk_app_remove_widget (app, app->widgets[0]);
ztk_assert (app->num_widgets == 22);
ztk_assert (app->widgets[0]->z == 1);
ztk_app_remove_widget (app, app->widgets[2]);
ztk_assert (app->num_widgets == 21);
ztk_assert (app->widgets[2]->z == 4);
return 0;
}
Loading…
Cancel
Save