/* * moocommanddisplay.c * * Copyright (C) 2004-2007 by Yevgen Muntyan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation. * * See COPYING file that comes with this distribution. */ #define MOOEDIT_COMPILATION #include "mooedit/moocommanddisplay.h" #include "mooedit/moocommand-private.h" #include "mooutils/mooutils-misc.h" #include typedef struct { MooCommandData *data; MooCommandFactory *factory; gboolean changed; } Data; struct _MooCommandDisplay { MooTreeHelper base; GtkComboBox *factory_combo; GtkNotebook *notebook; Data *data; int n_factories; int active; int original; }; struct _MooCommandDisplayClass { MooTreeHelperClass base_class; }; G_DEFINE_TYPE (MooCommandDisplay, _moo_command_display, MOO_TYPE_TREE_HELPER) static void combo_changed (MooCommandDisplay *display); static void block_combo (MooCommandDisplay *display) { g_signal_handlers_block_by_func (display->factory_combo, (gpointer) combo_changed, display); } static void unblock_combo (MooCommandDisplay *display) { g_signal_handlers_unblock_by_func (display->factory_combo, (gpointer) combo_changed, display); } static void combo_changed (MooCommandDisplay *display) { GtkWidget *widget; int index; MooCommandFactory *factory; index = gtk_combo_box_get_active (display->factory_combo); g_return_if_fail (index >= 0); if (index == display->active) return; if (display->active >= 0) { widget = gtk_notebook_get_nth_page (display->notebook, display->active); if (_moo_command_factory_save_data (display->data[display->active].factory, widget, display->data[display->active].data)) display->data[display->active].changed = TRUE; } display->active = index; factory = display->data[index].factory; g_return_if_fail (factory != NULL); if (!display->data[index].data) display->data[index].data = moo_command_data_new (factory->n_keys); gtk_notebook_set_current_page (display->notebook, index); widget = gtk_notebook_get_nth_page (display->notebook, index); _moo_command_factory_load_data (factory, widget, display->data[index].data); } static void combo_set_active (MooCommandDisplay *display, int index) { block_combo (display); gtk_combo_box_set_active (display->factory_combo, index); unblock_combo (display); if (index < 0) { gtk_widget_hide (GTK_WIDGET (display->notebook)); } else { gtk_notebook_set_current_page (display->notebook, index); gtk_widget_show (GTK_WIDGET (display->notebook)); } } static int combo_find_factory (MooCommandDisplay *display, MooCommandFactory *factory) { int i; g_return_val_if_fail (!factory || MOO_IS_COMMAND_FACTORY (factory), -1); if (!factory) return -1; for (i = 0; i < display->n_factories; ++i) if (display->data[i].factory == factory) return i; g_return_val_if_reached (-1); } void _moo_command_display_set (MooCommandDisplay *display, MooCommandFactory *factory, MooCommandData *data) { int index; GtkWidget *widget; g_return_if_fail (MOO_IS_COMMAND_DISPLAY (display)); g_return_if_fail (!factory || MOO_IS_COMMAND_FACTORY (factory)); g_return_if_fail (!factory == !data); for (index = 0; index < display->n_factories; ++index) { display->data[index].changed = FALSE; if (display->data[index].data) moo_command_data_unref (display->data[index].data); display->data[index].data = NULL; } index = combo_find_factory (display, factory); display->active = index; display->original = index; combo_set_active (display, index); if (index >= 0) { display->data[index].data = moo_command_data_ref (data); widget = gtk_notebook_get_nth_page (display->notebook, index); _moo_command_factory_load_data (factory, widget, data); } } gboolean _moo_command_display_get (MooCommandDisplay *display, MooCommandFactory **factory_p, MooCommandData **data_p) { GtkWidget *widget; Data *data; g_return_val_if_fail (MOO_IS_COMMAND_DISPLAY (display), FALSE); if (display->active < 0) return FALSE; data = &display->data[display->active]; widget = gtk_notebook_get_nth_page (display->notebook, display->active); if (_moo_command_factory_save_data (data->factory, widget, data->data)) data->changed = TRUE; if (display->active == display->original && !data->changed) return FALSE; *factory_p = data->factory; *data_p = data->data; data->changed = FALSE; display->original = display->active; return TRUE; } static void init_factory_combo (MooCommandDisplay *display, GtkComboBox *combo, GtkNotebook *notebook) { GtkListStore *store; GSList *factories; GtkCellRenderer *cell; g_return_if_fail (MOO_IS_COMMAND_DISPLAY (display)); g_return_if_fail (GTK_IS_COMBO_BOX (combo)); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); display->factory_combo = combo; display->notebook = notebook; cell = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (display->factory_combo), cell, TRUE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (display->factory_combo), cell, "text", 0, NULL); store = gtk_list_store_new (1, G_TYPE_STRING); factories = moo_command_list_factories (); display->active = -1; display->original = -1; display->n_factories = 0; display->data = g_new0 (Data, g_slist_length (factories)); while (factories) { GtkTreeIter iter; MooCommandFactory *cmd_factory; GtkWidget *widget; cmd_factory = factories->data; widget = _moo_command_factory_create_widget (cmd_factory); if (widget) { gtk_widget_show (widget); gtk_notebook_append_page (display->notebook, widget, NULL); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, cmd_factory->display_name, -1); display->data[display->n_factories].factory = cmd_factory; display->n_factories++; } factories = g_slist_delete_link (factories, factories); } gtk_combo_box_set_model (display->factory_combo, GTK_TREE_MODEL (store)); g_signal_connect_swapped (display->factory_combo, "changed", G_CALLBACK (combo_changed), display); g_object_unref (store); } MooCommandDisplay * _moo_command_display_new (GtkComboBox *factory_combo, GtkNotebook *notebook, GtkWidget *treeview, GtkWidget *new_btn, GtkWidget *delete_btn, GtkWidget *up_btn, GtkWidget *down_btn) { MooCommandDisplay *display; display = g_object_new (MOO_TYPE_COMMAND_DISPLAY, NULL); _moo_tree_helper_connect (MOO_TREE_HELPER (display), treeview, new_btn, delete_btn, up_btn, down_btn); init_factory_combo (display, factory_combo, notebook); MOO_OBJECT_REF_SINK (display); return display; } static void moo_command_display_dispose (GObject *object) { MooCommandDisplay *display = MOO_COMMAND_DISPLAY (object); if (display->data) { int i; for (i = 0; i < display->n_factories; ++i) if (display->data[i].data) moo_command_data_unref (display->data[i].data); g_free (display->data); display->data = NULL; } G_OBJECT_CLASS (_moo_command_display_parent_class)->dispose (object); } static void _moo_command_display_init (G_GNUC_UNUSED MooCommandDisplay *display) { } static void _moo_command_display_class_init (MooCommandDisplayClass *klass) { G_OBJECT_CLASS (klass)->dispose = moo_command_display_dispose; }