aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am5
-rw-r--r--src/mainwindow.c118
-rw-r--r--src/objects.c81
-rw-r--r--src/objects.h62
-rw-r--r--src/presentation.c63
-rw-r--r--src/presentation.h23
-rw-r--r--src/slide_render.c38
7 files changed, 345 insertions, 45 deletions
diff --git a/Makefile.am b/Makefile.am
index d8cf801..1b777f5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,11 +9,12 @@ AM_CPPFLAGS = -DDATADIR=\""$(datadir)"\" -I$(top_builddir)/lib -I$(top_srcdir)/l
LDADD = $(top_builddir)/lib/libgnu.a @IGNORE_UNUSED_LIBRARIES_CFLAGS@
src_colloquium_SOURCES = src/colloquium.c src/presentation.c src/mainwindow.c \
- src/slide_render.c
+ src/slide_render.c src/objects.c
INCLUDES = "-I$(top_srcdir)/data"
-EXTRA_DIST += src/presentation.h src/mainwindow.h src/slide_render.h
+EXTRA_DIST += src/presentation.h src/mainwindow.h src/slide_render.h \
+ src/objects.h
colloquiumdir = $(datadir)/colloquium
colloquium_DATA = data/colloquium.ui
diff --git a/src/mainwindow.c b/src/mainwindow.c
index 289a096..904c69f 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -33,6 +33,7 @@
#include "presentation.h"
#include "mainwindow.h"
#include "slide_render.h"
+#include "objects.h"
static void add_ui_sig(GtkUIManager *ui, GtkWidget *widget,
@@ -138,12 +139,82 @@ static gint close_sig(GtkWidget *window, struct presentation *p)
}
+static gboolean im_commit_sig(GtkIMContext *im, gchar *str,
+ struct presentation *p)
+{
+ return FALSE;
+}
+
+
+static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event,
+ struct presentation *p)
+{
+ gboolean r;
+
+ if ( p->editing_object == NULL ) return FALSE;
+
+ /* Throw the event to the IM context and let it sort things out */
+ gtk_im_context_filter_keypress(GTK_IM_CONTEXT(p->im_context), event);
+
+ /* FIXME: Invalidate only the necessary region */
+ gdk_window_invalidate_rect(p->drawingarea->window, NULL, FALSE);
+
+ return FALSE;
+}
+
+
static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event,
struct presentation *p)
{
- printf("%f %f\n", event->x - p->border_offs_x,
- event->y - p->border_offs_y);
- return 0;
+ if ( p->editing_object && p->editing_object->empty ) {
+ delete_object(p->editing_object);
+ }
+
+ p->editing_object = add_text_object(p->view_slide,
+ event->x - p->border_offs_x,
+ event->y - p->border_offs_y);
+
+ gtk_widget_grab_focus(GTK_WIDGET(da));
+
+ /* FIXME: Invalidate only the necessary region */
+ gdk_window_invalidate_rect(p->drawingarea->window, NULL, FALSE);
+
+ return FALSE;
+}
+
+
+static void draw_editing_box(cairo_t *cr, double xmin, double ymin,
+ double width, double height)
+{
+ cairo_new_path(cr);
+ cairo_rectangle(cr, xmin, ymin, width, height);
+ cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+ cairo_set_line_width(cr, 1.0);
+ cairo_stroke(cr);
+}
+
+
+static void draw_editing_bits(cairo_t *cr, struct object *o)
+{
+ switch ( o->type ) {
+
+ case TEXT :
+
+ draw_editing_box(cr, o->x - o->bb_width/2.0,
+ o->y - o->bb_height/2.0,
+ o->bb_width, o->bb_height);
+ break;
+
+ }
+}
+
+
+static void check_redraw_slide(struct slide *s)
+{
+ /* Update necessary? */
+ if ( s->object_seq <= s->render_cache_seq ) return;
+
+ render_slide(s);
}
@@ -154,12 +225,14 @@ static gboolean expose_sig(GtkWidget *da, GdkEventExpose *event,
GtkAllocation allocation;
double xoff, yoff;
+ check_redraw_slide(p->view_slide);
+
cr = gdk_cairo_create(da->window);
/* Overall background */
cairo_rectangle(cr, event->area.x, event->area.y,
event->area.width, event->area.height);
- cairo_set_source_rgb(cr, 0.8, 0.8, 1.0);
+ cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
cairo_fill(cr);
/* Get the overall size */
@@ -168,27 +241,22 @@ static gboolean expose_sig(GtkWidget *da, GdkEventExpose *event,
yoff = (allocation.height - p->slide_height)/2.0;
p->border_offs_x = xoff; p->border_offs_y = yoff;
- cairo_translate(cr, xoff, yoff);
-
/* Draw the slide from the cache */
cairo_rectangle(cr, event->area.x, event->area.y,
event->area.width, event->area.height);
- cairo_set_source_surface(cr, p->slides[p->view_slide]->render_cache,
- 0.0, 0.0);
+ cairo_set_source_surface(cr, p->view_slide->render_cache, xoff, yoff);
cairo_fill(cr);
- cairo_destroy(cr);
-
- return FALSE;
-}
+ cairo_translate(cr, xoff, yoff);
+ /* Draw editing bits for selected object */
+ if ( p->editing_object != NULL ) {
+ draw_editing_bits(cr, p->editing_object);
+ }
-static void check_redraw_slide(struct presentation *p, int n)
-{
- /* Update necessary? */
- if ( p->slides[n]->object_seq <= p->slides[n]->render_cache_seq ) return;
+ cairo_destroy(cr);
- render_slide(p->slides[n]);
+ return FALSE;
}
@@ -235,17 +303,25 @@ int open_mainwindow(struct presentation *p)
GDK_POINTER_MOTION_HINT_MASK
| GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
| GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
- g_signal_connect(GTK_OBJECT(p->drawingarea), "button-press-event",
- G_CALLBACK(button_press_sig), p);
- g_signal_connect(GTK_OBJECT(p->drawingarea), "expose-event",
+ g_signal_connect(G_OBJECT(p->drawingarea), "button-press-event",
+ G_CALLBACK(button_press_sig), p);
+ g_signal_connect(G_OBJECT(p->drawingarea), "key-press-event",
+ G_CALLBACK(key_press_sig), p);
+ g_signal_connect(G_OBJECT(p->drawingarea), "expose-event",
G_CALLBACK(expose_sig), p);
+ p->im_context = gtk_im_multicontext_new();
+ gtk_im_context_set_client_window(GTK_IM_CONTEXT(p->im_context),
+ p->drawingarea->window);
+ g_signal_connect(G_OBJECT(p->im_context), "commit",
+ G_CALLBACK(im_commit_sig), p);
+
gtk_window_set_default_size(GTK_WINDOW(p->window), 1024+100, 768+100);
gtk_window_set_resizable(GTK_WINDOW(p->window), TRUE);
assert(p->num_slides > 0);
- check_redraw_slide(p, p->view_slide);
+ check_redraw_slide(p->view_slide);
gtk_widget_show_all(window);
return 0;
diff --git a/src/objects.c b/src/objects.c
new file mode 100644
index 0000000..576eeb8
--- /dev/null
+++ b/src/objects.c
@@ -0,0 +1,81 @@
+/*
+ * objects.c
+ *
+ * Colloquium - A tiny presentation program
+ *
+ * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "presentation.h"
+#include "objects.h"
+
+
+static struct object *new_object(enum objtype t)
+{
+ struct object *new;
+
+ new = malloc(sizeof(struct object));
+ if ( new == NULL ) return NULL;
+
+ new->type = t;
+ new->empty = 1;
+ new->parent = NULL;
+
+ return new;
+}
+
+
+static void free_object(struct object *o)
+{
+ free(o);
+}
+
+
+struct object *add_text_object(struct slide *s, double x, double y)
+{
+ struct object *new;
+
+ new = new_object(TEXT);
+ if ( add_object_to_slide(s, new) ) {
+ free_object(new);
+ return NULL;
+ }
+
+ new->x = x; new->y = y;
+ new->bb_width = 10.0;
+ new->bb_height = 40.0;
+ new->text = "Hello";
+
+ s->object_seq++;
+
+ return new;
+}
+
+
+void delete_object(struct object *o)
+{
+ remove_object_from_slide(o->parent, o);
+ free_object(o);
+}
diff --git a/src/objects.h b/src/objects.h
new file mode 100644
index 0000000..c220b00
--- /dev/null
+++ b/src/objects.h
@@ -0,0 +1,62 @@
+/*
+ * presentation.h
+ *
+ * Colloquium - A tiny presentation program
+ *
+ * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OBJECTS_H
+#define OBJECTS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+enum objtype
+{
+ TEXT,
+};
+
+
+struct object
+{
+ enum objtype type;
+ struct slide *parent;
+
+ /* Position of object, the interpretation of which depends on
+ * the type of the object */
+ double x;
+ double y;
+
+ /* Side of rectangular bounding box of object */
+ double bb_width;
+ double bb_height;
+
+ int empty;
+
+ /* For type TEXT */
+ char *text;
+};
+
+
+extern struct object *add_text_object(struct slide *s, double x, double y);
+extern void delete_object(struct object *o);
+
+
+#endif /* OBJECTS_H */
diff --git a/src/presentation.c b/src/presentation.c
index b67c8fd..38b50fc 100644
--- a/src/presentation.c
+++ b/src/presentation.c
@@ -27,27 +27,29 @@
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include "presentation.h"
#include "slide_render.h"
+#include "objects.h"
-int add_slide(struct presentation *p)
+struct slide *add_slide(struct presentation *p)
{
struct slide **try;
struct slide *new;
- try = realloc(p->slides, p->num_slides*sizeof(struct slide **));
- if ( try == NULL ) return 1;
+ try = realloc(p->slides, (1+p->num_slides)*sizeof(struct slide *));
+ if ( try == NULL ) return NULL;
p->slides = try;
new = malloc(sizeof(struct slide));
- if ( new == NULL ) return 1;
+ if ( new == NULL ) return NULL;
/* Doesn't matter that p->slides now has some excess space -
* it'll get corrected the next time a slide is added or deleted. */
/* No objects to start with */
- new->n_objects = 0;
+ new->num_objects = 0;
new->object_seq = 0;
new->objects = NULL;
@@ -59,10 +61,55 @@ int add_slide(struct presentation *p)
render_slide(new); /* Render nothing, just to make the surface exist */
p->slides[p->num_slides++] = new;
+ printf("Now %i slides\n", p->num_slides);
+ return new;
+}
+
+
+int add_object_to_slide(struct slide *s, struct object *o)
+{
+ struct object **try;
+
+ try = realloc(s->objects, (1+s->num_objects)*sizeof(struct object *));
+ if ( try == NULL ) return 1;
+ s->objects = try;
+
+ s->objects[s->num_objects++] = o;
+ o->parent = s;
+
+ printf("Now %i objects in slide %p\n", s->num_objects, s);
+
return 0;
}
+void remove_object_from_slide(struct slide *s, struct object *o)
+{
+ int i;
+ int found = 0;
+
+ for ( i=0; i<s->num_objects; i++ ) {
+
+ if ( s->objects[i] == o ) {
+ assert(!found);
+ found = 1;
+ continue;
+ }
+
+ if ( found ) {
+ if ( i == s->num_objects-1 ) {
+ s->objects[i] = NULL;
+ } else {
+ s->objects[i] = s->objects[i+1];
+ }
+ }
+
+ }
+
+ s->num_objects--;
+}
+
+
struct presentation *new_presentation()
{
struct presentation *new;
@@ -79,11 +126,13 @@ struct presentation *new_presentation()
new->slide_width = 1024.0;
new->slide_height = 768.0;
+ /* Add one blank slide and view it */
new->num_slides = 0;
new->slides = NULL;
- add_slide(new);
+ new -> view_slide = add_slide(new);
+ new->view_slide_number = 0;
- new->view_slide = 0;
+ new->editing_object = NULL;
return new;
}
diff --git a/src/presentation.h b/src/presentation.h
index 5b219a2..528084d 100644
--- a/src/presentation.h
+++ b/src/presentation.h
@@ -31,25 +31,13 @@
#include <gtk/gtk.h>
-enum objtype
-{
- RECTANGLE,
-};
-
-
-struct object
-{
- enum objtype type;
-};
-
-
struct slide
{
cairo_surface_t *render_cache;
int render_cache_seq;
- int n_objects;
- struct object *objects;
+ int num_objects;
+ struct object **objects;
int object_seq;
double slide_width;
@@ -66,6 +54,7 @@ struct presentation
GtkWidget *drawingarea;
GtkUIManager *ui;
GtkActionGroup *action_group;
+ GtkIMContext *im_context;
double slide_width;
double slide_height;
@@ -73,7 +62,9 @@ struct presentation
double border_offs_y;
/* The slide currently being displayed */
- unsigned int view_slide;
+ unsigned int view_slide_number;
+ struct slide *view_slide;
+ struct object *editing_object;
unsigned int num_slides;
struct slide **slides;
@@ -81,6 +72,8 @@ struct presentation
extern struct presentation *new_presentation(void);
+extern int add_object_to_slide(struct slide *s, struct object *o);
+extern void remove_object_from_slide(struct slide *s, struct object *o);
#endif /* PRESENTATION_H */
diff --git a/src/slide_render.c b/src/slide_render.c
index 1966fe7..33eee36 100644
--- a/src/slide_render.c
+++ b/src/slide_render.c
@@ -26,15 +26,40 @@
#endif
#include <cairo.h>
+#include <pango/pangocairo.h>
#include "slide_render.h"
#include "presentation.h"
+#include "objects.h"
+
+
+static void render_text_object(cairo_t *cr, struct object *o)
+{
+ PangoLayout *l;
+ PangoFontDescription *d;
+ int width, height;
+
+ l = pango_cairo_create_layout(cr);
+ pango_layout_set_text(l, o->text, -1);
+ d = pango_font_description_from_string("Sans 30");
+ pango_layout_set_font_description(l, d);
+ pango_font_description_free(d);
+
+ pango_cairo_update_layout(cr, l);
+ pango_layout_get_size(l, &width, &height);
+ cairo_move_to(cr, o->x - (width/PANGO_SCALE)/2.0,
+ o->y - (height/PANGO_SCALE)/2.0);
+
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ pango_cairo_show_layout(cr, l);
+}
int render_slide(struct slide *s)
{
cairo_surface_t *surf;
cairo_t *cr;
+ int i;
surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
s->slide_width, s->slide_height);
@@ -45,10 +70,23 @@ int render_slide(struct slide *s)
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_fill(cr);
+ for ( i=0; i<s->num_objects; i++ ) {
+
+ struct object *o = s->objects[i];
+
+ switch ( o->type ) {
+ case TEXT :
+ render_text_object(cr, o);
+ break;
+ }
+
+ }
+
cairo_destroy(cr);
if ( s->render_cache != NULL ) cairo_surface_destroy(s->render_cache);
s->render_cache = surf;
+ s->render_cache_seq = s->object_seq;
return 0;
}