Commit d3038a8e authored by Tristan Van Berkom's avatar Tristan Van Berkom

Added glade_property_[push/pop]_superuser()


	* src/glade-property.[ch]: Added glade_property_[push/pop]_superuser()

	* src/glade-command.c: refined set_property_execute() and started using
	  glade_property_push/pop_superuser().

	* src/glade-project.c: super-user property mode at load time.

	* src/glade-fixed.c: Added "can-resize" property

	* src/glade-widget-class.c: Made sure to parse a "Fixed" if there are no
	  other child tags.

	* src/glade-gtk.c, widgets/gtk+.xml.in: Implemented drag on GtkBox children
parent aa13bb67
2006-06-16 Tristan Van Berkom <tvb@gnome.org>
* src/glade-property.[ch]: Added glade_property_[push/pop]_superuser()
* src/glade-command.c: refined set_property_execute() and started using
glade_property_push/pop_superuser().
* src/glade-project.c: super-user property mode at load time.
* src/glade-fixed.c: Added "can-resize" property
* src/glade-widget-class.c: Made sure to parse a "Fixed" if there are no
other child tags.
* src/glade-gtk.c, widgets/gtk+.xml.in: Implemented drag on GtkBox children
2006-06-12 Tristan Van Berkom <tvb@gnome.org>
* src/glade-widget-class.c: Vincent pointed out compile errors on gcc 4.x,
......
......@@ -68,6 +68,11 @@ for the values passed to configure-child via the #GdkRectangle.
@arg1:
@Returns:
<!-- ##### ARG GladeFixed:can-resize ##### -->
<para>
</para>
<!-- ##### ARG GladeFixed:height-prop ##### -->
<para>
......
......@@ -386,8 +386,10 @@ glade_command_push_undo (GladeProject *project, GladeCommand *cmd)
* encapsulate a "set property" operation */
typedef struct {
GladeCommand parent;
GList *sdata;
GladeCommand parent;
gboolean set_once;
gboolean undo;
GList *sdata;
} GladeCommandSetProperty;
/* standard macros */
......@@ -417,29 +419,59 @@ glade_command_set_property_execute (GladeCommand *cmd)
g_return_val_if_fail (me != NULL, FALSE);
if (me->set_once != FALSE)
glade_property_push_superuser ();
for (l = me->sdata; l; l = l->next)
{
GValue new_value = { 0, };
GCSetPropData *sdata = l->data;
g_value_init (&new_value, G_VALUE_TYPE (sdata->new_value));
g_value_copy (sdata->new_value, &new_value);
/* store the current value for undo */
if (sdata->old_value)
if (me->undo)
g_value_copy (sdata->old_value, &new_value);
else
g_value_copy (sdata->new_value, &new_value);
{
g_value_copy (sdata->old_value, sdata->new_value);
g_value_unset (sdata->old_value);
sdata->old_value = (g_free (sdata->old_value), NULL);
gchar *txt =
glade_property_class_make_string_from_gvalue
(sdata->property->class, &new_value);
g_print ("Setting %s of %s to %s (su mode %d)\n",
sdata->property->class->id,
sdata->property->widget->name,
txt, glade_property_superuser ());
g_free (txt);
}
else
g_value_copy (sdata->property->value, sdata->new_value);
glade_property_set_value (sdata->property, &new_value);
if (!me->set_once)
{
/* If some verify functions didnt pass on
* the first go.. we need to record the actual
* properties here.
*/
g_value_copy (sdata->property->value,
sdata->new_value);
}
g_value_unset (&new_value);
}
if (me->set_once != FALSE)
glade_property_pop_superuser ();
me->set_once = TRUE;
me->undo = !me->undo;
return TRUE;
}
......
......@@ -44,7 +44,8 @@ enum {
PROP_X_PROP,
PROP_Y_PROP,
PROP_WIDTH_PROP,
PROP_HEIGHT_PROP
PROP_HEIGHT_PROP,
PROP_CAN_RESIZE
};
/* signals */
......@@ -67,8 +68,8 @@ typedef struct {
#define CHILD_WIDTH_DEF 100
#define CHILD_HEIGHT_DEF 80
#define GRAB_BORDER_WIDTH 10
#define GRAB_CORNER_WIDTH 10
#define GRAB_BORDER_WIDTH 7
#define GRAB_CORNER_WIDTH 7
static GObjectClass *parent_class;
static guint glade_fixed_signals[FIXED_SIGNALS];
......@@ -433,20 +434,14 @@ glade_fixed_handle_child_event (GladeFixed *fixed,
GtkWidget *fixed_widget, *child_widget;
gint parent_x, parent_y, child_x, child_y, trim_x, trim_y;
GladeCursorType operation;
GladeWidget *debug;
fixed_widget = GTK_WIDGET (GLADE_WIDGET (fixed)->object);
child_widget = GTK_WIDGET (child->object);
/* Get relative mouse position
*/
/* when widget->window points to a parent window, these calculations
* would be wrong if we based them on the GTK_WIDGET (fixed)->window,
* so we must always consult the event widget's window
*/
gdk_window_get_pointer (event_widget->window,
&parent_x, &parent_y, NULL);
......@@ -458,11 +453,12 @@ glade_fixed_handle_child_event (GladeFixed *fixed,
trim_y = child_widget == event_widget &&
GTK_WIDGET_NO_WINDOW (child_widget) ? child_widget->allocation.y : 0;
operation = glade_fixed_get_operation (GTK_WIDGET (child->object),
child_x - trim_x,
child_y - trim_y);
debug = glade_widget_get_from_gobject (event_widget);
if (fixed->can_resize)
operation = glade_fixed_get_operation (GTK_WIDGET (child->object),
child_x - trim_x,
child_y - trim_y);
else
operation = GLADE_CURSOR_DRAG;
switch (event->type)
{
......@@ -674,7 +670,6 @@ glade_fixed_replace_child_impl (GladeWidget *fixed,
GObject *new_object)
{
GladeWidget *gnew_widget = glade_widget_get_from_gobject (new_object);
GladeWidget *gold_widget = glade_widget_get_from_gobject (old_object);
glade_fixed_disconnect_child (GLADE_FIXED (fixed), old_object);
......@@ -903,6 +898,9 @@ glade_fixed_set_property (GObject *object,
g_free (fixed->height_prop);
fixed->height_prop = g_value_dup_string (value);
break;
case PROP_CAN_RESIZE:
fixed->can_resize = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -919,10 +917,11 @@ glade_fixed_get_property (GObject *object,
switch (prop_id)
{
case PROP_X_PROP: g_value_set_string (value, fixed->x_prop); break;
case PROP_Y_PROP: g_value_set_string (value, fixed->y_prop); break;
case PROP_WIDTH_PROP: g_value_set_string (value, fixed->width_prop); break;
case PROP_HEIGHT_PROP: g_value_set_string (value, fixed->height_prop); break;
case PROP_X_PROP: g_value_set_string (value, fixed->x_prop); break;
case PROP_Y_PROP: g_value_set_string (value, fixed->y_prop); break;
case PROP_WIDTH_PROP: g_value_set_string (value, fixed->width_prop); break;
case PROP_HEIGHT_PROP: g_value_set_string (value, fixed->height_prop); break;
case PROP_CAN_RESIZE: g_value_set_boolean (value, fixed->can_resize); break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -937,6 +936,7 @@ glade_fixed_init (GladeFixed *fixed)
fixed->y_prop = g_strdup ("y");
fixed->width_prop = g_strdup ("width");
fixed->height_prop = g_strdup ("height");
fixed->can_resize = TRUE;
}
static void
......@@ -993,6 +993,14 @@ glade_fixed_class_init (GladeFixedClass *fixed_class)
_("The property used to set the height of a child object"),
"height-request", G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property
(gobject_class, PROP_CAN_RESIZE,
g_param_spec_boolean
("can_resize", _("Can resize"),
_("Whether this container supports resizes of child widgets"),
TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/**
* GladeFixed::configure-child:
* @gladewidget: the #GladeFixed which received the signal.
......
......@@ -49,7 +49,10 @@ struct _GladeFixed {
gchar *y_prop; /* to obtain & configure widget coordinates */
gchar *width_prop; /* property names (on child widgets) used to obtain */
gchar *height_prop; /* & configure widget dimentions. */
gboolean can_resize; /* whether the container supports child resizes or only
* drags.
*/
/* State machine used to commit properties at the end
* of a drag or a resize (i.e. a "configure").
......
......@@ -346,36 +346,280 @@ glade_gtk_container_remove_child (GtkWidget *container,
}
/* ----------------------------- GtkBox ------------------------------ */
typedef struct {
GtkWidget *widget;
gint position;
} GladeGtkBoxChild;
static GList *glade_gtk_box_original_positions = NULL;
static gboolean
glade_gtk_box_configure_child (GladeFixed *fixed,
GladeWidget *child,
GdkRectangle *rect,
GtkWidget *box)
{
GList *list;
GtkBoxChild *bchild;
gint point, trans_point, span, position;
gboolean found, offset;
if (GTK_IS_HBOX (box))
{
point = rect->x + (rect->width / 2);
}
else
{
point = rect->y + (rect->height / 2);
}
for (list = GTK_BOX (box)->children; list; list = list->next)
{
bchild = list->data;
/* Find the widget in the box where the center of
* this rectangle fits... and set the position to that
* position.
*/
if (GTK_IS_HBOX (box))
{
gtk_widget_translate_coordinates
(GTK_WIDGET (box), bchild->widget,
point, 0, &trans_point, NULL);
span = bchild->widget->allocation.width;
offset = rect->x;
}
else
{
gtk_widget_translate_coordinates
(GTK_WIDGET (box), bchild->widget,
0, point, NULL, &trans_point);
span = bchild->widget->allocation.height;
offset = rect->y;
}
#if 0
gtk_container_child_get (GTK_CONTAINER (box),
bchild->widget,
"position", &position, NULL);
g_print ("pos %d, point %d span %d thresh %d upleft %d\n",
position, trans_point, span, MAX (span, 1) / 2,
offset <= glade_gtk_box_last_offset);
#endif
found = trans_point >= 0 && trans_point < span;
if (found)
{
gtk_container_child_get (GTK_CONTAINER (box),
bchild->widget,
"position", &position, NULL);
glade_widget_pack_property_set
(child, "position", position);
break;
}
}
return TRUE;
}
static gboolean
glade_gtk_box_configure_begin (GladeFixed *fixed,
GladeWidget *child,
GtkWidget *box)
{
GList *list;
GtkBoxChild *bchild;
g_assert (glade_gtk_box_original_positions == NULL);
for (list = GTK_BOX (box)->children; list; list = list->next)
{
GladeGtkBoxChild *gbchild;
GladeWidget *gchild;
bchild = list->data;
if ((gchild = glade_widget_get_from_gobject (bchild->widget)) == NULL)
continue;
gbchild = g_new0 (GladeGtkBoxChild, 1);
gbchild->widget = bchild->widget;
glade_widget_pack_property_get (gchild, "position",
&gbchild->position);
glade_gtk_box_original_positions =
g_list_prepend (glade_gtk_box_original_positions, gbchild);
}
return TRUE;
}
static gboolean
glade_gtk_box_configure_end (GladeFixed *fixed,
GladeWidget *child,
GtkWidget *box)
{
GList *list, *l;
GList *prop_list = NULL;
for (list = GTK_BOX (box)->children; list; list = list->next)
{
GtkBoxChild *bchild = list->data;
for (l = glade_gtk_box_original_positions; l; l = l->next)
{
GladeGtkBoxChild *gbchild = l->data;
GladeWidget *gchild =
glade_widget_get_from_gobject (gbchild->widget);
if (bchild->widget == gbchild->widget)
{
GCSetPropData *prop_data = g_new0 (GCSetPropData, 1);
prop_data->property =
glade_widget_get_pack_property
(gchild, "position");
prop_data->old_value = g_new0 (GValue, 1);
prop_data->new_value = g_new0 (GValue, 1);
glade_property_get_value (prop_data->property,
prop_data->new_value);
g_value_init (prop_data->old_value, G_TYPE_INT);
g_value_set_int (prop_data->old_value, gbchild->position);
prop_list = g_list_prepend (prop_list, prop_data);
break;
}
}
}
glade_property_push_superuser ();
glade_command_set_properties_list (GLADE_WIDGET (fixed)->project,
prop_list);
glade_property_pop_superuser ();
for (l = glade_gtk_box_original_positions; l; l = l->next)
{
g_free (l->data);
}
glade_gtk_box_original_positions =
(g_list_free (glade_gtk_box_original_positions), NULL);
return TRUE;
}
void GLADEGTK_API
glade_gtk_box_post_create (GObject *container, GladeCreateReason reason)
{
GladeWidget *gwidget =
glade_widget_get_from_gobject (container);
/* Implement drag in GtkBox but not resize.
*/
g_object_set (gwidget, "can-resize", FALSE, NULL);
g_signal_connect (G_OBJECT (gwidget), "configure-child",
G_CALLBACK (glade_gtk_box_configure_child), container);
g_signal_connect (G_OBJECT (gwidget), "configure-begin",
G_CALLBACK (glade_gtk_box_configure_begin), container);
g_signal_connect (G_OBJECT (gwidget), "configure-end",
G_CALLBACK (glade_gtk_box_configure_end), container);
}
void GLADEGTK_API
glade_gtk_box_set_child_property (GObject *container,
GObject *child,
const gchar *property_name,
GValue *value)
{
GladeWidget *gbox;
GladeWidget *gbox, *gchild, *gchild_iter;
GList *children, *list;
gboolean is_position;
gint old_position, iter_position, new_position;
g_return_if_fail (GTK_IS_BOX (container));
g_return_if_fail (GTK_IS_WIDGET (child));
gbox = glade_widget_get_from_gobject (container);
g_return_if_fail (GLADE_IS_WIDGET (gbox));
g_return_if_fail (property_name != NULL || value != NULL);
/* Chain Up */
gtk_container_child_set_property (GTK_CONTAINER (container),
GTK_WIDGET (child),
property_name,
value);
if (strcmp (property_name, "position") == 0)
gbox = glade_widget_get_from_gobject (container);
gchild = glade_widget_get_from_gobject (child);
g_return_if_fail (GLADE_IS_WIDGET (gbox));
/* Get old position */
if ((is_position = (strcmp (property_name, "position") == 0)) != FALSE)
{
gint position, size;
gtk_container_child_get (GTK_CONTAINER (container),
GTK_WIDGET (child),
property_name, &old_position, NULL);
position = g_value_get_int (value) + 1;
glade_widget_property_get (gbox, "size", &size);
/* Get the real value */
new_position = g_value_get_int (value);
if (size < position)
glade_widget_property_set (gbox, "size", position);
}
if (is_position && glade_property_superuser () == FALSE)
{
children = glade_widget_class_container_get_children
(gbox->widget_class, container);
for (list = children; list; list = list->next)
{
if ((gchild_iter =
glade_widget_get_from_gobject (list->data)) == NULL)
continue;
if (gchild_iter == gchild)
continue;
/* Get the old value from glade */
glade_widget_property_get
(gchild_iter, "position", &iter_position);
/* Search for the child at the old position and update it */
if (iter_position == new_position)
{
/* Update glade with the real value */
glade_widget_property_set
(gchild_iter, "position", old_position);
break;
}
}
if (children)
g_list_free (children);
}
/* Chain Up */
if (is_position)
/* XXX FIXME: reorder child is dependant on the order
* in which we add children... take em all out and repack them.
*/
gtk_box_reorder_child (GTK_BOX (container),
GTK_WIDGET (child),
new_position);
else
gtk_container_child_set_property (GTK_CONTAINER (container),
GTK_WIDGET (child),
property_name,
value);
}
void GLADEGTK_API
......@@ -629,7 +873,8 @@ glade_gtk_table_get_row_col_from_point (GtkTable *table,
tchild->widget->allocation.width;
if (trans_point >= 0 &&
trans_point <= end)
/* should be trans_point < end ... test FIXME ! */
trans_point < end)
{
base = row ? tchild->top_attach : tchild->left_attach;
size = row ? (tchild->widget->allocation.height) :
......@@ -853,10 +1098,9 @@ static gboolean
glade_gtk_table_configure_child (GladeFixed *fixed,
GladeWidget *child,
GdkRectangle *rect,
gpointer unused)
GtkWidget *table)
{
GtkWidget *table = GTK_WIDGET (GLADE_WIDGET (fixed)->object);
GladeGtkTableChild configure = { child, };
GladeGtkTableChild configure = { child, };
/* Sometimes we are unable to find a widget in the appropriate column,
* usually because a placeholder hasnt had its size allocation yet.
......@@ -904,7 +1148,7 @@ glade_gtk_table_configure_child (GladeFixed *fixed,
static gboolean
glade_gtk_table_configure_begin (GladeFixed *fixed,
GladeWidget *child,
gpointer unused)
GtkWidget *table)
{
table_edit.widget = child;
......@@ -926,7 +1170,7 @@ glade_gtk_table_configure_begin (GladeFixed *fixed,
static gboolean
glade_gtk_table_configure_end (GladeFixed *fixed,
GladeWidget *child,
gpointer unused)
GtkWidget *table)
{
GladeGtkTableChild new = { child, };
......@@ -1010,13 +1254,13 @@ glade_gtk_table_post_create (GObject *container, GladeCreateReason reason)
glade_widget_get_from_gobject (container);
g_signal_connect (G_OBJECT (gwidget), "configure-child",
G_CALLBACK (glade_gtk_table_configure_child), NULL);
G_CALLBACK (glade_gtk_table_configure_child), container);
g_signal_connect (G_OBJECT (gwidget), "configure-begin",
G_CALLBACK (glade_gtk_table_configure_begin), NULL);
G_CALLBACK (glade_gtk_table_configure_begin), container);
g_signal_connect (G_OBJECT (gwidget), "configure-end",
G_CALLBACK (glade_gtk_table_configure_end), NULL);
G_CALLBACK (glade_gtk_table_configure_end), container);
}
static gboolean
......
......@@ -59,8 +59,8 @@ struct _GladeProjectWindowPriv {
GtkActionGroup *recent_actions; /* Recent projects actions */
GtkActionGroup *projects_list_menu_actions;/* Projects list menu actions */
GQueue *recent_projects; /* A GtkAction queue */
gint rp_max; /* Maximun Recent Projects entries */
GQueue *recent_projects; /* A GtkAction queue */
gint rp_max; /* Maximun Recent Projects entries */
GtkWindow *palette_window; /* The window that will contain the palette */
GtkWindow *editor_window; /* The window that will contain the editor */
......
......@@ -1161,6 +1161,9 @@ glade_project_loading_done_idle (gpointer data)
GladeProject *project = (GladeProject *) data;
project->loading = project->changed = FALSE;
glade_property_pop_superuser ();
return FALSE;
}
......@@ -1214,6 +1217,8 @@ glade_project_new_from_interface (GladeInterface *interface, const gchar *path)
project->objects = NULL;
project->loading = TRUE;
glade_property_push_superuser ();
for (i = 0; i < interface->n_toplevels; ++i)
{
widget = glade_widget_read ((gpointer)project, interface->toplevels[i]);
......
......@@ -152,8 +152,6 @@ 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,
......@@ -1591,3 +1589,27 @@ glade_property_get_enabled (GladeProperty *property)
g_return_val_if_fail (GLADE_IS_PROPERTY (property), FALSE);
return property->enabled;
}
glade_property_su_stack = 0;
void
glade_property_push_superuser (void)
{
glade_property_su_stack++;
}
void
glade_property_pop_superuser (void)
{
if (--glade_property_su_stack < 0)
{
g_critical ("Bug: property super user stack is corrupt.\n");
}
}
gboolean
glade_property_superuser (void)
{
return glade_property_su_stack > 0;
}
......@@ -170,6 +170,13 @@ void glade_property_i18n_set_has_context (GladeProperty
LIBGLADEUI_API
gboolean glade_property_i18n_get_has_context (GladeProperty *property);
LIBGLADEUI_API
void glade_property_push_superuser (void);
LIBGLADEUI_API
void glade_property_pop_superuser (void);
LIBGLADEUI_API
gboolean glade_property_superuser (void);
G_END_DECLS
#endif /* __GLADE_PROPERTY_H__ */
......@@ -888,7 +888,7 @@ glade_widget_class_merge (GladeWidgetClass *widget_class,
{
g_return_if_fail (GLADE_IS_WIDGET_CLASS (widget_class));
g_return_if_fail (GLADE_IS_WIDGET_CLASS (parent_class));
if (widget_class->post_create_function == NULL)
widget_class->post_create_function = parent_class->post_create_function;
......@@ -1042,8 +1042,7 @@ glade_widget_class_new (GladeXmlNode *class_node,
}
}
if (glade_xml_node_get_children (class_node))
glade_widget_class_extend_with_node (widget_class, class_node, domain);
glade_widget_class_extend_with_node (widget_class, class_node, domain);
/* store the GladeWidgetClass on the cache,
* if it's the first time we store a widget class, then
......
......@@ -94,8 +94,8 @@
</properties>
</glade-widget-class>
<glade-widget-class name="GtkBox" _title="Box">
<post-create-function>empty</post-create-function>
<glade-widget-class name="GtkBox" _title="Box" fixed="True">
<post-create-function>glade_gtk_box_post_create</post-create-function>
<get-internal-child-function>glade_gtk_box_get_internal_child</get-internal-child-function>
<properties>
<property id="size" _name="Number of items" query="True" default="3" save="False">
......@@ -746,8 +746,8 @@
</children>
</glade-widget-class>
<glade-widget-class name="GtkHBox" generic-name="hbox" _title="Horizontal Box"/>
<glade-widget-class name="GtkVBox" generic-name="vbox" _title="Vertical Box"/>
<glade-widget-class name="GtkHBox" generic-name="hbox" _title="Horizontal Box" fixed="True"/>
<glade-widget-class name="GtkVBox" generic-name="vbox" _title="Vertical Box" fixed="True"/>
<glade-widget-class name="GtkTable" generic-name="table" _title="Table" fixed="True">
<post-create-function>glade_gtk_table_post_create</post-create-function>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment