Compare commits
8 Commits
tree-list-
...
composite-
Author | SHA1 | Date | |
---|---|---|---|
|
f2e1df6066 | ||
|
a22821390a | ||
|
fabc18d551 | ||
|
1441fc5fb0 | ||
|
67310786cb | ||
|
0409e5958f | ||
|
48d8d2c819 | ||
|
6a8a584a95 |
217
gtk/gtkbuilder.c
217
gtk/gtkbuilder.c
@@ -81,12 +81,14 @@
|
||||
* <!ATTLIST property name #REQUIRED
|
||||
* translatable #IMPLIED
|
||||
* comments #IMPLIED
|
||||
* context #IMPLIED >
|
||||
* context #IMPLIED
|
||||
* external-object #IMPLIED >
|
||||
* <!ATTLIST signal name #REQUIRED
|
||||
* handler #REQUIRED
|
||||
* after #IMPLIED
|
||||
* swapped #IMPLIED
|
||||
* object #IMPLIED
|
||||
* external-object #IMPLIED
|
||||
* last_modification_time #IMPLIED >
|
||||
* <!ATTLIST child type #IMPLIED
|
||||
* internal-child #IMPLIED >
|
||||
@@ -148,22 +150,27 @@
|
||||
* (can be specified by their name, nick or integer value), flags (can be
|
||||
* specified by their name, nick, integer value, optionally combined with "|",
|
||||
* e.g. "GTK_VISIBLE|GTK_REALIZED") and colors (in a format understood by
|
||||
* gdk_color_parse()). Objects can be referred to by their name. Pixbufs can be
|
||||
* specified as a filename of an image file to load. In general, GtkBuilder
|
||||
* allows forward references to objects — an object doesn't have to be
|
||||
* constructed before it can be referred to. The exception to this rule is that
|
||||
* an object has to be constructed before it can be used as the value of a
|
||||
* construct-only property.
|
||||
* gdk_color_parse()). Pixbufs can be specified as a filename of an image file to load.
|
||||
* Objects can be referred to by their name and by default refer to objects declared
|
||||
* in the local xml fragment, however external objects exposed via gtk_builder_expose_object()
|
||||
* can be referred to by specifying the "external-object" attribute.
|
||||
*
|
||||
* In general, GtkBuilder allows forward references to objects &mdash declared
|
||||
* in the local xml; an object doesn't have to be constructed before it can be referred to.
|
||||
* The exception to this rule is that an object has to be constructed before
|
||||
* it can be used as the value of a construct-only property.
|
||||
*
|
||||
* Signal handlers are set up with the <signal> element. The "name"
|
||||
* attribute specifies the name of the signal, and the "handler" attribute
|
||||
* specifies the function to connect to the signal. By default, GTK+ tries to
|
||||
* find the handler using g_module_symbol(), but this can be changed by passing
|
||||
* a custom #GtkBuilderConnectFunc to gtk_builder_connect_signals_full(). The
|
||||
* remaining attributes, "after", "swapped" and "object", have the same meaning
|
||||
* attributes "after", "swapped" and "object", have the same meaning
|
||||
* as the corresponding parameters of the g_signal_connect_object() or
|
||||
* g_signal_connect_data() functions. A "last_modification_time" attribute
|
||||
* is also allowed, but it does not have a meaning to the builder.
|
||||
* g_signal_connect_data() functions. Extenral objects can also be referred
|
||||
* to by specifying the "external-object" attribute in the same way as described
|
||||
* with the <property> element. A "last_modification_time" attribute is also
|
||||
* allowed, but it does not have a meaning to the builder.
|
||||
*
|
||||
* Sometimes it is necessary to refer to widgets which have implicitly been
|
||||
* constructed by GTK+ as part of a composite widget, to set properties on them
|
||||
@@ -278,6 +285,7 @@ struct _GtkBuilderPrivate
|
||||
{
|
||||
gchar *domain;
|
||||
GHashTable *objects;
|
||||
GHashTable *external_objects;
|
||||
GSList *delayed_properties;
|
||||
GSList *signals;
|
||||
gchar *filename;
|
||||
@@ -327,6 +335,8 @@ gtk_builder_init (GtkBuilder *builder)
|
||||
builder->priv->domain = NULL;
|
||||
builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
builder->priv->external_objects = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
}
|
||||
|
||||
|
||||
@@ -343,6 +353,7 @@ gtk_builder_finalize (GObject *object)
|
||||
g_free (priv->filename);
|
||||
|
||||
g_hash_table_destroy (priv->objects);
|
||||
g_hash_table_destroy (priv->external_objects);
|
||||
|
||||
g_slist_foreach (priv->signals, (GFunc) _free_signal_info, NULL);
|
||||
g_slist_free (priv->signals);
|
||||
@@ -498,10 +509,27 @@ gtk_builder_get_parameters (GtkBuilder *builder,
|
||||
if (G_IS_PARAM_SPEC_OBJECT (pspec) &&
|
||||
(G_PARAM_SPEC_VALUE_TYPE (pspec) != GDK_TYPE_PIXBUF))
|
||||
{
|
||||
if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
|
||||
GObject *object;
|
||||
|
||||
if (prop->external)
|
||||
{
|
||||
object = g_hash_table_lookup (builder->priv->external_objects, prop->data);
|
||||
|
||||
if (!object)
|
||||
{
|
||||
g_warning ("Failed to get external object property "
|
||||
"%s of %s with value `%s'",
|
||||
prop->name, object_name, prop->data);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_value_init (¶meter.value, G_OBJECT_TYPE (object));
|
||||
g_value_set_object (¶meter.value, object);
|
||||
}
|
||||
else if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
|
||||
{
|
||||
GObject *object;
|
||||
object = gtk_builder_get_object (builder, prop->data);
|
||||
object = gtk_builder_get_object (builder, prop->data);
|
||||
|
||||
if (!object)
|
||||
{
|
||||
g_warning ("Failed to get constuct only property "
|
||||
@@ -512,7 +540,7 @@ gtk_builder_get_parameters (GtkBuilder *builder,
|
||||
g_value_init (¶meter.value, G_OBJECT_TYPE (object));
|
||||
g_value_set_object (¶meter.value, object);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
property = g_slice_new (DelayedProperty);
|
||||
property->object = g_strdup (object_name);
|
||||
@@ -570,6 +598,9 @@ gtk_builder_get_internal_child (GtkBuilder *builder,
|
||||
obj = gtk_buildable_get_internal_child (GTK_BUILDABLE (info->object),
|
||||
builder,
|
||||
childname);
|
||||
if (!obj && GTK_IS_CONTAINER (info->object))
|
||||
obj = (GObject *)gtk_container_get_composite_child (GTK_CONTAINER (info->object), childname);
|
||||
|
||||
};
|
||||
|
||||
if (!obj)
|
||||
@@ -893,7 +924,64 @@ gtk_builder_add_from_file (GtkBuilder *builder,
|
||||
g_free (builder->priv->filename);
|
||||
builder->priv->filename = g_strdup (filename);
|
||||
|
||||
_gtk_builder_parser_parse_buffer (builder, filename,
|
||||
_gtk_builder_parser_parse_buffer (builder, NULL, filename,
|
||||
buffer, length,
|
||||
NULL,
|
||||
&tmp_error);
|
||||
|
||||
g_free (buffer);
|
||||
|
||||
if (tmp_error != NULL)
|
||||
{
|
||||
g_propagate_error (error, tmp_error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_builder_add_to_parent_from_file:
|
||||
* @builder: a #GtkBuilder
|
||||
* @parent: the parent object to be assumed in context while parsing the file
|
||||
* @filename: the name of the file to parse
|
||||
* @error: (allow-none): return location for an error, or %NULL
|
||||
*
|
||||
* Like gtk_builder_add_from_file() except the format will expect
|
||||
* <child> instead of <object> as its first elements and expose
|
||||
* @parent in the build context, children defined in the UI fragment
|
||||
* will be added to @parent.
|
||||
*
|
||||
* Returns: A positive value on success, 0 if an error occurred
|
||||
*
|
||||
* Since: ...
|
||||
**/
|
||||
guint
|
||||
gtk_builder_add_to_parent_from_file (GtkBuilder *builder,
|
||||
GObject *parent,
|
||||
const gchar *filename,
|
||||
GError **error)
|
||||
{
|
||||
gchar *buffer;
|
||||
gsize length;
|
||||
GError *tmp_error;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
|
||||
g_return_val_if_fail (filename != NULL, 0);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, 0);
|
||||
|
||||
tmp_error = NULL;
|
||||
|
||||
if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
|
||||
{
|
||||
g_propagate_error (error, tmp_error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_free (builder->priv->filename);
|
||||
builder->priv->filename = g_strdup (filename);
|
||||
|
||||
_gtk_builder_parser_parse_buffer (builder, parent, filename,
|
||||
buffer, length,
|
||||
NULL,
|
||||
&tmp_error);
|
||||
@@ -960,7 +1048,7 @@ gtk_builder_add_objects_from_file (GtkBuilder *builder,
|
||||
g_free (builder->priv->filename);
|
||||
builder->priv->filename = g_strdup (filename);
|
||||
|
||||
_gtk_builder_parser_parse_buffer (builder, filename,
|
||||
_gtk_builder_parser_parse_buffer (builder, NULL, filename,
|
||||
buffer, length,
|
||||
object_ids,
|
||||
&tmp_error);
|
||||
@@ -1010,7 +1098,56 @@ gtk_builder_add_from_string (GtkBuilder *builder,
|
||||
g_free (builder->priv->filename);
|
||||
builder->priv->filename = g_strdup (".");
|
||||
|
||||
_gtk_builder_parser_parse_buffer (builder, "<input>",
|
||||
_gtk_builder_parser_parse_buffer (builder, NULL, "<input>",
|
||||
buffer, length,
|
||||
NULL,
|
||||
&tmp_error);
|
||||
if (tmp_error != NULL)
|
||||
{
|
||||
g_propagate_error (error, tmp_error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gtk_builder_add_to_parent_from_string:
|
||||
* @builder: a #GtkBuilder
|
||||
* @parent: the parent object to be assumed in context while parsing
|
||||
* @buffer: the string to parse
|
||||
* @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
|
||||
* @error: (allow-none): return location for an error, or %NULL
|
||||
*
|
||||
* Like gtk_builder_add_from_string() except the format will expect
|
||||
* <child> instead of <object> as its first elements and expose
|
||||
* @parent in the build context, children defined in the UI fragment
|
||||
* will be added to @parent.
|
||||
*
|
||||
* Returns: A positive value on success, 0 if an error occurred
|
||||
*
|
||||
* Since: ...
|
||||
**/
|
||||
guint
|
||||
gtk_builder_add_to_parent_from_string (GtkBuilder *builder,
|
||||
GObject *parent,
|
||||
const gchar *buffer,
|
||||
gsize length,
|
||||
GError **error)
|
||||
{
|
||||
GError *tmp_error;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
|
||||
g_return_val_if_fail (buffer != NULL, 0);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, 0);
|
||||
|
||||
tmp_error = NULL;
|
||||
|
||||
g_free (builder->priv->filename);
|
||||
builder->priv->filename = g_strdup (".");
|
||||
|
||||
_gtk_builder_parser_parse_buffer (builder, parent, "<input>",
|
||||
buffer, length,
|
||||
NULL,
|
||||
&tmp_error);
|
||||
@@ -1067,7 +1204,7 @@ gtk_builder_add_objects_from_string (GtkBuilder *builder,
|
||||
g_free (builder->priv->filename);
|
||||
builder->priv->filename = g_strdup (".");
|
||||
|
||||
_gtk_builder_parser_parse_buffer (builder, "<input>",
|
||||
_gtk_builder_parser_parse_buffer (builder, NULL, "<input>",
|
||||
buffer, length,
|
||||
object_ids,
|
||||
&tmp_error);
|
||||
@@ -1182,6 +1319,30 @@ gtk_builder_get_translation_domain (GtkBuilder *builder)
|
||||
return builder->priv->domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_builder_expose_object:
|
||||
* @builder: a #GtkBuilder
|
||||
* @name: the name of the object exposed to the builder
|
||||
* @object: the object to expose
|
||||
*
|
||||
* Adds @object to a pool of objects external to the
|
||||
* objects built by builder. Objects exposed in the pool
|
||||
* can be referred to by xml fragments in the builder.
|
||||
*/
|
||||
void
|
||||
gtk_builder_expose_object (GtkBuilder *builder,
|
||||
const gchar *name,
|
||||
GObject *object)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_BUILDER (builder));
|
||||
g_return_if_fail (name && name[0]);
|
||||
g_return_if_fail (G_IS_OBJECT (object));
|
||||
|
||||
g_hash_table_insert (builder->priv->external_objects,
|
||||
g_strdup (name), g_object_ref (object));
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
GModule *module;
|
||||
gpointer data;
|
||||
@@ -1211,7 +1372,6 @@ gtk_builder_connect_signals_default (GtkBuilder *builder,
|
||||
g_signal_connect_data (object, signal_name, func, args->data, NULL, flags);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gtk_builder_connect_signals:
|
||||
* @builder: a #GtkBuilder
|
||||
@@ -1307,7 +1467,7 @@ gtk_builder_connect_signals_full (GtkBuilder *builder,
|
||||
for (l = builder->priv->signals; l; l = l->next)
|
||||
{
|
||||
SignalInfo *signal = (SignalInfo*)l->data;
|
||||
|
||||
|
||||
g_assert (signal != NULL);
|
||||
g_assert (signal->name != NULL);
|
||||
|
||||
@@ -1319,14 +1479,19 @@ gtk_builder_connect_signals_full (GtkBuilder *builder,
|
||||
|
||||
if (signal->connect_object_name)
|
||||
{
|
||||
connect_object = g_hash_table_lookup (builder->priv->objects,
|
||||
signal->connect_object_name);
|
||||
if (signal->external)
|
||||
connect_object = g_hash_table_lookup (builder->priv->external_objects,
|
||||
signal->connect_object_name);
|
||||
else
|
||||
connect_object = g_hash_table_lookup (builder->priv->objects,
|
||||
signal->connect_object_name);
|
||||
|
||||
if (!connect_object)
|
||||
g_warning ("Could not lookup object %s on signal %s of object %s",
|
||||
signal->connect_object_name, signal->name,
|
||||
signal->object_name);
|
||||
g_warning ("Could not lookup object %s on signal %s of object %s.",
|
||||
signal->connect_object_name, signal->name,
|
||||
signal->object_name);
|
||||
}
|
||||
|
||||
|
||||
func (builder, object, signal->name, signal->handler,
|
||||
connect_object, signal->flags, user_data);
|
||||
}
|
||||
|
@@ -133,9 +133,21 @@ guint gtk_builder_add_objects_from_string (GtkBuilder *builder,
|
||||
gsize length,
|
||||
gchar **object_ids,
|
||||
GError **error);
|
||||
guint gtk_builder_add_to_parent_from_file (GtkBuilder *builder,
|
||||
GObject *parent,
|
||||
const gchar *filename,
|
||||
GError **error);
|
||||
guint gtk_builder_add_to_parent_from_string (GtkBuilder *builder,
|
||||
GObject *parent,
|
||||
const gchar *buffer,
|
||||
gsize length,
|
||||
GError **error);
|
||||
GObject* gtk_builder_get_object (GtkBuilder *builder,
|
||||
const gchar *name);
|
||||
GSList* gtk_builder_get_objects (GtkBuilder *builder);
|
||||
void gtk_builder_expose_object (GtkBuilder *builder,
|
||||
const gchar *name,
|
||||
GObject *object);
|
||||
void gtk_builder_connect_signals (GtkBuilder *builder,
|
||||
gpointer user_data);
|
||||
void gtk_builder_connect_signals_full (GtkBuilder *builder,
|
||||
|
@@ -437,6 +437,7 @@ parse_child (ParserData *data,
|
||||
{
|
||||
ObjectInfo* object_info;
|
||||
ChildInfo *child_info;
|
||||
GObject *object;
|
||||
guint i;
|
||||
|
||||
object_info = state_peek_info (data, ObjectInfo);
|
||||
@@ -445,6 +446,9 @@ parse_child (ParserData *data,
|
||||
error_invalid_tag (data, element_name, NULL, error);
|
||||
return;
|
||||
}
|
||||
|
||||
GTK_NOTE (BUILDER, g_print ("parsing child of parent type %s\n",
|
||||
object_info->object ? G_OBJECT_TYPE_NAME (object_info->object) : "(none)"));
|
||||
|
||||
child_info = g_slice_new0 (ChildInfo);
|
||||
state_push (data, child_info);
|
||||
@@ -461,7 +465,9 @@ parse_child (ParserData *data,
|
||||
|
||||
child_info->parent = (CommonInfo*)object_info;
|
||||
|
||||
object_info->object = builder_construct (data, object_info, error);
|
||||
object = builder_construct (data, object_info, error);
|
||||
object_info->object = object;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -483,6 +489,7 @@ parse_property (ParserData *data,
|
||||
gchar *name = NULL;
|
||||
gchar *context = NULL;
|
||||
gboolean translatable = FALSE;
|
||||
gboolean external = FALSE;
|
||||
ObjectInfo *object_info;
|
||||
int i;
|
||||
|
||||
@@ -511,6 +518,11 @@ parse_property (ParserData *data,
|
||||
{
|
||||
context = g_strdup (values[i]);
|
||||
}
|
||||
else if (strcmp (names[i], "external-object") == 0)
|
||||
{
|
||||
if (!_gtk_builder_boolean_from_string (values[i], &external, error))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_invalid_attribute (data, element_name, names[i], error);
|
||||
@@ -525,10 +537,11 @@ parse_property (ParserData *data,
|
||||
}
|
||||
|
||||
info = g_slice_new0 (PropertyInfo);
|
||||
info->name = name;
|
||||
info->name = name;
|
||||
info->translatable = translatable;
|
||||
info->context = context;
|
||||
info->text = g_string_new ("");
|
||||
info->context = context;
|
||||
info->text = g_string_new ("");
|
||||
info->external = external;
|
||||
state_push (data, info);
|
||||
|
||||
info->tag.name = element_name;
|
||||
@@ -556,6 +569,7 @@ parse_signal (ParserData *data,
|
||||
gboolean after = FALSE;
|
||||
gboolean swapped = FALSE;
|
||||
gboolean swapped_set = FALSE;
|
||||
gboolean external = FALSE;
|
||||
ObjectInfo *object_info;
|
||||
int i;
|
||||
|
||||
@@ -583,6 +597,11 @@ parse_signal (ParserData *data,
|
||||
return;
|
||||
swapped_set = TRUE;
|
||||
}
|
||||
else if (strcmp (names[i], "external-object") == 0)
|
||||
{
|
||||
if (!_gtk_builder_boolean_from_string (values[i], &external, error))
|
||||
return;
|
||||
}
|
||||
else if (strcmp (names[i], "object") == 0)
|
||||
object = g_strdup (values[i]);
|
||||
else if (strcmp (names[i], "last_modification_time") == 0)
|
||||
@@ -617,6 +636,7 @@ parse_signal (ParserData *data,
|
||||
info->flags |= G_CONNECT_AFTER;
|
||||
if (swapped)
|
||||
info->flags |= G_CONNECT_SWAPPED;
|
||||
info->external = external;
|
||||
info->connect_object_name = object;
|
||||
state_push (data, info);
|
||||
|
||||
@@ -1113,6 +1133,7 @@ static const GMarkupParser parser = {
|
||||
|
||||
void
|
||||
_gtk_builder_parser_parse_buffer (GtkBuilder *builder,
|
||||
GObject *parent,
|
||||
const gchar *filename,
|
||||
const gchar *buffer,
|
||||
gsize length,
|
||||
@@ -1137,6 +1158,18 @@ _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
|
||||
data->object_ids = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify)g_free, NULL);
|
||||
|
||||
if (parent)
|
||||
{
|
||||
ObjectInfo *object_info = g_slice_new0 (ObjectInfo);
|
||||
|
||||
GTK_NOTE (BUILDER, g_print ("parsing with contextual parent info ptr %p\n", object_info));
|
||||
|
||||
object_info->object = parent;
|
||||
object_info->id = g_strdup ("__container");
|
||||
state_push (data, object_info);
|
||||
object_info->tag.name = "object";
|
||||
}
|
||||
|
||||
data->requested_objects = NULL;
|
||||
if (requested_objs)
|
||||
{
|
||||
|
@@ -57,8 +57,9 @@ typedef struct {
|
||||
gchar *name;
|
||||
GString *text;
|
||||
gchar *data;
|
||||
gboolean translatable;
|
||||
gchar *context;
|
||||
guint8 translatable : 1;
|
||||
guint8 external : 1;
|
||||
} PropertyInfo;
|
||||
|
||||
typedef struct {
|
||||
@@ -66,6 +67,7 @@ typedef struct {
|
||||
gchar *object_name;
|
||||
gchar *name;
|
||||
gchar *handler;
|
||||
gboolean external;
|
||||
GConnectFlags flags;
|
||||
gchar *connect_object_name;
|
||||
} SignalInfo;
|
||||
@@ -109,6 +111,7 @@ typedef GType (*GTypeGetFunc) (void);
|
||||
|
||||
/* Things only GtkBuilder should use */
|
||||
void _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
|
||||
GObject *parent,
|
||||
const gchar *filename,
|
||||
const gchar *buffer,
|
||||
gsize length,
|
||||
|
@@ -67,6 +67,9 @@ static void gtk_container_base_class_init (GtkContainerClass *klass);
|
||||
static void gtk_container_base_class_finalize (GtkContainerClass *klass);
|
||||
static void gtk_container_class_init (GtkContainerClass *klass);
|
||||
static void gtk_container_init (GtkContainer *container);
|
||||
static GObject *gtk_container_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties);
|
||||
static void gtk_container_destroy (GtkObject *object);
|
||||
static void gtk_container_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -181,6 +184,9 @@ gtk_container_base_class_init (GtkContainerClass *class)
|
||||
/* reset instance specifc class fields that don't get inherited */
|
||||
class->set_child_property = NULL;
|
||||
class->get_child_property = NULL;
|
||||
class->tmpl = NULL;
|
||||
class->tmpl_file = NULL;
|
||||
class->connect_func = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -198,6 +204,9 @@ gtk_container_base_class_finalize (GtkContainerClass *class)
|
||||
g_param_spec_unref (pspec);
|
||||
}
|
||||
g_list_free (list);
|
||||
|
||||
g_free (class->tmpl);
|
||||
g_free (class->tmpl_file);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -212,6 +221,7 @@ gtk_container_class_init (GtkContainerClass *class)
|
||||
vadjustment_key_id = g_quark_from_static_string (vadjustment_key);
|
||||
hadjustment_key_id = g_quark_from_static_string (hadjustment_key);
|
||||
|
||||
gobject_class->constructor = gtk_container_constructor;
|
||||
gobject_class->set_property = gtk_container_set_property;
|
||||
gobject_class->get_property = gtk_container_get_property;
|
||||
|
||||
@@ -1025,6 +1035,132 @@ gtk_container_class_list_child_properties (GObjectClass *cclass,
|
||||
return pspecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_container_get_composite_child:
|
||||
* @container: a #GtkContainer
|
||||
* @composite_name: the name of a composite child as defined by installation of a #GtkParamSpecComposite property
|
||||
*
|
||||
* Retrieves a composite child by name by checking installed composite typed properties.
|
||||
*
|
||||
* Returns: the composite child of @container with the name @composite_name
|
||||
*/
|
||||
GtkWidget *
|
||||
gtk_container_get_composite_child (GtkContainer *container,
|
||||
const gchar *composite_name)
|
||||
{
|
||||
GParamSpec **pspecs;
|
||||
guint n_pspecs = 0, i;
|
||||
GtkWidget *composite_child = NULL;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
|
||||
g_return_val_if_fail (composite_name && composite_name[0], NULL);
|
||||
|
||||
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (container), &n_pspecs);
|
||||
for (i = 0; i < n_pspecs; i++)
|
||||
{
|
||||
if (strcmp (pspecs[i]->name, composite_name) == 0)
|
||||
{
|
||||
if (GTK_IS_PARAM_SPEC_COMPOSITE (pspecs[i]) &&
|
||||
(pspecs[i]->flags & G_PARAM_WRITABLE) != 0)
|
||||
{
|
||||
g_object_get (G_OBJECT (container),
|
||||
composite_name, &composite_child,
|
||||
NULL);
|
||||
|
||||
if (composite_child)
|
||||
g_object_unref (composite_child);
|
||||
else
|
||||
g_warning ("Failed to get composite child named %s for type %s",
|
||||
composite_name, G_OBJECT_TYPE_NAME (container));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free (pspecs);
|
||||
|
||||
return composite_child;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_container_class_set_template:
|
||||
* @container_class: a #GtkContainerClass
|
||||
* @tmpl: the #GtkBuilder xml fragment used to build children
|
||||
*
|
||||
* This is used when implementing new composite widget types
|
||||
* to setup a UI template for instances of this type.
|
||||
*
|
||||
* Templates are in the <link linkend="BUILDER-UI">GtkBuilder UI description</link>
|
||||
* format and are used to implement composite widget types in
|
||||
* an automated way.
|
||||
*
|
||||
* Instances with an assigned template will have thier children
|
||||
* built at object construct time.
|
||||
*
|
||||
* The provided xml fragment is expected to start with <child>
|
||||
* instead of <object> and will be parsed with a fresh instance
|
||||
* of the implementing composite widget type in context as the
|
||||
* parent container. The composite instance itself will be exposed
|
||||
* to the GtkBuilder as an external object named "container" and in this way can
|
||||
* be referred to in child signal and property declarations.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
void
|
||||
gtk_container_class_set_template (GtkContainerClass *container_class,
|
||||
const gchar *tmpl)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONTAINER_CLASS(container_class));
|
||||
g_return_if_fail (tmpl && tmpl[0]);
|
||||
|
||||
g_free (container_class->tmpl);
|
||||
g_free (container_class->tmpl_file);
|
||||
|
||||
container_class->tmpl = g_strdup (tmpl);
|
||||
container_class->tmpl_file = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gtk_container_class_set_template_file:
|
||||
* @container_class: a #GtkContainerClass
|
||||
* @tmpl_file: the #GtkBuilder xml file used to build children
|
||||
*
|
||||
* Sets a file to be used as this class's template; see gtk_container_class_set_template().
|
||||
*
|
||||
*/
|
||||
void
|
||||
gtk_container_class_set_template_file (GtkContainerClass *container_class,
|
||||
const gchar *tmpl_file)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONTAINER_CLASS(container_class));
|
||||
g_return_if_fail (tmpl_file && tmpl_file[0]);
|
||||
|
||||
|
||||
g_free (container_class->tmpl);
|
||||
g_free (container_class->tmpl_file);
|
||||
|
||||
container_class->tmpl = NULL;
|
||||
container_class->tmpl_file = g_strdup (tmpl_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_container_class_set_connect_func:
|
||||
* @container_class: a #GtkContainerClass
|
||||
* @connect_func: the #GtkBuilderConnectFunc to use when connecting signals internally.
|
||||
*
|
||||
* Sets the function to be used when automatically connecting signals
|
||||
* defined by this class's GtkBuilder template.
|
||||
*/
|
||||
void
|
||||
gtk_container_class_set_connect_func (GtkContainerClass *container_class,
|
||||
GtkBuilderConnectFunc connect_func)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONTAINER_CLASS(container_class));
|
||||
g_return_if_fail (connect_func != NULL);
|
||||
|
||||
container_class->connect_func = connect_func;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_container_add_unimplemented (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
@@ -1068,6 +1204,94 @@ gtk_container_destroy (GtkObject *object)
|
||||
GTK_OBJECT_CLASS (parent_class)->destroy (object);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
gtk_container_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_properties)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GParamSpec **pspecs;
|
||||
GError *error = NULL;
|
||||
guint ret = 0, n_pspecs = 0, i;
|
||||
GObject *ret_obj;
|
||||
GtkContainer *container;
|
||||
GObjectClass *oclass;
|
||||
GSList *classes = NULL, *l;
|
||||
|
||||
ret_obj = G_OBJECT_CLASS (parent_class)->constructor
|
||||
(type, n_construct_properties, construct_properties);
|
||||
|
||||
container = GTK_CONTAINER (ret_obj);
|
||||
|
||||
/* Collect an ordered list of class which have templates to build */
|
||||
for (oclass = G_OBJECT_GET_CLASS (container);
|
||||
GTK_IS_CONTAINER_CLASS (oclass);
|
||||
oclass = g_type_class_peek_parent (oclass))
|
||||
{
|
||||
|
||||
if (GTK_CONTAINER_CLASS (oclass)->tmpl ||
|
||||
GTK_CONTAINER_CLASS (oclass)->tmpl_file)
|
||||
classes = g_slist_prepend (classes, oclass);
|
||||
}
|
||||
|
||||
/* Build the templates for each class starting with the superclass descending */
|
||||
for (l = classes; l; l = l->next)
|
||||
{
|
||||
GtkContainerClass *cclass = l->data;
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_expose_object (builder, "container", ret_obj);
|
||||
|
||||
if (cclass->tmpl)
|
||||
ret = gtk_builder_add_to_parent_from_string (builder, ret_obj,
|
||||
cclass->tmpl, -1, &error);
|
||||
else
|
||||
ret = gtk_builder_add_to_parent_from_file (builder, ret_obj,
|
||||
cclass->tmpl_file, &error);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
g_critical ("Unable to build GtkContainer class %s from template: %s",
|
||||
G_OBJECT_TYPE_NAME (container),
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (builder);
|
||||
|
||||
return ret_obj;
|
||||
}
|
||||
|
||||
pspecs = g_object_class_list_properties (G_OBJECT_CLASS (cclass), &n_pspecs);
|
||||
for (i = 0; i < n_pspecs; i++)
|
||||
{
|
||||
if (GTK_IS_PARAM_SPEC_COMPOSITE (pspecs[i]) &&
|
||||
pspecs[i]->owner_type == G_OBJECT_CLASS_TYPE (cclass))
|
||||
{
|
||||
GObject *composite_child;
|
||||
|
||||
composite_child = gtk_builder_get_object (builder, (pspecs[i])->name);
|
||||
|
||||
if (composite_child)
|
||||
/* Let GObject fire a warning if there is an object type mismatch */
|
||||
g_object_set (container, (pspecs[i])->name, composite_child, NULL);
|
||||
else
|
||||
g_critical ("Expected internal child %s not found for container class %s",
|
||||
(pspecs[i])->name, G_OBJECT_TYPE_NAME (container));
|
||||
}
|
||||
}
|
||||
g_free (pspecs);
|
||||
|
||||
if (cclass->connect_func)
|
||||
gtk_builder_connect_signals_full (builder, GTK_CONTAINER_GET_CLASS (container)->connect_func, container);
|
||||
else
|
||||
gtk_builder_connect_signals (builder, container);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
g_slist_free (classes);
|
||||
|
||||
return ret_obj;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_container_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -2685,5 +2909,121 @@ gtk_container_propagate_expose (GtkContainer *container,
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- Declaration of GtkParamSpecComposite
|
||||
*/
|
||||
static void
|
||||
param_composite_init (GParamSpec *pspec)
|
||||
{
|
||||
/* GtkParamSpecComposite *ospec = GTK_PARAM_SPEC_COMPOSITE (pspec); */
|
||||
}
|
||||
|
||||
static void
|
||||
param_composite_set_default (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
{
|
||||
value->data[0].v_pointer = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
param_composite_validate (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
{
|
||||
GtkParamSpecComposite *ospec = GTK_PARAM_SPEC_COMPOSITE (pspec);
|
||||
GObject *object = value->data[0].v_pointer;
|
||||
guint changed = 0;
|
||||
|
||||
if (object && !g_value_type_compatible (G_OBJECT_TYPE (object), G_PARAM_SPEC_VALUE_TYPE (ospec)))
|
||||
{
|
||||
g_object_unref (object);
|
||||
value->data[0].v_pointer = NULL;
|
||||
changed++;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static gint
|
||||
param_composite_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
|
||||
gtk_param_composite_get_type (void)
|
||||
{
|
||||
static GType composite_type = 0;
|
||||
|
||||
if (composite_type == 0)
|
||||
{
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GtkParamSpecComposite), /* instance_size */
|
||||
0, /* n_preallocs */
|
||||
param_composite_init, /* instance_init */
|
||||
G_TYPE_OBJECT, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_composite_set_default, /* value_set_default */
|
||||
param_composite_validate, /* value_validate */
|
||||
param_composite_values_cmp, /* values_cmp */
|
||||
};
|
||||
composite_type =
|
||||
g_param_type_register_static (g_intern_static_string ("GtkParamComposite"), &pspec_info);
|
||||
}
|
||||
return composite_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_param_spec_composite:
|
||||
* @name: canonical name of the property specified
|
||||
* @nick: nick name for the property specified
|
||||
* @blurb: description of the property specified
|
||||
* @object_type: %G_TYPE_OBJECT derived type of this property
|
||||
*
|
||||
* Creates a new #GtkParamSpecComposite instance specifying a %G_TYPE_OBJECT
|
||||
* derived property, these work exactly the same as #GParamSpecObject properties
|
||||
* except that #GtkContainer will automatically assign all properties defined
|
||||
* as composite object properties to instances built from the composite derived
|
||||
* class's #GtkBuilder UI template.
|
||||
*
|
||||
* See g_param_spec_internal() for details on property names.
|
||||
*
|
||||
* Composite child properties must all be writable a rule but can be private
|
||||
* if they are declared without the readable flag.
|
||||
* Dynamic widget contents should generally not be advertized as composite children
|
||||
* although at times they can be writable for the purpose of being overridden by a
|
||||
* third party. Such dynamic composite children should not be refferred to by child
|
||||
* UIs that extend a widget, but can be mentioned in templates which include a widget
|
||||
* and override it's child.
|
||||
*
|
||||
* Returns: a newly created parameter specification
|
||||
*/
|
||||
GParamSpec*
|
||||
gtk_param_spec_composite (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
GType object_type,
|
||||
GParamFlags flags)
|
||||
{
|
||||
GParamSpecObject *ospec;
|
||||
|
||||
g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
|
||||
|
||||
ospec = g_param_spec_internal (GTK_TYPE_PARAM_COMPOSITE,
|
||||
name,
|
||||
nick,
|
||||
blurb,
|
||||
flags | G_PARAM_WRITABLE);
|
||||
|
||||
G_PARAM_SPEC (ospec)->value_type = object_type;
|
||||
|
||||
return G_PARAM_SPEC (ospec);
|
||||
}
|
||||
|
||||
#define __GTK_CONTAINER_C__
|
||||
#include "gtkaliasdef.c"
|
||||
|
@@ -34,10 +34,44 @@
|
||||
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include <gtk/gtkadjustment.h>
|
||||
#include <gtk/gtkbuilder.h>
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GTK_TYPE_PARAM_COMPOSITE:
|
||||
*
|
||||
* The #GType of #GtkParamSpecComposite.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
#define GTK_TYPE_PARAM_COMPOSITE (gtk_param_composite_get_type())
|
||||
|
||||
/**
|
||||
* GTK_IS_PARAM_SPEC_COMPOSITE:
|
||||
* @pspec: a valid #GParamSpec instance
|
||||
*
|
||||
* Checks whether the given #GParamSpec is of type %GTK_TYPE_PARAM_COMPOSITE.
|
||||
*
|
||||
* Returns: %TRUE on success.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
#define GTK_IS_PARAM_SPEC_COMPOSITE(pspec) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GTK_TYPE_PARAM_COMPOSITE))
|
||||
|
||||
/**
|
||||
* GTK_PARAM_SPEC_COMPOSITE:
|
||||
* @pspec: a valid #GParamSpec instance
|
||||
*
|
||||
* Casts a #GParamSpec instance into a #GtkParamSpecComposite.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
#define GTK_PARAM_SPEC_COMPOSITE(pspec) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((pspec), GTK_TYPE_PARAM_COMPOSITE, GtkParamSpecComposite))
|
||||
|
||||
#define GTK_TYPE_CONTAINER (gtk_container_get_type ())
|
||||
#define GTK_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CONTAINER, GtkContainer))
|
||||
#define GTK_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CONTAINER, GtkContainerClass))
|
||||
@@ -48,8 +82,22 @@ G_BEGIN_DECLS
|
||||
#define GTK_IS_RESIZE_CONTAINER(widget) (GTK_IS_CONTAINER (widget) && ((GtkContainer*) (widget))->resize_mode != GTK_RESIZE_PARENT)
|
||||
|
||||
|
||||
typedef struct _GtkContainer GtkContainer;
|
||||
typedef struct _GtkContainerClass GtkContainerClass;
|
||||
typedef struct _GtkContainer GtkContainer;
|
||||
typedef struct _GtkContainerClass GtkContainerClass;
|
||||
typedef struct _GtkParamSpecComposite GtkParamSpecComposite;
|
||||
|
||||
/**
|
||||
* GtkParamSpecComposite:
|
||||
* @parent_instance: private #GParamSpec portion
|
||||
*
|
||||
* A #GParamSpec derived structure that contains the meta data for composite child object properties.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
struct _GtkParamSpecComposite
|
||||
{
|
||||
GParamSpec parent_instance;
|
||||
};
|
||||
|
||||
struct _GtkContainer
|
||||
{
|
||||
@@ -95,15 +143,24 @@ struct _GtkContainerClass
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
/* GtkBuilder templates for automated composite classes */
|
||||
gchar *GSEAL (tmpl);
|
||||
gchar *GSEAL (tmpl_file);
|
||||
GtkBuilderConnectFunc GSEAL (connect_func);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
};
|
||||
|
||||
/* Application-level methods */
|
||||
|
||||
GType gtk_param_composite_get_type (void) G_GNUC_CONST;
|
||||
GParamSpec *gtk_param_spec_composite (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
GType object_type,
|
||||
GParamFlags flags);
|
||||
|
||||
GType gtk_container_get_type (void) G_GNUC_CONST;
|
||||
void gtk_container_set_border_width (GtkContainer *container,
|
||||
guint border_width);
|
||||
@@ -198,6 +255,17 @@ void gtk_container_forall (GtkContainer *container,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data);
|
||||
|
||||
GtkWidget *gtk_container_get_composite_child (GtkContainer *container,
|
||||
const gchar *composite_name);
|
||||
|
||||
/* Class-level functions */
|
||||
void gtk_container_class_set_template (GtkContainerClass *container_class,
|
||||
const gchar *tmpl);
|
||||
void gtk_container_class_set_template_file (GtkContainerClass *container_class,
|
||||
const gchar *tmpl_file);
|
||||
void gtk_container_class_set_connect_func (GtkContainerClass *container_class,
|
||||
GtkBuilderConnectFunc connect_func);
|
||||
|
||||
/* Non-public methods */
|
||||
void _gtk_container_queue_resize (GtkContainer *container);
|
||||
void _gtk_container_clear_resize_widgets (GtkContainer *container);
|
||||
|
141
gtk/gtkdialog.c
141
gtk/gtkdialog.c
@@ -81,9 +81,6 @@ static ResponseData * get_response_data (GtkWidget *widget,
|
||||
gboolean create);
|
||||
|
||||
static void gtk_dialog_buildable_interface_init (GtkBuildableIface *iface);
|
||||
static GObject * gtk_dialog_buildable_get_internal_child (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
const gchar *childname);
|
||||
static gboolean gtk_dialog_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
@@ -97,9 +94,44 @@ static void gtk_dialog_buildable_custom_finished (GtkBuildable *buildab
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
static const gchar *gtk_dialog_template =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<interface>"
|
||||
" <requires lib=\"gtk+\" version=\"2.20\"/>"
|
||||
" <child>"
|
||||
" <object class=\"GtkVBox\" id=\"vbox\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <child>"
|
||||
" <object class=\"GtkHSeparator\" id=\"separator\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" </object>"
|
||||
" <packing>"
|
||||
" <property name=\"expand\">False</property>"
|
||||
" <property name=\"pack_type\">end</property>"
|
||||
" <property name=\"position\">1</property>"
|
||||
" </packing>"
|
||||
" </child>"
|
||||
" <child>"
|
||||
" <object class=\"GtkHButtonBox\" id=\"action-area\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <property name=\"layout_style\">end</property>"
|
||||
" </object>"
|
||||
" <packing>"
|
||||
" <property name=\"expand\">False</property>"
|
||||
" <property name=\"pack_type\">end</property>"
|
||||
" <property name=\"position\">0</property>"
|
||||
" </packing>"
|
||||
" </child>"
|
||||
" </object>"
|
||||
" </child>"
|
||||
"</interface>";
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_HAS_SEPARATOR
|
||||
PROP_HAS_SEPARATOR,
|
||||
PROP_SEPARATOR,
|
||||
PROP_VBOX,
|
||||
PROP_ACTION_AREA
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -147,6 +179,51 @@ gtk_dialog_class_init (GtkDialogClass *class)
|
||||
TRUE,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* GtkDialog:separator:
|
||||
*
|
||||
* The separator above the action buttons.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SEPARATOR,
|
||||
gtk_param_spec_composite ("separator",
|
||||
P_("Separator"),
|
||||
P_("The separator above the action buttons"),
|
||||
GTK_TYPE_SEPARATOR,
|
||||
GTK_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/**
|
||||
* GtkDialog:vbox:
|
||||
*
|
||||
* The dialog content area.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_VBOX,
|
||||
gtk_param_spec_composite ("vbox",
|
||||
P_("Content Area"),
|
||||
P_("The dialog content area"),
|
||||
GTK_TYPE_BOX,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/**
|
||||
* GtkDialog:action-area:
|
||||
*
|
||||
* The dialog action area.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ACTION_AREA,
|
||||
gtk_param_spec_composite ("action-area",
|
||||
P_("Action Area"),
|
||||
P_("The dialog action area"),
|
||||
GTK_TYPE_BUTTON_BOX,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/**
|
||||
* GtkDialog::response:
|
||||
* @dialog: the object on which the signal is emitted
|
||||
@@ -233,6 +310,8 @@ gtk_dialog_class_init (GtkDialogClass *class)
|
||||
binding_set = gtk_binding_set_by_class (class);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, "close", 0);
|
||||
|
||||
gtk_container_class_set_template (GTK_CONTAINER_CLASS (class), gtk_dialog_template);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -280,24 +359,6 @@ gtk_dialog_init (GtkDialog *dialog)
|
||||
G_CALLBACK (gtk_dialog_delete_event_handler),
|
||||
NULL);
|
||||
|
||||
dialog->vbox = gtk_vbox_new (FALSE, 0);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox);
|
||||
gtk_widget_show (dialog->vbox);
|
||||
|
||||
dialog->action_area = gtk_hbutton_box_new ();
|
||||
|
||||
gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog->action_area),
|
||||
GTK_BUTTONBOX_END);
|
||||
|
||||
gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_area,
|
||||
FALSE, TRUE, 0);
|
||||
gtk_widget_show (dialog->action_area);
|
||||
|
||||
dialog->separator = gtk_hseparator_new ();
|
||||
gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->separator, FALSE, TRUE, 0);
|
||||
gtk_widget_show (dialog->separator);
|
||||
|
||||
gtk_window_set_type_hint (GTK_WINDOW (dialog),
|
||||
GDK_WINDOW_TYPE_HINT_DIALOG);
|
||||
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
|
||||
@@ -309,26 +370,10 @@ static void
|
||||
gtk_dialog_buildable_interface_init (GtkBuildableIface *iface)
|
||||
{
|
||||
parent_buildable_iface = g_type_interface_peek_parent (iface);
|
||||
iface->get_internal_child = gtk_dialog_buildable_get_internal_child;
|
||||
iface->custom_tag_start = gtk_dialog_buildable_custom_tag_start;
|
||||
iface->custom_finished = gtk_dialog_buildable_custom_finished;
|
||||
}
|
||||
|
||||
static GObject *
|
||||
gtk_dialog_buildable_get_internal_child (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
const gchar *childname)
|
||||
{
|
||||
if (strcmp (childname, "vbox") == 0)
|
||||
return G_OBJECT (GTK_DIALOG (buildable)->vbox);
|
||||
else if (strcmp (childname, "action_area") == 0)
|
||||
return G_OBJECT (GTK_DIALOG (buildable)->action_area);
|
||||
|
||||
return parent_buildable_iface->get_internal_child (buildable,
|
||||
builder,
|
||||
childname);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_dialog_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -345,6 +390,18 @@ gtk_dialog_set_property (GObject *object,
|
||||
gtk_dialog_set_has_separator (dialog, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_SEPARATOR:
|
||||
dialog->separator = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
case PROP_VBOX:
|
||||
dialog->vbox = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
case PROP_ACTION_AREA:
|
||||
dialog->action_area = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -367,6 +424,14 @@ gtk_dialog_get_property (GObject *object,
|
||||
g_value_set_boolean (value, dialog->separator != NULL);
|
||||
break;
|
||||
|
||||
case PROP_VBOX:
|
||||
g_value_set_object (value, dialog->vbox);
|
||||
break;
|
||||
|
||||
case PROP_ACTION_AREA:
|
||||
g_value_set_object (value, dialog->action_area);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@@ -3084,7 +3084,7 @@ get_label_wrap_width (GtkLabel *label)
|
||||
PangoLayout *layout;
|
||||
|
||||
layout = gtk_widget_create_pango_layout (GTK_WIDGET (label),
|
||||
"This string is just about long enough.");
|
||||
"The minimum width for a wrapping label is long enough for a dialog");
|
||||
pango_layout_get_size (layout, &priv->wrap_width, NULL);
|
||||
g_object_unref (layout);
|
||||
}
|
||||
|
@@ -95,23 +95,100 @@ struct _GtkMessageDialogPrivate
|
||||
{
|
||||
GtkWidget *secondary_label;
|
||||
guint message_type : 3;
|
||||
guint buttons_type : 3;
|
||||
guint has_primary_markup : 1;
|
||||
guint has_secondary_text : 1;
|
||||
};
|
||||
|
||||
static void gtk_message_dialog_style_set (GtkWidget *widget,
|
||||
GtkStyle *prev_style);
|
||||
static void gtk_message_dialog_style_set (GtkWidget *widget,
|
||||
GtkStyle *prev_style);
|
||||
static GObject *gtk_message_dialog_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_params);
|
||||
static void gtk_message_dialog_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gtk_message_dialog_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gtk_message_dialog_add_buttons (GtkMessageDialog *message_dialog,
|
||||
GtkButtonsType buttons);
|
||||
|
||||
static void gtk_message_dialog_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gtk_message_dialog_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gtk_message_dialog_add_buttons (GtkMessageDialog *message_dialog,
|
||||
GtkButtonsType buttons);
|
||||
static const gchar *gtk_message_dialog_template =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<interface>"
|
||||
" <requires lib=\"gtk+\" version=\"2.20\"/>"
|
||||
" <child internal-child=\"vbox\">"
|
||||
" <object class=\"GtkVBox\" id=\"vbox\">"
|
||||
" <property name=\"spacing\">14</property>"
|
||||
" <child>"
|
||||
" <object class=\"GtkHBox\" id=\"hbox1\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <property name=\"border_width\">5</property>"
|
||||
" <property name=\"spacing\">12</property>"
|
||||
" <child>"
|
||||
" <object class=\"GtkImage\" id=\"image\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <property name=\"yalign\">0</property>"
|
||||
" <property name=\"icon-size\">6</property>"
|
||||
" </object>"
|
||||
" <packing>"
|
||||
" <property name=\"expand\">False</property>"
|
||||
" <property name=\"fill\">False</property>"
|
||||
" <property name=\"position\">0</property>"
|
||||
" </packing>"
|
||||
" </child>"
|
||||
" <child>"
|
||||
" <object class=\"GtkVBox\" id=\"vbox1\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <property name=\"spacing\">12</property>"
|
||||
" <child>"
|
||||
" <object class=\"GtkLabel\" id=\"label\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <property name=\"xalign\">0</property>"
|
||||
" <property name=\"yalign\">0</property>"
|
||||
" <property name=\"label\" translatable=\"yes\">primary message</property>"
|
||||
" <property name=\"wrap\">True</property>"
|
||||
" <property name=\"selectable\">True</property>"
|
||||
" </object>"
|
||||
" <packing>"
|
||||
" <property name=\"expand\">False</property>"
|
||||
" <property name=\"fill\">False</property>"
|
||||
" <property name=\"position\">0</property>"
|
||||
" </packing>"
|
||||
" </child>"
|
||||
" <child>"
|
||||
" <object class=\"GtkLabel\" id=\"secondary-label\">"
|
||||
" <property name=\"visible\">False</property>"
|
||||
" <property name=\"no_show_all\">True</property>"
|
||||
" <property name=\"xalign\">0</property>"
|
||||
" <property name=\"yalign\">0</property>"
|
||||
" <property name=\"label\" translatable=\"yes\">secondary message</property>"
|
||||
" <property name=\"wrap\">True</property>"
|
||||
" <property name=\"selectable\">True</property>"
|
||||
" </object>"
|
||||
" <packing>"
|
||||
" <property name=\"position\">1</property>"
|
||||
" </packing>"
|
||||
" </child>"
|
||||
" </object>"
|
||||
" <packing>"
|
||||
" <property name=\"position\">1</property>"
|
||||
" </packing>"
|
||||
" </child>"
|
||||
" </object>"
|
||||
" </child>"
|
||||
" </object>"
|
||||
" </child>"
|
||||
" <child internal-child=\"action-area\">"
|
||||
" <object class=\"GtkHButtonBox\" id=\"action-area\">"
|
||||
" <property name=\"border_width\">5</property>"
|
||||
" <property name=\"spacing\">6</property>"
|
||||
" </object>"
|
||||
" </child>"
|
||||
"</interface>";
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
@@ -121,7 +198,9 @@ enum {
|
||||
PROP_USE_MARKUP,
|
||||
PROP_SECONDARY_TEXT,
|
||||
PROP_SECONDARY_USE_MARKUP,
|
||||
PROP_IMAGE
|
||||
PROP_IMAGE,
|
||||
PROP_LABEL,
|
||||
PROP_SECONDARY_LABEL
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkMessageDialog, gtk_message_dialog, GTK_TYPE_DIALOG)
|
||||
@@ -137,6 +216,7 @@ gtk_message_dialog_class_init (GtkMessageDialogClass *class)
|
||||
|
||||
widget_class->style_set = gtk_message_dialog_style_set;
|
||||
|
||||
gobject_class->constructor = gtk_message_dialog_constructor;
|
||||
gobject_class->set_property = gtk_message_dialog_set_property;
|
||||
gobject_class->get_property = gtk_message_dialog_get_property;
|
||||
|
||||
@@ -176,7 +256,7 @@ gtk_message_dialog_class_init (GtkMessageDialogClass *class)
|
||||
P_("The type of message"),
|
||||
GTK_TYPE_MESSAGE_TYPE,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
GTK_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_BUTTONS,
|
||||
g_param_spec_enum ("buttons",
|
||||
@@ -258,20 +338,54 @@ gtk_message_dialog_class_init (GtkMessageDialogClass *class)
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_IMAGE,
|
||||
g_param_spec_object ("image",
|
||||
P_("Image"),
|
||||
P_("The image"),
|
||||
GTK_TYPE_WIDGET,
|
||||
GTK_PARAM_READWRITE));
|
||||
gtk_param_spec_composite ("image",
|
||||
P_("Image"),
|
||||
P_("The image"),
|
||||
GTK_TYPE_WIDGET,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
|
||||
/**
|
||||
* GtkMessageDialog:label:
|
||||
*
|
||||
* The message label for this dialog.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_LABEL,
|
||||
gtk_param_spec_composite ("label",
|
||||
P_("Label"),
|
||||
P_("The label"),
|
||||
GTK_TYPE_LABEL,
|
||||
GTK_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/**
|
||||
* GtkMessageDialog:secondary-label:
|
||||
*
|
||||
* The secondary message label for this dialog.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SECONDARY_LABEL,
|
||||
gtk_param_spec_composite ("secondary-label",
|
||||
P_("Secondary Label"),
|
||||
P_("The secondary message label"),
|
||||
GTK_TYPE_LABEL,
|
||||
GTK_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
|
||||
g_type_class_add_private (gobject_class,
|
||||
sizeof (GtkMessageDialogPrivate));
|
||||
|
||||
gtk_container_class_set_template (GTK_CONTAINER_CLASS (class), gtk_message_dialog_template);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_message_dialog_init (GtkMessageDialog *dialog)
|
||||
{
|
||||
GtkWidget *hbox, *vbox;
|
||||
GtkMessageDialogPrivate *priv;
|
||||
|
||||
priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (dialog);
|
||||
@@ -282,47 +396,8 @@ gtk_message_dialog_init (GtkMessageDialog *dialog)
|
||||
|
||||
priv->has_primary_markup = FALSE;
|
||||
priv->has_secondary_text = FALSE;
|
||||
priv->secondary_label = gtk_label_new (NULL);
|
||||
gtk_widget_set_no_show_all (priv->secondary_label, TRUE);
|
||||
|
||||
dialog->label = gtk_label_new (NULL);
|
||||
dialog->image = gtk_image_new_from_stock (NULL, GTK_ICON_SIZE_DIALOG);
|
||||
gtk_misc_set_alignment (GTK_MISC (dialog->image), 0.5, 0.0);
|
||||
|
||||
gtk_label_set_line_wrap (GTK_LABEL (dialog->label), TRUE);
|
||||
gtk_label_set_selectable (GTK_LABEL (dialog->label), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (dialog->label), 0.0, 0.0);
|
||||
|
||||
gtk_label_set_line_wrap (GTK_LABEL (priv->secondary_label), TRUE);
|
||||
gtk_label_set_selectable (GTK_LABEL (priv->secondary_label), TRUE);
|
||||
gtk_misc_set_alignment (GTK_MISC (priv->secondary_label), 0.0, 0.0);
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 12);
|
||||
vbox = gtk_vbox_new (FALSE, 12);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), dialog->label,
|
||||
FALSE, FALSE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), priv->secondary_label,
|
||||
TRUE, TRUE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (hbox), dialog->image,
|
||||
FALSE, FALSE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox,
|
||||
TRUE, TRUE, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
|
||||
hbox,
|
||||
FALSE, FALSE, 0);
|
||||
|
||||
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
|
||||
gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14); /* 14 + 2 * 5 = 24 */
|
||||
gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5);
|
||||
gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
|
||||
|
||||
gtk_widget_show_all (hbox);
|
||||
|
||||
_gtk_dialog_set_ignore_separator (GTK_DIALOG (dialog), TRUE);
|
||||
}
|
||||
@@ -404,6 +479,30 @@ setup_type (GtkMessageDialog *dialog,
|
||||
}
|
||||
}
|
||||
|
||||
static GObject *
|
||||
gtk_message_dialog_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GObject *object;
|
||||
GtkMessageDialog *dialog;
|
||||
GtkMessageDialogPrivate *priv;
|
||||
|
||||
object =
|
||||
G_OBJECT_CLASS (gtk_message_dialog_parent_class)->constructor (type,
|
||||
n_construct_properties,
|
||||
construct_params);
|
||||
|
||||
dialog = GTK_MESSAGE_DIALOG (object);
|
||||
priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (dialog);
|
||||
|
||||
/* Setup widget's now that they've been built */
|
||||
setup_type (dialog, priv->message_type);
|
||||
gtk_message_dialog_add_buttons (dialog, priv->buttons_type);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_message_dialog_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -419,10 +518,17 @@ gtk_message_dialog_set_property (GObject *object,
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MESSAGE_TYPE:
|
||||
setup_type (dialog, g_value_get_enum (value));
|
||||
|
||||
if (dialog->image)
|
||||
setup_type (dialog, g_value_get_enum (value));
|
||||
else
|
||||
/* Deffer assignment at construct time until image is built */
|
||||
priv->message_type = g_value_get_enum (value);
|
||||
|
||||
break;
|
||||
|
||||
case PROP_BUTTONS:
|
||||
gtk_message_dialog_add_buttons (dialog, g_value_get_enum (value));
|
||||
priv->buttons_type = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_TEXT:
|
||||
if (priv->has_primary_markup)
|
||||
@@ -467,6 +573,12 @@ gtk_message_dialog_set_property (GObject *object,
|
||||
case PROP_IMAGE:
|
||||
gtk_message_dialog_set_image (dialog, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_LABEL:
|
||||
dialog->label = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_SECONDARY_LABEL:
|
||||
priv->secondary_label = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
@@ -685,12 +797,19 @@ gtk_message_dialog_set_image (GtkMessageDialog *dialog,
|
||||
|
||||
priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (dialog);
|
||||
|
||||
priv->message_type = GTK_MESSAGE_OTHER;
|
||||
/* Only change the message type and the image if
|
||||
* the image is not already in the dialog (which is
|
||||
* the case when GtkBuilder builds the image).
|
||||
*/
|
||||
if (dialog->image && dialog->image != image)
|
||||
{
|
||||
priv->message_type = GTK_MESSAGE_OTHER;
|
||||
|
||||
parent = dialog->image->parent;
|
||||
gtk_container_add (GTK_CONTAINER (parent), image);
|
||||
gtk_container_remove (GTK_CONTAINER (parent), dialog->image);
|
||||
gtk_box_reorder_child (GTK_BOX (parent), image, 0);
|
||||
parent = dialog->image->parent;
|
||||
gtk_container_add (GTK_CONTAINER (parent), image);
|
||||
gtk_container_remove (GTK_CONTAINER (parent), dialog->image);
|
||||
gtk_box_reorder_child (GTK_BOX (parent), image, 0);
|
||||
}
|
||||
|
||||
dialog->image = image;
|
||||
|
||||
|
Reference in New Issue
Block a user