First part of new concept for styles and layout elements
authorThomas White <taw@bitwiz.org.uk>
Sun, 25 Sep 2011 17:29:11 +0000 (19:29 +0200)
committerThomas White <taw@bitwiz.org.uk>
Sun, 25 Sep 2011 17:29:11 +0000 (19:29 +0200)
Makefile.am
data/colloquium.ui
src/mainwindow.c
src/objects.c
src/objects.h
src/presentation.h
src/slide_render.c
src/stylesheet.c
src/stylesheet.h
src/tool_text.c [new file with mode: 0644]
src/tool_text.h [new file with mode: 0644]

index 98e31d7..445f004 100644 (file)
@@ -10,12 +10,13 @@ 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/objects.c src/slideshow.c \
-                         src/stylesheet.c src/loadsave.c
+                         src/stylesheet.c src/loadsave.c src/tool_text.c
 
 INCLUDES = "-I$(top_srcdir)/data"
 
 EXTRA_DIST += src/presentation.h src/mainwindow.h src/slide_render .h \
-              src/objects.h src/slideshow.h src/stylesheet.h src/loadsave.h
+              src/objects.h src/slideshow.h src/stylesheet.h src/loadsave.h \
+              src/tool_text.h
 
 colloquiumdir = $(datadir)/colloquium
 colloquium_DATA = data/colloquium.ui
index f52500d..532056b 100644 (file)
                        <menuitem name="Stylesheet..." action="EditStyleAction" />
                </menu>
 
+               <menu name="insert" action="InsertAction">
+                       <menuitem name="newslide" action="NewSlideAction" />
+                       <separator />
+               </menu>
+
                <menu name="tools" action="ToolsAction">
                        <menuitem name="slideshow" action="TSlideshowAction" />
                        <menuitem name="preferences" action="PrefsAction" />
index b308cfe..3446aed 100644 (file)
@@ -38,6 +38,7 @@
 #include "slideshow.h"
 #include "stylesheet.h"
 #include "loadsave.h"
+#include "tool_text.h"
 
 
 static void add_ui_sig(GtkUIManager *ui, GtkWidget *widget,
@@ -255,6 +256,8 @@ static void update_toolbar(struct presentation *p)
                gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE);
 
        }
+
+
 }
 
 
@@ -369,44 +372,11 @@ static gint set_tool_sig(GtkWidget *widget, GtkRadioAction *action,
 }
 
 
-static void layout_changed_sig(GtkComboBox *combo, struct presentation *p)
-{
-       int n;
-
-       if ( p->editing_object != NULL ) {
-               printf("Can't change layout element!\n");
-               return;
-       }
-
-       n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-       p->cur_layout = p->ss->layout_elements[n];
-
-
-}
-
-
-static void text_style_changed_sig(GtkComboBox *combo, struct presentation *p)
-{
-       int n;
-
-       n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-       p->cur_style = p->ss->text_styles[n];
-
-       if ( p->editing_object != NULL ) {
-               set_text_style(p->editing_object, p->cur_style);
-               gdk_window_invalidate_rect(p->drawingarea->window, NULL, FALSE);
-       }
-}
-
-
 static void add_menu_bar(struct presentation *p, GtkWidget *vbox)
 {
        GError *error = NULL;
-       GtkWidget *label;
-       GtkWidget *combo;
        GtkToolItem *titem;
-       GtkWidget *box;
-       int i;
+       GtkWidget *toolbar;
        GtkActionEntry entries[] = {
 
                { "FileAction", NULL, "_File", NULL, NULL, NULL },
@@ -439,6 +409,10 @@ static void add_menu_bar(struct presentation *p, GtkWidget *vbox)
                { "EditStyleAction", NULL, "Stylesheet...",
                        NULL, NULL, G_CALLBACK(open_stylesheet_sig) },
 
+               { "InsertAction", NULL, "_Insert", NULL, NULL, NULL },
+               { "NewSlideAction", GTK_STOCK_ADD, "_New Slide",
+                       NULL, NULL, G_CALLBACK(add_slide_sig) },
+
                { "ToolsAction", NULL, "_Tools", NULL, NULL, NULL },
                { "TSlideshowAction", GTK_STOCK_FULLSCREEN, "_Start slideshow",
                        "F5", NULL, G_CALLBACK(start_slideshow_sig) },
@@ -492,43 +466,15 @@ static void add_menu_bar(struct presentation *p, GtkWidget *vbox)
                                   gtk_ui_manager_get_accel_group(p->ui));
        gtk_ui_manager_ensure_update(p->ui);
 
-       p->toolbar = gtk_ui_manager_get_widget(p->ui,
-                                              "/ui/displaywindowtoolbar");
-
+       toolbar = gtk_ui_manager_get_widget(p->ui,
+                                       "/ui/displaywindowtoolbar");
        titem = gtk_separator_tool_item_new();
-       gtk_toolbar_insert(GTK_TOOLBAR(p->toolbar), titem, -1);
+       gtk_toolbar_insert(GTK_TOOLBAR(toolbar), titem, -1);
 
-       box = gtk_vbox_new(FALSE, 0.0);
        p->tbox = gtk_hbox_new(FALSE, 0.0);
        titem = gtk_tool_item_new();
-       gtk_box_pack_start(GTK_BOX(box), p->tbox, FALSE, FALSE, 5.0);
-       gtk_container_add(GTK_CONTAINER(titem), box);
-       gtk_toolbar_insert(GTK_TOOLBAR(p->toolbar), titem, -1);
-       label = gtk_label_new("Layout element:");
-       gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
-       gtk_box_pack_start(GTK_BOX(p->tbox), label, FALSE, FALSE, 5.0);
-       combo = gtk_combo_box_new_text();
-       for ( i=0; i<p->ss->n_layout_elements; i++ ) {
-               gtk_combo_box_append_text(GTK_COMBO_BOX(combo),
-                                         p->ss->layout_elements[i]->name);
-       }
-       gtk_box_pack_start(GTK_BOX(p->tbox), combo, FALSE, FALSE, 5.0);
-       g_signal_connect(G_OBJECT(combo), "changed",
-                        G_CALLBACK(layout_changed_sig), p);
-       gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
-
-       label = gtk_label_new("Text style:");
-       gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
-       gtk_box_pack_start(GTK_BOX(p->tbox), label, FALSE, FALSE, 5.0);
-       combo = gtk_combo_box_new_text();
-       for ( i=0; i<p->ss->n_text_styles; i++ ) {
-               gtk_combo_box_append_text(GTK_COMBO_BOX(combo),
-                                         p->ss->text_styles[i]->name);
-       }
-       gtk_box_pack_start(GTK_BOX(p->tbox), combo, FALSE, FALSE, 5.0);
-       g_signal_connect(G_OBJECT(combo), "changed",
-                        G_CALLBACK(text_style_changed_sig), p);
-       gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
+       gtk_container_add(GTK_CONTAINER(titem), p->tbox);
+       gtk_toolbar_insert(GTK_TOOLBAR(toolbar), titem, -1);
 
        update_toolbar(p);
 }
@@ -670,9 +616,10 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event,
                case TOOL_TEXT :
                        if ( !clicked ) {
                                struct object *n;
+                               /* FIXME: Insert ESP here and possibly
+                                * select a different style */
                                n = add_text_object(p->view_slide, x, y,
-                                                   p->cur_layout,
-                                                   p->cur_style);
+                                                   p->ss->styles[0]);
                                p->editing_object = n;
                        } else {
                                p->editing_object = clicked;
@@ -707,6 +654,7 @@ static void draw_editing_bits(cairo_t *cr, struct presentation *p,
 {
        draw_editing_box(cr, o->x, o->y, o->bb_width, o->bb_height);
 
+       /* FIXME: Dispatch table */
        switch ( o->type ) {
 
        case TEXT :
@@ -716,31 +664,27 @@ static void draw_editing_bits(cairo_t *cr, struct presentation *p,
 
        }
 
-       if ( o->le != NULL ) {
-
-               cairo_move_to(cr, o->le->margin_left, -p->border_offs_y);
-               cairo_line_to(cr, o->le->margin_left,
-                                 p->slide_height+p->border_offs_y);
+       cairo_move_to(cr, o->style->margin_left, -p->border_offs_y);
+       cairo_line_to(cr, o->style->margin_left,
+                         p->slide_height+p->border_offs_y);
 
-               cairo_move_to(cr, p->slide_width-o->le->margin_right,
-                                 -p->border_offs_y);
-               cairo_line_to(cr, p->slide_width-o->le->margin_right,
-                                 p->slide_height+p->border_offs_y);
+       cairo_move_to(cr, p->slide_width-o->style->margin_right,
+                         -p->border_offs_y);
+       cairo_line_to(cr, p->slide_width-o->style->margin_right,
+                         p->slide_height+p->border_offs_y);
 
-               cairo_move_to(cr, -p->border_offs_x, o->le->margin_top);
-               cairo_line_to(cr, p->slide_width+p->border_offs_x,
-                                 o->le->margin_top);
+       cairo_move_to(cr, -p->border_offs_x, o->style->margin_top);
+       cairo_line_to(cr, p->slide_width+p->border_offs_x,
+                         o->style->margin_top);
 
-               cairo_move_to(cr, -p->border_offs_x,
-                                 p->slide_height-o->le->margin_bottom);
-               cairo_line_to(cr, p->slide_width+p->border_offs_x,
-                                 p->slide_height-o->le->margin_bottom);
+       cairo_move_to(cr, -p->border_offs_x,
+                         p->slide_height-o->style->margin_bottom);
+       cairo_line_to(cr, p->slide_width+p->border_offs_x,
+                         p->slide_height-o->style->margin_bottom);
 
-               cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
-               cairo_set_line_width(cr, 1.0);
-               cairo_stroke(cr);
-
-       }
+       cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
+       cairo_set_line_width(cr, 1.0);
+       cairo_stroke(cr);
 }
 
 
index ae634a5..4d18df1 100644 (file)
@@ -34,7 +34,7 @@
 #include "mainwindow.h"
 
 
-static struct object *new_object(enum objtype t, struct layout_element *le)
+struct object *new_object(enum objtype t, struct style *sty)
 {
        struct object *new;
 
@@ -44,13 +44,13 @@ static struct object *new_object(enum objtype t, struct layout_element *le)
        new->type = t;
        new->empty = 1;
        new->parent = NULL;
-       new->le = le;
+       new->style = sty;
 
        return new;
 }
 
 
-static void free_object(struct object *o)
+void free_object(struct object *o)
 {
        if ( o->layout != NULL ) g_object_unref(o->layout);
        if ( o->fontdesc != NULL ) pango_font_description_free(o->fontdesc);
@@ -58,207 +58,29 @@ static void free_object(struct object *o)
 }
 
 
-struct object *add_text_object(struct slide *s, double x, double y,
-                               struct layout_element *el, struct text_style *ts)
+struct object *add_image_object(struct slide *s, double x, double y,
+                                const char *filename,
+                                double width, double height)
 {
        struct object *new;
 
-       new = new_object(TEXT, el);
+       new = new_object(IMAGE, NULL);
+
+       new->x = x;  new->y = y;
+       new->bb_width = width;
+       new->bb_height = height;
+
        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 = malloc(1);
-       new->text[0] = '\0';
-       new->text_len = 1;
-       new->insertion_point = 0;
-       new->style = ts;
-       new->layout = NULL;
-       new->fontdesc = NULL;
-
        s->object_seq++;
 
        return new;
 }
 
 
-void insert_text(struct object *o, char *t)
-{
-       char *tmp;
-       size_t tlen, olen;
-       int i;
-
-       assert(o->type == TEXT);
-       tlen = strlen(t);
-       olen = strlen(o->text);
-
-       if ( tlen + olen + 1 > o->text_len ) {
-
-               char *try;
-
-               try = realloc(o->text, o->text_len + tlen + 64);
-               if ( try == NULL ) return;  /* Failed to insert */
-               o->text = try;
-               o->text_len += 64;
-               o->text_len += tlen;
-
-       }
-
-       tmp = malloc(o->text_len);
-       if ( tmp == NULL ) return;
-
-       for ( i=0; i<o->insertion_point; i++ ) {
-               tmp[i] = o->text[i];
-       }
-       for ( i=0; i<tlen; i++ ) {
-               tmp[i+o->insertion_point] = t[i];
-       }
-       for ( i=0; i<olen-o->insertion_point; i++ ) {
-               tmp[i+o->insertion_point+tlen] = o->text[i+o->insertion_point];
-       }
-       tmp[olen+tlen] = '\0';
-       memcpy(o->text, tmp, o->text_len);
-       free(tmp);
-
-       o->insertion_point += tlen;
-       o->parent->object_seq++;
-       o->empty = 0;
-}
-
-
-void set_text_style(struct object *o, struct text_style *ts)
-{
-       assert(o->type == TEXT);
-       o->style = ts;
-       o->parent->object_seq++;
-}
-
-
-static int find_prev_index(const char *t, int p)
-{
-       int i, nback;
-
-       if ( p == 0 ) return 0;
-
-       if ( !(t[p-1] & 0x80) ) {
-               nback = 1;
-       } else {
-               nback = 0;
-               for ( i=1; i<=6; i++ ) {
-                       if ( p-i == 0 ) return 0;
-                       if ( !(t[p-i] & 0xC0) ) nback++;
-               }
-       }
-
-       return p - nback;
-}
-
-
-static int find_next_index(const char *t, int p)
-{
-       int i, nfor;
-
-       if ( t[p] == '\0' ) return p;
-
-       if ( !(t[p+1] & 0x80) ) {
-               nfor = 1;
-       } else {
-               nfor = 0;
-               for ( i=1; i<=6; i++ ) {
-                       if ( t[p+i] == '\0' ) return p+i;
-                       if ( !(t[p+i] & 0xC0) ) nfor++;
-               }
-       }
-
-       return p + nfor;
-}
-
-
-void handle_text_backspace(struct object *o)
-{
-       int prev_index;
-
-       assert(o->type == TEXT);
-
-       if ( o->insertion_point == 0 ) return;  /* Nothing to delete */
-
-       prev_index = find_prev_index(o->text, o->insertion_point);
-
-       memmove(o->text+prev_index, o->text+o->insertion_point,
-               o->text_len-o->insertion_point);
-
-       o->insertion_point = prev_index;
-
-       if ( strlen(o->text) == 0 ) o->empty = 1;
-
-       o->parent->object_seq++;
-}
-
-
-void move_cursor_left(struct object *o)
-{
-       o->insertion_point = find_prev_index(o->text, o->insertion_point);
-}
-
-
-void move_cursor_right(struct object *o)
-{
-       o->insertion_point = find_next_index(o->text, o->insertion_point);
-}
-
-
-void position_caret(struct object *o, double x, double y)
-{
-       int idx, trail;
-       int xp, yp;
-       gboolean v;
-
-       assert(o->type == TEXT);
-
-       xp = (x - o->x)*PANGO_SCALE;
-       yp = (y - o->y)*PANGO_SCALE;
-
-       v = pango_layout_xy_to_index(o->layout, xp, yp, &idx, &trail);
-
-       o->insertion_point = idx+trail;
-}
-
-
-void notify_style_update(struct presentation *p, struct text_style *ts)
-{
-       int i;
-       int changed = 0;
-
-       for ( i=0; i<p->num_slides; i++ ) {
-
-               int j;
-               struct slide *s;
-
-               s = p->slides[i];
-
-               for ( j=0; j<p->slides[i]->num_objects; j++ ) {
-
-                       if ( s->objects[j]->type != TEXT ) continue;
-                       if ( s->objects[j]->style != ts ) continue;
-
-                       s->object_seq++;
-                       if ( p->view_slide == s ) changed = 1;
-                       break;
-
-               }
-
-       }
-
-       p->completely_empty = 0;
-       if ( changed ) notify_slide_update(p);
-}
-
-
-void notify_layout_update(struct presentation *p, struct layout_element *le)
+void notify_style_update(struct presentation *p, struct style *sty)
 {
        int i;
        int changed = 0;
@@ -272,7 +94,7 @@ void notify_layout_update(struct presentation *p, struct layout_element *le)
 
                for ( j=0; j<p->slides[i]->num_objects; j++ ) {
 
-                       if ( s->objects[j]->le != le ) continue;
+                       if ( s->objects[j]->style != sty ) continue;
 
                        s->object_seq++;
                        if ( p->view_slide == s ) changed = 1;
index ddbd2a8..d7eb706 100644 (file)
@@ -31,6 +31,7 @@
 enum objtype
 {
        TEXT,
+       IMAGE,
 };
 
 
@@ -38,7 +39,7 @@ struct object
 {
        enum objtype   type;
        struct slide  *parent;
-       struct layout_element *le;
+       struct style  *style;
 
        /* Position of corner of object */
        double         x;
@@ -56,23 +57,17 @@ struct object
        int            insertion_point;
        PangoLayout   *layout;
        PangoFontDescription *fontdesc;
-       struct text_style *style;
 };
 
+extern struct object *new_object(enum objtype t, struct style *sty);
+extern void free_object(struct object *o);
+extern struct object *add_image_object(struct slide *s, double x, double y,
+                                       const char *filename,
+                                       double width, double height);
 
-extern struct object *add_text_object(struct slide *s, double x, double y,
-                                      struct layout_element *el,
-                                      struct text_style *ts);
-extern void insert_text(struct object *o, char *t);
-extern void set_text_style(struct object *o, struct text_style *ts);
-extern void notify_style_update(struct presentation *p, struct text_style *ts);
-extern void handle_text_backspace(struct object *o);
-extern void move_cursor_left(struct object *o);
-extern void move_cursor_right(struct object *o);
-extern void position_caret(struct object *o, double x, double y);
 
-extern void notify_layout_update(struct presentation *p,
-                                 struct layout_element *ts);
+extern void notify_style_update(struct presentation *p,
+                                 struct style *sty);
 
 extern void delete_object(struct object *o);
 
index d48fd96..db53f07 100644 (file)
@@ -67,7 +67,6 @@ struct presentation
        GtkUIManager     *ui;
        GtkActionGroup   *action_group;
        GtkIMContext     *im_context;
-       GtkWidget        *toolbar;
        GtkWidget        *tbox;
        int               drag_preview_pending;
        int               have_drag_data;
@@ -79,9 +78,8 @@ struct presentation
        int               drag_y;
 
        /* Stylesheet */
-       StyleSheet            *ss;
-       struct text_style     *cur_style;
-       struct layout_element *cur_layout;
+       StyleSheet       *ss;
+       struct style     *default_style;
 
        /* Dialogue boxes */
        StylesheetWindow *stylesheetwindow;
index 3a34f6a..8c438d4 100644 (file)
 #include "stylesheet.h"
 
 
-static void render_text_object(cairo_t *cr, struct object *o)
+static void calculate_size_from_style(struct object *o,
+                                      double *peright, double *pebottom,
+                                      double *pmw, double *pmh)
 {
-       double ebottom, eright, mw, mh;
        double max_width, max_height;
-       double xo, yo;
-       PangoRectangle ink, logical;
-
-       o->layout = pango_cairo_create_layout(cr);
-       pango_layout_set_text(o->layout, o->text, -1);
-       o->fontdesc = pango_font_description_from_string(o->style->font);
-       pango_layout_set_font_description(o->layout, o->fontdesc);
+       double ebottom, eright, mw, mh;
 
-       eright = o->parent->slide_width - o->le->margin_right;
-       ebottom = o->parent->slide_height - o->le->margin_bottom;
+       eright = o->parent->slide_width - o->style->margin_right;
+       ebottom = o->parent->slide_height - o->style->margin_bottom;
        mw = o->parent->slide_width;
        mh = o->parent->slide_height;
 
-       max_width = mw - o->le->margin_left - o->le->margin_right;
+       *peright = eright;  *pebottom = ebottom;
+       *pmw = mw;  *pmh = mh;
+
+       max_width = mw - o->style->margin_left - o->style->margin_right;
 
        /* Use the provided maximum width if it exists and is smaller */
-       if ( o->le->use_max_width && (o->le->max_width < max_width) ) {
-               max_width = o->le->max_width;
+       if ( o->style->use_max_width && (o->style->max_width < max_width) )
+       {
+               max_width = o->style->max_width;
        }
 
-       max_height = mh - o->le->margin_top - o->le->margin_bottom;
+       max_height = mh - o->style->margin_top - o->style->margin_bottom;
 
        pango_layout_set_width(o->layout, max_width*PANGO_SCALE);
        pango_layout_set_height(o->layout, max_height*PANGO_SCALE);
        pango_layout_set_wrap(o->layout, PANGO_WRAP_WORD_CHAR);
        pango_layout_set_ellipsize(o->layout, PANGO_ELLIPSIZE_MIDDLE);
 
-       switch ( o->le->halign ) {
+       switch ( o->style->halign ) {
        case J_LEFT :
                pango_layout_set_alignment(o->layout, PANGO_ALIGN_LEFT);
                break;
@@ -77,66 +76,100 @@ static void render_text_object(cairo_t *cr, struct object *o)
                pango_layout_set_alignment(o->layout, PANGO_ALIGN_CENTER);
                break;
        }
+}
 
-       pango_cairo_update_layout(cr, o->layout);
+
+static void calculate_position_from_style(struct object *o,
+                                          double eright, double ebottom,
+                                          double mw, double mh)
+{
+       double xo, yo;
+       PangoRectangle ink, logical;
 
        pango_layout_get_extents(o->layout, &ink, &logical);
-       o->bb_width = ink.width / PANGO_SCALE;
-       o->bb_height = logical.height/PANGO_SCALE;
        xo = ink.x/PANGO_SCALE;  yo = logical.y/PANGO_SCALE;
 
-       switch ( o->le->halign ) {
+       switch ( o->style->halign ) {
        case J_LEFT :
-               o->x = -xo + o->le->margin_left;
+               o->x = -xo + o->style->margin_left;
                break;
        case J_RIGHT :
                o->x = -xo + eright - o->bb_width;
                break;
        case J_CENTER :
-               o->x = mw/2.0 - o->bb_width/2.0 - xo + o->le->offset_x;
+               o->x = mw/2.0 - o->bb_width/2.0 - xo + o->style->offset_x;
                break;
        }
 
-       if ( o->le->halign == J_CENTER ) {
+       if ( o->style->halign == J_CENTER ) {
 
-               if ( o->x+xo < o->le->margin_left ) {
-                       o->x = o->le->margin_left - xo;
+               if ( o->x+xo < o->style->margin_left ) {
+                       o->x = o->style->margin_left - xo;
                }
 
-               if ( o->x+xo + o->bb_width > mw-o->le->margin_right ) {
-                       o->x = mw-o->le->margin_right - xo - o->bb_width;
+               if ( o->x+xo + o->bb_width > mw-o->style->margin_right ) {
+                       o->x = mw-o->style->margin_right - xo - o->bb_width;
                }
        }
 
-       switch ( o->le->valign ) {
+       switch ( o->style->valign ) {
        case V_TOP :
-               o->y = o->le->margin_top;
+               o->y = o->style->margin_top;
                break;
        case V_BOTTOM :
                o->y = ebottom - o->bb_height;
                break;
        case V_CENTER :
-               o->y = mh/2.0 - o->bb_height/2.0 + yo - o->le->offset_y;
+               o->y = mh/2.0 - o->bb_height/2.0 + yo - o->style->offset_y;
                break;
        }
 
-       if ( o->le->valign == V_CENTER ) {
+       if ( o->style->valign == V_CENTER ) {
 
-               if ( o->y < o->le->margin_top ) {
-                       o->y = o->le->margin_top;
+               if ( o->y < o->style->margin_top ) {
+                       o->y = o->style->margin_top;
                }
 
-               if ( o->y+yo + o->bb_height > mh - o->le->margin_bottom ) {
-                       o->y = mh-o->le->margin_bottom - yo - o->bb_height;
+               if ( o->y+yo + o->bb_height > mh - o->style->margin_bottom ) {
+                       o->y = mh-o->style->margin_bottom - yo - o->bb_height;
                }
        }
 
+       o->x += xo;
+       o->y += yo;
+}
+
+
+static void render_text_object(cairo_t *cr, struct object *o)
+{
+       PangoRectangle ink, logical;
+       double eright, ebottom, mw, mh;
+
+       o->layout = pango_cairo_create_layout(cr);
+       pango_layout_set_text(o->layout, o->text, -1);
+       o->fontdesc = pango_font_description_from_string(o->style->font);
+       pango_layout_set_font_description(o->layout, o->fontdesc);
+
+       if ( o->style != o->parent->parent->ss->styles[0] )
+       {
+               calculate_size_from_style(o, &eright, &ebottom, &mw, &mh);
+       }
+
+       pango_cairo_update_layout(cr, o->layout);
+
+       pango_layout_get_extents(o->layout, &ink, &logical);
+       o->bb_width = ink.width / PANGO_SCALE;
+       o->bb_height = logical.height/PANGO_SCALE;
+
+       if ( o->style != o->parent->parent->ss->styles[0] )
+       {
+               calculate_position_from_style(o, eright, ebottom, mw, mh);
+       }
+
        cairo_move_to(cr, o->x, o->y);
        cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
        pango_cairo_show_layout(cr, o->layout);
 
-       o->x += xo;
-       o->y += yo;
 }
 
 
index 46167a1..b4cc11e 100644 (file)
@@ -57,38 +57,20 @@ struct _stylesheetwindow
        GtkWidget           *max_width;
        GtkWidget           *use_max;
 
-       struct text_style *cur_text_style;
-       struct layout_element *cur_layout_element;
+       struct style        *cur_style;
 };
 
 
-static void text_changed_sig(GtkComboBox *combo,
-                             struct _stylesheetwindow *s)
-{
-       int n;
-       GdkColor col;
-
-       n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-       s->cur_text_style = s->ss->text_styles[n];
-
-       gtk_font_button_set_font_name(GTK_FONT_BUTTON(s->text_font),
-                                     s->cur_text_style->font);
-
-       gdk_color_parse(s->cur_text_style->colour, &col);
-       gtk_color_button_set_color(GTK_COLOR_BUTTON(s->text_colour), &col);
-}
-
-
 static void text_font_set_sig(GtkFontButton *widget,
                               struct _stylesheetwindow *s)
 {
        const gchar *font;
 
        font = gtk_font_button_get_font_name(widget);
-       free(s->cur_text_style->font);
-       s->cur_text_style->font = strdup(font);
+       free(s->cur_style->font);
+       s->cur_style->font = strdup(font);
 
-       notify_style_update(s->p, s->cur_text_style);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
@@ -99,147 +81,84 @@ static void text_colour_set_sig(GtkColorButton *widget,
        guint16 al;
 
        gtk_color_button_get_color(widget, &col);
-       free(s->cur_text_style->colour);
-       s->cur_text_style->colour = gdk_color_to_string(&col);
+       free(s->cur_style->colour);
+       s->cur_style->colour = gdk_color_to_string(&col);
        al = gtk_color_button_get_alpha(widget);
-       s->cur_text_style->alpha = (double)al / 65535.0;
+       s->cur_style->alpha = (double)al / 65535.0;
 
-       notify_style_update(s->p, s->cur_text_style);
-}
-
-
-static void do_text(struct _stylesheetwindow *s, GtkWidget *b)
-{
-       GtkWidget *table;
-       GtkWidget *box;
-       GtkWidget *line;
-       GtkWidget *label;
-       GtkWidget *combo;
-       GtkWidget *vbox;
-       int i;
-
-       vbox = gtk_vbox_new(FALSE, 0);
-       gtk_box_pack_start(GTK_BOX(b), vbox, TRUE, TRUE, 0);
-
-       table = gtk_table_new(4, 2, FALSE);
-       gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 5);
-       gtk_table_set_row_spacings(GTK_TABLE(table), 5.0);
-       gtk_table_set_col_spacings(GTK_TABLE(table), 5.0);
-
-       label = gtk_label_new("Style:");
-       gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
-       gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
-       combo = gtk_combo_box_new_text();
-       gtk_table_attach_defaults(GTK_TABLE(table), combo, 1, 4, 0, 1);
-
-       for ( i=0; i<s->ss->n_text_styles; i++ ) {
-               gtk_combo_box_append_text(GTK_COMBO_BOX(combo),
-                                         s->ss->text_styles[i]->name);
-       }
-       gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
-       gtk_widget_set_size_request(GTK_WIDGET(combo), 300, -1);
-       g_signal_connect(G_OBJECT(combo), "changed",
-                        G_CALLBACK(text_changed_sig), s);
-
-       line = gtk_hseparator_new();
-       gtk_table_attach_defaults(GTK_TABLE(table), line, 0, 4, 1, 2);
-       gtk_table_set_row_spacing(GTK_TABLE(table), 0, 10);
-       gtk_table_set_row_spacing(GTK_TABLE(table), 1, 10);
-
-       label = gtk_label_new("Font:");
-       gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
-       gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
-       s->text_font = gtk_font_button_new_with_font("Sans 12");
-       box = gtk_hbox_new(FALSE, 0);
-       gtk_table_attach_defaults(GTK_TABLE(table), box, 1, 2, 2, 3);
-       gtk_box_pack_start(GTK_BOX(box), s->text_font, FALSE, FALSE, 0);
-       g_signal_connect(G_OBJECT(s->text_font), "font-set",
-                        G_CALLBACK(text_font_set_sig), s);
-
-       label = gtk_label_new("Colour:");
-       gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
-       gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
-       s->text_colour = gtk_color_button_new();
-       box = gtk_hbox_new(FALSE, 0);
-       gtk_table_attach_defaults(GTK_TABLE(table), box, 1, 2, 3, 4);
-       gtk_box_pack_start(GTK_BOX(box), s->text_colour, FALSE, FALSE, 0);
-       g_signal_connect(G_OBJECT(s->text_colour), "color-set",
-                        G_CALLBACK(text_colour_set_sig), s);
-
-       /* Force first update */
-       text_changed_sig(GTK_COMBO_BOX(combo), s);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
 static void margin_left_changed_sig(GtkSpinButton *spin,
                                     struct _stylesheetwindow *s)
 {
-       s->cur_layout_element->margin_left = gtk_spin_button_get_value(spin);
-       notify_layout_update(s->p, s->cur_layout_element);
+       s->cur_style->margin_left = gtk_spin_button_get_value(spin);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
 static void margin_right_changed_sig(GtkSpinButton *spin,
                                      struct _stylesheetwindow *s)
 {
-       s->cur_layout_element->margin_right = gtk_spin_button_get_value(spin);
-       notify_layout_update(s->p, s->cur_layout_element);
+       s->cur_style->margin_right = gtk_spin_button_get_value(spin);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
 static void margin_top_changed_sig(GtkSpinButton *spin,
                                    struct _stylesheetwindow *s)
 {
-       s->cur_layout_element->margin_top = gtk_spin_button_get_value(spin);
-       notify_layout_update(s->p, s->cur_layout_element);
+       s->cur_style->margin_top = gtk_spin_button_get_value(spin);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
 static void margin_bottom_changed_sig(GtkSpinButton *spin,
                                       struct _stylesheetwindow *s)
 {
-       s->cur_layout_element->margin_bottom = gtk_spin_button_get_value(spin);
-       notify_layout_update(s->p, s->cur_layout_element);
+       s->cur_style->margin_bottom = gtk_spin_button_get_value(spin);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
 static void offset_x_changed_sig(GtkSpinButton *spin,
                                  struct _stylesheetwindow *s)
 {
-       s->cur_layout_element->offset_x = gtk_spin_button_get_value(spin);
-       notify_layout_update(s->p, s->cur_layout_element);
+       s->cur_style->offset_x = gtk_spin_button_get_value(spin);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
 static void offset_y_changed_sig(GtkSpinButton *spin,
                                  struct _stylesheetwindow *s)
 {
-       s->cur_layout_element->offset_y = gtk_spin_button_get_value(spin);
-       notify_layout_update(s->p, s->cur_layout_element);
+       s->cur_style->offset_y = gtk_spin_button_get_value(spin);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
 static void halign_changed_sig(GtkComboBox *combo,
                                  struct _stylesheetwindow *s)
 {
-       s->cur_layout_element->halign = gtk_combo_box_get_active(combo);
-       notify_layout_update(s->p, s->cur_layout_element);
+       s->cur_style->halign = gtk_combo_box_get_active(combo);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
 static void valign_changed_sig(GtkComboBox *combo,
                                  struct _stylesheetwindow *s)
 {
-       s->cur_layout_element->valign = gtk_combo_box_get_active(combo);
-       notify_layout_update(s->p, s->cur_layout_element);
+       s->cur_style->valign = gtk_combo_box_get_active(combo);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
 static void max_changed_sig(GtkSpinButton *spin,
                             struct _stylesheetwindow *s)
 {
-       s->cur_layout_element->max_width = gtk_spin_button_get_value(spin);
-       notify_layout_update(s->p, s->cur_layout_element);
+       s->cur_style->max_width = gtk_spin_button_get_value(spin);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
@@ -249,45 +168,56 @@ static void use_max_toggled_sig(GtkToggleButton *combo,
        int v;
 
        v = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(s->use_max));
-       s->cur_layout_element->use_max_width = v;
+       s->cur_style->use_max_width = v;
        gtk_widget_set_sensitive(s->max_width,
-                                s->cur_layout_element->use_max_width);
-       notify_layout_update(s->p, s->cur_layout_element);
+                                s->cur_style->use_max_width);
+       notify_style_update(s->p, s->cur_style);
 }
 
 
-static void layout_changed_sig(GtkComboBox *combo,
+static void style_changed_sig(GtkComboBox *combo,
                                struct _stylesheetwindow *s)
 {
        int n;
+       GdkColor col;
 
        n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-       s->cur_layout_element = s->ss->layout_elements[n];
+       s->cur_style = s->ss->styles[n];
+       /* FIXME: Handle default style */
 
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->margin_left),
-                                 s->cur_layout_element->margin_left);
+                                 s->cur_style->margin_left);
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->margin_right),
-                                 s->cur_layout_element->margin_right);
+                                 s->cur_style->margin_right);
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->margin_bottom),
-                                 s->cur_layout_element->margin_bottom);
+                                 s->cur_style->margin_bottom);
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->margin_top),
-                                 s->cur_layout_element->margin_top);
+                                 s->cur_style->margin_top);
 
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->offset_x),
-                                 s->cur_layout_element->offset_x);
+                                 s->cur_style->offset_x);
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->offset_y),
-                                 s->cur_layout_element->offset_y);
+                                 s->cur_style->offset_y);
 
        gtk_combo_box_set_active(GTK_COMBO_BOX(s->halign),
-                                s->cur_layout_element->halign);
+                                s->cur_style->halign);
        gtk_combo_box_set_active(GTK_COMBO_BOX(s->valign),
-                                s->cur_layout_element->valign);
+                                s->cur_style->valign);
 
        gtk_widget_set_sensitive(s->max_width,
-                                s->cur_layout_element->use_max_width);
+                                s->cur_style->use_max_width);
 
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->max_width),
-                                 s->cur_layout_element->max_width);
+                                 s->cur_style->max_width);
+
+       n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
+       s->cur_style = s->ss->styles[n];
+
+       gtk_font_button_set_font_name(GTK_FONT_BUTTON(s->text_font),
+                                     s->cur_style->font);
+
+       gdk_color_parse(s->cur_style->colour, &col);
+       gtk_color_button_set_color(GTK_COLOR_BUTTON(s->text_colour), &col);
 }
 
 
@@ -307,13 +237,13 @@ static void do_layout(struct _stylesheetwindow *s, GtkWidget *b)
        gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
        gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
        combo = gtk_combo_box_new_text();
-       for ( i=0; i<s->ss->n_layout_elements; i++ ) {
+       for ( i=0; i<s->ss->n_styles; i++ ) {
                gtk_combo_box_append_text(GTK_COMBO_BOX(combo),
-                                         s->ss->layout_elements[i]->name);
+                                         s->ss->styles[i]->name);
        }
        gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
        g_signal_connect(G_OBJECT(combo), "changed",
-                        G_CALLBACK(layout_changed_sig), s);
+                        G_CALLBACK(style_changed_sig), s);
        gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0);
 
        line = gtk_hseparator_new();
@@ -428,8 +358,34 @@ static void do_layout(struct _stylesheetwindow *s, GtkWidget *b)
        g_signal_connect(G_OBJECT(s->max_width), "value-changed",
                         G_CALLBACK(max_changed_sig), s);
 
+       /* Font/colour stuff */
+       table = gtk_table_new(3, 2, FALSE);
+       gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 5);
+       gtk_table_set_row_spacings(GTK_TABLE(table), 5.0);
+       gtk_table_set_col_spacings(GTK_TABLE(table), 5.0);
+
+       label = gtk_label_new("Font:");
+       gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
+       gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
+       s->text_font = gtk_font_button_new_with_font("Sans 12");
+       box = gtk_hbox_new(FALSE, 0);
+       gtk_table_attach_defaults(GTK_TABLE(table), box, 1, 2, 0, 1);
+       gtk_box_pack_start(GTK_BOX(box), s->text_font, FALSE, FALSE, 0);
+       g_signal_connect(G_OBJECT(s->text_font), "font-set",
+                        G_CALLBACK(text_font_set_sig), s);
+
+       label = gtk_label_new("Colour:");
+       gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
+       gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
+       s->text_colour = gtk_color_button_new();
+       box = gtk_hbox_new(FALSE, 0);
+       gtk_table_attach_defaults(GTK_TABLE(table), box, 1, 2, 1, 2);
+       gtk_box_pack_start(GTK_BOX(box), s->text_colour, FALSE, FALSE, 0);
+       g_signal_connect(G_OBJECT(s->text_colour), "color-set",
+                        G_CALLBACK(text_colour_set_sig), s);
+
        /* Force first update */
-       layout_changed_sig(GTK_COMBO_BOX(combo), s);
+       style_changed_sig(GTK_COMBO_BOX(combo), s);
 }
 
 
@@ -442,115 +398,85 @@ static gint destroy_stylesheet_sig(GtkWidget *w, struct _stylesheetwindow *s)
 }
 
 
-static void add_text_style(StyleSheet *ss, struct text_style *st)
-{
-       int n = ss->n_text_styles;
-       ss->text_styles = realloc(ss->text_styles,
-                                       (n+1)*sizeof(st));
-
-       ss->text_styles[n] = st;
-
-       ss->n_text_styles = n+1;
-}
-
-
-static struct text_style *new_text_style(StyleSheet *ss, const char *name)
+static struct style *new_style(StyleSheet *ss, const char *name)
 {
-       struct text_style *st;
-
-       st = malloc(sizeof(*st));
-       if ( st == NULL ) return NULL;
-
-       st->name = strdup(name);
-       st->colour = strdup("#000000000000");  /* Black */
-       st->alpha = 1.0;
-
-       add_text_style(ss, st);
-
-       return st;
-}
-
-
-static struct layout_element *new_layout_element(StyleSheet *ss,
-                                                 const char *name)
-{
-       struct layout_element *ly;
+       struct style *sty;
        int n;
+       struct style **styles_new;
 
-       ly = malloc(sizeof(*ly));
-       if ( ly == NULL ) return NULL;
-
-       ly->name = strdup(name);
-
-       n = ss->n_layout_elements;
-       ss->layout_elements = realloc(ss->layout_elements, (n+1)*sizeof(ly));
-       /* Yes, the size of the pointer */
+       sty = malloc(sizeof(*sty));
+       if ( sty == NULL ) return NULL;
 
-       ss->layout_elements[n] = ly;
-       ss->n_layout_elements = n+1;
+       n = ss->n_styles;
+       styles_new = realloc(ss->styles, (n+1)*sizeof(sty));
+       if ( styles_new == NULL ) {
+               free(sty);
+               return NULL;
+       }
+       ss->styles = styles_new;
+       ss->styles[n] = sty;
+       ss->n_styles = n+1;
 
-       return ly;
+       return sty;
 }
 
 
 static void default_stylesheet(StyleSheet *ss)
 {
-       struct text_style *st;
-       struct layout_element *ly;
-
-       st = new_text_style(ss, "Slide title");
-       st->font = strdup("Sans 40");
-       ly = new_layout_element(ss, st->name);
-       ly->text_style = st;
-       ly->margin_left = 20.0;
-       ly->margin_right = 20.0;
-       ly->margin_top = 20.0;
-       ly->margin_bottom = 20.0;
-       ly->halign = J_CENTER;
-       ly->valign = V_TOP;
-       ly->offset_x = 0.0;
-       ly->offset_y = 0.0;  /* irrelevant */
-
-       st = new_text_style(ss, "Presentation title");
-       st->font = strdup("Sans 50");
-       ly = new_layout_element(ss, st->name);
-       ly->text_style = st;
-       ly->margin_left = 20.0;
-       ly->margin_right = 20.0;
-       ly->margin_top = 20.0;
-       ly->margin_bottom = 20.0;
-       ly->halign = J_CENTER;
-       ly->valign = V_CENTER;
-       ly->offset_x = -200.0;
-       ly->offset_y = +300.0;
-
-       st = new_text_style(ss, "Presentation author");
-       st->font = strdup("Sans 30");
-       ly = new_layout_element(ss, st->name);
-       ly->text_style = st;
-       ly->margin_left = 20.0;
-       ly->margin_right = 20.0;
-       ly->margin_top = 20.0;
-       ly->margin_bottom = 20.0;
-       ly->halign = J_CENTER;
-       ly->valign = V_CENTER;
-       ly->offset_x = +200.0;
-       ly->offset_y = -300.0;
-
-       st = new_text_style(ss, "Running text");
-       st->font = strdup("Sans 14");
-
-       ly = new_layout_element(ss, "Slide content");
-       ly->text_style = st;
-       ly->margin_left = 20.0;
-       ly->margin_right = 20.0;
-       ly->margin_top = 20.0;
-       ly->margin_bottom = 20.0;
-       ly->halign = J_CENTER;
-       ly->valign = V_CENTER;
-       ly->offset_x = +200.0;
-       ly->offset_y = -300.0;
-
+       struct style *sty;
+
+       /* Default style must be first */
+       sty = new_style(ss, "Default");
+       sty->font = strdup("Sans 18");
+       sty->colour = strdup("#000000000000");  /* Black */
+       sty->alpha = 1.0;
+       sty->margin_left = 20.0;
+       sty->margin_right = 20.0;
+       sty->margin_top = 20.0;
+       sty->margin_bottom = 20.0;
+       sty->halign = J_CENTER;  /* Ignored */
+       sty->valign = V_CENTER;  /* Ignored */
+       sty->offset_x = 0.0;  /* Ignored */
+       sty->offset_y = 0.0;  /* Ignored */
+
+       sty = new_style(ss, "Slide title");
+       sty->font = strdup("Sans 40");
+       sty->colour = strdup("#000000000000");  /* Black */
+       sty->alpha = 1.0;
+       sty->margin_left = 20.0;
+       sty->margin_right = 20.0;
+       sty->margin_top = 20.0;
+       sty->margin_bottom = 20.0;
+       sty->halign = J_CENTER;
+       sty->valign = V_TOP;
+       sty->offset_x = 0.0;
+       sty->offset_y = 0.0;  /* irrelevant */
+
+       sty = new_style(ss, "Presentation title");
+       sty->font = strdup("Sans 50");
+       sty->colour = strdup("#000000000000");  /* Black */
+       sty->alpha = 1.0;
+       sty->margin_left = 20.0;
+       sty->margin_right = 20.0;
+       sty->margin_top = 20.0;
+       sty->margin_bottom = 20.0;
+       sty->halign = J_CENTER;
+       sty->valign = V_CENTER;
+       sty->offset_x = -200.0;
+       sty->offset_y = +300.0;
+
+       sty = new_style(ss, "Presentation author");
+       sty->font = strdup("Sans 30");
+       sty->colour = strdup("#000000000000");  /* Black */
+       sty->alpha = 1.0;
+       sty->margin_left = 20.0;
+       sty->margin_right = 20.0;
+       sty->margin_top = 20.0;
+       sty->margin_bottom = 20.0;
+       sty->halign = J_CENTER;
+       sty->valign = V_CENTER;
+       sty->offset_x = +200.0;
+       sty->offset_y = -300.0;
 }
 
 
@@ -561,10 +487,8 @@ StyleSheet *new_stylesheet()
        ss = calloc(1, sizeof(struct _stylesheet));
        if ( ss == NULL ) return NULL;
 
-       ss->n_text_styles = 0;
-       ss->text_styles = NULL;
-       ss->n_layout_elements = 0;
-       ss->layout_elements = NULL;
+       ss->n_styles = 0;
+       ss->styles = NULL;
        default_stylesheet(ss);
 
        return ss;
@@ -622,8 +546,8 @@ StylesheetWindow *open_stylesheet(struct presentation *p)
 
        s->p = p;
        s->ss = p->ss;
-       s->cur_text_style = NULL;
-       s->cur_layout_element = NULL;
+       s->cur_style = NULL;
+       s->cur_style = NULL;
 
        s->window = gtk_dialog_new_with_buttons("Stylesheet",
                                           GTK_WINDOW(p->window), 0,
@@ -639,12 +563,6 @@ StylesheetWindow *open_stylesheet(struct presentation *p)
        text_box = gtk_vbox_new(FALSE, 0);
        gtk_container_set_border_width(GTK_CONTAINER(text_box), 12);
        gtk_notebook_append_page(GTK_NOTEBOOK(nb), text_box,
-                                gtk_label_new("Text styles"));
-       do_text(s, text_box);
-
-       text_box = gtk_vbox_new(FALSE, 0);
-       gtk_container_set_border_width(GTK_CONTAINER(text_box), 12);
-       gtk_notebook_append_page(GTK_NOTEBOOK(nb), text_box,
                                 gtk_label_new("Slide layout"));
        do_layout(s, text_box);
 
index 8f9733e..4b7f7fb 100644 (file)
 #endif
 
 
-struct text_style
-{
-       char   *name;
-       char   *font;
-       char   *colour;
-       double  alpha;
-};
-
-
 enum justify
 {
        J_LEFT   = 0,
@@ -53,10 +44,9 @@ enum vert_pos
 };
 
 
-struct layout_element
+struct style
 {
        char              *name;
-       struct text_style *text_style;
 
        double             margin_left;
        double             margin_right;
@@ -70,22 +60,19 @@ struct layout_element
 
        double             offset_x;
        double             offset_y;
+
+       char              *font;
+       char              *colour;
+       double             alpha;
 };
 
 
 struct _stylesheet
 {
-       /* Slide layout */
-       struct layout_element **layout_elements;
-       int                     n_layout_elements;
-
-       /* Normal text styles */
-       struct text_style **text_styles;
-       int                 n_text_styles;
+       struct style **styles;
+       int            n_styles;
 
        /* Background stuff */
-
-       /* Image styles */
 };
 
 
diff --git a/src/tool_text.c b/src/tool_text.c
new file mode 100644 (file)
index 0000000..9419a12
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * tool_text.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 <assert.h>
+
+#include "presentation.h"
+#include "objects.h"
+#include "mainwindow.h"
+
+
+struct object *add_text_object(struct slide *s, double x, double y,
+                               struct style *sty)
+{
+       struct object *new;
+
+       new = new_object(TEXT, sty);
+
+       new->x = x;  new->y = y;
+       new->bb_width = 10.0;
+       new->bb_height = 40.0;
+       new->text = malloc(1);
+       new->text[0] = '\0';
+       new->text_len = 1;
+       new->insertion_point = 0;
+       new->layout = NULL;
+       new->fontdesc = NULL;
+
+       if ( add_object_to_slide(s, new) ) {
+               free_object(new);
+               return NULL;
+       }
+       s->object_seq++;
+
+       return new;
+}
+
+
+void insert_text(struct object *o, char *t)
+{
+       char *tmp;
+       size_t tlen, olen;
+       int i;
+
+       assert(o->type == TEXT);
+       tlen = strlen(t);
+       olen = strlen(o->text);
+
+       if ( tlen + olen + 1 > o->text_len ) {
+
+               char *try;
+
+               try = realloc(o->text, o->text_len + tlen + 64);
+               if ( try == NULL ) return;  /* Failed to insert */
+               o->text = try;
+               o->text_len += 64;
+               o->text_len += tlen;
+
+       }
+
+       tmp = malloc(o->text_len);
+       if ( tmp == NULL ) return;
+
+       for ( i=0; i<o->insertion_point; i++ ) {
+               tmp[i] = o->text[i];
+       }
+       for ( i=0; i<tlen; i++ ) {
+               tmp[i+o->insertion_point] = t[i];
+       }
+       for ( i=0; i<olen-o->insertion_point; i++ ) {
+               tmp[i+o->insertion_point+tlen] = o->text[i+o->insertion_point];
+       }
+       tmp[olen+tlen] = '\0';
+       memcpy(o->text, tmp, o->text_len);
+       free(tmp);
+
+       o->insertion_point += tlen;
+       o->parent->object_seq++;
+       o->empty = 0;
+}
+
+
+void set_text_style(struct object *o, struct style *sty)
+{
+       assert(o->type == TEXT);
+       o->style = sty;
+       o->parent->object_seq++;
+}
+
+
+static int find_prev_index(const char *t, int p)
+{
+       int i, nback;
+
+       if ( p == 0 ) return 0;
+
+       if ( !(t[p-1] & 0x80) ) {
+               nback = 1;
+       } else {
+               nback = 0;
+               for ( i=1; i<=6; i++ ) {
+                       if ( p-i == 0 ) return 0;
+                       if ( !(t[p-i] & 0xC0) ) nback++;
+               }
+       }
+
+       return p - nback;
+}
+
+
+static int find_next_index(const char *t, int p)
+{
+       int i, nfor;
+
+       if ( t[p] == '\0' ) return p;
+
+       if ( !(t[p+1] & 0x80) ) {
+               nfor = 1;
+       } else {
+               nfor = 0;
+               for ( i=1; i<=6; i++ ) {
+                       if ( t[p+i] == '\0' ) return p+i;
+                       if ( !(t[p+i] & 0xC0) ) nfor++;
+               }
+       }
+
+       return p + nfor;
+}
+
+
+void handle_text_backspace(struct object *o)
+{
+       int prev_index;
+
+       assert(o->type == TEXT);
+
+       if ( o->insertion_point == 0 ) return;  /* Nothing to delete */
+
+       prev_index = find_prev_index(o->text, o->insertion_point);
+
+       memmove(o->text+prev_index, o->text+o->insertion_point,
+               o->text_len-o->insertion_point);
+
+       o->insertion_point = prev_index;
+
+       if ( strlen(o->text) == 0 ) o->empty = 1;
+
+       o->parent->object_seq++;
+}
+
+
+void move_cursor_left(struct object *o)
+{
+       o->insertion_point = find_prev_index(o->text, o->insertion_point);
+}
+
+
+void move_cursor_right(struct object *o)
+{
+       o->insertion_point = find_next_index(o->text, o->insertion_point);
+}
+
+
+void position_caret(struct object *o, double x, double y)
+{
+       int idx, trail;
+       int xp, yp;
+       gboolean v;
+
+       assert(o->type == TEXT);
+
+       xp = (x - o->x)*PANGO_SCALE;
+       yp = (y - o->y)*PANGO_SCALE;
+
+       v = pango_layout_xy_to_index(o->layout, xp, yp, &idx, &trail);
+
+       o->insertion_point = idx+trail;
+}
diff --git a/src/tool_text.h b/src/tool_text.h
new file mode 100644 (file)
index 0000000..cd190ae
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * tool_text.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 TOOL_TEXT_H
+#define TOOL_TEXT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+extern struct object *add_text_object(struct slide *s, double x, double y,
+                                      struct style *sty);
+extern void insert_text(struct object *o, char *t);
+extern void handle_text_backspace(struct object *o);
+extern void move_cursor_left(struct object *o);
+extern void move_cursor_right(struct object *o);
+extern void position_caret(struct object *o, double x, double y);
+
+
+#endif /* TOOL_TEXT_H */