glade-editor-skeleton.c 8.63 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
/*
 * 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,
52
                         G_ADD_PRIVATE (GladeEditorSkeleton)
53
                         G_IMPLEMENT_INTERFACE (GLADE_TYPE_EDITABLE,
54
                                                glade_editor_skeleton_editable_init)
55 56
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                glade_editor_skeleton_buildable_init));
57 58 59 60

static void
glade_editor_skeleton_init (GladeEditorSkeleton *skeleton)
{
61
  skeleton->priv = glade_editor_skeleton_get_instance_private (skeleton);
62 63 64
}

static void
65
glade_editor_skeleton_class_init (GladeEditorSkeletonClass *klass)
66
{
67
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
  
  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
94 95
glade_editor_skeleton_load (GladeEditable *editable,
                            GladeWidget   *widget)
96 97 98 99 100 101 102 103 104 105
{
  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)
    {
106
      GladeEditable *editor = l->data;
107

108
      glade_editable_load (editor, widget);
109 110 111 112
    }
}

static void
113
glade_editor_skeleton_set_show_name (GladeEditable *editable, gboolean show_name)
114 115 116 117 118 119 120
{
  GladeEditorSkeleton *skeleton = GLADE_EDITOR_SKELETON (editable);
  GladeEditorSkeletonPrivate *priv = skeleton->priv;
  GSList *l;

  for (l = priv->editors; l; l = l->next)
    {
121
      GladeEditable *editor = l->data;
122

123
      glade_editable_set_show_name (editor, show_name);
124 125 126 127
    }
}

static void
128
glade_editor_skeleton_editable_init (GladeEditableIface *iface)
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
{
  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,
146 147 148 149 150
                      const gchar          *element_name,
                      const gchar         **names,
                      const gchar         **values,
                      gpointer              user_data,
                      GError              **error)
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
{
  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,
180 181 182 183 184
                                        GtkBuilder    *builder,
                                        GObject       *child,
                                        const gchar   *tagname,
                                        GMarkupParser *parser,
                                        gpointer      *data)
185 186 187 188 189 190 191 192 193 194 195 196
{
  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,
197
                                                   tagname, parser, data);
198 199 200 201
}

static void
glade_editor_skeleton_custom_finished (GtkBuildable *buildable,
202 203 204 205
                                       GtkBuilder   *builder,
                                       GObject      *child,
                                       const gchar  *tagname,
                                       gpointer      user_data)
206 207 208 209
{
  EditorParserData *editor_data = (EditorParserData *)user_data;
  GSList *l;

210
  if (strcmp (tagname, "child-editors") != 0)
211 212
    {
      parent_buildable_iface->custom_finished (buildable, builder, child,
213
                                               tagname, user_data);
214 215 216 217 218 219 220 221 222 223
      return;
    }

  for (l = editor_data->editors; l; l = l->next)
    {
      GObject *object;
      gchar *id = l->data;

      object = gtk_builder_get_object (builder, id);

224
      if (!GLADE_EDITABLE (object))
225 226
        g_warning ("Object '%s' is not a GladeEditable\n",
                   object ? G_OBJECT_TYPE_NAME (object) : "(null)");
227
      else
228 229
        glade_editor_skeleton_add_editor (GLADE_EDITOR_SKELETON (buildable),
                                          GLADE_EDITABLE (object));
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
    }

  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,
255
                                  GladeEditable       *editor)
256 257 258 259
{
  GladeEditorSkeletonPrivate *priv;

  g_return_if_fail (GLADE_IS_EDITOR_SKELETON (skeleton));
260
  g_return_if_fail (GLADE_IS_EDITABLE (editor));
261 262 263 264 265 266

  priv = skeleton->priv;

  g_object_ref (editor);
  priv->editors = g_slist_prepend (priv->editors, editor);
}