/* * slide_window.c * * Copyright © 2013-2016 Thomas White * * 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 . * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "presentation.h" #include "slide_window.h" #include "render.h" #include "frame.h" #include "slideshow.h" #include "pr_clock.h" #include "sc_parse.h" #include "sc_interp.h" #include "sc_editor.h" struct _slidewindow { struct presentation *p; GtkWidget *window; GtkToolItem *bfirst; GtkToolItem *bprev; GtkToolItem *bnext; GtkToolItem *blast; /* The slide being displayed. Note that the SCEditor is using the * child of this block, but we need to keep a record of it for changing * the slide. */ SCBlock *scblocks; SCEditor *sceditor; struct menu_pl *style_menu; int n_style_menu; }; /* Inelegance to make furniture selection menus work */ struct menu_pl { SlideWindow *sw; char *style_name; GtkWidget *widget; }; static gint UNUSED add_furniture(GtkWidget *widget, struct menu_pl *pl) { sc_block_append_end(pl->sw->scblocks, strdup(pl->style_name), NULL, NULL); //do_slide_update(pl->p, pl->sw->pc); FIXME return 0; } static void UNUSED update_style_menus(SlideWindow *sw) { //GtkWidget *menu; SCInterpreter *scin; struct style_id *styles; int i, n_sty; /* Free old list */ for ( i=0; in_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, sw->p->lang, 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; #if 0 // FIXME /* 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; istyle_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); #endif } 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" */ void change_edit_slide(SlideWindow *sw, SCBlock *np) { SCBlock *ch; sc_editor_set_slidenum(sw->sceditor, slide_number(sw->p, np)); ch = sc_block_child(np); if ( ch == NULL ) { ch = sc_block_append_inside(sw->scblocks, NULL, NULL, ""); } sc_editor_set_scblock(sw->sceditor, ch); sw->scblocks = np; } static void change_slide_first(SlideWindow *sw) { change_edit_slide(sw, first_slide(sw->p)); } static void change_slide_backwards(SlideWindow *sw) { SCBlock *tt; tt = prev_slide(sw->p, sw->scblocks); if ( tt == NULL ) return; change_edit_slide(sw, tt); } static void change_slide_forwards(SlideWindow *sw) { SCBlock *tt; tt = next_slide(sw->p, sw->scblocks); if ( tt == NULL ) return; change_edit_slide(sw, tt); } static void change_slide_last(SlideWindow *sw) { change_edit_slide(sw, last_slide(sw->p)); } 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); } void slidewindow_redraw(SlideWindow *sw) { sc_editor_redraw(sw->sceditor); } 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); } } static gboolean close_sig(GtkWidget *w, SlideWindow *sw) { sw->p->slidewindow = NULL; return FALSE; } static gboolean 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; } GActionEntry sw_entries[] = { { "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 }, }; SlideWindow *slide_window_open(struct presentation *p, SCBlock *scblocks, GApplication *app) { GtkWidget *window; GtkWidget *scroll; SlideWindow *sw; SCBlock *stylesheets[2]; SCBlock *ch; 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); update_titlebar(p); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(close_sig), sw); stylesheets[0] = p->stylesheet; stylesheets[1] = NULL; sw->scblocks = scblocks; ch = sc_block_child(scblocks); if ( ch == NULL ) { ch = sc_block_append_inside(scblocks, NULL, NULL, ""); } sw->sceditor = sc_editor_new(ch, stylesheets, p->lang); sc_editor_set_slidenum(sw->sceditor, slide_number(sw->p, scblocks)); scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(sw->sceditor)); gtk_window_set_focus(GTK_WINDOW(window), GTK_WIDGET(sw->sceditor)); g_signal_connect(G_OBJECT(sw->sceditor), "key-press-event", G_CALLBACK(key_press_sig), sw); /* Size of SCEditor surface in pixels */ /* FIXME: Somewhat arbitrary. Should come from slide itself */ sc_editor_set_size(sw->sceditor, 1024, 768); sc_editor_set_logical_size(sw->sceditor, 1024.0, 768.0); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(scroll)); /* Default size */ gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(scroll), 1024); gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll), 768); gtk_window_set_resizable(GTK_WINDOW(sw->window), TRUE); gtk_widget_show_all(window); gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(scroll), 100); gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll), 100); return sw; }