|
From: <gi...@gp...> - 2011-08-29 21:46:24
|
The branch, master has been updated
via 2fecf3a75bdbc47f8317fa92f361444bb885d23d (commit)
via 4e63bedd088a4830735d9161c50da94f6784314f (commit)
via 8eddcff25d69024c5afe336f9f1ddab7e341df49 (commit)
via 707dd2dc7245cec6f15adc1ae1f735944602c561 (commit)
via d721448d923feaad8a7c89410caff698fa52d0fd (commit)
from 448a50d473e83f4202a70df36fcffe30373ffc38 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
=========
Summary
=========
src/Makefile.am | 6 +-
src/hid/gtk/ghid-layer-selector.c | 432 ++++++++------
src/hid/gtk/ghid-layer-selector.h | 10 +-
src/hid/gtk/ghid-main-menu.c | 559 +++++++++++++++++
src/hid/gtk/ghid-main-menu.h | 42 ++
src/hid/gtk/gtkhid-main.c | 18 +-
src/hid/gtk/gui-command-window.c | 8 +-
src/hid/gtk/gui-output-events.c | 8 +-
src/hid/gtk/gui-top-window.c | 1235 ++++---------------------------------
src/hid/gtk/gui.h | 14 +-
10 files changed, 1001 insertions(+), 1331 deletions(-)
create mode 100644 src/hid/gtk/ghid-main-menu.c
create mode 100644 src/hid/gtk/ghid-main-menu.h
=================
Commit Messages
=================
commit 2fecf3a75bdbc47f8317fa92f361444bb885d23d
Author: Andrew Poelstra <as...@sf...>
Commit: Andrew Poelstra <as...@sf...>
Link GHidLayerSelector and GHidMainMenu
Layer visibility-toggle and selection menu items now appear
in the main menu. Accelerators work correctly and are reassigned
on deletion/addition of layers to simulate the old behavior.
:100644 100644 684f061... 582fe67... M src/hid/gtk/ghid-layer-selector.c
:100644 100644 bfeffe9... 10355a7... M src/hid/gtk/ghid-layer-selector.h
:100644 100644 945b522... 5693c56... M src/hid/gtk/ghid-main-menu.c
:100644 100644 3b8c728... d667e34... M src/hid/gtk/ghid-main-menu.h
:100644 100644 b2d9c22... c292660... M src/hid/gtk/gui-top-window.c
commit 4e63bedd088a4830735d9161c50da94f6784314f
Author: Andrew Poelstra <as...@sf...>
Commit: Andrew Poelstra <as...@sf...>
Clean up layer data handling in ghid-layer-selector.c
:100644 100644 bd57f57... 684f061... M src/hid/gtk/ghid-layer-selector.c
commit 8eddcff25d69024c5afe336f9f1ddab7e341df49
Author: Andrew Poelstra <as...@sf...>
Commit: Andrew Poelstra <as...@sf...>
Give GHidLayerSelector an internal layer structure
Before we had various arrays to resize and index; now each
row has a structure associated with it, that is easier to
access and maintain.
:100644 100644 7f11f7f... bd57f57... M src/hid/gtk/ghid-layer-selector.c
commit 707dd2dc7245cec6f15adc1ae1f735944602c561
Author: Andrew Poelstra <as...@sf...>
Commit: Andrew Poelstra <as...@sf...>
Replace gtk UI manager with GHidMainMenu widget
This commit replaces the old UI manager with a customize gtk
widget that builds menus directly from a resource tree. This
eliminates the translate-to-XML step, the ugly hacks used to
access individual actions, and all the associated manual
memory management.
This will also give us the ability to have more dynamic menus,
in particular layer lists without maximum capacities.
Layers and route styles are still not hooked into the menu.
This means that those accelerators DO NOT WORK. (This will
be fixed in a later commit.) Checkboxes have been replaced
with radio buttons where appropriate. There are now tearoffs
on the context-menu's submenus.
Other than that, there should be no user-visible changes. ;)
:100644 100644 0c9019d... 46a9347... M src/hid/gtk/gtkhid-main.c
:100644 100644 b08836e... 1728bd3... M src/hid/gtk/gui-command-window.c
:100644 100644 5929a37... b9c5ab3... M src/hid/gtk/gui-output-events.c
:100644 100644 b4dbcaa... b2d9c22... M src/hid/gtk/gui-top-window.c
:100644 100644 30ff593... e7e5f55... M src/hid/gtk/gui.h
commit d721448d923feaad8a7c89410caff698fa52d0fd
Author: Andrew Poelstra <as...@sf...>
Commit: Andrew Poelstra <as...@sf...>
Created ghid-main-menu.[ch]
Still need to hook up layer selector and route styles.
:100644 100644 4b66ac7... a9c51b2... M src/Makefile.am
:000000 100644 0000000... 945b522... A src/hid/gtk/ghid-main-menu.c
:000000 100644 0000000... 3b8c728... A src/hid/gtk/ghid-main-menu.h
=========
Changes
=========
commit 2fecf3a75bdbc47f8317fa92f361444bb885d23d
Author: Andrew Poelstra <as...@sf...>
Commit: Andrew Poelstra <as...@sf...>
Link GHidLayerSelector and GHidMainMenu
Layer visibility-toggle and selection menu items now appear
in the main menu. Accelerators work correctly and are reassigned
on deletion/addition of layers to simulate the old behavior.
diff --git a/src/hid/gtk/ghid-layer-selector.c b/src/hid/gtk/ghid-layer-selector.c
index 684f061..582fe67 100644
--- a/src/hid/gtk/ghid-layer-selector.c
+++ b/src/hid/gtk/ghid-layer-selector.c
@@ -56,10 +56,13 @@ struct _GHidLayerSelector
GtkTreeViewColumn *visibility_column;
GtkActionGroup *action_group;
+ GtkAccelGroup *accel_group;
GSList *radio_group;
int n_actions;
+ gboolean accel_available[20];
+
gboolean last_activatable;
gboolean prevent_recursion;
};
@@ -74,6 +77,9 @@ struct _GHidLayerSelectorClass
struct _layer
{
+ gint accel_index; /* Index into ls->accel_available */
+ GtkWidget *pick_item;
+ GtkWidget *view_item;
GtkToggleAction *view_action;
GtkRadioAction *pick_action;
GtkTreeRowReference *rref;
@@ -102,6 +108,8 @@ free_ldata (GHidLayerSelector *ls, struct _layer *ldata)
g_object_unref (G_OBJECT (ldata->view_action));
}
gtk_tree_row_reference_free (ldata->rref);
+ if (ldata->accel_index >= 0)
+ ls->accel_available[ldata->accel_index] = TRUE;
g_free (ldata);
}
@@ -278,6 +286,7 @@ ghid_layer_selector_finalize (GObject *object)
GtkTreeIter iter;
GHidLayerSelector *ls = (GHidLayerSelector *) object;
+ g_object_unref (ls->accel_group);
g_object_unref (ls->action_group);
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls->list_store), &iter);
@@ -334,6 +343,7 @@ ghid_layer_selector_get_type (void)
GtkWidget *
ghid_layer_selector_new (void)
{
+ int i;
GtkCellRenderer *renderer1 = ghid_cell_renderer_visibility_new ();
GtkCellRenderer *renderer2 = gtk_cell_renderer_text_new ();
GtkTreeViewColumn *opacity_col =
@@ -361,9 +371,12 @@ ghid_layer_selector_new (void)
ls->last_activatable = TRUE;
ls->visibility_column = opacity_col;
ls->selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ls));
+ ls->accel_group = gtk_accel_group_new ();
ls->action_group = gtk_action_group_new ("LayerSelector");
ls->prevent_recursion = FALSE;
ls->n_actions = 0;
+ for (i = 0; i < 20; ++i)
+ ls->accel_available[i] = TRUE;
gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (ls),
tree_view_separator_func,
@@ -378,7 +391,7 @@ ghid_layer_selector_new (void)
g_signal_connect (ls->selection, "changed",
G_CALLBACK (selection_changed_cb), ls);
- g_object_ref (ls->action_group);
+ g_object_ref (ls->accel_group);
return GTK_WIDGET (ls);
}
@@ -409,11 +422,12 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
gboolean activatable)
{
struct _layer *new_layer = NULL;
- gchar *pname, *vname, *paccel, *vaccel;
+ gchar *pname, *vname;
gboolean new_iter = TRUE;
gboolean last_activatable = TRUE;
GtkTreePath *path;
GtkTreeIter iter;
+ int i;
/* Look for existing layer with this ID */
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls->list_store), &iter))
@@ -484,24 +498,6 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
/* -- Setup new actions -- */
vname = g_strdup_printf ("LayerView%d", ls->n_actions);
pname = g_strdup_printf ("LayerPick%d", ls->n_actions);
- vaccel = NULL;
- paccel = NULL;
-
- /* Determine keyboard accelerators */
- if (ls->n_actions < 10)
- {
- /* Map 1-0 to actions 1-10 (with '0' meaning 10) */
- int i = (ls->n_actions + 1) % 10;
- vaccel = g_strdup_printf ("<Ctrl>%d", i);
- paccel = g_strdup_printf ("%d", i);
- }
- else
- {
- /* Map 1-0 to actions 11-20 (with '0' meaning 10) */
- int i = (ls->n_actions + 1) % 10;
- vaccel = g_strdup_printf ("<Alt><Ctrl>%d", i);
- paccel = g_strdup_printf ("<Alt>%d", i);
- }
/* Create row reference for actions */
path = gtk_tree_model_get_path (GTK_TREE_MODEL (ls->list_store), &iter);
@@ -516,12 +512,6 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
= gtk_radio_action_new (pname, name, NULL, NULL, user_id);
gtk_radio_action_set_group (new_layer->pick_action, ls->radio_group);
ls->radio_group = gtk_radio_action_get_group (new_layer->pick_action);
- gtk_action_group_add_action_with_accel
- (ls->action_group,
- GTK_ACTION (new_layer->pick_action),
- paccel);
- g_signal_connect (new_layer->pick_action, "toggled",
- G_CALLBACK (menu_pick_cb), new_layer);
}
else
new_layer->pick_action = NULL;
@@ -530,112 +520,148 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
new_layer->view_action = gtk_toggle_action_new (vname, name, NULL, NULL);
gtk_toggle_action_set_active (new_layer->view_action, visible);
- gtk_action_group_add_action_with_accel
- (ls->action_group,
- GTK_ACTION (new_layer->view_action),
- vaccel);
- g_signal_connect (new_layer->view_action, "toggled",
- G_CALLBACK (menu_view_cb), new_layer->rref);
-
-
/* Select new layer, if we need */
if (activatable
&& !gtk_tree_selection_get_selected (ls->selection, NULL, NULL))
gtk_tree_selection_select_iter (ls->selection, &iter);
- /* cleanup */
- if (vaccel)
+ /* Determine keyboard accelerators */
+ for (i = 0; i < 20; ++i)
+ if (ls->accel_available[i])
+ break;
+ if (i < 20)
{
- g_free (vaccel);
- g_free (paccel);
+ /* Map 1-0 to actions 1-10 (with '0' meaning 10) */
+ gchar *accel1 = g_strdup_printf ("%s%d",
+ i < 10 ? "" : "<Alt>",
+ (i + 1) % 10);
+ gchar *accel2 = g_strdup_printf ("<Ctrl>%s%d",
+ i < 10 ? "" : "<Alt>",
+ (i + 1) % 10);
+
+ if (activatable)
+ {
+ GtkAction *action = GTK_ACTION (new_layer->pick_action);
+ gtk_action_set_accel_group (action, ls->accel_group);
+ gtk_action_group_add_action_with_accel (ls->action_group,
+ action,
+ accel1);
+ gtk_action_connect_accelerator (action);
+ g_signal_connect (G_OBJECT (action), "activate",
+ G_CALLBACK (menu_pick_cb), new_layer);
+ }
+ gtk_action_set_accel_group (GTK_ACTION (new_layer->view_action),
+ ls->accel_group);
+ gtk_action_group_add_action_with_accel
+ (ls->action_group, GTK_ACTION (new_layer->view_action), accel2);
+ gtk_action_connect_accelerator (GTK_ACTION (new_layer->view_action));
+ g_signal_connect (G_OBJECT (new_layer->view_action), "activate",
+ G_CALLBACK (menu_view_cb), new_layer);
+
+ ls->accel_available[i] = FALSE;
+ new_layer->accel_index = i;
+ g_free (accel2);
+ g_free (accel1);
}
+ else
+ {
+ new_layer->accel_index = -1;
+ }
+ /* finalize new layer struct */
+ new_layer->pick_item = new_layer->view_item = NULL;
+
+ /* cleanup */
g_free (vname);
g_free (pname);
ls->n_actions++;
}
-/*! \brief used internally */
-static gboolean
-pick_xml_foreach_func (GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer data)
-{
- struct _layer *ldata;
- GString *str = data;
-
- gtk_tree_model_get (model, iter, STRUCT_COL, &ldata, -1);
- if (ldata && ldata->pick_action)
- g_string_append_printf (str, "<menuitem action=\"%s\" />\n",
- gtk_action_get_name (GTK_ACTION (ldata->pick_action)));
- return FALSE;
-}
-/*! \brief used internally */
-static gboolean
-view_xml_foreach_func (GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer data)
-{
- struct _layer *ldata;
- GString *str = data;
-
- gtk_tree_model_get (model, iter, STRUCT_COL, &ldata, -1);
- if (ldata && ldata->view_action)
- g_string_append_printf (str, "<menuitem action=\"%s\" />\n",
- gtk_action_get_name (GTK_ACTION (ldata->view_action)));
- return FALSE;
-}
-
-/*! \brief Get the "Current Layer" menu description of a layer selector
+/*! \brief Install the "Current Layer" menu items for a layer selector
* \par Function Description
- * Returns the XML content used by Gtk in building the layer-selection
- * part of the menu. This is a radio-button list describing which layer
- * is active.
+ * Takes a menu shell and installs menu items for layer selection in
+ * the shell, at the given position.
*
- * \param [in] ls The selector to be acted on
+ * \param [in] ls The selector to be acted on
+ * \param [in] shell The menu to install the items in
+ * \param [in] pos The position in the menu to install items
*
- * \return the requested XML
+ * \return the number of items installed
*/
-gchar *
-ghid_layer_selector_get_pick_xml (GHidLayerSelector *ls)
+gint
+ghid_layer_selector_install_pick_items (GHidLayerSelector *ls,
+ GtkMenuShell *shell, gint pos)
{
- GString *str = g_string_new ("");
- gtk_tree_model_foreach (GTK_TREE_MODEL (ls->list_store),
- pick_xml_foreach_func, str);
- return g_string_free (str, FALSE);
+ GtkTreeIter iter;
+ int n = 0;
+
+ gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls->list_store), &iter);
+ do
+ {
+ struct _layer *ldata;
+ gtk_tree_model_get (GTK_TREE_MODEL (ls->list_store),
+ &iter, STRUCT_COL, &ldata, -1);
+ if (ldata && ldata->pick_action)
+ {
+ GtkAction *action = GTK_ACTION (ldata->pick_action);
+ ldata->pick_item = gtk_action_create_menu_item (action);
+ gtk_menu_shell_insert (shell, ldata->pick_item, pos + n);
+ ++n;
+ }
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (ls->list_store), &iter));
+
+ return n;
}
-/*! \brief Get the "Shown Layers" menu description of a layer selector
+/*! \brief Install the "Shown Layers" menu items for a layer selector
* \par Function Description
- * Returns the XML content used by Gtk in building the layer-selection
- * part of the menu. This is a toggle-button list describing which layer(s)
- * are visible.
+ * Takes a menu shell and installs menu items for layer selection in
+ * the shell, at the given position.
*
- * \param [in] ls The selector to be acted on
+ * \param [in] ls The selector to be acted on
+ * \param [in] shell The menu to install the items in
+ * \param [in] pos The position in the menu to install items
*
- * \return the requested XML
+ * \return the number of items installed
*/
-gchar *
-ghid_layer_selector_get_view_xml (GHidLayerSelector *ls)
+gint
+ghid_layer_selector_install_view_items (GHidLayerSelector *ls,
+ GtkMenuShell *shell, gint pos)
{
- GString *str = g_string_new ("");
- gtk_tree_model_foreach (GTK_TREE_MODEL (ls->list_store),
- view_xml_foreach_func, str);
- return g_string_free (str, FALSE);
+ GtkTreeIter iter;
+ int n = 0;
+
+ gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls->list_store), &iter);
+ do
+ {
+ struct _layer *ldata;
+ gtk_tree_model_get (GTK_TREE_MODEL (ls->list_store),
+ &iter, STRUCT_COL, &ldata, -1);
+ if (ldata && ldata->view_action)
+ {
+ GtkAction *action = GTK_ACTION (ldata->view_action);
+ ldata->view_item = gtk_action_create_menu_item (action);
+ gtk_menu_shell_insert (shell, ldata->view_item, pos + n);
+ ++n;
+ }
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (ls->list_store), &iter));
+
+ return n;
}
-/*! \brief Get the GtkActionGroup containing accelerators, etc, of a layer selector
+/*! \brief Returns the GtkAccelGroup of a layer selector
* \par Function Description
- * Returns the GtkActionGroup containing the toggle and radio buttons used
- * in the menu. Also contains the accelerators. This action group should be
- * added to the main UI. See Gtk docs for details.
*
* \param [in] ls The selector to be acted on
*
- * \return the action group of the selector
+ * \return the accel group of the selector
*/
-GtkActionGroup *
-ghid_layer_selector_get_action_group (GHidLayerSelector *ls)
+GtkAccelGroup *
+ghid_layer_selector_get_accel_group (GHidLayerSelector *ls)
{
- return ls->action_group;
+ return ls->accel_group;
}
/*! \brief used internally */
diff --git a/src/hid/gtk/ghid-layer-selector.h b/src/hid/gtk/ghid-layer-selector.h
index bfeffe9..10355a7 100644
--- a/src/hid/gtk/ghid-layer-selector.h
+++ b/src/hid/gtk/ghid-layer-selector.h
@@ -26,9 +26,13 @@ void ghid_layer_selector_add_layer (GHidLayerSelector *ls,
gboolean visible,
gboolean activatable);
GtkAccelGroup *ghid_layer_selector_get_accel_group (GHidLayerSelector *ls);
-gchar *ghid_layer_selector_get_pick_xml (GHidLayerSelector *ls);
-gchar *ghid_layer_selector_get_view_xml (GHidLayerSelector *ls);
-GtkActionGroup *ghid_layer_selector_get_action_group (GHidLayerSelector *ls);
+
+gint ghid_layer_selector_install_pick_items (GHidLayerSelector *ls,
+ GtkMenuShell *shell, gint pos);
+gint ghid_layer_selector_install_view_items (GHidLayerSelector *ls,
+ GtkMenuShell *shell, gint pos);
+
+GtkAccelGroup *ghid_layer_selector_get_accel_group (GHidLayerSelector *ls);
void ghid_layer_selector_toggle_layer (GHidLayerSelector *ls,
gint user_id);
diff --git a/src/hid/gtk/ghid-main-menu.c b/src/hid/gtk/ghid-main-menu.c
index 945b522..5693c56 100644
--- a/src/hid/gtk/ghid-main-menu.c
+++ b/src/hid/gtk/ghid-main-menu.c
@@ -13,6 +13,7 @@
#include "pcb-printf.h"
#include "ghid-main-menu.h"
+#include "ghid-layer-selector.h"
void Message (const char *, ...);
@@ -36,10 +37,13 @@ struct _GHidMainMenu
GList *actions;
GHashTable *popup_table;
+ gint n_layer_views;
+ gint n_layer_picks;
+ gint n_route_styles;
+
GCallback action_cb;
void (*special_key_cb) (const char *accel, GtkAction *action,
const Resource *node);
-
};
struct _GHidMainMenuClass
@@ -433,6 +437,9 @@ ghid_main_menu_new (GCallback action_cb,
mm->layer_view_pos = 0;
mm->layer_pick_pos = 0;
mm->route_style_pos = 0;
+ mm->n_layer_views = 0;
+ mm->n_layer_picks = 0;
+ mm->n_route_styles = 0;
mm->layer_view_shell = NULL;
mm->layer_pick_shell = NULL;
mm->route_style_shell = NULL;
@@ -499,6 +506,50 @@ ghid_main_menu_update_toggle_state (GHidMainMenu *menu,
}
}
+/*! \brief Installs or updates layer selector items */
+void
+ghid_main_menu_install_layer_selector (GHidMainMenu *mm,
+ GHidLayerSelector *ls)
+{
+ GList *children;
+
+ /* @layerview */
+ if (mm->layer_view_shell)
+ {
+ /* Remove old children */
+ children = gtk_container_get_children
+ (GTK_CONTAINER (mm->layer_view_shell));
+ children = g_list_nth (children, mm->layer_view_pos);
+ while (children && mm->n_layer_views--)
+ {
+ gtk_container_remove (GTK_CONTAINER (mm->layer_view_shell),
+ children->data);
+ children = g_list_next (children);
+ }
+ /* Install new ones */
+ mm->n_layer_views = ghid_layer_selector_install_view_items
+ (ls, mm->layer_view_shell, mm->layer_view_pos);
+ }
+
+ /* @layerpick */
+ if (mm->layer_pick_shell)
+ {
+ /* Remove old children */
+ children = gtk_container_get_children
+ (GTK_CONTAINER (mm->layer_pick_shell));
+ children = g_list_nth (children, mm->layer_pick_pos);
+ while (children && mm->n_layer_picks--)
+ {
+ gtk_container_remove (GTK_CONTAINER (mm->layer_pick_shell),
+ children->data);
+ children = g_list_next (children);
+ }
+ /* Install new ones */
+ mm->n_layer_picks = ghid_layer_selector_install_pick_items
+ (ls, mm->layer_pick_shell, mm->layer_pick_pos);
+ }
+}
+
/*! \brief Returns the menu bar's accelerator group */
GtkAccelGroup *
ghid_main_menu_get_accel_group (GHidMainMenu *menu)
diff --git a/src/hid/gtk/ghid-main-menu.h b/src/hid/gtk/ghid-main-menu.h
index 3b8c728..d667e34 100644
--- a/src/hid/gtk/ghid-main-menu.h
+++ b/src/hid/gtk/ghid-main-menu.h
@@ -1,12 +1,13 @@
#ifndef GHID_MAIN_MENU_H__
#define GHID_MAIN_MENU_H__
-#include "resource.h"
-
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
+#include "ghid-layer-selector.h"
+#include "resource.h"
+
G_BEGIN_DECLS /* keep c++ happy */
#define GHID_MAIN_MENU_TYPE (ghid_main_menu_get_type ())
@@ -34,5 +35,8 @@ void ghid_main_menu_add_popup_resource (GHidMainMenu *menu, const char *name,
const Resource *res);
GtkMenu *ghid_main_menu_get_popup (GHidMainMenu *menu, const char *name);
+void ghid_main_menu_install_layer_selector (GHidMainMenu *mm,
+ GHidLayerSelector *ls);
+
G_END_DECLS /* keep c++ happy */
#endif
diff --git a/src/hid/gtk/gui-top-window.c b/src/hid/gtk/gui-top-window.c
index b2d9c22..c292660 100644
--- a/src/hid/gtk/gui-top-window.c
+++ b/src/hid/gtk/gui-top-window.c
@@ -598,7 +598,6 @@ make_top_menubar (GtkWidget *menu_bar, GtkWidget * hbox, GHidPort * port)
{
GtkWidget *frame;
GtkActionGroup *actions;
- GtkActionGroup *layer_actions;
frame = gtk_frame_new (NULL);
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
@@ -609,12 +608,13 @@ make_top_menubar (GtkWidget *menu_bar, GtkWidget * hbox, GHidPort * port)
ghidgui->main_actions = actions;
make_menu_actions (actions, port);
- layer_actions = ghid_layer_selector_get_action_group
- (GHID_LAYER_SELECTOR (ghidgui->layer_selector));
gtk_window_add_accel_group (GTK_WINDOW (gport->top_window),
ghid_main_menu_get_accel_group
(GHID_MAIN_MENU (ghidgui->menu_bar)));
+ gtk_window_add_accel_group (GTK_WINDOW (gport->top_window),
+ ghid_layer_selector_get_accel_group
+ (GHID_LAYER_SELECTOR (ghidgui->layer_selector)));
gtk_container_add (GTK_CONTAINER (frame), menu_bar);
@@ -842,6 +842,9 @@ ghid_layer_buttons_update (void)
get_layer_delete);
make_layer_buttons (ghidgui->layer_selector);
make_virtual_layer_buttons (ghidgui->layer_selector);
+ ghid_main_menu_install_layer_selector
+ (GHID_MAIN_MENU (ghidgui->menu_bar),
+ GHID_LAYER_SELECTOR (ghidgui->layer_selector));
/* Sync selected layer with PCB's state */
if (PCB->RatDraw)
commit 4e63bedd088a4830735d9161c50da94f6784314f
Author: Andrew Poelstra <as...@sf...>
Commit: Andrew Poelstra <as...@sf...>
Clean up layer data handling in ghid-layer-selector.c
diff --git a/src/hid/gtk/ghid-layer-selector.c b/src/hid/gtk/ghid-layer-selector.c
index bd57f57..684f061 100644
--- a/src/hid/gtk/ghid-layer-selector.c
+++ b/src/hid/gtk/ghid-layer-selector.c
@@ -79,6 +79,33 @@ struct _layer
GtkTreeRowReference *rref;
};
+/*! \brief Deletes the action and accelerator from a layer */
+static void
+free_ldata (GHidLayerSelector *ls, struct _layer *ldata)
+{
+ if (ldata->pick_action)
+ {
+ gtk_action_disconnect_accelerator
+ (GTK_ACTION (ldata->pick_action));
+ gtk_action_group_remove_action (ls->action_group,
+ GTK_ACTION (ldata->pick_action));
+/* TODO: make this work without wrecking the radio action group
+ * g_object_unref (G_OBJECT (ldata->pick_action));
+ * */
+ }
+ if (ldata->view_action)
+ {
+ gtk_action_disconnect_accelerator
+ (GTK_ACTION (ldata->view_action));
+ gtk_action_group_remove_action (ls->action_group,
+ GTK_ACTION (ldata->view_action));
+ g_object_unref (G_OBJECT (ldata->view_action));
+ }
+ gtk_tree_row_reference_free (ldata->rref);
+ g_free (ldata);
+
+}
+
/*! \brief Flip the visibility state of a given layer
* \par Function Description
* Changes the internal toggle state and menu checkbox state
@@ -173,11 +200,11 @@ selection_changed_cb (GtkTreeSelection *selection, GHidLayerSelector *ls)
/*! \brief Callback for menu actions: sync layer selection list, emit signal */
static void
-menu_view_cb (GtkToggleAction *action, GtkTreeRowReference *rref)
+menu_view_cb (GtkToggleAction *action, struct _layer *ldata)
{
GHidLayerSelector *ls;
- GtkTreeModel *model = gtk_tree_row_reference_get_model (rref);
- GtkTreePath *path = gtk_tree_row_reference_get_path (rref);
+ GtkTreeModel *model = gtk_tree_row_reference_get_model (ldata->rref);
+ GtkTreePath *path = gtk_tree_row_reference_get_path (ldata->rref);
gboolean state = gtk_toggle_action_get_active (action);
GtkTreeIter iter;
gint user_id;
@@ -193,11 +220,11 @@ menu_view_cb (GtkToggleAction *action, GtkTreeRowReference *rref)
/*! \brief Callback for menu actions: sync layer selection list, emit signal */
static void
-menu_pick_cb (GtkRadioAction *action, GtkTreeRowReference *rref)
+menu_pick_cb (GtkRadioAction *action, struct _layer *ldata)
{
GHidLayerSelector *ls;
- GtkTreeModel *model = gtk_tree_row_reference_get_model (rref);
- GtkTreePath *path = gtk_tree_row_reference_get_path (rref);
+ GtkTreeModel *model = gtk_tree_row_reference_get_model (ldata->rref);
+ GtkTreePath *path = gtk_tree_row_reference_get_path (ldata->rref);
GtkTreeIter iter;
gint user_id;
@@ -437,14 +464,21 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
}
else
{
+ /* If the row exists, we clear out its ldata to create
+ * a new action, accelerator and menu item. */
+ gtk_tree_model_get (GTK_TREE_MODEL (ls->list_store), &iter,
+ STRUCT_COL, &new_layer, -1);
+ free_ldata (ls, new_layer);
+ new_layer = malloc (sizeof (*new_layer));
+
gtk_list_store_set (ls->list_store, &iter,
+ STRUCT_COL, new_layer,
VISIBLE_COL, visible,
COLOR_COL, color_string,
TEXT_COL, name,
FONT_COL, activatable ? NULL : "Italic",
ACTIVATABLE_COL, activatable,
-1);
- return;
}
/* -- Setup new actions -- */
@@ -487,7 +521,7 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
GTK_ACTION (new_layer->pick_action),
paccel);
g_signal_connect (new_layer->pick_action, "toggled",
- G_CALLBACK (menu_pick_cb), new_layer->rref);
+ G_CALLBACK (menu_pick_cb), new_layer);
}
else
new_layer->pick_action = NULL;
@@ -786,44 +820,44 @@ ghid_layer_selector_delete_layers (GHidLayerSelector *ls,
gboolean (*callback)(int user_id))
{
GtkTreeIter iter, last_iter;
- gboolean needs_inc;
- gboolean was_separator = FALSE;
- gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls->list_store), &iter);
- do
+
+ gboolean iter_valid =
+ gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls->list_store), &iter);
+ while (iter_valid)
{
struct _layer *ldata;
- gboolean sep;
+ gboolean sep, was_sep = FALSE;
gint user_id;
- gtk_tree_model_get (GTK_TREE_MODEL (ls->list_store),
- &iter, USER_ID_COL, &user_id,
- STRUCT_COL, &ldata, SEPARATOR_COL, &sep, -1);
- /* gtk_list_store_remove will increment the iter for us, so we
- * don't want to do it again in the loop condition */
- needs_inc = TRUE;
- if (!sep && callback (user_id))
+
+ /* Find next iter to delete */
+ while (iter_valid)
{
- if (gtk_list_store_remove (ls->list_store, &iter))
- {
- if (ldata->view_action)
- gtk_action_group_remove_action (ls->action_group,
- GTK_ACTION (ldata->view_action));
- if (ldata->pick_action)
- gtk_action_group_remove_action (ls->action_group,
- GTK_ACTION (ldata->pick_action));
- gtk_tree_row_reference_free (ldata->rref);
- g_free (ldata);
- needs_inc = FALSE;
- }
- else
- return;
- if (was_separator)
+ gtk_tree_model_get (GTK_TREE_MODEL (ls->list_store),
+ &iter, USER_ID_COL, &user_id,
+ STRUCT_COL, &ldata, SEPARATOR_COL, &sep, -1);
+ if (!sep && callback (user_id))
+ break;
+
+ /* save iter in case it's a bad separator */
+ was_sep = sep;
+ last_iter = iter;
+ /* iterate */
+ iter_valid =
+ gtk_tree_model_iter_next (GTK_TREE_MODEL (ls->list_store), &iter);
+ }
+
+ if (iter_valid)
+ {
+ /* remove preceeding separator */
+ if (was_sep)
gtk_list_store_remove (ls->list_store, &last_iter);
+
+ /*** remove row ***/
+ iter_valid = gtk_list_store_remove (ls->list_store, &iter);
+ free_ldata (ls, ldata);
}
last_iter = iter;
- was_separator = sep;
}
- while (!needs_inc ||
- gtk_tree_model_iter_next (GTK_TREE_MODEL (ls->list_store), &iter));
}
commit 8eddcff25d69024c5afe336f9f1ddab7e341df49
Author: Andrew Poelstra <as...@sf...>
Commit: Andrew Poelstra <as...@sf...>
Give GHidLayerSelector an internal layer structure
Before we had various arrays to resize and index; now each
row has a structure associated with it, that is easier to
access and maintain.
diff --git a/src/hid/gtk/ghid-layer-selector.c b/src/hid/gtk/ghid-layer-selector.c
index 7f11f7f..bd57f57 100644
--- a/src/hid/gtk/ghid-layer-selector.c
+++ b/src/hid/gtk/ghid-layer-selector.c
@@ -33,7 +33,7 @@ enum {
/*! \brief Columns used for internal data store */
enum {
- INDEX_COL,
+ STRUCT_COL,
USER_ID_COL,
VISIBLE_COL,
COLOR_COL,
@@ -57,11 +57,7 @@ struct _GHidLayerSelector
GtkActionGroup *action_group;
- GtkToggleAction **view_actions;
- GtkRadioAction **pick_actions;
- GtkTreeRowReference **rows;
GSList *radio_group;
- int max_actions;
int n_actions;
gboolean last_activatable;
@@ -76,6 +72,13 @@ struct _GHidLayerSelectorClass
void (* toggle_layer) (GHidLayerSelector *, gint);
};
+struct _layer
+{
+ GtkToggleAction *view_action;
+ GtkRadioAction *pick_action;
+ GtkTreeRowReference *rref;
+};
+
/*! \brief Flip the visibility state of a given layer
* \par Function Description
* Changes the internal toggle state and menu checkbox state
@@ -90,12 +93,13 @@ struct _GHidLayerSelectorClass
static void
toggle_visibility (GHidLayerSelector *ls, GtkTreeIter *iter)
{
- gint idx;
+ struct _layer *ldata;
gboolean toggle;
gtk_tree_model_get (GTK_TREE_MODEL (ls->list_store), iter,
- VISIBLE_COL, &toggle, INDEX_COL, &idx, -1);
+ VISIBLE_COL, &toggle, STRUCT_COL, &ldata, -1);
gtk_list_store_set (ls->list_store, iter, VISIBLE_COL, !toggle, -1);
- gtk_toggle_action_set_active (ls->view_actions[idx], !toggle);
+ if (ldata)
+ gtk_toggle_action_set_active (ldata->view_action, !toggle);
}
/*! \brief Decide if a GtkListStore entry is a layer or separator */
@@ -157,11 +161,12 @@ selection_changed_cb (GtkTreeSelection *selection, GHidLayerSelector *ls)
ls->prevent_recursion = TRUE;
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
{
- gint idx;
+ gint user_id;
+ struct _layer *ldata;
gtk_tree_model_get (GTK_TREE_MODEL (ls->list_store), &iter,
- INDEX_COL, &idx, -1);
- if (ls->pick_actions[0])
- gtk_radio_action_set_current_value (ls->pick_actions[0], idx);
+ STRUCT_COL, &ldata, USER_ID_COL, &user_id, -1);
+ if (ldata && ldata->pick_action)
+ gtk_radio_action_set_current_value (ldata->pick_action, user_id);
}
ls->prevent_recursion = FALSE;
}
@@ -243,16 +248,24 @@ ghid_layer_selector_class_init (GHidLayerSelectorClass *klass)
static void
ghid_layer_selector_finalize (GObject *object)
{
- int i;
+ GtkTreeIter iter;
GHidLayerSelector *ls = (GHidLayerSelector *) object;
g_object_unref (ls->action_group);
- g_free (ls->view_actions);
- g_free (ls->pick_actions);
- for (i = 0; i < ls->n_actions; ++i)
- if (ls->rows[i])
- gtk_tree_row_reference_free (ls->rows[i]);
- g_free (ls->rows);
+
+ gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls->list_store), &iter);
+ do
+ {
+ struct _layer *ldata;
+ gtk_tree_model_get (GTK_TREE_MODEL (ls->list_store),
+ &iter, STRUCT_COL, &ldata, -1);
+
+ g_object_unref (G_OBJECT (ldata->pick_action));
+ g_object_unref (G_OBJECT (ldata->view_action));
+ gtk_tree_row_reference_free (ldata->rref);
+ g_free (ldata);
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (ls->list_store), &iter));
G_OBJECT_CLASS (ghid_layer_selector_parent_class)->finalize (object);
}
@@ -309,7 +322,7 @@ ghid_layer_selector_new (void)
GHidLayerSelector *ls = g_object_new (GHID_LAYER_SELECTOR_TYPE, NULL);
/* action index, active, color, text, font, is_separator */
- ls->list_store = gtk_list_store_new (N_COLS, G_TYPE_INT, G_TYPE_INT,
+ ls->list_store = gtk_list_store_new (N_COLS, G_TYPE_POINTER, G_TYPE_INT,
G_TYPE_BOOLEAN, G_TYPE_STRING,
G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
@@ -324,10 +337,6 @@ ghid_layer_selector_new (void)
ls->action_group = gtk_action_group_new ("LayerSelector");
ls->prevent_recursion = FALSE;
ls->n_actions = 0;
- ls->max_actions = INITIAL_ACTION_MAX;
- ls->view_actions = g_malloc0 (ls->max_actions * sizeof (*ls->view_actions));
- ls->pick_actions = g_malloc0 (ls->max_actions * sizeof (*ls->pick_actions));
- ls->rows = g_malloc0 (ls->max_actions * sizeof (*ls->rows));
gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (ls),
tree_view_separator_func,
@@ -372,6 +381,7 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
gboolean visible,
gboolean activatable)
{
+ struct _layer *new_layer = NULL;
gchar *pname, *vname, *paccel, *vaccel;
gboolean new_iter = TRUE;
gboolean last_activatable = TRUE;
@@ -408,12 +418,14 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
/* Add separator between activatable/non-activatable boundaries */
gtk_list_store_append (ls->list_store, &iter);
gtk_list_store_set (ls->list_store, &iter,
+ STRUCT_COL, NULL,
SEPARATOR_COL, TRUE, -1);
}
/* Create new layer */
+ new_layer = malloc (sizeof (*new_layer));
gtk_list_store_append (ls->list_store, &iter);
gtk_list_store_set (ls->list_store, &iter,
- INDEX_COL, ls->n_actions,
+ STRUCT_COL, new_layer,
USER_ID_COL, user_id,
VISIBLE_COL, visible,
COLOR_COL, color_string,
@@ -424,40 +436,15 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
-1);
}
else
- gtk_list_store_set (ls->list_store, &iter,
- VISIBLE_COL, visible,
- COLOR_COL, color_string,
- TEXT_COL, name,
- FONT_COL, activatable ? NULL : "Italic",
- ACTIVATABLE_COL, activatable,
- -1);
-
- /* Unless we're adding new actions, we're done now */
- if (!new_iter)
- return;
-
- if (activatable && ls->n_actions == 0)
- gtk_tree_selection_select_iter (ls->selection, &iter);
-
- /* Allocate new actions if necessary */
- if (ls->n_actions == ls->max_actions)
{
- void *tmp[2];
- ls->max_actions *= 2;
- tmp[0] = g_realloc (ls->view_actions,
- ls->max_actions * sizeof (*ls->view_actions));
- tmp[1] = g_realloc (ls->pick_actions,
- ls->max_actions * sizeof (*ls->pick_actions));
- tmp[2] = g_realloc (ls->rows,
- ls->max_actions * sizeof (*ls->rows));
- if (tmp[0] == NULL || tmp[1] == NULL || tmp[2] == NULL)
- g_critical ("realloc failed allocating new actions");
- else
- {
- ls->view_actions = tmp[0];
- ls->pick_actions = tmp[1];
- ls->rows = tmp[2];
- }
+ gtk_list_store_set (ls->list_store, &iter,
+ VISIBLE_COL, visible,
+ COLOR_COL, color_string,
+ TEXT_COL, name,
+ FONT_COL, activatable ? NULL : "Italic",
+ ACTIVATABLE_COL, activatable,
+ -1);
+ return;
}
/* -- Setup new actions -- */
@@ -484,40 +471,43 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
/* Create row reference for actions */
path = gtk_tree_model_get_path (GTK_TREE_MODEL (ls->list_store), &iter);
- ls->rows[ls->n_actions] = gtk_tree_row_reference_new
- (GTK_TREE_MODEL (ls->list_store), path);
+ new_layer->rref = gtk_tree_row_reference_new
+ (GTK_TREE_MODEL (ls->list_store), path);
gtk_tree_path_free (path);
/* Create selection action */
if (activatable)
{
- ls->pick_actions[ls->n_actions]
- = gtk_radio_action_new (pname, name, NULL, NULL, ls->n_actions);
- gtk_radio_action_set_group (ls->pick_actions[ls->n_actions],
- ls->radio_group);
- ls->radio_group
- = gtk_radio_action_get_group (ls->pick_actions[ls->n_actions]);
+ new_layer->pick_action
+ = gtk_radio_action_new (pname, name, NULL, NULL, user_id);
+ gtk_radio_action_set_group (new_layer->pick_action, ls->radio_group);
+ ls->radio_group = gtk_radio_action_get_group (new_layer->pick_action);
gtk_action_group_add_action_with_accel
(ls->action_group,
- GTK_ACTION (ls->pick_actions[ls->n_actions]),
+ GTK_ACTION (new_layer->pick_action),
paccel);
- g_signal_connect (ls->pick_actions[ls->n_actions], "toggled",
- G_CALLBACK (menu_pick_cb), ls->rows[ls->n_actions]);
+ g_signal_connect (new_layer->pick_action, "toggled",
+ G_CALLBACK (menu_pick_cb), new_layer->rref);
}
else
- ls->pick_actions[ls->n_actions] = NULL;
+ new_layer->pick_action = NULL;
/* Create visibility action */
- ls->view_actions[ls->n_actions] = gtk_toggle_action_new (vname, name,
- NULL, NULL);
- gtk_toggle_action_set_active (ls->view_actions[ls->n_actions], visible);
+ new_layer->view_action = gtk_toggle_action_new (vname, name, NULL, NULL);
+ gtk_toggle_action_set_active (new_layer->view_action, visible);
gtk_action_group_add_action_with_accel
(ls->action_group,
- GTK_ACTION (ls->view_actions[ls->n_actions]),
+ GTK_ACTION (new_layer->view_action),
vaccel);
- g_signal_connect (ls->view_actions[ls->n_actions], "toggled",
- G_CALLBACK (menu_view_cb), ls->rows[ls->n_actions]);
+ g_signal_connect (new_layer->view_action, "toggled",
+ G_CALLBACK (menu_view_cb), new_layer->rref);
+
+
+ /* Select new layer, if we need */
+ if (activatable
+ && !gtk_tree_selection_get_selected (ls->selection, NULL, NULL))
+ gtk_tree_selection_select_iter (ls->selection, &iter);
/* cleanup */
if (vaccel)
@@ -531,6 +521,35 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
ls->n_actions++;
}
+/*! \brief used internally */
+static gboolean
+pick_xml_foreach_func (GtkTreeModel *model, GtkTreePath *path,
+ GtkTreeIter *iter, gpointer data)
+{
+ struct _layer *ldata;
+ GString *str = data;
+
+ gtk_tree_model_get (model, iter, STRUCT_COL, &ldata, -1);
+ if (ldata && ldata->pick_action)
+ g_string_append_printf (str, "<menuitem action=\"%s\" />\n",
+ gtk_action_get_name (GTK_ACTION (ldata->pick_action)));
+ return FALSE;
+}
+/*! \brief used internally */
+static gboolean
+view_xml_foreach_func (GtkTreeModel *model, GtkTreePath *path,
+ GtkTreeIter *iter, gpointer data)
+{
+ struct _layer *ldata;
+ GString *str = data;
+
+ gtk_tree_model_get (model, iter, STRUCT_COL, &ldata, -1);
+ if (ldata && ldata->view_action)
+ g_string_append_printf (str, "<menuitem action=\"%s\" />\n",
+ gtk_action_get_name (GTK_ACTION (ldata->view_action)));
+ return FALSE;
+}
+
/*! \brief Get the "Current Layer" menu description of a layer selector
* \par Function Description
* Returns the XML content used by Gtk in building the layer-selection
@@ -544,13 +563,9 @@ ghid_layer_selector_add_layer (GHidLayerSelector *ls,
gchar *
ghid_layer_selector_get_pick_xml (GHidLayerSelector *ls)
{
- int i;
GString *str = g_string_new ("");
-
- for (i = 0; i < ls->n_actions; ++i)
- if (ls->pick_actions[i])
- g_string_append_printf (str, "<menuitem action=\"LayerPick%d\" />\n", i);
-
+ gtk_tree_model_foreach (GTK_TREE_MODEL (ls->list_store),
+ pick_xml_foreach_func, str);
return g_string_free (str, FALSE);
}
@@ -567,13 +582,9 @@ ghid_layer_selector_get_pick_xml (GHidLayerSelector *ls)
gchar *
ghid_layer_selector_get_view_xml (GHidLayerSelector *ls)
{
- int i;
GString *str = g_string_new ("");
-
- for (i = 0; i < ls->n_actions; ++i)
- if (ls->view_actions[i])
- g_string_append_printf (str, "<menuitem action=\"LayerView%d\" />\n", i);
-
+ gtk_tree_model_foreach (GTK_TREE_MODEL (ls->list_store),
+ view_xml_foreach_func, str);
return g_string_free (str, FALSE);
}
@@ -780,11 +791,12 @@ ghid_layer_selector_delete_layers (GHidLayerSelector *ls,
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls->list_store), &iter);
do
{
+ struct _layer *ldata;
gboolean sep;
- gint user_id, idx;
+ gint user_id;
gtk_tree_model_get (GTK_TREE_MODEL (ls->list_store),
&iter, USER_ID_COL, &user_id,
- INDEX_COL, &idx, SEPARATOR_COL, &sep, -1);
+ STRUCT_COL, &ldata, SEPARATOR_COL, &sep, -1);
/* gtk_list_store_remove will increment the iter for us, so we
* don't want to do it again in the loop condition */
needs_inc = TRUE;
@@ -792,16 +804,14 @@ ghid_layer_selector_delete_layers (GHidLayerSelector *ls,
{
if (gtk_list_store_remove (ls->list_store, &iter))
{
- if (ls->view_actions[idx])
+ if (ldata->view_action)
gtk_action_group_remove_action (ls->action_group,
- GTK_ACTION (ls->view_actions[idx]));
- if (ls->pick_actions[idx])
+ GTK_ACTION (ldata->view_action));
+ if (ldata->pick_action)
gtk_action_group_remove_action (ls->action_group,
- GTK_ACTION (ls->pick_actions[idx]));
- gtk_tree_row_reference_free (ls->rows[idx]);
- ls->view_actions[idx] = NULL;
- ls->pick_actions[idx] = NULL;
- ls->rows[idx] = NULL;
+ GTK_ACTION (ldata->pick_action));
+ gtk_tree_row_reference_free (ldata->rref);
+ g_free (ldata);
needs_inc = FALSE;
}
else
commit 707dd2dc7245cec6f15adc1ae1f735944602c561
Author: Andrew Poelstra <as...@sf...>
Commit: Andrew Poelstra <as...@sf...>
Replace gtk UI manager with GHidMainMenu widget
This commit replaces the old UI manager with a customize gtk
widget that builds menus directly from a resource tree. This
eliminates the translate-to-XML step, the ugly hacks used to
access individual actions, and all the associated manual
memory management.
This will also give us the ability to have more dynamic menus,
in particular layer lists without maximum capacities.
Layers and route styles are still not hooked into the menu.
This means that those accelerators DO NOT WORK. (This will
be fixed in a later commit.) Checkboxes have been replaced
with radio buttons where appropriate. There are now tearoffs
on the context-menu's submenus.
Other than that, there should be no user-visible changes. ;)
diff --git a/src/hid/gtk/gtkhid-main.c b/src/hid/gtk/gtkhid-main.c
index 0c9019d..46a9347 100644
--- a/src/hid/gtk/gtkhid-main.c
+++ b/src/hid/gtk/gtkhid-main.c
@@ -1937,8 +1937,7 @@ button number must be specified as the second argument.
static int
Popup (int argc, char **argv, Coord x, Coord y)
{
- GtkWidget *menu;
- char *element;
+ GtkMenu *menu;
guint button;
if (argc != 1 && argc != 2)
@@ -1949,18 +1948,7 @@ Popup (int argc, char **argv, Coord x, Coord y)
else
button = atoi (argv[1]);
- if ( (element = (char *) malloc ( (strlen (argv[0]) + 2) * sizeof (char))) == NULL )
- {
- fprintf (stderr, _("Popup(): malloc failed\n"));
- exit (1);
- }
-
- sprintf (element, "/%s", argv[0]);
- printf (_("Loading popup \"%s\". Button = %u\n"), element, button);
-
- menu = gtk_ui_manager_get_widget (ghidgui->ui_manager, element);
- free (element);
-
+ menu = ghid_main_menu_get_popup (GHID_MAIN_MENU (ghidgui->menu_bar), argv[0]);
if (! GTK_IS_MENU (menu))
{
Message (_("The specified popup menu \"%s\" has not been defined.\n"), argv[0]);
@@ -1970,7 +1958,7 @@ Popup (int argc, char **argv, Coord x, Coord y)
{
ghidgui->in_popup = TRUE;
gtk_widget_grab_focus (ghid_port.drawing_area);
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0,
+ gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0,
gtk_get_current_event_time());
}
return 0;
diff --git a/src/hid/gtk/gui-command-window.c b/src/hid/gtk/gui-command-window.c
index b08836e..1728bd3 100644
--- a/src/hid/gtk/gui-command-window.c
+++ b/src/hid/gtk/gui-command-window.c
@@ -415,8 +415,8 @@ ghid_command_entry_get (gchar * prompt, gchar * command)
| and connect a handler to look for the escape key.
*/
gtk_window_remove_accel_group (GTK_WINDOW (out->top_window),
- gtk_ui_manager_get_accel_group (ghidgui->
- ui_manager));
+ ghid_main_menu_get_accel_group
+ (GHID_MAIN_MENU (ghidgui->menu_bar)));
ghid_interface_input_signals_disconnect ();
ghid_interface_set_sensitive (FALSE);
gtk_widget_grab_focus (GTK_WIDGET (ghidgui->command_entry));
@@ -438,8 +438,8 @@ ghid_command_entry_get (gchar * prompt, gchar * command)
ghid_interface_input_signals_connect ();
ghid_interface_set_sensitive (TRUE);
gtk_window_add_accel_group (GTK_WINDOW (out->top_window),
- gtk_ui_manager_get_accel_group (ghidgui->
- ui_manager));
+ ghid_main_menu_get_accel_group
+ (GHID_MAIN_MENU (ghidgui->menu_bar)));
/* Restore the status line label and give focus back to the drawing area
*/
diff --git a/src/hid/gtk/gui-output-events.c b/src/hid/gtk/gui-output-events.c
index 5929a37..b9c5ab3 100644
--- a/src/hid/gtk/gui-output-events.c
+++ b/src/hid/gtk/gui-output-events.c
@@ -199,7 +199,7 @@ ghid_idle_cb (gpointer data)
gboolean
ghid_port_key_release_cb (GtkWidget * drawing_area, GdkEventKey * kev,
- GtkUIManager * ui)
+ gpointer data)
{
gint ksym = kev->keyval;
@@ -225,7 +225,7 @@ ghid_port_key_release_cb (GtkWidget * drawing_area, GdkEventKey * kev,
gboolean
ghid_port_key_press_cb (GtkWidget * drawing_area,
- GdkEventKey * kev, GtkUIManager * ui)
+ GdkEventKey * kev, gpointer data)
{
ModifierKeysState mk;
gint ksym = kev->keyval;
@@ -332,7 +332,7 @@ ghid_port_key_press_cb (GtkWidget * drawing_area,
gboolean
ghid_port_button_press_cb (GtkWidget * drawing_area,
- GdkEventButton * ev, GtkUIManager * ui)
+ GdkEventButton * ev, gpointer data)
{
ModifierKeysState mk;
GdkModifierType state;
@@ -357,7 +357,7 @@ ghid_port_button_press_cb (GtkWidget * drawing_area,
gboolean
ghid_port_button_release_cb (GtkWidget * drawing_area,
- GdkEventButton * ev, GtkUIManager * ui)
+ GdkEventButton * ev, gpointer data)
{
ModifierKeysState mk;
GdkModifierType state;
diff --git a/src/hid/gtk/gui-top-window.c b/src/hid/gtk/gui-top-window.c
index b4dbcaa..b2d9c22 100644
--- a/src/hid/gtk/gui-top-window.c
+++ b/src/hid/gtk/gui-top-window.c
@@ -136,19 +136,6 @@ RCSID ("$Id$");
* local types
*/
-
-typedef enum {GHID_FLAG_ACTIVE, GHID_FLAG_CHECKED, GHID_FLAG_VISIBLE} MenuFlagType;
-
-/* Used by the menuitems that are toggle actions */
-typedef struct
-{
- const char *actionname;
- const char *flagname;
- MenuFlagType flagtype;
- int oldval;
- const char *xres;
-} ToggleFlagType;
-
/* Used by the route style buttons and menu */
typedef struct
{
@@ -169,47 +156,25 @@ RouteStyleButton;
#define N_ROUTE_STYLES (NUM_STYLES + 3)
-static void ghid_load_menus (void);
-static void ghid_ui_info_append (const gchar *);
-static void ghid_ui_info_indent (int);
-
static bool ignore_layer_update;
-static gchar * new_ui_info;
-static size_t new_ui_info_sz = 0;
-
-/* the array of actions for "normal" menuitems */
-static GtkActionEntry *new_entries = NULL;
-static gint menuitem_cnt = 0;
-
-/* the array of actions for "toggle" menuitems */
-static GtkToggleActionEntry *new_toggle_entries = NULL;
-static gint tmenuitem_cnt = 0;
-static Resource **action_resources = NULL;
-static Resource **toggle_action_resources = NULL;
+static GtkWidget *ghid_load_menus (void);
/* actions for the @routestyles menuitems */
static GtkToggleActionEntry routestyle_toggle_entries[N_ROUTE_STYLES];
static Resource *routestyle_resources[N_ROUTE_STYLES];
-
-#define MENUITEM "MenuItem"
-#define TMENUITEM "TMenuItem"
#define ROUTESTYLE "RouteStyle"
-
-static ToggleFlagType *tflags = 0;
-static int n_tflags = 0;
-static int max_tflags = 0;
-
GhidGui _ghidgui, *ghidgui = NULL;
GHidPort ghid_port, *gport;
-static GdkColor WhitePixel;
-
-static gchar *bg_image_file;
+static gchar *bg_image_file;
-static char *ghid_hotkey_actions[256];
+static struct { GtkAction *action; const Resource *node; }
+ ghid_hotkey_actions[256];
+#define N_HOTKEY_ACTIONS \
+ (sizeof (ghid_hotkey_actions) / sizeof (ghid_hotkey_actions[0]))
/* ------------------------------------------------------------------
@@ -228,125 +193,39 @@ static gint route_style_index;
static GtkWidget *route_style_edit_button;
-static const char *
-ghid_check_unique_accel (const char *accelerator)
+/*! \brief callback for ghid_main_menu_update_toggle_state () */
+void
+menu_toggle_update_cb (GtkAction *act, const char *tflag, const char *aflag)
{
- static int n_list = 0;
- static char **accel_list;
- static int amax = 0;
- int i;
- const char * a = accelerator;
-
- if (accelerator == NULL)
- return NULL;
-
- if (strlen (accelerator) == 0)
- return accelerator;
-
- if (amax >= n_list)
+ if (tflag != NULL)
{
- n_list += 128;
- if ( (accel_list = (char **)realloc (accel_list, n_list * sizeof (char *))) == NULL)
- {
- fprintf (stderr, "%s(): realloc failed\n", __FUNCTION__);
- exit (1);
- }
+ int v = hid_get_flag (tflag);
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (act), !!v);
}
-
- for (i = 0; i < amax ; i++)
- {
- if (strcmp (accel_list[i], accelerator) == 0)
- {
- Message (_("Duplicate accelerator found: \"%s\"\n"
- "The second occurance will be dropped\n"),
- accelerator);
- a = NULL;
- break;
- }
- }
- accel_list[amax] = strdup (accelerator);
- amax++;
-
- return a;
-}
-
-
-/* ------------------------------------------------------------------
- * note_toggle_flag()
- */
-
-static void
-note_toggle_flag (const char *actionname, MenuFlagType type, const char *name)
-{
-
- #ifdef DEBUG_MENUS
- printf ("note_toggle_flag(\"%s\", %d, \"%s\")\n", actionname, type, name);
- #endif
-
- if (n_tflags >= max_tflags)
+ if (aflag != NULL)
{
- max_tflags += 20;
- tflags = (ToggleFlagType *)realloc (tflags, max_tflags * sizeof (ToggleFlagType));
+ int v = hid_get_flag (aflag);
+ gtk_action_set_sensitive (act, !!v);
}
- tflags[n_tflags].actionname = strdup (actionname);
- tflags[n_tflags].flagname = name;
- tflags[n_tflags].flagtype = type;
- tflags[n_tflags].oldval = -1;
- tflags[n_tflags].xres = "none";
- n_tflags++;
}
-
+/*! \brief sync the menu checkboxes with actual pcb state */
void
ghid_update_toggle_flags ()
{
int i;
GtkAction *a;
- gboolean old_holdoff;
gboolean active;
+ gboolean old_holdoff;
char tmpnm[40];
- GValue setfalse = { 0 };
- GValue settrue = { 0 };
- GValue setlabel = { 0 };
-
- g_value_init (&setfalse, G_TYPE_BOOLEAN);
- g_value_init (&settrue, G_TYPE_BOOLEAN);
- g_value_set_boolean (&setfalse, FALSE);
- g_value_set_boolean (&settrue, TRUE);
- g_value_init (&setlabel, G_TYPE_STRING);
/* mask the callbacks */
old_holdoff = ghidgui->toggle_holdoff;
ghidgui->toggle_holdoff = TRUE;
- for (i = 0; i < n_tflags; i++)
- {
- switch (tflags[i].flagtype)
- {
- case GHID_FLAG_ACTIVE:
- {
- int v = hid_get_flag (tflags[i].flagname);
- a = gtk_action_group_get_action (ghidgui->main_actions, tflags[i].actionname);
- g_object_set_property (G_OBJECT (a), "sensitive", v? &settrue : &setfalse);
- tflags[i].oldval = v;
- }
- break;
-
- case GHID_FLAG_CHECKED:
- {
- int v = hid_get_flag (tflags[i].flagname);
- a = gtk_action_group_get_action (ghidgui->main_actions, tflags[i].actionname);
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (a), v? TRUE : FALSE);
- tflags[i].oldval = v;
- }
- break;
-
- default:
- printf ("Skipping flagtype %d\n", tflags[i].flagtype);
- break;
- }
- }
+ ghid_main_menu_update_toggle_state (GHID_MAIN_MENU (ghidgui->menu_bar),
+ menu_toggle_update_cb);
for (i = 0; i < N_ROUTE_STYLES; i++)
{
@@ -354,7 +233,7 @@ ghid_update_toggle_flags ()
a = gtk_action_group_get_action (ghidgui->main_actions, tmpnm);
if (i >= NUM_STYLES)
{
- g_object_set_property (G_OBJECT (a), "visible", &setfalse);
+ gtk_action_set_visible (a, FALSE);
}
/* Update the toggle states */
@@ -366,11 +245,7 @@ ghid_update_toggle_flags ()
}
- g_value_unset (&setfalse);
- g_value_unset (&settrue);
- g_value_unset (&setlabel);
ghidgui->toggle_holdoff = old_holdoff;
-
}
static void
@@ -412,103 +287,47 @@ top_window_configure_event_cb (GtkWidget * widget, GdkEventConfigure * ev,
}
-/*
- * This is the main menu callback function. The callback looks at
- * the gtk action name to figure out which menuitem was chosen. Then
- * it looks up in a table to find the pcb actions which should be
- * executed. All menus go through this callback. The tables of
- * actions are loaded from the menu resource file at startup.
+/*! \brief Menu action callback function
+ * \par Function Description
+ * This is the main menu callback function. The callback receives
+ * the original Resource pointer containing the HID actions to be
+ * executed.
*
- * In addition, all hotkeys go through the menus which means they go
- * through here.
+ * All hotkeys go through the menus which means they go through here.
+ * Some, such as tab, are caught by Gtk instead of passed here, so
+ * pcb calls this function directly through ghid_hotkey_cb() for them.
+ *
+ * \param [in] The action that was activated
+ * \param [in] The menu resource associated with the action
*/
static void
-ghid_menu_cb (GtkAction * action, gpointer data)
+ghid_menu_cb (GtkAction *action, const Resource *node)
{
- const gchar * name;
- int id = 0;
- int vi;
- const Resource *node = NULL;
- static int in_cb = 0;
- gboolean old_holdoff;
+ const gchar *name = gtk_action_get_name (action);
- /* If we don't do this then we can end up in loops where changing
- * the state of the toggle actions triggers the callbacks and
- * the call back updates the state of the actions.
- */
- if (in_cb)
+ if (action == NULL || node == NULL)
+ return;
+
+ /* Prevent recursion */
+ if (ghidgui->toggle_holdoff == TRUE)
return;
- else
- in_cb = 1;
- /*
- * Normally this callback is triggered by the menus in which case
- * action will be the gtk action which was triggered. In the case
- * of the "special" hotkeys we will call this callback directly and
- * pass in the name of the menu that it corresponds to in via the
- * data argument
- */
- if (action != NULL)
- {
- name = gtk_action_get_name (action);
- }
- else
- {
- name = (const char *) data;
#ifdef DEBUG_MENUS
- printf ("ghid_menu_cb(): name = \"%s\"\n", UNKNOWN (name));
+ printf ("ghid_menu_cb(): name = \"%s\"\n", name);
#endif
- }
- if (name == NULL)
+ /* Special-case route styles */
+ if (strncmp (name, ROUTESTYLE, strlen (ROUTESTYLE)) == 0)
{
- fprintf (stderr, "%s(%p, %p): name == NULL\n",
- __FUNCTION__, action, data);
- in_cb = 0;
- return;
- }
-
- if ( strncmp (name, MENUITEM, strlen (MENUITEM)) == 0)
- {
- /* This is a "normal" menuitem as opposed to a toggle menuitem
- */
- id = atoi (name + strlen (MENUITEM));
- node = action_resources[id];
- }
- else if ( strncmp (name, TMENUITEM, strlen (TMENUITEM)) == 0)
- {
- /* This is a "toggle" menuitem */
- id = atoi (name + strlen (TMENUITEM));
-
- /* toggle_holdoff lets us update the state of the menus without
- * actually triggering all the callbacks
- */
- if (ghidgui->toggle_holdoff == TRUE)
- node = NULL;
- else
- node = toggle_action_resources[id];
- }
- else if ( strncmp (name, ROUTESTYLE, strlen (ROUTESTYLE)) == 0)
- {
- id = atoi (name + strlen (ROUTESTYLE));
+ int id = atoi (name + strlen (ROUTESTYLE));
if (ghidgui->toggle_holdoff != TRUE)
ghid_route_style_button_set_active (id);
node = NULL;
}
else
{
- fprintf (stderr, "ERROR: ghid_menu_cb(): name = \"%s\" is unknown\n", name);
- }
-
-
-#ifdef DEBUG_MENUS
- printf ("ghid_menu_cb(): name = \"%s\", id = %d\n", name, id);
-#endif
-
- /* Now we should have a pointer to the actions to execute */
- if (node != NULL)
- {
+ int vi;
for (vi = 1; vi < node->c; vi++)
if (resource_type (node->v[vi]) == 10)
{
@@ -518,67 +337,24 @@ ghid_menu_cb (GtkAction * action, gpointer data)
hid_parse_actions (node->v[vi].value);
}
}
- else {
-#ifdef DEBUG_MENUS
-...
[truncated message content] |