示例#1
0
static void refreshPorts(void)
{
	struct viewport *pp = NULL;
	GList *it = ports;

	/* display. */
	while (it)
	{
		pp = (struct viewport *)(it->data);
		updatePortPixbuf(pp);
		it = g_list_next(it);
	}

	refreshFrames();

	/* queue prerendering of next slides unless this has already been
	 * done.
	 *
	 * note: usually, it's not safe to use booleans for purposes like
	 * this. however, we're in a singlethreaded program, so no other
	 * thread can do concurrent modifications to this variable. hence
	 * it's okay. */
	if (!preQueued)
	{
		preQueued = TRUE;
		g_idle_add(idleFillCaches, NULL);
	}
}
示例#2
0
文件: pdfpres.c 项目: dwol/pdfPres
static void refreshPorts(void)
{
	struct viewport *pp = NULL;
	GList *it = ports;

	/* Queue a draw signal for all ports. */
	while (it)
	{
		pp = (struct viewport *)(it->data);
		gtk_widget_queue_draw(pp->canvas);
		it = g_list_next(it);
	}

	refreshFrames();
}
示例#3
0
static void initGUI(int numframes, gchar *notefile)
{
	int i = 0, transIndex = 0;
	GtkWidget *timeBox = NULL,
			  *notePadBox = NULL,
			  *notePadScroll = NULL,
			  *table = NULL;
	GtkWidget *image = NULL,
			  *frame = NULL,
			  *evbox = NULL,
			  *outerevbox = NULL,
			  *timeFrame = NULL;
	GtkWidget *mainVBox = NULL;
	GdkColor black;

	GtkWidget *toolbar = NULL, *timeToolbar = NULL;
	GtkToolItem *openButton = NULL,
				*saveAsButton = NULL,
				*fontSelectButton = NULL,
				*timeFontSelectButton = NULL;

	PangoFontDescription *font_desc = NULL;

	struct viewport *thisport = NULL;

	/* init colors */
	if (gdk_color_parse("#000000", &black) != TRUE)
		fprintf(stderr, "Could not resolve color \"black\".\n");
	if (gdk_color_parse("#BBFFBB", &col_current) != TRUE)
		fprintf(stderr, "Could not resolve color \"col_current\".\n");
	if (gdk_color_parse("#FFBBBB", &col_marked) != TRUE)
		fprintf(stderr, "Could not resolve color \"col_marked\".\n");
	if (gdk_color_parse("#BBBBBB", &col_dim) != TRUE)
		fprintf(stderr, "Could not resolve color \"col_dim\".\n");


	/* init our two windows */
	win_preview = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	win_beamer  = gtk_window_new(GTK_WINDOW_TOPLEVEL);

	gtk_window_set_title(GTK_WINDOW(win_preview), "pdfpres - Preview");
	gtk_window_set_title(GTK_WINDOW(win_beamer),  "pdfpres - Beamer");

	g_signal_connect(G_OBJECT(win_preview), "delete_event",
			G_CALLBACK(onQuit), NULL);
	g_signal_connect(G_OBJECT(win_preview), "destroy",
			G_CALLBACK(onQuit), NULL);
	g_signal_connect(G_OBJECT(win_beamer), "delete_event",
			G_CALLBACK(onQuit), NULL);
	g_signal_connect(G_OBJECT(win_beamer), "destroy",
			G_CALLBACK(onQuit), NULL);

	g_signal_connect(G_OBJECT(win_preview), "key_press_event",
			G_CALLBACK(onKeyPressed), NULL);
	g_signal_connect(G_OBJECT(win_beamer), "key_press_event",
			G_CALLBACK(onKeyPressed), NULL);

	gtk_widget_add_events(win_beamer, GDK_BUTTON_RELEASE_MASK
					| GDK_SCROLL_MASK);
	g_signal_connect(G_OBJECT(win_beamer), "button_release_event",
			G_CALLBACK(onMouseReleased), NULL);
	g_signal_connect(G_OBJECT(win_beamer), "scroll_event",
			G_CALLBACK(onScroll), NULL);

	gtk_widget_add_events(win_preview, GDK_BUTTON_RELEASE_MASK
					 | GDK_SCROLL_MASK);
	g_signal_connect(G_OBJECT(win_preview), "button_release_event",
			G_CALLBACK(onMouseReleased), NULL);
	g_signal_connect(G_OBJECT(win_preview), "scroll_event",
			G_CALLBACK(onScroll), NULL);

	gtk_container_set_border_width(GTK_CONTAINER(win_preview), 0);
	gtk_container_set_border_width(GTK_CONTAINER(win_beamer), 0);

	gtk_widget_modify_bg(win_beamer, GTK_STATE_NORMAL, &black);

	/* create buttons */
	timeToolbar = gtk_toolbar_new();
	gtk_toolbar_set_style(GTK_TOOLBAR(timeToolbar), GTK_TOOLBAR_ICONS);
	gtk_container_set_border_width(GTK_CONTAINER(timeToolbar), 5);

	if (!prefs.timer_is_clock)
	{
		startButton = gtk_tool_button_new_from_stock(
				GTK_STOCK_MEDIA_PLAY);
		g_signal_connect(G_OBJECT(startButton), "clicked",
				G_CALLBACK(toggleTimer), NULL);
		gtk_toolbar_insert(GTK_TOOLBAR(timeToolbar), startButton, -1);

		resetButton = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_REWIND);
		g_signal_connect(G_OBJECT(resetButton), "clicked",
				G_CALLBACK(resetTimer), NULL);
		gtk_toolbar_insert(GTK_TOOLBAR(timeToolbar), resetButton, -1);

		gtk_toolbar_insert(GTK_TOOLBAR(timeToolbar),
				gtk_separator_tool_item_new(), -1);
	}

	timeFontSelectButton =
		gtk_tool_button_new_from_stock(GTK_STOCK_SELECT_FONT);
	gtk_toolbar_insert(GTK_TOOLBAR(timeToolbar),
			timeFontSelectButton, -1);
	g_signal_connect(G_OBJECT(timeFontSelectButton), "clicked",
			G_CALLBACK(onTimerFontSelectClick), NULL);

	/* setting text size for time label */
	timeElapsedLabel = gtk_label_new(NULL);
	font_desc = pango_font_description_from_string(prefs.font_timer);
	gtk_widget_modify_font(GTK_WIDGET(timeElapsedLabel), font_desc);
	pango_font_description_free(font_desc);
	if (prefs.timer_is_clock)
	{
		printCurrentTime(timeElapsedLabel);
	}
	else
	{
		gtk_label_set_text(GTK_LABEL(timeElapsedLabel), "00:00");
	}

	/* Add timer label to another event box so we can set a nice border.
	 */
	evbox = gtk_event_box_new();
	gtk_container_add(GTK_CONTAINER(evbox), timeElapsedLabel);
	gtk_container_set_border_width(GTK_CONTAINER(evbox), 10);

	/* create timer */
	timeBox = gtk_vbox_new(FALSE, 5);
	gtk_box_pack_start(GTK_BOX(timeBox), evbox,
			TRUE, TRUE, 5);
	gtk_box_pack_start(GTK_BOX(timeBox), timeToolbar,
			FALSE, FALSE, 5);

	if (prefs.timer_is_clock)
	{
		timeFrame = gtk_frame_new("Clock");
	}
	else
	{
		timeFrame = gtk_frame_new("Timer");
	}
	gtk_container_add(GTK_CONTAINER(timeFrame), timeBox);

	/* create note pad inside a scrolled window */
	notePadBox = gtk_vbox_new(FALSE, 2);
	notePadScroll = gtk_scrolled_window_new(NULL, NULL);
	gtk_container_set_border_width(GTK_CONTAINER(notePadScroll), 5);
	notePadFrame = gtk_frame_new("Notes for current slide");
	notePad = gtk_text_view_new();
	gtk_text_view_set_editable(GTK_TEXT_VIEW(notePad), FALSE);
	gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(notePad), FALSE);
	g_signal_connect(G_OBJECT(notePad), "key_press_event",
			G_CALLBACK(onPadKeyPressed), NULL);

	/* Remarks:
	 *
	 * - The note pad uses word wrapping. If that's not enough, it also
	 *   uses wrapping on a per character basis.
	 * - The note pad is placed into a GtkScrolledWindow. This window
	 *   allows vertical scrolling but no horizontal scrolling.
	 */
	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(notePad),
			GTK_WRAP_WORD_CHAR);
	gtk_container_add(GTK_CONTAINER(notePadScroll), notePad);
	gtk_scrolled_window_set_shadow_type(
			GTK_SCROLLED_WINDOW(notePadScroll), GTK_SHADOW_IN);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(notePadScroll),
			GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
	gtk_box_pack_start(GTK_BOX(notePadBox), notePadScroll, TRUE,
			TRUE, 2);

	/* set note pad font and margin */
	font_desc = pango_font_description_from_string(prefs.font_notes);
	gtk_widget_modify_font(notePad, font_desc);
	pango_font_description_free(font_desc);

	gtk_text_view_set_left_margin(GTK_TEXT_VIEW(notePad), 5);
	gtk_text_view_set_right_margin(GTK_TEXT_VIEW(notePad), 5);

	noteBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(notePad));

	/* We detect changes of the notes by catching the "changed" signal.
	 * As this signal is also emitted when we change the buffer
	 * programmatically, we first have a look if there was a
	 * "begin_user_action" signal. If so, the user has changed the
	 * buffer.
	 */
	g_signal_connect(G_OBJECT(noteBuffer), "changed",
			G_CALLBACK(onEditing), NULL);
	g_signal_connect(G_OBJECT(noteBuffer), "begin_user_action",
			G_CALLBACK(onBeginUserAction), NULL);
	g_signal_connect(G_OBJECT(noteBuffer), "end_user_action",
			G_CALLBACK(onEndUserAction), NULL);

	/* create toolbar */
	toolbar = gtk_toolbar_new();
	gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
	gtk_container_set_border_width(GTK_CONTAINER(toolbar), 5);

	openButton = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), openButton, -1);
	g_signal_connect(G_OBJECT(openButton), "clicked",
			G_CALLBACK(onOpenClicked), NULL);

	/* TODO: Tooltips?! */
	saveButton = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), saveButton, -1);
	gtk_widget_set_sensitive(GTK_WIDGET(saveButton), FALSE);
	g_signal_connect(G_OBJECT(saveButton), "clicked",
			G_CALLBACK(onSaveClicked), NULL);

	saveAsButton = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE_AS);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), saveAsButton, -1);
	g_signal_connect(G_OBJECT(saveAsButton), "clicked",
			G_CALLBACK(onSaveAsClicked), NULL);

	gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
			gtk_separator_tool_item_new(), -1);

	editButton = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_EDIT);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), editButton, -1);
	g_signal_connect(G_OBJECT(editButton), "toggled",
			G_CALLBACK(onEditToggled), NULL);

	fontSelectButton =
		gtk_tool_button_new_from_stock(GTK_STOCK_SELECT_FONT);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), fontSelectButton, -1);
	g_signal_connect(G_OBJECT(fontSelectButton), "clicked",
			G_CALLBACK(onFontSelectClick), NULL);

	gtk_box_pack_start(GTK_BOX(notePadBox), toolbar, FALSE, FALSE, 2);
	gtk_container_add(GTK_CONTAINER(notePadFrame), notePadBox);

	/* init containers for "preview" */
	table = gtk_table_new(numframes, numframes + 1, TRUE);
	gtk_table_set_col_spacings(GTK_TABLE(table), 5);
	gtk_container_set_border_width(GTK_CONTAINER(table), 10);

	/* dynamically create all the frames */
	for (i = 0; i < numframes; i++)
	{
		/* calc the offset for this frame */
		transIndex = i - (int)((double)numframes / 2.0);

		/* create the widget - note that it is important not to
		 * set the title to NULL. this would cause a lot more
		 * redraws on startup because the frame will get re-
		 * allocated when the title changes. */
		frame = gtk_frame_new("");

		/* create a new drawing area - the pdf will be rendered in
		 * there */
		image = gtk_image_new();

		/* add widgets to their parents. the image is placed in an
		 * eventbox, the box's size_allocate signal will be handled. so,
		 * we know the exact width/height we can render into. (placing
		 * the image into the frame would create the need of knowing the
		 * frame's border size...)
		 */
		evbox = gtk_event_box_new();
		gtk_container_add(GTK_CONTAINER(evbox), image);
		gtk_container_add(GTK_CONTAINER(frame), evbox);

		/* every frame will be placed in another eventbox so we can set a
		 * background color */
		outerevbox = gtk_event_box_new();
		gtk_container_add(GTK_CONTAINER(outerevbox), frame);

		if (i == 0)
		{
			gtk_table_attach_defaults(GTK_TABLE(table), notePadFrame,
					0, 1, 0, numframes - 1);
			gtk_table_attach_defaults(GTK_TABLE(table), outerevbox,
					0, 1, numframes - 1, numframes);
		}
		else
		{
			if (i == numframes - 1)
			{
				gtk_table_attach_defaults(GTK_TABLE(table), outerevbox,
						numframes, numframes + 1,
						0, 1);
				gtk_table_attach_defaults(GTK_TABLE(table), timeFrame,
						numframes, numframes + 1,
						numframes - 1, numframes);
			}
			else
			{
				if (i == (int)(numframes / 2))
				{
					gtk_table_attach_defaults(GTK_TABLE(table),
							outerevbox, i, i + 2, 0, numframes);
				}
				else
				{
					if (i < (int)(numframes / 2))
					{
						gtk_table_attach_defaults(GTK_TABLE(table),
								outerevbox, i, i + 1,
								numframes - i - 1, numframes - i);
					}
					else
					{
						gtk_table_attach_defaults(GTK_TABLE(table),
								outerevbox, i + 1, i + 2,
								numframes - i - 1, numframes - i);
					}
				}
			}
		}

		/* make the eventbox "transparent" */
		gtk_event_box_set_visible_window(GTK_EVENT_BOX(evbox), FALSE);

		/* save info of this rendering port */
		thisport = (struct viewport *)malloc(sizeof(struct viewport));
		g_assert(thisport);
		thisport->offset = transIndex;
		thisport->image = image;
		thisport->frame = frame;
		thisport->pixbuf = NULL;
		thisport->width = -1;
		thisport->height = -1;
		thisport->isBeamer = FALSE;
		ports = g_list_append(ports, thisport);

		/* resize callback */
		g_signal_connect(G_OBJECT(evbox), "size_allocate",
				G_CALLBACK(onResize), thisport);
		g_signal_connect(G_OBJECT(evbox), "expose_event",
				G_CALLBACK(onExpose), thisport);
	}

	/* Add main content and a status bar to preview window.
	 *
	 * Note: It's important to use gtk_box_pack_* to add the statusbar
	 * because gtk_container_add will pick unappropriate defaults. */
	mainVBox = gtk_vbox_new(FALSE, 5);
	gtk_container_add(GTK_CONTAINER(mainVBox), table);

	mainStatusbar = gtk_statusbar_new();
	gtk_box_pack_end(GTK_BOX(mainVBox), mainStatusbar,
			FALSE, FALSE, 0);

	setStatusText_strdup("Ready.");

	gtk_container_add(GTK_CONTAINER(win_preview), mainVBox);

	/* in order to set the initially highlighted frame */
	refreshFrames();

	/* add a rendering area to the beamer window */
	image = gtk_image_new();

	gtk_container_add(GTK_CONTAINER(win_beamer), image);

	/* save info of this rendering port */
	thisport = (struct viewport *)malloc(sizeof(struct viewport));
	g_assert(thisport);
	thisport->offset = 0;
	thisport->image = image;
	thisport->frame = NULL;
	thisport->pixbuf = NULL;
	thisport->width = -1;
	thisport->height = -1;
	thisport->isBeamer = TRUE;
	ports = g_list_append(ports, thisport);

	/* connect the on-resize-callback directly to the window */
	g_signal_connect(G_OBJECT(win_beamer), "size_allocate",
			G_CALLBACK(onResize), thisport);
	g_signal_connect(G_OBJECT(win_beamer), "expose_event",
			G_CALLBACK(onExpose), thisport);

	/* load notes if requested */
	if (notefile)
	{
		showNotesFromFile(notefile);
	}

	/* Set default sizes for both windows. (Note: If the widgets don't
	 * fit into that space, the windows will be larger. Also, they are
	 * allowed to get shrinked by the user.) */
	gtk_window_set_default_size(GTK_WINDOW(win_preview), 640, 480);
	gtk_window_set_default_size(GTK_WINDOW(win_beamer), 320, 240);

	/* show the windows */
	gtk_widget_show_all(win_preview);
	gtk_widget_show_all(win_beamer);

	/* now, as the real gdk window exists, hide mouse cursor in the
	 * beamer window */
	gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(win_beamer)),
			gdk_cursor_new(GDK_BLANK_CURSOR));

	/* Show a clock or a timer? */
	if (prefs.timer_is_clock)
	{
		g_timeout_add(500, (GSourceFunc)printCurrentTime,
				(gpointer)timeElapsedLabel);
	}
	else
	{
		g_timeout_add(500, (GSourceFunc)printTimeElapsed,
				(gpointer)timeElapsedLabel);
	}
}