"Fossies" - the Fresh Open Source Software Archive

Member "poppler-0.82.0/glib/demo/layers.c" (25 Oct 2019, 11449 Bytes) of package /linux/misc/poppler-0.82.0.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Copyright (C) 2008 Carlos Garcia Campos  <carlosgc@gnome.org>
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; either version 2, or (at your option)
    7  * any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
   17  */
   18 
   19 #include "config.h"
   20 
   21 #include <gtk/gtk.h>
   22 
   23 #include "layers.h"
   24 
   25 enum {
   26     LAYERS_TITLE_COLUMN,
   27     LAYERS_VISIBILITY_COLUMN,
   28     LAYERS_ENABLE_COLUMN,
   29     LAYERS_SHOWTOGGLE_COLUMN,
   30     LAYERS_RB_GROUP_COLUMN,
   31     LAYERS_LAYER_COLUMN,
   32     N_COLUMNS
   33 };
   34 
   35 typedef struct {
   36     PopplerDocument *doc;
   37     guint            page;
   38     GtkWidget       *treeview;
   39     GtkWidget       *darea;
   40 
   41     cairo_surface_t *surface;
   42 } PgdLayersDemo;
   43 
   44 static void
   45 pgd_layers_free (PgdLayersDemo *demo)
   46 {
   47     if (!demo)
   48         return;
   49 
   50     if (demo->doc) {
   51         g_object_unref (demo->doc);
   52         demo->doc = NULL;
   53     }
   54 
   55     if (demo->surface) {
   56         cairo_surface_destroy (demo->surface);
   57         demo->surface = NULL;
   58     }
   59 
   60     g_free (demo);
   61 }
   62 
   63 static void
   64 build_tree (PopplerDocument   *document,
   65         GtkTreeModel      *model,
   66         GtkTreeIter       *parent,
   67         PopplerLayersIter *iter)
   68 {
   69 
   70     do {
   71         GtkTreeIter        tree_iter;
   72         PopplerLayersIter *child;
   73         PopplerLayer      *layer;
   74         gboolean           visible;
   75         gchar             *markup;
   76         gint               rb_group = 0;
   77 
   78         layer = poppler_layers_iter_get_layer (iter);
   79         if (layer) {
   80             markup = g_markup_escape_text (poppler_layer_get_title (layer), -1);
   81             visible = poppler_layer_is_visible (layer);
   82             rb_group = poppler_layer_get_radio_button_group_id (layer);
   83         } else {
   84             gchar *title;
   85 
   86             title = poppler_layers_iter_get_title (iter);
   87             markup = g_markup_escape_text (title, -1);
   88             g_free (title);
   89 
   90             visible = FALSE;
   91             layer = NULL;
   92         }
   93 
   94         gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
   95         gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
   96                     LAYERS_TITLE_COLUMN, markup,
   97                     LAYERS_VISIBILITY_COLUMN, visible,
   98                     LAYERS_ENABLE_COLUMN, TRUE, /* FIXME */
   99                     LAYERS_SHOWTOGGLE_COLUMN, (layer != NULL),
  100                     LAYERS_RB_GROUP_COLUMN, rb_group,
  101                     LAYERS_LAYER_COLUMN, layer,
  102                     -1);
  103         if (layer)
  104             g_object_unref (layer);
  105         g_free (markup);
  106 
  107         child = poppler_layers_iter_get_child (iter);
  108         if (child)
  109             build_tree (document, model, &tree_iter, child);
  110         poppler_layers_iter_free (child);
  111     } while (poppler_layers_iter_next (iter));
  112 }
  113 
  114 GtkTreeModel *
  115 pgd_layers_create_model (PopplerDocument *document)
  116 {
  117     GtkTreeModel     *model;
  118     PopplerLayersIter *iter;
  119 
  120     iter = poppler_layers_iter_new (document);
  121     if (iter) {
  122         model = GTK_TREE_MODEL (
  123             gtk_tree_store_new (N_COLUMNS,
  124                         G_TYPE_STRING, 
  125                         G_TYPE_BOOLEAN,
  126                         G_TYPE_BOOLEAN,
  127                         G_TYPE_BOOLEAN,
  128                         G_TYPE_INT,
  129                         G_TYPE_OBJECT));
  130         build_tree (document, model, NULL, iter);
  131         poppler_layers_iter_free (iter);
  132     } else {
  133         GtkTreeIter tree_iter;
  134         gchar      *markup;
  135         
  136         model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
  137         gtk_list_store_append (GTK_LIST_STORE (model), &tree_iter);
  138         markup = g_strdup_printf ("<span size=\"larger\" style=\"italic\">%s</span>",
  139                       "The document doesn't contain layers");
  140         gtk_list_store_set (GTK_LIST_STORE (model), &tree_iter,
  141                     0, markup, -1);
  142         g_free (markup);
  143     }
  144 
  145     return model;
  146 }
  147 
  148 static cairo_surface_t *
  149 pgd_layers_render_page (PgdLayersDemo *demo)
  150 {
  151     cairo_t *cr;
  152     PopplerPage *page;
  153     gdouble width, height;
  154     cairo_surface_t *surface = NULL;
  155 
  156     page = poppler_document_get_page (demo->doc, demo->page);
  157     if (!page)
  158         return NULL;
  159 
  160     poppler_page_get_size (page, &width, &height);
  161     gtk_widget_set_size_request (demo->darea, width, height);
  162     
  163     surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
  164                           width, height);
  165     cr = cairo_create (surface);
  166 
  167     cairo_save (cr);
  168     cairo_set_source_rgb (cr, 1, 1, 1);
  169     cairo_rectangle (cr, 0, 0, width, height);
  170     cairo_fill (cr);
  171     cairo_restore (cr);
  172 
  173     cairo_save (cr);
  174     poppler_page_render (page, cr);
  175     cairo_restore (cr);
  176     
  177     cairo_destroy (cr);
  178     g_object_unref (page);
  179 
  180     return surface;
  181 }
  182 
  183 static gboolean
  184 pgd_layers_viewer_drawing_area_draw (GtkWidget     *area,
  185                                      cairo_t       *cr,
  186                                      PgdLayersDemo *demo)
  187 {
  188     if (!demo->surface) {
  189         demo->surface = pgd_layers_render_page (demo);
  190         if (!demo->surface)
  191             return FALSE;
  192     }
  193 
  194     cairo_set_source_surface (cr, demo->surface, 0, 0);
  195     cairo_paint (cr);
  196 
  197     return TRUE;
  198 }
  199 
  200 static gboolean
  201 pgd_layers_viewer_redraw (PgdLayersDemo *demo)
  202 {
  203     cairo_surface_destroy (demo->surface);
  204     demo->surface = NULL;
  205 
  206     gtk_widget_queue_draw (demo->darea);
  207 
  208     return FALSE;
  209 }
  210 
  211 static void
  212 pgd_layers_viewer_queue_redraw (PgdLayersDemo *demo)
  213 {
  214     g_idle_add ((GSourceFunc)pgd_layers_viewer_redraw, demo);
  215 }
  216 
  217 static void
  218 pgd_layers_page_selector_value_changed (GtkSpinButton *spinbutton,
  219                     PgdLayersDemo *demo)
  220 {
  221     demo->page = (gint)gtk_spin_button_get_value (spinbutton) - 1;
  222     pgd_layers_viewer_queue_redraw (demo);
  223 }
  224 
  225 static GtkWidget *
  226 pgd_layers_create_viewer (PgdLayersDemo *demo)
  227 {
  228     GtkWidget *vbox, *hbox;
  229     GtkWidget *label;
  230     GtkWidget *swindow;
  231     GtkWidget *page_selector;
  232     guint      n_pages;
  233     gchar     *str;
  234 
  235     vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
  236 
  237     hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  238 
  239     label = gtk_label_new ("Page:");
  240     gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
  241     gtk_widget_show (label);
  242 
  243     n_pages = poppler_document_get_n_pages (demo->doc);
  244     page_selector = gtk_spin_button_new_with_range (1, n_pages, 1);
  245     g_signal_connect (G_OBJECT (page_selector), "value-changed",
  246               G_CALLBACK (pgd_layers_page_selector_value_changed),
  247               (gpointer)demo);
  248     gtk_box_pack_start (GTK_BOX (hbox), page_selector, FALSE, TRUE, 0);
  249     gtk_widget_show (page_selector);
  250 
  251     str = g_strdup_printf ("of %d", n_pages);
  252     label = gtk_label_new (str);
  253     gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
  254     gtk_widget_show (label);
  255     g_free (str);
  256 
  257     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
  258     gtk_widget_show (hbox);
  259 
  260     demo->darea = gtk_drawing_area_new ();
  261     g_signal_connect (G_OBJECT (demo->darea), "draw",
  262               G_CALLBACK (pgd_layers_viewer_drawing_area_draw),
  263               (gpointer)demo);
  264 
  265     swindow = gtk_scrolled_window_new (NULL, NULL);
  266     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
  267                     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  268 #if GTK_CHECK_VERSION(3, 7, 8)
  269     gtk_container_add(GTK_CONTAINER(swindow), demo->darea);
  270 #else
  271     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (swindow), demo->darea);
  272 #endif
  273     gtk_widget_show (demo->darea);
  274 
  275     gtk_box_pack_start (GTK_BOX (vbox), swindow, TRUE, TRUE, 0);
  276     gtk_widget_show (swindow);
  277 
  278     return vbox;
  279 }
  280 
  281 static gboolean
  282 update_kids (GtkTreeModel *model,
  283          GtkTreePath  *path,
  284          GtkTreeIter  *iter,
  285          GtkTreeIter  *parent)
  286 {
  287     if (gtk_tree_store_is_ancestor (GTK_TREE_STORE (model), parent, iter)) {
  288         gboolean visible;
  289 
  290         gtk_tree_model_get (model, parent,
  291                     LAYERS_VISIBILITY_COLUMN, &visible,
  292                     -1);
  293         gtk_tree_store_set (GTK_TREE_STORE (model), iter,
  294                     LAYERS_ENABLE_COLUMN, visible,
  295                     -1);
  296     }
  297 
  298     return FALSE;
  299 }
  300 
  301 static gboolean
  302 clear_rb_group (GtkTreeModel *model,
  303         GtkTreePath  *path,
  304         GtkTreeIter  *iter,
  305         gint         *rb_group)
  306 {
  307     gint group;
  308     
  309     gtk_tree_model_get (model, iter,
  310                 LAYERS_RB_GROUP_COLUMN, &group,
  311                 -1);
  312     
  313     if (group == *rb_group) {
  314         gtk_tree_store_set (GTK_TREE_STORE (model), iter,
  315                     LAYERS_VISIBILITY_COLUMN, FALSE,
  316                     -1);
  317     }
  318     
  319     return FALSE;
  320 }
  321 
  322 static void
  323 pgd_layers_visibility_changed (GtkCellRendererToggle *cell,
  324                    gchar                 *path_str,
  325                    PgdLayersDemo         *demo)
  326 {
  327     GtkTreeModel *model;
  328     GtkTreePath *path;
  329     GtkTreeIter iter;
  330     gboolean visible;
  331     PopplerLayer *layer;
  332 
  333     model = gtk_tree_view_get_model (GTK_TREE_VIEW (demo->treeview));
  334 
  335     path = gtk_tree_path_new_from_string (path_str);
  336     gtk_tree_model_get_iter (model, &iter, path);
  337     gtk_tree_model_get (model, &iter,
  338                 LAYERS_VISIBILITY_COLUMN, &visible,
  339                 LAYERS_LAYER_COLUMN, &layer,
  340                 -1);
  341 
  342     visible = !visible;
  343     visible ? poppler_layer_show (layer) : poppler_layer_hide (layer);
  344 
  345     if (visible) {
  346         gint rb_group;
  347         
  348         rb_group = poppler_layer_get_radio_button_group_id (layer);
  349         if (rb_group) {
  350             gtk_tree_model_foreach (model,
  351                         (GtkTreeModelForeachFunc)clear_rb_group,
  352                         &rb_group);
  353         }
  354     }
  355     
  356     gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
  357                 LAYERS_VISIBILITY_COLUMN, visible,
  358                 -1);
  359     
  360     if (poppler_layer_is_parent (layer)) {
  361         gtk_tree_model_foreach (model,
  362                     (GtkTreeModelForeachFunc)update_kids,
  363                     &iter);
  364     }
  365 
  366     pgd_layers_viewer_queue_redraw (demo);
  367 
  368     gtk_tree_path_free (path);
  369     g_object_unref (layer);
  370 }
  371 
  372 GtkWidget *
  373 pgd_layers_create_widget (PopplerDocument *document)
  374 {
  375     PgdLayersDemo    *demo;
  376     GtkWidget        *swindow;
  377     GtkWidget        *treeview;
  378     GtkTreeModel     *model;
  379     GtkCellRenderer  *renderer;
  380     GtkWidget        *hpaned, *viewer;
  381 
  382     demo = g_new0 (PgdLayersDemo, 1);
  383     demo->doc = g_object_ref (document);
  384     
  385     hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
  386 
  387     viewer = pgd_layers_create_viewer (demo);
  388     
  389     swindow = gtk_scrolled_window_new (NULL, NULL);
  390     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
  391                     GTK_POLICY_AUTOMATIC,
  392                     GTK_POLICY_AUTOMATIC);
  393 
  394     model = pgd_layers_create_model (document);
  395     treeview = gtk_tree_view_new_with_model (model);
  396     demo->treeview = treeview;
  397     g_object_unref (model);
  398 
  399     renderer = gtk_cell_renderer_text_new ();
  400     gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
  401                              0, "Layer",
  402                              renderer,
  403                              "markup", LAYERS_TITLE_COLUMN,
  404                              NULL);
  405     g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
  406     g_object_set (G_OBJECT (gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 0)),
  407               "expand", TRUE, NULL);
  408 
  409     if (GTK_IS_TREE_STORE (model)) {
  410         renderer = gtk_cell_renderer_toggle_new ();
  411         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
  412                                  1, "Show/Hide",
  413                                  renderer,
  414                                  "active", LAYERS_VISIBILITY_COLUMN,
  415                                  "activatable", LAYERS_ENABLE_COLUMN,
  416                                  "visible", LAYERS_SHOWTOGGLE_COLUMN,
  417                                  NULL);
  418 
  419         g_signal_connect (renderer, "toggled",
  420                   G_CALLBACK (pgd_layers_visibility_changed),
  421                   (gpointer)demo);
  422         gtk_tree_view_column_set_clickable (gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 1),
  423                             TRUE);
  424     }
  425 
  426     gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
  427                      GTK_SELECTION_NONE);
  428 
  429     gtk_container_add (GTK_CONTAINER (swindow), treeview);
  430     gtk_widget_show (treeview);
  431 
  432     gtk_paned_add1 (GTK_PANED (hpaned), swindow);
  433     gtk_widget_show (swindow);
  434 
  435     gtk_paned_add2 (GTK_PANED (hpaned), viewer);
  436     gtk_widget_show (viewer);
  437 
  438     gtk_paned_set_position (GTK_PANED (hpaned), 150);
  439 
  440     g_object_weak_ref (G_OBJECT (hpaned),
  441                (GWeakNotify)pgd_layers_free,
  442                (gpointer)demo);
  443 
  444     return hpaned;
  445 }