[tepl] Implement TeplAbstractFactoryVala to work-around Vala bugs



commit 19fe423bd50d228a0711f1f8a1bf708ac235ed72
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Fri Nov 3 12:42:28 2017 +0100

    Implement TeplAbstractFactoryVala to work-around Vala bugs

 docs/reference/tepl-4.0-sections.txt |   16 ++++
 docs/reference/tepl-docs.xml.in      |    1 +
 po/POTFILES.in                       |    1 +
 tepl/Makefile.am                     |    2 +
 tepl/tepl-abstract-factory-vala.c    |  132 ++++++++++++++++++++++++++++++++++
 tepl/tepl-abstract-factory-vala.h    |   77 ++++++++++++++++++++
 tepl/tepl-abstract-factory.c         |    2 +
 tepl/tepl-types.h                    |    1 +
 tepl/tepl.h                          |    1 +
 9 files changed, 233 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/tepl-4.0-sections.txt b/docs/reference/tepl-4.0-sections.txt
index cad100b..f1b30df 100644
--- a/docs/reference/tepl-4.0-sections.txt
+++ b/docs/reference/tepl-4.0-sections.txt
@@ -189,6 +189,22 @@ tepl_abstract_factory_get_type
 </SECTION>
 
 <SECTION>
+<FILE>abstract-factory-vala</FILE>
+TeplAbstractFactoryVala
+TeplAbstractFactoryValaClass
+tepl_abstract_factory_vala_set_singleton_vala
+tepl_abstract_factory_vala_create_main_window_vala
+<SUBSECTION Standard>
+TEPL_ABSTRACT_FACTORY_VALA
+TEPL_ABSTRACT_FACTORY_VALA_CLASS
+TEPL_ABSTRACT_FACTORY_VALA_GET_CLASS
+TEPL_IS_ABSTRACT_FACTORY_VALA
+TEPL_IS_ABSTRACT_FACTORY_VALA_CLASS
+TEPL_TYPE_ABSTRACT_FACTORY_VALA
+tepl_abstract_factory_vala_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 b1c566b..2a4901a 100644
--- a/docs/reference/tepl-docs.xml.in
+++ b/docs/reference/tepl-docs.xml.in
@@ -77,6 +77,7 @@
 
     <chapter id="misc">
       <title>Misc</title>
+      <xi:include href="xml/abstract-factory-vala.xml"/>
       <xi:include href="xml/info-bar.xml"/>
       <xi:include href="xml/iter.xml"/>
     </chapter>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3be9975..5a0b12e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -10,6 +10,7 @@ amtk/amtk-menu-item.c
 amtk/amtk-menu-shell.c
 amtk/amtk-utils.c
 tepl/tepl-abstract-factory.c
+tepl/tepl-abstract-factory-vala.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 aa7f03d..ec6a810 100644
--- a/tepl/Makefile.am
+++ b/tepl/Makefile.am
@@ -13,6 +13,7 @@ AM_CPPFLAGS =                         \
 tepl_public_headers =                          \
        tepl.h                                  \
        tepl-abstract-factory.h                 \
+       tepl-abstract-factory-vala.h            \
        tepl-application.h                      \
        tepl-application-window.h               \
        tepl-buffer.h                           \
@@ -38,6 +39,7 @@ tepl_public_headers =                         \
 
 tepl_public_c_files =                          \
        tepl-abstract-factory.c                 \
+       tepl-abstract-factory-vala.c            \
        tepl-application.c                      \
        tepl-application-window.c               \
        tepl-buffer.c                           \
diff --git a/tepl/tepl-abstract-factory-vala.c b/tepl/tepl-abstract-factory-vala.c
new file mode 100644
index 0000000..96dc1b9
--- /dev/null
+++ b/tepl/tepl-abstract-factory-vala.c
@@ -0,0 +1,132 @@
+/*
+ * 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-vala.h"
+
+/**
+ * SECTION:abstract-factory-vala
+ * @Short_description: #TeplAbstractFactory subclass to work-around Vala bugs
+ * @Title: TeplAbstractFactoryVala
+ *
+ * #TeplAbstractFactoryVala is a subclass of #TeplAbstractFactory to work-around
+ * Vala bugs.
+ *
+ * There are two bugs:
+ * - See tepl_abstract_factory_vala_set_singleton_vala().
+ * - For the functions or vfuncs in #TeplAbstractFactory which have a (transfer
+ *   floating) return value: apparently when a Vala function returns a newly
+ *   created #GInitiallyUnowned object, the return value is (transfer full).
+ *   Which is not correct, it should be (transfer floating) instead (i.e. equal
+ *   to (transfer none)). So to be able to implement easily those vfuncs in
+ *   Vala, new Vala-specific vfuncs have been added which have a (transfer full)
+ *   return value. The original vfuncs are implemented by
+ *   #TeplAbstractFactoryVala by calling the Vala ones and transforming the
+ *   strong ref into a floating ref.
+ *
+ * It would have been possible to modify the #TeplAbstractFactory API so that
+ * it's usable in Vala as well, but in that case the API would be less
+ * convenient and less natural in C. So #TeplAbstractFactoryVala has been
+ * implemented as something separate, to not clutter #TeplAbstractFactory.
+ */
+
+G_DEFINE_TYPE (TeplAbstractFactoryVala,
+              tepl_abstract_factory_vala,
+              TEPL_TYPE_ABSTRACT_FACTORY)
+
+static GtkApplicationWindow *
+tepl_abstract_factory_vala_create_main_window (TeplAbstractFactory *factory,
+                                              GtkApplication      *app)
+{
+       TeplAbstractFactoryVala *factory_vala = TEPL_ABSTRACT_FACTORY_VALA (factory);
+       GtkApplicationWindow *main_window;
+
+       main_window = tepl_abstract_factory_vala_create_main_window_vala (factory_vala, app);
+       if (main_window == NULL)
+       {
+               return NULL;
+       }
+
+       /* Transform strong ref to floating ref. */
+       g_return_val_if_fail (!g_object_is_floating (main_window), main_window);
+       g_object_force_floating (G_OBJECT (main_window));
+
+       return main_window;
+}
+
+static void
+tepl_abstract_factory_vala_class_init (TeplAbstractFactoryValaClass *klass)
+{
+       TeplAbstractFactoryClass *parent_class = TEPL_ABSTRACT_FACTORY_CLASS (klass);
+
+       parent_class->create_main_window = tepl_abstract_factory_vala_create_main_window;
+}
+
+static void
+tepl_abstract_factory_vala_init (TeplAbstractFactoryVala *factory_vala)
+{
+}
+
+/**
+ * tepl_abstract_factory_vala_set_singleton_vala:
+ * @factory_vala: (transfer none): a #TeplAbstractFactoryVala.
+ *
+ * Like tepl_abstract_factory_set_singleton(), but with (transfer none) for the
+ * @factory_vala parameter.
+ *
+ * Apparently Vala doesn't support (transfer full) for the self parameter,
+ * resulting to a double unref if tepl_abstract_factory_set_singleton() is
+ * called in Vala...
+ *
+ * Since: 4.0
+ */
+void
+tepl_abstract_factory_vala_set_singleton_vala (TeplAbstractFactoryVala *factory_vala)
+{
+       g_return_if_fail (TEPL_IS_ABSTRACT_FACTORY_VALA (factory_vala));
+
+       tepl_abstract_factory_set_singleton (g_object_ref (factory_vala));
+}
+
+/**
+ * tepl_abstract_factory_vala_create_main_window_vala:
+ * @factory_vala: the #TeplAbstractFactoryVala.
+ * @app: a #GtkApplication.
+ *
+ * Like tepl_abstract_factory_create_main_window(), but with a (transfer full)
+ * return value.
+ *
+ * Returns: (transfer full) (nullable): a new main application window, or %NULL
+ * if the vfunc is not implemented.
+ * Since: 4.0
+ */
+GtkApplicationWindow *
+tepl_abstract_factory_vala_create_main_window_vala (TeplAbstractFactoryVala *factory_vala,
+                                                   GtkApplication          *app)
+{
+       g_return_val_if_fail (TEPL_IS_ABSTRACT_FACTORY_VALA (factory_vala), NULL);
+       g_return_val_if_fail (GTK_IS_APPLICATION (app), NULL);
+
+       if (TEPL_ABSTRACT_FACTORY_VALA_GET_CLASS (factory_vala)->create_main_window_vala != NULL)
+       {
+               return TEPL_ABSTRACT_FACTORY_VALA_GET_CLASS (factory_vala)->create_main_window_vala 
(factory_vala, app);
+       }
+
+       g_warning ("The TeplAbstractFactoryVala::create_main_window_vala vfunc is not implemented.");
+       return NULL;
+}
diff --git a/tepl/tepl-abstract-factory-vala.h b/tepl/tepl-abstract-factory-vala.h
new file mode 100644
index 0000000..bdfa0d7
--- /dev/null
+++ b/tepl/tepl-abstract-factory-vala.h
@@ -0,0 +1,77 @@
+/*
+ * 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_VALA_H
+#define TEPL_ABSTRACT_FACTORY_VALA_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>
+#include <tepl/tepl-abstract-factory.h>
+
+G_BEGIN_DECLS
+
+#define TEPL_TYPE_ABSTRACT_FACTORY_VALA             (tepl_abstract_factory_vala_get_type ())
+#define TEPL_ABSTRACT_FACTORY_VALA(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
TEPL_TYPE_ABSTRACT_FACTORY_VALA, TeplAbstractFactoryVala))
+#define TEPL_ABSTRACT_FACTORY_VALA_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
TEPL_TYPE_ABSTRACT_FACTORY_VALA, TeplAbstractFactoryValaClass))
+#define TEPL_IS_ABSTRACT_FACTORY_VALA(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
TEPL_TYPE_ABSTRACT_FACTORY_VALA))
+#define TEPL_IS_ABSTRACT_FACTORY_VALA_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
TEPL_TYPE_ABSTRACT_FACTORY_VALA))
+#define TEPL_ABSTRACT_FACTORY_VALA_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), 
TEPL_TYPE_ABSTRACT_FACTORY_VALA, TeplAbstractFactoryValaClass))
+
+typedef struct _TeplAbstractFactoryValaClass TeplAbstractFactoryValaClass;
+
+struct _TeplAbstractFactoryVala
+{
+       TeplAbstractFactory parent;
+};
+
+/**
+ * TeplAbstractFactoryValaClass:
+ * @parent_class: The parent class.
+ * @create_main_window_vala: Virtual function pointer for
+ *   tepl_abstract_factory_vala_create_main_window_vala(). It is not implemented
+ *   by default. The #TeplAbstractFactory ::create_main_window vfunc is
+ *   implemented by #TeplAbstractFactoryVala by calling
+ *   tepl_abstract_factory_vala_create_main_window_vala() and adapting the ref.
+ */
+struct _TeplAbstractFactoryValaClass
+{
+       TeplAbstractFactoryClass parent_class;
+
+       GtkApplicationWindow *  (* create_main_window_vala)     (TeplAbstractFactoryVala *factory_vala,
+                                                                GtkApplication          *app);
+
+       /*< private >*/
+       gpointer padding[12];
+};
+
+GType  tepl_abstract_factory_vala_get_type                     (void);
+
+void   tepl_abstract_factory_vala_set_singleton_vala           (TeplAbstractFactoryVala *factory_vala);
+
+GtkApplicationWindow *
+       tepl_abstract_factory_vala_create_main_window_vala      (TeplAbstractFactoryVala *factory_vala,
+                                                                GtkApplication          *app);
+
+G_END_DECLS
+
+#endif /* TEPL_ABSTRACT_FACTORY_VALA_H */
diff --git a/tepl/tepl-abstract-factory.c b/tepl/tepl-abstract-factory.c
index 9c2ac5e..3642ffb 100644
--- a/tepl/tepl-abstract-factory.c
+++ b/tepl/tepl-abstract-factory.c
@@ -43,6 +43,8 @@
  * “MyappAbstractFactory” is not a good name for a #TeplAbstractFactory
  * subclass. “MyappFactory” is a better name (of course change “Myapp” with the
  * application namespace).
+ *
+ * For an application written in Vala, see #TeplAbstractFactoryVala.
  */
 
 /* API design:
diff --git a/tepl/tepl-types.h b/tepl/tepl-types.h
index 26fdf9a..37808b3 100644
--- a/tepl/tepl-types.h
+++ b/tepl/tepl-types.h
@@ -29,6 +29,7 @@
 G_BEGIN_DECLS
 
 typedef struct _TeplAbstractFactory            TeplAbstractFactory;
+typedef struct _TeplAbstractFactoryVala                TeplAbstractFactoryVala;
 typedef struct _TeplApplication                        TeplApplication;
 typedef struct _TeplApplicationWindow          TeplApplicationWindow;
 typedef struct _TeplBuffer                     TeplBuffer;
diff --git a/tepl/tepl.h b/tepl/tepl.h
index 131c5b5..6bf1f16 100644
--- a/tepl/tepl.h
+++ b/tepl/tepl.h
@@ -28,6 +28,7 @@
 #include <tepl/tepl-enum-types.h>
 
 #include <tepl/tepl-abstract-factory.h>
+#include <tepl/tepl-abstract-factory-vala.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]