From 616c49a5053830a5e0a31c71fd6114926e43235f Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Mon, 10 Jan 2011 16:49:13 +0100
Subject: Make a separate library.
This is required for gtkdoc-scangobj. So far it's much like it's been
before, the main differences are that source files are in two directories
from now on and the build process has two stages.
---
CMakeLists.txt | 74 +-
liblogdiag/ld-canvas.c | 1417 ++++++++++++++++++++++++++++++++++++
liblogdiag/ld-canvas.h | 91 +++
liblogdiag/ld-diagram-object.c | 186 +++++
liblogdiag/ld-diagram-object.h | 65 ++
liblogdiag/ld-diagram-symbol.c | 171 +++++
liblogdiag/ld-diagram-symbol.h | 64 ++
liblogdiag/ld-diagram.c | 550 ++++++++++++++
liblogdiag/ld-diagram.h | 98 +++
liblogdiag/ld-library.c | 524 +++++++++++++
liblogdiag/ld-library.h | 73 ++
liblogdiag/ld-lua-private.h | 26 +
liblogdiag/ld-lua-symbol-private.h | 40 +
liblogdiag/ld-lua-symbol.c | 138 ++++
liblogdiag/ld-lua-symbol.h | 60 ++
liblogdiag/ld-lua.c | 808 ++++++++++++++++++++
liblogdiag/ld-lua.h | 70 ++
liblogdiag/ld-marshal.c | 88 +++
liblogdiag/ld-marshal.h | 20 +
liblogdiag/ld-marshal.list | 1 +
liblogdiag/ld-symbol-category.c | 339 +++++++++
liblogdiag/ld-symbol-category.h | 79 ++
liblogdiag/ld-symbol.c | 232 ++++++
liblogdiag/ld-symbol.h | 74 ++
liblogdiag/ld-types.c | 221 ++++++
liblogdiag/ld-types.h | 101 +++
liblogdiag/liblogdiag.h | 34 +
po/make-template.sh | 5 +-
src/ld-canvas.c | 1417 ------------------------------------
src/ld-canvas.h | 91 ---
src/ld-diagram-object.c | 186 -----
src/ld-diagram-object.h | 65 --
src/ld-diagram-symbol.c | 171 -----
src/ld-diagram-symbol.h | 64 --
src/ld-diagram.c | 550 --------------
src/ld-diagram.h | 98 ---
src/ld-library.c | 524 -------------
src/ld-library.h | 73 --
src/ld-lua-private.h | 26 -
src/ld-lua-symbol-private.h | 40 -
src/ld-lua-symbol.c | 138 ----
src/ld-lua-symbol.h | 60 --
src/ld-lua.c | 808 --------------------
src/ld-lua.h | 70 --
src/ld-marshal.c | 88 ---
src/ld-marshal.h | 20 -
src/ld-marshal.list | 1 -
src/ld-symbol-category.c | 339 ---------
src/ld-symbol-category.h | 79 --
src/ld-symbol.c | 232 ------
src/ld-symbol.h | 74 --
src/ld-types.c | 221 ------
src/ld-types.h | 101 ---
src/ld-window-main.c | 3 -
src/liblogdiag.h | 34 -
55 files changed, 5616 insertions(+), 5606 deletions(-)
create mode 100644 liblogdiag/ld-canvas.c
create mode 100644 liblogdiag/ld-canvas.h
create mode 100644 liblogdiag/ld-diagram-object.c
create mode 100644 liblogdiag/ld-diagram-object.h
create mode 100644 liblogdiag/ld-diagram-symbol.c
create mode 100644 liblogdiag/ld-diagram-symbol.h
create mode 100644 liblogdiag/ld-diagram.c
create mode 100644 liblogdiag/ld-diagram.h
create mode 100644 liblogdiag/ld-library.c
create mode 100644 liblogdiag/ld-library.h
create mode 100644 liblogdiag/ld-lua-private.h
create mode 100644 liblogdiag/ld-lua-symbol-private.h
create mode 100644 liblogdiag/ld-lua-symbol.c
create mode 100644 liblogdiag/ld-lua-symbol.h
create mode 100644 liblogdiag/ld-lua.c
create mode 100644 liblogdiag/ld-lua.h
create mode 100644 liblogdiag/ld-marshal.c
create mode 100644 liblogdiag/ld-marshal.h
create mode 100644 liblogdiag/ld-marshal.list
create mode 100644 liblogdiag/ld-symbol-category.c
create mode 100644 liblogdiag/ld-symbol-category.h
create mode 100644 liblogdiag/ld-symbol.c
create mode 100644 liblogdiag/ld-symbol.h
create mode 100644 liblogdiag/ld-types.c
create mode 100644 liblogdiag/ld-types.h
create mode 100644 liblogdiag/liblogdiag.h
delete mode 100644 src/ld-canvas.c
delete mode 100644 src/ld-canvas.h
delete mode 100644 src/ld-diagram-object.c
delete mode 100644 src/ld-diagram-object.h
delete mode 100644 src/ld-diagram-symbol.c
delete mode 100644 src/ld-diagram-symbol.h
delete mode 100644 src/ld-diagram.c
delete mode 100644 src/ld-diagram.h
delete mode 100644 src/ld-library.c
delete mode 100644 src/ld-library.h
delete mode 100644 src/ld-lua-private.h
delete mode 100644 src/ld-lua-symbol-private.h
delete mode 100644 src/ld-lua-symbol.c
delete mode 100644 src/ld-lua-symbol.h
delete mode 100644 src/ld-lua.c
delete mode 100644 src/ld-lua.h
delete mode 100644 src/ld-marshal.c
delete mode 100644 src/ld-marshal.h
delete mode 100644 src/ld-marshal.list
delete mode 100644 src/ld-symbol-category.c
delete mode 100644 src/ld-symbol-category.h
delete mode 100644 src/ld-symbol.c
delete mode 100644 src/ld-symbol.h
delete mode 100644 src/ld-types.c
delete mode 100644 src/ld-types.h
delete mode 100644 src/liblogdiag.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 75eb11a..762a9ba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -79,37 +79,41 @@ find_package (GtkDoc)
set (project_DOC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/docs/reference")
# Project source files
+set (liblogdiag_SOURCES
+ liblogdiag/ld-marshal.c
+ liblogdiag/ld-types.c
+ liblogdiag/ld-diagram.c
+ liblogdiag/ld-diagram-object.c
+ liblogdiag/ld-diagram-symbol.c
+ liblogdiag/ld-canvas.c
+ liblogdiag/ld-library.c
+ liblogdiag/ld-symbol-category.c
+ liblogdiag/ld-symbol.c
+ liblogdiag/ld-lua.c
+ liblogdiag/ld-lua-symbol.c)
+set (liblogdiag_HEADERS
+ ${CMAKE_CURRENT_BINARY_DIR}/config.h
+ liblogdiag/liblogdiag.h
+ liblogdiag/ld-marshal.h
+ liblogdiag/ld-types.h
+ liblogdiag/ld-diagram.h
+ liblogdiag/ld-diagram-object.h
+ liblogdiag/ld-diagram-symbol.h
+ liblogdiag/ld-canvas.h
+ liblogdiag/ld-library.h
+ liblogdiag/ld-symbol-category.h
+ liblogdiag/ld-symbol.h
+ liblogdiag/ld-lua.h
+ liblogdiag/ld-lua-private.h
+ liblogdiag/ld-lua-symbol.h
+ liblogdiag/ld-lua-symbol-private.h)
+
set (logdiag_SOURCES
- src/logdiag.c
- src/ld-marshal.c
- src/ld-types.c
src/ld-window-main.c
- src/ld-diagram.c
- src/ld-diagram-object.c
- src/ld-diagram-symbol.c
- src/ld-canvas.c
- src/ld-library.c
- src/ld-symbol-category.c
- src/ld-symbol.c
- src/ld-lua.c
- src/ld-lua-symbol.c)
+ src/logdiag.c)
set (logdiag_HEADERS
- ${CMAKE_CURRENT_BINARY_DIR}/config.h
- src/liblogdiag.h
- src/ld-marshal.h
- src/ld-types.h
- src/ld-window-main.h
- src/ld-diagram.h
- src/ld-diagram-object.h
- src/ld-diagram-symbol.h
- src/ld-canvas.h
- src/ld-library.h
- src/ld-symbol-category.h
- src/ld-symbol.h
- src/ld-lua.h
- src/ld-lua-private.h
- src/ld-lua-symbol.h
- src/ld-lua-symbol-private.h)
+ ${liblogdiag_HEADERS}
+ src/ld-window-main.h)
# Generate a configure file
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
@@ -151,18 +155,24 @@ function (glib_genmarshal base prefix)
endif (GLIB_GENMARSHAL_EXECUTABLE)
endfunction (glib_genmarshal)
-glib_genmarshal (${CMAKE_CURRENT_SOURCE_DIR}/src/ld-marshal
+glib_genmarshal (${CMAKE_CURRENT_SOURCE_DIR}/liblogdiag/ld-marshal
g_cclosure_user_marshal)
-# Build the executable
+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/liblogdiag)
include_directories (${GTK2_INCLUDE_DIRS} ${JSON_GLIB_INCLUDE_DIRS} ${LUA_INCLUDE_DIR})
+
+# Build the library
+add_library (liblogdiag STATIC ${liblogdiag_SOURCES} ${liblogdiag_HEADERS})
+set_target_properties (liblogdiag PROPERTIES OUTPUT_NAME logdiag)
+
+# Build the executable
add_executable (logdiag ${logdiag_SOURCES} ${logdiag_HEADERS})
-target_link_libraries (logdiag ${GTK2_LIBRARIES} ${JSON_GLIB_LIBRARIES} ${LUA_LIBRARIES})
+target_link_libraries (logdiag liblogdiag ${GTK2_LIBRARIES} ${JSON_GLIB_LIBRARIES} ${LUA_LIBRARIES})
# Generate documentation
if (GTK_DOC_FOUND)
GTK_DOC_RUN (WORKING_DIR ${project_DOC_DIR}
- SOURCE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src
+ SOURCE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/liblogdiag
XML ${project_DOC_DIR}/xml --sgml-mode
HTML ${project_DOC_DIR}/html)
endif (GTK_DOC_FOUND)
diff --git a/liblogdiag/ld-canvas.c b/liblogdiag/ld-canvas.c
new file mode 100644
index 0000000..9523d9d
--- /dev/null
+++ b/liblogdiag/ld-canvas.c
@@ -0,0 +1,1417 @@
+/*
+ * ld-canvas.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include
+#include
+#include
+
+#include "liblogdiag.h"
+#include "config.h"
+
+
+/**
+ * SECTION:ld-canvas
+ * @short_description: A canvas.
+ * @see_also: #LdDiagram
+ *
+ * #LdCanvas displays and enables the user to manipulate with an #LdDiagram.
+ */
+
+/* Milimetres per inch. */
+#define MM_PER_INCH 25.4
+/* The default screen resolution in DPI units. */
+#define DEFAULT_SCREEN_RESOLUTION 96
+
+/* The maximal, minimal and default values of zoom. */
+#define ZOOM_MIN 0.01
+#define ZOOM_MAX 100
+#define ZOOM_DEFAULT 1
+/* Multiplication factor for zooming with mouse wheel. */
+#define ZOOM_WHEEL_STEP 1.4
+
+/* When drawing is requested, extend all sides of
+ * the rectangle to be drawn by this number of pixels.
+ */
+#define QUEUE_DRAW_EXTEND 3
+/* Cursor tolerance for object borders. */
+#define OBJECT_BORDER_TOLERANCE 3
+/* Tolerance on all sides of symbols for strokes. */
+#define SYMBOL_CLIP_TOLERANCE 5
+
+/* Size of a highlighted terminal. */
+#define TERMINAL_RADIUS 5
+/* Tolerance around terminal points. */
+#define TERMINAL_HOVER_TOLERANCE 8
+
+/*
+ * OperationEnd:
+ *
+ * Called upon ending an operation.
+ */
+typedef void (*OperationEnd) (LdCanvas *self);
+
+enum
+{
+ OPER_0,
+ OPER_ADD_OBJECT
+};
+
+typedef struct _AddObjectData AddObjectData;
+
+struct _AddObjectData
+{
+ LdDiagramObject *object;
+ gboolean visible;
+};
+
+enum
+{
+ COLOR_BASE,
+ COLOR_GRID,
+ COLOR_OBJECT,
+ COLOR_SELECTION,
+ COLOR_TERMINAL,
+ COLOR_COUNT
+};
+
+typedef struct _LdCanvasColor LdCanvasColor;
+
+struct _LdCanvasColor
+{
+ gdouble r;
+ gdouble g;
+ gdouble b;
+ gdouble a;
+};
+
+/*
+ * LdCanvasPrivate:
+ * @diagram: A diagram object assigned to this canvas as a model.
+ * @library: A library object assigned to this canvas as a model.
+ * @adjustment_h: An adjustment object for the horizontal axis, if any.
+ * @adjustment_v: An adjustment object for the vertical axis, if any.
+ * @x: The X coordinate of the center of view.
+ * @y: The Y coordinate of the center of view.
+ * @zoom: The current zoom of the canvas.
+ * @operation: The current operation.
+ * @operation_data: Data related to the current operation.
+ * @operation_end: A callback to end the operation.
+ * @palette: Colors used by the widget.
+ */
+struct _LdCanvasPrivate
+{
+ LdDiagram *diagram;
+ LdLibrary *library;
+
+ GtkAdjustment *adjustment_h;
+ GtkAdjustment *adjustment_v;
+
+ gdouble x;
+ gdouble y;
+ gdouble zoom;
+
+ LdPoint terminal;
+ gboolean terminal_highlighted;
+
+ gint operation;
+ union
+ {
+ AddObjectData add_object;
+ }
+ operation_data;
+ OperationEnd operation_end;
+
+ LdCanvasColor palette[COLOR_COUNT];
+};
+
+#define OPER_DATA(self, member) ((self)->priv->operation_data.member)
+#define COLOR_GET(self, name) (&(self)->priv->palette[name])
+
+/*
+ * DrawData:
+ * @self: Our #LdCanvas.
+ * @cr: A cairo context to draw on.
+ * @exposed_rect: The area that is to be redrawn.
+ * @scale: Computed size of one diagram unit in pixels.
+ */
+typedef struct _DrawData DrawData;
+
+struct _DrawData
+{
+ LdCanvas *self;
+ cairo_t *cr;
+ LdRectangle exposed_rect;
+ gdouble scale;
+};
+
+enum
+{
+ PROP_0,
+ PROP_DIAGRAM,
+ PROP_LIBRARY,
+ PROP_ZOOM
+};
+
+static void ld_canvas_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec);
+static void ld_canvas_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec);
+static void ld_canvas_finalize (GObject *gobject);
+
+static void ld_canvas_real_set_scroll_adjustments
+ (LdCanvas *self, GtkAdjustment *horizontal, GtkAdjustment *vertical);
+static void on_adjustment_value_changed
+ (GtkAdjustment *adjustment, LdCanvas *self);
+static void on_size_allocate (GtkWidget *widget, GtkAllocation *allocation,
+ gpointer user_data);
+static void update_adjustments (LdCanvas *self);
+
+static void diagram_connect_signals (LdCanvas *self);
+static void diagram_disconnect_signals (LdCanvas *self);
+
+static gdouble ld_canvas_get_base_unit_in_px (GtkWidget *self);
+static gdouble ld_canvas_get_scale_in_px (LdCanvas *self);
+
+static void simulate_motion (LdCanvas *self);
+static gboolean on_motion_notify (GtkWidget *widget, GdkEventMotion *event,
+ gpointer user_data);
+static gboolean on_leave_notify (GtkWidget *widget, GdkEventCrossing *event,
+ gpointer user_data);
+static gboolean on_button_press (GtkWidget *widget, GdkEventButton *event,
+ gpointer user_data);
+static gboolean on_button_release (GtkWidget *widget, GdkEventButton *event,
+ gpointer user_data);
+static gboolean on_scroll (GtkWidget *widget, GdkEventScroll *event,
+ gpointer user_data);
+
+static void ld_canvas_color_set (LdCanvasColor *color,
+ gdouble r, gdouble g, gdouble b, gdouble a);
+static void ld_canvas_color_apply (LdCanvasColor *color, cairo_t *cr);
+
+static void move_object_to_coords (LdCanvas *self, LdDiagramObject *object,
+ gdouble x, gdouble y);
+static LdDiagramObject *get_object_at_coords (LdCanvas *self,
+ gdouble x, gdouble y);
+static gboolean is_object_selected (LdCanvas *self, LdDiagramObject *object);
+static LdSymbol *resolve_diagram_symbol (LdCanvas *self,
+ LdDiagramSymbol *diagram_symbol);
+static gboolean get_symbol_area (LdCanvas *self, LdDiagramSymbol *symbol,
+ LdRectangle *rect);
+static gboolean get_symbol_clip_area (LdCanvas *self, LdDiagramSymbol *symbol,
+ LdRectangle *rect);
+static gboolean get_object_area (LdCanvas *self, LdDiagramObject *object,
+ LdRectangle *rect);
+static gboolean object_hit_test (LdCanvas *self, LdDiagramObject *object,
+ gdouble x, gdouble y);
+static void check_terminals (LdCanvas *self, gdouble x, gdouble y);
+static void hide_terminals (LdCanvas *self);
+static void queue_draw (LdCanvas *self, LdRectangle *rect);
+static void queue_object_draw (LdCanvas *self, LdDiagramObject *object);
+static void queue_terminal_draw (LdCanvas *self, LdPoint *terminal);
+
+static void ld_canvas_real_cancel_operation (LdCanvas *self);
+static void ld_canvas_add_object_end (LdCanvas *self);
+
+static gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event,
+ gpointer user_data);
+static void draw_grid (GtkWidget *widget, DrawData *data);
+static void draw_diagram (GtkWidget *widget, DrawData *data);
+static void draw_terminal (GtkWidget *widget, DrawData *data);
+static void draw_object (LdDiagramObject *diagram_object, DrawData *data);
+static void draw_symbol (LdDiagramSymbol *diagram_symbol, DrawData *data);
+
+
+G_DEFINE_TYPE (LdCanvas, ld_canvas, GTK_TYPE_DRAWING_AREA);
+
+static void
+ld_canvas_class_init (LdCanvasClass *klass)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkBindingSet *binding_set;
+ GParamSpec *pspec;
+
+ widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = ld_canvas_get_property;
+ object_class->set_property = ld_canvas_set_property;
+ object_class->finalize = ld_canvas_finalize;
+
+ klass->set_scroll_adjustments = ld_canvas_real_set_scroll_adjustments;
+ klass->cancel_operation = ld_canvas_real_cancel_operation;
+
+ binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
+ "cancel-operation", 0);
+
+/**
+ * LdCanvas:diagram:
+ *
+ * The underlying #LdDiagram object of this canvas.
+ */
+ pspec = g_param_spec_object ("diagram", "Diagram",
+ "The underlying diagram object of this canvas.",
+ LD_TYPE_DIAGRAM, G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_DIAGRAM, pspec);
+
+/**
+ * LdCanvas:library:
+ *
+ * The #LdLibrary that this canvas retrieves symbols from.
+ */
+ pspec = g_param_spec_object ("library", "Library",
+ "The library that this canvas retrieves symbols from.",
+ LD_TYPE_LIBRARY, G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_LIBRARY, pspec);
+
+/**
+ * LdCanvas:zoom:
+ *
+ * The zoom of this canvas.
+ */
+ pspec = g_param_spec_double ("zoom", "Zoom",
+ "The zoom of this canvas.",
+ ZOOM_MIN, ZOOM_MAX, ZOOM_DEFAULT, G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_ZOOM, pspec);
+
+/**
+ * LdCanvas::set-scroll-adjustments:
+ * @horizontal: The horizontal #GtkAdjustment.
+ * @vertical: The vertical #GtkAdjustment.
+ *
+ * Set scroll adjustments for the canvas.
+ */
+ widget_class->set_scroll_adjustments_signal = g_signal_new
+ ("set-scroll-adjustments", G_TYPE_FROM_CLASS (widget_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (LdCanvasClass, set_scroll_adjustments),
+ NULL, NULL,
+ g_cclosure_user_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+
+/**
+ * LdCanvas::cancel-operation:
+ *
+ * Cancel any current operation.
+ */
+ klass->cancel_operation_signal = g_signal_new
+ ("cancel-operation", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (LdCanvasClass, cancel_operation), NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (klass, sizeof (LdCanvasPrivate));
+}
+
+static void
+ld_canvas_init (LdCanvas *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self, LD_TYPE_CANVAS, LdCanvasPrivate);
+
+ self->priv->x = 0;
+ self->priv->y = 0;
+ self->priv->zoom = ZOOM_DEFAULT;
+
+ ld_canvas_color_set (COLOR_GET (self, COLOR_BASE), 1, 1, 1, 1);
+ ld_canvas_color_set (COLOR_GET (self, COLOR_GRID), 0.5, 0.5, 0.5, 1);
+ ld_canvas_color_set (COLOR_GET (self, COLOR_OBJECT), 0, 0, 0, 1);
+ ld_canvas_color_set (COLOR_GET (self, COLOR_SELECTION), 0, 0, 1, 1);
+ ld_canvas_color_set (COLOR_GET (self, COLOR_TERMINAL), 1, 0.5, 0.5, 1);
+
+ g_signal_connect (self, "size-allocate",
+ G_CALLBACK (on_size_allocate), NULL);
+ g_signal_connect (self, "expose-event",
+ G_CALLBACK (on_expose_event), NULL);
+
+ g_signal_connect (self, "motion-notify-event",
+ G_CALLBACK (on_motion_notify), NULL);
+ g_signal_connect (self, "leave-notify-event",
+ G_CALLBACK (on_leave_notify), NULL);
+ g_signal_connect (self, "button-press-event",
+ G_CALLBACK (on_button_press), NULL);
+ g_signal_connect (self, "button-release-event",
+ G_CALLBACK (on_button_release), NULL);
+ g_signal_connect (self, "scroll-event",
+ G_CALLBACK (on_scroll), NULL);
+
+ g_object_set (self, "can-focus", TRUE, NULL);
+
+ gtk_widget_add_events (GTK_WIDGET (self),
+ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK
+ | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+ | GDK_LEAVE_NOTIFY_MASK);
+}
+
+static void
+ld_canvas_finalize (GObject *gobject)
+{
+ LdCanvas *self;
+
+ self = LD_CANVAS (gobject);
+
+ ld_canvas_real_set_scroll_adjustments (self, NULL, NULL);
+
+ if (self->priv->diagram)
+ {
+ diagram_disconnect_signals (self);
+ g_object_unref (self->priv->diagram);
+ }
+ if (self->priv->library)
+ g_object_unref (self->priv->library);
+
+ /* Chain up to the parent class. */
+ G_OBJECT_CLASS (ld_canvas_parent_class)->finalize (gobject);
+}
+
+static void
+ld_canvas_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec)
+{
+ LdCanvas *self;
+
+ self = LD_CANVAS (object);
+ switch (property_id)
+ {
+ case PROP_DIAGRAM:
+ g_value_set_object (value, ld_canvas_get_diagram (self));
+ break;
+ case PROP_LIBRARY:
+ g_value_set_object (value, ld_canvas_get_library (self));
+ break;
+ case PROP_ZOOM:
+ g_value_set_double (value, ld_canvas_get_zoom (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ld_canvas_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ LdCanvas *self;
+
+ self = LD_CANVAS (object);
+ switch (property_id)
+ {
+ case PROP_DIAGRAM:
+ ld_canvas_set_diagram (self, LD_DIAGRAM (g_value_get_object (value)));
+ break;
+ case PROP_LIBRARY:
+ ld_canvas_set_library (self, LD_LIBRARY (g_value_get_object (value)));
+ break;
+ case PROP_ZOOM:
+ ld_canvas_set_zoom (self, g_value_get_double (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ld_canvas_real_set_scroll_adjustments (LdCanvas *self,
+ GtkAdjustment *horizontal, GtkAdjustment *vertical)
+{
+ /* TODO: Infinite canvas. */
+ GtkWidget *widget;
+ gdouble scale;
+
+ widget = GTK_WIDGET (self);
+ scale = ld_canvas_get_scale_in_px (self);
+
+ if (horizontal != self->priv->adjustment_h)
+ {
+ if (self->priv->adjustment_h)
+ {
+ g_signal_handlers_disconnect_by_func (self->priv->adjustment_h,
+ on_adjustment_value_changed, self);
+ g_object_unref (self->priv->adjustment_h);
+
+ self->priv->adjustment_h = NULL;
+ }
+ if (horizontal)
+ {
+ g_object_ref (horizontal);
+ g_signal_connect (horizontal, "value-changed",
+ G_CALLBACK (on_adjustment_value_changed), self);
+
+ horizontal->upper = 100;
+ horizontal->lower = -100;
+ horizontal->step_increment = 0.5;
+ horizontal->page_increment = 5;
+ horizontal->page_size = widget->allocation.width / scale;
+ horizontal->value = -horizontal->page_size / 2;
+
+ self->priv->adjustment_h = horizontal;
+ }
+ }
+
+ if (vertical != self->priv->adjustment_v)
+ {
+ if (self->priv->adjustment_v)
+ {
+ g_signal_handlers_disconnect_by_func (self->priv->adjustment_v,
+ on_adjustment_value_changed, self);
+ g_object_unref (self->priv->adjustment_v);
+
+ self->priv->adjustment_v = NULL;
+ }
+ if (vertical)
+ {
+ g_object_ref (vertical);
+ g_signal_connect (vertical, "value-changed",
+ G_CALLBACK (on_adjustment_value_changed), self);
+
+ vertical->upper = 100;
+ vertical->lower = -100;
+ vertical->step_increment = 0.5;
+ vertical->page_increment = 5;
+ vertical->page_size = widget->allocation.height / scale;
+ vertical->value = -vertical->page_size / 2;
+
+ self->priv->adjustment_v = vertical;
+ }
+ }
+}
+
+static void
+on_adjustment_value_changed (GtkAdjustment *adjustment, LdCanvas *self)
+{
+ GtkWidget *widget;
+ gdouble scale;
+
+ widget = GTK_WIDGET (self);
+ scale = ld_canvas_get_scale_in_px (self);
+
+ if (adjustment == self->priv->adjustment_h)
+ {
+ self->priv->x = adjustment->value
+ + widget->allocation.width / scale / 2;
+ gtk_widget_queue_draw (widget);
+ }
+ else if (adjustment == self->priv->adjustment_v)
+ {
+ self->priv->y = adjustment->value
+ + widget->allocation.height / scale / 2;
+ gtk_widget_queue_draw (widget);
+ }
+}
+
+static void
+on_size_allocate (GtkWidget *widget, GtkAllocation *allocation,
+ gpointer user_data)
+{
+ LdCanvas *self;
+
+ self = LD_CANVAS (widget);
+
+ /* FIXME: If the new allocation is bigger, we may see more than
+ * what we're supposed to be able to see -> adjust X and Y.
+ *
+ * If the visible area is so large that we simply must see more,
+ * let's disable the scrollbars in question.
+ */
+ update_adjustments (self);
+}
+
+static void
+update_adjustments (LdCanvas *self)
+{
+ gdouble scale;
+
+ scale = ld_canvas_get_scale_in_px (self);
+
+ if (self->priv->adjustment_h)
+ {
+ self->priv->adjustment_h->page_size
+ = GTK_WIDGET (self)->allocation.width / scale;
+ self->priv->adjustment_h->value
+ = self->priv->x - self->priv->adjustment_h->page_size / 2;
+ gtk_adjustment_changed (self->priv->adjustment_h);
+ }
+ if (self->priv->adjustment_v)
+ {
+ self->priv->adjustment_v->page_size
+ = GTK_WIDGET (self)->allocation.height / scale;
+ self->priv->adjustment_v->value
+ = self->priv->y - self->priv->adjustment_v->page_size / 2;
+ gtk_adjustment_changed (self->priv->adjustment_v);
+ }
+}
+
+
+/* ===== Generic interface etc. ============================================ */
+
+/**
+ * ld_canvas_new:
+ *
+ * Create an instance.
+ */
+LdCanvas *
+ld_canvas_new (void)
+{
+ return g_object_new (LD_TYPE_CANVAS, NULL);
+}
+
+/**
+ * ld_canvas_set_diagram:
+ * @self: An #LdCanvas object.
+ * @diagram: The #LdDiagram to be assigned to the canvas.
+ *
+ * Assign an #LdDiagram object to the canvas.
+ */
+void
+ld_canvas_set_diagram (LdCanvas *self, LdDiagram *diagram)
+{
+ g_return_if_fail (LD_IS_CANVAS (self));
+ g_return_if_fail (LD_IS_DIAGRAM (diagram));
+
+ if (self->priv->diagram)
+ {
+ diagram_disconnect_signals (self);
+ g_object_unref (self->priv->diagram);
+ }
+
+ self->priv->diagram = diagram;
+ diagram_connect_signals (self);
+ g_object_ref (diagram);
+
+ g_object_notify (G_OBJECT (self), "diagram");
+}
+
+/**
+ * ld_canvas_get_diagram:
+ * @self: An #LdCanvas object.
+ *
+ * Get the #LdDiagram object assigned to this canvas.
+ * The reference count on the diagram is not incremented.
+ */
+LdDiagram *
+ld_canvas_get_diagram (LdCanvas *self)
+{
+ g_return_val_if_fail (LD_IS_CANVAS (self), NULL);
+ return self->priv->diagram;
+}
+
+static void
+diagram_connect_signals (LdCanvas *self)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self->priv->diagram));
+
+ g_signal_connect_swapped (self->priv->diagram, "changed",
+ G_CALLBACK (gtk_widget_queue_draw), self);
+ g_signal_connect_swapped (self->priv->diagram, "selection-changed",
+ G_CALLBACK (gtk_widget_queue_draw), self);
+}
+
+static void
+diagram_disconnect_signals (LdCanvas *self)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self->priv->diagram));
+
+ g_signal_handlers_disconnect_matched (self->priv->diagram,
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL,
+ gtk_widget_queue_draw, self);
+}
+
+/**
+ * ld_canvas_set_library:
+ * @self: An #LdCanvas object.
+ * @library: The #LdLibrary to be assigned to the canvas.
+ *
+ * Assign an #LdLibrary object to the canvas.
+ */
+void
+ld_canvas_set_library (LdCanvas *self, LdLibrary *library)
+{
+ g_return_if_fail (LD_IS_CANVAS (self));
+ g_return_if_fail (LD_IS_LIBRARY (library));
+
+ if (self->priv->library)
+ g_object_unref (self->priv->library);
+
+ self->priv->library = library;
+ g_object_ref (library);
+
+ g_object_notify (G_OBJECT (self), "library");
+}
+
+/**
+ * ld_canvas_get_library:
+ * @self: An #LdCanvas object.
+ *
+ * Get the #LdLibrary object assigned to this canvas.
+ * The reference count on the library is not incremented.
+ */
+LdLibrary *
+ld_canvas_get_library (LdCanvas *self)
+{
+ g_return_val_if_fail (LD_IS_CANVAS (self), NULL);
+ return self->priv->library;
+}
+
+/*
+ * ld_canvas_get_base_unit_in_px:
+ * @self: A #GtkWidget object to retrieve DPI from (indirectly).
+ *
+ * Return value: Length of the base unit in pixels.
+ */
+static gdouble
+ld_canvas_get_base_unit_in_px (GtkWidget *self)
+{
+ gdouble resolution;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (self), 1);
+
+ resolution = gdk_screen_get_resolution (gtk_widget_get_screen (self));
+ if (resolution == -1)
+ resolution = DEFAULT_SCREEN_RESOLUTION;
+
+ /* XXX: It might look better if the unit was rounded to a whole number. */
+ return resolution / MM_PER_INCH * LD_CANVAS_BASE_UNIT_LENGTH;
+}
+
+/*
+ * ld_canvas_get_scale_in_px:
+ * @self: An #LdCanvas object.
+ *
+ * Return value: Displayed length of the base unit in pixels.
+ */
+static gdouble
+ld_canvas_get_scale_in_px (LdCanvas *self)
+{
+ g_return_val_if_fail (LD_IS_CANVAS (self), 1);
+
+ return ld_canvas_get_base_unit_in_px (GTK_WIDGET (self))
+ * self->priv->zoom;
+}
+
+/**
+ * ld_canvas_widget_to_diagram_coords:
+ * @self: An #LdCanvas object.
+ * @wx: The X coordinate to be translated.
+ * @wy: The Y coordinate to be translated.
+ * @dx: (out): The translated X coordinate.
+ * @dy: (out): The translated Y coordinate.
+ *
+ * Translate coordinates located inside the canvas window
+ * into diagram coordinates.
+ */
+void
+ld_canvas_widget_to_diagram_coords (LdCanvas *self,
+ gdouble wx, gdouble wy, gdouble *dx, gdouble *dy)
+{
+ GtkWidget *widget;
+ gdouble scale;
+
+ g_return_if_fail (LD_IS_CANVAS (self));
+ g_return_if_fail (dx != NULL);
+ g_return_if_fail (dy != NULL);
+
+ widget = GTK_WIDGET (self);
+ scale = ld_canvas_get_scale_in_px (self);
+
+ /* We know diagram coordinates of the center of the canvas, so we may
+ * translate the given X and Y coordinates to this center and then scale
+ * them by dividing them by the current scale.
+ */
+ *dx = self->priv->x + (wx - (widget->allocation.width * 0.5)) / scale;
+ *dy = self->priv->y + (wy - (widget->allocation.height * 0.5)) / scale;
+}
+
+/**
+ * ld_canvas_diagram_to_widget_coords:
+ * @self: An #LdCanvas object.
+ * @dx: The X coordinate to be translated.
+ * @dy: The Y coordinate to be translated.
+ * @wx: (out): The translated X coordinate.
+ * @wy: (out): The translated Y coordinate.
+ *
+ * Translate diagram coordinates into canvas coordinates.
+ */
+void
+ld_canvas_diagram_to_widget_coords (LdCanvas *self,
+ gdouble dx, gdouble dy, gdouble *wx, gdouble *wy)
+{
+ GtkWidget *widget;
+ gdouble scale;
+
+ g_return_if_fail (LD_IS_CANVAS (self));
+ g_return_if_fail (wx != NULL);
+ g_return_if_fail (wy != NULL);
+
+ widget = GTK_WIDGET (self);
+ scale = ld_canvas_get_scale_in_px (self);
+
+ /* Just the reversal of ld_canvas_widget_to_diagram_coords(). */
+ *wx = scale * (dx - self->priv->x) + 0.5 * widget->allocation.width;
+ *wy = scale * (dy - self->priv->y) + 0.5 * widget->allocation.height;
+}
+
+/**
+ * ld_canvas_get_zoom:
+ * @self: An #LdCanvas object.
+ *
+ * Return value: Zoom of the canvas.
+ */
+gdouble
+ld_canvas_get_zoom (LdCanvas *self)
+{
+ g_return_val_if_fail (LD_IS_CANVAS (self), -1);
+ return self->priv->zoom;
+}
+
+/**
+ * ld_canvas_set_zoom:
+ * @self: An #LdCanvas object.
+ * @zoom: The zoom.
+ *
+ * Set zoom of the canvas.
+ */
+void
+ld_canvas_set_zoom (LdCanvas *self, gdouble zoom)
+{
+ gdouble clamped_zoom;
+
+ g_return_if_fail (LD_IS_CANVAS (self));
+
+ clamped_zoom = CLAMP (zoom, ZOOM_MIN, ZOOM_MAX);
+ if (self->priv->zoom == clamped_zoom)
+ return;
+
+ self->priv->zoom = clamped_zoom;
+
+ simulate_motion (self);
+ update_adjustments (self);
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+
+ g_object_notify (G_OBJECT (self), "zoom");
+}
+
+
+/* ===== Operations ======================================================== */
+
+static void
+ld_canvas_real_cancel_operation (LdCanvas *self)
+{
+ g_return_if_fail (LD_IS_CANVAS (self));
+
+ if (self->priv->operation)
+ {
+ if (self->priv->operation_end)
+ self->priv->operation_end (self);
+ self->priv->operation = OPER_0;
+ self->priv->operation_end = NULL;
+ }
+}
+
+/**
+ * ld_canvas_add_object_begin:
+ * @self: An #LdCanvas object.
+ * @object: (transfer full): The object to be added to the diagram.
+ *
+ * Begin an operation for adding an object into the diagram.
+ */
+void
+ld_canvas_add_object_begin (LdCanvas *self, LdDiagramObject *object)
+{
+ AddObjectData *data;
+
+ g_return_if_fail (LD_IS_CANVAS (self));
+ g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
+
+ ld_canvas_real_cancel_operation (self);
+
+ self->priv->operation = OPER_ADD_OBJECT;
+ self->priv->operation_end = ld_canvas_add_object_end;
+
+ data = &OPER_DATA (self, add_object);
+ data->object = object;
+}
+
+static void
+ld_canvas_add_object_end (LdCanvas *self)
+{
+ AddObjectData *data;
+
+ data = &OPER_DATA (self, add_object);
+ if (data->object)
+ {
+ queue_object_draw (self, data->object);
+ g_object_unref (data->object);
+ data->object = NULL;
+ }
+}
+
+
+/* ===== Events, rendering ================================================= */
+
+static void
+ld_canvas_color_set (LdCanvasColor *color,
+ gdouble r, gdouble g, gdouble b, gdouble a)
+{
+ color->r = r;
+ color->g = g;
+ color->b = b;
+ color->a = a;
+}
+
+static void
+ld_canvas_color_apply (LdCanvasColor *color, cairo_t *cr)
+{
+ cairo_set_source_rgba (cr, color->r, color->g, color->b, color->a);
+}
+
+static void
+move_object_to_coords (LdCanvas *self, LdDiagramObject *object,
+ gdouble x, gdouble y)
+{
+ gdouble dx, dy;
+
+ ld_canvas_widget_to_diagram_coords (self, x, y, &dx, &dy);
+ ld_diagram_object_set_x (object, floor (dx + 0.5));
+ ld_diagram_object_set_y (object, floor (dy + 0.5));
+}
+
+static LdDiagramObject *
+get_object_at_coords (LdCanvas *self, gdouble x, gdouble y)
+{
+ GList *objects, *iter;
+
+ /* Iterate from the top object downwards. */
+ objects = (GList *) ld_diagram_get_objects (self->priv->diagram);
+ for (iter = objects; iter; iter = g_list_next (iter))
+ {
+ LdDiagramObject *object;
+
+ object = LD_DIAGRAM_OBJECT (iter->data);
+ if (object_hit_test (self, object, x, y))
+ return object;
+ }
+ return NULL;
+}
+
+static gboolean
+is_object_selected (LdCanvas *self, LdDiagramObject *object)
+{
+ return g_list_find (ld_diagram_get_selection (self->priv->diagram),
+ object) != NULL;
+}
+
+static LdSymbol *
+resolve_diagram_symbol (LdCanvas *self, LdDiagramSymbol *diagram_symbol)
+{
+ if (!self->priv->library)
+ return NULL;
+
+ return ld_library_find_symbol (self->priv->library,
+ ld_diagram_symbol_get_class (diagram_symbol));
+}
+
+static gboolean
+get_symbol_area (LdCanvas *self, LdDiagramSymbol *symbol, LdRectangle *rect)
+{
+ LdDiagramObject *object;
+ gdouble object_x, object_y;
+ LdSymbol *library_symbol;
+ LdRectangle area;
+ gdouble x1, x2;
+ gdouble y1, y2;
+
+ object = LD_DIAGRAM_OBJECT (symbol);
+ object_x = ld_diagram_object_get_x (object);
+ object_y = ld_diagram_object_get_y (object);
+
+ library_symbol = resolve_diagram_symbol (self, symbol);
+ if (library_symbol)
+ ld_symbol_get_area (library_symbol, &area);
+ else
+ return FALSE;
+
+ /* TODO: Rotate the rectangle for other orientations. */
+ ld_canvas_diagram_to_widget_coords (self,
+ object_x + area.x,
+ object_y + area.y,
+ &x1, &y1);
+ ld_canvas_diagram_to_widget_coords (self,
+ object_x + area.x + area.width,
+ object_y + area.y + area.height,
+ &x2, &y2);
+
+ rect->x = x1;
+ rect->y = y1;
+ rect->width = x2 - x1;
+ rect->height = y2 - y1;
+ return TRUE;
+}
+
+static gboolean
+get_symbol_clip_area (LdCanvas *self, LdDiagramSymbol *symbol,
+ LdRectangle *rect)
+{
+ LdRectangle object_rect;
+
+ if (!get_object_area (self, LD_DIAGRAM_OBJECT (symbol), &object_rect))
+ return FALSE;
+
+ *rect = object_rect;
+ ld_rectangle_extend (rect, SYMBOL_CLIP_TOLERANCE);
+ return TRUE;
+}
+
+static gboolean
+get_object_area (LdCanvas *self, LdDiagramObject *object, LdRectangle *rect)
+{
+ if (LD_IS_DIAGRAM_SYMBOL (object))
+ return get_symbol_area (self, LD_DIAGRAM_SYMBOL (object), rect);
+ return FALSE;
+}
+
+static gboolean
+object_hit_test (LdCanvas *self, LdDiagramObject *object, gdouble x, gdouble y)
+{
+ LdRectangle rect;
+
+ if (!get_object_area (self, object, &rect))
+ return FALSE;
+ ld_rectangle_extend (&rect, OBJECT_BORDER_TOLERANCE);
+ return ld_rectangle_contains (&rect, x, y);
+}
+
+static void
+check_terminals (LdCanvas *self, gdouble x, gdouble y)
+{
+ GList *objects, *iter;
+ LdDiagramSymbol *closest_symbol = NULL;
+ gdouble closest_distance = TERMINAL_HOVER_TOLERANCE;
+ LdPoint closest_terminal;
+
+ objects = (GList *) ld_diagram_get_objects (self->priv->diagram);
+ for (iter = objects; iter; iter = g_list_next (iter))
+ {
+ LdDiagramObject *diagram_object;
+ gdouble object_x, object_y;
+ LdDiagramSymbol *diagram_symbol;
+ LdSymbol *symbol;
+ const LdPointArray *terminals;
+ gint i;
+
+ if (!LD_IS_DIAGRAM_SYMBOL (iter->data))
+ continue;
+
+ diagram_symbol = LD_DIAGRAM_SYMBOL (iter->data);
+ symbol = resolve_diagram_symbol (self, diagram_symbol);
+ if (!symbol)
+ continue;
+
+ diagram_object = LD_DIAGRAM_OBJECT (iter->data);
+ object_x = ld_diagram_object_get_x (diagram_object);
+ object_y = ld_diagram_object_get_y (diagram_object);
+
+ terminals = ld_symbol_get_terminals (symbol);
+
+ for (i = 0; i < terminals->num_points; i++)
+ {
+ LdPoint cur_term;
+ gdouble distance;
+
+ cur_term = terminals->points[i];
+ cur_term.x += object_x;
+ cur_term.y += object_y;
+ ld_canvas_diagram_to_widget_coords (self,
+ cur_term.x, cur_term.y, &cur_term.x, &cur_term.y);
+
+ distance = ld_point_distance (&cur_term, x, y);
+ if (distance <= closest_distance)
+ {
+ closest_symbol = diagram_symbol;
+ closest_distance = distance;
+ closest_terminal = cur_term;
+ }
+ }
+ }
+
+ hide_terminals (self);
+
+ if (closest_symbol)
+ {
+ self->priv->terminal_highlighted = TRUE;
+ self->priv->terminal = closest_terminal;
+ queue_terminal_draw (self, &closest_terminal);
+ }
+}
+
+static void
+hide_terminals (LdCanvas *self)
+{
+ if (self->priv->terminal_highlighted)
+ {
+ self->priv->terminal_highlighted = FALSE;
+ queue_terminal_draw (self, &self->priv->terminal);
+ }
+}
+
+static void
+queue_draw (LdCanvas *self, LdRectangle *rect)
+{
+ LdRectangle area;
+
+ area = *rect;
+ ld_rectangle_extend (&area, QUEUE_DRAW_EXTEND);
+ gtk_widget_queue_draw_area (GTK_WIDGET (self),
+ area.x, area.y, area.width, area.height);
+}
+
+static void
+queue_object_draw (LdCanvas *self, LdDiagramObject *object)
+{
+ if (LD_IS_DIAGRAM_SYMBOL (object))
+ {
+ LdRectangle rect;
+
+ if (!get_symbol_clip_area (self, LD_DIAGRAM_SYMBOL (object), &rect))
+ return;
+ queue_draw (self, &rect);
+ }
+}
+
+static void
+queue_terminal_draw (LdCanvas *self, LdPoint *terminal)
+{
+ LdRectangle rect;
+
+ rect.x = terminal->x - TERMINAL_RADIUS;
+ rect.y = terminal->y - TERMINAL_RADIUS;
+ rect.width = 2 * TERMINAL_RADIUS;
+ rect.height = 2 * TERMINAL_RADIUS;
+ queue_draw (self, &rect);
+}
+
+static void
+simulate_motion (LdCanvas *self)
+{
+ GdkEventMotion event;
+ GtkWidget *widget;
+ gint x, y;
+ GdkModifierType state;
+
+ widget = GTK_WIDGET (self);
+
+ if (gdk_window_get_pointer (widget->window, &x, &y, &state)
+ != widget->window)
+ return;
+
+ memset (&event, 0, sizeof (event));
+ event.type = GDK_MOTION_NOTIFY;
+ event.window = widget->window;
+ event.x = x;
+ event.y = y;
+ event.state = state;
+
+ on_motion_notify (widget, &event, NULL);
+}
+
+static gboolean
+on_motion_notify (GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
+{
+ LdCanvas *self;
+
+ self = LD_CANVAS (widget);
+ switch (self->priv->operation)
+ {
+ AddObjectData *data;
+
+ case OPER_ADD_OBJECT:
+ data = &OPER_DATA (self, add_object);
+ data->visible = TRUE;
+
+ queue_object_draw (self, data->object);
+ move_object_to_coords (self, data->object, event->x, event->y);
+ queue_object_draw (self, data->object);
+ break;
+ case OPER_0:
+ check_terminals (self, event->x, event->y);
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+on_leave_notify (GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
+{
+ LdCanvas *self;
+
+ self = LD_CANVAS (widget);
+ switch (self->priv->operation)
+ {
+ AddObjectData *data;
+
+ case OPER_ADD_OBJECT:
+ data = &OPER_DATA (self, add_object);
+ data->visible = FALSE;
+
+ queue_object_draw (self, data->object);
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+on_button_press (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+ LdCanvas *self;
+
+ if (!gtk_widget_has_focus (widget))
+ gtk_widget_grab_focus (widget);
+
+ self = LD_CANVAS (widget);
+ switch (self->priv->operation)
+ {
+ AddObjectData *data;
+
+ case OPER_ADD_OBJECT:
+ data = &OPER_DATA (self, add_object);
+
+ queue_object_draw (self, data->object);
+ move_object_to_coords (self, data->object, event->x, event->y);
+
+ if (self->priv->diagram)
+ ld_diagram_insert_object (self->priv->diagram, data->object, 0);
+
+ /* XXX: "cancel" causes confusion. */
+ ld_canvas_real_cancel_operation (self);
+ break;
+ case OPER_0:
+ if (self->priv->diagram)
+ {
+ LdDiagramObject *object;
+
+ if (event->state != GDK_SHIFT_MASK)
+ ld_diagram_unselect_all (self->priv->diagram);
+
+ object = get_object_at_coords (self, event->x, event->y);
+ if (object)
+ ld_diagram_selection_add (self->priv->diagram, object, 0);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+on_button_release (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+ return FALSE;
+}
+
+static gboolean
+on_scroll (GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
+{
+ gdouble prev_x, prev_y;
+ gdouble new_x, new_y;
+ LdCanvas *self;
+
+ self = LD_CANVAS (widget);
+
+ ld_canvas_widget_to_diagram_coords (self,
+ event->x, event->y, &prev_x, &prev_y);
+
+ switch (event->direction)
+ {
+ case GDK_SCROLL_UP:
+ ld_canvas_set_zoom (self, self->priv->zoom * ZOOM_WHEEL_STEP);
+ break;
+ case GDK_SCROLL_DOWN:
+ ld_canvas_set_zoom (self, self->priv->zoom / ZOOM_WHEEL_STEP);
+ break;
+ default:
+ return FALSE;
+ }
+
+ ld_canvas_widget_to_diagram_coords (self,
+ event->x, event->y, &new_x, &new_y);
+
+ /* Focus on the point under the cursor. */
+ self->priv->x += prev_x - new_x;
+ self->priv->y += prev_y - new_y;
+
+ check_terminals (self, event->x, event->y);
+ return TRUE;
+}
+
+static gboolean
+on_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
+{
+ DrawData data;
+
+ data.cr = gdk_cairo_create (widget->window);
+ data.self = LD_CANVAS (widget);
+ data.scale = ld_canvas_get_scale_in_px (data.self);
+ data.exposed_rect.x = event->area.x;
+ data.exposed_rect.y = event->area.y;
+ data.exposed_rect.width = event->area.width;
+ data.exposed_rect.height = event->area.height;
+
+ gdk_cairo_rectangle (data.cr, &event->area);
+ cairo_clip (data.cr);
+
+ ld_canvas_color_apply (COLOR_GET (data.self, COLOR_BASE), data.cr);
+ cairo_paint (data.cr);
+
+ draw_grid (widget, &data);
+ draw_diagram (widget, &data);
+ draw_terminal (widget, &data);
+
+ cairo_destroy (data.cr);
+ return FALSE;
+}
+
+static void
+draw_grid (GtkWidget *widget, DrawData *data)
+{
+ gdouble grid_step;
+ gdouble x_init, y_init;
+ gdouble x, y;
+
+ grid_step = data->scale;
+ while (grid_step < 5)
+ grid_step *= 5;
+
+ ld_canvas_color_apply (COLOR_GET (data->self, COLOR_GRID), data->cr);
+ cairo_set_line_width (data->cr, 1);
+ cairo_set_line_cap (data->cr, CAIRO_LINE_CAP_ROUND);
+
+ /* Get coordinates of the top-left point. */
+ ld_canvas_widget_to_diagram_coords (data->self,
+ data->exposed_rect.x, data->exposed_rect.y, &x_init, &y_init);
+ ld_canvas_diagram_to_widget_coords (data->self,
+ ceil (x_init), ceil (y_init), &x_init, &y_init);
+
+ /* Iterate over all the points. */
+ for (x = x_init; x <= data->exposed_rect.x + data->exposed_rect.width;
+ x += grid_step)
+ {
+ for (y = y_init; y <= data->exposed_rect.y + data->exposed_rect.height;
+ y += grid_step)
+ {
+ cairo_move_to (data->cr, x, y);
+ cairo_line_to (data->cr, x, y);
+ }
+ }
+ cairo_stroke (data->cr);
+}
+
+static void
+draw_terminal (GtkWidget *widget, DrawData *data)
+{
+ LdCanvasPrivate *priv;
+
+ priv = data->self->priv;
+ if (!priv->terminal_highlighted)
+ return;
+
+ ld_canvas_color_apply (COLOR_GET (data->self, COLOR_TERMINAL), data->cr);
+ cairo_set_line_width (data->cr, 1);
+
+ cairo_new_path (data->cr);
+ cairo_arc (data->cr, priv->terminal.x, priv->terminal.y,
+ TERMINAL_RADIUS, 0, 2 * G_PI);
+ cairo_stroke (data->cr);
+}
+
+static void
+draw_diagram (GtkWidget *widget, DrawData *data)
+{
+ GList *objects, *iter;
+
+ if (!data->self->priv->diagram)
+ return;
+
+ cairo_save (data->cr);
+ cairo_set_line_width (data->cr, 1 / data->scale);
+
+ /* Draw objects from the diagram, from bottom to top. */
+ objects = (GList *) ld_diagram_get_objects (data->self->priv->diagram);
+ for (iter = g_list_last (objects); iter; iter = g_list_previous (iter))
+ draw_object (LD_DIAGRAM_OBJECT (iter->data), data);
+
+ switch (data->self->priv->operation)
+ {
+ AddObjectData *op_data;
+
+ case OPER_ADD_OBJECT:
+ op_data = &OPER_DATA (data->self, add_object);
+ if (op_data->visible)
+ draw_object (op_data->object, data);
+ break;
+ }
+
+ cairo_restore (data->cr);
+}
+
+static void
+draw_object (LdDiagramObject *diagram_object, DrawData *data)
+{
+ g_return_if_fail (LD_IS_DIAGRAM_OBJECT (diagram_object));
+ g_return_if_fail (data != NULL);
+
+ if (is_object_selected (data->self, diagram_object))
+ ld_canvas_color_apply (COLOR_GET (data->self,
+ COLOR_SELECTION), data->cr);
+ else
+ ld_canvas_color_apply (COLOR_GET (data->self,
+ COLOR_OBJECT), data->cr);
+
+ if (LD_IS_DIAGRAM_SYMBOL (diagram_object))
+ draw_symbol (LD_DIAGRAM_SYMBOL (diagram_object), data);
+}
+
+static void
+draw_symbol (LdDiagramSymbol *diagram_symbol, DrawData *data)
+{
+ LdSymbol *symbol;
+ LdRectangle clip_rect;
+ gdouble x, y;
+
+ symbol = resolve_diagram_symbol (data->self, diagram_symbol);
+
+ /* TODO: Resolve this better; draw a cross or whatever. */
+ if (!symbol)
+ {
+ g_warning ("Cannot find symbol %s in the library.",
+ ld_diagram_symbol_get_class (diagram_symbol));
+ return;
+ }
+
+ if (!get_symbol_clip_area (data->self, diagram_symbol, &clip_rect)
+ || !ld_rectangle_intersects (&clip_rect, &data->exposed_rect))
+ return;
+
+ cairo_save (data->cr);
+
+ cairo_rectangle (data->cr, clip_rect.x, clip_rect.y,
+ clip_rect.width, clip_rect.height);
+ cairo_clip (data->cr);
+
+ /* TODO: Rotate the space for other orientations. */
+ ld_canvas_diagram_to_widget_coords (data->self,
+ ld_diagram_object_get_x (LD_DIAGRAM_OBJECT (diagram_symbol)),
+ ld_diagram_object_get_y (LD_DIAGRAM_OBJECT (diagram_symbol)),
+ &x, &y);
+ cairo_translate (data->cr, x, y);
+ cairo_scale (data->cr, data->scale, data->scale);
+ ld_symbol_draw (symbol, data->cr);
+
+ cairo_restore (data->cr);
+}
diff --git a/liblogdiag/ld-canvas.h b/liblogdiag/ld-canvas.h
new file mode 100644
index 0000000..702f2fe
--- /dev/null
+++ b/liblogdiag/ld-canvas.h
@@ -0,0 +1,91 @@
+/*
+ * ld-canvas.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_CANVAS_H__
+#define __LD_CANVAS_H__
+
+G_BEGIN_DECLS
+
+
+#define LD_TYPE_CANVAS (ld_canvas_get_type ())
+#define LD_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), LD_TYPE_CANVAS, LdCanvas))
+#define LD_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), LD_TYPE_CANVAS, LdCanvasClass))
+#define LD_IS_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), LD_TYPE_CANVAS))
+#define LD_IS_CANVAS_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((klass), LD_TYPE_CANVAS))
+#define LD_CANVAS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), LD_CANVAS, LdCanvasClass))
+
+typedef struct _LdCanvas LdCanvas;
+typedef struct _LdCanvasPrivate LdCanvasPrivate;
+typedef struct _LdCanvasClass LdCanvasClass;
+
+
+/**
+ * LdCanvas:
+ */
+struct _LdCanvas
+{
+/*< private >*/
+ GtkDrawingArea parent_instance;
+ LdCanvasPrivate *priv;
+
+/*< public >*/
+};
+
+struct _LdCanvasClass
+{
+/*< private >*/
+ GtkDrawingAreaClass parent_class;
+
+ guint cancel_operation_signal;
+
+ void (*set_scroll_adjustments) (LdCanvas *self,
+ GtkAdjustment *horizontal, GtkAdjustment *vertical);
+ void (*cancel_operation) (LdCanvas *self);
+};
+
+
+/**
+ * LD_CANVAS_BASE_UNIT:
+ *
+ * Length of the base unit in milimetres.
+ */
+#define LD_CANVAS_BASE_UNIT_LENGTH 2.5
+
+
+GType ld_canvas_get_type (void) G_GNUC_CONST;
+
+LdCanvas *ld_canvas_new (void);
+
+void ld_canvas_set_diagram (LdCanvas *self, LdDiagram *diagram);
+LdDiagram *ld_canvas_get_diagram (LdCanvas *self);
+void ld_canvas_set_library (LdCanvas *self, LdLibrary *library);
+LdLibrary *ld_canvas_get_library (LdCanvas *self);
+
+void ld_canvas_widget_to_diagram_coords (LdCanvas *self,
+ gdouble wx, gdouble wy, gdouble *dx, gdouble *dy);
+void ld_canvas_diagram_to_widget_coords (LdCanvas *self,
+ gdouble dx, gdouble dy, gdouble *wx, gdouble *wy);
+
+gdouble ld_canvas_get_zoom (LdCanvas *self);
+void ld_canvas_set_zoom (LdCanvas *self, gdouble zoom);
+
+void ld_canvas_add_object_begin (LdCanvas *self, LdDiagramObject *object);
+
+/* TODO: The rest of the interface. */
+
+
+G_END_DECLS
+
+#endif /* ! __LD_CANVAS_H__ */
diff --git a/liblogdiag/ld-diagram-object.c b/liblogdiag/ld-diagram-object.c
new file mode 100644
index 0000000..f43e620
--- /dev/null
+++ b/liblogdiag/ld-diagram-object.c
@@ -0,0 +1,186 @@
+/*
+ * ld-diagram-object.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include "liblogdiag.h"
+#include "config.h"
+
+
+/**
+ * SECTION:ld-diagram-object
+ * @short_description: A diagram object.
+ * @see_also: #LdDiagram, #LdCanvas
+ *
+ * #LdDiagramObject represents an object in an #LdDiagram.
+ */
+
+/*
+ * LdDiagramObjectPrivate:
+ * @x: The X coordinate of this object.
+ * @y: The Y coordinate of this object.
+ */
+struct _LdDiagramObjectPrivate
+{
+ gdouble x;
+ gdouble y;
+};
+
+enum
+{
+ PROP_0,
+ PROP_X,
+ PROP_Y
+};
+
+static void ld_diagram_object_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec);
+static void ld_diagram_object_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec);
+
+
+G_DEFINE_ABSTRACT_TYPE (LdDiagramObject, ld_diagram_object, G_TYPE_OBJECT);
+
+static void
+ld_diagram_object_class_init (LdDiagramObjectClass *klass)
+{
+ GObjectClass *object_class;
+ GParamSpec *pspec;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = ld_diagram_object_get_property;
+ object_class->set_property = ld_diagram_object_set_property;
+
+/**
+ * LdDiagramObject:x:
+ *
+ * The X coordinate of the object.
+ */
+ pspec = g_param_spec_double ("x", "X",
+ "The X coordinate of this object.",
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_X, pspec);
+
+/**
+ * LdDiagramObject:y:
+ *
+ * The Y coordinate of the object.
+ */
+ pspec = g_param_spec_double ("y", "Y",
+ "The Y coordinate of this object.",
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_Y, pspec);
+
+ g_type_class_add_private (klass, sizeof (LdDiagramObjectPrivate));
+}
+
+static void
+ld_diagram_object_init (LdDiagramObject *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self, LD_TYPE_DIAGRAM_OBJECT, LdDiagramObjectPrivate);
+}
+
+static void
+ld_diagram_object_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec)
+{
+ LdDiagramObject *self;
+
+ self = LD_DIAGRAM_OBJECT (object);
+ switch (property_id)
+ {
+ case PROP_X:
+ g_value_set_double (value, ld_diagram_object_get_x (self));
+ break;
+ case PROP_Y:
+ g_value_set_double (value, ld_diagram_object_get_y (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ld_diagram_object_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ LdDiagramObject *self;
+
+ self = LD_DIAGRAM_OBJECT (object);
+ switch (property_id)
+ {
+ case PROP_X:
+ ld_diagram_object_set_x (self, g_value_get_double (value));
+ break;
+ case PROP_Y:
+ ld_diagram_object_set_y (self, g_value_get_double (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+
+/**
+ * ld_diagram_object_get_x:
+ * @self: An #LdDiagramObject object.
+ *
+ * Return value: The X coordinate of the object.
+ */
+gdouble
+ld_diagram_object_get_x (LdDiagramObject *self)
+{
+ g_return_val_if_fail (LD_IS_DIAGRAM_OBJECT (self), 0);
+ return self->priv->x;
+}
+
+/**
+ * ld_diagram_object_get_y:
+ * @self: An #LdDiagramObject object.
+ *
+ * Return value: The Y coordinate of the object.
+ */
+gdouble
+ld_diagram_object_get_y (LdDiagramObject *self)
+{
+ g_return_val_if_fail (LD_IS_DIAGRAM_OBJECT (self), 0);
+ return self->priv->y;
+}
+
+/**
+ * ld_diagram_object_set_x:
+ * @self: An #LdDiagramObject object.
+ * @x: The new X coordinate.
+ *
+ * Set the X coordinate of the object.
+ */
+void
+ld_diagram_object_set_x (LdDiagramObject *self, gdouble x)
+{
+ g_return_if_fail (LD_IS_DIAGRAM_OBJECT (self));
+ self->priv->x = x;
+
+ g_object_notify (G_OBJECT (self), "x");
+}
+
+/**
+ * ld_diagram_object_set_y:
+ * @self: An #LdDiagramObject object.
+ * @y: The new Y coordinate.
+ *
+ * Set the Y coordinate of the object.
+ */
+void
+ld_diagram_object_set_y (LdDiagramObject *self, gdouble y)
+{
+ g_return_if_fail (LD_IS_DIAGRAM_OBJECT (self));
+ self->priv->y = y;
+
+ g_object_notify (G_OBJECT (self), "y");
+}
diff --git a/liblogdiag/ld-diagram-object.h b/liblogdiag/ld-diagram-object.h
new file mode 100644
index 0000000..c727602
--- /dev/null
+++ b/liblogdiag/ld-diagram-object.h
@@ -0,0 +1,65 @@
+/*
+ * ld-diagram-object.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_DIAGRAM_OBJECT_H__
+#define __LD_DIAGRAM_OBJECT_H__
+
+G_BEGIN_DECLS
+
+
+#define LD_TYPE_DIAGRAM_OBJECT (ld_diagram_object_get_type ())
+#define LD_DIAGRAM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), LD_TYPE_DIAGRAM_OBJECT, LdDiagramObject))
+#define LD_DIAGRAM_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), LD_TYPE_DIAGRAM_OBJECT, LdDiagramObjectClass))
+#define LD_IS_DIAGRAM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), LD_TYPE_DIAGRAM_OBJECT))
+#define LD_IS_DIAGRAM_OBJECT_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((klass), LD_TYPE_DIAGRAM_OBJECT))
+#define LD_DIAGRAM_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), LD_DIAGRAM_OBJECT, LdDiagramObjectClass))
+
+typedef struct _LdDiagramObject LdDiagramObject;
+typedef struct _LdDiagramObjectPrivate LdDiagramObjectPrivate;
+typedef struct _LdDiagramObjectClass LdDiagramObjectClass;
+
+
+/**
+ * LdDiagramObject:
+ */
+struct _LdDiagramObject
+{
+/*< private >*/
+ GObject parent_instance;
+ LdDiagramObjectPrivate *priv;
+};
+
+/**
+ * LdDiagramObjectClass:
+ */
+struct _LdDiagramObjectClass
+{
+/*< private >*/
+ GObjectClass parent_class;
+};
+
+
+GType ld_diagram_object_get_type (void) G_GNUC_CONST;
+
+gdouble ld_diagram_object_get_x (LdDiagramObject *self);
+gdouble ld_diagram_object_get_y (LdDiagramObject *self);
+void ld_diagram_object_set_x (LdDiagramObject *self, gdouble x);
+void ld_diagram_object_set_y (LdDiagramObject *self, gdouble y);
+
+
+G_END_DECLS
+
+#endif /* ! __LD_DIAGRAM_OBJECT_H__ */
+
diff --git a/liblogdiag/ld-diagram-symbol.c b/liblogdiag/ld-diagram-symbol.c
new file mode 100644
index 0000000..3308dbb
--- /dev/null
+++ b/liblogdiag/ld-diagram-symbol.c
@@ -0,0 +1,171 @@
+/*
+ * ld-diagram-symbol.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include "liblogdiag.h"
+#include "config.h"
+
+
+/**
+ * SECTION:ld-diagram-symbol
+ * @short_description: A symbol object.
+ * @see_also: #LdDiagramObject
+ *
+ * #LdDiagramSymbol is an implementation of #LdDiagramObject.
+ */
+
+/*
+ * LdDiagramSymbolPrivate:
+ * @klass: The class of this symbol.
+ */
+struct _LdDiagramSymbolPrivate
+{
+ gchar *klass;
+};
+
+enum
+{
+ PROP_0,
+ PROP_CLASS
+};
+
+static void ld_diagram_symbol_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec);
+static void ld_diagram_symbol_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec);
+static void ld_diagram_symbol_finalize (GObject *gobject);
+
+
+G_DEFINE_TYPE (LdDiagramSymbol, ld_diagram_symbol, LD_TYPE_DIAGRAM_OBJECT);
+
+static void
+ld_diagram_symbol_class_init (LdDiagramSymbolClass *klass)
+{
+ GObjectClass *object_class;
+ GParamSpec *pspec;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = ld_diagram_symbol_get_property;
+ object_class->set_property = ld_diagram_symbol_set_property;
+ object_class->finalize = ld_diagram_symbol_finalize;
+
+/**
+ * LdDiagramSymbol:class:
+ *
+ * The class of this symbol.
+ */
+ pspec = g_param_spec_string ("class", "Class",
+ "The class of this symbol.",
+ "", G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_CLASS, pspec);
+
+ g_type_class_add_private (klass, sizeof (LdDiagramSymbolPrivate));
+}
+
+static void
+ld_diagram_symbol_init (LdDiagramSymbol *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self, LD_TYPE_DIAGRAM_SYMBOL, LdDiagramSymbolPrivate);
+}
+
+static void
+ld_diagram_symbol_finalize (GObject *gobject)
+{
+ LdDiagramSymbol *self;
+
+ self = LD_DIAGRAM_SYMBOL (gobject);
+
+ if (self->priv->klass)
+ g_free (self->priv->klass);
+
+ /* Chain up to the parent class. */
+ G_OBJECT_CLASS (ld_diagram_symbol_parent_class)->finalize (gobject);
+}
+
+static void
+ld_diagram_symbol_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec)
+{
+ LdDiagramSymbol *self;
+
+ self = LD_DIAGRAM_SYMBOL (object);
+ switch (property_id)
+ {
+ case PROP_CLASS:
+ g_value_set_string (value, ld_diagram_symbol_get_class (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ld_diagram_symbol_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ LdDiagramSymbol *self;
+
+ self = LD_DIAGRAM_SYMBOL (object);
+ switch (property_id)
+ {
+ case PROP_CLASS:
+ ld_diagram_symbol_set_class (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+
+/**
+ * ld_diagram_symbol_new:
+ * @klass: The class of the new symbol.
+ *
+ * Return value: A new #LdDiagramSymbol object.
+ */
+LdDiagramSymbol *
+ld_diagram_symbol_new (const gchar *klass)
+{
+ LdDiagramSymbol *self;
+
+ self = g_object_new (LD_TYPE_DIAGRAM_SYMBOL, NULL);
+ ld_diagram_symbol_set_class (self, klass);
+ return self;
+}
+
+/**
+ * ld_diagram_symbol_get_class:
+ * @self: An #LdDiagramSymbol object.
+ *
+ * Return value: The class of the symbol.
+ */
+const gchar *
+ld_diagram_symbol_get_class (LdDiagramSymbol *self)
+{
+ g_return_val_if_fail (LD_IS_DIAGRAM_SYMBOL (self), NULL);
+ return self->priv->klass;
+}
+
+/**
+ * ld_diagram_symbol_get_class:
+ * @self: An #LdDiagramSymbol object.
+ * @klass: The class.
+ *
+ * Set the class of the symbol.
+ */
+void
+ld_diagram_symbol_set_class (LdDiagramSymbol *self, const gchar *klass)
+{
+ g_return_if_fail (LD_IS_DIAGRAM_SYMBOL (self));
+
+ if (self->priv->klass)
+ g_free (self->priv->klass);
+ self->priv->klass = g_strdup (klass);
+}
diff --git a/liblogdiag/ld-diagram-symbol.h b/liblogdiag/ld-diagram-symbol.h
new file mode 100644
index 0000000..09d8739
--- /dev/null
+++ b/liblogdiag/ld-diagram-symbol.h
@@ -0,0 +1,64 @@
+/*
+ * ld-diagram-symbol.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_DIAGRAM_SYMBOL_H__
+#define __LD_DIAGRAM_SYMBOL_H__
+
+G_BEGIN_DECLS
+
+
+#define LD_TYPE_DIAGRAM_SYMBOL (ld_diagram_symbol_get_type ())
+#define LD_DIAGRAM_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), LD_TYPE_DIAGRAM_SYMBOL, LdDiagramSymbol))
+#define LD_DIAGRAM_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), LD_TYPE_DIAGRAM_SYMBOL, LdDiagramSymbolClass))
+#define LD_IS_DIAGRAM_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), LD_TYPE_DIAGRAM_SYMBOL))
+#define LD_IS_DIAGRAM_SYMBOL_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((klass), LD_TYPE_DIAGRAM_SYMBOL))
+#define LD_DIAGRAM_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), LD_DIAGRAM_SYMBOL, LdDiagramSymbolClass))
+
+typedef struct _LdDiagramSymbol LdDiagramSymbol;
+typedef struct _LdDiagramSymbolPrivate LdDiagramSymbolPrivate;
+typedef struct _LdDiagramSymbolClass LdDiagramSymbolClass;
+
+
+/**
+ * LdDiagramSymbol:
+ */
+struct _LdDiagramSymbol
+{
+/*< private >*/
+ LdDiagramObject parent_instance;
+ LdDiagramSymbolPrivate *priv;
+};
+
+/**
+ * LdDiagramSymbolClass:
+ */
+struct _LdDiagramSymbolClass
+{
+/*< private >*/
+ LdDiagramObjectClass parent_class;
+};
+
+
+GType ld_diagram_symbol_get_type (void) G_GNUC_CONST;
+
+LdDiagramSymbol *ld_diagram_symbol_new (const gchar *klass);
+const gchar *ld_diagram_symbol_get_class (LdDiagramSymbol *self);
+void ld_diagram_symbol_set_class (LdDiagramSymbol *self, const gchar *klass);
+
+
+G_END_DECLS
+
+#endif /* ! __LD_DIAGRAM_SYMBOL_H__ */
+
diff --git a/liblogdiag/ld-diagram.c b/liblogdiag/ld-diagram.c
new file mode 100644
index 0000000..0129e2b
--- /dev/null
+++ b/liblogdiag/ld-diagram.c
@@ -0,0 +1,550 @@
+/*
+ * ld-diagram.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include "liblogdiag.h"
+#include "config.h"
+
+
+/**
+ * SECTION:ld-diagram
+ * @short_description: A diagram object.
+ * @see_also: #LdCanvas
+ *
+ * #LdDiagram is a model used for storing diagrams.
+ */
+
+/*
+ * LdDiagramPrivate:
+ * @modified: Whether the diagram has been modified.
+ * @objects: All objects in the diagram.
+ * @selection: All currently selected objects.
+ * @connections: Connections between objects.
+ */
+struct _LdDiagramPrivate
+{
+ gboolean modified;
+
+ GList *objects;
+ GList *selection;
+ GList *connections;
+};
+
+enum
+{
+ PROP_0,
+ PROP_MODIFIED
+};
+
+static void ld_diagram_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec);
+static void ld_diagram_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec);
+static void ld_diagram_dispose (GObject *gobject);
+static void ld_diagram_finalize (GObject *gobject);
+
+static gboolean write_signature (GOutputStream *stream, GError **error);
+
+static void ld_diagram_real_changed (LdDiagram *self);
+static void ld_diagram_clear_internal (LdDiagram *self);
+static void ld_diagram_unselect_all_internal (LdDiagram *self);
+
+
+G_DEFINE_TYPE (LdDiagram, ld_diagram, G_TYPE_OBJECT);
+
+static void
+ld_diagram_class_init (LdDiagramClass *klass)
+{
+ GObjectClass *object_class;
+ GParamSpec *pspec;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = ld_diagram_get_property;
+ object_class->set_property = ld_diagram_set_property;
+ object_class->dispose = ld_diagram_dispose;
+ object_class->finalize = ld_diagram_finalize;
+
+ klass->changed = ld_diagram_real_changed;
+
+/**
+ * LdDiagram:modified:
+ *
+ * Whether the diagram has been modified.
+ */
+ pspec = g_param_spec_boolean ("modified", "Modified",
+ "Whether the diagram has been modified.",
+ FALSE, G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_MODIFIED, pspec);
+
+/**
+ * LdDiagram::changed:
+ * @diagram: The diagram object.
+ *
+ * Contents of the diagram have changed.
+ */
+ klass->changed_signal = g_signal_new
+ ("changed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LdDiagramClass, changed), NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+/**
+ * LdDiagram::selection-changed:
+ * @diagram: The diagram object.
+ *
+ * The current selection has changed.
+ */
+ klass->selection_changed_signal = g_signal_new
+ ("selection-changed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LdDiagramClass, selection_changed), NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+ g_type_class_add_private (klass, sizeof (LdDiagramPrivate));
+}
+
+static void
+ld_diagram_init (LdDiagram *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self, LD_TYPE_DIAGRAM, LdDiagramPrivate);
+}
+
+static void
+ld_diagram_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec)
+{
+ LdDiagram *self;
+
+ self = LD_DIAGRAM (object);
+ switch (property_id)
+ {
+ case PROP_MODIFIED:
+ g_value_set_boolean (value, ld_diagram_get_modified (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ld_diagram_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ LdDiagram *self;
+
+ self = LD_DIAGRAM (object);
+ switch (property_id)
+ {
+ case PROP_MODIFIED:
+ ld_diagram_set_modified (self, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ld_diagram_dispose (GObject *gobject)
+{
+ LdDiagram *self;
+
+ self = LD_DIAGRAM (gobject);
+ ld_diagram_clear_internal (self);
+
+ /* Chain up to the parent class. */
+ G_OBJECT_CLASS (ld_diagram_parent_class)->dispose (gobject);
+}
+
+static void
+ld_diagram_finalize (GObject *gobject)
+{
+ /* Chain up to the parent class. */
+ G_OBJECT_CLASS (ld_diagram_parent_class)->finalize (gobject);
+}
+
+static void
+ld_diagram_real_changed (LdDiagram *self)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self));
+
+ ld_diagram_set_modified (self, TRUE);
+}
+
+
+/**
+ * ld_diagram_new:
+ *
+ * Create an instance.
+ */
+LdDiagram *
+ld_diagram_new (void)
+{
+ return g_object_new (LD_TYPE_DIAGRAM, NULL);
+}
+
+/**
+ * ld_diagram_clear:
+ * @self: An #LdDiagram object.
+ *
+ * Clear the whole diagram with it's objects and selection.
+ */
+void
+ld_diagram_clear (LdDiagram *self)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self));
+
+ ld_diagram_clear_internal (self);
+
+ g_signal_emit (self,
+ LD_DIAGRAM_GET_CLASS (self)->changed_signal, 0);
+}
+
+/*
+ * ld_diagram_clear_internal:
+ * @self: An #LdDiagram object.
+ *
+ * Do the same as ld_diagram_clear() does but don't emit signals.
+ */
+static void
+ld_diagram_clear_internal (LdDiagram *self)
+{
+ ld_diagram_unselect_all (self);
+
+ g_list_free (self->priv->connections);
+ self->priv->connections = NULL;
+
+ g_list_foreach (self->priv->objects, (GFunc) g_object_unref, NULL);
+ g_list_free (self->priv->objects);
+ self->priv->objects = NULL;
+}
+
+/**
+ * ld_diagram_load_from_file:
+ * @self: An #LdDiagram object.
+ * @filename: A filename.
+ * @error: Return location for a GError, or NULL.
+ *
+ * Load a file into the diagram.
+ *
+ * Return value: TRUE if the file could be loaded, FALSE otherwise.
+ */
+gboolean
+ld_diagram_load_from_file (LdDiagram *self,
+ const gchar *filename, GError **error)
+{
+ JsonParser *parser;
+ GError *json_error;
+
+ g_return_val_if_fail (LD_IS_DIAGRAM (self), FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+
+ /* TODO: Implement loading for real. This is just a stub. */
+ parser = json_parser_new ();
+
+ json_error = NULL;
+ json_parser_load_from_file (parser, filename, &json_error);
+ if (json_error)
+ {
+ g_propagate_error (error, json_error);
+ g_object_unref (parser);
+ return FALSE;
+ }
+
+ ld_diagram_clear (self);
+ g_object_unref (parser);
+ return TRUE;
+}
+
+/**
+ * ld_diagram_save_to_file:
+ * @self: An #LdDiagram object.
+ * @filename: A filename.
+ * @error: Return location for a GError, or NULL.
+ *
+ * Save the diagram into a file.
+ *
+ * Return value: TRUE if the diagram could be saved, FALSE otherwise.
+ */
+gboolean
+ld_diagram_save_to_file (LdDiagram *self,
+ const gchar *filename, GError **error)
+{
+ GFile *file;
+ GFileOutputStream *file_stream;
+ JsonGenerator *generator;
+ JsonNode *root;
+ GError *local_error;
+
+ g_return_val_if_fail (LD_IS_DIAGRAM (self), FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+
+ file = g_file_new_for_path (filename);
+
+ local_error = NULL;
+ file_stream = g_file_replace (file, NULL, FALSE,
+ G_FILE_CREATE_NONE, NULL, &local_error);
+ g_object_unref (file);
+
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ local_error = NULL;
+ write_signature (G_OUTPUT_STREAM (file_stream), &local_error);
+ if (local_error)
+ {
+ g_object_unref (file_stream);
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ /* TODO: Implement saving for real. This is just a stub. */
+ generator = json_generator_new ();
+ g_object_set (generator, "pretty", TRUE, NULL);
+
+ /* XXX: json-glib dislikes empty objects. */
+ root = json_node_new (JSON_NODE_OBJECT);
+ json_generator_set_root (generator, root);
+ json_node_free (root);
+
+ local_error = NULL;
+ json_generator_to_stream (generator, G_OUTPUT_STREAM (file_stream),
+ NULL, &local_error);
+ g_object_unref (file_stream);
+ g_object_unref (generator);
+
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+write_signature (GOutputStream *stream, GError **error)
+{
+ static const gchar signature[] = "/* logdiag diagram */\n";
+ GError *local_error = NULL;
+
+ g_output_stream_write (stream, signature, sizeof (signature) - 1,
+ NULL, &local_error);
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * ld_diagram_get_modified:
+ * @self: An #LdDiagram object.
+ *
+ * Return value: The modification status of diagram.
+ */
+gboolean
+ld_diagram_get_modified (LdDiagram *self)
+{
+ g_return_val_if_fail (LD_IS_DIAGRAM (self), FALSE);
+ return self->priv->modified;
+}
+
+/**
+ * ld_diagram_set_modified:
+ * @self: An #LdDiagram object.
+ * @value: Whether the diagram has been modified.
+ *
+ * Set the modification status of diagram.
+ */
+void
+ld_diagram_set_modified (LdDiagram *self, gboolean value)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self));
+ self->priv->modified = value;
+
+ g_object_notify (G_OBJECT (self), "modified");
+}
+
+/**
+ * ld_diagram_get_objects:
+ * @self: An #LdDiagram object.
+ *
+ * Get a list of objects in the diagram. Do not modify.
+ */
+GList *
+ld_diagram_get_objects (LdDiagram *self)
+{
+ g_return_val_if_fail (LD_IS_DIAGRAM (self), NULL);
+ return self->priv->objects;
+}
+
+/**
+ * ld_diagram_insert_object:
+ * @self: An #LdDiagram object.
+ * @object: The object to be inserted.
+ * @pos: The position at which the object is to be inserted.
+ * Negative values will append to the end.
+ *
+ * Insert an object into the diagram.
+ */
+void
+ld_diagram_insert_object (LdDiagram *self, LdDiagramObject *object, gint pos)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self));
+ g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
+
+ if (!g_list_find (self->priv->objects, object))
+ {
+ self->priv->objects =
+ g_list_insert (self->priv->objects, object, pos);
+ g_object_ref (object);
+
+ g_signal_emit (self,
+ LD_DIAGRAM_GET_CLASS (self)->changed_signal, 0);
+ }
+}
+
+/**
+ * ld_diagram_remove_object:
+ * @self: An #LdDiagram object.
+ * @object: The object to be removed.
+ *
+ * Remove an object from the diagram.
+ */
+void
+ld_diagram_remove_object (LdDiagram *self, LdDiagramObject *object)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self));
+ g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
+
+ if (g_list_find (self->priv->objects, object))
+ {
+ ld_diagram_selection_remove (self, object);
+
+ self->priv->objects = g_list_remove (self->priv->objects, object);
+ g_object_unref (object);
+
+ g_signal_emit (self,
+ LD_DIAGRAM_GET_CLASS (self)->changed_signal, 0);
+ }
+}
+
+/**
+ * ld_diagram_get_selection:
+ * @self: An #LdDiagram object.
+ *
+ * Get a list of objects that are currently selected in the diagram.
+ * Do not modify.
+ */
+GList *
+ld_diagram_get_selection (LdDiagram *self)
+{
+ g_return_val_if_fail (LD_IS_DIAGRAM (self), NULL);
+ return self->priv->selection;
+}
+
+/**
+ * ld_diagram_selection_add:
+ * @self: An #LdDiagram object.
+ * @object: The object to be added to the selection.
+ * @pos: The position at which the object is to be inserted.
+ * Negative values will append to the end.
+ *
+ * Add an object to selection.
+ */
+void
+ld_diagram_selection_add (LdDiagram *self, LdDiagramObject *object, gint pos)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self));
+ g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
+
+ g_return_if_fail (g_list_find (self->priv->objects, object) != NULL);
+
+ if (!g_list_find (self->priv->selection, object))
+ {
+ self->priv->selection =
+ g_list_insert (self->priv->selection, object, pos);
+ g_object_ref (object);
+
+ g_signal_emit (self,
+ LD_DIAGRAM_GET_CLASS (self)->selection_changed_signal, 0);
+ }
+}
+
+/**
+ * ld_diagram_selection_remove:
+ * @self: An #LdDiagram object.
+ * @object: The object to be removed from the selection.
+ *
+ * Remove an object from the selection.
+ */
+void
+ld_diagram_selection_remove (LdDiagram *self, LdDiagramObject *object)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self));
+ g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
+
+ if (g_list_find (self->priv->selection, object))
+ {
+ self->priv->selection = g_list_remove (self->priv->selection, object);
+ g_object_unref (object);
+
+ g_signal_emit (self,
+ LD_DIAGRAM_GET_CLASS (self)->selection_changed_signal, 0);
+ }
+}
+
+/**
+ * ld_diagram_select_all:
+ * @self: An #LdDiagram object.
+ *
+ * Include all objects in the document to the selection.
+ */
+void
+ld_diagram_select_all (LdDiagram *self)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self));
+
+ ld_diagram_unselect_all_internal (self);
+
+ self->priv->selection = g_list_copy (self->priv->objects);
+ g_list_foreach (self->priv->selection, (GFunc) g_object_ref, NULL);
+
+ g_signal_emit (self,
+ LD_DIAGRAM_GET_CLASS (self)->selection_changed_signal, 0);
+}
+
+/**
+ * ld_diagram_unselect_all:
+ * @self: An #LdDiagram object.
+ *
+ * Remove all objects from the current selection.
+ */
+void
+ld_diagram_unselect_all (LdDiagram *self)
+{
+ g_return_if_fail (LD_IS_DIAGRAM (self));
+
+ ld_diagram_unselect_all_internal (self);
+
+ g_signal_emit (self,
+ LD_DIAGRAM_GET_CLASS (self)->selection_changed_signal, 0);
+}
+
+static void
+ld_diagram_unselect_all_internal (LdDiagram *self)
+{
+ g_list_foreach (self->priv->selection, (GFunc) g_object_unref, NULL);
+ g_list_free (self->priv->selection);
+ self->priv->selection = NULL;
+}
diff --git a/liblogdiag/ld-diagram.h b/liblogdiag/ld-diagram.h
new file mode 100644
index 0000000..f364189
--- /dev/null
+++ b/liblogdiag/ld-diagram.h
@@ -0,0 +1,98 @@
+/*
+ * ld-diagram.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_DIAGRAM_H__
+#define __LD_DIAGRAM_H__
+
+G_BEGIN_DECLS
+
+
+#define LD_TYPE_DIAGRAM (ld_diagram_get_type ())
+#define LD_DIAGRAM(obj) (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), LD_TYPE_DIAGRAM, LdDiagram))
+#define LD_DIAGRAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), LD_TYPE_DIAGRAM, LdDiagramClass))
+#define LD_IS_DIAGRAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), LD_TYPE_DIAGRAM))
+#define LD_IS_DIAGRAM_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((klass), LD_TYPE_DIAGRAM))
+#define LD_DIAGRAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), LD_DIAGRAM, LdDiagramClass))
+
+typedef struct _LdDiagram LdDiagram;
+typedef struct _LdDiagramClass LdDiagramClass;
+typedef struct _LdDiagramPrivate LdDiagramPrivate;
+
+
+/**
+ * LdDiagram:
+ *
+ * A diagram object.
+ */
+struct _LdDiagram
+{
+/*< private >*/
+ GObject parent_instance;
+ LdDiagramPrivate *priv;
+};
+
+struct _LdDiagramClass
+{
+/*< private >*/
+ GObjectClass parent_class;
+
+ guint changed_signal;
+ guint selection_changed_signal;
+
+ void (*changed) (LdDiagram *self);
+ void (*selection_changed) (LdDiagram *self);
+};
+
+
+GType ld_diagram_get_type (void) G_GNUC_CONST;
+
+LdDiagram *ld_diagram_new (void);
+void ld_diagram_clear (LdDiagram *self);
+gboolean ld_diagram_load_from_file (LdDiagram *self,
+ const gchar *filename, GError **error);
+gboolean ld_diagram_save_to_file (LdDiagram *self,
+ const gchar *filename, GError **error);
+
+gboolean ld_diagram_get_modified (LdDiagram *self);
+void ld_diagram_set_modified (LdDiagram *self, gboolean value);
+
+GList *ld_diagram_get_objects (LdDiagram *self);
+void ld_diagram_insert_object (LdDiagram *self,
+ LdDiagramObject *object, gint pos);
+void ld_diagram_remove_object (LdDiagram *self,
+ LdDiagramObject *object);
+
+GList *ld_diagram_get_selection (LdDiagram *self);
+void ld_diagram_selection_add (LdDiagram *self,
+ LdDiagramObject *object, gint pos);
+void ld_diagram_selection_remove (LdDiagram *self,
+ LdDiagramObject *object);
+
+void ld_diagram_select_all (LdDiagram *self);
+void ld_diagram_unselect_all (LdDiagram *self);
+
+/*
+GList *ld_diagram_get_connections (LdDiagram *self);
+void ld_diagram_connection_add (LdDiagram *self,
+ LdConnection *connection, gint pos);
+void ld_diagram_connection_remove (LdDiagram *self,
+ LdConnection *connection);
+*/
+
+
+G_END_DECLS
+
+#endif /* ! __LD_DIAGRAM_H__ */
+
diff --git a/liblogdiag/ld-library.c b/liblogdiag/ld-library.c
new file mode 100644
index 0000000..37e2bc9
--- /dev/null
+++ b/liblogdiag/ld-library.c
@@ -0,0 +1,524 @@
+/*
+ * ld-library.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include
+
+#include "liblogdiag.h"
+#include "config.h"
+
+
+/**
+ * SECTION:ld-library
+ * @short_description: A symbol library.
+ * @see_also: #LdSymbol, #LdSymbolCategory
+ *
+ * #LdLibrary is used for loading symbols from their files.
+ */
+
+/*
+ * LdLibraryPrivate:
+ * @lua: State of the scripting language.
+ * @children: Child objects of the library.
+ */
+struct _LdLibraryPrivate
+{
+ LdLua *lua;
+ GSList *children;
+};
+
+static void ld_library_finalize (GObject *gobject);
+
+static LdSymbolCategory *load_category (LdLibrary *self,
+ const gchar *path, const gchar *name);
+static gboolean load_category_cb (const gchar *base,
+ const gchar *filename, gpointer userdata);
+static void load_category_symbol_cb (LdSymbol *symbol, gpointer user_data);
+
+static gchar *read_human_name_from_file (const gchar *filename);
+
+static gboolean foreach_dir (const gchar *path,
+ gboolean (*callback) (const gchar *, const gchar *, gpointer),
+ gpointer userdata, GError **error);
+static gboolean ld_library_load_cb
+ (const gchar *base, const gchar *filename, gpointer userdata);
+
+
+G_DEFINE_TYPE (LdLibrary, ld_library, G_TYPE_OBJECT);
+
+static void
+ld_library_class_init (LdLibraryClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = ld_library_finalize;
+
+/**
+ * LdLibrary::changed:
+ * @library: The library object.
+ *
+ * Contents of the library have changed.
+ */
+ klass->changed_signal = g_signal_new
+ ("changed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+ g_type_class_add_private (klass, sizeof (LdLibraryPrivate));
+}
+
+static void
+ld_library_init (LdLibrary *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self, LD_TYPE_LIBRARY, LdLibraryPrivate);
+
+ self->priv->lua = ld_lua_new ();
+ self->priv->children = NULL;
+}
+
+static void
+ld_library_finalize (GObject *gobject)
+{
+ LdLibrary *self;
+
+ self = LD_LIBRARY (gobject);
+
+ g_object_unref (self->priv->lua);
+
+ g_slist_foreach (self->priv->children, (GFunc) g_object_unref, NULL);
+ g_slist_free (self->priv->children);
+
+ /* Chain up to the parent class. */
+ G_OBJECT_CLASS (ld_library_parent_class)->finalize (gobject);
+}
+
+/**
+ * ld_library_new:
+ *
+ * Create an instance.
+ */
+LdLibrary *
+ld_library_new (void)
+{
+ return g_object_new (LD_TYPE_LIBRARY, NULL);
+}
+
+/*
+ * foreach_dir:
+ *
+ * Call a user-defined function for each file within a directory.
+ */
+static gboolean
+foreach_dir (const gchar *path,
+ gboolean (*callback) (const gchar *, const gchar *, gpointer),
+ gpointer userdata, GError **error)
+{
+ GDir *dir;
+ const gchar *item;
+
+ g_return_val_if_fail (path != NULL, FALSE);
+ g_return_val_if_fail (callback != NULL, FALSE);
+
+ dir = g_dir_open (path, 0, error);
+ if (!dir)
+ return FALSE;
+
+ while ((item = g_dir_read_name (dir)))
+ {
+ gchar *filename;
+
+ filename = g_build_filename (path, item, NULL);
+ if (!callback (item, filename, userdata))
+ break;
+ g_free (filename);
+ }
+ g_dir_close (dir);
+ return TRUE;
+}
+
+/*
+ * LoadCategoryData:
+ *
+ * Data shared between load_category() and load_category_cb().
+ */
+typedef struct
+{
+ LdLibrary *self;
+ LdSymbolCategory *cat;
+}
+LoadCategoryData;
+
+/*
+ * load_category:
+ * @self: An #LdLibrary object.
+ * @path: The path to the category.
+ * @name: The default name of the category.
+ *
+ * Loads a category into the library.
+ */
+static LdSymbolCategory *
+load_category (LdLibrary *self, const gchar *path, const gchar *name)
+{
+ LdSymbolCategory *cat;
+ gchar *icon_file, *category_file;
+ gchar *human_name;
+ LoadCategoryData data;
+
+ g_return_val_if_fail (LD_IS_LIBRARY (self), NULL);
+ g_return_val_if_fail (path != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ if (!g_file_test (path, G_FILE_TEST_IS_DIR))
+ goto load_category_fail_1;
+
+ icon_file = g_build_filename (path, "icon.svg", NULL);
+ if (!g_file_test (icon_file, G_FILE_TEST_IS_REGULAR))
+ {
+ g_warning ("The category in %s has no icon.", path);
+ goto load_category_fail_2;
+ }
+
+ category_file = g_build_filename (path, "category.json", NULL);
+ human_name = read_human_name_from_file (category_file);
+ if (!human_name)
+ human_name = g_strdup (name);
+
+ cat = ld_symbol_category_new (name, human_name);
+ ld_symbol_category_set_image_path (cat, icon_file);
+
+ data.self = self;
+ data.cat = cat;
+ foreach_dir (path, load_category_cb, &data, NULL);
+
+ g_free (human_name);
+ g_free (category_file);
+ g_free (icon_file);
+ return cat;
+
+load_category_fail_2:
+ g_free (icon_file);
+load_category_fail_1:
+ return NULL;
+}
+
+/*
+ * load_category_cb:
+ *
+ * Load script files from a directory into a symbol category.
+ */
+static gboolean
+load_category_cb (const gchar *base, const gchar *filename, gpointer userdata)
+{
+ LoadCategoryData *data;
+
+ g_return_val_if_fail (base != NULL, FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (userdata != NULL, FALSE);
+
+ data = (LoadCategoryData *) userdata;
+
+ if (ld_lua_check_file (data->self->priv->lua, filename))
+ ld_lua_load_file (data->self->priv->lua, filename,
+ load_category_symbol_cb, data->cat);
+ return TRUE;
+}
+
+/*
+ * load_category_symbol_cb:
+ *
+ * Insert newly registered symbols into the category.
+ */
+static void
+load_category_symbol_cb (LdSymbol *symbol, gpointer user_data)
+{
+ const gchar *name;
+ LdSymbolCategory *cat;
+ const GSList *children, *iter;
+
+ g_return_if_fail (LD_IS_SYMBOL (symbol));
+ g_return_if_fail (LD_IS_SYMBOL_CATEGORY (user_data));
+
+ cat = LD_SYMBOL_CATEGORY (user_data);
+ name = ld_symbol_get_name (symbol);
+
+ /* Check for name collisions with other symbols. */
+ children = ld_symbol_category_get_children (cat);
+ for (iter = children; iter; iter = iter->next)
+ {
+ if (!LD_IS_SYMBOL (iter->data))
+ continue;
+ if (!strcmp (name, ld_symbol_get_name (LD_SYMBOL (iter->data))))
+ {
+ g_warning ("Attempted to insert multiple '%s' symbols into"
+ " category '%s'.", name, ld_symbol_category_get_name (cat));
+ return;
+ }
+ }
+ ld_symbol_category_insert_child (cat, G_OBJECT (symbol), -1);
+}
+
+/*
+ * read_human_name_from_file:
+ * @filename: Location of the JSON file.
+ *
+ * Read the human name of the processed category.
+ */
+static gchar *
+read_human_name_from_file (const gchar *filename)
+{
+ const gchar *const *lang;
+ JsonParser *parser;
+ JsonNode *root;
+ JsonObject *object;
+ GError *error;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ parser = json_parser_new ();
+ error = NULL;
+ if (!json_parser_load_from_file (parser, filename, &error))
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ goto read_human_name_from_file_end;
+ }
+
+ root = json_parser_get_root (parser);
+ if (!JSON_NODE_HOLDS_OBJECT (root))
+ {
+ g_warning ("Failed to parse '%s': %s", filename,
+ "The root node is not an object.");
+ goto read_human_name_from_file_end;
+ }
+
+ object = json_node_get_object (root);
+ for (lang = g_get_language_names (); *lang; lang++)
+ {
+ const gchar *member;
+
+ if (!json_object_has_member (object, *lang))
+ continue;
+ member = json_object_get_string_member (object, *lang);
+
+ if (member != NULL)
+ {
+ gchar *result;
+
+ result = g_strdup (member);
+ g_object_unref (parser);
+ return result;
+ }
+ }
+
+read_human_name_from_file_end:
+ g_object_unref (parser);
+ return NULL;
+}
+
+/*
+ * LibraryLoadData:
+ *
+ * Data shared between ld_library_load() and ld_library_load_cb().
+ */
+typedef struct
+{
+ LdLibrary *self;
+ gboolean changed;
+}
+LibraryLoadData;
+
+/**
+ * ld_library_load:
+ * @self: An #LdLibrary object.
+ * @directory: A directory to be loaded.
+ *
+ * Load the contents of a directory into the library.
+ */
+gboolean
+ld_library_load (LdLibrary *self, const gchar *directory)
+{
+ LibraryLoadData data;
+
+ g_return_val_if_fail (LD_IS_LIBRARY (self), FALSE);
+ g_return_val_if_fail (directory != NULL, FALSE);
+
+ data.self = self;
+ data.changed = FALSE;
+ foreach_dir (directory, ld_library_load_cb, &data, NULL);
+
+ if (data.changed)
+ g_signal_emit (self, LD_LIBRARY_GET_CLASS (self)->changed_signal, 0);
+
+ return TRUE;
+}
+
+/*
+ * ld_library_load_cb:
+ *
+ * A callback that's called for each file in the root directory.
+ */
+static gboolean
+ld_library_load_cb (const gchar *base, const gchar *filename, gpointer userdata)
+{
+ LdSymbolCategory *cat;
+ LibraryLoadData *data;
+
+ g_return_val_if_fail (base != NULL, FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (userdata != NULL, FALSE);
+
+ data = (LibraryLoadData *) userdata;
+
+ cat = load_category (data->self, filename, base);
+ if (cat)
+ ld_library_insert_child (data->self, G_OBJECT (cat), -1);
+
+ data->changed = TRUE;
+ return TRUE;
+}
+
+/**
+ * ld_library_find_symbol:
+ * @self: An #LdLibrary object.
+ * @identifier: An identifier of the symbol to be searched for.
+ *
+ * Search for a symbol in the library.
+ *
+ * Return value: A symbol object if found, NULL otherwise.
+ */
+/* XXX: With this level of indentation, this function is really ugly. */
+LdSymbol *
+ld_library_find_symbol (LdLibrary *self, const gchar *identifier)
+{
+ gchar **id_el_start, **id_el;
+ const GSList *list, *list_el;
+
+ g_return_val_if_fail (LD_IS_LIBRARY (self), NULL);
+ g_return_val_if_fail (identifier != NULL, NULL);
+
+ id_el_start = g_strsplit (identifier, LD_LIBRARY_IDENTIFIER_SEPARATOR, 0);
+ if (!id_el_start)
+ return NULL;
+
+ list = ld_library_get_children (self);
+ for (id_el = id_el_start; id_el[0]; id_el++)
+ {
+ LdSymbolCategory *cat;
+ LdSymbol *symbol;
+ gboolean found = FALSE;
+
+ for (list_el = list; list_el; list_el = g_slist_next (list_el))
+ {
+ /* If the current identifier element is a category (not last)
+ * and this list element is a category.
+ */
+ if (id_el[1] && LD_IS_SYMBOL_CATEGORY (list_el->data))
+ {
+ cat = LD_SYMBOL_CATEGORY (list_el->data);
+ if (strcmp (id_el[0], ld_symbol_category_get_name (cat)))
+ continue;
+
+ list = ld_symbol_category_get_children (cat);
+ found = TRUE;
+ break;
+ }
+ /* If the current identifier element is a symbol (last)
+ * and this list element is a symbol.
+ */
+ else if (!id_el[1] && LD_IS_SYMBOL (list_el->data))
+ {
+ symbol = LD_SYMBOL (list_el->data);
+ if (strcmp (id_el[0], ld_symbol_get_name (symbol)))
+ continue;
+
+ g_strfreev (id_el_start);
+ return symbol;
+ }
+ }
+
+ if (!found)
+ break;
+ }
+ g_strfreev (id_el_start);
+ return NULL;
+}
+
+/**
+ * ld_library_clear:
+ * @self: An #LdLibrary object.
+ *
+ * Clear all the contents.
+ */
+void
+ld_library_clear (LdLibrary *self)
+{
+ g_return_if_fail (LD_IS_LIBRARY (self));
+
+ g_slist_foreach (self->priv->children, (GFunc) g_object_unref, NULL);
+ g_slist_free (self->priv->children);
+ self->priv->children = NULL;
+
+ g_signal_emit (self,
+ LD_LIBRARY_GET_CLASS (self)->changed_signal, 0);
+}
+
+/**
+ * ld_library_insert_child:
+ * @self: An #LdLibrary object.
+ * @child: The child to be inserted.
+ * @pos: The position at which the child will be inserted.
+ * Negative values will append to the end of list.
+ *
+ * Insert a child into the library.
+ */
+void
+ld_library_insert_child (LdLibrary *self, GObject *child, gint pos)
+{
+ g_return_if_fail (LD_IS_LIBRARY (self));
+ g_return_if_fail (G_IS_OBJECT (child));
+
+ g_object_ref (child);
+ self->priv->children = g_slist_insert (self->priv->children, child, pos);
+}
+
+/**
+ * ld_library_remove_child:
+ * @self: An #LdLibrary object.
+ * @child: The child to be removed.
+ *
+ * Remove a child from the library.
+ */
+void
+ld_library_remove_child (LdLibrary *self, GObject *child)
+{
+ g_return_if_fail (LD_IS_LIBRARY (self));
+ g_return_if_fail (G_IS_OBJECT (child));
+
+ if (g_slist_find (self->priv->children, child))
+ {
+ g_object_unref (child);
+ self->priv->children = g_slist_remove (self->priv->children, child);
+ }
+}
+
+/**
+ * ld_library_get_children:
+ * @self: An #LdLibrary object.
+ *
+ * Return value: The internal list of children. Do not modify.
+ */
+const GSList *
+ld_library_get_children (LdLibrary *self)
+{
+ g_return_val_if_fail (LD_IS_LIBRARY (self), NULL);
+ return self->priv->children;
+}
+
diff --git a/liblogdiag/ld-library.h b/liblogdiag/ld-library.h
new file mode 100644
index 0000000..26521ed
--- /dev/null
+++ b/liblogdiag/ld-library.h
@@ -0,0 +1,73 @@
+/*
+ * ld-library.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_LIBRARY_H__
+#define __LD_LIBRARY_H__
+
+G_BEGIN_DECLS
+
+
+#define LD_TYPE_LIBRARY (ld_library_get_type ())
+#define LD_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), LD_TYPE_LIBRARY, LdLibrary))
+#define LD_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), LD_TYPE_LIBRARY, LdLibraryClass))
+#define LD_IS_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), LD_TYPE_LIBRARY))
+#define LD_IS_LIBRARY_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((klass), LD_TYPE_LIBRARY))
+#define LD_LIBRARY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), LD_LIBRARY, LdLibraryClass))
+
+typedef struct _LdLibrary LdLibrary;
+typedef struct _LdLibraryPrivate LdLibraryPrivate;
+typedef struct _LdLibraryClass LdLibraryClass;
+
+
+struct _LdLibrary
+{
+/*< private >*/
+ GObject parent_instance;
+ LdLibraryPrivate *priv;
+};
+
+struct _LdLibraryClass
+{
+/*< private >*/
+ GObjectClass parent_class;
+
+ guint changed_signal;
+};
+
+
+/**
+ * LD_LIBRARY_IDENTIFIER_SEPARATOR:
+ *
+ * Defines a string that separates categories and symbols in identifiers.
+ */
+#define LD_LIBRARY_IDENTIFIER_SEPARATOR "/"
+
+
+GType ld_library_get_type (void) G_GNUC_CONST;
+
+LdLibrary *ld_library_new (void);
+gboolean ld_library_load (LdLibrary *self, const gchar *directory);
+LdSymbol *ld_library_find_symbol (LdLibrary *self, const gchar *identifier);
+void ld_library_clear (LdLibrary *self);
+
+void ld_library_insert_child (LdLibrary *self, GObject *child, gint pos);
+void ld_library_remove_child (LdLibrary *self, GObject *child);
+const GSList *ld_library_get_children (LdLibrary *self);
+
+
+G_END_DECLS
+
+#endif /* ! __LD_LIBRARY_H__ */
+
diff --git a/liblogdiag/ld-lua-private.h b/liblogdiag/ld-lua-private.h
new file mode 100644
index 0000000..7d6943a
--- /dev/null
+++ b/liblogdiag/ld-lua-private.h
@@ -0,0 +1,26 @@
+/*
+ * ld-lua-private.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_LUA_PRIVATE_H__
+#define __LD_LUA_PRIVATE_H__
+
+G_BEGIN_DECLS
+
+
+/*< private_header >*/
+
+void ld_lua_private_unregister (LdLua *self, LdLuaSymbol *symbol);
+void ld_lua_private_draw (LdLua *self, LdLuaSymbol *symbol, cairo_t *cr);
+
+
+G_END_DECLS
+
+#endif /* ! __LD_LUA_PRIVATE_H__ */
+
diff --git a/liblogdiag/ld-lua-symbol-private.h b/liblogdiag/ld-lua-symbol-private.h
new file mode 100644
index 0000000..83bc646
--- /dev/null
+++ b/liblogdiag/ld-lua-symbol-private.h
@@ -0,0 +1,40 @@
+/*
+ * ld-lua-symbol-private.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_LUA_SYMBOL_PRIVATE_H__
+#define __LD_LUA_SYMBOL_PRIVATE_H__
+
+G_BEGIN_DECLS
+
+
+/*< private_header >*/
+
+/*
+ * LdLuaSymbolPrivate:
+ * @lua: Parent #LdLua object.
+ * @name: Name of this symbol.
+ * @human_name: Localized human name of this symbol.
+ * @area: Area of this symbol.
+ * @terminals: Terminals of this symbol.
+ */
+struct _LdLuaSymbolPrivate
+{
+ LdLua *lua;
+ gchar *name;
+ gchar *human_name;
+ LdRectangle area;
+ LdPointArray *terminals;
+};
+
+
+G_END_DECLS
+
+#endif /* ! __LD_LUA_SYMBOL_PRIVATE_H__ */
+
diff --git a/liblogdiag/ld-lua-symbol.c b/liblogdiag/ld-lua-symbol.c
new file mode 100644
index 0000000..27a6279
--- /dev/null
+++ b/liblogdiag/ld-lua-symbol.c
@@ -0,0 +1,138 @@
+/*
+ * ld-lua-symbol.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include "liblogdiag.h"
+#include "config.h"
+
+#include "ld-lua-private.h"
+#include "ld-lua-symbol-private.h"
+
+
+/**
+ * SECTION:ld-lua-symbol
+ * @short_description: A symbol.
+ * @see_also: #LdSymbol
+ *
+ * #LdLuaSymbol is an implementation of #LdSymbol.
+ */
+
+static void ld_lua_symbol_finalize (GObject *gobject);
+
+static const gchar *ld_lua_symbol_real_get_name (LdSymbol *symbol);
+static const gchar *ld_lua_symbol_real_get_human_name (LdSymbol *symbol);
+static void ld_lua_symbol_real_get_area (LdSymbol *symbol, LdRectangle *area);
+static const LdPointArray *ld_lua_symbol_real_get_terminals (LdSymbol *symbol);
+static void ld_lua_symbol_real_draw (LdSymbol *symbol, cairo_t *cr);
+
+
+G_DEFINE_TYPE (LdLuaSymbol, ld_lua_symbol, LD_TYPE_SYMBOL);
+
+static void
+ld_lua_symbol_class_init (LdLuaSymbolClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = ld_lua_symbol_finalize;
+
+ klass->parent_class.get_name = ld_lua_symbol_real_get_name;
+ klass->parent_class.get_human_name = ld_lua_symbol_real_get_human_name;
+ klass->parent_class.get_area = ld_lua_symbol_real_get_area;
+ klass->parent_class.get_terminals = ld_lua_symbol_real_get_terminals;
+ klass->parent_class.draw = ld_lua_symbol_real_draw;
+
+ g_type_class_add_private (klass, sizeof (LdLuaSymbolPrivate));
+}
+
+static void
+ld_lua_symbol_init (LdLuaSymbol *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self, LD_TYPE_LUA_SYMBOL, LdLuaSymbolPrivate);
+}
+
+static void
+ld_lua_symbol_finalize (GObject *gobject)
+{
+ LdLuaSymbol *self;
+
+ self = LD_LUA_SYMBOL (gobject);
+
+ if (self->priv->lua)
+ {
+ ld_lua_private_unregister (self->priv->lua, self);
+ g_object_unref (self->priv->lua);
+ }
+
+ if (self->priv->name)
+ g_free (self->priv->name);
+ if (self->priv->human_name)
+ g_free (self->priv->human_name);
+
+ if (self->priv->terminals)
+ ld_point_array_free (self->priv->terminals);
+
+ /* Chain up to the parent class. */
+ G_OBJECT_CLASS (ld_lua_symbol_parent_class)->finalize (gobject);
+}
+
+
+static const gchar *
+ld_lua_symbol_real_get_name (LdSymbol *symbol)
+{
+ g_return_val_if_fail (LD_IS_LUA_SYMBOL (symbol), NULL);
+ return LD_LUA_SYMBOL (symbol)->priv->name;
+}
+
+static const gchar *
+ld_lua_symbol_real_get_human_name (LdSymbol *symbol)
+{
+ g_return_val_if_fail (LD_IS_LUA_SYMBOL (symbol), NULL);
+ return LD_LUA_SYMBOL (symbol)->priv->human_name;
+}
+
+static void
+ld_lua_symbol_real_get_area (LdSymbol *symbol, LdRectangle *area)
+{
+ LdLuaSymbol *self;
+
+ g_return_if_fail (LD_IS_LUA_SYMBOL (symbol));
+ g_return_if_fail (area != NULL);
+
+ self = LD_LUA_SYMBOL (symbol);
+ *area = self->priv->area;
+}
+
+static const LdPointArray *
+ld_lua_symbol_real_get_terminals (LdSymbol *symbol)
+{
+ LdLuaSymbol *self;
+
+ g_return_val_if_fail (LD_IS_LUA_SYMBOL (symbol), NULL);
+
+ self = LD_LUA_SYMBOL (symbol);
+ return self->priv->terminals;
+}
+
+static void
+ld_lua_symbol_real_draw (LdSymbol *symbol, cairo_t *cr)
+{
+ LdLuaSymbol *self;
+
+ g_return_if_fail (LD_IS_LUA_SYMBOL (symbol));
+ g_return_if_fail (cr != NULL);
+
+ self = LD_LUA_SYMBOL (symbol);
+
+ cairo_save (cr);
+ ld_lua_private_draw (self->priv->lua, self, cr);
+ cairo_restore (cr);
+}
+
diff --git a/liblogdiag/ld-lua-symbol.h b/liblogdiag/ld-lua-symbol.h
new file mode 100644
index 0000000..5f68b59
--- /dev/null
+++ b/liblogdiag/ld-lua-symbol.h
@@ -0,0 +1,60 @@
+/*
+ * ld-lua-symbol.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_LUA_SYMBOL_H__
+#define __LD_LUA_SYMBOL_H__
+
+G_BEGIN_DECLS
+
+
+#define LD_TYPE_LUA_SYMBOL (ld_lua_symbol_get_type ())
+#define LD_LUA_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), LD_TYPE_LUA_SYMBOL, LdLuaSymbol))
+#define LD_LUA_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), LD_TYPE_LUA_SYMBOL, LdLuaSymbolClass))
+#define LD_IS_LUA_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), LD_TYPE_LUA_SYMBOL))
+#define LD_IS_LUA_SYMBOL_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((klass), LD_TYPE_LUA_SYMBOL))
+#define LD_LUA_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), LD_LUA_SYMBOL, LdLuaSymbolClass))
+
+typedef struct _LdLuaSymbol LdLuaSymbol;
+typedef struct _LdLuaSymbolPrivate LdLuaSymbolPrivate;
+typedef struct _LdLuaSymbolClass LdLuaSymbolClass;
+
+
+/**
+ * LdLuaSymbol:
+ */
+struct _LdLuaSymbol
+{
+/*< private >*/
+ LdSymbol parent_instance;
+ LdLuaSymbolPrivate *priv;
+};
+
+/**
+ * LdLuaSymbolClass:
+ * @parent_class: The parent class.
+ */
+struct _LdLuaSymbolClass
+{
+ LdSymbolClass parent_class;
+};
+
+
+GType ld_lua_symbol_get_type (void) G_GNUC_CONST;
+
+
+G_END_DECLS
+
+#endif /* ! __LD_LUA_SYMBOL_H__ */
+
diff --git a/liblogdiag/ld-lua.c b/liblogdiag/ld-lua.c
new file mode 100644
index 0000000..47a41b5
--- /dev/null
+++ b/liblogdiag/ld-lua.c
@@ -0,0 +1,808 @@
+/*
+ * ld-lua.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include
+#include
+#include
+
+#include "liblogdiag.h"
+#include "config.h"
+
+#include "ld-lua-private.h"
+#include "ld-lua-symbol-private.h"
+
+
+/**
+ * SECTION:ld-lua
+ * @short_description: Lua symbol engine.
+ * @see_also: #LdLuaSymbol
+ *
+ * #LdLua is a symbol engine that uses Lua scripts to manage symbols.
+ */
+
+/*
+ * LdLuaPrivate:
+ * @L: Lua state.
+ *
+ * The library contains the real function for rendering.
+ */
+struct _LdLuaPrivate
+{
+ lua_State *L;
+};
+
+/* registry.logdiag_symbols
+ * -> A table indexed by pointers to LdLuaSymbol objects
+ * registry.logdiag_symbols.object.render(cr)
+ * -> The rendering function
+ */
+
+#define LD_LUA_LIBRARY_NAME "logdiag"
+#define LD_LUA_DATA_INDEX LD_LUA_LIBRARY_NAME "_data"
+#define LD_LUA_SYMBOLS_INDEX LD_LUA_LIBRARY_NAME "_symbols"
+
+/*
+ * LdLuaData:
+ * @self: A reference to self.
+ * @load_callback: A callback for newly registered symbols.
+ * @load_user_data: User data to be passed to the callback.
+ *
+ * Full user data to be stored in Lua registry.
+ */
+typedef struct _LdLuaData LdLuaData;
+
+struct _LdLuaData
+{
+ LdLua *self;
+ LdLuaLoadCallback load_callback;
+ gpointer load_user_data;
+};
+
+typedef struct _LdLuaDrawData LdLuaDrawData;
+
+struct _LdLuaDrawData
+{
+ LdLuaSymbol *symbol;
+ cairo_t *cr;
+ unsigned save_count;
+};
+
+static void ld_lua_finalize (GObject *gobject);
+
+static void *ld_lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize);
+
+static int ld_lua_private_draw_cb (lua_State *L);
+static int ld_lua_private_unregister_cb (lua_State *L);
+
+static int ld_lua_logdiag_register (lua_State *L);
+static int process_registration (lua_State *L);
+static gchar *get_translation (lua_State *L, int index);
+static gboolean read_symbol_area (lua_State *L, int index, LdRectangle *area);
+static gboolean read_terminals (lua_State *L, int index,
+ LdPointArray **terminals);
+
+static void push_cairo_object (lua_State *L, LdLuaDrawData *draw_data);
+static gdouble get_cairo_scale (cairo_t *cr);
+static int ld_lua_cairo_save (lua_State *L);
+static int ld_lua_cairo_restore (lua_State *L);
+static int ld_lua_cairo_get_line_width (lua_State *L);
+static int ld_lua_cairo_set_line_width (lua_State *L);
+static int ld_lua_cairo_move_to (lua_State *L);
+static int ld_lua_cairo_line_to (lua_State *L);
+static int ld_lua_cairo_curve_to (lua_State *L);
+static int ld_lua_cairo_arc (lua_State *L);
+static int ld_lua_cairo_arc_negative (lua_State *L);
+static int ld_lua_cairo_new_path (lua_State *L);
+static int ld_lua_cairo_new_sub_path (lua_State *L);
+static int ld_lua_cairo_close_path (lua_State *L);
+static int ld_lua_cairo_stroke (lua_State *L);
+static int ld_lua_cairo_stroke_preserve (lua_State *L);
+static int ld_lua_cairo_fill (lua_State *L);
+static int ld_lua_cairo_fill_preserve (lua_State *L);
+static int ld_lua_cairo_clip (lua_State *L);
+static int ld_lua_cairo_clip_preserve (lua_State *L);
+
+
+static luaL_Reg ld_lua_logdiag_lib[] =
+{
+ {"register", ld_lua_logdiag_register},
+ {NULL, NULL}
+};
+
+static luaL_Reg ld_lua_cairo_table[] =
+{
+ {"save", ld_lua_cairo_save},
+ {"restore", ld_lua_cairo_restore},
+ {"get_line_width", ld_lua_cairo_get_line_width},
+ {"set_line_width", ld_lua_cairo_set_line_width},
+ {"move_to", ld_lua_cairo_move_to},
+ {"line_to", ld_lua_cairo_line_to},
+ {"curve_to", ld_lua_cairo_curve_to},
+ {"arc", ld_lua_cairo_arc},
+ {"arc_negative", ld_lua_cairo_arc_negative},
+ {"new_path", ld_lua_cairo_new_path},
+ {"new_sub_path", ld_lua_cairo_new_sub_path},
+ {"close_path", ld_lua_cairo_close_path},
+ {"stroke", ld_lua_cairo_stroke},
+ {"stroke_preserve", ld_lua_cairo_stroke_preserve},
+ {"fill", ld_lua_cairo_fill},
+ {"fill_preserve", ld_lua_cairo_fill_preserve},
+ {"clip", ld_lua_cairo_clip},
+ {"clip_preserve", ld_lua_cairo_clip_preserve},
+ {NULL, NULL}
+};
+
+
+/* ===== Generic =========================================================== */
+
+G_DEFINE_TYPE (LdLua, ld_lua, G_TYPE_OBJECT);
+
+static void
+ld_lua_class_init (LdLuaClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = ld_lua_finalize;
+
+ g_type_class_add_private (klass, sizeof (LdLuaPrivate));
+}
+
+static void
+ld_lua_init (LdLua *self)
+{
+ lua_State *L;
+ LdLuaData *ud;
+
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self, LD_TYPE_LUA, LdLuaPrivate);
+
+ L = self->priv->L = lua_newstate (ld_lua_alloc, NULL);
+ g_return_if_fail (L != NULL);
+
+ /* TODO: lua_atpanic () */
+
+ /* Load some safe libraries. */
+ lua_pushcfunction (L, luaopen_string);
+ lua_call (L, 0, 0);
+
+ lua_pushcfunction (L, luaopen_table);
+ lua_call (L, 0, 0);
+
+ lua_pushcfunction (L, luaopen_math);
+ lua_call (L, 0, 0);
+
+ /* Load the application library. */
+ luaL_register (L, LD_LUA_LIBRARY_NAME, ld_lua_logdiag_lib);
+
+ /* Store user data to the registry. */
+ ud = lua_newuserdata (L, sizeof (LdLuaData));
+ ud->self = self;
+ ud->load_callback = NULL;
+ ud->load_user_data = NULL;
+
+ lua_setfield (L, LUA_REGISTRYINDEX, LD_LUA_DATA_INDEX);
+
+ /* Create an empty symbol table. */
+ lua_newtable (L);
+ lua_setfield (L, LUA_REGISTRYINDEX, LD_LUA_SYMBOLS_INDEX);
+}
+
+static void
+ld_lua_finalize (GObject *gobject)
+{
+ LdLua *self;
+
+ self = LD_LUA (gobject);
+ lua_close (self->priv->L);
+
+ /* Chain up to the parent class. */
+ G_OBJECT_CLASS (ld_lua_parent_class)->finalize (gobject);
+}
+
+/**
+ * ld_lua_new:
+ *
+ * Create an instance of #LdLua.
+ */
+LdLua *
+ld_lua_new (void)
+{
+ return g_object_new (LD_TYPE_LUA, NULL);
+}
+
+static void *
+ld_lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize)
+{
+ if (!nsize)
+ {
+ g_free (ptr);
+ return NULL;
+ }
+ else
+ return g_try_realloc (ptr, nsize);
+}
+
+/**
+ * ld_lua_check_file:
+ * @self: An #LdLua object.
+ * @filename: The file to be checked.
+ *
+ * Check if the given filename can be loaded by #LdLua.
+ */
+gboolean
+ld_lua_check_file (LdLua *self, const gchar *filename)
+{
+ g_return_val_if_fail (LD_IS_LUA (self), FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+
+ return g_str_has_suffix (filename, ".lua")
+ && g_file_test (filename, G_FILE_TEST_IS_REGULAR);
+}
+
+/**
+ * ld_lua_load_file:
+ * @self: An #LdLua object.
+ * @filename: The file to be loaded.
+ * @callback: A callback for newly registered symbols.
+ * The callee is responsible for referencing the symbol.
+ * @user_data: User data to be passed to the callback.
+ *
+ * Loads a file and creates #LdLuaSymbol objects for contained symbols.
+ *
+ * Returns: TRUE if no error has occured, FALSE otherwise.
+ */
+gboolean
+ld_lua_load_file (LdLua *self, const gchar *filename,
+ LdLuaLoadCallback callback, gpointer user_data)
+{
+ gint retval;
+ LdLuaData *ud;
+
+ g_return_val_if_fail (LD_IS_LUA (self), FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (callback != NULL, FALSE);
+
+ /* XXX: If something from the following fails, Lua will call exit(). */
+ lua_getfield (self->priv->L, LUA_REGISTRYINDEX, LD_LUA_DATA_INDEX);
+ ud = lua_touserdata (self->priv->L, -1);
+ lua_pop (self->priv->L, 1);
+ g_return_val_if_fail (ud != NULL, FALSE);
+
+ ud->load_callback = callback;
+ ud->load_user_data = user_data;
+
+ retval = luaL_loadfile (self->priv->L, filename);
+ if (retval)
+ goto ld_lua_lftc_fail;
+
+ retval = lua_pcall (self->priv->L, 0, 0, 0);
+ if (retval)
+ goto ld_lua_lftc_fail;
+
+ ud->load_callback = NULL;
+ ud->load_user_data = NULL;
+ return TRUE;
+
+ld_lua_lftc_fail:
+ g_warning ("Lua error: %s", lua_tostring (self->priv->L, -1));
+ lua_remove (self->priv->L, -1);
+
+ ud->load_callback = NULL;
+ ud->load_user_data = NULL;
+ return FALSE;
+}
+
+/* ===== LdLuaSymbol callbacks ============================================= */
+
+/**
+ * ld_lua_private_draw:
+ * @self: An #LdLua object.
+ * @symbol: A symbol to be drawn.
+ * @cr: A Cairo context to be drawn onto.
+ *
+ * Draw a symbol onto a Cairo context.
+ */
+void
+ld_lua_private_draw (LdLua *self, LdLuaSymbol *symbol, cairo_t *cr)
+{
+ LdLuaDrawData data;
+
+ g_return_if_fail (LD_IS_LUA (self));
+ g_return_if_fail (LD_IS_LUA_SYMBOL (symbol));
+ g_return_if_fail (cr != NULL);
+
+ data.symbol = symbol;
+ data.cr = cr;
+ data.save_count = 0;
+
+ if (lua_cpcall (self->priv->L, ld_lua_private_draw_cb, &data))
+ {
+ g_warning ("Lua error: %s", lua_tostring (self->priv->L, -1));
+ lua_pop (self->priv->L, 1);
+ }
+
+ while (data.save_count--)
+ cairo_restore (cr);
+}
+
+static int
+ld_lua_private_draw_cb (lua_State *L)
+{
+ LdLuaDrawData *data;
+
+ data = lua_touserdata (L, -1);
+
+ /* Retrieve the function for rendering from the registry. */
+ lua_getfield (L, LUA_REGISTRYINDEX, LD_LUA_SYMBOLS_INDEX);
+ lua_pushlightuserdata (L, data->symbol);
+ lua_gettable (L, -2);
+
+ luaL_checktype (L, -1, LUA_TTABLE);
+ lua_getfield (L, -1, "render");
+ luaL_checktype (L, -1, LUA_TFUNCTION);
+
+ /* Call the function do draw the symbol. */
+ push_cairo_object (L, data);
+ lua_pcall (L, 1, 0, 0);
+ return 0;
+}
+
+/**
+ * ld_lua_private_unregister:
+ * @self: An #LdLua object.
+ * @symbol: A symbol to be unregistered.
+ *
+ * Unregister a symbol from the internal Lua state.
+ */
+void
+ld_lua_private_unregister (LdLua *self, LdLuaSymbol *symbol)
+{
+ g_return_if_fail (LD_IS_LUA (self));
+ g_return_if_fail (LD_IS_LUA_SYMBOL (symbol));
+
+ if (lua_cpcall (self->priv->L, ld_lua_private_unregister_cb, symbol))
+ {
+ g_warning ("Lua error: %s", lua_tostring (self->priv->L, -1));
+ lua_pop (self->priv->L, 1);
+ }
+}
+
+static int
+ld_lua_private_unregister_cb (lua_State *L)
+{
+ /* Set the entry in the symbol table to nil. */
+ lua_getfield (L, LUA_REGISTRYINDEX, LD_LUA_SYMBOLS_INDEX);
+ lua_insert (L, -2);
+ lua_pushnil (L);
+ lua_settable (L, -3);
+ return 0;
+}
+
+/* ===== Application library =============================================== */
+
+static int
+ld_lua_logdiag_register (lua_State *L)
+{
+ LdLuaData *ud;
+ LdLuaSymbol *symbol;
+
+ lua_getfield (L, LUA_REGISTRYINDEX, LD_LUA_DATA_INDEX);
+ ud = lua_touserdata (L, -1);
+ lua_pop (L, 1);
+ g_return_val_if_fail (ud != NULL, 0);
+
+ /* Use a protected environment, so script errors won't cause leaking
+ * of the symbol object. Only a failure of the last three function calls
+ * before lua_pcall() may cause the symbol to leak.
+ */
+ lua_checkstack (L, 3);
+ symbol = g_object_new (LD_TYPE_LUA_SYMBOL, NULL);
+
+ lua_pushlightuserdata (L, symbol);
+ lua_pushcclosure (L, process_registration, 1);
+ lua_insert (L, 1);
+
+ /* On the stack, there are function arguments plus the function itself. */
+ if (lua_pcall (L, lua_gettop (L) - 1, 0, 0))
+ {
+ luaL_where (L, 1);
+ lua_insert (L, -2);
+ lua_concat (L, 2);
+
+ g_warning ("Lua symbol registration failed: %s",
+ lua_tostring (L, -1));
+ lua_pushboolean (L, FALSE);
+ }
+ else
+ {
+ /* We don't want an extra LdLua reference either. */
+ symbol->priv->lua = ud->self;
+ g_object_ref (ud->self);
+
+ ud->load_callback (LD_SYMBOL (symbol), ud->load_user_data);
+ lua_pushboolean (L, TRUE);
+ }
+ g_object_unref (symbol);
+
+ return 1;
+}
+
+/*
+ * process_registration:
+ * @L: A Lua state.
+ *
+ * Parse arguments, write them to a symbol object and register the object.
+ */
+static int
+process_registration (lua_State *L)
+{
+ LdLuaSymbol *symbol;
+ gchar *human_name;
+
+ int i, type, types[] =
+ {LUA_TSTRING, LUA_TTABLE, LUA_TTABLE, LUA_TTABLE, LUA_TFUNCTION};
+ int n_args_needed = sizeof (types) / sizeof (int);
+
+ if (lua_gettop (L) < n_args_needed)
+ return luaL_error (L, "Too few arguments.");
+
+ for (i = 0; i < n_args_needed; i++)
+ if ((type = lua_type (L, i + 1)) != types[i])
+ return luaL_error (L, "Bad type of argument #%d."
+ " Expected %s, got %s.", i + 1,
+ lua_typename (L, types[i]), lua_typename (L, type));
+
+ symbol = LD_LUA_SYMBOL (lua_touserdata (L, lua_upvalueindex (1)));
+ symbol->priv->name = g_strdup (lua_tostring (L, 1));
+
+ human_name = get_translation (L, 2);
+ if (!human_name)
+ human_name = g_strdup (symbol->priv->name);
+ symbol->priv->human_name = human_name;
+
+ if (!read_symbol_area (L, 3, &symbol->priv->area))
+ return luaL_error (L, "Malformed symbol area array.");
+ if (!read_terminals (L, 4, &symbol->priv->terminals))
+ return luaL_error (L, "Malformed terminals array.");
+
+ lua_getfield (L, LUA_REGISTRYINDEX, LD_LUA_SYMBOLS_INDEX);
+ lua_pushlightuserdata (L, symbol);
+
+ lua_newtable (L);
+ lua_pushvalue (L, 5);
+ lua_setfield (L, -2, "render");
+
+ lua_settable (L, -3);
+ return 0;
+}
+
+/*
+ * get_translation:
+ * @L: A Lua state.
+ * @index: Stack index of the table.
+ *
+ * Select an applicable translation from a table.
+ * The return value has to be freed with g_free().
+ *
+ * Return value: The translation, if found. If none was found, returns NULL.
+ */
+static gchar *
+get_translation (lua_State *L, int index)
+{
+ const gchar *const *lang;
+ gchar *result;
+
+ for (lang = g_get_language_names (); *lang; lang++)
+ {
+ lua_getfield (L, 2, *lang);
+ if (lua_isstring (L, -1))
+ {
+ result = g_strdup (lua_tostring (L, -1));
+ lua_pop (L, 1);
+ return result;
+ }
+ lua_pop (L, 1);
+ }
+ return NULL;
+}
+
+/*
+ * read_symbol_area:
+ * @L: A Lua state.
+ * @index: Stack index of the table.
+ * @area: Where the area will be returned.
+ *
+ * Read a symbol area from a Lua table.
+ *
+ * Return value: TRUE on success, FALSE on failure.
+ */
+static gboolean
+read_symbol_area (lua_State *L, int index, LdRectangle *area)
+{
+ lua_Number x1, x2, y1, y2;
+
+ if (lua_objlen (L, index) != 4)
+ return FALSE;
+
+ lua_rawgeti (L, index, 1);
+ if (!lua_isnumber (L, -1))
+ return FALSE;
+ x1 = lua_tonumber (L, -1);
+
+ lua_rawgeti (L, index, 2);
+ if (!lua_isnumber (L, -1))
+ return FALSE;
+ y1 = lua_tonumber (L, -1);
+
+ lua_rawgeti (L, index, 3);
+ if (!lua_isnumber (L, -1))
+ return FALSE;
+ x2 = lua_tonumber (L, -1);
+
+ lua_rawgeti (L, index, 4);
+ if (!lua_isnumber (L, -1))
+ return FALSE;
+ y2 = lua_tonumber (L, -1);
+
+ area->x = MIN (x1, x2);
+ area->y = MIN (y1, y2);
+ area->width = ABS (x2 - x1);
+ area->height = ABS (y2 - y1);
+
+ lua_pop (L, 4);
+ return TRUE;
+}
+
+/*
+ * read_terminals:
+ * @L: A Lua state.
+ * @index: Stack index of the table.
+ * @area: Where the point array will be returned.
+ *
+ * Read symbol terminals from a Lua table.
+ *
+ * Return value: TRUE on success, FALSE on failure.
+ */
+static gboolean
+read_terminals (lua_State *L, int index, LdPointArray **terminals)
+{
+ LdPointArray *points;
+ size_t num_points;
+ unsigned i = 0;
+
+ num_points = lua_objlen (L, index);
+ points = ld_point_array_new (num_points);
+
+ lua_pushnil (L);
+ while (lua_next (L, index) != 0)
+ {
+ g_assert (i < num_points);
+
+ if (!lua_istable (L, -1) || lua_objlen (L, -1) != 2)
+ goto read_terminals_fail;
+
+ lua_rawgeti (L, -1, 1);
+ if (!lua_isnumber (L, -1))
+ goto read_terminals_fail;
+ points->points[i].x = lua_tonumber (L, -1);
+ lua_pop (L, 1);
+
+ lua_rawgeti (L, -1, 2);
+ if (!lua_isnumber (L, -1))
+ goto read_terminals_fail;
+ points->points[i].y = lua_tonumber (L, -1);
+
+ lua_pop (L, 2);
+ i++;
+ }
+ *terminals = points;
+ return TRUE;
+
+read_terminals_fail:
+ ld_point_array_free (points);
+ *terminals = NULL;
+ return FALSE;
+}
+
+
+/* ===== Cairo ============================================================= */
+
+static void
+push_cairo_object (lua_State *L, LdLuaDrawData *draw_data)
+{
+ luaL_Reg *fn;
+
+ /* Create a table. */
+ lua_newtable (L);
+
+ /* Add methods. */
+ /* XXX: The light user data pointer gets invalid after the end of
+ * "render" function invocation. If the script stores the "cr" object
+ * in some global variable and then tries to reuse it the next time,
+ * the application may go SIGSEGV.
+ *
+ * The solution is creating a full user data instead, referencing
+ * the cairo object and dereferencing it upon garbage collection
+ * of the user data object.
+ */
+ for (fn = ld_lua_cairo_table; fn->name; fn++)
+ {
+ lua_pushlightuserdata (L, draw_data);
+ lua_pushcclosure (L, fn->func, 1);
+ lua_setfield (L, -2, fn->name);
+ }
+}
+
+static gdouble
+get_cairo_scale (cairo_t *cr)
+{
+ double dx = 1, dy = 0;
+
+ cairo_user_to_device_distance (cr, &dx, &dy);
+ return dx;
+}
+
+#define LD_LUA_CAIRO_TRIVIAL(name) \
+static int \
+ld_lua_cairo_ ## name (lua_State *L) \
+{ \
+ LdLuaDrawData *data; \
+ data = lua_touserdata (L, lua_upvalueindex (1)); \
+ cairo_ ## name (data->cr); \
+ return 0; \
+}
+
+LD_LUA_CAIRO_TRIVIAL (new_path)
+LD_LUA_CAIRO_TRIVIAL (new_sub_path)
+LD_LUA_CAIRO_TRIVIAL (close_path)
+
+LD_LUA_CAIRO_TRIVIAL (stroke)
+LD_LUA_CAIRO_TRIVIAL (stroke_preserve)
+LD_LUA_CAIRO_TRIVIAL (fill)
+LD_LUA_CAIRO_TRIVIAL (fill_preserve)
+LD_LUA_CAIRO_TRIVIAL (clip)
+LD_LUA_CAIRO_TRIVIAL (clip_preserve)
+
+static int
+ld_lua_cairo_save (lua_State *L)
+{
+ LdLuaDrawData *data;
+
+ data = lua_touserdata (L, lua_upvalueindex (1));
+ if (data->save_count + 1)
+ {
+ data->save_count++;
+ cairo_save (data->cr);
+ }
+ return 0;
+}
+
+static int
+ld_lua_cairo_restore (lua_State *L)
+{
+ LdLuaDrawData *data;
+
+ data = lua_touserdata (L, lua_upvalueindex (1));
+ if (data->save_count)
+ {
+ data->save_count--;
+ cairo_restore (data->cr);
+ }
+ return 0;
+}
+
+static int
+ld_lua_cairo_get_line_width (lua_State *L)
+{
+ LdLuaDrawData *data;
+
+ data = lua_touserdata (L, lua_upvalueindex (1));
+ lua_pushnumber (L, cairo_get_line_width (data->cr)
+ * get_cairo_scale (data->cr));
+ return 1;
+}
+
+static int
+ld_lua_cairo_set_line_width (lua_State *L)
+{
+ LdLuaDrawData *data;
+
+ data = lua_touserdata (L, lua_upvalueindex (1));
+ cairo_set_line_width (data->cr, luaL_checknumber (L, 1)
+ / get_cairo_scale (data->cr));
+ return 0;
+}
+
+static int
+ld_lua_cairo_move_to (lua_State *L)
+{
+ LdLuaDrawData *data;
+ lua_Number x, y;
+
+ data = lua_touserdata (L, lua_upvalueindex (1));
+
+ x = luaL_checknumber (L, 1);
+ y = luaL_checknumber (L, 2);
+
+ cairo_move_to (data->cr, x, y);
+ return 0;
+}
+
+static int
+ld_lua_cairo_line_to (lua_State *L)
+{
+ LdLuaDrawData *data;
+ lua_Number x, y;
+
+ data = lua_touserdata (L, lua_upvalueindex (1));
+
+ x = luaL_checknumber (L, 1);
+ y = luaL_checknumber (L, 2);
+
+ cairo_line_to (data->cr, x, y);
+ return 0;
+}
+
+static int
+ld_lua_cairo_curve_to (lua_State *L)
+{
+ LdLuaDrawData *data;
+ lua_Number x1, y1, x2, y2, x3, y3;
+
+ data = lua_touserdata (L, lua_upvalueindex (1));
+
+ x1 = luaL_checknumber (L, 1);
+ y1 = luaL_checknumber (L, 2);
+ x2 = luaL_checknumber (L, 3);
+ y2 = luaL_checknumber (L, 4);
+ x3 = luaL_checknumber (L, 5);
+ y3 = luaL_checknumber (L, 6);
+
+ cairo_curve_to (data->cr, x1, y1, x2, y2, x3, y3);
+ return 0;
+}
+
+static int
+ld_lua_cairo_arc (lua_State *L)
+{
+ LdLuaDrawData *data;
+ lua_Number xc, yc, radius, angle1, angle2;
+
+ data = lua_touserdata (L, lua_upvalueindex (1));
+
+ xc = luaL_checknumber (L, 1);
+ yc = luaL_checknumber (L, 2);
+ radius = luaL_checknumber (L, 3);
+ angle1 = luaL_checknumber (L, 4);
+ angle2 = luaL_checknumber (L, 5);
+
+ cairo_arc (data->cr, xc, yc, radius, angle1, angle2);
+ return 0;
+}
+
+static int
+ld_lua_cairo_arc_negative (lua_State *L)
+{
+ LdLuaDrawData *data;
+ lua_Number xc, yc, radius, angle1, angle2;
+
+ data = lua_touserdata (L, lua_upvalueindex (1));
+
+ xc = luaL_checknumber (L, 1);
+ yc = luaL_checknumber (L, 2);
+ radius = luaL_checknumber (L, 3);
+ angle1 = luaL_checknumber (L, 4);
+ angle2 = luaL_checknumber (L, 5);
+
+ cairo_arc_negative (data->cr, xc, yc, radius, angle1, angle2);
+ return 0;
+}
+
diff --git a/liblogdiag/ld-lua.h b/liblogdiag/ld-lua.h
new file mode 100644
index 0000000..b207d66
--- /dev/null
+++ b/liblogdiag/ld-lua.h
@@ -0,0 +1,70 @@
+/*
+ * ld-lua.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_LUA_H__
+#define __LD_LUA_H__
+
+G_BEGIN_DECLS
+
+
+#define LD_TYPE_LUA (ld_lua_get_type ())
+#define LD_LUA(obj) (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), LD_TYPE_LUA, LdLua))
+#define LD_LUA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), LD_TYPE_LUA, LdLuaClass))
+#define LD_IS_LUA(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), LD_TYPE_LUA))
+#define LD_IS_LUA_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((klass), LD_TYPE_LUA))
+#define LD_LUA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), LD_LUA, LdLuaClass))
+
+typedef struct _LdLua LdLua;
+typedef struct _LdLuaPrivate LdLuaPrivate;
+typedef struct _LdLuaClass LdLuaClass;
+
+
+struct _LdLua
+{
+/*< private >*/
+ GObject parent_instance;
+ LdLuaPrivate *priv;
+};
+
+/* TODO: A virtual superclass, so other engines can be used. */
+struct _LdLuaClass
+{
+/*< private >*/
+ GObjectClass parent_class;
+};
+
+
+/**
+ * LdLuaLoadCallback:
+ * @symbol: The symbol that has been created.
+ * @user_data: User data passed to ld_lua_load_file().
+ *
+ * A callback function that is called when a symbol is created.
+ */
+typedef void (*LdLuaLoadCallback) (LdSymbol *symbol, gpointer user_data);
+
+
+GType ld_lua_get_type (void) G_GNUC_CONST;
+
+LdLua *ld_lua_new (void);
+gboolean ld_lua_check_file (LdLua *self, const gchar *filename);
+gboolean ld_lua_load_file (LdLua *self, const gchar *filename,
+ LdLuaLoadCallback callback, gpointer user_data);
+
+
+G_END_DECLS
+
+#endif /* ! __LD_LUA_H__ */
+
diff --git a/liblogdiag/ld-marshal.c b/liblogdiag/ld-marshal.c
new file mode 100644
index 0000000..ac88836
--- /dev/null
+++ b/liblogdiag/ld-marshal.c
@@ -0,0 +1,88 @@
+
+#include
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#define g_marshal_value_peek_variant(v) g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:OBJECT,OBJECT (ld-marshal.list:1) */
+void
+g_cclosure_user_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_OBJECT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_object (param_values + 2),
+ data2);
+}
+
diff --git a/liblogdiag/ld-marshal.h b/liblogdiag/ld-marshal.h
new file mode 100644
index 0000000..545735a
--- /dev/null
+++ b/liblogdiag/ld-marshal.h
@@ -0,0 +1,20 @@
+
+#ifndef __g_cclosure_user_marshal_MARSHAL_H__
+#define __g_cclosure_user_marshal_MARSHAL_H__
+
+#include
+
+G_BEGIN_DECLS
+
+/* VOID:OBJECT,OBJECT (ld-marshal.list:1) */
+extern void g_cclosure_user_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+G_END_DECLS
+
+#endif /* __g_cclosure_user_marshal_MARSHAL_H__ */
+
diff --git a/liblogdiag/ld-marshal.list b/liblogdiag/ld-marshal.list
new file mode 100644
index 0000000..38076d6
--- /dev/null
+++ b/liblogdiag/ld-marshal.list
@@ -0,0 +1 @@
+VOID:OBJECT,OBJECT
diff --git a/liblogdiag/ld-symbol-category.c b/liblogdiag/ld-symbol-category.c
new file mode 100644
index 0000000..e4b86a9
--- /dev/null
+++ b/liblogdiag/ld-symbol-category.c
@@ -0,0 +1,339 @@
+/*
+ * ld-symbol-category.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include "liblogdiag.h"
+#include "config.h"
+
+
+/**
+ * SECTION:ld-symbol-category
+ * @short_description: A category of symbols.
+ * @see_also: #LdSymbol, #LdLibrary
+ *
+ * #LdSymbolCategory represents a category of #LdSymbol objects.
+ */
+
+/*
+ * LdSymbolCategoryPrivate:
+ * @name: The name of this category.
+ * @image_path: Path to the image for this category.
+ * @children: Children of this category.
+ */
+struct _LdSymbolCategoryPrivate
+{
+ gchar *name;
+ gchar *human_name;
+ gchar *image_path;
+ GSList *children;
+};
+
+enum
+{
+ PROP_0,
+ PROP_NAME,
+ PROP_HUMAN_NAME,
+ PROP_IMAGE_PATH
+};
+
+static void ld_symbol_category_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec);
+static void ld_symbol_category_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec);
+static void ld_symbol_category_finalize (GObject *gobject);
+
+
+G_DEFINE_TYPE (LdSymbolCategory, ld_symbol_category, G_TYPE_OBJECT);
+
+static void
+ld_symbol_category_class_init (LdSymbolCategoryClass *klass)
+{
+ GObjectClass *object_class;
+ GParamSpec *pspec;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = ld_symbol_category_get_property;
+ object_class->set_property = ld_symbol_category_set_property;
+ object_class->finalize = ld_symbol_category_finalize;
+
+/**
+ * LdSymbolCategory:name:
+ *
+ * The name of this symbol category.
+ */
+ pspec = g_param_spec_string ("name", "Name",
+ "The name of this symbol category.",
+ "", G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_NAME, pspec);
+
+/**
+ * LdSymbolCategory:human-name:
+ *
+ * The localized human name of this symbol category.
+ */
+ pspec = g_param_spec_string ("human-name", "Human name",
+ "The localized human name of this symbol category.",
+ "", G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_HUMAN_NAME, pspec);
+
+/**
+ * LdSymbolCategory:image-path:
+ *
+ * Path to an image file representing this category.
+ */
+ pspec = g_param_spec_string ("image-path", "Image path",
+ "Path to an image file representing this category.",
+ "", G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_IMAGE_PATH, pspec);
+
+ g_type_class_add_private (klass, sizeof (LdSymbolCategoryPrivate));
+}
+
+static void
+ld_symbol_category_init (LdSymbolCategory *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (self, LD_TYPE_SYMBOL_CATEGORY, LdSymbolCategoryPrivate);
+}
+
+static void
+ld_symbol_category_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec)
+{
+ LdSymbolCategory *self;
+
+ self = LD_SYMBOL_CATEGORY (object);
+ switch (property_id)
+ {
+ case PROP_NAME:
+ g_value_set_string (value, ld_symbol_category_get_name (self));
+ break;
+ case PROP_HUMAN_NAME:
+ g_value_set_string (value, ld_symbol_category_get_human_name (self));
+ break;
+ case PROP_IMAGE_PATH:
+ g_value_set_string (value, ld_symbol_category_get_image_path (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ld_symbol_category_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ LdSymbolCategory *self;
+
+ self = LD_SYMBOL_CATEGORY (object);
+ switch (property_id)
+ {
+ case PROP_NAME:
+ ld_symbol_category_set_name (self, g_value_get_string (value));
+ break;
+ case PROP_HUMAN_NAME:
+ ld_symbol_category_set_human_name (self, g_value_get_string (value));
+ break;
+ case PROP_IMAGE_PATH:
+ ld_symbol_category_set_image_path (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ld_symbol_category_finalize (GObject *gobject)
+{
+ LdSymbolCategory *self;
+
+ self = LD_SYMBOL_CATEGORY (gobject);
+
+ if (self->priv->name)
+ g_free (self->priv->name);
+ if (self->priv->human_name)
+ g_free (self->priv->human_name);
+ if (self->priv->image_path)
+ g_free (self->priv->image_path);
+
+ g_slist_foreach (self->priv->children, (GFunc) g_object_unref, NULL);
+ g_slist_free (self->priv->children);
+
+ /* Chain up to the parent class. */
+ G_OBJECT_CLASS (ld_symbol_category_parent_class)->finalize (gobject);
+}
+
+
+/**
+ * ld_symbol_category_new:
+ * @name: The name of the new category.
+ * @human_name: The localized human name of the new category.
+ *
+ * Create an instance.
+ */
+LdSymbolCategory *
+ld_symbol_category_new (const gchar *name, const gchar *human_name)
+{
+ LdSymbolCategory *cat;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (human_name != NULL, NULL);
+
+ cat = g_object_new (LD_TYPE_SYMBOL_CATEGORY, NULL);
+ cat->priv->name = g_strdup (name);
+ cat->priv->human_name = g_strdup (human_name);
+
+ return cat;
+}
+
+/**
+ * ld_symbol_category_set_name:
+ * @self: An #LdSymbolCategory object.
+ * @name: The new name for this category.
+ */
+void
+ld_symbol_category_set_name (LdSymbolCategory *self, const gchar *name)
+{
+ g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
+ g_return_if_fail (name != NULL);
+
+ if (self->priv->name)
+ g_free (self->priv->name);
+ self->priv->name = g_strdup (name);
+
+ g_object_notify (G_OBJECT (self), "name");
+}
+
+/**
+ * ld_symbol_category_get_name:
+ * @self: An #LdSymbolCategory object.
+ *
+ * Return the name of this category.
+ */
+const gchar *
+ld_symbol_category_get_name (LdSymbolCategory *self)
+{
+ g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
+ return self->priv->name;
+}
+
+/**
+ * ld_symbol_category_set_human_name:
+ * @self: An #LdSymbolCategory object.
+ * @human_name: The new localized human name for this category.
+ */
+void
+ld_symbol_category_set_human_name (LdSymbolCategory *self,
+ const gchar *human_name)
+{
+ g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
+ g_return_if_fail (human_name != NULL);
+
+ if (self->priv->human_name)
+ g_free (self->priv->human_name);
+ self->priv->human_name = g_strdup (human_name);
+
+ g_object_notify (G_OBJECT (self), "human-name");
+}
+
+/**
+ * ld_symbol_category_get_human_name:
+ * @self: An #LdSymbolCategory object.
+ *
+ * Return the localized human name of this category.
+ */
+const gchar *
+ld_symbol_category_get_human_name (LdSymbolCategory *self)
+{
+ g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
+ return self->priv->human_name;
+}
+
+/**
+ * ld_symbol_category_set_image_path:
+ * @self: An #LdSymbolCategory object.
+ * @image_path: The new path to the image for this category. May be NULL.
+ */
+void
+ld_symbol_category_set_image_path (LdSymbolCategory *self,
+ const gchar *image_path)
+{
+ g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
+
+ if (self->priv->image_path)
+ g_free (self->priv->image_path);
+ self->priv->image_path = g_strdup (image_path);
+
+ g_object_notify (G_OBJECT (self), "image-path");
+}
+
+/**
+ * ld_symbol_category_get_image_path:
+ * @self: An #LdSymbolCategory object.
+ *
+ * Return the filesystem path to the image for this category. May be NULL.
+ */
+const gchar *
+ld_symbol_category_get_image_path (LdSymbolCategory *self)
+{
+ g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
+ return self->priv->image_path;
+}
+
+/**
+ * ld_symbol_category_insert_child:
+ * @self: An #LdSymbolCategory object.
+ * @child: The child to be inserted.
+ * @pos: The position at which the child will be inserted.
+ * Negative values will append to the end of list.
+ *
+ * Insert a child into the category.
+ */
+void
+ld_symbol_category_insert_child (LdSymbolCategory *self,
+ GObject *child, gint pos)
+{
+ g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
+ g_return_if_fail (G_IS_OBJECT (child));
+
+ g_object_ref (child);
+ self->priv->children = g_slist_insert (self->priv->children, child, pos);
+}
+
+/**
+ * ld_symbol_category_remove_child:
+ * @self: An #LdSymbolCategory object.
+ * @child: The child to be removed.
+ *
+ * Removes a child from the category.
+ */
+void
+ld_symbol_category_remove_child (LdSymbolCategory *self,
+ GObject *child)
+{
+ g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
+ g_return_if_fail (G_IS_OBJECT (child));
+
+ g_object_unref (child);
+ self->priv->children = g_slist_remove (self->priv->children, child);
+}
+
+/**
+ * ld_symbol_category_get_children:
+ * @self: An #LdSymbolCategory object.
+ *
+ * Return value: The internal list of children. Do not modify.
+ */
+const GSList *
+ld_symbol_category_get_children (LdSymbolCategory *self)
+{
+ g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
+ return self->priv->children;
+}
+
diff --git a/liblogdiag/ld-symbol-category.h b/liblogdiag/ld-symbol-category.h
new file mode 100644
index 0000000..3b1f05b
--- /dev/null
+++ b/liblogdiag/ld-symbol-category.h
@@ -0,0 +1,79 @@
+/*
+ * ld-symbol-category.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_SYMBOL_CATEGORY_H__
+#define __LD_SYMBOL_CATEGORY_H__
+
+G_BEGIN_DECLS
+
+
+#define LD_TYPE_SYMBOL_CATEGORY (ld_symbol_category_get_type ())
+#define LD_SYMBOL_CATEGORY(obj) (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), LD_TYPE_SYMBOL_CATEGORY, LdSymbolCategory))
+#define LD_SYMBOL_CATEGORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), LD_TYPE_SYMBOL_CATEGORY, LdSymbolCategoryClass))
+#define LD_IS_SYMBOL_CATEGORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), LD_TYPE_SYMBOL_CATEGORY))
+#define LD_IS_SYMBOL_CATEGORY_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((klass), LD_TYPE_SYMBOL_CATEGORY))
+#define LD_SYMBOL_CATEGORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), LD_SYMBOL_CATEGORY, LdSymbolCategoryClass))
+
+typedef struct _LdSymbolCategory LdSymbolCategory;
+typedef struct _LdSymbolCategoryPrivate LdSymbolCategoryPrivate;
+typedef struct _LdSymbolCategoryClass LdSymbolCategoryClass;
+
+
+/**
+ * LdSymbolCategory:
+ */
+struct _LdSymbolCategory
+{
+/*< private >*/
+ GObject parent_instance;
+ LdSymbolCategoryPrivate *priv;
+};
+
+/* TODO: If required sometime, categories (and maybe symbols) should implement
+ * a "changed" signal. This can be somewhat tricky. The library might be
+ * a good candidate for what they call a proxy. See GtkUIManager.
+ */
+struct _LdSymbolCategoryClass
+{
+/*< private >*/
+ GObjectClass parent_class;
+};
+
+
+GType ld_symbol_category_get_type (void) G_GNUC_CONST;
+
+LdSymbolCategory *ld_symbol_category_new (const gchar *name,
+ const gchar *human_name);
+
+void ld_symbol_category_set_name (LdSymbolCategory *self, const gchar *name);
+const gchar *ld_symbol_category_get_name (LdSymbolCategory *self);
+void ld_symbol_category_set_human_name (LdSymbolCategory *self,
+ const gchar *human_name);
+const gchar *ld_symbol_category_get_human_name (LdSymbolCategory *self);
+void ld_symbol_category_set_image_path (LdSymbolCategory *self,
+ const gchar *image_path);
+const gchar *ld_symbol_category_get_image_path (LdSymbolCategory *self);
+
+void ld_symbol_category_insert_child (LdSymbolCategory *self,
+ GObject *child, gint pos);
+void ld_symbol_category_remove_child (LdSymbolCategory *self,
+ GObject *child);
+const GSList *ld_symbol_category_get_children (LdSymbolCategory *self);
+
+
+G_END_DECLS
+
+#endif /* ! __LD_SYMBOL_CATEGORY_H__ */
+
diff --git a/liblogdiag/ld-symbol.c b/liblogdiag/ld-symbol.c
new file mode 100644
index 0000000..fafa9ab
--- /dev/null
+++ b/liblogdiag/ld-symbol.c
@@ -0,0 +1,232 @@
+/*
+ * ld-symbol.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include "liblogdiag.h"
+#include "config.h"
+
+
+/**
+ * SECTION:ld-symbol
+ * @short_description: A symbol.
+ * @see_also: #LdDiagramSymbol, #LdCanvas
+ *
+ * #LdSymbol represents a symbol to be drawn onto a #LdCanvas.
+ *
+ * All implementations of this abstract class are required to use
+ * cairo_save() and cairo_restore() when drawing to store the state.
+ */
+
+enum
+{
+ PROP_0,
+ PROP_NAME,
+ PROP_HUMAN_NAME,
+ PROP_AREA,
+ PROP_TERMINALS
+};
+
+static void ld_symbol_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec);
+static void ld_symbol_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec);
+
+
+G_DEFINE_ABSTRACT_TYPE (LdSymbol, ld_symbol, G_TYPE_OBJECT);
+
+static void
+ld_symbol_class_init (LdSymbolClass *klass)
+{
+ GObjectClass *object_class;
+ GParamSpec *pspec;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = ld_symbol_get_property;
+ object_class->set_property = ld_symbol_set_property;
+
+/**
+ * LdSymbol:name:
+ *
+ * The name of this symbol.
+ */
+ pspec = g_param_spec_string ("name", "Name",
+ "The name of this symbol.",
+ "", G_PARAM_READABLE);
+ g_object_class_install_property (object_class, PROP_NAME, pspec);
+
+/**
+ * LdSymbol:human-name:
+ *
+ * The localized human name of this symbol.
+ */
+ pspec = g_param_spec_string ("human-name", "Human name",
+ "The localized human name of this symbol.",
+ "", G_PARAM_READABLE);
+ g_object_class_install_property (object_class, PROP_HUMAN_NAME, pspec);
+
+/**
+ * LdSymbol:area:
+ *
+ * The area of this symbol.
+ */
+ pspec = g_param_spec_boxed ("area", "Area",
+ "The area of this symbol.",
+ LD_TYPE_RECTANGLE, G_PARAM_READABLE);
+ g_object_class_install_property (object_class, PROP_AREA, pspec);
+
+/**
+ * LdSymbol:terminals:
+ *
+ * A point array that specifies terminals of this symbol.
+ */
+ pspec = g_param_spec_boxed ("terminals", "Terminals",
+ "A point array that specifies terminals of this symbol.",
+ LD_TYPE_POINT_ARRAY, G_PARAM_READABLE);
+ g_object_class_install_property (object_class, PROP_TERMINALS, pspec);
+}
+
+static void
+ld_symbol_init (LdSymbol *self)
+{
+}
+
+static void
+ld_symbol_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec)
+{
+ LdSymbol *self;
+
+ self = LD_SYMBOL (object);
+ switch (property_id)
+ {
+ case PROP_NAME:
+ g_value_set_string (value, ld_symbol_get_name (self));
+ break;
+ case PROP_HUMAN_NAME:
+ g_value_set_string (value, ld_symbol_get_human_name (self));
+ break;
+ case PROP_AREA:
+ {
+ LdRectangle area;
+
+ ld_symbol_get_area (self, &area);
+ g_value_set_boxed (value, &area);
+ }
+ break;
+ case PROP_TERMINALS:
+ g_value_set_boxed (value, ld_symbol_get_terminals (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ld_symbol_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+
+/**
+ * ld_symbol_get_name:
+ * @self: An #LdSymbol object.
+ *
+ * Return value: The name of the symbol.
+ */
+const gchar *
+ld_symbol_get_name (LdSymbol *self)
+{
+ LdSymbolClass *klass;
+
+ g_return_val_if_fail (LD_IS_SYMBOL (self), NULL);
+
+ klass = LD_SYMBOL_GET_CLASS (self);
+ g_return_val_if_fail (klass->get_name != NULL, NULL);
+ return klass->get_name (self);
+}
+
+/**
+ * ld_symbol_get_human_name:
+ * @self: An #LdSymbol object.
+ *
+ * Return value: The localised human name of the symbol.
+ */
+const gchar *
+ld_symbol_get_human_name (LdSymbol *self)
+{
+ LdSymbolClass *klass;
+
+ g_return_val_if_fail (LD_IS_SYMBOL (self), NULL);
+
+ klass = LD_SYMBOL_GET_CLASS (self);
+ g_return_val_if_fail (klass->get_human_name != NULL, NULL);
+ return klass->get_human_name (self);
+}
+
+/**
+ * ld_symbol_get_area:
+ * @self: An #LdSymbol object.
+ * @area: Where the area of the symbol will be returned.
+ *
+ * Get the area of the symbol.
+ */
+void
+ld_symbol_get_area (LdSymbol *self, LdRectangle *area)
+{
+ LdSymbolClass *klass;
+
+ g_return_if_fail (LD_IS_SYMBOL (self));
+ g_return_if_fail (area != NULL);
+
+ klass = LD_SYMBOL_GET_CLASS (self);
+ g_return_if_fail (klass->get_area != NULL);
+ klass->get_area (self, area);
+}
+
+/**
+ * ld_symbol_get_terminals:
+ * @self: An #LdSymbol object.
+ *
+ * Get a list of symbol terminals.
+ *
+ * Return value: An #LdPointArray structure.
+ */
+const LdPointArray *
+ld_symbol_get_terminals (LdSymbol *self)
+{
+ LdSymbolClass *klass;
+
+ g_return_val_if_fail (LD_IS_SYMBOL (self), NULL);
+
+ klass = LD_SYMBOL_GET_CLASS (self);
+ g_return_val_if_fail (klass->get_terminals != NULL, NULL);
+ return klass->get_terminals (self);
+}
+
+/**
+ * ld_symbol_draw:
+ * @self: An #LdSymbol object.
+ * @cr: A cairo surface to be drawn on.
+ *
+ * Draw the symbol onto a Cairo surface.
+ */
+void
+ld_symbol_draw (LdSymbol *self, cairo_t *cr)
+{
+ LdSymbolClass *klass;
+
+ g_return_if_fail (LD_IS_SYMBOL (self));
+ g_return_if_fail (cr != NULL);
+
+ klass = LD_SYMBOL_GET_CLASS (self);
+ g_return_if_fail (klass->draw != NULL);
+ klass->draw (self, cr);
+}
diff --git a/liblogdiag/ld-symbol.h b/liblogdiag/ld-symbol.h
new file mode 100644
index 0000000..409eba5
--- /dev/null
+++ b/liblogdiag/ld-symbol.h
@@ -0,0 +1,74 @@
+/*
+ * ld-symbol.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_SYMBOL_H__
+#define __LD_SYMBOL_H__
+
+G_BEGIN_DECLS
+
+
+#define LD_TYPE_SYMBOL (ld_symbol_get_type ())
+#define LD_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), LD_TYPE_SYMBOL, LdSymbol))
+#define LD_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), LD_TYPE_SYMBOL, LdSymbolClass))
+#define LD_IS_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), LD_TYPE_SYMBOL))
+#define LD_IS_SYMBOL_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((klass), LD_TYPE_SYMBOL))
+#define LD_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), LD_SYMBOL, LdSymbolClass))
+
+typedef struct _LdSymbol LdSymbol;
+typedef struct _LdSymbolPrivate LdSymbolPrivate;
+typedef struct _LdSymbolClass LdSymbolClass;
+
+
+struct _LdSymbol
+{
+/*< private >*/
+ GObject parent_instance;
+ LdSymbolPrivate *priv;
+};
+
+/**
+ * LdSymbolClass:
+ * @parent_class: The parent class.
+ * @get_name: Get the name of the symbol.
+ * @get_human_name: Get the localized human name of the symbol.
+ * @get_area: Get the area of the symbol.
+ * @get_terminals: Get a list of symbol terminals.
+ * @draw: Draw the symbol on a Cairo surface.
+ */
+struct _LdSymbolClass
+{
+ GObjectClass parent_class;
+
+ const gchar *(*get_name) (LdSymbol *self);
+ const gchar *(*get_human_name) (LdSymbol *self);
+ void (*get_area) (LdSymbol *self, LdRectangle *area);
+ const LdPointArray *(*get_terminals) (LdSymbol *self);
+ void (*draw) (LdSymbol *self, cairo_t *cr);
+};
+
+
+GType ld_symbol_get_type (void) G_GNUC_CONST;
+
+const gchar *ld_symbol_get_name (LdSymbol *self);
+const gchar *ld_symbol_get_human_name (LdSymbol *self);
+void ld_symbol_get_area (LdSymbol *self, LdRectangle *area);
+const LdPointArray *ld_symbol_get_terminals (LdSymbol *self);
+void ld_symbol_draw (LdSymbol *self, cairo_t *cr);
+
+
+G_END_DECLS
+
+#endif /* ! __LD_SYMBOL_H__ */
+
diff --git a/liblogdiag/ld-types.c b/liblogdiag/ld-types.c
new file mode 100644
index 0000000..cde3da6
--- /dev/null
+++ b/liblogdiag/ld-types.c
@@ -0,0 +1,221 @@
+/*
+ * ld-types.c
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#include
+
+#include "liblogdiag.h"
+#include "config.h"
+
+
+#define DEFINE_BOXED_TYPE(TypeName, type_name) \
+GType \
+type_name ## _get_type (void) \
+{ \
+ static GType our_type = 0; \
+ if (our_type == 0) \
+ our_type = g_boxed_type_register_static \
+ (g_intern_static_string (#TypeName), \
+ (GBoxedCopyFunc) type_name ## _copy, \
+ (GBoxedFreeFunc) type_name ## _free); \
+ return our_type; \
+}
+
+DEFINE_BOXED_TYPE (LdPoint, ld_point)
+DEFINE_BOXED_TYPE (LdPointArray, ld_point_array)
+DEFINE_BOXED_TYPE (LdRectangle, ld_rectangle)
+
+#define DEFINE_BOXED_TRIVIAL_COPY(TypeName, type_name) \
+TypeName * \
+type_name ## _copy (const TypeName *self) \
+{ \
+ TypeName *new_copy; \
+ g_return_val_if_fail (self != NULL, NULL); \
+ new_copy = g_slice_new (TypeName); \
+ *new_copy = *self; \
+ return new_copy; \
+}
+
+#define DEFINE_BOXED_TRIVIAL_FREE(TypeName, type_name) \
+void \
+type_name ## _free (TypeName *self) \
+{ \
+ g_return_if_fail (self != NULL); \
+ g_slice_free (TypeName, self); \
+}
+
+/**
+ * ld_point_copy:
+ * @self: An #LdPoint structure.
+ *
+ * Makes a copy of the structure.
+ * The result must be freed by ld_point_free().
+ *
+ * Return value: A copy of @self.
+ */
+DEFINE_BOXED_TRIVIAL_COPY (LdPoint, ld_point)
+
+/**
+ * ld_point_free:
+ * @self: An #LdPoint structure.
+ *
+ * Frees the structure created with ld_point_copy().
+ */
+DEFINE_BOXED_TRIVIAL_FREE (LdPoint, ld_point)
+
+/**
+ * ld_point_distance:
+ * @self: An #LdPoint structure.
+ * @x: The X coordinate of the second point.
+ * @y: The Y coordinate of the second point.
+ *
+ * Compute the distance between two points.
+ */
+gdouble
+ld_point_distance (LdPoint *self, gdouble x, gdouble y)
+{
+ gdouble dx, dy;
+
+ g_return_val_if_fail (self != NULL, -1);
+
+ dx = self->x - x;
+ dy = self->y - y;
+ return sqrt (dx * dx + dy * dy);
+}
+
+/**
+ * ld_point_array_new:
+ * @num_points: The number of points the array can store.
+ *
+ * Create a new array of points and initialize.
+ *
+ * Return value: An #LdPointArray structure.
+ */
+LdPointArray *
+ld_point_array_new (gint num_points)
+{
+ LdPointArray *new_array;
+
+ g_return_val_if_fail (num_points >= 1, NULL);
+
+ new_array = g_slice_new (LdPointArray);
+ new_array->num_points = num_points;
+ new_array->points = g_malloc0 (num_points * sizeof (LdPoint));
+ return new_array;
+}
+
+/**
+ * ld_point_array_copy:
+ * @self: An #LdPointArray structure.
+ *
+ * Makes a copy of the structure.
+ * The result must be freed by ld_point_array_free().
+ *
+ * Return value: A copy of @self.
+ */
+LdPointArray *
+ld_point_array_copy (const LdPointArray *self)
+{
+ LdPointArray *new_array;
+
+ g_return_val_if_fail (self != NULL, NULL);
+
+ new_array = g_slice_new (LdPointArray);
+ new_array->num_points = self->num_points;
+ new_array->points = g_memdup (self->points,
+ self->num_points * sizeof (LdPoint));
+ return new_array;
+}
+
+/**
+ * ld_point_array_free:
+ * @self: An #LdPointArray structure.
+ *
+ * Frees the structure created with ld_point_array_copy().
+ */
+void
+ld_point_array_free (LdPointArray *self)
+{
+ g_return_if_fail (self != NULL);
+
+ g_free (self->points);
+ g_slice_free (LdPointArray, self);
+}
+
+/**
+ * ld_rectangle_copy:
+ * @self: An #LdRectangle structure.
+ *
+ * Makes a copy of the structure.
+ * The result must be freed by ld_rectangle_free().
+ *
+ * Return value: A copy of @self.
+ */
+DEFINE_BOXED_TRIVIAL_COPY (LdRectangle, ld_rectangle)
+
+/**
+ * ld_rectangle_free:
+ * @self: An #LdRectangle structure.
+ *
+ * Frees the structure created with ld_rectangle_copy().
+ */
+DEFINE_BOXED_TRIVIAL_FREE (LdRectangle, ld_rectangle)
+
+/**
+ * ld_rectangle_contains:
+ * @self: An #LdRectangle structure.
+ * @x: The X coordinate of the point to be checked.
+ * @y: The Y coordinate of the point to be checked.
+ *
+ * Return value: TRUE if the rectangle contains the specified point.
+ */
+gboolean
+ld_rectangle_contains (LdRectangle *self, gdouble x, gdouble y)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ return (x >= self->x && x <= self->x + self->width
+ && y >= self->y && y <= self->y + self->height);
+}
+
+/**
+ * ld_rectangle_intersects:
+ * @self: An #LdRectangle structure.
+ * @rect: An #LdRectangle to be checked for intersection.
+ *
+ * Return value: TRUE if the two rectangles intersect.
+ */
+gboolean
+ld_rectangle_intersects (LdRectangle *self, LdRectangle *rect)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (rect != NULL, FALSE);
+
+ return !(self->x > rect->x + rect->width
+ || self->y > rect->y + rect->height
+ || self->x + self->width < rect->x
+ || self->y + self->height < rect->y);
+}
+
+/**
+ * ld_rectangle_extend:
+ * @self: An #LdRectangle structure.
+ * @border: The border by which the rectangle should be extended.
+ *
+ * Extend a rectangle on all sides.
+ */
+void
+ld_rectangle_extend (LdRectangle *self, gdouble border)
+{
+ g_return_if_fail (self != NULL);
+
+ self->x -= border;
+ self->y -= border;
+ self->width += 2 * border;
+ self->height += 2 * border;
+}
diff --git a/liblogdiag/ld-types.h b/liblogdiag/ld-types.h
new file mode 100644
index 0000000..61a1a7d
--- /dev/null
+++ b/liblogdiag/ld-types.h
@@ -0,0 +1,101 @@
+/*
+ * ld-types.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LD_TYPES_H__
+#define __LD_TYPES_H__
+
+G_BEGIN_DECLS
+
+
+/**
+ * SECTION:ld-types
+ * @short_description: Simple data types.
+ *
+ * #LdPoint defines coordinates of a point.
+ *
+ * #LdRectangle defines the position and size of a rectangle.
+ */
+
+#define LD_TYPE_POINT (ld_point_get_type ())
+#define LD_TYPE_POINT_ARRAY (ld_point_array_get_type ())
+#define LD_TYPE_RECTANGLE (ld_rectangle_get_type ())
+
+typedef struct _LdPoint LdPoint;
+typedef struct _LdPointArray LdPointArray;
+typedef struct _LdRectangle LdRectangle;
+
+
+/**
+ * LdPoint:
+ * @x: The X coordinate.
+ * @y: The Y coordinate.
+ *
+ * Defines a point.
+ */
+struct _LdPoint
+{
+ gdouble x, y;
+};
+
+GType ld_point_get_type (void) G_GNUC_CONST;
+
+LdPoint *ld_point_copy (const LdPoint *self);
+void ld_point_free (LdPoint *self);
+gdouble ld_point_distance (LdPoint *self, gdouble x, gdouble y);
+
+
+/**
+ * LdPointArray:
+ * @points: An array of #LdPoint structures.
+ * @num_points: Count of points in @points.
+ *
+ * Moves quickly.
+ */
+struct _LdPointArray
+{
+ LdPoint *points;
+ gint num_points;
+};
+
+GType ld_point_array_get_type (void) G_GNUC_CONST;
+
+LdPointArray *ld_point_array_new (gint num_points);
+LdPointArray *ld_point_array_copy (const LdPointArray *self);
+void ld_point_array_free (LdPointArray *self);
+
+
+/**
+ * LdRectangle:
+ * @x: Left-top X coordinate.
+ * @y: Left-top Y coordinate.
+ * @width: Width of the area, must be positive.
+ * @height: Height of the area, must be positive.
+ *
+ * Defines a rectangle.
+ */
+struct _LdRectangle
+{
+ gdouble x, y;
+ gdouble width, height;
+};
+
+GType ld_rectangle_get_type (void) G_GNUC_CONST;
+
+LdRectangle *ld_rectangle_copy (const LdRectangle *self);
+void ld_rectangle_free (LdRectangle *self);
+gboolean ld_rectangle_contains (LdRectangle *self, gdouble x, gdouble y);
+gboolean ld_rectangle_intersects (LdRectangle *self, LdRectangle *rect);
+void ld_rectangle_extend (LdRectangle *self, gdouble border);
+
+
+G_END_DECLS
+
+#endif /* ! __LD_TYPES_H__ */
+
diff --git a/liblogdiag/liblogdiag.h b/liblogdiag/liblogdiag.h
new file mode 100644
index 0000000..800826f
--- /dev/null
+++ b/liblogdiag/liblogdiag.h
@@ -0,0 +1,34 @@
+/*
+ * liblogdiag.h
+ *
+ * This file is a part of logdiag.
+ * Copyright Přemysl Janouch 2011. All rights reserved.
+ *
+ * See the file LICENSE for licensing information.
+ *
+ */
+
+#ifndef __LIBLOGDIAG_H__
+#define __LIBLOGDIAG_H__
+
+#include
+#include
+
+#include "ld-marshal.h"
+#include "ld-types.h"
+
+#include "ld-symbol.h"
+#include "ld-symbol-category.h"
+#include "ld-library.h"
+
+#include "ld-diagram-object.h"
+#include "ld-diagram-symbol.h"
+#include "ld-diagram.h"
+
+#include "ld-canvas.h"
+
+#include "ld-lua.h"
+#include "ld-lua-symbol.h"
+
+#endif /* ! __LIBLOGDIAG_H__ */
+
diff --git a/po/make-template.sh b/po/make-template.sh
index e688847..f76a620 100755
--- a/po/make-template.sh
+++ b/po/make-template.sh
@@ -4,6 +4,9 @@
# is that the translator should not need to run
# the whole configure process to get this single stupid file.
+# Source files
+SOURCES=$(echo ../{src,liblogdiag}/*.c)
+
# Get the package name from CMakeLists.txt
PACKAGE=$(sed -n '/^[ \t]*[pP][rR][oO][jJ][eE][cC][tT][ \t]*([ \t]*\([^ \t)]\{1,\}\).*).*/{s//\1/p;q}' \
../CMakeLists.txt)
@@ -27,7 +30,7 @@ if [ "$MAJOR" != "" ]; then
fi
# Finally make the template
-xgettext -LC -k_ -kN_:1,2 -kG_ ../src/*.c -o "$PACKAGE".pot \
+xgettext -LC -k_ -kN_:1,2 -kG_ $SOURCES -o "$PACKAGE".pot \
--package-name="$PACKAGE" --package-version="$VERSION" \
--copyright-holder="Přemysl Janouch"
diff --git a/src/ld-canvas.c b/src/ld-canvas.c
deleted file mode 100644
index 9523d9d..0000000
--- a/src/ld-canvas.c
+++ /dev/null
@@ -1,1417 +0,0 @@
-/*
- * ld-canvas.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include
-#include
-#include
-
-#include "liblogdiag.h"
-#include "config.h"
-
-
-/**
- * SECTION:ld-canvas
- * @short_description: A canvas.
- * @see_also: #LdDiagram
- *
- * #LdCanvas displays and enables the user to manipulate with an #LdDiagram.
- */
-
-/* Milimetres per inch. */
-#define MM_PER_INCH 25.4
-/* The default screen resolution in DPI units. */
-#define DEFAULT_SCREEN_RESOLUTION 96
-
-/* The maximal, minimal and default values of zoom. */
-#define ZOOM_MIN 0.01
-#define ZOOM_MAX 100
-#define ZOOM_DEFAULT 1
-/* Multiplication factor for zooming with mouse wheel. */
-#define ZOOM_WHEEL_STEP 1.4
-
-/* When drawing is requested, extend all sides of
- * the rectangle to be drawn by this number of pixels.
- */
-#define QUEUE_DRAW_EXTEND 3
-/* Cursor tolerance for object borders. */
-#define OBJECT_BORDER_TOLERANCE 3
-/* Tolerance on all sides of symbols for strokes. */
-#define SYMBOL_CLIP_TOLERANCE 5
-
-/* Size of a highlighted terminal. */
-#define TERMINAL_RADIUS 5
-/* Tolerance around terminal points. */
-#define TERMINAL_HOVER_TOLERANCE 8
-
-/*
- * OperationEnd:
- *
- * Called upon ending an operation.
- */
-typedef void (*OperationEnd) (LdCanvas *self);
-
-enum
-{
- OPER_0,
- OPER_ADD_OBJECT
-};
-
-typedef struct _AddObjectData AddObjectData;
-
-struct _AddObjectData
-{
- LdDiagramObject *object;
- gboolean visible;
-};
-
-enum
-{
- COLOR_BASE,
- COLOR_GRID,
- COLOR_OBJECT,
- COLOR_SELECTION,
- COLOR_TERMINAL,
- COLOR_COUNT
-};
-
-typedef struct _LdCanvasColor LdCanvasColor;
-
-struct _LdCanvasColor
-{
- gdouble r;
- gdouble g;
- gdouble b;
- gdouble a;
-};
-
-/*
- * LdCanvasPrivate:
- * @diagram: A diagram object assigned to this canvas as a model.
- * @library: A library object assigned to this canvas as a model.
- * @adjustment_h: An adjustment object for the horizontal axis, if any.
- * @adjustment_v: An adjustment object for the vertical axis, if any.
- * @x: The X coordinate of the center of view.
- * @y: The Y coordinate of the center of view.
- * @zoom: The current zoom of the canvas.
- * @operation: The current operation.
- * @operation_data: Data related to the current operation.
- * @operation_end: A callback to end the operation.
- * @palette: Colors used by the widget.
- */
-struct _LdCanvasPrivate
-{
- LdDiagram *diagram;
- LdLibrary *library;
-
- GtkAdjustment *adjustment_h;
- GtkAdjustment *adjustment_v;
-
- gdouble x;
- gdouble y;
- gdouble zoom;
-
- LdPoint terminal;
- gboolean terminal_highlighted;
-
- gint operation;
- union
- {
- AddObjectData add_object;
- }
- operation_data;
- OperationEnd operation_end;
-
- LdCanvasColor palette[COLOR_COUNT];
-};
-
-#define OPER_DATA(self, member) ((self)->priv->operation_data.member)
-#define COLOR_GET(self, name) (&(self)->priv->palette[name])
-
-/*
- * DrawData:
- * @self: Our #LdCanvas.
- * @cr: A cairo context to draw on.
- * @exposed_rect: The area that is to be redrawn.
- * @scale: Computed size of one diagram unit in pixels.
- */
-typedef struct _DrawData DrawData;
-
-struct _DrawData
-{
- LdCanvas *self;
- cairo_t *cr;
- LdRectangle exposed_rect;
- gdouble scale;
-};
-
-enum
-{
- PROP_0,
- PROP_DIAGRAM,
- PROP_LIBRARY,
- PROP_ZOOM
-};
-
-static void ld_canvas_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec);
-static void ld_canvas_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec);
-static void ld_canvas_finalize (GObject *gobject);
-
-static void ld_canvas_real_set_scroll_adjustments
- (LdCanvas *self, GtkAdjustment *horizontal, GtkAdjustment *vertical);
-static void on_adjustment_value_changed
- (GtkAdjustment *adjustment, LdCanvas *self);
-static void on_size_allocate (GtkWidget *widget, GtkAllocation *allocation,
- gpointer user_data);
-static void update_adjustments (LdCanvas *self);
-
-static void diagram_connect_signals (LdCanvas *self);
-static void diagram_disconnect_signals (LdCanvas *self);
-
-static gdouble ld_canvas_get_base_unit_in_px (GtkWidget *self);
-static gdouble ld_canvas_get_scale_in_px (LdCanvas *self);
-
-static void simulate_motion (LdCanvas *self);
-static gboolean on_motion_notify (GtkWidget *widget, GdkEventMotion *event,
- gpointer user_data);
-static gboolean on_leave_notify (GtkWidget *widget, GdkEventCrossing *event,
- gpointer user_data);
-static gboolean on_button_press (GtkWidget *widget, GdkEventButton *event,
- gpointer user_data);
-static gboolean on_button_release (GtkWidget *widget, GdkEventButton *event,
- gpointer user_data);
-static gboolean on_scroll (GtkWidget *widget, GdkEventScroll *event,
- gpointer user_data);
-
-static void ld_canvas_color_set (LdCanvasColor *color,
- gdouble r, gdouble g, gdouble b, gdouble a);
-static void ld_canvas_color_apply (LdCanvasColor *color, cairo_t *cr);
-
-static void move_object_to_coords (LdCanvas *self, LdDiagramObject *object,
- gdouble x, gdouble y);
-static LdDiagramObject *get_object_at_coords (LdCanvas *self,
- gdouble x, gdouble y);
-static gboolean is_object_selected (LdCanvas *self, LdDiagramObject *object);
-static LdSymbol *resolve_diagram_symbol (LdCanvas *self,
- LdDiagramSymbol *diagram_symbol);
-static gboolean get_symbol_area (LdCanvas *self, LdDiagramSymbol *symbol,
- LdRectangle *rect);
-static gboolean get_symbol_clip_area (LdCanvas *self, LdDiagramSymbol *symbol,
- LdRectangle *rect);
-static gboolean get_object_area (LdCanvas *self, LdDiagramObject *object,
- LdRectangle *rect);
-static gboolean object_hit_test (LdCanvas *self, LdDiagramObject *object,
- gdouble x, gdouble y);
-static void check_terminals (LdCanvas *self, gdouble x, gdouble y);
-static void hide_terminals (LdCanvas *self);
-static void queue_draw (LdCanvas *self, LdRectangle *rect);
-static void queue_object_draw (LdCanvas *self, LdDiagramObject *object);
-static void queue_terminal_draw (LdCanvas *self, LdPoint *terminal);
-
-static void ld_canvas_real_cancel_operation (LdCanvas *self);
-static void ld_canvas_add_object_end (LdCanvas *self);
-
-static gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event,
- gpointer user_data);
-static void draw_grid (GtkWidget *widget, DrawData *data);
-static void draw_diagram (GtkWidget *widget, DrawData *data);
-static void draw_terminal (GtkWidget *widget, DrawData *data);
-static void draw_object (LdDiagramObject *diagram_object, DrawData *data);
-static void draw_symbol (LdDiagramSymbol *diagram_symbol, DrawData *data);
-
-
-G_DEFINE_TYPE (LdCanvas, ld_canvas, GTK_TYPE_DRAWING_AREA);
-
-static void
-ld_canvas_class_init (LdCanvasClass *klass)
-{
- GObjectClass *object_class;
- GtkWidgetClass *widget_class;
- GtkBindingSet *binding_set;
- GParamSpec *pspec;
-
- widget_class = GTK_WIDGET_CLASS (klass);
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->get_property = ld_canvas_get_property;
- object_class->set_property = ld_canvas_set_property;
- object_class->finalize = ld_canvas_finalize;
-
- klass->set_scroll_adjustments = ld_canvas_real_set_scroll_adjustments;
- klass->cancel_operation = ld_canvas_real_cancel_operation;
-
- binding_set = gtk_binding_set_by_class (klass);
- gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
- "cancel-operation", 0);
-
-/**
- * LdCanvas:diagram:
- *
- * The underlying #LdDiagram object of this canvas.
- */
- pspec = g_param_spec_object ("diagram", "Diagram",
- "The underlying diagram object of this canvas.",
- LD_TYPE_DIAGRAM, G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_DIAGRAM, pspec);
-
-/**
- * LdCanvas:library:
- *
- * The #LdLibrary that this canvas retrieves symbols from.
- */
- pspec = g_param_spec_object ("library", "Library",
- "The library that this canvas retrieves symbols from.",
- LD_TYPE_LIBRARY, G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_LIBRARY, pspec);
-
-/**
- * LdCanvas:zoom:
- *
- * The zoom of this canvas.
- */
- pspec = g_param_spec_double ("zoom", "Zoom",
- "The zoom of this canvas.",
- ZOOM_MIN, ZOOM_MAX, ZOOM_DEFAULT, G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_ZOOM, pspec);
-
-/**
- * LdCanvas::set-scroll-adjustments:
- * @horizontal: The horizontal #GtkAdjustment.
- * @vertical: The vertical #GtkAdjustment.
- *
- * Set scroll adjustments for the canvas.
- */
- widget_class->set_scroll_adjustments_signal = g_signal_new
- ("set-scroll-adjustments", G_TYPE_FROM_CLASS (widget_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (LdCanvasClass, set_scroll_adjustments),
- NULL, NULL,
- g_cclosure_user_marshal_VOID__OBJECT_OBJECT,
- G_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
-
-/**
- * LdCanvas::cancel-operation:
- *
- * Cancel any current operation.
- */
- klass->cancel_operation_signal = g_signal_new
- ("cancel-operation", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (LdCanvasClass, cancel_operation), NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_type_class_add_private (klass, sizeof (LdCanvasPrivate));
-}
-
-static void
-ld_canvas_init (LdCanvas *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE
- (self, LD_TYPE_CANVAS, LdCanvasPrivate);
-
- self->priv->x = 0;
- self->priv->y = 0;
- self->priv->zoom = ZOOM_DEFAULT;
-
- ld_canvas_color_set (COLOR_GET (self, COLOR_BASE), 1, 1, 1, 1);
- ld_canvas_color_set (COLOR_GET (self, COLOR_GRID), 0.5, 0.5, 0.5, 1);
- ld_canvas_color_set (COLOR_GET (self, COLOR_OBJECT), 0, 0, 0, 1);
- ld_canvas_color_set (COLOR_GET (self, COLOR_SELECTION), 0, 0, 1, 1);
- ld_canvas_color_set (COLOR_GET (self, COLOR_TERMINAL), 1, 0.5, 0.5, 1);
-
- g_signal_connect (self, "size-allocate",
- G_CALLBACK (on_size_allocate), NULL);
- g_signal_connect (self, "expose-event",
- G_CALLBACK (on_expose_event), NULL);
-
- g_signal_connect (self, "motion-notify-event",
- G_CALLBACK (on_motion_notify), NULL);
- g_signal_connect (self, "leave-notify-event",
- G_CALLBACK (on_leave_notify), NULL);
- g_signal_connect (self, "button-press-event",
- G_CALLBACK (on_button_press), NULL);
- g_signal_connect (self, "button-release-event",
- G_CALLBACK (on_button_release), NULL);
- g_signal_connect (self, "scroll-event",
- G_CALLBACK (on_scroll), NULL);
-
- g_object_set (self, "can-focus", TRUE, NULL);
-
- gtk_widget_add_events (GTK_WIDGET (self),
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK
- | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- | GDK_LEAVE_NOTIFY_MASK);
-}
-
-static void
-ld_canvas_finalize (GObject *gobject)
-{
- LdCanvas *self;
-
- self = LD_CANVAS (gobject);
-
- ld_canvas_real_set_scroll_adjustments (self, NULL, NULL);
-
- if (self->priv->diagram)
- {
- diagram_disconnect_signals (self);
- g_object_unref (self->priv->diagram);
- }
- if (self->priv->library)
- g_object_unref (self->priv->library);
-
- /* Chain up to the parent class. */
- G_OBJECT_CLASS (ld_canvas_parent_class)->finalize (gobject);
-}
-
-static void
-ld_canvas_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- LdCanvas *self;
-
- self = LD_CANVAS (object);
- switch (property_id)
- {
- case PROP_DIAGRAM:
- g_value_set_object (value, ld_canvas_get_diagram (self));
- break;
- case PROP_LIBRARY:
- g_value_set_object (value, ld_canvas_get_library (self));
- break;
- case PROP_ZOOM:
- g_value_set_double (value, ld_canvas_get_zoom (self));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-ld_canvas_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- LdCanvas *self;
-
- self = LD_CANVAS (object);
- switch (property_id)
- {
- case PROP_DIAGRAM:
- ld_canvas_set_diagram (self, LD_DIAGRAM (g_value_get_object (value)));
- break;
- case PROP_LIBRARY:
- ld_canvas_set_library (self, LD_LIBRARY (g_value_get_object (value)));
- break;
- case PROP_ZOOM:
- ld_canvas_set_zoom (self, g_value_get_double (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-ld_canvas_real_set_scroll_adjustments (LdCanvas *self,
- GtkAdjustment *horizontal, GtkAdjustment *vertical)
-{
- /* TODO: Infinite canvas. */
- GtkWidget *widget;
- gdouble scale;
-
- widget = GTK_WIDGET (self);
- scale = ld_canvas_get_scale_in_px (self);
-
- if (horizontal != self->priv->adjustment_h)
- {
- if (self->priv->adjustment_h)
- {
- g_signal_handlers_disconnect_by_func (self->priv->adjustment_h,
- on_adjustment_value_changed, self);
- g_object_unref (self->priv->adjustment_h);
-
- self->priv->adjustment_h = NULL;
- }
- if (horizontal)
- {
- g_object_ref (horizontal);
- g_signal_connect (horizontal, "value-changed",
- G_CALLBACK (on_adjustment_value_changed), self);
-
- horizontal->upper = 100;
- horizontal->lower = -100;
- horizontal->step_increment = 0.5;
- horizontal->page_increment = 5;
- horizontal->page_size = widget->allocation.width / scale;
- horizontal->value = -horizontal->page_size / 2;
-
- self->priv->adjustment_h = horizontal;
- }
- }
-
- if (vertical != self->priv->adjustment_v)
- {
- if (self->priv->adjustment_v)
- {
- g_signal_handlers_disconnect_by_func (self->priv->adjustment_v,
- on_adjustment_value_changed, self);
- g_object_unref (self->priv->adjustment_v);
-
- self->priv->adjustment_v = NULL;
- }
- if (vertical)
- {
- g_object_ref (vertical);
- g_signal_connect (vertical, "value-changed",
- G_CALLBACK (on_adjustment_value_changed), self);
-
- vertical->upper = 100;
- vertical->lower = -100;
- vertical->step_increment = 0.5;
- vertical->page_increment = 5;
- vertical->page_size = widget->allocation.height / scale;
- vertical->value = -vertical->page_size / 2;
-
- self->priv->adjustment_v = vertical;
- }
- }
-}
-
-static void
-on_adjustment_value_changed (GtkAdjustment *adjustment, LdCanvas *self)
-{
- GtkWidget *widget;
- gdouble scale;
-
- widget = GTK_WIDGET (self);
- scale = ld_canvas_get_scale_in_px (self);
-
- if (adjustment == self->priv->adjustment_h)
- {
- self->priv->x = adjustment->value
- + widget->allocation.width / scale / 2;
- gtk_widget_queue_draw (widget);
- }
- else if (adjustment == self->priv->adjustment_v)
- {
- self->priv->y = adjustment->value
- + widget->allocation.height / scale / 2;
- gtk_widget_queue_draw (widget);
- }
-}
-
-static void
-on_size_allocate (GtkWidget *widget, GtkAllocation *allocation,
- gpointer user_data)
-{
- LdCanvas *self;
-
- self = LD_CANVAS (widget);
-
- /* FIXME: If the new allocation is bigger, we may see more than
- * what we're supposed to be able to see -> adjust X and Y.
- *
- * If the visible area is so large that we simply must see more,
- * let's disable the scrollbars in question.
- */
- update_adjustments (self);
-}
-
-static void
-update_adjustments (LdCanvas *self)
-{
- gdouble scale;
-
- scale = ld_canvas_get_scale_in_px (self);
-
- if (self->priv->adjustment_h)
- {
- self->priv->adjustment_h->page_size
- = GTK_WIDGET (self)->allocation.width / scale;
- self->priv->adjustment_h->value
- = self->priv->x - self->priv->adjustment_h->page_size / 2;
- gtk_adjustment_changed (self->priv->adjustment_h);
- }
- if (self->priv->adjustment_v)
- {
- self->priv->adjustment_v->page_size
- = GTK_WIDGET (self)->allocation.height / scale;
- self->priv->adjustment_v->value
- = self->priv->y - self->priv->adjustment_v->page_size / 2;
- gtk_adjustment_changed (self->priv->adjustment_v);
- }
-}
-
-
-/* ===== Generic interface etc. ============================================ */
-
-/**
- * ld_canvas_new:
- *
- * Create an instance.
- */
-LdCanvas *
-ld_canvas_new (void)
-{
- return g_object_new (LD_TYPE_CANVAS, NULL);
-}
-
-/**
- * ld_canvas_set_diagram:
- * @self: An #LdCanvas object.
- * @diagram: The #LdDiagram to be assigned to the canvas.
- *
- * Assign an #LdDiagram object to the canvas.
- */
-void
-ld_canvas_set_diagram (LdCanvas *self, LdDiagram *diagram)
-{
- g_return_if_fail (LD_IS_CANVAS (self));
- g_return_if_fail (LD_IS_DIAGRAM (diagram));
-
- if (self->priv->diagram)
- {
- diagram_disconnect_signals (self);
- g_object_unref (self->priv->diagram);
- }
-
- self->priv->diagram = diagram;
- diagram_connect_signals (self);
- g_object_ref (diagram);
-
- g_object_notify (G_OBJECT (self), "diagram");
-}
-
-/**
- * ld_canvas_get_diagram:
- * @self: An #LdCanvas object.
- *
- * Get the #LdDiagram object assigned to this canvas.
- * The reference count on the diagram is not incremented.
- */
-LdDiagram *
-ld_canvas_get_diagram (LdCanvas *self)
-{
- g_return_val_if_fail (LD_IS_CANVAS (self), NULL);
- return self->priv->diagram;
-}
-
-static void
-diagram_connect_signals (LdCanvas *self)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self->priv->diagram));
-
- g_signal_connect_swapped (self->priv->diagram, "changed",
- G_CALLBACK (gtk_widget_queue_draw), self);
- g_signal_connect_swapped (self->priv->diagram, "selection-changed",
- G_CALLBACK (gtk_widget_queue_draw), self);
-}
-
-static void
-diagram_disconnect_signals (LdCanvas *self)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self->priv->diagram));
-
- g_signal_handlers_disconnect_matched (self->priv->diagram,
- G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL,
- gtk_widget_queue_draw, self);
-}
-
-/**
- * ld_canvas_set_library:
- * @self: An #LdCanvas object.
- * @library: The #LdLibrary to be assigned to the canvas.
- *
- * Assign an #LdLibrary object to the canvas.
- */
-void
-ld_canvas_set_library (LdCanvas *self, LdLibrary *library)
-{
- g_return_if_fail (LD_IS_CANVAS (self));
- g_return_if_fail (LD_IS_LIBRARY (library));
-
- if (self->priv->library)
- g_object_unref (self->priv->library);
-
- self->priv->library = library;
- g_object_ref (library);
-
- g_object_notify (G_OBJECT (self), "library");
-}
-
-/**
- * ld_canvas_get_library:
- * @self: An #LdCanvas object.
- *
- * Get the #LdLibrary object assigned to this canvas.
- * The reference count on the library is not incremented.
- */
-LdLibrary *
-ld_canvas_get_library (LdCanvas *self)
-{
- g_return_val_if_fail (LD_IS_CANVAS (self), NULL);
- return self->priv->library;
-}
-
-/*
- * ld_canvas_get_base_unit_in_px:
- * @self: A #GtkWidget object to retrieve DPI from (indirectly).
- *
- * Return value: Length of the base unit in pixels.
- */
-static gdouble
-ld_canvas_get_base_unit_in_px (GtkWidget *self)
-{
- gdouble resolution;
-
- g_return_val_if_fail (GTK_IS_WIDGET (self), 1);
-
- resolution = gdk_screen_get_resolution (gtk_widget_get_screen (self));
- if (resolution == -1)
- resolution = DEFAULT_SCREEN_RESOLUTION;
-
- /* XXX: It might look better if the unit was rounded to a whole number. */
- return resolution / MM_PER_INCH * LD_CANVAS_BASE_UNIT_LENGTH;
-}
-
-/*
- * ld_canvas_get_scale_in_px:
- * @self: An #LdCanvas object.
- *
- * Return value: Displayed length of the base unit in pixels.
- */
-static gdouble
-ld_canvas_get_scale_in_px (LdCanvas *self)
-{
- g_return_val_if_fail (LD_IS_CANVAS (self), 1);
-
- return ld_canvas_get_base_unit_in_px (GTK_WIDGET (self))
- * self->priv->zoom;
-}
-
-/**
- * ld_canvas_widget_to_diagram_coords:
- * @self: An #LdCanvas object.
- * @wx: The X coordinate to be translated.
- * @wy: The Y coordinate to be translated.
- * @dx: (out): The translated X coordinate.
- * @dy: (out): The translated Y coordinate.
- *
- * Translate coordinates located inside the canvas window
- * into diagram coordinates.
- */
-void
-ld_canvas_widget_to_diagram_coords (LdCanvas *self,
- gdouble wx, gdouble wy, gdouble *dx, gdouble *dy)
-{
- GtkWidget *widget;
- gdouble scale;
-
- g_return_if_fail (LD_IS_CANVAS (self));
- g_return_if_fail (dx != NULL);
- g_return_if_fail (dy != NULL);
-
- widget = GTK_WIDGET (self);
- scale = ld_canvas_get_scale_in_px (self);
-
- /* We know diagram coordinates of the center of the canvas, so we may
- * translate the given X and Y coordinates to this center and then scale
- * them by dividing them by the current scale.
- */
- *dx = self->priv->x + (wx - (widget->allocation.width * 0.5)) / scale;
- *dy = self->priv->y + (wy - (widget->allocation.height * 0.5)) / scale;
-}
-
-/**
- * ld_canvas_diagram_to_widget_coords:
- * @self: An #LdCanvas object.
- * @dx: The X coordinate to be translated.
- * @dy: The Y coordinate to be translated.
- * @wx: (out): The translated X coordinate.
- * @wy: (out): The translated Y coordinate.
- *
- * Translate diagram coordinates into canvas coordinates.
- */
-void
-ld_canvas_diagram_to_widget_coords (LdCanvas *self,
- gdouble dx, gdouble dy, gdouble *wx, gdouble *wy)
-{
- GtkWidget *widget;
- gdouble scale;
-
- g_return_if_fail (LD_IS_CANVAS (self));
- g_return_if_fail (wx != NULL);
- g_return_if_fail (wy != NULL);
-
- widget = GTK_WIDGET (self);
- scale = ld_canvas_get_scale_in_px (self);
-
- /* Just the reversal of ld_canvas_widget_to_diagram_coords(). */
- *wx = scale * (dx - self->priv->x) + 0.5 * widget->allocation.width;
- *wy = scale * (dy - self->priv->y) + 0.5 * widget->allocation.height;
-}
-
-/**
- * ld_canvas_get_zoom:
- * @self: An #LdCanvas object.
- *
- * Return value: Zoom of the canvas.
- */
-gdouble
-ld_canvas_get_zoom (LdCanvas *self)
-{
- g_return_val_if_fail (LD_IS_CANVAS (self), -1);
- return self->priv->zoom;
-}
-
-/**
- * ld_canvas_set_zoom:
- * @self: An #LdCanvas object.
- * @zoom: The zoom.
- *
- * Set zoom of the canvas.
- */
-void
-ld_canvas_set_zoom (LdCanvas *self, gdouble zoom)
-{
- gdouble clamped_zoom;
-
- g_return_if_fail (LD_IS_CANVAS (self));
-
- clamped_zoom = CLAMP (zoom, ZOOM_MIN, ZOOM_MAX);
- if (self->priv->zoom == clamped_zoom)
- return;
-
- self->priv->zoom = clamped_zoom;
-
- simulate_motion (self);
- update_adjustments (self);
- gtk_widget_queue_draw (GTK_WIDGET (self));
-
- g_object_notify (G_OBJECT (self), "zoom");
-}
-
-
-/* ===== Operations ======================================================== */
-
-static void
-ld_canvas_real_cancel_operation (LdCanvas *self)
-{
- g_return_if_fail (LD_IS_CANVAS (self));
-
- if (self->priv->operation)
- {
- if (self->priv->operation_end)
- self->priv->operation_end (self);
- self->priv->operation = OPER_0;
- self->priv->operation_end = NULL;
- }
-}
-
-/**
- * ld_canvas_add_object_begin:
- * @self: An #LdCanvas object.
- * @object: (transfer full): The object to be added to the diagram.
- *
- * Begin an operation for adding an object into the diagram.
- */
-void
-ld_canvas_add_object_begin (LdCanvas *self, LdDiagramObject *object)
-{
- AddObjectData *data;
-
- g_return_if_fail (LD_IS_CANVAS (self));
- g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
-
- ld_canvas_real_cancel_operation (self);
-
- self->priv->operation = OPER_ADD_OBJECT;
- self->priv->operation_end = ld_canvas_add_object_end;
-
- data = &OPER_DATA (self, add_object);
- data->object = object;
-}
-
-static void
-ld_canvas_add_object_end (LdCanvas *self)
-{
- AddObjectData *data;
-
- data = &OPER_DATA (self, add_object);
- if (data->object)
- {
- queue_object_draw (self, data->object);
- g_object_unref (data->object);
- data->object = NULL;
- }
-}
-
-
-/* ===== Events, rendering ================================================= */
-
-static void
-ld_canvas_color_set (LdCanvasColor *color,
- gdouble r, gdouble g, gdouble b, gdouble a)
-{
- color->r = r;
- color->g = g;
- color->b = b;
- color->a = a;
-}
-
-static void
-ld_canvas_color_apply (LdCanvasColor *color, cairo_t *cr)
-{
- cairo_set_source_rgba (cr, color->r, color->g, color->b, color->a);
-}
-
-static void
-move_object_to_coords (LdCanvas *self, LdDiagramObject *object,
- gdouble x, gdouble y)
-{
- gdouble dx, dy;
-
- ld_canvas_widget_to_diagram_coords (self, x, y, &dx, &dy);
- ld_diagram_object_set_x (object, floor (dx + 0.5));
- ld_diagram_object_set_y (object, floor (dy + 0.5));
-}
-
-static LdDiagramObject *
-get_object_at_coords (LdCanvas *self, gdouble x, gdouble y)
-{
- GList *objects, *iter;
-
- /* Iterate from the top object downwards. */
- objects = (GList *) ld_diagram_get_objects (self->priv->diagram);
- for (iter = objects; iter; iter = g_list_next (iter))
- {
- LdDiagramObject *object;
-
- object = LD_DIAGRAM_OBJECT (iter->data);
- if (object_hit_test (self, object, x, y))
- return object;
- }
- return NULL;
-}
-
-static gboolean
-is_object_selected (LdCanvas *self, LdDiagramObject *object)
-{
- return g_list_find (ld_diagram_get_selection (self->priv->diagram),
- object) != NULL;
-}
-
-static LdSymbol *
-resolve_diagram_symbol (LdCanvas *self, LdDiagramSymbol *diagram_symbol)
-{
- if (!self->priv->library)
- return NULL;
-
- return ld_library_find_symbol (self->priv->library,
- ld_diagram_symbol_get_class (diagram_symbol));
-}
-
-static gboolean
-get_symbol_area (LdCanvas *self, LdDiagramSymbol *symbol, LdRectangle *rect)
-{
- LdDiagramObject *object;
- gdouble object_x, object_y;
- LdSymbol *library_symbol;
- LdRectangle area;
- gdouble x1, x2;
- gdouble y1, y2;
-
- object = LD_DIAGRAM_OBJECT (symbol);
- object_x = ld_diagram_object_get_x (object);
- object_y = ld_diagram_object_get_y (object);
-
- library_symbol = resolve_diagram_symbol (self, symbol);
- if (library_symbol)
- ld_symbol_get_area (library_symbol, &area);
- else
- return FALSE;
-
- /* TODO: Rotate the rectangle for other orientations. */
- ld_canvas_diagram_to_widget_coords (self,
- object_x + area.x,
- object_y + area.y,
- &x1, &y1);
- ld_canvas_diagram_to_widget_coords (self,
- object_x + area.x + area.width,
- object_y + area.y + area.height,
- &x2, &y2);
-
- rect->x = x1;
- rect->y = y1;
- rect->width = x2 - x1;
- rect->height = y2 - y1;
- return TRUE;
-}
-
-static gboolean
-get_symbol_clip_area (LdCanvas *self, LdDiagramSymbol *symbol,
- LdRectangle *rect)
-{
- LdRectangle object_rect;
-
- if (!get_object_area (self, LD_DIAGRAM_OBJECT (symbol), &object_rect))
- return FALSE;
-
- *rect = object_rect;
- ld_rectangle_extend (rect, SYMBOL_CLIP_TOLERANCE);
- return TRUE;
-}
-
-static gboolean
-get_object_area (LdCanvas *self, LdDiagramObject *object, LdRectangle *rect)
-{
- if (LD_IS_DIAGRAM_SYMBOL (object))
- return get_symbol_area (self, LD_DIAGRAM_SYMBOL (object), rect);
- return FALSE;
-}
-
-static gboolean
-object_hit_test (LdCanvas *self, LdDiagramObject *object, gdouble x, gdouble y)
-{
- LdRectangle rect;
-
- if (!get_object_area (self, object, &rect))
- return FALSE;
- ld_rectangle_extend (&rect, OBJECT_BORDER_TOLERANCE);
- return ld_rectangle_contains (&rect, x, y);
-}
-
-static void
-check_terminals (LdCanvas *self, gdouble x, gdouble y)
-{
- GList *objects, *iter;
- LdDiagramSymbol *closest_symbol = NULL;
- gdouble closest_distance = TERMINAL_HOVER_TOLERANCE;
- LdPoint closest_terminal;
-
- objects = (GList *) ld_diagram_get_objects (self->priv->diagram);
- for (iter = objects; iter; iter = g_list_next (iter))
- {
- LdDiagramObject *diagram_object;
- gdouble object_x, object_y;
- LdDiagramSymbol *diagram_symbol;
- LdSymbol *symbol;
- const LdPointArray *terminals;
- gint i;
-
- if (!LD_IS_DIAGRAM_SYMBOL (iter->data))
- continue;
-
- diagram_symbol = LD_DIAGRAM_SYMBOL (iter->data);
- symbol = resolve_diagram_symbol (self, diagram_symbol);
- if (!symbol)
- continue;
-
- diagram_object = LD_DIAGRAM_OBJECT (iter->data);
- object_x = ld_diagram_object_get_x (diagram_object);
- object_y = ld_diagram_object_get_y (diagram_object);
-
- terminals = ld_symbol_get_terminals (symbol);
-
- for (i = 0; i < terminals->num_points; i++)
- {
- LdPoint cur_term;
- gdouble distance;
-
- cur_term = terminals->points[i];
- cur_term.x += object_x;
- cur_term.y += object_y;
- ld_canvas_diagram_to_widget_coords (self,
- cur_term.x, cur_term.y, &cur_term.x, &cur_term.y);
-
- distance = ld_point_distance (&cur_term, x, y);
- if (distance <= closest_distance)
- {
- closest_symbol = diagram_symbol;
- closest_distance = distance;
- closest_terminal = cur_term;
- }
- }
- }
-
- hide_terminals (self);
-
- if (closest_symbol)
- {
- self->priv->terminal_highlighted = TRUE;
- self->priv->terminal = closest_terminal;
- queue_terminal_draw (self, &closest_terminal);
- }
-}
-
-static void
-hide_terminals (LdCanvas *self)
-{
- if (self->priv->terminal_highlighted)
- {
- self->priv->terminal_highlighted = FALSE;
- queue_terminal_draw (self, &self->priv->terminal);
- }
-}
-
-static void
-queue_draw (LdCanvas *self, LdRectangle *rect)
-{
- LdRectangle area;
-
- area = *rect;
- ld_rectangle_extend (&area, QUEUE_DRAW_EXTEND);
- gtk_widget_queue_draw_area (GTK_WIDGET (self),
- area.x, area.y, area.width, area.height);
-}
-
-static void
-queue_object_draw (LdCanvas *self, LdDiagramObject *object)
-{
- if (LD_IS_DIAGRAM_SYMBOL (object))
- {
- LdRectangle rect;
-
- if (!get_symbol_clip_area (self, LD_DIAGRAM_SYMBOL (object), &rect))
- return;
- queue_draw (self, &rect);
- }
-}
-
-static void
-queue_terminal_draw (LdCanvas *self, LdPoint *terminal)
-{
- LdRectangle rect;
-
- rect.x = terminal->x - TERMINAL_RADIUS;
- rect.y = terminal->y - TERMINAL_RADIUS;
- rect.width = 2 * TERMINAL_RADIUS;
- rect.height = 2 * TERMINAL_RADIUS;
- queue_draw (self, &rect);
-}
-
-static void
-simulate_motion (LdCanvas *self)
-{
- GdkEventMotion event;
- GtkWidget *widget;
- gint x, y;
- GdkModifierType state;
-
- widget = GTK_WIDGET (self);
-
- if (gdk_window_get_pointer (widget->window, &x, &y, &state)
- != widget->window)
- return;
-
- memset (&event, 0, sizeof (event));
- event.type = GDK_MOTION_NOTIFY;
- event.window = widget->window;
- event.x = x;
- event.y = y;
- event.state = state;
-
- on_motion_notify (widget, &event, NULL);
-}
-
-static gboolean
-on_motion_notify (GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
-{
- LdCanvas *self;
-
- self = LD_CANVAS (widget);
- switch (self->priv->operation)
- {
- AddObjectData *data;
-
- case OPER_ADD_OBJECT:
- data = &OPER_DATA (self, add_object);
- data->visible = TRUE;
-
- queue_object_draw (self, data->object);
- move_object_to_coords (self, data->object, event->x, event->y);
- queue_object_draw (self, data->object);
- break;
- case OPER_0:
- check_terminals (self, event->x, event->y);
- break;
- }
- return FALSE;
-}
-
-static gboolean
-on_leave_notify (GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
-{
- LdCanvas *self;
-
- self = LD_CANVAS (widget);
- switch (self->priv->operation)
- {
- AddObjectData *data;
-
- case OPER_ADD_OBJECT:
- data = &OPER_DATA (self, add_object);
- data->visible = FALSE;
-
- queue_object_draw (self, data->object);
- break;
- }
- return FALSE;
-}
-
-static gboolean
-on_button_press (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
-{
- LdCanvas *self;
-
- if (!gtk_widget_has_focus (widget))
- gtk_widget_grab_focus (widget);
-
- self = LD_CANVAS (widget);
- switch (self->priv->operation)
- {
- AddObjectData *data;
-
- case OPER_ADD_OBJECT:
- data = &OPER_DATA (self, add_object);
-
- queue_object_draw (self, data->object);
- move_object_to_coords (self, data->object, event->x, event->y);
-
- if (self->priv->diagram)
- ld_diagram_insert_object (self->priv->diagram, data->object, 0);
-
- /* XXX: "cancel" causes confusion. */
- ld_canvas_real_cancel_operation (self);
- break;
- case OPER_0:
- if (self->priv->diagram)
- {
- LdDiagramObject *object;
-
- if (event->state != GDK_SHIFT_MASK)
- ld_diagram_unselect_all (self->priv->diagram);
-
- object = get_object_at_coords (self, event->x, event->y);
- if (object)
- ld_diagram_selection_add (self->priv->diagram, object, 0);
- }
- break;
- }
- return FALSE;
-}
-
-static gboolean
-on_button_release (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
-{
- return FALSE;
-}
-
-static gboolean
-on_scroll (GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
-{
- gdouble prev_x, prev_y;
- gdouble new_x, new_y;
- LdCanvas *self;
-
- self = LD_CANVAS (widget);
-
- ld_canvas_widget_to_diagram_coords (self,
- event->x, event->y, &prev_x, &prev_y);
-
- switch (event->direction)
- {
- case GDK_SCROLL_UP:
- ld_canvas_set_zoom (self, self->priv->zoom * ZOOM_WHEEL_STEP);
- break;
- case GDK_SCROLL_DOWN:
- ld_canvas_set_zoom (self, self->priv->zoom / ZOOM_WHEEL_STEP);
- break;
- default:
- return FALSE;
- }
-
- ld_canvas_widget_to_diagram_coords (self,
- event->x, event->y, &new_x, &new_y);
-
- /* Focus on the point under the cursor. */
- self->priv->x += prev_x - new_x;
- self->priv->y += prev_y - new_y;
-
- check_terminals (self, event->x, event->y);
- return TRUE;
-}
-
-static gboolean
-on_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
-{
- DrawData data;
-
- data.cr = gdk_cairo_create (widget->window);
- data.self = LD_CANVAS (widget);
- data.scale = ld_canvas_get_scale_in_px (data.self);
- data.exposed_rect.x = event->area.x;
- data.exposed_rect.y = event->area.y;
- data.exposed_rect.width = event->area.width;
- data.exposed_rect.height = event->area.height;
-
- gdk_cairo_rectangle (data.cr, &event->area);
- cairo_clip (data.cr);
-
- ld_canvas_color_apply (COLOR_GET (data.self, COLOR_BASE), data.cr);
- cairo_paint (data.cr);
-
- draw_grid (widget, &data);
- draw_diagram (widget, &data);
- draw_terminal (widget, &data);
-
- cairo_destroy (data.cr);
- return FALSE;
-}
-
-static void
-draw_grid (GtkWidget *widget, DrawData *data)
-{
- gdouble grid_step;
- gdouble x_init, y_init;
- gdouble x, y;
-
- grid_step = data->scale;
- while (grid_step < 5)
- grid_step *= 5;
-
- ld_canvas_color_apply (COLOR_GET (data->self, COLOR_GRID), data->cr);
- cairo_set_line_width (data->cr, 1);
- cairo_set_line_cap (data->cr, CAIRO_LINE_CAP_ROUND);
-
- /* Get coordinates of the top-left point. */
- ld_canvas_widget_to_diagram_coords (data->self,
- data->exposed_rect.x, data->exposed_rect.y, &x_init, &y_init);
- ld_canvas_diagram_to_widget_coords (data->self,
- ceil (x_init), ceil (y_init), &x_init, &y_init);
-
- /* Iterate over all the points. */
- for (x = x_init; x <= data->exposed_rect.x + data->exposed_rect.width;
- x += grid_step)
- {
- for (y = y_init; y <= data->exposed_rect.y + data->exposed_rect.height;
- y += grid_step)
- {
- cairo_move_to (data->cr, x, y);
- cairo_line_to (data->cr, x, y);
- }
- }
- cairo_stroke (data->cr);
-}
-
-static void
-draw_terminal (GtkWidget *widget, DrawData *data)
-{
- LdCanvasPrivate *priv;
-
- priv = data->self->priv;
- if (!priv->terminal_highlighted)
- return;
-
- ld_canvas_color_apply (COLOR_GET (data->self, COLOR_TERMINAL), data->cr);
- cairo_set_line_width (data->cr, 1);
-
- cairo_new_path (data->cr);
- cairo_arc (data->cr, priv->terminal.x, priv->terminal.y,
- TERMINAL_RADIUS, 0, 2 * G_PI);
- cairo_stroke (data->cr);
-}
-
-static void
-draw_diagram (GtkWidget *widget, DrawData *data)
-{
- GList *objects, *iter;
-
- if (!data->self->priv->diagram)
- return;
-
- cairo_save (data->cr);
- cairo_set_line_width (data->cr, 1 / data->scale);
-
- /* Draw objects from the diagram, from bottom to top. */
- objects = (GList *) ld_diagram_get_objects (data->self->priv->diagram);
- for (iter = g_list_last (objects); iter; iter = g_list_previous (iter))
- draw_object (LD_DIAGRAM_OBJECT (iter->data), data);
-
- switch (data->self->priv->operation)
- {
- AddObjectData *op_data;
-
- case OPER_ADD_OBJECT:
- op_data = &OPER_DATA (data->self, add_object);
- if (op_data->visible)
- draw_object (op_data->object, data);
- break;
- }
-
- cairo_restore (data->cr);
-}
-
-static void
-draw_object (LdDiagramObject *diagram_object, DrawData *data)
-{
- g_return_if_fail (LD_IS_DIAGRAM_OBJECT (diagram_object));
- g_return_if_fail (data != NULL);
-
- if (is_object_selected (data->self, diagram_object))
- ld_canvas_color_apply (COLOR_GET (data->self,
- COLOR_SELECTION), data->cr);
- else
- ld_canvas_color_apply (COLOR_GET (data->self,
- COLOR_OBJECT), data->cr);
-
- if (LD_IS_DIAGRAM_SYMBOL (diagram_object))
- draw_symbol (LD_DIAGRAM_SYMBOL (diagram_object), data);
-}
-
-static void
-draw_symbol (LdDiagramSymbol *diagram_symbol, DrawData *data)
-{
- LdSymbol *symbol;
- LdRectangle clip_rect;
- gdouble x, y;
-
- symbol = resolve_diagram_symbol (data->self, diagram_symbol);
-
- /* TODO: Resolve this better; draw a cross or whatever. */
- if (!symbol)
- {
- g_warning ("Cannot find symbol %s in the library.",
- ld_diagram_symbol_get_class (diagram_symbol));
- return;
- }
-
- if (!get_symbol_clip_area (data->self, diagram_symbol, &clip_rect)
- || !ld_rectangle_intersects (&clip_rect, &data->exposed_rect))
- return;
-
- cairo_save (data->cr);
-
- cairo_rectangle (data->cr, clip_rect.x, clip_rect.y,
- clip_rect.width, clip_rect.height);
- cairo_clip (data->cr);
-
- /* TODO: Rotate the space for other orientations. */
- ld_canvas_diagram_to_widget_coords (data->self,
- ld_diagram_object_get_x (LD_DIAGRAM_OBJECT (diagram_symbol)),
- ld_diagram_object_get_y (LD_DIAGRAM_OBJECT (diagram_symbol)),
- &x, &y);
- cairo_translate (data->cr, x, y);
- cairo_scale (data->cr, data->scale, data->scale);
- ld_symbol_draw (symbol, data->cr);
-
- cairo_restore (data->cr);
-}
diff --git a/src/ld-canvas.h b/src/ld-canvas.h
deleted file mode 100644
index 702f2fe..0000000
--- a/src/ld-canvas.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * ld-canvas.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_CANVAS_H__
-#define __LD_CANVAS_H__
-
-G_BEGIN_DECLS
-
-
-#define LD_TYPE_CANVAS (ld_canvas_get_type ())
-#define LD_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), LD_TYPE_CANVAS, LdCanvas))
-#define LD_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
- ((klass), LD_TYPE_CANVAS, LdCanvasClass))
-#define LD_IS_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), LD_TYPE_CANVAS))
-#define LD_IS_CANVAS_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((klass), LD_TYPE_CANVAS))
-#define LD_CANVAS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), LD_CANVAS, LdCanvasClass))
-
-typedef struct _LdCanvas LdCanvas;
-typedef struct _LdCanvasPrivate LdCanvasPrivate;
-typedef struct _LdCanvasClass LdCanvasClass;
-
-
-/**
- * LdCanvas:
- */
-struct _LdCanvas
-{
-/*< private >*/
- GtkDrawingArea parent_instance;
- LdCanvasPrivate *priv;
-
-/*< public >*/
-};
-
-struct _LdCanvasClass
-{
-/*< private >*/
- GtkDrawingAreaClass parent_class;
-
- guint cancel_operation_signal;
-
- void (*set_scroll_adjustments) (LdCanvas *self,
- GtkAdjustment *horizontal, GtkAdjustment *vertical);
- void (*cancel_operation) (LdCanvas *self);
-};
-
-
-/**
- * LD_CANVAS_BASE_UNIT:
- *
- * Length of the base unit in milimetres.
- */
-#define LD_CANVAS_BASE_UNIT_LENGTH 2.5
-
-
-GType ld_canvas_get_type (void) G_GNUC_CONST;
-
-LdCanvas *ld_canvas_new (void);
-
-void ld_canvas_set_diagram (LdCanvas *self, LdDiagram *diagram);
-LdDiagram *ld_canvas_get_diagram (LdCanvas *self);
-void ld_canvas_set_library (LdCanvas *self, LdLibrary *library);
-LdLibrary *ld_canvas_get_library (LdCanvas *self);
-
-void ld_canvas_widget_to_diagram_coords (LdCanvas *self,
- gdouble wx, gdouble wy, gdouble *dx, gdouble *dy);
-void ld_canvas_diagram_to_widget_coords (LdCanvas *self,
- gdouble dx, gdouble dy, gdouble *wx, gdouble *wy);
-
-gdouble ld_canvas_get_zoom (LdCanvas *self);
-void ld_canvas_set_zoom (LdCanvas *self, gdouble zoom);
-
-void ld_canvas_add_object_begin (LdCanvas *self, LdDiagramObject *object);
-
-/* TODO: The rest of the interface. */
-
-
-G_END_DECLS
-
-#endif /* ! __LD_CANVAS_H__ */
diff --git a/src/ld-diagram-object.c b/src/ld-diagram-object.c
deleted file mode 100644
index f43e620..0000000
--- a/src/ld-diagram-object.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * ld-diagram-object.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include "liblogdiag.h"
-#include "config.h"
-
-
-/**
- * SECTION:ld-diagram-object
- * @short_description: A diagram object.
- * @see_also: #LdDiagram, #LdCanvas
- *
- * #LdDiagramObject represents an object in an #LdDiagram.
- */
-
-/*
- * LdDiagramObjectPrivate:
- * @x: The X coordinate of this object.
- * @y: The Y coordinate of this object.
- */
-struct _LdDiagramObjectPrivate
-{
- gdouble x;
- gdouble y;
-};
-
-enum
-{
- PROP_0,
- PROP_X,
- PROP_Y
-};
-
-static void ld_diagram_object_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec);
-static void ld_diagram_object_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec);
-
-
-G_DEFINE_ABSTRACT_TYPE (LdDiagramObject, ld_diagram_object, G_TYPE_OBJECT);
-
-static void
-ld_diagram_object_class_init (LdDiagramObjectClass *klass)
-{
- GObjectClass *object_class;
- GParamSpec *pspec;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->get_property = ld_diagram_object_get_property;
- object_class->set_property = ld_diagram_object_set_property;
-
-/**
- * LdDiagramObject:x:
- *
- * The X coordinate of the object.
- */
- pspec = g_param_spec_double ("x", "X",
- "The X coordinate of this object.",
- -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_X, pspec);
-
-/**
- * LdDiagramObject:y:
- *
- * The Y coordinate of the object.
- */
- pspec = g_param_spec_double ("y", "Y",
- "The Y coordinate of this object.",
- -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_Y, pspec);
-
- g_type_class_add_private (klass, sizeof (LdDiagramObjectPrivate));
-}
-
-static void
-ld_diagram_object_init (LdDiagramObject *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE
- (self, LD_TYPE_DIAGRAM_OBJECT, LdDiagramObjectPrivate);
-}
-
-static void
-ld_diagram_object_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- LdDiagramObject *self;
-
- self = LD_DIAGRAM_OBJECT (object);
- switch (property_id)
- {
- case PROP_X:
- g_value_set_double (value, ld_diagram_object_get_x (self));
- break;
- case PROP_Y:
- g_value_set_double (value, ld_diagram_object_get_y (self));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-ld_diagram_object_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- LdDiagramObject *self;
-
- self = LD_DIAGRAM_OBJECT (object);
- switch (property_id)
- {
- case PROP_X:
- ld_diagram_object_set_x (self, g_value_get_double (value));
- break;
- case PROP_Y:
- ld_diagram_object_set_y (self, g_value_get_double (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-
-/**
- * ld_diagram_object_get_x:
- * @self: An #LdDiagramObject object.
- *
- * Return value: The X coordinate of the object.
- */
-gdouble
-ld_diagram_object_get_x (LdDiagramObject *self)
-{
- g_return_val_if_fail (LD_IS_DIAGRAM_OBJECT (self), 0);
- return self->priv->x;
-}
-
-/**
- * ld_diagram_object_get_y:
- * @self: An #LdDiagramObject object.
- *
- * Return value: The Y coordinate of the object.
- */
-gdouble
-ld_diagram_object_get_y (LdDiagramObject *self)
-{
- g_return_val_if_fail (LD_IS_DIAGRAM_OBJECT (self), 0);
- return self->priv->y;
-}
-
-/**
- * ld_diagram_object_set_x:
- * @self: An #LdDiagramObject object.
- * @x: The new X coordinate.
- *
- * Set the X coordinate of the object.
- */
-void
-ld_diagram_object_set_x (LdDiagramObject *self, gdouble x)
-{
- g_return_if_fail (LD_IS_DIAGRAM_OBJECT (self));
- self->priv->x = x;
-
- g_object_notify (G_OBJECT (self), "x");
-}
-
-/**
- * ld_diagram_object_set_y:
- * @self: An #LdDiagramObject object.
- * @y: The new Y coordinate.
- *
- * Set the Y coordinate of the object.
- */
-void
-ld_diagram_object_set_y (LdDiagramObject *self, gdouble y)
-{
- g_return_if_fail (LD_IS_DIAGRAM_OBJECT (self));
- self->priv->y = y;
-
- g_object_notify (G_OBJECT (self), "y");
-}
diff --git a/src/ld-diagram-object.h b/src/ld-diagram-object.h
deleted file mode 100644
index c727602..0000000
--- a/src/ld-diagram-object.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * ld-diagram-object.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_DIAGRAM_OBJECT_H__
-#define __LD_DIAGRAM_OBJECT_H__
-
-G_BEGIN_DECLS
-
-
-#define LD_TYPE_DIAGRAM_OBJECT (ld_diagram_object_get_type ())
-#define LD_DIAGRAM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), LD_TYPE_DIAGRAM_OBJECT, LdDiagramObject))
-#define LD_DIAGRAM_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
- ((klass), LD_TYPE_DIAGRAM_OBJECT, LdDiagramObjectClass))
-#define LD_IS_DIAGRAM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), LD_TYPE_DIAGRAM_OBJECT))
-#define LD_IS_DIAGRAM_OBJECT_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((klass), LD_TYPE_DIAGRAM_OBJECT))
-#define LD_DIAGRAM_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), LD_DIAGRAM_OBJECT, LdDiagramObjectClass))
-
-typedef struct _LdDiagramObject LdDiagramObject;
-typedef struct _LdDiagramObjectPrivate LdDiagramObjectPrivate;
-typedef struct _LdDiagramObjectClass LdDiagramObjectClass;
-
-
-/**
- * LdDiagramObject:
- */
-struct _LdDiagramObject
-{
-/*< private >*/
- GObject parent_instance;
- LdDiagramObjectPrivate *priv;
-};
-
-/**
- * LdDiagramObjectClass:
- */
-struct _LdDiagramObjectClass
-{
-/*< private >*/
- GObjectClass parent_class;
-};
-
-
-GType ld_diagram_object_get_type (void) G_GNUC_CONST;
-
-gdouble ld_diagram_object_get_x (LdDiagramObject *self);
-gdouble ld_diagram_object_get_y (LdDiagramObject *self);
-void ld_diagram_object_set_x (LdDiagramObject *self, gdouble x);
-void ld_diagram_object_set_y (LdDiagramObject *self, gdouble y);
-
-
-G_END_DECLS
-
-#endif /* ! __LD_DIAGRAM_OBJECT_H__ */
-
diff --git a/src/ld-diagram-symbol.c b/src/ld-diagram-symbol.c
deleted file mode 100644
index 3308dbb..0000000
--- a/src/ld-diagram-symbol.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * ld-diagram-symbol.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include "liblogdiag.h"
-#include "config.h"
-
-
-/**
- * SECTION:ld-diagram-symbol
- * @short_description: A symbol object.
- * @see_also: #LdDiagramObject
- *
- * #LdDiagramSymbol is an implementation of #LdDiagramObject.
- */
-
-/*
- * LdDiagramSymbolPrivate:
- * @klass: The class of this symbol.
- */
-struct _LdDiagramSymbolPrivate
-{
- gchar *klass;
-};
-
-enum
-{
- PROP_0,
- PROP_CLASS
-};
-
-static void ld_diagram_symbol_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec);
-static void ld_diagram_symbol_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec);
-static void ld_diagram_symbol_finalize (GObject *gobject);
-
-
-G_DEFINE_TYPE (LdDiagramSymbol, ld_diagram_symbol, LD_TYPE_DIAGRAM_OBJECT);
-
-static void
-ld_diagram_symbol_class_init (LdDiagramSymbolClass *klass)
-{
- GObjectClass *object_class;
- GParamSpec *pspec;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->get_property = ld_diagram_symbol_get_property;
- object_class->set_property = ld_diagram_symbol_set_property;
- object_class->finalize = ld_diagram_symbol_finalize;
-
-/**
- * LdDiagramSymbol:class:
- *
- * The class of this symbol.
- */
- pspec = g_param_spec_string ("class", "Class",
- "The class of this symbol.",
- "", G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_CLASS, pspec);
-
- g_type_class_add_private (klass, sizeof (LdDiagramSymbolPrivate));
-}
-
-static void
-ld_diagram_symbol_init (LdDiagramSymbol *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE
- (self, LD_TYPE_DIAGRAM_SYMBOL, LdDiagramSymbolPrivate);
-}
-
-static void
-ld_diagram_symbol_finalize (GObject *gobject)
-{
- LdDiagramSymbol *self;
-
- self = LD_DIAGRAM_SYMBOL (gobject);
-
- if (self->priv->klass)
- g_free (self->priv->klass);
-
- /* Chain up to the parent class. */
- G_OBJECT_CLASS (ld_diagram_symbol_parent_class)->finalize (gobject);
-}
-
-static void
-ld_diagram_symbol_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- LdDiagramSymbol *self;
-
- self = LD_DIAGRAM_SYMBOL (object);
- switch (property_id)
- {
- case PROP_CLASS:
- g_value_set_string (value, ld_diagram_symbol_get_class (self));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-ld_diagram_symbol_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- LdDiagramSymbol *self;
-
- self = LD_DIAGRAM_SYMBOL (object);
- switch (property_id)
- {
- case PROP_CLASS:
- ld_diagram_symbol_set_class (self, g_value_get_string (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-
-/**
- * ld_diagram_symbol_new:
- * @klass: The class of the new symbol.
- *
- * Return value: A new #LdDiagramSymbol object.
- */
-LdDiagramSymbol *
-ld_diagram_symbol_new (const gchar *klass)
-{
- LdDiagramSymbol *self;
-
- self = g_object_new (LD_TYPE_DIAGRAM_SYMBOL, NULL);
- ld_diagram_symbol_set_class (self, klass);
- return self;
-}
-
-/**
- * ld_diagram_symbol_get_class:
- * @self: An #LdDiagramSymbol object.
- *
- * Return value: The class of the symbol.
- */
-const gchar *
-ld_diagram_symbol_get_class (LdDiagramSymbol *self)
-{
- g_return_val_if_fail (LD_IS_DIAGRAM_SYMBOL (self), NULL);
- return self->priv->klass;
-}
-
-/**
- * ld_diagram_symbol_get_class:
- * @self: An #LdDiagramSymbol object.
- * @klass: The class.
- *
- * Set the class of the symbol.
- */
-void
-ld_diagram_symbol_set_class (LdDiagramSymbol *self, const gchar *klass)
-{
- g_return_if_fail (LD_IS_DIAGRAM_SYMBOL (self));
-
- if (self->priv->klass)
- g_free (self->priv->klass);
- self->priv->klass = g_strdup (klass);
-}
diff --git a/src/ld-diagram-symbol.h b/src/ld-diagram-symbol.h
deleted file mode 100644
index 09d8739..0000000
--- a/src/ld-diagram-symbol.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * ld-diagram-symbol.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_DIAGRAM_SYMBOL_H__
-#define __LD_DIAGRAM_SYMBOL_H__
-
-G_BEGIN_DECLS
-
-
-#define LD_TYPE_DIAGRAM_SYMBOL (ld_diagram_symbol_get_type ())
-#define LD_DIAGRAM_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), LD_TYPE_DIAGRAM_SYMBOL, LdDiagramSymbol))
-#define LD_DIAGRAM_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
- ((klass), LD_TYPE_DIAGRAM_SYMBOL, LdDiagramSymbolClass))
-#define LD_IS_DIAGRAM_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), LD_TYPE_DIAGRAM_SYMBOL))
-#define LD_IS_DIAGRAM_SYMBOL_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((klass), LD_TYPE_DIAGRAM_SYMBOL))
-#define LD_DIAGRAM_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), LD_DIAGRAM_SYMBOL, LdDiagramSymbolClass))
-
-typedef struct _LdDiagramSymbol LdDiagramSymbol;
-typedef struct _LdDiagramSymbolPrivate LdDiagramSymbolPrivate;
-typedef struct _LdDiagramSymbolClass LdDiagramSymbolClass;
-
-
-/**
- * LdDiagramSymbol:
- */
-struct _LdDiagramSymbol
-{
-/*< private >*/
- LdDiagramObject parent_instance;
- LdDiagramSymbolPrivate *priv;
-};
-
-/**
- * LdDiagramSymbolClass:
- */
-struct _LdDiagramSymbolClass
-{
-/*< private >*/
- LdDiagramObjectClass parent_class;
-};
-
-
-GType ld_diagram_symbol_get_type (void) G_GNUC_CONST;
-
-LdDiagramSymbol *ld_diagram_symbol_new (const gchar *klass);
-const gchar *ld_diagram_symbol_get_class (LdDiagramSymbol *self);
-void ld_diagram_symbol_set_class (LdDiagramSymbol *self, const gchar *klass);
-
-
-G_END_DECLS
-
-#endif /* ! __LD_DIAGRAM_SYMBOL_H__ */
-
diff --git a/src/ld-diagram.c b/src/ld-diagram.c
deleted file mode 100644
index 0129e2b..0000000
--- a/src/ld-diagram.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
- * ld-diagram.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include "liblogdiag.h"
-#include "config.h"
-
-
-/**
- * SECTION:ld-diagram
- * @short_description: A diagram object.
- * @see_also: #LdCanvas
- *
- * #LdDiagram is a model used for storing diagrams.
- */
-
-/*
- * LdDiagramPrivate:
- * @modified: Whether the diagram has been modified.
- * @objects: All objects in the diagram.
- * @selection: All currently selected objects.
- * @connections: Connections between objects.
- */
-struct _LdDiagramPrivate
-{
- gboolean modified;
-
- GList *objects;
- GList *selection;
- GList *connections;
-};
-
-enum
-{
- PROP_0,
- PROP_MODIFIED
-};
-
-static void ld_diagram_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec);
-static void ld_diagram_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec);
-static void ld_diagram_dispose (GObject *gobject);
-static void ld_diagram_finalize (GObject *gobject);
-
-static gboolean write_signature (GOutputStream *stream, GError **error);
-
-static void ld_diagram_real_changed (LdDiagram *self);
-static void ld_diagram_clear_internal (LdDiagram *self);
-static void ld_diagram_unselect_all_internal (LdDiagram *self);
-
-
-G_DEFINE_TYPE (LdDiagram, ld_diagram, G_TYPE_OBJECT);
-
-static void
-ld_diagram_class_init (LdDiagramClass *klass)
-{
- GObjectClass *object_class;
- GParamSpec *pspec;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->get_property = ld_diagram_get_property;
- object_class->set_property = ld_diagram_set_property;
- object_class->dispose = ld_diagram_dispose;
- object_class->finalize = ld_diagram_finalize;
-
- klass->changed = ld_diagram_real_changed;
-
-/**
- * LdDiagram:modified:
- *
- * Whether the diagram has been modified.
- */
- pspec = g_param_spec_boolean ("modified", "Modified",
- "Whether the diagram has been modified.",
- FALSE, G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_MODIFIED, pspec);
-
-/**
- * LdDiagram::changed:
- * @diagram: The diagram object.
- *
- * Contents of the diagram have changed.
- */
- klass->changed_signal = g_signal_new
- ("changed", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (LdDiagramClass, changed), NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
-/**
- * LdDiagram::selection-changed:
- * @diagram: The diagram object.
- *
- * The current selection has changed.
- */
- klass->selection_changed_signal = g_signal_new
- ("selection-changed", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (LdDiagramClass, selection_changed), NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
- g_type_class_add_private (klass, sizeof (LdDiagramPrivate));
-}
-
-static void
-ld_diagram_init (LdDiagram *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE
- (self, LD_TYPE_DIAGRAM, LdDiagramPrivate);
-}
-
-static void
-ld_diagram_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- LdDiagram *self;
-
- self = LD_DIAGRAM (object);
- switch (property_id)
- {
- case PROP_MODIFIED:
- g_value_set_boolean (value, ld_diagram_get_modified (self));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-ld_diagram_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- LdDiagram *self;
-
- self = LD_DIAGRAM (object);
- switch (property_id)
- {
- case PROP_MODIFIED:
- ld_diagram_set_modified (self, g_value_get_boolean (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-ld_diagram_dispose (GObject *gobject)
-{
- LdDiagram *self;
-
- self = LD_DIAGRAM (gobject);
- ld_diagram_clear_internal (self);
-
- /* Chain up to the parent class. */
- G_OBJECT_CLASS (ld_diagram_parent_class)->dispose (gobject);
-}
-
-static void
-ld_diagram_finalize (GObject *gobject)
-{
- /* Chain up to the parent class. */
- G_OBJECT_CLASS (ld_diagram_parent_class)->finalize (gobject);
-}
-
-static void
-ld_diagram_real_changed (LdDiagram *self)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self));
-
- ld_diagram_set_modified (self, TRUE);
-}
-
-
-/**
- * ld_diagram_new:
- *
- * Create an instance.
- */
-LdDiagram *
-ld_diagram_new (void)
-{
- return g_object_new (LD_TYPE_DIAGRAM, NULL);
-}
-
-/**
- * ld_diagram_clear:
- * @self: An #LdDiagram object.
- *
- * Clear the whole diagram with it's objects and selection.
- */
-void
-ld_diagram_clear (LdDiagram *self)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self));
-
- ld_diagram_clear_internal (self);
-
- g_signal_emit (self,
- LD_DIAGRAM_GET_CLASS (self)->changed_signal, 0);
-}
-
-/*
- * ld_diagram_clear_internal:
- * @self: An #LdDiagram object.
- *
- * Do the same as ld_diagram_clear() does but don't emit signals.
- */
-static void
-ld_diagram_clear_internal (LdDiagram *self)
-{
- ld_diagram_unselect_all (self);
-
- g_list_free (self->priv->connections);
- self->priv->connections = NULL;
-
- g_list_foreach (self->priv->objects, (GFunc) g_object_unref, NULL);
- g_list_free (self->priv->objects);
- self->priv->objects = NULL;
-}
-
-/**
- * ld_diagram_load_from_file:
- * @self: An #LdDiagram object.
- * @filename: A filename.
- * @error: Return location for a GError, or NULL.
- *
- * Load a file into the diagram.
- *
- * Return value: TRUE if the file could be loaded, FALSE otherwise.
- */
-gboolean
-ld_diagram_load_from_file (LdDiagram *self,
- const gchar *filename, GError **error)
-{
- JsonParser *parser;
- GError *json_error;
-
- g_return_val_if_fail (LD_IS_DIAGRAM (self), FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
-
- /* TODO: Implement loading for real. This is just a stub. */
- parser = json_parser_new ();
-
- json_error = NULL;
- json_parser_load_from_file (parser, filename, &json_error);
- if (json_error)
- {
- g_propagate_error (error, json_error);
- g_object_unref (parser);
- return FALSE;
- }
-
- ld_diagram_clear (self);
- g_object_unref (parser);
- return TRUE;
-}
-
-/**
- * ld_diagram_save_to_file:
- * @self: An #LdDiagram object.
- * @filename: A filename.
- * @error: Return location for a GError, or NULL.
- *
- * Save the diagram into a file.
- *
- * Return value: TRUE if the diagram could be saved, FALSE otherwise.
- */
-gboolean
-ld_diagram_save_to_file (LdDiagram *self,
- const gchar *filename, GError **error)
-{
- GFile *file;
- GFileOutputStream *file_stream;
- JsonGenerator *generator;
- JsonNode *root;
- GError *local_error;
-
- g_return_val_if_fail (LD_IS_DIAGRAM (self), FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
-
- file = g_file_new_for_path (filename);
-
- local_error = NULL;
- file_stream = g_file_replace (file, NULL, FALSE,
- G_FILE_CREATE_NONE, NULL, &local_error);
- g_object_unref (file);
-
- if (local_error)
- {
- g_propagate_error (error, local_error);
- return FALSE;
- }
-
- local_error = NULL;
- write_signature (G_OUTPUT_STREAM (file_stream), &local_error);
- if (local_error)
- {
- g_object_unref (file_stream);
- g_propagate_error (error, local_error);
- return FALSE;
- }
-
- /* TODO: Implement saving for real. This is just a stub. */
- generator = json_generator_new ();
- g_object_set (generator, "pretty", TRUE, NULL);
-
- /* XXX: json-glib dislikes empty objects. */
- root = json_node_new (JSON_NODE_OBJECT);
- json_generator_set_root (generator, root);
- json_node_free (root);
-
- local_error = NULL;
- json_generator_to_stream (generator, G_OUTPUT_STREAM (file_stream),
- NULL, &local_error);
- g_object_unref (file_stream);
- g_object_unref (generator);
-
- if (local_error)
- {
- g_propagate_error (error, local_error);
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-write_signature (GOutputStream *stream, GError **error)
-{
- static const gchar signature[] = "/* logdiag diagram */\n";
- GError *local_error = NULL;
-
- g_output_stream_write (stream, signature, sizeof (signature) - 1,
- NULL, &local_error);
- if (local_error)
- {
- g_propagate_error (error, local_error);
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * ld_diagram_get_modified:
- * @self: An #LdDiagram object.
- *
- * Return value: The modification status of diagram.
- */
-gboolean
-ld_diagram_get_modified (LdDiagram *self)
-{
- g_return_val_if_fail (LD_IS_DIAGRAM (self), FALSE);
- return self->priv->modified;
-}
-
-/**
- * ld_diagram_set_modified:
- * @self: An #LdDiagram object.
- * @value: Whether the diagram has been modified.
- *
- * Set the modification status of diagram.
- */
-void
-ld_diagram_set_modified (LdDiagram *self, gboolean value)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self));
- self->priv->modified = value;
-
- g_object_notify (G_OBJECT (self), "modified");
-}
-
-/**
- * ld_diagram_get_objects:
- * @self: An #LdDiagram object.
- *
- * Get a list of objects in the diagram. Do not modify.
- */
-GList *
-ld_diagram_get_objects (LdDiagram *self)
-{
- g_return_val_if_fail (LD_IS_DIAGRAM (self), NULL);
- return self->priv->objects;
-}
-
-/**
- * ld_diagram_insert_object:
- * @self: An #LdDiagram object.
- * @object: The object to be inserted.
- * @pos: The position at which the object is to be inserted.
- * Negative values will append to the end.
- *
- * Insert an object into the diagram.
- */
-void
-ld_diagram_insert_object (LdDiagram *self, LdDiagramObject *object, gint pos)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self));
- g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
-
- if (!g_list_find (self->priv->objects, object))
- {
- self->priv->objects =
- g_list_insert (self->priv->objects, object, pos);
- g_object_ref (object);
-
- g_signal_emit (self,
- LD_DIAGRAM_GET_CLASS (self)->changed_signal, 0);
- }
-}
-
-/**
- * ld_diagram_remove_object:
- * @self: An #LdDiagram object.
- * @object: The object to be removed.
- *
- * Remove an object from the diagram.
- */
-void
-ld_diagram_remove_object (LdDiagram *self, LdDiagramObject *object)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self));
- g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
-
- if (g_list_find (self->priv->objects, object))
- {
- ld_diagram_selection_remove (self, object);
-
- self->priv->objects = g_list_remove (self->priv->objects, object);
- g_object_unref (object);
-
- g_signal_emit (self,
- LD_DIAGRAM_GET_CLASS (self)->changed_signal, 0);
- }
-}
-
-/**
- * ld_diagram_get_selection:
- * @self: An #LdDiagram object.
- *
- * Get a list of objects that are currently selected in the diagram.
- * Do not modify.
- */
-GList *
-ld_diagram_get_selection (LdDiagram *self)
-{
- g_return_val_if_fail (LD_IS_DIAGRAM (self), NULL);
- return self->priv->selection;
-}
-
-/**
- * ld_diagram_selection_add:
- * @self: An #LdDiagram object.
- * @object: The object to be added to the selection.
- * @pos: The position at which the object is to be inserted.
- * Negative values will append to the end.
- *
- * Add an object to selection.
- */
-void
-ld_diagram_selection_add (LdDiagram *self, LdDiagramObject *object, gint pos)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self));
- g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
-
- g_return_if_fail (g_list_find (self->priv->objects, object) != NULL);
-
- if (!g_list_find (self->priv->selection, object))
- {
- self->priv->selection =
- g_list_insert (self->priv->selection, object, pos);
- g_object_ref (object);
-
- g_signal_emit (self,
- LD_DIAGRAM_GET_CLASS (self)->selection_changed_signal, 0);
- }
-}
-
-/**
- * ld_diagram_selection_remove:
- * @self: An #LdDiagram object.
- * @object: The object to be removed from the selection.
- *
- * Remove an object from the selection.
- */
-void
-ld_diagram_selection_remove (LdDiagram *self, LdDiagramObject *object)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self));
- g_return_if_fail (LD_IS_DIAGRAM_OBJECT (object));
-
- if (g_list_find (self->priv->selection, object))
- {
- self->priv->selection = g_list_remove (self->priv->selection, object);
- g_object_unref (object);
-
- g_signal_emit (self,
- LD_DIAGRAM_GET_CLASS (self)->selection_changed_signal, 0);
- }
-}
-
-/**
- * ld_diagram_select_all:
- * @self: An #LdDiagram object.
- *
- * Include all objects in the document to the selection.
- */
-void
-ld_diagram_select_all (LdDiagram *self)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self));
-
- ld_diagram_unselect_all_internal (self);
-
- self->priv->selection = g_list_copy (self->priv->objects);
- g_list_foreach (self->priv->selection, (GFunc) g_object_ref, NULL);
-
- g_signal_emit (self,
- LD_DIAGRAM_GET_CLASS (self)->selection_changed_signal, 0);
-}
-
-/**
- * ld_diagram_unselect_all:
- * @self: An #LdDiagram object.
- *
- * Remove all objects from the current selection.
- */
-void
-ld_diagram_unselect_all (LdDiagram *self)
-{
- g_return_if_fail (LD_IS_DIAGRAM (self));
-
- ld_diagram_unselect_all_internal (self);
-
- g_signal_emit (self,
- LD_DIAGRAM_GET_CLASS (self)->selection_changed_signal, 0);
-}
-
-static void
-ld_diagram_unselect_all_internal (LdDiagram *self)
-{
- g_list_foreach (self->priv->selection, (GFunc) g_object_unref, NULL);
- g_list_free (self->priv->selection);
- self->priv->selection = NULL;
-}
diff --git a/src/ld-diagram.h b/src/ld-diagram.h
deleted file mode 100644
index f364189..0000000
--- a/src/ld-diagram.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * ld-diagram.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_DIAGRAM_H__
-#define __LD_DIAGRAM_H__
-
-G_BEGIN_DECLS
-
-
-#define LD_TYPE_DIAGRAM (ld_diagram_get_type ())
-#define LD_DIAGRAM(obj) (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), LD_TYPE_DIAGRAM, LdDiagram))
-#define LD_DIAGRAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
- ((klass), LD_TYPE_DIAGRAM, LdDiagramClass))
-#define LD_IS_DIAGRAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), LD_TYPE_DIAGRAM))
-#define LD_IS_DIAGRAM_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((klass), LD_TYPE_DIAGRAM))
-#define LD_DIAGRAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), LD_DIAGRAM, LdDiagramClass))
-
-typedef struct _LdDiagram LdDiagram;
-typedef struct _LdDiagramClass LdDiagramClass;
-typedef struct _LdDiagramPrivate LdDiagramPrivate;
-
-
-/**
- * LdDiagram:
- *
- * A diagram object.
- */
-struct _LdDiagram
-{
-/*< private >*/
- GObject parent_instance;
- LdDiagramPrivate *priv;
-};
-
-struct _LdDiagramClass
-{
-/*< private >*/
- GObjectClass parent_class;
-
- guint changed_signal;
- guint selection_changed_signal;
-
- void (*changed) (LdDiagram *self);
- void (*selection_changed) (LdDiagram *self);
-};
-
-
-GType ld_diagram_get_type (void) G_GNUC_CONST;
-
-LdDiagram *ld_diagram_new (void);
-void ld_diagram_clear (LdDiagram *self);
-gboolean ld_diagram_load_from_file (LdDiagram *self,
- const gchar *filename, GError **error);
-gboolean ld_diagram_save_to_file (LdDiagram *self,
- const gchar *filename, GError **error);
-
-gboolean ld_diagram_get_modified (LdDiagram *self);
-void ld_diagram_set_modified (LdDiagram *self, gboolean value);
-
-GList *ld_diagram_get_objects (LdDiagram *self);
-void ld_diagram_insert_object (LdDiagram *self,
- LdDiagramObject *object, gint pos);
-void ld_diagram_remove_object (LdDiagram *self,
- LdDiagramObject *object);
-
-GList *ld_diagram_get_selection (LdDiagram *self);
-void ld_diagram_selection_add (LdDiagram *self,
- LdDiagramObject *object, gint pos);
-void ld_diagram_selection_remove (LdDiagram *self,
- LdDiagramObject *object);
-
-void ld_diagram_select_all (LdDiagram *self);
-void ld_diagram_unselect_all (LdDiagram *self);
-
-/*
-GList *ld_diagram_get_connections (LdDiagram *self);
-void ld_diagram_connection_add (LdDiagram *self,
- LdConnection *connection, gint pos);
-void ld_diagram_connection_remove (LdDiagram *self,
- LdConnection *connection);
-*/
-
-
-G_END_DECLS
-
-#endif /* ! __LD_DIAGRAM_H__ */
-
diff --git a/src/ld-library.c b/src/ld-library.c
deleted file mode 100644
index 37e2bc9..0000000
--- a/src/ld-library.c
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * ld-library.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include
-
-#include "liblogdiag.h"
-#include "config.h"
-
-
-/**
- * SECTION:ld-library
- * @short_description: A symbol library.
- * @see_also: #LdSymbol, #LdSymbolCategory
- *
- * #LdLibrary is used for loading symbols from their files.
- */
-
-/*
- * LdLibraryPrivate:
- * @lua: State of the scripting language.
- * @children: Child objects of the library.
- */
-struct _LdLibraryPrivate
-{
- LdLua *lua;
- GSList *children;
-};
-
-static void ld_library_finalize (GObject *gobject);
-
-static LdSymbolCategory *load_category (LdLibrary *self,
- const gchar *path, const gchar *name);
-static gboolean load_category_cb (const gchar *base,
- const gchar *filename, gpointer userdata);
-static void load_category_symbol_cb (LdSymbol *symbol, gpointer user_data);
-
-static gchar *read_human_name_from_file (const gchar *filename);
-
-static gboolean foreach_dir (const gchar *path,
- gboolean (*callback) (const gchar *, const gchar *, gpointer),
- gpointer userdata, GError **error);
-static gboolean ld_library_load_cb
- (const gchar *base, const gchar *filename, gpointer userdata);
-
-
-G_DEFINE_TYPE (LdLibrary, ld_library, G_TYPE_OBJECT);
-
-static void
-ld_library_class_init (LdLibraryClass *klass)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = ld_library_finalize;
-
-/**
- * LdLibrary::changed:
- * @library: The library object.
- *
- * Contents of the library have changed.
- */
- klass->changed_signal = g_signal_new
- ("changed", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
- g_type_class_add_private (klass, sizeof (LdLibraryPrivate));
-}
-
-static void
-ld_library_init (LdLibrary *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE
- (self, LD_TYPE_LIBRARY, LdLibraryPrivate);
-
- self->priv->lua = ld_lua_new ();
- self->priv->children = NULL;
-}
-
-static void
-ld_library_finalize (GObject *gobject)
-{
- LdLibrary *self;
-
- self = LD_LIBRARY (gobject);
-
- g_object_unref (self->priv->lua);
-
- g_slist_foreach (self->priv->children, (GFunc) g_object_unref, NULL);
- g_slist_free (self->priv->children);
-
- /* Chain up to the parent class. */
- G_OBJECT_CLASS (ld_library_parent_class)->finalize (gobject);
-}
-
-/**
- * ld_library_new:
- *
- * Create an instance.
- */
-LdLibrary *
-ld_library_new (void)
-{
- return g_object_new (LD_TYPE_LIBRARY, NULL);
-}
-
-/*
- * foreach_dir:
- *
- * Call a user-defined function for each file within a directory.
- */
-static gboolean
-foreach_dir (const gchar *path,
- gboolean (*callback) (const gchar *, const gchar *, gpointer),
- gpointer userdata, GError **error)
-{
- GDir *dir;
- const gchar *item;
-
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (callback != NULL, FALSE);
-
- dir = g_dir_open (path, 0, error);
- if (!dir)
- return FALSE;
-
- while ((item = g_dir_read_name (dir)))
- {
- gchar *filename;
-
- filename = g_build_filename (path, item, NULL);
- if (!callback (item, filename, userdata))
- break;
- g_free (filename);
- }
- g_dir_close (dir);
- return TRUE;
-}
-
-/*
- * LoadCategoryData:
- *
- * Data shared between load_category() and load_category_cb().
- */
-typedef struct
-{
- LdLibrary *self;
- LdSymbolCategory *cat;
-}
-LoadCategoryData;
-
-/*
- * load_category:
- * @self: An #LdLibrary object.
- * @path: The path to the category.
- * @name: The default name of the category.
- *
- * Loads a category into the library.
- */
-static LdSymbolCategory *
-load_category (LdLibrary *self, const gchar *path, const gchar *name)
-{
- LdSymbolCategory *cat;
- gchar *icon_file, *category_file;
- gchar *human_name;
- LoadCategoryData data;
-
- g_return_val_if_fail (LD_IS_LIBRARY (self), NULL);
- g_return_val_if_fail (path != NULL, NULL);
- g_return_val_if_fail (name != NULL, NULL);
-
- if (!g_file_test (path, G_FILE_TEST_IS_DIR))
- goto load_category_fail_1;
-
- icon_file = g_build_filename (path, "icon.svg", NULL);
- if (!g_file_test (icon_file, G_FILE_TEST_IS_REGULAR))
- {
- g_warning ("The category in %s has no icon.", path);
- goto load_category_fail_2;
- }
-
- category_file = g_build_filename (path, "category.json", NULL);
- human_name = read_human_name_from_file (category_file);
- if (!human_name)
- human_name = g_strdup (name);
-
- cat = ld_symbol_category_new (name, human_name);
- ld_symbol_category_set_image_path (cat, icon_file);
-
- data.self = self;
- data.cat = cat;
- foreach_dir (path, load_category_cb, &data, NULL);
-
- g_free (human_name);
- g_free (category_file);
- g_free (icon_file);
- return cat;
-
-load_category_fail_2:
- g_free (icon_file);
-load_category_fail_1:
- return NULL;
-}
-
-/*
- * load_category_cb:
- *
- * Load script files from a directory into a symbol category.
- */
-static gboolean
-load_category_cb (const gchar *base, const gchar *filename, gpointer userdata)
-{
- LoadCategoryData *data;
-
- g_return_val_if_fail (base != NULL, FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
- g_return_val_if_fail (userdata != NULL, FALSE);
-
- data = (LoadCategoryData *) userdata;
-
- if (ld_lua_check_file (data->self->priv->lua, filename))
- ld_lua_load_file (data->self->priv->lua, filename,
- load_category_symbol_cb, data->cat);
- return TRUE;
-}
-
-/*
- * load_category_symbol_cb:
- *
- * Insert newly registered symbols into the category.
- */
-static void
-load_category_symbol_cb (LdSymbol *symbol, gpointer user_data)
-{
- const gchar *name;
- LdSymbolCategory *cat;
- const GSList *children, *iter;
-
- g_return_if_fail (LD_IS_SYMBOL (symbol));
- g_return_if_fail (LD_IS_SYMBOL_CATEGORY (user_data));
-
- cat = LD_SYMBOL_CATEGORY (user_data);
- name = ld_symbol_get_name (symbol);
-
- /* Check for name collisions with other symbols. */
- children = ld_symbol_category_get_children (cat);
- for (iter = children; iter; iter = iter->next)
- {
- if (!LD_IS_SYMBOL (iter->data))
- continue;
- if (!strcmp (name, ld_symbol_get_name (LD_SYMBOL (iter->data))))
- {
- g_warning ("Attempted to insert multiple '%s' symbols into"
- " category '%s'.", name, ld_symbol_category_get_name (cat));
- return;
- }
- }
- ld_symbol_category_insert_child (cat, G_OBJECT (symbol), -1);
-}
-
-/*
- * read_human_name_from_file:
- * @filename: Location of the JSON file.
- *
- * Read the human name of the processed category.
- */
-static gchar *
-read_human_name_from_file (const gchar *filename)
-{
- const gchar *const *lang;
- JsonParser *parser;
- JsonNode *root;
- JsonObject *object;
- GError *error;
-
- g_return_val_if_fail (filename != NULL, NULL);
-
- parser = json_parser_new ();
- error = NULL;
- if (!json_parser_load_from_file (parser, filename, &error))
- {
- g_warning ("%s", error->message);
- g_error_free (error);
- goto read_human_name_from_file_end;
- }
-
- root = json_parser_get_root (parser);
- if (!JSON_NODE_HOLDS_OBJECT (root))
- {
- g_warning ("Failed to parse '%s': %s", filename,
- "The root node is not an object.");
- goto read_human_name_from_file_end;
- }
-
- object = json_node_get_object (root);
- for (lang = g_get_language_names (); *lang; lang++)
- {
- const gchar *member;
-
- if (!json_object_has_member (object, *lang))
- continue;
- member = json_object_get_string_member (object, *lang);
-
- if (member != NULL)
- {
- gchar *result;
-
- result = g_strdup (member);
- g_object_unref (parser);
- return result;
- }
- }
-
-read_human_name_from_file_end:
- g_object_unref (parser);
- return NULL;
-}
-
-/*
- * LibraryLoadData:
- *
- * Data shared between ld_library_load() and ld_library_load_cb().
- */
-typedef struct
-{
- LdLibrary *self;
- gboolean changed;
-}
-LibraryLoadData;
-
-/**
- * ld_library_load:
- * @self: An #LdLibrary object.
- * @directory: A directory to be loaded.
- *
- * Load the contents of a directory into the library.
- */
-gboolean
-ld_library_load (LdLibrary *self, const gchar *directory)
-{
- LibraryLoadData data;
-
- g_return_val_if_fail (LD_IS_LIBRARY (self), FALSE);
- g_return_val_if_fail (directory != NULL, FALSE);
-
- data.self = self;
- data.changed = FALSE;
- foreach_dir (directory, ld_library_load_cb, &data, NULL);
-
- if (data.changed)
- g_signal_emit (self, LD_LIBRARY_GET_CLASS (self)->changed_signal, 0);
-
- return TRUE;
-}
-
-/*
- * ld_library_load_cb:
- *
- * A callback that's called for each file in the root directory.
- */
-static gboolean
-ld_library_load_cb (const gchar *base, const gchar *filename, gpointer userdata)
-{
- LdSymbolCategory *cat;
- LibraryLoadData *data;
-
- g_return_val_if_fail (base != NULL, FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
- g_return_val_if_fail (userdata != NULL, FALSE);
-
- data = (LibraryLoadData *) userdata;
-
- cat = load_category (data->self, filename, base);
- if (cat)
- ld_library_insert_child (data->self, G_OBJECT (cat), -1);
-
- data->changed = TRUE;
- return TRUE;
-}
-
-/**
- * ld_library_find_symbol:
- * @self: An #LdLibrary object.
- * @identifier: An identifier of the symbol to be searched for.
- *
- * Search for a symbol in the library.
- *
- * Return value: A symbol object if found, NULL otherwise.
- */
-/* XXX: With this level of indentation, this function is really ugly. */
-LdSymbol *
-ld_library_find_symbol (LdLibrary *self, const gchar *identifier)
-{
- gchar **id_el_start, **id_el;
- const GSList *list, *list_el;
-
- g_return_val_if_fail (LD_IS_LIBRARY (self), NULL);
- g_return_val_if_fail (identifier != NULL, NULL);
-
- id_el_start = g_strsplit (identifier, LD_LIBRARY_IDENTIFIER_SEPARATOR, 0);
- if (!id_el_start)
- return NULL;
-
- list = ld_library_get_children (self);
- for (id_el = id_el_start; id_el[0]; id_el++)
- {
- LdSymbolCategory *cat;
- LdSymbol *symbol;
- gboolean found = FALSE;
-
- for (list_el = list; list_el; list_el = g_slist_next (list_el))
- {
- /* If the current identifier element is a category (not last)
- * and this list element is a category.
- */
- if (id_el[1] && LD_IS_SYMBOL_CATEGORY (list_el->data))
- {
- cat = LD_SYMBOL_CATEGORY (list_el->data);
- if (strcmp (id_el[0], ld_symbol_category_get_name (cat)))
- continue;
-
- list = ld_symbol_category_get_children (cat);
- found = TRUE;
- break;
- }
- /* If the current identifier element is a symbol (last)
- * and this list element is a symbol.
- */
- else if (!id_el[1] && LD_IS_SYMBOL (list_el->data))
- {
- symbol = LD_SYMBOL (list_el->data);
- if (strcmp (id_el[0], ld_symbol_get_name (symbol)))
- continue;
-
- g_strfreev (id_el_start);
- return symbol;
- }
- }
-
- if (!found)
- break;
- }
- g_strfreev (id_el_start);
- return NULL;
-}
-
-/**
- * ld_library_clear:
- * @self: An #LdLibrary object.
- *
- * Clear all the contents.
- */
-void
-ld_library_clear (LdLibrary *self)
-{
- g_return_if_fail (LD_IS_LIBRARY (self));
-
- g_slist_foreach (self->priv->children, (GFunc) g_object_unref, NULL);
- g_slist_free (self->priv->children);
- self->priv->children = NULL;
-
- g_signal_emit (self,
- LD_LIBRARY_GET_CLASS (self)->changed_signal, 0);
-}
-
-/**
- * ld_library_insert_child:
- * @self: An #LdLibrary object.
- * @child: The child to be inserted.
- * @pos: The position at which the child will be inserted.
- * Negative values will append to the end of list.
- *
- * Insert a child into the library.
- */
-void
-ld_library_insert_child (LdLibrary *self, GObject *child, gint pos)
-{
- g_return_if_fail (LD_IS_LIBRARY (self));
- g_return_if_fail (G_IS_OBJECT (child));
-
- g_object_ref (child);
- self->priv->children = g_slist_insert (self->priv->children, child, pos);
-}
-
-/**
- * ld_library_remove_child:
- * @self: An #LdLibrary object.
- * @child: The child to be removed.
- *
- * Remove a child from the library.
- */
-void
-ld_library_remove_child (LdLibrary *self, GObject *child)
-{
- g_return_if_fail (LD_IS_LIBRARY (self));
- g_return_if_fail (G_IS_OBJECT (child));
-
- if (g_slist_find (self->priv->children, child))
- {
- g_object_unref (child);
- self->priv->children = g_slist_remove (self->priv->children, child);
- }
-}
-
-/**
- * ld_library_get_children:
- * @self: An #LdLibrary object.
- *
- * Return value: The internal list of children. Do not modify.
- */
-const GSList *
-ld_library_get_children (LdLibrary *self)
-{
- g_return_val_if_fail (LD_IS_LIBRARY (self), NULL);
- return self->priv->children;
-}
-
diff --git a/src/ld-library.h b/src/ld-library.h
deleted file mode 100644
index 26521ed..0000000
--- a/src/ld-library.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * ld-library.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_LIBRARY_H__
-#define __LD_LIBRARY_H__
-
-G_BEGIN_DECLS
-
-
-#define LD_TYPE_LIBRARY (ld_library_get_type ())
-#define LD_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), LD_TYPE_LIBRARY, LdLibrary))
-#define LD_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
- ((klass), LD_TYPE_LIBRARY, LdLibraryClass))
-#define LD_IS_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), LD_TYPE_LIBRARY))
-#define LD_IS_LIBRARY_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((klass), LD_TYPE_LIBRARY))
-#define LD_LIBRARY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), LD_LIBRARY, LdLibraryClass))
-
-typedef struct _LdLibrary LdLibrary;
-typedef struct _LdLibraryPrivate LdLibraryPrivate;
-typedef struct _LdLibraryClass LdLibraryClass;
-
-
-struct _LdLibrary
-{
-/*< private >*/
- GObject parent_instance;
- LdLibraryPrivate *priv;
-};
-
-struct _LdLibraryClass
-{
-/*< private >*/
- GObjectClass parent_class;
-
- guint changed_signal;
-};
-
-
-/**
- * LD_LIBRARY_IDENTIFIER_SEPARATOR:
- *
- * Defines a string that separates categories and symbols in identifiers.
- */
-#define LD_LIBRARY_IDENTIFIER_SEPARATOR "/"
-
-
-GType ld_library_get_type (void) G_GNUC_CONST;
-
-LdLibrary *ld_library_new (void);
-gboolean ld_library_load (LdLibrary *self, const gchar *directory);
-LdSymbol *ld_library_find_symbol (LdLibrary *self, const gchar *identifier);
-void ld_library_clear (LdLibrary *self);
-
-void ld_library_insert_child (LdLibrary *self, GObject *child, gint pos);
-void ld_library_remove_child (LdLibrary *self, GObject *child);
-const GSList *ld_library_get_children (LdLibrary *self);
-
-
-G_END_DECLS
-
-#endif /* ! __LD_LIBRARY_H__ */
-
diff --git a/src/ld-lua-private.h b/src/ld-lua-private.h
deleted file mode 100644
index 7d6943a..0000000
--- a/src/ld-lua-private.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * ld-lua-private.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_LUA_PRIVATE_H__
-#define __LD_LUA_PRIVATE_H__
-
-G_BEGIN_DECLS
-
-
-/*< private_header >*/
-
-void ld_lua_private_unregister (LdLua *self, LdLuaSymbol *symbol);
-void ld_lua_private_draw (LdLua *self, LdLuaSymbol *symbol, cairo_t *cr);
-
-
-G_END_DECLS
-
-#endif /* ! __LD_LUA_PRIVATE_H__ */
-
diff --git a/src/ld-lua-symbol-private.h b/src/ld-lua-symbol-private.h
deleted file mode 100644
index 83bc646..0000000
--- a/src/ld-lua-symbol-private.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * ld-lua-symbol-private.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_LUA_SYMBOL_PRIVATE_H__
-#define __LD_LUA_SYMBOL_PRIVATE_H__
-
-G_BEGIN_DECLS
-
-
-/*< private_header >*/
-
-/*
- * LdLuaSymbolPrivate:
- * @lua: Parent #LdLua object.
- * @name: Name of this symbol.
- * @human_name: Localized human name of this symbol.
- * @area: Area of this symbol.
- * @terminals: Terminals of this symbol.
- */
-struct _LdLuaSymbolPrivate
-{
- LdLua *lua;
- gchar *name;
- gchar *human_name;
- LdRectangle area;
- LdPointArray *terminals;
-};
-
-
-G_END_DECLS
-
-#endif /* ! __LD_LUA_SYMBOL_PRIVATE_H__ */
-
diff --git a/src/ld-lua-symbol.c b/src/ld-lua-symbol.c
deleted file mode 100644
index 27a6279..0000000
--- a/src/ld-lua-symbol.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * ld-lua-symbol.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include "liblogdiag.h"
-#include "config.h"
-
-#include "ld-lua-private.h"
-#include "ld-lua-symbol-private.h"
-
-
-/**
- * SECTION:ld-lua-symbol
- * @short_description: A symbol.
- * @see_also: #LdSymbol
- *
- * #LdLuaSymbol is an implementation of #LdSymbol.
- */
-
-static void ld_lua_symbol_finalize (GObject *gobject);
-
-static const gchar *ld_lua_symbol_real_get_name (LdSymbol *symbol);
-static const gchar *ld_lua_symbol_real_get_human_name (LdSymbol *symbol);
-static void ld_lua_symbol_real_get_area (LdSymbol *symbol, LdRectangle *area);
-static const LdPointArray *ld_lua_symbol_real_get_terminals (LdSymbol *symbol);
-static void ld_lua_symbol_real_draw (LdSymbol *symbol, cairo_t *cr);
-
-
-G_DEFINE_TYPE (LdLuaSymbol, ld_lua_symbol, LD_TYPE_SYMBOL);
-
-static void
-ld_lua_symbol_class_init (LdLuaSymbolClass *klass)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = ld_lua_symbol_finalize;
-
- klass->parent_class.get_name = ld_lua_symbol_real_get_name;
- klass->parent_class.get_human_name = ld_lua_symbol_real_get_human_name;
- klass->parent_class.get_area = ld_lua_symbol_real_get_area;
- klass->parent_class.get_terminals = ld_lua_symbol_real_get_terminals;
- klass->parent_class.draw = ld_lua_symbol_real_draw;
-
- g_type_class_add_private (klass, sizeof (LdLuaSymbolPrivate));
-}
-
-static void
-ld_lua_symbol_init (LdLuaSymbol *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE
- (self, LD_TYPE_LUA_SYMBOL, LdLuaSymbolPrivate);
-}
-
-static void
-ld_lua_symbol_finalize (GObject *gobject)
-{
- LdLuaSymbol *self;
-
- self = LD_LUA_SYMBOL (gobject);
-
- if (self->priv->lua)
- {
- ld_lua_private_unregister (self->priv->lua, self);
- g_object_unref (self->priv->lua);
- }
-
- if (self->priv->name)
- g_free (self->priv->name);
- if (self->priv->human_name)
- g_free (self->priv->human_name);
-
- if (self->priv->terminals)
- ld_point_array_free (self->priv->terminals);
-
- /* Chain up to the parent class. */
- G_OBJECT_CLASS (ld_lua_symbol_parent_class)->finalize (gobject);
-}
-
-
-static const gchar *
-ld_lua_symbol_real_get_name (LdSymbol *symbol)
-{
- g_return_val_if_fail (LD_IS_LUA_SYMBOL (symbol), NULL);
- return LD_LUA_SYMBOL (symbol)->priv->name;
-}
-
-static const gchar *
-ld_lua_symbol_real_get_human_name (LdSymbol *symbol)
-{
- g_return_val_if_fail (LD_IS_LUA_SYMBOL (symbol), NULL);
- return LD_LUA_SYMBOL (symbol)->priv->human_name;
-}
-
-static void
-ld_lua_symbol_real_get_area (LdSymbol *symbol, LdRectangle *area)
-{
- LdLuaSymbol *self;
-
- g_return_if_fail (LD_IS_LUA_SYMBOL (symbol));
- g_return_if_fail (area != NULL);
-
- self = LD_LUA_SYMBOL (symbol);
- *area = self->priv->area;
-}
-
-static const LdPointArray *
-ld_lua_symbol_real_get_terminals (LdSymbol *symbol)
-{
- LdLuaSymbol *self;
-
- g_return_val_if_fail (LD_IS_LUA_SYMBOL (symbol), NULL);
-
- self = LD_LUA_SYMBOL (symbol);
- return self->priv->terminals;
-}
-
-static void
-ld_lua_symbol_real_draw (LdSymbol *symbol, cairo_t *cr)
-{
- LdLuaSymbol *self;
-
- g_return_if_fail (LD_IS_LUA_SYMBOL (symbol));
- g_return_if_fail (cr != NULL);
-
- self = LD_LUA_SYMBOL (symbol);
-
- cairo_save (cr);
- ld_lua_private_draw (self->priv->lua, self, cr);
- cairo_restore (cr);
-}
-
diff --git a/src/ld-lua-symbol.h b/src/ld-lua-symbol.h
deleted file mode 100644
index 5f68b59..0000000
--- a/src/ld-lua-symbol.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * ld-lua-symbol.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_LUA_SYMBOL_H__
-#define __LD_LUA_SYMBOL_H__
-
-G_BEGIN_DECLS
-
-
-#define LD_TYPE_LUA_SYMBOL (ld_lua_symbol_get_type ())
-#define LD_LUA_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), LD_TYPE_LUA_SYMBOL, LdLuaSymbol))
-#define LD_LUA_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
- ((klass), LD_TYPE_LUA_SYMBOL, LdLuaSymbolClass))
-#define LD_IS_LUA_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), LD_TYPE_LUA_SYMBOL))
-#define LD_IS_LUA_SYMBOL_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((klass), LD_TYPE_LUA_SYMBOL))
-#define LD_LUA_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), LD_LUA_SYMBOL, LdLuaSymbolClass))
-
-typedef struct _LdLuaSymbol LdLuaSymbol;
-typedef struct _LdLuaSymbolPrivate LdLuaSymbolPrivate;
-typedef struct _LdLuaSymbolClass LdLuaSymbolClass;
-
-
-/**
- * LdLuaSymbol:
- */
-struct _LdLuaSymbol
-{
-/*< private >*/
- LdSymbol parent_instance;
- LdLuaSymbolPrivate *priv;
-};
-
-/**
- * LdLuaSymbolClass:
- * @parent_class: The parent class.
- */
-struct _LdLuaSymbolClass
-{
- LdSymbolClass parent_class;
-};
-
-
-GType ld_lua_symbol_get_type (void) G_GNUC_CONST;
-
-
-G_END_DECLS
-
-#endif /* ! __LD_LUA_SYMBOL_H__ */
-
diff --git a/src/ld-lua.c b/src/ld-lua.c
deleted file mode 100644
index 47a41b5..0000000
--- a/src/ld-lua.c
+++ /dev/null
@@ -1,808 +0,0 @@
-/*
- * ld-lua.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include
-#include
-#include
-
-#include "liblogdiag.h"
-#include "config.h"
-
-#include "ld-lua-private.h"
-#include "ld-lua-symbol-private.h"
-
-
-/**
- * SECTION:ld-lua
- * @short_description: Lua symbol engine.
- * @see_also: #LdLuaSymbol
- *
- * #LdLua is a symbol engine that uses Lua scripts to manage symbols.
- */
-
-/*
- * LdLuaPrivate:
- * @L: Lua state.
- *
- * The library contains the real function for rendering.
- */
-struct _LdLuaPrivate
-{
- lua_State *L;
-};
-
-/* registry.logdiag_symbols
- * -> A table indexed by pointers to LdLuaSymbol objects
- * registry.logdiag_symbols.object.render(cr)
- * -> The rendering function
- */
-
-#define LD_LUA_LIBRARY_NAME "logdiag"
-#define LD_LUA_DATA_INDEX LD_LUA_LIBRARY_NAME "_data"
-#define LD_LUA_SYMBOLS_INDEX LD_LUA_LIBRARY_NAME "_symbols"
-
-/*
- * LdLuaData:
- * @self: A reference to self.
- * @load_callback: A callback for newly registered symbols.
- * @load_user_data: User data to be passed to the callback.
- *
- * Full user data to be stored in Lua registry.
- */
-typedef struct _LdLuaData LdLuaData;
-
-struct _LdLuaData
-{
- LdLua *self;
- LdLuaLoadCallback load_callback;
- gpointer load_user_data;
-};
-
-typedef struct _LdLuaDrawData LdLuaDrawData;
-
-struct _LdLuaDrawData
-{
- LdLuaSymbol *symbol;
- cairo_t *cr;
- unsigned save_count;
-};
-
-static void ld_lua_finalize (GObject *gobject);
-
-static void *ld_lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize);
-
-static int ld_lua_private_draw_cb (lua_State *L);
-static int ld_lua_private_unregister_cb (lua_State *L);
-
-static int ld_lua_logdiag_register (lua_State *L);
-static int process_registration (lua_State *L);
-static gchar *get_translation (lua_State *L, int index);
-static gboolean read_symbol_area (lua_State *L, int index, LdRectangle *area);
-static gboolean read_terminals (lua_State *L, int index,
- LdPointArray **terminals);
-
-static void push_cairo_object (lua_State *L, LdLuaDrawData *draw_data);
-static gdouble get_cairo_scale (cairo_t *cr);
-static int ld_lua_cairo_save (lua_State *L);
-static int ld_lua_cairo_restore (lua_State *L);
-static int ld_lua_cairo_get_line_width (lua_State *L);
-static int ld_lua_cairo_set_line_width (lua_State *L);
-static int ld_lua_cairo_move_to (lua_State *L);
-static int ld_lua_cairo_line_to (lua_State *L);
-static int ld_lua_cairo_curve_to (lua_State *L);
-static int ld_lua_cairo_arc (lua_State *L);
-static int ld_lua_cairo_arc_negative (lua_State *L);
-static int ld_lua_cairo_new_path (lua_State *L);
-static int ld_lua_cairo_new_sub_path (lua_State *L);
-static int ld_lua_cairo_close_path (lua_State *L);
-static int ld_lua_cairo_stroke (lua_State *L);
-static int ld_lua_cairo_stroke_preserve (lua_State *L);
-static int ld_lua_cairo_fill (lua_State *L);
-static int ld_lua_cairo_fill_preserve (lua_State *L);
-static int ld_lua_cairo_clip (lua_State *L);
-static int ld_lua_cairo_clip_preserve (lua_State *L);
-
-
-static luaL_Reg ld_lua_logdiag_lib[] =
-{
- {"register", ld_lua_logdiag_register},
- {NULL, NULL}
-};
-
-static luaL_Reg ld_lua_cairo_table[] =
-{
- {"save", ld_lua_cairo_save},
- {"restore", ld_lua_cairo_restore},
- {"get_line_width", ld_lua_cairo_get_line_width},
- {"set_line_width", ld_lua_cairo_set_line_width},
- {"move_to", ld_lua_cairo_move_to},
- {"line_to", ld_lua_cairo_line_to},
- {"curve_to", ld_lua_cairo_curve_to},
- {"arc", ld_lua_cairo_arc},
- {"arc_negative", ld_lua_cairo_arc_negative},
- {"new_path", ld_lua_cairo_new_path},
- {"new_sub_path", ld_lua_cairo_new_sub_path},
- {"close_path", ld_lua_cairo_close_path},
- {"stroke", ld_lua_cairo_stroke},
- {"stroke_preserve", ld_lua_cairo_stroke_preserve},
- {"fill", ld_lua_cairo_fill},
- {"fill_preserve", ld_lua_cairo_fill_preserve},
- {"clip", ld_lua_cairo_clip},
- {"clip_preserve", ld_lua_cairo_clip_preserve},
- {NULL, NULL}
-};
-
-
-/* ===== Generic =========================================================== */
-
-G_DEFINE_TYPE (LdLua, ld_lua, G_TYPE_OBJECT);
-
-static void
-ld_lua_class_init (LdLuaClass *klass)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = ld_lua_finalize;
-
- g_type_class_add_private (klass, sizeof (LdLuaPrivate));
-}
-
-static void
-ld_lua_init (LdLua *self)
-{
- lua_State *L;
- LdLuaData *ud;
-
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE
- (self, LD_TYPE_LUA, LdLuaPrivate);
-
- L = self->priv->L = lua_newstate (ld_lua_alloc, NULL);
- g_return_if_fail (L != NULL);
-
- /* TODO: lua_atpanic () */
-
- /* Load some safe libraries. */
- lua_pushcfunction (L, luaopen_string);
- lua_call (L, 0, 0);
-
- lua_pushcfunction (L, luaopen_table);
- lua_call (L, 0, 0);
-
- lua_pushcfunction (L, luaopen_math);
- lua_call (L, 0, 0);
-
- /* Load the application library. */
- luaL_register (L, LD_LUA_LIBRARY_NAME, ld_lua_logdiag_lib);
-
- /* Store user data to the registry. */
- ud = lua_newuserdata (L, sizeof (LdLuaData));
- ud->self = self;
- ud->load_callback = NULL;
- ud->load_user_data = NULL;
-
- lua_setfield (L, LUA_REGISTRYINDEX, LD_LUA_DATA_INDEX);
-
- /* Create an empty symbol table. */
- lua_newtable (L);
- lua_setfield (L, LUA_REGISTRYINDEX, LD_LUA_SYMBOLS_INDEX);
-}
-
-static void
-ld_lua_finalize (GObject *gobject)
-{
- LdLua *self;
-
- self = LD_LUA (gobject);
- lua_close (self->priv->L);
-
- /* Chain up to the parent class. */
- G_OBJECT_CLASS (ld_lua_parent_class)->finalize (gobject);
-}
-
-/**
- * ld_lua_new:
- *
- * Create an instance of #LdLua.
- */
-LdLua *
-ld_lua_new (void)
-{
- return g_object_new (LD_TYPE_LUA, NULL);
-}
-
-static void *
-ld_lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize)
-{
- if (!nsize)
- {
- g_free (ptr);
- return NULL;
- }
- else
- return g_try_realloc (ptr, nsize);
-}
-
-/**
- * ld_lua_check_file:
- * @self: An #LdLua object.
- * @filename: The file to be checked.
- *
- * Check if the given filename can be loaded by #LdLua.
- */
-gboolean
-ld_lua_check_file (LdLua *self, const gchar *filename)
-{
- g_return_val_if_fail (LD_IS_LUA (self), FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
-
- return g_str_has_suffix (filename, ".lua")
- && g_file_test (filename, G_FILE_TEST_IS_REGULAR);
-}
-
-/**
- * ld_lua_load_file:
- * @self: An #LdLua object.
- * @filename: The file to be loaded.
- * @callback: A callback for newly registered symbols.
- * The callee is responsible for referencing the symbol.
- * @user_data: User data to be passed to the callback.
- *
- * Loads a file and creates #LdLuaSymbol objects for contained symbols.
- *
- * Returns: TRUE if no error has occured, FALSE otherwise.
- */
-gboolean
-ld_lua_load_file (LdLua *self, const gchar *filename,
- LdLuaLoadCallback callback, gpointer user_data)
-{
- gint retval;
- LdLuaData *ud;
-
- g_return_val_if_fail (LD_IS_LUA (self), FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
- g_return_val_if_fail (callback != NULL, FALSE);
-
- /* XXX: If something from the following fails, Lua will call exit(). */
- lua_getfield (self->priv->L, LUA_REGISTRYINDEX, LD_LUA_DATA_INDEX);
- ud = lua_touserdata (self->priv->L, -1);
- lua_pop (self->priv->L, 1);
- g_return_val_if_fail (ud != NULL, FALSE);
-
- ud->load_callback = callback;
- ud->load_user_data = user_data;
-
- retval = luaL_loadfile (self->priv->L, filename);
- if (retval)
- goto ld_lua_lftc_fail;
-
- retval = lua_pcall (self->priv->L, 0, 0, 0);
- if (retval)
- goto ld_lua_lftc_fail;
-
- ud->load_callback = NULL;
- ud->load_user_data = NULL;
- return TRUE;
-
-ld_lua_lftc_fail:
- g_warning ("Lua error: %s", lua_tostring (self->priv->L, -1));
- lua_remove (self->priv->L, -1);
-
- ud->load_callback = NULL;
- ud->load_user_data = NULL;
- return FALSE;
-}
-
-/* ===== LdLuaSymbol callbacks ============================================= */
-
-/**
- * ld_lua_private_draw:
- * @self: An #LdLua object.
- * @symbol: A symbol to be drawn.
- * @cr: A Cairo context to be drawn onto.
- *
- * Draw a symbol onto a Cairo context.
- */
-void
-ld_lua_private_draw (LdLua *self, LdLuaSymbol *symbol, cairo_t *cr)
-{
- LdLuaDrawData data;
-
- g_return_if_fail (LD_IS_LUA (self));
- g_return_if_fail (LD_IS_LUA_SYMBOL (symbol));
- g_return_if_fail (cr != NULL);
-
- data.symbol = symbol;
- data.cr = cr;
- data.save_count = 0;
-
- if (lua_cpcall (self->priv->L, ld_lua_private_draw_cb, &data))
- {
- g_warning ("Lua error: %s", lua_tostring (self->priv->L, -1));
- lua_pop (self->priv->L, 1);
- }
-
- while (data.save_count--)
- cairo_restore (cr);
-}
-
-static int
-ld_lua_private_draw_cb (lua_State *L)
-{
- LdLuaDrawData *data;
-
- data = lua_touserdata (L, -1);
-
- /* Retrieve the function for rendering from the registry. */
- lua_getfield (L, LUA_REGISTRYINDEX, LD_LUA_SYMBOLS_INDEX);
- lua_pushlightuserdata (L, data->symbol);
- lua_gettable (L, -2);
-
- luaL_checktype (L, -1, LUA_TTABLE);
- lua_getfield (L, -1, "render");
- luaL_checktype (L, -1, LUA_TFUNCTION);
-
- /* Call the function do draw the symbol. */
- push_cairo_object (L, data);
- lua_pcall (L, 1, 0, 0);
- return 0;
-}
-
-/**
- * ld_lua_private_unregister:
- * @self: An #LdLua object.
- * @symbol: A symbol to be unregistered.
- *
- * Unregister a symbol from the internal Lua state.
- */
-void
-ld_lua_private_unregister (LdLua *self, LdLuaSymbol *symbol)
-{
- g_return_if_fail (LD_IS_LUA (self));
- g_return_if_fail (LD_IS_LUA_SYMBOL (symbol));
-
- if (lua_cpcall (self->priv->L, ld_lua_private_unregister_cb, symbol))
- {
- g_warning ("Lua error: %s", lua_tostring (self->priv->L, -1));
- lua_pop (self->priv->L, 1);
- }
-}
-
-static int
-ld_lua_private_unregister_cb (lua_State *L)
-{
- /* Set the entry in the symbol table to nil. */
- lua_getfield (L, LUA_REGISTRYINDEX, LD_LUA_SYMBOLS_INDEX);
- lua_insert (L, -2);
- lua_pushnil (L);
- lua_settable (L, -3);
- return 0;
-}
-
-/* ===== Application library =============================================== */
-
-static int
-ld_lua_logdiag_register (lua_State *L)
-{
- LdLuaData *ud;
- LdLuaSymbol *symbol;
-
- lua_getfield (L, LUA_REGISTRYINDEX, LD_LUA_DATA_INDEX);
- ud = lua_touserdata (L, -1);
- lua_pop (L, 1);
- g_return_val_if_fail (ud != NULL, 0);
-
- /* Use a protected environment, so script errors won't cause leaking
- * of the symbol object. Only a failure of the last three function calls
- * before lua_pcall() may cause the symbol to leak.
- */
- lua_checkstack (L, 3);
- symbol = g_object_new (LD_TYPE_LUA_SYMBOL, NULL);
-
- lua_pushlightuserdata (L, symbol);
- lua_pushcclosure (L, process_registration, 1);
- lua_insert (L, 1);
-
- /* On the stack, there are function arguments plus the function itself. */
- if (lua_pcall (L, lua_gettop (L) - 1, 0, 0))
- {
- luaL_where (L, 1);
- lua_insert (L, -2);
- lua_concat (L, 2);
-
- g_warning ("Lua symbol registration failed: %s",
- lua_tostring (L, -1));
- lua_pushboolean (L, FALSE);
- }
- else
- {
- /* We don't want an extra LdLua reference either. */
- symbol->priv->lua = ud->self;
- g_object_ref (ud->self);
-
- ud->load_callback (LD_SYMBOL (symbol), ud->load_user_data);
- lua_pushboolean (L, TRUE);
- }
- g_object_unref (symbol);
-
- return 1;
-}
-
-/*
- * process_registration:
- * @L: A Lua state.
- *
- * Parse arguments, write them to a symbol object and register the object.
- */
-static int
-process_registration (lua_State *L)
-{
- LdLuaSymbol *symbol;
- gchar *human_name;
-
- int i, type, types[] =
- {LUA_TSTRING, LUA_TTABLE, LUA_TTABLE, LUA_TTABLE, LUA_TFUNCTION};
- int n_args_needed = sizeof (types) / sizeof (int);
-
- if (lua_gettop (L) < n_args_needed)
- return luaL_error (L, "Too few arguments.");
-
- for (i = 0; i < n_args_needed; i++)
- if ((type = lua_type (L, i + 1)) != types[i])
- return luaL_error (L, "Bad type of argument #%d."
- " Expected %s, got %s.", i + 1,
- lua_typename (L, types[i]), lua_typename (L, type));
-
- symbol = LD_LUA_SYMBOL (lua_touserdata (L, lua_upvalueindex (1)));
- symbol->priv->name = g_strdup (lua_tostring (L, 1));
-
- human_name = get_translation (L, 2);
- if (!human_name)
- human_name = g_strdup (symbol->priv->name);
- symbol->priv->human_name = human_name;
-
- if (!read_symbol_area (L, 3, &symbol->priv->area))
- return luaL_error (L, "Malformed symbol area array.");
- if (!read_terminals (L, 4, &symbol->priv->terminals))
- return luaL_error (L, "Malformed terminals array.");
-
- lua_getfield (L, LUA_REGISTRYINDEX, LD_LUA_SYMBOLS_INDEX);
- lua_pushlightuserdata (L, symbol);
-
- lua_newtable (L);
- lua_pushvalue (L, 5);
- lua_setfield (L, -2, "render");
-
- lua_settable (L, -3);
- return 0;
-}
-
-/*
- * get_translation:
- * @L: A Lua state.
- * @index: Stack index of the table.
- *
- * Select an applicable translation from a table.
- * The return value has to be freed with g_free().
- *
- * Return value: The translation, if found. If none was found, returns NULL.
- */
-static gchar *
-get_translation (lua_State *L, int index)
-{
- const gchar *const *lang;
- gchar *result;
-
- for (lang = g_get_language_names (); *lang; lang++)
- {
- lua_getfield (L, 2, *lang);
- if (lua_isstring (L, -1))
- {
- result = g_strdup (lua_tostring (L, -1));
- lua_pop (L, 1);
- return result;
- }
- lua_pop (L, 1);
- }
- return NULL;
-}
-
-/*
- * read_symbol_area:
- * @L: A Lua state.
- * @index: Stack index of the table.
- * @area: Where the area will be returned.
- *
- * Read a symbol area from a Lua table.
- *
- * Return value: TRUE on success, FALSE on failure.
- */
-static gboolean
-read_symbol_area (lua_State *L, int index, LdRectangle *area)
-{
- lua_Number x1, x2, y1, y2;
-
- if (lua_objlen (L, index) != 4)
- return FALSE;
-
- lua_rawgeti (L, index, 1);
- if (!lua_isnumber (L, -1))
- return FALSE;
- x1 = lua_tonumber (L, -1);
-
- lua_rawgeti (L, index, 2);
- if (!lua_isnumber (L, -1))
- return FALSE;
- y1 = lua_tonumber (L, -1);
-
- lua_rawgeti (L, index, 3);
- if (!lua_isnumber (L, -1))
- return FALSE;
- x2 = lua_tonumber (L, -1);
-
- lua_rawgeti (L, index, 4);
- if (!lua_isnumber (L, -1))
- return FALSE;
- y2 = lua_tonumber (L, -1);
-
- area->x = MIN (x1, x2);
- area->y = MIN (y1, y2);
- area->width = ABS (x2 - x1);
- area->height = ABS (y2 - y1);
-
- lua_pop (L, 4);
- return TRUE;
-}
-
-/*
- * read_terminals:
- * @L: A Lua state.
- * @index: Stack index of the table.
- * @area: Where the point array will be returned.
- *
- * Read symbol terminals from a Lua table.
- *
- * Return value: TRUE on success, FALSE on failure.
- */
-static gboolean
-read_terminals (lua_State *L, int index, LdPointArray **terminals)
-{
- LdPointArray *points;
- size_t num_points;
- unsigned i = 0;
-
- num_points = lua_objlen (L, index);
- points = ld_point_array_new (num_points);
-
- lua_pushnil (L);
- while (lua_next (L, index) != 0)
- {
- g_assert (i < num_points);
-
- if (!lua_istable (L, -1) || lua_objlen (L, -1) != 2)
- goto read_terminals_fail;
-
- lua_rawgeti (L, -1, 1);
- if (!lua_isnumber (L, -1))
- goto read_terminals_fail;
- points->points[i].x = lua_tonumber (L, -1);
- lua_pop (L, 1);
-
- lua_rawgeti (L, -1, 2);
- if (!lua_isnumber (L, -1))
- goto read_terminals_fail;
- points->points[i].y = lua_tonumber (L, -1);
-
- lua_pop (L, 2);
- i++;
- }
- *terminals = points;
- return TRUE;
-
-read_terminals_fail:
- ld_point_array_free (points);
- *terminals = NULL;
- return FALSE;
-}
-
-
-/* ===== Cairo ============================================================= */
-
-static void
-push_cairo_object (lua_State *L, LdLuaDrawData *draw_data)
-{
- luaL_Reg *fn;
-
- /* Create a table. */
- lua_newtable (L);
-
- /* Add methods. */
- /* XXX: The light user data pointer gets invalid after the end of
- * "render" function invocation. If the script stores the "cr" object
- * in some global variable and then tries to reuse it the next time,
- * the application may go SIGSEGV.
- *
- * The solution is creating a full user data instead, referencing
- * the cairo object and dereferencing it upon garbage collection
- * of the user data object.
- */
- for (fn = ld_lua_cairo_table; fn->name; fn++)
- {
- lua_pushlightuserdata (L, draw_data);
- lua_pushcclosure (L, fn->func, 1);
- lua_setfield (L, -2, fn->name);
- }
-}
-
-static gdouble
-get_cairo_scale (cairo_t *cr)
-{
- double dx = 1, dy = 0;
-
- cairo_user_to_device_distance (cr, &dx, &dy);
- return dx;
-}
-
-#define LD_LUA_CAIRO_TRIVIAL(name) \
-static int \
-ld_lua_cairo_ ## name (lua_State *L) \
-{ \
- LdLuaDrawData *data; \
- data = lua_touserdata (L, lua_upvalueindex (1)); \
- cairo_ ## name (data->cr); \
- return 0; \
-}
-
-LD_LUA_CAIRO_TRIVIAL (new_path)
-LD_LUA_CAIRO_TRIVIAL (new_sub_path)
-LD_LUA_CAIRO_TRIVIAL (close_path)
-
-LD_LUA_CAIRO_TRIVIAL (stroke)
-LD_LUA_CAIRO_TRIVIAL (stroke_preserve)
-LD_LUA_CAIRO_TRIVIAL (fill)
-LD_LUA_CAIRO_TRIVIAL (fill_preserve)
-LD_LUA_CAIRO_TRIVIAL (clip)
-LD_LUA_CAIRO_TRIVIAL (clip_preserve)
-
-static int
-ld_lua_cairo_save (lua_State *L)
-{
- LdLuaDrawData *data;
-
- data = lua_touserdata (L, lua_upvalueindex (1));
- if (data->save_count + 1)
- {
- data->save_count++;
- cairo_save (data->cr);
- }
- return 0;
-}
-
-static int
-ld_lua_cairo_restore (lua_State *L)
-{
- LdLuaDrawData *data;
-
- data = lua_touserdata (L, lua_upvalueindex (1));
- if (data->save_count)
- {
- data->save_count--;
- cairo_restore (data->cr);
- }
- return 0;
-}
-
-static int
-ld_lua_cairo_get_line_width (lua_State *L)
-{
- LdLuaDrawData *data;
-
- data = lua_touserdata (L, lua_upvalueindex (1));
- lua_pushnumber (L, cairo_get_line_width (data->cr)
- * get_cairo_scale (data->cr));
- return 1;
-}
-
-static int
-ld_lua_cairo_set_line_width (lua_State *L)
-{
- LdLuaDrawData *data;
-
- data = lua_touserdata (L, lua_upvalueindex (1));
- cairo_set_line_width (data->cr, luaL_checknumber (L, 1)
- / get_cairo_scale (data->cr));
- return 0;
-}
-
-static int
-ld_lua_cairo_move_to (lua_State *L)
-{
- LdLuaDrawData *data;
- lua_Number x, y;
-
- data = lua_touserdata (L, lua_upvalueindex (1));
-
- x = luaL_checknumber (L, 1);
- y = luaL_checknumber (L, 2);
-
- cairo_move_to (data->cr, x, y);
- return 0;
-}
-
-static int
-ld_lua_cairo_line_to (lua_State *L)
-{
- LdLuaDrawData *data;
- lua_Number x, y;
-
- data = lua_touserdata (L, lua_upvalueindex (1));
-
- x = luaL_checknumber (L, 1);
- y = luaL_checknumber (L, 2);
-
- cairo_line_to (data->cr, x, y);
- return 0;
-}
-
-static int
-ld_lua_cairo_curve_to (lua_State *L)
-{
- LdLuaDrawData *data;
- lua_Number x1, y1, x2, y2, x3, y3;
-
- data = lua_touserdata (L, lua_upvalueindex (1));
-
- x1 = luaL_checknumber (L, 1);
- y1 = luaL_checknumber (L, 2);
- x2 = luaL_checknumber (L, 3);
- y2 = luaL_checknumber (L, 4);
- x3 = luaL_checknumber (L, 5);
- y3 = luaL_checknumber (L, 6);
-
- cairo_curve_to (data->cr, x1, y1, x2, y2, x3, y3);
- return 0;
-}
-
-static int
-ld_lua_cairo_arc (lua_State *L)
-{
- LdLuaDrawData *data;
- lua_Number xc, yc, radius, angle1, angle2;
-
- data = lua_touserdata (L, lua_upvalueindex (1));
-
- xc = luaL_checknumber (L, 1);
- yc = luaL_checknumber (L, 2);
- radius = luaL_checknumber (L, 3);
- angle1 = luaL_checknumber (L, 4);
- angle2 = luaL_checknumber (L, 5);
-
- cairo_arc (data->cr, xc, yc, radius, angle1, angle2);
- return 0;
-}
-
-static int
-ld_lua_cairo_arc_negative (lua_State *L)
-{
- LdLuaDrawData *data;
- lua_Number xc, yc, radius, angle1, angle2;
-
- data = lua_touserdata (L, lua_upvalueindex (1));
-
- xc = luaL_checknumber (L, 1);
- yc = luaL_checknumber (L, 2);
- radius = luaL_checknumber (L, 3);
- angle1 = luaL_checknumber (L, 4);
- angle2 = luaL_checknumber (L, 5);
-
- cairo_arc_negative (data->cr, xc, yc, radius, angle1, angle2);
- return 0;
-}
-
diff --git a/src/ld-lua.h b/src/ld-lua.h
deleted file mode 100644
index b207d66..0000000
--- a/src/ld-lua.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * ld-lua.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_LUA_H__
-#define __LD_LUA_H__
-
-G_BEGIN_DECLS
-
-
-#define LD_TYPE_LUA (ld_lua_get_type ())
-#define LD_LUA(obj) (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), LD_TYPE_LUA, LdLua))
-#define LD_LUA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
- ((klass), LD_TYPE_LUA, LdLuaClass))
-#define LD_IS_LUA(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), LD_TYPE_LUA))
-#define LD_IS_LUA_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((klass), LD_TYPE_LUA))
-#define LD_LUA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), LD_LUA, LdLuaClass))
-
-typedef struct _LdLua LdLua;
-typedef struct _LdLuaPrivate LdLuaPrivate;
-typedef struct _LdLuaClass LdLuaClass;
-
-
-struct _LdLua
-{
-/*< private >*/
- GObject parent_instance;
- LdLuaPrivate *priv;
-};
-
-/* TODO: A virtual superclass, so other engines can be used. */
-struct _LdLuaClass
-{
-/*< private >*/
- GObjectClass parent_class;
-};
-
-
-/**
- * LdLuaLoadCallback:
- * @symbol: The symbol that has been created.
- * @user_data: User data passed to ld_lua_load_file().
- *
- * A callback function that is called when a symbol is created.
- */
-typedef void (*LdLuaLoadCallback) (LdSymbol *symbol, gpointer user_data);
-
-
-GType ld_lua_get_type (void) G_GNUC_CONST;
-
-LdLua *ld_lua_new (void);
-gboolean ld_lua_check_file (LdLua *self, const gchar *filename);
-gboolean ld_lua_load_file (LdLua *self, const gchar *filename,
- LdLuaLoadCallback callback, gpointer user_data);
-
-
-G_END_DECLS
-
-#endif /* ! __LD_LUA_H__ */
-
diff --git a/src/ld-marshal.c b/src/ld-marshal.c
deleted file mode 100644
index ac88836..0000000
--- a/src/ld-marshal.c
+++ /dev/null
@@ -1,88 +0,0 @@
-
-#include
-
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v) g_value_get_char (v)
-#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v) g_value_get_int (v)
-#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
-#define g_marshal_value_peek_long(v) g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
-#define g_marshal_value_peek_float(v) g_value_get_float (v)
-#define g_marshal_value_peek_double(v) g_value_get_double (v)
-#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v) g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v) g_value_get_object (v)
-#define g_marshal_value_peek_variant(v) g_value_get_variant (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- * Do not access GValues directly in your code. Instead, use the
- * g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
-#define g_marshal_value_peek_char(v) (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v) (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v) (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
-#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
-#define g_marshal_value_peek_float(v) (v)->data[0].v_float
-#define g_marshal_value_peek_double(v) (v)->data[0].v_double
-#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
-#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-/* VOID:OBJECT,OBJECT (ld-marshal.list:1) */
-void
-g_cclosure_user_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
- GValue *return_value G_GNUC_UNUSED,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint G_GNUC_UNUSED,
- gpointer marshal_data)
-{
- typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1,
- gpointer arg_1,
- gpointer arg_2,
- gpointer data2);
- register GMarshalFunc_VOID__OBJECT_OBJECT callback;
- register GCClosure *cc = (GCClosure*) closure;
- register gpointer data1, data2;
-
- g_return_if_fail (n_param_values == 3);
-
- if (G_CCLOSURE_SWAP_DATA (closure))
- {
- data1 = closure->data;
- data2 = g_value_peek_pointer (param_values + 0);
- }
- else
- {
- data1 = g_value_peek_pointer (param_values + 0);
- data2 = closure->data;
- }
- callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
-
- callback (data1,
- g_marshal_value_peek_object (param_values + 1),
- g_marshal_value_peek_object (param_values + 2),
- data2);
-}
-
diff --git a/src/ld-marshal.h b/src/ld-marshal.h
deleted file mode 100644
index 545735a..0000000
--- a/src/ld-marshal.h
+++ /dev/null
@@ -1,20 +0,0 @@
-
-#ifndef __g_cclosure_user_marshal_MARSHAL_H__
-#define __g_cclosure_user_marshal_MARSHAL_H__
-
-#include
-
-G_BEGIN_DECLS
-
-/* VOID:OBJECT,OBJECT (ld-marshal.list:1) */
-extern void g_cclosure_user_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-G_END_DECLS
-
-#endif /* __g_cclosure_user_marshal_MARSHAL_H__ */
-
diff --git a/src/ld-marshal.list b/src/ld-marshal.list
deleted file mode 100644
index 38076d6..0000000
--- a/src/ld-marshal.list
+++ /dev/null
@@ -1 +0,0 @@
-VOID:OBJECT,OBJECT
diff --git a/src/ld-symbol-category.c b/src/ld-symbol-category.c
deleted file mode 100644
index e4b86a9..0000000
--- a/src/ld-symbol-category.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * ld-symbol-category.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include "liblogdiag.h"
-#include "config.h"
-
-
-/**
- * SECTION:ld-symbol-category
- * @short_description: A category of symbols.
- * @see_also: #LdSymbol, #LdLibrary
- *
- * #LdSymbolCategory represents a category of #LdSymbol objects.
- */
-
-/*
- * LdSymbolCategoryPrivate:
- * @name: The name of this category.
- * @image_path: Path to the image for this category.
- * @children: Children of this category.
- */
-struct _LdSymbolCategoryPrivate
-{
- gchar *name;
- gchar *human_name;
- gchar *image_path;
- GSList *children;
-};
-
-enum
-{
- PROP_0,
- PROP_NAME,
- PROP_HUMAN_NAME,
- PROP_IMAGE_PATH
-};
-
-static void ld_symbol_category_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec);
-static void ld_symbol_category_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec);
-static void ld_symbol_category_finalize (GObject *gobject);
-
-
-G_DEFINE_TYPE (LdSymbolCategory, ld_symbol_category, G_TYPE_OBJECT);
-
-static void
-ld_symbol_category_class_init (LdSymbolCategoryClass *klass)
-{
- GObjectClass *object_class;
- GParamSpec *pspec;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->get_property = ld_symbol_category_get_property;
- object_class->set_property = ld_symbol_category_set_property;
- object_class->finalize = ld_symbol_category_finalize;
-
-/**
- * LdSymbolCategory:name:
- *
- * The name of this symbol category.
- */
- pspec = g_param_spec_string ("name", "Name",
- "The name of this symbol category.",
- "", G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_NAME, pspec);
-
-/**
- * LdSymbolCategory:human-name:
- *
- * The localized human name of this symbol category.
- */
- pspec = g_param_spec_string ("human-name", "Human name",
- "The localized human name of this symbol category.",
- "", G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_HUMAN_NAME, pspec);
-
-/**
- * LdSymbolCategory:image-path:
- *
- * Path to an image file representing this category.
- */
- pspec = g_param_spec_string ("image-path", "Image path",
- "Path to an image file representing this category.",
- "", G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_IMAGE_PATH, pspec);
-
- g_type_class_add_private (klass, sizeof (LdSymbolCategoryPrivate));
-}
-
-static void
-ld_symbol_category_init (LdSymbolCategory *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE
- (self, LD_TYPE_SYMBOL_CATEGORY, LdSymbolCategoryPrivate);
-}
-
-static void
-ld_symbol_category_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- LdSymbolCategory *self;
-
- self = LD_SYMBOL_CATEGORY (object);
- switch (property_id)
- {
- case PROP_NAME:
- g_value_set_string (value, ld_symbol_category_get_name (self));
- break;
- case PROP_HUMAN_NAME:
- g_value_set_string (value, ld_symbol_category_get_human_name (self));
- break;
- case PROP_IMAGE_PATH:
- g_value_set_string (value, ld_symbol_category_get_image_path (self));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-ld_symbol_category_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- LdSymbolCategory *self;
-
- self = LD_SYMBOL_CATEGORY (object);
- switch (property_id)
- {
- case PROP_NAME:
- ld_symbol_category_set_name (self, g_value_get_string (value));
- break;
- case PROP_HUMAN_NAME:
- ld_symbol_category_set_human_name (self, g_value_get_string (value));
- break;
- case PROP_IMAGE_PATH:
- ld_symbol_category_set_image_path (self, g_value_get_string (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-ld_symbol_category_finalize (GObject *gobject)
-{
- LdSymbolCategory *self;
-
- self = LD_SYMBOL_CATEGORY (gobject);
-
- if (self->priv->name)
- g_free (self->priv->name);
- if (self->priv->human_name)
- g_free (self->priv->human_name);
- if (self->priv->image_path)
- g_free (self->priv->image_path);
-
- g_slist_foreach (self->priv->children, (GFunc) g_object_unref, NULL);
- g_slist_free (self->priv->children);
-
- /* Chain up to the parent class. */
- G_OBJECT_CLASS (ld_symbol_category_parent_class)->finalize (gobject);
-}
-
-
-/**
- * ld_symbol_category_new:
- * @name: The name of the new category.
- * @human_name: The localized human name of the new category.
- *
- * Create an instance.
- */
-LdSymbolCategory *
-ld_symbol_category_new (const gchar *name, const gchar *human_name)
-{
- LdSymbolCategory *cat;
-
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (human_name != NULL, NULL);
-
- cat = g_object_new (LD_TYPE_SYMBOL_CATEGORY, NULL);
- cat->priv->name = g_strdup (name);
- cat->priv->human_name = g_strdup (human_name);
-
- return cat;
-}
-
-/**
- * ld_symbol_category_set_name:
- * @self: An #LdSymbolCategory object.
- * @name: The new name for this category.
- */
-void
-ld_symbol_category_set_name (LdSymbolCategory *self, const gchar *name)
-{
- g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
- g_return_if_fail (name != NULL);
-
- if (self->priv->name)
- g_free (self->priv->name);
- self->priv->name = g_strdup (name);
-
- g_object_notify (G_OBJECT (self), "name");
-}
-
-/**
- * ld_symbol_category_get_name:
- * @self: An #LdSymbolCategory object.
- *
- * Return the name of this category.
- */
-const gchar *
-ld_symbol_category_get_name (LdSymbolCategory *self)
-{
- g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
- return self->priv->name;
-}
-
-/**
- * ld_symbol_category_set_human_name:
- * @self: An #LdSymbolCategory object.
- * @human_name: The new localized human name for this category.
- */
-void
-ld_symbol_category_set_human_name (LdSymbolCategory *self,
- const gchar *human_name)
-{
- g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
- g_return_if_fail (human_name != NULL);
-
- if (self->priv->human_name)
- g_free (self->priv->human_name);
- self->priv->human_name = g_strdup (human_name);
-
- g_object_notify (G_OBJECT (self), "human-name");
-}
-
-/**
- * ld_symbol_category_get_human_name:
- * @self: An #LdSymbolCategory object.
- *
- * Return the localized human name of this category.
- */
-const gchar *
-ld_symbol_category_get_human_name (LdSymbolCategory *self)
-{
- g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
- return self->priv->human_name;
-}
-
-/**
- * ld_symbol_category_set_image_path:
- * @self: An #LdSymbolCategory object.
- * @image_path: The new path to the image for this category. May be NULL.
- */
-void
-ld_symbol_category_set_image_path (LdSymbolCategory *self,
- const gchar *image_path)
-{
- g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
-
- if (self->priv->image_path)
- g_free (self->priv->image_path);
- self->priv->image_path = g_strdup (image_path);
-
- g_object_notify (G_OBJECT (self), "image-path");
-}
-
-/**
- * ld_symbol_category_get_image_path:
- * @self: An #LdSymbolCategory object.
- *
- * Return the filesystem path to the image for this category. May be NULL.
- */
-const gchar *
-ld_symbol_category_get_image_path (LdSymbolCategory *self)
-{
- g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
- return self->priv->image_path;
-}
-
-/**
- * ld_symbol_category_insert_child:
- * @self: An #LdSymbolCategory object.
- * @child: The child to be inserted.
- * @pos: The position at which the child will be inserted.
- * Negative values will append to the end of list.
- *
- * Insert a child into the category.
- */
-void
-ld_symbol_category_insert_child (LdSymbolCategory *self,
- GObject *child, gint pos)
-{
- g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
- g_return_if_fail (G_IS_OBJECT (child));
-
- g_object_ref (child);
- self->priv->children = g_slist_insert (self->priv->children, child, pos);
-}
-
-/**
- * ld_symbol_category_remove_child:
- * @self: An #LdSymbolCategory object.
- * @child: The child to be removed.
- *
- * Removes a child from the category.
- */
-void
-ld_symbol_category_remove_child (LdSymbolCategory *self,
- GObject *child)
-{
- g_return_if_fail (LD_IS_SYMBOL_CATEGORY (self));
- g_return_if_fail (G_IS_OBJECT (child));
-
- g_object_unref (child);
- self->priv->children = g_slist_remove (self->priv->children, child);
-}
-
-/**
- * ld_symbol_category_get_children:
- * @self: An #LdSymbolCategory object.
- *
- * Return value: The internal list of children. Do not modify.
- */
-const GSList *
-ld_symbol_category_get_children (LdSymbolCategory *self)
-{
- g_return_val_if_fail (LD_IS_SYMBOL_CATEGORY (self), NULL);
- return self->priv->children;
-}
-
diff --git a/src/ld-symbol-category.h b/src/ld-symbol-category.h
deleted file mode 100644
index 3b1f05b..0000000
--- a/src/ld-symbol-category.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * ld-symbol-category.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_SYMBOL_CATEGORY_H__
-#define __LD_SYMBOL_CATEGORY_H__
-
-G_BEGIN_DECLS
-
-
-#define LD_TYPE_SYMBOL_CATEGORY (ld_symbol_category_get_type ())
-#define LD_SYMBOL_CATEGORY(obj) (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), LD_TYPE_SYMBOL_CATEGORY, LdSymbolCategory))
-#define LD_SYMBOL_CATEGORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
- ((klass), LD_TYPE_SYMBOL_CATEGORY, LdSymbolCategoryClass))
-#define LD_IS_SYMBOL_CATEGORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), LD_TYPE_SYMBOL_CATEGORY))
-#define LD_IS_SYMBOL_CATEGORY_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((klass), LD_TYPE_SYMBOL_CATEGORY))
-#define LD_SYMBOL_CATEGORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), LD_SYMBOL_CATEGORY, LdSymbolCategoryClass))
-
-typedef struct _LdSymbolCategory LdSymbolCategory;
-typedef struct _LdSymbolCategoryPrivate LdSymbolCategoryPrivate;
-typedef struct _LdSymbolCategoryClass LdSymbolCategoryClass;
-
-
-/**
- * LdSymbolCategory:
- */
-struct _LdSymbolCategory
-{
-/*< private >*/
- GObject parent_instance;
- LdSymbolCategoryPrivate *priv;
-};
-
-/* TODO: If required sometime, categories (and maybe symbols) should implement
- * a "changed" signal. This can be somewhat tricky. The library might be
- * a good candidate for what they call a proxy. See GtkUIManager.
- */
-struct _LdSymbolCategoryClass
-{
-/*< private >*/
- GObjectClass parent_class;
-};
-
-
-GType ld_symbol_category_get_type (void) G_GNUC_CONST;
-
-LdSymbolCategory *ld_symbol_category_new (const gchar *name,
- const gchar *human_name);
-
-void ld_symbol_category_set_name (LdSymbolCategory *self, const gchar *name);
-const gchar *ld_symbol_category_get_name (LdSymbolCategory *self);
-void ld_symbol_category_set_human_name (LdSymbolCategory *self,
- const gchar *human_name);
-const gchar *ld_symbol_category_get_human_name (LdSymbolCategory *self);
-void ld_symbol_category_set_image_path (LdSymbolCategory *self,
- const gchar *image_path);
-const gchar *ld_symbol_category_get_image_path (LdSymbolCategory *self);
-
-void ld_symbol_category_insert_child (LdSymbolCategory *self,
- GObject *child, gint pos);
-void ld_symbol_category_remove_child (LdSymbolCategory *self,
- GObject *child);
-const GSList *ld_symbol_category_get_children (LdSymbolCategory *self);
-
-
-G_END_DECLS
-
-#endif /* ! __LD_SYMBOL_CATEGORY_H__ */
-
diff --git a/src/ld-symbol.c b/src/ld-symbol.c
deleted file mode 100644
index fafa9ab..0000000
--- a/src/ld-symbol.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * ld-symbol.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include "liblogdiag.h"
-#include "config.h"
-
-
-/**
- * SECTION:ld-symbol
- * @short_description: A symbol.
- * @see_also: #LdDiagramSymbol, #LdCanvas
- *
- * #LdSymbol represents a symbol to be drawn onto a #LdCanvas.
- *
- * All implementations of this abstract class are required to use
- * cairo_save() and cairo_restore() when drawing to store the state.
- */
-
-enum
-{
- PROP_0,
- PROP_NAME,
- PROP_HUMAN_NAME,
- PROP_AREA,
- PROP_TERMINALS
-};
-
-static void ld_symbol_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec);
-static void ld_symbol_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec);
-
-
-G_DEFINE_ABSTRACT_TYPE (LdSymbol, ld_symbol, G_TYPE_OBJECT);
-
-static void
-ld_symbol_class_init (LdSymbolClass *klass)
-{
- GObjectClass *object_class;
- GParamSpec *pspec;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->get_property = ld_symbol_get_property;
- object_class->set_property = ld_symbol_set_property;
-
-/**
- * LdSymbol:name:
- *
- * The name of this symbol.
- */
- pspec = g_param_spec_string ("name", "Name",
- "The name of this symbol.",
- "", G_PARAM_READABLE);
- g_object_class_install_property (object_class, PROP_NAME, pspec);
-
-/**
- * LdSymbol:human-name:
- *
- * The localized human name of this symbol.
- */
- pspec = g_param_spec_string ("human-name", "Human name",
- "The localized human name of this symbol.",
- "", G_PARAM_READABLE);
- g_object_class_install_property (object_class, PROP_HUMAN_NAME, pspec);
-
-/**
- * LdSymbol:area:
- *
- * The area of this symbol.
- */
- pspec = g_param_spec_boxed ("area", "Area",
- "The area of this symbol.",
- LD_TYPE_RECTANGLE, G_PARAM_READABLE);
- g_object_class_install_property (object_class, PROP_AREA, pspec);
-
-/**
- * LdSymbol:terminals:
- *
- * A point array that specifies terminals of this symbol.
- */
- pspec = g_param_spec_boxed ("terminals", "Terminals",
- "A point array that specifies terminals of this symbol.",
- LD_TYPE_POINT_ARRAY, G_PARAM_READABLE);
- g_object_class_install_property (object_class, PROP_TERMINALS, pspec);
-}
-
-static void
-ld_symbol_init (LdSymbol *self)
-{
-}
-
-static void
-ld_symbol_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- LdSymbol *self;
-
- self = LD_SYMBOL (object);
- switch (property_id)
- {
- case PROP_NAME:
- g_value_set_string (value, ld_symbol_get_name (self));
- break;
- case PROP_HUMAN_NAME:
- g_value_set_string (value, ld_symbol_get_human_name (self));
- break;
- case PROP_AREA:
- {
- LdRectangle area;
-
- ld_symbol_get_area (self, &area);
- g_value_set_boxed (value, &area);
- }
- break;
- case PROP_TERMINALS:
- g_value_set_boxed (value, ld_symbol_get_terminals (self));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-ld_symbol_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-
-/**
- * ld_symbol_get_name:
- * @self: An #LdSymbol object.
- *
- * Return value: The name of the symbol.
- */
-const gchar *
-ld_symbol_get_name (LdSymbol *self)
-{
- LdSymbolClass *klass;
-
- g_return_val_if_fail (LD_IS_SYMBOL (self), NULL);
-
- klass = LD_SYMBOL_GET_CLASS (self);
- g_return_val_if_fail (klass->get_name != NULL, NULL);
- return klass->get_name (self);
-}
-
-/**
- * ld_symbol_get_human_name:
- * @self: An #LdSymbol object.
- *
- * Return value: The localised human name of the symbol.
- */
-const gchar *
-ld_symbol_get_human_name (LdSymbol *self)
-{
- LdSymbolClass *klass;
-
- g_return_val_if_fail (LD_IS_SYMBOL (self), NULL);
-
- klass = LD_SYMBOL_GET_CLASS (self);
- g_return_val_if_fail (klass->get_human_name != NULL, NULL);
- return klass->get_human_name (self);
-}
-
-/**
- * ld_symbol_get_area:
- * @self: An #LdSymbol object.
- * @area: Where the area of the symbol will be returned.
- *
- * Get the area of the symbol.
- */
-void
-ld_symbol_get_area (LdSymbol *self, LdRectangle *area)
-{
- LdSymbolClass *klass;
-
- g_return_if_fail (LD_IS_SYMBOL (self));
- g_return_if_fail (area != NULL);
-
- klass = LD_SYMBOL_GET_CLASS (self);
- g_return_if_fail (klass->get_area != NULL);
- klass->get_area (self, area);
-}
-
-/**
- * ld_symbol_get_terminals:
- * @self: An #LdSymbol object.
- *
- * Get a list of symbol terminals.
- *
- * Return value: An #LdPointArray structure.
- */
-const LdPointArray *
-ld_symbol_get_terminals (LdSymbol *self)
-{
- LdSymbolClass *klass;
-
- g_return_val_if_fail (LD_IS_SYMBOL (self), NULL);
-
- klass = LD_SYMBOL_GET_CLASS (self);
- g_return_val_if_fail (klass->get_terminals != NULL, NULL);
- return klass->get_terminals (self);
-}
-
-/**
- * ld_symbol_draw:
- * @self: An #LdSymbol object.
- * @cr: A cairo surface to be drawn on.
- *
- * Draw the symbol onto a Cairo surface.
- */
-void
-ld_symbol_draw (LdSymbol *self, cairo_t *cr)
-{
- LdSymbolClass *klass;
-
- g_return_if_fail (LD_IS_SYMBOL (self));
- g_return_if_fail (cr != NULL);
-
- klass = LD_SYMBOL_GET_CLASS (self);
- g_return_if_fail (klass->draw != NULL);
- klass->draw (self, cr);
-}
diff --git a/src/ld-symbol.h b/src/ld-symbol.h
deleted file mode 100644
index 409eba5..0000000
--- a/src/ld-symbol.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * ld-symbol.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_SYMBOL_H__
-#define __LD_SYMBOL_H__
-
-G_BEGIN_DECLS
-
-
-#define LD_TYPE_SYMBOL (ld_symbol_get_type ())
-#define LD_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), LD_TYPE_SYMBOL, LdSymbol))
-#define LD_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \
- ((klass), LD_TYPE_SYMBOL, LdSymbolClass))
-#define LD_IS_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), LD_TYPE_SYMBOL))
-#define LD_IS_SYMBOL_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \
- ((klass), LD_TYPE_SYMBOL))
-#define LD_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), LD_SYMBOL, LdSymbolClass))
-
-typedef struct _LdSymbol LdSymbol;
-typedef struct _LdSymbolPrivate LdSymbolPrivate;
-typedef struct _LdSymbolClass LdSymbolClass;
-
-
-struct _LdSymbol
-{
-/*< private >*/
- GObject parent_instance;
- LdSymbolPrivate *priv;
-};
-
-/**
- * LdSymbolClass:
- * @parent_class: The parent class.
- * @get_name: Get the name of the symbol.
- * @get_human_name: Get the localized human name of the symbol.
- * @get_area: Get the area of the symbol.
- * @get_terminals: Get a list of symbol terminals.
- * @draw: Draw the symbol on a Cairo surface.
- */
-struct _LdSymbolClass
-{
- GObjectClass parent_class;
-
- const gchar *(*get_name) (LdSymbol *self);
- const gchar *(*get_human_name) (LdSymbol *self);
- void (*get_area) (LdSymbol *self, LdRectangle *area);
- const LdPointArray *(*get_terminals) (LdSymbol *self);
- void (*draw) (LdSymbol *self, cairo_t *cr);
-};
-
-
-GType ld_symbol_get_type (void) G_GNUC_CONST;
-
-const gchar *ld_symbol_get_name (LdSymbol *self);
-const gchar *ld_symbol_get_human_name (LdSymbol *self);
-void ld_symbol_get_area (LdSymbol *self, LdRectangle *area);
-const LdPointArray *ld_symbol_get_terminals (LdSymbol *self);
-void ld_symbol_draw (LdSymbol *self, cairo_t *cr);
-
-
-G_END_DECLS
-
-#endif /* ! __LD_SYMBOL_H__ */
-
diff --git a/src/ld-types.c b/src/ld-types.c
deleted file mode 100644
index cde3da6..0000000
--- a/src/ld-types.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * ld-types.c
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#include
-
-#include "liblogdiag.h"
-#include "config.h"
-
-
-#define DEFINE_BOXED_TYPE(TypeName, type_name) \
-GType \
-type_name ## _get_type (void) \
-{ \
- static GType our_type = 0; \
- if (our_type == 0) \
- our_type = g_boxed_type_register_static \
- (g_intern_static_string (#TypeName), \
- (GBoxedCopyFunc) type_name ## _copy, \
- (GBoxedFreeFunc) type_name ## _free); \
- return our_type; \
-}
-
-DEFINE_BOXED_TYPE (LdPoint, ld_point)
-DEFINE_BOXED_TYPE (LdPointArray, ld_point_array)
-DEFINE_BOXED_TYPE (LdRectangle, ld_rectangle)
-
-#define DEFINE_BOXED_TRIVIAL_COPY(TypeName, type_name) \
-TypeName * \
-type_name ## _copy (const TypeName *self) \
-{ \
- TypeName *new_copy; \
- g_return_val_if_fail (self != NULL, NULL); \
- new_copy = g_slice_new (TypeName); \
- *new_copy = *self; \
- return new_copy; \
-}
-
-#define DEFINE_BOXED_TRIVIAL_FREE(TypeName, type_name) \
-void \
-type_name ## _free (TypeName *self) \
-{ \
- g_return_if_fail (self != NULL); \
- g_slice_free (TypeName, self); \
-}
-
-/**
- * ld_point_copy:
- * @self: An #LdPoint structure.
- *
- * Makes a copy of the structure.
- * The result must be freed by ld_point_free().
- *
- * Return value: A copy of @self.
- */
-DEFINE_BOXED_TRIVIAL_COPY (LdPoint, ld_point)
-
-/**
- * ld_point_free:
- * @self: An #LdPoint structure.
- *
- * Frees the structure created with ld_point_copy().
- */
-DEFINE_BOXED_TRIVIAL_FREE (LdPoint, ld_point)
-
-/**
- * ld_point_distance:
- * @self: An #LdPoint structure.
- * @x: The X coordinate of the second point.
- * @y: The Y coordinate of the second point.
- *
- * Compute the distance between two points.
- */
-gdouble
-ld_point_distance (LdPoint *self, gdouble x, gdouble y)
-{
- gdouble dx, dy;
-
- g_return_val_if_fail (self != NULL, -1);
-
- dx = self->x - x;
- dy = self->y - y;
- return sqrt (dx * dx + dy * dy);
-}
-
-/**
- * ld_point_array_new:
- * @num_points: The number of points the array can store.
- *
- * Create a new array of points and initialize.
- *
- * Return value: An #LdPointArray structure.
- */
-LdPointArray *
-ld_point_array_new (gint num_points)
-{
- LdPointArray *new_array;
-
- g_return_val_if_fail (num_points >= 1, NULL);
-
- new_array = g_slice_new (LdPointArray);
- new_array->num_points = num_points;
- new_array->points = g_malloc0 (num_points * sizeof (LdPoint));
- return new_array;
-}
-
-/**
- * ld_point_array_copy:
- * @self: An #LdPointArray structure.
- *
- * Makes a copy of the structure.
- * The result must be freed by ld_point_array_free().
- *
- * Return value: A copy of @self.
- */
-LdPointArray *
-ld_point_array_copy (const LdPointArray *self)
-{
- LdPointArray *new_array;
-
- g_return_val_if_fail (self != NULL, NULL);
-
- new_array = g_slice_new (LdPointArray);
- new_array->num_points = self->num_points;
- new_array->points = g_memdup (self->points,
- self->num_points * sizeof (LdPoint));
- return new_array;
-}
-
-/**
- * ld_point_array_free:
- * @self: An #LdPointArray structure.
- *
- * Frees the structure created with ld_point_array_copy().
- */
-void
-ld_point_array_free (LdPointArray *self)
-{
- g_return_if_fail (self != NULL);
-
- g_free (self->points);
- g_slice_free (LdPointArray, self);
-}
-
-/**
- * ld_rectangle_copy:
- * @self: An #LdRectangle structure.
- *
- * Makes a copy of the structure.
- * The result must be freed by ld_rectangle_free().
- *
- * Return value: A copy of @self.
- */
-DEFINE_BOXED_TRIVIAL_COPY (LdRectangle, ld_rectangle)
-
-/**
- * ld_rectangle_free:
- * @self: An #LdRectangle structure.
- *
- * Frees the structure created with ld_rectangle_copy().
- */
-DEFINE_BOXED_TRIVIAL_FREE (LdRectangle, ld_rectangle)
-
-/**
- * ld_rectangle_contains:
- * @self: An #LdRectangle structure.
- * @x: The X coordinate of the point to be checked.
- * @y: The Y coordinate of the point to be checked.
- *
- * Return value: TRUE if the rectangle contains the specified point.
- */
-gboolean
-ld_rectangle_contains (LdRectangle *self, gdouble x, gdouble y)
-{
- g_return_val_if_fail (self != NULL, FALSE);
- return (x >= self->x && x <= self->x + self->width
- && y >= self->y && y <= self->y + self->height);
-}
-
-/**
- * ld_rectangle_intersects:
- * @self: An #LdRectangle structure.
- * @rect: An #LdRectangle to be checked for intersection.
- *
- * Return value: TRUE if the two rectangles intersect.
- */
-gboolean
-ld_rectangle_intersects (LdRectangle *self, LdRectangle *rect)
-{
- g_return_val_if_fail (self != NULL, FALSE);
- g_return_val_if_fail (rect != NULL, FALSE);
-
- return !(self->x > rect->x + rect->width
- || self->y > rect->y + rect->height
- || self->x + self->width < rect->x
- || self->y + self->height < rect->y);
-}
-
-/**
- * ld_rectangle_extend:
- * @self: An #LdRectangle structure.
- * @border: The border by which the rectangle should be extended.
- *
- * Extend a rectangle on all sides.
- */
-void
-ld_rectangle_extend (LdRectangle *self, gdouble border)
-{
- g_return_if_fail (self != NULL);
-
- self->x -= border;
- self->y -= border;
- self->width += 2 * border;
- self->height += 2 * border;
-}
diff --git a/src/ld-types.h b/src/ld-types.h
deleted file mode 100644
index 61a1a7d..0000000
--- a/src/ld-types.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * ld-types.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2010 - 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LD_TYPES_H__
-#define __LD_TYPES_H__
-
-G_BEGIN_DECLS
-
-
-/**
- * SECTION:ld-types
- * @short_description: Simple data types.
- *
- * #LdPoint defines coordinates of a point.
- *
- * #LdRectangle defines the position and size of a rectangle.
- */
-
-#define LD_TYPE_POINT (ld_point_get_type ())
-#define LD_TYPE_POINT_ARRAY (ld_point_array_get_type ())
-#define LD_TYPE_RECTANGLE (ld_rectangle_get_type ())
-
-typedef struct _LdPoint LdPoint;
-typedef struct _LdPointArray LdPointArray;
-typedef struct _LdRectangle LdRectangle;
-
-
-/**
- * LdPoint:
- * @x: The X coordinate.
- * @y: The Y coordinate.
- *
- * Defines a point.
- */
-struct _LdPoint
-{
- gdouble x, y;
-};
-
-GType ld_point_get_type (void) G_GNUC_CONST;
-
-LdPoint *ld_point_copy (const LdPoint *self);
-void ld_point_free (LdPoint *self);
-gdouble ld_point_distance (LdPoint *self, gdouble x, gdouble y);
-
-
-/**
- * LdPointArray:
- * @points: An array of #LdPoint structures.
- * @num_points: Count of points in @points.
- *
- * Moves quickly.
- */
-struct _LdPointArray
-{
- LdPoint *points;
- gint num_points;
-};
-
-GType ld_point_array_get_type (void) G_GNUC_CONST;
-
-LdPointArray *ld_point_array_new (gint num_points);
-LdPointArray *ld_point_array_copy (const LdPointArray *self);
-void ld_point_array_free (LdPointArray *self);
-
-
-/**
- * LdRectangle:
- * @x: Left-top X coordinate.
- * @y: Left-top Y coordinate.
- * @width: Width of the area, must be positive.
- * @height: Height of the area, must be positive.
- *
- * Defines a rectangle.
- */
-struct _LdRectangle
-{
- gdouble x, y;
- gdouble width, height;
-};
-
-GType ld_rectangle_get_type (void) G_GNUC_CONST;
-
-LdRectangle *ld_rectangle_copy (const LdRectangle *self);
-void ld_rectangle_free (LdRectangle *self);
-gboolean ld_rectangle_contains (LdRectangle *self, gdouble x, gdouble y);
-gboolean ld_rectangle_intersects (LdRectangle *self, LdRectangle *rect);
-void ld_rectangle_extend (LdRectangle *self, gdouble border);
-
-
-G_END_DECLS
-
-#endif /* ! __LD_TYPES_H__ */
-
diff --git a/src/ld-window-main.c b/src/ld-window-main.c
index 6cea286..56ab59a 100644
--- a/src/ld-window-main.c
+++ b/src/ld-window-main.c
@@ -22,9 +22,6 @@
*
* #LdWindowMain is the main window of the application.
*/
-/* NOTE: The main window should not maybe be included in either
- * the documentation or the static library.
- */
/*
* SymbolMenuItem:
diff --git a/src/liblogdiag.h b/src/liblogdiag.h
deleted file mode 100644
index 800826f..0000000
--- a/src/liblogdiag.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * liblogdiag.h
- *
- * This file is a part of logdiag.
- * Copyright Přemysl Janouch 2011. All rights reserved.
- *
- * See the file LICENSE for licensing information.
- *
- */
-
-#ifndef __LIBLOGDIAG_H__
-#define __LIBLOGDIAG_H__
-
-#include
-#include
-
-#include "ld-marshal.h"
-#include "ld-types.h"
-
-#include "ld-symbol.h"
-#include "ld-symbol-category.h"
-#include "ld-library.h"
-
-#include "ld-diagram-object.h"
-#include "ld-diagram-symbol.h"
-#include "ld-diagram.h"
-
-#include "ld-canvas.h"
-
-#include "ld-lua.h"
-#include "ld-lua-symbol.h"
-
-#endif /* ! __LIBLOGDIAG_H__ */
-
--
cgit v1.2.3-70-g09d2