diff options
Diffstat (limited to 'src/slide_window.c')
-rw-r--r-- | src/slide_window.c | 620 |
1 files changed, 620 insertions, 0 deletions
diff --git a/src/slide_window.c b/src/slide_window.c new file mode 100644 index 0000000..bd64538 --- /dev/null +++ b/src/slide_window.c @@ -0,0 +1,620 @@ +/* + * slide_window.c + * + * Copyright © 2013-2014 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_window.h" +#include "render.h" +#include "frame.h" +#include "slideshow.h" +#include "wrap.h" +#include "notes.h" +#include "pr_clock.h" +#include "slide_sorter.h" +#include "sc_parse.h" +#include "sc_interp.h" +#include "sc_editor.h" + + +struct _slidewindow +{ + struct presentation *p; + GtkWidget *window; + GtkUIManager *ui; + GtkActionGroup *action_group; + + SCEditor *sceditor; + + struct menu_pl *style_menu; + int n_style_menu; + + struct slide *cur_slide; /* FIXME: SPOT inside SCEditor */ +}; + + +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); + } +} + +void update_toolbar(SlideWindow *sw) +{ + GtkWidget *d; + int cur_slide_number; + + d = gtk_ui_manager_get_widget(sw->ui, "/ui/displaywindowtoolbar/first"); + gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); + d = gtk_ui_manager_get_widget(sw->ui, "/ui/displaywindowtoolbar/prev"); + gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); + d = gtk_ui_manager_get_widget(sw->ui, "/ui/displaywindowtoolbar/next"); + gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); + d = gtk_ui_manager_get_widget(sw->ui, "/ui/displaywindowtoolbar/last"); + gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); + + cur_slide_number = slide_number(sw->p, sw->cur_slide); + if ( cur_slide_number == 0 ) { + + d = gtk_ui_manager_get_widget(sw->ui, + "/ui/displaywindowtoolbar/first"); + gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE); + d = gtk_ui_manager_get_widget(sw->ui, + "/ui/displaywindowtoolbar/prev"); + gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE); + + } + + if ( cur_slide_number == sw->p->num_slides-1 ) { + + d = gtk_ui_manager_get_widget(sw->ui, + "/ui/displaywindowtoolbar/next"); + gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE); + d = gtk_ui_manager_get_widget(sw->ui, + "/ui/displaywindowtoolbar/last"); + gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE); + + } + + +} + + +/* Inelegance to make furniture selection menus work */ +struct menu_pl +{ + SlideWindow *sw; + char *style_name; + GtkWidget *widget; +}; + + +static gint add_furniture(GtkWidget *widget, struct menu_pl *pl) +{ + sc_block_append_end(pl->sw->cur_slide->scblocks, + strdup(pl->style_name), NULL, NULL); + + //do_slide_update(pl->p, pl->sw->pc); FIXME + + return 0; +} + + +static void update_style_menus(SlideWindow *sw) +{ + GtkWidget *menu; + SCInterpreter *scin; + struct style_id *styles; + int i, n_sty; + + /* Free old list */ + for ( i=0; i<sw->n_style_menu; i++ ) { + gtk_widget_destroy(sw->style_menu[i].widget); + free(sw->style_menu[i].style_name); + } + free(sw->style_menu); + + /* Get the list of styles from the style sheet */ + scin = sc_interp_new(NULL, NULL); + if ( scin == NULL ) { + fprintf(stderr, "Failed to set up interpreter.\n"); + return; + } + sc_interp_run_stylesheet(scin, sw->p->stylesheet); + + styles = list_styles(scin, &n_sty); + if ( styles == NULL ) return; + + sc_interp_destroy(scin); + + /* Set up list for next time */ + sw->style_menu = calloc(n_sty, sizeof(struct menu_pl)); + if ( sw->style_menu == NULL ) return; + + /* Add the styles to the "Insert" menu */ + menu = gtk_ui_manager_get_widget(sw->ui, "/displaywindow/insert"); + menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu)); + + for ( i=0; i<n_sty; i++ ) { + + GtkWidget *item; + + item = gtk_menu_item_new_with_label(styles[i].friendlyname); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + + sw->style_menu[i].sw = sw; + sw->style_menu[i].widget = item; + sw->style_menu[i].style_name = styles[i].name; + + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK(add_furniture), + &sw->style_menu[i]); + + free(styles[i].friendlyname); + } + + gtk_widget_show_all(menu); + free(styles); +} + + +static gint saveas_response_sig(GtkWidget *d, gint response, + SlideWindow *sw) +{ + if ( response == GTK_RESPONSE_ACCEPT ) { + + char *filename; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d)); + + if ( save_presentation(sw->p, filename) ) { + //show_error(sw, "Failed to save presentation"); + } + + g_free(filename); + + } + + gtk_widget_destroy(d); + + return 0; +} + + +static gint saveas_sig(GtkWidget *widget, SlideWindow *sw) +{ + GtkWidget *d; + + d = gtk_file_chooser_dialog_new("Save Presentation", + GTK_WINDOW(sw->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), sw); + + gtk_widget_show_all(d); + + return 0; +} + + +static gint save_sig(GtkWidget *widget, SlideWindow *sw) +{ + if ( sw->p->filename == NULL ) { + return saveas_sig(widget, sw); + } + + save_presentation(sw->p, sw->p->filename); + + return 0; +} + + +static gint export_pdf_response_sig(GtkWidget *d, gint response, + SlideWindow *sw) +{ + if ( response == GTK_RESPONSE_ACCEPT ) { + + char *filename; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d)); + + if ( export_pdf(sw->p, filename) ) { + //show_error(sw, "Failed to export as PDF"); + } + + g_free(filename); + + } + + gtk_widget_destroy(d); + + return 0; +} + + +static gint export_pdf_sig(GtkWidget *widget, SlideWindow *sw) +{ + GtkWidget *d; + + d = gtk_file_chooser_dialog_new("Export PDF", + GTK_WINDOW(sw->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), sw); + + gtk_widget_show_all(d); + + return 0; +} + + +static gint about_sig(GtkWidget *widget, SlideWindow *sw) +{ + 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(sw->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), + "© 2014 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), + "© 2014 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, SlideWindow *sw) +{ + sw->p->slideshow = try_start_slideshow(sw->p); + return FALSE; +} + + +/* Change the editor's slide to "np" */ +void change_edit_slide(SlideWindow *sw, struct slide *np) +{ + sw->cur_slide = np; + + update_toolbar(sw); + + sc_editor_set_slide(sw->sceditor, np); + + notify_notes_slide_changed(sw->p, np); + + if ( slideshow_linked(sw->p->slideshow) ) { + change_proj_slide(sw->p->slideshow, np); + } /* else leave the slideshow alone */ +} + + +static gint add_slide_sig(GtkWidget *widget, SlideWindow *sw) +{ + struct slide *new; + int cur_slide_number; + + cur_slide_number = slide_number(sw->p, sw->cur_slide); + + new = add_slide(sw->p, cur_slide_number+1); + new->scblocks = sc_block_insert_after(sw->cur_slide->scblocks, + "slide", NULL, NULL); + + change_edit_slide(sw, new); + + return FALSE; +} + + +static gint first_slide_sig(GtkWidget *widget, SlideWindow *sw) +{ + change_edit_slide(sw, sw->p->slides[0]); + return FALSE; +} + + +static gint prev_slide_sig(GtkWidget *widget, SlideWindow *sw) +{ + int cur_slide_number; + + cur_slide_number = slide_number(sw->p, sw->cur_slide); + if ( cur_slide_number == 0 ) return FALSE; + + change_edit_slide(sw, sw->p->slides[cur_slide_number-1]); + + return FALSE; +} + + +static gint next_slide_sig(GtkWidget *widget, SlideWindow *sw) +{ + int cur_slide_number; + + cur_slide_number = slide_number(sw->p, sw->cur_slide); + if ( cur_slide_number == sw->p->num_slides-1 ) return FALSE; + + change_edit_slide(sw, sw->p->slides[cur_slide_number+1]); + + return FALSE; +} + + +static gint last_slide_sig(GtkWidget *widget, SlideWindow *sw) +{ + change_edit_slide(sw, sw->p->slides[sw->p->num_slides-1]); + + return FALSE; +} + + +static gint open_notes_sig(GtkWidget *widget, SlideWindow *sw) +{ + open_notes(sw->p); + return FALSE; +} + + +static gint open_clock_sig(GtkWidget *widget, SlideWindow *sw) +{ + open_clock(sw->p); + return FALSE; +} + + +static gint open_slidesorter_sig(GtkWidget *widget, SlideWindow *sw) +{ + open_slidesorter(sw->p); + return FALSE; +} + +static gint delete_frame_sig(GtkWidget *widget, SlideWindow *sw) +{ +#if 0 + int i; + + delete_subframe(sw->cur_slide, sw->p->selection); + p->n_selection = 0; + + rerender_slide(p); + redraw_editor(p); +#endif +/* FIXME: implement */ + return FALSE; +} + + +static void add_menu_bar(SlideWindow *sw, GtkWidget *vbox) +{ + GError *error = NULL; + GtkWidget *toolbar; + GtkWidget *menu; + GtkWidget *item; + + 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) }, +// { "LoadStyleAction", NULL, "_Load Stylesheet...", +// NULL, NULL, G_CALLBACK(loadstyle_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", NULL, "Save St_ylesheet", +// NULL, NULL, G_CALLBACK(save_ss_sig) }, + { "ExportPDFAction", NULL, "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 }, + { "SorterAction", NULL, "_Open Slide Sorter...", + NULL, NULL, G_CALLBACK(open_slidesorter_sig) }, + { "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 }, + { "DeleteFrameAction", GTK_STOCK_DELETE, "Delete Frame", + NULL, NULL, G_CALLBACK(delete_frame_sig) }, +// { "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", + "F8", NULL, G_CALLBACK(open_notes_sig) }, + { "ClockAction", NULL, "_Open presentation clock", + "F9", NULL, G_CALLBACK(open_clock_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); + + sw->action_group = gtk_action_group_new("mainwindow"); + gtk_action_group_add_actions(sw->action_group, entries, n_entries, sw); + + sw->ui = gtk_ui_manager_new(); + gtk_ui_manager_insert_action_group(sw->ui, sw->action_group, 0); + g_signal_connect(sw->ui, "add_widget", G_CALLBACK(add_ui_sig), vbox); + if ( gtk_ui_manager_add_ui_from_file(sw->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(sw->window), + gtk_ui_manager_get_accel_group(sw->ui)); + gtk_ui_manager_ensure_update(sw->ui); + + toolbar = gtk_ui_manager_get_widget(sw->ui, "/displaywindowtoolbar"); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), + gtk_separator_tool_item_new(), -1); + + menu = gtk_ui_manager_get_widget(sw->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); + + update_style_menus(sw); + update_toolbar(sw); +} + + +void update_titlebar(struct presentation *p) +{ + get_titlebar_string(p); + + if ( p->slidewindow != NULL ) { + + char *title; + + title = malloc(strlen(p->titlebar)+14); + sprintf(title, "%s - Colloquium", p->titlebar); + gtk_window_set_title(GTK_WINDOW(p->slidewindow->window), title); + free(title); + + } + +} + + +SlideWindow *slide_window_open(struct presentation *p, GApplication *app) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *scroll; + SlideWindow *sw; + + if ( p->slidewindow != NULL ) { + fprintf(stderr, "Slide window is already open!\n"); + return p->slidewindow; + } + + sw = calloc(1, sizeof(SlideWindow)); + if ( sw == NULL ) return NULL; + + window = gtk_application_window_new(GTK_APPLICATION(app)); + sw->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); + + sw->sceditor = sc_editor_new(p); + scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), + sc_editor_get_widget(sw->sceditor)); + + add_menu_bar(sw, vbox); + gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0); + + /* Default size */ + gtk_window_set_default_size(GTK_WINDOW(sw->window), 1024+100, 768+150); + gtk_window_set_resizable(GTK_WINDOW(sw->window), TRUE); + + gtk_widget_show_all(window); + + return sw; +} |