aboutsummaryrefslogtreecommitdiff
path: root/lib/gtk-experiment-widgets
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gtk-experiment-widgets')
-rw-r--r--lib/gtk-experiment-widgets/Makefile.am46
-rw-r--r--lib/gtk-experiment-widgets/cclosure-marshallers.list5
-rw-r--r--lib/gtk-experiment-widgets/gtk-experiment-navigator.c638
-rw-r--r--lib/gtk-experiment-widgets/gtk-experiment-navigator.h114
-rw-r--r--lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c417
-rw-r--r--lib/gtk-experiment-widgets/gtk-experiment-transcript-private.h140
-rw-r--r--lib/gtk-experiment-widgets/gtk-experiment-transcript.c1082
-rw-r--r--lib/gtk-experiment-widgets/gtk-experiment-transcript.h144
-rw-r--r--lib/gtk-experiment-widgets/gtk-experiment-widgets-catalog.xml23
9 files changed, 0 insertions, 2609 deletions
diff --git a/lib/gtk-experiment-widgets/Makefile.am b/lib/gtk-experiment-widgets/Makefile.am
deleted file mode 100644
index 57390db..0000000
--- a/lib/gtk-experiment-widgets/Makefile.am
+++ /dev/null
@@ -1,46 +0,0 @@
-AM_CFLAGS = -Wall
-
-BUILT_SOURCES = cclosure-marshallers.c cclosure-marshallers.h
-
-noinst_LTLIBRARIES = libgtk-experiment-transcript.la
-libgtk_experiment_transcript_la_SOURCES = gtk-experiment-transcript.h \
- gtk-experiment-transcript-private.h \
- gtk-experiment-transcript.c \
- gtk-experiment-transcript-formats.c
-
-libgtk_experiment_transcript_la_CFLAGS = $(AM_CFLAGS) \
- @LIBGTK_CFLAGS@
-libgtk_experiment_transcript_la_CPPFLAGS = -I@top_srcdir@/lib/experiment-reader
-
-lib_LTLIBRARIES = libgtk-experiment-widgets.la
-libgtk_experiment_widgets_la_SOURCES = gtk-experiment-navigator.h \
- gtk-experiment-navigator.c
-nodist_libgtk_experiment_widgets_la_SOURCES = $(BUILT_SOURCES)
-
-libgtk_experiment_widgets_la_CFLAGS = $(AM_CFLAGS)
-libgtk_experiment_widgets_la_CPPFLAGS =
-libgtk_experiment_widgets_la_LDFLAGS = -no-undefined -shared -bindir @bindir@ \
- -avoid-version
-libgtk_experiment_widgets_la_LIBADD = libgtk-experiment-transcript.la
-
-libgtk_experiment_widgets_la_CFLAGS += @LIBGTK_CFLAGS@
-libgtk_experiment_widgets_la_LIBADD += @LIBGTK_LIBS@
-
-libgtk_experiment_widgets_la_CPPFLAGS += -I@top_srcdir@/lib/experiment-reader
-libgtk_experiment_widgets_la_LIBADD += @top_srcdir@/lib/experiment-reader/libexperiment-reader.la
-
-include_HEADERS = gtk-experiment-navigator.h \
- gtk-experiment-transcript.h
-
-dist_gtk_experiment_widgets_catalogs_DATA = gtk-experiment-widgets-catalog.xml
-
-dist_noinst_DATA = cclosure-marshallers.list
-CLEANFILES = $(BUILT_SOURCES)
-
-MARSHAL_PREFIX = gtk_experiment_widgets_marshal
-
-cclosure-marshallers.c : cclosure-marshallers.list
- @GLIB_GENMARSHAL@ --prefix $(MARSHAL_PREFIX) --body $< >$@
-
-cclosure-marshallers.h : cclosure-marshallers.list
- @GLIB_GENMARSHAL@ --prefix $(MARSHAL_PREFIX) --header $< >$@
diff --git a/lib/gtk-experiment-widgets/cclosure-marshallers.list b/lib/gtk-experiment-widgets/cclosure-marshallers.list
deleted file mode 100644
index 539e1a4..0000000
--- a/lib/gtk-experiment-widgets/cclosure-marshallers.list
+++ /dev/null
@@ -1,5 +0,0 @@
-# Standard marshallers for "time-selected" signal callbacks
-VOID:INT64
-
-# Standard marshallers for "section-activated" signal callbacks
-VOID:INT64,INT64
diff --git a/lib/gtk-experiment-widgets/gtk-experiment-navigator.c b/lib/gtk-experiment-widgets/gtk-experiment-navigator.c
deleted file mode 100644
index 23b380e..0000000
--- a/lib/gtk-experiment-widgets/gtk-experiment-navigator.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/**
- * @file
- * GTK widget, extending a \e GtkTreeView, for displaying an experiment's
- * structure for navigational purposes.
- */
-
-/*
- * Copyright (C) 2012-2013 Otto-von-Guericke-Universität Magdeburg
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <assert.h>
-
-#include <glib.h>
-#include <glib/gprintf.h>
-
-#include <gtk/gtk.h>
-#include <experiment-reader.h>
-
-#include "cclosure-marshallers.h"
-#include "gtk-experiment-navigator.h"
-
-static void gtk_experiment_navigator_class_init(GtkExperimentNavigatorClass *klass);
-static void gtk_experiment_navigator_init(GtkExperimentNavigator *klass);
-
-static void gtk_experiment_navigator_dispose(GObject *gobject);
-static void gtk_experiment_navigator_finalize(GObject *gobject);
-
-static void gtk_experiment_navigator_row_activated(GtkTreeView *tree_view,
- GtkTreePath *path,
- GtkTreeViewColumn *column);
-static void gtk_experiment_navigator_cursor_changed(GtkTreeView *tree_view);
-
-static void time_cell_data_cb(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model, GtkTreeIter *iter,
- gpointer user_data);
-
-static inline void select_time(GtkExperimentNavigator *navi,
- gint64 selected_time);
-static inline void activate_section(GtkExperimentNavigator *navi,
- gint64 start, gint64 end);
-
-static void topic_row_callback(ExperimentReader *reader,
- const gchar *topic_id,
- gint64 start_time,
- gint64 end_time,
- gpointer data);
-
-/**
- * @private
- * Unreference object given by variable, but only once.
- * Use it in \ref gtk_experiment_navigator_dispose to unreference object
- * references in public or private instance attributes.
- *
- * @sa gtk_experiment_navigator_dispose
- *
- * @param VAR Variable to unreference
- */
-#define GOBJECT_UNREF_SAFE(VAR) G_STMT_START { \
- if ((VAR) != NULL) { \
- g_object_unref(VAR); \
- VAR = NULL; \
- } \
-} G_STMT_END
-
-/** @private */
-#define GTK_EXPERIMENT_NAVIGATOR_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE((obj), GTK_TYPE_EXPERIMENT_NAVIGATOR, GtkExperimentNavigatorPrivate))
-
-/**
- * @private
- * Private instance attribute structure.
- * You can access these attributes using \c klass->priv->attribute.
- */
-struct _GtkExperimentNavigatorPrivate {
- gint dummy; /**< unused dummy attribute, may be deleted when other attributes are added */
-
- /**
- * @todo
- * Add necessary \b private instance attributes. They must be
- * initialized in the instance initializer function.
- */
-};
-
-struct TopicCallbackData {
- GtkTreeIter iter;
- GtkTreeStore *store;
- gint64 start_time;
- gint64 end_time;
-};
-
-/** @private */
-enum {
- TIME_SELECTED_SIGNAL,
- SECTION_ACTIVATED_SIGNAL,
- LAST_SIGNAL
-};
-static guint gtk_experiment_navigator_signals[LAST_SIGNAL] = {0, 0};
-
-/**
- * @private
- * Enumeration of tree store columns that serve as Ids when manipulating
- * the store.
- */
-enum {
- COL_NAME, /**< Name of the section, subsection or topic (\c G_TYPE_STRING) */
- COL_START_TIME, /**< Start time of the entity (\c G_TYPE_INT64 in milliseconds) */
- COL_END_TIME, /**< End time of the entity (\c G_TYPE_INT64 in milliseconds) */
- NUM_COLS /**< Number of columns */
-
- /** @todo Add additional tree store columns as necessary */
-};
-
-/**
- * @private
- * Will create \e gtk_experiment_navigator_get_type and set
- * \e gtk_experiment_navigator_parent_class
- */
-G_DEFINE_TYPE(GtkExperimentNavigator, gtk_experiment_navigator, GTK_TYPE_TREE_VIEW);
-
-static void
-gtk_experiment_navigator_class_init(GtkExperimentNavigatorClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- GtkTreeViewClass *treeview_class = GTK_TREE_VIEW_CLASS(klass);
-
- gobject_class->dispose = gtk_experiment_navigator_dispose;
- gobject_class->finalize = gtk_experiment_navigator_finalize;
-
- treeview_class->row_activated = gtk_experiment_navigator_row_activated;
- treeview_class->cursor_changed = gtk_experiment_navigator_cursor_changed;
-
- gtk_experiment_navigator_signals[TIME_SELECTED_SIGNAL] =
- g_signal_new("time-selected",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET(GtkExperimentNavigatorClass, time_selected),
- NULL, NULL,
- gtk_experiment_widgets_marshal_VOID__INT64,
- G_TYPE_NONE, 1, G_TYPE_INT64);
-
- gtk_experiment_navigator_signals[SECTION_ACTIVATED_SIGNAL] =
- g_signal_new("section-activated",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET(GtkExperimentNavigatorClass, section_activated),
- NULL, NULL,
- gtk_experiment_widgets_marshal_VOID__INT64_INT64,
- G_TYPE_NONE, 2, G_TYPE_INT64, G_TYPE_INT64);
-
- g_type_class_add_private(klass, sizeof(GtkExperimentNavigatorPrivate));
-}
-
-/**
- * @brief Instance initializer function for the \e GtkExperimentNavigator widget
- *
- * It has to create the \e GtkTreeStore (MVC model), add and configure
- * view columns and add cell renderers to the view columns.
- * It should connect the necessary signals to respond to row activations
- * (double click) in order to emit the "time-selected" signal.
- * It should also initialize all used \b public and \b private attributes.
- *
- * @param klass Newly constructed \e GtkExperimentNavigator instance
- */
-static void
-gtk_experiment_navigator_init(GtkExperimentNavigator *klass)
-{
- GtkTreeView *view = GTK_TREE_VIEW(klass);
- GtkTreeViewColumn *col;
- GtkCellRenderer *renderer;
-
- GtkTreeStore *store;
-
- klass->priv = GTK_EXPERIMENT_NAVIGATOR_GET_PRIVATE(klass);
- /*
- * Create tree store (and model)
- * NOTE: GtkTreeStore is directly derived from GObject and has a
- * reference count of 1 after creation.
- */
- store = gtk_tree_store_new(NUM_COLS, G_TYPE_STRING,
- G_TYPE_INT64, G_TYPE_INT64);
-
- /*
- * Create TreeView column corresponding to the
- * TreeStore column \e COL_NAME
- */
- col = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(col, "Name");
- gtk_tree_view_column_set_expand(col, TRUE);
- gtk_tree_view_append_column(view, col);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(col, renderer, TRUE);
- gtk_tree_view_column_add_attribute(col, renderer, "text", COL_NAME);
- /**
- * @todo
- * Perhaps an icon should be rendered in front of the name to
- * indicate the entity's type (section, subsection, topic...)
- */
-
- /*
- * Create TreeView column corresponding to the
- * TreeStore column \c COL_START_TIME
- */
- col = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(col, "Start");
- gtk_tree_view_append_column(view, col);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(col, renderer, TRUE);
- /* Cell data function for custom formatting */
- gtk_tree_view_column_set_cell_data_func(col, renderer,
- time_cell_data_cb,
- GINT_TO_POINTER(COL_START_TIME),
- NULL);
-
- /*
- * Create TreeView column corresponding to the
- * TreeStore column \c COL_END_TIME
- */
- col = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(col, "End");
- gtk_tree_view_append_column(view, col);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(col, renderer, TRUE);
- /* Cell data function for custom formatting */
- gtk_tree_view_column_set_cell_data_func(col, renderer,
- time_cell_data_cb,
- GINT_TO_POINTER(COL_END_TIME),
- NULL);
-
- /*
- * Set TreeView model to store's model
- */
- gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
- /* destroy store/model automatically with view */
- g_object_unref(store);
-
- /** @todo better \e TreeViewColumn formatting */
- /**
- * @todo
- * Initialize necessary \b public and \b private attributes.
- * When using object references, they must be unreferenced in
- * \ref gtk_experiment_navigator_dispose.
- * Keep in mind that when using objects derived from \e GtkObject,
- * they will not be reference-counted like ordinary \e GObjects (you
- * will not own an ordinary reference after object creation that can
- * be unreferenced).
- * In order to get an ordinary reference, use \e g_object_ref_sink
- * on the object after creation.
- */
-}
-
-/**
- * @brief Instance disposal function
- *
- * Its purpose is to unreference \e GObjects
- * the instance keeps references to (object pointers saved in the
- * instance attributes).
- * Keep in mind that this function may be called more than once, so
- * you must guard against unreferencing an object more than once (since you
- * will only own a single reference).
- * Also keep in mind that instance methods may be invoked \b after the instance
- * disposal function was executed but \b before instance finalization. This
- * case has to be handled gracefully in the instance methods.
- *
- * @sa GOBJECT_UNREF_SAFE
- * @sa gtk_experiment_navigator_finalize
- * @sa gtk_experiment_navigator_init
- *
- * @param gobject \e GObject to dispose
- */
-static void
-gtk_experiment_navigator_dispose(GObject *gobject)
-{
- //GtkExperimentNavigator *navi = GTK_EXPERIMENT_NAVIGATOR(gobject);
-
- /*
- * destroy might be called more than once, but we have only one
- * reference for each object
- */
- /**
- * @todo
- * Unreference all \e GObject references kept in public or
- * private attributes. Use \ref GOBJECT_UNREF_SAFE.
- * For example, to unreference private object \c widget:
- * @code
- * GOBJECT_UNREF_SAFE(navi->priv->widget);
- * @endcode
- */
-
- /* Chain up to the parent class */
- G_OBJECT_CLASS(gtk_experiment_navigator_parent_class)->dispose(gobject);
-}
-
-/**
- * @brief Instance finalization function
- *
- * Its purpose is to free all remaining allocated memory referenced
- * in public and private instance attributes (e.g. a string).
- * For freeing (unreferencing) objects,
- * use \ref gtk_experiment_navigator_dispose.
- *
- * @sa gtk_experiment_navigator_dispose
- * @sa gtk_experiment_navigator_init
- *
- * @param gobject \e GObject to finalize
- */
-static void
-gtk_experiment_navigator_finalize(GObject *gobject)
-{
- //GtkExperimentNavigator *navi = GTK_EXPERIMENT_NAVIGATOR(gobject);
-
- /** @todo Free all memory referenced in public and private attributes */
-
- /* Chain up to the parent class */
- G_OBJECT_CLASS(gtk_experiment_navigator_parent_class)->finalize(gobject);
-}
-
-/**
- * Send time-selected Signal when a row is double-clicked
- *
- * @param tree_view the object on which the signal is emitted
- * @param path the GtkTreePath for the activated row
- * @param column the GtkTreeViewColumn in which the activation occurred
- */
-static void
-gtk_experiment_navigator_row_activated(GtkTreeView *tree_view,
- GtkTreePath *path,
- GtkTreeViewColumn *column __attribute__((unused)))
-{
- GtkTreeModel *treemodel = gtk_tree_view_get_model(tree_view);
- gint64 start_time;
- GtkTreeIter treeiter;
-
- gtk_tree_model_get_iter(treemodel, &treeiter, path);
- gtk_tree_model_get(treemodel, &treeiter,
- COL_START_TIME, &start_time,
- -1);
-
- select_time(GTK_EXPERIMENT_NAVIGATOR(tree_view), start_time);
-}
-
-/**
- * Send cursor-changed when the cursor has changed
- *
- * @param tree_view the object on which the signal is emitted
- */
-static void
-gtk_experiment_navigator_cursor_changed(GtkTreeView *tree_view)
-{
- GtkTreeModel *treemodel = gtk_tree_view_get_model(tree_view);
- GtkTreePath *treepath;
- GtkTreeIter treeiter;
- gint64 start_time;
- gint64 end_time;
-
- gtk_tree_view_get_cursor(tree_view, &treepath, NULL);
- gtk_tree_model_get_iter(treemodel, &treeiter, treepath);
- gtk_tree_path_free(treepath);
-
- gtk_tree_model_get(treemodel, &treeiter,
- COL_START_TIME, &start_time,
- COL_END_TIME, &end_time,
- -1);
-
- activate_section(GTK_EXPERIMENT_NAVIGATOR(tree_view), start_time, end_time);
-}
-
-/**
- * @brief Cell data function to invoke when rendering the "Start" and
- * "End" columns.
- *
- * @param col \e GtkTreeViewColumn to render for
- * @param renderer Cell renderer to use for rendering
- * @param model \e GtkTreeModel associated with the view
- * @param iter Row identifier
- * @param user_data Callback user data
- */
-static void
-time_cell_data_cb(GtkTreeViewColumn *col __attribute__((unused)),
- GtkCellRenderer *renderer,
- GtkTreeModel *model, GtkTreeIter *iter,
- gpointer user_data)
-{
- gint column = GPOINTER_TO_INT(user_data);
-
- gint64 time_val;
- gchar buf[20];
-
- gtk_tree_model_get(model, iter,
- column, &time_val, -1);
-
- g_snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ,
- time_val /1000/60, time_val/1000 % 60);
-
- g_object_set(renderer, "text", buf, NULL);
-}
-
-/**
- * @brief Emit "time-selected" signal on a \e GtkExperimentNavigator instance.
- *
- * It should be emitted when a row entry was selected (double-clicked).
- *
- * @sa GtkExperimentNavigatorClass::time_selected
- *
- * @param navi Widget to emit the signal on
- * @param selected_time Selected time in milliseconds
- */
-static inline void
-select_time(GtkExperimentNavigator *navi, gint64 selected_time)
-{
- g_signal_emit(navi, gtk_experiment_navigator_signals[TIME_SELECTED_SIGNAL], 0,
- selected_time);
-}
-
-/**
- * @brief Emit "section-activated" signal on a \e GtkExperimentNavigator instance.
- *
- * It should be emitted when a row entry was activated (e.g. single-clicked)
- *
- * @sa GtkExperimentNavigatorClass::section_activated
- *
- * @param navi Widget to emit the signal on
- * @param start Start time of section in milliseconds
- * @param end End time of section in milliseconds
- */
-static inline void
-activate_section(GtkExperimentNavigator *navi, gint64 start, gint64 end)
-{
- g_signal_emit(navi, gtk_experiment_navigator_signals[SECTION_ACTIVATED_SIGNAL], 0,
- start, end);
-}
-
-/**
- * Callback function insert new row in GtkTreeStore
- * initialised colomb name and start time out of userdata
- *
- * @param reader \e ExperimentReader the information refers to
- * @param topic_id Symbolic identifier of experiment \b topic
- * @param start_time Beginning of first \b contribution in \e topic (milliseconds)
- * @param end_time End of last \b contribution in \e topic (milliseconds)
- * @param data Callback user data
- */
-static void
-topic_row_callback(ExperimentReader *reader,
- const gchar *topic_id,
- gint64 start_time,
- gint64 end_time,
- gpointer data)
-{
- struct TopicCallbackData *tcb = (struct TopicCallbackData *) data;
- GtkTreeIter topic;
-
- if (tcb->start_time < 0)
- tcb->start_time = start_time;
- tcb->end_time = end_time;
-
- gtk_tree_store_append(tcb->store, &topic, &tcb->iter);
- gtk_tree_store_set(tcb->store, &topic,
- COL_NAME, topic_id,
- COL_START_TIME, start_time,
- COL_END_TIME, end_time,
- -1);
-}
-
-/*
- * API
- */
-
-/**
- * @brief Construct new \e GtkExperimentNavigator widget instance.
- *
- * @return New \e GtkExperimentNavigator widget instance
- */
-GtkWidget *
-gtk_experiment_navigator_new(void)
-{
- return GTK_WIDGET(g_object_new(GTK_TYPE_EXPERIMENT_NAVIGATOR, NULL));
-}
-
-/**
- * Fills the \e GtkExperimentNavigator widget with the structure specified
- * in an experiment-XML file (see session.dtd).
- * Any existing contents should be cleared.
- *
- * @param navi Object instance to display the structure in
- * @param exp \e ExperimentReader instance of opened XML-file
- * @return \c TRUE on success, else \c FALSE
- */
-gboolean
-gtk_experiment_navigator_load(GtkExperimentNavigator *navi,
- ExperimentReader *exp)
-{
- struct TopicCallbackData tcd;
- GtkTreeIter experiment_level;
- GtkTreeIter last_minute_level;
-
- tcd.store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(navi)));
- gtk_tree_store_clear(tcd.store);
-
- /* greeting */
- gtk_tree_store_append(tcd.store, &tcd.iter, NULL);
-
- tcd.start_time = -1;
- experiment_reader_foreach_greeting_topic(exp, topic_row_callback, &tcd);
-
- gtk_tree_store_set(tcd.store, &tcd.iter,
- COL_NAME, "greeting",
- COL_START_TIME, tcd.start_time,
- COL_END_TIME, tcd.end_time,
- -1);
-
- /* experiment */
- gtk_tree_store_append(tcd.store, &experiment_level, NULL);
- gtk_tree_store_set(tcd.store, &experiment_level,
- COL_NAME, "experiment",
- -1);
-
- gtk_tree_store_append(tcd.store, &tcd.iter, &experiment_level);
-
- tcd.start_time = -1;
- experiment_reader_foreach_exp_initial_narrative_topic(exp,
- topic_row_callback,
- &tcd);
-
- gtk_tree_store_set(tcd.store, &tcd.iter,
- COL_NAME, "initial-narrative",
- COL_START_TIME, tcd.start_time < 0 ? tcd.end_time
- : tcd.start_time,
- COL_END_TIME, tcd.end_time,
- -1);
-
- gtk_tree_store_set(tcd.store, &experiment_level,
- COL_START_TIME, tcd.start_time < 0 ? tcd.end_time
- : tcd.start_time,
- -1);
-
- gtk_tree_store_append(tcd.store, &last_minute_level, &experiment_level);
- gtk_tree_store_set(tcd.store, &last_minute_level,
- COL_NAME, "last minute",
- -1);
-
- for (gint i = 1; i <= 6; i++) {
- gchar phasename[8];
-
- g_snprintf(phasename, sizeof(phasename), "phase %d", i);
- gtk_tree_store_append(tcd.store,
- &tcd.iter,
- &last_minute_level);
-
- tcd.start_time = -1;
- experiment_reader_foreach_exp_last_minute_phase_topic(exp, i, topic_row_callback, &tcd);
-
- gtk_tree_store_set(tcd.store, &tcd.iter,
- COL_NAME, phasename,
- COL_START_TIME, tcd.start_time < 0 ? tcd.end_time
- : tcd.start_time,
- COL_END_TIME, tcd.end_time,
- -1);
-
- if (i == 1) {
- gtk_tree_store_set(tcd.store, &last_minute_level,
- COL_START_TIME,
- tcd.start_time < 0 ? tcd.end_time
- : tcd.start_time,
- -1);
- }
- }
-
- gtk_tree_store_set(tcd.store, &last_minute_level,
- COL_END_TIME, tcd.end_time,
- -1);
-
- gtk_tree_store_set(tcd.store, &experiment_level,
- COL_END_TIME, tcd.end_time,
- -1);
-
- /* farewell */
- gtk_tree_store_append(tcd.store, &tcd.iter, NULL);
-
- tcd.start_time = -1;
- experiment_reader_foreach_farewell_topic(exp, topic_row_callback, &tcd);
-
- gtk_tree_store_set(tcd.store, &tcd.iter,
- COL_NAME, "farewell",
- COL_START_TIME, tcd.start_time,
- COL_END_TIME, tcd.end_time,
- -1);
-
- return TRUE;
-}
-
-/**
- * Fills the \e GtkExperimentNavigator widget with the structure specified
- * in an experiment-XML file (see session.dtd).
- * It accepts an XML filename and is otherwise identical to
- * \ref gtk_experiment_navigator_load.
- *
- * @sa gtk_experiment_navigator_load
- *
- * @param navi Object instance to display the structure in
- * @param exp Filename of XML-file to open and use for configuring \e navi
- * @return \c TRUE on success, else \c FALSE
- */
-gboolean
-gtk_experiment_navigator_load_filename(GtkExperimentNavigator *navi,
- const gchar *exp)
-{
- gboolean returnvalue;
- ExperimentReader *expread = experiment_reader_new(exp);
-
- if (expread == NULL)
- return FALSE;
- returnvalue = gtk_experiment_navigator_load(navi, expread);
-
- g_object_unref(expread);
-
- return returnvalue;
-}
diff --git a/lib/gtk-experiment-widgets/gtk-experiment-navigator.h b/lib/gtk-experiment-widgets/gtk-experiment-navigator.h
deleted file mode 100644
index d1be33c..0000000
--- a/lib/gtk-experiment-widgets/gtk-experiment-navigator.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * @file
- * Header file necessary to include when using the \e GtkExperimentNavigator
- * widget.
- */
-
-/*
- * Copyright (C) 2012-2013 Otto-von-Guericke-Universität Magdeburg
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GTK_EXPERIMENT_NAVIGATOR_H
-#define __GTK_EXPERIMENT_NAVIGATOR_H
-
-#include <glib-object.h>
-#include <gtk/gtk.h>
-
-#include <experiment-reader.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_EXPERIMENT_NAVIGATOR \
- (gtk_experiment_navigator_get_type())
-/**
- * Cast instance pointer to \e GtkExperimentNavigator
- *
- * @param obj Object to cast to \e GtkExperimentNavigator
- * @return \e obj casted to \e GtkExperimentNavigator
- */
-#define GTK_EXPERIMENT_NAVIGATOR(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_EXPERIMENT_NAVIGATOR, GtkExperimentNavigator))
-#define GTK_EXPERIMENT_NAVIGATOR_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_EXPERIMENT_NAVIGATOR, GtkExperimentNavigatorClass))
-#define GTK_IS_EXPERIMENT_NAVIGATOR(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_EXPERIMENT_NAVIGATOR))
-#define GTK_IS_EXPERIMENT_NAVIGATOR_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_EXPERIMENT_NAVIGATOR))
-#define GTK_EXPERIMENT_NAVIGATOR_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_EXPERIMENT_NAVIGATOR, GtkExperimentNavigatorClass))
-
-/** @private */
-typedef struct _GtkExperimentNavigatorPrivate GtkExperimentNavigatorPrivate;
-
-/**
- * \e GtkExperimentNavigator instance structure
- */
-typedef struct _GtkExperimentNavigator {
- GtkTreeView parent_instance; /**< Parent instance structure */
-
- /**
- * @todo
- * Add necessary \b public instance attributes. They must be
- * initialized in the instance initializer function.
- */
-
- GtkExperimentNavigatorPrivate *priv; /**< @private Pointer to \b private instance attributes */
-} GtkExperimentNavigator;
-
-/**
- * \e GtkExperimentNavigator class structure
- */
-typedef struct _GtkExperimentNavigatorClass {
- GtkTreeViewClass parent_class; /**< Parent class structure */
-
- /**
- * Callback function to invoke when emitting the "time-selected"
- * signal.
- *
- * @param self \e GtkExperimentNavigator the event was emitted on.
- * @param selected_time Time selected by the navigator in milliseconds
- */
- void (*time_selected)(GtkExperimentNavigator *self,
- gint64 selected_time);
-
- /**
- * Callback function to invoke when emitting the "section-activated"
- * signal.
- *
- * @param self \e GtkExperimentNavigator the event was emitted on.
- * @param start Start time of section in milliseconds
- * @param end End time of section in milliseconds
- */
- void (*section_activated)(GtkExperimentNavigator *self,
- gint64 start, gint64 end);
-} GtkExperimentNavigatorClass;
-
-/** @private */
-GType gtk_experiment_navigator_get_type(void);
-
-/*
- * API
- */
-GtkWidget *gtk_experiment_navigator_new(void);
-
-gboolean gtk_experiment_navigator_load(GtkExperimentNavigator *navi,
- ExperimentReader *exp);
-gboolean gtk_experiment_navigator_load_filename(GtkExperimentNavigator *navi,
- const gchar *exp);
-
-G_END_DECLS
-
-#endif
diff --git a/lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c b/lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c
deleted file mode 100644
index d81d6b9..0000000
--- a/lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/**
- * @file
- * "Format" expression-related functions of the \e GtkExperimentTranscript
- * widget
- */
-
-/*
- * Copyright (C) 2012-2013 Otto-von-Guericke-Universität Magdeburg
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <glib/gstdio.h>
-
-#include <gtk/gtk.h>
-
-#include "gtk-experiment-transcript.h"
-#include "gtk-experiment-transcript-private.h"
-
-static inline gint attr_list_get_length(PangoAttrList *list);
-static gboolean gtk_experiment_transcript_parse_format(GtkExperimentTranscriptFormat *fmt,
- const gchar *str,
- GError **error);
-
-#define FORMAT_REGEX_COMPILE_FLAGS (G_REGEX_CASELESS)
-#define FORMAT_REGEX_MATCH_FLAGS (0)
-
-static inline gint
-attr_list_get_length(PangoAttrList *list)
-{
- PangoAttrIterator *iter = pango_attr_list_get_iterator(list);
- gint length = 0;
-
- do
- length++;
- while (pango_attr_iterator_next(iter));
- pango_attr_iterator_destroy(iter);
-
- return length;
-}
-
-static gboolean
-gtk_experiment_transcript_parse_format(GtkExperimentTranscriptFormat *fmt,
- const gchar *str,
- GError **error)
-{
- PangoAttrIterator *iter;
-
- gchar *pattern, *pattern_captures, *p;
- gint capture_count = 0;
-
- g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
-
- if (!pango_parse_markup(str, -1, 0, &fmt->attribs, &pattern,
- NULL, error))
- return FALSE;
-
- p = pattern_captures = g_malloc(strlen(pattern) + 1 +
- 2*attr_list_get_length(fmt->attribs));
- iter = pango_attr_list_get_iterator(fmt->attribs);
- do {
- gint start, end;
-
- pango_attr_iterator_range(iter, &start, &end);
- if (end == G_MAXINT)
- end = strlen(pattern);
-
- if (end - start > 0) {
- *p++ = '(';
- strncpy(p, pattern + start, end - start);
- p += end - start;
- *p++ = ')';
-
- capture_count++;
- }
- } while (pango_attr_iterator_next(iter));
- pango_attr_iterator_destroy(iter);
- *p = '\0';
- g_free(pattern);
-
- fmt->regexp = g_regex_new(pattern_captures,
- FORMAT_REGEX_COMPILE_FLAGS, 0, error);
- g_free(pattern_captures);
- if (fmt->regexp == NULL) {
- gtk_experiment_transcript_free_format(fmt);
- fmt->attribs = NULL;
-
- return FALSE;
- }
-
- if (g_regex_get_capture_count(fmt->regexp) != capture_count) {
- g_set_error(error,
- GTK_EXPERIMENT_TRANSCRIPT_ERROR,
- GTK_EXPERIMENT_TRANSCRIPT_ERROR_REGEXCAPTURES,
- "Additional regular expression captures not allowed");
-
- gtk_experiment_transcript_free_format(fmt);
- fmt->regexp = NULL;
- fmt->attribs = NULL;
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-/** @private */
-G_GNUC_INTERNAL void
-gtk_experiment_transcript_apply_format(GtkExperimentTranscriptFormat *fmt,
- const gchar *text,
- PangoAttrList *attrib_list)
-{
- GMatchInfo *match_info;
-
- if (fmt->regexp == NULL || fmt->attribs == NULL)
- return;
-
- g_regex_match(fmt->regexp, text, FORMAT_REGEX_MATCH_FLAGS, &match_info);
-
- while (g_match_info_matches(match_info)) {
- PangoAttrIterator *iter;
- gint match_num = 0;
-
- iter = pango_attr_list_get_iterator(fmt->attribs);
- do {
- gint start, end;
- GSList *attribs;
-
- pango_attr_iterator_range(iter, &start, &end);
- if (end == G_MAXINT)
- end = strlen(g_regex_get_pattern(fmt->regexp));
-
- if (end - start == 0)
- continue;
-
- start = end = -1;
- g_match_info_fetch_pos(match_info, ++match_num,
- &start, &end);
- if (start < 0 || end < 0)
- continue;
-
- attribs = pango_attr_iterator_get_attrs(iter);
- for (GSList *cur = attribs; cur != NULL; cur = cur->next) {
- PangoAttribute *attrib;
-
- attrib = pango_attribute_copy((PangoAttribute *)cur->data);
- attrib->start_index = (guint)start;
- attrib->end_index = (guint)end;
- pango_attr_list_change(attrib_list, attrib);
- }
- g_slist_free(attribs);
- } while (pango_attr_iterator_next(iter));
- pango_attr_iterator_destroy(iter);
-
- g_match_info_next(match_info, NULL);
- }
-
- g_match_info_free(match_info);
-}
-
-/** @private */
-G_GNUC_INTERNAL void
-gtk_experiment_transcript_free_formats(GSList *formats)
-{
- for (GSList *cur = formats; cur != NULL; cur = cur->next) {
- GtkExperimentTranscriptFormat *fmt =
- (GtkExperimentTranscriptFormat *)cur->data;
-
- gtk_experiment_transcript_free_format(fmt);
- g_free(fmt);
- }
-
- g_slist_free(formats);
-}
-
-/*
- * API
- */
-
-/**
- * @brief Load a format file to use with the transcript widget
- *
- * Loading a format file applies additional formattings (highlighting) to the
- * transcript's contributions according to the rules specified in the file.
- * For information about the format file syntax and semantics, refer to the
- * "Experiment Player" manual.
- *
- * The format file is parsed and and compiled to an internal representation.
- *
- * @param trans Widget instance
- * @param filename File name of format file to load (\c NULL or empty string
- * resets any formattings of a previously loaded file)
- * @param error GError to set on failure, or \c NULL
- * @return \c TRUE on success, else \c FALSE
- */
-gboolean
-gtk_experiment_transcript_load_formats(GtkExperimentTranscript *trans,
- const gchar *filename,
- GError **error)
-{
- FILE *file;
- gchar buf[1024];
- gint cur_line = 0;
-
- gboolean res = FALSE;
-
- g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
-
- gtk_experiment_transcript_free_formats(trans->priv->formats);
- trans->priv->formats = NULL;
-
- if (filename == NULL || !*filename) {
- res = TRUE;
- goto redraw;
- }
-
- if ((file = g_fopen(filename, "r")) == NULL) {
- g_set_error(error,
- GTK_EXPERIMENT_TRANSCRIPT_ERROR,
- GTK_EXPERIMENT_TRANSCRIPT_ERROR_FILEOPEN,
- "Failed to open format file \"%s\":\n%s",
- filename, g_strerror(errno));
-
- goto redraw;
- }
-
- while (fgets((char *)buf, sizeof(buf), file) != NULL) {
- GtkExperimentTranscriptFormat *fmt;
-
- cur_line++;
-
- if (!feof(file) && !is_newline(buf[strlen(buf) - 1])) {
- g_set_error(error,
- GTK_EXPERIMENT_TRANSCRIPT_ERROR,
- GTK_EXPERIMENT_TRANSCRIPT_ERROR_LINELENGTH,
- "Line %d in file \"%s\" is too long. "
- "It must be less than %d characters.",
- cur_line, filename, (int)sizeof(buf));
-
- fclose(file);
- gtk_experiment_transcript_free_formats(trans->priv->formats);
- trans->priv->formats = NULL;
-
- goto redraw;
- }
-
- g_strchug(buf);
-
- /* strip new line chars from end of `buf' */
- for (gchar *p = buf + strlen(buf) - 1;
- p >= buf && is_newline(*p);
- p--)
- *p = '\0';
-
- if (*buf == '#' || *buf == '\0')
- continue;
-
- fmt = g_new(GtkExperimentTranscriptFormat, 1);
-
- if (!gtk_experiment_transcript_parse_format(fmt, buf, error)) {
- g_prefix_error(error,
- "Error parsing \"%s\" on line %d:\n",
- filename, cur_line);
-
- g_free(fmt);
- fclose(file);
- gtk_experiment_transcript_free_formats(trans->priv->formats);
- trans->priv->formats = NULL;
-
- goto redraw;
- }
-
- trans->priv->formats = g_slist_prepend(trans->priv->formats, fmt);
- }
- trans->priv->formats = g_slist_reverse(trans->priv->formats);
-
- fclose(file);
- res = TRUE;
-
-redraw:
- gtk_experiment_transcript_text_layer_redraw(trans);
- return res;
-}
-
-/**
- * @brief Specify an interactive format string for a transcript widget
- *
- * Associates a single format rule with a transcript widget. The formatting
- * changes are cumulatively applied after any changes introduced by a format
- * file loaded into the widget. The interactive format rule is independant of
- * any format file rules, that is it is not reset when format file rules are
- * reset.
- * A rule may also be given without Pango markup (plain regular expression),
- * applying default formattings for that regular expression. Default formattings
- * may be configured via public instance attributes of the widget.
- * For information about the format rule syntax and semantics, refer to the
- * "Experiment Player" manual.
- *
- * @sa gtk_experiment_transcript_load_formats
- *
- * @param trans Widget instance
- * @param format_str Format rule string (with or without markup)
- * @param with_markup Must be \c TRUE if the format_str contains Pango markup,
- * else \c FALSE
- * @param error GError to set on failure, or \c NULL
- * @return \c TRUE on success, else \c FALSE
- */
-gboolean
-gtk_experiment_transcript_set_interactive_format(GtkExperimentTranscript *trans,
- const gchar *format_str,
- gboolean with_markup,
- GError **error)
-{
- GtkExperimentTranscriptFormat *fmt = &trans->priv->interactive_format;
-
- gchar *pattern;
- PangoAttribute *attrib;
-
- gboolean res = FALSE;
-
- g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
-
- gtk_experiment_transcript_free_format(fmt);
- fmt->regexp = NULL;
- fmt->attribs = NULL;
-
- if (format_str == NULL || !*format_str) {
- res = TRUE;
- goto redraw;
- }
-
- if (with_markup) {
- res = gtk_experiment_transcript_parse_format(fmt, format_str,
- error);
- goto redraw;
- }
- /* else if (!with_markup) */
-
- fmt->attribs = pango_attr_list_new();
- g_warn_if_fail(fmt->attribs != NULL);
- if (fmt->attribs == NULL)
- goto redraw;
-
- if (trans->interactive_format.default_font != NULL) {
- attrib = pango_attr_font_desc_new(trans->interactive_format.default_font);
- attrib->end_index = 1;
- pango_attr_list_insert(fmt->attribs, attrib);
- }
- if (trans->interactive_format.default_text_color != NULL) {
- GdkColor *color = trans->interactive_format.default_text_color;
-
- attrib = pango_attr_foreground_new(color->red,
- color->green,
- color->blue);
- attrib->end_index = 1;
- pango_attr_list_insert(fmt->attribs, attrib);
- }
- if (trans->interactive_format.default_bg_color != NULL) {
- GdkColor *color = trans->interactive_format.default_bg_color;
-
- attrib = pango_attr_background_new(color->red,
- color->green,
- color->blue);
- attrib->end_index = 1;
- pango_attr_list_insert(fmt->attribs, attrib);
- }
-
- pattern = g_strconcat("(", format_str, ")", NULL);
- fmt->regexp = g_regex_new(pattern, FORMAT_REGEX_COMPILE_FLAGS, 0, error);
- g_free(pattern);
- if (fmt->regexp == NULL) {
- gtk_experiment_transcript_free_format(fmt);
- fmt->attribs = NULL;
-
- goto redraw;
- }
-
- if (g_regex_get_capture_count(fmt->regexp) != 1) {
- g_set_error(error,
- GTK_EXPERIMENT_TRANSCRIPT_ERROR,
- GTK_EXPERIMENT_TRANSCRIPT_ERROR_REGEXCAPTURES,
- "Additional regular expression captures not allowed");
-
- gtk_experiment_transcript_free_format(fmt);
- fmt->regexp = NULL;
- fmt->attribs = NULL;
-
- goto redraw;
- }
- res = TRUE;
-
-redraw:
- gtk_experiment_transcript_text_layer_redraw(trans);
- return res;
-}
diff --git a/lib/gtk-experiment-widgets/gtk-experiment-transcript-private.h b/lib/gtk-experiment-widgets/gtk-experiment-transcript-private.h
deleted file mode 100644
index 8281b0d..0000000
--- a/lib/gtk-experiment-widgets/gtk-experiment-transcript-private.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- * @file
- * Private header for the \e GtkExperimentTranscript widget
- */
-
-/*
- * Copyright (C) 2012-2013 Otto-von-Guericke-Universität Magdeburg
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GTK_EXPERIMENT_TRANSCRIPT_PRIVATE_H
-#define __GTK_EXPERIMENT_TRANSCRIPT_PRIVATE_H
-
-#include <glib.h>
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-#include <experiment-reader.h>
-
-#include "gtk-experiment-transcript.h"
-
-/** @private */
-#define GTK_EXPERIMENT_TRANSCRIPT_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE((obj), GTK_TYPE_EXPERIMENT_TRANSCRIPT, GtkExperimentTranscriptPrivate))
-
-/** @private */
-typedef struct _GtkExperimentTranscriptFormat {
- GRegex *regexp;
- PangoAttrList *attribs;
-} GtkExperimentTranscriptFormat;
-
-/** @private */
-typedef enum {
- GTK_EXPERIMENT_TRANSCRIPT_REVERSE_MASK = 1 << 0,
- GTK_EXPERIMENT_TRANSCRIPT_USE_BACKDROP_MASK = 1 << 1
-} GtkExperimentTranscriptFlagMask;
-
-/**
- * @private
- * Private instance attribute structure.
- * You can access these attributes using \c klass->priv->attribute.
- */
-struct _GtkExperimentTranscriptPrivate {
- gint flag_mask;
-
- GtkObject *time_adjustment;
- gulong time_adj_on_value_changed_id;
-
- GdkPixmap *layer_text;
- PangoLayout *layer_text_layout;
-
- struct _GtkExperimentTranscriptBackdropArea {
- gint64 start;
- gint64 end;
- } backdrop;
-
- GList *contribs;
- GSList *formats;
- GtkExperimentTranscriptFormat interactive_format;
-
- GtkWidget *menu; /**< Drop-down menu, doesn't have to be unreferenced manually */
- GSList *alignment_group; /**< GtkRadioMenuItem group for Alignment settings (owned by GTK) */
- GtkWidget *menu_reverse_item;
-};
-
-/** @private */
-typedef gboolean (*GtkExperimentTranscriptContribRenderer)
- (GtkExperimentTranscript *, ExperimentReaderContrib *,
- gint64, gint64, gint *);
-
-/** @todo scale should be configurable */
-#define PX_PER_SECOND 15
-#define TIME_TO_PX(TIME) ((TIME)/(1000/PX_PER_SECOND))
-#define PX_TO_TIME(PX) (((PX)*1000)/PX_PER_SECOND)
-
-#define BACKDROP_VALUE \
- ((G_MAXUINT16*GTK_EXPERIMENT_TRANSCRIPT_BACKDROP)/100)
-
-/**
- * @private
- * Unreference object given by variable, but only once.
- * Use it in \ref gtk_experiment_transcript_dispose to unreference object
- * references in public or private instance attributes.
- *
- * @sa gtk_experiment_transcript_dispose
- *
- * @param VAR Variable to unreference
- */
-#define GOBJECT_UNREF_SAFE(VAR) G_STMT_START { \
- if ((VAR) != NULL) { \
- g_object_unref(VAR); \
- VAR = NULL; \
- } \
-} G_STMT_END
-
-/** @private */
-G_GNUC_INTERNAL
-void gtk_experiment_transcript_text_layer_redraw(GtkExperimentTranscript *trans);
-
-/** @private */
-G_GNUC_INTERNAL
-void gtk_experiment_transcript_apply_format(GtkExperimentTranscriptFormat *fmt,
- const gchar *text,
- PangoAttrList *attrib_list);
-
-/** @private */
-static inline void
-gtk_experiment_transcript_free_format(GtkExperimentTranscriptFormat *format)
-{
- if (format->regexp != NULL)
- g_regex_unref(format->regexp);
- if (format->attribs != NULL)
- pango_attr_list_unref(format->attribs);
-}
-
-/** @private */
-G_GNUC_INTERNAL
-void gtk_experiment_transcript_free_formats(GSList *formats);
-
-/** @private */
-static inline gboolean
-is_newline(gchar c)
-{
- return c == '\r' || c == '\n';
-}
-
-#endif
diff --git a/lib/gtk-experiment-widgets/gtk-experiment-transcript.c b/lib/gtk-experiment-widgets/gtk-experiment-transcript.c
deleted file mode 100644
index 093b608..0000000
--- a/lib/gtk-experiment-widgets/gtk-experiment-transcript.c
+++ /dev/null
@@ -1,1082 +0,0 @@
-/**
- * @file
- * GTK widget, extending a \e GtkWidget, for displaying an experiment's
- * transcript.
- */
-
-/*
- * Copyright (C) 2012-2013 Otto-von-Guericke-Universität Magdeburg
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <assert.h>
-
-#include <glib.h>
-#include <glib/gprintf.h>
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-#include <experiment-reader.h>
-
-#include "gtk-experiment-transcript.h"
-#include "gtk-experiment-transcript-private.h"
-
-static void gtk_experiment_transcript_class_init(GtkExperimentTranscriptClass *klass);
-static void gtk_experiment_transcript_init(GtkExperimentTranscript *klass);
-
-static void gtk_experiment_transcript_realize(GtkWidget *widget);
-static void gtk_experiment_transcript_size_allocate(GtkWidget *widget,
- GtkAllocation *allocation);
-static gboolean gtk_experiment_transcript_expose(GtkWidget *widget,
- GdkEventExpose *event);
-
-static void gtk_experiment_transcript_dispose(GObject *gobject);
-static void gtk_experiment_transcript_finalize(GObject *gobject);
-
-static void time_adj_on_value_changed(GtkAdjustment *adj, gpointer user_data);
-
-static void gtk_experiment_transcript_reconfigure(GtkExperimentTranscript *trans);
-
-static gboolean configure_text_layout(GtkExperimentTranscript *trans,
- ExperimentReaderContrib *contrib,
- gint64 current_time,
- gint y, gint last_contrib_y,
- int *logical_height);
-static gboolean render_contribution_bottomup(GtkExperimentTranscript *trans,
- ExperimentReaderContrib *contrib,
- gint64 current_time, gint64 current_time_px,
- gint *last_contrib_y);
-static gboolean render_contribution_topdown(GtkExperimentTranscript *trans,
- ExperimentReaderContrib *contrib,
- gint64 current_time, gint64 current_time_px,
- gint *last_contrib_y);
-static inline void render_backdrop_area(GtkExperimentTranscript *trans,
- gint64 current_time_px);
-
-static void state_changed(GtkWidget *widget, GtkStateType state);
-static gboolean button_pressed(GtkWidget *widget, GdkEventButton *event);
-static gboolean scrolled(GtkWidget *widget, GdkEventScroll *event);
-
-static void choose_font_activated(GtkWidget *widget, gpointer data);
-static void choose_text_color_activated(GtkWidget *widget, gpointer data);
-static void choose_bg_color_activated(GtkWidget *widget, gpointer data);
-static void text_alignment_activated(GtkWidget *widget, gpointer data);
-
-static void reverse_activated(GtkWidget *widget, gpointer data);
-
-/** @private */
-GQuark
-gtk_experiment_transcript_error_quark(void)
-{
- return g_quark_from_static_string("gtk-experiment-transcript-error-quark");
-}
-
-/**
- * @private
- * Will create \e gtk_experiment_transcript_get_type and set
- * \e gtk_experiment_transcript_parent_class
- */
-G_DEFINE_TYPE(GtkExperimentTranscript, gtk_experiment_transcript, GTK_TYPE_WIDGET);
-
-static void
-gtk_experiment_transcript_class_init(GtkExperimentTranscriptClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
-
- gobject_class->dispose = gtk_experiment_transcript_dispose;
- gobject_class->finalize = gtk_experiment_transcript_finalize;
-
- widget_class->realize = gtk_experiment_transcript_realize;
- widget_class->expose_event = gtk_experiment_transcript_expose;
- widget_class->size_allocate = gtk_experiment_transcript_size_allocate;
-
- widget_class->state_changed = state_changed;
- widget_class->button_press_event = button_pressed;
- widget_class->scroll_event = scrolled;
-
- g_type_class_add_private(klass, sizeof(GtkExperimentTranscriptPrivate));
-}
-
-/**
- * @brief Instance initializer function for the \e GtkExperimentTranscript widget
- *
- * @param klass Newly constructed \e GtkExperimentTranscript instance
- */
-static void
-gtk_experiment_transcript_init(GtkExperimentTranscript *klass)
-{
- GtkWidget *item, *submenu, *image;
-
- klass->priv = GTK_EXPERIMENT_TRANSCRIPT_GET_PRIVATE(klass);
-
- klass->speaker = NULL;
-
- klass->interactive_format.default_font = NULL;
- klass->interactive_format.default_text_color = NULL;
- klass->interactive_format.default_bg_color = NULL;
-
- klass->priv->flag_mask = 0;
-
- klass->priv->time_adjustment = gtk_adjustment_new(0., 0., 0.,
- 0., 0., 0.);
- g_object_ref_sink(klass->priv->time_adjustment);
- klass->priv->time_adj_on_value_changed_id =
- g_signal_connect(G_OBJECT(klass->priv->time_adjustment),
- "value-changed",
- G_CALLBACK(time_adj_on_value_changed), klass);
-
- klass->priv->layer_text = NULL;
- klass->priv->layer_text_layout =
- gtk_widget_create_pango_layout(GTK_WIDGET(klass), NULL);
- pango_layout_set_wrap(klass->priv->layer_text_layout, PANGO_WRAP_WORD_CHAR);
- pango_layout_set_ellipsize(klass->priv->layer_text_layout, PANGO_ELLIPSIZE_END);
-
- klass->priv->backdrop.start = 0;
- klass->priv->backdrop.end = 0;
-
- klass->priv->contribs = NULL;
- klass->priv->formats = NULL;
- klass->priv->interactive_format.regexp = NULL;
- klass->priv->interactive_format.attribs = NULL;
-
- /** @todo It should be possible to reset font and colors (to widget defaults) */
- klass->priv->menu = gtk_menu_new();
- gtk_menu_attach_to_widget(GTK_MENU(klass->priv->menu),
- GTK_WIDGET(klass), NULL);
-
- item = gtk_image_menu_item_new_with_mnemonic("Choose _Font...");
- image = gtk_image_new_from_stock(GTK_STOCK_SELECT_FONT,
- GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
- g_signal_connect(item, "activate",
- G_CALLBACK(choose_font_activated), klass);
- gtk_menu_shell_append(GTK_MENU_SHELL(klass->priv->menu), item);
- gtk_widget_show(item);
-
- item = gtk_image_menu_item_new_with_mnemonic("Choose _Text Color...");
- image = gtk_image_new_from_stock(GTK_STOCK_SELECT_COLOR,
- GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
- g_signal_connect(item, "activate",
- G_CALLBACK(choose_text_color_activated), klass);
- gtk_menu_shell_append(GTK_MENU_SHELL(klass->priv->menu), item);
- gtk_widget_show(item);
-
- item = gtk_image_menu_item_new_with_mnemonic("Choose _Background Color...");
- image = gtk_image_new_from_stock(GTK_STOCK_SELECT_COLOR,
- GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
- g_signal_connect(item, "activate",
- G_CALLBACK(choose_bg_color_activated), klass);
- gtk_menu_shell_append(GTK_MENU_SHELL(klass->priv->menu), item);
- gtk_widget_show(item);
-
- submenu = gtk_menu_new();
- item = gtk_menu_item_new_with_label("Text Alignment");
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
- gtk_menu_shell_append(GTK_MENU_SHELL(klass->priv->menu), item);
- gtk_widget_show(item);
-
- /*
- * position in alignment_group list corresponds with PangoAlignment
- * (PANGO_ALIGN_RIGHT, PANGO_ALIGN_CENTER, PANGO_ALIGN_LEFT)
- */
- item = gtk_radio_menu_item_new_with_mnemonic(NULL, "_Left");
- klass->priv->alignment_group =
- gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
- g_signal_connect(item, "activate",
- G_CALLBACK(text_alignment_activated), klass);
- gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item);
-
- item = gtk_radio_menu_item_new_with_mnemonic(klass->priv->alignment_group,
- "_Center");
- klass->priv->alignment_group =
- gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
- g_signal_connect(item, "activate",
- G_CALLBACK(text_alignment_activated), klass);
- gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item);
-
- item = gtk_radio_menu_item_new_with_mnemonic(klass->priv->alignment_group,
- "_Right");
- klass->priv->alignment_group =
- gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
- g_signal_connect(item, "activate",
- G_CALLBACK(text_alignment_activated), klass);
- gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item);
-
- gtk_widget_show_all(submenu);
- gtk_experiment_transcript_set_alignment(klass, PANGO_ALIGN_LEFT);
-
- item = gtk_separator_menu_item_new();
- gtk_menu_shell_append(GTK_MENU_SHELL(klass->priv->menu), item);
- gtk_widget_show(item);
-
- klass->priv->menu_reverse_item =
- gtk_check_menu_item_new_with_mnemonic("_Reverse");
- g_signal_connect(klass->priv->menu_reverse_item, "activate",
- G_CALLBACK(reverse_activated), klass);
- gtk_menu_shell_append(GTK_MENU_SHELL(klass->priv->menu),
- klass->priv->menu_reverse_item);
- gtk_widget_show(klass->priv->menu_reverse_item);
-
- gtk_widget_set_can_focus(GTK_WIDGET(klass), TRUE);
-}
-
-/**
- * @brief Instance disposal function
- *
- * Its purpose is to unreference \e GObjects
- * the instance keeps references to (object pointers saved in the
- * instance attributes).
- * Keep in mind that this function may be called more than once, so
- * you must guard against unreferencing an object more than once (since you
- * will only own a single reference).
- * Also keep in mind that instance methods may be invoked \b after the instance
- * disposal function was executed but \b before instance finalization. This
- * case has to be handled gracefully in the instance methods.
- *
- * @sa GOBJECT_UNREF_SAFE
- * @sa gtk_experiment_transcript_finalize
- * @sa gtk_experiment_transcript_init
- *
- * @param gobject \e GObject to dispose
- */
-static void
-gtk_experiment_transcript_dispose(GObject *gobject)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(gobject);
-
- /*
- * destroy might be called more than once, but we have only one
- * reference for each object
- */
- if (trans->priv->time_adjustment != NULL) {
- g_signal_handler_disconnect(G_OBJECT(trans->priv->time_adjustment),
- trans->priv->time_adj_on_value_changed_id);
- g_object_unref(trans->priv->time_adjustment);
- trans->priv->time_adjustment = NULL;
- }
- GOBJECT_UNREF_SAFE(trans->priv->layer_text);
- GOBJECT_UNREF_SAFE(trans->priv->layer_text_layout);
-
- /* Chain up to the parent class */
- G_OBJECT_CLASS(gtk_experiment_transcript_parent_class)->dispose(gobject);
-}
-
-/**
- * @brief Instance finalization function
- *
- * Its purpose is to free all remaining allocated memory referenced
- * in public and private instance attributes (e.g. a string).
- * For freeing (unreferencing) objects,
- * use \ref gtk_experiment_transcript_dispose.
- *
- * @sa gtk_experiment_transcript_dispose
- * @sa gtk_experiment_transcript_init
- *
- * @param gobject \e GObject to finalize
- */
-static void
-gtk_experiment_transcript_finalize(GObject *gobject)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(gobject);
-
- g_free(trans->speaker);
-
- if (trans->interactive_format.default_font != NULL)
- pango_font_description_free(trans->interactive_format.default_font);
- if (trans->interactive_format.default_text_color != NULL)
- gdk_color_free(trans->interactive_format.default_text_color);
- if (trans->interactive_format.default_bg_color != NULL)
- gdk_color_free(trans->interactive_format.default_bg_color);
-
- experiment_reader_free_contributions(trans->priv->contribs);
- gtk_experiment_transcript_free_formats(trans->priv->formats);
- gtk_experiment_transcript_free_format(&trans->priv->interactive_format);
-
- /* Chain up to the parent class */
- G_OBJECT_CLASS(gtk_experiment_transcript_parent_class)->finalize(gobject);
-}
-
-static void
-gtk_experiment_transcript_realize(GtkWidget *widget)
-{
- GdkWindowAttr attributes;
- gint attributes_mask;
-
- gtk_widget_set_realized(widget, TRUE);
-
- attributes.x = widget->allocation.x;
- attributes.y = widget->allocation.y;
- attributes.width = widget->allocation.width;
- attributes.height = widget->allocation.height;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.event_mask = gtk_widget_get_events(widget)
- | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
- attributes.visual = gtk_widget_get_visual(widget);
- attributes.colormap = gtk_widget_get_colormap(widget);
-
- gtk_widget_set_has_window(widget, TRUE);
-
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- widget->window = gdk_window_new(gtk_widget_get_parent_window(widget),
- &attributes, attributes_mask);
-
- widget->style = gtk_style_attach(widget->style, widget->window);
-
- gdk_window_set_user_data(widget->window, widget);
-
- gtk_style_set_background(widget->style, widget->window, GTK_STATE_ACTIVE);
-
- gtk_experiment_transcript_reconfigure(GTK_EXPERIMENT_TRANSCRIPT(widget));
-}
-
-static void
-gtk_experiment_transcript_size_allocate(GtkWidget *widget,
- GtkAllocation *allocation)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(widget);
- gboolean sizeChanged = widget->allocation.width != allocation->width ||
- widget->allocation.height != allocation->height;
-
- gtk_widget_set_allocation(widget, allocation);
-
- if (gtk_widget_get_realized(widget)) {
- gdk_window_move_resize(gtk_widget_get_window(widget),
- allocation->x, allocation->y,
- allocation->width, allocation->height);
-
- if (sizeChanged || trans->priv->layer_text == NULL)
- gtk_experiment_transcript_reconfigure(trans);
- }
-}
-
-static gboolean
-gtk_experiment_transcript_expose(GtkWidget *widget, GdkEventExpose *event)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(widget);
-
- gdk_draw_drawable(GDK_DRAWABLE(gtk_widget_get_window(widget)),
- widget->style->fg_gc[gtk_widget_get_state(widget)],
- GDK_DRAWABLE(trans->priv->layer_text),
- event->area.x, event->area.y,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
-
- return FALSE;
-}
-
-static void
-time_adj_on_value_changed(GtkAdjustment *adj, gpointer user_data)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(user_data);
-
- /**
- * @todo
- * heuristic to improve performance in the common case of advancing
- * time in small steps
- */
- gtk_experiment_transcript_text_layer_redraw(trans);
-}
-
-static void
-gtk_experiment_transcript_reconfigure(GtkExperimentTranscript *trans)
-{
- GtkWidget *widget = GTK_WIDGET(trans);
-
- gtk_adjustment_set_page_size(GTK_ADJUSTMENT(trans->priv->time_adjustment),
- (gdouble)PX_TO_TIME(widget->allocation.height));
-
- GOBJECT_UNREF_SAFE(trans->priv->layer_text);
- trans->priv->layer_text = gdk_pixmap_new(gtk_widget_get_window(widget),
- widget->allocation.width,
- widget->allocation.height,
- -1);
- pango_layout_set_width(trans->priv->layer_text_layout,
- widget->allocation.width*PANGO_SCALE);
-
- gtk_experiment_transcript_text_layer_redraw(trans);
-}
-
-static gboolean
-configure_text_layout(GtkExperimentTranscript *trans,
- ExperimentReaderContrib *contrib,
- gint64 current_time,
- gint y, gint last_contrib_y,
- int *logical_height)
-{
- PangoAttrList *attrib_list;
-
- if (contrib->start_time > current_time)
- return FALSE;
-
- attrib_list = pango_attr_list_new();
-
- for (GSList *cur = trans->priv->formats; cur != NULL; cur = cur->next) {
- GtkExperimentTranscriptFormat *fmt =
- (GtkExperimentTranscriptFormat *)cur->data;
-
- gtk_experiment_transcript_apply_format(fmt, contrib->text,
- attrib_list);
- }
- gtk_experiment_transcript_apply_format(&trans->priv->interactive_format,
- contrib->text, attrib_list);
-
- pango_layout_set_attributes(trans->priv->layer_text_layout,
- attrib_list);
- pango_attr_list_unref(attrib_list);
-
- pango_layout_set_text(trans->priv->layer_text_layout,
- contrib->text, -1);
-
- pango_layout_set_height(trans->priv->layer_text_layout,
- last_contrib_y == -1
- ? G_MAXINT
- : ABS(last_contrib_y - y)*PANGO_SCALE);
-
- pango_layout_get_pixel_size(trans->priv->layer_text_layout,
- NULL, logical_height);
-
- return TRUE;
-}
-
-static gboolean
-render_contribution_bottomup(GtkExperimentTranscript *trans,
- ExperimentReaderContrib *contrib,
- gint64 current_time, gint64 current_time_px,
- gint *last_contrib_y)
-{
- GtkWidget *widget = GTK_WIDGET(trans);
-
- gint old_last_contrib_y = *last_contrib_y;
- int logical_height;
-
- *last_contrib_y = widget->allocation.height -
- (current_time_px - TIME_TO_PX(contrib->start_time));
-
- if (!configure_text_layout(trans, contrib, current_time,
- *last_contrib_y, old_last_contrib_y,
- &logical_height))
- return TRUE;
-
- if (*last_contrib_y + logical_height < 0)
- return FALSE;
-
- gdk_draw_layout(GDK_DRAWABLE(trans->priv->layer_text),
- widget->style->text_gc[gtk_widget_get_state(widget)],
- 0, *last_contrib_y,
- trans->priv->layer_text_layout);
-
- return *last_contrib_y > 0;
-}
-
-static gboolean
-render_contribution_topdown(GtkExperimentTranscript *trans,
- ExperimentReaderContrib *contrib,
- gint64 current_time, gint64 current_time_px,
- gint *last_contrib_y)
-{
- GtkWidget *widget = GTK_WIDGET(trans);
-
- gint old_last_contrib_y = *last_contrib_y;
- int logical_height;
-
- *last_contrib_y = current_time_px - TIME_TO_PX(contrib->start_time);
-
- if (!configure_text_layout(trans, contrib, current_time,
- *last_contrib_y, old_last_contrib_y,
- &logical_height))
- return TRUE;
-
- if (*last_contrib_y - logical_height > widget->allocation.height)
- return FALSE;
-
- gdk_draw_layout(GDK_DRAWABLE(trans->priv->layer_text),
- widget->style->text_gc[gtk_widget_get_state(widget)],
- 0, *last_contrib_y - logical_height,
- trans->priv->layer_text_layout);
-
- return *last_contrib_y < widget->allocation.height;
-}
-
-static inline void
-render_backdrop_area(GtkExperimentTranscript *trans, gint64 current_time_px)
-{
- GtkWidget *widget = GTK_WIDGET(trans);
-
- gint y_start, y_end;
- GdkColor color;
- GdkColor *bg = &widget->style->bg[gtk_widget_get_state(widget)];
-
- if (!gtk_experiment_transcript_get_use_backdrop_area(trans))
- return;
-
- if (gtk_experiment_transcript_get_reverse_mode(trans)) {
- y_end = current_time_px - TIME_TO_PX(trans->priv->backdrop.start);
- y_start = current_time_px - TIME_TO_PX(trans->priv->backdrop.end);
- } else {
- y_start = widget->allocation.height -
- (current_time_px - TIME_TO_PX(trans->priv->backdrop.start));
- y_end = widget->allocation.height -
- (current_time_px - TIME_TO_PX(trans->priv->backdrop.end));
- }
-
- if ((y_start < 0 && y_end < 0) ||
- (y_start > widget->allocation.height &&
- y_end > widget->allocation.height))
- return;
-
- y_start = CLAMP(y_start, 0, widget->allocation.height);
- y_end = CLAMP(y_end, 0, widget->allocation.height);
-
- color.pixel = 0;
- color.red = MAX((gint)bg->red - BACKDROP_VALUE, 0);
- color.blue = MAX((gint)bg->blue - BACKDROP_VALUE, 0);
- color.green = MAX((gint)bg->green - BACKDROP_VALUE, 0);
- if (!color.red && !color.blue && !color.green) {
- color.red = MIN((gint)bg->red + BACKDROP_VALUE, G_MAXUINT16);
- color.blue = MIN((gint)bg->blue + BACKDROP_VALUE, G_MAXUINT16);
- color.green = MIN((gint)bg->green + BACKDROP_VALUE, G_MAXUINT16);
- }
- gtk_widget_modify_fg(widget, gtk_widget_get_state(widget), &color);
-
- gdk_draw_rectangle(GDK_DRAWABLE(trans->priv->layer_text),
- widget->style->fg_gc[gtk_widget_get_state(widget)],
- TRUE,
- 0, y_start,
- widget->allocation.width, y_end - y_start);
-}
-
-/** @private */
-G_GNUC_INTERNAL void
-gtk_experiment_transcript_text_layer_redraw(GtkExperimentTranscript *trans)
-{
- GtkWidget *widget = GTK_WIDGET(trans);
-
- gint64 current_time = 0, current_time_px;
- gint last_contrib_y = -1;
-
- GtkExperimentTranscriptContribRenderer renderer;
-
- if (trans->priv->time_adjustment != NULL) {
- GtkAdjustment *adj =
- GTK_ADJUSTMENT(trans->priv->time_adjustment);
- current_time = (gint64)gtk_adjustment_get_value(adj);
- }
- current_time_px = TIME_TO_PX(current_time);
-
- gdk_draw_rectangle(GDK_DRAWABLE(trans->priv->layer_text),
- widget->style->bg_gc[gtk_widget_get_state(widget)],
- TRUE,
- 0, 0,
- widget->allocation.width,
- widget->allocation.height);
-
- render_backdrop_area(trans, current_time_px);
-
- gtk_widget_queue_draw_area(widget, 0, 0,
- widget->allocation.width,
- widget->allocation.height);
-
- if (trans->priv->contribs == NULL)
- return;
-
- renderer = gtk_experiment_transcript_get_reverse_mode(trans)
- ? render_contribution_topdown
- : render_contribution_bottomup;
-
- for (GList *cur = experiment_reader_get_contribution_by_time(
- trans->priv->contribs,
- current_time);
- cur != NULL;
- cur = cur->prev) {
- ExperimentReaderContrib *contrib = (ExperimentReaderContrib *)
- cur->data;
-
- if (!renderer(trans, contrib, current_time, current_time_px,
- &last_contrib_y))
- break;
- }
-}
-
-static void
-state_changed(GtkWidget *widget, GtkStateType state __attribute__((unused)))
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(widget);
-
- if (gtk_widget_get_realized(widget) &&
- trans->priv->layer_text != NULL)
- gtk_experiment_transcript_text_layer_redraw(trans);
-}
-
-static gboolean
-button_pressed(GtkWidget *widget, GdkEventButton *event)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(widget);
-
- gtk_widget_grab_focus(widget);
-
- /* Ignore double-clicks and triple-clicks */
- if (event->button != 3 || event->type != GDK_BUTTON_PRESS)
- return FALSE;
-
- gtk_menu_popup(GTK_MENU(trans->priv->menu), NULL, NULL, NULL, NULL,
- event->button, event->time);
- return TRUE;
-}
-
-static gboolean
-scrolled(GtkWidget *widget, GdkEventScroll *event)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(widget);
-
- GtkAdjustment *adj;
- gdouble value, real_upper;
-
- if (trans->priv->time_adjustment == NULL)
- return FALSE;
-
- adj = GTK_ADJUSTMENT(trans->priv->time_adjustment);
- value = gtk_adjustment_get_value(adj);
- real_upper = gtk_adjustment_get_upper(adj) -
- gtk_adjustment_get_page_size(adj);
-
- switch (event->direction) {
- case GDK_SCROLL_UP:
- value -= gtk_adjustment_get_step_increment(adj);
- break;
- case GDK_SCROLL_DOWN:
- value += gtk_adjustment_get_step_increment(adj);
- default:
- break;
- }
-
- gtk_adjustment_set_value(adj, MIN(value, real_upper));
-
- return TRUE;
-}
-
-static void
-choose_font_activated(GtkWidget *widget __attribute__((unused)),
- gpointer data)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(data);
-
- GtkWidget *dialog;
- gchar *font_name;
-
- dialog = gtk_font_selection_dialog_new("Choose Font...");
-
- font_name = pango_font_description_to_string(GTK_WIDGET(trans)->style->font_desc);
- gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog),
- font_name);
- g_free(font_name);
-
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
- PangoFontDescription *font_desc;
-
- font_name = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dialog));
- font_desc = pango_font_description_from_string(font_name);
-
- gtk_widget_modify_font(GTK_WIDGET(trans), font_desc);
-
- pango_font_description_free(font_desc);
- g_free(font_name);
-
- gtk_experiment_transcript_text_layer_redraw(trans);
- }
-
- gtk_widget_destroy(dialog);
-}
-
-static void
-choose_text_color_activated(GtkWidget *widget __attribute__((unused)),
- gpointer data)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(data);
-
- GtkWidget *dialog, *colorsel;
-
- dialog = gtk_color_selection_dialog_new("Choose Text Color...");
- colorsel = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog));
-
- gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel),
- &GTK_WIDGET(trans)->style->text[GTK_STATE_NORMAL]);
-
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
- GdkColor color;
-
- gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(colorsel),
- &color);
- gtk_widget_modify_text(GTK_WIDGET(trans),
- GTK_STATE_NORMAL, &color);
-
- gtk_experiment_transcript_text_layer_redraw(trans);
- }
-
- gtk_widget_destroy(dialog);
-}
-
-static void
-choose_bg_color_activated(GtkWidget *widget __attribute__((unused)),
- gpointer data)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(data);
-
- GtkWidget *dialog, *colorsel;
-
- dialog = gtk_color_selection_dialog_new("Choose Background Color...");
- colorsel = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog));
-
- gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel),
- &GTK_WIDGET(trans)->style->bg[GTK_STATE_NORMAL]);
-
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
- GdkColor color;
-
- gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(colorsel),
- &color);
- gtk_widget_modify_bg(GTK_WIDGET(trans),
- GTK_STATE_NORMAL, &color);
-
- gtk_experiment_transcript_text_layer_redraw(trans);
- }
-
- gtk_widget_destroy(dialog);
-}
-
-static void
-text_alignment_activated(GtkWidget *widget __attribute__((unused)),
- gpointer data)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(data);
- PangoAlignment alignment;
-
- if (trans->priv->layer_text_layout == NULL)
- return;
-
- alignment = PANGO_ALIGN_RIGHT;
- for (GSList *cur = trans->priv->alignment_group;
- cur != NULL;
- cur = cur->next, alignment--) {
- if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(cur->data)))
- continue;
-
- pango_layout_set_alignment(trans->priv->layer_text_layout,
- alignment);
-
- if (gtk_widget_get_realized(GTK_WIDGET(trans)) &&
- trans->priv->layer_text != NULL)
- gtk_experiment_transcript_text_layer_redraw(trans);
-
- break;
- }
-}
-
-static void
-reverse_activated(GtkWidget *widget, gpointer data)
-{
- GtkExperimentTranscript *trans = GTK_EXPERIMENT_TRANSCRIPT(data);
-
- trans->priv->flag_mask &= ~GTK_EXPERIMENT_TRANSCRIPT_REVERSE_MASK;
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
- trans->priv->flag_mask |= GTK_EXPERIMENT_TRANSCRIPT_REVERSE_MASK;
-
- if (gtk_widget_get_realized(GTK_WIDGET(trans)) &&
- trans->priv->layer_text != NULL)
- gtk_experiment_transcript_text_layer_redraw(trans);
-}
-
-/*
- * API
- */
-
-/**
- * @brief Construct new \e GtkExperimentTranscript widget instance.
- *
- * @param speaker Name of speaker whose contributions are displayed
- * @return New \e GtkExperimentTranscript widget instance
- */
-GtkWidget *
-gtk_experiment_transcript_new(const gchar *speaker)
-{
- GtkExperimentTranscript *trans;
-
- trans = GTK_EXPERIMENT_TRANSCRIPT(g_object_new(GTK_TYPE_EXPERIMENT_TRANSCRIPT, NULL));
- trans->speaker = g_strdup(speaker);
- if (trans->speaker == NULL) {
- gtk_widget_destroy(GTK_WIDGET(trans));
- return NULL;
- }
-
- return GTK_WIDGET(trans);
-}
-
-/**
- * @brief Load contributions from an experiment transcript file.
- *
- * The transcript file is given as an \e ExperimentReader object instance.
- * Only contributions (every text fragment identified by a timepoint) of the
- * configured speaker are used.
- *
- * @param trans Widget instance
- * @param exp \e ExperimentReader instance
- * @return \c TRUE on success, else \c FALSE
- */
-gboolean
-gtk_experiment_transcript_load(GtkExperimentTranscript *trans,
- ExperimentReader *exp)
-{
- experiment_reader_free_contributions(trans->priv->contribs);
- trans->priv->contribs =
- experiment_reader_get_contributions_by_speaker(exp, trans->speaker);
-
- gtk_experiment_transcript_text_layer_redraw(trans);
-
- return trans->priv->contribs != NULL;
-}
-
-/**
- * @brief Load contributions from an experiment transcript file.
- *
- * The transcript file is given as a file name.
- * Only contributions (every text fragment identified by a timepoint) of the
- * configured speaker are used.
- *
- * @sa gtk_experiment_transcript_load
- *
- * @param trans Widget instance
- * @param filename \e ExperimentReader instance
- * @return \c TRUE on success, else \c FALSE
- */
-gboolean
-gtk_experiment_transcript_load_filename(GtkExperimentTranscript *trans,
- const gchar *filename)
-{
- gboolean res = FALSE;
- ExperimentReader *exp = experiment_reader_new(filename);
-
- if (exp != NULL) {
- res = gtk_experiment_transcript_load(trans, exp);
- g_object_unref(exp);
- }
-
- return res;
-}
-
-/**
- * @brief Enable or disable drawing a backdrop area
- *
- * @param trans Widget instance
- * @param use Whether to enable (\c TRUE) or disable (\c FALSE) the backdrop
- * area
- */
-void
-gtk_experiment_transcript_set_use_backdrop_area(GtkExperimentTranscript *trans,
- gboolean use)
-{
- trans->priv->flag_mask &= ~GTK_EXPERIMENT_TRANSCRIPT_USE_BACKDROP_MASK;
- trans->priv->flag_mask |=
- use ? GTK_EXPERIMENT_TRANSCRIPT_USE_BACKDROP_MASK : 0;
-
- if (gtk_widget_get_realized(GTK_WIDGET(trans)) &&
- trans->priv->layer_text != NULL)
- gtk_experiment_transcript_text_layer_redraw(trans);
-}
-
-/**
- * @brief Retrieve whether a backdrop area is drawn or not
- *
- * @param trans Widget instance
- * @return \c TRUE if it is, else \c FALSE
- */
-gboolean
-gtk_experiment_transcript_get_use_backdrop_area(GtkExperimentTranscript *trans)
-{
- return trans->priv->flag_mask &
- GTK_EXPERIMENT_TRANSCRIPT_USE_BACKDROP_MASK;
-}
-
-/**
- * @brief Configure transcript's backdrop area
- *
- * Set a highlighted area of the transcript by specifying start
- * and end timepoints. The highlighted area is drawn with a 16% lighter or
- * darker background color than the widgets current background color.
- * It is ownly drawn when the backdrop area is enabled.
- *
- * @sa gtk_experiment_transcript_set_use_backdrop_area
- *
- * @param trans Widget instance
- * @param start Start time in milliseconds
- * @param end End time in milliseconds
- */
-void
-gtk_experiment_transcript_set_backdrop_area(GtkExperimentTranscript *trans,
- gint64 start, gint64 end)
-{
- start = MAX(start, 0);
- end = MAX(end, 0);
-
- if (start <= end) {
- trans->priv->backdrop.start = start;
- trans->priv->backdrop.end = end;
- } else {
- trans->priv->backdrop.end = start;
- trans->priv->backdrop.start = end;
- }
-
- if (!gtk_experiment_transcript_get_use_backdrop_area(trans))
- return;
-
- if (gtk_widget_get_realized(GTK_WIDGET(trans)) &&
- trans->priv->layer_text != NULL)
- gtk_experiment_transcript_text_layer_redraw(trans);
-}
-
-/**
- * @brief Set or unset reverse (top-down) render mode
- *
- * The render mode defaults to bottom-up mode for new widget instances.
- *
- * @param trans Widget instance
- * @param reverse Activate reverse-mode (\c TRUE), or deactivate (\c FALSE)
- */
-void
-gtk_experiment_transcript_set_reverse_mode(GtkExperimentTranscript *trans,
- gboolean reverse)
-{
- GtkCheckMenuItem *item =
- GTK_CHECK_MENU_ITEM(trans->priv->menu_reverse_item);
-
- gtk_check_menu_item_set_active(item, reverse);
-}
-
-/**
- * @brief Get current reverse (top-down) render mode state
- *
- * @sa gtk_experiment_transcript_set_reverse_mode
- *
- * @param trans Widget instance
- * @return \c TRUE if reverse-mode is active, else \c FALSE
- */
-gboolean
-gtk_experiment_transcript_get_reverse_mode(GtkExperimentTranscript *trans)
-{
- return trans->priv->flag_mask & GTK_EXPERIMENT_TRANSCRIPT_REVERSE_MASK;
-}
-
-/**
- * @brief Set alignment (justification) of text blocks in a transcript widget
- *
- * The alignment defaults to \c PANGO_ALIGN_LEFT for new widget instances.
- *
- * @param trans Widget instance
- * @param alignment New text alignment
- */
-void
-gtk_experiment_transcript_set_alignment(GtkExperimentTranscript *trans,
- PangoAlignment alignment)
-{
- PangoAlignment cur_alignment = PANGO_ALIGN_RIGHT;
-
- for (GSList *cur = trans->priv->alignment_group;
- cur != NULL;
- cur = cur->next, cur_alignment--)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(cur->data),
- cur_alignment == alignment);
-}
-
-/**
- * @brief Get alignment (justification) of text blocks in a transcript widget
- *
- * @sa gtk_experiment_transcript_set_alignment
- *
- * @param trans Widget instance
- * @return Current text alignment
- */
-PangoAlignment
-gtk_experiment_transcript_get_alignment(GtkExperimentTranscript *trans)
-{
- if (trans->priv->layer_text_layout == NULL)
- return PANGO_ALIGN_LEFT;
-
- return pango_layout_get_alignment(trans->priv->layer_text_layout);
-}
-
-/**
- * @brief Get time-adjustment currently used by a transcript widget
- *
- * The time-adjustment is the only way to control the portion of the transcript
- * displayed by the widget.
- * The adjustment's value is in milliseconds.
- * The widget will initialize one on construction, so there \e should always be
- * an adjustment to get.
- *
- * @param trans Widget instance
- * @return Currently used time-adjustment
- */
-
-GtkAdjustment *
-gtk_experiment_transcript_get_time_adjustment(GtkExperimentTranscript *trans)
-{
- return trans->priv->time_adjustment != NULL
- ? GTK_ADJUSTMENT(trans->priv->time_adjustment)
- : NULL;
-}
-
-/**
- * @brief Change time-adjustment used by \e GtkExperimentTranscript
- *
- * The old adjustment will be
- * unreferenced (and possibly destroyed) and a reference to the new
- * adjustment will be fetched.
- *
- * @sa gtk_experiment_transcript_get_time_adjustment
- *
- * @param trans Widget instance
- * @param adj New \e GtkAdjustment to use as time-adjustment.
- */
-void
-gtk_experiment_transcript_set_time_adjustment(GtkExperimentTranscript *trans,
- GtkAdjustment *adj)
-{
- GtkWidget *widget = GTK_WIDGET(trans);
-
- if (trans->priv->time_adjustment == NULL)
- return;
-
- g_signal_handler_disconnect(G_OBJECT(trans->priv->time_adjustment),
- trans->priv->time_adj_on_value_changed_id);
-
- g_object_unref(trans->priv->time_adjustment);
- trans->priv->time_adjustment = GTK_OBJECT(adj);
- g_object_ref_sink(trans->priv->time_adjustment);
-
- gtk_adjustment_set_page_size(GTK_ADJUSTMENT(trans->priv->time_adjustment),
- (gdouble)PX_TO_TIME(widget->allocation.height));
-
- trans->priv->time_adj_on_value_changed_id =
- g_signal_connect(G_OBJECT(trans->priv->time_adjustment),
- "value-changed",
- G_CALLBACK(time_adj_on_value_changed), trans);
-}
diff --git a/lib/gtk-experiment-widgets/gtk-experiment-transcript.h b/lib/gtk-experiment-widgets/gtk-experiment-transcript.h
deleted file mode 100644
index e537e48..0000000
--- a/lib/gtk-experiment-widgets/gtk-experiment-transcript.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- * @file
- * Header file necessary to include when using the \e GtkExperimentTranscript
- * widget.
- */
-
-/*
- * Copyright (C) 2012-2013 Otto-von-Guericke-Universität Magdeburg
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GTK_EXPERIMENT_TRANSCRIPT_H
-#define __GTK_EXPERIMENT_TRANSCRIPT_H
-
-#include <glib-object.h>
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include <gtk/gtk.h>
-
-#include <experiment-reader.h>
-
-G_BEGIN_DECLS
-
-/** \e GtkExperimentTranscript error domain */
-#define GTK_EXPERIMENT_TRANSCRIPT_ERROR \
- (gtk_experiment_transcript_error_quark())
-
-/** \e GtkExperimentTranscript error codes */
-typedef enum {
- GTK_EXPERIMENT_TRANSCRIPT_ERROR_FILEOPEN, /**< Error opening file */
- GTK_EXPERIMENT_TRANSCRIPT_ERROR_REGEXCAPTURES, /**< Additional regular expression captures used */
- GTK_EXPERIMENT_TRANSCRIPT_ERROR_LINELENGTH /**< Line read is too long */
-} GtkExperimentTranscriptError;
-
-/** \e GtkExperimentTranscript type */
-#define GTK_TYPE_EXPERIMENT_TRANSCRIPT \
- (gtk_experiment_transcript_get_type())
-/**
- * Cast instance pointer to \e GtkExperimentTranscript
- *
- * @param obj Object to cast to \e GtkExperimentTranscript
- * @return \e obj casted to \e GtkExperimentTranscript
- */
-#define GTK_EXPERIMENT_TRANSCRIPT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_EXPERIMENT_TRANSCRIPT, GtkExperimentTranscript))
-#define GTK_EXPERIMENT_TRANSCRIPT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_EXPERIMENT_TRANSCRIPT, GtkExperimentTranscriptClass))
-#define GTK_IS_EXPERIMENT_TRANSCRIPT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_EXPERIMENT_TRANSCRIPT))
-#define GTK_IS_EXPERIMENT_TRANSCRIPT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_EXPERIMENT_TRANSCRIPT))
-#define GTK_EXPERIMENT_TRANSCRIPT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_EXPERIMENT_TRANSCRIPT, GtkExperimentTranscriptClass))
-
-/** @private */
-typedef struct _GtkExperimentTranscriptPrivate GtkExperimentTranscriptPrivate;
-
-/**
- * \e GtkExperimentTranscript instance structure
- */
-typedef struct _GtkExperimentTranscript {
- GtkWidget parent_instance; /**< Parent instance structure */
-
- gchar *speaker; /**< Name of speaker whose contributions are displayed (\b read-only) */
-
- /**
- * Default formattings to apply for interactive for interactive format
- * rules if no Pango markup is specified.
- * A \c NULL pointer means that the correspondig text property will not
- * be changed. After widget instantiation all fields are \c NULL.
- */
- struct _GtkExperimentTranscriptInteractiveFormat {
- PangoFontDescription *default_font; /**< Default interactive format font */
- GdkColor *default_text_color; /**< Default interactive format text color */
- GdkColor *default_bg_color; /**< Default interactive format background color */
- } interactive_format;
-
- GtkExperimentTranscriptPrivate *priv; /**< @private Pointer to \b private instance attributes */
-} GtkExperimentTranscript;
-
-/**
- * \e GtkExperimentTranscript class structure
- */
-typedef struct _GtkExperimentTranscriptClass {
- GtkWidgetClass parent_class; /**< Parent class structure */
-} GtkExperimentTranscriptClass;
-
-/** @private */
-GQuark gtk_experiment_transcript_error_quark(void);
-/** @private */
-GType gtk_experiment_transcript_get_type(void);
-
-/*
- * API
- */
-GtkWidget *gtk_experiment_transcript_new(const gchar *speaker);
-
-gboolean gtk_experiment_transcript_load(GtkExperimentTranscript *trans,
- ExperimentReader *exp);
-gboolean gtk_experiment_transcript_load_filename(GtkExperimentTranscript *trans,
- const gchar *filename);
-
-void gtk_experiment_transcript_set_use_backdrop_area(GtkExperimentTranscript *trans,
- gboolean use);
-gboolean gtk_experiment_transcript_get_use_backdrop_area(GtkExperimentTranscript *trans);
-void gtk_experiment_transcript_set_backdrop_area(GtkExperimentTranscript *trans,
- gint64 start, gint64 end);
-
-void gtk_experiment_transcript_set_reverse_mode(GtkExperimentTranscript *trans,
- gboolean reverse);
-gboolean gtk_experiment_transcript_get_reverse_mode(GtkExperimentTranscript *trans);
-
-void gtk_experiment_transcript_set_alignment(GtkExperimentTranscript *trans,
- PangoAlignment alignment);
-PangoAlignment gtk_experiment_transcript_get_alignment(GtkExperimentTranscript *trans);
-
-gboolean gtk_experiment_transcript_load_formats(GtkExperimentTranscript *trans,
- const gchar *filename,
- GError **error);
-gboolean gtk_experiment_transcript_set_interactive_format(GtkExperimentTranscript *trans,
- const gchar *format_str,
- gboolean with_markup,
- GError **error);
-
-GtkAdjustment *gtk_experiment_transcript_get_time_adjustment(GtkExperimentTranscript *trans);
-void gtk_experiment_transcript_set_time_adjustment(GtkExperimentTranscript *trans,
- GtkAdjustment *adj);
-
-G_END_DECLS
-
-#endif
diff --git a/lib/gtk-experiment-widgets/gtk-experiment-widgets-catalog.xml b/lib/gtk-experiment-widgets/gtk-experiment-widgets-catalog.xml
deleted file mode 100644
index 73a1ec9..0000000
--- a/lib/gtk-experiment-widgets/gtk-experiment-widgets-catalog.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- Install into $GLADE_CATALOG_PATH (default: /usr/share/glade3/catalogs)
--->
-
-<glade-catalog name="gtk-experiment-widgets"
- library="gtk-experiment-widgets" depends="gtk+">
- <glade-widget-classes>
- <glade-widget-class name="GtkExperimentNavigator"
- generic-name="gtk-experiment-navigator"
- title="Experiment Navigator"/>
- <glade-widget-class name="GtkExperimentTranscript"
- generic-name="gtk-experiment-transcript"
- title="Experiment Transcript"/>
- </glade-widget-classes>
-
- <glade-widget-group name="gtk-experiment-widgets"
- title="Experiment Widgets">
- <glade-widget-class-ref name="GtkExperimentNavigator"/>
- <glade-widget-class-ref name="GtkExperimentTranscript"/>
- </glade-widget-group>
-</glade-catalog>