#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "toolbar.h"
#include "menu.h"
#include "button.h"
#include "icon.h"
#include "list.h"
#include <cx/mempool.h>
#include <cx/hash_map.h>
#include <cx/linked_list.h>
#include <cx/array_list.h>
#include "../common/context.h"
#if UI_GTK2 ||
UI_GTK3
GtkWidget* ui_create_toolbar(UiObject *obj) {
GtkWidget *toolbar = gtk_toolbar_new();
#ifdef UI_GTK3
gtk_style_context_add_class(
gtk_widget_get_style_context(toolbar),
GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
#endif
CxMap *items = uic_get_toolbar_items();
CxList *left_defaults = uic_get_toolbar_defaults(
UI_TOOLBAR_LEFT);
CxList *center_defaults = uic_get_toolbar_defaults(
UI_TOOLBAR_CENTER);
CxList *right_defaults = uic_get_toolbar_defaults(
UI_TOOLBAR_RIGHT);
ui_toolbar_add_items(obj, toolbar, items, left_defaults);
ui_toolbar_add_items(obj, toolbar, items, center_defaults);
ui_toolbar_add_items(obj, toolbar, items, right_defaults);
return toolbar;
}
static void create_item(UiObject *obj, GtkWidget *toolbar, UiToolbarItemI *i) {
GtkToolbar *tb =
GTK_TOOLBAR(toolbar);
switch(i->type) {
case UI_TOOLBAR_ITEM: {
add_toolitem_widget(tb, (UiToolbarItem*)i, obj);
break;
}
case UI_TOOLBAR_TOGGLEITEM: {
add_toolitem_toggle_widget(tb, (UiToolbarToggleItem*)i, obj);
break;
}
case UI_TOOLBAR_MENU: {
add_toolitem_menu_widget(tb, (UiToolbarMenuItem*)i, obj);
break;
}
default: fprintf(stderr,
"toolbar item type unimplemented: %d\n", (
int)i->type);
}
}
void ui_toolbar_add_items(UiObject *obj, GtkWidget *toolbar, CxMap *items, CxList *defaults) {
CxIterator i = cxListIterator(defaults);
cx_foreach(
char*, def, i) {
UiToolbarItemI* item = uic_toolbar_get_item(def);
if (!item) {
fprintf(stderr,
"unknown toolbar item: %s\n", def);
continue;
}
create_item(obj, toolbar, item);
}
}
static void set_toolbutton_icon(GtkToolItem *item,
const char *icon_name) {
#if GTK_MAJOR_VERSION >=
3
gtk_tool_button_set_icon_name(
GTK_TOOL_BUTTON(item), icon_name);
#else
UiIcon *icon = ui_icon(icon_name,
24);
if(icon) {
GdkPixbuf *pixbuf = ui_icon_pixbuf(icon);
if(pixbuf) {
GtkWidget *image = gtk_image_new_from_pixbuf(pixbuf);
gtk_tool_button_set_icon_widget(
GTK_TOOL_BUTTON(item), image);
}
}
#endif
}
void add_toolitem_widget(GtkToolbar *tb, UiToolbarItem *item, UiObject *obj) {
GtkToolItem *button;
if(item->args.stockid) {
#ifdef UI_GTK2
button = gtk_tool_button_new_from_stock(item->args.stockid);
#else
button = gtk_tool_button_new(
NULL, item->args.label);
#endif
}
else {
button = gtk_tool_button_new(
NULL, item->args.label);
}
gtk_tool_item_set_homogeneous(button,
FALSE);
if(item->args.icon) {
set_toolbutton_icon(button, item->args.icon);
}
gtk_tool_item_set_is_important(button,
TRUE);
ui_set_widget_ngroups(obj->ctx,
GTK_WIDGET(button), item->args.groups, item->ngroups);
if(item->args.onclick) {
UiEventData *event = cxMalloc(
obj->ctx->allocator,
sizeof(UiEventData));
event->obj = obj;
event->callback = item->args.onclick;
event->userdata = item->args.onclickdata;
event->customdata =
NULL;
event->value =
0;
g_signal_connect(
button,
"clicked",
G_CALLBACK(ui_button_clicked),
event);
}
gtk_toolbar_insert(tb, button, -
1);
}
void add_toolitem_toggle_widget(GtkToolbar *tb, UiToolbarToggleItem *item, UiObject *obj) {
GtkToolItem *button;
if(item->args.stockid) {
#ifdef UI_GTK2
button = gtk_toggle_tool_button_new_from_stock(item->args.stockid);
#else
button = gtk_toggle_tool_button_new_from_stock(item->args.stockid);
#endif
}
else {
button = gtk_toggle_tool_button_new();
gtk_tool_item_set_homogeneous(button,
FALSE);
if(item->args.label) {
gtk_tool_button_set_label(
GTK_TOOL_BUTTON(button), item->args.label);
}
if(item->args.icon) {
set_toolbutton_icon(button, item->args.icon);
}
}
ui_set_widget_ngroups(obj->ctx,
GTK_WIDGET(button), item->args.groups, item->ngroups);
UiVar* var = uic_widget_var(obj->ctx, obj->ctx,
NULL, item->args.varname,
UI_VAR_INTEGER);
if(var) {
UiInteger *i = (UiInteger*)var->value;
if(i) {
i->get = ui_tool_toggle_button_get;
i->set = ui_tool_toggle_button_set;
i->obj = button;
if(i->value !=
0) {
gtk_toggle_tool_button_set_active(
GTK_TOGGLE_TOOL_BUTTON(button),
TRUE);
}
}
}
UiVarEventData *event = cxMalloc(
obj->ctx->allocator,
sizeof(UiVarEventData));
event->obj = obj;
event->callback = item->args.onchange;
event->userdata = item->args.onchangedata;
event->var = var;
g_signal_connect(
button,
"toggled",
G_CALLBACK(ui_tool_button_toggled),
event);
gtk_toolbar_insert(tb, button, -
1);
}
void ui_tool_button_toggled(GtkToggleToolButton *widget, UiVarEventData *event) {
UiEvent e;
e.obj = event->obj;
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata =
NULL;
e.intval = gtk_toggle_tool_button_get_active(widget);
if(event->callback) {
event->callback(&e, event->userdata);
}
UiVar *var = event->var;
UiInteger *i = var ? var->value :
NULL;
if(i) {
ui_notify_evt(i->observers, &e);
}
}
int64_t ui_tool_toggle_button_get(UiInteger *integer) {
integer->value = gtk_toggle_tool_button_get_active(
GTK_TOGGLE_TOOL_BUTTON(integer->obj));
return integer->value;
}
void ui_tool_toggle_button_set(UiInteger *integer,
int64_t value) {
gboolean s = value !=
0 ?
TRUE :
FALSE;
gtk_toggle_tool_button_set_active(
GTK_TOGGLE_TOOL_BUTTON(integer->obj), s);
integer->value = s;
}
typedef struct UiToolbarMenuWidget {
GtkWidget *button;
GtkMenu *menu;
} UiToolbarMenuWidget;
static void ui_toolbar_menubutton_clicked(GtkWidget *widget, UiToolbarMenuWidget *menu) {
int x;
gtk_menu_popup_at_widget(menu->menu, menu->button,
GDK_GRAVITY_SOUTH_WEST,
GDK_GRAVITY_NORTH_WEST,
NULL);
}
static void ui_toolbar_menubutton_destroy(GtkWidget *widget, UiToolbarMenuWidget *menu) {
free(menu);
}
void add_toolitem_menu_widget(GtkToolbar *tb, UiToolbarMenuItem *item, UiObject *obj) {
GtkToolItem *button;
if(item->args.stockid) {
#ifdef UI_GTK2
button = gtk_tool_button_new_from_stock(item->args.stockid);
#else
button = gtk_tool_button_new(
NULL, item->args.label);
#endif
}
else {
button = gtk_tool_button_new(
NULL, item->args.label);
}
gtk_tool_item_set_homogeneous(button,
FALSE);
if(item->args.icon) {
set_toolbutton_icon(button, item->args.icon);
}
gtk_tool_item_set_is_important(button,
TRUE);
gtk_toolbar_insert(tb, button, -
1);
GtkWidget *menu_widget = gtk_menu_new();
ui_add_menu_items(menu_widget,
0, &item->menu, obj);
gtk_widget_show_all(menu_widget);
UiToolbarMenuWidget *tbmenu = malloc(
sizeof(UiToolbarMenuWidget));
tbmenu->button =
GTK_WIDGET(button);
tbmenu->menu =
GTK_MENU(menu_widget);
g_signal_connect(
button,
"clicked",
G_CALLBACK(ui_toolbar_menubutton_clicked),
tbmenu);
g_signal_connect(
button,
"destroy",
G_CALLBACK(ui_toolbar_menubutton_destroy),
tbmenu);
}
#ifdef UI_GTK3
GtkWidget* ui_create_headerbar(UiObject *obj) {
GtkWidget *headerbar = gtk_header_bar_new();
CxMap *items = uic_get_toolbar_items();
CxList *left_defaults = uic_get_toolbar_defaults(
UI_TOOLBAR_LEFT);
CxList *center_defaults = uic_get_toolbar_defaults(
UI_TOOLBAR_CENTER);
CxList *right_defaults = uic_get_toolbar_defaults(
UI_TOOLBAR_RIGHT);
ui_toolbar_headerbar_add_items(obj, headerbar, items, left_defaults);
ui_toolbar_headerbar_add_items(obj, headerbar, items, center_defaults);
ui_toolbar_headerbar_add_items(obj, headerbar, items, right_defaults);
return headerbar;
}
static void hb_create_item(UiObject *obj, GtkWidget *toolbar, UiToolbarItemI *i) {
GtkHeaderBar *tb =
GTK_HEADER_BAR(toolbar);
switch(i->type) {
case UI_TOOLBAR_ITEM: {
add_headerbar_item_widget(tb, (UiToolbarItem*)i, obj);
break;
}
case UI_TOOLBAR_TOGGLEITEM: {
add_headerbar_item_toggle_widget(tb, (UiToolbarToggleItem*)i, obj);
break;
}
case UI_TOOLBAR_MENU: {
add_headerbar_item_menu_widget(tb, (UiToolbarMenuItem*)i, obj);
break;
}
default: fprintf(stderr,
"toolbar item type unimplemented: %d\n", (
int)i->type);
}
}
void ui_toolbar_headerbar_add_items(UiObject *obj, GtkWidget *headerbar, CxMap *items, CxList *defaults) {
CxIterator i = cxListIterator(defaults);
cx_foreach(
char*, def, i) {
UiToolbarItemI* item = uic_toolbar_get_item(def);
if (!item) {
fprintf(stderr,
"unknown toolbar item: %s\n", def);
continue;
}
hb_create_item(obj, headerbar, item);
}
}
void add_headerbar_item_widget(GtkHeaderBar *hb, UiToolbarItem *item, UiObject *obj) {
GtkWidget *button = gtk_button_new_with_label(item->args.label);
if(item->args.icon) {
ui_button_set_icon_name(button, item->args.icon);
}
ui_set_widget_groups(obj->ctx, button, item->args.groups);
gtk_header_bar_pack_start(hb, button);
}
void add_headerbar_item_toggle_widget(GtkHeaderBar *hb, UiToolbarToggleItem *item, UiObject *obj) {
}
void add_headerbar_item_menu_widget(GtkHeaderBar *hb, UiToolbarMenuItem *item, UiObject *obj) {
}
#endif
#endif