diff options
author | Thomas White <taw@bitwiz.org.uk> | 2012-09-04 22:40:53 +0200 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2012-09-04 22:40:53 +0200 |
commit | c4b897371ba6772bfed962e7ac067fac5e8a2df8 (patch) | |
tree | 0b0a6581aee0dcbe854d2c1b00f0cf966900faac | |
parent | 66ba736f5e448ebb5bf64fe88048b930e3b0e821 (diff) |
Plug mainwindow back in
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | src/colloquium.c | 21 | ||||
-rw-r--r-- | src/mainwindow.c | 730 | ||||
-rw-r--r-- | src/mainwindow.h | 38 | ||||
-rw-r--r-- | src/presentation.c | 227 | ||||
-rw-r--r-- | src/presentation.h | 82 |
6 files changed, 1090 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am index 9da9649..f565eb7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,7 @@ AM_CPPFLAGS = -DDATADIR=\""$(datadir)"\" -I$(top_builddir)/lib \ LDADD = $(top_builddir)/lib/libgnu.a @IGNORE_UNUSED_LIBRARIES_CFLAGS@ src_colloquium_SOURCES = src/colloquium.c src/storycode.c src/render.c \ - src/layout.c + src/layout.c src/mainwindow.c src/presentation.c INCLUDES = "-I$(top_srcdir)/data" diff --git a/src/colloquium.c b/src/colloquium.c index 93d2c4e..5af188b 100644 --- a/src/colloquium.c +++ b/src/colloquium.c @@ -3,7 +3,7 @@ * * Colloquium - A tiny presentation program * - * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk> + * Copyright (c) 2012 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 @@ -28,6 +28,9 @@ #include <gtk/gtk.h> #include <getopt.h> +#include "presentation.h" +#include "mainwindow.h" + static void show_help(const char *s) { @@ -43,7 +46,7 @@ static void show_help(const char *s) int main(int argc, char *argv[]) { int c; -// struct presentation *p; + struct presentation *p; /* Long options */ const struct option longopts[] = { @@ -71,13 +74,13 @@ int main(int argc, char *argv[]) } -// p = new_presentation(); -// p->cur_edit_slide = add_slide(p, 0); -// p->completely_empty = 1; -// if ( open_mainwindow(p) ) { -// fprintf(stderr, "Couldn't open main window.\n"); -// return 1; -// } + p = new_presentation(); + p->cur_edit_slide = add_slide(p, 0); + p->completely_empty = 1; + if ( open_mainwindow(p) ) { + fprintf(stderr, "Couldn't open main window.\n"); + return 1; + } gtk_main(); diff --git a/src/mainwindow.c b/src/mainwindow.c new file mode 100644 index 0000000..23cbdf7 --- /dev/null +++ b/src/mainwindow.c @@ -0,0 +1,730 @@ +/* + * mainwindow.c + * + * Colloquium - A tiny presentation program + * + * Copyright (c) 2012 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 <gtk/gtk.h> +#include <assert.h> +#include <gdk/gdkkeysyms.h> +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include "presentation.h" +#include "mainwindow.h" +#include "render.h" + + +static void add_ui_sig(GtkUIManager *ui, GtkWidget *widget, + GtkContainer *container) +{ + gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0); + if ( GTK_IS_TOOLBAR(widget) ) { + gtk_toolbar_set_show_arrow(GTK_TOOLBAR(widget), TRUE); + } +} + + +static gint quit_sig(GtkWidget *widget, struct presentation *p) +{ + return 0; +} + + +/* FIXME (unused) */ +static UNUSED void show_error(struct presentation *p, const char *message) +{ + GtkWidget *window; + + window = gtk_message_dialog_new(GTK_WINDOW(p->window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CLOSE, message); + gtk_window_set_title(GTK_WINDOW(window), "Error"); + + g_signal_connect_swapped(window, "response", + G_CALLBACK(gtk_widget_destroy), window); + gtk_widget_show(window); +} + + +static void update_toolbar(struct presentation *p) +{ + GtkWidget *d; + int cur_slide_number; + + d = gtk_ui_manager_get_widget(p->ui, "/ui/displaywindowtoolbar/first"); + gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); + d = gtk_ui_manager_get_widget(p->ui, "/ui/displaywindowtoolbar/prev"); + gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); + d = gtk_ui_manager_get_widget(p->ui, "/ui/displaywindowtoolbar/next"); + gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); + d = gtk_ui_manager_get_widget(p->ui, "/ui/displaywindowtoolbar/last"); + gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); + + cur_slide_number = slide_number(p, p->cur_edit_slide); + if ( cur_slide_number == 0 ) { + + d = gtk_ui_manager_get_widget(p->ui, + "/ui/displaywindowtoolbar/first"); + gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE); + d = gtk_ui_manager_get_widget(p->ui, + "/ui/displaywindowtoolbar/prev"); + gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE); + + } + + if ( cur_slide_number == p->num_slides-1 ) { + + d = gtk_ui_manager_get_widget(p->ui, + "/ui/displaywindowtoolbar/next"); + gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE); + d = gtk_ui_manager_get_widget(p->ui, + "/ui/displaywindowtoolbar/last"); + gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE); + + } + + +} + + +static gint open_response_sig(GtkWidget *d, gint response, + struct presentation *p) +{ + if ( response == GTK_RESPONSE_ACCEPT ) { + + char *filename; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d)); + + if ( p->completely_empty ) { + + /* FIXME */ + //if ( load_presentation(p, filename) ) { + // show_error(p, "Failed to open presentation"); + //} + //redraw_slide(p->cur_edit_slide); + update_toolbar(p); + + } else { + + struct presentation *p; + + /* FIXME */ + p = new_presentation(); + //if ( load_presentation(p, filename) ) { + // show_error(p, "Failed to open presentation"); + //} else { + open_mainwindow(p); + //} + + } + + g_free(filename); + + } + + gtk_widget_destroy(d); + + return 0; +} + + +static gint open_sig(GtkWidget *widget, struct presentation *p) +{ + GtkWidget *d; + + d = gtk_file_chooser_dialog_new("Open Presentation", + GTK_WINDOW(p->window), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + g_signal_connect(G_OBJECT(d), "response", + G_CALLBACK(open_response_sig), p); + + gtk_widget_show_all(d); + + return 0; +} + + +static gint new_sig(GtkWidget *widget, struct presentation *pnn) +{ + struct presentation *p; + + p = new_presentation(); + if ( p != NULL ) { + p->cur_edit_slide = add_slide(p, 0); + p->completely_empty = 1; + open_mainwindow(p); + } + + return 0; +} + + +static gint saveas_response_sig(GtkWidget *d, gint response, + struct presentation *p) +{ + if ( response == GTK_RESPONSE_ACCEPT ) { + + char *filename; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d)); + + /* FIXME */ + //if ( save_presentation(p, filename) ) { + // show_error(p, "Failed to save presentation"); + //} + + g_free(filename); + + } + + gtk_widget_destroy(d); + + return 0; +} + + +static gint saveas_sig(GtkWidget *widget, struct presentation *p) +{ + GtkWidget *d; + + d = gtk_file_chooser_dialog_new("Save Presentation", + GTK_WINDOW(p->window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(d), + TRUE); + + g_signal_connect(G_OBJECT(d), "response", + G_CALLBACK(saveas_response_sig), p); + + gtk_widget_show_all(d); + + return 0; +} + + +static gint save_sig(GtkWidget *widget, struct presentation *p) +{ + if ( p->filename == NULL ) { + return saveas_sig(widget, p); + } + + /* FIXME */ + //save_presentation(p, p->filename); + + return 0; +} + + +static gint save_ss_response_sig(GtkWidget *d, gint response, + struct presentation *p) +{ + if ( response == GTK_RESPONSE_ACCEPT ) { + + char *filename; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d)); + + /* FIXME */ + //if ( save_stylesheet(p->ss, filename) ) { + // show_error(p, "Failed to save style sheet"); + //} + + g_free(filename); + + } + + gtk_widget_destroy(d); + + return 0; +} + + +static gint save_ss_sig(GtkWidget *widget, struct presentation *p) +{ + GtkWidget *d; + + d = gtk_file_chooser_dialog_new("Save Style sheet", + GTK_WINDOW(p->window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(d), + TRUE); + + g_signal_connect(G_OBJECT(d), "response", + G_CALLBACK(save_ss_response_sig), p); + + gtk_widget_show_all(d); + + return 0; +} + + +static gint export_pdf_response_sig(GtkWidget *d, gint response, + struct presentation *p) +{ + if ( response == GTK_RESPONSE_ACCEPT ) { + + char *filename; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d)); + + /* FIXME */ + //if ( export_pdf(p, filename) ) { + // show_error(p, "Failed to export as PDF"); + //} + + g_free(filename); + + } + + gtk_widget_destroy(d); + + return 0; +} + + +static gint export_pdf_sig(GtkWidget *widget, struct presentation *p) +{ + GtkWidget *d; + + d = gtk_file_chooser_dialog_new("Export PDF", + GTK_WINDOW(p->window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(d), + TRUE); + + g_signal_connect(G_OBJECT(d), "response", + G_CALLBACK(export_pdf_response_sig), p); + + gtk_widget_show_all(d); + + return 0; +} + + +static gint about_sig(GtkWidget *widget, struct presentation *p) +{ + GtkWidget *window; + + const gchar *authors[] = { + "Thomas White <taw@bitwiz.org.uk>", + NULL + }; + + window = gtk_about_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(p->window)); + + gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(window), + "Colloquium"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(window), + PACKAGE_VERSION); + gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(window), + "(c) 2012 Thomas White <taw@bitwiz.org.uk>"); + gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(window), + "A tiny presentation program"); + gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(window), + "(c) 2012 Thomas White <taw@bitwiz.org.uk>\n"); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(window), + "http://www.bitwiz.org.uk/"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(window), authors); + + g_signal_connect(window, "response", G_CALLBACK(gtk_widget_destroy), + NULL); + + gtk_widget_show_all(window); + + return 0; +} + + +static gint start_slideshow_sig(GtkWidget *widget, struct presentation *p) +{ + /* FIXME */ + //try_start_slideshow(p); + return FALSE; +} + + +void notify_slide_changed(struct presentation *p, struct slide *np) +{ + p->cur_edit_slide = np; + + /* FIXME: Free old rendered stuff */ + + update_toolbar(p); + //redraw_slide(p->cur_edit_slide); + + if ( p->notes != NULL ) { + //notify_notes_slide_changed(p, np); + } + + if ( (p->slideshow != NULL) && p->slideshow_linked ) { + //notify_slideshow_slide_changed(p, np); + } +} + + +static gint add_slide_sig(GtkWidget *widget, struct presentation *p) +{ + struct slide *new; + int cur_slide_number; + + cur_slide_number = slide_number(p, p->cur_edit_slide); + + new = add_slide(p, cur_slide_number); + notify_slide_changed(p, new); + + return FALSE; +} + + +static gint first_slide_sig(GtkWidget *widget, struct presentation *p) +{ + notify_slide_changed(p, p->slides[0]); + return FALSE; +} + + +static gint prev_slide_sig(GtkWidget *widget, struct presentation *p) +{ + int cur_slide_number; + + cur_slide_number = slide_number(p, p->cur_edit_slide); + if ( cur_slide_number == 0 ) return FALSE; + + notify_slide_changed(p, p->slides[cur_slide_number-1]); + + return FALSE; +} + + +static gint next_slide_sig(GtkWidget *widget, struct presentation *p) +{ + int cur_slide_number; + + cur_slide_number = slide_number(p, p->cur_edit_slide); + if ( cur_slide_number == p->num_slides-1 ) return FALSE; + + notify_slide_changed(p, p->slides[cur_slide_number+1]); + + return FALSE; +} + + +static gint last_slide_sig(GtkWidget *widget, struct presentation *p) +{ + notify_slide_changed(p, p->slides[p->num_slides-1]); + + return FALSE; +} + + +static gint open_stylesheet_sig(GtkWidget *widget, struct presentation *p) +{ + /* FIXME */ + //if ( p->stylesheetwindow == NULL ) { + // p->stylesheetwindow = open_stylesheet(p); + //} /* else already open */ + + return FALSE; +} + + +static gint open_notes_sig(GtkWidget *widget, struct presentation *p) +{ + /* FIXME */ + //open_notes(p); + return FALSE; +} + + +static void add_menu_bar(struct presentation *p, GtkWidget *vbox) +{ + GError *error = NULL; + GtkWidget *toolbar; + GtkWidget *menu; + GtkWidget *item; + //int i; + GtkActionEntry entries[] = { + + { "FileAction", NULL, "_File", NULL, NULL, NULL }, + { "NewAction", GTK_STOCK_NEW, "_New", + NULL, NULL, G_CALLBACK(new_sig) }, + { "OpenAction", GTK_STOCK_OPEN, "_Open...", + NULL, NULL, G_CALLBACK(open_sig) }, + { "SaveAction", GTK_STOCK_SAVE, "_Save", + NULL, NULL, G_CALLBACK(save_sig) }, + { "SaveAsAction", GTK_STOCK_SAVE_AS, "Save _As...", + NULL, NULL, G_CALLBACK(saveas_sig) }, + { "SaveStyleAction", GTK_STOCK_SAVE_AS, "Save St_ylesheet", + NULL, NULL, G_CALLBACK(save_ss_sig) }, + { "ExportPDFAction", GTK_STOCK_SAVE_AS, "Export PDF", + NULL, NULL, G_CALLBACK(export_pdf_sig) }, + { "QuitAction", GTK_STOCK_QUIT, "_Quit", + NULL, NULL, G_CALLBACK(quit_sig) }, + + { "EditAction", NULL, "_Edit", NULL, NULL, NULL }, + { "UndoAction", GTK_STOCK_UNDO, "_Undo", + NULL, NULL, NULL }, + { "RedoAction", GTK_STOCK_REDO, "_Redo", + NULL, NULL, NULL }, + { "CutAction", GTK_STOCK_CUT, "Cut", + NULL, NULL, NULL }, + { "CopyAction", GTK_STOCK_COPY, "Copy", + NULL, NULL, NULL }, + { "PasteAction", GTK_STOCK_PASTE, "Paste", + NULL, NULL, NULL }, + { "DeleteAction", GTK_STOCK_DELETE, "Delete", + NULL, NULL, NULL }, + { "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) }, + { "NotesAction", NULL, "_Open slide notes", + "F5", NULL, G_CALLBACK(open_notes_sig) }, + { "PrefsAction", GTK_STOCK_PREFERENCES, "_Preferences", + NULL, NULL, NULL }, + + { "HelpAction", NULL, "_Help", NULL, NULL, NULL }, + { "AboutAction", GTK_STOCK_ABOUT, "_About...", + NULL, NULL, G_CALLBACK(about_sig) }, + + { "SlideshowAction", GTK_STOCK_FULLSCREEN, "Start Presentation", + NULL, NULL, G_CALLBACK(start_slideshow_sig) }, + { "AddSlideAction", GTK_STOCK_ADD, "Add Slide", + NULL, NULL, G_CALLBACK(add_slide_sig) }, + { "ButtonFirstSlideAction", GTK_STOCK_GOTO_FIRST, "First Slide", + NULL, NULL, G_CALLBACK(first_slide_sig) }, + { "ButtonPrevSlideAction", GTK_STOCK_GO_BACK, "Previous Slide", + NULL, NULL, G_CALLBACK(prev_slide_sig) }, + { "ButtonNextSlideAction", GTK_STOCK_GO_FORWARD, "Next Slide", + NULL, NULL, G_CALLBACK(next_slide_sig) }, + { "ButtonLastSlideAction", GTK_STOCK_GOTO_LAST, "Last Slide", + NULL, NULL, G_CALLBACK(last_slide_sig) }, + + }; + guint n_entries = G_N_ELEMENTS(entries); + + p->action_group = gtk_action_group_new("mainwindow"); + gtk_action_group_add_actions(p->action_group, entries, n_entries, p); + + p->ui = gtk_ui_manager_new(); + gtk_ui_manager_insert_action_group(p->ui, p->action_group, 0); + g_signal_connect(p->ui, "add_widget", G_CALLBACK(add_ui_sig), vbox); + if ( gtk_ui_manager_add_ui_from_file(p->ui, + DATADIR"/colloquium/colloquium.ui", &error) == 0 ) { + fprintf(stderr, "Error loading main window menu bar: %s\n", + error->message); + return; + } + + gtk_window_add_accel_group(GTK_WINDOW(p->window), + gtk_ui_manager_get_accel_group(p->ui)); + gtk_ui_manager_ensure_update(p->ui); + + toolbar = gtk_ui_manager_get_widget(p->ui, "/displaywindowtoolbar"); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), + gtk_separator_tool_item_new(), -1); + + p->tbox = GTK_WIDGET(gtk_tool_item_new()); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(p->tbox), -1); + + /* Add the styles to the "Insert" menu */ + menu = gtk_ui_manager_get_widget(p->ui, "/displaywindow/insert"); + menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu)); + item = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + + /* FIXME */ + //for ( i=1; i<p->ss->n_styles; i++ ) + //{ + // char *name; + // name = p->ss->styles[i]->name; + // item = gtk_menu_item_new_with_label(name); + // gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + // g_signal_connect(G_OBJECT(item), "activate", + // G_CALLBACK(add_furniture), p); + // + //} + + update_toolbar(p); +} + + +static gint close_sig(GtkWidget *window, struct presentation *p) +{ + free_presentation(p); + return 0; +} + + +static gboolean draw_sig(GtkWidget *da, cairo_t *cr, + struct presentation *p) +{ + double xoff, yoff; + int width, height; + + width = gtk_widget_get_allocated_width(GTK_WIDGET(da)); + height = gtk_widget_get_allocated_height(GTK_WIDGET(da)); + + /* Overall background */ + cairo_rectangle(cr, 0.0, 0.0, width, height); + if ( (p->slideshow != NULL) && !p->slideshow_linked ) { + cairo_set_source_rgb(cr, 1.0, 0.3, 0.2); + } else { + cairo_set_source_rgb(cr, 0.9, 0.9, 0.9); + } + cairo_fill(cr); + + /* Get the overall size */ + xoff = (width - p->slide_width)/2.0; + yoff = (height - p->slide_height)/2.0; + p->border_offs_x = xoff; p->border_offs_y = yoff; + + /* Draw the slide from the cache */ + cairo_rectangle(cr, 0.0, 0.0, width, height); + cairo_set_source_surface(cr, p->cur_edit_slide->rendered_edit, + xoff, yoff); + cairo_fill(cr); + + cairo_translate(cr, xoff, yoff); + + /* FIXME */ + //draw_overlay(cr, p); + + return FALSE; +} + + +void update_titlebar(struct presentation *p) +{ + get_titlebar_string(p); + + if ( p->window != NULL ) { + + char *title; + + title = malloc(strlen(p->titlebar)+14); + sprintf(title, "%s - Colloquium", p->titlebar); + gtk_window_set_title(GTK_WINDOW(p->window), title); + free(title); + + } +} + + +int open_mainwindow(struct presentation *p) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *sw; + + if ( p->window != NULL ) { + fprintf(stderr, "Presentation window is already open!\n"); + return 1; + } + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + p->window = window; + + update_titlebar(p); + + g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(close_sig), p); + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_container_add(GTK_CONTAINER(window), vbox); + + p->drawingarea = gtk_drawing_area_new(); + sw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), + p->drawingarea); + gtk_widget_set_size_request(GTK_WIDGET(p->drawingarea), + p->slide_width + 20, + p->slide_height + 20); + + add_menu_bar(p, vbox); + gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); + + gtk_widget_set_can_focus(GTK_WIDGET(p->drawingarea), TRUE); + gtk_widget_add_events(GTK_WIDGET(p->drawingarea), + 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); + + g_signal_connect(G_OBJECT(p->drawingarea), "draw", + G_CALLBACK(draw_sig), p); + + /* Input method */ + /* FIXME */ + p->im_context = gtk_im_multicontext_new(); + //gtk_im_context_set_client_window(GTK_IM_CONTEXT(p->im_context), + // p->drawingarea->window); + //g_signal_connect(G_OBJECT(p->im_context), "commit", + // G_CALLBACK(im_commit_sig), p); + + /* Default size */ + gtk_window_set_default_size(GTK_WINDOW(p->window), 1024+100, 768+100); + gtk_window_set_resizable(GTK_WINDOW(p->window), TRUE); + + assert(p->num_slides > 0); + + gtk_widget_grab_focus(GTK_WIDGET(p->drawingarea)); + + gtk_widget_show_all(window); + + p->edit_slide_width = 1024; + p->proj_slide_width = 2048; + p->thumb_slide_width = 320; /* FIXME: Completely made up */ + + /* FIXME */ + //redraw_slide(p->cur_edit_slide); + + return 0; +} diff --git a/src/mainwindow.h b/src/mainwindow.h new file mode 100644 index 0000000..3bfff44 --- /dev/null +++ b/src/mainwindow.h @@ -0,0 +1,38 @@ +/* + * presentation.h + * + * Colloquium - A tiny presentation program + * + * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +extern int open_mainwindow(struct presentation *p); +extern void notify_slide_changed(struct presentation *p, struct slide *np); +extern void update_titlebar(struct presentation *p); + +extern void redraw_overlay(struct presentation *p); + + +#endif /* MAINWINDOW_H */ diff --git a/src/presentation.c b/src/presentation.c new file mode 100644 index 0000000..01a8fbf --- /dev/null +++ b/src/presentation.c @@ -0,0 +1,227 @@ +/* + * presentation.c + * + * Colloquium - A tiny presentation program + * + * Copyright (c) 2012 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 <gtk/gtk.h> + +#include "presentation.h" +#include "stylesheet.h" + + +static int num_presentations = 0; + + +void free_presentation(struct presentation *p) +{ + int i; + int final = 0; + + for ( i=0; i<p->num_slides; i++ ) { + free_slide(p->slides[i]); + } + + (*p->num_presentations)--; + if ( *p->num_presentations == 0 ) final = 1; + + /* FIXME: Loads of stuff leaks here */ + free(p->filename); + free(p); + + if ( final ) { + gtk_main_quit(); + } +} + + +int insert_slide(struct presentation *p, struct slide *new, int pos) +{ + struct slide **try; + + try = realloc(p->slides, (1+p->num_slides)*sizeof(struct slide *)); + if ( try == NULL ) { + free(new); + return 1; + } + p->slides = try; + p->completely_empty = 0; + + /* Insert into list. Yuk yuk yuk etc. */ + if ( (p->num_slides>1) && (pos<p->num_slides-1) ) { + + int i; + + for ( i=p->num_slides; i>pos+1; i-- ) { + p->slides[i] = p->slides[i-1]; + } + p->slides[pos+1] = new; + + } else if ( pos == p->num_slides-1 ) { + + p->slides[pos+1] = new; + + } else { + assert(pos == 0); + p->slides[pos] = new; + } + + new->parent = p; + p->num_slides++; + + return 0; +} + + +struct slide *new_slide() +{ + struct slide *new; + + new = calloc(1, sizeof(struct slide)); + if ( new == NULL ) return NULL; + + new->rendered_edit = NULL; + new->rendered_proj = NULL; + new->rendered_thumb = NULL; + + new->notes = strdup(""); + + return new; +} + + +void free_slide(struct slide *s) +{ + free(s); +} + + +struct slide *add_slide(struct presentation *p, int pos) +{ + struct slide *s = new_slide(); + if ( insert_slide(p, s, pos) ) { + free_slide(s); + return NULL; + } + + return s; +} + + +static char *safe_basename(const char *in) +{ + int i; + char *cpy; + char *res; + + cpy = strdup(in); + + /* Get rid of any trailing slashes */ + for ( i=strlen(cpy)-1; i>0; i-- ) { + if ( cpy[i] == '/' ) { + cpy[i] = '\0'; + } else { + break; + } + } + + /* Find the base name */ + for ( i=strlen(cpy)-1; i>0; i-- ) { + if ( cpy[i] == '/' ) { + i++; + break; + } + } + + res = strdup(cpy+i); + /* If we didn't find a previous slash, i==0 so res==cpy */ + + free(cpy); + + return res; +} + + +void get_titlebar_string(struct presentation *p) +{ + free(p->titlebar); + + if ( p->filename == NULL ) { + p->titlebar = strdup("(untitled)"); + } else { + p->titlebar = safe_basename(p->filename); + } +} + + +int slide_number(struct presentation *p, struct slide *s) +{ + int i; + + for ( i=0; i<p->num_slides; i++ ) { + if ( p->slides[i] == s ) return i; + } + + return p->num_slides; +} + + +struct presentation *new_presentation() +{ + struct presentation *new; + + new = calloc(1, sizeof(struct presentation)); + + num_presentations++; + new->num_presentations = &num_presentations; + + new->filename = NULL; + new->titlebar = NULL; + get_titlebar_string(new); + + new->window = NULL; + new->ui = NULL; + new->action_group = NULL; + new->slideshow = NULL; + new->notes = NULL; + + new->slide_width = 1024.0; + new->slide_height = 768.0; + + /* Add one blank slide and view it */ + new->num_slides = 0; + new->slides = NULL; + new->cur_edit_slide = NULL; + new->cur_proj_slide = NULL; + + new->completely_empty = 1; + + //new->ss = new_stylesheet(); + //default_stylesheet(new->ss); + + return new; +} diff --git a/src/presentation.h b/src/presentation.h index 73eb5b3..d8fe5c4 100644 --- a/src/presentation.h +++ b/src/presentation.h @@ -29,6 +29,7 @@ #include <cairo.h> #include <pango/pango.h> +#include <gtk/gtk.h> struct frame; #include "layout.h" @@ -75,4 +76,85 @@ struct frame }; +struct presentation +{ + char *titlebar; + char *filename; + int completely_empty; + int *num_presentations; + + struct prefs *prefs; + + struct toolinfo *select_tool; + struct toolinfo *text_tool; + struct toolinfo *image_tool; + + GtkWidget *window; + GtkWidget *drawingarea; + GtkUIManager *ui; + GtkActionGroup *action_group; + GtkIMContext *im_context; + GtkWidget *tbox; + GtkWidget *cur_tbox; + struct notes *notes; + + /* Pointers to the current "editing" and "projection" slides */ + struct slide *cur_edit_slide; + struct slide *cur_proj_slide; + struct slide *cur_notes_slide; + int slideshow_linked; + + /* This is the "native" size of the slide. It only exists to give + * font size some meaning in the context of a somewhat arbitrary DPI */ + double slide_width; + double slide_height; + + /* Width of a slide in the editor, projector or thumbnail (pixels) */ + int edit_slide_width; + int proj_slide_width; + int thumb_slide_width; + + /* This is just to help with rendering the slides within the + * editing window. */ + double border_offs_x; + double border_offs_y; + + /* Slideshow stuff */ + GtkWidget *slideshow; + GtkWidget *ss_drawingarea; + GdkCursor *blank_cursor; + int ss_blank; + char ss_geom[256]; + + /* Tool status */ + struct toolinfo *cur_tool; + + /* Stuff to do with drag and drop import of "content" */ + int drag_preview_pending; + int have_drag_data; + int drag_highlight; + double import_width; + double import_height; + int import_acceptable; + + unsigned int num_slides; + struct slide **slides; +}; + + +extern struct presentation *new_presentation(void); +extern void free_presentation(struct presentation *p); + +extern struct slide *new_slide(void); +extern struct slide *add_slide(struct presentation *p, int pos); +extern int insert_slide(struct presentation *p, struct slide *s, int pos); +extern void free_slide(struct slide *s); + +extern void get_titlebar_string(struct presentation *p); + +extern int slide_number(struct presentation *p, struct slide *s); + +#define UNUSED __attribute__((unused)) + + #endif /* PRESENTATION_H */ |