aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/misc
diff options
context:
space:
mode:
authorChris Toshok <toshok@ximian.com>2004-01-31 05:44:46 +0800
committerChris Toshok <toshok@src.gnome.org>2004-01-31 05:44:46 +0800
commite8ab6acfb9f1fe2cfcdc0dde3f246fcc5dd7cc4e (patch)
treeaa10f2c7b26dbee9281aaaf0415023dcfeeab83b /widgets/misc
parentaf2899875563337fe95a6fed42275aeeb74686a4 (diff)
downloadgsoc2013-evolution-e8ab6acfb9f1fe2cfcdc0dde3f246fcc5dd7cc4e.tar
gsoc2013-evolution-e8ab6acfb9f1fe2cfcdc0dde3f246fcc5dd7cc4e.tar.gz
gsoc2013-evolution-e8ab6acfb9f1fe2cfcdc0dde3f246fcc5dd7cc4e.tar.bz2
gsoc2013-evolution-e8ab6acfb9f1fe2cfcdc0dde3f246fcc5dd7cc4e.tar.lz
gsoc2013-evolution-e8ab6acfb9f1fe2cfcdc0dde3f246fcc5dd7cc4e.tar.xz
gsoc2013-evolution-e8ab6acfb9f1fe2cfcdc0dde3f246fcc5dd7cc4e.tar.zst
gsoc2013-evolution-e8ab6acfb9f1fe2cfcdc0dde3f246fcc5dd7cc4e.zip
abstract out the drag and droppable image widget from the contact list
2004-01-30 Chris Toshok <toshok@ximian.com> * e-image-chooser.[ch]: abstract out the drag and droppable image widget from the contact list editor and stick it here. There's some code for a "Browse..." button here but it's not enabled. * Makefile.am (widgetsinclude_HEADERS): add e-image-chooser.h. (libemiscwidgets_la_SOURCES): add e-image-chooser.c svn path=/trunk/; revision=24549
Diffstat (limited to 'widgets/misc')
-rw-r--r--widgets/misc/ChangeLog9
-rw-r--r--widgets/misc/Makefile.am2
-rw-r--r--widgets/misc/e-image-chooser.c482
-rw-r--r--widgets/misc/e-image-chooser.h61
4 files changed, 554 insertions, 0 deletions
diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog
index 434e7cb863..826be8b970 100644
--- a/widgets/misc/ChangeLog
+++ b/widgets/misc/ChangeLog
@@ -1,3 +1,12 @@
+2004-01-30 Chris Toshok <toshok@ximian.com>
+
+ * e-image-chooser.[ch]: abstract out the drag and droppable image
+ widget from the contact list editor and stick it here. There's
+ some code for a "Browse..." button here but it's not enabled.
+
+ * Makefile.am (widgetsinclude_HEADERS): add e-image-chooser.h.
+ (libemiscwidgets_la_SOURCES): add e-image-chooser.c
+
2004-01-30 Jeffrey Stedfast <fejj@ximian.com>
* e-filter-bar.c (get_property): Only save the search-bar state OR
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 5ddcf72d2a..9db2180be2 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -28,6 +28,7 @@ widgetsinclude_HEADERS = \
e-dateedit.h \
e-dropdown-button.h \
e-expander.h \
+ e-image-chooser.h \
e-map.h \
e-multi-config-dialog.h \
e-search-bar.h \
@@ -52,6 +53,7 @@ libemiscwidgets_la_SOURCES = \
e-dateedit.c \
e-dropdown-button.c \
e-expander.c \
+ e-image-chooser.c \
e-map.c \
e-multi-config-dialog.c \
e-search-bar.c \
diff --git a/widgets/misc/e-image-chooser.c b/widgets/misc/e-image-chooser.c
new file mode 100644
index 0000000000..ade79a5892
--- /dev/null
+++ b/widgets/misc/e-image-chooser.c
@@ -0,0 +1,482 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* e-image-chooser.c
+ * Copyright (C) 2004 Novell, Inc.
+ * Author: Chris Toshok <toshok@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <gtk/gtkframe.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkdnd.h>
+
+#include <libgnomevfs/gnome-vfs-ops.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "e-image-chooser.h"
+#include "e-util-marshal.h"
+
+struct _EImageChooserPrivate {
+
+ GtkWidget *frame;
+ GtkWidget *image;
+ GtkWidget *browse_button;
+
+ char *image_buf;
+ int image_buf_size;
+ int image_width;
+ int image_height;
+
+ gboolean editable;
+};
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+
+static gint image_chooser_signals [LAST_SIGNAL] = { 0 };
+
+static void e_image_chooser_init (EImageChooser *chooser);
+static void e_image_chooser_class_init (EImageChooserClass *klass);
+#if 0
+static void e_image_chooser_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void e_image_chooser_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+#endif
+static void e_image_chooser_dispose (GObject *object);
+
+static gboolean image_drag_motion_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x, gint y, guint time, EImageChooser *chooser);
+static void image_drag_leave_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time, EImageChooser *chooser);
+static gboolean image_drag_drop_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x, gint y, guint time, EImageChooser *chooser);
+static void image_drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x, gint y,
+ GtkSelectionData *selection_data,
+ guint info, guint time, EImageChooser *chooser);
+
+static GtkObjectClass *parent_class = NULL;
+#define PARENT_TYPE GTK_TYPE_VBOX
+
+enum DndTargetType {
+ DND_TARGET_TYPE_URI_LIST
+};
+#define URI_LIST_TYPE "text/uri-list"
+
+static GtkTargetEntry image_drag_types[] = {
+ { URI_LIST_TYPE, 0, DND_TARGET_TYPE_URI_LIST },
+};
+static const int num_image_drag_types = sizeof (image_drag_types) / sizeof (image_drag_types[0]);
+
+GtkWidget *
+e_image_chooser_new (void)
+{
+ return g_object_new (E_TYPE_IMAGE_CHOOSER, NULL);
+}
+
+GType
+e_image_chooser_get_type (void)
+{
+ static GType eic_type = 0;
+
+ if (!eic_type) {
+ static const GTypeInfo eic_info = {
+ sizeof (EImageChooserClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) e_image_chooser_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EImageChooser),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_image_chooser_init,
+ };
+
+ eic_type = g_type_register_static (PARENT_TYPE, "EImageChooser", &eic_info, 0);
+ }
+
+ return eic_type;
+}
+
+
+static void
+e_image_chooser_class_init (EImageChooserClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ image_chooser_signals [CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EImageChooserClass, changed),
+ NULL, NULL,
+ e_util_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ /*
+ object_class->set_property = e_image_chooser_set_property;
+ object_class->get_property = e_image_chooser_get_property;
+ */
+ object_class->dispose = e_image_chooser_dispose;
+}
+
+#if UI_CHANGE_OK
+static void
+browse_for_image_cb (GtkWidget *button, gpointer data)
+{
+}
+#endif
+
+static void
+e_image_chooser_init (EImageChooser *chooser)
+{
+ EImageChooserPrivate *priv;
+
+ priv = chooser->priv = g_new0 (EImageChooserPrivate, 1);
+
+ priv->frame = gtk_frame_new ("");
+ priv->image = gtk_image_new ();
+#if UI_CHANGE_OK
+ priv->browse_button = gtk_button_new_with_label (_("Choose Image"));
+#endif
+
+ gtk_frame_set_shadow_type (GTK_FRAME (priv->frame), GTK_SHADOW_NONE);
+
+ gtk_container_add (GTK_CONTAINER (priv->frame), priv->image);
+ gtk_box_set_homogeneous (GTK_BOX (chooser), FALSE);
+ gtk_box_pack_start (GTK_BOX (chooser), priv->frame, TRUE, TRUE, 0);
+#if UI_CHANGE_OK
+ gtk_box_pack_start (GTK_BOX (chooser), priv->browse_button, FALSE, FALSE, 0);
+
+ g_signal_connect (priv->browse_button, "clicked", G_CALLBACK (browse_for_image_cb), NULL);
+#endif
+
+ gtk_drag_dest_set (priv->image, 0, image_drag_types, num_image_drag_types, GDK_ACTION_COPY);
+ g_signal_connect (priv->image,
+ "drag_motion", G_CALLBACK (image_drag_motion_cb), chooser);
+ g_signal_connect (priv->image,
+ "drag_leave", G_CALLBACK (image_drag_leave_cb), chooser);
+ g_signal_connect (priv->image,
+ "drag_drop", G_CALLBACK (image_drag_drop_cb), chooser);
+ g_signal_connect (priv->image,
+ "drag_data_received", G_CALLBACK (image_drag_data_received_cb), chooser);
+
+ gtk_widget_show_all (priv->frame);
+#if UI_CHANGE_OK
+ gtk_widget_show (priv->browse_button);
+#endif
+
+ /* we default to being editable */
+ priv->editable = TRUE;
+}
+
+static void
+e_image_chooser_dispose (GObject *object)
+{
+ EImageChooser *eic = E_IMAGE_CHOOSER (object);
+
+ if (eic->priv) {
+ EImageChooserPrivate *priv = eic->priv;
+
+ if (priv->image_buf) {
+ g_free (priv->image_buf);
+ priv->image_buf = NULL;
+ }
+
+ g_free (eic->priv);
+ eic->priv = NULL;
+ }
+
+ if (G_OBJECT_CLASS (parent_class)->dispose)
+ (* G_OBJECT_CLASS (parent_class)->dispose) (object);
+}
+
+
+static gboolean
+set_image_from_data (EImageChooser *chooser,
+ char *data, int length)
+{
+ gboolean rv = FALSE;
+ GdkPixbufLoader *loader = gdk_pixbuf_loader_new ();
+ GdkPixbuf *pixbuf;
+
+ gdk_pixbuf_loader_write (loader, data, length, NULL);
+
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ if (pixbuf)
+ gdk_pixbuf_ref (pixbuf);
+ gdk_pixbuf_loader_close (loader, NULL);
+ g_object_unref (loader);
+
+ if (pixbuf) {
+ GdkPixbuf *scaled;
+ GdkPixbuf *composite;
+
+ float scale;
+ int new_height, new_width;
+
+ new_height = gdk_pixbuf_get_height (pixbuf);
+ new_width = gdk_pixbuf_get_width (pixbuf);
+
+ printf ("new dimensions = (%d,%d)\n", new_width, new_height);
+
+ if (chooser->priv->image_height < new_height
+ || chooser->priv->image_width < new_width) {
+ /* we need to scale down */
+ printf ("we need to scale down\n");
+ if (new_height > new_width)
+ scale = (float)chooser->priv->image_height / new_height;
+ else
+ scale = (float)chooser->priv->image_width / new_width;
+ }
+ else {
+ /* we need to scale up */
+ printf ("we need to scale up\n");
+ if (new_height > new_width)
+ scale = (float)new_height / chooser->priv->image_height;
+ else
+ scale = (float)new_width / chooser->priv->image_width;
+ }
+
+ printf ("scale = %g\n", scale);
+
+ new_width *= scale;
+ new_height *= scale;
+ new_width = MIN (new_width, chooser->priv->image_width);
+ new_height = MIN (new_height, chooser->priv->image_height);
+
+ printf ("new scaled dimensions = (%d,%d)\n", new_width, new_height);
+
+ scaled = gdk_pixbuf_scale_simple (pixbuf,
+ new_width, new_height,
+ GDK_INTERP_BILINEAR);
+
+ composite = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, gdk_pixbuf_get_bits_per_sample (pixbuf),
+ chooser->priv->image_width, chooser->priv->image_height);
+
+ gdk_pixbuf_fill (composite, 0x00000000);
+
+ gdk_pixbuf_copy_area (scaled, 0, 0, new_width, new_height,
+ composite,
+ chooser->priv->image_width / 2 - new_width / 2,
+ chooser->priv->image_height / 2 - new_height / 2);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (chooser->priv->image), composite);
+ gdk_pixbuf_unref (pixbuf);
+ gdk_pixbuf_unref (scaled);
+ gdk_pixbuf_unref (composite);
+
+ rv = TRUE;
+ }
+
+ return rv;
+}
+
+static gboolean
+image_drag_motion_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x, gint y, guint time, EImageChooser *chooser)
+{
+ GList *p;
+
+ if (!chooser->priv->editable)
+ return FALSE;
+
+ for (p = context->targets; p != NULL; p = p->next) {
+ char *possible_type;
+
+ possible_type = gdk_atom_name (GDK_POINTER_TO_ATOM (p->data));
+ if (!strcmp (possible_type, URI_LIST_TYPE)) {
+ g_free (possible_type);
+ gdk_drag_status (context, GDK_ACTION_COPY, time);
+ gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_IN);
+ return TRUE;
+ }
+
+ g_free (possible_type);
+ }
+
+ gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+ return FALSE;
+}
+
+static void
+image_drag_leave_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time, EImageChooser *chooser)
+{
+ gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+}
+
+static gboolean
+image_drag_drop_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x, gint y, guint time, EImageChooser *chooser)
+{
+ GList *p;
+
+ if (!chooser->priv->editable)
+ return FALSE;
+
+ if (context->targets == NULL) {
+ gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+ return FALSE;
+ }
+
+ for (p = context->targets; p != NULL; p = p->next) {
+ char *possible_type;
+
+ possible_type = gdk_atom_name (GDK_POINTER_TO_ATOM (p->data));
+ if (!strcmp (possible_type, URI_LIST_TYPE)) {
+ g_free (possible_type);
+ gtk_drag_get_data (widget, context,
+ GDK_POINTER_TO_ATOM (p->data),
+ time);
+ gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+ return TRUE;
+ }
+
+ g_free (possible_type);
+ }
+
+ gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
+ return FALSE;
+}
+
+static void
+image_drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x, gint y,
+ GtkSelectionData *selection_data,
+ guint info, guint time, EImageChooser *chooser)
+{
+ char *target_type;
+ gboolean changed = FALSE;
+ gboolean handled = FALSE;
+
+ target_type = gdk_atom_name (selection_data->target);
+
+ printf ("target_type == %s\n", target_type);
+
+ if (!strcmp (target_type, URI_LIST_TYPE)) {
+ GnomeVFSResult result;
+ GnomeVFSHandle *handle;
+ char *uri;
+ char *nl = strstr (selection_data->data, "\r\n");
+ char *buf = NULL;
+ GnomeVFSFileInfo info;
+
+ if (nl)
+ uri = g_strndup (selection_data->data, nl - (char*)selection_data->data);
+ else
+ uri = g_strdup (selection_data->data);
+
+ printf ("uri == %s\n", uri);
+
+ result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+ if (result == GNOME_VFS_OK) {
+ result = gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_DEFAULT);
+ if (result == GNOME_VFS_OK) {
+ GnomeVFSFileSize num_left;
+ GnomeVFSFileSize num_read;
+ GnomeVFSFileSize total_read;
+
+ printf ("file size = %d\n", (int)info.size);
+ buf = g_malloc (info.size);
+
+ num_left = info.size;
+ total_read = 0;
+
+ while ((result = gnome_vfs_read (handle, buf + total_read, num_left, &num_read)) == GNOME_VFS_OK) {
+ num_left -= num_read;
+ total_read += num_read;
+ }
+
+ printf ("read %d bytes\n", (int)total_read);
+ if (set_image_from_data (chooser, buf, total_read)) {
+ changed = TRUE;
+ handled = TRUE;
+ g_free (chooser->priv->image_buf);
+ chooser->priv->image_buf = buf;
+ chooser->priv->image_buf_size = total_read;
+ }
+ else {
+ /* XXX we should pop up a
+ warning dialog here */
+ g_free (buf);
+ }
+ }
+
+ gnome_vfs_close (handle);
+ }
+ else {
+ printf ("gnome_vfs_open failed (%s)\n", gnome_vfs_result_to_string (result));
+ }
+
+ g_free (uri);
+
+ if (changed) {
+ g_signal_emit (chooser,
+ image_chooser_signals [CHANGED], 0);
+ }
+ }
+
+ gtk_drag_finish (context, handled, FALSE, time);
+}
+
+
+
+gboolean
+e_image_chooser_set_from_file (EImageChooser *chooser, const char *filename)
+{
+ gchar *data;
+ gsize data_length;
+
+ g_return_val_if_fail (E_IS_IMAGE_CHOOSER (chooser), FALSE);
+
+ if (!g_file_get_contents (filename, &data, &data_length, NULL)) {
+ return FALSE;
+ }
+
+ set_image_from_data (chooser, data, data_length);
+
+ g_free (data);
+
+ return TRUE;
+}
+
+void
+e_image_chooser_set_editable (EImageChooser *chooser, gboolean editable)
+{
+ g_return_if_fail (E_IS_IMAGE_CHOOSER (chooser));
+
+ chooser->priv->editable = editable;
+
+ gtk_widget_set_sensitive (chooser->priv->browse_button, editable);
+}
diff --git a/widgets/misc/e-image-chooser.h b/widgets/misc/e-image-chooser.h
new file mode 100644
index 0000000000..55d260ff00
--- /dev/null
+++ b/widgets/misc/e-image-chooser.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* e-image-chooser.c
+ * Copyright (C) 2004 Novell, Inc.
+ * Author: Chris Toshok <toshok@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _E_IMAGE_CHOOSER_H_
+#define _E_IMAGE_CHOOSER_H_
+
+#include <gtk/gtkvbox.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_IMAGE_CHOOSER (e_image_chooser_get_type ())
+#define E_IMAGE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_IMAGE_CHOOSER, EImageChooser))
+#define E_IMAGE_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_IMAGE_CHOOSER, EImageChooserClass))
+#define E_IS_IMAGE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_IMAGE_CHOOSER))
+#define E_IS_IMAGE_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_IMAGE_CHOOSER))
+
+typedef struct _EImageChooser EImageChooser;
+typedef struct _EImageChooserClass EImageChooserClass;
+typedef struct _EImageChooserPrivate EImageChooserPrivate;
+
+struct _EImageChooser
+{
+ GtkVBox parent;
+
+ EImageChooserPrivate *priv;
+};
+
+struct _EImageChooserClass
+{
+ GtkVBoxClass parent_class;
+
+ /* signals */
+ void (*changed) (EImageChooser *chooser);
+
+
+};
+
+GtkWidget *e_image_chooser_new (void);
+GType e_image_chooser_get_type (void);
+
+gboolean e_image_chooser_set_from_file (EImageChooser *chooser, const char *filename);
+void e_image_chooser_set_editable (EImageChooser *chooser, gboolean editable);
+
+#endif /* _E_IMAGE_CHOOSER_H_ */