[tepl] Implement TeplAbstractFactory



commit e6f06a8fc58b519659a21c924465bde48fcdac6d
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Sat Jul 29 18:08:39 2017 +0200

    Implement TeplAbstractFactory
    
    The final missing core piece of the Tepl framework.

 docs/reference/tepl-3.0-sections.txt |   16 ++++
 docs/reference/tepl-docs.xml.in      |    1 +
 po/POTFILES.in                       |    1 +
 tepl/Makefile.am                     |    2 +
 tepl/tepl-abstract-factory.c         |  133 ++++++++++++++++++++++++++++++++++
 tepl/tepl-abstract-factory.h         |   65 +++++++++++++++++
 tepl/tepl-init.c                     |   10 +++-
 tepl/tepl-types.h                    |    1 +
 tepl/tepl.h                          |    1 +
 9 files changed, 229 insertions(+), 1 deletions(-)
---
diff --git a/docs/reference/tepl-3.0-sections.txt b/docs/reference/tepl-3.0-sections.txt
index 7e8958c..1d0c19f 100644
--- a/docs/reference/tepl-3.0-sections.txt
+++ b/docs/reference/tepl-3.0-sections.txt
@@ -176,6 +176,22 @@ tepl_finalize
 </SECTION>
 
 <SECTION>
+<FILE>abstract-factory</FILE>
+TeplAbstractFactory
+TeplAbstractFactoryClass
+tepl_abstract_factory_set_singleton
+tepl_abstract_factory_get_singleton
+<SUBSECTION Standard>
+TEPL_ABSTRACT_FACTORY
+TEPL_ABSTRACT_FACTORY_CLASS
+TEPL_ABSTRACT_FACTORY_GET_CLASS
+TEPL_IS_ABSTRACT_FACTORY
+TEPL_IS_ABSTRACT_FACTORY_CLASS
+TEPL_TYPE_ABSTRACT_FACTORY
+tepl_abstract_factory_get_type
+</SECTION>
+
+<SECTION>
 <FILE>application</FILE>
 TeplApplication
 tepl_application_get_from_gtk_application
diff --git a/docs/reference/tepl-docs.xml.in b/docs/reference/tepl-docs.xml.in
index ae312b4..3ffddcd 100644
--- a/docs/reference/tepl-docs.xml.in
+++ b/docs/reference/tepl-docs.xml.in
@@ -44,6 +44,7 @@
 
     <chapter id="framework">
       <title>Framework</title>
+      <xi:include href="xml/abstract-factory.xml"/>
       <xi:include href="xml/application.xml"/>
       <xi:include href="xml/application-window.xml"/>
       <xi:include href="xml/tab-group.xml"/>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 904ac91..7dbbe53 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -10,6 +10,7 @@ amtk/amtk-init.c
 amtk/amtk-menu-item.c
 amtk/amtk-menu-shell.c
 amtk/amtk-utils.c
+tepl/tepl-abstract-factory.c
 tepl/tepl-application.c
 tepl/tepl-application-window.c
 tepl/tepl-buffer.c
diff --git a/tepl/Makefile.am b/tepl/Makefile.am
index 5a95784..3843fac 100644
--- a/tepl/Makefile.am
+++ b/tepl/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS =                         \
 
 tepl_public_headers =                          \
        tepl.h                                  \
+       tepl-abstract-factory.h                 \
        tepl-application.h                      \
        tepl-application-window.h               \
        tepl-buffer.h                           \
@@ -35,6 +36,7 @@ tepl_public_headers =                         \
        tepl-view.h
 
 tepl_public_c_files =                          \
+       tepl-abstract-factory.c                 \
        tepl-application.c                      \
        tepl-application-window.c               \
        tepl-buffer.c                           \
diff --git a/tepl/tepl-abstract-factory.c b/tepl/tepl-abstract-factory.c
new file mode 100644
index 0000000..10da36d
--- /dev/null
+++ b/tepl/tepl-abstract-factory.c
@@ -0,0 +1,133 @@
+/*
+ * This file is part of Tepl, a text editor library.
+ *
+ * Copyright 2017 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * Tepl 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.
+ *
+ * Tepl 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 library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tepl-abstract-factory.h"
+
+/**
+ * SECTION:abstract-factory
+ * @Short_description: Abstract factory singleton class
+ * @Title: TeplAbstractFactory
+ *
+ * The Tepl framework uses the #TeplAbstractFactory singleton to create some
+ * objects and widgets. By creating a subclass of #TeplAbstractFactory (to
+ * override the desired virtual functions) and setting the instance with
+ * tepl_abstract_factory_set_singleton(), an application can tell Tepl to create
+ * custom objects and widgets.
+ */
+
+/* API design:
+ *
+ * An example of another sub-classable singleton is PeasEngine, in libpeas. I
+ * didn't really like the PeasEngine implementation with get_default(), so I've
+ * implemented TeplAbstractFactory differently. But I'll maybe change my mind in
+ * the future. -- swilmet
+ */
+
+static TeplAbstractFactory *singleton = NULL;
+
+G_DEFINE_TYPE (TeplAbstractFactory, tepl_abstract_factory, G_TYPE_OBJECT)
+
+static void
+tepl_abstract_factory_finalize (GObject *object)
+{
+       if (singleton == TEPL_ABSTRACT_FACTORY (object))
+       {
+               singleton = NULL;
+       }
+
+       G_OBJECT_CLASS (tepl_abstract_factory_parent_class)->finalize (object);
+}
+
+static void
+tepl_abstract_factory_class_init (TeplAbstractFactoryClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = tepl_abstract_factory_finalize;
+}
+
+static void
+tepl_abstract_factory_init (TeplAbstractFactory *factory)
+{
+}
+
+/**
+ * tepl_abstract_factory_set_singleton:
+ * @factory: (transfer full): a #TeplAbstractFactory.
+ *
+ * Sets the #TeplAbstractFactory singleton. This should be called early in
+ * main(), for example just after calling tepl_init().
+ *
+ * This function must be called only once, before the first call to
+ * tepl_abstract_factory_get_singleton().
+ *
+ * Tepl takes ownership of the @factory reference.
+ *
+ * Since: 3.0
+ */
+void
+tepl_abstract_factory_set_singleton (TeplAbstractFactory *factory)
+{
+       g_return_if_fail (TEPL_IS_ABSTRACT_FACTORY (factory));
+
+       if (singleton != NULL)
+       {
+               g_warning ("%s(): the TeplAbstractFactory singleton is already created.",
+                          G_STRFUNC);
+               return;
+       }
+
+       singleton = factory;
+}
+
+/**
+ * tepl_abstract_factory_get_singleton:
+ *
+ * Gets the #TeplAbstractFactory singleton instance.
+ *
+ * If tepl_abstract_factory_set_singleton() has not been called, the singleton
+ * is created with a #TeplAbstractFactory instance.
+ *
+ * Returns: (transfer none): the #TeplAbstractFactory singleton instance.
+ * Since: 3.0
+ */
+TeplAbstractFactory *
+tepl_abstract_factory_get_singleton (void)
+{
+       if (G_UNLIKELY (singleton == NULL))
+       {
+               singleton = g_object_new (TEPL_TYPE_ABSTRACT_FACTORY, NULL);
+       }
+
+       return singleton;
+}
+
+void
+_tepl_abstract_factory_unref_singleton (void)
+{
+       if (singleton != NULL)
+       {
+               g_object_unref (singleton);
+       }
+
+       /* singleton is not set to NULL here, it is set to NULL in
+        * tepl_abstract_factory_finalize() (i.e. when we are sure that the ref
+        * count reaches 0).
+        */
+}
diff --git a/tepl/tepl-abstract-factory.h b/tepl/tepl-abstract-factory.h
new file mode 100644
index 0000000..8cb2183
--- /dev/null
+++ b/tepl/tepl-abstract-factory.h
@@ -0,0 +1,65 @@
+/*
+ * This file is part of Tepl, a text editor library.
+ *
+ * Copyright 2017 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * Tepl 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.
+ *
+ * Tepl 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 library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TEPL_ABSTRACT_FACTORY_H
+#define TEPL_ABSTRACT_FACTORY_H
+
+#if !defined (TEPL_H_INSIDE) && !defined (TEPL_COMPILATION)
+#error "Only <tepl/tepl.h> can be included directly."
+#endif
+
+#include <gtk/gtk.h>
+#include <tepl/tepl-types.h>
+
+G_BEGIN_DECLS
+
+#define TEPL_TYPE_ABSTRACT_FACTORY             (tepl_abstract_factory_get_type ())
+#define TEPL_ABSTRACT_FACTORY(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
TEPL_TYPE_ABSTRACT_FACTORY, TeplAbstractFactory))
+#define TEPL_ABSTRACT_FACTORY_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
TEPL_TYPE_ABSTRACT_FACTORY, TeplAbstractFactoryClass))
+#define TEPL_IS_ABSTRACT_FACTORY(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
TEPL_TYPE_ABSTRACT_FACTORY))
+#define TEPL_IS_ABSTRACT_FACTORY_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
TEPL_TYPE_ABSTRACT_FACTORY))
+#define TEPL_ABSTRACT_FACTORY_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), 
TEPL_TYPE_ABSTRACT_FACTORY, TeplAbstractFactoryClass))
+
+typedef struct _TeplAbstractFactoryClass TeplAbstractFactoryClass;
+
+struct _TeplAbstractFactory
+{
+       GObject parent;
+};
+
+struct _TeplAbstractFactoryClass
+{
+       GObjectClass parent_class;
+
+       /*< private >*/
+       gpointer padding[12];
+};
+
+GType                  tepl_abstract_factory_get_type                  (void);
+
+void                   tepl_abstract_factory_set_singleton             (TeplAbstractFactory *factory);
+
+TeplAbstractFactory *  tepl_abstract_factory_get_singleton             (void);
+
+G_GNUC_INTERNAL
+void                   _tepl_abstract_factory_unref_singleton          (void);
+
+G_END_DECLS
+
+#endif /* TEPL_ABSTRACT_FACTORY_H */
diff --git a/tepl/tepl-init.c b/tepl/tepl-init.c
index b1be71f..8ad0d0a 100644
--- a/tepl/tepl-init.c
+++ b/tepl/tepl-init.c
@@ -19,6 +19,7 @@
 
 #include "tepl-init.h"
 #include <amtk/amtk.h>
+#include "tepl-abstract-factory.h"
 #include "tepl-metadata-manager.h"
 
 /**
@@ -75,8 +76,15 @@ tepl_finalize (void)
 
        if (!done)
        {
-               amtk_finalize ();
                tepl_metadata_manager_shutdown ();
+               _tepl_abstract_factory_unref_singleton ();
+
+               /* Since Tepl depends on Amtk, it's better to first finalize
+                * Tepl stuff and then finalize Amtk, in case the Tepl
+                * singletons depends on Amtk.
+                */
+               amtk_finalize ();
+
                done = TRUE;
        }
 }
diff --git a/tepl/tepl-types.h b/tepl/tepl-types.h
index 878906d..feae7c1 100644
--- a/tepl/tepl-types.h
+++ b/tepl/tepl-types.h
@@ -28,6 +28,7 @@
 
 G_BEGIN_DECLS
 
+typedef struct _TeplAbstractFactory            TeplAbstractFactory;
 typedef struct _TeplApplication                        TeplApplication;
 typedef struct _TeplApplicationWindow          TeplApplicationWindow;
 typedef struct _TeplBuffer                     TeplBuffer;
diff --git a/tepl/tepl.h b/tepl/tepl.h
index f05f081..bf78137 100644
--- a/tepl/tepl.h
+++ b/tepl/tepl.h
@@ -27,6 +27,7 @@
 #include <tepl/tepl-types.h>
 #include <tepl/tepl-enum-types.h>
 
+#include <tepl/tepl-abstract-factory.h>
 #include <tepl/tepl-application.h>
 #include <tepl/tepl-application-window.h>
 #include <tepl/tepl-buffer.h>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]