aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.me.uk>2019-03-15 23:37:27 +0100
committerThomas White <taw@bitwiz.me.uk>2019-03-15 23:37:27 +0100
commit0e1f2f49f4d3b02901c8ba291a8ffb2605418db4 (patch)
treededb4e864a02cb8181f2b44d13891bafc91a12d4
parent44f874ed89b364bc0b60b35572f64fae44154733 (diff)
Initial GtkSlideView
-rw-r--r--libstorycode/gtk/gtknarrativeview.c26
-rw-r--r--libstorycode/gtk/gtknarrativeview.h2
-rw-r--r--libstorycode/gtk/gtkslideview.c2150
-rw-r--r--libstorycode/gtk/gtkslideview.h123
-rw-r--r--libstorycode/presentation.c15
-rw-r--r--libstorycode/presentation.h6
-rw-r--r--libstorycode/slide.c3
-rw-r--r--libstorycode/slide_render_cairo.h7
-rw-r--r--meson.build5
-rw-r--r--src/narrative_window.c17
-rw-r--r--src/pdfstorycode.c4
-rw-r--r--src/slide_window.c244
-rw-r--r--src/slide_window.h35
13 files changed, 491 insertions, 2146 deletions
diff --git a/libstorycode/gtk/gtknarrativeview.c b/libstorycode/gtk/gtknarrativeview.c
index ec34778..226ce93 100644
--- a/libstorycode/gtk/gtknarrativeview.c
+++ b/libstorycode/gtk/gtknarrativeview.c
@@ -285,8 +285,12 @@ static void gtk_narrative_view_class_init(GtkNarrativeViewClass *klass)
GTK_WIDGET_CLASS(klass)->get_preferred_height = get_preferred_height;
GTK_WIDGET_CLASS(klass)->get_preferred_height_for_width = NULL;
- g_signal_new("changed", GTK_TYPE_NARRATIVE_VIEW, G_SIGNAL_RUN_LAST, 0,
+ g_signal_new("changed", GTK_TYPE_NARRATIVE_VIEW,
+ G_SIGNAL_RUN_LAST, 0,
NULL, NULL, NULL, G_TYPE_NONE, 0);
+ g_signal_new("slide-double-clicked", GTK_TYPE_NARRATIVE_VIEW,
+ G_SIGNAL_RUN_LAST, 0,
+ NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER);
}
@@ -905,16 +909,26 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event,
GtkNarrativeView *e)
{
gdouble x, y;
+ Narrative *n;
+ n = presentation_get_narrative(e->p);
x = event->x;
y = event->y + e->scroll_pos;
/* Clicked an existing frame, no immediate dragging */
e->drag_status = DRAG_STATUS_COULD_DRAG;
unset_selection(e);
- find_cursor(presentation_get_narrative(e->p), x, y, &e->sel_start);
- find_cursor(presentation_get_narrative(e->p), x, y, &e->sel_end);
- find_cursor(presentation_get_narrative(e->p), x, y, &e->cpos);
+ find_cursor(n, x, y, &e->sel_start);
+ e->sel_end = e->sel_start;
+ e->cpos = e->sel_start;
+
+ if ( event->type == GDK_2BUTTON_PRESS ) {
+ struct narrative_item *item = &n->items[e->cpos.para];
+ if ( item->type == NARRATIVE_ITEM_SLIDE ) {
+ g_signal_emit_by_name(e, "slide-double-clicked",
+ item->slide);
+ }
+ }
gtk_widget_grab_focus(GTK_WIDGET(da));
redraw(e);
@@ -1101,7 +1115,7 @@ static gint realise_sig(GtkWidget *da, GtkNarrativeView *e)
}
-GtkNarrativeView *gtk_narrative_view_new(Presentation *p)
+GtkWidget *gtk_narrative_view_new(Presentation *p)
{
GtkNarrativeView *nview;
GtkTargetEntry targets[1];
@@ -1159,5 +1173,5 @@ GtkNarrativeView *gtk_narrative_view_new(Presentation *p)
gtk_widget_show(GTK_WIDGET(nview));
- return nview;
+ return GTK_WIDGET(nview);
}
diff --git a/libstorycode/gtk/gtknarrativeview.h b/libstorycode/gtk/gtknarrativeview.h
index 942044e..ec27a06 100644
--- a/libstorycode/gtk/gtknarrativeview.h
+++ b/libstorycode/gtk/gtknarrativeview.h
@@ -110,7 +110,7 @@ struct _gtknarrativeviewclass
typedef struct _gtknarrativeview GtkNarrativeView;
typedef struct _gtknarrativeviewclass GtkNarrativeViewClass;
-extern GtkNarrativeView *gtk_narrative_view_new(Presentation *p);
+extern GtkWidget *gtk_narrative_view_new(Presentation *p);
extern void gtk_narrative_view_set_logical_size(GtkNarrativeView *e, double w, double h);
diff --git a/libstorycode/gtk/gtkslideview.c b/libstorycode/gtk/gtkslideview.c
index 8e79fd8..bf32cdb 100644
--- a/libstorycode/gtk/gtkslideview.c
+++ b/libstorycode/gtk/gtkslideview.c
@@ -1,7 +1,7 @@
/*
- * sc_editor.c
+ * gtkslideview.c
*
- * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2013-2019 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -32,790 +32,95 @@
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <math.h>
+#include <libintl.h>
+#define _(x) gettext(x)
-#include "colloquium.h"
-#include "presentation.h"
-#include "slide_window.h"
-#include "render.h"
-#include "frame.h"
-#include "sc_parse.h"
-#include "sc_interp.h"
-#include "sc_editor.h"
-#include "slideshow.h"
-#include "debugger.h"
-#include "utils.h"
+#include <presentation.h>
+#include <slide_render_cairo.h>
+//#include "slide_window.h"
+#include "gtkslideview.h"
+#include "slide_priv.h"
+//#include "slideshow.h"
-static void scroll_interface_init(GtkScrollable *iface)
-{
-}
-
-
-enum
-{
- SCEDITOR_0,
- SCEDITOR_VADJ,
- SCEDITOR_HADJ,
- SCEDITOR_VPOL,
- SCEDITOR_HPOL,
-};
-
-
-G_DEFINE_TYPE_WITH_CODE(SCEditor, sc_editor, GTK_TYPE_DRAWING_AREA,
- G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE,
- scroll_interface_init))
-
-static void debug_paragraphs(SCEditor *e)
-{
- struct frame *fr = e->cursor_frame;
- int i;
-
- printf("Paragraphs in current frame:\n");
- for ( i=0; i<fr->n_paras; i++ ) {
- show_para(fr->paras[i]);
- }
-}
-
-
-static void horizontal_adjust(GtkAdjustment *adj, SCEditor *e)
-{
- e->h_scroll_pos = gtk_adjustment_get_value(adj);
- sc_editor_redraw(e);
-}
-
-static void set_horizontal_params(SCEditor *e)
-{
- if ( e->hadj == NULL ) return;
- gtk_adjustment_configure(e->hadj, e->h_scroll_pos, 0, e->w, 100,
- e->visible_width, e->visible_width);
-}
-
-
-static void vertical_adjust(GtkAdjustment *adj, SCEditor *e)
-{
- e->scroll_pos = gtk_adjustment_get_value(adj);
- sc_editor_redraw(e);
-}
-
-
-static void set_vertical_params(SCEditor *e)
-{
- double page;
-
- if ( e->vadj == NULL ) return;
-
- /* Ensure we do not scroll off the top of the document */
- if ( e->scroll_pos < 0.0 ) e->scroll_pos = 0.0;
-
- /* Ensure we do not scroll off the bottom of the document */
- if ( e->scroll_pos > e->h - e->visible_height ) {
- e->scroll_pos = e->h - e->visible_height;
- }
-
- /* If we can show the whole document, show it at the top */
- if ( e->h < e->visible_height ) {
- e->scroll_pos = 0.0;
- }
-
- if ( e->h > e->visible_height ) {
- page = e->visible_height;
- } else {
- page = e->h;
- }
-
- gtk_adjustment_configure(e->vadj, e->scroll_pos, 0, e->h, 100,
- e->visible_height, page);
-}
-
-
-static void update_size(SCEditor *e)
-{
- if ( e->flow ) {
-
- double total = total_height(e->top);
-
- e->w = e->top->w;
- e->h = total + e->top->pad_t + e->top->pad_b;
-
- e->log_w = e->w;
- e->log_h = e->h;
- e->top->h = e->h;
- } else {
- e->top->w = e->log_w;
- e->top->h = e->log_h;
- }
-
- if ( e->flow && (e->top->h < e->visible_height) ) {
- e->top->h = e->visible_height;
- }
-
- set_vertical_params(e);
- set_horizontal_params(e);
-}
+G_DEFINE_TYPE_WITH_CODE(GtkSlideView, gtk_slide_view, GTK_TYPE_DRAWING_AREA,
+ NULL)
static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event,
- SCEditor *e)
+ GtkSlideView *e)
{
- PangoContext *pc;
-
- pc = gdk_pango_context_get();
-
- if ( e->scale ) {
+ double sx, sy;
+ double aw, ah;
+ double log_w, log_h;
+ Stylesheet *ss;
- double sx, sy;
- double aw, ah;
+ ss = presentation_get_stylesheet(e->p);
+ if ( slide_get_logical_size(e->slide, ss, &log_w, &log_h) ) {
+ fprintf(stderr, "Failed to get logical size\n");
+ return FALSE;
+ }
- e->w = event->width;
- e->h = event->height;
- sx = (double)e->w / e->log_w;
- sy = (double)e->h / e->log_h;
- e->view_scale = (sx < sy) ? sx : sy;
+ e->w = event->width;
+ e->h = event->height;
+ sx = (double)e->w / log_w;
+ sy = (double)e->h / log_h;
+ e->view_scale = (sx < sy) ? sx : sy;
- /* Actual size (in device units) */
- aw = e->view_scale * e->log_w;
- ah = e->view_scale * e->log_h;
+ /* Actual size (in device units) */
+ aw = e->view_scale * log_w;
+ ah = e->view_scale * log_h;
- e->border_offs_x = (event->width - aw)/2.0;
- e->border_offs_y = (event->height - ah)/2.0;
-
- }
+ e->border_offs_x = (event->width - aw)/2.0;
+ e->border_offs_y = (event->height - ah)/2.0;
e->visible_height = event->height;
e->visible_width = event->width;
- /* Interpret and shape, if not already done */
- if ( e->top == NULL ) {
- double w, h;
- if ( e->flow ) {
- w = event->width;
- h = 0.0;
- } else {
- w = e->log_w;
- h = e->log_h;
- }
- e->top = interp_and_shape(e->scblocks, e->stylesheet, e->cbl,
- e->is, e->slidenum, pc,
- w, h, e->lang);
- e->top->scblocks = e->scblocks;
- recursive_wrap(e->top, pc);
- }
-
- if ( e->flow ) {
- /* Wrap using current width */
- e->top->w = event->width;
- e->top->h = 0.0; /* To be updated in a moment */
- e->top->x = 0.0;
- e->top->y = 0.0;
- /* Only the top level needs to be wrapped */
- wrap_frame(e->top, pc);
- }
-
- update_size(e);
-
- g_object_unref(pc);
+ //update_size(e);
return FALSE;
}
-static void emit_change_sig(SCEditor *e)
+static void emit_change_sig(GtkSlideView *e)
{
g_signal_emit_by_name(e, "changed");
}
-void sc_editor_set_flow(SCEditor *e, int flow)
-{
- e->flow = flow;
-}
-
-
-static void sc_editor_set_property(GObject *obj, guint id, const GValue *val,
- GParamSpec *spec)
-{
- SCEditor *e = SC_EDITOR(obj);
-
- switch ( id ) {
-
- case SCEDITOR_VPOL :
- e->vpol = g_value_get_enum(val);
- break;
-
- case SCEDITOR_HPOL :
- e->hpol = g_value_get_enum(val);
- break;
-
- case SCEDITOR_VADJ :
- e->vadj = g_value_get_object(val);
- set_vertical_params(e);
- if ( e->vadj != NULL ) {
- g_signal_connect(G_OBJECT(e->vadj), "value-changed",
- G_CALLBACK(vertical_adjust), e);
- }
- break;
-
- case SCEDITOR_HADJ :
- e->hadj = g_value_get_object(val);
- set_horizontal_params(e);
- if ( e->hadj != NULL ) {
- g_signal_connect(G_OBJECT(e->hadj), "value-changed",
- G_CALLBACK(horizontal_adjust), e);
- }
- break;
-
- default :
- printf("setting %i\n", id);
- break;
-
- }
-}
-
-
-static void sc_editor_get_property(GObject *obj, guint id, GValue *val,
- GParamSpec *spec)
-{
- SCEditor *e = SC_EDITOR(obj);
-
- switch ( id ) {
-
- case SCEDITOR_VADJ :
- g_value_set_object(val, e->vadj);
- break;
-
- case SCEDITOR_HADJ :
- g_value_set_object(val, e->hadj);
- break;
-
- case SCEDITOR_VPOL :
- g_value_set_enum(val, e->vpol);
- break;
-
- case SCEDITOR_HPOL :
- g_value_set_enum(val, e->hpol);
- break;
-
- default :
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, spec);
- break;
-
- }
-}
-
-
-static GtkSizeRequestMode get_request_mode(GtkWidget *widget)
-{
- return GTK_SIZE_REQUEST_CONSTANT_SIZE;
-}
-
-
-static void get_preferred_width(GtkWidget *widget, gint *min, gint *natural)
-{
- SCEditor *e = SC_EDITOR(widget);
- if ( e->flow ) {
- *min = 100;
- *natural = 640;
- } else {
- *min = e->w;
- *natural = e->w;
- }
-}
-
-
-static void get_preferred_height(GtkWidget *widget, gint *min, gint *natural)
+static void gtk_slide_view_class_init(GtkSlideViewClass *klass)
{
- SCEditor *e = SC_EDITOR(widget);
- if ( e->flow ) {
- *min = 1000;
- *natural = 1000;
- } else {
- *min = e->h;
- *natural = e->h;
- }
-}
-
-
-static void sc_editor_class_init(SCEditorClass *klass)
-{
- GObjectClass *goc = G_OBJECT_CLASS(klass);
- goc->set_property = sc_editor_set_property;
- goc->get_property = sc_editor_get_property;
- g_object_class_override_property(goc, SCEDITOR_VADJ, "vadjustment");
- g_object_class_override_property(goc, SCEDITOR_HADJ, "hadjustment");
- g_object_class_override_property(goc, SCEDITOR_VPOL, "vscroll-policy");
- g_object_class_override_property(goc, SCEDITOR_HPOL, "hscroll-policy");
-
- GTK_WIDGET_CLASS(klass)->get_request_mode = get_request_mode;
- GTK_WIDGET_CLASS(klass)->get_preferred_width = get_preferred_width;
- GTK_WIDGET_CLASS(klass)->get_preferred_height = get_preferred_height;
- GTK_WIDGET_CLASS(klass)->get_preferred_height_for_width = NULL;
-
- g_signal_new("changed", SC_TYPE_EDITOR, G_SIGNAL_RUN_LAST, 0,
+ g_signal_new("changed", GTK_TYPE_SLIDE_VIEW, G_SIGNAL_RUN_LAST, 0,
NULL, NULL, NULL, G_TYPE_NONE, 0);
}
-static void sc_editor_init(SCEditor *e)
+static void gtk_slide_view_init(GtkSlideView *e)
{
- e->vpol = GTK_SCROLL_NATURAL;
- e->hpol = GTK_SCROLL_NATURAL;
- e->vadj = gtk_adjustment_new(0, 0, 100, 1, 10, 10);
- e->hadj = gtk_adjustment_new(0, 0, 100, 1, 10, 10);
}
-void sc_editor_set_background(SCEditor *e, double r, double g, double b)
-{
- e->bgcol[0] = r;
- e->bgcol[1] = g;
- e->bgcol[2] = b;
-}
-
-
-void sc_editor_ensure_cursor(SCEditor *e)
-{
- if ( e->cursor_frame != NULL ) return;
- e->cursor_frame = e->top;
- e->cpos.para = 0;
- e->cpos.pos = 0;
- e->cpos.trail = 0;
- e->selection = NULL;
-}
-
-
-static void sc_editor_remove_cursor(SCEditor *e)
-{
- e->cursor_frame = NULL;
- e->cpos.para = 0;
- e->cpos.pos = 0;
- e->cpos.trail = 0;
- e->selection = NULL;
-}
-
-
-/* (Re-)run the entire rendering pipeline.
- * NB "full" means "full". All frame, line and box handles will become
- * invalid. The cursor position will be unset. */
-static void full_rerender(SCEditor *e)
-{
- PangoContext *pc;
-
- frame_free(e->top);
- sc_editor_remove_cursor(e);
-
- pc = gdk_pango_context_get();
-
- e->top = interp_and_shape(e->scblocks, e->stylesheet, e->cbl,
- e->is, e->slidenum,
- pc, e->log_w, 0.0, e->lang);
-
- e->top->x = 0.0;
- e->top->y = 0.0;
- e->top->w = e->w;
- e->top->h = 0.0; /* To be updated in a moment */
-
- recursive_wrap(e->top, pc);
- update_size(e);
-
- sc_editor_redraw(e);
-
- g_object_unref(pc);
-}
-
-
-void sc_editor_redraw(SCEditor *e)
+static void redraw(GtkSlideView *e)
{
gint w, h;
-
w = gtk_widget_get_allocated_width(GTK_WIDGET(e));
h = gtk_widget_get_allocated_height(GTK_WIDGET(e));
-
gtk_widget_queue_draw_area(GTK_WIDGET(e), 0, 0, w, h);
}
-static void paste_storycode_received(GtkClipboard *cb, GtkSelectionData *seldata,
- gpointer vp)
-{
- SCEditor *e = vp;
- SCBlock *nf;
- const guchar *t;
-
- t = gtk_selection_data_get_data(seldata);
-
- printf("received storycode paste\n");
- printf("'%s'\n", t);
- if ( t == NULL ) return;
-
- /* FIXME: It might not be a new frame */
- nf = sc_parse((char *)t);
- show_sc_blocks(nf);
- sc_block_append_block(sc_block_child(e->scblocks), nf);
- full_rerender(e);
-}
-
-
-static void paste_text_received(GtkClipboard *cb, GtkSelectionData *seldata,
- gpointer vp)
-{
- SCEditor *e = vp;
- SCBlock *bl;
- guchar *t;
- SCBlock *cur_bl;
- size_t cur_sc_pos;
- size_t offs;
- Paragraph *para;
-
- t = gtk_selection_data_get_text(seldata);
-
- printf("received text paste\n");
- printf("'%s'\n", t);
- if ( t == NULL ) return;
-
- bl = sc_parse((char *)t);
-
- if ( e->cursor_frame == NULL ) {
- fprintf(stderr, _("No frame selected for paste\n"));
- return;
- }
-
- para = e->cursor_frame->paras[e->cpos.para];
- offs = pos_trail_to_offset(para, e->cpos.pos, e->cpos.trail);
-
- get_sc_pos(e->cursor_frame, e->cpos.para, offs, &cur_bl, &cur_sc_pos);
- sc_insert_block(cur_bl, cur_sc_pos, bl);
- full_rerender(e);
-}
-
-
-static void paste_targets_received(GtkClipboard *cb, GdkAtom *targets,
- gint n_targets, gpointer vp)
-{
- SCEditor *e = vp;
- int i;
- int have_sc = 0;
- int index_sc, index_text;
- int have_text = 0;
-
- if ( targets == NULL ) {
- fprintf(stderr, "No paste targets offered.\n");
- return;
- }
-
- for ( i=0; i<n_targets; i++ ) {
- gchar *name = gdk_atom_name(targets[i]);
- if ( g_strcmp0(name, "text/x-storycode") == 0 ) {
- have_sc = 1;
- index_sc = i;
- }
- if ( g_strcmp0(name, "text/plain") == 0 ) {
- have_text = 1;
- index_text = i;
- }
- g_free(name);
- }
-
- if ( have_sc ) {
- printf("storycode is offered\n");
- gtk_clipboard_request_contents(cb, targets[index_sc],
- paste_storycode_received, e);
- } else if ( have_text ) {
- printf("text is offered\n");
- gtk_clipboard_request_contents(cb, targets[index_text],
- paste_text_received, e);
- } else {
- printf("nothing useful is offered\n");
- }
-}
-
-
-void sc_editor_paste(SCEditor *e)
-{
- GtkClipboard *cb;
- GdkAtom atom;
-
- printf("pasting\n");
-
- atom = gdk_atom_intern("CLIPBOARD", FALSE);
- if ( atom == GDK_NONE ) return;
- cb = gtk_clipboard_get(atom);
- gtk_clipboard_request_targets(cb, paste_targets_received, e);
-}
-
-
-void sc_editor_add_storycode(SCEditor *e, const char *sc)
-{
- SCBlock *nf;
- nf = sc_parse(sc);
- sc_block_append_block(sc_block_child(e->scblocks), nf);
- full_rerender(e);
-}
-
-
-static void clipboard_get(GtkClipboard *cb, GtkSelectionData *seldata,
- guint info, gpointer data)
-{
- char *t = data;
-
- printf("clipboard get\n");
-
- if ( info == 0 ) {
- printf("sending SC frame\n");
- gtk_selection_data_set(seldata,
- gtk_selection_data_get_target(seldata),
- 8, (const guchar *)t, strlen(t)+1);
- } else {
- GdkAtom target;
- gchar *name;
- target = gtk_selection_data_get_target(seldata);
- name = gdk_atom_name(target);
- fprintf(stderr, "Don't know what to send for %s\n", name);
- g_free(name);
- }
-}
-
-
-static void clipboard_clear(GtkClipboard *cb, gpointer data)
-{
- free(data);
-}
-
-
-void sc_editor_copy_selected_frame(SCEditor *e)
-{
- char *t;
- GtkClipboard *cb;
- GdkAtom atom;
- GtkTargetEntry targets[1];
-
- if ( e->selection == NULL ) return;
-
- atom = gdk_atom_intern("CLIPBOARD", FALSE);
- if ( atom == GDK_NONE ) return;
-
- cb = gtk_clipboard_get(atom);
-
- targets[0].target = "text/x-storycode";
- targets[0].flags = 0;
- targets[0].info = 0;
-
- /* FIXME: Offer image, PDF etc? */
-
- printf("copying frame\n");
-
- t = serialise_sc_block(e->selection->scblocks);
-
- gtk_clipboard_set_with_data(cb, targets, 1,
- clipboard_get, clipboard_clear, t);
-}
-
-
-static void copy_selection(SCEditor *e)
-{
- char *t;
- GtkClipboard *cb;
- GdkAtom atom;
- GtkTargetEntry targets[1];
- SCBlock *bl;
-
- if ( e->selection == NULL ) return;
-
- atom = gdk_atom_intern("CLIPBOARD", FALSE);
- if ( atom == GDK_NONE ) return;
-
- cb = gtk_clipboard_get(atom);
-
-
- targets[0].target = "text/x-storycode";
- targets[0].flags = 0;
- targets[0].info = 0;
-
- printf("copying selection\n");
-
- bl = block_at_cursor(e->cursor_frame, e->cpos.para, 0);
- if ( bl == NULL ) return;
-
- t = serialise_sc_block(bl);
-
- gtk_clipboard_set_with_data(cb, targets, 1,
- clipboard_get, clipboard_clear, t);
-}
-
-
-void sc_editor_delete_selected_frame(SCEditor *e)
-{
- SCBlock *scb_old = e->scblocks;
- sc_block_delete(&e->scblocks, e->selection->scblocks);
- assert(scb_old == e->scblocks);
- full_rerender(e);
- emit_change_sig(e);
-}
-
-
-static gint destroy_sig(GtkWidget *window, SCEditor *e)
+static gint destroy_sig(GtkWidget *window, GtkSlideView *e)
{
return 0;
}
-static void draw_editing_box(cairo_t *cr, struct frame *fr)
-{
- const double dash[] = {2.0, 2.0};
- double xmin, ymin, width, height;
- double ptot_w, ptot_h;
-
- xmin = fr->x;
- ymin = fr->y;
- width = fr->w;
- height = fr->h;
-
- cairo_new_path(cr);
- cairo_rectangle(cr, xmin, ymin, width, height);
- cairo_set_source_rgb(cr, 0.0, 0.69, 1.0);
- cairo_set_line_width(cr, 0.5);
- cairo_stroke(cr);
-
- cairo_new_path(cr);
- ptot_w = fr->pad_l + fr->pad_r;
- ptot_h = fr->pad_t + fr->pad_b;
- cairo_rectangle(cr, xmin+fr->pad_l, ymin+fr->pad_t,
- width-ptot_w, height-ptot_h);
- cairo_set_dash(cr, dash, 2, 0.0);
- cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
- cairo_set_line_width(cr, 0.1);
- cairo_stroke(cr);
-
- cairo_set_dash(cr, NULL, 0, 0.0);
-}
-
-
-static void draw_para_highlight(cairo_t *cr, struct frame *fr, int cursor_para)
-{
- double cx, cy, w, h;
-
- if ( get_para_highlight(fr, cursor_para, &cx, &cy, &w, &h) != 0 ) {
- return;
- }
-
- cairo_new_path(cr);
- cairo_rectangle(cr, cx+fr->x, cy+fr->y, w, h);
- cairo_set_source_rgba(cr, 0.7, 0.7, 1.0, 0.5);
- cairo_set_line_width(cr, 5.0);
- cairo_stroke(cr);
-}
-
-
-static void draw_caret(cairo_t *cr, struct frame *fr, struct edit_pos cpos,
- int hgh)
-{
- double cx, clow, chigh, h;
- const double t = 1.8;
- size_t offs;
- Paragraph *para;
-
- if ( hgh ) {
- draw_para_highlight(cr, fr, cpos.para);
- return;
- }
-
- assert(fr != NULL);
-
- para = fr->paras[cpos.para];
- if ( para_type(para) != PARA_TYPE_TEXT ) {
- draw_para_highlight(cr, fr, cpos.para);
- return;
- }
-
- offs = pos_trail_to_offset(para, cpos.pos, cpos.trail);
- get_cursor_pos(fr, cpos.para, offs, &cx, &clow, &h);
-
- cx += fr->x;
- clow += fr->y;
- chigh = clow + h;
-
- cairo_move_to(cr, cx, clow);
- cairo_line_to(cr, cx, chigh);
-
- cairo_move_to(cr, cx-t, clow-t);
- cairo_line_to(cr, cx, clow);
- cairo_move_to(cr, cx+t, clow-t);
- cairo_line_to(cr, cx, clow);
-
- cairo_move_to(cr, cx-t, chigh+t);
- cairo_line_to(cr, cx, chigh);
- cairo_move_to(cr, cx+t, chigh+t);
- cairo_line_to(cr, cx, chigh);
-
- cairo_set_source_rgb(cr, 0.86, 0.0, 0.0);
- cairo_set_line_width(cr, 1.0);
- cairo_stroke(cr);
-}
-
-
-static void draw_resize_handle(cairo_t *cr, double x, double y)
-{
- cairo_new_path(cr);
- cairo_rectangle(cr, x, y, 20.0, 20.0);
- cairo_set_source_rgba(cr, 0.9, 0.9, 0.9, 0.5);
- cairo_fill(cr);
-}
-
-
-static void draw_overlay(cairo_t *cr, SCEditor *e)
+static gboolean draw_sig(GtkWidget *da, cairo_t *cr, GtkSlideView *e)
{
- if ( e->selection != NULL ) {
-
- double x, y, w, h;
-
- draw_editing_box(cr, e->selection);
-
- x = e->selection->x;
- y = e->selection->y;
- w = e->selection->w;
- h = e->selection->h;
-
- if ( e->selection->resizable ) {
- /* Draw resize handles */
- draw_resize_handle(cr, x, y+h-20.0);
- draw_resize_handle(cr, x+w-20.0, y);
- draw_resize_handle(cr, x, y);
- draw_resize_handle(cr, x+w-20.0, y+h-20.0);
- }
-
- draw_caret(cr, e->cursor_frame, e->cpos, e->para_highlight);
-
- }
-
- if ( (e->drag_status == DRAG_STATUS_DRAGGING)
- && ((e->drag_reason == DRAG_REASON_CREATE)
- || (e->drag_reason == DRAG_REASON_IMPORT)) )
- {
- cairo_new_path(cr);
- cairo_rectangle(cr, e->start_corner_x, e->start_corner_y,
- e->drag_corner_x - e->start_corner_x,
- e->drag_corner_y - e->start_corner_y);
- cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
- cairo_set_line_width(cr, 0.5);
- cairo_stroke(cr);
- }
-
- if ( (e->drag_status == DRAG_STATUS_DRAGGING)
- && ((e->drag_reason == DRAG_REASON_RESIZE)
- || (e->drag_reason == DRAG_REASON_MOVE)) )
- {
- cairo_new_path(cr);
- cairo_rectangle(cr, e->box_x, e->box_y,
- e->box_width, e->box_height);
- cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
- cairo_set_line_width(cr, 0.5);
- cairo_stroke(cr);
- }
-}
-
+ PangoContext *pc;
-static gboolean draw_sig(GtkWidget *da, cairo_t *cr, SCEditor *e)
-{
/* Ultimate background */
if ( e->bg_pixbuf != NULL ) {
gdk_cairo_set_source_pixbuf(cr, e->bg_pixbuf, 0.0, 0.0);
@@ -828,1132 +133,25 @@ static gboolean draw_sig(GtkWidget *da, cairo_t *cr, SCEditor *e)
}
cairo_translate(cr, e->border_offs_x, e->border_offs_y);
- cairo_translate(cr, -e->h_scroll_pos, -e->scroll_pos);
+ cairo_translate(cr, -e->h_scroll_pos, -e->v_scroll_pos);
cairo_scale(cr, e->view_scale, e->view_scale);
- /* Rendering background */
- cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
- cairo_rectangle(cr, 0.0, 0.0, e->log_w, e->log_h);
- cairo_fill(cr);
-
/* Contents */
- recursive_draw(e->top, cr, e->is,
- e->scroll_pos/e->view_scale,
- (e->scroll_pos + e->visible_height)/e->view_scale);
+ pc = pango_cairo_create_context(cr);
+ slide_render_cairo(e->slide, cr, presentation_get_imagestore(e->p),
+ presentation_get_stylesheet(e->p),
+ presentation_get_slide_number(e->p, e->slide),
+ pango_language_get_default(), pc);
+ g_object_unref(pc);
/* Editing overlay */
- draw_overlay(cr, e);
-
- return FALSE;
-}
-
-
-SCBlock *split_paragraph_at_cursor(SCEditor *e)
-{
- size_t offs;
- Paragraph *para;
-
- if ( e->cursor_frame == NULL ) return NULL;
-
- para = e->cursor_frame->paras[e->cpos.para];
- offs = pos_trail_to_offset(para, e->cpos.pos, e->cpos.trail);
- return split_paragraph(e->cursor_frame, e->cpos.para, offs, e->pc);
-}
-
-
-static void check_cursor_visible(SCEditor *e)
-{
- double x, y, h;
- size_t offs;
- Paragraph *para;
-
- if ( e->cursor_frame == NULL ) return;
-
- para = e->cursor_frame->paras[e->cpos.para];
- offs = pos_trail_to_offset(para, e->cpos.pos, e->cpos.trail);
- get_cursor_pos(e->cursor_frame, e->cpos.para, offs, &x, &y, &h);
-
- /* Off the bottom? */
- if ( y - e->scroll_pos + h > e->visible_height ) {
- e->scroll_pos = y + h - e->visible_height;
- e->scroll_pos += e->cursor_frame->pad_b;
- }
-
- /* Off the top? */
- if ( y < e->scroll_pos ) {
- e->scroll_pos = y - e->cursor_frame->pad_t;
- }
-}
-
-
-static void do_backspace(struct frame *fr, SCEditor *e)
-{
- double wrapw = e->cursor_frame->w - e->cursor_frame->pad_l - e->cursor_frame->pad_r;
-
- if ( e->sel_active ) {
-
- /* Delete the selected block */
- delete_text_from_frame(e->cursor_frame, e->sel_start, e->sel_end, wrapw);
-
- /* Cursor goes at start of deletion */
- sort_positions(&e->sel_start, &e->sel_end);
- e->cpos = e->sel_start;
- e->sel_active = 0;
-
- } else {
-
- if ( para_type(e->cursor_frame->paras[e->cpos.para]) == PARA_TYPE_TEXT ) {
-
- /* Delete one character */
- struct edit_pos p1, p2;
-
- p1 = e->cpos;
-
- p2 = p1;
-
- cursor_moveh(e->cursor_frame, &p2, -1);
- show_edit_pos(p1);
- show_edit_pos(p2);
-
- delete_text_from_frame(e->cursor_frame, p1, p2, wrapw);
- e->cpos = p2;
-
- } else {
-
- /* FIXME: Implement this */
- fprintf(stderr, "Deleting non-text paragraph\n");
-
- }
-
- }
-
- emit_change_sig(e);
- sc_editor_redraw(e);
-}
-
-
-static void insert_text(char *t, SCEditor *e)
-{
- Paragraph *para;
-
- if ( e->cursor_frame == NULL ) return;
-
- if ( e->sel_active ) {
- do_backspace(e->cursor_frame, e);
- }
-
- if ( strcmp(t, "\n") == 0 ) {
- split_paragraph_at_cursor(e);
- if ( e->flow ) update_size(e);
- cursor_moveh(e->cursor_frame, &e->cpos, +1);
- check_cursor_visible(e);
- emit_change_sig(e);
- sc_editor_redraw(e);
- return;
- }
-
- para = e->cursor_frame->paras[e->cpos.para];
-
- /* Is this paragraph even a text one? */
- if ( para_type(para) == PARA_TYPE_TEXT ) {
-
- size_t off;
-
- /* Yes. The "easy" case */
-
- if ( !position_editable(e->cursor_frame, e->cpos) ) {
- fprintf(stderr, "Position not editable\n");
- return;
- }
-
- off = pos_trail_to_offset(para, e->cpos.pos, e->cpos.trail);
- insert_text_in_paragraph(para, off, t);
- wrap_paragraph(para, NULL,
- e->cursor_frame->w - e->cursor_frame->pad_l
- - e->cursor_frame->pad_r, 0, 0);
- if ( e->flow ) update_size(e);
-
- cursor_moveh(e->cursor_frame, &e->cpos, +1);
-
- } else {
-
- SCBlock *bd;
- SCBlock *ad;
- Paragraph *pnew;
-
- bd = para_scblock(para);
- if ( bd == NULL ) {
- fprintf(stderr, "No SCBlock for para\n");
- return;
- }
-
- /* No. Create a new text paragraph straight afterwards */
- ad = sc_block_insert_after(bd, NULL, NULL, strdup(t));
- if ( ad == NULL ) {
- fprintf(stderr, "Failed to add SCBlock\n");
- return;
- }
-
- pnew = insert_paragraph(e->cursor_frame, e->cpos.para);
- if ( pnew == NULL ) {
- fprintf(stderr, "Failed to insert paragraph\n");
- return;
- }
- add_run(pnew, ad, e->cursor_frame->fontdesc,
- e->cursor_frame->col, NULL);
-
- wrap_frame(e->cursor_frame, e->pc);
-
- e->cpos.para += 1;
- e->cpos.pos = 0;
- e->cpos.trail = 1;
-
- }
-
- emit_change_sig(e);
- check_cursor_visible(e);
- sc_editor_redraw(e);
-}
-
-
-static gboolean im_commit_sig(GtkIMContext *im, gchar *str,
- SCEditor *e)
-{
- insert_text(str, e);
- return FALSE;
-}
+ //draw_overlay(cr, e);
-
-static int within_frame(struct frame *fr, double x, double y)
-{
- if ( fr == NULL ) return 0;
- if ( x < fr->x ) return 0;
- if ( y < fr->y ) return 0;
- if ( x > fr->x + fr->w ) return 0;
- if ( y > fr->y + fr->h ) return 0;
- return 1;
-}
-
-
-static struct frame *find_frame_at_position(struct frame *fr,
- double x, double y)
-{
- int i;
-
- for ( i=0; i<fr->num_children; i++ ) {
-
- if ( within_frame(fr->children[i], x, y) ) {
- return find_frame_at_position(fr->children[i], x, y);
- }
-
- }
-
- if ( within_frame(fr, x, y) ) return fr;
- return NULL;
-}
-
-
-static enum corner which_corner(double xp, double yp, struct frame *fr)
-{
- double x, y; /* Relative to object position */
-
- x = xp - fr->x;
- y = yp - fr->y;
-
- if ( x < 0.0 ) return CORNER_NONE;
- if ( y < 0.0 ) return CORNER_NONE;
- if ( x > fr->w ) return CORNER_NONE;
- if ( y > fr->h ) return CORNER_NONE;
-
- /* Top left? */
- if ( (x<20.0) && (y<20.0) ) return CORNER_TL;
- if ( (x>fr->w-20.0) && (y<20.0) ) return CORNER_TR;
- if ( (x<20.0) && (y>fr->h-20.0) ) return CORNER_BL;
- if ( (x>fr->w-20.0) && (y>fr->h-20.0) ) return CORNER_BR;
-
- return CORNER_NONE;
-}
-
-
-static void calculate_box_size(struct frame *fr, SCEditor *e,
- double x, double y)
-{
- double ddx, ddy, dlen, mult;
- double vx, vy, dbx, dby;
-
- ddx = x - e->start_corner_x;
- ddy = y - e->start_corner_y;
-
- if ( !fr->is_image ) {
-
- switch ( e->drag_corner ) {
-
- case CORNER_BR :
- e->box_x = fr->x;
- e->box_y = fr->y;
- e->box_width = fr->w + ddx;
- e->box_height = fr->h + ddy;
- break;
-
- case CORNER_BL :
- e->box_x = fr->x + ddx;
- e->box_y = fr->y;
- e->box_width = fr->w - ddx;
- e->box_height = fr->h + ddy;
- break;
-
- case CORNER_TL :
- e->box_x = fr->x + ddx;
- e->box_y = fr->y + ddy;
- e->box_width = fr->w - ddx;
- e->box_height = fr->h - ddy;
- break;
-
- case CORNER_TR :
- e->box_x = fr->x;
- e->box_y = fr->y + ddy;
- e->box_width = fr->w + ddx;
- e->box_height = fr->h - ddy;
- break;
-
- case CORNER_NONE :
- break;
-
- }
- return;
-
-
- }
-
- switch ( e->drag_corner ) {
-
- case CORNER_BR :
- vx = fr->w;
- vy = fr->h;
- break;
-
- case CORNER_BL :
- vx = -fr->w;
- vy = fr->h;
- break;
-
- case CORNER_TL :
- vx = -fr->w;
- vy = -fr->h;
- break;
-
- case CORNER_TR :
- vx = fr->w;
- vy = -fr->h;
- break;
-
- case CORNER_NONE :
- default:
- vx = 0.0;
- vy = 0.0;
- break;
-
- }
-
- dlen = (ddx*vx + ddy*vy) / e->diagonal_length;
- mult = (dlen+e->diagonal_length) / e->diagonal_length;
-
- e->box_width = fr->w * mult;
- e->box_height = fr->h * mult;
- dbx = e->box_width - fr->w;
- dby = e->box_height - fr->h;
-
- if ( e->box_width < 40.0 ) {
- mult = 40.0 / fr->w;
- }
- if ( e->box_height < 40.0 ) {
- mult = 40.0 / fr->h;
- }
- e->box_width = fr->w * mult;
- e->box_height = fr->h * mult;
- dbx = e->box_width - fr->w;
- dby = e->box_height - fr->h;
-
- switch ( e->drag_corner ) {
-
- case CORNER_BR :
- e->box_x = fr->x;
- e->box_y = fr->y;
- break;
-
- case CORNER_BL :
- e->box_x = fr->x - dbx;
- e->box_y = fr->y;
- break;
-
- case CORNER_TL :
- e->box_x = fr->x - dbx;
- e->box_y = fr->y - dby;
- break;
-
- case CORNER_TR :
- e->box_x = fr->x;
- e->box_y = fr->y - dby;
- break;
-
- case CORNER_NONE :
- break;
-
- }
-}
-
-
-static void check_paragraph(struct frame *fr, PangoContext *pc,
- SCBlock *scblocks)
-{
- if ( fr->n_paras > 0 ) return;
- Paragraph *para = last_para(fr);
-
- if ( scblocks == NULL ) {
- /* We have no SCBlocks at all! Better create one... */
- scblocks = sc_parse("");
- fr->scblocks = scblocks;
- }
-
- /* We are creating the first paragraph. It uses the last SCBlock
- * in the chain */
- while ( sc_block_next(scblocks) != NULL ) {
- scblocks = sc_block_next(scblocks);
- }
- scblocks = sc_block_append(scblocks, NULL, NULL, strdup(""), NULL);
-
- add_run(para, scblocks, fr->fontdesc, fr->col, NULL);
- wrap_paragraph(para, pc, fr->w - fr->pad_l - fr->pad_r, 0, 0);
-}
-
-
-static void rewrap_paragraph_range(struct frame *fr, int a, int b,
- struct edit_pos sel_start,
- struct edit_pos sel_end,
- int sel_active)
-{
- int i;
- int sel_s, sel_e;
- Paragraph *para;
-
- if ( a > b ) {
- int t = a;
- a = b; b = t;
- }
-
- if ( fr == NULL ) return;
- if ( fr->paras == NULL ) return;
-
- sort_positions(&sel_start, &sel_end);
-
- //printf("frame %p\n", fr);
- //printf("start: ");
- //show_edit_pos(sel_start);
- //printf(" end: ");
- //show_edit_pos(sel_end);
-
- para = fr->paras[sel_start.para];
- sel_s = pos_trail_to_offset(para, sel_start.pos, sel_start.trail);
- para = fr->paras[sel_end.para];
- sel_e = pos_trail_to_offset(para, sel_end.pos, sel_end.trail);
-
- for ( i=a; i<=b; i++ ) {
- size_t srt, end;
- if ( sel_active ) {
- if ( i == sel_start.para ) {
- srt = sel_s;
- } else {
- srt = 0;
- }
- if ( i == sel_end.para ) {
- end = sel_e;
- } else {
- end = G_MAXUINT;
- }
- if ( i > sel_start.para && i < sel_end.para ) {
- end = G_MAXUINT;
- }
- } else {
- srt = 0;
- end = 0;
- }
- wrap_paragraph(fr->paras[i], NULL,
- fr->w - fr->pad_l - fr->pad_r, srt, end);
- }
-}
-
-
-static void unset_selection(SCEditor *e)
-{
- int a, b;
-
- if ( !e->sel_active ) return;
-
- a = e->sel_start.para;
- b = e->sel_end.para;
- if ( a > b ) {
- a = e->sel_end.para;
- b = e->sel_start.para;
- }
- e->sel_active = 0;
- rewrap_paragraph_range(e->cursor_frame, a, b, e->sel_start, e->sel_end, 0);
-}
-
-
-static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event,
- SCEditor *e)
-{
- enum corner c;
- gdouble x, y;
- struct frame *clicked;
- int shift;
-
- x = event->x - e->border_offs_x;
- y = event->y - e->border_offs_y + e->scroll_pos;
- x /= e->view_scale;
- y /= e->view_scale;
- shift = event->state & GDK_SHIFT_MASK;
-
- if ( within_frame(e->selection, x, y) ) {
- clicked = e->selection;
- } else {
- clicked = find_frame_at_position(e->top, x, y);
- }
-
- /* Clicked within the currently selected frame
- * -> resize, move or select text */
- if ( (e->selection != NULL) && (clicked == e->selection) ) {
-
- struct frame *fr;
-
- fr = e->selection;
-
- /* Within the resizing region? */
- c = which_corner(x, y, fr);
- if ( (c != CORNER_NONE) && fr->resizable && shift ) {
-
- e->drag_reason = DRAG_REASON_RESIZE;
- e->drag_corner = c;
-
- e->start_corner_x = x;
- e->start_corner_y = y;
- e->diagonal_length = pow(fr->w, 2.0);
- e->diagonal_length += pow(fr->h, 2.0);
- e->diagonal_length = sqrt(e->diagonal_length);
-
- calculate_box_size(fr, e, x, y);
-
- e->drag_status = DRAG_STATUS_COULD_DRAG;
- e->drag_reason = DRAG_REASON_RESIZE;
-
- } else {
-
- /* Position cursor and prepare for possible drag */
- e->cursor_frame = clicked;
- check_paragraph(e->cursor_frame, e->pc, sc_block_child(fr->scblocks));
- find_cursor(clicked, x-fr->x, y-fr->y, &e->cpos);
- ensure_run(e->cursor_frame, e->cpos);
-
- e->start_corner_x = x;
- e->start_corner_y = y;
-
- if ( event->type == GDK_2BUTTON_PRESS ) {
- check_callback_click(e->cursor_frame, e->cpos.para);
- }
-
- if ( fr->resizable && shift ) {
- e->drag_status = DRAG_STATUS_COULD_DRAG;
- e->drag_reason = DRAG_REASON_MOVE;
- } else if ( !e->para_highlight ) {
- e->drag_status = DRAG_STATUS_COULD_DRAG;
- e->drag_reason = DRAG_REASON_TEXTSEL;
- unset_selection(e);
- find_cursor(clicked, x-fr->x, y-fr->y, &e->sel_start);
- }
-
- }
-
- } else if ( (clicked == NULL)
- || ( !e->top_editable && (clicked == e->top) ) )
- {
- /* Clicked no object. Deselect old object.
- * If shift held, set up for creating a new one. */
- e->selection = NULL;
- unset_selection(e);
-
- if ( shift ) {
- e->start_corner_x = x;
- e->start_corner_y = y;
- e->drag_status = DRAG_STATUS_COULD_DRAG;
- e->drag_reason = DRAG_REASON_CREATE;
- } else {
- e->drag_status = DRAG_STATUS_NONE;
- e->drag_reason = DRAG_REASON_NONE;
- }
-
- } else {
-
- /* Clicked an existing frame, no immediate dragging */
- e->drag_status = DRAG_STATUS_COULD_DRAG;
- e->drag_reason = DRAG_REASON_TEXTSEL;
- unset_selection(e);
- find_cursor(clicked, x-clicked->x, y-clicked->y,
- &e->sel_start);
- find_cursor(clicked, x-clicked->x, y-clicked->y,
- &e->sel_end);
- e->selection = clicked;
- e->cursor_frame = clicked;
- if ( clicked == e->top ) {
- check_paragraph(e->cursor_frame, e->pc, clicked->scblocks);
- } else {
- check_paragraph(e->cursor_frame, e->pc,
- sc_block_child(clicked->scblocks));
- }
- find_cursor(clicked, x-clicked->x, y-clicked->y, &e->cpos);
- ensure_run(e->cursor_frame, e->cpos);
-
- }
-
- gtk_widget_grab_focus(GTK_WIDGET(da));
- sc_editor_redraw(e);
return FALSE;
}
-static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event,
- SCEditor *e)
-{
- struct frame *fr = e->selection;
- gdouble x, y;
-
- x = event->x - e->border_offs_x;
- y = event->y - e->border_offs_y + e->scroll_pos;
- x /= e->view_scale;
- y /= e->view_scale;
-
- if ( e->drag_status == DRAG_STATUS_COULD_DRAG ) {
-
- /* We just got a motion signal, and the status was "could drag",
- * therefore the drag has started. */
- e->drag_status = DRAG_STATUS_DRAGGING;
-
- }
-
- switch ( e->drag_reason ) {
-
- case DRAG_REASON_NONE :
- break;
-
- case DRAG_REASON_CREATE :
- e->drag_corner_x = x;
- e->drag_corner_y = y;
- sc_editor_redraw(e);
- break;
-
- case DRAG_REASON_IMPORT :
- /* Do nothing, handled by dnd_motion() */
- break;
-
- case DRAG_REASON_RESIZE :
- calculate_box_size(fr, e, x, y);
- sc_editor_redraw(e);
- break;
-
- case DRAG_REASON_MOVE :
- e->box_x = (fr->x - e->start_corner_x) + x;
- e->box_y = (fr->y - e->start_corner_y) + y;
- e->box_width = fr->w;
- e->box_height = fr->h;
- sc_editor_redraw(e);
- break;
-
- case DRAG_REASON_TEXTSEL :
- unset_selection(e);
- find_cursor(fr, x-fr->x, y-fr->y, &e->sel_end);
- rewrap_paragraph_range(fr, e->sel_start.para, e->sel_end.para,
- e->sel_start, e->sel_end, 1);
- find_cursor(fr, x-fr->x, y-fr->y, &e->cpos);
- e->sel_active = !positions_equal(e->sel_start, e->sel_end);
- sc_editor_redraw(e);
- break;
-
- }
-
- gdk_event_request_motions(event);
- return FALSE;
-}
-
-
-static struct frame *create_frame(SCEditor *e, double x, double y,
- double w, double h)
-{
- struct frame *parent;
- struct frame *fr;
- SCBlock *scblocks;
-
- parent = e->top;
-
- if ( w < 0.0 ) {
- x += w;
- w = -w;
- }
-
- if ( h < 0.0 ) {
- y += h;
- h = -h;
- }
-
- /* Add to frame structure */
- fr = add_subframe(parent);
-
- /* Add to SC */
- scblocks = sc_block_append_end(sc_block_child(e->scblocks), "f", NULL, NULL);
- fr->scblocks = scblocks;
- sc_block_append_inside(scblocks, NULL, NULL, strdup(""));
-
- fr->x = x;
- fr->y = y;
- fr->w = w;
- fr->h = h;
- fr->is_image = 0;
- fr->empty = 1;
- fr->resizable = 1;
-
- update_geom(fr);
-
- full_rerender(e);
- return find_frame_with_scblocks(e->top, scblocks);
-}
-
-
-static void do_resize(SCEditor *e, double x, double y, double w, double h)
-{
- struct frame *fr;
-
- assert(e->selection != NULL);
-
- if ( w < 0.0 ) {
- w = -w;
- x -= w;
- }
-
- if ( h < 0.0 ) {
- h = -h;
- y -= h;
- }
-
- fr = e->selection;
- fr->x = x;
- fr->y = y;
- fr->w = w;
- fr->h = h;
- update_geom(fr);
-
- full_rerender(e);
- sc_editor_redraw(e);
-}
-
-
-static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event,
- SCEditor *e)
-{
- gdouble x, y;
- struct frame *fr;
-
- x = event->x - e->border_offs_x;
- y = event->y - e->border_offs_y;
- x /= e->view_scale;
- y /= e->view_scale;
-
- /* Not dragging? Then I don't care. */
- if ( e->drag_status != DRAG_STATUS_DRAGGING ) return FALSE;
-
- e->drag_corner_x = x;
- e->drag_corner_y = y;
- e->drag_status = DRAG_STATUS_NONE;
-
- switch ( e->drag_reason )
- {
-
- case DRAG_REASON_NONE :
- printf("Release on pointless drag.\n");
- break;
-
- case DRAG_REASON_CREATE :
- fr = create_frame(e, e->start_corner_x, e->start_corner_y,
- e->drag_corner_x - e->start_corner_x,
- e->drag_corner_y - e->start_corner_y);
- if ( fr != NULL ) {
- check_paragraph(fr, e->pc, sc_block_child(fr->scblocks));
- e->selection = fr;
- e->cursor_frame = fr;
- e->cpos.para = 0;
- e->cpos.pos = 0;
- e->cpos.trail = 0;
- } else {
- fprintf(stderr, _("Failed to create frame!\n"));
- }
- break;
-
- case DRAG_REASON_IMPORT :
- /* Do nothing, handled in dnd_drop() or dnd_leave() */
- break;
-
- case DRAG_REASON_RESIZE :
- do_resize(e, e->box_x, e->box_y, e->box_width, e->box_height);
- break;
-
- case DRAG_REASON_MOVE :
- do_resize(e, e->box_x, e->box_y, e->box_width, e->box_height);
- break;
-
- case DRAG_REASON_TEXTSEL :
- /* Do nothing (text is already selected) */
- break;
-
- }
-
- e->drag_reason = DRAG_REASON_NONE;
-
- gtk_widget_grab_focus(GTK_WIDGET(da));
- sc_editor_redraw(e);
- return FALSE;
-}
-
-
-static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event,
- SCEditor *e)
-{
- gboolean r;
- int claim = 0;
-
- /* Throw the event to the IM context and let it sort things out */
- r = gtk_im_context_filter_keypress(GTK_IM_CONTEXT(e->im_context),
- event);
- if ( r ) return FALSE; /* IM ate it */
-
- switch ( event->keyval ) {
-
- case GDK_KEY_Escape :
- if ( !e->para_highlight ) {
- sc_editor_remove_cursor(e);
- sc_editor_redraw(e);
- claim = 1;
- }
- break;
-
- case GDK_KEY_Left :
- if ( e->selection != NULL ) {
- cursor_moveh(e->cursor_frame, &e->cpos, -1);
- sc_editor_redraw(e);
- }
- claim = 1;
- break;
-
- case GDK_KEY_Right :
- if ( e->selection != NULL ) {
- cursor_moveh(e->cursor_frame, &e->cpos, +1);
- sc_editor_redraw(e);
- }
- claim = 1;
- break;
-
- case GDK_KEY_Up :
- if ( e->selection != NULL ) {
- cursor_moveh(e->cursor_frame, &e->cpos, -1);
- sc_editor_redraw(e);
- }
- claim = 1;
- break;
-
- case GDK_KEY_Down :
- if ( e->selection != NULL ) {
- cursor_moveh(e->cursor_frame, &e->cpos, +1);
- sc_editor_redraw(e);
- }
- claim = 1;
- break;
-
-
- case GDK_KEY_Return :
- im_commit_sig(NULL, "\n", e);
- claim = 1;
- break;
-
- case GDK_KEY_BackSpace :
- if ( e->selection != NULL ) {
- do_backspace(e->selection, e);
- claim = 1;
- }
- break;
-
- case GDK_KEY_F5 :
- full_rerender(e);
- break;
-
- case GDK_KEY_F6 :
- show_edit_pos(e->cpos);
- break;
-
- case GDK_KEY_F7 :
- if ( e->cursor_frame != NULL ) {
- if ( event->state & GDK_CONTROL_MASK ) {
- debug_paragraphs(e);
- } else if ( event->state & GDK_SHIFT_MASK ) {
- printf("Cursor frame block = %p\n", e->cursor_frame->scblocks);
- printf("Editor top block = %p\n", e->scblocks);
- show_sc_block(e->cursor_frame->scblocks, "");
- } else {
- open_debugger(e->cursor_frame);
- }
- } else {
- if ( event->state & GDK_SHIFT_MASK ) {
- printf("Debugging the top frame:\n");
- printf("Editor top block = %p\n", e->scblocks);
- show_sc_block(e->top->scblocks, "");
- }
- }
- break;
-
- case GDK_KEY_C :
- case GDK_KEY_c :
- if ( event->state == GDK_CONTROL_MASK ) {
- copy_selection(e);
- }
- break;
-
- case GDK_KEY_V :
- case GDK_KEY_v :
- if ( event->state == GDK_CONTROL_MASK ) {
- sc_editor_paste(e);
- }
- break;
-
-
- }
-
- if ( claim ) return TRUE;
- return FALSE;
-}
-
-
-static gboolean dnd_motion(GtkWidget *widget, GdkDragContext *drag_context,
- gint x, gint y, guint time, SCEditor *e)
-{
- GdkAtom target;
-
- /* If we haven't already requested the data, do so now */
- if ( !e->drag_preview_pending && !e->have_drag_data ) {
-
- target = gtk_drag_dest_find_target(widget, drag_context, NULL);
-
- if ( target != GDK_NONE ) {
- gtk_drag_get_data(widget, drag_context, target, time);
- e->drag_preview_pending = 1;
- } else {
- e->import_acceptable = 0;
- gdk_drag_status(drag_context, 0, time);
- }
-
- }
-
- if ( e->have_drag_data && e->import_acceptable ) {
-
- gdk_drag_status(drag_context, GDK_ACTION_LINK, time);
- e->start_corner_x = x - e->import_width/2.0;
- e->start_corner_y = y - e->import_height/2.0;
- e->drag_corner_x = x + e->import_width/2.0;
- e->drag_corner_y = y + e->import_height/2.0;
-
- sc_editor_redraw(e);
-
- }
-
- return TRUE;
-}
-
-
-static gboolean dnd_drop(GtkWidget *widget, GdkDragContext *drag_context,
- gint x, gint y, guint time, SCEditor *e)
-{
- GdkAtom target;
-
- target = gtk_drag_dest_find_target(widget, drag_context, NULL);
-
- if ( target == GDK_NONE ) {
- gtk_drag_finish(drag_context, FALSE, FALSE, time);
- } else {
- gtk_drag_get_data(widget, drag_context, target, time);
- }
-
- return TRUE;
-}
-
-
-/* Scale the image down if it's a silly size */
-static void check_import_size(SCEditor *e)
-{
- if ( e->import_width > e->w ) {
-
- int new_import_width;
-
- new_import_width = e->w/2;
- e->import_height = (new_import_width * e->import_height) /
- e->import_width;
- e->import_width = new_import_width;
-
- }
-
- if ( e->import_height > e->h ) {
-
- int new_import_height;
-
- new_import_height = e->w/2;
- e->import_width = (new_import_height*e->import_width) /
- e->import_height;
- e->import_height = new_import_height;
-
- }
-}
-
-
-static void dnd_receive(GtkWidget *widget, GdkDragContext *drag_context,
- gint x, gint y, GtkSelectionData *seldata,
- guint info, guint time, SCEditor *e)
-{
- if ( e->drag_preview_pending ) {
-
- gchar *filename = NULL;
- GdkPixbufFormat *f;
- gchar **uris;
- int w, h;
-
- e->have_drag_data = 1;
- e->drag_preview_pending = 0;
- uris = gtk_selection_data_get_uris(seldata);
- if ( uris != NULL ) {
- filename = g_filename_from_uri(uris[0], NULL, NULL);
- }
- g_strfreev(uris);
-
- if ( filename == NULL ) {
-
- /* This doesn't even look like a sensible URI.
- * Bail out. */
- gdk_drag_status(drag_context, 0, time);
- if ( e->drag_highlight ) {
- gtk_drag_unhighlight(widget);
- e->drag_highlight = 0;
- }
- e->import_acceptable = 0;
- return;
-
- }
- chomp(filename);
-
- f = gdk_pixbuf_get_file_info(filename, &w, &h);
- g_free(filename);
-
- e->import_width = w;
- e->import_height = h;
-
- if ( f == NULL ) {
-
- gdk_drag_status(drag_context, 0, time);
- if ( e->drag_highlight ) {
- gtk_drag_unhighlight(widget);
- e->drag_highlight = 0;
- }
- e->drag_status = DRAG_STATUS_NONE;
- e->drag_reason = DRAG_REASON_NONE;
- e->import_acceptable = 0;
-
- } else {
-
- /* Looks like a sensible image */
- gdk_drag_status(drag_context, GDK_ACTION_PRIVATE, time);
- e->import_acceptable = 1;
-
- if ( !e->drag_highlight ) {
- gtk_drag_highlight(widget);
- e->drag_highlight = 1;
- }
-
- check_import_size(e);
- e->drag_reason = DRAG_REASON_IMPORT;
- e->drag_status = DRAG_STATUS_DRAGGING;
-
- }
-
- } else {
-
- gchar **uris;
- char *filename = NULL;
-
- uris = gtk_selection_data_get_uris(seldata);
- if ( uris != NULL ) {
- filename = g_filename_from_uri(uris[0], NULL, NULL);
- }
- g_strfreev(uris);
-
- if ( filename != NULL ) {
-
- struct frame *fr;
- char *opts;
- size_t len;
- int w, h;
-
- gtk_drag_finish(drag_context, TRUE, FALSE, time);
- chomp(filename);
-
- w = e->drag_corner_x - e->start_corner_x;
- h = e->drag_corner_y - e->start_corner_y;
-
- len = strlen(filename)+64;
- opts = malloc(len);
- if ( opts == NULL ) {
- free(filename);
- fprintf(stderr, "Failed to allocate SC\n");
- return;
- }
- snprintf(opts, len, "1fx1f+0+0,filename=\"%s\"",
- filename);
-
- fr = create_frame(e, e->start_corner_x,
- e->start_corner_y, w, h);
- fr->is_image = 1;
- fr->empty = 0;
- sc_block_set_name(sc_block_child(fr->scblocks), strdup("image"));
- sc_block_set_options(sc_block_child(fr->scblocks), opts);
- full_rerender(e);
- sc_editor_remove_cursor(e);
- sc_editor_redraw(e);
- free(filename);
-
- } else {
-
- gtk_drag_finish(drag_context, FALSE, FALSE, time);
-
- }
-
- }
-}
-
-
-static void dnd_leave(GtkWidget *widget, GdkDragContext *drag_context,
- guint time, SCEditor *sceditor)
-{
- if ( sceditor->drag_highlight ) {
- gtk_drag_unhighlight(widget);
- }
- sceditor->have_drag_data = 0;
- sceditor->drag_highlight = 0;
- sceditor->drag_status = DRAG_STATUS_NONE;
- sceditor->drag_reason = DRAG_REASON_NONE;
-}
-
-
-static gint realise_sig(GtkWidget *da, SCEditor *e)
+static gint realise_sig(GtkWidget *da, GtkSlideView *e)
{
GdkWindow *win;
@@ -1962,236 +160,104 @@ static gint realise_sig(GtkWidget *da, SCEditor *e)
win = gtk_widget_get_window(GTK_WIDGET(e));
gtk_im_context_set_client_window(GTK_IM_CONTEXT(e->im_context), win);
gdk_window_set_accept_focus(win, TRUE);
- g_signal_connect(G_OBJECT(e->im_context), "commit", G_CALLBACK(im_commit_sig), e);
- g_signal_connect(G_OBJECT(e), "key-press-event", G_CALLBACK(key_press_sig), e);
-
- /* FIXME: Can do this "properly" by setting up a separate font map */
- e->pc = gtk_widget_get_pango_context(GTK_WIDGET(e));
+ //g_signal_connect(G_OBJECT(e->im_context), "commit", G_CALLBACK(im_commit_sig), e);
+ //g_signal_connect(G_OBJECT(e), "key-press-event", G_CALLBACK(key_press_sig), e);
return FALSE;
}
-void sc_editor_set_scblock(SCEditor *e, SCBlock *scblocks)
-{
- e->scblocks = scblocks;
- full_rerender(e);
-}
-
-
-static void update_size_request(SCEditor *e)
+static void update_size_request(GtkSlideView *e)
{
gtk_widget_set_size_request(GTK_WIDGET(e), 0, e->h + 2.0*e->min_border);
}
-void sc_editor_set_logical_size(SCEditor *e, double w, double h)
-{
- e->log_w = w;
- e->log_h = h;
- if ( gtk_widget_get_mapped(GTK_WIDGET(e)) ) {
- full_rerender(e);
- sc_editor_redraw(e);
- }
-}
-
-
-void sc_editor_set_slidenum(SCEditor *e, int slidenum)
-{
- e->slidenum = slidenum;
-}
-
-
-void sc_editor_set_min_border(SCEditor *e, double min_border)
-{
- e->min_border = min_border;
- update_size_request(e);
-}
-
-
-void sc_editor_set_top_frame_editable(SCEditor *e, int top_frame_editable)
-{
- e->top_editable = top_frame_editable;
-}
-
-
-void sc_editor_set_stylesheet(SCEditor *e, Stylesheet *stylesheet)
-{
- e->stylesheet = stylesheet;
-}
-
-
-void sc_editor_set_callbacks(SCEditor *e, SCCallbackList *cbl)
-{
- if ( e->cbl != NULL ) sc_callback_list_free(e->cbl);
- e->cbl = cbl;
-}
-
-
-void sc_editor_set_para_highlight(SCEditor *e, int para_highlight)
-{
- e->para_highlight = para_highlight;
- sc_editor_redraw(e);
-}
-
-int sc_editor_get_cursor_para(SCEditor *e)
-{
- if ( e->cursor_frame == NULL ) return 0;
- return e->cpos.para;
-}
-
-
-void *sc_editor_get_cursor_bvp(SCEditor *e)
-{
- Paragraph *para;
- if ( e->cursor_frame == NULL ) return 0;
- para = e->cursor_frame->paras[e->cpos.para];
- return get_para_bvp(para);
-}
-
-
-void sc_editor_set_cursor_para(SCEditor *e, signed int pos)
+void gtk_slide_view_set_scale(GtkSlideView *e, double scale)
{
- double h;
- int i;
-
- if ( e->cursor_frame == NULL ) {
- e->cursor_frame = e->top;
- e->selection = e->top;
- }
-
- if ( pos < 0 ) {
- e->cpos.para = e->cursor_frame->n_paras - 1;
- } else if ( pos >= e->cursor_frame->n_paras ) {
- e->cpos.para = e->cursor_frame->n_paras - 1;
- } else {
- e->cpos.para = pos;
- }
- e->cpos.pos = 0;
- e->cpos.trail = 0;
-
- h = 0;
- for ( i=0; i<e->cpos.para; i++ ) {
- h += paragraph_height(e->cursor_frame->paras[i]);
- }
- h += (paragraph_height(e->cursor_frame->paras[e->cpos.para]))/2;
- e->scroll_pos = h - (e->visible_height/2);
- set_vertical_params(e);
-
- sc_editor_redraw(e);
+ e->view_scale = 1.0;
}
-int sc_editor_get_num_paras(SCEditor *e)
+void gtk_slide_view_set_slide(GtkWidget *e, Slide *slide)
{
- if ( e->cursor_frame == NULL ) return 1;
- return e->cursor_frame->n_paras;
+ GTK_SLIDE_VIEW(e)->slide = slide;
+ redraw(GTK_SLIDE_VIEW(e));
}
-void sc_editor_set_scale(SCEditor *e, int scale)
+GtkWidget *gtk_slide_view_new(Presentation *p, Slide *slide)
{
- e->scale = scale;
- if ( !scale ) {
- e->view_scale = 1.0;
- }
-}
-
-
-void sc_editor_set_imagestore(SCEditor *e, ImageStore *is)
-{
- if ( e->is != NULL ) {
- fprintf(stderr, "WARNING: Changing imagestore\n");
- }
- e->is = is;
-}
-
-
-SCEditor *sc_editor_new(SCBlock *scblocks, Stylesheet *stylesheet,
- PangoLanguage *lang, const char *storename)
-{
- SCEditor *sceditor;
+ GtkSlideView *sv;
GtkTargetEntry targets[1];
GError *err;
- sceditor = g_object_new(SC_TYPE_EDITOR, NULL);
-
- sceditor->scblocks = scblocks;
- sceditor->w = 100;
- sceditor->h = 100;
- sceditor->log_w = 100;
- sceditor->log_h = 100;
- sceditor->border_offs_x = 0;
- sceditor->border_offs_y = 0;
- sceditor->is = NULL;
- sceditor->slidenum = 0;
- sceditor->min_border = 0.0;
- sceditor->top_editable = 0;
- sceditor->cbl = NULL;
- sceditor->scroll_pos = 0;
- sceditor->flow = 0;
- sceditor->scale = 0;
- sceditor->view_scale = 1.0;
- sceditor->lang = lang;
+ sv = g_object_new(GTK_TYPE_SLIDE_VIEW, NULL);
- sceditor->para_highlight = 0;
- sc_editor_remove_cursor(sceditor);
-
- sceditor->stylesheet = stylesheet;
+ sv->p = p;
+ sv->slide = slide;
+ sv->w = 100;
+ sv->h = 100;
+ sv->border_offs_x = 0;
+ sv->border_offs_y = 0;
+ sv->min_border = 0.0;
+ sv->h_scroll_pos = 0;
+ sv->v_scroll_pos = 0;
+ sv->view_scale = 1.0;
err = NULL;
- sceditor->bg_pixbuf = gdk_pixbuf_new_from_resource("/uk/me/bitwiz/Colloquium/sky.png",
+ sv->bg_pixbuf = gdk_pixbuf_new_from_resource("/uk/me/bitwiz/Colloquium/sky.png",
&err);
- if ( sceditor->bg_pixbuf == NULL ) {
+ if ( sv->bg_pixbuf == NULL ) {
fprintf(stderr, _("Failed to load background: %s\n"),
err->message);
}
- gtk_widget_set_size_request(GTK_WIDGET(sceditor),
- sceditor->w, sceditor->h);
+ gtk_widget_set_size_request(GTK_WIDGET(sv),
+ sv->w, sv->h);
- g_signal_connect(G_OBJECT(sceditor), "destroy",
- G_CALLBACK(destroy_sig), sceditor);
- g_signal_connect(G_OBJECT(sceditor), "realize",
- G_CALLBACK(realise_sig), sceditor);
- g_signal_connect(G_OBJECT(sceditor), "button-press-event",
- G_CALLBACK(button_press_sig), sceditor);
- g_signal_connect(G_OBJECT(sceditor), "button-release-event",
- G_CALLBACK(button_release_sig), sceditor);
- g_signal_connect(G_OBJECT(sceditor), "motion-notify-event",
- G_CALLBACK(motion_sig), sceditor);
- g_signal_connect(G_OBJECT(sceditor), "configure-event",
- G_CALLBACK(resize_sig), sceditor);
+ g_signal_connect(G_OBJECT(sv), "destroy",
+ G_CALLBACK(destroy_sig), sv);
+ g_signal_connect(G_OBJECT(sv), "realize",
+ G_CALLBACK(realise_sig), sv);
+ //g_signal_connect(G_OBJECT(sv), "button-press-event",
+ // G_CALLBACK(button_press_sig), sv);
+ //g_signal_connect(G_OBJECT(sv), "button-release-event",
+ // G_CALLBACK(button_release_sig), sv);
+ //g_signal_connect(G_OBJECT(sv), "motion-notify-event",
+ // G_CALLBACK(motion_sig), sv);
+ g_signal_connect(G_OBJECT(sv), "configure-event",
+ G_CALLBACK(resize_sig), sv);
/* Drag and drop */
- targets[0].target = "text/uri-list";
- targets[0].flags = 0;
- targets[0].info = 1;
- gtk_drag_dest_set(GTK_WIDGET(sceditor), 0, targets, 1,
- GDK_ACTION_PRIVATE);
- g_signal_connect(sceditor, "drag-data-received",
- G_CALLBACK(dnd_receive), sceditor);
- g_signal_connect(sceditor, "drag-motion",
- G_CALLBACK(dnd_motion), sceditor);
- g_signal_connect(sceditor, "drag-drop",
- G_CALLBACK(dnd_drop), sceditor);
- g_signal_connect(sceditor, "drag-leave",
- G_CALLBACK(dnd_leave), sceditor);
-
- gtk_widget_set_can_focus(GTK_WIDGET(sceditor), TRUE);
- gtk_widget_add_events(GTK_WIDGET(sceditor),
+ //targets[0].target = "text/uri-list";
+ //targets[0].flags = 0;
+ //targets[0].info = 1;
+ //gtk_drag_dest_set(GTK_WIDGET(sv), 0, targets, 1,
+ // GDK_ACTION_PRIVATE);
+ //g_signal_connect(sv, "drag-data-received",
+ // G_CALLBACK(dnd_receive), sv);
+ //g_signal_connect(sv, "drag-motion",
+ // G_CALLBACK(dnd_motion), sv);
+ //g_signal_connect(sv, "drag-drop",
+ // G_CALLBACK(dnd_drop), sv);
+ //g_signal_connect(sv, "drag-leave",
+ // G_CALLBACK(dnd_leave), sv);
+
+ gtk_widget_set_can_focus(GTK_WIDGET(sv), TRUE);
+ gtk_widget_add_events(GTK_WIDGET(sv),
GDK_POINTER_MOTION_HINT_MASK
| GDK_BUTTON1_MOTION_MASK
| GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
| GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK
| GDK_SCROLL_MASK);
- g_signal_connect(G_OBJECT(sceditor), "draw",
- G_CALLBACK(draw_sig), sceditor);
+ g_signal_connect(G_OBJECT(sv), "draw",
+ G_CALLBACK(draw_sig), sv);
- gtk_widget_grab_focus(GTK_WIDGET(sceditor));
+ gtk_widget_grab_focus(GTK_WIDGET(sv));
- gtk_widget_show(GTK_WIDGET(sceditor));
+ gtk_widget_show(GTK_WIDGET(sv));
- return sceditor;
+ return GTK_WIDGET(sv);
}
diff --git a/libstorycode/gtk/gtkslideview.h b/libstorycode/gtk/gtkslideview.h
index d3c111b..3ad77d9 100644
--- a/libstorycode/gtk/gtkslideview.h
+++ b/libstorycode/gtk/gtkslideview.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef SC_EDITOR_H
-#define SC_EDITOR_H
+#ifndef GTK_SLIDE_VIEW_H
+#define GTK_SLIDE_VIEW_H
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -30,29 +30,31 @@
#include <gtk/gtk.h>
#include <glib-object.h>
-#include "frame.h"
-#include "sc_interp.h"
-#include "stylesheet.h"
-struct presentation;
+#include <stylesheet.h>
+#include <narrative.h>
+#include <presentation.h>
+#include <imagestore.h>
+#include <slide_render_cairo.h>
-#define SC_TYPE_EDITOR (sc_editor_get_type())
+#define GTK_TYPE_SLIDE_VIEW (gtk_slide_view_get_type())
-#define SC_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
- SC_TYPE_EDITOR, SCEditor))
+#define GTK_SLIDE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ GTK_TYPE_SLIDE_VIEW, GtkSlideView))
-#define SC_IS_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
- SC_TYPE_EDITOR))
+#define GTK_IS_SLIDE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
+ GTK_TYPE_SLIDE_VIEW))
-#define SC_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), \
- SC_TYPE_EDITOR, SCEditorClass))
+#define GTK_SLIDE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), \
+ GTK_TYPE_SLIDE_VIEW, GtkSlideViewClass))
-#define SC_IS_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), \
- SC_TYPE_EDITOR))
+#define GTK_IS_SLIDE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), \
+ GTK_TYPE_SLIDE_VIEW))
+
+#define GTK_SLIDE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ GTK_TYPE_SLIDE_VIEW, GtkSlideViewClass))
-#define SC_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
- SC_TYPE_EDITOR, SCEditorClass))
enum drag_reason
{
@@ -83,46 +85,28 @@ enum drag_status
};
-struct _sceditor
+struct _gtkslideview
{
GtkDrawingArea parent_instance;
- PangoLanguage *lang;
/*< private >*/
+ Presentation *p;
+ Slide *slide;
GtkIMContext *im_context;
+
int w; /* Surface size in pixels */
int h;
- double log_w; /* Size of surface in "SC units" */
- double log_h;
- SCBlock *scblocks;
- Stylesheet *stylesheet;
- ImageStore *is;
- SCCallbackList *cbl;
- struct frame *top;
- int para_highlight;
/* Redraw/scroll stuff */
- GtkScrollablePolicy hpol;
- GtkScrollablePolicy vpol;
- GtkAdjustment *hadj;
- GtkAdjustment *vadj;
- double scroll_pos;
+ double view_scale; /* The scale factor */
double h_scroll_pos;
- int visible_height;
- int visible_width;
- int flow;
- int scale; /* Whether the SCEditor should scale to fit */
- double view_scale; /* The scale factor, if scale=1 */
-
- /* Pointers to the frame currently being edited */
- struct frame *selection;
- int top_editable;
-
- PangoContext *pc;
+ double v_scroll_pos;
+ double visible_width;
+ double visible_height;
/* Location of the cursor */
- struct frame *cursor_frame;
- struct edit_pos cpos;
+ struct slide_item *cursor_frame;
+ struct slide_pos cpos;
/* Border surrounding actual slide within drawingarea */
double border_offs_x;
@@ -144,9 +128,8 @@ struct _sceditor
enum drag_reason drag_reason;
enum drag_status drag_status;
enum corner drag_corner;
- int sel_active;
- struct edit_pos sel_start; /* Where the user dragged from */
- struct edit_pos sel_end;
+ struct slide_pos sel_start; /* Where the user dragged from */
+ struct slide_pos sel_end;
/* Stuff to do with drag and drop import of "content" */
int drag_preview_pending;
@@ -155,45 +138,17 @@ struct _sceditor
double import_width;
double import_height;
int import_acceptable;
-
- /* Stuff that doesn't really belong here */
- int slidenum;
};
-struct _sceditorclass
+struct _gtkslideviewclass
{
GtkDrawingAreaClass parent_class;
};
-typedef struct _sceditor SCEditor;
-typedef struct _sceditorclass SCEditorClass;
-
-extern void sc_editor_set_scblock(SCEditor *e, SCBlock *scblocks);
-extern void sc_editor_set_stylesheet(SCEditor *e, Stylesheet *stylesheet);
-extern SCEditor *sc_editor_new(SCBlock *scblocks, Stylesheet *stylesheet,
- PangoLanguage *lang, const char *storename);
-extern void sc_editor_set_logical_size(SCEditor *e, double w, double h);
-extern void sc_editor_set_flow(SCEditor *e, int flow);
-extern void sc_editor_set_scale(SCEditor *e, int scale);
-extern void sc_editor_redraw(SCEditor *e);
-extern void sc_editor_set_background(SCEditor *e, double r, double g, double b);
-extern void sc_editor_set_slidenum(SCEditor *e, int slidenum);
-extern void sc_editor_set_min_border(SCEditor *e, double min_border);
-extern void sc_editor_set_top_frame_editable(SCEditor *e,
- int top_frame_editable);
-extern void sc_editor_set_callbacks(SCEditor *e, SCCallbackList *cbl);
-extern void sc_editor_paste(SCEditor *e);
-extern void sc_editor_add_storycode(SCEditor *e, const char *sc);
-extern void sc_editor_copy_selected_frame(SCEditor *e);
-extern void sc_editor_delete_selected_frame(SCEditor *e);
-extern void sc_editor_ensure_cursor(SCEditor *e);
-extern SCBlock *split_paragraph_at_cursor(SCEditor *e);
-
-extern void sc_editor_set_imagestore(SCEditor *e, ImageStore *is);
-extern void sc_editor_set_para_highlight(SCEditor *e, int para_highlight);
-extern int sc_editor_get_cursor_para(SCEditor *e);
-extern void *sc_editor_get_cursor_bvp(SCEditor *e);
-extern void sc_editor_set_cursor_para(SCEditor *e, signed int pos);
-extern int sc_editor_get_num_paras(SCEditor *e);
-
-#endif /* SC_EDITOR_H */
+typedef struct _gtkslideview GtkSlideView;
+typedef struct _gtkslideviewclass GtkSlideViewClass;
+
+extern GtkWidget *gtk_slide_view_new(Presentation *p, Slide *slide);
+extern void gtk_slide_view_set_slide(GtkWidget *sv, Slide *slide);
+
+#endif /* GTK_SLIDE_VIEW_H */
diff --git a/libstorycode/presentation.c b/libstorycode/presentation.c
index d49f965..d862ac0 100644
--- a/libstorycode/presentation.c
+++ b/libstorycode/presentation.c
@@ -141,13 +141,13 @@ void presentation_add_slide(Presentation *p, Slide *s)
}
-int presentation_num_slides(Presentation *p)
+int presentation_get_num_slides(Presentation *p)
{
return p->n_slides;
}
-Slide *presentation_slide(Presentation *p, int i)
+Slide *presentation_get_slide_by_number(Presentation *p, int i)
{
if ( i >= p->n_slides ) return NULL;
if ( i < 0 ) return NULL;
@@ -155,6 +155,17 @@ Slide *presentation_slide(Presentation *p, int i)
}
+signed int presentation_get_slide_number(Presentation *p, Slide *s)
+{
+ int i;
+ if ( p == NULL ) return -1;
+ for ( i=0; i<p->n_slides; i++ ) {
+ if ( s == p->slides[i] ) return i;
+ }
+ return -1;
+}
+
+
Stylesheet *presentation_get_stylesheet(Presentation *p)
{
if ( p == NULL ) return NULL;
diff --git a/libstorycode/presentation.h b/libstorycode/presentation.h
index 3abe91e..ad01382 100644
--- a/libstorycode/presentation.h
+++ b/libstorycode/presentation.h
@@ -44,11 +44,13 @@ extern void presentation_add_stylesheet(Presentation *p, Stylesheet *ss);
extern void presentation_add_narrative(Presentation *p, Narrative *n);
extern void presentation_add_slide(Presentation *p, Slide *s);
-extern int presentation_num_slides(Presentation *p);
-extern Slide *presentation_slide(Presentation *p, int i);
+extern int presentation_get_num_slides(Presentation *p);
+extern Slide *presentation_get_slide_by_number(Presentation *p, int i);
+extern signed int presentation_get_slide_number(Presentation *p, Slide *s);
extern Stylesheet *presentation_get_stylesheet(Presentation *p);
extern Narrative *presentation_get_narrative(Presentation *p);
extern const char *presentation_get_language(Presentation *p);
extern ImageStore *presentation_get_imagestore(Presentation *p);
+
#endif /* PRESENTATION_H */
diff --git a/libstorycode/slide.c b/libstorycode/slide.c
index 694f29a..eaf5f4e 100644
--- a/libstorycode/slide.c
+++ b/libstorycode/slide.c
@@ -205,8 +205,7 @@ int slide_get_logical_size(Slide *s, Stylesheet *ss, double *w, double *h)
if ( s->logical_w < 0.0 ) {
/* Slide-specific value not set, use stylesheet */
- stylesheet_get_slide_default_size(ss, w, h);
- return 0;
+ return stylesheet_get_slide_default_size(ss, w, h);
}
*w = s->logical_w;
diff --git a/libstorycode/slide_render_cairo.h b/libstorycode/slide_render_cairo.h
index 4f8fd68..39c0f59 100644
--- a/libstorycode/slide_render_cairo.h
+++ b/libstorycode/slide_render_cairo.h
@@ -30,6 +30,13 @@
#include "presentation.h"
#include "imagestore.h"
+struct slide_pos
+{
+ int para; /* Paragraph number (corresponding to narrative items) */
+ int pos; /* Byte position within paragraph (yes, really) */
+ int trail; /* 1 = end of character, 0 = before */
+};
+
extern int slide_render_cairo(Slide *s, cairo_t *cr, ImageStore *is, Stylesheet *stylesheet,
int slide_number, PangoLanguage *lang,
PangoContext *pc);
diff --git a/meson.build b/meson.build
index c1daeea..c7747a9 100644
--- a/meson.build
+++ b/meson.build
@@ -87,7 +87,8 @@ libstorycode_dep = declare_dependency(include_directories : libstorycode_include
libgtkstorycode_includes = include_directories('libstorycode/gtk')
libgtkstorycode = library('gtkstorycode',
- ['libstorycode/gtk/gtknarrativeview.c'],
+ ['libstorycode/gtk/gtknarrativeview.c',
+ 'libstorycode/gtk/gtkslideview.c'],
include_directories : libgtkstorycode_includes,
dependencies : [gtk_dep, libstorycode_dep],
install : true)
@@ -111,7 +112,7 @@ executable('colloquium',
'src/narrative_window.c',
# 'src/slideshow.c',
# 'src/pr_clock.c',
-# 'src/slide_window.c',
+ 'src/slide_window.c',
# 'src/testcard.c',
# 'src/stylesheet_editor.c',
],
diff --git a/src/narrative_window.c b/src/narrative_window.c
index b6d8514..7e635b5 100644
--- a/src/narrative_window.c
+++ b/src/narrative_window.c
@@ -38,22 +38,22 @@
#include "colloquium.h"
#include "narrative_window.h"
+#include "slide_window.h"
//#include "testcard.h"
//#include "pr_clock.h"
//#include "print.h"
//#include "stylesheet_editor.h"
typedef struct _ss SCSlideshow; /* FIXME placeholder */
-typedef struct _sw SlideWindow; /* FIXME placeholder */
typedef struct _pc PRClock; /* FIXME placeholder */
struct _narrative_window
{
- GtkWidget *window;
+ GtkWidget *window;
GtkToolItem *bfirst;
GtkToolItem *bprev;
GtkToolItem *bnext;
GtkToolItem *blast;
- GtkNarrativeView *nv;
+ GtkWidget *nv;
GApplication *app;
Presentation *p;
GFile *file;
@@ -465,6 +465,15 @@ static gboolean nw_destroy_sig(GtkWidget *da, NarrativeWindow *nw)
}
+static gboolean nw_double_click_sig(GtkWidget *da, gpointer *pslide,
+ NarrativeWindow *nw)
+{
+ Slide *slide = (Slide *)pslide;
+ slide_window_open(nw->p, slide, nw->app);
+ return FALSE;
+}
+
+
static gboolean nw_key_press_sig(GtkWidget *da, GdkEventKey *event,
NarrativeWindow *nw)
{
@@ -768,6 +777,8 @@ NarrativeWindow *narrative_window_new(Presentation *p, GApplication *papp)
G_CALLBACK(nw_key_press_sig), nw);
g_signal_connect(G_OBJECT(nw->window), "destroy",
G_CALLBACK(nw_destroy_sig), nw);
+ g_signal_connect(G_OBJECT(nw->nv), "slide-double-clicked",
+ G_CALLBACK(nw_double_click_sig), nw);
gtk_window_set_default_size(GTK_WINDOW(nw->window), 768, 768);
gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0);
diff --git a/src/pdfstorycode.c b/src/pdfstorycode.c
index 92e2809..566f924 100644
--- a/src/pdfstorycode.c
+++ b/src/pdfstorycode.c
@@ -61,12 +61,12 @@ static int render_slides_to_pdf(Presentation *p, ImageStore *is, const char *fil
cr = cairo_create(surf);
pc = pango_cairo_create_context(cr);
- for ( i=0; i<presentation_num_slides(p); i++ )
+ for ( i=0; i<presentation_get_num_slides(p); i++ )
{
Slide *s;
double log_w, log_h;
- s = presentation_slide(p, i);
+ s = presentation_get_slide_by_number(p, i);
slide_get_logical_size(s, presentation_get_stylesheet(p),
&log_w, &log_h);
diff --git a/src/slide_window.c b/src/slide_window.c
new file mode 100644
index 0000000..b6c60da
--- /dev/null
+++ b/src/slide_window.c
@@ -0,0 +1,244 @@
+/*
+ * slide_window.c
+ *
+ * Copyright © 2013-2018 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium 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 <gtk/gtk.h>
+#include <assert.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <math.h>
+
+#include <presentation.h>
+#include <slide.h>
+#include <gtkslideview.h>
+
+#include "colloquium.h"
+#include "slide_window.h"
+
+
+struct _slidewindow
+{
+ GtkWidget *window;
+ Presentation *p;
+ Slide *slide;
+ GtkWidget *sv;
+};
+
+
+static void insert_slidetitle_sig(GSimpleAction *action, GVariant *parameter,
+ gpointer vp)
+{
+ SlideWindow *sw = vp;
+ char **text = malloc(sizeof(char *));
+ *text = strdup("Slide title");
+ slide_add_slidetitle(sw->slide, text, 1);
+}
+
+
+static void paste_sig(GSimpleAction *action, GVariant *parameter,
+ gpointer vp)
+{
+ //SlideWindow *sw = vp;
+ //sc_editor_paste(sw->sceditor);
+}
+
+
+static void copy_frame_sig(GSimpleAction *action, GVariant *parameter,
+ gpointer vp)
+{
+ //SlideWindow *sw = vp;
+ //sc_editor_copy_selected_frame(sw->sceditor);
+}
+
+
+static void delete_frame_sig(GSimpleAction *action, GVariant *parameter,
+ gpointer vp)
+{
+ //SlideWindow *sw = vp;
+ //sc_editor_delete_selected_frame(sw->sceditor);
+}
+
+
+/* Change the editor's slide to "np" */
+static void change_edit_slide(SlideWindow *sw, Slide *np)
+{
+ gtk_slide_view_set_slide(sw->sv, np);
+ sw->slide = np;
+}
+
+
+static void change_slide_first(SlideWindow *sw)
+{
+ Slide *s = presentation_get_slide_by_number(sw->p, 0);
+ if ( s != NULL ) change_edit_slide(sw, s);
+}
+
+
+static void change_slide_backwards(SlideWindow *sw)
+{
+ int slide_n = presentation_get_slide_number(sw->p, sw->slide);
+ if ( slide_n > 0 ) {
+ Slide *s = presentation_get_slide_by_number(sw->p, slide_n-1);
+ change_edit_slide(sw, s);
+ }
+}
+
+
+static void change_slide_forwards(SlideWindow *sw)
+{
+ int slide_n = presentation_get_slide_number(sw->p, sw->slide);
+ Slide *s = presentation_get_slide_by_number(sw->p, slide_n+1);
+ if ( s != NULL ) change_edit_slide(sw, s);
+}
+
+
+static void change_slide_last(SlideWindow *sw)
+{
+ int slide_n = presentation_get_num_slides(sw->p);
+ Slide *s = presentation_get_slide_by_number(sw->p, slide_n);
+ if ( s != NULL ) change_edit_slide(sw, s);
+}
+
+
+static void first_slide_sig(GSimpleAction *action, GVariant *parameter,
+ gpointer vp)
+{
+ SlideWindow *sw = vp;
+ change_slide_first(sw);
+}
+
+
+static void prev_slide_sig(GSimpleAction *action, GVariant *parameter,
+ gpointer vp)
+{
+ SlideWindow *sw = vp;
+ change_slide_backwards(sw);
+}
+
+
+static void next_slide_sig(GSimpleAction *action, GVariant *parameter,
+ gpointer vp)
+{
+ SlideWindow *sw = vp;
+ change_slide_forwards(sw);
+}
+
+
+static void last_slide_sig(GSimpleAction *action, GVariant *parameter,
+ gpointer vp)
+{
+ SlideWindow *sw = vp;
+ change_slide_last(sw);
+}
+
+
+static gboolean sw_close_sig(GtkWidget *w, SlideWindow *sw)
+{
+ //narrative_window_sw_closed(sw->p->narrative_window, sw);
+ return FALSE;
+}
+
+
+static gboolean sw_key_press_sig(GtkWidget *da, GdkEventKey *event,
+ SlideWindow *sw)
+{
+ switch ( event->keyval ) {
+
+ case GDK_KEY_Page_Up :
+ change_slide_backwards(sw);
+ break;
+
+ case GDK_KEY_Page_Down :
+ change_slide_forwards(sw);
+ break;
+
+ }
+
+ return FALSE;
+}
+
+
+static void about_sig(GSimpleAction *action, GVariant *parameter, gpointer vp)
+{
+ SlideWindow *sw = vp;
+ open_about_dialog(sw->window);
+}
+
+
+GActionEntry sw_entries[] = {
+
+ { "about", about_sig, NULL, NULL, NULL },
+ { "paste", paste_sig, NULL, NULL, NULL },
+ { "copyframe", copy_frame_sig, NULL, NULL, NULL },
+ { "deleteframe", delete_frame_sig, NULL, NULL, NULL },
+ { "first", first_slide_sig, NULL, NULL, NULL },
+ { "prev", prev_slide_sig, NULL, NULL, NULL },
+ { "next", next_slide_sig, NULL, NULL, NULL },
+ { "last", last_slide_sig, NULL, NULL, NULL },
+ { "slidetitle", insert_slidetitle_sig, NULL, NULL, NULL },
+};
+
+
+extern SlideWindow *slide_window_open(Presentation *p, Slide *slide,
+ GApplication *papp)
+{
+ GtkWidget *window;
+ SlideWindow *sw;
+ double w, h;
+ Colloquium *app = COLLOQUIUM(papp);
+
+ sw = calloc(1, sizeof(SlideWindow));
+ if ( sw == NULL ) return NULL;
+
+ window = gtk_application_window_new(GTK_APPLICATION(app));
+ gtk_window_set_role(GTK_WINDOW(window), "slide");
+ sw->window = window;
+ sw->p = p;
+
+ g_action_map_add_action_entries(G_ACTION_MAP(window), sw_entries,
+ G_N_ELEMENTS(sw_entries), sw);
+
+ g_signal_connect(G_OBJECT(window), "destroy",
+ G_CALLBACK(sw_close_sig), sw);
+
+ sw->sv = gtk_slide_view_new(p, slide);
+
+ g_signal_connect(G_OBJECT(sw->sv), "key-press-event",
+ G_CALLBACK(sw_key_press_sig), sw);
+
+ slide_get_logical_size(slide, presentation_get_stylesheet(p), &w, &h);
+ gtk_window_set_default_size(GTK_WINDOW(window), w, h);
+
+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(sw->sv));
+
+ gtk_window_set_resizable(GTK_WINDOW(sw->window), TRUE);
+
+ gtk_widget_show_all(window);
+
+ return sw;
+}
diff --git a/src/slide_window.h b/src/slide_window.h
new file mode 100644
index 0000000..f59fad1
--- /dev/null
+++ b/src/slide_window.h
@@ -0,0 +1,35 @@
+/*
+ * slide_window.h
+ *
+ * Copyright © 2013-2019 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium 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 SLIDEWINDOW_H
+#define SLIDEWINDOW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+typedef struct _slidewindow SlideWindow;
+
+extern SlideWindow *slide_window_open(Presentation *p, Slide *slide,
+ GApplication *papp);
+
+#endif /* SLIDEWINDOW_H */