X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcelllayout.c;h=b34bb24de6c007c3f4a46f05470ce49a060d0317;hb=9d0febc9a64a5bfb0fcfc3a88de4757f6c1ff090;hp=49b2ec4d4675282d8e7b02f5dd529663c1e8e9cf;hpb=5984fa007333e6c70db2491e0fae1059d493ce54;p=~andy%2Fgtk
diff --git a/gtk/gtkcelllayout.c b/gtk/gtkcelllayout.c
index 49b2ec4d4..b34bb24de 100644
--- a/gtk/gtkcelllayout.c
+++ b/gtk/gtkcelllayout.c
@@ -12,9 +12,7 @@
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see .
*/
/**
@@ -83,6 +81,55 @@
*
*
*
+ *
+ *
+ * Subclassing GtkCellLayout implementations
+ *
+ * When subclassing a widget that implements #GtkCellLayout like
+ * #GtkIconView or #GtkComboBox, there are some considerations related
+ * to the fact that these widgets internally use a #GtkCellArea.
+ * The cell area is exposed as a construct-only property by these
+ * widgets. This means that it is possible to e.g. do
+ *
+ * combo = g_object_new (GTK_TYPE_COMBO_BOX, "cell-area", my_cell_area, NULL);
+ *
+ * to use a custom cell area with a combo box. But construct properties
+ * are only initialized after instance init()
+ * functions have run, which means that using functions which rely on
+ * the existence of the cell area in your subclass' init() function will
+ * cause the default cell area to be instantiated. In this case, a provided
+ * construct property value will be ignored (with a warning, to alert
+ * you to the problem).
+ *
+ * static void
+ * my_combo_box_init (MyComboBox *b)
+ * {
+ * GtkCellRenderer *cell;
+ *
+ * cell = gtk_cell_renderer_pixbuf_new ();
+ * /* The following call causes the default cell area for combo boxes,
+ * * a GtkCellAreaBox, to be instantiated
+ * */
+ * gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (b), cell, FALSE);
+ * ...
+ * }
+ *
+ * GtkWidget *
+ * my_combo_box_new (GtkCellArea *area)
+ * {
+ * /* This call is going to cause a warning
+ * * about area being ignored
+ * */
+ * return g_object_new (MY_TYPE_COMBO_BOX, "cell-area", area, NULL);
+ * }
+ *
+ * If supporting alternative cell areas with your derived widget is
+ * not important, then this does not have to concern you. If you want
+ * to support alternative cell areas, you can do so by moving the
+ * problematic calls out of init() and into a constructor()
+ * for your class.
+ *
+ *
*/
#include "config.h"
@@ -93,16 +140,220 @@
#include "gtkbuilderprivate.h"
#include "gtkintl.h"
+#define warn_no_cell_area(func) \
+ g_critical ("%s: Called but no GtkCellArea is available yet", func)
typedef GtkCellLayoutIface GtkCellLayoutInterface;
G_DEFINE_INTERFACE (GtkCellLayout, gtk_cell_layout, G_TYPE_OBJECT);
+static void gtk_cell_layout_default_pack_start (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ gboolean expand);
+static void gtk_cell_layout_default_pack_end (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ gboolean expand);
+static void gtk_cell_layout_default_clear (GtkCellLayout *cell_layout);
+static void gtk_cell_layout_default_add_attribute (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ const gchar *attribute,
+ gint column);
+static void gtk_cell_layout_default_set_cell_data_func (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ GtkCellLayoutDataFunc func,
+ gpointer func_data,
+ GDestroyNotify destroy);
+static void gtk_cell_layout_default_clear_attributes (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell);
+static void gtk_cell_layout_default_reorder (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ gint position);
+static GList *gtk_cell_layout_default_get_cells (GtkCellLayout *cell_layout);
+
+
+static void
+gtk_cell_layout_default_init (GtkCellLayoutIface *iface)
+{
+ iface->pack_start = gtk_cell_layout_default_pack_start;
+ iface->pack_end = gtk_cell_layout_default_pack_end;
+ iface->clear = gtk_cell_layout_default_clear;
+ iface->add_attribute = gtk_cell_layout_default_add_attribute;
+ iface->set_cell_data_func = gtk_cell_layout_default_set_cell_data_func;
+ iface->clear_attributes = gtk_cell_layout_default_clear_attributes;
+ iface->reorder = gtk_cell_layout_default_reorder;
+ iface->get_cells = gtk_cell_layout_default_get_cells;
+}
+
+/* Default implementation is to fall back on an underlying cell area */
+static void
+gtk_cell_layout_default_pack_start (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ gboolean expand)
+{
+ GtkCellLayoutIface *iface;
+ GtkCellArea *area;
+
+ iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
+
+ if (iface->get_area)
+ {
+ area = iface->get_area (cell_layout);
+
+ if (area)
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (area), cell, expand);
+ else
+ warn_no_cell_area ("GtkCellLayoutIface->pack_start()");
+ }
+}
+
+static void
+gtk_cell_layout_default_pack_end (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ gboolean expand)
+{
+ GtkCellLayoutIface *iface;
+ GtkCellArea *area;
+
+ iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
+
+ if (iface->get_area)
+ {
+ area = iface->get_area (cell_layout);
+
+ if (area)
+ gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (area), cell, expand);
+ else
+ warn_no_cell_area ("GtkCellLayoutIface->pack_end()");
+ }
+}
static void
-gtk_cell_layout_default_init (GtkCellLayoutInterface *iface)
+gtk_cell_layout_default_clear (GtkCellLayout *cell_layout)
{
+ GtkCellLayoutIface *iface;
+ GtkCellArea *area;
+
+ iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
+
+ if (iface->get_area)
+ {
+ area = iface->get_area (cell_layout);
+
+ if (area)
+ gtk_cell_layout_clear (GTK_CELL_LAYOUT (area));
+ else
+ warn_no_cell_area ("GtkCellLayoutIface->clear()");
+ }
}
+static void
+gtk_cell_layout_default_add_attribute (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ const gchar *attribute,
+ gint column)
+{
+ GtkCellLayoutIface *iface;
+ GtkCellArea *area;
+
+ iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
+
+ if (iface->get_area)
+ {
+ area = iface->get_area (cell_layout);
+
+ if (area)
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (area), cell, attribute, column);
+ else
+ warn_no_cell_area ("GtkCellLayoutIface->add_attribute()");
+ }
+}
+
+static void
+gtk_cell_layout_default_set_cell_data_func (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ GtkCellLayoutDataFunc func,
+ gpointer func_data,
+ GDestroyNotify destroy)
+{
+ GtkCellLayoutIface *iface;
+ GtkCellArea *area;
+
+ iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
+
+ if (iface->get_area)
+ {
+ area = iface->get_area (cell_layout);
+
+ if (area)
+ _gtk_cell_area_set_cell_data_func_with_proxy (area, cell,
+ (GFunc)func, func_data, destroy,
+ cell_layout);
+ else
+ warn_no_cell_area ("GtkCellLayoutIface->set_cell_data_func()");
+ }
+}
+
+static void
+gtk_cell_layout_default_clear_attributes (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell)
+{
+ GtkCellLayoutIface *iface;
+ GtkCellArea *area;
+
+ iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
+
+ if (iface->get_area)
+ {
+ area = iface->get_area (cell_layout);
+
+ if (area)
+ gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (area), cell);
+ else
+ warn_no_cell_area ("GtkCellLayoutIface->clear_attributes()");
+ }
+}
+
+static void
+gtk_cell_layout_default_reorder (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ gint position)
+{
+ GtkCellLayoutIface *iface;
+ GtkCellArea *area;
+
+ iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
+
+ if (iface->get_area)
+ {
+ area = iface->get_area (cell_layout);
+
+ if (area)
+ gtk_cell_layout_reorder (GTK_CELL_LAYOUT (area), cell, position);
+ else
+ warn_no_cell_area ("GtkCellLayoutIface->reorder()");
+ }
+}
+
+static GList *
+gtk_cell_layout_default_get_cells (GtkCellLayout *cell_layout)
+{
+ GtkCellLayoutIface *iface;
+ GtkCellArea *area;
+
+ iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
+
+ if (iface->get_area)
+ {
+ area = iface->get_area (cell_layout);
+
+ if (area)
+ return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (area));
+ else
+ warn_no_cell_area ("GtkCellLayoutIface->get_cells()");
+ }
+ return NULL;
+}
+
+
/**
* gtk_cell_layout_pack_start:
* @cell_layout: a #GtkCellLayout
@@ -122,23 +373,10 @@ gtk_cell_layout_pack_start (GtkCellLayout *cell_layout,
GtkCellRenderer *cell,
gboolean expand)
{
- GtkCellLayoutIface *iface;
- GtkCellArea *area;
-
g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
- iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
-
- if (iface->pack_start)
- iface->pack_start (cell_layout, cell, expand);
- else
- {
- area = iface->get_area (cell_layout);
-
- if (area)
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (area), cell, expand);
- }
+ GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->pack_start (cell_layout, cell, expand);
}
/**
@@ -160,23 +398,10 @@ gtk_cell_layout_pack_end (GtkCellLayout *cell_layout,
GtkCellRenderer *cell,
gboolean expand)
{
- GtkCellLayoutIface *iface;
- GtkCellArea *area;
-
g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
- iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
-
- if (iface->pack_end)
- iface->pack_end (cell_layout, cell, expand);
- else
- {
- area = iface->get_area (cell_layout);
-
- if (area)
- gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (area), cell, expand);
- }
+ GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->pack_end (cell_layout, cell, expand);
}
/**
@@ -191,22 +416,9 @@ gtk_cell_layout_pack_end (GtkCellLayout *cell_layout,
void
gtk_cell_layout_clear (GtkCellLayout *cell_layout)
{
- GtkCellLayoutIface *iface;
- GtkCellArea *area;
-
g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
- iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
-
- if (iface->clear)
- iface->clear (cell_layout);
- else
- {
- area = iface->get_area (cell_layout);
-
- if (area)
- gtk_cell_layout_clear (GTK_CELL_LAYOUT (area));
- }
+ GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->clear (cell_layout);
}
static void
@@ -216,28 +428,16 @@ gtk_cell_layout_set_attributesv (GtkCellLayout *cell_layout,
{
gchar *attribute;
gint column;
- GtkCellLayoutIface *iface;
- GtkCellArea *area;
attribute = va_arg (args, gchar *);
- iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
-
- if (iface->get_area)
- area = iface->get_area (cell_layout);
-
- if (iface->clear_attributes)
- iface->clear_attributes (cell_layout, cell);
- else if (area)
- gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (area), cell);
+ gtk_cell_layout_clear_attributes (cell_layout, cell);
while (attribute != NULL)
{
column = va_arg (args, gint);
- if (iface->add_attribute)
- iface->add_attribute (cell_layout, cell, attribute, column);
- else if (area)
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (area), cell, attribute, column);
+
+ gtk_cell_layout_add_attribute (cell_layout, cell, attribute, column);
attribute = va_arg (args, gchar *);
}
@@ -247,7 +447,7 @@ gtk_cell_layout_set_attributesv (GtkCellLayout *cell_layout,
* gtk_cell_layout_set_attributes:
* @cell_layout: a #GtkCellLayout
* @cell: a #GtkCellRenderer
- * @Varargs: a %NULL-terminated list of attributes
+ * @...: a %NULL-terminated list of attributes
*
* Sets the attributes in list as the attributes of @cell_layout.
*
@@ -294,28 +494,12 @@ gtk_cell_layout_add_attribute (GtkCellLayout *cell_layout,
const gchar *attribute,
gint column)
{
- GtkCellLayoutIface *iface;
- GtkCellArea *area;
-
g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
g_return_if_fail (attribute != NULL);
g_return_if_fail (column >= 0);
- iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
-
- if (iface->add_attribute)
- iface->add_attribute (cell_layout,
- cell,
- attribute,
- column);
- else
- {
- area = iface->get_area (cell_layout);
-
- if (area)
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (area), cell, attribute, column);
- }
+ GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->add_attribute (cell_layout, cell, attribute, column);
}
/**
@@ -343,36 +527,11 @@ gtk_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
gpointer func_data,
GDestroyNotify destroy)
{
- GtkCellLayoutIface *iface;
- GtkCellArea *area;
-
g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
- iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
-
- if (iface->set_cell_data_func)
- iface->set_cell_data_func (cell_layout,
- cell,
- func,
- func_data,
- destroy);
- else
- {
- area = iface->get_area (cell_layout);
-
- if (area)
- {
- /* Ensure that the correct proxy object is sent to 'func' */
- if (GTK_CELL_LAYOUT (area) != cell_layout)
- _gtk_cell_area_set_cell_data_func_with_proxy (area, cell,
- (GFunc)func, func_data, destroy,
- cell_layout);
- else
- gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (area), cell,
- func, func_data, destroy);
- }
- }
+ GTK_CELL_LAYOUT_GET_IFACE
+ (cell_layout)->set_cell_data_func (cell_layout, cell, func, func_data, destroy);
}
/**
@@ -389,23 +548,10 @@ void
gtk_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
GtkCellRenderer *cell)
{
- GtkCellLayoutIface *iface;
- GtkCellArea *area;
-
g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
- iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
-
- if (iface->clear_attributes)
- iface->clear_attributes (cell_layout, cell);
- else
- {
- area = iface->get_area (cell_layout);
-
- if (area)
- gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (area), cell);
- }
+ GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->clear_attributes (cell_layout, cell);
}
/**
@@ -426,23 +572,10 @@ gtk_cell_layout_reorder (GtkCellLayout *cell_layout,
GtkCellRenderer *cell,
gint position)
{
- GtkCellLayoutIface *iface;
- GtkCellArea *area;
-
g_return_if_fail (GTK_IS_CELL_LAYOUT (cell_layout));
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
- iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
-
- if (iface->reorder)
- iface->reorder (cell_layout, cell, position);
- else
- {
- area = iface->get_area (cell_layout);
-
- if (area)
- gtk_cell_layout_reorder (GTK_CELL_LAYOUT (area), cell, position);
- }
+ GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->reorder (cell_layout, cell, position);
}
/**
@@ -461,23 +594,9 @@ gtk_cell_layout_reorder (GtkCellLayout *cell_layout,
GList *
gtk_cell_layout_get_cells (GtkCellLayout *cell_layout)
{
- GtkCellLayoutIface *iface;
- GtkCellArea *area;
-
g_return_val_if_fail (GTK_IS_CELL_LAYOUT (cell_layout), NULL);
- iface = GTK_CELL_LAYOUT_GET_IFACE (cell_layout);
- if (iface->get_cells)
- return iface->get_cells (cell_layout);
- else
- {
- area = iface->get_area (cell_layout);
-
- if (area)
- return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (area));
- }
-
- return NULL;
+ return GTK_CELL_LAYOUT_GET_IFACE (cell_layout)->get_cells (cell_layout);
}
/**
@@ -590,7 +709,7 @@ gtk_cell_layout_buildable_set_cell_property (GtkCellArea *area,
const gchar *value)
{
GParamSpec *pspec;
- GValue gvalue = { 0, };
+ GValue gvalue = G_VALUE_INIT;
GError *error = NULL;
pspec = gtk_cell_area_class_find_cell_property (GTK_CELL_AREA_GET_CLASS (area), name);
@@ -621,6 +740,7 @@ typedef struct {
GtkBuilder *builder;
GtkCellLayout *cell_layout;
GtkCellRenderer *renderer;
+ GString *string;
gchar *cell_prop_name;
gchar *context;
gboolean translatable;
@@ -671,53 +791,63 @@ cell_packing_text_element (GMarkupParseContext *context,
GError **error)
{
CellPackingSubParserData *parser_data = (CellPackingSubParserData*)user_data;
+
+ if (parser_data->cell_prop_name)
+ g_string_append_len (parser_data->string, text, text_len);
+}
+
+static void
+cell_packing_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ CellPackingSubParserData *parser_data = (CellPackingSubParserData*)user_data;
GtkCellArea *area;
- gchar* value;
- if (!parser_data->cell_prop_name)
- return;
+ area = gtk_cell_layout_get_area (parser_data->cell_layout);
- if (parser_data->translatable && text_len)
+ if (area)
{
- const gchar* domain;
- domain = gtk_builder_get_translation_domain (parser_data->builder);
+ /* translate the string */
+ if (parser_data->string->len && parser_data->translatable)
+ {
+ gchar *translated;
+ const gchar* domain;
- value = _gtk_builder_parser_translate (domain,
- parser_data->context,
- text);
- }
- else
- {
- value = g_strdup (text);
- }
+ domain = gtk_builder_get_translation_domain (parser_data->builder);
- area = gtk_cell_layout_get_area (parser_data->cell_layout);
+ translated = _gtk_builder_parser_translate (domain,
+ parser_data->context,
+ parser_data->string->str);
+ g_string_set_size (parser_data->string, 0);
+ g_string_append (parser_data->string, translated);
+ }
- if (!area)
- {
- g_warning ("%s does not have an internal GtkCellArea class and cannot apply child cell properties",
- g_type_name (G_OBJECT_TYPE (parser_data->cell_layout)));
- return;
+ if (parser_data->cell_prop_name)
+ gtk_cell_layout_buildable_set_cell_property (area,
+ parser_data->builder,
+ parser_data->renderer,
+ parser_data->cell_prop_name,
+ parser_data->string->str);
}
+ else
+ g_warning ("%s does not have an internal GtkCellArea class and cannot apply child cell properties",
+ g_type_name (G_OBJECT_TYPE (parser_data->cell_layout)));
- gtk_cell_layout_buildable_set_cell_property (area,
- parser_data->builder,
- parser_data->renderer,
- parser_data->cell_prop_name,
- value);
-
+ g_string_set_size (parser_data->string, 0);
g_free (parser_data->cell_prop_name);
g_free (parser_data->context);
- g_free (value);
parser_data->cell_prop_name = NULL;
parser_data->context = NULL;
parser_data->translatable = FALSE;
}
+
static const GMarkupParser cell_packing_parser =
{
cell_packing_start_element,
- NULL,
+ cell_packing_end_element,
cell_packing_text_element,
};
@@ -749,6 +879,7 @@ _gtk_cell_layout_buildable_custom_tag_start (GtkBuildable *buildable,
else if (strcmp (tagname, "cell-packing") == 0)
{
packing_data = g_slice_new0 (CellPackingSubParserData);
+ packing_data->string = g_string_new ("");
packing_data->builder = builder;
packing_data->cell_layout = GTK_CELL_LAYOUT (buildable);
packing_data->renderer = GTK_CELL_RENDERER (child);
@@ -769,6 +900,7 @@ _gtk_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
gpointer *data)
{
AttributesSubParserData *attr_data;
+ CellPackingSubParserData *packing_data;
if (strcmp (tagname, "attributes") == 0)
{
@@ -779,7 +911,9 @@ _gtk_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
}
else if (strcmp (tagname, "cell-packing") == 0)
{
- g_slice_free (CellPackingSubParserData, (gpointer)data);
+ packing_data = (CellPackingSubParserData *)data;
+ g_string_free (packing_data->string, TRUE);
+ g_slice_free (CellPackingSubParserData, packing_data);
return TRUE;
}
return FALSE;