changeset 18440:be10fc22d649

Allow trigger keys for menuitems.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Fri, 06 Jul 2007 01:20:20 +0000
parents ec80e921818c
children 24ecab0d40b3
files finch/libgnt/gntmenu.c finch/libgnt/gntmenuitem.c finch/libgnt/gntmenuitem.h finch/libgnt/gnttree.c finch/libgnt/gnttree.h
diffstat 5 files changed, 125 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/finch/libgnt/gntmenu.c	Thu Jul 05 19:58:35 2007 +0000
+++ b/finch/libgnt/gntmenu.c	Fri Jul 06 01:20:20 2007 +0000
@@ -30,11 +30,20 @@
 	SIGS = 1,
 };
 
+enum
+{
+	ITEM_TEXT = 0,
+	ITEM_TRIGGER,
+	ITEM_SUBMENU,
+	NUM_COLUMNS
+};
+
 static GntTreeClass *parent_class = NULL;
 
 static void (*org_draw)(GntWidget *wid);
 static void (*org_destroy)(GntWidget *wid);
 static void (*org_map)(GntWidget *wid);
+static void (*org_size_request)(GntWidget *wid);
 static gboolean (*org_key_pressed)(GntWidget *w, const char *t);
 
 static void
@@ -75,21 +84,26 @@
 		widget->priv.height = 1;
 		widget->priv.width = getmaxx(stdscr);
 	} else {
+		org_size_request(widget);
 		widget->priv.height = g_list_length(menu->list) + 2;
-		widget->priv.width = 25;  /* XXX: */
 	}
 }
 
 static void
 menu_tree_add(GntMenu *menu, GntMenuItem *item, GntMenuItem *parent)
 {
+	char trigger[4] = "\0 )\0";
+
+	if ((trigger[1] = gnt_menuitem_get_trigger(item)))
+		trigger[0] = '(';
+
 	if (GNT_IS_MENU_ITEM_CHECK(item)) {
 		gnt_tree_add_choice(GNT_TREE(menu), item,
-			gnt_tree_create_row(GNT_TREE(menu), item->text, " "), parent, NULL);
+			gnt_tree_create_row(GNT_TREE(menu), item->text, trigger, " "), parent, NULL);
 		gnt_tree_set_choice(GNT_TREE(menu), item, gnt_menuitem_check_get_checked(GNT_MENU_ITEM_CHECK(item)));
 	} else
 		gnt_tree_add_row_last(GNT_TREE(menu), item,
-			gnt_tree_create_row(GNT_TREE(menu), item->text, item->submenu ? ">" : " "), parent);
+			gnt_tree_create_row(GNT_TREE(menu), item->text, trigger, item->submenu ? ">" : " "), parent);
 
 	if (0 && item->submenu) {
 		GntMenu *sub = GNT_MENU(item->submenu);
@@ -149,6 +163,41 @@
 	}
 }
 
+static GList*
+find_item_with_trigger(GList *start, GList *end, char trigger)
+{
+	GList *iter;
+	for (iter = start; iter != (end ? end : NULL); iter = iter->next) {
+		if (gnt_menuitem_get_trigger(iter->data) == trigger)
+			return iter;
+	}
+	return NULL;
+}
+
+static gboolean
+check_for_trigger(GntMenu *menu, char trigger)
+{
+	/* check for a trigger key */
+	GList *iter;
+	GList *nth = g_list_find(menu->list, gnt_tree_get_selection_data(GNT_TREE(menu)));
+	GList *find = find_item_with_trigger(nth->next, NULL, trigger);
+	if (!find)
+		find = find_item_with_trigger(menu->list, nth->next, trigger);
+	if (!find)
+		return FALSE;
+	if (find != nth) {
+		gnt_tree_set_selected(GNT_TREE(menu), find->data);
+		iter = find_item_with_trigger(find->next, NULL, trigger);
+		if (iter != NULL && iter != find)
+			return TRUE;
+		iter = find_item_with_trigger(menu->list, nth, trigger);
+		if (iter != NULL && iter != find)
+			return TRUE;
+	}
+	gnt_widget_activate(GNT_WIDGET(menu));
+	return TRUE;
+}
+
 static gboolean
 gnt_menu_key_pressed(GntWidget *widget, const char *text)
 {
@@ -189,6 +238,10 @@
 			return TRUE;
 		}
 	} else {
+		if (text[1] == '\0') {
+			if (check_for_trigger(menu, text[0]))
+				return TRUE;
+		}
 		return org_key_pressed(widget, text);
 	}
 
@@ -260,6 +313,7 @@
 	org_map = wid_class->map;
 	org_draw = wid_class->draw;
 	org_key_pressed = wid_class->key_pressed;
+	org_size_request = wid_class->size_request;
 
 	wid_class->destroy = gnt_menu_destroy;
 	wid_class->draw = gnt_menu_draw;
@@ -327,9 +381,11 @@
 		widget->priv.y = 0;
 	} else {
 		GNT_TREE(widget)->show_separator = FALSE;
-		_gnt_tree_init_internals(GNT_TREE(widget), 2);
-		gnt_tree_set_col_width(GNT_TREE(widget), 1, 1);  /* The second column is to indicate that it has a submenu */
-		gnt_tree_set_column_resizable(GNT_TREE(widget), 1, FALSE);
+		_gnt_tree_init_internals(GNT_TREE(widget), NUM_COLUMNS);
+		gnt_tree_set_col_width(GNT_TREE(widget), ITEM_TRIGGER, 3);
+		gnt_tree_set_column_resizable(GNT_TREE(widget), ITEM_TRIGGER, FALSE);
+		gnt_tree_set_col_width(GNT_TREE(widget), ITEM_SUBMENU, 1);
+		gnt_tree_set_column_resizable(GNT_TREE(widget), ITEM_SUBMENU, FALSE);
 		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
 	}
 
--- a/finch/libgnt/gntmenuitem.c	Thu Jul 05 19:58:35 2007 +0000
+++ b/finch/libgnt/gntmenuitem.c	Fri Jul 06 01:20:20 2007 +0000
@@ -104,3 +104,13 @@
 	item->submenu = menu;
 }
 
+void gnt_menuitem_set_trigger(GntMenuItem *item, char trigger)
+{
+	item->priv.trigger = trigger;
+}
+
+char gnt_menuitem_get_trigger(GntMenuItem *item)
+{
+	return item->priv.trigger;
+}
+
--- a/finch/libgnt/gntmenuitem.h	Thu Jul 05 19:58:35 2007 +0000
+++ b/finch/libgnt/gntmenuitem.h	Fri Jul 06 01:20:20 2007 +0000
@@ -52,6 +52,7 @@
 	/* These will be used to determine the position of the submenu */
 	int x;
 	int y;
+	char trigger;
 };
 
 typedef void (*GntMenuItemCallback)(GntMenuItem *item, gpointer data);
@@ -114,6 +115,25 @@
  */
 void gnt_menuitem_set_submenu(GntMenuItem *item, GntMenu *menu);
 
+/**
+ * Set a trigger key for the item.
+ *
+ * @param item     The menuitem
+ * @param trigger  The key that will trigger the item when the parent manu is visible
+ */
+void gnt_menuitem_set_trigger(GntMenuItem *item, char trigger);
+
+/**
+ * Get the trigger key for a menuitem.
+ *
+ * @param item   The menuitem
+ *
+ * @return The trigger key for the menuitem.
+ *
+ * @see gnt_menuitem_set_trigger
+ */
+char gnt_menuitem_get_trigger(GntMenuItem *item);
+
 G_END_DECLS
 
 #endif /* GNT_MENUITEM_H */
--- a/finch/libgnt/gnttree.c	Thu Jul 05 19:58:35 2007 +0000
+++ b/finch/libgnt/gnttree.c	Fri Jul 06 01:20:20 2007 +0000
@@ -86,13 +86,15 @@
 	int width;
 #define WIDTH(i) (tree->columns[i].width_ratio ? tree->columns[i].width_ratio : tree->columns[i].width)
 	gnt_widget_get_size(GNT_WIDGET(tree), &width, NULL);
+	if (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER))
+		width -= 2;
 	for (i = 0, total = 0; i < tree->ncol ; i++) {
 		if (tree->columns[i].flags & GNT_TREE_COLUMN_INVISIBLE)
 			continue;
 		if (tree->columns[i].flags & GNT_TREE_COLUMN_FIXED_SIZE)
-			width -= WIDTH(i);
+			width -= WIDTH(i) + 1;
 		else
-			total += WIDTH(i);
+			total += WIDTH(i) + 1;
 	}
 
 	if (total == 0)
@@ -283,10 +285,6 @@
 	GList *iter;
 	int i;
 	gboolean notfirst = FALSE;
-	int lastvisible = tree->ncol;
-
-	while (lastvisible && COLUMN_INVISIBLE(tree, lastvisible))
-		lastvisible--;
 
 	for (i = 0, iter = row->columns; i < tree->ncol && iter; i++, iter = iter->next)
 	{
@@ -308,7 +306,7 @@
 
 		len = gnt_util_onscreen_width(display, NULL);
 
-		if (i == lastvisible)
+		if (i == tree->lastvisible)
 			width = GNT_WIDGET(tree)->priv.width - gnt_util_onscreen_width(string->str, NULL);
 		else
 			width = tree->columns[i].width;
@@ -339,8 +337,7 @@
 				g_string_append_printf(string, "%*s", fl, "");
 			}
 			len += fl;
-		}
-		else if (notfirst)
+		} else if (notfirst && tree->show_separator)
 			g_string_append_c(string, '|');
 		else
 			g_string_append_c(string, ' ');
@@ -598,9 +595,13 @@
 	{
 		GntTree *tree = GNT_TREE(widget);
 		int i, width = 0;
+		width = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER));
 		for (i = 0; i < tree->ncol; i++)
-			if (!COLUMN_INVISIBLE(tree, i))
-				width += tree->columns[i].width + 1;
+			if (!COLUMN_INVISIBLE(tree, i)) {
+				width = width + tree->columns[i].width;
+				if (tree->lastvisible != i)
+					width++;
+			}
 		widget->priv.width = width;
 	}
 }
@@ -1502,6 +1503,7 @@
 	tree->ncol = col;
 	tree->hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_tree_row);
 	tree->columns = g_new0(struct _GntTreeColInfo, col);
+	tree->lastvisible = col - 1;
 	while (col--)
 	{
 		tree->columns[col].width = 15;
@@ -1647,9 +1649,14 @@
 
 	twidth = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER));
 	for (i = 0; i < tree->ncol; i++) {
+		if (tree->columns[i].flags & GNT_TREE_COLUMN_FIXED_SIZE)
+			widths[i] = tree->columns[i].width;
 		gnt_tree_set_col_width(tree, i, widths[i]);
-		if (!COLUMN_INVISIBLE(tree, i))
-			twidth += widths[i] + (tree->show_separator ? 1 : 0) + 1;
+		if (!COLUMN_INVISIBLE(tree, i)) {
+			twidth = twidth + widths[i];
+			if (tree->lastvisible != i)
+				twidth += 1;
+		}
 	}
 	g_free(widths);
 
@@ -1676,6 +1683,18 @@
 {
 	g_return_if_fail(col < tree->ncol);
 	set_column_flag(tree, col, GNT_TREE_COLUMN_INVISIBLE, !vis);
+	if (vis) {
+		/* the column is visible */
+		if (tree->lastvisible < col)
+			tree->lastvisible = col;
+	} else {
+		if (tree->lastvisible == col)
+			while (tree->lastvisible) {
+				tree->lastvisible--;
+				if (!COLUMN_INVISIBLE(tree, tree->lastvisible))
+					break;
+			}
+	}
 }
 
 void gnt_tree_set_column_resizable(GntTree *tree, int col, gboolean res)
--- a/finch/libgnt/gnttree.h	Thu Jul 05 19:58:35 2007 +0000
+++ b/finch/libgnt/gnttree.h	Fri Jul 06 01:20:20 2007 +0000
@@ -86,6 +86,7 @@
 	int search_timeout;
 
 	GCompareFunc compare;
+	int lastvisible;
 };
 
 struct _GntTreeClass