#include #include #include #include #include #include #include "scrollarea.h" #include "deck.h" #include "toolbar.h" typedef struct { GladeXML * xml; FooScrollArea * main_area; FooScrollArea * thumbnails; Deck * deck; int nth_slide; Toolbar * toolbar; } App; #define TOOLBAR_Y_OFFSET 12 #define TOOLBAR_X_OFFSET 12 static void * get_widget (App *app, const char *name) { void *result = glade_xml_get_widget (app->xml, name); if (!result) g_error ("Could not find widget %s\n", name); return result; } static void on_thumbs_paint (FooScrollArea *scroll_area, cairo_t *cr, GdkRectangle *extents, GdkRegion *region, gpointer data) { App *app = data; GdkRectangle viewport; foo_scroll_area_get_viewport (app->thumbnails, &viewport); deck_paint_thumbs (app->deck, cr, 0, 0); } static void on_thumbs_viewport_size_changed (FooScrollArea *scroll_area, GdkRectangle *viewport, GdkRectangle *old_viewport, gpointer data) { App *app = data; deck_set_thumb_width (app->deck, viewport->width); foo_scroll_area_set_size (scroll_area, viewport->width, deck_get_thumb_height (app->deck)); } static gboolean is_maximized (App *app) { GtkWidget *window = get_widget (app, "main_window"); return !!(gdk_window_get_state (window->window) & GDK_WINDOW_STATE_MAXIMIZED); } static void offset_toolbar (App *app, GdkRectangle *viewport) { if (!is_maximized (app)) { viewport->x += TOOLBAR_X_OFFSET; viewport->y += TOOLBAR_Y_OFFSET; } } static void paint_toolbar (App *app, FooScrollArea *area, cairo_t *cr) { GdkRectangle viewport; foo_scroll_area_get_viewport (app->main_area, &viewport); offset_toolbar (app, &viewport); toolbar_paint (app->toolbar, area, cr, viewport.x, viewport.y); } static void invalidate_toolbar (App *app, GdkRectangle *viewport) { offset_toolbar (app, viewport); toolbar_invalidate (app->toolbar, app->main_area, viewport->x, viewport->y); } static int get_toolbar_width (App *app) { if (is_maximized (app)) return toolbar_get_width (app->toolbar) + 12; else return toolbar_get_width (app->toolbar) + 6; } static void on_main_paint (FooScrollArea *scroll_area, cairo_t *cr, GdkRectangle *extents, GdkRegion *region, gpointer data) { App *app = data; GdkRectangle viewport; foo_scroll_area_get_viewport (scroll_area, &viewport); cairo_save (cr); deck_paint_main (app->deck, cr, get_toolbar_width (app), 0); cairo_restore (cr); paint_toolbar (app, scroll_area, cr); } static void on_main_viewport_size_changed (FooScrollArea *scroll_area, GdkRectangle *new_viewport, GdkRectangle *old_viewport, gpointer data) { App *app = data; int new_height; int toolbar_width = get_toolbar_width (app); int deck_width = new_viewport->width - toolbar_width; /* Ugh, fixme */ static int first = 1; if (first) { old_viewport = NULL; first = 0; } deck_set_main_width (app->deck, deck_width); new_height = deck_get_main_height (app->deck); if (old_viewport) { int nth_slide, old_location, new_location; nth_slide = app->nth_slide; deck_set_main_width (app->deck, old_viewport->width - toolbar_width); old_location = deck_get_main_slide_location (app->deck, nth_slide); deck_set_main_width (app->deck, deck_width); new_location = deck_get_main_slide_location (app->deck, nth_slide); foo_scroll_area_set_size_fixed_y (scroll_area, new_viewport->width, new_height, old_location, new_location); } else { deck_set_main_width (app->deck, deck_width); foo_scroll_area_set_size (scroll_area, new_viewport->width, new_height); foo_scroll_area_set_viewport_pos (scroll_area, 0, 0); } foo_scroll_area_invalidate (scroll_area); } static void make_thumbnail_viewable (App *app) { FooScrollArea *area = app->thumbnails; GdkRectangle viewport; int top, height; const int margin = 10; foo_scroll_area_get_viewport (area, &viewport); top = deck_get_thumb_slide_location (app->deck, app->nth_slide); height = deck_get_thumb_slide_height (app->deck); if (top - margin < viewport.y) viewport.y = top - margin; else if (top + height + margin > viewport.y + viewport.height) viewport.y = top + height - viewport.height - margin; foo_scroll_area_set_viewport_pos (area, viewport.x, viewport.y); } static void on_viewport_changed (FooScrollArea *scroll_area, GdkRectangle *viewport, GdkRectangle *old_viewport, gpointer data) { App *app = data; if (!foo_scroll_area_is_resizing (scroll_area)) { app->nth_slide = deck_get_view_slide (app->deck, viewport); make_thumbnail_viewable (app); } /* Invalidate toolbar */ invalidate_toolbar (app, old_viewport); invalidate_toolbar (app, viewport); } static void on_deck_changed (gpointer data) { App *app = data; } static void set_window_size (GtkWindow *window) { GdkScreen *screen; int monitor_num; GdkRectangle monitor; int width, height; GtkWidget *widget = GTK_WIDGET (window); screen = gtk_widget_get_screen (widget); monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window); gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); width = monitor.width * 3 / 4; height = monitor.height * 3 / 4; gtk_window_resize (window, width, height); } static void on_state_change (GtkWidget *widget, GdkEvent *event, App *app) { /* Apparently, on unmaximize we get size allocated before * the window has actually changed state, so we need to * invalidate here. */ foo_scroll_area_invalidate (app->main_area); } int main (int argc, char **argv) { App *app; gtk_init (&argc, &argv); app = g_new0 (App, 1); app->xml = glade_xml_new (GLADE_FILE, NULL, NULL); app->main_area = foo_scroll_area_new(); app->thumbnails = foo_scroll_area_new(); app->deck = deck_new (on_deck_changed, app); app->toolbar = toolbar_new (); gtk_container_add ( GTK_CONTAINER (get_widget (app, "main_area_scrolled_window")), GTK_WIDGET (app->main_area)); gtk_container_add ( GTK_CONTAINER (get_widget (app, "thumbnails_scrolled_window")), GTK_WIDGET (app->thumbnails)); foo_scroll_area_set_min_size (app->thumbnails, 200, -1); g_signal_connect (app->main_area, "paint", G_CALLBACK (on_main_paint), app); g_signal_connect (app->main_area, "viewport_size_changed", G_CALLBACK (on_main_viewport_size_changed), app); g_signal_connect (app->main_area, "viewport_changed", G_CALLBACK (on_viewport_changed), app); g_signal_connect (app->thumbnails, "paint", G_CALLBACK (on_thumbs_paint), app); g_signal_connect (app->thumbnails, "viewport_size_changed", G_CALLBACK (on_thumbs_viewport_size_changed), app); g_signal_connect (get_widget (app, "main_window"), "delete_event", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (get_widget (app, "main_window"), "window_state_event", G_CALLBACK (on_state_change), app); set_window_size (get_widget (app, "main_window")); gtk_widget_show_all (get_widget (app, "main_window")); gtk_widget_hide (get_widget (app, "toolbar1")); gtk_main (); return 0; }