Started writing the GTK+ menu code.
This commit is contained in:
parent
7618dd6237
commit
cfc4dfb787
12
new/ui.idl
12
new/ui.idl
|
@ -131,12 +131,12 @@ interface Tab from Control {
|
|||
func NewTab(void) *Tab;
|
||||
|
||||
interface Menu {
|
||||
func AddItem(name *const char) *MenuItem;
|
||||
func AddCheckItem(name *const char) *MenuItem;
|
||||
func AddQuitItem(void) *MenuItem;
|
||||
func AddPreferencesItem(void) *MenuItem;
|
||||
func AddAboutItem(void) *MenuItem;
|
||||
func AddSeparator(void);
|
||||
func AppendItem(name *const char) *MenuItem;
|
||||
func AppendCheckItem(name *const char) *MenuItem;
|
||||
func AppendQuitItem(void) *MenuItem;
|
||||
func AppendPreferencesItem(void) *MenuItem;
|
||||
func AppendAboutItem(void) *MenuItem;
|
||||
func AppendSeparator(void);
|
||||
};
|
||||
func NewMenu(name *const char) *Menu;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
osCFILES = \
|
||||
unix/alloc.c \
|
||||
unix/main.c \
|
||||
unix/menu.c \
|
||||
unix/oscontainer.c \
|
||||
unix/text.c \
|
||||
unix/util.c \
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
// 23 april 2015
|
||||
#include "uipriv_unix.h"
|
||||
|
||||
static GArray *menus = NULL;
|
||||
static gboolean menusFinalized = FALSE;
|
||||
|
||||
struct menu {
|
||||
uiMenu m;
|
||||
char *name;
|
||||
GHashTable *gtkMenuItems; // map[GtkWindow]GtkMenuItem
|
||||
GHashTable *gtkSubmenus; // map[GtkWindow]GtkMenu
|
||||
GArray *items; // []struct menuItem
|
||||
};
|
||||
|
||||
struct menuItem {
|
||||
uiMenuItem mi;
|
||||
char *name;
|
||||
int type;
|
||||
void (*onClicked)(uiMenuItem *, uiWindow *, void *);
|
||||
void *onClickedData;
|
||||
GtkWidget *baseItem; // for property binding
|
||||
GHashTable *uiWindows; // map[GtkMenuItem]uiWindow
|
||||
};
|
||||
|
||||
enum {
|
||||
typeRegular,
|
||||
typeCheckbox,
|
||||
typeQuit,
|
||||
typePreferences,
|
||||
typeAbout,
|
||||
typeSeparator,
|
||||
};
|
||||
|
||||
#define NEWHASH() g_hash_table_new(g_direct_hash, g_direct_equal)
|
||||
|
||||
static uiMenuItem *newItem(struct menu *m, int type, const char *name)
|
||||
{
|
||||
struct menuItem *item;
|
||||
|
||||
if (menusFinalized)
|
||||
complain("attempt to create a new menu item after menus have been finalized");
|
||||
|
||||
g_array_set_size(m->items, m->items->len + 1);
|
||||
item = &g_array_index(m->items, struct menuItem, m->items->len - 1);
|
||||
|
||||
item->type = type;
|
||||
switch (item->type) {
|
||||
case typeQuit:
|
||||
item->name = g_strdup("Quit");
|
||||
break;
|
||||
case typePreferences:
|
||||
item->name = g_strdup("Preferences...");
|
||||
break;
|
||||
case typeAbout:
|
||||
item->name = g_strdup("About");
|
||||
break;
|
||||
case typeSeparator:
|
||||
break;
|
||||
default:
|
||||
item->name = g_strdup(name);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (item->type) {
|
||||
case typeCheckbox:
|
||||
item->baseItem = gtk_check_menu_item_new_with_label(item->name);
|
||||
break;
|
||||
case typeSeparator:
|
||||
item->baseItem = gtk_separator_menu_item_new();
|
||||
break;
|
||||
default:
|
||||
item->baseItem = gtk_menu_item_new_with_label(item->name);
|
||||
break;
|
||||
}
|
||||
|
||||
item->uiWindows = NEWHASH();
|
||||
|
||||
// TODO vtable
|
||||
|
||||
return uiMenuItem(item);
|
||||
}
|
||||
|
||||
uiMenuItem *menuAppendItem(uiMenu *mm, const char *name)
|
||||
{
|
||||
return newItem((struct menu *) mm, typeRegular, name);
|
||||
}
|
||||
|
||||
uiMenuItem *menuAppendCheckItem(uiMenu *mm, const char *name)
|
||||
{
|
||||
return newItem((struct menu *) mm, typeCheckbox, name);
|
||||
}
|
||||
|
||||
uiMenuItem *menuAppendQuitItem(uiMenu *mm)
|
||||
{
|
||||
// TODO check multiple quit items
|
||||
// TODO conditionally add separator
|
||||
newItem((struct menu *) mm, typeSeparator, NULL);
|
||||
return newItem((struct menu *) mm, typeQuit, NULL);
|
||||
}
|
||||
|
||||
uiMenuItem *menuAppendPreferencesItem(uiMenu *mm)
|
||||
{
|
||||
// TODO check multiple preferences items
|
||||
// TODO conditionally add separator
|
||||
newItem((struct menu *) mm, typeSeparator, NULL);
|
||||
return newItem((struct menu *) mm, typePreferences, NULL);
|
||||
}
|
||||
|
||||
uiMenuItem *menuAppendAboutItem(uiMenu *mm)
|
||||
{
|
||||
// TODO check multiple about items
|
||||
// TODO conditionally add separator
|
||||
newItem((struct menu *) mm, typeSeparator, NULL);
|
||||
return newItem((struct menu *) mm, typeAbout, NULL);
|
||||
}
|
||||
|
||||
void menuAppendSeparator(uiMenu *mm)
|
||||
{
|
||||
// TODO check multiple about items
|
||||
newItem((struct menu *) mm, typeSeparator, NULL);
|
||||
}
|
||||
|
||||
uiMenu *uiNewMenu(const char *name)
|
||||
{
|
||||
struct menu *m;
|
||||
|
||||
if (menusFinalized)
|
||||
complain("attempt to create a new menu after menus have been finalized");
|
||||
if (menus == NULL)
|
||||
menus = g_array_new(FALSE, TRUE, sizeof (struct menu));
|
||||
|
||||
// thanks Company in irc.gimp.net/#gtk+
|
||||
g_array_set_size(menus, menus->len + 1);
|
||||
m = &g_array_index(menus, struct menu, menus->len - 1);
|
||||
|
||||
m->name = g_strdup(name);
|
||||
m->gtkMenuItems = NEWHASH();
|
||||
m->gtkSubmenus = NEWHASH();
|
||||
m->items = g_array_new(FALSE, TRUE, sizeof (struct menuItem));
|
||||
|
||||
uiMenu(m)->AppendItem = menuAppendItem;
|
||||
uiMenu(m)->AppendCheckItem = menuAppendCheckItem;
|
||||
uiMenu(m)->AppendQuitItem = menuAppendQuitItem;
|
||||
uiMenu(m)->AppendPreferencesItem = menuAppendPreferencesItem;
|
||||
uiMenu(m)->AppendAboutItem = menuAppendAboutItem;
|
||||
uiMenu(m)->AppendSeparator = menuAppendSeparator;
|
||||
|
||||
return uiMenu(m);
|
||||
}
|
||||
|
||||
/*
|
||||
void menuItemDestroy(struct menuItem *item)
|
||||
{
|
||||
// TODO checck that item->uiWindows is empty
|
||||
g_hash_table_destroy(item->uiWindows);
|
||||
gtk_widget_destroy(item->baseItem);
|
||||
if (item->name != NULL)
|
||||
g_free(item->name);
|
||||
}
|
||||
|
||||
void menuDestroy(void)
|
||||
{
|
||||
guint i, j;
|
||||
struct menu *m;
|
||||
|
||||
for (i = 0; i < menus->len; i++) {
|
||||
m = &g_array_index(menus, struct menu, i);
|
||||
for (j = 0; j < m->items->len; j++)
|
||||
menuItemDestroy(&g_array_index(m->items, struct menuItem, j));
|
||||
g_array_free(m->items, TRUE);
|
||||
// TODO check that m->gtkSubmenus is empty
|
||||
g_hash_table_destroy(m->gtkSubmenus);
|
||||
// TODO check that m->gtkMenuItem is empty
|
||||
g_hash_table_destroy(m->gtkMenuItem);
|
||||
g_free(m->name);
|
||||
}
|
||||
g_array_free(menus, TRUE);
|
||||
}
|
||||
*/
|
Loading…
Reference in New Issue