Implemented glade_editor_query_popup(), also obsoleted common & packing

2004-10-28  Tristan Van Berkom  <tristan.van.berkom@gmail.com>

        * src/glade-editor.[ch]: Implemented glade_editor_query_popup(), also obsoleted
          common & packing booleans for a more convenient GladeEditorTableType field.

        * src/glade-gtk.c:
          - Refitted and integrated Mickael Cornet's patch to bug 153823
          - glade_gtk_table_set_n_common() now refuses to shrink when it involves
            orhpaning widgets, Its also been improved to fill in all the blanks.
          - Removed all dialogs.
          - Fixed children are now born with size-request properties enabled.
          - Removed some `#if 0' code that I trust we dont need.
          - glade_gtk_box_set_size() Adjusted to match gtk_table behaviour

        * src/glade-plugin.h:
          - Added a header to the batch.

        * src/glade-popup.c: glade_popup_copy_cb() now duplicates the
          widget in question with glade_widget_dup().

        * src/glade-property-class.[ch]: glade_property_class_update_from_node() now
          flags properties that need a pupop dialog at creation time.

        * src/glade-property.[ch]: Implemented glade_property_sync() (Sychronizes
          the object with its glade_property), glade_property_set() now calls
          glade_property_sync().

        * src/glade-widget.[ch]:
          - Implemented glade_widget_dup().
          - Added call to glade_property_sync on appropriate properties that
            need to be synchronized after a glade_widget_rebuild().
          - Added a call to glade_editor_query_popup() in the appropriate situation.
          - glade_widget_build_object() now takes into account property_class default values
          - glade_widget_new() now calls new function glade_widget_sync_query_props() in
            popup cases (If properties dont change from there default, a synchronization is
            needed at this point).
        * widgets/gtkbox.xml:
          - Removed reference to obsoleted post_create function.
          - Changed `ignore' to `empty' for the fill_empty funciton.
          - Tagged "Size" property as type "Query".
          - Added Default size 3
          - Changed Minimum size to 2

        * widgets/gtknotebook.xml:
          - Tagged "pages" property as type "Query".
          - Removed obsolete (or never implemented) Query section.

        * widgets/gtktable.xml:
          - Tagged "n-rows" and "n-columns" properties as type "Query".
          - Removed obsolete (or never implemented) Query section.

        * widgets/gtklabel.xml: Added default "" value for pattern property, this
          works around gtk+ bug 156720 which was causing us segfaults.
This commit is contained in:
Tristan Van Berkom 2004-10-28 18:35:30 +00:00 committed by David Hoover
parent 8bbe96b0b0
commit d718761fc7
14 changed files with 504 additions and 324 deletions

View File

@ -1,3 +1,58 @@
2004-10-28 Tristan Van Berkom <tristan.van.berkom@gmail.com>
* src/glade-editor.[ch]: Implemented glade_editor_query_popup(), also obsoleted
common & packing booleans for a more convenient GladeEditorTableType field.
* src/glade-gtk.c:
- Refitted and integrated Mickael Cornet's patch to bug 153823
- glade_gtk_table_set_n_common() now refuses to shrink when it involves
orhpaning widgets, Its also been improved to fill in all the blanks.
- Removed all dialogs.
- Fixed children are now born with size-request properties enabled.
- Removed some `#if 0' code that I trust we dont need.
- glade_gtk_box_set_size() Adjusted to match gtk_table behaviour
* src/glade-plugin.h:
- Added a header to the batch.
* src/glade-popup.c: glade_popup_copy_cb() now duplicates the
widget in question with glade_widget_dup().
* src/glade-property-class.[ch]: glade_property_class_update_from_node() now
flags properties that need a pupop dialog at creation time.
* src/glade-property.[ch]: Implemented glade_property_sync() (Sychronizes
the object with its glade_property), glade_property_set() now calls
glade_property_sync().
* src/glade-widget.[ch]:
- Implemented glade_widget_dup().
- Added call to glade_property_sync on appropriate properties that
need to be synchronized after a glade_widget_rebuild().
- Added a call to glade_editor_query_popup() in the appropriate situation.
- glade_widget_build_object() now takes into account property_class default values
- glade_widget_new() now calls new function glade_widget_sync_query_props() in
popup cases (If properties dont change from there default, a synchronization is
needed at this point).
* widgets/gtkbox.xml:
- Removed reference to obsoleted post_create function.
- Changed `ignore' to `empty' for the fill_empty funciton.
- Tagged "Size" property as type "Query".
- Added Default size 3
- Changed Minimum size to 2
* widgets/gtknotebook.xml:
- Tagged "pages" property as type "Query".
- Removed obsolete (or never implemented) Query section.
* widgets/gtktable.xml:
- Tagged "n-rows" and "n-columns" properties as type "Query".
- Removed obsolete (or never implemented) Query section.
* widgets/gtklabel.xml: Added default "" value for pattern property, this
works around gtk+ bug 156720 which was causing us segfaults.
2004-10-27 David Hoover <karma@deadmoose.com>
* src/Makefile.am: Fix up dependency issues with automatically generated

View File

@ -63,7 +63,7 @@ static GtkNotebookClass *parent_class = NULL;
static gboolean glade_editor_table_append_items (GladeEditorTable *table,
GladeWidgetClass *class,
GList **list,
gboolean common);
GladeEditorTableType type);
static void glade_editor_property_load_flags (GladeEditorProperty *property);
@ -839,7 +839,7 @@ glade_editor_create_input_object (GladeEditorProperty *property,
g_return_val_if_fail (GLADE_IS_EDITOR_PROPERTY (property), NULL);
glade_editor_table_append_items (table, property->class->child,
&property->children, FALSE);
&property->children, TABLE_TYPE_GENERAL);
return NULL;
}
@ -1004,7 +1004,7 @@ static gboolean
glade_editor_table_append_items (GladeEditorTable *table,
GladeWidgetClass *class,
GList **list_,
gboolean common)
GladeEditorTableType type)
{
GladeEditorProperty *property;
GladePropertyClass *property_class;
@ -1018,17 +1018,20 @@ glade_editor_table_append_items (GladeEditorTable *table,
for (; list != NULL; list = list->next)
{
property_class = (GladePropertyClass *) list->data;
if (!glade_property_class_is_visible (property_class, class))
continue;
if (common != property_class->common)
if (type == TABLE_TYPE_QUERY && property_class->query == FALSE)
continue;
else if (type == TABLE_TYPE_COMMON && property_class->common == FALSE)
continue;
property = glade_editor_table_append_item (table, property_class);
if (property != NULL)
new_list = g_list_prepend (new_list, property);
}
*list_ = new_list;
return TRUE;
}
@ -1068,13 +1071,15 @@ glade_editor_table_new (void)
gtk_table_set_row_spacings (GTK_TABLE (table->table_widget),
GLADE_PROPERY_TABLE_ROW_SPACING);
g_object_ref (G_OBJECT(table->table_widget));
return table;
}
static GladeEditorTable *
glade_editor_table_create (GladeEditor *editor,
GladeWidgetClass *class,
gboolean common)
GladeEditorTableType type)
{
GladeEditorTable *table;
@ -1084,15 +1089,16 @@ glade_editor_table_create (GladeEditor *editor,
table = glade_editor_table_new ();
table->editor = editor;
table->glade_widget_class = class;
table->common = common;
if (!common)
table->type = type;
if (type == TABLE_TYPE_GENERAL)
glade_editor_table_append_standard_fields (table);
if (!glade_editor_table_append_items (table, class, &table->properties, common))
if (!glade_editor_table_append_items (table, class,
&table->properties, type))
return NULL;
/* Hack: We don't have currently a way to put a "Edit Menus..." button through the
* xml files. */
if (!common && !strcmp (class->name, "GtkMenuBar")) {
if (type == TABLE_TYPE_GENERAL && !strcmp (class->name, "GtkMenuBar")) {
GtkWidget *edit_menu_button = gtk_button_new_with_label (_("Edit Menus..."));
g_signal_connect (G_OBJECT (edit_menu_button), "clicked",
@ -1104,7 +1110,6 @@ glade_editor_table_create (GladeEditor *editor,
}
gtk_widget_show_all (table->table_widget);
editor->widget_tables = g_list_prepend (editor->widget_tables, table);
return table;
}
@ -1112,7 +1117,7 @@ glade_editor_table_create (GladeEditor *editor,
static GladeEditorTable *
glade_editor_get_table_from_class (GladeEditor *editor,
GladeWidgetClass *class,
gboolean common)
GladeEditorTableType type)
{
GladeEditorTable *table;
GList *list;
@ -1120,15 +1125,17 @@ glade_editor_get_table_from_class (GladeEditor *editor,
for (list = editor->widget_tables; list; list = list->next)
{
table = list->data;
if (common != table->common)
if (type != table->type)
continue;
if (table->glade_widget_class == class)
return table;
}
table = glade_editor_table_create (editor, class, common);
table = glade_editor_table_create (editor, class, type);
g_return_val_if_fail (table != NULL, NULL);
editor->widget_tables = g_list_prepend (editor->widget_tables, table);
return table;
}
@ -1601,15 +1608,15 @@ glade_editor_load_packing_page (GladeEditor *editor, GladeWidget *widget)
/* Now add the new properties */
table = glade_editor_table_new ();
table->editor = editor;
table->common = FALSE;
table->packing = TRUE;
table->type = TABLE_TYPE_PACKING;
for (ancestor = parent; ancestor != NULL; ancestor = glade_widget_get_parent (ancestor))
{
for (list = ancestor->widget_class->child_properties; list; list = list->next)
{
property_class = list->data;
if (!ancestor->widget_class->child_property_applies (ancestor->widget, widget->widget, property_class->id))
if (!ancestor->widget_class->child_property_applies
(ancestor->widget, widget->widget, property_class->id))
continue;
g_assert (property_class->packing == TRUE);
@ -1715,3 +1722,44 @@ glade_editor_add_signal (GladeEditor *editor,
glade_editor_signals [ADD_SIGNAL], 0,
widget_name, widget_type, signal_id, callback_name);
}
void
glade_editor_query_popup (GladeEditor *editor, GladeWidget *widget)
{
GtkWidget *dialog;
GladeEditorTable *table;
gchar *title;
GList *list;
GladeEditorProperty *property;
title = g_strdup_printf ("%s %s", _("Create a"), 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);
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,
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);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_container_remove (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
table->table_widget);
gtk_widget_destroy (dialog);
}

View File

@ -17,11 +17,20 @@ G_BEGIN_DECLS
#define GLADE_EDITOR_PROPERTY(p) ((GladeEditorProperty *)p)
#define GLADE_IS_EDITOR_PROPERTY(p) (p != NULL)
typedef struct _GladeEditorClass GladeEditorClass;
typedef struct _GladeEditorTable GladeEditorTable;
typedef struct _GladeEditorProperty GladeEditorProperty;
typedef struct _GladeEditorClass GladeEditorClass;
typedef struct _GladeEditorTable GladeEditorTable;
typedef struct _GladeEditorProperty GladeEditorProperty;
typedef enum _GladeEditorTableType GladeEditorTableType;
enum _GladeEditorTableType
{
TABLE_TYPE_GENERAL,
TABLE_TYPE_COMMON,
TABLE_TYPE_PACKING,
TABLE_TYPE_QUERY
};
/* The GladeEditor is a window that is used to display and modify widget
* properties. The glade editor contains the details of the selected
* widget for the selected project
@ -141,10 +150,9 @@ struct _GladeEditorTable
* corrsponding GladeEditorProperty struct.
*/
gboolean common; /* Is this table to be used in the common tab ?
* or the general tab ?
*/
gboolean packing;
GladeEditorTableType type; /* Is this table to be used in the common tab, ?
* the general tab, a packing tab or the query popup ?
*/
gint rows;
};
@ -192,6 +200,7 @@ 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);
G_END_DECLS

View File

@ -313,8 +313,8 @@ glade_gtk_box_set_size (GObject *object, GValue *value)
{
GladeWidget *widget;
GtkBox *box;
gint new_size;
gint old_size;
GList *child;
gint new_size, old_size, i;
box = GTK_BOX (object);
g_return_if_fail (GTK_IS_BOX (box));
@ -325,44 +325,31 @@ glade_gtk_box_set_size (GObject *object, GValue *value)
old_size = g_list_length (box->children);
new_size = g_value_get_int (value);
if (new_size == old_size)
return;
if (new_size > old_size)
/* Ensure placeholders first...
*/
for (i = 0; i < new_size; i++)
{
/* The box has grown. Add placeholders */
while (new_size > old_size)
{
GladePlaceholder *placeholder =
GLADE_PLACEHOLDER (glade_placeholder_new ());
gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (placeholder));
old_size++;
}
}
else
{
/* new_size < old_size */
/* The box has shrunk. Remove the widgets that are on those slots */
GList *child = g_list_last (box->children);
while (child && old_size > new_size)
{
GtkWidget *child_widget = ((GtkBoxChild *) (child->data))->widget;
GladeWidget *glade_widget;
glade_widget = glade_widget_get_from_gtk_widget (child_widget);
if (glade_widget) /* it may be NULL, e.g a placeholder */
glade_project_remove_widget
(glade_widget->project, child_widget);
gtk_container_remove (GTK_CONTAINER (box), child_widget);
child = g_list_last (box->children);
old_size--;
}
if (i + 1 < g_list_length(box->children))
continue;
gtk_container_add (GTK_CONTAINER (box),
GTK_WIDGET (glade_placeholder_new ()));
}
g_object_set_data (object, "glade_nb_placeholders", GINT_TO_POINTER (new_size));
/* The box has shrunk. Remove the widgets that are on those slots */
for (child = g_list_last (box->children);
child && old_size > new_size;
child = g_list_last (box->children), old_size--)
{
GtkWidget *child_widget = ((GtkBoxChild *) (child->data))->widget;
GladeWidget *glade_widget;
glade_widget = glade_widget_get_from_gtk_widget (child_widget);
if (glade_widget)
/* In this case, refuse to shrink */
break;
gtk_container_remove (GTK_CONTAINER (box), child_widget);
}
}
/**
@ -524,6 +511,44 @@ glade_gtk_notebook_set_n_pages (GObject *object, GValue *value)
}
}
static gboolean
glade_gtk_table_has_child (GtkTable *table,
guint left_attach,
guint right_attach,
guint top_attach,
guint bottom_attach)
{
GList *list;
for (list = table->children; list && list->data; list = list->next)
{
GtkTableChild *child = list->data;
if (child->left_attach == left_attach &&
child->right_attach == right_attach &&
child->top_attach == top_attach &&
child->bottom_attach == bottom_attach)
return TRUE;
}
return FALSE;
}
static gboolean
glade_gtk_table_widget_exceeds_bounds (GtkTable *table, gint n_rows, gint n_cols)
{
GList *list;
for (list = table->children; list && list->data; list = list->next)
{
GtkTableChild *child = list->data;
if (GLADE_IS_PLACEHOLDER(child->widget) == FALSE &&
(child->right_attach > n_cols ||
child->bottom_attach > n_rows))
return TRUE;
}
return FALSE;
}
/**
* glade_gtk_notebook_set_n_common:
* @object:
@ -546,46 +571,48 @@ glade_gtk_table_set_n_common (GObject *object, GValue *value, gboolean for_rows)
new_size = g_value_get_int (value);
old_size = for_rows ? table->nrows : table->ncols;
if (new_size == old_size)
return;
if (new_size < 1)
return;
if (glade_gtk_table_widget_exceeds_bounds
(table,
for_rows ? new_size : table->nrows,
for_rows ? table->ncols : new_size))
/* Refuse to shrink if it means orphaning widgets */
return;
widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (table));
g_return_if_fail (widget != NULL);
if (new_size > old_size) {
if (for_rows) {
gtk_table_resize (table, new_size, table->ncols);
if (for_rows)
gtk_table_resize (table, new_size, table->ncols);
else
gtk_table_resize (table, table->nrows, new_size);
for (i = 0; i < table->ncols; i++)
for (j = old_size; j < table->nrows; j++)
gtk_table_attach_defaults
(table, glade_placeholder_new (),
i, i + 1, j, j + 1);
} else {
gtk_table_resize (table, table->nrows, new_size);
for (i = 0; i < table->ncols; i++)
for (j = 0; j < table->nrows; j++)
if (glade_gtk_table_has_child
(table, i, i + 1, j, j + 1) == FALSE)
gtk_table_attach_defaults
(table, glade_placeholder_new (),
i, i + 1, j, j + 1);
for (i = old_size; i < table->ncols; i++)
for (j = 0; j < table->nrows; j++)
gtk_table_attach_defaults
(table, glade_placeholder_new (),
i, i + 1, j, j + 1);
}
} else {
if (new_size < old_size)
{
/* Remove from the bottom up */
GList *list = g_list_reverse
(g_list_copy (gtk_container_get_children (GTK_CONTAINER (table))));
GList *freeme = list;
for (; list; list = list->next) {
GList *list;
GList *list_to_free = NULL;
for (list = table->children; list && list->data; list = list->next)
{
GtkTableChild *child = list->data;
gint start = for_rows ? child->top_attach : child->left_attach;
gint end = for_rows ? child->bottom_attach : child->right_attach;
/* We need to completely remove it */
if (start >= new_size) {
gtk_container_remove (GTK_CONTAINER (table),
child->widget);
if (start >= new_size)
{
list_to_free = g_list_prepend (list_to_free, child->widget);
continue;
}
@ -596,17 +623,23 @@ glade_gtk_table_set_n_common (GObject *object, GValue *value, gboolean for_rows)
(GTK_CONTAINER (table), GTK_WIDGET (child),
for_rows ? "bottom_attach" : "right_attach",
new_size, NULL);
}
g_list_free (freeme);
if (list_to_free)
{
for (list = g_list_first(list_to_free);
list && list->data;
list = list->next)
{
gtk_container_remove (GTK_CONTAINER (table),
GTK_WIDGET(list->data));
}
g_list_free (list_to_free);
}
gtk_table_resize (table,
for_rows ? new_size : table->nrows,
for_rows ? table->ncols : new_size);
}
g_object_set_data (object, "glade_nb_placeholders",
GINT_TO_POINTER
(new_size * (for_rows ? table->ncols : table->nrows)));
}
/**
@ -780,17 +813,6 @@ ignore (GObject *object, GValue *value)
* rows/columns expect * the GtkTable to hold this number of placeholders, so
* we should add it
*/
/**
* glade_gtk_table_pre_create:
* @object:
*
* TODO: write me
*/
void GLADEGTK_API
glade_gtk_table_pre_create (GObject *object)
{
gtk_table_attach_defaults (GTK_TABLE (object), glade_placeholder_new (), 0, 1, 0, 1);
}
/**
* glade_gtk_tree_pre_create:
@ -821,82 +843,6 @@ glade_gtk_tree_view_pre_create (GObject *object)
}
/* ------------------------- Post Create functions ------------------------- */
static gint
ask_for_number (const gchar *title, const gchar *name, gint min, gint max, gint def)
{
gint number;
GtkWidget *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);
GtkWidget *label = gtk_label_new (name);
GtkWidget *spin_button = gtk_spin_button_new_with_range ((double) min, (double) max, 1.0);
GtkWidget *hbox = gtk_hbox_new (FALSE, 4);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spin_button), 0);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin_button), FALSE);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), (double) def);
gtk_box_pack_end (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
gtk_box_pack_end (GTK_BOX (hbox), label, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 12);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, TRUE, TRUE, 4);
gtk_widget_show_all (hbox);
/* even if the user destroys the dialog box, we retrieve the number and we accept it.
* I.e., this function never fails */
gtk_dialog_run (GTK_DIALOG (dialog));
number = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin_button));
gtk_widget_destroy (dialog);
return number;
}
/**
* glade_gtk_box_post_create:
* @object:
*
* TODO: write me
*/
void GLADEGTK_API
glade_gtk_box_post_create (GObject *object)
{
GladeProperty *property =
glade_widget_get_property
(glade_widget_get_from_gtk_widget (object), "size");
GValue value = {0,};
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, ask_for_number(_("Create a box"),
_("Number of items:"), 0, 10000, 3));
glade_property_set (property, &value);
}
/**
* glade_gtk_notebook_post_create:
* @object:
*
* TODO: write me
*/
void GLADEGTK_API
glade_gtk_notebook_post_create (GObject *object)
{
GValue value = {0,};
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, ask_for_number(_("Create a notebook"),
_("Number of pages:"), 0, 100, 3));
}
static gboolean
glade_gtk_fixed_button_press (GtkWidget *widget,
GdkEventButton *event,
@ -909,8 +855,13 @@ glade_gtk_fixed_button_press (GtkWidget *widget,
gpw = glade_project_window_get ();
if (gpw->add_class != NULL)
{
GtkWidget *placeholder = glade_placeholder_new ();
GList *selection;
GtkWidget *placeholder = glade_placeholder_new ();
GtkWidget *new_widget;
GladeWidget *new_gwidget;
GladeProperty *property;
GList *selection;
GValue value = { 0, };
/* A widget type is selected in the palette.
* Create a placeholder at the mouse position and
* add a new widget of that type with a default
@ -924,10 +875,26 @@ glade_gtk_fixed_button_press (GtkWidget *widget,
selection = glade_project_selection_get
(glade_project_window_get_active_project(gpw));
gtk_widget_set_size_request(GTK_WIDGET(selection->data),
FIXED_DEFAULT_CHILD_WIDTH,
FIXED_DEFAULT_CHILD_HEIGHT);
new_widget = GTK_WIDGET(selection->data);
new_gwidget = glade_widget_get_from_gtk_widget(new_widget);
g_value_init (&value, G_TYPE_INT);
property = glade_widget_get_property (new_gwidget, "width-request");
property->enabled = TRUE;
g_value_set_int (&value, FIXED_DEFAULT_CHILD_WIDTH);
glade_property_set (property, &value);
property = glade_widget_get_property (new_gwidget, "height-request");
property->enabled = TRUE;
g_value_set_int (&value, FIXED_DEFAULT_CHILD_HEIGHT);
glade_property_set (property, &value);
/* We need to resync the editor so that width-request/height-request
* are actualy enabled in the editor
*/
glade_editor_load_widget (gpw->editor, gpw->editor->loaded_widget);
}
return TRUE;
@ -971,74 +938,6 @@ glade_gtk_fixed_post_create (GObject *object)
G_CALLBACK(glade_gtk_fixed_button_press), NULL);
}
/**
* glade_gtk_table_post_create:
* @object:
*
* TODO: write me
*/
void GLADEGTK_API
glade_gtk_table_post_create (GObject *object)
{
GladeWidget *widget = glade_widget_get_from_gtk_widget (object);
GladeProperty *property_rows = glade_widget_get_property (widget, "n-rows");
GladeProperty *property_cols = glade_widget_get_property (widget, "n-columns");
GValue gvrows = {0,};
GValue gvcols = {0,};
GtkWidget *dialog =
gtk_dialog_new_with_buttons (_("Create a table"), NULL,
GTK_DIALOG_MODAL |
GTK_DIALOG_DESTROY_WITH_PARENT |
GTK_DIALOG_NO_SEPARATOR,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
GtkWidget *label_rows = gtk_label_new (_("Number of rows:"));
GtkWidget *label_cols = gtk_label_new (_("Number of columns:"));
GtkWidget *spin_button_rows = gtk_spin_button_new_with_range (0.0, 10000.0, 1.0);
GtkWidget *spin_button_cols = gtk_spin_button_new_with_range (0.0, 10000.0, 1.0);
GtkWidget *table = gtk_table_new (2, 2, TRUE);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
g_value_init (&gvrows, G_TYPE_INT);
g_value_init (&gvcols, G_TYPE_INT);
gtk_misc_set_alignment (GTK_MISC (label_rows), 0.0, 0.5);
gtk_misc_set_alignment (GTK_MISC (label_cols), 0.0, 0.5);
gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spin_button_rows), 0);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin_button_rows), FALSE);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button_rows), 3.0);
gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spin_button_cols), 0);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin_button_cols), FALSE);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button_cols), 3.0);
gtk_table_attach_defaults (GTK_TABLE (table), label_rows, 0, 1, 0, 1);
gtk_table_attach_defaults (GTK_TABLE (table), spin_button_rows, 1, 2, 0, 1);
gtk_table_attach_defaults (GTK_TABLE (table), label_cols, 0, 1, 1, 2);
gtk_table_attach_defaults (GTK_TABLE (table), spin_button_cols, 1, 2, 1, 2);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_container_set_border_width (GTK_CONTAINER (table), 12);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, TRUE, TRUE, 0);
gtk_widget_show_all (table);
/* even if the user destroys the dialog box, we retrieve the number and we accept it.
* I.e., this function never fails */
gtk_dialog_run (GTK_DIALOG (dialog));
g_value_set_int (&gvrows, gtk_spin_button_get_value_as_int
(GTK_SPIN_BUTTON (spin_button_rows)));
g_value_set_int (&gvcols, gtk_spin_button_get_value_as_int
(GTK_SPIN_BUTTON (spin_button_cols)));
glade_property_set (property_rows, &gvrows);
glade_property_set (property_cols, &gvcols);
gtk_widget_destroy (dialog);
}
/**
* glade_gtk_window_post_create:
* @object:
@ -1093,6 +992,7 @@ glade_gtk_dialog_post_create (GObject *object)
GTK_WIDGET (glade_placeholder_new ()), TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (dialog->action_area),
GTK_WIDGET (glade_placeholder_new ()), TRUE, TRUE, 0);
actionarea_widget =
glade_widget_new_for_internal_child
(child_class, vbox_widget, dialog->action_area, "action_area");
@ -1151,30 +1051,6 @@ glade_gtk_message_dialog_post_create (GObject *object)
}
#if 0
void GLADEGTK_API
glade_gtk_table_post_create (GObject *object)
{
GtkTable *table = GTK_TABLE (object);
GList *list;
g_return_if_fail (GTK_IS_TABLE (table));
list = table->children;
/* When we create a table and we are loading from disk a glade
* file, we need to add a placeholder because the size can't be
* 0 so gtk+ adds a widget that we don't want there.
* GtkBox does not have this problem because
* a size of 0x0 is the default one. Check if the size is 0
* and that we don't have a children.
*/
if (g_list_length (list) == 0) {
gtk_container_add (GTK_CONTAINER (table),
glade_placeholder_new ());
}
}
#endif
/* ------------------------ Replace child functions ------------------------ */
/**
* glade_gtk_container_replace_child:

View File

@ -7,6 +7,7 @@
#include "glade-project.h"
#include "glade-project-window.h"
#include "glade-command.h"
#include "glade-editor.h"
#include "glade-property.h"
#include "glade-property-class.h"
#include "glade-choice.h"

View File

@ -47,9 +47,11 @@ static void
glade_popup_copy_cb (GtkMenuItem *item, GladeWidget *widget)
{
GladeProjectWindow *gpw;
GladeWidget *dupped;
gpw = glade_project_window_get ();
dupped = glade_widget_dup (widget);
gpw = glade_project_window_get ();
glade_clipboard_add (gpw->clipboard, widget);
glade_clipboard_add (gpw->clipboard, dupped);
}
static void

View File

@ -855,6 +855,8 @@ glade_property_class_update_from_node (GladeXmlNode *node,
/* common, optional, etc */
class->common = glade_xml_get_property_boolean (node, GLADE_TAG_COMMON, FALSE);
class->optional = glade_xml_get_property_boolean (node, GLADE_TAG_OPTIONAL, FALSE);
class->query = glade_xml_get_property_boolean (node, GLADE_TAG_QUERY, FALSE);
if (class->optional)
class->optional_default = glade_xml_get_property_boolean (node, GLADE_TAG_OPTIONAL_DEFAULT, FALSE);

View File

@ -127,25 +127,32 @@ struct _GladePropertyClass
* a spin button entry. Also the default choice
* for a type == CHOICE
*/
GList *choices; /* list of GladeChoice items. This is only used
* for propeties of type GLADE_PROPERTY_TYPE_CHOICE
* and is NULL for other poperties.
* [See glade-choice.h]
*/
GType enum_type; /* If it is GLADE_PROPERTY_TYPE_ENUM or
* GLADE_PROPERTY_TYPE_FLAGS, this holds
* the GType of the enum or flags, otherwise it's 0.
*/
gboolean query; /* Whether we should explicitly ask the user about this property
* when instantiating a widget with this property (through a popup
* dialog).
*/
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
*/
gboolean optional_default; /* For optional values, what the default is */
gboolean optional_default; /* For optional values, what the default is */
gboolean construct_only; /* Whether this property is G_PARAM_CONSTRUCT_ONLY or not */
GladeWidgetClass *child; /* A GladeWidgetClass pointer of objects
* that we need to set for this widget
* for example : GtkSpinButton has a Adjustment inside

View File

@ -171,6 +171,26 @@ glade_property_set (GladeProperty *property, const GValue *value)
return;
}
/* Assign property first so that; if the object need be
* rebuilt, it will reflect the new value
*/
g_value_reset (property->value);
g_value_copy (value, property->value);
glade_property_sync(property);
}
/**
* glade_property_sync:
* @property: a #GladeProperty
*
* TODO: write me
*/
void
glade_property_sync (GladeProperty *property)
{
g_return_if_fail (GLADE_IS_PROPERTY (property));
if (!property->enabled)
return;
@ -179,15 +199,10 @@ glade_property_set (GladeProperty *property, const GValue *value)
property->loading = TRUE;
/* Assign property first so that; if the object need be
* rebuilt, it will reflect the new value
*/
g_value_reset (property->value);
g_value_copy (value, property->value);
if (property->class->set_function)
/* if there is a custom set_property, use it */
(*property->class->set_function) (G_OBJECT (property->widget->widget), value);
(*property->class->set_function) (G_OBJECT (property->widget->widget),
property->value);
else if (property->class->construct_only)
{
/* In the case of construct_only, the widget must be rebuilt, here we
@ -224,7 +239,7 @@ glade_property_set (GladeProperty *property, const GValue *value)
}
}
else
glade_property_set_property (property, value);
glade_property_set_property (property, property->value);
property->loading = FALSE;
}

View File

@ -46,6 +46,8 @@ void glade_property_free (GladeProperty *property);
void glade_property_set (GladeProperty *property, const GValue *value);
void glade_property_sync (GladeProperty *property);
GladeXmlNode *glade_property_write (GladeXmlContext *context, GladeProperty *property);

View File

@ -785,14 +785,15 @@ glade_widget_class_get_type (GladeWidgetClass *widget)
}
/**
* glade_widget_class_has_property:
* glade_widget_class_get_property_class:
* @class: a #GladeWidgetClass
* @name: a string
*
* Returns: %TRUE if @class has a property named @name, %FALSE otherwise
* Returns: The #GladePropertyClass object if there is one associated to this widget
* class.
*/
gboolean
glade_widget_class_has_property (GladeWidgetClass *class, const gchar *name)
GladePropertyClass *
glade_widget_class_get_property_class (GladeWidgetClass *class, const gchar *name)
{
GList *list;
GladePropertyClass *pclass;
@ -801,10 +802,9 @@ glade_widget_class_has_property (GladeWidgetClass *class, const gchar *name)
{
pclass = list->data;
if (strcmp (pclass->id, name) == 0)
return TRUE;
return pclass;
}
return FALSE;
return NULL;
}
/**

View File

@ -119,7 +119,8 @@ gboolean glade_widget_class_has_queries (GladeWidgetClass *class);
gboolean glade_widget_class_is (GladeWidgetClass *class, const char *name);
void glade_widget_class_dump_param_specs (GladeWidgetClass *class);
gboolean glade_widget_class_has_property (GladeWidgetClass *class, const gchar *name);
GladePropertyClass *glade_widget_class_get_property_class (GladeWidgetClass *class,
const gchar *name);
G_END_DECLS

View File

@ -34,6 +34,8 @@
#include "glade-placeholder.h"
#include "glade-signal.h"
#include "glade-popup.h"
#include "glade-editor.h"
#include "glade-project-window.h"
#include <glib.h>
#include <gdk/gdkkeysyms.h>
@ -280,6 +282,64 @@ glade_widget_debug (GladeWidget *widget)
glade_widget_debug_real (widget, 0);
}
static void
glade_widget_copy_packing_props (GladeWidget *parent,
GladeWidget *child,
GladeWidget *template)
{
GList *l;
glade_widget_set_packing_properties (child, parent);
for (l = child->packing_properties; l && l->data; l = l->next)
{
GladeProperty *dup_prop = GLADE_PROPERTY(l->data);
GladeProperty *orig_prop =
glade_widget_get_property (template, dup_prop->class->id);
glade_property_set (dup_prop, orig_prop->value);
}
}
static void
glade_widget_copy_custom_props (GladeWidget *widget,
GladeWidget *template)
{
GList *l;
for (l = widget->properties; l && l->data; l = l->next)
{
GladeProperty *dup_prop = GLADE_PROPERTY(l->data);
GladeProperty *orig_prop;
if (dup_prop->class->set_function)
{
orig_prop = glade_widget_get_property (template, dup_prop->class->id);
glade_property_set (dup_prop, orig_prop->value);
}
}
}
static void
glade_widget_sync_custom_props (GladeWidget *widget)
{
GList *l;
for (l = widget->properties; l && l->data; l = l->next)
{
GladeProperty *prop = GLADE_PROPERTY(l->data);
if (prop->class->set_function)
glade_property_sync (prop);
}
}
static void
glade_widget_sync_query_props (GladeWidget *widget)
{
GList *l;
for (l = widget->properties; l && l->data; l = l->next)
{
GladeProperty *prop = GLADE_PROPERTY(l->data);
if (prop->class->query)
glade_property_sync (prop);
}
}
/**
* glade_widget_build_object:
@ -295,12 +355,13 @@ glade_widget_debug (GladeWidget *widget)
static GObject *
glade_widget_build_object (GladeWidgetClass *klass, GladeWidget *widget)
{
GArray *params;
GObjectClass *oclass;
GParamSpec **pspec;
GladeProperty *glade_property;
GObject *object;
gint n_props, i;
GArray *params;
GObjectClass *oclass;
GParamSpec **pspec;
GladeProperty *glade_property;
GladePropertyClass *glade_property_class;
GObject *object;
gint n_props, i;
/* As a slight optimization, we never unref the class
*/
@ -312,7 +373,7 @@ glade_widget_build_object (GladeWidgetClass *klass, GladeWidget *widget)
{
GParameter parameter = { 0, };
if (!glade_widget_class_has_property(klass, pspec[i]->name))
if (glade_widget_class_get_property_class (klass, pspec[i]->name) == NULL)
/* Ignore properties that are not accounted for
* by the GladeWidgetClass
*/
@ -335,7 +396,23 @@ glade_widget_build_object (GladeWidgetClass *klass, GladeWidget *widget)
else
{
g_critical("Type mismatch on %s property of %s",
parameter.name, widget->widget_class->name);
parameter.name, klass->name);
continue;
}
}
/* If the class has a default, use it.
*/
else if ((glade_property_class =
glade_widget_class_get_property_class(klass, pspec[i]->name)) &&
glade_property_class->def != NULL)
{
if (g_value_type_compatible(G_VALUE_TYPE(glade_property_class->def),
G_VALUE_TYPE(&parameter.value)))
g_value_copy(glade_property_class->def, &parameter.value);
else
{
g_critical("Type mismatch on %s property of %s",
parameter.name, klass->name);
continue;
}
}
@ -364,23 +441,14 @@ glade_widget_build_object (GladeWidgetClass *klass, GladeWidget *widget)
return object;
}
/**
* glade_widget_new:
* @klass: a #GladeWidgetClass
* @project: a #GladeProject
*
* TODO: write me
*
* Returns:
*/
GladeWidget *
glade_widget_new (GladeWidgetClass *klass, GladeProject *project)
static GladeWidget *
glade_widget_internal_new (GladeWidgetClass *klass, GladeProject *project, GladeWidget *template)
{
GObject *widget;
GObject *glade_widget;
gchar *widget_name;
widget = glade_widget_build_object(klass, NULL);
widget = glade_widget_build_object(klass, template);
if (klass->pre_create_function)
klass->pre_create_function (G_OBJECT (widget));
@ -397,6 +465,82 @@ glade_widget_new (GladeWidgetClass *klass, GladeProject *project)
return (GladeWidget *) glade_widget;
}
/**
* glade_widget_new:
* @klass: a #GladeWidgetClass
* @project: a #GladeProject
*
* TODO: write me
*
* Returns:
*/
GladeWidget *
glade_widget_new (GladeWidgetClass *klass, GladeProject *project)
{
GladeWidget *widget;
if ((widget = glade_widget_internal_new (klass, project, NULL)) != NULL &&
widget->query_user)
{
GladeProjectWindow *gpw = glade_project_window_get ();
glade_editor_query_popup (gpw->editor, widget);
/* The glade editor code only sets properties if they change,
* this is just in case they dont.
*/
glade_widget_sync_query_props (widget);
}
return widget;
}
/**
* glade_widget_dup:
* @widget: a #GladeWidget
*
* TODO: write me
*
* Returns:
*/
GladeWidget *
glade_widget_dup (GladeWidget *template)
{
GladeWidget *gwidget;
GList *l, *children;
g_return_val_if_fail (template != NULL && GLADE_IS_WIDGET(template), NULL);
gwidget = glade_widget_internal_new (template->widget_class,
template->project,
template);
if (GTK_IS_CONTAINER(template->widget))
{
children = gtk_container_get_children(GTK_CONTAINER(template->widget));
for (l = children; l && l->data; l = l->next)
{
GtkWidget *child_widget = GTK_WIDGET(l->data);
GladeWidget *child_gwidget;
if ((child_gwidget =
glade_widget_get_from_gtk_widget(child_widget)) != NULL)
{
GladeWidget *child_dup =
glade_widget_dup(child_gwidget);
gtk_container_add(GTK_CONTAINER(gwidget->widget),
child_dup->widget);
glade_widget_copy_packing_props (gwidget,
child_dup,
child_gwidget);
}
}
}
gtk_widget_show_all (gwidget->widget);
glade_widget_copy_custom_props (gwidget, template);
return gwidget;
}
/**
* glade_widget_rebuild:
@ -421,6 +565,11 @@ glade_widget_rebuild (GladeWidget *glade_widget)
glade_widget_set_widget(glade_widget, new_widget);
/* Custom properties aren't transfered in build_object, since build_object
* is only concerned with object creation.
*/
glade_widget_sync_custom_props (glade_widget);
/* Must use gtk_widget_destroy here for cases like dialogs and toplevels
* (otherwise I'd prefer g_object_unref() )
*/
@ -455,6 +604,7 @@ glade_widget_new_for_internal_child (GladeWidgetClass *klass,
"internal", internal_name,
"widget", internal_widget, NULL);
g_free (widget_name);
glade_widget_set_packing_properties (widget, parent);
return widget;
}
@ -469,6 +619,12 @@ glade_widget_finalize (GObject *object)
g_free (widget->internal);
g_hash_table_destroy (widget->signals);
g_list_foreach (widget->properties, (GFunc)glade_property_free, NULL);
g_list_free (widget->properties);
g_list_foreach (widget->packing_properties, (GFunc)glade_property_free, NULL);
g_list_free (widget->packing_properties);
G_OBJECT_CLASS(parent_class)->finalize(object);
}
@ -692,7 +848,7 @@ glade_widget_set_class (GladeWidget *widget, GladeWidgetClass *klass)
{
GladePropertyClass *property_class;
GladeProperty *property;
GList *list = klass->properties;
GList *list;
g_return_if_fail (GLADE_IS_WIDGET (widget));
g_return_if_fail (GLADE_IS_WIDGET_CLASS (klass));
@ -702,9 +858,9 @@ glade_widget_set_class (GladeWidget *widget, GladeWidgetClass *klass)
// g_object_ref (klass); TODO, GladeWidgetClass is not a GObject
widget->widget_class = klass;
for (; list; list = list->next)
for (list = klass->properties; list; list = list->next)
{
property_class = list->data;
property_class = GLADE_PROPERTY_CLASS(list->data);
property = glade_property_new (property_class, widget);
if (!property) {
g_print ("Failed to create [%s] property.\n",
@ -713,9 +869,10 @@ glade_widget_set_class (GladeWidget *widget, GladeWidgetClass *klass)
}
widget->properties = g_list_prepend (widget->properties, property);
}
if (property_class->query) widget->query_user = TRUE;
widget->properties = g_list_reverse (widget->properties);
}
widget->properties = g_list_reverse (widget->properties);
}
/**
@ -1064,7 +1221,8 @@ glade_widget_update_parent(GladeWidget *gwidget, GtkWidget *old_widget, GtkWidge
(old_widget, new_widget,
glade_widget_get_widget (parent));
glade_widget_set_packing_properties (gwidget, parent);
if (GLADE_IS_PLACEHOLDER(new_widget) == FALSE)
glade_widget_set_packing_properties (gwidget, parent);
}
else
g_warning ("Unable to set packing properties on new instance: replace "
@ -1122,7 +1280,6 @@ glade_widget_set_widget (GladeWidget *gwidget, GtkWidget *new_widget)
G_CALLBACK (glade_widget_key_press), NULL);
glade_widget_connect_signal_handlers (new_widget, NULL);
/* Take care of reparenting and packing.
*/

View File

@ -59,6 +59,10 @@ struct _GladeWidget
* GladeWidgetClass.
*/
gboolean query_user; /* Whether the user should be prompted for some initial
* values with a dialog popup upon creation.
*/
GHashTable *signals; /* A table with a GPtrArray of GladeSignals (signal handlers),
* indexed by its name */
};
@ -109,6 +113,7 @@ GladeWidget * glade_widget_read (GladeProject *project, GladeXmlNode *node);
GladeWidget * glade_widget_get_parent (GladeWidget *widget);
void glade_widget_rebuild (GladeWidget *widget);
GladeWidget * glade_widget_dup (GladeWidget *widget);
G_END_DECLS