Fix for #157667 and misc cleanups

This commit is contained in:
Archit Baweja 2004-12-21 21:44:18 +00:00
parent b8657d4331
commit 8f58541773
12 changed files with 235 additions and 113 deletions

View File

@ -1,3 +1,60 @@
2004-12-18 Archit Baweja <bighead@users.sourceforge.net>
* src/glade-editor.c (glade_editor_table_append_item): Added
gboolean from_query_dialog parameter to function definition.
All callers changed.
(glade_editor_property_changed_text_common): added from_query_dialog
parameter.
* src/glade-editor.c: removed prototypes for glade_editor_init()
and glade_editor_class_init() and moved definition of
glade_editor_get_type lower().
* src/glade-command.c (glade_command_set_name): push action onto undo
stack only if execute is successfully.
* src/glade-editor.c (glade_editor_query_dialog): renamed from
glade_editor_query_popup(). I feel a *_popup() is mis-named (atleast
from a Gtk+ point of view, since a popup in Gtk+ is a right click menu)
All callers changed.
2004-12-17 Archit Baweja <bighead@users.sourceforge.net>
* src/glade-command.c (glade_command_create_delete_common): there
was a semi-colon immediately after the if-statement on the same line.
So glade_command_push_undo go called no matter what. Fixed.
* src/glade-project.c (glade_project_selection_set): no need to get
GladeProjectWindow ptr.
(glade_project_selection_add): likewise.
* src/glade-editor.c (glade_editor_query_popup): don't set a default
size for query popup dialogs.
Show a "Cancel" button to cancel operation.
Also, if "Cancel" button pressed, return FALSE to stop "create" command
(glade_editor_table_append_items): we're not using this recursively.
Remove prototype.
* src/glade-widget.c (glade_widget_new): if glade_editor_query_popup
returns FALSE, stop "create" command.
* src/glade-clipboard-view.c (glade_clipboard_view_construct): use
named constants instead of "magic numbers" for the height and width of
the clipboard view window.
* src/glade-project-window.c (gpw_create_widget_tree): don't use magic
numbers for gtk_window_set_default_size(). Use named constants.
* src/glade-placeholder.c (glade_placeholder_button_press): since
we can, why not extract the GladeProject for calling
glade_command_create instead of leave it to glade_command_create to get
project.
(glade_placeholder_button_press): reset palette here. No need to do it
in glade_command_create.
* src/glade-command.c (glade_command_cut): notify the user if user
tries to cut a widget which is internal to a composite widget.
(glade_command_copy): likewise.
(glade_command_delete): likewise.
2004-12-16 Archit Baweja <bighead@users.sourceforge.net>
* widgets/gtk-obsolete.xml: added entry for GtkFileSelection

View File

@ -29,6 +29,9 @@
#include "glade-widget-class.h"
const gint GLADE_CLIPBOARD_VIEW_WIDTH = 230;
const gint GLADE_CLIPBOARD_VIEW_HEIGHT = 200;
static void
glade_clipboard_view_class_init (GladeClipboardViewClass *class)
{
@ -189,7 +192,10 @@ glade_clipboard_view_construct (GladeClipboardView *view)
gtk_container_add (GTK_CONTAINER (scrolled_window), view->widget);
gtk_container_add (GTK_CONTAINER (view), scrolled_window);
gtk_window_set_default_size (GTK_WINDOW (view), 272, 130);
gtk_window_set_default_size (GTK_WINDOW (view),
GLADE_CLIPBOARD_VIEW_WIDTH,
GLADE_CLIPBOARD_VIEW_HEIGHT);
gtk_window_set_type_hint (GTK_WINDOW (view), GDK_WINDOW_TYPE_HINT_UTILITY);
gtk_widget_show_all (scrolled_window);

View File

@ -93,7 +93,7 @@ glade_clipboard_new (void)
* @widget: a #GladeWidget
*
* Adds @widget to @clipboard.
* This increses the reference count of @widget.
* This increases the reference count of @widget.
*/
void
glade_clipboard_add (GladeClipboard *clipboard, GladeWidget *widget)

View File

@ -306,7 +306,7 @@ glade_command_set_property_execute (GladeCommand *cmd)
GladeCommandSetProperty* me = (GladeCommandSetProperty*) cmd;
GValue new_value = { 0, };
g_return_val_if_fail (me != NULL, TRUE);
g_return_val_if_fail (me != NULL, FALSE);
g_value_init (&new_value, G_VALUE_TYPE (me->arg_value));
g_value_copy (me->arg_value, &new_value);
@ -408,8 +408,12 @@ glade_command_set_property (GladeProperty *property, const GValue* pvalue)
g_assert (cmd->description);
g_free (value_name);
glade_command_set_property_execute (GLADE_COMMAND (me));
glade_command_push_undo (gwidget->project, GLADE_COMMAND (me));
/* Push onto undo stack only if it executes successfully. */
if (glade_command_set_property_execute (GLADE_COMMAND (me)))
glade_command_push_undo (gwidget->project, GLADE_COMMAND (me));
else
/* No leaks on my shift! */
g_object_unref (G_OBJECT (me));
}
/**************************************************/
@ -536,8 +540,10 @@ glade_command_set_name (GladeWidget *widget, const gchar* name)
g_debug(("Pushing: %s\n", cmd->description));
glade_command_set_name_execute (GLADE_COMMAND (me));
glade_command_push_undo (widget->project, GLADE_COMMAND (me));
if (glade_command_set_name_execute (GLADE_COMMAND (me)))
glade_command_push_undo (widget->project, GLADE_COMMAND (me));
else
g_object_unref (G_OBJECT (me));
}
/***************************************************
@ -677,14 +683,16 @@ glade_command_create_delete_common (GladeWidget *widget,
me->create = create;
me->placeholder = placeholder;
cmd->description =
g_strdup_printf (_("%s %s"), create ?
"Create" : "Delete", widget->name);
g_strdup_printf ("%s %s", (create ? _("Create") : _("Delete")),
widget->name);
if (placeholder)
g_object_ref (G_OBJECT (placeholder));
if (glade_command_create_delete_execute (GLADE_COMMAND (me)));
if (glade_command_create_delete_execute (GLADE_COMMAND (me)))
glade_command_push_undo (widget->project, GLADE_COMMAND (me));
else
g_object_unref (G_OBJECT (me));
}
/**
@ -698,42 +706,36 @@ glade_command_delete (GladeWidget *widget)
{
g_return_if_fail (GLADE_IS_WIDGET (widget));
/* internal children cannot be deleted. Should we notify the user? */
/* internal children cannot be deleted. Notify the user. */
if (widget->internal)
{
glade_util_ui_warn (glade_project_window_get()->window, _("You cannot delete a widget internal to a composite widget."));
return;
}
glade_command_create_delete_common (widget, NULL, FALSE);
}
/**
* Creates a new widget. In placeholder we expect the placeholder that will
* be substituted by the new widget (if any), and in project the project that
* the new widget will be assigned to (if NULL, the project will be extracted
* from the placeholder).
*/
/**
* glade_command_create:
* @class:
* @placeholder:
* @project:
* @class: the class of the widget (GtkWindow or GtkButton)
* @placeholder: the placeholder which will be substituted by the widget
* @project: the project his widget belongs to.
*
* TODO: write me
* Creates a new widget of @class and put in place of the @placeholder
* in the @project
*/
void
glade_command_create (GladeWidgetClass *class,
GladePlaceholder *placeholder,
GladeProject *project)
{
GladeProjectWindow *gpw;
GladeWidget *widget;
GladeWidget *parent = NULL;
g_return_if_fail (GLADE_IS_WIDGET_CLASS (class));
g_return_if_fail (placeholder != NULL || GLADE_IS_PROJECT (project));
gpw = glade_project_window_get ();
g_return_if_fail (GLADE_IS_PALETTE (gpw->palette));
if (placeholder)
{
parent = glade_util_get_parent (GTK_WIDGET (placeholder));
@ -750,9 +752,6 @@ glade_command_create (GladeWidgetClass *class,
return;
glade_command_create_delete_common (widget, placeholder, TRUE);
/* reset the palette */
glade_palette_unselect_widget (gpw->palette);
}
typedef enum {
@ -975,6 +974,8 @@ glade_command_cut_copy_paste_common (GladeWidget *widget,
*/
if (glade_command_cut_copy_paste_execute (cmd))
glade_command_push_undo (project, cmd);
else
g_object_unref (G_OBJECT (me));
}
/**
@ -992,7 +993,8 @@ glade_command_paste (GladePlaceholder *placeholder)
gpw = glade_project_window_get ();
if (!placeholder) {
if (!placeholder)
{
glade_util_ui_warn (gpw->window, _("Placeholder not selected!"));
return;
}
@ -1020,16 +1022,20 @@ glade_command_cut (GladeWidget *widget)
gpw = glade_project_window_get ();
if (!widget) {
if (!widget)
{
glade_util_ui_warn (gpw->window, _("No widget selected!"));
return;
}
g_return_if_fail (GLADE_IS_WIDGET (widget));
/* internal children cannot be cut. Should we notify the user? */
/* internal children cannot be cut. Notify the user. */
if (widget->internal)
{
glade_util_ui_warn (gpw->window, _("You cannot cut a widget internal to a composite widget."));
return;
}
glade_command_cut_copy_paste_common (widget, NULL, widget->project, GLADE_CUT);
}
@ -1047,16 +1053,20 @@ glade_command_copy (GladeWidget *widget)
gpw = glade_project_window_get ();
if (!widget) {
if (!widget)
{
glade_util_ui_warn (gpw->window, _("No widget selected!"));
return;
}
g_return_if_fail (GLADE_IS_WIDGET (widget));
/* internal children cannot be cut. Should we notify the user? */
/* internal children cannot be copied. Notify the user */
if (widget->internal)
{
glade_util_ui_warn (gpw->window, _("You cannot copy a widget internal to a composite widget."));
return;
}
glade_command_cut_copy_paste_common (widget, NULL, widget->project, GLADE_COPY);
}
@ -1149,6 +1159,8 @@ glade_command_add_remove_signal (GladeWidget *glade_widget, const GladeSignal *s
if (glade_command_add_signal_execute (cmd))
glade_command_push_undo (glade_widget->project, cmd);
else
g_object_unref (G_OBJECT (me));
}
/**

View File

@ -44,9 +44,6 @@
#include "glade-project.h"
#include "glade-utils.h"
static void glade_editor_class_init (GladeEditorClass *class);
static void glade_editor_init (GladeEditor *editor);
enum
{
ADD_SIGNAL,
@ -58,47 +55,10 @@ static guint glade_editor_signals[LAST_SIGNAL] = {0};
static GtkNotebookClass *parent_class = NULL;
/* We use this function recursively so we need to declare it */
static gboolean glade_editor_table_append_items (GladeEditorTable *table,
GladeWidgetClass *class,
GList **list,
GladeEditorTableType type);
static void glade_editor_property_load (GladeEditorProperty *property, GladeWidget *widget);
static void glade_editor_property_load_flags (GladeEditorProperty *property);
/**
* glade_editor_get_type:
*
* Creates the typecode for the #GladeEditor object type.
*
* Returns: the typecode for the #GladeEditor object type
*/
GType
glade_editor_get_type (void)
{
static GType type = 0;
if (!type) {
static const GTypeInfo info = {
sizeof (GladeEditorClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) glade_editor_class_init,
(GClassFinalizeFunc) NULL,
NULL,
sizeof (GladeEditor),
0,
(GInstanceInitFunc) glade_editor_init
};
type = g_type_register_static (GTK_TYPE_NOTEBOOK, "GladeEditor", &info, 0);
}
return type;
}
static void
glade_editor_class_init (GladeEditorClass *class)
{
@ -169,6 +129,37 @@ glade_editor_init (GladeEditor *editor)
editor->loading = FALSE;
}
/**
* glade_editor_get_type:
*
* Creates the typecode for the #GladeEditor object type.
*
* Returns: the typecode for the #GladeEditor object type
*/
GType
glade_editor_get_type (void)
{
static GType type = 0;
if (!type) {
static const GTypeInfo info = {
sizeof (GladeEditorClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) glade_editor_class_init,
(GClassFinalizeFunc) NULL,
NULL,
sizeof (GladeEditor),
0,
(GInstanceInitFunc) glade_editor_init
};
type = g_type_register_static (GTK_TYPE_NOTEBOOK, "GladeEditor", &info, 0);
}
return type;
}
/**
* glade_editor_new:
*
@ -214,14 +205,18 @@ glade_editor_widget_name_changed (GtkWidget *editable, GladeEditor *editor)
/* ============================ Property Changed ============================ */
static void
glade_editor_property_changed_text_common (GladeProperty *property,
const gchar *text)
const gchar *text,
gboolean from_query_dialog)
{
GValue val = { 0, };
g_value_init (&val, G_TYPE_STRING);
g_value_set_string (&val, text);
glade_command_set_property (property, &val);
if (from_query_dialog == TRUE)
glade_property_set (property, &val);
else
glade_command_set_property (property, &val);
g_value_unset (&val);
}
@ -239,7 +234,8 @@ glade_editor_property_changed_text (GtkWidget *entry,
text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
glade_editor_property_changed_text_common (property->property, text);
glade_editor_property_changed_text_common (property->property, text,
property->from_query_dialog);
g_free (text);
@ -265,7 +261,8 @@ glade_editor_property_changed_text_view (GtkTextBuffer *buffer,
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
glade_editor_property_changed_text_common (property->property, text);
glade_editor_property_changed_text_common (property->property, text,
property->from_query_dialog);
g_free (text);
@ -292,7 +289,11 @@ glade_editor_property_changed_enum (GtkWidget *menu_item,
g_value_init (&val, gproperty->class->pspec->value_type);
g_value_set_enum (&val, ival);
glade_command_set_property (gproperty, &val);
if (property->from_query_dialog)
glade_property_set (gproperty, &val);
else
glade_command_set_property (gproperty, &val);
g_value_unset (&val);
@ -379,7 +380,10 @@ glade_editor_property_changed_numeric (GtkWidget *spin,
g_warning ("Unsupported type %s\n",
g_type_name(property->class->pspec->value_type));
glade_command_set_property (property->property, &val);
if (property->from_query_dialog)
glade_property_set (property->property, &val);
else
glade_command_set_property (property->property, &val);
g_value_unset (&val);
@ -406,7 +410,11 @@ glade_editor_property_changed_boolean (GtkWidget *button,
g_value_init (&val, G_TYPE_BOOLEAN);
g_value_set_boolean (&val, state);
glade_command_set_property (property->property, &val);
if (property->from_query_dialog)
glade_property_set (property->property, &val);
else
glade_command_set_property (property->property, &val);
g_value_unset (&val);
@ -434,7 +442,11 @@ glade_editor_property_changed_unichar (GtkWidget *entry,
g_value_init (&val, G_TYPE_UINT);
g_value_set_uint (&val, unich);
glade_command_set_property (property->property, &val);
if (property->from_query_dialog)
glade_property_set (property->property, &val);
else
glade_command_set_property (property->property, &val);
g_value_unset (&val);
g_free (text);
@ -627,7 +639,12 @@ glade_editor_property_show_flags_dialog (GtkWidget *entry,
g_value_init (&val, G_VALUE_TYPE (property->property->value));
g_value_set_flags (&val, new_value);
glade_command_set_property (property->property, &val);
if (property->from_query_dialog)
glade_property_set (property->property, &val);
else
glade_command_set_property (property->property, &val);
g_value_unset (&val);
/* Update the entry in the property editor. */
@ -921,7 +938,8 @@ glade_editor_append_item_real (GladeEditorTable *table,
static GladeEditorProperty *
glade_editor_table_append_item (GladeEditorTable *table,
GladePropertyClass *class)
GladePropertyClass *class,
gboolean from_query_dialog)
{
GladeEditorProperty *property;
@ -930,9 +948,12 @@ glade_editor_table_append_item (GladeEditorTable *table,
property->class = class;
property->children = NULL;
/* Set this before creating the widget. */
property->from_query_dialog = from_query_dialog;
property->input = glade_editor_append_item_real (table, property);
property->property = NULL;
return property;
}
@ -996,7 +1017,11 @@ glade_editor_table_append_items (GladeEditorTable *table,
else if (type == TABLE_TYPE_COMMON && property_class->common == FALSE)
continue;
property = glade_editor_table_append_item (table, property_class);
if (type == TABLE_TYPE_QUERY)
property = glade_editor_table_append_item (table, property_class, TRUE);
else
property = glade_editor_table_append_item (table, property_class, FALSE);
if (property != NULL)
new_list = g_list_prepend (new_list, property);
}
@ -1532,7 +1557,7 @@ glade_editor_load_packing_page (GladeEditor *editor, GladeWidget *widget)
continue;
g_assert (property_class->packing == TRUE);
editor_property = glade_editor_table_append_item (table, property_class);
editor_property = glade_editor_table_append_item (table, property_class, FALSE);
old_props = g_list_prepend (old_props, editor_property);
glade_editor_property_load (editor_property, widget);
}
@ -1635,43 +1660,54 @@ glade_editor_add_signal (GladeEditor *editor,
widget_name, widget_type, signal_id, callback_name);
}
void
glade_editor_query_popup (GladeEditor *editor, GladeWidget *widget)
gboolean
glade_editor_query_dialog (GladeEditor *editor, GladeWidget *widget)
{
GtkWidget *dialog;
GladeEditorTable *table;
gchar *title;
GList *list;
GladeEditorProperty *property;
gint answer;
gboolean retval = TRUE;
title = g_strdup_printf (_("Create a %s"), widget->widget_class->name);
dialog = gtk_dialog_new_with_buttons
(title, NULL,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT |
GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
GTK_DIALOG_NO_SEPARATOR,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
g_free (title);
table = glade_editor_get_table_from_class (editor,
widget->widget_class,
TABLE_TYPE_QUERY);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table->table_widget,
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
table->table_widget,
TRUE, TRUE, 4);
for (list = table->properties; list; list = list->next)
{
property = list->data;
glade_editor_property_load (property, widget);
}
gtk_window_set_default_size (GTK_WINDOW(dialog), 300, -1);
answer = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_dialog_run (GTK_DIALOG (dialog));
/*
* If user cancel's we cancel the whole "create operation" by
* return FALSE. glade_widget_new() will see the FALSE, and
* take care of canceling the "create" operation.
*/
if (answer == GTK_RESPONSE_CANCEL)
retval = FALSE;
gtk_container_remove (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
table->table_widget);
gtk_widget_destroy (dialog);
return retval;
}

View File

@ -163,8 +163,8 @@ struct _GladeEditorTable
struct _GladeEditorProperty
{
GladePropertyClass *class; /* The class this property
* corresponds to.
*/
* corresponds to.
*/
GladeProperty *property; /* The loaded GladeProperty
*/
@ -185,6 +185,10 @@ struct _GladeEditorProperty
GList *children; /* Used for class->type = OBJECT. Where a sigle entry corresponds
* to a number of inputs
*/
gboolean from_query_dialog; /* If this input is part of a query dialog
* this is TRUE.
*/
};
GType glade_editor_get_type (void);
@ -194,7 +198,8 @@ GladeEditor *glade_editor_new (void);
void glade_editor_load_widget (GladeEditor *editor, GladeWidget *widget);
void glade_editor_add_signal (GladeEditor *editor, guint id_signal, const char *callback_name);
void glade_editor_update_widget_name (GladeEditor *editor);
void glade_editor_query_popup (GladeEditor *editor, GladeWidget *widget);
gboolean glade_editor_query_dialog (GladeEditor *editor, GladeWidget *widget);
G_END_DECLS

View File

@ -26,6 +26,7 @@
#include "glade-project-window.h"
#include "glade-project.h"
#include "glade-command.h"
#include "glade-palette.h"
#include "glade-popup.h"
#include "glade-cursor.h"
#include "glade-widget.h"
@ -298,28 +299,32 @@ glade_placeholder_button_press (GtkWidget *widget, GdkEventButton *event)
{
GladeProjectWindow *gpw;
GladePlaceholder *placeholder;
GladeProject *project;
g_return_val_if_fail (GLADE_IS_PLACEHOLDER (widget), FALSE);
gpw = glade_project_window_get ();
placeholder = GLADE_PLACEHOLDER (widget);
project = glade_placeholder_get_project (placeholder);
if (!GTK_WIDGET_HAS_FOCUS (widget))
gtk_widget_grab_focus (widget);
if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
{
if (gpw->add_class != NULL) {
if (gpw->add_class != NULL)
{
/* A widget type is selected in the palette.
* Add a new widget of that type.
*/
glade_command_create (gpw->add_class, placeholder, NULL);
glade_command_create (gpw->add_class, placeholder,
project);
/* reset the palette */
glade_palette_unselect_widget (gpw->palette);
}
else
{
GladeProject *project;
project = glade_placeholder_get_project (placeholder);
glade_project_selection_set (project, GTK_WIDGET (placeholder), TRUE);
}
}

View File

@ -47,6 +47,8 @@
#include <gtk/gtkstock.h>
const gchar *WINDOW_TITLE = "Glade-3 GUI Builder";
const gint GLADE_WIDGET_TREE_WIDTH = 230;
const gint GLADE_WIDGET_TREE_HEIGHT = 300;
static void
gpw_refresh_title (GladeProjectWindow *gpw)
@ -715,7 +717,9 @@ gpw_create_widget_tree (GladeProjectWindow *gpw)
GtkWidget *widget_tree_item;
widget_tree = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (widget_tree), 230, 300);
gtk_window_set_default_size (GTK_WINDOW (widget_tree),
GLADE_WIDGET_TREE_WIDTH,
GLADE_WIDGET_TREE_HEIGHT);
gtk_window_set_title (GTK_WINDOW (widget_tree), _("Widget Tree"));
view = glade_project_view_new (GLADE_PROJECT_VIEW_TREE);

View File

@ -618,13 +618,10 @@ glade_project_selection_add (GladeProject *project,
GtkWidget *widget,
gboolean emit_signal)
{
GladeProjectWindow *gpw;
gboolean has_nodes;
g_return_if_fail (GLADE_IS_PROJECT (project));
g_return_if_fail (GTK_IS_WIDGET (widget));
gpw = glade_project_window_get ();
if (glade_util_has_nodes (widget))
return;
@ -653,12 +650,9 @@ glade_project_selection_set (GladeProject *project,
GtkWidget *widget,
gboolean emit_signal)
{
GladeProjectWindow *gpw;
g_return_if_fail (GLADE_IS_PROJECT (project));
g_return_if_fail (GTK_IS_WIDGET (widget));
gpw = glade_project_window_get ();
if (glade_util_has_nodes (widget))
return;

View File

@ -124,7 +124,7 @@ struct _GladePropertyClass
gboolean optional; /* Some properties are optional by nature like
* default width. It can be set or not set. A
* default property has a check box in the
* left that enables/disables de input
* left that enables/disables the input
*/
gboolean optional_default; /* For optional values, what the default is */

View File

@ -450,7 +450,7 @@ glade_widget_internal_new (GladeWidgetClass *klass, GladeProject *project, Glade
NULL);
g_free (widget_name);
return (GladeWidget *) glade_widget;
return GLADE_WIDGET (glade_widget);
}
/**
@ -472,7 +472,10 @@ glade_widget_new (GladeWidgetClass *klass, GladeProject *project)
if (widget->query_user)
{
GladeProjectWindow *gpw = glade_project_window_get ();
glade_editor_query_popup (gpw->editor, widget);
/* If user pressed cancel on query popup. */
if (!glade_editor_query_dialog (gpw->editor, widget))
return NULL;
}
/* Properties that have custom set_functions on them need to be

View File

@ -16,7 +16,7 @@
<GetFunction>ignore</GetFunction>
</Property>
<Property Id="label" Default="button"/>
<Property Id="label" Default="button"/>
</Properties>