diff options
34 files changed, 2886 insertions, 1262 deletions
@@ -1,3 +1,75 @@ +2006-04-24 Tristan Van Berkom <tvb@gnome.org> + + * TODO: Updated + + * doc/gladeui-sections.txt updated + + * src/glade-app.[ch]: Majorly reduced the api, now GladeApp is a + singleton. Added "active-project" signal. + + * src/glade-builtins.[ch]: Removed unused variable. Enhanced objects + pspec type to recognize interfaces. Added glade_param_spec_objects_get_type() + + * src/glade-clipboard-view.c: Trying a cute border. + + * src/glade-command.c, src/glade-fixed-manager.c, + src/glade-placehodler.c, src/glade-popup.c, src/glade-project-view.c, + src/glade-project-window.c: + Updated for glade-app changes + + * src/glade-editor-property.c: Implemented objects pspec + + * src/glade-editor.[ch]: Added atk tab, added cuteness. + + * src/glade-gtk.c: + o Translated image type names + o Added button types (translated) + o Support for button label & use-underline properties + + * src/glade-parser.c: + o Updated for glade-app changes + o Added save support for atk actions and relations. + + * src/glade-project.c: + o Updated for glade-app changes + o Fixed glade_project_fix_object_props for object lists + + * src/glade-property-class.[ch]: + o Hardcoded atk relations and action names + o Added glade_property_class_make_gvalue(), + glade_property_class_get_from_gvalue(), + glade_property_class_new_atk_action(), + glade_property_class_list_atk_relations(), + glade_property_class_atk_realname() + o Fixed glade_property_class_is_object() + (object lists qualify) + + * src/glade-property.[ch]: + o Integrated property load proceedure into glade-property, + loading code much cleaner and less redundant. + (Added glade_property_read()) + o Implemented atk properties (save/load) + + * src/glade-utils.[ch]: Added glade_util_read_prop_name(), + glade_util_added_in_list(), glade_util_removed_from_list(), + glade_util_class_implements_interface() + + * src/glade-widget-class.c: Introspect atk properties + + * src/glade-widget.c: Simplified load code, moved property load + code to glade-property, save atk props properly. + + * src/glade.h: Removed the unused atk-relation tag. + + * src/main.c: Load gail (for atk action introspection) + + * src/atk.xpm: New atk icon + + * widgets/gtk+.xml.in: + o GtkLabel label property --> translatable + o GtkButton label property --> translatable, multi-line + o Added GtkButton "type" property and GtkButton remove-child-function + 2006-04-19 Juan Pablo Ugarte <juanpablougarte@gmail.com> * src/glade-editor-property.c: Simplified code and added comments @@ -5,10 +5,9 @@ Blockers for glade-3 2.92.0 beta Tasks: ====== - o Implement atk properties (parser already works) o Toolbar editor / Popup menu editor ? o Add / Implement gnome widget catalogs (bug 315601) - o Handled startup errors correctly (bug 331797) + o Handle startup errors correctly (bug 331797) o Implement accelerator keys (bug 331808) Complex bugs: diff --git a/doc/gladeui-sections.txt b/doc/gladeui-sections.txt index 0fb8e35b..5b04665e 100644 --- a/doc/gladeui-sections.txt +++ b/doc/gladeui-sections.txt @@ -4,7 +4,7 @@ <FILE>glade-app</FILE> <TITLE>GladeApp</TITLE> GladeApp -glade_app_new +glade_app_get glade_app_update_ui glade_app_set_window glade_app_get_window @@ -14,8 +14,8 @@ glade_app_get_alt_class glade_app_get_palette glade_app_get_clipboard glade_app_get_clipboard_view -glade_app_get_active_project glade_app_set_project +glade_app_get_project glade_app_add_project glade_app_remove_project glade_app_get_projects @@ -24,12 +24,13 @@ glade_app_is_project_loaded glade_app_show_properties glade_app_hide_properties glade_app_add_project_view +glade_app_command_undo +glade_app_command_redo glade_app_command_copy glade_app_command_cut glade_app_command_paste glade_app_command_delete -glade_app_command_undo -glade_app_command_redo +glade_app_command_delete_clipboard glade_app_config_save glade_app_set_transient_parent glade_app_get_transient_parent @@ -37,34 +38,13 @@ glade_app_set_accel_group glade_app_update_instance_count glade_app_undo_button_new glade_app_redo_button_new -glade_default_app_set -glade_default_app_get_window -glade_default_app_get_editor -glade_default_app_get_add_class -glade_default_app_get_alt_class -glade_default_app_get_palette -glade_default_app_get_clipboard -glade_default_app_get_active_project -glade_default_app_update_ui -glade_default_app_get_selection -glade_default_app_get_projects -glade_default_app_show_properties -glade_default_app_hide_properties -glade_default_app_set_transient_parent -glade_default_app_get_transient_parent -glade_default_app_command_cut -glade_default_app_command_copy -glade_default_app_command_paste -glade_default_app_command_delete -glade_default_app_command_delete_clipboard -glade_default_app_is_selected -glade_default_app_selection_set -glade_default_app_selection_add -glade_default_app_selection_remove -glade_default_app_selection_clear -glade_default_app_selection_changed -glade_default_app_undo_button_new -glade_default_app_redo_button_new +glade_app_selection_add +glade_app_selection_remove +glade_app_selection_changed +glade_app_get_selection +glade_app_selection_clear +glade_app_selection_set +glade_app_is_selected <SUBSECTION Standard> GLADE_APP GLADE_IS_APP @@ -316,11 +296,13 @@ GladeProjectClass <FILE>glade-property-class</FILE> <TITLE>GladePropertyClass</TITLE> GladePropertyClass +GPCAtkType GladeVerifyPropertyFunc GladeGetPropertyFunc GladeSetPropertyFunc glade_property_class_new glade_property_class_new_from_spec +glade_property_class_new_atk_action glade_property_class_clone glade_property_class_free glade_property_class_is_visible @@ -330,10 +312,14 @@ glade_property_class_make_gvalue_from_string glade_property_class_make_string_from_gvalue glade_property_class_make_gvalue_from_vl glade_property_class_set_vl_from_gvalue +glade_property_class_get_from_gvalue +glade_property_class_make_gvalue glade_property_class_update_from_node glade_property_class_get_displayable_value glade_property_class_make_adjustment glade_property_class_match +glade_property_class_void_value +glade_property_class_list_atk_relations <SUBSECTION Standard> GLADE_PROPERTY_CLASS GLADE_IS_PROPERTY_CLASS @@ -356,7 +342,10 @@ glade_property_get_value glade_property_get_default glade_property_get_va_list glade_property_get +glade_property_add_object +glade_property_remove_object glade_property_sync +glade_property_read glade_property_write glade_property_get_tooltip glade_property_set_sensitive @@ -442,6 +431,7 @@ glade_widget_class_get_type GLADE_WIDGET_CLASS GLADE_IS_WIDGET_CLASS <SUBSECTION Private> +GPC_OBJECT_DELIMITER GLADE_VALID_CREATE_REASON GladeSupportedChild GladeWidgetClassSignal @@ -560,6 +550,7 @@ glade_util_gtk_combo_func glade_util_gtk_combo_find glade_util_file_dialog_new glade_util_replace +glade_util_read_prop_name glade_util_duplicate_underscores glade_util_add_selection glade_util_remove_selection diff --git a/doc/tmpl/glade-property.sgml b/doc/tmpl/glade-property.sgml index 656dabc5..6834127a 100644 --- a/doc/tmpl/glade-property.sgml +++ b/doc/tmpl/glade-property.sgml @@ -192,6 +192,24 @@ the #GladePropertyClass describes how a #GladeProperty will function. @Varargs: +<!-- ##### FUNCTION glade_property_add_object ##### --> +<para> + +</para> + +@property: +@object: + + +<!-- ##### FUNCTION glade_property_remove_object ##### --> +<para> + +</para> + +@property: +@object: + + <!-- ##### FUNCTION glade_property_sync ##### --> <para> @@ -200,6 +218,19 @@ the #GladePropertyClass describes how a #GladeProperty will function. @property: +<!-- ##### FUNCTION glade_property_read ##### --> +<para> + +</para> + +@property: +@pclass: +@project: +@info: +@free_value: +@Returns: + + <!-- ##### FUNCTION glade_property_write ##### --> <para> diff --git a/doc/tmpl/glade-utils.sgml b/doc/tmpl/glade-utils.sgml index dc734903..3d6ec3e4 100644 --- a/doc/tmpl/glade-utils.sgml +++ b/doc/tmpl/glade-utils.sgml @@ -135,6 +135,15 @@ This is where all of that really usefull miscalanious stuff lands up. @b: +<!-- ##### FUNCTION glade_util_read_prop_name ##### --> +<para> + +</para> + +@str: +@Returns: + + <!-- ##### FUNCTION glade_util_duplicate_underscores ##### --> <para> @@ -296,6 +305,26 @@ This is where all of that really usefull miscalanious stuff lands up. @Returns: +<!-- ##### FUNCTION glade_util_added_in_list ##### --> +<para> + +</para> + +@old: +@new: +@Returns: + + +<!-- ##### FUNCTION glade_util_removed_from_list ##### --> +<para> + +</para> + +@old: +@new: +@Returns: + + <!-- ##### FUNCTION glade_util_canonical_path ##### --> <para> @@ -315,6 +344,16 @@ This is where all of that really usefull miscalanious stuff lands up. @Returns: +<!-- ##### FUNCTION glade_util_class_implements_interface ##### --> +<para> + +</para> + +@class_type: +@iface_type: +@Returns: + + <!-- ##### FUNCTION glade_util_file_is_writeable ##### --> <para> diff --git a/src/atk.xpm b/src/atk.xpm new file mode 100644 index 00000000..d6a051b1 --- /dev/null +++ b/src/atk.xpm @@ -0,0 +1,112 @@ +/* XPM */ +static char * glade_atk_xpm[] = { +"20 20 89 1", +" c None", +". c #AEAFAE", +"+ c #FFFFFF", +"@ c #C4C4F1", +"# c #4646D3", +"$ c #8484E2", +"% c #3535D0", +"& c #0000C4", +"* c #D5D5F5", +"= c #6363DB", +"- c #1515C9", +"; c #EEEEFB", +"> c #F7F7FD", +", c #6969DC", +"' c #B7B7EE", +") c #7A7AE0", +"! c #0606C5", +"~ c #DDDDF7", +"{ c #5656D8", +"] c #B2B2ED", +"^ c #6464DB", +"/ c #6868DC", +"( c #9F9FE9", +"_ c #BCBCEF", +": c #7373DE", +"< c #2929CD", +"[ c #EFEFFB", +"} c #2121CC", +"| c #8282E2", +"1 c #E7E7FA", +"2 c #E7E7F9", +"3 c #E6E6F9", +"4 c #F0F0FB", +"5 c #7474DF", +"6 c #FBFBFE", +"7 c #9090E5", +"8 c #CACAF3", +"9 c #FEFEFF", +"0 c #1616C9", +"a c #ACACEC", +"b c #D0D0F4", +"c c #0808C6", +"d c #3636D0", +"e c #FDFDFF", +"f c #E9E9FA", +"g c #E4E4F8", +"h c #E5E5F9", +"i c #C1C1F1", +"j c #4A4AD5", +"k c #9B9BE8", +"l c #EAEAFA", +"m c #E2E2F8", +"n c #0909C6", +"o c #CECEF4", +"p c #F3F3FC", +"q c #1A1ACA", +"r c #A7A7EB", +"s c #F5F5FD", +"t c #5656D7", +"u c #8181E2", +"v c #2424CC", +"w c #0101C4", +"x c #A6A6EA", +"y c #2E2ECF", +"z c #F8F8FD", +"A c #2323CC", +"B c #F4F4FC", +"C c #2222CC", +"D c #1919CA", +"E c #A6A6EB", +"F c #F2F2FC", +"G c #2727CD", +"H c #4E4ED6", +"I c #9696E7", +"J c #0707C6", +"K c #E3E3F9", +"L c #3737D1", +"M c #1313C8", +"N c #8F8FE5", +"O c #7D7DE1", +"P c #3030CF", +"Q c #1010C8", +"R c #AFAFEC", +"S c #FCFCFE", +"T c #5E5EDA", +"U c #4040D3", +"V c #4F4FD6", +"W c #8B8BE4", +"X c #ECECFA", +"....................", +".+++++@#$++++++++++.", +".+++++%&&*+++++++++.", +".+++++=&-;+++++++++.", +".+++++>,'++++++++++.", +".+++++)&!~+++++++++.", +".+++++{&&]+++++++++.", +".+++++^&&/((_++++++.", +".+++~,:&&&&&<++++++.", +".++[}/|&&)1234+++++.", +".++5%67&&&&&&!8++++.", +".+90a+bc&&&&&&de+++.", +".+f&g++hiiiiij&k+++.", +".+l&m++++++++*n-;op.", +".+9qr+++++++stu&vwx.", +".++)yz++++++uABCDE+.", +".++FGH[+++9IJ_+b4++.", +".+++KLM,NOPQR++++++.", +".++++SaTUVWX+++++++.", +"...................."}; diff --git a/src/glade-app.c b/src/glade-app.c index f552c1da..e7274ddf 100644 --- a/src/glade-app.c +++ b/src/glade-app.c @@ -62,7 +62,6 @@ struct _GladeAppPriv { * project; then this is always valid) */ GladeEditor *editor; /* See glade-editor */ GladeClipboard *clipboard; /* See glade-clipboard */ - GladeProjectView *active_view; /* See glade-project-view */ GList *catalogs; /* See glade-catalog */ GladeWidgetClass *add_class; /* The GladeWidgetClass that we are about * to add to a container. NULL if no @@ -91,6 +90,13 @@ enum LAST_SIGNAL }; + +enum +{ + PROP_0, + PROP_ACTIVE_PROJECT +}; + static guint glade_app_signals[LAST_SIGNAL] = { 0 }; gchar *glade_pixmaps_dir = GLADE_PIXMAPSDIR; @@ -100,7 +106,30 @@ gchar *glade_locale_dir = GLADE_LOCALEDIR; gchar *glade_icon_dir = GLADE_ICONDIR; gboolean glade_verbose = FALSE; -static GObjectClass* parent_class = NULL; +static GObjectClass * parent_class = NULL; +static GladeApp * the_app = NULL; + + +/***************************************************************** + * GObjectClass * + *****************************************************************/ +static GObject * +glade_app_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + + /* Singleton */ + if (!the_app) + the_app = (GladeApp *)parent_class->constructor + (type, n_construct_properties, construct_properties); + else + g_object_ref (the_app); + + return G_OBJECT (the_app); +} + + static void glade_app_dispose (GObject *app) @@ -151,6 +180,47 @@ glade_app_finalize (GObject *app) } static void +glade_app_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) + { + case PROP_ACTIVE_PROJECT: + glade_app_set_project (g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID + (object, property_id, pspec); + break; + } +} + +static void +glade_app_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GladeApp *app = GLADE_APP (object); + + + switch (property_id) + { + case PROP_ACTIVE_PROJECT: + g_value_set_object (value, app->priv->active_project); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); + break; + } +} + +/***************************************************************** + * GladeAppClass * + *****************************************************************/ +static void glade_app_refresh_undo_redo_button (GladeApp *app, GtkWidget *button, gboolean undo) @@ -163,7 +233,7 @@ glade_app_refresh_undo_redo_button (GladeApp *app, if (button_tips == NULL) button_tips = gtk_tooltips_new (); - if ((project = glade_app_get_active_project (app)) != NULL) + if ((project = glade_app_get_project ()) != NULL) { if (undo) command = glade_command_next_undo_item (project); @@ -196,40 +266,6 @@ glade_app_update_ui_default (GladeApp *app) } static void -glade_app_class_init (GladeAppClass * klass) -{ - GObjectClass *object_class; - g_return_if_fail (klass != NULL); - - parent_class = g_type_class_peek_parent (klass); - object_class = (GObjectClass *) klass; - - object_class->dispose = glade_app_dispose; - object_class->finalize = glade_app_finalize; - - klass->update_ui_signal = glade_app_update_ui_default; - klass->show_properties = NULL; - klass->hide_properties = NULL; - - - /** - * GladeApp::update-ui: - * @gladeapp: the #GladeApp which received the signal. - * - * Emitted when a project name changes or a cut/copy/paste/delete occurred. - */ - glade_app_signals[UPDATE_UI_SIGNAL] = - g_signal_new ("update-ui", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (GladeAppClass, - update_ui_signal), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void on_palette_button_clicked (GladePalette *palette, GladeApp *app) { GladeWidgetClass *class; @@ -273,11 +309,6 @@ clipboard_view_on_delete_cb (GtkWidget *clipboard_view, GdkEvent *e, GladeApp *a return TRUE; } -/** - * glade_app_config_load - * @app: - * Returns: a new GKeyFile - */ static GKeyFile * glade_app_config_load (GladeApp *app) { @@ -293,16 +324,186 @@ glade_app_config_load (GladeApp *app) return config; } +static void +glade_app_init (GladeApp *app) +{ + static gboolean initialized = FALSE; + + if (!initialized) + { +#ifdef G_OS_WIN32 + gchar *prefix; + + prefix = g_win32_get_package_installation_directory (NULL, NULL); + glade_pixmaps_dir = g_build_filename (prefix, "share", PACKAGE, "pixmaps", NULL); + glade_catalogs_dir = g_build_filename (prefix, "share", PACKAGE, "catalogs", NULL); + glade_modules_dir = g_build_filename (prefix, "lib", PACKAGE, "modules", NULL); + glade_locale_dir = g_build_filename (prefix, "share", "locale", NULL); + glade_icon_dir = g_build_filename (prefix, "share", "pixmaps", NULL); + g_free (prefix); +#endif + + glade_cursor_init (); + initialized = TRUE; + } + app->priv = g_new0 (GladeAppPriv, 1); + + app->priv->add_class = NULL; + app->priv->alt_class = NULL; + app->priv->accel_group = NULL; + + /* Initialize app objects */ + app->priv->catalogs = glade_catalog_load_all (); + + /* Create palette */ + app->priv->palette = glade_palette_new (app->priv->catalogs); + g_object_ref (app->priv->palette); + gtk_object_sink (GTK_OBJECT (app->priv->palette)); + gtk_widget_show_all (GTK_WIDGET (app->priv->palette)); + g_signal_connect (G_OBJECT (app->priv->palette), "toggled", + G_CALLBACK (on_palette_button_clicked), app); + g_signal_connect (G_OBJECT (app->priv->palette), "catalog-changed", + G_CALLBACK (on_palette_catalog_changed), app); + + /* Create Editor */ + app->priv->editor = GLADE_EDITOR (glade_editor_new ()); + g_object_ref (app->priv->editor); + gtk_object_sink (GTK_OBJECT (app->priv->editor)); + gtk_widget_show_all (GTK_WIDGET (app->priv->editor)); + glade_editor_refresh (app->priv->editor); + + /* Create clipboard */ + app->priv->clipboard = glade_clipboard_new (); + app->priv->clipboard->view = glade_clipboard_view_new (app->priv->clipboard); + gtk_window_set_title (GTK_WINDOW (app->priv->clipboard->view), _("Clipboard")); + g_signal_connect_after (G_OBJECT (app->priv->clipboard->view), "delete_event", + G_CALLBACK (clipboard_view_on_delete_cb), + app); + + /* Load the configuration file */ + app->priv->config = glade_app_config_load (app); + + /* Undo/Redo button list */ + app->priv->undo_list = app->priv->redo_list = NULL; +} + +static void +glade_app_class_init (GladeAppClass * klass) +{ + GObjectClass *object_class; + g_return_if_fail (klass != NULL); + + parent_class = g_type_class_peek_parent (klass); + object_class = (GObjectClass *) klass; + + object_class->constructor = glade_app_constructor; + object_class->dispose = glade_app_dispose; + object_class->finalize = glade_app_finalize; + object_class->get_property = glade_app_get_property; + object_class->set_property = glade_app_set_property; + + klass->update_ui_signal = glade_app_update_ui_default; + klass->show_properties = NULL; + klass->hide_properties = NULL; + + /** + * GladeApp::update-ui: + * @gladeapp: the #GladeApp which received the signal. + * + * Emitted when a project name changes or a cut/copy/paste/delete occurred. + */ + glade_app_signals[UPDATE_UI_SIGNAL] = + g_signal_new ("update-ui", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GladeAppClass, + update_ui_signal), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + + g_object_class_install_property + (object_class, PROP_ACTIVE_PROJECT, + g_param_spec_object + ("active-project", _("Active Project"), + _("The active project"), + GLADE_TYPE_PROJECT, G_PARAM_READWRITE)); + +} + +GType +glade_app_get_type () +{ + static GType obj_type = 0; + + if (!obj_type) + { + static const GTypeInfo obj_info = + { + sizeof (GladeAppClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) glade_app_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GladeApp), + 0, /* n_preallocs */ + (GInstanceInitFunc) glade_app_init, + NULL /* value_table */ + }; + obj_type = g_type_register_static (G_TYPE_OBJECT, + "GladeApp", &obj_info, 0); + } + return obj_type; +} + +/***************************************************************** + * Public API * + *****************************************************************/ +static void +on_widget_name_changed_cb (GladeProject *project, + GladeWidget *widget, + GladeEditor *editor) +{ + glade_editor_update_widget_name (editor); +} + +static void +on_project_selection_changed_cb (GladeProject *project, GladeApp *app) +{ + GList *list; + gint num; + + g_return_if_fail (GLADE_IS_PROJECT (project)); + g_return_if_fail (GLADE_IS_APP (app)); + + /* Only update the editor if the selection has changed on + * the currently active project. + */ + if (app->priv->editor && + (project == glade_app_get_project ())) + { + list = glade_project_selection_get (project); + num = g_list_length (list); + if (num == 1 && !GLADE_IS_PLACEHOLDER (list->data)) + glade_editor_load_widget (app->priv->editor, + glade_widget_get_from_gobject + (G_OBJECT (list->data))); + else + glade_editor_load_widget (app->priv->editor, NULL); + } +} + /** * glade_app_config_save - * @app: * * Saves the GKeyFile to "g_get_user_config_dir()/GLADE_CONFIG_FILENAME" * * Return 0 on success. */ gint -glade_app_config_save (GladeApp *app) +glade_app_config_save () { GIOChannel *channel; GIOStatus status; @@ -311,10 +512,13 @@ glade_app_config_save (GladeApp *app) GError *error = NULL; gsize size, written, bytes_written = 0; static gboolean error_shown = FALSE; + GladeApp *app; /* If we had any errors; wait untill next session to retry. */ if (error_shown) return -1; + + app = glade_app_get (); /* Just in case... try to create the config directory */ if (g_file_test (config_dir, G_FILE_TEST_IS_DIR) == FALSE) @@ -323,24 +527,24 @@ glade_app_config_save (GladeApp *app) { /* Config dir exists but is not a directory */ glade_util_ui_message - (glade_default_app_get_window(), + (glade_app_get_window(), GLADE_UI_ERROR, _("Trying to save private data to %s directory " "but it is a regular file.\n" "No private data will be saved in this session"), config_dir); - error_shown = TRUE; + error_shown = TRUE; return -1; } else if (g_mkdir (config_dir, S_IRWXU) != 0) { /* Doesnt exist; failed to create */ glade_util_ui_message - (glade_default_app_get_window(), + (glade_app_get_window(), GLADE_UI_ERROR, _("Failed to create directory %s to save private data.\n" "No private data will be saved in this session"), config_dir); - error_shown = TRUE; + error_shown = TRUE; return -1; } } @@ -364,7 +568,7 @@ glade_app_config_save (GladeApp *app) if (status == G_IO_STATUS_ERROR) { glade_util_ui_message - (glade_default_app_get_window(), + (glade_app_get_window(), GLADE_UI_ERROR, _("Error writing private data to %s (%s).\n" "No private data will be saved in this session"), @@ -376,7 +580,7 @@ glade_app_config_save (GladeApp *app) else { glade_util_ui_message - (glade_default_app_get_window(), + (glade_app_get_window(), GLADE_UI_ERROR, _("Error serializing configuration data to save (%s).\n" "No private data will be saved in this session"), @@ -389,7 +593,7 @@ glade_app_config_save (GladeApp *app) else { glade_util_ui_message - (glade_default_app_get_window(), + (glade_app_get_window(), GLADE_UI_ERROR, _("Error opening %s to write private data (%s).\n" "No private data will be saved in this session"), @@ -407,260 +611,158 @@ glade_app_config_save (GladeApp *app) } void -glade_app_set_transient_parent (GladeApp *app, - GtkWindow *parent) +glade_app_set_transient_parent (GtkWindow *parent) { - GList *projects, *objects; - - g_return_if_fail (GLADE_IS_APP (app)); + GList *projects, *objects; + GladeApp *app; + g_return_if_fail (GTK_IS_WINDOW (parent)); + app = glade_app_get (); app->priv->transient_parent = parent; /* Loop over all projects/widgets and set_transient_for the toplevels. */ - for (projects = glade_app_get_projects(app); // projects + for (projects = glade_app_get_projects (); // projects projects; projects = projects->next) for (objects = GLADE_PROJECT (projects->data)->objects; // widgets objects; objects = objects->next) if (GTK_IS_WINDOW (objects->data)) - gtk_window_set_transient_for (GTK_WINDOW (objects->data), parent); + gtk_window_set_transient_for + (GTK_WINDOW (objects->data), parent); } GtkWindow * -glade_app_get_transient_parent (GladeApp *app) +glade_app_get_transient_parent (void) { - g_return_val_if_fail (GLADE_IS_APP (app), NULL); - return app->priv->transient_parent; -} - -static void -glade_app_init (GladeApp *app) -{ - static gboolean initialized = FALSE; - - if (!initialized) - { -#ifdef G_OS_WIN32 - gchar *prefix; - - prefix = g_win32_get_package_installation_directory (NULL, NULL); - glade_pixmaps_dir = g_build_filename (prefix, "share", PACKAGE, "pixmaps", NULL); - glade_catalogs_dir = g_build_filename (prefix, "share", PACKAGE, "catalogs", NULL); - glade_modules_dir = g_build_filename (prefix, "lib", PACKAGE, "modules", NULL); - glade_locale_dir = g_build_filename (prefix, "share", "locale", NULL); - glade_icon_dir = g_build_filename (prefix, "share", "pixmaps", NULL); - g_free (prefix); -#endif - - /* - * 1. Init the cursors - * 2. Create the catalog - * 3. Create the project window - */ - glade_cursor_init (); - initialized = TRUE; - } - app->priv = g_new0 (GladeAppPriv, 1); - - app->priv->add_class = NULL; - app->priv->alt_class = NULL; - app->priv->accel_group = NULL; - - /* Initialize app objects */ - app->priv->catalogs = glade_catalog_load_all (); - - /* Create palette */ - app->priv->palette = glade_palette_new (app->priv->catalogs); - g_object_ref (app->priv->palette); - gtk_object_sink (GTK_OBJECT (app->priv->palette)); - gtk_widget_show_all (GTK_WIDGET (app->priv->palette)); - g_signal_connect (G_OBJECT (app->priv->palette), "toggled", - G_CALLBACK (on_palette_button_clicked), app); - g_signal_connect (G_OBJECT (app->priv->palette), "catalog-changed", - G_CALLBACK (on_palette_catalog_changed), app); - - /* Create Editor */ - app->priv->editor = GLADE_EDITOR (glade_editor_new ()); - g_object_ref (app->priv->editor); - gtk_object_sink (GTK_OBJECT (app->priv->editor)); - gtk_widget_show_all (GTK_WIDGET (app->priv->editor)); - glade_editor_refresh (app->priv->editor); - - /* Create clipboard */ - app->priv->clipboard = glade_clipboard_new (); - app->priv->clipboard->view = glade_clipboard_view_new (app->priv->clipboard); - gtk_window_set_title (GTK_WINDOW (app->priv->clipboard->view), _("Clipboard")); - g_signal_connect_after (G_OBJECT (app->priv->clipboard->view), "delete_event", - G_CALLBACK (clipboard_view_on_delete_cb), - app); - - /* Load the configuration file */ - app->priv->config = glade_app_config_load (app); - - /* Undo/Redo button list */ - app->priv->undo_list = app->priv->redo_list = NULL; -} + GtkWindow *parent; + GladeApp *app = glade_app_get (); -GType -glade_app_get_type () -{ - static GType obj_type = 0; + parent = app->priv->transient_parent; - if (!obj_type) - { - static const GTypeInfo obj_info = - { - sizeof (GladeAppClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) glade_app_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (GladeApp), - 0, /* n_preallocs */ - (GInstanceInitFunc) glade_app_init, - NULL /* value_table */ - }; - obj_type = g_type_register_static (G_TYPE_OBJECT, - "GladeApp", &obj_info, 0); - } - return obj_type; + return parent; } GladeApp * -glade_app_new (void) +glade_app_get (void) { - GladeApp *app; - - app = g_object_new (GLADE_TYPE_APP, NULL); - return app; + if (!the_app) + g_critical ("No available GladeApp"); + return the_app; } void -glade_app_update_ui (GladeApp* app) +glade_app_update_ui (void) { + GladeApp *app = glade_app_get (); + g_signal_emit (G_OBJECT (app), glade_app_signals[UPDATE_UI_SIGNAL], 0); + } void -glade_app_set_window (GladeApp* app, GtkWidget *window) +glade_app_set_window (GtkWidget *window) { + GladeApp *app = glade_app_get (); + app->priv->window = window; } -GtkWidget* -glade_app_get_window (GladeApp* app) +GtkWidget * +glade_app_get_window (void) { + GladeApp *app = glade_app_get (); return app->priv->window; } -GladeEditor* -glade_app_get_editor (GladeApp* app) +GladeEditor * +glade_app_get_editor (void) { + GladeApp *app = glade_app_get (); return app->priv->editor; } -GladeWidgetClass* -glade_app_get_add_class (GladeApp* app) +GladeWidgetClass * +glade_app_get_add_class (void) { + GladeApp *app = glade_app_get (); return app->priv->add_class; } -GladeWidgetClass* -glade_app_get_alt_class (GladeApp* app) +GladeWidgetClass * +glade_app_get_alt_class (void) { + GladeApp *app = glade_app_get (); return app->priv->alt_class; } -GladePalette* -glade_app_get_palette (GladeApp* app) +GladePalette * +glade_app_get_palette (void) { + GladeApp *app = glade_app_get (); return app->priv->palette; } -GladeClipboard* -glade_app_get_clipboard (GladeApp* app) +GladeClipboard * +glade_app_get_clipboard (void) { + GladeApp *app = glade_app_get (); return app->priv->clipboard; } -GtkWidget* -glade_app_get_clipboard_view (GladeApp* app) +GtkWidget * +glade_app_get_clipboard_view (void) { + GladeApp *app = glade_app_get (); return app->priv->clipboard->view; } -GladeProject* -glade_app_get_active_project (GladeApp* app) +GladeProject * +glade_app_get_project (void) { + GladeApp *app = glade_app_get (); return app->priv->active_project; } -GList* -glade_app_get_projects (GladeApp *app) +GList * +glade_app_get_projects (void) { + GladeApp *app = glade_app_get (); return app->priv->projects; } -GKeyFile* -glade_app_get_config (GladeApp *app) +GKeyFile * +glade_app_get_config (void) { + GladeApp *app = glade_app_get (); return app->priv->config; } void -glade_app_add_project_view (GladeApp *app, GladeProjectView *view) +glade_app_add_project_view (GladeProjectView *view) { + GladeApp *app; + g_return_if_fail (GLADE_IS_PROJECT_VIEW (view)); + + app = glade_app_get (); + app->priv->views = g_list_prepend (app->priv->views, view); - app->priv->active_view = view; if (app->priv->active_project) glade_project_view_set_project (view, app->priv->active_project); } -static void -on_widget_name_changed_cb (GladeProject *project, - GladeWidget *widget, - GladeEditor *editor) -{ - glade_editor_update_widget_name (editor); -} - -static void -on_project_selection_changed_cb (GladeProject *project, GladeApp *app) -{ - GList *list; - gint num; - - g_return_if_fail (GLADE_IS_PROJECT (project)); - g_return_if_fail (GLADE_IS_APP (app)); - - /* Only update the editor if the selection has changed on - * the currently active project. - */ - if (app->priv->editor && - (project == glade_app_get_active_project (app))) - { - list = glade_project_selection_get (project); - num = g_list_length (list); - if (num == 1 && !GLADE_IS_PLACEHOLDER (list->data)) - glade_editor_load_widget (app->priv->editor, - glade_widget_get_from_gobject - (G_OBJECT (list->data))); - else - glade_editor_load_widget (app->priv->editor, NULL); - } -} - gboolean -glade_app_is_project_loaded (GladeApp *app, const gchar *project_path) +glade_app_is_project_loaded (const gchar *project_path) { + GladeApp *app; GList *list; gboolean loaded = FALSE; if (project_path == NULL) return FALSE; + app = glade_app_get (); + for (list = app->priv->projects; list; list = list->next) { GladeProject *cur_project = GLADE_PROJECT (list->data); @@ -675,9 +777,9 @@ glade_app_is_project_loaded (GladeApp *app, const gchar *project_path) void -glade_app_show_properties (GladeApp* app, gboolean raise) +glade_app_show_properties (gboolean raise) { - g_return_if_fail (GLADE_IS_APP (app)); + GladeApp *app = glade_app_get (); if (GLADE_APP_GET_CLASS (app)->show_properties) GLADE_APP_GET_CLASS (app)->show_properties (app, raise); @@ -686,25 +788,31 @@ glade_app_show_properties (GladeApp* app, gboolean raise) } void -glade_app_hide_properties (GladeApp* app) +glade_app_hide_properties (void) { - g_return_if_fail (GLADE_IS_APP (app)); + GladeApp *app = glade_app_get (); if (GLADE_APP_GET_CLASS (app)->hide_properties) GLADE_APP_GET_CLASS (app)->hide_properties (app); else g_critical ("%s not implemented\n", G_GNUC_FUNCTION); + } void -glade_app_update_instance_count (GladeApp *app, GladeProject *project) +glade_app_update_instance_count (GladeProject *project) { + GladeApp *app; GladeProject *prj; GList *l; gint temp, max = 0, i = 0, uncounted_projects = 0; + + g_return_if_fail (GLADE_IS_PROJECT (project)); if (project->instance > 0) return; + app = glade_app_get (); + for (l = app->priv->projects; l; l = l->next) { prj = l->data; @@ -725,22 +833,25 @@ glade_app_update_instance_count (GladeApp *app, GladeProject *project) if (uncounted_projects > 1 || g_list_find (app->priv->projects, project) == NULL) project->instance = MAX (max, i); + } void -glade_app_add_project (GladeApp *app, GladeProject *project) +glade_app_add_project (GladeProject *project) { + GladeApp *app; g_return_if_fail (GLADE_IS_PROJECT (project)); /* If the project was previously loaded, don't re-load */ - if (glade_app_is_project_loaded (app, project->path)) + if (glade_app_is_project_loaded (project->path)) { - glade_app_set_project (app, project); + glade_app_set_project (project); return; } + glade_app_update_instance_count (project); - glade_app_update_instance_count (app, project); - + app = glade_app_get (); + app->priv->projects = g_list_append (app->priv->projects, project); /* connect to the project signals so that the editor can be updated */ @@ -753,20 +864,23 @@ glade_app_add_project (GladeApp *app, GladeProject *project) if (app->priv->accel_group) glade_project_set_accel_group (project, app->priv->accel_group); - glade_app_set_project (app, project); + glade_app_set_project (project); /* XXX I think the palette should detect this by itself */ gtk_widget_set_sensitive (GTK_WIDGET (app->priv->palette), TRUE); + } void -glade_app_remove_project (GladeApp *app, GladeProject *project) +glade_app_remove_project (GladeProject *project) { - g_return_if_fail (GLADE_IS_APP (app)); + GladeApp *app; g_return_if_fail (GLADE_IS_PROJECT (project)); + app = glade_app_get (); + app->priv->projects = g_list_remove (app->priv->projects, project); - + /* this is needed to prevent clearing the selection of a closed project */ app->priv->active_project = NULL; @@ -778,18 +892,27 @@ glade_app_remove_project (GladeApp *app, GladeProject *project) gtk_widget_set_sensitive (GTK_WIDGET (app->priv->palette), FALSE); } else - glade_app_set_project (app, g_list_last (app->priv->projects)->data); + glade_app_set_project (g_list_last (app->priv->projects)->data); /* Its safe to just release the project as the project emits a * "close" signal and everyone is responsable for cleaning up at * that point. */ g_object_unref (project); + } + +/** + * glade_app_set_project: + * @project: A #GladeProject + * + * Sets the active project in the #GladeApp to @project. + */ void -glade_app_set_project (GladeApp *app, GladeProject *project) +glade_app_set_project (GladeProject *project) { + GladeApp *app = glade_app_get(); GList *list; g_return_if_fail (GLADE_IS_PROJECT (project)); @@ -816,11 +939,13 @@ glade_app_set_project (GladeApp *app, GladeProject *project) glade_project_view_set_project (view, project); } - /* trigger the selection changed signal to update the editor */ + /* (XXX really ?) trigger the selection changed signal to update the editor */ glade_project_selection_changed (project); /* Update UI */ - glade_app_update_ui (app); + glade_app_update_ui (); + + g_object_notify (G_OBJECT (app), "active-project"); } /** @@ -832,16 +957,20 @@ glade_app_set_project (GladeApp *app, GladeProject *project) * the clipboards selection). */ void -glade_app_command_copy (GladeApp *app) +glade_app_command_copy (void) { + GladeApp *app; GList *widgets = NULL, *list; GladeWidget *widget; gboolean failed = FALSE; - g_return_if_fail (GLADE_IS_APP (app)); - if (app->priv->active_project == NULL) return; + app = glade_app_get(); + if (app->priv->active_project == NULL) + { + return; + } - for (list = glade_default_app_get_selection (); + for (list = glade_app_get_selection (); list && list->data; list = list->next) { widget = glade_widget_get_from_gobject (GTK_WIDGET (list->data)); @@ -851,7 +980,7 @@ glade_app_command_copy (GladeApp *app) if (widget->internal) { glade_util_ui_message - (glade_app_get_window(app), + (glade_app_get_window(), GLADE_UI_INFO, _("You cannot copy a widget " "internal to a composite widget.")); @@ -863,14 +992,15 @@ glade_app_command_copy (GladeApp *app) if (failed == FALSE && widgets != NULL) { glade_command_copy (widgets); - glade_app_update_ui (app); + glade_app_update_ui (); } else if (widgets == NULL) - glade_util_ui_message (glade_app_get_window(app), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_INFO, _("No widget selected.")); if (widgets) g_list_free (widgets); + } /** @@ -882,16 +1012,18 @@ glade_app_command_copy (GladeApp *app) * the clipboards selection). */ void -glade_app_command_cut (GladeApp *app) +glade_app_command_cut (void) { + GladeApp *app; GList *widgets = NULL, *list; GladeWidget *widget; gboolean failed = FALSE; - g_return_if_fail (GLADE_IS_APP (app)); - if (app->priv->active_project == NULL) return; - - for (list = glade_default_app_get_selection (); + app = glade_app_get(); + if (app->priv->active_project == NULL) + return; + + for (list = glade_app_get_selection (); list && list->data; list = list->next) { widget = glade_widget_get_from_gobject (GTK_WIDGET (list->data)); @@ -901,7 +1033,7 @@ glade_app_command_cut (GladeApp *app) if (widget->internal) { glade_util_ui_message - (glade_app_get_window(app), + (glade_app_get_window(), GLADE_UI_INFO, _("You cannot cut a widget " "internal to a composite widget.")); @@ -913,14 +1045,15 @@ glade_app_command_cut (GladeApp *app) if (failed == FALSE && widgets != NULL) { glade_command_cut (widgets); - glade_app_update_ui (app); + glade_app_update_ui (); } else if (widgets == NULL) - glade_util_ui_message (glade_app_get_window(app), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_INFO, _("No widget selected.")); if (widgets) g_list_free (widgets); + } /** @@ -931,8 +1064,9 @@ glade_app_command_cut (GladeApp *app) * selection (the project must have only one object selected). */ void -glade_app_command_paste (GladeApp *app) +glade_app_command_paste (void) { + GladeApp *app; GladeClipboard *clipboard; GList *list; GladeWidget *widget = NULL; @@ -940,12 +1074,12 @@ glade_app_command_paste (GladeApp *app) GladePlaceholder *placeholder; GladeWidget *parent; - - g_return_if_fail (GLADE_IS_APP (app)); - if (app->priv->active_project == NULL) return; + app = glade_app_get(); + if (app->priv->active_project == NULL) + return; list = glade_project_selection_get (app->priv->active_project); - clipboard = glade_app_get_clipboard (app); + clipboard = glade_app_get_clipboard (); /* If there is a selection, dont use a placeholder to paste into */ placeholder = list ? NULL : glade_util_selected_placeholder (); @@ -953,19 +1087,20 @@ glade_app_command_paste (GladeApp *app) /* If there is a selection, paste in to the selected widget, otherwise * paste into the placeholder's parent. */ - parent = list ? glade_widget_get_from_gobject (list->data) : + parent = list ? glade_widget_get_from_gobject (list->data) : (placeholder ? glade_placeholder_get_parent (placeholder) : NULL); /* Check if selection is good */ - if ((list = glade_default_app_get_selection ()) != NULL) + if ((list = glade_app_get_selection ()) != NULL) { if (placeholder == NULL && g_list_length (list) != 1) { - glade_util_ui_message (glade_app_get_window(app), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_INFO, _("Unable to paste to multiple widgets")); + return; } } @@ -973,8 +1108,9 @@ glade_app_command_paste (GladeApp *app) /* Check if we have anything to paste */ if (g_list_length (clipboard->selection) == 0) { - glade_util_ui_message (glade_app_get_window (app), GLADE_UI_INFO, + glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO, _("No widget selected on the clipboard")); + return; } @@ -990,7 +1126,7 @@ glade_app_command_paste (GladeApp *app) */ if (glade_util_widget_pastable (widget, parent) == FALSE) { - glade_util_ui_message (glade_default_app_get_window (), + glade_util_ui_message (glade_app_get_window (), GLADE_UI_ERROR, _("Unable to paste widget %s to parent %s"), widget->name, parent->name); @@ -1011,7 +1147,7 @@ glade_app_command_paste (GladeApp *app) parent && parent->manager != NULL && gtkcontainer_relations != 1) { - glade_util_ui_message (glade_default_app_get_window (), + glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO, _("Only one widget can be pasted at a " "time to this container")); @@ -1022,7 +1158,7 @@ glade_app_command_paste (GladeApp *app) if (parent && parent->manager == NULL && glade_util_count_placeholders (parent) < gtkcontainer_relations) { - glade_util_ui_message (glade_default_app_get_window (), + glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO, _("Insufficient amount of placeholders in " "target container")); @@ -1030,7 +1166,7 @@ glade_app_command_paste (GladeApp *app) } glade_command_paste (clipboard->selection, parent, placeholder); - glade_app_update_ui (app); + glade_app_update_ui (); } @@ -1041,16 +1177,18 @@ glade_app_command_paste (GladeApp *app) * Delete the active project's selection. */ void -glade_app_command_delete (GladeApp *app) +glade_app_command_delete (void) { + GladeApp *app; GList *widgets = NULL, *list; GladeWidget *widget; gboolean failed = FALSE; - g_return_if_fail (GLADE_IS_APP (app)); - if (app->priv->active_project == NULL) return; + app = glade_app_get(); + if (app->priv->active_project == NULL) + return; - for (list = glade_default_app_get_selection (); + for (list = glade_app_get_selection (); list && list->data; list = list->next) { widget = glade_widget_get_from_gobject (GTK_WIDGET (list->data)); @@ -1060,7 +1198,7 @@ glade_app_command_delete (GladeApp *app) if (widget->internal) { glade_util_ui_message - (glade_app_get_window(app), + (glade_app_get_window(), GLADE_UI_INFO, _("You cannot delete a widget " "internal to a composite widget.")); @@ -1072,10 +1210,10 @@ glade_app_command_delete (GladeApp *app) if (failed == FALSE && widgets != NULL) { glade_command_delete (widgets); - glade_app_update_ui (app); + glade_app_update_ui (); } else if (widgets == NULL) - glade_util_ui_message (glade_app_get_window(app), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_INFO, _("No widget selected.")); @@ -1089,18 +1227,16 @@ glade_app_command_delete (GladeApp *app) * Delete the clipboard's selection. */ void -glade_app_command_delete_clipboard (GladeApp *app) +glade_app_command_delete_clipboard (void) { - GladeClipboard *clipboard; - GladeWidget *gwidget; - GList *list; + GladeClipboard *clipboard; + GladeWidget *gwidget; + GList *list; - g_return_if_fail (GLADE_IS_APP (app)); - - clipboard = glade_app_get_clipboard (app); + clipboard = glade_app_get_clipboard (); if (clipboard->selection == NULL) - glade_util_ui_message (glade_app_get_window (app), GLADE_UI_INFO, + glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO, _("No widget selected on the clipboard")); for (list = clipboard->selection; list; list = list->next) @@ -1109,7 +1245,7 @@ glade_app_command_delete_clipboard (GladeApp *app) if (gwidget->internal) { glade_util_ui_message - (glade_default_app_get_window(), + (glade_app_get_window(), GLADE_UI_INFO, _("You cannot delete a widget " "internal to a composite widget.")); @@ -1118,31 +1254,33 @@ glade_app_command_delete_clipboard (GladeApp *app) } glade_command_delete (clipboard->selection); - glade_app_update_ui (app); + glade_app_update_ui (); } void -glade_app_command_undo (GladeApp *app) +glade_app_command_undo (void) { + GladeApp *app = glade_app_get(); if (app->priv->active_project) { glade_command_undo (app->priv->active_project); glade_editor_refresh (app->priv->editor); /* Update UI. */ - glade_app_update_ui (app); + glade_app_update_ui (); } } void -glade_app_command_redo (GladeApp *app) +glade_app_command_redo (void) { + GladeApp *app = glade_app_get(); if (app->priv->active_project) { glade_command_redo (app->priv->active_project); glade_editor_refresh (app->priv->editor); /* Update UI. */ - glade_app_update_ui (app); + glade_app_update_ui (); } } @@ -1153,12 +1291,14 @@ glade_app_command_redo (GladeApp *app) * The acceleration group will be atached to every toplevel widget in this application. */ void -glade_app_set_accel_group (GladeApp *app, GtkAccelGroup *accel_group) +glade_app_set_accel_group (GtkAccelGroup *accel_group) { + GladeApp *app; GList *l; GladeProject *project; - g_return_if_fail(GLADE_IS_APP(app) && - GTK_IS_ACCEL_GROUP (accel_group)); + g_return_if_fail(GTK_IS_ACCEL_GROUP (accel_group)); + + app = glade_app_get (); for (l = app->priv->projects; l; l = l->next) { @@ -1224,8 +1364,9 @@ glade_app_undo_redo_button_new (GladeApp *app, gboolean undo) * The button will be automatically updated with @app's undo stack. */ GtkWidget * -glade_app_undo_button_new (GladeApp *app) +glade_app_undo_button_new (void) { + GladeApp *app = glade_app_get(); return glade_app_undo_redo_button_new (app, TRUE); } @@ -1236,123 +1377,20 @@ glade_app_undo_button_new (GladeApp *app) * The button will be automatically updated with @app's redo stack. */ GtkWidget * -glade_app_redo_button_new (GladeApp *app) +glade_app_redo_button_new (void) { + GladeApp *app = glade_app_get(); return glade_app_undo_redo_button_new (app, FALSE); } -/* Default application convinience functions */ - -static GladeApp *glade_default_app = NULL; - -void -glade_default_app_set (GladeApp *app) -{ - if (app) - g_object_ref (G_OBJECT (app)); - if (glade_default_app) - g_object_unref (glade_default_app); - glade_default_app = app; -} - -GtkWidget* -glade_default_app_get_window (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_get_window (glade_default_app); -} - -GladeEditor* -glade_default_app_get_editor (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_get_editor (glade_default_app); -} - -GladeWidgetClass* -glade_default_app_get_add_class (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_get_add_class (glade_default_app); -} - -GladeWidgetClass* -glade_default_app_get_alt_class (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_get_alt_class (glade_default_app); -} - -GladePalette* -glade_default_app_get_palette (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_get_palette (glade_default_app); -} - -GladeClipboard* -glade_default_app_get_clipboard (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_get_clipboard (glade_default_app); -} GList* -glade_default_app_get_projects (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_get_projects (glade_default_app); -} - -void -glade_default_app_show_properties (gboolean raise) -{ - g_return_if_fail (glade_default_app != NULL); - return glade_app_show_properties (glade_default_app, raise); -} - -void -glade_default_app_hide_properties (void) -{ - g_return_if_fail (glade_default_app != NULL); - return glade_app_hide_properties (glade_default_app); -} - -GladeProject* -glade_default_app_get_active_project (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_get_active_project (glade_default_app); -} - -void -glade_default_app_update_ui (void) -{ - g_return_if_fail (glade_default_app != NULL); - glade_app_update_ui (glade_default_app); -} - -void -glade_default_app_set_transient_parent (GtkWindow *parent) -{ - g_return_if_fail (glade_default_app != NULL); - glade_app_set_transient_parent (glade_default_app, parent); -} - -GtkWindow * -glade_default_app_get_transient_parent (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_get_transient_parent (glade_default_app); -} - -GList* -glade_default_app_get_selection (void) +glade_app_get_selection (void) { GList *selection = NULL, *list; GladeProject *project; - for (list = glade_default_app_get_projects (); + for (list = glade_app_get_projects (); list && list->data; list = list->next) { /* Only one project may have selection at a time @@ -1369,20 +1407,19 @@ glade_default_app_get_selection (void) gboolean -glade_default_app_is_selected (GObject *object) +glade_app_is_selected (GObject *object) { - return (g_list_find (glade_default_app_get_selection (), - object) != NULL); + return (g_list_find (glade_app_get_selection (), object) != NULL); } void -glade_default_app_selection_set (GObject *object, - gboolean emit_signal) +glade_app_selection_set (GObject *object, + gboolean emit_signal) { GList *list; GladeProject *project; - for (list = glade_default_app_get_projects (); + for (list = glade_app_get_projects (); list && list->data; list = list->next) { project = list->data; @@ -1402,8 +1439,8 @@ glade_default_app_selection_set (GObject *object, } void -glade_default_app_selection_add (GObject *object, - gboolean emit_signal) +glade_app_selection_add (GObject *object, + gboolean emit_signal) { GList *list; GladeWidget *widget = glade_widget_get_from_gobject (object), @@ -1413,7 +1450,7 @@ glade_default_app_selection_add (GObject *object, /* Ignore request if the there is a selection * from another project. */ - if ((list = glade_default_app_get_selection ()) != NULL) + if ((list = glade_app_get_selection ()) != NULL) { selected = glade_widget_get_from_gobject (list->data); if (glade_widget_get_project (selected) != project) @@ -1423,8 +1460,8 @@ glade_default_app_selection_add (GObject *object, } void -glade_default_app_selection_remove (GObject *object, - gboolean emit_signal) +glade_app_selection_remove (GObject *object, + gboolean emit_signal) { GladeWidget *widget = glade_widget_get_from_gobject (object); GladeProject *project = glade_widget_get_project (widget);; @@ -1433,13 +1470,13 @@ glade_default_app_selection_remove (GObject *object, } void -glade_default_app_selection_clear (gboolean emit_signal) +glade_app_selection_clear (gboolean emit_signal) { GList *list; GladeProject *project; glade_util_clear_selection (); - for (list = glade_default_app_get_projects (); + for (list = glade_app_get_projects (); list && list->data; list = list->next) { project = list->data; @@ -1448,64 +1485,15 @@ glade_default_app_selection_clear (gboolean emit_signal) } void -glade_default_app_selection_changed (void) +glade_app_selection_changed (void) { GList *list; GladeProject *project; - for (list = glade_default_app_get_projects (); + for (list = glade_app_get_projects (); list && list->data; list = list->next) { project = list->data; glade_project_selection_changed (project); } } - -GtkWidget * -glade_default_app_undo_button_new (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_undo_redo_button_new (glade_default_app, TRUE); -} - -GtkWidget * -glade_default_app_redo_button_new (void) -{ - g_return_val_if_fail (glade_default_app != NULL, NULL); - return glade_app_undo_redo_button_new (glade_default_app, FALSE); -} - -void -glade_default_app_command_cut (void) -{ - g_return_if_fail (glade_default_app != NULL); - return glade_app_command_cut (glade_default_app); -} - -void -glade_default_app_command_copy (void) -{ - g_return_if_fail (glade_default_app != NULL); - return glade_app_command_copy (glade_default_app); -} - -void -glade_default_app_command_paste (void) -{ - g_return_if_fail (glade_default_app != NULL); - return glade_app_command_paste (glade_default_app); -} - -void -glade_default_app_command_delete (void) -{ - g_return_if_fail (glade_default_app != NULL); - return glade_app_command_delete (glade_default_app); -} - -void -glade_default_app_command_delete_clipboard (void) -{ - g_return_if_fail (glade_default_app != NULL); - return glade_app_command_delete_clipboard (glade_default_app); -} diff --git a/src/glade-app.h b/src/glade-app.h index a966b62b..c430cb8a 100644 --- a/src/glade-app.h +++ b/src/glade-app.h @@ -64,150 +64,104 @@ LIBGLADEUI_API GType glade_app_get_type (void) G_GNUC_CONST; LIBGLADEUI_API -GladeApp* glade_app_new (void); +GladeApp* glade_app_get (void); LIBGLADEUI_API -void glade_app_update_ui (GladeApp* app); +void glade_app_update_ui (void); LIBGLADEUI_API -void glade_app_set_window (GladeApp* app, GtkWidget *window); +void glade_app_set_window (GtkWidget *window); LIBGLADEUI_API -GtkWidget* glade_app_get_window (GladeApp* app); +GtkWidget* glade_app_get_window (void); LIBGLADEUI_API -GladeEditor* glade_app_get_editor (GladeApp* app); +GladeEditor* glade_app_get_editor (void); LIBGLADEUI_API -GladeWidgetClass* glade_app_get_add_class (GladeApp* app); +GladeWidgetClass* glade_app_get_add_class (void); LIBGLADEUI_API -GladeWidgetClass* glade_app_get_alt_class (GladeApp* app); +GladeWidgetClass* glade_app_get_alt_class (void); LIBGLADEUI_API -GladePalette* glade_app_get_palette (GladeApp* app); +GladePalette* glade_app_get_palette (void); LIBGLADEUI_API -GladeClipboard* glade_app_get_clipboard (GladeApp* app); +GladeClipboard* glade_app_get_clipboard (void); LIBGLADEUI_API -GtkWidget* glade_app_get_clipboard_view (GladeApp* app); +GtkWidget* glade_app_get_clipboard_view (void); LIBGLADEUI_API -GladeProject* glade_app_get_active_project (GladeApp* app); +GladeProject* glade_app_get_project (void); LIBGLADEUI_API -void glade_app_set_project (GladeApp *app, GladeProject *project); +void glade_app_set_project (GladeProject *project); LIBGLADEUI_API -void glade_app_add_project (GladeApp *app, GladeProject *project); +void glade_app_add_project (GladeProject *project); LIBGLADEUI_API -void glade_app_remove_project (GladeApp *app, GladeProject *project); +void glade_app_remove_project (GladeProject *project); LIBGLADEUI_API -GList* glade_app_get_projects (GladeApp *app); +GList* glade_app_get_projects (void); LIBGLADEUI_API -GKeyFile* glade_app_get_config (GladeApp *app); +GKeyFile* glade_app_get_config (void); LIBGLADEUI_API -gboolean glade_app_is_project_loaded (GladeApp *app, const gchar *project_path); +gboolean glade_app_is_project_loaded (const gchar *project_path); LIBGLADEUI_API -void glade_app_show_properties (GladeApp* app, gboolean raise); +void glade_app_show_properties (gboolean raise); LIBGLADEUI_API -void glade_app_hide_properties (GladeApp* app); +void glade_app_hide_properties (void); LIBGLADEUI_API -void glade_app_add_project_view (GladeApp *app, GladeProjectView *view); +void glade_app_add_project_view (GladeProjectView *view); LIBGLADEUI_API -void glade_app_command_copy (GladeApp *app); +void glade_app_command_copy (void); LIBGLADEUI_API -void glade_app_command_cut (GladeApp *app); +void glade_app_command_cut (void); LIBGLADEUI_API -void glade_app_command_paste (GladeApp *app); +void glade_app_command_paste (void); LIBGLADEUI_API -void glade_app_command_delete (GladeApp *app); +void glade_app_command_delete (void); +LIBGLADEUI_API +void glade_app_command_delete_clipboard (void); LIBGLADEUI_API -void glade_app_command_undo (GladeApp *app); +void glade_app_command_undo (void); LIBGLADEUI_API -void glade_app_command_redo (GladeApp *app); +void glade_app_command_redo (void); LIBGLADEUI_API -gint glade_app_config_save (GladeApp *app); -LIBGLADEUI_API -void glade_app_set_transient_parent (GladeApp *app, GtkWindow *parent); +gint glade_app_config_save (void); LIBGLADEUI_API -GtkWindow *glade_app_get_transient_parent (GladeApp *app); +void glade_app_set_transient_parent (GtkWindow *parent); LIBGLADEUI_API -void glade_app_set_accel_group (GladeApp *app, GtkAccelGroup *accel_group); -LIBGLADEUI_API -void glade_app_update_instance_count (GladeApp *app, GladeProject *project); - +GtkWindow *glade_app_get_transient_parent (void); LIBGLADEUI_API -GtkWidget *glade_app_undo_button_new (GladeApp *app); +void glade_app_set_accel_group (GtkAccelGroup *accel_group); LIBGLADEUI_API -GtkWidget *glade_app_redo_button_new (GladeApp *app); +void glade_app_update_instance_count (GladeProject *project); -/* Default glade application */ -LIBGLADEUI_API -void glade_default_app_set (GladeApp *app); -LIBGLADEUI_API -GtkWidget* glade_default_app_get_window (void); -LIBGLADEUI_API -GladeEditor* glade_default_app_get_editor (void); -LIBGLADEUI_API -GladeWidgetClass* glade_default_app_get_add_class (void); -LIBGLADEUI_API -GladeWidgetClass* glade_default_app_get_alt_class (void); -LIBGLADEUI_API -GladePalette* glade_default_app_get_palette (void); -LIBGLADEUI_API -GladeClipboard* glade_default_app_get_clipboard (void); -LIBGLADEUI_API -GladeProject* glade_default_app_get_active_project (void); -LIBGLADEUI_API -void glade_default_app_update_ui (void); LIBGLADEUI_API -GList* glade_default_app_get_selection (void); +GtkWidget *glade_app_undo_button_new (void); LIBGLADEUI_API -GList* glade_default_app_get_projects (void); -LIBGLADEUI_API -void glade_default_app_show_properties (gboolean raise); -LIBGLADEUI_API -void glade_default_app_hide_properties (void); -LIBGLADEUI_API -void glade_default_app_set_transient_parent (GtkWindow *parent); -LIBGLADEUI_API -GtkWindow *glade_default_app_get_transient_parent (void); +GtkWidget *glade_app_redo_button_new (void); LIBGLADEUI_API -GtkWidget *glade_default_app_undo_button_new (void); -LIBGLADEUI_API -GtkWidget *glade_default_app_redo_button_new (void); - - -/* GladeCommand interface stuff - */ -LIBGLADEUI_API -void glade_default_app_command_cut (void); -LIBGLADEUI_API -void glade_default_app_command_copy (void); -LIBGLADEUI_API -void glade_default_app_command_paste (void); -LIBGLADEUI_API -void glade_default_app_command_delete (void); -LIBGLADEUI_API -void glade_default_app_command_delete_clipboard (void); +GList *glade_app_get_selection (void); /* These handle selection on a global scope and take care * of multiple project logic. */ LIBGLADEUI_API -gboolean glade_default_app_is_selected (GObject *object); +gboolean glade_app_is_selected (GObject *object); LIBGLADEUI_API -void glade_default_app_selection_set (GObject *object, - gboolean emit_signal); +void glade_app_selection_set (GObject *object, + gboolean emit_signal); LIBGLADEUI_API -void glade_default_app_selection_add (GObject *object, - gboolean emit_signal); +void glade_app_selection_add (GObject *object, + gboolean emit_signal); LIBGLADEUI_API -void glade_default_app_selection_remove (GObject *object, - gboolean emit_signal); +void glade_app_selection_remove (GObject *object, + gboolean emit_signal); LIBGLADEUI_API -void glade_default_app_selection_clear (gboolean emit_signal); +void glade_app_selection_clear (gboolean emit_signal); LIBGLADEUI_API -void glade_default_app_selection_changed(void); +void glade_app_selection_changed(void); G_END_DECLS diff --git a/src/glade-builtins.c b/src/glade-builtins.c index 8c1e47bb..84957679 100644 --- a/src/glade-builtins.c +++ b/src/glade-builtins.c @@ -37,7 +37,6 @@ struct _GladeParamSpecObjects { GParamSpec parent_instance; GType type; - GPtrArray *objects; }; @@ -97,23 +96,143 @@ glade_standard_stock_spec (void) 0, G_PARAM_READWRITE); } + /**************************************************************** - * Built-in GladeParamSpecObjects for object array properties * + * A GList boxed type used by GladeParamSpecObjects and * + * GladeParamSpecAccel * ****************************************************************/ GType glade_glist_get_type (void) { - static GType type_id = 0; + static GType type_id = 0; + + if (!type_id) + type_id = g_boxed_type_register_static + ("GladeGList", + (GBoxedCopyFunc) g_list_copy, + (GBoxedFreeFunc) g_list_free); + return type_id; +} + + + +/**************************************************************** + * Built-in GladeParamSpecAccel for accelerator properties * + ****************************************************************/ +#if 0 +static void +param_accel_init (GParamSpec *pspec) +{ + GladeParamSpecAccel *ospec = GLADE_PARAM_SPEC_ACCEL (pspec); + ospec->type = G_TYPE_OBJECT; +} - if (!type_id) - type_id = g_boxed_type_register_static ("GladeGList", - (GBoxedCopyFunc) g_list_copy, - (GBoxedFreeFunc) g_list_free); - return type_id; +static void +param_accel_set_default (GParamSpec *pspec, + GValue *value) +{ + if (value->data[0].v_pointer != NULL) + { + g_free (value->data[0].v_pointer); + } + value->data[0].v_pointer = NULL; } +static gboolean +param_accel_validate (GParamSpec *pspec, + GValue *value) +{ + GladeParamSpecAccel *ospec = GLADE_PARAM_SPEC_ACCEL (pspec); + GList *accels, *list, *toremove = NULL; + GladeAccelInfo *info; + + accel = value->data[0].v_pointer; + + for (list = accels; list; list = list->next) + { + info = list->data; + + /* Is it a valid key ? */ + if (info->key /* XXX */ || + /* Does the modifier contain any unwanted bits ? */ + info->modifier & GLADE_MODIFIER_MASK || + /* Do we have a signal ? */ + info->signal == NULL) + toremove = g_list_prepend (toremove, info); + } + + for (list = toremove; list; list = list->next) + { + object = list->data; + accels = g_list_remove (accels, object); + } + if (toremove) g_list_free (toremove); + + value->data[0].v_pointer = accels; + return toremove != NULL; +} +static gint +param_accel_values_cmp (GParamSpec *pspec, + const GValue *value1, + const GValue *value2) +{ + guint8 *p1 = value1->data[0].v_pointer; + guint8 *p2 = value2->data[0].v_pointer; + + /* not much to compare here, try to at least provide stable lesser/greater result */ + + return p1 < p2 ? -1 : p1 > p2; +} + +GType +glade_param_accel_get_type (void) +{ + static GType accel_type = 0; + + if (accel_type == 0) + { + static /* const */ GParamSpecTypeInfo pspec_info = { + sizeof (GladeParamSpecAccel), /* instance_size */ + 16, /* n_preallocs */ + param_accel_init, /* instance_init */ + 0xdeadbeef, /* value_type, assigned further down */ + NULL, /* finalize */ + param_accel_set_default, /* value_set_default */ + param_accel_validate, /* value_validate */ + param_accel_values_cmp, /* values_cmp */ + }; + pspec_info.value_type = GLADE_TYPE_GLIST; + + accel_type = g_param_type_register_static + ("GladeParamAccel", &pspec_info); + } + return accel_type; +} + +GParamSpec * +glade_param_spec_accel (const gchar *name, + const gchar *nick, + const gchar *blurb, + GType accepted_type, + GParamFlags flags) +{ + GladeParamSpecAccel *pspec; + + pspec = g_param_spec_internal (GLADE_TYPE_PARAM_ACCEL, + name, nick, blurb, flags); + + pspec->type = accepted_type; + return G_PARAM_SPEC (pspec); +} +#endif + +/**************************************************************** + * Built-in GladeParamSpecObjects for object list properties * + * (Used as a pspec to desctibe an AtkRelationSet, but can * + * for any object list property) * + ****************************************************************/ static void param_objects_init (GParamSpec *pspec) { @@ -145,10 +264,15 @@ param_objects_validate (GParamSpec *pspec, for (list = objects; list; list = list->next) { object = list->data; - if (!g_value_type_compatible (G_OBJECT_TYPE (object), ospec->type)) - { + + if (G_TYPE_IS_INTERFACE (ospec->type) && + glade_util_class_implements_interface + (G_OBJECT_TYPE (object), ospec->type) == FALSE) + toremove = g_list_prepend (toremove, object); + else if (G_TYPE_IS_INTERFACE (ospec->type) == FALSE && + g_type_is_a (G_OBJECT_TYPE (object), + ospec->type) == FALSE) toremove = g_list_prepend (toremove, object); - } } for (list = toremove; list; list = list->next) @@ -184,7 +308,7 @@ glade_param_objects_get_type (void) if (objects_type == 0) { static /* const */ GParamSpecTypeInfo pspec_info = { - sizeof (GParamSpecObject), /* instance_size */ + sizeof (GladeParamSpecObjects), /* instance_size */ 16, /* n_preallocs */ param_objects_init, /* instance_init */ 0xdeadbeef, /* value_type, assigned further down */ @@ -224,6 +348,11 @@ glade_param_spec_objects_set_type (GladeParamSpecObjects *pspec, pspec->type = type; } +GType +glade_param_spec_objects_get_type (GladeParamSpecObjects *pspec) +{ + return pspec->type; +} /* This was developed for the purpose of holding a list * of 'targets' in an AtkRelation (we are setting it up diff --git a/src/glade-builtins.h b/src/glade-builtins.h index 918fb5bc..d4dd70e2 100644 --- a/src/glade-builtins.h +++ b/src/glade-builtins.h @@ -41,6 +41,7 @@ LIBGLADEUI_API GParamSpec *glade_param_spec_objects (const gchar *name, LIBGLADEUI_API void glade_param_spec_objects_set_type (GladeParamSpecObjects *pspec, GType type); +LIBGLADEUI_API GType glade_param_spec_objects_get_type (GladeParamSpecObjects *pspec); LIBGLADEUI_API GParamSpec **glade_list_atk_relations (GType owner_type, guint *n_specs); diff --git a/src/glade-clipboard-view.c b/src/glade-clipboard-view.c index 3e034e81..bd15d1a8 100644 --- a/src/glade-clipboard-view.c +++ b/src/glade-clipboard-view.c @@ -230,7 +230,7 @@ glade_clipboard_view_create_tree_view (GladeClipboardView *view) static void glade_clipboard_view_construct (GladeClipboardView *view) { - GtkWidget *scrolled_window; + GtkWidget *scrolled_window, *viewport; view->model = gtk_list_store_new (1, G_TYPE_POINTER); @@ -238,12 +238,20 @@ glade_clipboard_view_construct (GladeClipboardView *view) glade_clipboard_view_create_tree_view (view); glade_clipboard_view_refresh_sel (view); + viewport = gtk_viewport_new (NULL, NULL); + gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_OUT); + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type + (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); + gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), + GLADE_GENERIC_BORDER_WIDTH); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (scrolled_window), view->widget); - gtk_container_add (GTK_CONTAINER (view), scrolled_window); + gtk_container_add (GTK_CONTAINER (viewport), scrolled_window); + gtk_container_add (GTK_CONTAINER (view), viewport); gtk_window_set_default_size (GTK_WINDOW (view), GLADE_CLIPBOARD_VIEW_WIDTH, diff --git a/src/glade-command.c b/src/glade-command.c index bb895859..4816e71c 100644 --- a/src/glade-command.c +++ b/src/glade-command.c @@ -375,7 +375,7 @@ glade_command_push_undo (GladeProject *project, GladeCommand *cmd) else project->prev_redo_item = g_list_next (project->prev_redo_item); - glade_default_app_update_ui (); + glade_app_update_ui (); } /**************************************************/ @@ -507,7 +507,7 @@ glade_command_set_property_collapse (GladeCommand *this, GladeCommand *other) this->description = other->description; other->description = NULL; - glade_default_app_update_ui (); + glade_app_update_ui (); } @@ -733,7 +733,7 @@ glade_command_set_name_collapse (GladeCommand *this, GladeCommand *other) g_free (this->description); this->description = g_strdup_printf (_("Renaming %s to %s"), nthis->name, nthis->old_name); - glade_default_app_update_ui (); + glade_app_update_ui (); } /* this function takes the ownership of name */ @@ -822,11 +822,11 @@ glade_command_placeholder_connect (CommandData *cdata, static gboolean glade_command_create_execute (GladeCommandCreateDelete *me) { - GladeClipboard *clipboard = glade_default_app_get_clipboard(); + GladeClipboard *clipboard = glade_app_get_clipboard(); CommandData *cdata = NULL; GList *list, *wlist = NULL, *l; - glade_default_app_selection_clear (FALSE); + glade_app_selection_clear (FALSE); for (list = me->widgets; list && list->data; list = list->next) { @@ -904,7 +904,7 @@ glade_command_create_execute (GladeCommandCreateDelete *me) glade_project_add_object (GLADE_PROJECT (cdata->widget->project), NULL, cdata->widget->object); - glade_default_app_selection_add + glade_app_selection_add (cdata->widget->object, TRUE); } } @@ -924,7 +924,7 @@ glade_command_create_execute (GladeCommandCreateDelete *me) static gboolean glade_command_delete_execute (GladeCommandCreateDelete *me) { - GladeClipboard *clipboard = glade_default_app_get_clipboard(); + GladeClipboard *clipboard = glade_app_get_clipboard(); CommandData *cdata; GList *list, *wlist = NULL; @@ -1038,7 +1038,7 @@ glade_command_create_delete_collapse (GladeCommand *this, GladeCommand *other) void glade_command_delete (GList *widgets) { - GladeClipboard *clipboard = glade_default_app_get_clipboard(); + GladeClipboard *clipboard = glade_app_get_clipboard(); GladeCommandCreateDelete *me; GladeWidget *widget = NULL; CommandData *cdata; @@ -1059,7 +1059,7 @@ glade_command_delete (GList *widgets) widget = list->data; if (widget->internal) { - glade_util_ui_message (glade_default_app_get_window(), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_WARN, _("You cannot delete a widget internal to a composite widget.")); return; @@ -1219,14 +1219,13 @@ GLADE_MAKE_COMMAND (GladeCommandCutCopyPaste, glade_command_cut_copy_paste); static gboolean glade_command_paste_execute (GladeCommandCutCopyPaste *me) { - GladeProject *active_project = - glade_default_app_get_active_project (); + GladeProject *active_project = glade_app_get_project (); CommandData *cdata; GList *list, *remove = NULL, *l; if (me->widgets) { - glade_default_app_selection_clear (FALSE); + glade_app_selection_clear (FALSE); for (list = me->widgets; list && list->data; list = list->next) { @@ -1310,16 +1309,16 @@ glade_command_paste_execute (GladeCommandCutCopyPaste *me) (me->project, cdata->project, cdata->widget->object); - glade_default_app_selection_add + glade_app_selection_add (cdata->widget->object, FALSE); glade_widget_show (cdata->widget); } - glade_default_app_selection_changed (); + glade_app_selection_changed (); if (remove) { - glade_clipboard_remove (glade_default_app_get_clipboard(), remove); + glade_clipboard_remove (glade_app_get_clipboard(), remove); g_list_free (remove); } } @@ -1362,7 +1361,7 @@ glade_command_cut_execute (GladeCommandCutCopyPaste *me) if (add) { - glade_clipboard_add (glade_default_app_get_clipboard(), add); + glade_clipboard_add (glade_app_get_clipboard(), add); g_list_free (add); } return TRUE; @@ -1378,7 +1377,7 @@ glade_command_copy_execute (GladeCommandCutCopyPaste *me) if (add) { - glade_clipboard_add (glade_default_app_get_clipboard(), add); + glade_clipboard_add (glade_app_get_clipboard(), add); g_list_free (add); } return TRUE; @@ -1394,7 +1393,7 @@ glade_command_copy_undo (GladeCommandCutCopyPaste *me) if (remove) { - glade_clipboard_remove (glade_default_app_get_clipboard(), remove); + glade_clipboard_remove (glade_app_get_clipboard(), remove); g_list_free (remove); } return TRUE; @@ -1524,7 +1523,7 @@ glade_command_cut_copy_paste_common (GList *widgets, me->project = glade_widget_get_project (some_widget); } else if (type == GLADE_PASTE) - me->project = glade_default_app_get_active_project(); + me->project = glade_app_get_project(); else me->project = glade_widget_get_project (widget); @@ -1645,7 +1644,7 @@ glade_command_cut_copy_paste_common (GList *widgets, */ if (glade_command_cut_copy_paste_execute (GLADE_COMMAND (me))) glade_command_push_undo - (glade_default_app_get_active_project(), + (glade_app_get_project(), GLADE_COMMAND (me)); else g_object_unref (G_OBJECT (me)); diff --git a/src/glade-editor-property.c b/src/glade-editor-property.c index 5930f92a..3e2863fc 100644 --- a/src/glade-editor-property.c +++ b/src/glade-editor-property.c @@ -118,6 +118,10 @@ static MAKE_TYPE(func, type, GLADE_TYPE_EDITOR_PROPERTY) GladeEditorPropertyClass *******************************************************************************/ +/* declare this forwardly for the finalize routine */ +static void glade_editor_property_load_common (GladeEditorProperty *eprop, + GladeProperty *property); + /* For use in editor implementations */ static void @@ -269,7 +273,7 @@ glade_editor_property_finalize (GObject *object) GladeEditorProperty *eprop = GLADE_EDITOR_PROPERTY (object); /* detatch from loaded property */ - glade_editor_property_load (eprop, NULL); + glade_editor_property_load_common (eprop, NULL); G_OBJECT_CLASS (table_class)->finalize (object); } @@ -763,6 +767,7 @@ typedef struct { GladeEditorProperty parent_instance; GtkTreeModel *model; + GtkWidget *entry; } GladeEPropFlags; GLADE_MAKE_EPROP (GladeEPropFlags, glade_eprop_flags) @@ -786,20 +791,19 @@ glade_eprop_flags_load (GladeEditorProperty *eprop, GladeProperty *property) GladeEPropFlags *eprop_flags = GLADE_EPROP_FLAGS (eprop); GFlagsClass *class; guint flag_num, value; - + GString *string = g_string_new (NULL); /* Chain up first */ editor_property_class->load (eprop, property); + gtk_list_store_clear(GTK_LIST_STORE(eprop_flags->model)); + if (property) { - /* Populate the model with the flags. */ - class = g_type_class_ref (G_VALUE_TYPE (property->value)); value = g_value_get_flags (property->value); - gtk_list_store_clear(GTK_LIST_STORE(eprop_flags->model)); /* Step through each of the flags in the class. */ for (flag_num = 0; flag_num < class->n_values; flag_num++) { GtkTreeIter iter; @@ -813,6 +817,14 @@ glade_eprop_flags_load (GladeEditorProperty *eprop, GladeProperty *property) value_name = glade_property_class_get_displayable_value (eprop->class, class->values[flag_num].value); + /* Setup string for property label */ + if (setting) + { + if (string->len > 0) + g_string_append (string, "|"); + g_string_append (string, value_name); + } + if (value_name == NULL) value_name = class->values[flag_num].value_name; /* Add a row to represent the flag. */ @@ -823,9 +835,13 @@ glade_eprop_flags_load (GladeEditorProperty *eprop, GladeProperty *property) FLAGS_COLUMN_SYMBOL, value_name, -1); + } g_type_class_unref(class); } + + gtk_entry_set_text (GTK_ENTRY (eprop_flags->entry), + g_string_free (string, FALSE)); } @@ -842,7 +858,7 @@ flag_toggled_direct (GtkCellRendererToggle *cell, gint flag_num=0; GFlagsClass *class; - GladeEPropFlags *eprop_flags= GLADE_EPROP_FLAGS(eprop); + GladeEPropFlags *eprop_flags = GLADE_EPROP_FLAGS(eprop); if (!eprop->property) return ; @@ -917,9 +933,6 @@ glade_eprop_flags_create_treeview(GladeEditorProperty *eprop) GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); - gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), - GLADE_GENERIC_BORDER_WIDTH); - gtk_widget_show (scrolled_window); @@ -960,7 +973,7 @@ glade_eprop_flags_show_dialog (GtkWidget *button, { GtkWidget *editor; GtkWidget *dialog; - GtkWidget *scrolled_window; + GtkWidget *swindow; guint response_id ; editor = gtk_widget_get_toplevel (button); @@ -974,9 +987,11 @@ glade_eprop_flags_show_dialog (GtkWidget *button, NULL); gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400); - scrolled_window = glade_eprop_flags_create_treeview(eprop); + swindow = glade_eprop_flags_create_treeview (eprop); + gtk_container_set_border_width (GTK_CONTAINER (swindow), + GLADE_GENERIC_BORDER_WIDTH); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), - scrolled_window, TRUE, TRUE, 0); + swindow, TRUE, TRUE, 0); response_id = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); @@ -986,13 +1001,20 @@ glade_eprop_flags_show_dialog (GtkWidget *button, static GtkWidget * glade_eprop_flags_create_input (GladeEditorProperty *eprop) { - GtkWidget *hbox; - GtkWidget *button; - GtkWidget *widget; + GtkWidget *vbox, *hbox, *button, *widget; + GladeEPropFlags *eprop_flags = GLADE_EPROP_FLAGS(eprop); + + hbox = gtk_hbox_new (FALSE, 0); + vbox = gtk_vbox_new (FALSE, 0); + + widget = glade_eprop_flags_create_treeview (eprop); + + eprop_flags->entry = gtk_entry_new (); + gtk_entry_set_editable (GTK_ENTRY (eprop_flags->entry), FALSE); - hbox = gtk_hbox_new (FALSE, 0); - widget = glade_eprop_flags_create_treeview(eprop); - gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), eprop_flags->entry, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); button = gtk_button_new_with_label ("..."); gtk_widget_show (button); @@ -1895,6 +1917,20 @@ glade_eprop_object_name (const gchar *name, return g_string_free (string, FALSE); } +static gboolean +glade_eprop_object_is_selected (GladeEditorProperty *eprop, + GladeWidget *widget) +{ + GList *list; + + if (GLADE_IS_PARAM_SPEC_OBJECTS (eprop->class->pspec)) + { + glade_property_get (eprop->property, &list); + return g_list_find (list, widget->object) != NULL; + } + return glade_property_equals (eprop->property, widget->object); +} + /* * Note that widgets is a list of GtkWidgets, while what we store @@ -1916,11 +1952,29 @@ glade_eprop_object_populate_view_real (GladeEditorProperty *eprop, if ((widget = glade_widget_get_from_gobject (list->data)) != NULL) { - good_type = g_type_is_a (widget->widget_class->type, - eprop->class->pspec->value_type); - has_decendant = glade_widget_has_decendant - (widget, eprop->class->pspec->value_type); + if (GLADE_IS_PARAM_SPEC_OBJECTS (eprop->class->pspec)) + { + has_decendant = glade_widget_has_decendant + (widget, + glade_param_spec_objects_get_type + (GLADE_PARAM_SPEC_OBJECTS(eprop->class->pspec))); + good_type = + glade_util_class_implements_interface + (widget->widget_class->type, + glade_param_spec_objects_get_type + (GLADE_PARAM_SPEC_OBJECTS(eprop->class->pspec))); + } + else + { + has_decendant = glade_widget_has_decendant + (widget, eprop->class->pspec->value_type); + + good_type = g_type_is_a (widget->widget_class->type, + eprop->class->pspec->value_type); + + } + if (good_type || has_decendant) { gtk_tree_store_append (model, &iter, parent_iter); @@ -1937,8 +1991,8 @@ glade_eprop_object_populate_view_real (GladeEditorProperty *eprop, OBJ_COLUMN_SELECTABLE, good_type && (widget != eprop->property->widget), OBJ_COLUMN_SELECTED, - good_type && glade_property_equals (eprop->property, - widget->object), -1); + good_type && glade_eprop_object_is_selected + (eprop, widget), -1); } if (has_decendant && @@ -1962,7 +2016,7 @@ glade_eprop_object_populate_view (GladeEditorProperty *eprop, GtkTreeView *view) { GtkTreeStore *model = (GtkTreeStore *)gtk_tree_view_get_model (view); - GladeProject *project = glade_default_app_get_active_project (); + GladeProject *project = glade_app_get_project (); GList *list, *toplevels = NULL; /* Make a list of only the toplevel widgets */ @@ -2020,25 +2074,29 @@ glade_eprop_object_selected (GtkCellRendererToggle *cell, { GtkTreePath *path = gtk_tree_path_new_from_string (path_str); GtkTreeIter iter; - gboolean enabled; + gboolean enabled, radio; + + radio = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model), "radio-list")); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, OBJ_COLUMN_SELECTED, &enabled, -1); - if (enabled == FALSE) - { - /* Clear the rest of the view first - */ + /* Clear the rest of the view first + */ + if (radio) gtk_tree_model_foreach (model, glade_eprop_object_clear_iter, NULL); - gtk_tree_store_set (GTK_TREE_STORE (model), &iter, - OBJ_COLUMN_SELECTED, !enabled, -1); - } + + gtk_tree_store_set (GTK_TREE_STORE (model), &iter, + OBJ_COLUMN_SELECTED, + radio ? TRUE : !enabled, -1); + gtk_tree_path_free (path); } static GtkWidget * -glade_eprop_object_view (GladeEditorProperty *eprop) +glade_eprop_object_view (GladeEditorProperty *eprop, + gboolean radio) { GtkWidget *view_widget; GtkTreeModel *model; @@ -2056,6 +2114,8 @@ glade_eprop_object_view (GladeEditorProperty *eprop) * therefore can be selected. */ + g_object_set_data (G_OBJECT (model), "radio-list", GINT_TO_POINTER (radio)); + view_widget = gtk_tree_view_new_with_model (model); g_object_set (G_OBJECT (view_widget), "enable-search", FALSE, NULL); @@ -2074,7 +2134,7 @@ glade_eprop_object_view (GladeEditorProperty *eprop) g_object_set (G_OBJECT (renderer), "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, "activatable", TRUE, - "radio", TRUE, + "radio", radio, NULL); g_signal_connect (renderer, "toggled", G_CALLBACK (glade_eprop_object_selected), model); @@ -2115,13 +2175,19 @@ static gchar * glade_eprop_object_dialog_title (GladeEditorProperty *eprop) { GladeWidgetClass *klass; - const gchar *format = _("Choose a %s in this project"); - - if ((klass = - glade_widget_class_get_by_type - (eprop->class->pspec->value_type)) != NULL) + const gchar *format = + GLADE_IS_PARAM_SPEC_OBJECTS (eprop->class->pspec) ? + _("Choose %s implementors") : _("Choose a %s in this project"); + + if (GLADE_IS_PARAM_SPEC_OBJECTS (eprop->class->pspec)) + return g_strdup_printf (format, g_type_name + (glade_param_spec_objects_get_type + (GLADE_PARAM_SPEC_OBJECTS (eprop->class->pspec)))); + else if ((klass = + glade_widget_class_get_by_type + (eprop->class->pspec->value_type)) != NULL) return g_strdup_printf (format, klass->palette_name); - + /* Fallback on type name (which would look like "GtkButton" * instead of "Button" and maybe not translated). */ @@ -2148,7 +2214,7 @@ glade_eprop_object_show_dialog (GtkWidget *dialog_button, dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - _("Clear"), GLADE_RESPONSE_CLEAR, + GTK_STOCK_CLEAR, GLADE_RESPONSE_CLEAR, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); @@ -2177,7 +2243,7 @@ glade_eprop_object_show_dialog (GtkWidget *dialog_button, gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); - tree_view = glade_eprop_object_view (eprop); + tree_view = glade_eprop_object_view (eprop, TRUE); glade_eprop_object_populate_view (eprop, GTK_TREE_VIEW (tree_view)); @@ -2315,6 +2381,115 @@ glade_eprop_objects_load (GladeEditorProperty *eprop, GladeProperty *property) } +gboolean +glade_eprop_objects_selected_widget (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + GList **ret) +{ + gboolean selected; + GladeWidget *widget; + + gtk_tree_model_get (model, iter, + OBJ_COLUMN_SELECTED, &selected, + OBJ_COLUMN_WIDGET, &widget, -1); + + if (selected) + *ret = g_list_append (*ret, widget->object); + + return FALSE; +} + +static void +glade_eprop_objects_show_dialog (GtkWidget *dialog_button, + GladeEditorProperty *eprop) +{ + GtkWidget *dialog, *parent; + GtkWidget *vbox, *label, *sw; + GtkWidget *tree_view; + GladeProject *project; + gchar *title = glade_eprop_object_dialog_title (eprop); + gint res; + + + project = glade_widget_get_project (eprop->property->widget); + parent = gtk_widget_get_toplevel (GTK_WIDGET (eprop)); + + + dialog = gtk_dialog_new_with_buttons (title, + GTK_WINDOW (parent), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CLEAR, GLADE_RESPONSE_CLEAR, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, + NULL); + g_free (title); + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + + gtk_container_set_border_width (GTK_CONTAINER (vbox), GLADE_GENERIC_BORDER_WIDTH); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), vbox, TRUE, TRUE, 0); + + /* Checklist */ + label = gtk_label_new (_("Objects:")); + gtk_widget_show (label); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (sw); + gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0); + gtk_widget_set_size_request (sw, 400, 200); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); + + tree_view = glade_eprop_object_view (eprop, FALSE); + glade_eprop_object_populate_view (eprop, GTK_TREE_VIEW (tree_view)); + + gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view)); + + gtk_widget_show (tree_view); + gtk_container_add (GTK_CONTAINER (sw), tree_view); + + /* Run the dialog */ + res = gtk_dialog_run (GTK_DIALOG (dialog)); + if (res == GTK_RESPONSE_OK) + { + GValue *value; + GList *selected = NULL; + + gtk_tree_model_foreach + (gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)), + (GtkTreeModelForeachFunc) + glade_eprop_objects_selected_widget, &selected); + + + + value = glade_property_class_make_gvalue + (eprop->class, selected); + + glade_editor_property_commit (eprop, value); + + g_value_unset (value); + g_free (value); + } + else if (res == GLADE_RESPONSE_CLEAR) + { + GValue *value = glade_property_class_make_gvalue + (eprop->class, NULL); + + glade_editor_property_commit (eprop, value); + + g_value_unset (value); + g_free (value); + } + gtk_widget_destroy (dialog); +} + static GtkWidget * glade_eprop_objects_create_input (GladeEditorProperty *eprop) { @@ -2332,9 +2507,9 @@ glade_eprop_objects_create_input (GladeEditorProperty *eprop) gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); -/* g_signal_connect (G_OBJECTS (button), "clicked", */ -/* G_CALLBACK (glade_eprop_objects_show_dialog), */ -/* eprop); */ + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (glade_eprop_objects_show_dialog), + eprop); return hbox; } diff --git a/src/glade-editor.c b/src/glade-editor.c index f50d27f4..a7ee391b 100644 --- a/src/glade-editor.c +++ b/src/glade-editor.c @@ -43,6 +43,7 @@ #include "glade-project.h" #include "glade-utils.h" #include "glade-editor-property.h" +#include "atk.xpm" static GtkVBoxClass *parent_class = NULL; @@ -59,7 +60,8 @@ glade_editor_notebook_page (const gchar *name, GtkWidget *notebook) { GtkWidget *vbox; GtkWidget *scrolled_window; - GtkWidget *label; + GtkWidget *label_widget; + GdkPixbuf *pixbuf; GtkAdjustment *adj; static gint page = 0; @@ -77,13 +79,25 @@ glade_editor_notebook_page (const gchar *name, GtkWidget *notebook) /* Enable tabbed keynav in the editor */ adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)); gtk_container_set_focus_vadjustment (GTK_CONTAINER (scrolled_window), adj); - + gtk_adjustment_set_value (adj, 0); + adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window)); gtk_container_set_focus_hadjustment (GTK_CONTAINER (scrolled_window), adj); + gtk_adjustment_set_value (adj, 0); + + if (!strcmp (name, "glade-atk")) + { + pixbuf = gdk_pixbuf_new_from_xpm_data ((const char**) glade_atk_xpm); + label_widget = gtk_image_new_from_pixbuf (pixbuf); + g_object_unref (G_OBJECT (pixbuf)); + gtk_widget_show (label_widget); + } + else + label_widget = gtk_label_new_with_mnemonic (name); + + gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), scrolled_window, + label_widget, page++); - label = gtk_label_new_with_mnemonic (name); - gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), scrolled_window, label, page++); - return vbox; } @@ -104,22 +118,32 @@ glade_editor_on_launch_click (GtkButton *button, static void glade_editor_init (GladeEditor *editor) { - GtkWidget *hbox, *button; + GtkWidget *hbox, *button, *viewport; editor->notebook = gtk_notebook_new (); - editor->vbox_widget = glade_editor_notebook_page (_("_General"), GTK_WIDGET (editor->notebook)); - editor->vbox_packing = glade_editor_notebook_page (_("_Packing"), GTK_WIDGET (editor->notebook)); - editor->vbox_common = glade_editor_notebook_page (_("_Common"), GTK_WIDGET (editor->notebook)); - editor->vbox_signals = glade_editor_notebook_page (_("_Signals"), GTK_WIDGET (editor->notebook)); + editor->vbox_widget = glade_editor_notebook_page + (_("_General"), GTK_WIDGET (editor->notebook)); + editor->vbox_packing = glade_editor_notebook_page + (_("_Packing"), GTK_WIDGET (editor->notebook)); + editor->vbox_common = glade_editor_notebook_page + (_("_Common"), GTK_WIDGET (editor->notebook)); + editor->vbox_signals = glade_editor_notebook_page + (_("_Signals"), GTK_WIDGET (editor->notebook)); + editor->vbox_atk = glade_editor_notebook_page + ("glade-atk", GTK_WIDGET (editor->notebook)); editor->widget_tables = NULL; editor->packing_etable = NULL; editor->loading = FALSE; gtk_box_pack_start (GTK_BOX (editor), editor->notebook, TRUE, TRUE, 0); + viewport = gtk_viewport_new (NULL, NULL); + gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_OUT); hbox = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END); - gtk_box_pack_start (GTK_BOX (editor), hbox, FALSE, FALSE, 0); + + gtk_container_add (GTK_CONTAINER (viewport), hbox); + gtk_box_pack_start (GTK_BOX (editor), viewport, FALSE, FALSE, 0); /* Custom editor button */ @@ -302,10 +326,15 @@ glade_editor_table_append_items (GladeEditorTable *table, continue; else if (type == TABLE_TYPE_GENERAL && property_class->common) continue; + else if (type == TABLE_TYPE_ATK && + property_class->atk_type == GPC_ATK_NONE) + continue; + else if (type != TABLE_TYPE_ATK && + property_class->atk_type != GPC_ATK_NONE) + continue; property = glade_editor_table_append_item (table, property_class, type == TABLE_TYPE_QUERY); - table->properties = g_list_prepend (table->properties, property); } return TRUE; @@ -387,42 +416,33 @@ glade_editor_get_table_from_class (GladeEditor *editor, } static void -glade_editor_load_widget_page (GladeEditor *editor, GladeWidgetClass *class) +glade_editor_load_page (GladeEditor *editor, + GladeWidgetClass *class, + GladeEditorTableType type) { GladeEditorTable *table; - GtkContainer *container; + GtkContainer *container = NULL; GList *list, *children; /* Remove the old table that was in this container */ - container = GTK_CONTAINER (editor->vbox_widget); - children = gtk_container_get_children (container); - for (list = children; list; list = list->next) { - GtkWidget *widget = list->data; - g_return_if_fail (GTK_IS_WIDGET (widget)); - gtk_widget_ref (widget); - gtk_container_remove (container, widget); + switch (type) + { + case TABLE_TYPE_GENERAL: + container = GTK_CONTAINER (editor->vbox_widget); + break; + case TABLE_TYPE_COMMON: + container = GTK_CONTAINER (editor->vbox_common); + break; + case TABLE_TYPE_ATK: + container = GTK_CONTAINER (editor->vbox_atk); + break; + case TABLE_TYPE_PACKING: + case TABLE_TYPE_QUERY: + default: + g_critical ("Unreachable code reached !"); + break; } - g_list_free (children); - if (!class) - return; - - table = glade_editor_get_table_from_class (editor, class, FALSE); - - /* Attach the new table */ - gtk_box_pack_start (GTK_BOX (editor->vbox_widget), table->table_widget, - FALSE, TRUE, 0); -} - -static void -glade_editor_load_common_page (GladeEditor *editor, GladeWidgetClass *class) -{ - GladeEditorTable *table; - GtkContainer *container; - GList *list, *children; - - /* Remove the old table that was in this container */ - container = GTK_CONTAINER (editor->vbox_common); children = gtk_container_get_children (container); for (list = children; list; list = list->next) { GtkWidget *widget = list->data; @@ -434,11 +454,11 @@ glade_editor_load_common_page (GladeEditor *editor, GladeWidgetClass *class) if (!class) return; - - table = glade_editor_get_table_from_class (editor, class, TRUE); + + table = glade_editor_get_table_from_class (editor, class, type); /* Attach the new table */ - gtk_box_pack_start (GTK_BOX (editor->vbox_common), table->table_widget, + gtk_box_pack_start (GTK_BOX (container), table->table_widget, FALSE, TRUE, 0); } @@ -472,8 +492,10 @@ glade_editor_load_signal_page (GladeEditor *editor, GladeWidgetClass *class) static void glade_editor_load_widget_class (GladeEditor *editor, GladeWidgetClass *class) { - glade_editor_load_widget_page (editor, class); - glade_editor_load_common_page (editor, class); + glade_editor_load_page (editor, class, TABLE_TYPE_GENERAL); + glade_editor_load_page (editor, class, TABLE_TYPE_COMMON); + glade_editor_load_page (editor, class, TABLE_TYPE_ATK); + glade_editor_load_signal_page (editor, class); editor->loaded_class = class; @@ -544,13 +566,31 @@ glade_editor_close_cb (GladeProject *project, } static void +glade_editor_load_table (GladeEditor *editor, + GladeWidget *widget, + GladeEditorTableType type) +{ + GladeEditorProperty *property; + GladeEditorTable *table; + GList *list; + + table = glade_editor_get_table_from_class + (editor, widget->widget_class, type); + if (table->name_entry) + gtk_entry_set_text (GTK_ENTRY (table->name_entry), widget->name); + + for (list = table->properties; list; list = list->next) + { + property = list->data; + glade_editor_property_load_by_widget (property, widget); + } +} + +static void glade_editor_load_widget_real (GladeEditor *editor, GladeWidget *widget) { GladeWidgetClass *class; - GladeEditorTable *table; - GladeEditorProperty *property; - GladeProject *project; - GList *list; + GladeProject *project; /* Disconnect from last widget */ if (editor->loaded_widget != NULL) @@ -583,24 +623,10 @@ glade_editor_load_widget_real (GladeEditor *editor, GladeWidget *widget) editor->loading = TRUE; - /* Load each GladeEditorProperty */ - table = glade_editor_get_table_from_class (editor, class, TABLE_TYPE_GENERAL); - if (table->name_entry) - gtk_entry_set_text (GTK_ENTRY (table->name_entry), widget->name); - - for (list = table->properties; list; list = list->next) - { - property = list->data; - glade_editor_property_load_by_widget (property, widget); - } - - /* Load each GladeEditorProperty for the common tab */ - table = glade_editor_get_table_from_class (editor, class, TABLE_TYPE_COMMON); - for (list = table->properties; list; list = list->next) - { - property = list->data; - glade_editor_property_load_by_widget (property, widget); - } + /* Load each GladeEditorProperty from 'widget' */ + glade_editor_load_table (editor, widget, TABLE_TYPE_GENERAL); + glade_editor_load_table (editor, widget, TABLE_TYPE_COMMON); + glade_editor_load_table (editor, widget, TABLE_TYPE_ATK); editor->loaded_widget = widget; editor->loading = FALSE; @@ -812,7 +838,7 @@ glade_editor_populate_reset_view (GladeEditor *editor, GtkTreeView *tree_view) { GtkTreeStore *model = (GtkTreeStore *)gtk_tree_view_get_model (tree_view); - GtkTreeIter property_iter, general_iter, common_iter, *iter; + GtkTreeIter property_iter, general_iter, common_iter, atk_iter, *iter; GList *list; GladeProperty *property; gboolean def; @@ -839,6 +865,16 @@ glade_editor_populate_reset_view (GladeEditor *editor, COLUMN_NDEFAULT, FALSE, -1); + gtk_tree_store_append (model, &atk_iter, NULL); + gtk_tree_store_set (model, &atk_iter, + COLUMN_PROP_NAME, _("Accessibility"), + COLUMN_PROPERTY, NULL, + COLUMN_PARENT, TRUE, + COLUMN_CHILD, FALSE, + COLUMN_DEFAULT, FALSE, + COLUMN_NDEFAULT, FALSE, + -1); + /* General & Common */ for (list = editor->loaded_widget->properties; list; list = list->next) { @@ -847,7 +883,9 @@ glade_editor_populate_reset_view (GladeEditor *editor, if (glade_property_class_is_visible (property->class) == FALSE) continue; - if (property->class->common) + if (property->class->atk_type != GPC_ATK_NONE) + iter = &atk_iter; + else if (property->class->common) iter = &common_iter; else iter = &general_iter; diff --git a/src/glade-editor.h b/src/glade-editor.h index b7dfbc96..c9e7894d 100644 --- a/src/glade-editor.h +++ b/src/glade-editor.h @@ -27,6 +27,7 @@ enum _GladeEditorTableType TABLE_TYPE_GENERAL, TABLE_TYPE_COMMON, TABLE_TYPE_PACKING, + TABLE_TYPE_ATK, TABLE_TYPE_QUERY }; @@ -73,7 +74,7 @@ struct _GladeEditor GtkWidget *vbox_packing; GtkWidget *vbox_common; GtkWidget *vbox_signals; - + GtkWidget *vbox_atk; GladeSignalEditor *signal_editor; /* The signal editor packed into vbox_signals */ diff --git a/src/glade-fixed-manager.c b/src/glade-fixed-manager.c index c5a5ede0..b2c99d91 100644 --- a/src/glade-fixed-manager.c +++ b/src/glade-fixed-manager.c @@ -598,8 +598,8 @@ glade_fixed_manager_event (GtkWidget *widget, { case GDK_BUTTON_PRESS: // add widget - add_class = glade_default_app_get_add_class (); - alt_class = glade_default_app_get_alt_class (); + add_class = glade_app_get_add_class (); + alt_class = glade_app_get_alt_class (); if (((GdkEventButton *)event)->button == 1) { @@ -623,14 +623,14 @@ glade_fixed_manager_event (GtkWidget *widget, /* reset the palette */ glade_palette_unselect_widget - (glade_default_app_get_palette ()); + (glade_app_get_palette ()); handled = TRUE; } } break; case GDK_ENTER_NOTIFY: case GDK_MOTION_NOTIFY: - if (glade_default_app_get_add_class ()) + if (glade_app_get_add_class ()) glade_cursor_set (((GdkEventCrossing *)event)->window, GLADE_CURSOR_ADD_WIDGET); else glade_cursor_set (((GdkEventCrossing *)event)->window, GLADE_CURSOR_SELECTOR); diff --git a/src/glade-gtk.c b/src/glade-gtk.c index e6ec1eaf..9eb3bdc8 100644 --- a/src/glade-gtk.c +++ b/src/glade-gtk.c @@ -54,31 +54,71 @@ typedef enum { GLADEGTK_IMAGE_ICONTHEME } GladeGtkImageType; +typedef enum { + GLADEGTK_BUTTON_LABEL = 0, + GLADEGTK_BUTTON_STOCK, + GLADEGTK_BUTTON_CONTAINER +} GladeGtkButtonType; + + static GType glade_gtk_image_type_get_type (void) { static GType etype = 0; if (etype == 0) { - static const GEnumValue values[] = { - { GLADEGTK_IMAGE_FILENAME, "Filename", "glade-gtk-image-filename" }, - { GLADEGTK_IMAGE_STOCK, "Stock", "glade-gtk-image-stock" }, - { GLADEGTK_IMAGE_ICONTHEME, "Icon Theme", "glade-gtk-image-icontheme" }, + static GEnumValue values[] = { + { GLADEGTK_IMAGE_FILENAME, "a", "glade-gtk-image-filename" }, + { GLADEGTK_IMAGE_STOCK, "b", "glade-gtk-image-stock" }, + { GLADEGTK_IMAGE_ICONTHEME, "c", "glade-gtk-image-icontheme" }, { 0, NULL, NULL } }; + values[GLADEGTK_IMAGE_FILENAME].value_name = _("Filename"); + values[GLADEGTK_IMAGE_STOCK].value_name = _("Stock"); + values[GLADEGTK_IMAGE_ICONTHEME].value_name = _("Icon Theme"); + etype = g_enum_register_static ("GladeGtkImageType", values); } return etype; } +static GType +glade_gtk_button_type_get_type (void) +{ + static GType etype = 0; + if (etype == 0) { + static GEnumValue values[] = { + { GLADEGTK_BUTTON_LABEL, "a", "glade-gtk-button-label" }, + { GLADEGTK_BUTTON_STOCK, "b", "glade-gtk-button-stock" }, + { GLADEGTK_BUTTON_CONTAINER, "c", "glade-gtk-button-container" }, + { 0, NULL, NULL } + }; + values[GLADEGTK_BUTTON_LABEL].value_name = _("Label"); + values[GLADEGTK_BUTTON_STOCK].value_name = _("Stock"); + values[GLADEGTK_BUTTON_CONTAINER].value_name = _("Container"); + + etype = g_enum_register_static ("GladeGtkButtonType", values); + } + return etype; +} + GParamSpec * GLADEGTK_API glade_gtk_image_type_spec (void) { - return g_param_spec_enum ("type", _("Type"), - _("Chose the image type"), + return g_param_spec_enum ("type", _("Method"), + _("The method to use to edit this image"), glade_gtk_image_type_get_type (), 0, G_PARAM_READWRITE); } +GParamSpec * GLADEGTK_API +glade_gtk_button_type_spec (void) +{ + return g_param_spec_enum ("type", _("Method"), + _("The method to use to edit this button"), + glade_gtk_button_type_get_type (), + 0, G_PARAM_READWRITE); +} + /* ------------------------------------ Custom Properties ------------------------------ */ void GLADEGTK_API @@ -565,42 +605,164 @@ glade_gtk_notebook_verify_n_pages (GObject *object, GValue *value) return TRUE; } -/* GtkButton */ +static void +glade_gtk_button_backup_label (GladeWidget *gwidget) +{ + gchar *text; + gboolean use_underline; -static gboolean -glade_gtk_button_ensure_glabel (GtkWidget *button) + glade_widget_property_get (gwidget, "label", &text); + g_object_set_data_full (G_OBJECT (gwidget), "glade-label", + g_strdup (text), g_free); + + glade_widget_property_get (gwidget, "use-underline", &use_underline); + g_object_set_data (G_OBJECT (gwidget), "glade-use-underline", + GINT_TO_POINTER (use_underline)); +} + +static void +glade_gtk_button_disable_label (GladeWidget *gwidget) { - GladeWidgetClass *wclass; - GladeWidget *gbutton, *glabel; - GtkWidget *child; + glade_gtk_button_backup_label (gwidget); + glade_widget_property_set (gwidget, "label", NULL); + glade_widget_property_set (gwidget, "use-underline", NULL); - gbutton = glade_widget_get_from_gobject (button); + glade_widget_property_set_sensitive + (gwidget, "label", FALSE, + _("This only applies with label type buttons")); - /* If we didnt put this object here... (or its a placeholder) */ - if ((child = gtk_bin_get_child (GTK_BIN (button))) == NULL || - (glade_widget_get_from_gobject (child) == NULL)) - { - wclass = glade_widget_class_get_by_type (GTK_TYPE_LABEL); - glabel = glade_widget_new (gbutton, wclass, - glade_widget_get_project (gbutton), FALSE); + glade_widget_property_set_sensitive + (gwidget, "use-underline", FALSE, + _("This only applies with label type buttons")); +} + +static void +glade_gtk_button_restore_label (GladeWidget *gwidget) +{ + gchar *label = g_object_get_data (G_OBJECT (gwidget), "glade-label"); + gboolean use_underline = GPOINTER_TO_INT + (g_object_get_data (G_OBJECT (gwidget), "glade-use-underline")); - glade_widget_property_set - (glabel, "label", gbutton->widget_class->generic_name); + glade_widget_property_set_sensitive (gwidget, "label", TRUE, NULL); + glade_widget_property_set (gwidget, "label", label); - if (child) gtk_container_remove (GTK_CONTAINER (button), child); - gtk_container_add (GTK_CONTAINER (button), GTK_WIDGET (glabel->object)); + glade_widget_property_set_sensitive (gwidget, "use-underline", TRUE, NULL); + glade_widget_property_set (gwidget, "use-underline", use_underline); - glade_project_add_object (GLADE_PROJECT (gbutton->project), - NULL, glabel->object); - gtk_widget_show (GTK_WIDGET (glabel->object)); +} + + +static void +glade_gtk_button_backup_stock (GladeWidget *gwidget) +{ + gint stock_num; + if (glade_widget_property_default (gwidget, "stock") == FALSE) + { + glade_widget_property_get (gwidget, "stock", &stock_num); + g_object_set_data (G_OBJECT (gwidget), "glade-stock", + GINT_TO_POINTER (stock_num)); } +} - glade_widget_property_set_sensitive - (gbutton, "stock", FALSE, - _("There must be no children in the button")); - return FALSE; +static void +glade_gtk_button_disable_stock (GladeWidget *gwidget) +{ + glade_gtk_button_backup_stock (gwidget); + glade_widget_property_set (gwidget, "use-stock", FALSE); + glade_widget_property_set (gwidget, "stock", 0); + glade_widget_property_set_sensitive + (gwidget, "stock", FALSE, + _("This only applies with stock type buttons")); +} + +static void +glade_gtk_button_restore_stock (GladeWidget *gwidget) +{ + gint stock_num = GPOINTER_TO_INT + (g_object_get_data (G_OBJECT (gwidget), "glade-stock")); + glade_widget_property_set_sensitive (gwidget, "stock", TRUE, NULL); + glade_widget_property_set (gwidget, "stock", stock_num); + glade_widget_property_set (gwidget, "use-stock", TRUE); } +static void +glade_gtk_button_disable_contianer (GladeWidget *gwidget) +{ + if (glade_widget_get_from_gobject (GTK_BIN (gwidget->object)->child) == NULL) + gtk_container_remove (GTK_CONTAINER (gwidget->object), + GTK_BIN (gwidget->object)->child); + else + g_critical ("Trying to leave container button mode when " + "GTK_BIN (button)->child is a project widget"); +} + +static void +glade_gtk_button_restore_container (GladeWidget *gwidget) +{ + GtkWidget *child = GTK_BIN (gwidget->object)->child; + if (child && glade_widget_get_from_gobject (child) == NULL) + gtk_container_remove (GTK_CONTAINER (gwidget->object), child); + + if (GTK_BIN (gwidget->object)->child == NULL) + gtk_container_add (GTK_CONTAINER (gwidget->object), + glade_placeholder_new ()); +} + +void GLADEGTK_API +glade_gtk_button_set_type (GObject *object, GValue *value) +{ + static gboolean first = TRUE; + GladeWidget *gwidget; + GladeGtkButtonType type; + + gwidget = glade_widget_get_from_gobject (object); + g_return_if_fail (GTK_IS_BUTTON (object)); + g_return_if_fail (GLADE_IS_WIDGET (gwidget)); + + + type = GPOINTER_TO_INT (g_object_get_data (object, "glade-last-type")); + + /* Exit if we're still loading project objects + */ + if (GPOINTER_TO_INT (g_object_get_data + (object, "glade-button-post-ran")) == 0) + return; + + if (!first) + { + switch (type) + { + case GLADEGTK_BUTTON_LABEL: + glade_gtk_button_disable_label (gwidget); + break; + case GLADEGTK_BUTTON_STOCK: + glade_gtk_button_disable_stock (gwidget); + break; + case GLADEGTK_BUTTON_CONTAINER: + glade_gtk_button_disable_contianer (gwidget); + break; + } + } + + type = g_value_get_enum (value); + g_object_set_data (object, "glade-last-type", GINT_TO_POINTER (type)); + + + switch (type) + { + case GLADEGTK_BUTTON_LABEL: + glade_gtk_button_restore_label (gwidget); + if (first) glade_gtk_button_disable_stock (gwidget); + break; + case GLADEGTK_BUTTON_STOCK: + glade_gtk_button_restore_stock (gwidget); + if (first) glade_gtk_button_disable_label (gwidget); + break; + case GLADEGTK_BUTTON_CONTAINER: + glade_gtk_button_restore_container (gwidget); + break; + } +} void GLADEGTK_API glade_gtk_button_set_stock (GObject *object, GValue *value) @@ -614,6 +776,12 @@ glade_gtk_button_set_stock (GObject *object, GValue *value) g_return_if_fail (GTK_IS_BUTTON (object)); g_return_if_fail (GLADE_IS_WIDGET (gwidget)); + /* Exit if we're still loading project objects + */ + if (GPOINTER_TO_INT (g_object_get_data + (object, "glade-button-post-ran")) == 0) + return; + val = g_value_get_enum (value); if (val == GPOINTER_TO_INT (g_object_get_data (G_OBJECT (gwidget), "stock"))) return; @@ -624,14 +792,7 @@ glade_gtk_button_set_stock (GObject *object, GValue *value) { /* setting to "none", ensure an appropriate label */ if (val == 0) - { - glade_widget_property_set (gwidget, "use-stock", FALSE); glade_widget_property_set (gwidget, "label", NULL); - - glade_gtk_button_ensure_glabel (GTK_WIDGET (gwidget->object)); - glade_project_selection_set (GLADE_PROJECT (gwidget->project), - G_OBJECT (gwidget->object), TRUE); - } else { if (GTK_BIN (object)->child) @@ -649,7 +810,6 @@ glade_gtk_button_set_stock (GObject *object, GValue *value) /* Here we should remove any previously added GladeWidgets manualy * and from the project, not to leak them. */ - glade_widget_property_set (gwidget, "use-stock", TRUE); glade_widget_property_set (gwidget, "label", eval->value_nick); } } @@ -794,11 +954,7 @@ glade_gtk_image_set_type (GObject *object, GValue *value) g_return_if_fail (GTK_IS_IMAGE (object)); g_return_if_fail (GLADE_IS_WIDGET (gwidget)); - /* Since this gets called at object construction - * (during the sync_custom_props phase), we need to make - * sure this isn't called before the post_create_idle - * function, otherwise file loading breaks due to the - * cascade of dependant properties in GtkImage. + /* Exit if we're still loading project objects */ if (GPOINTER_TO_INT (g_object_get_data (object, "glade-image-post-ran")) == 0) @@ -1300,15 +1456,71 @@ glade_gtk_color_button_refresh_color (GtkColorButton *button, } } -void GLADEGTK_API -glade_gtk_button_post_create (GObject *button, GladeCreateReason reason) +static gboolean +glade_gtk_button_post_create_idle (GObject *button) { gboolean use_stock = FALSE; gchar *label = NULL; - GladeWidget *gbutton = - gbutton = glade_widget_get_from_gobject (button); GEnumValue *eval; GEnumClass *eclass; + GladeWidget *gbutton = glade_widget_get_from_gobject (button); + GladeCreateReason reason; + + eclass = g_type_class_ref (GLADE_TYPE_STOCK); + + g_object_set_data (button, "glade-button-post-ran", GINT_TO_POINTER (1)); + reason = GPOINTER_TO_INT (g_object_get_data (button, "glade-reason")); + + /* Just incase */ + glade_gtk_button_backup_stock (gbutton); + glade_gtk_button_backup_label (gbutton); + + if (reason == GLADE_CREATE_USER) + { + glade_widget_property_set (gbutton, "glade-type", GLADEGTK_BUTTON_LABEL); + glade_project_selection_set (GLADE_PROJECT (gbutton->project), + G_OBJECT (button), TRUE); + return FALSE; + } + + glade_widget_property_get (gbutton, "use-stock", &use_stock); + if (use_stock) + { + glade_widget_property_get (gbutton, "label", &label); + + if (label != NULL && strcmp (label, "glade-none") != 0 && + (eval = g_enum_get_value_by_nick (eclass, label)) != NULL) + { + g_object_set_data (G_OBJECT (gbutton), "stock", + GINT_TO_POINTER (eval->value)); + + glade_widget_property_set (gbutton, "stock", eval->value); + } + + /* Backup stock prop fisrt since setting the type + * will restore it. + */ + glade_gtk_button_backup_stock (gbutton); + glade_widget_property_set (gbutton, "glade-type", GLADEGTK_BUTTON_STOCK); + } + else if (GTK_BIN (button)->child != NULL && + glade_widget_get_from_gobject (GTK_BIN (button)->child) != NULL) + glade_widget_property_set (gbutton, "glade-type", GLADEGTK_BUTTON_CONTAINER); + else if (glade_widget_property_default (gbutton, "label") == FALSE) + glade_widget_property_set (gbutton, "glade-type", GLADEGTK_BUTTON_LABEL); + else + glade_widget_property_reset (gbutton, "glade-type"); + + g_type_class_unref (eclass); + + return FALSE; +} + +void GLADEGTK_API +glade_gtk_button_post_create (GObject *button, GladeCreateReason reason) +{ + GladeWidget *gbutton = glade_widget_get_from_gobject (button); + gchar *string; g_return_if_fail (GTK_IS_BUTTON (button)); g_return_if_fail (GLADE_IS_WIDGET (gbutton)); @@ -1325,49 +1537,17 @@ glade_gtk_button_post_create (GObject *button, GladeCreateReason reason) if (GTK_IS_COLOR_BUTTON (button) || GTK_IS_FONT_BUTTON (button)) - return; - - eclass = g_type_class_ref (GLADE_TYPE_STOCK); - - - /* Internal buttons get created with stock stuff, handle that here. */ - if (gbutton->internal) - g_object_get (gbutton->object, "use-stock", &use_stock, NULL); - else - glade_widget_property_get (gbutton, "use-stock", &use_stock); - - if (use_stock) { - gboolean free_label = FALSE; - if (gbutton->internal) - { - /* Free strings returned from g_object_get() */ - free_label = TRUE; - g_object_get (gbutton->object, "label", &label, NULL); - } - else - glade_widget_property_get (gbutton, "label", &label); - - eval = g_enum_get_value_by_nick (eclass, label); - g_object_set_data (G_OBJECT (gbutton), "stock", GINT_TO_POINTER (eval->value)); - - if (label != NULL && strcmp (label, "glade-none") != 0) - glade_widget_property_set (gbutton, "stock", eval->value); + string = g_strdup_printf (_("This property does not apply to a %s"), + gbutton->widget_class->palette_name); + glade_widget_property_set_sensitive (gbutton, "glade-type", + FALSE, string); + g_free (string); + return; + } - if (free_label && label) - g_free (label); - } - else if (reason == GLADE_CREATE_USER) - { - /* We need to use an idle function so as not to screw up - * the widget tree (i.e. the hierarchic order of widget creation - * needs to be parent first child last). - */ - g_idle_add ((GSourceFunc)glade_gtk_button_ensure_glabel, button); - glade_project_selection_set (GLADE_PROJECT (gbutton->project), - G_OBJECT (button), TRUE); - } - g_type_class_unref (eclass); + g_object_set_data (button, "glade-reason", GINT_TO_POINTER (reason)); + g_idle_add ((GSourceFunc)glade_gtk_button_post_create_idle, button); } @@ -1661,15 +1841,14 @@ glade_gtk_button_replace_child (GtkWidget *container, g_return_if_fail (GLADE_IS_WIDGET (gbutton)); glade_gtk_container_replace_child (container, current, new); - + if (GLADE_IS_PLACEHOLDER (new)) - glade_widget_property_set_sensitive (gbutton, - "stock", - TRUE, NULL); + glade_widget_property_set_sensitive (gbutton, "glade-type", TRUE, NULL); else - glade_widget_property_set_sensitive - (gbutton, "stock", FALSE, - _("There must be no children in the button")); + glade_widget_property_set_sensitive (gbutton, "glade-type", FALSE, + _("You must remove any children before " + "you can set the type")); + } /* ---------------------- Get Internal Child functions ---------------------- */ @@ -1876,16 +2055,36 @@ glade_gtk_notebook_add_child (GObject *object, GObject *child) GLADEGTK_API void glade_gtk_button_add_child (GObject *object, GObject *child) { - GtkWidget *old; + GladeWidget *gwidget; - old = GTK_BIN (object)->child; - if (old) - gtk_container_remove (GTK_CONTAINER (object), old); + if (GTK_BIN (object)->child) + gtk_container_remove (GTK_CONTAINER (object), + GTK_BIN (object)->child); gtk_container_add (GTK_CONTAINER (object), GTK_WIDGET (child)); + + if (GLADE_IS_PLACEHOLDER (child) == FALSE) + { + gwidget = glade_widget_get_from_gobject (object); + glade_widget_property_set_sensitive (gwidget, "glade-type", FALSE, + _("You must remove any children before " + "you can set the type")); + } } GLADEGTK_API void +glade_gtk_button_remove_child (GObject *object, GObject *child) +{ + GladeWidget *gwidget = glade_widget_get_from_gobject (object); + + gtk_container_remove (GTK_CONTAINER (object), GTK_WIDGET (child)); + gtk_container_add (GTK_CONTAINER (object), glade_placeholder_new()); + + glade_widget_property_set_sensitive (gwidget, "glade-type", TRUE, NULL); +} + + +GLADEGTK_API void glade_gtk_frame_add_child (GObject *object, GObject *child) { gchar *special_child_type; @@ -4022,10 +4221,10 @@ glade_gtk_menu_editor_new (GObject *menubar) gtk_box_set_spacing (GTK_BOX (buttonbox), 8); gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, TRUE, 0); - button = glade_default_app_undo_button_new (); + button = glade_app_undo_button_new (); gtk_container_add (GTK_CONTAINER (buttonbox), button); - button = glade_default_app_redo_button_new (); + button = glade_app_redo_button_new (); gtk_container_add (GTK_CONTAINER (buttonbox), button); button = gtk_button_new_from_stock (GTK_STOCK_CLOSE); @@ -4056,7 +4255,7 @@ glade_gtk_menu_bar_launch_editor (GObject *menubar) else { GladeWidget *gmenubar = glade_widget_get_from_gobject (menubar); - glade_util_ui_message (GTK_WIDGET (glade_default_app_get_transient_parent ()), + glade_util_ui_message (GTK_WIDGET (glade_app_get_transient_parent ()), GLADE_UI_INFO, _("A MenuBar editor is already runing for \"%s\"\n" "Cannot launch more than one editor per menubar."), diff --git a/src/glade-parser.c b/src/glade-parser.c index 3e086b7a..964e08c1 100644 --- a/src/glade-parser.c +++ b/src/glade-parser.c @@ -1175,7 +1175,7 @@ glade_parser_parse_file(const gchar *file, const gchar *domain) GladeParseState state = { 0 }; if (!g_file_test(file, G_FILE_TEST_IS_REGULAR)) { - glade_util_ui_message (glade_default_app_get_window (), + glade_util_ui_message (glade_app_get_window (), GLADE_UI_ERROR, _("Could not find glade file %s"), file); return NULL; @@ -1188,7 +1188,7 @@ glade_parser_parse_file(const gchar *file, const gchar *domain) state.domain = textdomain(NULL); if (xmlSAXUserParseFile(&glade_parser, &state, file) < 0) { - glade_util_ui_message (glade_default_app_get_window (), + glade_util_ui_message (glade_app_get_window (), GLADE_UI_ERROR, _("Errors parsing glade file %s"), file); if (state.interface) @@ -1196,7 +1196,7 @@ glade_parser_parse_file(const gchar *file, const gchar *domain) return NULL; } if (state.state != PARSER_FINISH) { - glade_util_ui_message (glade_default_app_get_window (), + glade_util_ui_message (glade_app_get_window (), GLADE_UI_ERROR, _("Errors parsing glade file %s"), file); if (state.interface) @@ -1285,7 +1285,9 @@ dump_widget(xmlNode *parent, GladeWidgetInfo *info, gint indent) xmlNodeAddContent(widget, BAD_CAST("\n")); } - if (info->n_atk_props != 0) { + if (info->n_atk_props != 0 || + info->n_atk_actions != 0 || + info->n_relations != 0) { xmlNode *atk; for (j = 0; j < indent + 1; j++) @@ -1300,7 +1302,7 @@ dump_widget(xmlNode *parent, GladeWidgetInfo *info, gint indent) for (j = 0; j < indent + 2; j++) xmlNodeAddContent(atk, BAD_CAST(" ")); - node = xmlNewNode(NULL, BAD_CAST("property")); + node = xmlNewNode(NULL, BAD_CAST("atkproperty")); xmlSetProp(node, BAD_CAST("name"), BAD_CAST(info->atk_props[i].name)); if (info->atk_props[i].translatable) xmlSetProp(node, BAD_CAST("translatable"), BAD_CAST("yes")); @@ -1313,6 +1315,35 @@ dump_widget(xmlNode *parent, GladeWidgetInfo *info, gint indent) xmlAddChild(atk, node); xmlNodeAddContent(atk, BAD_CAST("\n")); } + + for (i = 0; i < info->n_atk_actions; i++) { + xmlNode *node; + + for (j = 0; j < indent + 2; j++) + xmlNodeAddContent(atk, BAD_CAST(" ")); + node = xmlNewNode(NULL, BAD_CAST("atkaction")); + xmlSetProp(node, BAD_CAST("action_name"), + BAD_CAST(info->atk_actions[i].action_name)); + xmlSetProp(node, BAD_CAST("description"), + BAD_CAST(info->atk_actions[i].description)); + xmlAddChild(atk, node); + xmlNodeAddContent(atk, BAD_CAST("\n")); + } + + for (i = 0; i < info->n_relations; i++) { + xmlNode *node; + + for (j = 0; j < indent + 2; j++) + xmlNodeAddContent(atk, BAD_CAST(" ")); + node = xmlNewNode(NULL, BAD_CAST("atkrelation")); + xmlSetProp(node, BAD_CAST("target"), + BAD_CAST(info->relations[i].target)); + xmlSetProp(node, BAD_CAST("type"), + BAD_CAST(info->relations[i].type)); + xmlAddChild(atk, node); + xmlNodeAddContent(atk, BAD_CAST("\n")); + } + for (j = 0; j < indent + 1; j++) xmlNodeAddContent(atk, BAD_CAST(" ")); } diff --git a/src/glade-placeholder.c b/src/glade-placeholder.c index 6478e866..1b5780f3 100644 --- a/src/glade-placeholder.c +++ b/src/glade-placeholder.c @@ -279,7 +279,7 @@ glade_placeholder_motion_notify_event (GtkWidget *widget, GdkEventMotion *event) g_return_val_if_fail (GLADE_IS_PLACEHOLDER (widget), FALSE); - add_class = glade_default_app_get_add_class (); + add_class = glade_app_get_add_class (); if (add_class == NULL) glade_cursor_set (event->window, GLADE_CURSOR_SELECTOR); else @@ -298,9 +298,9 @@ glade_placeholder_button_press (GtkWidget *widget, GdkEventButton *event) g_return_val_if_fail (GLADE_IS_PLACEHOLDER (widget), FALSE); - add_class = glade_default_app_get_add_class (); - alt_class = glade_default_app_get_alt_class (); - palette = glade_default_app_get_palette (); + add_class = glade_app_get_add_class (); + alt_class = glade_app_get_alt_class (); + palette = glade_app_get_palette (); placeholder = GLADE_PLACEHOLDER (widget); project = glade_placeholder_get_project (placeholder); @@ -335,7 +335,7 @@ glade_placeholder_button_press (GtkWidget *widget, GdkEventButton *event) g_list_length (glade_util_get_selection ()) != 1) { glade_project_selection_clear - (glade_default_app_get_active_project (), + (glade_app_get_project (), TRUE); glade_util_clear_selection (); glade_util_add_selection (widget); diff --git a/src/glade-popup.c b/src/glade-popup.c index d4d2b0ed..09324c9c 100644 --- a/src/glade-popup.c +++ b/src/glade-popup.c @@ -43,14 +43,14 @@ static void glade_popup_select_cb (GtkMenuItem *item, GladeWidget *widget) { glade_util_clear_selection (); - glade_default_app_selection_set + glade_app_selection_set (glade_widget_get_object (widget), TRUE); } static void glade_popup_cut_cb (GtkMenuItem *item, GladeWidget *widget) { - GladeProject *project = glade_default_app_get_active_project (); + GladeProject *project = glade_app_get_project (); glade_util_clear_selection (); @@ -58,26 +58,26 @@ glade_popup_cut_cb (GtkMenuItem *item, GladeWidget *widget) if (glade_project_is_selected (project, glade_widget_get_object (widget)) == FALSE) { - glade_default_app_selection_set + glade_app_selection_set (glade_widget_get_object (widget), FALSE); } - glade_default_app_command_cut (); + glade_app_command_cut (); } static void glade_popup_copy_cb (GtkMenuItem *item, GladeWidget *widget) { - GladeProject *project = glade_default_app_get_active_project (); + GladeProject *project = glade_app_get_project (); glade_util_clear_selection (); /* Assign selection first */ if (glade_project_is_selected (project, glade_widget_get_object (widget)) == FALSE) - glade_default_app_selection_set + glade_app_selection_set (glade_widget_get_object (widget), FALSE); - glade_default_app_command_copy (); + glade_app_command_copy (); } static void @@ -87,24 +87,24 @@ glade_popup_paste_cb (GtkMenuItem *item, GladeWidget *widget) /* The selected widget is the paste destination */ - glade_default_app_selection_set + glade_app_selection_set (glade_widget_get_object (widget), FALSE); - glade_default_app_command_paste (); + glade_app_command_paste (); } static void glade_popup_delete_cb (GtkMenuItem *item, GladeWidget *widget) { - GladeProject *project = glade_default_app_get_active_project (); + GladeProject *project = glade_app_get_project (); /* Assign selection first */ if (glade_project_is_selected (project, glade_widget_get_object (widget)) == FALSE) - glade_default_app_selection_set + glade_app_selection_set (glade_widget_get_object (widget), FALSE); - glade_default_app_command_delete (); + glade_app_command_delete (); } @@ -117,7 +117,7 @@ glade_popup_add_item_cb (GtkMenuItem *item, if ((class = g_object_get_data (G_OBJECT (item), "widget_class")) != NULL) glade_command_create (class, widget, NULL, - glade_default_app_get_active_project ()); + glade_app_get_project ()); } @@ -129,11 +129,11 @@ glade_popup_placeholder_paste_cb (GtkMenuItem *item, GladePlaceholder *placeholder) { glade_util_clear_selection (); - glade_default_app_selection_clear (FALSE); + glade_app_selection_clear (FALSE); /* Set selection on the placeholder first */ glade_util_add_selection (GTK_WIDGET (placeholder)); - glade_default_app_command_paste (); + glade_app_command_paste (); } @@ -145,22 +145,22 @@ glade_popup_clipboard_paste_cb (GtkMenuItem *item, GladeWidget *widget) { glade_util_clear_selection (); - glade_default_app_selection_clear (FALSE); + glade_app_selection_clear (FALSE); - glade_default_app_command_paste (); + glade_app_command_paste (); } static void glade_popup_clipboard_delete_cb (GtkMenuItem *item, GladeWidget *widget) { - glade_default_app_command_delete_clipboard (); + glade_app_command_delete_clipboard (); } static void glade_popup_properties_cb (GtkMenuItem *item, GladeWidget *widget) { glade_popup_select_cb (item, widget); - glade_default_app_show_properties (TRUE); + glade_app_show_properties (TRUE); } /******************************************************** diff --git a/src/glade-project-view.c b/src/glade-project-view.c index cea03578..552e934a 100644 --- a/src/glade-project-view.c +++ b/src/glade-project-view.c @@ -163,7 +163,7 @@ gpw_foreach_add_selection (GtkTreeModel *model, { GladeWidget *widget; gtk_tree_model_get (model, iter, WIDGET_COLUMN, &widget, -1); - glade_default_app_selection_add + glade_app_selection_add (glade_widget_get_object (widget), FALSE); } @@ -515,10 +515,10 @@ glade_project_view_selection_changed_cb (GtkTreeSelection *selection, { view->updating_selection = TRUE; - glade_default_app_selection_clear (FALSE); + glade_app_selection_clear (FALSE); gtk_tree_selection_selected_foreach (selection, gpw_foreach_add_selection, view); - glade_default_app_selection_changed (); + glade_app_selection_changed (); view->updating_selection = FALSE; } diff --git a/src/glade-project-window.c b/src/glade-project-window.c index be8c4771..4a060325 100644 --- a/src/glade-project-window.c +++ b/src/glade-project-window.c @@ -81,7 +81,7 @@ gpw_refresh_title (GladeProjectWindow *gpw) GladeProject *active_project; gchar *title, *disp; - active_project = glade_app_get_active_project (GLADE_APP (gpw)); + active_project = glade_app_get_project (); if (active_project) { disp = glade_project_display_name (active_project, TRUE, FALSE, FALSE); @@ -119,7 +119,7 @@ gpw_recent_project_open_cb (GtkAction *action, GladeProjectWindow *gpw) if (path == NULL) return; - if (!glade_app_is_project_loaded (GLADE_APP (gpw), path)) + if (!glade_app_is_project_loaded (path)) gpw_recent_project_delete (action, gpw); glade_project_window_open_project (gpw, path); @@ -189,7 +189,7 @@ gpw_recent_project_config_load (GladeProjectWindow *gpw) gint i; gpw->priv->rp_max = g_key_file_get_integer ( - glade_app_get_config (GLADE_APP (gpw)), + glade_app_get_config (), CONFIG_RECENT_PROJECTS, CONFIG_RECENT_PROJECTS_MAX, NULL); @@ -200,7 +200,7 @@ gpw_recent_project_config_load (GladeProjectWindow *gpw) { g_snprintf(key, 8, "%d", i); - filename = g_key_file_get_string (glade_app_get_config (GLADE_APP (gpw)), + filename = g_key_file_get_string (glade_app_get_config (), CONFIG_RECENT_PROJECTS, key, NULL); if (filename) { @@ -214,7 +214,7 @@ gpw_recent_project_config_load (GladeProjectWindow *gpw) static void gpw_recent_project_config_save (GladeProjectWindow *gpw) { - GKeyFile *config = glade_app_get_config (GLADE_APP (gpw)); + GKeyFile *config = glade_app_get_config (); GList *list; gchar key[8]; gint i = 0; @@ -323,7 +323,7 @@ gpw_set_sensitivity_according_to_project (GladeProjectWindow *gpw, GladeProject action = gtk_action_group_get_action (gpw->priv->project_actions, "Paste"); gtk_action_set_sensitive (action, glade_clipboard_get_has_selection - (glade_app_get_clipboard (GLADE_APP (gpw)))); + (glade_app_get_clipboard ())); action = gtk_action_group_get_action (gpw->priv->project_actions, "Delete"); gtk_action_set_sensitive (action, @@ -338,7 +338,7 @@ gpw_projects_list_menu_activate_cb (GtkAction *action, GladeProjectWindow *gpw) project = GLADE_PROJECT (g_object_get_data (G_OBJECT (action), "project")); g_assert (GLADE_IS_PROJECT (project)); - glade_app_set_project (GLADE_APP (gpw), project); + glade_app_set_project (project); gpw_set_sensitivity_according_to_project (gpw, project); @@ -368,7 +368,7 @@ gpw_refresh_projects_list_menu (GladeProjectWindow *gpw) } g_list_free (actions); - projects = glade_app_get_projects (GLADE_APP (gpw)); + projects = glade_app_get_projects (); id = (projects != NULL) ? gtk_ui_manager_new_merge_id (p->ui) : 0; p->projects_list_menu_ui_id = id; @@ -398,7 +398,7 @@ gpw_refresh_projects_list_menu (GladeProjectWindow *gpw) gtk_action_group_add_action (p->projects_list_menu_actions, GTK_ACTION (action)); - if (project == glade_app_get_active_project (GLADE_APP (gpw))) + if (project == glade_app_get_project ()) gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); g_signal_connect (action, "activate", @@ -498,7 +498,7 @@ gpw_recent_project_clear_cb (GtkAction *action, GladeProjectWindow *gpw) /* Save it */ gpw_recent_project_config_save (gpw); - glade_app_config_save (GLADE_APP (gpw)); + glade_app_config_save (); } gtk_widget_destroy (dialog); } @@ -524,14 +524,14 @@ gpw_save (GladeProjectWindow *gpw, GladeProject *project, const gchar *path) return; } - glade_app_update_instance_count (GLADE_APP (gpw), project); + glade_app_update_instance_count (project); /* Get display_name here, it could have changed with "Save As..." */ display_name = glade_project_display_name (project, FALSE, FALSE, FALSE), gpw_recent_project_add (gpw, project->path); gpw_recent_project_config_save (gpw); - glade_app_config_save (GLADE_APP (gpw)); + glade_app_config_save (); /* refresh names */ gpw_refresh_title (gpw); @@ -553,8 +553,9 @@ gpw_save_as (GladeProjectWindow *gpw, const gchar *dialog_title) gchar *path = NULL; gchar *real_path, *ch; - if ((project = glade_app_get_active_project (GLADE_APP (gpw))) == NULL) + if ((project = glade_app_get_project ()) == NULL) { + /* Just incase the menu-item is not insensitive */ glade_util_ui_message (gpw->priv->window, GLADE_UI_WARN, _("No open projects to save")); return; @@ -596,7 +597,7 @@ gpw_save_as (GladeProjectWindow *gpw, const gchar *dialog_title) g_free (path); - if (glade_app_is_project_loaded (GLADE_APP (gpw), real_path)) + if (glade_app_is_project_loaded (real_path)) { glade_util_ui_message (gpw->priv->window, GLADE_UI_WARN, _("%s is already open"), real_path); @@ -613,8 +614,9 @@ gpw_save_cb (GtkAction *action, GladeProjectWindow *gpw) { GladeProject *project; - if ((project = glade_app_get_active_project (GLADE_APP (gpw))) == NULL) + if ((project = glade_app_get_project ()) == NULL) { + /* Just incase the menu-item or button is not insensitive */ glade_util_ui_message (gpw->priv->window, GLADE_UI_WARN, _("No open projects to save")); @@ -749,13 +751,13 @@ do_close (GladeProjectWindow *gpw, GladeProject *project) G_CALLBACK (gpw_project_notify_handler_cb), gpw); - glade_app_remove_project (GLADE_APP (gpw), project); + glade_app_remove_project (project); gpw_refresh_projects_list_menu (gpw); gpw_refresh_title (gpw); - active_project = glade_app_get_active_project (GLADE_APP (gpw)); + active_project = glade_app_get_project (); if (active_project != NULL) gpw_set_sensitivity_according_to_project (gpw, active_project); else @@ -768,7 +770,7 @@ gpw_close_cb (GtkAction *action, GladeProjectWindow *gpw) GladeProject *project; gboolean close; - project = glade_app_get_active_project (GLADE_APP (gpw)); + project = glade_app_get_project (); if (!project) return; @@ -787,7 +789,7 @@ gpw_quit_cb (GtkAction *action, GladeProjectWindow *gpw) { GList *list; - for (list = glade_app_get_projects (GLADE_APP (gpw)); list; list = list->next) + for (list = glade_app_get_projects (); list; list = list->next) { GladeProject *project = GLADE_PROJECT (list->data); @@ -799,8 +801,9 @@ gpw_quit_cb (GtkAction *action, GladeProjectWindow *gpw) } } - while (glade_app_get_projects (GLADE_APP (gpw))) { - GladeProject *project = GLADE_PROJECT (glade_app_get_projects (GLADE_APP (gpw))->data); + while (glade_app_get_projects ()) + { + GladeProject *project = GLADE_PROJECT (glade_app_get_projects ()->data); do_close (gpw, project); } @@ -810,52 +813,52 @@ gpw_quit_cb (GtkAction *action, GladeProjectWindow *gpw) static void gpw_copy_cb (GtkAction *action, GladeProjectWindow *gpw) { - glade_app_command_copy (GLADE_APP (gpw)); + glade_app_command_copy (); } static void gpw_cut_cb (GtkAction *action, GladeProjectWindow *gpw) { - glade_app_command_cut (GLADE_APP (gpw)); + glade_app_command_cut (); } static void gpw_paste_cb (GtkAction *action, GladeProjectWindow *gpw) { - glade_app_command_paste (GLADE_APP (gpw)); + glade_app_command_paste (); } static void gpw_delete_cb (GtkAction *action, GladeProjectWindow *gpw) { - if (!glade_app_get_active_project (GLADE_APP (gpw))) + if (!glade_app_get_project ()) { g_warning ("delete should not be sensitive: we don't have a project"); return; } - glade_app_command_delete (GLADE_APP (gpw)); + glade_app_command_delete (); } static void gpw_undo_cb (GtkAction *action, GladeProjectWindow *gpw) { - if (!glade_app_get_active_project (GLADE_APP (gpw))) + if (!glade_app_get_project ()) { g_warning ("undo should not be sensitive: we don't have a project"); return; } - glade_app_command_undo (GLADE_APP (gpw)); + glade_app_command_undo (); } static void gpw_redo_cb (GtkAction *action, GladeProjectWindow *gpw) { - if (!glade_app_get_active_project (GLADE_APP (gpw))) + if (!glade_app_get_project ()) { g_warning ("redo should not be sensitive: we don't have a project"); return; } - glade_app_command_redo (GLADE_APP (gpw)); + glade_app_command_redo (); } static gboolean @@ -888,7 +891,8 @@ gpw_create_palette (GladeProjectWindow *gpw) gtk_window_set_resizable (gpw->priv->palette_window, TRUE); gtk_window_move (gpw->priv->palette_window, 0, 250); - gtk_container_add (GTK_CONTAINER (gpw->priv->palette_window), GTK_WIDGET (glade_app_get_palette(GLADE_APP (gpw)))); + gtk_container_add (GTK_CONTAINER (gpw->priv->palette_window), + GTK_WIDGET (glade_app_get_palette())); /* Delete event, don't destroy it */ g_signal_connect (G_OBJECT (gpw->priv->palette_window), "delete_event", @@ -974,7 +978,7 @@ gpw_create_editor (GladeProjectWindow *gpw) gtk_window_move (gpw->priv->editor_window, 350, 0); gtk_container_add (GTK_CONTAINER (gpw->priv->editor_window), - GTK_WIDGET (glade_app_get_editor (GLADE_APP(gpw)))); + GTK_WIDGET (glade_app_get_editor ())); /* Delete event, don't destroy it */ g_signal_connect (G_OBJECT (gpw->priv->editor_window), "delete_event", @@ -1038,7 +1042,7 @@ gpw_create_widget_tree_contents (GladeProjectWindow *gpw) GladeProjectView *view; view = glade_project_view_new (GLADE_PROJECT_VIEW_TREE); - glade_app_add_project_view (GLADE_APP (gpw), view); + glade_app_add_project_view (view); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); @@ -1099,7 +1103,7 @@ gpw_create_clipboard_view (GladeProjectWindow *gpw) GtkWidget *view; GtkWidget *clipboard_item; - view = glade_app_get_clipboard_view (GLADE_APP (gpw)); + view = glade_app_get_clipboard_view (); g_signal_connect (G_OBJECT (view), "delete_event", G_CALLBACK (gpw_hide_clipboard_view_on_delete), @@ -1123,7 +1127,7 @@ gpw_show_clipboard_view (GladeProjectWindow *gpw) created = TRUE; } - gtk_widget_show_all (GTK_WIDGET (glade_app_get_clipboard_view (GLADE_APP(gpw)))); + gtk_widget_show_all (GTK_WIDGET (glade_app_get_clipboard_view ())); clipboard_item = gtk_ui_manager_get_widget (gpw->priv->ui, "/MenuBar/ViewMenu/Clipboard"); @@ -1137,7 +1141,7 @@ gpw_hide_clipboard_view (GladeProjectWindow *gpw) g_return_if_fail (gpw != NULL); - glade_util_hide_window (GTK_WINDOW (glade_app_get_clipboard_view (GLADE_APP(gpw)))); + glade_util_hide_window (GTK_WINDOW (glade_app_get_clipboard_view ())); clipboard_item = gtk_ui_manager_get_widget (gpw->priv->ui, "/MenuBar/ViewMenu/Clipboard"); @@ -1594,7 +1598,7 @@ glade_project_window_add_project (GladeProjectWindow *gpw, GladeProject *project { g_return_if_fail (GLADE_IS_PROJECT (project)); - glade_app_add_project (GLADE_APP (gpw), project); + glade_app_add_project (project); /* Connect callback handler for notify signals emitted by projects */ g_signal_connect (G_OBJECT (project), "notify::has-unsaved-changes", @@ -1646,7 +1650,7 @@ glade_project_window_open_project (GladeProjectWindow *gpw, const gchar *path) /* dont allow more than one project with the same name to be * opened simultainiously. */ - if (glade_app_is_project_loaded (GLADE_APP (gpw), (gchar*)path)) + if (glade_app_is_project_loaded ((gchar*)path)) { glade_util_ui_message (gpw->priv->window, GLADE_UI_WARN, _("%s is already open"), path); @@ -1658,7 +1662,7 @@ glade_project_window_open_project (GladeProjectWindow *gpw, const gchar *path) gpw_recent_project_add (gpw, project->path); gpw_recent_project_config_save (gpw); - glade_app_config_save (GLADE_APP (gpw)); + glade_app_config_save (); glade_project_window_add_project (gpw, project); } @@ -1698,7 +1702,7 @@ gpw_refresh_undo_redo (GladeProjectWindow *gpw) GtkAction *action; gchar *tooltip; - project = glade_app_get_active_project (GLADE_APP (gpw)); + project = glade_app_get_project (); if (project != NULL) { @@ -1826,17 +1830,17 @@ glade_project_window_new (void) gpw_create_palette (gpw); gpw_create_editor (gpw); - glade_app_set_window (GLADE_APP (gpw), gpw->priv->window); + glade_app_set_window (gpw->priv->window); accel_group = gtk_ui_manager_get_accel_group(gpw->priv->ui); - glade_app_set_accel_group (GLADE_APP (gpw), accel_group); + glade_app_set_accel_group (accel_group); gtk_window_add_accel_group(gpw->priv->palette_window, accel_group); gtk_window_add_accel_group(gpw->priv->editor_window, accel_group); - gtk_window_add_accel_group(GTK_WINDOW (glade_app_get_clipboard_view (GLADE_APP (gpw))), accel_group); + gtk_window_add_accel_group(GTK_WINDOW (glade_app_get_clipboard_view ()), accel_group); /* Connect callback handler for notify signals emitted by clipboard */ - g_signal_connect (G_OBJECT (glade_app_get_clipboard (GLADE_APP (gpw))), "notify::has-selection", + g_signal_connect (G_OBJECT (glade_app_get_clipboard ()), "notify::has-selection", G_CALLBACK (gpw_clipboard_notify_handler_cb), gpw); diff --git a/src/glade-project.c b/src/glade-project.c index 234dd6e1..1efe5c82 100644 --- a/src/glade-project.c +++ b/src/glade-project.c @@ -643,7 +643,7 @@ glade_project_add_object (GladeProject *project, gwidget); if (GTK_IS_WINDOW (object) && - (transient_parent = glade_default_app_get_transient_parent ()) != NULL) + (transient_parent = glade_app_get_transient_parent ()) != NULL) gtk_window_set_transient_for (GTK_WINDOW (object), transient_parent); /* Notify widget it was added to the project */ @@ -1180,7 +1180,7 @@ loadable_interface (GladeInterface *interface, const gchar *path) } if (loadable == FALSE) - glade_util_ui_message (glade_default_app_get_window(), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_ERROR, _("Failed to load %s.\n" "The following required catalogs are unavailable: %s"), @@ -1245,7 +1245,8 @@ static void glade_project_fix_object_props (GladeProject *project) { GList *l, *ll; - GladeWidget *gwidget, *value_widget; + GValue *value; + GladeWidget *gwidget; GladeProperty *property; gchar *txt; @@ -1261,11 +1262,19 @@ glade_project_fix_object_props (GladeProject *project) (txt = g_object_get_data (G_OBJECT (property), "glade-loaded-object")) != NULL) { - if ((value_widget = - glade_project_get_widget_by_name (project, txt)) != NULL) - glade_property_set (property, value_widget->object); - - g_object_set_data (G_OBJECT (property), "glade-loaded-object", NULL); + /* Parse the object list and set the property to it + * (this magicly works for both objects & object lists) + */ + value = glade_property_class_make_gvalue_from_string + (property->class, txt, project); + + glade_property_set_value (property, value); + + g_value_unset (value); + g_free (value); + + g_object_set_data (G_OBJECT (property), + "glade-loaded-object", NULL); } } } diff --git a/src/glade-property-class.c b/src/glade-property-class.c index a90e313c..e95f5b18 100644 --- a/src/glade-property-class.c +++ b/src/glade-property-class.c @@ -38,6 +38,92 @@ #include "glade-editor-property.h" #include "glade-debug.h" + +/* Hardcoded recognized atk actions + */ +typedef struct { + gchar *prop_name; + gchar *id; + gchar *name; + gchar *tooltip; +} GPCAtkPropertyTab; + +static const GPCAtkPropertyTab action_names_table[] = { + { "click", "atk-click", N_("Click"), + N_("Set the desctription of the Click atk action") }, + { "press", "atk-press", N_("Press"), + N_("Set the desctription of the Press atk action") }, + { "release", "atk-release", N_("Release"), + N_("Set the desctription of the Release atk action") }, + { "activate", "atk-activate", N_("Activate"), + N_("Set the desctription of the Activate atk action") } +}; + +static const GPCAtkPropertyTab relation_names_table[] = { + { "controlled-by", "atk-controlled-by", N_("Controlled By"), + N_("Indicates an object controlled by one or more target objects") }, + + { "controlled-for", "atk-controlled-for", N_("Controlled For"), + N_("Indicates an object is an controller for one or more target objects") }, + + { "labelled-by", "atk-labelled-by", N_("Labelled By"), + N_("Indicates an object is labelled by one or more target objects") }, + + { "label-for", "atk-label-for", N_("Label For"), + N_("Indicates an object is a label for one or more target objects") }, + + { "member-of", "atk-member-of", N_("Member Of"), + N_("Indicates an object is a member of a group of one or more target objects") }, + + { "child-node-of", "atk-child-node-of", N_("Child Node Of"), + N_("Indicates an object is a cell in a treetable which is displayed " + "because a cell in the same column is expanded and identifies that cell") }, + + { "flows-to", "atk-flows-to", N_("Flows To"), + N_("Indicates that the object has content that flows logically to another " + "AtkObject in a sequential way, (for instance text-flow)") }, + + { "flows-from", "atk-flows-from", N_("Flows From"), + N_("Indicates that the object has content that flows logically from another " + "AtkObject in a sequential way, (for instance text-flow)") }, + + { "subwindow-of", "atk-subwindow-of", N_("Subwindow Of"), + N_("Indicates a subwindow attached to a component but otherwise has no " + "connection in the UI heirarchy to that component") }, + + { "embeds", "atk-embeds", N_("Embeds"), + N_("Indicates that the object visually embeds another object's content, " + "i.e. this object's content flows around another's content") }, + + { "embedded-by", "atk-embedded-by", N_("Embedded By"), + N_("Inverse of 'Embeds', indicates that this object's content " + "is visualy embedded in another object") }, + + { "popup-for", "atk-popup-for", N_("Popup For"), + N_("Indicates that an object is a popup for another object") }, + + { "parent-window-of", "atk-parent-window-of", N_("Parent Window Of"), + N_("Indicates that an object is a parent window of another object") } +}; + +G_CONST_RETURN gchar * +glade_property_class_atk_realname (const gchar *atk_name) +{ + gint i; + + g_return_val_if_fail (atk_name != NULL, NULL); + + for (i = 0; i < G_N_ELEMENTS (action_names_table); i++) + if (!strcmp (action_names_table[i].id, atk_name)) + return action_names_table[i].prop_name; + + for (i = 0; i < G_N_ELEMENTS (relation_names_table); i++) + if (!strcmp (relation_names_table[i].id, atk_name)) + return relation_names_table[i].prop_name; + + return atk_name; +} + /** * glade_property_class_new: * @@ -71,8 +157,7 @@ glade_property_class_new (void) property_class->ignore = FALSE; property_class->resource = FALSE; property_class->translatable = FALSE; - property_class->atk_property = FALSE; - property_class->atk_relation = FALSE; + property_class->atk_type = GPC_ATK_NONE; return property_class; } @@ -316,8 +401,6 @@ glade_property_class_make_string_from_objects (GladePropertyClass *property_clas GList *list; gchar *string = NULL, *obj_str, *tmp; -#define GPC_OBJECT_DELIMITER ", " - for (list = objects; list; list = list->next) { object = list->data; @@ -781,13 +864,39 @@ glade_property_class_make_gvalue_from_vl (GladePropertyClass *class, g_value_set_object (value, va_arg (vl, gpointer)); else if (G_IS_PARAM_SPEC_BOXED(class->pspec)) g_value_set_boxed (value, va_arg (vl, gpointer)); + else if (GLADE_IS_PARAM_SPEC_OBJECTS(class->pspec)) + g_value_set_boxed (value, va_arg (vl, gpointer)); else g_critical ("Unsupported pspec type %s", - g_type_name(class->pspec->value_type)); + g_type_name(G_PARAM_SPEC_TYPE (class->pspec))); return value; } +/** + * glade_property_class_make_gvalue: + * @class: A #GladePropertyClass + * @...: an argument of the correct type specified by @property_class + * + * Returns: A #GValue created based on the @property_class + * and the provided argument. + */ +GValue * +glade_property_class_make_gvalue (GladePropertyClass *class, + ...) +{ + GValue *value; + va_list vl; + + g_return_val_if_fail (class != NULL, NULL); + + va_start (vl, class); + value = glade_property_class_make_gvalue_from_vl (class, vl); + va_end (vl); + + return value; +} + /** * glade_property_class_set_vl_from_gvalue: @@ -797,7 +906,7 @@ glade_property_class_make_gvalue_from_vl (GladePropertyClass *class, * specified by @class * * - * Sets @value from @vl based on @class criteria. + * Sets @vl from @value based on @class criteria. */ void glade_property_class_set_vl_from_gvalue (GladePropertyClass *class, @@ -844,9 +953,140 @@ glade_property_class_set_vl_from_gvalue (GladePropertyClass *class, *(gpointer *)(va_arg (vl, gpointer *)) = g_value_get_object (value); else if (G_IS_PARAM_SPEC_BOXED(class->pspec)) *(gpointer *)(va_arg (vl, gpointer *)) = g_value_get_boxed (value); + else if (GLADE_IS_PARAM_SPEC_OBJECTS(class->pspec)) + *(gpointer *)(va_arg (vl, gpointer *)) = g_value_get_boxed (value); else g_critical ("Unsupported pspec type %s", - g_type_name(class->pspec->value_type)); + g_type_name(G_PARAM_SPEC_TYPE (class->pspec))); +} + +/** + * glade_property_class_get_from_gvalue: + * @class: A #GladePropertyClass + * @value: A #GValue to set + * @...: a return location of the correct type + * + * + * Assignes the provided return location to @value + */ +void +glade_property_class_get_from_gvalue (GladePropertyClass *class, + GValue *value, + ...) +{ + va_list vl; + + g_return_if_fail (class != NULL); + + va_start (vl, value); + glade_property_class_set_vl_from_gvalue (class, value, vl); + va_end (vl); +} + + +/** + * glade_property_class_new_atk_action: + * @name: The atk action name + * @def: The default desctription + * @owner_type: The #GType of the owning widget class. + * + * Returns: a newly created atk action #GladePropertyClass + * for the said criteria. + */ +GladePropertyClass * +glade_property_class_new_atk_action (const gchar *name, + const gchar *def, + GType owner_type) +{ + const GPCAtkPropertyTab *action_tab = NULL; + GladePropertyClass *property_class; + gint i; + + g_return_val_if_fail (name != NULL, NULL); + + /* Find our hard-coded table entry */ + for (i = 0; i < G_N_ELEMENTS (action_names_table); i++) + { + if (!strcmp (name, action_names_table[i].prop_name)) + action_tab = &action_names_table[i]; + } + if (action_tab == NULL) + { + g_warning ("Unrecognized atk action '%s' on class %s", + name, g_type_name (owner_type)); + return NULL; + } + + property_class = glade_property_class_new (); + property_class->pspec = glade_standard_string_spec(); + property_class->pspec->owner_type = owner_type; + + property_class->id = g_strdup (action_tab->id); + property_class->name = g_strdup (_(action_tab->name)); + property_class->tooltip = g_strdup (_(action_tab->tooltip)); + property_class->atk_type = GPC_ATK_ACTION; + property_class->ignore = TRUE; + property_class->visible_lines = 2; + + property_class->def = + glade_property_class_make_gvalue_from_string + (property_class, def, NULL); + + property_class->orig_def = + glade_property_class_make_gvalue_from_string + (property_class, def, NULL); + + return property_class; +} + + +/** + * glade_property_class_new_atk_relation: + * @owner_type: The #GType of the owning widget class. + * + * Returns: a #GList of newly created atk relation #GladePropertyClass. + */ +GList * +glade_property_class_list_atk_relations (GType owner_type) +{ + const GPCAtkPropertyTab *relation_tab = NULL; + GladePropertyClass *property_class; + GList *list = NULL; + gint i; + + /* Loop through our hard-coded table enties */ + for (i = 0; i < G_N_ELEMENTS (relation_names_table); i++) + { + relation_tab = &relation_names_table[i]; + + property_class = glade_property_class_new (); + property_class->pspec = + glade_param_spec_objects (relation_tab->id, + _(relation_tab->name), + _(relation_tab->tooltip), + ATK_TYPE_IMPLEMENTOR, + G_PARAM_READWRITE); + + property_class->pspec->owner_type = owner_type; + property_class->id = g_strdup (relation_tab->id); + property_class->name = g_strdup (_(relation_tab->name)); + property_class->tooltip = g_strdup (_(relation_tab->tooltip)); + property_class->atk_type = GPC_ATK_RELATION; + property_class->visible_lines = 2; + property_class->ignore = TRUE; + + property_class->def = + glade_property_class_make_gvalue_from_string + (property_class, "", NULL); + + property_class->orig_def = + glade_property_class_make_gvalue_from_string + (property_class, "", NULL); + + list = g_list_prepend (list, property_class); + } + + return g_list_reverse (list); } @@ -872,12 +1112,12 @@ glade_property_class_new_from_spec (GParamSpec *spec) /* We only use the writable properties */ if ((spec->flags & G_PARAM_WRITABLE) == 0) - goto lblError; + goto failed; /* Register only editable properties. */ if (!glade_editor_property_supported (property_class->pspec)) - goto lblError; + goto failed; property_class->id = g_strdup (spec->name); property_class->name = g_strdup (g_param_spec_get_nick (spec)); @@ -893,13 +1133,23 @@ glade_property_class_new_from_spec (GParamSpec *spec) /* Flag the construct only properties */ if (spec->flags & G_PARAM_CONSTRUCT_ONLY) property_class->construct_only = TRUE; - + + if (g_type_is_a (spec->owner_type, ATK_TYPE_OBJECT)) + { + property_class->atk_type = GPC_ATK_PROPERTY; + property_class->ignore = TRUE; + + /* We only use the name and desctription props, + * they are both translatable. + */ + property_class->translatable = TRUE; + } if (!property_class->id || !property_class->name) { g_critical ("No name or id for " "glade_property_class_new_from_spec, failed."); - goto lblError; + goto failed; } property_class->tooltip = g_strdup (g_param_spec_get_blurb (spec)); @@ -909,7 +1159,7 @@ glade_property_class_new_from_spec (GParamSpec *spec) g_type_class_unref (gtk_widget_class); return property_class; - lblError: + failed: glade_property_class_free (property_class); g_type_class_unref (gtk_widget_class); return NULL; @@ -929,7 +1179,6 @@ glade_property_class_is_visible (GladePropertyClass *class) return class->visible; } - /** * glade_property_class_is_object: * @property_class: A #GladePropertyClass @@ -942,9 +1191,11 @@ gboolean glade_property_class_is_object (GladePropertyClass *class) { g_return_val_if_fail (GLADE_IS_PROPERTY_CLASS (class), FALSE); - return (G_IS_PARAM_SPEC_OBJECT(class->pspec) && - class->pspec->value_type != GDK_TYPE_PIXBUF && - class->pspec->value_type != GTK_TYPE_ADJUSTMENT); + + return (GLADE_IS_PARAM_SPEC_OBJECTS (class->pspec) || + (G_IS_PARAM_SPEC_OBJECT(class->pspec) && + class->pspec->value_type != GDK_TYPE_PIXBUF && + class->pspec->value_type != GTK_TYPE_ADJUSTMENT)); } @@ -1283,12 +1534,6 @@ glade_property_class_update_from_node (GladeXmlNode *node, class->ignore = glade_xml_get_property_boolean (node, GLADE_TAG_IGNORE, class->ignore); class->resource = glade_xml_get_property_boolean (node, GLADE_TAG_RESOURCE, class->resource); - /* Atk relations are 'atk properties' */ - if ((class->atk_relation = - glade_xml_get_property_boolean (node, GLADE_TAG_ATK_RELATION, - class->atk_relation)) == TRUE) - class->atk_property = TRUE; - /* Special case pixbuf here. */ if (class->pspec->value_type == GDK_TYPE_PIXBUF) diff --git a/src/glade-property-class.h b/src/glade-property-class.h index f276fb12..d7c45d77 100644 --- a/src/glade-property-class.h +++ b/src/glade-property-class.h @@ -11,9 +11,25 @@ G_BEGIN_DECLS #define GLADE_PROPERTY_CLASS(gpc) ((GladePropertyClass *) gpc) #define GLADE_IS_PROPERTY_CLASS(gpc) (gpc != NULL) +#define GPC_OBJECT_DELIMITER ", " + typedef struct _GladePropertyClass GladePropertyClass; /** + * GPCAtkType: + * @GPC_ATK_NONE: is not an atk property + * @GPC_ATK_PROPERTY: is a property of an #AtkImplementor object + * @GPC_ATK_RELATION: is an atk relation set property + * @GPC_ATK_ACTION: is an atk action property + */ +typedef enum { + GPC_ATK_NONE, + GPC_ATK_PROPERTY, + GPC_ATK_RELATION, + GPC_ATK_ACTION +} GPCAtkType; + +/** * GladeVerifyPropertyFunc: * @object: A #GObject * @value: The #GValue @@ -107,10 +123,11 @@ struct _GladePropertyClass gboolean common; /* Common properties go in the common tab */ gboolean packing; /* Packing properties go in the packing tab */ - gboolean atk_property; /* atk props go in the a11y tab */ - gboolean atk_relation; /* whether this is an atk relation property - * (they are saved/loaded differently) - */ + + GPCAtkType atk_type; /* Whether this is an atk property and if so; + * whether its a relation, action or atkobject + * property + */ gboolean translatable; /* The property should be translatable, which * means that it needs extra parameters in the @@ -175,6 +192,12 @@ GladePropertyClass *glade_property_class_new (void); LIBGLADEUI_API GladePropertyClass *glade_property_class_new_from_spec (GParamSpec *spec); LIBGLADEUI_API +GladePropertyClass *glade_property_class_new_atk_action (const gchar *name, + const gchar *def, + GType owner_type); +LIBGLADEUI_API +GList *glade_property_class_list_atk_relations (GType owner_type); +LIBGLADEUI_API GladePropertyClass *glade_property_class_clone (GladePropertyClass *property_class); LIBGLADEUI_API void glade_property_class_free (GladePropertyClass *property_class); @@ -197,6 +220,13 @@ void glade_property_class_set_vl_from_gvalue (GladePropertyC GValue *value, va_list vl); LIBGLADEUI_API +GValue *glade_property_class_make_gvalue (GladePropertyClass *class, + ...); +LIBGLADEUI_API +void glade_property_class_get_from_gvalue (GladePropertyClass *class, + GValue *value, + ...); +LIBGLADEUI_API gboolean glade_property_class_update_from_node (GladeXmlNode *node, GModule *module, GType object_type, @@ -207,14 +237,14 @@ gchar *glade_property_class_get_displayable_value (GladePropertyC gint value); LIBGLADEUI_API GtkAdjustment *glade_property_class_make_adjustment (GladePropertyClass *property_class); - LIBGLADEUI_API gboolean glade_property_class_match (GladePropertyClass *class, GladePropertyClass *comp); - LIBGLADEUI_API gboolean glade_property_class_void_value (GladePropertyClass *class, GValue *value); +LIBGLADEUI_API +G_CONST_RETURN gchar *glade_property_class_atk_realname (const gchar *atk_name); G_END_DECLS diff --git a/src/glade-property.c b/src/glade-property.c index 9c111385..c2680270 100644 --- a/src/glade-property.c +++ b/src/glade-property.c @@ -140,6 +140,62 @@ glade_property_set_property (GladeProperty *property, const GValue *value) extern gboolean glade_widget_dupping; static void +glade_property_update_prop_refs (GladeProperty *property, + const GValue *old_value, + const GValue *new_value) +{ + GladeWidget *gold, *gnew; + GObject *old_object, *new_object; + GList *old_list, *new_list, *list, *removed, *added; + + if (GLADE_IS_PARAM_SPEC_OBJECTS (property->class->pspec)) + { + /* Make our own copies incase we're walking an + * unstable list + */ + old_list = g_value_dup_boxed (old_value); + new_list = g_value_dup_boxed (new_value); + + /* Diff up the GList */ + removed = glade_util_removed_from_list (old_list, new_list); + added = glade_util_added_in_list (old_list, new_list); + + /* Adjust the appropriate prop refs */ + for (list = removed; list; list = list->next) + { + old_object = list->data; + gold = glade_widget_get_from_gobject (old_object); + glade_widget_remove_prop_ref (gold, property); + } + for (list = added; list; list = list->next) + { + new_object = list->data; + gnew = glade_widget_get_from_gobject (new_object); + glade_widget_add_prop_ref (gnew, property); + } + + g_list_free (removed); + g_list_free (added); + g_list_free (old_list); + g_list_free (new_list); + } + else + { + if ((old_object = g_value_get_object (old_value)) != NULL) + { + gold = glade_widget_get_from_gobject (old_object); + glade_widget_remove_prop_ref (gold, property); + } + + if ((new_object = g_value_get_object (new_value)) != NULL) + { + gnew = glade_widget_get_from_gobject (new_object); + glade_widget_add_prop_ref (gnew, property); + } + } +} + +static void glade_property_set_value_impl (GladeProperty *property, const GValue *value) { GladeProject *project = glade_widget_get_project (property->widget); @@ -152,7 +208,9 @@ glade_property_set_value_impl (GladeProperty *property, const GValue *value) return; } - if (property->class->verify_function && glade_widget_is_dupping() == FALSE && + if (property->widget && + property->class->verify_function && + glade_widget_is_dupping() == FALSE && project && glade_project_is_loading (project) == FALSE) { GObject *object = glade_widget_get_object (property->widget); @@ -167,24 +225,11 @@ glade_property_set_value_impl (GladeProperty *property, const GValue *value) /* Add/Remove references from widget ref stacks here + * (before assigning the value) */ - if (changed && glade_property_class_is_object (property->class)) - { - GladeWidget *gold, *gnew; - GObject *old_object, *new_object; + if (property->widget && changed && glade_property_class_is_object (property->class)) + glade_property_update_prop_refs (property, property->value, value); - if ((old_object = g_value_get_object (property->value)) != NULL) - { - gold = glade_widget_get_from_gobject (old_object); - glade_widget_remove_prop_ref (gold, property); - } - - if ((new_object = g_value_get_object (value)) != NULL) - { - gnew = glade_widget_get_from_gobject (new_object); - glade_widget_add_prop_ref (gnew, property); - } - } /* Assign property first so that; if the object need be * rebuilt, it will reflect the new value @@ -194,7 +239,7 @@ glade_property_set_value_impl (GladeProperty *property, const GValue *value) GLADE_PROPERTY_GET_KLASS (property)->sync (property); - if (changed) + if (changed && property->widget) { if (project) glade_project_changed (project); @@ -227,10 +272,14 @@ glade_property_sync_impl (GladeProperty *property) /* Heh, here are the many reasons not to * sync a property ;-) */ - if (property->enabled == FALSE || /* optional properties that are disabled */ - property->class->ignore || /* catalog says "never sync" */ - property->class->atk_property || /* dont bother with atk related properties */ - property->syncing) /* avoid recursion */ + if (/* optional properties that are disabled */ + property->enabled == FALSE || + /* explicit "never sync" flag */ + property->class->ignore || + /* avoid recursion */ + property->syncing || + /* No widget owns this property yet */ + property->widget == NULL) return; property->syncing = TRUE; @@ -294,74 +343,94 @@ glade_property_write_impl (GladeProperty *property, GladeInterface *interface, GArray *props) { - GladePropInfo info = { 0 }; - gchar *tmp; - gchar *default_str = NULL; - gboolean skip; + GladePropInfo info = { 0, }; + GladeAtkActionInfo ainfo = { 0, }; + gchar *name, *value, **split, *tmp; + gint i; if (!property->class->save || !property->enabled) return FALSE; - /* we should change each '-' by '_' on the name of the property - * (<property name="...">) */ - tmp = g_strdup (property->class->id); - if (!tmp) - return FALSE; - glade_util_replace (tmp, '-', '_'); + g_assert (property->class->orig_def); + g_assert (property->class->def); - /* put the name="..." part on the <property ...> tag */ - info.name = alloc_propname(interface, tmp); - g_free (tmp); - - /* convert the value of this property to a string, and put it between - * the opening and the closing of the property tag */ - tmp = glade_property_class_make_string_from_gvalue (property->class, - property->value); - - /* an empty string is a valid value (a flag set to 0) */ - if (tmp == NULL) return FALSE; + /* Skip properties that are default + * (by original pspec default) + */ + if (glade_property_equals_value (property, property->class->orig_def)) + return FALSE; - if (property->class->orig_def == NULL) + /* we should change each '-' by '_' on the name of the property + * (<property name="...">) */ + if (property->class->atk_type != GPC_ATK_NONE) { - /* Skip custom properties that are NULL string types. */ - skip = G_IS_PARAM_SPEC_STRING (property->class->pspec) && - !g_value_get_string (property->value); + + tmp = (gchar *)glade_property_class_atk_realname (property->class->id); + name = g_strdup (tmp); } else { - /* Skip properties that are default - * (by original pspec default) - */ - default_str = - glade_property_class_make_string_from_gvalue - (property->class, property->class->orig_def); - skip = default_str && !strcmp (tmp, default_str); - g_free (default_str); + name = g_strdup (property->class->id); } - - if (skip) + + /* convert the value of this property to a string */ + /* XXX Is this right to return here ??? */ + if ((value = glade_property_class_make_string_from_gvalue + (property->class, property->value)) == NULL) { - g_free (tmp); + g_free (name); return FALSE; } - if (property->class->translatable) + switch (property->class->atk_type) { - info.translatable = property->i18n_translatable; - info.has_context = property->i18n_has_context; - if (property->i18n_comment) - info.comment = alloc_string - (interface, property->i18n_comment); + case GPC_ATK_PROPERTY: + tmp = g_strdup_printf ("AtkObject::%s", name); + g_free (name); + name = tmp; + /* Dont break here ... */ + case GPC_ATK_NONE: + info.name = alloc_propname(interface, name); + info.value = alloc_string(interface, value); + + if (property->class->translatable) + { + info.translatable = property->i18n_translatable; + info.has_context = property->i18n_has_context; + if (property->i18n_comment) + info.comment = alloc_string + (interface, property->i18n_comment); + } + g_array_append_val (props, info); + break; + case GPC_ATK_RELATION: + if ((split = g_strsplit (value, GPC_OBJECT_DELIMITER, 0)) != NULL) + { + for (i = 0; split[i] != NULL; i++) + { + GladeAtkRelationInfo rinfo = { 0, }; + rinfo.type = alloc_string(interface, name); + rinfo.target = alloc_string(interface, split[i]); + g_array_append_val (props, rinfo); + } + g_strfreev (split); + } + break; + case GPC_ATK_ACTION: + ainfo.action_name = alloc_string(interface, name); + ainfo.description = alloc_string(interface, value); + g_array_append_val (props, ainfo); + break; + default: + break; } - info.value = alloc_string(interface, tmp); - g_array_append_val (props, info); - g_free (tmp); + g_free (name); + g_free (value); return TRUE; } - static G_CONST_RETURN gchar * glade_property_get_tooltip_impl (GladeProperty *property) { @@ -581,6 +650,259 @@ glade_property_get_type (void) } /******************************************************************************* + GladeInterface Parsing code + *******************************************************************************/ +static GValue * +glade_property_read_packing (GladeProperty *property, + GladePropertyClass *pclass, + GladeProject *project, + GladeChildInfo *info, + gboolean free_value) +{ + GValue *gvalue = NULL; + gint i; + gchar *id; + + for (i = 0; i < info->n_properties; ++i) + { + GladePropInfo *pinfo = info->properties + i; + + id = glade_util_read_prop_name (pinfo->name); + + if (!strcmp (id, pclass->id)) + { + gvalue = glade_property_class_make_gvalue_from_string + (pclass, pinfo->value, project); + + if (property) + { + glade_property_i18n_set_translatable + (property, pinfo->translatable); + glade_property_i18n_set_has_context + (property, pinfo->has_context); + glade_property_i18n_set_comment + (property, pinfo->comment); + property->enabled = TRUE; + + GLADE_PROPERTY_GET_KLASS (property)->set_value + (property, gvalue); + } + + if (free_value) + { + g_value_unset (gvalue); + g_free (gvalue); + } + + g_free (id); + break; + } + g_free (id); + } + return gvalue; +} + +static GValue * +glade_property_read_normal (GladeProperty *property, + GladePropertyClass *pclass, + GladeProject *project, + GladeWidgetInfo *info, + gboolean free_value) +{ + GValue *gvalue = NULL; + gint i; + gchar *id; + + for (i = 0; i < info->n_properties; ++i) + { + GladePropInfo *pinfo = info->properties + i; + + id = glade_util_read_prop_name (pinfo->name); + + if (!strcmp (id, pclass->id)) + { + if (property && glade_property_class_is_object (pclass)) + { + /* we must synchronize this directly after loading this project + * (i.e. lookup the actual objects after they've been parsed and + * are present). + */ + g_object_set_data_full (G_OBJECT (property), + "glade-loaded-object", + g_strdup (pinfo->value), g_free); + } + else + { + gvalue = glade_property_class_make_gvalue_from_string + (pclass, pinfo->value, project); + + if (property) + GLADE_PROPERTY_GET_KLASS + (property)->set_value (property, gvalue); + + if (free_value) + { + g_value_unset (gvalue); + g_free (gvalue); + } + } + + if (property) + { + glade_property_i18n_set_translatable + (property, pinfo->translatable); + glade_property_i18n_set_has_context + (property, pinfo->has_context); + glade_property_i18n_set_comment + (property, pinfo->comment); + + property->enabled = TRUE; + } + + g_free (id); + break; + } + g_free (id); + } + return gvalue; +} + +static GValue * +glade_property_read_atk_prop (GladeProperty *property, + GladePropertyClass *pclass, + GladeProject *project, + GladeWidgetInfo *info, + gboolean free_value) +{ + GValue *gvalue = NULL; + gint i; + gchar *id; + + for (i = 0; i < info->n_atk_props; ++i) + { + GladePropInfo *pinfo = info->atk_props + i; + + id = glade_util_read_prop_name (pinfo->name); + + if (!strcmp (id, pclass->id)) + { + gvalue = glade_property_class_make_gvalue_from_string + (pclass, pinfo->value, project); + + if (property) + { + glade_property_i18n_set_translatable + (property, pinfo->translatable); + glade_property_i18n_set_has_context + (property, pinfo->has_context); + glade_property_i18n_set_comment + (property, pinfo->comment); + GLADE_PROPERTY_GET_KLASS (property)->set_value + (property, gvalue); + + property->enabled = TRUE; + } + + if (free_value) + { + g_value_unset (gvalue); + g_free (gvalue); + } + + g_free (id); + break; + } + g_free (id); + } + return gvalue; +} + +static GValue * +glade_property_read_atk_relation (GladeProperty *property, + GladePropertyClass *pclass, + GladeProject *project, + GladeWidgetInfo *info) +{ + const gchar *class_id; + gchar *id, *string = NULL, *tmp; + gint i; + + for (i = 0; i < info->n_relations; ++i) + { + GladeAtkRelationInfo *rinfo = info->relations + i; + + id = glade_util_read_prop_name (rinfo->type); + class_id = glade_property_class_atk_realname (pclass->id); + + if (!strcmp (id, class_id)) + { + if (string == NULL) + string = g_strdup (rinfo->target); + else + { + tmp = g_strdup_printf ("%s%s%s", string, + GPC_OBJECT_DELIMITER, rinfo->target); + string = (g_free (string), tmp); + } + } + g_free (id); + } + + /* we must synchronize this directly after loading this project + * (i.e. lookup the actual objects after they've been parsed and + * are present). + */ + if (property) + { + g_object_set_data_full (G_OBJECT (property), "glade-loaded-object", + g_strdup (string), g_free); + } + + return NULL; +} + +static GValue * +glade_property_read_atk_action (GladeProperty *property, + GladePropertyClass *pclass, + GladeProject *project, + GladeWidgetInfo *info, + gboolean free_value) +{ + GValue *gvalue = NULL; + const gchar *class_id; + gchar *id; + gint i; + + for (i = 0; i < info->n_atk_actions; ++i) + { + GladeAtkActionInfo *ainfo = info->atk_actions + i; + + id = glade_util_read_prop_name (ainfo->action_name); + class_id = glade_property_class_atk_realname (pclass->id); + + if (!strcmp (id, class_id)) + { + gvalue = glade_property_class_make_gvalue_from_string + (pclass, ainfo->description, project); + + if (property) + GLADE_PROPERTY_GET_KLASS + (property)->set_value (property, gvalue); + + if (free_value) + { + g_value_unset (gvalue); + g_free (gvalue); + } + g_free (id); + break; + } + g_free (id); + } + return gvalue; +} + +/******************************************************************************* API *******************************************************************************/ /** @@ -871,6 +1193,67 @@ glade_property_sync (GladeProperty *property) } /** + * glade_property_read: + * @property: a #GladeProperty or #NULL + * @pclass: the #GladePropertyClass + * @project: the #GladeProject + * @info: a #GladeWidgetInfo struct or a #GladeChildInfo struct if + * a packing property is passed. + * @free_value: Whether the return value should be freed after applying + * it to the property or if it should be returned in tact. + * + * Read the value and any attributes for @property from @info, assumes + * @property is being loaded for @project + * + * Returns: The newly created #GValue if successfull (and if @free_value == FALSE) + * + * Note that object values will only be resolved after the project is + * completely loaded + */ +GValue * +glade_property_read (GladeProperty *property, + GladePropertyClass *pclass, + GladeProject *project, + gpointer info, + gboolean free_value) +{ + GValue *ret = NULL; + + g_return_val_if_fail (pclass != NULL, FALSE); + g_return_val_if_fail (info != NULL, FALSE); + + if (pclass->packing) + { + ret = glade_property_read_packing + (property, pclass, project, (GladeChildInfo *)info, free_value); + } + else switch (pclass->atk_type) + { + case GPC_ATK_NONE: + ret = glade_property_read_normal + (property, pclass, project, (GladeWidgetInfo *)info, free_value); + break; + case GPC_ATK_PROPERTY: + ret = glade_property_read_atk_prop + (property, pclass, project, (GladeWidgetInfo *)info, free_value); + break; + case GPC_ATK_RELATION: + ret = glade_property_read_atk_relation + (property, pclass, project, (GladeWidgetInfo *)info); + break; + case GPC_ATK_ACTION: + ret = glade_property_read_atk_action + (property, pclass, project, (GladeWidgetInfo *)info, free_value); + break; + default: + break; + } + + return ret; +} + + +/** * glade_property_write: * @property: a #GladeProperty * @interface: a #GladeInterface @@ -887,6 +1270,95 @@ glade_property_write (GladeProperty *property, GladeInterface *interface, GArray return GLADE_PROPERTY_GET_KLASS (property)->write (property, interface, props); } +/** + * glade_property_add_object: + * @property: a #GladeProperty + * @object: The #GObject to add + * + * Adds @object to the object list in @property. + * + * Note: This function expects @property to be a #GladeParamSpecObjects + * or #GParamSpecObject type property. + */ +void +glade_property_add_object (GladeProperty *property, + GObject *object) +{ + GList *list = NULL, *new_list = NULL; + + g_return_if_fail (GLADE_IS_PROPERTY (property)); + g_return_if_fail (G_IS_OBJECT (object)); + g_return_if_fail (GLADE_IS_PARAM_SPEC_OBJECTS (property->class->pspec) || + G_IS_PARAM_SPEC_OBJECT (property->class->pspec)); + + if (GLADE_IS_PARAM_SPEC_OBJECTS (property->class->pspec)) + { + glade_property_get (property, &list); + new_list = g_list_copy (list); + + new_list = g_list_append (new_list, object); + glade_property_set (property, new_list); + + /* ownership of the list is not passed + * through glade_property_set() + */ + g_list_free (new_list); + } + else + { + glade_property_set (property, object); + } +} + +/** + * glade_property_remove_object: + * @property: a #GladeProperty + * @object: The #GObject to add + * + * Removes @object from the object list in @property. + * + * Note: This function expects @property to be a #GladeParamSpecObjects + * or #GParamSpecObject type property. + */ +void +glade_property_remove_object (GladeProperty *property, + GObject *object) +{ + GList *list = NULL, *new_list = NULL; + + g_return_if_fail (GLADE_IS_PROPERTY (property)); + g_return_if_fail (G_IS_OBJECT (object)); + g_return_if_fail (GLADE_IS_PARAM_SPEC_OBJECTS (property->class->pspec) || + G_IS_PARAM_SPEC_OBJECT (property->class->pspec)); + + if (GLADE_IS_PARAM_SPEC_OBJECTS (property->class->pspec)) + { + /* If object isnt in list; list should stay in tact. + * not bothering to check for now. + */ + glade_property_get (property, &list); + new_list = g_list_copy (list); + + new_list = g_list_remove (new_list, object); + glade_property_set (property, new_list); + + /* ownership of the list is not passed + * through glade_property_set() + */ + g_list_free (new_list); + } + else + { + glade_property_set (property, object); + } + + glade_property_class_get_from_gvalue (property->class, + property->value, + &list); + + glade_property_set (property, list); +} + /** * glade_property_get_tooltip: diff --git a/src/glade-property.h b/src/glade-property.h index 60dac050..47ee0363 100644 --- a/src/glade-property.h +++ b/src/glade-property.h @@ -120,8 +120,20 @@ LIBGLADEUI_API void glade_property_get (GladeProperty *property, ...); LIBGLADEUI_API +void glade_property_add_object (GladeProperty *property, + GObject *object); +LIBGLADEUI_API +void glade_property_remove_object (GladeProperty *property, + GObject *object); +LIBGLADEUI_API void glade_property_sync (GladeProperty *property); LIBGLADEUI_API +GValue *glade_property_read (GladeProperty *property, + GladePropertyClass *pclass, + GladeProject *project, + gpointer info, + gboolean free_value); +LIBGLADEUI_API gboolean glade_property_write (GladeProperty *property, GladeInterface *interface, GArray *props); diff --git a/src/glade-utils.c b/src/glade-utils.c index a92ffeda..b599769f 100644 --- a/src/glade-utils.c +++ b/src/glade-utils.c @@ -559,6 +559,33 @@ glade_util_replace (gchar *str, gchar a, gchar b) } /** + * glade_util_read_prop_name: + * @str: a string + * + * Return a usable version of a property identifier as found + * in a freshly parserd #GladeInterface + */ +gchar * +glade_util_read_prop_name (const gchar *str) +{ + gchar *id = g_strdup (str); + + glade_util_replace (id, '_', '-'); + + if (strstr (id, "::")) + { + /* Extract the second half of "AtkObject::accessible_name" + */ + gchar **split = g_strsplit (id, "::", 0); + g_free (id); + id = g_strdup (split[1]); + g_strfreev (split); + } + return id; +} + + +/** * glade_util_duplicate_underscores: * @name: a string * @@ -1218,7 +1245,8 @@ glade_util_basenames_match (const gchar *path1, * glade_util_purify_list: * @list: A #GList * - * Returns: A list with no duplicate data entries + * Returns: A newly allocated version of @list with no + * duplicate data entries */ GList * glade_util_purify_list (GList *list) @@ -1235,6 +1263,55 @@ glade_util_purify_list (GList *list) } /** + * glade_util_added_in_list: + * @old: the old #GList + * @new: the new #GList + * + * Returns: A newly allocated #GList of elements that + * are in @new but not in @old + * + */ +GList * +glade_util_added_in_list (GList *old, + GList *new) +{ + GList *added = NULL, *list; + + for (list = new; list; list = list->next) + { + if (!g_list_find (old, list->data)) + added = g_list_prepend (added, list->data); + } + + return g_list_reverse (added); +} + +/** + * glade_util_removed_from_list: + * @old: the old #GList + * @new: the new #GList + * + * Returns: A newly allocated #GList of elements that + * are in @old no longer in @new + * + */ +GList * +glade_util_removed_from_list (GList *old, + GList *new) +{ + GList *added = NULL, *list; + + for (list = old; list; list = list->next) + { + if (!g_list_find (new, list->data)) + added = g_list_prepend (added, list->data); + } + + return g_list_reverse (added); +} + + +/** * glade_util_canonical_path: * @path: any path that may contain ".." or "." components * @@ -1333,7 +1410,7 @@ glade_util_copy_file (const gchar *src_path, if (g_file_test (dest_path, G_FILE_TEST_IS_REGULAR) == TRUE) if (glade_util_ui_message - (glade_default_app_get_window(), GLADE_UI_YES_OR_NO, + (glade_app_get_window(), GLADE_UI_YES_OR_NO, _("%s exists.\nDo you want to replace it?"), dest_path) == FALSE) return FALSE; @@ -1360,7 +1437,7 @@ glade_util_copy_file (const gchar *src_path, if (write_status == G_IO_STATUS_ERROR) { - glade_util_ui_message (glade_default_app_get_window(), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_ERROR, _("Error writing to %s: %s"), dest_path, error->message); @@ -1374,7 +1451,7 @@ glade_util_copy_file (const gchar *src_path, if (read_status == G_IO_STATUS_ERROR) { - glade_util_ui_message (glade_default_app_get_window(), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_ERROR, _("Error reading %s: %s"), src_path, error->message); @@ -1389,7 +1466,7 @@ glade_util_copy_file (const gchar *src_path, if (g_io_channel_shutdown (dest, TRUE, &error) != G_IO_STATUS_NORMAL) { glade_util_ui_message - (glade_default_app_get_window(), + (glade_app_get_window(), GLADE_UI_ERROR, _("Error shutting down I/O channel %s: %s"), dest_path, error->message); @@ -1399,7 +1476,7 @@ glade_util_copy_file (const gchar *src_path, } else { - glade_util_ui_message (glade_default_app_get_window(), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_ERROR, _("Failed to open %s for writing: %s"), dest_path, error->message); @@ -1410,7 +1487,7 @@ glade_util_copy_file (const gchar *src_path, if (g_io_channel_shutdown (src, TRUE, &error) != G_IO_STATUS_NORMAL) { - glade_util_ui_message (glade_default_app_get_window(), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_ERROR, _("Error shutting down io channel %s: %s"), src_path, error->message); @@ -1419,7 +1496,7 @@ glade_util_copy_file (const gchar *src_path, } else { - glade_util_ui_message (glade_default_app_get_window(), + glade_util_ui_message (glade_app_get_window(), GLADE_UI_ERROR, _("Failed to open %s for reading: %s"), src_path, error->message); @@ -1428,6 +1505,34 @@ glade_util_copy_file (const gchar *src_path, return success; } +/** + * glade_util_class_implements_interface: + * @class_type: A #GType + * @iface_type: A #GType + * + * Returns: whether @class_type implements the @iface_type interface + */ +gboolean +glade_util_class_implements_interface (GType class_type, + GType iface_type) +{ + GType *ifaces; + guint n_ifaces, i; + gboolean implemented = FALSE; + + if ((ifaces = g_type_interfaces (class_type, &n_ifaces)) != NULL) + { + for (i = 0; i < n_ifaces; i++) + if (ifaces[i] == iface_type) + { + implemented = TRUE; + break; + } + g_free (ifaces); + } + return implemented; +} + /** * glade_util_load_library: diff --git a/src/glade-utils.h b/src/glade-utils.h index 60f22c0d..e7c5b6ac 100644 --- a/src/glade-utils.h +++ b/src/glade-utils.h @@ -56,7 +56,9 @@ GtkWidget *glade_util_file_dialog_new (const gchar *title, GtkWindow *parent, GladeUtilFileDialogType action); LIBGLADEUI_API -void glade_util_replace (char *str, char a, char b); +void glade_util_replace (gchar *str, gchar a, gchar b); +LIBGLADEUI_API +gchar *glade_util_read_prop_name (const gchar *str); LIBGLADEUI_API gchar *glade_util_duplicate_underscores (const gchar *name); @@ -109,11 +111,20 @@ gboolean glade_util_basenames_match (const gchar *path1, LIBGLADEUI_API GList *glade_util_purify_list (GList *list); LIBGLADEUI_API +GList *glade_util_added_in_list (GList *old, + GList *new); +LIBGLADEUI_API +GList *glade_util_removed_from_list (GList *old, + GList *new); +LIBGLADEUI_API gchar *glade_util_canonical_path (const gchar *path); LIBGLADEUI_API gboolean glade_util_copy_file (const gchar *src_path, const gchar *dest_path); +LIBGLADEUI_API +gboolean glade_util_class_implements_interface (GType class_type, + GType iface_type); LIBGLADEUI_API GModule *glade_util_load_library (const gchar *library_name); diff --git a/src/glade-widget-class.c b/src/glade-widget-class.c index 10c1f4c3..80bf9f1c 100644 --- a/src/glade-widget-class.c +++ b/src/glade-widget-class.c @@ -131,25 +131,82 @@ gwc_props_from_pspecs (GParamSpec **specs, gint n_specs) return g_list_reverse (list); } -static gboolean -gwc_class_implements_interface (GType class_type, - GType iface_type) +static GList * +gwc_list_atk_actions (GladeWidgetClass *class, AtkAction *action) { - GType *ifaces; - guint n_ifaces, i; - gboolean implemented = FALSE; + GladePropertyClass *pclass; + GList *actions = NULL; + gint n_actions, i; + const gchar *name, *def; - if ((ifaces = g_type_interfaces (class_type, &n_ifaces)) != NULL) + n_actions = atk_action_get_n_actions (action); + + for (i = 0; i < n_actions; i++) { - for (i = 0; i < n_ifaces; i++) - if (ifaces[i] == iface_type) - { - implemented = TRUE; - break; - } - g_free (ifaces); + name = atk_action_get_name (action, i); + def = atk_action_get_description (action, i); + + pclass = glade_property_class_new_atk_action + (name, def, class->type); + + actions = g_list_prepend (actions, pclass); } - return implemented; + + return g_list_reverse (actions); +} + +static GList * +gwc_list_atk_properties (GladeWidgetClass *class) +{ + GladePropertyClass *pclass; + GObjectClass *object_class; + GObject *object; + GParamSpec *spec; + AtkObject *accessible; + GList *list, *atk_list = NULL; + + /* Atk props are only applied on instantiatable classes */ + if (G_TYPE_IS_INSTANTIATABLE (class->type) == FALSE || + G_TYPE_IS_ABSTRACT (class->type)) + return NULL; + + object = g_object_new (class->type, NULL); + + if ((accessible = + atk_implementor_ref_accessible(ATK_IMPLEMENTOR (object))) != NULL) + { + object_class = G_OBJECT_GET_CLASS (accessible); + + /* Get the desctiption pspec and add it (also touch up visible-lines) */ + spec = g_object_class_find_property + (object_class, "accessible_description"); + pclass = glade_property_class_new_from_spec (spec); + + /* multiple lines on the desctription */ + pclass->visible_lines = 2; + atk_list = g_list_prepend (atk_list, pclass); + + /* Get the name pspec and add it */ + spec = g_object_class_find_property (object_class, + "accessible_name"); + pclass = glade_property_class_new_from_spec (spec); + atk_list = g_list_prepend (atk_list, pclass); + + if (ATK_IS_ACTION (accessible)) + { + list = gwc_list_atk_actions (class, ATK_ACTION (accessible)); + atk_list = g_list_concat (atk_list, list); + } + + list = glade_property_class_list_atk_relations (class->type); + atk_list = g_list_concat (atk_list, list); + + g_object_unref (G_OBJECT (accessible)); + } + + // XXX FIXME: Leek :( g_object_unref (object); + // g_object_unref causes segfaults here... why ? + return atk_list; } static GList * @@ -175,31 +232,11 @@ glade_widget_class_list_properties (GladeWidgetClass *class) list = gwc_props_from_pspecs (specs, n_specs); g_free (specs); - -#if 0 - /* XXX ATK compiled out for now, just for cvs sake. - */ - - /* XXX FIXME: We shouldnt just do ATK_TYPE_OBJECT, we need - * to instanciate an object of the right type and use - * atk_implementor_ref_accessible()... so as to get the correct - * ATK_TYPE_OBJECT derivative (this might be overkill for the - * task at hand...) - */ - /* list atk properties if applicable */ - if (gwc_class_implements_interface (class->type, ATK_TYPE_IMPLEMENTOR)) - { - if ((object_class = g_type_class_ref (ATK_TYPE_OBJECT)) == NULL) - g_critical ("Failed to get class for type %s\n", - g_type_name (ATK_TYPE_OBJECT)); - - /* list atk properties */ - specs = g_object_class_list_properties (object_class, &n_specs); - atk_list = gwc_props_from_pspecs (specs, n_specs); - g_free (specs); - } -#endif + if (glade_util_class_implements_interface (class->type, + ATK_TYPE_IMPLEMENTOR)) + atk_list = gwc_list_atk_properties (class); + return g_list_concat (list, atk_list); } diff --git a/src/glade-widget.c b/src/glade-widget.c index f2327fff..1be98417 100644 --- a/src/glade-widget.c +++ b/src/glade-widget.c @@ -435,6 +435,11 @@ glade_widget_project_notify (GladeWidget *widget, GladeProject *project) GList *l; GladeProperty *property; + g_return_if_fail (GLADE_IS_WIDGET (widget)); + + /* Since glade_property_set() will try to modify list, + * we protect it with the 'prop_refs_readonly' flag. + */ widget->prop_refs_readonly = TRUE; for (l = widget->prop_refs; l && l->data; l = l->next) { @@ -442,9 +447,9 @@ glade_widget_project_notify (GladeWidget *widget, GladeProject *project) if (project != NULL && project == property->widget->project) - glade_property_set (property, widget->object); + glade_property_add_object (property, widget->object); else - glade_property_set (property, NULL); + glade_property_remove_object (property, widget->object); } widget->prop_refs_readonly = FALSE; } @@ -752,16 +757,21 @@ glade_widget_new (GladeWidget *parent, gboolean query) { GladeWidget *widget; - gchar *widget_name = - glade_project_new_widget_name - (GLADE_PROJECT (project), klass->generic_name); + gchar *widget_name; + + g_return_val_if_fail (GLADE_IS_WIDGET_CLASS (klass), NULL); + + if (project) + widget_name = glade_project_new_widget_name + (GLADE_PROJECT (project), klass->generic_name); + else widget_name = g_strdup (klass->generic_name); if ((widget = glade_widget_internal_new (widget_name, parent, klass, project, NULL, GLADE_CREATE_USER)) != NULL) { if (query && widget->query_user) { - GladeEditor *editor = glade_default_app_get_editor (); + GladeEditor *editor = glade_app_get_editor (); /* If user pressed cancel on query popup. */ if (!glade_editor_query_dialog (editor, widget)) @@ -2014,10 +2024,10 @@ glade_widget_button_press (GtkWidget *widget, { if (glade_project_is_selected (glade_widget->project, glade_widget->object)) - glade_default_app_selection_remove + glade_app_selection_remove (glade_widget->object, TRUE); else - glade_default_app_selection_add + glade_app_selection_add (glade_widget->object, TRUE); handled = TRUE; } @@ -2025,7 +2035,7 @@ glade_widget_button_press (GtkWidget *widget, glade_widget->object) == FALSE) { glade_util_clear_selection (); - glade_default_app_selection_set + glade_app_selection_set (glade_widget->object, TRUE); handled = TRUE; } @@ -2396,7 +2406,8 @@ glade_widget_set_packing_properties (GladeWidget *widget, * @widget: a #GladeWidget * @type: a #GType * - * Returns: whether this GladeWidget has any decendants of type `type' + * Returns: whether this GladeWidget has any decendants of type @type + * or any decendants that implement the @type interface */ gboolean glade_widget_has_decendant (GladeWidget *widget, GType type) @@ -2405,7 +2416,12 @@ glade_widget_has_decendant (GladeWidget *widget, GType type) GList *children, *l; gboolean found = FALSE; - if (g_type_is_a (widget->widget_class->type, type)) + if (G_TYPE_IS_INTERFACE (type) && + glade_util_class_implements_interface + (widget->widget_class->type, type)) + return TRUE; + else if (G_TYPE_IS_INTERFACE (type) == FALSE && + g_type_is_a (widget->widget_class->type, type)) return TRUE; if ((children = glade_widget_class_container_get_children @@ -2499,7 +2515,7 @@ glade_widget_write (GladeWidget *widget, GladeInterface *interface) { WriteSignalsContext write_signals_context; GladeWidgetInfo *info; - GArray *props, *children; + GArray *props, *atk_props, *atk_actions, *atk_relations, *children; GList *list; g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL); @@ -2510,22 +2526,59 @@ glade_widget_write (GladeWidget *widget, GladeInterface *interface) info->name = alloc_string (interface, widget->name); /* Write the properties */ - list = widget->properties; - props = g_array_new (FALSE, FALSE, - sizeof (GladePropInfo)); - for (; list; list = list->next) + props = g_array_new (FALSE, FALSE, sizeof (GladePropInfo)); + atk_props = g_array_new (FALSE, FALSE, sizeof (GladePropInfo)); + atk_relations = g_array_new (FALSE, FALSE, sizeof (GladeAtkRelationInfo)); + atk_actions = g_array_new (FALSE, FALSE, sizeof (GladeAtkActionInfo)); + + for (list = widget->properties; list; list = list->next) { GladeProperty *property = list->data; + /* This should never happen */ if (property->class->packing) continue; - glade_property_write (property, interface, props); + switch (property->class->atk_type) + { + case GPC_ATK_NONE: + glade_property_write (property, interface, props); + break; + case GPC_ATK_PROPERTY: + glade_property_write (property, interface, atk_props); + break; + case GPC_ATK_RELATION: + glade_property_write (property, interface, atk_relations); + break; + case GPC_ATK_ACTION: + glade_property_write (property, interface, atk_actions); + break; + default: + break; + } } + + /* Properties */ info->properties = (GladePropInfo *) props->data; info->n_properties = props->len; g_array_free(props, FALSE); + /* Atk Properties */ + info->atk_props = (GladePropInfo *) atk_props->data; + info->n_atk_props = atk_props->len; + g_array_free(atk_props, FALSE); + + /* Atk Relations */ + info->relations = (GladeAtkRelationInfo *) atk_relations->data; + info->n_relations = atk_relations->len; + g_array_free(atk_relations, FALSE); + + /* Atk Actions */ + info->atk_actions = (GladeAtkActionInfo *) atk_actions->data; + info->n_atk_actions = atk_actions->len; + g_array_free(atk_actions, FALSE); + + /* Signals */ write_signals_context.interface = interface; write_signals_context.signals = g_array_new (FALSE, FALSE, @@ -2586,9 +2639,9 @@ glade_widget_write_special_child_prop (GArray *props, } gboolean -glade_widget_write_child (GArray *children, - GladeWidget *parent, - GObject *object, +glade_widget_write_child (GArray *children, + GladeWidget *parent, + GObject *object, GladeInterface *interface) { GladeChildInfo info = { 0 }; @@ -2657,80 +2710,6 @@ glade_widget_write_child (GArray *children, return TRUE; } -static GValue * -glade_widget_value_from_prop_info (GladePropInfo *info, - GladeWidgetClass *class) -{ - GladePropertyClass *pclass; - GValue *gvalue = NULL; - gchar *id; - - g_return_val_if_fail (info != NULL, NULL); - - id = g_strdup (info->name); - glade_util_replace (id, '_', '-'); - - if (info->name && info->value && - (pclass = glade_widget_class_get_property_class (class, id)) != NULL) - gvalue = glade_property_class_make_gvalue_from_string (pclass, - info->value, - loading_project); - - g_free (id); - - return gvalue; -} - -static gboolean -glade_widget_apply_property_from_prop_info (GladePropInfo *info, - GladeWidget *widget, - gboolean is_packing) -{ - GladeProperty *property; - GladeWidgetClass *wclass; - GValue *gvalue; - gchar *id; - - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (widget != NULL, FALSE); - - id = g_strdup (info->name); - - glade_util_replace (id, '_', '-'); - property = !is_packing ? glade_widget_get_property (widget, id): - glade_widget_get_pack_property (widget, id); - g_free (id); - - if (!property) - { - return FALSE; - } - - wclass = property->class->packing ? - widget->parent->widget_class : - widget->widget_class; - - - if (glade_property_class_is_object (property->class)) - { - /* we must synchronize this directly after loading this project. - */ - g_object_set_data_full (G_OBJECT (property), "glade-loaded-object", - g_strdup (info->value), g_free); - } - - if ((gvalue = glade_widget_value_from_prop_info (info, wclass)) != NULL) - { - glade_property_set_value (property, gvalue); - - g_value_unset (gvalue); - g_free (gvalue); - } - return TRUE; -} - - - static gboolean glade_widget_new_child_from_child_info (GladeChildInfo *info, GladeProject *project, @@ -2741,11 +2720,13 @@ glade_widget_fill_from_widget_info (GladeWidgetInfo *info, GladeWidget *widget, gboolean apply_props) { - guint i; + GladeProperty *property; + GList *list; + guint i; g_return_if_fail (GLADE_IS_WIDGET (widget)); g_return_if_fail (info != NULL); - + g_assert (strcmp (info->classname, widget->widget_class->name) == 0); /* Children */ @@ -2777,53 +2758,13 @@ glade_widget_fill_from_widget_info (GladeWidgetInfo *info, /* Properties */ if (apply_props) { - for (i = 0; i < info->n_properties; ++i) - { - GladePropInfo *prop_info = info->properties + i; - if (!glade_widget_apply_property_from_prop_info (prop_info, - widget, FALSE)) - g_warning ("Failed to apply property %s in %s", - prop_info->name, - glade_widget_get_name (widget)); - } - } -} - -static GValue * -glade_widget_get_property_from_widget_info (GladeWidgetClass *class, - GladeWidgetInfo *info, - const gchar *name, - gboolean *translatable, - gboolean *has_context, - gchar **comment) -{ - GValue *value = NULL; - guint i; - gchar *id; - - for (i = 0; i < info->n_properties; ++i) - { - GladePropInfo *pinfo = info->properties + i; - - id = g_strdup (pinfo->name); - glade_util_replace (id, '_', '-'); - - if (!strcmp (id, name)) - { - g_free (id); - - if (translatable) - *translatable = pinfo->translatable; - if (has_context) - *has_context = pinfo->has_context; - if (comment) - *comment = g_strdup (pinfo->comment); - - return glade_widget_value_from_prop_info (pinfo, class); + for (list = widget->properties; list; list = list->next) + { + property = list->data; + glade_property_read (property, property->class, + loading_project, info, TRUE); } - g_free (id); } - return value; } static void @@ -2847,42 +2788,19 @@ glade_widget_properties_from_widget_info (GladeWidgetClass *class, for (list = class->properties; list && list->data; list = list->next) { GladePropertyClass *pclass = list->data; - GValue *value; GladeProperty *property; - gboolean translatable; - gboolean has_context; - gchar *comment = NULL; - const gchar *obj_name; /* If there is a value in the XML, initialize property with it, * otherwise initialize property to default. */ - value = glade_widget_get_property_from_widget_info - (class, info, pclass->id, - &translatable, &has_context, &comment); - - property = glade_property_new (pclass, NULL, value, FALSE); - property->enabled = value ? TRUE : property->enabled; + property = glade_property_new (pclass, NULL, NULL, FALSE); - if (glade_property_class_is_object (pclass)) - { - /* we must synchronize this directly after loading this project. - */ - obj_name = glade_parser_pvalue_from_winfo (info, pclass->id); - g_object_set_data_full (G_OBJECT (property), "glade-loaded-object", - g_strdup (obj_name), g_free); - } - - if (value) { - glade_property_i18n_set_translatable (property, translatable); - glade_property_i18n_set_has_context (property, has_context); - glade_property_i18n_set_comment (property, comment); - } - - g_free (comment); + glade_property_read (property, property->class, + loading_project, info, TRUE); properties = g_list_prepend (properties, property); } + return g_list_reverse (properties); } @@ -2894,7 +2812,7 @@ glade_widget_params_from_widget_info (GladeWidgetClass *widget_class, GObjectClass *oclass; GParamSpec **pspec; GArray *params; - guint i, n_props; + guint i, n_props; oclass = g_type_class_ref (widget_class->type); pspec = g_object_class_list_properties (oclass, &n_props); @@ -2919,9 +2837,8 @@ glade_widget_params_from_widget_info (GladeWidgetClass *widget_class, /* Try filling parameter with value from widget info. */ - if ((value = glade_widget_get_property_from_widget_info - (widget_class, info, parameter.name, - NULL, NULL, NULL)) != NULL) + if ((value = glade_property_read (NULL, glade_property_class, + loading_project, info, FALSE)) != NULL) { if (g_value_type_compatible (G_VALUE_TYPE (value), G_VALUE_TYPE (¶meter.value))) @@ -3087,11 +3004,11 @@ glade_widget_set_child_type_from_child_info (GladeChildInfo *child_info, static gboolean glade_widget_new_child_from_child_info (GladeChildInfo *info, - GladeProject *project, - GladeWidget *parent) + GladeProject *project, + GladeWidget *parent) { GladeWidget *child; - gint i, special_child_type_index = -1; + GList *list; g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (project != NULL, FALSE); @@ -3138,10 +3055,8 @@ glade_widget_new_child_from_child_info (GladeChildInfo *info, child->parent = parent; - special_child_type_index = - glade_widget_set_child_type_from_child_info (info, - parent->widget_class, - child->object); + glade_widget_set_child_type_from_child_info + (info, parent->widget_class, child->object); if (parent->manager != NULL) glade_fixed_manager_add_child (parent->manager, child, FALSE); @@ -3153,15 +3068,12 @@ glade_widget_new_child_from_child_info (GladeChildInfo *info, } /* Get the packing properties */ - for (i = 0; i < info->n_properties; ++i) + for (list = child->packing_properties; list; list = list->next) { - if (special_child_type_index == i) - continue; - if (!glade_widget_apply_property_from_prop_info (info->properties + i, - child, TRUE)) - g_warning ("Failed to apply packing property"); + GladeProperty *property = list->data; + glade_property_read (property, property->class, + loading_project, info, TRUE); } - return TRUE; } diff --git a/src/glade.h b/src/glade.h index 18615999..cea57dea 100644 --- a/src/glade.h +++ b/src/glade.h @@ -130,7 +130,6 @@ typedef struct _GladeProject GladeProject; #define GLADE_TAG_IGNORE "ignore" #define GLADE_TAG_VISIBLE_LINES "visible-lines" #define GLADE_TAG_RESOURCE "resource" -#define GLADE_TAG_ATK_RELATION "atk-relation" #define GLADE_TAG_INIT_FUNCTION "init-function" #define GLADE_NUMERICAL_STEP_INCREMENT 1 @@ -69,7 +69,19 @@ main (int argc, char *argv[]) GOptionContext *option_context; GOptionGroup *option_group; GError *error = NULL; + gchar *modules, *new_modules; + /* We need to ensure that gail is loaded, so that we can query accessibility + info. I can't see a GTK+ function to do that. For now we just add the + modules we need to the GTK_MODULES environment variable. It doesn't + matter if modules appear twice. */ + modules = (char*) g_getenv ("GTK_MODULES"); + new_modules = g_strdup_printf ("%s%s%s", + modules ? modules : "", + modules ? G_SEARCHPATH_SEPARATOR_S : "", + "gail"); + g_setenv ("GTK_MODULES", new_modules, TRUE); + #ifdef ENABLE_NLS setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, glade_locale_dir); @@ -129,7 +141,6 @@ main (int argc, char *argv[]) } project_window = glade_project_window_new (); - glade_default_app_set (GLADE_APP (project_window)); if (widget_name != NULL) { diff --git a/widgets/gtk+.xml.in b/widgets/gtk+.xml.in index eaee7655..7ba123aa 100644 --- a/widgets/gtk+.xml.in +++ b/widgets/gtk+.xml.in @@ -48,6 +48,7 @@ <value id="GDK_ALL_EVENTS_MASK" _name="All Events"/> </displayable-values> </property> + <property id="name" disabled="True"/> <property id="parent" disabled="True"/> <property id="style" disabled="True"/> @@ -341,7 +342,7 @@ <property id="selectable" ignore="True"/> <property id="pattern" default=""/> <property id="max-width-chars" _name="Maximun Width"/> - <property id="label" default="label"> + <property id="label" default="label" translatable="True"> <visible-lines>2</visible-lines> <set-function>glade_gtk_label_set_label</set-function> </property> @@ -391,15 +392,23 @@ <post-create-function>glade_gtk_button_post_create</post-create-function> <properties> <property id="image" disabled="True"/> - <property id="use-underline" disabled="True"/> - <property id="label" visible="False"/> <property id="use-stock" visible="False"/> + + <property id="label" default="button" translatable="True"> + <visible-lines>2</visible-lines> + </property> + <property id="stock" _name="Stock Button" save="False"> <spec>glade_standard_stock_spec</spec> <_tooltip>The stock item for this button</_tooltip> <set-function>glade_gtk_button_set_stock</set-function> </property> + <property id="glade-type" _name="Edit Type" save="False"> + <spec>glade_gtk_button_type_spec</spec> + <set-function>glade_gtk_button_set_type</set-function> + </property> + <property id="response-id" _name="Response ID" default="0" common="False" ignore="True"> <spec>glade_standard_int_spec</spec> <_tooltip>The response ID of this button in a dialog (it's NOT useful if this button is not in a GtkDialog)</_tooltip> @@ -418,6 +427,7 @@ <child> <type>GtkWidget</type> <add-child-function>glade_gtk_button_add_child</add-child-function> + <remove-child-function>glade_gtk_button_remove_child</remove-child-function> <replace-child-function>glade_gtk_button_replace_child</replace-child-function> </child> </children> @@ -545,7 +555,7 @@ <property id="stock" visible="False" translatable="False"> <set-function>glade_gtk_image_set_real_stock</set-function> </property> - <property id="glade-type" _name="Image Type" save="False"> + <property id="glade-type" _name="Edit Type" save="False"> <spec>glade_gtk_image_type_spec</spec> <set-function>glade_gtk_image_set_type</set-function> </property> |