Logo Search packages:      
Sourcecode: danpei version File versions  Download package

viewer.c

/*
 * Danpei -- a GTK+ based Image Viewer
 * Copyright (C) 2001-2003 Shinji Moiino
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
/* viewer.c */

#include <stdio.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

#include "config.h"
#include "intl.h"
#include "pcx.h"
#include "version.h"
#include "viewer.h"
#include "xbm.h"
#include "icon/left_arrow_icon.xpm"
#include "icon/right_arrow_icon.xpm"

/* Static variables. */

/* Static functions declaration. */
static void     viewer_create_window          (TopLevel*         ,
                                               gfloat              );

static void     viewer_cb_destroy             (GtkWidget*        ,
                                               gpointer            );

static gint     viewer_cb_image_configure     (GtkWidget*        ,
                                               GdkEventConfigure*,
                                               gpointer            );

static gint     viewer_cb_image_expose        (GtkWidget*        ,
                                               GdkEventExpose*   ,
                                               gpointer            );

static void     viewer_cb_value_changed       (GtkAdjustment*    ,
                                               gpointer            );

static void     viewer_cb_prev_button_clicked (GtkButton*        ,
                                               gpointer            );

static void     viewer_cb_next_button_clicked (GtkButton*        ,
                                               gpointer            );

static void     viewer_read_image             (DanpeiViewer*     ,
                                               gchar*            ,
                                               TopLevel*           );

static void     viewer_free_rgb_buffer        (guchar*           ,
                                               gpointer            );

static gboolean viewer_cb_value_changed_real  (gpointer            );

/* Function definitions. */
/*
 * @viewer_cb_all
 *
 *  
 *
 */
void viewer_cb_all(GtkWidget *widget,
                   gpointer  data   ,
                   guint     action   ) {
  TopLevel *tp;

  /* Initialize local variables. */
  tp = (TopLevel*)data;

  viewer_start(tp, (tp->thumbnail_table).top_thumbnail);

  return;
}

/*
 * @viewer_start
 *
 *  
 *
 */
void viewer_start(TopLevel  *tp   ,
                  Thumbnail *thumb  ) {
  Thumbnail *wk_thumb;
  gint      i;

  /* Initialize local variables. */
  wk_thumb = (tp->thumbnail_table).top_thumbnail;
  i        = 1;

  while (wk_thumb != thumb) {
    wk_thumb = wk_thumb->next; i++;
    if (wk_thumb == NULL) { i = 0; break; }
  }
  if (i == 0) { return; }
  
  if ((tp->viewer).thumb == NULL) {
    (tp->viewer).thumb          = thumb;
    (tp->viewer).current_thumb  = NULL;
    viewer_create_window(tp, i);
    gtk_window_set_title(GTK_WINDOW((tp->viewer).window), 
      g_strconcat(thumb->path, "/", thumb->filename, NULL));
  }
  else {
    (tp->viewer).thumb          = thumb;
    (tp->viewer).current_thumb  = NULL;
    if ((tp->thumbnail_table).file_num != ((tp->viewer).hscale_adj)->upper) {
      ((tp->viewer).hscale_adj)->upper = (tp->thumbnail_table).file_num;
    }
    ((tp->viewer).hscale_adj)->lower = 1;

    if (((tp->viewer).hscale_adj)->upper > 0) {
      gtk_adjustment_set_value((tp->viewer).hscale_adj, i);
    }
  }

  return;
}

/*
 * @viewer_free
 *
 *  
 *
 */
void viewer_free(DanpeiViewer *dv) {
  dv->thumb  = dv->current_thumb = NULL;
  dv->area_x = dv->area_y        = -1;

  if (dv->idle_id != 0) {
    gtk_idle_remove(dv->idle_id);
    dv->idle_id = 0;
  }

  return;
}

/* Static function definitions. */
/*
 * @viewer_create_window
 *
 *
 *
 */
static void viewer_create_window(TopLevel *tp,
                                 gfloat   pos  ) {
  GdkPixmap *pixmap_data;
  GdkBitmap *pixmap_mask;

  (tp->viewer).window = gtk_window_new(GTK_WINDOW_DIALOG);
  gtk_signal_connect(GTK_OBJECT((tp->viewer).window), 
                     "destroy",
                     GTK_SIGNAL_FUNC(viewer_cb_destroy), &(tp->viewer));
  gtk_widget_show((tp->viewer).window);

  (tp->viewer).vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER((tp->viewer).window), (tp->viewer).vbox);
  gtk_window_set_policy(GTK_WINDOW((tp->viewer).window), FALSE, FALSE, TRUE);
  gtk_widget_show((tp->viewer).vbox);

  /* Image_box and image_area that are made here is dummy. */
  (tp->viewer).image_area = gtk_drawing_area_new();
  gtk_signal_connect(GTK_OBJECT((tp->viewer).image_area), 
                     "configure_event",
                     GTK_SIGNAL_FUNC(viewer_cb_image_configure), tp);
  gtk_signal_connect(GTK_OBJECT((tp->viewer).image_area),
                     "expose_event",
                     GTK_SIGNAL_FUNC(viewer_cb_image_expose), 
                     &(tp->viewer));
  gtk_box_pack_start(GTK_BOX((tp->viewer).vbox), (tp->viewer).image_area,
                     TRUE, TRUE, 0);
  gtk_widget_show((tp->viewer).image_area);

  (tp->viewer).hbox1 = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX((tp->viewer).vbox), (tp->viewer).hbox1,
                     FALSE, FALSE, 0);
  gtk_widget_show((tp->viewer).hbox1);

  (tp->viewer).hscale_adj = GTK_ADJUSTMENT(gtk_adjustment_new(pos, 1,
                               (tp->thumbnail_table).file_num, 1.0, 5.0, 0));
  gtk_signal_connect(GTK_OBJECT((tp->viewer).hscale_adj),
                     "value-changed",
                     GTK_SIGNAL_FUNC(viewer_cb_value_changed), tp);
  (tp->viewer).hscale = gtk_hscale_new((tp->viewer).hscale_adj);
  gtk_scale_set_digits(GTK_SCALE((tp->viewer).hscale), 0);
  gtk_box_pack_start(GTK_BOX((tp->viewer).hbox1), (tp->viewer).hscale,
                     TRUE, TRUE, 0);
  gtk_widget_show((tp->viewer).hscale);

  (tp->viewer).hbox2 = gtk_hbox_new(TRUE, 0);
  gtk_box_pack_start(GTK_BOX((tp->viewer).hbox1), (tp->viewer).hbox2,
                     FALSE, FALSE, 0);
  gtk_widget_show((tp->viewer).hbox2);

  pixmap_data = gdk_pixmap_create_from_xpm_d(GDK_ROOT_PARENT() ,
                                             &pixmap_mask, NULL,
                                             (gchar**)left_arrow_icon_xpm);
  (tp->viewer).prev_icon = gtk_pixmap_new(pixmap_data, pixmap_mask);
  (tp->viewer).prev_button = gtk_button_new();
  gtk_container_add(GTK_CONTAINER((tp->viewer).prev_button),
                    (tp->viewer).prev_icon                    );
  gtk_box_pack_start(GTK_BOX((tp->viewer).hbox2), (tp->viewer).prev_button,
                     TRUE, TRUE, 0);
  gtk_signal_connect(GTK_OBJECT((tp->viewer).prev_button),
                     "clicked",
                     GTK_SIGNAL_FUNC(viewer_cb_prev_button_clicked), tp);
  gtk_widget_show((tp->viewer).prev_icon);
  gtk_widget_show((tp->viewer).prev_button);
  gdk_pixmap_unref(pixmap_data);
  gdk_bitmap_unref(pixmap_mask);

  pixmap_data = gdk_pixmap_create_from_xpm_d(GDK_ROOT_PARENT() ,
                                             &pixmap_mask, NULL,
                                             (gchar**)right_arrow_icon_xpm);
  (tp->viewer).next_icon = gtk_pixmap_new(pixmap_data, pixmap_mask);
  (tp->viewer).next_button = gtk_button_new();
  gtk_container_add(GTK_CONTAINER((tp->viewer).next_button),
                    (tp->viewer).next_icon                    );
  gtk_signal_connect(GTK_OBJECT((tp->viewer).next_button),
                     "clicked",
                     GTK_SIGNAL_FUNC(viewer_cb_next_button_clicked), tp);
  gtk_box_pack_start(GTK_BOX((tp->viewer).hbox2), (tp->viewer).next_button,
                     TRUE, TRUE, 0);
  gtk_widget_show((tp->viewer).next_icon);
  gtk_widget_show((tp->viewer).next_button);
  gdk_pixmap_unref(pixmap_data);
  gdk_bitmap_unref(pixmap_mask);

  (tp->viewer).alive = TRUE;
  return;
}

/*
 * @viewer_cb_destroy
 *
 *
 *
 */
static void viewer_cb_destroy(GtkWidget *widget,
                              gpointer  data     ) {
  DanpeiViewer *dv;

  /* Initialize local variables. */
  dv = (DanpeiViewer*)data;

  if (dv->original_pixmap != NULL) {
    gdk_pixmap_unref(dv->original_pixmap);
    dv->original_pixmap = NULL;
  }
  if (dv->scaled_pixmap != NULL) {
    gdk_pixmap_unref(dv->scaled_pixmap);
    dv->scaled_pixmap = NULL;
  }

  viewer_free(dv);

  dv->alive = FALSE;

  return;
}

/*
 * @viewer_cb_image_configure
 *
 *
 *
 */
static gint viewer_cb_image_configure(GtkWidget         *widget,
                                      GdkEventConfigure *ev    ,
                                      gpointer          data     ) {
  TopLevel     *tp;
  DanpeiViewer *dv;
  gchar        *filename;

  /* Initialize local variables. */
  tp       = (TopLevel*)data;
  dv       = &(tp->viewer);
  filename = NULL;

  if ((dv->thumb == dv->current_thumb)  &&
      ((widget->allocation.x == dv->area_x) &&
       (widget->allocation.y == dv->area_y)    )){ return; }

  dv->area_x = widget->allocation.x;
  dv->area_y = widget->allocation.y;

  if (dv->original_pixmap != NULL) { 
    gdk_pixmap_unref(dv->original_pixmap); 
    dv->original_pixmap = NULL;
   }
  if (dv->scaled_pixmap != NULL) { 
    gdk_pixmap_unref(dv->scaled_pixmap);
    dv->scaled_pixmap = NULL;
  }
  if (dv->thumb != NULL) {
    if (strcmp(dv->thumb->path, "/") == 0) {
      filename = g_strconcat(dv->thumb->path, dv->thumb->filename, NULL);
    }
    else {
      filename = g_strconcat(dv->thumb->path, "/", dv->thumb->filename, NULL);
    }
  }
  if (filename == NULL) { return; }

  viewer_read_image(dv, filename, tp);

  if (dv->scaled_pixmap != NULL) {
    gdk_draw_pixmap(dv->image_area->window,
      dv->image_area->style->fg_gc[GTK_WIDGET_STATE(dv->image_area)],
      dv->scaled_pixmap, 0, 0, 0, 0, dv->image_width, dv->image_height);
  }

  g_free(filename);

  return 0;
}

/*
 * @viewer_cb_image_expose
 *
 *
 *
 */
static gint viewer_cb_image_expose(GtkWidget      *widget,
                                   GdkEventExpose *ev    ,
                                   gpointer       data     ) {
  DanpeiViewer  *dv;

  dv = (DanpeiViewer*)data;

  if (dv->scaled_pixmap != NULL) {
    gdk_draw_pixmap(widget->window,
      widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
      dv->scaled_pixmap,
      ev->area.x, ev->area.y,
      ev->area.x, ev->area.y,
      ev->area.width, ev->area.height);
  }

  return 0;
}

/*
 * @viewer_cb_value_changed
 *
 *
 *
 */
static void viewer_cb_value_changed(GtkAdjustment *adj,
                                    gpointer      data  ) {
  TopLevel *tp;

  /* Initialize local variables. */
  tp = (TopLevel*)data;

  (tp->viewer).adj.lower          = adj->lower;
  (tp->viewer).adj.upper          = adj->upper;
  (tp->viewer).adj.value          = adj->value;
  (tp->viewer).adj.step_increment = adj->step_increment;
  (tp->viewer).adj.page_increment = adj->page_increment;
  (tp->viewer).adj.page_size      = adj->page_size;
  if ((tp->viewer).idle_id == 0) {
    (tp->viewer).idle_id = gtk_idle_add(viewer_cb_value_changed_real, data);
  }

  return;
}

/*
 * @viewer_cb_prev_button_clicked
 *
 *
 *
 */
static void viewer_cb_prev_button_clicked(GtkButton *widget,
                                          gpointer  data     ) {
  TopLevel  *tp;
  gfloat    value;

  /* Initialize local variables. */
  tp    = (TopLevel*)data;
  value = ((tp->viewer).hscale_adj)->value;

  value--;
  if (value < ((tp->viewer).hscale_adj)->lower) ;
  else {
    gtk_adjustment_set_value((tp->viewer).hscale_adj, value);
  }

  return;
}

/*
 * @viewer_cb_next_button_clicked
 *
 *
 *
 */
static void viewer_cb_next_button_clicked(GtkButton *widget,
                                          gpointer  data     ) {
  TopLevel  *tp;
  gfloat    value;

  /* Initialize local variables. */
  tp    = (TopLevel*)data;
  value = ((tp->viewer).hscale_adj)->value;

  value++;
  if (value > ((tp->viewer).hscale_adj)->upper) ;
  else {
    gtk_adjustment_set_value((tp->viewer).hscale_adj, value);
  }

  return;
}

/*
 * @viewer_read_image
 *
 *
 *
 */
static void viewer_read_image(DanpeiViewer *dv      ,
                              gchar        *filename,
                              TopLevel     *tp        ) {
  GdkPixbuf  *image, *image2;
  guchar     *rgb_data;
  gint       image_width, image_height;

  /* Initialize local variables. */
  image    = NULL;
  rgb_data = NULL;

  dv->current_thumb = dv->thumb;

  /* Load the image and render it. */
  image = gdk_pixbuf_new_from_file(filename);
  if (image == NULL) {
    /* load image as pcx data. */
    rgb_data = pcx_load(filename, &image_width, &image_height);
    if (rgb_data != NULL) {
      image = gdk_pixbuf_new_from_data(rgb_data, GDK_COLORSPACE_RGB,
                                       FALSE, 8,
                                       image_width, image_height,
                                       image_width * 3,
                                       viewer_free_rgb_buffer, NULL);
    }
    /* load image as xbm data. */
    rgb_data = xbm_load(filename, &image_width, &image_height);
    if (rgb_data != NULL) {
      image = gdk_pixbuf_new_from_data(rgb_data, GDK_COLORSPACE_RGB,
                                       FALSE, 8,
                                       image_width, image_height,
                                       image_width * 3,
                                       viewer_free_rgb_buffer, NULL);
    }
  }
  if (image == NULL) {
    dv->original_pixmap = NULL;
    dv->scaled_pixmap   = NULL;
  }
  else {
    image_width  = gdk_pixbuf_get_width (image);
    image_height = gdk_pixbuf_get_height(image);

    dv->image_width  = (tp->app_option).viewer.width;
    dv->image_height = (tp->app_option).viewer.height;
    if (image_width < image_height) {
      dv->image_width = (gint)((tp->app_option).viewer.width *
                               ((float)(image_width ) /
                                (float)(image_height)   ));
    }
    else {
      dv->image_height = (gint)((tp->app_option).viewer.height *
                                ((float)(image_height) /
                                 (float)(image_width )   ));
    }

    gtk_drawing_area_size(GTK_DRAWING_AREA(dv->image_area),
                          dv->image_width, dv->image_height);
    dv->original_pixmap = gdk_pixmap_new(tp->window->window,
                                         image_width , image_height, -1);
    dv->scaled_pixmap   = gdk_pixmap_new(tp->window->window,
                                         dv->image_width ,
                                         dv->image_height, -1);
    gdk_pixbuf_render_to_drawable_alpha(image,
                                        dv->original_pixmap  ,
                                        0, 0, 0, 0,
                                        image_width,
                                        image_height,
                                        GDK_PIXBUF_ALPHA_BILEVEL,
                                        0, GDK_RGB_DITHER_MAX, 0, 0);
    image2 = gdk_pixbuf_scale_simple(image,
                                     dv->image_width,
                                     dv->image_height,
                                     GDK_INTERP_TILES  );
    gdk_pixbuf_render_to_drawable_alpha(image2,
                                        dv->scaled_pixmap  ,
                                        0, 0, 0, 0,
                                        dv->image_width,
                                        dv->image_height,
                                        GDK_PIXBUF_ALPHA_BILEVEL,
                                        0, GDK_RGB_DITHER_MAX, 0, 0);
    gdk_pixbuf_unref(image);
    gdk_pixbuf_unref(image2);
  }

  return;
}

/*
 * @viewer_free_rgb_buffer
 *
 *
 *
 */
static void viewer_free_rgb_buffer(guchar   *pixels,
                                   gpointer data     ) {
  g_free(pixels);

  return;
}


/*
 * @viewer__cb_value_changed_real
 *
 *
 *
 */
static gboolean viewer_cb_value_changed_real (gpointer data) {
  TopLevel      *tp;
  Thumbnail     *thumb;
  gint          i;

  /* Initialize local variables. */
  tp    = (TopLevel*)data;
  thumb = (tp->thumbnail_table).top_thumbnail;
  i     = 1;

  while ((thumb != NULL) && (i < (tp->viewer).adj.value)) {
    thumb = thumb->next; i++;
  }
  if (thumb == NULL) { return; }

  gtk_window_set_title(GTK_WINDOW((tp->viewer).window), 
    g_strconcat(thumb->path, "/", thumb->filename, NULL));
  (tp->viewer).thumb = thumb;
  viewer_cb_image_configure((tp->viewer).image_area, NULL, tp);

  if ((tp->viewer).idle_id != 0) {
    gtk_idle_remove((tp->viewer).idle_id);
    (tp->viewer).idle_id = 0;
  }

  return FALSE;
}

Generated by  Doxygen 1.6.0   Back to index