/*
* Copyright (C) 2013 Tristan Van Berkom.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Authors:
* Tristan Van Berkom <tvb@gnome.org>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n-lib.h>
#include "glade.h"
#include "glade-widget.h"
#include "glade-popup.h"
#include "glade-editable.h"
#include "glade-editor-skeleton.h"
/* GObjectClass */
static void glade_editor_skeleton_dispose (GObject *object);
/* GladeEditableIface */
static void glade_editor_skeleton_editable_init (GladeEditableIface *iface);
/* GtkBuildableIface */
static void glade_editor_skeleton_buildable_init (GtkBuildableIface *iface);
struct _GladeEditorSkeletonPrivate
{
GSList *editors;
};
static GladeEditableIface *parent_editable_iface;
static GtkBuildableIface *parent_buildable_iface;
G_DEFINE_TYPE_WITH_CODE (GladeEditorSkeleton, glade_editor_skeleton, GTK_TYPE_BOX,
G_ADD_PRIVATE (GladeEditorSkeleton)
G_IMPLEMENT_INTERFACE (GLADE_TYPE_EDITABLE,
glade_editor_skeleton_editable_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
glade_editor_skeleton_buildable_init));
static void
glade_editor_skeleton_init (GladeEditorSkeleton *skeleton)
{
skeleton->priv = glade_editor_skeleton_get_instance_private (skeleton);
}
static void
glade_editor_skeleton_class_init (GladeEditorSkeletonClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = glade_editor_skeleton_dispose;
}
/***********************************************************
* GObjectClass *
***********************************************************/
static void
glade_editor_skeleton_dispose (GObject *object)
{
GladeEditorSkeleton *skeleton = GLADE_EDITOR_SKELETON (object);
GladeEditorSkeletonPrivate *priv = skeleton->priv;
if (priv->editors)
{
g_slist_free_full (priv->editors, (GDestroyNotify)g_object_unref);
priv->editors = NULL;
}
G_OBJECT_CLASS (glade_editor_skeleton_parent_class)->dispose (object);
}
/*******************************************************************************
* GladeEditableIface *
*******************************************************************************/
static void
glade_editor_skeleton_load (GladeEditable *editable,
GladeWidget *widget)
{
GladeEditorSkeleton *skeleton = GLADE_EDITOR_SKELETON (editable);
GladeEditorSkeletonPrivate *priv = skeleton->priv;
GSList *l;
/* Chain up to default implementation */
parent_editable_iface->load (editable, widget);
for (l = priv->editors; l; l = l->next)
{
GladeEditable *editor = l->data;
glade_editable_load (editor, widget);
}
}
static void
glade_editor_skeleton_set_show_name (GladeEditable *editable, gboolean show_name)
{
GladeEditorSkeleton *skeleton = GLADE_EDITOR_SKELETON (editable);
GladeEditorSkeletonPrivate *priv = skeleton->priv;
GSList *l;
for (l = priv->editors; l; l = l->next)
{
GladeEditable *editor = l->data;
glade_editable_set_show_name (editor, show_name);
}
}
static void
glade_editor_skeleton_editable_init (GladeEditableIface *iface)
{
parent_editable_iface = g_type_default_interface_peek (GLADE_TYPE_EDITABLE);
iface->load = glade_editor_skeleton_load;
iface->set_show_name = glade_editor_skeleton_set_show_name;
}
/*******************************************************************************
* GtkBuildableIface *
*******************************************************************************/
typedef struct
{
GSList *editors;
} EditorParserData;
static void
editor_start_element (GMarkupParseContext *context,
const gchar *element_name,
const gchar **names,
const gchar **values,
gpointer user_data,
GError **error)
{
EditorParserData *editor_data = (EditorParserData *)user_data;
gchar *id;
if (strcmp (element_name, "editor") == 0)
{
if (g_markup_collect_attributes (element_name,
names,
values,
error,
G_MARKUP_COLLECT_STRDUP, "id", &id,
G_MARKUP_COLLECT_INVALID))
{
editor_data->editors = g_slist_append (editor_data->editors, id);
}
}
else if (strcmp (element_name, "child-editors") == 0)
;
else
g_warning ("Unsupported tag for GladeEditorSkeleton: %s\n", element_name);
}
static const GMarkupParser editor_parser =
{
editor_start_element,
};
static gboolean
glade_editor_skeleton_custom_tag_start (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
const gchar *tagname,
GMarkupParser *parser,
gpointer *data)
{
if (strcmp (tagname, "child-editors") == 0)
{
EditorParserData *parser_data;
parser_data = g_slice_new0 (EditorParserData);
*parser = editor_parser;
*data = parser_data;
return TRUE;
}
return parent_buildable_iface->custom_tag_start (buildable, builder, child,
tagname, parser, data);
}
static void
glade_editor_skeleton_custom_finished (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
const gchar *tagname,
gpointer user_data)
{
EditorParserData *editor_data = (EditorParserData *)user_data;
GSList *l;
if (strcmp (tagname, "child-editors") != 0)
{
parent_buildable_iface->custom_finished (buildable, builder, child,
tagname, user_data);
return;
}
for (l = editor_data->editors; l; l = l->next)
{
GObject *object;
gchar *id = l->data;
object = gtk_builder_get_object (builder, id);
if (!GLADE_EDITABLE (object))
g_warning ("Object '%s' is not a GladeEditable\n",
object ? G_OBJECT_TYPE_NAME (object) : "(null)");
else
glade_editor_skeleton_add_editor (GLADE_EDITOR_SKELETON (buildable),
GLADE_EDITABLE (object));
}
g_slist_free_full (editor_data->editors, g_free);
g_slice_free (EditorParserData, editor_data);
}
static void
glade_editor_skeleton_buildable_init (GtkBuildableIface *iface)
{
parent_buildable_iface = g_type_interface_peek_parent (iface);
iface->custom_tag_start = glade_editor_skeleton_custom_tag_start;
iface->custom_finished = glade_editor_skeleton_custom_finished;
}
/*******************************************************************************
* API *
*******************************************************************************/
GtkWidget *
glade_editor_skeleton_new (void)
{
return g_object_new (GLADE_TYPE_EDITOR_SKELETON, NULL);
}
void
glade_editor_skeleton_add_editor (GladeEditorSkeleton *skeleton,
GladeEditable *editor)
{
GladeEditorSkeletonPrivate *priv;
g_return_if_fail (GLADE_IS_EDITOR_SKELETON (skeleton));
g_return_if_fail (GLADE_IS_EDITABLE (editor));
priv = skeleton->priv;
g_object_ref (editor);
priv->editors = g_slist_prepend (priv->editors, editor);
}