diff --git a/moo/mooedit/plugins/activestrings/as-plugin-prefs.c b/moo/mooedit/plugins/activestrings/as-plugin-prefs.c index 8290de5f..38c4e16a 100644 --- a/moo/mooedit/plugins/activestrings/as-plugin-prefs.c +++ b/moo/mooedit/plugins/activestrings/as-plugin-prefs.c @@ -27,9 +27,9 @@ static void pattern_data_func (GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter); -static void new_item_func (MooConfig *config, - MooConfigItem *item, - gpointer data); +static void new_item (MooConfigHelper *helper, + MooConfig *config, + MooConfigItem *item); static MooPlugin * @@ -71,6 +71,7 @@ _as_plugin_prefs_page (MooPlugin *plugin) GtkWidget *treeview; GtkTreeViewColumn *column; GtkCellRenderer *cell; + MooConfigHelper *helper; xml = moo_glade_xml_new_empty (); moo_glade_xml_map_id (xml, "script", MOO_TYPE_TEXT_VIEW); @@ -97,21 +98,26 @@ _as_plugin_prefs_page (MooPlugin *plugin) (GtkTreeCellDataFunc) pattern_data_func, NULL, NULL); - moo_config_connect_widget (treeview, - moo_glade_xml_get_widget (xml, "new"), - moo_glade_xml_get_widget (xml, "delete"), - moo_glade_xml_get_widget (xml, "up"), - moo_glade_xml_get_widget (xml, "down"), - new_item_func, NULL); + helper = moo_config_helper_new (treeview, + moo_glade_xml_get_widget (xml, "new"), + moo_glade_xml_get_widget (xml, "delete"), + moo_glade_xml_get_widget (xml, "up"), + moo_glade_xml_get_widget (xml, "down")); - moo_config_add_widget (treeview, moo_glade_xml_get_widget (xml, "pattern"), - AS_KEY_PATTERN, TRUE); - moo_config_add_widget (treeview, moo_glade_xml_get_widget (xml, "lang"), - AS_KEY_LANG, FALSE); - moo_config_add_widget (treeview, moo_glade_xml_get_widget (xml, "enabled"), - AS_KEY_ENABLED, TRUE); - moo_config_add_widget (treeview, moo_glade_xml_get_widget (xml, "script"), - NULL, FALSE); + moo_config_helper_add_widget (helper, moo_glade_xml_get_widget (xml, "pattern"), + AS_KEY_PATTERN, TRUE); + moo_config_helper_add_widget (helper, moo_glade_xml_get_widget (xml, "lang"), + AS_KEY_LANG, FALSE); + moo_config_helper_add_widget (helper, moo_glade_xml_get_widget (xml, "enabled"), + AS_KEY_ENABLED, TRUE); + moo_config_helper_add_widget (helper, moo_glade_xml_get_widget (xml, "script"), + NULL, FALSE); + + g_signal_connect (helper, "new-item", + G_CALLBACK (new_item), NULL); + g_object_set_data_full (G_OBJECT (treeview), + "as-plugin-config-helper", + helper, g_object_unref); g_object_unref (xml); return page; @@ -146,10 +152,12 @@ prefs_page_apply (MooGladeXML *xml) { GtkWidget *treeview; MooConfig *config; + MooConfigHelper *helper; GError *error = NULL; treeview = moo_glade_xml_get_widget (xml, "treeview"); - moo_config_update_tree_view (treeview, NULL, NULL); + helper = g_object_get_data (G_OBJECT (treeview), "as-plugin-config-helper"); + moo_config_helper_update_model (helper, NULL, NULL); config = MOO_CONFIG (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview))); @@ -191,9 +199,9 @@ prefs_page_init (MooGladeXML *xml) static void -new_item_func (MooConfig *config, - MooConfigItem *item, - G_GNUC_UNUSED gpointer data) +new_item (G_GNUC_UNUSED MooConfigHelper *helper, + MooConfig *config, + MooConfigItem *item) { moo_config_set (config, item, AS_KEY_PATTERN, "?", TRUE); } diff --git a/moo/mooutils/moomarshals.list b/moo/mooutils/moomarshals.list index 37721a2b..07228645 100644 --- a/moo/mooutils/moomarshals.list +++ b/moo/mooutils/moomarshals.list @@ -3,6 +3,7 @@ BOOL:BOXED,UINT BOOL:ENUM,INT,BOOL BOOL:INT BOOL:OBJECT,BOXED +BOOL:OBJECT,BOXED,BOXED BOOL:OBJECT,OBJECT BOOL:POINTER BOOL:STRING @@ -26,7 +27,9 @@ VOID:ENUM,UINT VOID:INT VOID:OBJECT VOID:OBJECT,BOXED +VOID:OBJECT,BOXED,BOXED VOID:OBJECT,OBJECT +VOID:OBJECT,POINTER VOID:POINTER VOID:POINTER,BOOL VOID:POINTER,INT diff --git a/moo/mooutils/mooutils-treeview.c b/moo/mooutils/mooutils-treeview.c index ea33c07e..01ee44cd 100644 --- a/moo/mooutils/mooutils-treeview.c +++ b/moo/mooutils/mooutils-treeview.c @@ -12,6 +12,221 @@ */ #include "mooutils/mooutils-treeview.h" +#include "mooutils/moomarshals.h" + + +#define MOO_TYPE_TREE_HELPER (_moo_tree_helper_get_type ()) +#define MOO_TREE_HELPER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_TREE_HELPER, MooTreeHelper)) +#define MOO_TREE_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_TREE_HELPER, MooTreeHelperClass)) +#define MOO_IS_TREE_HELPER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_TREE_HELPER)) +#define MOO_IS_TREE_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_TREE_HELPER)) +#define MOO_TREE_HELPER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_TREE_HELPER, MooTreeHelperClass)) + + +struct _MooTreeHelper { + GtkObject parent; + + GtkTreeView *treeview; + GtkWidget *new_btn; + GtkWidget *delete_btn; + GtkWidget *up_btn; + GtkWidget *down_btn; +}; + + +GType _moo_tree_helper_get_type (void) G_GNUC_CONST; + +static void moo_tree_helper_new_row (MooTreeHelper *helper); +static void moo_tree_helper_delete_row (MooTreeHelper *helper); +static void moo_tree_helper_row_up (MooTreeHelper *helper); +static void moo_tree_helper_row_down (MooTreeHelper *helper); +static void moo_tree_helper_update_widgets (MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *path); +static void moo_tree_helper_update_model (MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *path); + + +G_DEFINE_TYPE (MooTreeHelper, _moo_tree_helper, GTK_TYPE_OBJECT) + + +enum { + NEW_ROW, + DELETE_ROW, + MOVE_ROW, + UPDATE_WIDGETS, + UPDATE_MODEL, + TREE_NUM_SIGNALS +}; + +static guint tree_signals[TREE_NUM_SIGNALS]; + + +static void +selection_changed (GtkTreeSelection *selection, + MooTreeHelper *helper) +{ + GtkTreeRowReference *old_row; + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path, *old_path; + + old_row = g_object_get_data (G_OBJECT (selection), "moo-tree-helper-current-row"); + old_path = old_row ? gtk_tree_row_reference_get_path (old_row) : NULL; + + if (old_row && !old_path) + { + g_object_set_data (G_OBJECT (selection), "moo-tree-helper-current-row", NULL); + old_row = NULL; + } + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + path = gtk_tree_model_get_path (model, &iter); + + if (old_path && !gtk_tree_path_compare (old_path, path)) + { + gtk_tree_path_free (old_path); + gtk_tree_path_free (path); + return; + } + } + else + { + if (!old_path) + return; + + path = NULL; + } + + if (old_path) + moo_tree_helper_update_model (helper, model, old_path); + + moo_tree_helper_update_widgets (helper, model, path); + + if (path) + { + GtkTreeRowReference *row; + row = gtk_tree_row_reference_new (model, path); + g_object_set_data_full (G_OBJECT (selection), "moo-tree-helper-current-row", row, + (GDestroyNotify) gtk_tree_row_reference_free); + } + else + { + g_object_set_data (G_OBJECT (selection), "moo-tree-helper-current-row", NULL); + } + + gtk_tree_path_free (path); + gtk_tree_path_free (old_path); +} + + +static void +moo_tree_helper_destroy (GtkObject *object) +{ + MooTreeHelper *helper = MOO_TREE_HELPER (object); + + if (helper->treeview) + { + GtkTreeSelection *selection; + + g_signal_handlers_disconnect_by_func (helper->treeview, + (gpointer) gtk_object_destroy, + helper); + + selection = gtk_tree_view_get_selection (helper->treeview); + g_signal_handlers_disconnect_by_func (selection, + (gpointer) selection_changed, + helper); + + if (helper->new_btn) + g_signal_handlers_disconnect_by_func (helper->new_btn, + (gpointer) moo_tree_helper_new_row, + helper); + if (helper->delete_btn) + g_signal_handlers_disconnect_by_func (helper->delete_btn, + (gpointer) moo_tree_helper_delete_row, + helper); + if (helper->up_btn) + g_signal_handlers_disconnect_by_func (helper->up_btn, + (gpointer) moo_tree_helper_row_up, + helper); + if (helper->down_btn) + g_signal_handlers_disconnect_by_func (helper->down_btn, + (gpointer) moo_tree_helper_row_down, + helper); + + helper->treeview = NULL; + } + + GTK_OBJECT_CLASS (_moo_tree_helper_parent_class)->destroy (object); +} + + +static void +_moo_tree_helper_class_init (MooTreeHelperClass *klass) +{ + GTK_OBJECT_CLASS(klass)->destroy = moo_tree_helper_destroy; + + tree_signals[NEW_ROW] = + g_signal_new ("new-row", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooTreeHelperClass, new_row), + g_signal_accumulator_true_handled, NULL, + _moo_marshal_BOOL__OBJECT_BOXED, + G_TYPE_BOOLEAN, 2, + GTK_TYPE_TREE_MODEL, + GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE); + + tree_signals[DELETE_ROW] = + g_signal_new ("delete-row", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooTreeHelperClass, delete_row), + g_signal_accumulator_true_handled, NULL, + _moo_marshal_BOOL__OBJECT_BOXED, + G_TYPE_BOOLEAN, 2, + GTK_TYPE_TREE_MODEL, + GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE); + + tree_signals[MOVE_ROW] = + g_signal_new ("move-row", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooTreeHelperClass, move_row), + g_signal_accumulator_true_handled, NULL, + _moo_marshal_BOOL__OBJECT_BOXED_BOXED, + G_TYPE_BOOLEAN, 3, + GTK_TYPE_TREE_MODEL, + GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE, + GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE); + + tree_signals[UPDATE_WIDGETS] = + g_signal_new ("update-widgets", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooTreeHelperClass, update_widgets), + NULL, NULL, + _moo_marshal_VOID__OBJECT_BOXED_BOXED, + G_TYPE_NONE, 3, + GTK_TYPE_TREE_MODEL, + GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE, + GTK_TYPE_TREE_ITER | G_SIGNAL_TYPE_STATIC_SCOPE); + + tree_signals[UPDATE_MODEL] = + g_signal_new ("update-model", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooTreeHelperClass, update_model), + NULL, NULL, + _moo_marshal_VOID__OBJECT_BOXED_BOXED, + G_TYPE_NONE, 3, + GTK_TYPE_TREE_MODEL, + GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE, + GTK_TYPE_TREE_ITER | G_SIGNAL_TYPE_STATIC_SCOPE); +} void @@ -31,101 +246,608 @@ moo_tree_view_select_first (GtkTreeView *tree_view) } +static void +moo_tree_helper_update_widgets (MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *path) +{ + GtkTreeIter iter; + + if (!path) + { + if (helper->delete_btn) + gtk_widget_set_sensitive (helper->delete_btn, FALSE); + if (helper->up_btn) + gtk_widget_set_sensitive (helper->up_btn, FALSE); + if (helper->down_btn) + gtk_widget_set_sensitive (helper->down_btn, FALSE); + } + else + { + int *indices; + int n_rows; + + if (helper->delete_btn) + gtk_widget_set_sensitive (helper->delete_btn, TRUE); + + indices = gtk_tree_path_get_indices (path); + + if (helper->up_btn) + gtk_widget_set_sensitive (helper->up_btn, indices[0] != 0); + + n_rows = gtk_tree_model_iter_n_children (model, NULL); + + if (helper->down_btn) + gtk_widget_set_sensitive (helper->down_btn, indices[0] != n_rows - 1); + } + + if (path) + gtk_tree_model_get_iter (model, &iter, path); + + g_signal_emit (helper, tree_signals[UPDATE_WIDGETS], 0, + model, path, path ? &iter : NULL); +} + + +static void +moo_tree_helper_update_model (MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *path) +{ + GtkTreePath *freeme = NULL; + GtkTreeIter iter; + + if (!model) + model = gtk_tree_view_get_model (helper->treeview); + + if (!path) + { + GtkTreeSelection *selection = gtk_tree_view_get_selection (helper->treeview); + + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) + path = freeme = gtk_tree_model_get_path (model, &iter); + } + + if (path) + { + gtk_tree_model_get_iter (model, &iter, path); + g_signal_emit (helper, tree_signals[UPDATE_MODEL], 0, + model, path, &iter); + } + + gtk_tree_path_free (freeme); +} + + +static int +iter_get_index (GtkTreeModel *model, + GtkTreeIter *iter) +{ + int index; + GtkTreePath *path; + + path = gtk_tree_model_get_path (model, iter); + + if (!path) + return -1; + + index = gtk_tree_path_get_indices(path)[0]; + + gtk_tree_path_free (path); + return index; +} + + +static void +moo_tree_helper_new_row (MooTreeHelper *helper) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreeSelection *selection; + GtkTreePath *path; + int index; + gboolean result; + + selection = gtk_tree_view_get_selection (helper->treeview); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + index = gtk_tree_model_iter_n_children (model, NULL); + else + index = iter_get_index (model, &iter) + 1; + + path = gtk_tree_path_new_from_indices (index, -1); + + g_signal_emit (helper, tree_signals[NEW_ROW], 0, model, path, &result); + + if (result && gtk_tree_model_get_iter (model, &iter, path)) + gtk_tree_selection_select_iter (selection, &iter); + + gtk_tree_path_free (path); +} + + +static void +moo_tree_helper_delete_row (MooTreeHelper *helper) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreeSelection *selection; + GtkTreePath *path; + gboolean result; + + selection = gtk_tree_view_get_selection (helper->treeview); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + g_return_if_reached (); + + path = gtk_tree_model_get_path (model, &iter); + + g_signal_emit (helper, tree_signals[DELETE_ROW], 0, model, path, &result); + + if (result && (gtk_tree_model_get_iter (model, &iter, path) || + (gtk_tree_path_prev (path) && gtk_tree_model_get_iter (model, &iter, path)))) + gtk_tree_selection_select_iter (selection, &iter); + + gtk_tree_path_free (path); +} + + +static void +moo_tree_helper_row_move (MooTreeHelper *helper, + gboolean up) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path, *new_path; + GtkTreeSelection *selection; + gboolean result; + + selection = gtk_tree_view_get_selection (helper->treeview); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + g_return_if_reached (); + + path = gtk_tree_model_get_path (model, &iter); + new_path = gtk_tree_path_copy (path); + + if (up && !gtk_tree_path_prev (new_path)) + g_return_if_reached (); + else if (!up) + gtk_tree_path_next (new_path); + + g_signal_emit (helper, tree_signals[MOVE_ROW], 0, model, path, new_path, &result); + + if (result) + moo_tree_helper_update_widgets (helper, model, new_path); + + gtk_tree_path_free (new_path); + gtk_tree_path_free (path); +} + + +static void +moo_tree_helper_row_up (MooTreeHelper *helper) +{ + moo_tree_helper_row_move (helper, TRUE); +} + + +static void +moo_tree_helper_row_down (MooTreeHelper *helper) +{ + moo_tree_helper_row_move (helper, FALSE); +} + + +static void +_moo_tree_helper_init (G_GNUC_UNUSED MooTreeHelper *helper) +{ +} + + +static void +moo_tree_helper_connect (MooTreeHelper *helper, + GtkWidget *tree_view, + GtkWidget *new_btn, + GtkWidget *delete_btn, + GtkWidget *up_btn, + GtkWidget *down_btn) +{ + GtkTreeSelection *selection; + + g_return_if_fail (MOO_IS_TREE_HELPER (helper)); + g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); + g_return_if_fail (helper->treeview == NULL); + + helper->treeview = GTK_TREE_VIEW (tree_view); + helper->new_btn = new_btn; + helper->delete_btn = delete_btn; + helper->up_btn = up_btn; + helper->down_btn = down_btn; + + g_signal_connect_swapped (tree_view, "destroy", + G_CALLBACK (gtk_object_destroy), + helper); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + g_signal_connect (selection, "changed", + G_CALLBACK (selection_changed), + helper); + + if (new_btn) + g_signal_connect_swapped (new_btn, "clicked", + G_CALLBACK (moo_tree_helper_new_row), + helper); + if (delete_btn) + g_signal_connect_swapped (delete_btn, "clicked", + G_CALLBACK (moo_tree_helper_delete_row), + helper); + if (up_btn) + g_signal_connect_swapped (up_btn, "clicked", + G_CALLBACK (moo_tree_helper_row_up), + helper); + if (down_btn) + g_signal_connect_swapped (down_btn, "clicked", + G_CALLBACK (moo_tree_helper_row_down), + helper); +} + + +/****************************************************************************/ +/* MooConfigHelper + */ + +#define MOO_TYPE_CONFIG_HELPER (_moo_config_helper_get_type ()) +#define MOO_CONFIG_HELPER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_CONFIG_HELPER, MooConfigHelper)) +#define MOO_CONFIG_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_CONFIG_HELPER, MooConfigHelperClass)) +#define MOO_IS_CONFIG_HELPER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_CONFIG_HELPER)) +#define MOO_IS_CONFIG_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_CONFIG_HELPER)) +#define MOO_CONFIG_HELPER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_CONFIG_HELPER, MooConfigHelperClass)) + + +enum { + NEW_ITEM, + SET_FROM_ITEM, + SET_FROM_WIDGETS, + CONFIG_NUM_SIGNALS +}; + +static guint config_signals[CONFIG_NUM_SIGNALS]; + + +typedef void (*MooConfigItemToWidget) (MooConfig *config, + MooConfigItem *item, + GtkWidget *widget, + gpointer data); +typedef void (*MooConfigWidgetToItem) (GtkWidget *widget, + MooConfig *config, + MooConfigItem *item, + gpointer data); + + typedef struct { char *key; gboolean update_live; gulong handler; - MooConfigWidgetToItem widget_to_item; MooConfigItemToWidget item_to_widget; + MooConfigWidgetToItem widget_to_item; gpointer data; } WidgetInfo; -typedef struct { - GtkTreeView *treeview; +struct _MooConfigHelper { + MooTreeHelper parent; GSList *widgets; - GtkWidget *new_btn; - GtkWidget *delete_btn; - GtkWidget *up_btn; - GtkWidget *down_btn; - MooConfigSetupItemFunc setup_func; - gpointer data; -} Widgets; +}; -static WidgetInfo *widget_info_new (const char *key, - gboolean update_live); -static void widget_info_free (WidgetInfo *info); -static Widgets *widgets_new (GtkWidget *tree_view, - GtkWidget *new_btn, - GtkWidget *delete_btn, - GtkWidget *up_btn, - GtkWidget *down_btn); -static void widgets_free (Widgets *widgets); - -static void selection_changed (GtkTreeSelection *selection, - Widgets *widgets); -static void set_from_model (Widgets *widgets, - GtkTreeModel *model, - GtkTreePath *path); -static void button_new (Widgets *widgets); -static void button_delete (Widgets *widgets); -static void button_up (Widgets *widgets); -static void button_down (Widgets *widgets); -static void entry_changed (Widgets *widgets, - GtkEntry *entry); -static void button_toggled (Widgets *widgets, - GtkToggleButton *button); - - -static Widgets * -get_widgets (GtkWidget *treeview) -{ - return g_object_get_data (G_OBJECT (treeview), "moo-config-widgets"); -} - - -void -moo_config_connect_widget (GtkWidget *treeview, - GtkWidget *new_btn, - GtkWidget *delete_btn, - GtkWidget *up_btn, - GtkWidget *down_btn, - MooConfigSetupItemFunc func, - gpointer data) -{ - Widgets *widgets; - GtkTreeSelection *selection; - - g_return_if_fail (GTK_IS_TREE_VIEW (treeview)); - g_return_if_fail (!get_widgets (treeview)); - - widgets = widgets_new (treeview, new_btn, delete_btn, up_btn, down_btn); - widgets->setup_func = func; - widgets->data = data; - g_object_set_data_full (G_OBJECT (treeview), "moo-config-widgets", widgets, - (GDestroyNotify) widgets_free); - g_signal_connect (treeview, "destroy", - G_CALLBACK (moo_config_disconnect_widget), - NULL); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); - g_signal_connect (selection, "changed", - G_CALLBACK (selection_changed), widgets); - - if (new_btn) - g_signal_connect_swapped (new_btn, "clicked", G_CALLBACK (button_new), widgets); - if (delete_btn) - g_signal_connect_swapped (delete_btn, "clicked", G_CALLBACK (button_delete), widgets); - if (up_btn) - g_signal_connect_swapped (up_btn, "clicked", G_CALLBACK (button_up), widgets); - if (down_btn) - g_signal_connect_swapped (down_btn, "clicked", G_CALLBACK (button_down), widgets); -} +GType _moo_config_helper_get_type (void) G_GNUC_CONST; +G_DEFINE_TYPE (MooConfigHelper, _moo_config_helper, MOO_TYPE_TREE_HELPER) static WidgetInfo * get_info (gpointer widget) { - return g_object_get_data (G_OBJECT (widget), "moo-config-widget-info"); + return g_object_get_data (G_OBJECT (widget), "moo-config-helper-widget-info"); +} + + +static void +moo_config_helper_destroy (GtkObject *object) +{ + MooConfigHelper *helper = MOO_CONFIG_HELPER (object); + + if (helper->widgets) + { + GSList *l; + + for (l = helper->widgets; l != NULL; l = l->next) + { + GtkWidget *widget = l->data; + WidgetInfo *info = get_info (widget); + + if (info->handler) + g_signal_handler_disconnect (widget, info->handler); + + g_object_set_data (G_OBJECT (widget), "moo-config-helper-widget-info", NULL); + } + + g_slist_free (helper->widgets); + helper->widgets = NULL; + } + + GTK_OBJECT_CLASS(_moo_config_helper_parent_class)->destroy (object); +} + + +static gboolean +moo_config_helper_new_row (MooTreeHelper *tree_helper, + GtkTreeModel *model, + GtkTreePath *path) +{ + int index; + MooConfigItem *item; + MooConfigHelper *helper = MOO_CONFIG_HELPER (tree_helper); + + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (gtk_tree_path_get_depth (path) == 1, FALSE); + + index = gtk_tree_path_get_indices(path)[0]; + item = moo_config_new_item (MOO_CONFIG (model), index, TRUE); + g_return_val_if_fail (item != NULL, FALSE); + + g_signal_emit (helper, config_signals[NEW_ITEM], 0, model, item); + + return TRUE; +} + + +static gboolean +moo_config_helper_delete_row (G_GNUC_UNUSED MooTreeHelper *tree_helper, + GtkTreeModel *model, + GtkTreePath *path) +{ + int index; + + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (gtk_tree_path_get_depth (path) == 1, FALSE); + + index = gtk_tree_path_get_indices(path)[0]; + moo_config_delete_item (MOO_CONFIG (model), index, TRUE); + + return TRUE; +} + + +static gboolean +moo_config_helper_move_row (G_GNUC_UNUSED MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *old_path, + GtkTreePath *new_path) +{ + g_return_val_if_fail (old_path && new_path, FALSE); + g_return_val_if_fail (gtk_tree_path_get_depth (old_path) == 1, FALSE); + g_return_val_if_fail (gtk_tree_path_get_depth (new_path) == 1, FALSE); + moo_config_move_item (MOO_CONFIG (model), + gtk_tree_path_get_indices(old_path)[0], + gtk_tree_path_get_indices(new_path)[0], + TRUE); + return TRUE; +} + + +static void +moo_config_helper_update_widgets_real (MooTreeHelper *tree_helper, + GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter) +{ + GSList *l; + MooConfigItem *item = NULL; + MooConfigHelper *helper = MOO_CONFIG_HELPER (tree_helper); + + g_return_if_fail (MOO_IS_CONFIG (model)); + + if (path) + { + gtk_tree_model_get (model, iter, 0, &item, -1); + g_return_if_fail (item != NULL); + } + + for (l = helper->widgets; l != NULL; l = l->next) + { + GtkWidget *widget; + WidgetInfo *info; + + widget = l->data; + info = get_info (widget); + + if (info->handler) + g_signal_handler_block (widget, info->handler); + + gtk_widget_set_sensitive (widget, item != NULL); + + if (item) + { + info->item_to_widget (MOO_CONFIG (model), item, widget, info->data); + } + else + { + if (GTK_IS_TOGGLE_BUTTON (widget)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE); + else if (GTK_IS_ENTRY (widget)) + gtk_entry_set_text (GTK_ENTRY (widget), ""); + else + gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget)), + "", -1); + } + + if (info->handler) + g_signal_handler_unblock (widget, info->handler); + } +} + + +static void +moo_config_helper_update_model_real (MooTreeHelper *tree_helper, + GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter) +{ + GSList *l; + MooConfigItem *item = NULL; + MooConfigHelper *helper = MOO_CONFIG_HELPER (tree_helper); + + g_return_if_fail (MOO_IS_CONFIG (model)); + g_return_if_fail (path != NULL); + + gtk_tree_model_get (model, iter, 0, &item, -1); + + if (!item) + return; + + for (l = helper->widgets; l != NULL; l = l->next) + { + GtkWidget *widget; + WidgetInfo *info; + + widget = l->data; + info = get_info (widget); + + info->widget_to_item (widget, MOO_CONFIG (model), item, info->data); + } +} + + +static void +_moo_config_helper_class_init (MooConfigHelperClass *klass) +{ + MooTreeHelperClass *tree_class = MOO_TREE_HELPER_CLASS (klass); + + GTK_OBJECT_CLASS(klass)->destroy = moo_config_helper_destroy; + + tree_class->new_row = moo_config_helper_new_row; + tree_class->delete_row = moo_config_helper_delete_row; + tree_class->move_row = moo_config_helper_move_row; + tree_class->update_widgets = moo_config_helper_update_widgets_real; + tree_class->update_model = moo_config_helper_update_model_real; + + config_signals[NEW_ITEM] = + g_signal_new ("new-item", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooConfigHelperClass, new_item), + NULL, NULL, + _moo_marshal_VOID__OBJECT_POINTER, + G_TYPE_NONE, 2, + MOO_TYPE_CONFIG, + MOO_TYPE_CONFIG_ITEM); + + config_signals[SET_FROM_ITEM] = + g_signal_new ("set-from-item", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooConfigHelperClass, set_from_item), + NULL, NULL, + _moo_marshal_VOID__OBJECT_POINTER, + G_TYPE_NONE, 2, + MOO_TYPE_CONFIG, + MOO_TYPE_CONFIG_ITEM); + + config_signals[SET_FROM_WIDGETS] = + g_signal_new ("set-from-widgets", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooConfigHelperClass, set_from_widgets), + NULL, NULL, + _moo_marshal_VOID__OBJECT_POINTER, + G_TYPE_NONE, 2, + MOO_TYPE_CONFIG, + MOO_TYPE_CONFIG_ITEM); +} + + +static void +_moo_config_helper_init (MooConfigHelper *helper) +{ + helper->widgets = NULL; +} + + +MooConfigHelper * +moo_config_helper_new (GtkWidget *tree_view, + GtkWidget *new_btn, + GtkWidget *delete_btn, + GtkWidget *up_btn, + GtkWidget *down_btn) +{ + MooConfigHelper *helper; + + g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL); + + helper = g_object_new (MOO_TYPE_CONFIG_HELPER, NULL); + gtk_object_sink (g_object_ref (helper)); + + moo_tree_helper_connect (MOO_TREE_HELPER (helper), tree_view, + new_btn, delete_btn, up_btn, down_btn); + + return helper; +} + + +static void +button_toggled (MooTreeHelper *helper, + GtkToggleButton *button) +{ + GtkTreeModel *model; + GtkTreeIter iter; + MooConfigItem *item = NULL; + WidgetInfo *info; + GtkTreeSelection *selection; + + selection = gtk_tree_view_get_selection (helper->treeview); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + info = get_info (button); + g_return_if_fail (info != NULL); + + gtk_tree_model_get (model, &iter, 0, &item, -1); + g_return_if_fail (item != NULL); + + moo_config_set_bool (MOO_CONFIG (model), item, info->key, + gtk_toggle_button_get_active (button), TRUE); +} + + +static void +entry_changed (MooTreeHelper *helper, + GtkEntry *entry) +{ + GtkTreeModel *model; + GtkTreeIter iter; + const char *text; + MooConfigItem *item = NULL; + WidgetInfo *info; + GtkTreeSelection *selection; + + selection = gtk_tree_view_get_selection (helper->treeview); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + info = get_info (entry); + g_return_if_fail (info != NULL); + + text = gtk_entry_get_text (entry); + gtk_tree_model_get (model, &iter, 0, &item, -1); + g_return_if_fail (item != NULL); + + if (info->key) + moo_config_set (MOO_CONFIG (model), item, + info->key, text, TRUE); + else + moo_config_set_item_content (MOO_CONFIG (model), item, + text, TRUE); } @@ -271,116 +993,6 @@ get_item_to_widget_func (GtkWidget *widget) } -void -moo_config_add_widget_full (GtkWidget *tree_view, - GtkWidget *widget, - const char *key, - MooConfigWidgetToItem widget_to_item_func, - MooConfigItemToWidget item_to_widget_func, - gpointer data, - gboolean update_live) -{ - Widgets *widgets; - WidgetInfo *info; - - widgets = get_widgets (tree_view); - g_return_if_fail (widgets != NULL); - g_return_if_fail (!update_live || key != NULL); - - g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget) || - GTK_IS_ENTRY (widget) || GTK_IS_TEXT_VIEW (widget)); - - if (!widget_to_item_func) - { - widget_to_item_func = get_widget_to_item_func (widget); - g_return_if_fail (widget_to_item_func != NULL); - } - - if (!item_to_widget_func) - { - item_to_widget_func = get_item_to_widget_func (widget); - g_return_if_fail (item_to_widget_func != NULL); - } - - info = widget_info_new (key, update_live); - info->widget_to_item = widget_to_item_func; - info->item_to_widget = item_to_widget_func; - info->data = data; - - widgets->widgets = g_slist_prepend (widgets->widgets, widget); - g_object_set_data_full (G_OBJECT (widget), "moo-config-widget-info", info, - (GDestroyNotify) widget_info_free); - - if (update_live) - { - if (GTK_IS_TOGGLE_BUTTON (widget)) - info->handler = - g_signal_connect_swapped (widget, "toggled", - G_CALLBACK (button_toggled), - widgets); - else if (GTK_IS_ENTRY (widget)) - info->handler = - g_signal_connect_swapped (widget, "changed", - G_CALLBACK (entry_changed), - widgets); - } -} - - -void -moo_config_add_widget (GtkWidget *tree_view, - GtkWidget *widget, - const char *key, - gboolean update_live) -{ - return moo_config_add_widget_full (tree_view, widget, key, - NULL, NULL, NULL, update_live); -} - - -void -moo_config_disconnect_widget (GtkWidget *treeview) -{ - GtkTreeSelection *selection; - Widgets *widgets; - GSList *l; - - widgets = get_widgets (treeview); - - if (!widgets) - return; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); - g_signal_handlers_disconnect_by_func (selection, (gpointer) selection_changed, widgets); - - if (widgets->new_btn) - g_signal_handlers_disconnect_by_func (widgets->new_btn, - (gpointer) button_new, widgets); - if (widgets->delete_btn) - g_signal_handlers_disconnect_by_func (widgets->delete_btn, - (gpointer) button_delete, widgets); - if (widgets->up_btn) - g_signal_handlers_disconnect_by_func (widgets->up_btn, - (gpointer) button_up, widgets); - if (widgets->down_btn) - g_signal_handlers_disconnect_by_func (widgets->down_btn, - (gpointer) button_down, widgets); - - for (l = widgets->widgets; l != NULL; l = l->next) - { - GtkWidget *widget = l->data; - WidgetInfo *info = get_info (widget); - - if (info->handler) - g_signal_handler_disconnect (widget, info->handler); - - g_object_set_data (G_OBJECT (widget), "moo-config-widget-info", NULL); - } - - g_object_set_data (G_OBJECT (treeview), "moo-config-widgets", NULL); -} - - static WidgetInfo * widget_info_new (const char *key, gboolean update_live) @@ -405,426 +1017,104 @@ widget_info_free (WidgetInfo *info) } -static Widgets * -widgets_new (GtkWidget *tree_view, - GtkWidget *new_btn, - GtkWidget *delete_btn, - GtkWidget *up_btn, - GtkWidget *down_btn) -{ - Widgets *w = g_new0 (Widgets, 1); - w->treeview = GTK_TREE_VIEW (tree_view); - w->new_btn = new_btn; - w->delete_btn = delete_btn; - w->up_btn = up_btn; - w->down_btn = down_btn; - return w; -} - - static void -widgets_free (Widgets *widgets) +moo_config_helper_add_widget_full (MooConfigHelper *helper, + GtkWidget *widget, + const char *key, + MooConfigWidgetToItem widget_to_item_func, + MooConfigItemToWidget item_to_widget_func, + gpointer data, + gboolean update_live) { - if (widgets) + WidgetInfo *info; + + g_return_if_fail (!update_live || key != NULL); + + g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget) || + GTK_IS_ENTRY (widget) || GTK_IS_TEXT_VIEW (widget)); + + if (!widget_to_item_func) { - g_slist_free (widgets->widgets); - g_free (widgets); - } -} - - -static void -selection_changed (GtkTreeSelection *selection, - Widgets *widgets) -{ - GtkTreeRowReference *old_row; - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path, *old_path; - - old_row = g_object_get_data (G_OBJECT (selection), "moo-config-current-row"); - old_path = old_row ? gtk_tree_row_reference_get_path (old_row) : NULL; - - if (old_row && !old_path) - { - g_object_set_data (G_OBJECT (selection), "moo-config-current-row", NULL); - old_row = NULL; + widget_to_item_func = get_widget_to_item_func (widget); + g_return_if_fail (widget_to_item_func != NULL); } - if (gtk_tree_selection_get_selected (selection, &model, &iter)) + if (!item_to_widget_func) { - path = gtk_tree_model_get_path (model, &iter); - - if (old_path && !gtk_tree_path_compare (old_path, path)) - { - gtk_tree_path_free (old_path); - gtk_tree_path_free (path); - return; - } - } - else - { - if (!old_path) - return; - - path = NULL; + item_to_widget_func = get_item_to_widget_func (widget); + g_return_if_fail (item_to_widget_func != NULL); } - if (old_path) - moo_config_update_tree_view (GTK_WIDGET (widgets->treeview), - model, old_path); + info = widget_info_new (key, update_live); + info->widget_to_item = widget_to_item_func; + info->item_to_widget = item_to_widget_func; + info->data = data; - set_from_model (widgets, model, path); + helper->widgets = g_slist_prepend (helper->widgets, widget); + g_object_set_data_full (G_OBJECT (widget), "moo-config-helper-widget-info", info, + (GDestroyNotify) widget_info_free); - if (path) + if (update_live) { - GtkTreeRowReference *row; - row = gtk_tree_row_reference_new (model, path); - g_object_set_data_full (G_OBJECT (selection), "moo-config-current-row", row, - (GDestroyNotify) gtk_tree_row_reference_free); - } - else - { - g_object_set_data (G_OBJECT (selection), "moo-config-current-row", NULL); - } - - gtk_tree_path_free (path); - gtk_tree_path_free (old_path); -} - - -static void -set_from_model (Widgets *widgets, - GtkTreeModel *model, - GtkTreePath *path) -{ - GtkTreeIter iter; - MooConfigItem *item = NULL; - GSList *l; - - g_return_if_fail (MOO_IS_CONFIG (model)); - - if (path) - { - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, 0, &item, -1); - g_return_if_fail (item != NULL); - } - - for (l = widgets->widgets; l != NULL; l = l->next) - { - GtkWidget *widget; - WidgetInfo *info; - - widget = l->data; - info = get_info (widget); - - if (info->handler) - g_signal_handler_block (widget, info->handler); - - gtk_widget_set_sensitive (widget, item != NULL); - - if (item) - { - info->item_to_widget (MOO_CONFIG (model), item, widget, info->data); - } - else - { - if (GTK_IS_TOGGLE_BUTTON (widget)) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE); - else if (GTK_IS_ENTRY (widget)) - gtk_entry_set_text (GTK_ENTRY (widget), ""); - else - gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget)), - "", -1); - } - - if (info->handler) - g_signal_handler_unblock (widget, info->handler); - } - - if (!item) - { - if (widgets->delete_btn) - gtk_widget_set_sensitive (widgets->delete_btn, FALSE); - if (widgets->up_btn) - gtk_widget_set_sensitive (widgets->up_btn, FALSE); - if (widgets->down_btn) - gtk_widget_set_sensitive (widgets->down_btn, FALSE); - } - else - { - int *indices; - - if (widgets->delete_btn) - gtk_widget_set_sensitive (widgets->delete_btn, TRUE); - - indices = gtk_tree_path_get_indices (path); - - if (widgets->up_btn) - gtk_widget_set_sensitive (widgets->up_btn, indices[0] != 0); - if (widgets->down_btn) - gtk_widget_set_sensitive (widgets->down_btn, (guint) indices[0] != - moo_config_n_items (MOO_CONFIG (model)) - 1); + if (GTK_IS_TOGGLE_BUTTON (widget)) + info->handler = + g_signal_connect_swapped (widget, "toggled", + G_CALLBACK (button_toggled), + helper); + else if (GTK_IS_ENTRY (widget)) + info->handler = + g_signal_connect_swapped (widget, "changed", + G_CALLBACK (entry_changed), + helper); } } void -moo_config_update_widgets (GtkWidget *treeview) +moo_config_helper_add_widget (MooConfigHelper *helper, + GtkWidget *widget, + const char *key, + gboolean update_live) { - Widgets *widgets; + g_return_if_fail (MOO_IS_CONFIG_HELPER (helper)); + g_return_if_fail (GTK_IS_WIDGET (widget)); + moo_config_helper_add_widget_full (helper, widget, key, + NULL, NULL, NULL, + update_live); +} + + +void +moo_config_helper_update_model (MooConfigHelper *helper, + GtkTreeModel *model, + GtkTreePath *path) +{ + g_return_if_fail (MOO_IS_CONFIG_HELPER (helper)); + moo_tree_helper_update_model (MOO_TREE_HELPER (helper), model, path); +} + + +void +moo_config_helper_update_widgets (MooConfigHelper *helper) +{ + GtkTreeView *treeview; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; - widgets = get_widgets (treeview); - g_return_if_fail (widgets != NULL); + g_return_if_fail (MOO_IS_CONFIG_HELPER (helper)); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + treeview = MOO_TREE_HELPER (helper)->treeview; + selection = gtk_tree_view_get_selection (treeview); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { GtkTreePath *path = gtk_tree_model_get_path (model, &iter); - set_from_model (widgets, model, path); + moo_tree_helper_update_widgets (MOO_TREE_HELPER (helper), model, path); gtk_tree_path_free (path); } else { - set_from_model (widgets, model, NULL); - } -} - - -static int -iter_get_index (GtkTreeModel *model, - GtkTreeIter *iter) -{ - int index; - GtkTreePath *path; - - path = gtk_tree_model_get_path (model, iter); - - if (!path) - return -1; - - index = gtk_tree_path_get_indices(path)[0]; - - gtk_tree_path_free (path); - return index; -} - - -static void -button_new (Widgets *widgets) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreeSelection *selection; - MooConfigItem *item; - int index; - - selection = gtk_tree_view_get_selection (widgets->treeview); - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - index = -1; - else - index = iter_get_index (model, &iter) + 1; - - item = moo_config_new_item (MOO_CONFIG (model), index, TRUE); - - if (widgets->setup_func) - widgets->setup_func (MOO_CONFIG (model), item, widgets->data); - - moo_config_get_item_iter (MOO_CONFIG (model), item, &iter); - gtk_tree_selection_select_iter (selection, &iter); -} - - -static void -button_delete (Widgets *widgets) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreeSelection *selection; - int index; - - selection = gtk_tree_view_get_selection (widgets->treeview); - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - g_return_if_reached (); - - index = iter_get_index (model, &iter); - moo_config_delete_item (MOO_CONFIG (model), index, TRUE); - - if (gtk_tree_model_iter_nth_child (model, &iter, NULL, index)) - gtk_tree_selection_select_iter (selection, &iter); -} - - -static void -button_up (Widgets *widgets) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path, *new_path; - GtkTreeSelection *selection; - int *indices; - - selection = gtk_tree_view_get_selection (widgets->treeview); - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - g_return_if_reached (); - - path = gtk_tree_model_get_path (model, &iter); - indices = gtk_tree_path_get_indices (path); - - if (!indices[0]) - g_return_if_reached (); - - moo_config_move_item (MOO_CONFIG (model), indices[0], indices[0] - 1, TRUE); - new_path = gtk_tree_path_new_from_indices (indices[0] - 1, -1); - set_from_model (widgets, model, new_path); - - gtk_tree_path_free (new_path); - gtk_tree_path_free (path); -} - - -static void -button_down (Widgets *widgets) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path, *new_path; - int *indices; - int n_children; - - selection = gtk_tree_view_get_selection (widgets->treeview); - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - g_return_if_reached (); - - path = gtk_tree_model_get_path (model, &iter); - indices = gtk_tree_path_get_indices (path); - n_children = gtk_tree_model_iter_n_children (model, NULL); - - if (indices[0] == n_children - 1) - g_return_if_reached (); - - moo_config_move_item (MOO_CONFIG (model), indices[0], indices[0] + 1, TRUE); - new_path = gtk_tree_path_new_from_indices (indices[0] + 1, -1); - set_from_model (widgets, model, new_path); - - gtk_tree_path_free (new_path); - gtk_tree_path_free (path); -} - - -static void -entry_changed (Widgets *widgets, - GtkEntry *entry) -{ - GtkTreeModel *model; - GtkTreeIter iter; - const char *text; - MooConfigItem *item = NULL; - WidgetInfo *info; - GtkTreeSelection *selection; - - selection = gtk_tree_view_get_selection (widgets->treeview); - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return; - - info = get_info (entry); - g_return_if_fail (info != NULL); - - text = gtk_entry_get_text (entry); - gtk_tree_model_get (model, &iter, 0, &item, -1); - g_return_if_fail (item != NULL); - - if (info->key) - moo_config_set (MOO_CONFIG (model), item, - info->key, text, TRUE); - else - moo_config_set_item_content (MOO_CONFIG (model), item, - text, TRUE); -} - - -static void -button_toggled (Widgets *widgets, - GtkToggleButton *button) -{ - GtkTreeModel *model; - GtkTreeIter iter; - MooConfigItem *item = NULL; - WidgetInfo *info; - GtkTreeSelection *selection; - - selection = gtk_tree_view_get_selection (widgets->treeview); - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return; - - info = get_info (button); - g_return_if_fail (info != NULL); - - gtk_tree_model_get (model, &iter, 0, &item, -1); - g_return_if_fail (item != NULL); - - moo_config_set_bool (MOO_CONFIG (model), item, info->key, - gtk_toggle_button_get_active (button), TRUE); -} - - -void -moo_config_update_tree_view (GtkWidget *treeview, - GtkTreeModel *model, - GtkTreePath *path) -{ - GtkTreeIter iter; - Widgets *widgets; - GSList *l; - MooConfigItem *item = NULL; - - widgets = get_widgets (treeview); - g_return_if_fail (widgets != NULL); - - if (!model) - model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); - - if (!path) - { - GtkTreeSelection *selection = - gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); - if (gtk_tree_selection_get_selected (selection, NULL, &iter)) - { - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, 0, &item, -1); - gtk_tree_path_free (path); - } - } - else - { - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, 0, &item, -1); - } - - if (!item) - return; - - for (l = widgets->widgets; l != NULL; l = l->next) - { - GtkWidget *widget; - WidgetInfo *info; - - widget = l->data; - info = get_info (widget); - - info->widget_to_item (widget, MOO_CONFIG (model), item, info->data); + moo_tree_helper_update_widgets (MOO_TREE_HELPER (helper), model, NULL); } } diff --git a/moo/mooutils/mooutils-treeview.h b/moo/mooutils/mooutils-treeview.h index cbdff506..e9459e58 100644 --- a/moo/mooutils/mooutils-treeview.h +++ b/moo/mooutils/mooutils-treeview.h @@ -20,44 +20,67 @@ G_BEGIN_DECLS -typedef void (*MooConfigSetupItemFunc) (MooConfig *config, - MooConfigItem *item, - gpointer data); -typedef void (*MooConfigWidgetToItem) (GtkWidget *widget, - MooConfig *config, - MooConfigItem *item, - gpointer data); -typedef void (*MooConfigItemToWidget) (MooConfig *config, - MooConfigItem *item, - GtkWidget *widget, - gpointer data); +typedef struct _MooTreeHelper MooTreeHelper; +typedef struct _MooConfigHelper MooConfigHelper; +typedef struct _MooTreeHelperClass MooTreeHelperClass; +typedef struct _MooConfigHelperClass MooConfigHelperClass; -void moo_config_connect_widget (GtkWidget *tree_view, - GtkWidget *new_btn, - GtkWidget *delete_btn, - GtkWidget *up_btn, - GtkWidget *down_btn, - MooConfigSetupItemFunc func, - gpointer data); -void moo_config_add_widget (GtkWidget *tree_view, - GtkWidget *widget, - const char *key, - gboolean update_live); -void moo_config_add_widget_full (GtkWidget *tree_view, - GtkWidget *widget, - const char *key, - MooConfigWidgetToItem widget_to_item_func, - MooConfigItemToWidget item_to_widget_func, - gpointer data, - gboolean update_live); -void moo_config_disconnect_widget(GtkWidget *tree_view); -void moo_config_update_tree_view (GtkWidget *tree_view, - GtkTreeModel *model, - GtkTreePath *path); -void moo_config_update_widgets (GtkWidget *tree_view); +struct _MooTreeHelperClass { + GtkObjectClass parent_class; + + gboolean (*new_row) (MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *path); + gboolean (*delete_row) (MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *path); + gboolean (*move_row) (MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *old_path, + GtkTreePath *new_path); + + void (*update_widgets) (MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter); + void (*update_model) (MooTreeHelper *helper, + GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter); +}; + +struct _MooConfigHelperClass { + MooTreeHelperClass parent_class; + + void (*new_item) (MooConfigHelper *helper, + MooConfig *config, + MooConfigItem *item); + void (*set_from_item) (MooConfigHelper *helper, + MooConfig *config, + MooConfigItem *item); + void (*set_from_widgets) (MooConfigHelper *helper, + MooConfig *config, + MooConfigItem *item); +}; -void moo_tree_view_select_first (GtkTreeView *tree_view); +MooConfigHelper *moo_config_helper_new (GtkWidget *tree_view, + GtkWidget *new_btn, + GtkWidget *delete_btn, + GtkWidget *up_btn, + GtkWidget *down_btn); + +void moo_config_helper_add_widget (MooConfigHelper *helper, + GtkWidget *widget, + const char *key, + gboolean update_live); +void moo_config_helper_update_model (MooConfigHelper *helper, + GtkTreeModel *model, + GtkTreePath *path); +void moo_config_helper_update_widgets (MooConfigHelper *helper); + + +void moo_tree_view_select_first (GtkTreeView *tree_view); G_END_DECLS