diff --git a/inc/widget_builder.h b/inc/widget_builder.h new file mode 100644 index 0000000..60c0857 --- /dev/null +++ b/inc/widget_builder.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 Scoopta + * This file is part of Wofi + * Wofi is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Wofi 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Wofi. If not, see . + */ + +#ifndef WIDGET_BUILDER_H +#define WIDGET_BUILDER_H + +#include + +#include + +struct widget_builder { + WofiPropertyBox* box; + struct widget* widget; + struct mode* mode; + size_t actions; +}; + +void wofi_free_widget_builder(struct widget_builder* builder); + +#endif diff --git a/inc/widget_builder_api.h b/inc/widget_builder_api.h new file mode 100644 index 0000000..d839c3e --- /dev/null +++ b/inc/widget_builder_api.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 Scoopta + * This file is part of Wofi + * Wofi is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Wofi 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Wofi. If not, see . + */ + +#ifndef WIDGET_BUILDER_API_H +#define WIDGET_BUILDER_API_H + +#include + +#include + +#include + +struct widget_builder* wofi_create_widget_builder(struct mode* mode, size_t actions); + +void wofi_widget_builder_set_search_text(struct widget_builder* builder, char* search_text); + +void wofi_widget_builder_set_action(struct widget_builder* builder, char* action); + +void wofi_widget_builder_insert_text(struct widget_builder* builder, char* text, char* css_name); + +void wofi_widget_builder_insert_image(struct widget_builder* builder, GdkPixbuf* pixbuf, char* css_name); + +struct widget_builder* wofi_widget_builder_get_idx(struct widget_builder* builder, size_t idx); + +struct widget* wofi_widget_builder_get_widget(struct widget_builder* builder); + +#endif diff --git a/inc/wofi.h b/inc/wofi.h index dc9247a..531891e 100644 --- a/inc/wofi.h +++ b/inc/wofi.h @@ -24,6 +24,21 @@ #include +#include + +struct widget { + size_t action_count; + char* mode, **text, *search_text, **actions; + struct widget_builder* builder; +}; + +struct mode { + void (*mode_exec)(const gchar* cmd); + struct widget* (*mode_get_widget)(void); + char* name, *dso; + struct wl_list link; +}; + void wofi_init(struct map* config); void wofi_load_css(bool nyan); diff --git a/man/wofi-widget-builder.3 b/man/wofi-widget-builder.3 new file mode 100644 index 0000000..3b8bc41 --- /dev/null +++ b/man/wofi-widget-builder.3 @@ -0,0 +1,79 @@ +.TH wofi\-widget\-builder 3 +.SH NAME +wofi \- Widget builder API functions + +.SH DESCRIPTION +The functions documented here are used for building custom widgets with more power and flexibility than previously allowed. They are defined in wofi_widget_builder_api.h + +.TP +.B struct widget_builder* wofi_create_widget_builder(struct mode* mode, size_t actions) +Creates multiple widget builders. The number of builders created is specified by actions and is returned as an array. + +.B struct mode* mode +\- The \fBstruct mode*\fR given to your mode's \fBinit()\fR function. + +.B size_t actions +\- The number of builders to create + +.TP +.B void wofi_widget_builder_set_search_text(struct widget_builder* builder, char* search_text) +Sets the search text for the widget specified by the builder + +.B struct widget_builder* builder +\- The builder that contains the widget to set the search text for + +.B char* search_text +\- The text to set as the search text + +.TP +.B void wofi_widget_builder_set_action(struct widget_builder* builder, char* action) +Sets the action for the widget specified by the builder + +.B struct widget_builder* builder +\- The builder that contains the widget to set the action for + +.B char* action +\- The text to set as the action + +.TP +.B void wofi_widget_builder_insert_text(struct widget_builder* builder, char* text, char* css_name) +Inserts text into the widget specified by the builder + +.B struct widget_builder* builder +\- The builder that contains the widget to add the text to + +.B char* text +\- The text to add to the widget + +.B char* css_name +\- The name of the CSS node for this text. The name that will be assigned is #mode_name-css_name where mode_name is the name of the mode, i.e. drun etc. + +.TP +.B void wofi_widget_builder_insert_image(struct widget_builder* builder, GdkPixbuf* pixbuf, char* css_name) +Inserts an image into the widget specified by the builder + +.B struct widget_builder* builder +\- The builder that contains the widget to add the image to + +.B GdkPixbuf* pixbuf +\- The image to add to the widget + +.B char* css_name +\- The name of the CSS node for this image. The name that will be assigned is #mode_name-css_name where mode_name is the name of the mode, i.e. drun etc. + +.TP +.B struct widget_builder* wofi_widget_builder_get_idx(struct widget_builder* builder, size_t idx) +Gets the widget_builder at the provided index in the array + +.B struct widget_builder* builder +\- The array of builders to get the builder from + +.B size_t idx +\- The index in the array to get + +.TP +.B struct widget* wofi_widget_builder_get_widget(struct widget_builder* builder) +Constructs a new widget from the specified builder, the widget can be returned by \fBstruct widget* get_widget(void)\fR + +.B struct widget_builder* builder +\- The builder to construct a widget for diff --git a/meson.build b/meson.build index 13b2bc2..0f84ae8 100644 --- a/meson.build +++ b/meson.build @@ -24,6 +24,7 @@ sources = ['src/config.c', 'src/map.c', 'src/property_box.c', 'src/utils.c', + 'src/widget_builder.c', 'src/wofi.c', 'proto/wlr-layer-shell-unstable-v1-protocol.c', 'proto/xdg-output-unstable-v1-protocol.c', diff --git a/src/widget_builder.c b/src/widget_builder.c new file mode 100644 index 0000000..d7c572f --- /dev/null +++ b/src/widget_builder.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2020 Scoopta + * This file is part of Wofi + * Wofi is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Wofi 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Wofi. If not, see . + */ + +#include + +#include +#include + +struct widget_builder* wofi_create_widget_builder(struct mode* mode, size_t actions) { + struct widget_builder* builder = calloc(actions, sizeof(struct widget_builder)); + + for(size_t count = 0; count < actions; ++count) { + builder[count].mode = mode; + builder[count].box = WOFI_PROPERTY_BOX(wofi_property_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); + + if(count == 0) { + builder->actions = actions; + } + } + return builder; +} + +void wofi_widget_builder_set_search_text(struct widget_builder* builder, char* search_text) { + wofi_property_box_add_property(builder->box, "filter", search_text); +} + +void wofi_widget_builder_set_action(struct widget_builder* builder, char* action) { + wofi_property_box_add_property(builder->box, "action", action); +} + +void wofi_widget_builder_insert_text(struct widget_builder* builder, char* text, char* css_name) { + GtkWidget* label = gtk_label_new(text); + gtk_container_add(GTK_CONTAINER(builder->box), label); + if(css_name != NULL) { + char* tmp = utils_concat(3, builder->mode->name, "-", css_name); + gtk_widget_set_name(label, tmp); + free(tmp); + } +} + +void wofi_widget_builder_insert_image(struct widget_builder* builder, GdkPixbuf* pixbuf, char* css_name) { + GtkWidget* img = gtk_image_new_from_pixbuf(pixbuf); + gtk_container_add(GTK_CONTAINER(builder->box), img); + if(css_name != NULL) { + char* tmp = utils_concat(3, builder->mode->name, "-", css_name); + gtk_widget_set_name(img, tmp); + free(tmp); + } +} + +struct widget_builder* wofi_widget_builder_get_idx(struct widget_builder* builder, size_t idx) { + return builder + idx; +} + +struct widget* wofi_widget_builder_get_widget(struct widget_builder* builder) { + if(builder->actions == 0) { + fprintf(stderr, "%s: This is not the 0 index of the widget_builder array\n", builder->mode->name); + return NULL; + } + + if(builder->widget == NULL) { + builder->widget = malloc(sizeof(struct widget)); + builder->widget->builder = builder; + builder->widget->action_count = builder->actions; + } + + for(size_t count = 0; count < builder->actions; ++count) { + } + + return builder->widget; +} + +void wofi_free_widget_builder(struct widget_builder* builder) { + if(builder->widget != NULL) { + free(builder->widget); + } + free(builder); +} diff --git a/src/wofi.c b/src/wofi.c index cbe5577..562c3cd 100644 --- a/src/wofi.c +++ b/src/wofi.c @@ -30,11 +30,11 @@ #include #include #include +#include #include #include -#include #include #include @@ -109,18 +109,6 @@ static struct wl_list outputs; static struct zxdg_output_manager_v1* output_manager; static struct zwlr_layer_surface_v1* wlr_surface; -struct mode { - void (*mode_exec)(const gchar* cmd); - struct widget* (*mode_get_widget)(void); - char* name, *dso; - struct wl_list link; -}; - -struct widget { - size_t action_count; - char* mode, **text, *search_text, **actions; -}; - struct output_node { char* name; struct wl_output* output; @@ -502,11 +490,17 @@ static gboolean _insert_widget(gpointer data) { if(node == NULL) { return FALSE; } + GtkWidget* parent; if(node->action_count > 1 && !no_actions) { parent = gtk_expander_new(""); g_signal_connect(parent, "activate", G_CALLBACK(expand), NULL); - GtkWidget* box = create_label(node->mode, node->text[0], node->search_text, node->actions[0]); + GtkWidget* box; + if(node->builder == NULL) { + box = create_label(node->mode, node->text[0], node->search_text, node->actions[0]); + } else { + box = GTK_WIDGET(node->builder->box); + } gtk_expander_set_label_widget(GTK_EXPANDER(parent), box); GtkWidget* exp_box = gtk_list_box_new(); @@ -514,7 +508,11 @@ static gboolean _insert_widget(gpointer data) { g_signal_connect(exp_box, "row-activated", G_CALLBACK(activate_item), NULL); gtk_container_add(GTK_CONTAINER(parent), exp_box); for(size_t count = 1; count < node->action_count; ++count) { - box = create_label(node->mode, node->text[count], node->search_text, node->actions[count]); + if(node->builder == NULL) { + box = create_label(node->mode, node->text[count], node->search_text, node->actions[count]); + } else { + box = GTK_WIDGET(node->builder[count].box); + } GtkWidget* row = gtk_list_box_row_new(); gtk_widget_set_name(row, "entry"); @@ -523,8 +521,13 @@ static gboolean _insert_widget(gpointer data) { gtk_container_add(GTK_CONTAINER(exp_box), row); } } else { - parent = create_label(node->mode, node->text[0], node->search_text, node->actions[0]); + if(node->builder == NULL) { + parent = create_label(node->mode, node->text[0], node->search_text, node->actions[0]); + } else { + parent = GTK_WIDGET(node->builder->box); + } } + gtk_widget_set_halign(parent, content_halign); GtkWidget* child = gtk_flow_box_child_new(); gtk_widget_set_name(child, "entry"); @@ -546,17 +549,21 @@ static gboolean _insert_widget(gpointer data) { gtk_widget_set_visible(box, FALSE); } - free(node->mode); - for(size_t count = 0; count < node->action_count; ++count) { - free(node->text[count]); + if(node->builder != NULL) { + wofi_free_widget_builder(node->builder); + } else { + free(node->mode); + for(size_t count = 0; count < node->action_count; ++count) { + free(node->text[count]); + } + free(node->text); + free(node->search_text); + for(size_t count = 0; count < node->action_count; ++count) { + free(node->actions[count]); + } + free(node->actions); + free(node); } - free(node->text); - free(node->search_text); - for(size_t count = 0; count < node->action_count; ++count) { - free(node->actions[count]); - } - free(node->actions); - free(node); return TRUE; } @@ -774,7 +781,7 @@ struct wl_list* wofi_read_cache(struct mode* mode) { } struct widget* wofi_create_widget(struct mode* mode, char* text[], char* search_text, char* actions[], size_t action_count) { - struct widget* widget = malloc(sizeof(struct widget)); + struct widget* widget = calloc(1, sizeof(struct widget)); widget->mode = strdup(mode->name); widget->text = malloc(action_count * sizeof(char*)); for(size_t count = 0; count < action_count; ++count) {