summaryrefslogtreecommitdiff
path: root/endless
diff options
context:
space:
mode:
authorP. F. Chimento <philip.chimento@gmail.com>2013-04-15 18:04:27 +0200
committerP. F. Chimento <philip.chimento@gmail.com>2013-04-24 14:48:15 +0200
commit096c63f7ed002b99a995c35a407483a0bfa161c5 (patch)
treecf324aae1bce4f5cb9edf42e68bc9c7cb4da0964 /endless
parent7fc4090461ad888612491814e5a44aaf7e52d7ff (diff)
Application class
Add an EosApplication class. Functionality: - present main application window when activated - warn if more than one application window is added Also add a stub EosWindow class that overrides GtkWindow's "application" property to be a construct-only property. [#4]
Diffstat (limited to 'endless')
-rw-r--r--endless/Makefile.am8
-rw-r--r--endless/application.c165
-rw-r--r--endless/application.h70
-rw-r--r--endless/endless.h2
-rw-r--r--endless/types.h2
-rw-r--r--endless/window.c121
-rw-r--r--endless/window.h71
7 files changed, 437 insertions, 2 deletions
diff --git a/endless/Makefile.am b/endless/Makefile.am
index e653097..583ca74 100644
--- a/endless/Makefile.am
+++ b/endless/Makefile.am
@@ -4,13 +4,17 @@ endless_public_installed_headers = endless/endless.h
endless_private_installed_headers = \
endless/apiversion.h \
+ endless/application.h \
endless/enums.h \
endless/macros.h \
- endless/types.h
+ endless/types.h \
+ endless/window.h
endless_library_sources = \
+ endless/application.c \
endless/hello.c \
- endless/init.c endless/init-private.h
+ endless/init.c endless/init-private.h \
+ endless/window.c
# Endless GUI library
lib_LTLIBRARIES = libendless-@EOS_SDK_API_VERSION@.la
diff --git a/endless/application.c b/endless/application.c
new file mode 100644
index 0000000..ef93e13
--- /dev/null
+++ b/endless/application.c
@@ -0,0 +1,165 @@
+/* Copyright 2013 Endless Mobile, Inc. */
+
+#include "config.h"
+#include "application.h"
+
+#include <gtk/gtk.h>
+
+#include "window.h"
+
+/**
+ * SECTION:application
+ * @short_description: Start here with your application
+ * @title: Applications
+ *
+ * The #EosApplication class is where you start when programming your
+ * application.
+ * You should create a class that extends #EosApplication.
+ *
+ * You also need to think up an application ID.
+ * This takes the form of a reverse domain name, and it should be unique.
+ * This ID is used to make sure that only one copy of your application is
+ * running at any time; if a user tries to start a second copy, then the first
+ * copy is brought to the front.
+ *
+ * To set up your application's data and window, override the
+ * #GApplication::startup function, like this example do-nothing application,
+ * <quote>Smoke Grinder</quote>:
+ * |[
+ * const Lang = imports.lang;
+ * const Endless = imports.gi.Endless;
+ *
+ * const SmokeGrinder = new Lang.Class ({
+ * Name: 'SmokeGrinder',
+ * Extends: Endless.Application,
+ *
+ * vfunc_startup: function() {
+ * this.parent();
+ * this._window = new Endless.Window({application: this});
+ * this._window.show_all();
+ * },
+ * });
+ *
+ * let app = new SmokeGrinder({ application_id: "com.example.smokegrinder",
+ * flags: 0 });
+ * app.run(ARGV);
+ * ]|
+ */
+
+G_DEFINE_TYPE (EosApplication, eos_application, GTK_TYPE_APPLICATION)
+
+#define APPLICATION_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), EOS_TYPE_APPLICATION, EosApplicationPrivate))
+
+struct _EosApplicationPrivate
+{
+ EosWindow *main_application_window;
+};
+
+static void
+eos_application_activate (GApplication *application)
+{
+ EosApplication *self = EOS_APPLICATION (application);
+
+ G_APPLICATION_CLASS (eos_application_parent_class)->activate (application);
+
+ /* Raise the main application window if it is iconified. This behavior will
+ be default in GTK at some future point, in which case the following
+ paragraph can be removed. */
+ if (self->priv->main_application_window)
+ {
+ gtk_window_present (GTK_WINDOW (self->priv->main_application_window));
+ }
+
+ /* TODO: Should it be required to override activate() as in GApplication? */
+}
+
+static void
+eos_application_window_added (GtkApplication *application,
+ GtkWindow *window)
+{
+ EosApplication *self = EOS_APPLICATION (application);
+
+ GTK_APPLICATION_CLASS (eos_application_parent_class)->window_added (
+ application, window);
+
+ /* If the new window is an EosWindow, then it is our main application window;
+ it should be raised when the application is activated */
+ if (EOS_IS_WINDOW (window))
+ {
+ if (self->priv->main_application_window != NULL)
+ {
+ g_error ("You should not add more than one application window.");
+ }
+ g_object_ref (window);
+ self->priv->main_application_window = EOS_WINDOW (window);
+ }
+}
+
+static void
+eos_application_window_removed (GtkApplication *application,
+ GtkWindow *window)
+{
+ EosApplication *self = EOS_APPLICATION (application);
+
+ GTK_APPLICATION_CLASS (eos_application_parent_class)->window_removed (
+ application, window);
+
+ if (EOS_IS_WINDOW (window))
+ {
+ if (self->priv->main_application_window == NULL)
+ {
+ g_warning ("EosWindow is being removed from EosApplication, although "
+ "none was added.");
+ return;
+ }
+ if (self->priv->main_application_window != EOS_WINDOW (window))
+ g_warning ("A different EosWindow is being removed from EosApplication "
+ "than the one that was added.");
+ g_object_unref (window);
+ self->priv->main_application_window = NULL;
+ }
+}
+
+static void
+eos_application_class_init (EosApplicationClass *klass)
+{
+ GApplicationClass *g_application_class = G_APPLICATION_CLASS (klass);
+ GtkApplicationClass *gtk_application_class = GTK_APPLICATION_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (EosApplicationPrivate));
+
+ g_application_class->activate = eos_application_activate;
+ gtk_application_class->window_added = eos_application_window_added;
+ gtk_application_class->window_removed = eos_application_window_removed;
+}
+
+static void
+eos_application_init (EosApplication *self)
+{
+ self->priv = APPLICATION_PRIVATE (self);
+}
+
+/* Public API */
+
+/**
+ * eos_application_new:
+ * @application_id: a unique identifier for the application, for example a
+ * reverse domain name.
+ * @flags: flags to apply to the application; see #GApplicationFlags.
+ *
+ * Create a new application. For the application ID, use a reverse domain name,
+ * such as <code>com.endlessm.weather</code>. See g_application_id_is_valid()
+ * for the full rules for application IDs.
+ *
+ * Returns: a pointer to the application.
+ */
+EosApplication *
+eos_application_new (const gchar *application_id,
+ GApplicationFlags flags)
+{
+ return g_object_new (EOS_TYPE_APPLICATION,
+ "application-id", application_id,
+ "flags", flags,
+ NULL);
+}
diff --git a/endless/application.h b/endless/application.h
new file mode 100644
index 0000000..5089c12
--- /dev/null
+++ b/endless/application.h
@@ -0,0 +1,70 @@
+/* Copyright 2013 Endless Mobile, Inc. */
+
+#if !(defined(_EOS_SDK_INSIDE_ENDLESS_H) || defined(COMPILING_EOS_SDK))
+#error "Please do not include this header file directly."
+#endif
+
+#ifndef EOS_APPLICATION_H
+#define EOS_APPLICATION_H
+
+#include "types.h"
+
+#include <gtk/gtk.h>
+
+#define EOS_TYPE_APPLICATION eos_application_get_type()
+
+#define EOS_APPLICATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ EOS_TYPE_APPLICATION, EosApplication))
+
+#define EOS_APPLICATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ EOS_TYPE_APPLICATION, EosApplicationClass))
+
+#define EOS_IS_APPLICATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ EOS_TYPE_APPLICATION))
+
+#define EOS_IS_APPLICATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ EOS_TYPE_APPLICATION))
+
+#define EOS_APPLICATION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ EOS_TYPE_APPLICATION, EosApplicationClass))
+
+typedef struct _EosApplication EosApplication;
+typedef struct _EosApplicationClass EosApplicationClass;
+typedef struct _EosApplicationPrivate EosApplicationPrivate;
+
+/**
+ * EosApplication:
+ *
+ * This class structure contains no public members.
+ */
+struct _EosApplication
+{
+ /*< private >*/
+ GtkApplication parent;
+
+ EosApplicationPrivate *priv;
+};
+
+struct _EosApplicationClass
+{
+ GtkApplicationClass parent_class;
+
+ /* For further expansion */
+ gpointer _padding[8];
+};
+
+EOS_SDK_ALL_API_VERSIONS
+GType eos_application_get_type (void) G_GNUC_CONST;
+
+EOS_SDK_ALL_API_VERSIONS
+EosApplication *eos_application_new (const gchar *application_id,
+ GApplicationFlags flags);
+
+G_END_DECLS
+
+#endif /* EOS_APPLICATION_H */
diff --git a/endless/endless.h b/endless/endless.h
index 84a33b0..b452247 100644
--- a/endless/endless.h
+++ b/endless/endless.h
@@ -12,6 +12,8 @@ G_BEGIN_DECLS
/* Pull in other header files */
#include "types.h"
+#include "application.h"
+#include "window.h"
#undef _EOS_SDK_INSIDE_ENDLESS_H
diff --git a/endless/types.h b/endless/types.h
index a572d7c..bfa5c1b 100644
--- a/endless/types.h
+++ b/endless/types.h
@@ -11,6 +11,8 @@
#include "macros.h"
#include "apiversion.h"
+#include <glib-object.h>
+
/* Shared typedefs for structures */
#endif /* EOS_TYPES_H */
diff --git a/endless/window.c b/endless/window.c
new file mode 100644
index 0000000..86c95fa
--- /dev/null
+++ b/endless/window.c
@@ -0,0 +1,121 @@
+/* Copyright 2013 Endless Mobile, Inc. */
+
+#include "config.h"
+#include "window.h"
+
+#include "application.h"
+
+#include <gtk/gtk.h>
+
+/**
+ * SECTION:window
+ * @short_description: A window for your application
+ * @title: Window
+ *
+ * Stub
+ */
+
+G_DEFINE_TYPE (EosWindow, eos_window, GTK_TYPE_APPLICATION_WINDOW)
+
+#define WINDOW_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), EOS_TYPE_WINDOW, EosWindowPrivate))
+
+struct _EosWindowPrivate
+{
+ EosApplication *application;
+};
+
+enum
+{
+ PROP_0,
+ PROP_APPLICATION,
+ NPROPS
+};
+
+static GParamSpec *eos_window_props[NPROPS] = { NULL, };
+
+static void
+eos_window_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EosWindow *self = EOS_WINDOW (object);
+
+ switch (property_id)
+ {
+ case PROP_APPLICATION:
+ g_value_set_object (value, self->priv->application);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+eos_window_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EosWindow *self = EOS_WINDOW (object);
+
+ switch (property_id)
+ {
+ case PROP_APPLICATION:
+ self->priv->application = g_value_get_object (value);
+ gtk_window_set_application (GTK_WINDOW (self),
+ GTK_APPLICATION (self->priv->application));
+ if (self->priv->application == NULL)
+ g_critical ("In order to create a window, you must have an application "
+ "for it to connect to.");
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+eos_window_class_init (EosWindowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (EosWindowPrivate));
+
+ object_class->get_property = eos_window_get_property;
+ object_class->set_property = eos_window_set_property;
+
+ eos_window_props[PROP_APPLICATION] =
+ g_param_spec_object ("application", "Application",
+ "Application associated with this window",
+ EOS_TYPE_APPLICATION,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, NPROPS, eos_window_props);
+}
+
+static void
+eos_window_init (EosWindow *self)
+{
+ self->priv = WINDOW_PRIVATE (self);
+}
+
+/* Public API */
+
+/**
+ * eos_window_new:
+ * @application: the #EosApplication that the window belongs to.
+ *
+ * Create a window. It is invisible by default.
+ *
+ * Returns: a pointer to the window.
+ */
+GtkWidget *
+eos_window_new (EosApplication *application)
+{
+ return GTK_WIDGET (g_object_new (EOS_TYPE_WINDOW,
+ "application", application,
+ NULL));
+}
diff --git a/endless/window.h b/endless/window.h
new file mode 100644
index 0000000..b92b4eb
--- /dev/null
+++ b/endless/window.h
@@ -0,0 +1,71 @@
+/* Copyright 2013 Endless Mobile, Inc. */
+
+#if !(defined(_EOS_SDK_INSIDE_ENDLESS_H) || defined(COMPILING_EOS_SDK))
+#error "Please do not include this header file directly."
+#endif
+
+#ifndef EOS_WINDOW_H
+#define EOS_WINDOW_H
+
+#include "types.h"
+
+#include "application.h"
+
+G_BEGIN_DECLS
+
+#define EOS_TYPE_WINDOW eos_window_get_type()
+
+#define EOS_WINDOW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ EOS_TYPE_WINDOW, EosWindow))
+
+#define EOS_WINDOW_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ EOS_TYPE_WINDOW, EosWindowClass))
+
+#define EOS_IS_WINDOW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ EOS_TYPE_WINDOW))
+
+#define EOS_IS_WINDOW_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ EOS_TYPE_WINDOW))
+
+#define EOS_WINDOW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ EOS_TYPE_WINDOW, EosWindowClass))
+
+typedef struct _EosWindow EosWindow;
+typedef struct _EosWindowClass EosWindowClass;
+typedef struct _EosWindowPrivate EosWindowPrivate;
+
+/**
+ * EosWindow:
+ *
+ * This class structure contains no public members.
+ */
+struct _EosWindow
+{
+ /*< private >*/
+ GtkApplicationWindow parent;
+
+ EosWindowPrivate *priv;
+};
+
+struct _EosWindowClass
+{
+ GtkApplicationWindowClass parent_class;
+
+ /* For further expansion */
+ gpointer _padding[8];
+};
+
+EOS_SDK_ALL_API_VERSIONS
+GType eos_window_get_type (void) G_GNUC_CONST;
+
+EOS_SDK_ALL_API_VERSIONS
+GtkWidget *eos_window_new (EosApplication *application);
+
+G_END_DECLS
+
+#endif /* EOS_WINDOW_H */