[recipes/lightbox: 2/2] Add a fullscreen image viewing mode



commit dee2ce378df0e27d524fb55577a49e5204fb2d42
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Jan 24 18:14:43 2017 +0300

    Add a fullscreen image viewing mode

 src/Makefile.am              |    2 +
 src/gr-image-page.c          |  337 ++++++++++++++++++++++++++++++++++++++++++
 src/gr-image-page.h          |   39 +++++
 src/gr-image-page.ui         |  117 +++++++++++++++
 src/gr-image-viewer.c        |   26 +++-
 src/gr-window.c              |   30 ++++
 src/gr-window.h              |    4 +
 src/gr-window.ui             |    6 +
 src/main.c                   |    2 +
 src/recipes-ui.gresource.xml |    1 +
 src/recipes.css              |    8 +
 11 files changed, 568 insertions(+), 4 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 2867298..60e7a36 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -58,6 +58,8 @@ recipes_SOURCES = \
        gr-images.c             \
        gr-image-viewer.h       \
        gr-image-viewer.c       \
+       gr-image-page.h         \
+       gr-image-page.c         \
        gr-ingredient.h         \
        gr-ingredient.c         \
        gr-ingredient-row.h     \
diff --git a/src/gr-image-page.c b/src/gr-image-page.c
new file mode 100644
index 0000000..4fc3515
--- /dev/null
+++ b/src/gr-image-page.c
@@ -0,0 +1,337 @@
+/* gr-image-page.c:
+ *
+ * Copyright (C) 2017 Matthias Clasen <mclasen redhat com>
+ *
+ * Licensed under the GNU General Public License Version 3.
+ *
+ * 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/>.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "gr-image-page.h"
+#include "gr-images.h"
+#include "gr-utils.h"
+#include "gr-window.h"
+
+
+struct _GrImagePage
+{
+        GtkBox parent_instance;
+
+        GtkWidget *image;
+        GtkWidget *event_box;
+        GtkWidget *next_revealer;
+        GtkWidget *prev_revealer;
+        GtkWidget *close_revealer;
+
+        GArray *images;
+        int index;
+
+        guint hide_timeout;
+};
+
+
+G_DEFINE_TYPE (GrImagePage, gr_image_page, GTK_TYPE_BOX)
+
+enum {
+        PROP_0,
+        PROP_IMAGES,
+        N_PROPS
+};
+
+
+GrImagePage *
+gr_image_page_new (void)
+{
+        return g_object_new (GR_TYPE_IMAGE_PAGE, NULL);
+}
+
+static void
+remove_hide_timeout (GrImagePage *page)
+{
+       if (page->hide_timeout != 0) {
+                g_source_remove (page->hide_timeout);
+                page->hide_timeout = 0;
+       }
+}
+
+static void
+gr_image_page_finalize (GObject *object)
+{
+        GrImagePage *page = GR_IMAGE_PAGE (object);
+
+        remove_hide_timeout (page);
+        g_clear_pointer (&page->images, g_array_unref);
+
+        G_OBJECT_CLASS (gr_image_page_parent_class)->finalize (object);
+}
+
+static void
+set_current_image (GrImagePage *page)
+{
+        if (page->images->len > page->index) {
+                GrRotatedImage *ri = NULL;
+                g_autoptr(GdkPixbuf) pixbuf = NULL;
+                GdkDisplay *display;
+                GdkWindow *win;
+                GdkMonitor *monitor;
+                GdkRectangle geom;
+
+                display = gtk_widget_get_display (GTK_WIDGET (page));
+                win = gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (page)));
+                monitor = gdk_display_get_monitor_at_window (display, win);
+                gdk_monitor_get_geometry (monitor, &geom);
+
+                ri = &g_array_index (page->images, GrRotatedImage, page->index);
+                pixbuf = load_pixbuf_fit_size (ri->path, ri->angle, geom.width - 80, geom.height - 80, 
FALSE);
+                gtk_image_set_from_pixbuf (GTK_IMAGE (page->image), pixbuf);
+        }
+}
+
+static void
+stop_viewing (GrImagePage *page)
+{
+        GtkWidget *window;
+
+        window = gtk_widget_get_ancestor (GTK_WIDGET (page), GTK_TYPE_APPLICATION_WINDOW);
+        gr_window_show_image (GR_WINDOW (window), NULL, -1);
+}
+
+static void
+prev_image (GrImagePage *page)
+{
+        page->index = (page->index + page->images->len - 1) % page->images->len;
+        set_current_image (page);
+}
+
+static void
+next_image (GrImagePage *page)
+{
+        page->index = (page->index + 1) % page->images->len;
+        set_current_image (page);
+}
+
+static void
+show_buttons (GrImagePage *page)
+{
+        if (!gtk_revealer_get_child_revealed (GTK_REVEALER (page->close_revealer)))
+                gtk_revealer_set_reveal_child (GTK_REVEALER (page->close_revealer), TRUE);
+
+        if (!page->images || page->images->len < 2)
+                return;
+
+        if (!gtk_revealer_get_child_revealed (GTK_REVEALER (page->next_revealer)))
+                gtk_revealer_set_reveal_child (GTK_REVEALER (page->next_revealer), TRUE);
+
+        if (!gtk_revealer_get_child_revealed (GTK_REVEALER (page->prev_revealer)))
+                        gtk_revealer_set_reveal_child (GTK_REVEALER (page->prev_revealer), TRUE);
+}
+
+static void
+hide_buttons (GrImagePage *page)
+{
+        if (gtk_revealer_get_child_revealed (GTK_REVEALER (page->close_revealer)))
+                gtk_revealer_set_reveal_child (GTK_REVEALER (page->close_revealer), FALSE);
+
+        if (gtk_revealer_get_child_revealed (GTK_REVEALER (page->next_revealer)))
+                gtk_revealer_set_reveal_child (GTK_REVEALER (page->next_revealer), FALSE);
+
+        if (gtk_revealer_get_child_revealed (GTK_REVEALER (page->prev_revealer)))
+                        gtk_revealer_set_reveal_child (GTK_REVEALER (page->prev_revealer), FALSE);
+}
+
+static gboolean
+hide_timeout (gpointer data)
+{
+        GrImagePage *page = data;
+
+        hide_buttons (page);
+
+        page->hide_timeout = 0;
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+reset_hide_timeout (GrImagePage *page)
+{
+        remove_hide_timeout (page);
+        page->hide_timeout = g_timeout_add (5000, hide_timeout, page);
+}
+
+static gboolean
+motion_notify (GtkWidget   *widget,
+               GdkEvent    *event,
+               GrImagePage *page)
+{
+        show_buttons (page);
+        reset_hide_timeout (page);
+
+        return FALSE;
+}
+
+static gboolean
+key_press_event (GtkWidget     *widget,
+                 GdkEvent      *event,
+                 GrImagePage   *page)
+{
+        GdkEventKey *key = (GdkEventKey *)event;
+
+        if (key->keyval == GDK_KEY_space) {
+                show_buttons (page);
+                return TRUE;
+        }
+        if (key->keyval == GDK_KEY_Escape) {
+                stop_viewing (page);
+                return TRUE;
+        }
+        else if (key->keyval == GDK_KEY_Left) {
+                prev_image (page);
+                return TRUE;
+        }
+        else if (key->keyval == GDK_KEY_Right) {
+                next_image (page);
+                return TRUE;
+        }
+
+        return FALSE;
+}
+
+static void
+gr_image_page_init (GrImagePage *self)
+{
+        gtk_widget_init_template (GTK_WIDGET (self));
+
+        gtk_widget_add_events (GTK_WIDGET (self->event_box), GDK_POINTER_MOTION_MASK);
+        gtk_widget_add_events (GTK_WIDGET (self->event_box), GDK_BUTTON_PRESS_MASK);
+g_signal_connect (self->event_box, "motion-notify-event", G_CALLBACK (motion_notify), self);
+        g_signal_connect (self->event_box, "key-press-event", G_CALLBACK (key_press_event), self);
+
+        self->images = gr_rotated_image_array_new ();
+}
+
+static void
+gr_image_page_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+        GrImagePage *self = GR_IMAGE_PAGE (object);
+
+        switch (prop_id)
+          {
+          case PROP_IMAGES:
+                  g_value_set_boxed (value, self->images);
+                  break;
+
+          default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+          }
+}
+
+static void
+gr_image_page_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+        GrImagePage *self = GR_IMAGE_PAGE (object);
+
+        switch (prop_id)
+          {
+          case PROP_IMAGES:
+                  gr_image_page_set_images (self, (GArray *) g_value_get_boxed (value));
+                  break;
+
+          default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+          }
+}
+
+static void
+gr_image_page_class_init (GrImagePageClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+        GParamSpec *pspec;
+
+        object_class->finalize = gr_image_page_finalize;
+        object_class->get_property = gr_image_page_get_property;
+        object_class->set_property = gr_image_page_set_property;
+
+        pspec = g_param_spec_boxed ("images", NULL, NULL,
+                                    G_TYPE_ARRAY,
+                                    G_PARAM_READWRITE);
+        g_object_class_install_property (object_class, PROP_IMAGES, pspec);
+
+        gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Recipes/gr-image-page.ui");
+        gtk_widget_class_bind_template_child (widget_class, GrImagePage, image);
+        gtk_widget_class_bind_template_child (widget_class, GrImagePage, event_box);
+        gtk_widget_class_bind_template_child (widget_class, GrImagePage, prev_revealer);
+        gtk_widget_class_bind_template_child (widget_class, GrImagePage, next_revealer);
+        gtk_widget_class_bind_template_child (widget_class, GrImagePage, close_revealer);
+
+        gtk_widget_class_bind_template_callback (widget_class, stop_viewing);
+        gtk_widget_class_bind_template_callback (widget_class, prev_image);
+        gtk_widget_class_bind_template_callback (widget_class, next_image);
+}
+
+static void
+add_image (GrImagePage    *page,
+           GrRotatedImage *ri,
+           gboolean        select)
+{
+        g_array_append_vals (page->images, ri, 1);
+        ri = &g_array_index (page->images, GrRotatedImage, page->images->len - 1);
+        ri->path = g_strdup (ri->path);
+
+        if (select)
+                page->index = page->images->len - 1;
+        set_current_image (page);
+
+        g_object_notify (G_OBJECT (page), "images");
+}
+
+void
+gr_image_page_set_images (GrImagePage *page,
+                          GArray      *images)
+{
+        int i;
+
+        g_object_freeze_notify (G_OBJECT (page));
+
+        g_array_remove_range (page->images, 0, page->images->len);
+        g_object_notify (G_OBJECT (page), "images");
+
+        for (i = 0; i < images->len; i++) {
+                GrRotatedImage *ri = &g_array_index (images, GrRotatedImage, i);
+                add_image (page, ri, FALSE);
+        }
+
+        page->index = 0;
+        set_current_image (page);
+
+        g_object_thaw_notify (G_OBJECT (page));
+}
+
+void
+gr_image_page_show_image (GrImagePage *page,
+                          int          idx)
+{
+        page->index = idx % page->images->len;
+        set_current_image (page);
+}
diff --git a/src/gr-image-page.h b/src/gr-image-page.h
new file mode 100644
index 0000000..111e454
--- /dev/null
+++ b/src/gr-image-page.h
@@ -0,0 +1,39 @@
+/* gr-image-page.h
+ *
+ * Copyright (C) 2017 Matthias Clasen <mclasen redhat com>
+ *
+ * Licensed under the GNU General Public License Version 3.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GR_TYPE_IMAGE_PAGE (gr_image_page_get_type())
+
+G_DECLARE_FINAL_TYPE (GrImagePage, gr_image_page, GR, IMAGE_PAGE, GtkBox)
+
+GrImagePage *gr_image_page_new        (void);
+void         gr_image_page_set_images (GrImagePage *page,
+                                       GArray      *images);
+
+void         gr_image_page_show_image (GrImagePage *page,
+                                       int          idx);
+
+G_END_DECLS
+
diff --git a/src/gr-image-page.ui b/src/gr-image-page.ui
new file mode 100644
index 0000000..82c2c11
--- /dev/null
+++ b/src/gr-image-page.ui
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="recipes">
+  <!-- interface-requires gtk+ 3.8 -->
+  <template class="GrImagePage" parent="GtkBox">
+    <property name="visible">True</property>
+    <property name="orientation">horizontal</property>
+    <style>
+      <class name="image-page"/>
+    </style>
+    <child>
+      <object class="GtkOverlay">
+        <property name="visible">1</property>
+        <child type="overlay">
+          <object class="GtkRevealer" id="prev_revealer">
+            <property name="visible">1</property>
+            <property name="halign">start</property>
+            <property name="valign">center</property>
+            <property name="transition-type">crossfade</property>
+            <style>
+              <class name="osd"/>
+            </style>
+            <child>
+              <object class="GtkButton">
+                <property name="visible">1</property>
+                <signal name="clicked" handler="prev_image" swapped="yes"/>
+                <style>
+                  <class name="image-button"/>
+                  <class name="osd"/>
+                </style>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">1</property>
+                    <property name="icon-name">pan-start-symbolic</property>
+                    <property name="pixel-size">32</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child type="overlay">
+          <object class="GtkRevealer" id="close_revealer">
+            <property name="visible">1</property>
+            <property name="halign">end</property>
+            <property name="valign">start</property>
+            <property name="transition-type">crossfade</property>
+            <child>
+              <object class="GtkButton">
+                <property name="visible">1</property>
+                <signal name="clicked" handler="stop_viewing" swapped="yes"/>
+                <style>
+                  <class name="image-button"/>
+                  <class name="osd"/>
+                </style>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">1</property>
+                    <property name="icon-name">window-close-symbolic</property>
+                    <property name="pixel-size">32</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child type="overlay">
+          <object class="GtkRevealer" id="next_revealer">
+            <property name="visible">1</property>
+            <property name="halign">end</property>
+            <property name="valign">center</property>
+            <property name="transition-type">crossfade</property>
+            <child>
+              <object class="GtkButton">
+                <property name="visible">1</property>
+                <signal name="clicked" handler="next_image" swapped="yes"/>
+                <style>
+                  <class name="image-button"/>
+                  <class name="osd"/>
+                </style>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">1</property>
+                    <property name="icon-name">pan-end-symbolic</property>
+                    <property name="pixel-size">32</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">1</property>
+            <child>
+              <object class="GtkEventBox" id="event_box">
+                <property name="visible">1</property>
+                <property name="above-child">1</property>
+                <property name="can-focus">1</property>
+                <child>
+                  <object class="GtkImage" id="image">
+                    <property name="visible">1</property>
+                    <property name="halign">center</property>
+                    <property name="valign">center</property>
+                    <property name="expand">1</property>
+                    <style>
+                      <class name="content"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/gr-image-viewer.c b/src/gr-image-viewer.c
index 6eaa4ae..6708123 100644
--- a/src/gr-image-viewer.c
+++ b/src/gr-image-viewer.c
@@ -25,6 +25,7 @@
 #include "gr-image-viewer.h"
 #include "gr-images.h"
 #include "gr-utils.h"
+#include "gr-window.h"
 
 
 struct _GrImageViewer
@@ -252,10 +253,26 @@ motion_notify (GtkWidget     *widget,
 }
 
 static void
-button_press (GrImageViewer *viewer)
+button_press (GtkGesture *gesture,
+              int         n_press,
+              double      x,
+              double      y,
+              GrImageViewer *viewer)
 {
-        toggle_preview (viewer);
-        gtk_widget_grab_focus (viewer->event_box);
+        int button;
+
+        button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+
+        if (button == GDK_BUTTON_PRIMARY) {
+                GtkWidget *window;
+
+                window = gtk_widget_get_ancestor (GTK_WIDGET (viewer), GTK_TYPE_APPLICATION_WINDOW);
+                gr_window_show_image (GR_WINDOW (window), viewer->images, viewer->index);
+        }
+        else {
+                toggle_preview (viewer);
+                gtk_widget_grab_focus (viewer->event_box);
+        }
 }
 
 static void
@@ -330,8 +347,9 @@ gr_image_viewer_init (GrImageViewer *self)
         g_signal_connect (self->event_box, "key-press-event", G_CALLBACK (key_press_event), self);
 
         self->gesture = gtk_gesture_multi_press_new (self->event_box);
+        gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (self->gesture), 0);
         gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (self->gesture), GTK_PHASE_BUBBLE);
-        g_signal_connect_swapped (self->gesture, "pressed", G_CALLBACK (button_press), self);
+        g_signal_connect (self->gesture, "pressed", G_CALLBACK (button_press), self);
         self->images = gr_rotated_image_array_new ();
 }
 
diff --git a/src/gr-window.c b/src/gr-window.c
index 38cc95d..0dc267f 100644
--- a/src/gr-window.c
+++ b/src/gr-window.c
@@ -33,6 +33,7 @@
 #include "gr-shopping-page.h"
 #include "gr-recipes-page.h"
 #include "gr-cuisines-page.h"
+#include "gr-image-page.h"
 #include "gr-query-editor.h"
 #include "gr-recipe-importer.h"
 
@@ -58,6 +59,7 @@ struct _GrWindow
         GtkWidget *search_page;
         GtkWidget *cuisines_page;
         GtkWidget *cuisine_page;
+        GtkWidget *image_page;
         GtkWidget *undo_revealer;
         GtkWidget *undo_label;
         GrRecipe  *undo_recipe;
@@ -125,6 +127,8 @@ go_back (GrWindow *window)
 
         entry = g_queue_pop_head (window->back_entry_stack);
 
+        gr_window_set_fullscreen (window, FALSE);
+
         gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (window->search_bar), FALSE);
 
         gtk_header_bar_set_title (GTK_HEADER_BAR (window->header), entry->header_title);
@@ -311,6 +315,14 @@ window_keypress_handler (GtkWidget *widget,
 
         visible = gtk_stack_get_visible_child_name (GTK_STACK (window->main_stack));
 
+        if (strcmp (visible, "image") == 0) {
+                GdkEventKey *e = (GdkEventKey *) event;
+                if (e->keyval == GDK_KEY_Escape) {
+                        gr_window_show_image (window, NULL, -1);
+                        return GDK_EVENT_STOP;
+                }
+        }
+
         if (strcmp (visible, "recipes") != 0 &&
             strcmp (visible, "cuisines") != 0 &&
             strcmp (visible, "search") != 0)
@@ -470,6 +482,7 @@ gr_window_class_init (GrWindowClass *klass)
         gtk_widget_class_bind_template_child (widget_class, GrWindow, search_page);
         gtk_widget_class_bind_template_child (widget_class, GrWindow, cuisines_page);
         gtk_widget_class_bind_template_child (widget_class, GrWindow, cuisine_page);
+        gtk_widget_class_bind_template_child (widget_class, GrWindow, image_page);
         gtk_widget_class_bind_template_child (widget_class, GrWindow, undo_revealer);
         gtk_widget_class_bind_template_child (widget_class, GrWindow, undo_label);
 
@@ -768,3 +781,20 @@ gr_window_show_search_by_ingredients (GrWindow   *window,
 
         gr_query_editor_set_terms (GR_QUERY_EDITOR (window->search_bar), (const char **)terms);
 }
+
+void
+gr_window_show_image (GrWindow *window,
+                      GArray   *images,
+                      int       index)
+{
+        if (images) {
+                gr_image_page_set_images (GR_IMAGE_PAGE (window->image_page), images);
+                gr_image_page_show_image (GR_IMAGE_PAGE (window->image_page), index);
+                gtk_stack_set_visible_child_name (GTK_STACK (window->main_stack), "image");
+                gr_window_set_fullscreen (window, TRUE);
+        }
+        else {
+                gr_window_set_fullscreen (window, FALSE);
+                gtk_stack_set_visible_child_name (GTK_STACK (window->main_stack), "details");
+        }
+}
diff --git a/src/gr-window.h b/src/gr-window.h
index c53f08b..2ea5a1b 100644
--- a/src/gr-window.h
+++ b/src/gr-window.h
@@ -65,4 +65,8 @@ void            gr_window_offer_undelete             (GrWindow   *window,
 void            gr_window_set_fullscreen             (GrWindow   *window,
                                                       gboolean    fullscreen);
 
+void            gr_window_show_image                 (GrWindow   *window,
+                                                      GArray     *images,
+                                                      int         index);
+
 G_END_DECLS
diff --git a/src/gr-window.ui b/src/gr-window.ui
index 3674464..5f80c8c 100644
--- a/src/gr-window.ui
+++ b/src/gr-window.ui
@@ -282,6 +282,12 @@
                     <property name="name">edit</property>
                   </packing>
                 </child>
+                <child>
+                  <object class="GrImagePage" id="image_page"/>
+                  <packing>
+                    <property name="name">image</property>
+                  </packing>
+                </child>
               </object>
             </child>
           </object>
diff --git a/src/main.c b/src/main.c
index 658809c..27d636d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -37,6 +37,7 @@
 #include "gr-timer-widget.h"
 #include "gr-toggle-button.h"
 #include "gr-image-viewer.h"
+#include "gr-image-page.h"
 
 
 int
@@ -50,6 +51,7 @@ main (int argc, char *argv[])
         g_type_ensure (GR_TYPE_DETAILS_PAGE);
         g_type_ensure (GR_TYPE_EDIT_PAGE);
         g_type_ensure (GR_TYPE_IMAGE_VIEWER);
+        g_type_ensure (GR_TYPE_IMAGE_PAGE);
         g_type_ensure (GR_TYPE_LIST_PAGE);
         g_type_ensure (GR_TYPE_QUERY_EDITOR);
         g_type_ensure (GR_TYPE_RECIPES_PAGE);
diff --git a/src/recipes-ui.gresource.xml b/src/recipes-ui.gresource.xml
index 56eb1d8..2d20a0b 100644
--- a/src/recipes-ui.gresource.xml
+++ b/src/recipes-ui.gresource.xml
@@ -11,6 +11,7 @@
     <file preprocess="xml-stripblanks">gr-edit-page.ui</file>
     <file preprocess="xml-stripblanks">gr-image-editor.ui</file>
     <file preprocess="xml-stripblanks">gr-image-viewer.ui</file>
+    <file preprocess="xml-stripblanks">gr-image-page.ui</file>
     <file preprocess="xml-stripblanks">gr-ingredient-row.ui</file>
     <file preprocess="xml-stripblanks">gr-list-page.ui</file>
     <file preprocess="xml-stripblanks">gr-meal-row.ui</file>
diff --git a/src/recipes.css b/src/recipes.css
index 951bce7..f5f60b4 100644
--- a/src/recipes.css
+++ b/src/recipes.css
@@ -259,3 +259,11 @@ flowbox flowboxchild {
   padding: 0;
   border-radius: 0;
 }
+
+.image-page {
+        background: black;
+}
+
+.image-page .content {
+        border: 1px solid white;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]