aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobody <nobody@localhost>2002-02-09 05:58:21 +0800
committernobody <nobody@localhost>2002-02-09 05:58:21 +0800
commit9d6c701bffc3ea0a9a62dfb69cebec830c4be22c (patch)
tree69ab7e75c9309b442dd034df4d8cccc53124a0d1
parent8df67e73f012204264933c4bb3b32a97af54acd3 (diff)
downloadgsoc2013-evolution-9d6c701bffc3ea0a9a62dfb69cebec830c4be22c.tar.gz
gsoc2013-evolution-9d6c701bffc3ea0a9a62dfb69cebec830c4be22c.tar.zst
gsoc2013-evolution-9d6c701bffc3ea0a9a62dfb69cebec830c4be22c.zip
This commit was manufactured by cvs2svn to create branch 'gal-2'.
svn path=/branches/gal-2/; revision=15624
-rw-r--r--e-util/e-iconv.c458
-rw-r--r--e-util/e-iconv.h44
-rw-r--r--widgets/menus/gal-view-instance-save-as-dialog.glade269
-rw-r--r--widgets/menus/gal-view-instance-save-as-dialog.h89
-rw-r--r--widgets/menus/gal-view-instance.c481
-rw-r--r--widgets/menus/gal-view-instance.h115
-rw-r--r--widgets/misc/e-canvas-background.c464
-rw-r--r--widgets/misc/e-canvas-background.h82
-rw-r--r--widgets/table/e-cell-progress.c450
-rw-r--r--widgets/table/e-cell-progress.h74
10 files changed, 2526 insertions, 0 deletions
diff --git a/e-util/e-iconv.c b/e-util/e-iconv.c
new file mode 100644
index 0000000000..44c91fd412
--- /dev/null
+++ b/e-util/e-iconv.c
@@ -0,0 +1,458 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-iconv.c
+ * Copyright 2000, 2001, Ximian, Inc.
+ *
+ * Authors:
+ * Michael Zucchi <notzed@ximian.com>
+ * Jeffery Stedfast <fejj@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include <glib.h>
+#include "e-iconv.h"
+
+#include <locale.h>
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#ifdef HAVE_CODESET
+#include <langinfo.h>
+#endif
+
+/* FIXME: Use feature test */
+#if !defined (__aix__) && !defined (__irix__) && !defined (__sun__)
+#define ICONV_ISO_NEEDS_DASH (1)
+#endif
+
+#define cd(x)
+
+#ifdef G_THREADS_ENABLED
+static GStaticMutex lock = G_STATIC_MUTEX_INIT;
+#define LOCK() g_static_mutex_lock(&lock)
+#define UNLOCK() g_static_mutex_unlock(&lock)
+#else
+#define LOCK()
+#define UNLOCK()
+#endif
+
+typedef struct _EDListNode {
+ struct _EDListNode *next;
+ struct _EDListNode *prev;
+} EDListNode;
+
+typedef struct _EDList {
+ struct _EDListNode *head;
+ struct _EDListNode *tail;
+ struct _EDListNode *tailpred;
+} EDList;
+
+#define E_DLIST_INITIALISER(l) { (EDListNode *)&l.tail, 0, (EDListNode *)&l.head }
+
+struct _iconv_cache_node {
+ struct _iconv_cache_node *next;
+ struct _iconv_cache_node *prev;
+
+ struct _iconv_cache *parent;
+
+ int busy;
+ iconv_t ip;
+};
+
+struct _iconv_cache {
+ struct _iconv_cache *next;
+ struct _iconv_cache *prev;
+
+ char *conv;
+
+ EDList open; /* stores iconv_cache_nodes, busy ones up front */
+};
+
+#define E_ICONV_CACHE_SIZE (16)
+
+static EDList iconv_cache_list;
+static GHashTable *iconv_cache;
+static GHashTable *iconv_cache_open;
+static unsigned int iconv_cache_size = 0;
+
+static GHashTable *iconv_charsets = NULL;
+static const char *locale_charset = NULL;
+
+struct {
+ char *charset;
+ char *iconv_name;
+} known_iconv_charsets[] = {
+#if 0
+ /* charset name, iconv-friendly charset name */
+ { "iso-8859-1", "iso-8859-1" },
+ { "iso8859-1", "iso-8859-1" },
+ /* the above mostly serves as an example for iso-style charsets,
+ but we have code that will populate the iso-*'s if/when they
+ show up in e_iconv_charset_name() so I'm
+ not going to bother putting them all in here... */
+ { "windows-cp1251", "cp1251" },
+ { "windows-1251", "cp1251" },
+ { "cp1251", "cp1251" },
+ /* the above mostly serves as an example for windows-style
+ charsets, but we have code that will parse and convert them
+ to their cp#### equivalents if/when they show up in
+ e_iconv_charset_name() so I'm not going to bother
+ putting them all in here either... */
+#endif
+ /* charset name (lowercase!), iconv-friendly name (sometimes case sensitive) */
+ { "utf-8", "UTF-8" },
+
+ /* 10646 is a special case, its usually UCS-2 big endian */
+ /* This might need some checking but should be ok for solaris/linux */
+ { "iso-10646-1", "UCS-2BE" },
+ { "iso_10646-1", "UCS-2BE" },
+ { "iso10646-1", "UCS-2BE" },
+ { "iso-10646", "UCS-2BE" },
+ { "iso_10646", "UCS-2BE" },
+ { "iso10646", "UCS-2BE" },
+
+ { "ks_c_5601-1987", "EUC-KR" },
+
+ /* FIXME: Japanese/Korean/Chinese stuff needs checking */
+ { "euckr-0", "EUC-KR" },
+ { "big5-0", "BIG5" },
+ { "big5.eten-0", "BIG5" },
+ { "big5hkscs-0", "BIG5HKCS" },
+ { "gb2312-0", "gb2312" },
+ { "gb2312.1980-0", "gb2312" },
+ { "gb18030-0", "gb18030" },
+ { "gbk-0", "GBK" },
+
+ { "eucjp-0", "eucJP" },
+ { "ujis-0", "ujis" },
+ { "jisx0208.1983-0","SJIS" },
+ { "jisx0212.1990-0","SJIS" },
+ { NULL, NULL }
+};
+
+
+
+/* Another copy of this trivial list implementation
+ Why? This stuff gets called a lot (potentially), should run fast,
+ and g_list's are f@@#$ed up to make this a hassle */
+static void e_dlist_init(EDList *v)
+{
+ v->head = (EDListNode *)&v->tail;
+ v->tail = 0;
+ v->tailpred = (EDListNode *)&v->head;
+}
+
+static EDListNode *e_dlist_addhead(EDList *l, EDListNode *n)
+{
+ n->next = l->head;
+ n->prev = (EDListNode *)&l->head;
+ l->head->prev = n;
+ l->head = n;
+ return n;
+}
+
+static EDListNode *e_dlist_addtail(EDList *l, EDListNode *n)
+{
+ n->next = (EDListNode *)&l->tail;
+ n->prev = l->tailpred;
+ l->tailpred->next = n;
+ l->tailpred = n;
+ return n;
+}
+
+static EDListNode *e_dlist_remove(EDListNode *n)
+{
+ n->next->prev = n->prev;
+ n->prev->next = n->next;
+ return n;
+}
+
+/* NOTE: Owns the lock on return if keep is TRUE ! */
+static void
+e_iconv_init(int keep)
+{
+ char *from, *to, *locale;
+ int i;
+
+ LOCK();
+
+ if (iconv_charsets != NULL) {
+ if (!keep)
+ UNLOCK();
+ return;
+ }
+
+ iconv_charsets = g_hash_table_new(g_str_hash, g_str_equal);
+
+ for (i = 0; known_iconv_charsets[i].charset != NULL; i++) {
+ from = g_strdup(known_iconv_charsets[i].charset);
+ to = g_strdup(known_iconv_charsets[i].iconv_name);
+ g_strdown(from);
+ g_hash_table_insert(iconv_charsets, from, to);
+ }
+
+ e_dlist_init(&iconv_cache_list);
+ iconv_cache = g_hash_table_new(g_str_hash, g_str_equal);
+ iconv_cache_open = g_hash_table_new(NULL, NULL);
+
+ locale = setlocale (LC_ALL, NULL);
+
+ if (!locale || !strcmp (locale, "C") || !strcmp (locale, "POSIX")) {
+ /* The locale "C" or "POSIX" is a portable locale; its
+ * LC_CTYPE part corresponds to the 7-bit ASCII character
+ * set.
+ */
+
+ locale_charset = NULL;
+ } else {
+#ifdef HAVE_CODESET
+ locale_charset = g_strdup(nl_langinfo(CODESET));
+ g_strdown((char *)locale_charset);
+#else
+ /* A locale name is typically of the form language[_terri-
+ * tory][.codeset][@modifier], where language is an ISO 639
+ * language code, territory is an ISO 3166 country code, and
+ * codeset is a character set or encoding identifier like
+ * ISO-8859-1 or UTF-8.
+ */
+ char *codeset, *p;
+
+ codeset = strchr (locale, '.');
+ if (codeset) {
+ codeset++;
+
+ /* ; is a hack for debian systems and / is a hack for Solaris systems */
+ for (p = codeset; *p && !strchr ("@;/", *p); p++);
+ locale_charset = g_strndup (codeset, p - codeset);
+ g_strdown (locale_charset);
+ } else {
+ /* charset unknown */
+ locale_charset = NULL;
+ }
+#endif
+ }
+
+ if (!keep)
+ UNLOCK();
+}
+
+const char *e_iconv_charset_name(const char *charset)
+{
+ char *name, *ret, *tmp;
+
+ if (charset == NULL)
+ return NULL;
+
+ name = alloca(strlen(charset)+1);
+ strcpy(name, charset);
+ g_strdown(name);
+
+ e_iconv_init(TRUE);
+ ret = g_hash_table_lookup(iconv_charsets, name);
+ if (ret != NULL) {
+ UNLOCK();
+ return ret;
+
+
+ }
+
+ /* Unknown, try canonicalise some basic charset types to something that should work */
+ if (strncmp(name, "iso", 3) == 0) {
+ /* Convert iso-nnnn-n or isonnnn-n or iso_nnnn-n to iso-nnnn-n or isonnnn-n */
+ tmp = name+3;
+ if (tmp[0] == '_' || tmp[0] == '-')
+ tmp++;
+#ifdef ICONV_ISO_NEEDS_DASH
+ ret = g_strdup_printf("ISO-%s", tmp);
+#else
+ ret = g_strdup_printf("ISO%s", tmp);
+#endif
+ } else if (strncmp(name, "windows-", 8) == 0) {
+ /* Convert windows-nnnnn or windows-cpnnnnn to cpnnnn */
+ tmp = name+8;
+ if (!strncmp(tmp, "cp", 2))
+ tmp+=2;
+ ret = g_strdup_printf("CP%s", tmp);
+ } else if (strncmp(name, "microsoft-", 10) == 0) {
+ /* Convert microsoft-nnnnn or microsoft-cpnnnnn to cpnnnn */
+ tmp = name+10;
+ if (!strncmp(tmp, "cp", 2))
+ tmp+=2;
+ ret = g_strdup_printf("CP%s", tmp);
+ } else {
+ /* Just assume its ok enough as is, case and all */
+ ret = g_strdup(charset);
+ }
+
+ g_hash_table_insert(iconv_charsets, g_strdup(name), ret);
+ UNLOCK();
+
+ return ret;
+}
+
+static void
+flush_entry(struct _iconv_cache *ic)
+{
+ struct _iconv_cache_node *in, *nn;
+
+ in = (struct _iconv_cache_node *)ic->open.head;
+ nn = in->next;
+ while (nn) {
+ if (in->ip != (iconv_t)-1) {
+ g_hash_table_remove(iconv_cache_open, in->ip);
+ iconv_close(in->ip);
+ }
+ g_free(in);
+ in = nn;
+ nn = in->next;
+ }
+ g_free(ic->conv);
+ g_free(ic);
+}
+
+/* This should run pretty quick, its called a lot */
+iconv_t e_iconv_open(const char *oto, const char *ofrom)
+{
+ const char *to, *from;
+ char *tofrom;
+ struct _iconv_cache *ic;
+ struct _iconv_cache_node *in;
+ iconv_t ip;
+
+ if (oto == NULL || ofrom == NULL)
+ return (iconv_t)-1;
+
+ to = e_iconv_charset_name (oto);
+ from = e_iconv_charset_name (ofrom);
+ tofrom = alloca(strlen(to) +strlen(from) + 2);
+ sprintf(tofrom, "%s%%%s", to, from);
+
+ LOCK();
+
+ ic = g_hash_table_lookup(iconv_cache, tofrom);
+ if (ic) {
+ e_dlist_remove((EDListNode *)ic);
+ } else {
+ struct _iconv_cache *last = (struct _iconv_cache *)iconv_cache_list.tailpred;
+ struct _iconv_cache *prev;
+
+ prev = last->prev;
+ while (prev && iconv_cache_size > E_ICONV_CACHE_SIZE) {
+ in = (struct _iconv_cache_node *)last->open.head;
+ if (in->next && !in->busy) {
+ cd(printf("Flushing iconv converter '%s'\n", last->conv));
+ e_dlist_remove((EDListNode *)last);
+ g_hash_table_remove(iconv_cache, last->conv);
+ flush_entry(last);
+ iconv_cache_size--;
+ }
+ last = prev;
+ prev = last->prev;
+ }
+
+ iconv_cache_size++;
+
+ ic = g_malloc(sizeof(*ic));
+ e_dlist_init(&ic->open);
+ ic->conv = g_strdup(tofrom);
+ g_hash_table_insert(iconv_cache, ic->conv, ic);
+
+ cd(printf("Creating iconv converter '%s'\n", ic->conv));
+ }
+ e_dlist_addhead(&iconv_cache_list, (EDListNode *)ic);
+
+ /* If we have a free iconv, use it */
+ in = (struct _iconv_cache_node *)ic->open.tailpred;
+ if (in->prev && !in->busy) {
+ cd(printf("using existing iconv converter '%s'\n", ic->conv));
+ ip = in->ip;
+ if (ip != (iconv_t)-1) {
+ /* work around some broken iconv implementations
+ * that die if the length arguments are NULL
+ */
+ size_t buggy_iconv = 0;
+
+ /* resets the converter */
+ iconv(ip, NULL, &buggy_iconv, NULL, &buggy_iconv);
+ in->busy = TRUE;
+ e_dlist_remove((EDListNode *)in);
+ e_dlist_addhead(&ic->open, (EDListNode *)in);
+ }
+ } else {
+ cd(printf("creating new iconv converter '%s'\n", ic->conv));
+ ip = iconv_open(to, from);
+ in = g_malloc(sizeof(*in));
+ in->ip = ip;
+ in->parent = ic;
+ e_dlist_addhead(&ic->open, (EDListNode *)in);
+ if (ip != (iconv_t)-1) {
+ g_hash_table_insert(iconv_cache_open, ip, in);
+ in->busy = TRUE;
+ } else {
+ g_warning("Could not open converter for '%s' to '%s' charset", from, to);
+ in->busy = FALSE;
+ }
+ }
+
+ UNLOCK();
+
+ return ip;
+}
+
+size_t e_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char ** outbuf, size_t *outbytesleft)
+{
+ return iconv(cd, (char **) inbuf, inbytesleft, outbuf, outbytesleft);
+}
+
+void
+e_iconv_close(iconv_t ip)
+{
+ struct _iconv_cache_node *in;
+
+ if (ip == (iconv_t)-1)
+ return;
+
+ LOCK();
+ in = g_hash_table_lookup(iconv_cache_open, ip);
+ if (in) {
+ cd(printf("closing iconv converter '%s'\n", in->parent->conv));
+ e_dlist_remove((EDListNode *)in);
+ in->busy = FALSE;
+ e_dlist_addtail(&in->parent->open, (EDListNode *)in);
+ } else {
+ g_warning("trying to close iconv i dont know about: %p", ip);
+ iconv_close(ip);
+ }
+ UNLOCK();
+
+}
+
+const char *e_iconv_locale_charset(void)
+{
+ e_iconv_init(FALSE);
+
+ return locale_charset;
+}
+
diff --git a/e-util/e-iconv.h b/e-util/e-iconv.h
new file mode 100644
index 0000000000..daf97a30ab
--- /dev/null
+++ b/e-util/e-iconv.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-iconv.h
+ * Copyright 2000, 2001, Ximian, Inc.
+ *
+ * Authors:
+ * Michael Zucchi <notzed@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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_ICONV_H_
+#define _E_ICONV_H_
+
+#include <iconv.h>
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+const char *e_iconv_charset_name(const char *charset);
+iconv_t e_iconv_open(const char *oto, const char *ofrom);
+size_t e_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char ** outbuf, size_t *outbytesleft);
+void e_iconv_close(iconv_t ip);
+const char *e_iconv_locale_charset(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* !_E_ICONV_H_ */
diff --git a/widgets/menus/gal-view-instance-save-as-dialog.glade b/widgets/menus/gal-view-instance-save-as-dialog.glade
new file mode 100644
index 0000000000..bc5d99dd58
--- /dev/null
+++ b/widgets/menus/gal-view-instance-save-as-dialog.glade
@@ -0,0 +1,269 @@
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>gal-view-instance-save-as-dialog</name>
+ <program_name>gal-view-instance-save-as-dialog</program_name>
+ <directory></directory>
+ <source_directory>src</source_directory>
+ <pixmaps_directory>pixmaps</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>True</gnome_support>
+ <gettext_support>True</gettext_support>
+ <use_widget_names>True</use_widget_names>
+ <output_main_file>False</output_main_file>
+ <output_support_files>False</output_support_files>
+ <output_build_files>False</output_build_files>
+ <gnome_help_support>True</gnome_help_support>
+</project>
+
+<widget>
+ <class>GnomeDialog</class>
+ <name>dialog1</name>
+ <visible>False</visible>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <auto_close>False</auto_close>
+ <hide_on_close>False</hide_on_close>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDialog:vbox</child_name>
+ <name>dialog-vbox1</name>
+ <homogeneous>False</homogeneous>
+ <spacing>8</spacing>
+ <child>
+ <padding>4</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <child_name>GnomeDialog:action_area</child_name>
+ <name>dialog-action_area1</name>
+ <layout_style>GTK_BUTTONBOX_END</layout_style>
+ <spacing>8</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button1</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button3</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table-top</name>
+ <rows>5</rows>
+ <columns>1</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>0</row_spacing>
+ <column_spacing>0</column_spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkNotebook</class>
+ <name>notebook-help</name>
+ <show_tabs>False</show_tabs>
+ <show_border>False</show_border>
+ <tab_pos>GTK_POS_TOP</tab_pos>
+ <scrollable>False</scrollable>
+ <tab_hborder>2</tab_hborder>
+ <tab_vborder>2</tab_vborder>
+ <popup_enable>False</popup_enable>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>4</top_attach>
+ <bottom_attach>5</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label6</name>
+ <label>The current view will replace the given view. Any folders
+set to this view wil be replaced with the current view.</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>label4</name>
+ <label>label4</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label7</name>
+ <label>This will create a new View.</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>label5</name>
+ <label>label5</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>Custom</class>
+ <name>custom-replace</name>
+ <creation_function>gal_view_instance_save_as_dialog_create_etable</creation_function>
+ <int1>0</int1>
+ <int2>0</int2>
+ <last_modification_time>Fri, 01 Feb 2002 20:18:32 GMT</last_modification_time>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>True</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>entry-create</name>
+ <sensitive>False</sensitive>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>radiobutton-replace</name>
+ <can_focus>True</can_focus>
+ <label>Replace Existing View</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>choice-group</group>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>radiobutton-create</name>
+ <can_focus>True</can_focus>
+ <label>Create New View Named</label>
+ <active>True</active>
+ <draw_indicator>True</draw_indicator>
+ <group>choice-group</group>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
diff --git a/widgets/menus/gal-view-instance-save-as-dialog.h b/widgets/menus/gal-view-instance-save-as-dialog.h
new file mode 100644
index 0000000000..567e00d7b0
--- /dev/null
+++ b/widgets/menus/gal-view-instance-save-as-dialog.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gal-define-views-dialog.h
+ * Copyright 2000, 2001, Ximian, Inc.
+ *
+ * Authors:
+ * Chris Lahey <clahey@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 __GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_H__
+#define __GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_H__
+
+#include <libgnomeui/gnome-dialog.h>
+#include <glade/glade.h>
+#include <gal/e-table/e-table-model.h>
+#include <gal/menus/gal-view-collection.h>
+#include <gal/menus/gal-view-instance.h>
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+/* GalViewInstanceSaveAsDialog - A dialog displaying information about a contact.
+ *
+ * The following arguments are available:
+ *
+ * name type read/write description
+ * --------------------------------------------------------------------------------
+ */
+
+#define GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TYPE (gal_view_instance_save_as_dialog_get_type ())
+#define GAL_VIEW_INSTANCE_SAVE_AS_DIALOG(obj) (GTK_CHECK_CAST ((obj), GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TYPE, GalViewInstanceSaveAsDialog))
+#define GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TYPE, GalViewInstanceSaveAsDialogClass))
+#define GAL_IS_VIEW_INSTANCE_SAVE_AS_DIALOG(obj) (GTK_CHECK_TYPE ((obj), GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TYPE))
+#define GAL_IS_VIEW_INSTANCE_SAVE_AS_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TYPE))
+
+typedef struct _GalViewInstanceSaveAsDialog GalViewInstanceSaveAsDialog;
+typedef struct _GalViewInstanceSaveAsDialogClass GalViewInstanceSaveAsDialogClass;
+
+typedef enum {
+ GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TOGGLE_REPLACE,
+ GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_TOGGLE_CREATE
+} GalViewInstanceSaveAsDialogToggle;
+
+struct _GalViewInstanceSaveAsDialog
+{
+ GnomeDialog parent;
+
+ /* item specific fields */
+ GladeXML *gui;
+ ETableModel *model;
+
+ GalViewInstance *instance;
+ GalViewCollection *collection;
+
+ GalViewInstanceSaveAsDialogToggle toggle;
+};
+
+struct _GalViewInstanceSaveAsDialogClass
+{
+ GnomeDialogClass parent_class;
+};
+
+GtkWidget *gal_view_instance_save_as_dialog_new (GalViewInstance *instance);
+GtkType gal_view_instance_save_as_dialog_get_type (void);
+
+void gal_view_instance_save_as_dialog_save (GalViewInstanceSaveAsDialog *dialog);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GAL_VIEW_INSTANCE_SAVE_AS_DIALOG_H__ */
diff --git a/widgets/menus/gal-view-instance.c b/widgets/menus/gal-view-instance.c
new file mode 100644
index 0000000000..26e1f5546d
--- /dev/null
+++ b/widgets/menus/gal-view-instance.c
@@ -0,0 +1,481 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gal-view-instance.c
+ * Copyright 2000, 2001, Ximian, Inc.
+ *
+ * Authors:
+ * Chris Lahey <clahey@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 <util/e-i18n.h>
+#include <ctype.h>
+#include <string.h>
+#include <gtk/gtksignal.h>
+#include <gnome-xml/parser.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-util.h>
+#include <libgnomeui/gnome-dialog.h>
+#include <gal/util/e-util.h>
+#include <gal/util/e-xml-utils.h>
+#include <gal/widgets/e-unicode.h>
+#include "gal-view-instance.h"
+#include "gal-view-instance-save-as-dialog.h"
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define GVI_CLASS(e) ((GalViewInstanceClass *)((GtkObject *)e)->klass)
+
+#define PARENT_TYPE gtk_object_get_type ()
+
+static GtkObjectClass *gal_view_instance_parent_class;
+
+#define d(x) x
+
+enum {
+ DISPLAY_VIEW,
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint gal_view_instance_signals [LAST_SIGNAL] = { 0, };
+
+static void
+gal_view_instance_changed (GalViewInstance *instance)
+{
+ g_return_if_fail (instance != NULL);
+ g_return_if_fail (GAL_IS_VIEW_INSTANCE (instance));
+
+ gtk_signal_emit (GTK_OBJECT (instance),
+ gal_view_instance_signals [CHANGED]);
+}
+
+static void
+gal_view_instance_display_view (GalViewInstance *instance, GalView *view)
+{
+ g_return_if_fail (instance != NULL);
+ g_return_if_fail (GAL_IS_VIEW_INSTANCE (instance));
+
+ gtk_signal_emit (GTK_OBJECT (instance),
+ gal_view_instance_signals [DISPLAY_VIEW],
+ view);
+}
+
+static void
+save_current_view (GalViewInstance *instance)
+{
+ xmlDoc *doc;
+ xmlNode *root;
+
+ doc = xmlNewDoc("1.0");
+ root = xmlNewNode (NULL, "GalViewCurrentView");
+ xmlDocSetRootElement(doc, root);
+
+ if (instance->current_id)
+ e_xml_set_string_prop_by_name (root, "current_view", instance->current_id);
+ if (instance->current_type)
+ e_xml_set_string_prop_by_name (root, "current_view_type", instance->current_type);
+
+ xmlSaveFile(instance->current_view_filename, doc);
+ xmlFreeDoc(doc);
+}
+
+static void
+view_changed (GalView *view, GalViewInstance *instance)
+{
+ if (instance->current_id != NULL) {
+ g_free (instance->current_id);
+ instance->current_id = NULL;
+ save_current_view (instance);
+ gal_view_instance_changed(instance);
+ }
+
+ gal_view_save (view, instance->custom_filename);
+}
+
+static void
+disconnect_view (GalViewInstance *instance)
+{
+ if (instance->current_view) {
+ if (instance->view_changed_id) {
+ gtk_signal_disconnect (GTK_OBJECT (instance->current_view),
+ instance->view_changed_id);
+ }
+
+ gtk_object_unref (GTK_OBJECT (instance->current_view));
+ }
+ g_free (instance->current_type);
+ g_free (instance->current_title);
+ instance->current_title = NULL;
+ instance->current_type = NULL;
+ instance->view_changed_id = 0;
+ instance->current_view = NULL;
+}
+
+static void
+connect_view (GalViewInstance *instance, GalView *view)
+{
+ if (instance->current_view)
+ disconnect_view (instance);
+ instance->current_view = view;
+
+ instance->current_title = g_strdup (gal_view_get_title(view));
+ instance->current_type = g_strdup (gal_view_get_type_code(view));
+ instance->view_changed_id =
+ gtk_signal_connect(GTK_OBJECT(instance->current_view), "changed",
+ GTK_SIGNAL_FUNC(view_changed), instance);
+
+ gal_view_instance_display_view (instance, instance->current_view);
+}
+
+static void
+gal_view_instance_destroy (GtkObject *object)
+{
+ GalViewInstance *instance = GAL_VIEW_INSTANCE(object);
+
+ if (instance->collection) {
+ if (instance->collection_changed_id) {
+ gtk_signal_disconnect (GTK_OBJECT (instance->collection),
+ instance->collection_changed_id);
+ }
+ gtk_object_unref (GTK_OBJECT (instance->collection));
+ }
+
+ g_free (instance->instance_id);
+ g_free (instance->custom_filename);
+ g_free (instance->current_view_filename);
+
+ g_free (instance->current_id);
+ disconnect_view (instance);
+
+ g_free (instance->default_view);
+
+ if (gal_view_instance_parent_class->destroy)
+ (*gal_view_instance_parent_class->destroy)(object);
+}
+
+static void
+gal_view_instance_class_init (GtkObjectClass *object_class)
+{
+ GalViewInstanceClass *klass = GAL_VIEW_INSTANCE_CLASS(object_class);
+ gal_view_instance_parent_class = gtk_type_class (PARENT_TYPE);
+
+ object_class->destroy = gal_view_instance_destroy;
+
+ gal_view_instance_signals [DISPLAY_VIEW] =
+ gtk_signal_new ("display_view",
+ GTK_RUN_LAST,
+ E_OBJECT_CLASS_TYPE (object_class),
+ GTK_SIGNAL_OFFSET (GalViewInstanceClass, display_view),
+ gtk_marshal_NONE__OBJECT,
+ GTK_TYPE_NONE, 1, GAL_VIEW_TYPE);
+
+ gal_view_instance_signals [CHANGED] =
+ gtk_signal_new ("changed",
+ GTK_RUN_LAST,
+ E_OBJECT_CLASS_TYPE (object_class),
+ GTK_SIGNAL_OFFSET (GalViewInstanceClass, changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ E_OBJECT_CLASS_ADD_SIGNALS (object_class, gal_view_instance_signals, LAST_SIGNAL);
+
+ klass->display_view = NULL;
+ klass->changed = NULL;
+}
+
+static void
+gal_view_instance_init (GalViewInstance *instance)
+{
+ instance->collection = NULL;
+
+ instance->instance_id = NULL;
+ instance->custom_filename = NULL;
+ instance->current_view_filename = NULL;
+
+ instance->current_title = NULL;
+ instance->current_type = NULL;
+ instance->current_id = NULL;
+ instance->current_view = NULL;
+
+ instance->view_changed_id = 0;
+ instance->collection_changed_id = 0;
+
+ instance->loaded = FALSE;
+ instance->default_view = NULL;
+}
+
+/**
+ * gal_view_instance_get_type:
+ *
+ */
+guint
+gal_view_instance_get_type (void)
+{
+ static guint type = 0;
+
+ if (!type)
+ {
+ GtkTypeInfo info =
+ {
+ "GalViewInstance",
+ sizeof (GalViewInstance),
+ sizeof (GalViewInstanceClass),
+ (GtkClassInitFunc) gal_view_instance_class_init,
+ (GtkObjectInitFunc) gal_view_instance_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (PARENT_TYPE, &info);
+ }
+
+ return type;
+}
+
+static void
+collection_changed (GalView *view, GalViewInstance *instance)
+{
+ if (instance->current_id) {
+ char *view_id = instance->current_id;
+ instance->current_id = NULL;
+ gal_view_instance_set_current_view_id (instance, view_id);
+ g_free (view_id);
+ }
+}
+
+static void
+load_current_view (GalViewInstance *instance)
+{
+ xmlDoc *doc;
+ xmlNode *root;
+ GalView *view = NULL;
+
+ doc = xmlParseFile(instance->current_view_filename);
+
+ if (doc == NULL) {
+ instance->current_id = g_strdup (gal_view_instance_get_default_view (instance));
+
+ if (instance->current_id) {
+ int index = gal_view_collection_get_view_index_by_id (instance->collection,
+ instance->current_id);
+
+ if (index != -1) {
+ view = gal_view_collection_get_view (instance->collection,
+ index);
+ view = gal_view_clone(view);
+ connect_view (instance, view);
+ }
+ }
+ return;
+ }
+
+ root = xmlDocGetRootElement(doc);
+ instance->current_id = e_xml_get_string_prop_by_name_with_default (root, "current_view", NULL);
+
+ if (instance->current_id != NULL) {
+ int index = gal_view_collection_get_view_index_by_id (instance->collection,
+ instance->current_id);
+
+ if (index != -1) {
+ view = gal_view_collection_get_view (instance->collection,
+ index);
+ view = gal_view_clone(view);
+ }
+ }
+ if (view == NULL) {
+ char *type;
+ type = e_xml_get_string_prop_by_name_with_default (root, "current_view_type", NULL);
+ view = gal_view_collection_load_view_from_file (instance->collection,
+ type,
+ instance->custom_filename);
+ g_free (type);
+ }
+
+ connect_view (instance, view);
+
+ xmlFreeDoc(doc);
+}
+
+/**
+ * gal_view_instance_new:
+ * @collection: This %GalViewCollection should be loaded before being passed to this function.
+ * @instance_id: Which instance of this type of object is this (for most of evo, this is the folder id.)
+ *
+ * Create a new %GalViewInstance.
+ *
+ * Return value: The new %GalViewInstance.
+ **/
+GalViewInstance *
+gal_view_instance_new (GalViewCollection *collection, const char *instance_id)
+{
+ GalViewInstance *instance = gtk_type_new(gal_view_instance_get_type());
+ if (gal_view_instance_construct (instance, collection, instance_id))
+ return instance;
+ else {
+ gtk_object_unref (GTK_OBJECT (instance));
+ return NULL;
+ }
+}
+
+GalViewInstance *
+gal_view_instance_construct (GalViewInstance *instance, GalViewCollection *collection, const char *instance_id)
+{
+ char *filename;
+ char *safe_id;
+
+ g_return_val_if_fail (gal_view_collection_loaded (collection), NULL);
+
+ instance->collection = collection;
+ if (collection)
+ gtk_object_ref (GTK_OBJECT (collection));
+ instance->collection_changed_id =
+ gtk_signal_connect (GTK_OBJECT (collection), "changed",
+ GTK_SIGNAL_FUNC (collection_changed), instance);
+ instance->instance_id = g_strdup (instance_id);
+
+ safe_id = g_strdup (instance->instance_id);
+ e_filename_make_safe (safe_id);
+
+ filename = g_strdup_printf ("custom_view-%s.xml", safe_id);
+ instance->custom_filename = g_concat_dir_and_file (instance->collection->local_dir, filename);
+ g_free (filename);
+
+ filename = g_strdup_printf ("current_view-%s.xml", safe_id);
+ instance->current_view_filename = g_concat_dir_and_file (instance->collection->local_dir, filename);
+ g_free (filename);
+
+ g_free (safe_id);
+
+ return instance;
+}
+
+/* Manipulate the current view. */
+char *
+gal_view_instance_get_current_view_id (GalViewInstance *instance)
+{
+ if (instance->current_id && gal_view_collection_get_view_index_by_id (instance->collection, instance->current_id) != -1)
+ return g_strdup (instance->current_id);
+ else
+ return NULL;
+}
+
+void
+gal_view_instance_set_current_view_id (GalViewInstance *instance, const char *view_id)
+{
+ GalView *view;
+ int index;
+
+ g_return_if_fail (instance != NULL);
+ g_return_if_fail (GAL_IS_VIEW_INSTANCE (instance));
+
+ d(g_print("%s: view_id set to %s\n", __FUNCTION__, view_id));
+
+ if (instance->current_id && !strcmp (instance->current_id, view_id))
+ return;
+
+ g_free (instance->current_id);
+ instance->current_id = g_strdup (view_id);
+
+ index = gal_view_collection_get_view_index_by_id (instance->collection, view_id);
+ if (index != -1) {
+ view = gal_view_collection_get_view (instance->collection, index);
+ connect_view (instance, gal_view_clone (view));
+ }
+
+ save_current_view (instance);
+ gal_view_instance_changed(instance);
+ gal_view_instance_display_view (instance, instance->current_view);
+}
+
+GalView *
+gal_view_instance_get_current_view (GalViewInstance *instance)
+{
+ return instance->current_view;
+}
+
+void
+gal_view_instance_set_custom_view (GalViewInstance *instance, GalView *view)
+{
+ g_free (instance->current_id);
+ instance->current_id = NULL;
+
+ view = gal_view_clone (view);
+ connect_view (instance, view);
+ gal_view_save (view, instance->custom_filename);
+ save_current_view (instance);
+ gal_view_instance_changed(instance);
+}
+
+static void
+dialog_clicked(GtkWidget *dialog, int button, GalViewInstance *instance)
+{
+ if (button == 0) {
+ gal_view_instance_save_as_dialog_save (GAL_VIEW_INSTANCE_SAVE_AS_DIALOG (dialog));
+ }
+ gnome_dialog_close(GNOME_DIALOG(dialog));
+}
+
+void
+gal_view_instance_save_as (GalViewInstance *instance)
+{
+ GtkWidget *dialog = gal_view_instance_save_as_dialog_new(instance);
+ gtk_signal_connect(GTK_OBJECT(dialog), "clicked",
+ GTK_SIGNAL_FUNC(dialog_clicked), instance);
+ gtk_widget_show(dialog);
+}
+
+/* This is idempotent. Once it's been called once, the rest of the calls are ignored. */
+void
+gal_view_instance_load (GalViewInstance *instance)
+{
+ if (!instance->loaded) {
+ load_current_view (instance);
+ instance->loaded = TRUE;
+ }
+}
+
+/* These only mean anything before gal_view_instance_load is called the first time. */
+const char *
+gal_view_instance_get_default_view (GalViewInstance *instance)
+{
+ if (instance->default_view)
+ return instance->default_view;
+ else
+ return gal_view_collection_get_default_view (instance->collection);
+}
+
+void
+gal_view_instance_set_default_view (GalViewInstance *instance, const char *id)
+{
+ g_free (instance->default_view);
+ instance->default_view = g_strdup (id);
+}
+
+gboolean
+gal_view_instance_exists (GalViewInstance *instance)
+{
+ struct stat st;
+
+ if (instance->current_view_filename && stat (instance->current_view_filename, &st) == 0 && st.st_size > 0 && S_ISREG (st.st_mode))
+ return TRUE;
+ else
+ return FALSE;
+
+}
diff --git a/widgets/menus/gal-view-instance.h b/widgets/menus/gal-view-instance.h
new file mode 100644
index 0000000000..9d0febf0f0
--- /dev/null
+++ b/widgets/menus/gal-view-instance.h
@@ -0,0 +1,115 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gal-view-instance.h
+ * Copyright 2000, 2001, Ximian, Inc.
+ *
+ * Authors:
+ * Chris Lahey <clahey@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 _GAL_VIEW_INSTANCE_H_
+#define _GAL_VIEW_INSTANCE_H_
+
+#include <gtk/gtkobject.h>
+#include <gal/menus/gal-view-collection.h>
+#include <libgnome/gnome-defs.h>
+
+BEGIN_GNOME_DECLS
+
+
+#define GAL_VIEW_INSTANCE_TYPE (gal_view_instance_get_type ())
+#define GAL_VIEW_INSTANCE(o) (GTK_CHECK_CAST ((o), GAL_VIEW_INSTANCE_TYPE, GalViewInstance))
+#define GAL_VIEW_INSTANCE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), GAL_VIEW_INSTANCE_TYPE, GalViewInstanceClass))
+#define GAL_IS_VIEW_INSTANCE(o) (GTK_CHECK_TYPE ((o), GAL_VIEW_INSTANCE_TYPE))
+#define GAL_IS_VIEW_INSTANCE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), GAL_VIEW_INSTANCE_TYPE))
+
+typedef struct {
+ GtkObject base;
+
+ GalViewCollection *collection;
+
+ char *instance_id;
+ char *current_view_filename;
+ char *custom_filename;
+
+ char *current_title;
+ char *current_type;
+ char *current_id;
+
+ GalView *current_view;
+
+ guint view_changed_id;
+ guint collection_changed_id;
+
+ guint loaded : 1;
+ char *default_view;
+} GalViewInstance;
+
+typedef struct {
+ GtkObjectClass parent_class;
+
+ /*
+ * Signals
+ */
+ void (*display_view) (GalViewInstance *instance,
+ GalView *view);
+ void (*changed) (GalViewInstance *instance);
+} GalViewInstanceClass;
+
+/* Standard functions */
+GtkType gal_view_instance_get_type (void);
+
+/* */
+/*collection should be loaded when you call this.
+ instance_id: Which instance of this type of object is this (for most of evo, this is the folder id.) */
+GalViewInstance *gal_view_instance_new (GalViewCollection *collection,
+ const char *instance_id);
+GalViewInstance *gal_view_instance_construct (GalViewInstance *instance,
+ GalViewCollection *collection,
+ const char *instance_id);
+
+/* Manipulate the current view. */
+char *gal_view_instance_get_current_view_id (GalViewInstance *instance);
+void gal_view_instance_set_current_view_id (GalViewInstance *instance,
+ const char *view_id);
+GalView *gal_view_instance_get_current_view (GalViewInstance *instance);
+
+/* Sets the current view to the given custom view. */
+void gal_view_instance_set_custom_view (GalViewInstance *instance,
+ GalView *view);
+
+
+/* Returns true if this instance has ever been used before. */
+gboolean gal_view_instance_exists (GalViewInstance *instance);
+
+/* Manipulate the view collection */
+/* void gal_view_instance_set_as_default (GalViewInstance *instance); */
+void gal_view_instance_save_as (GalViewInstance *instance);
+
+/* This is idempotent. Once it's been called once, the rest of the calls are ignored. */
+void gal_view_instance_load (GalViewInstance *instance);
+
+/* These only mean anything before gal_view_instance_load is called the first time. */
+const char *gal_view_instance_get_default_view (GalViewInstance *instance);
+void gal_view_instance_set_default_view (GalViewInstance *instance,
+ const char *id);
+
+
+END_GNOME_DECLS
+
+
+#endif /* _GAL_VIEW_INSTANCE_H_ */
diff --git a/widgets/misc/e-canvas-background.c b/widgets/misc/e-canvas-background.c
new file mode 100644
index 0000000000..36b84635ed
--- /dev/null
+++ b/widgets/misc/e-canvas-background.c
@@ -0,0 +1,464 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-canvas-background.c - background color for canvas.
+ * Copyright 2001, Ximian, Inc.
+ *
+ * Authors:
+ * Chris Lahey <clahey@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "e-canvas-background.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include "gal/widgets/e-hsv-utils.h"
+#include "gal/widgets/e-canvas.h"
+#include "gal/widgets/e-canvas-utils.h"
+#include "gal/util/e-util.h"
+#include <string.h>
+
+#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
+
+#define d(x)
+
+struct _ECanvasBackgroundPrivate {
+ guint rgba; /* Fill color, RGBA */
+ GdkColor color; /* Fill color */
+ GdkBitmap *stipple; /* Stipple for fill */
+ GdkGC *gc; /* GC for filling */
+ double x1;
+ double x2;
+ double y1;
+ double y2;
+
+ guint needs_redraw : 1;
+};
+
+static GnomeCanvasItemClass *parent_class;
+
+enum {
+ ARG_0,
+ ARG_FILL_COLOR,
+ ARG_FILL_COLOR_GDK,
+ ARG_FILL_COLOR_RGBA,
+ ARG_FILL_STIPPLE,
+ ARG_X1,
+ ARG_X2,
+ ARG_Y1,
+ ARG_Y2,
+};
+
+static void
+get_color(ECanvasBackground *ecb)
+{
+ int n;
+ GnomeCanvasItem *item = GNOME_CANVAS_ITEM (ecb);
+
+ n = 0;
+ gdk_color_context_get_pixels (item->canvas->cc,
+ &ecb->priv->color.red,
+ &ecb->priv->color.green,
+ &ecb->priv->color.blue,
+ 1,
+ &ecb->priv->color.pixel,
+ &n);
+}
+
+static void
+ecb_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
+{
+ double i2c [6];
+ ArtPoint c1, c2, i1, i2;
+ ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item);
+
+ /* Wrong BBox's are the source of redraw nightmares */
+
+ gnome_canvas_item_i2c_affine (GNOME_CANVAS_ITEM (ecb), i2c);
+
+ i1.x = ecb->priv->x1;
+ i1.y = ecb->priv->y1;
+ i2.x = ecb->priv->x2;
+ i2.y = ecb->priv->y2;
+ art_affine_point (&c1, &i1, i2c);
+ art_affine_point (&c2, &i2, i2c);
+
+ if (ecb->priv->x1 < 0)
+ c1.x = -(double)UINT_MAX;
+
+ if (ecb->priv->y1 < 0)
+ c1.y = -(double)UINT_MAX;
+
+ if (ecb->priv->x2 < 0)
+ c2.x = (double)UINT_MAX;
+
+ if (ecb->priv->y2 < 0)
+ c2.y = (double)UINT_MAX;
+
+ *x1 = c1.x;
+ *y1 = c1.y;
+ *x2 = c2.x + 1;
+ *y2 = c2.y + 1;
+}
+
+/*
+ * GnomeCanvasItem::update method
+ */
+static void
+ecb_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ ArtPoint o1, o2;
+ ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item);
+
+ if (GNOME_CANVAS_ITEM_CLASS (parent_class)->update)
+ GNOME_CANVAS_ITEM_CLASS (parent_class)->update (item, affine, clip_path, flags);
+
+ o1.x = item->x1;
+ o1.y = item->y1;
+ o2.x = item->x2;
+ o2.y = item->y2;
+
+ ecb_bounds (item, &item->x1, &item->y1, &item->x2, &item->y2);
+ if (item->x1 != o1.x ||
+ item->y1 != o1.y ||
+ item->x2 != o2.x ||
+ item->y2 != o2.y) {
+ gnome_canvas_request_redraw (item->canvas, o1.x, o1.y, o2.x, o2.y);
+ ecb->priv->needs_redraw = 1;
+ }
+
+ if (ecb->priv->needs_redraw) {
+ gnome_canvas_request_redraw (item->canvas, item->x1, item->y1,
+ item->x2, item->y2);
+ ecb->priv->needs_redraw = 0;
+ }
+}
+
+/* Sets the stipple pattern for the text */
+static void
+set_stipple (ECanvasBackground *ecb, GdkBitmap *stipple, int use_value)
+{
+ if (use_value) {
+ if (ecb->priv->stipple)
+ gdk_bitmap_unref (ecb->priv->stipple);
+
+ ecb->priv->stipple = stipple;
+ if (stipple)
+ gdk_bitmap_ref (stipple);
+ }
+
+ if (ecb->priv->gc) {
+ if (stipple) {
+ gdk_gc_set_stipple (ecb->priv->gc, stipple);
+ gdk_gc_set_fill (ecb->priv->gc, GDK_STIPPLED);
+ } else
+ gdk_gc_set_fill (ecb->priv->gc, GDK_SOLID);
+ }
+}
+
+static void
+ecb_destroy (GtkObject *object)
+{
+ ECanvasBackground *ecb = E_CANVAS_BACKGROUND (object);
+
+ if (ecb->priv->stipple)
+ gdk_bitmap_unref (ecb->priv->stipple);
+ ecb->priv->stipple = NULL;
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+ecb_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ GnomeCanvasItem *item;
+ ECanvasBackground *ecb;
+
+ GdkColor color = { 0, 0, 0, 0, };
+ GdkColor *pcolor;
+ gboolean color_changed = FALSE;
+
+ item = GNOME_CANVAS_ITEM (o);
+ ecb = E_CANVAS_BACKGROUND (o);
+
+ switch (arg_id){
+ case ARG_FILL_COLOR:
+ if (GTK_VALUE_STRING (*arg))
+ gdk_color_parse (GTK_VALUE_STRING (*arg), &color);
+
+ ecb->priv->rgba = ((color.red & 0xff00) << 16 |
+ (color.green & 0xff00) << 8 |
+ (color.blue & 0xff00) |
+ 0xff);
+ color_changed = TRUE;
+ break;
+
+ case ARG_FILL_COLOR_GDK:
+ pcolor = GTK_VALUE_BOXED (*arg);
+ if (pcolor) {
+ color = *pcolor;
+ }
+
+ ecb->priv->rgba = ((color.red & 0xff00) << 16 |
+ (color.green & 0xff00) << 8 |
+ (color.blue & 0xff00) |
+ 0xff);
+ color_changed = TRUE;
+ break;
+
+ case ARG_FILL_COLOR_RGBA:
+ ecb->priv->rgba = GTK_VALUE_UINT (*arg);
+ color.red = ((ecb->priv->rgba >> 24) & 0xff) * 0x101;
+ color.green = ((ecb->priv->rgba >> 16) & 0xff) * 0x101;
+ color.blue = ((ecb->priv->rgba >> 8) & 0xff) * 0x101;
+ color_changed = TRUE;
+ break;
+
+ case ARG_FILL_STIPPLE:
+ set_stipple (ecb, GTK_VALUE_BOXED (*arg), TRUE);
+ break;
+
+ case ARG_X1:
+ ecb->priv->x1 = GTK_VALUE_DOUBLE (*arg);
+ break;
+ case ARG_X2:
+ ecb->priv->x2 = GTK_VALUE_DOUBLE (*arg);
+ break;
+ case ARG_Y1:
+ ecb->priv->y1 = GTK_VALUE_DOUBLE (*arg);
+ break;
+ case ARG_Y2:
+ ecb->priv->y2 = GTK_VALUE_DOUBLE (*arg);
+ break;
+ }
+
+ if (color_changed) {
+ ecb->priv->color = color;
+
+ if (GNOME_CANVAS_ITEM_REALIZED & GTK_OBJECT_FLAGS(item)) {
+ get_color (ecb);
+ if (!item->canvas->aa) {
+ gdk_gc_set_foreground (ecb->priv->gc, &ecb->priv->color);
+ }
+ }
+ }
+
+ ecb->priv->needs_redraw = 1;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(ecb));
+}
+
+static void
+ecb_get_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ GnomeCanvasItem *item;
+ ECanvasBackground *ecb;
+
+ item = GNOME_CANVAS_ITEM (o);
+ ecb = E_CANVAS_BACKGROUND (o);
+
+ switch (arg_id){
+ case ARG_FILL_COLOR_GDK:
+ GTK_VALUE_BOXED (*arg) = gdk_color_copy (&ecb->priv->color);
+ break;
+ case ARG_FILL_COLOR_RGBA:
+ GTK_VALUE_UINT (*arg) = ecb->priv->rgba;
+ break;
+ case ARG_FILL_STIPPLE:
+ GTK_VALUE_BOXED (*arg) = ecb->priv->stipple;
+ break;
+ case ARG_X1:
+ GTK_VALUE_DOUBLE (*arg) = ecb->priv->x1;
+ break;
+ case ARG_X2:
+ GTK_VALUE_DOUBLE (*arg) = ecb->priv->x2;
+ break;
+ case ARG_Y1:
+ GTK_VALUE_DOUBLE (*arg) = ecb->priv->y1;
+ break;
+ case ARG_Y2:
+ GTK_VALUE_DOUBLE (*arg) = ecb->priv->y2;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+ecb_init (GnomeCanvasItem *item)
+{
+ ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item);
+
+ ecb->priv = g_new (ECanvasBackgroundPrivate, 1);
+
+ ecb->priv->color = (GdkColor) {0,};
+ ecb->priv->stipple = NULL;
+ ecb->priv->gc = NULL;
+ ecb->priv->x1 = -1.0;
+ ecb->priv->x2 = -1.0;
+ ecb->priv->y1 = -1.0;
+ ecb->priv->y2 = -1.0;
+}
+
+static void
+ecb_realize (GnomeCanvasItem *item)
+{
+ ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item);
+
+ if (GNOME_CANVAS_ITEM_CLASS (parent_class)->realize)
+ GNOME_CANVAS_ITEM_CLASS (parent_class)->realize (item);
+
+ ecb->priv->gc = gdk_gc_new (item->canvas->layout.bin_window);
+ get_color (ecb);
+ if (!item->canvas->aa)
+ gdk_gc_set_foreground (ecb->priv->gc, &ecb->priv->color);
+
+ set_stipple (ecb, NULL, FALSE);
+
+ ecb->priv->needs_redraw = 1;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (ecb));
+}
+
+static void
+ecb_unrealize (GnomeCanvasItem *item)
+{
+ ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item);
+
+ gdk_gc_unref (ecb->priv->gc);
+ ecb->priv->gc = NULL;
+
+ if (GNOME_CANVAS_ITEM_CLASS (parent_class)->unrealize)
+ GNOME_CANVAS_ITEM_CLASS (parent_class)->unrealize (item);
+}
+
+static void
+ecb_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height)
+{
+ ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item);
+ int x1, x2, y1, y2;
+ double i2c [6];
+ ArtPoint upper_left, lower_right, ecb_base_point;
+
+ /*
+ * Find out our real position after grouping
+ */
+ gnome_canvas_item_i2c_affine (item, i2c);
+ ecb_base_point.x = ecb->priv->x1;
+ ecb_base_point.y = ecb->priv->y1;
+ art_affine_point (&upper_left, &ecb_base_point, i2c);
+
+ ecb_base_point.x = ecb->priv->x2;
+ ecb_base_point.y = ecb->priv->y2;
+ art_affine_point (&lower_right, &ecb_base_point, i2c);
+
+ x1 = 0;
+ y1 = 0;
+ x2 = width;
+ y2 = height;
+ if (ecb->priv->x1 >= 0 && upper_left.x > x1)
+ x1 = upper_left.x;
+ if (ecb->priv->y1 >= 0 && upper_left.y > y1)
+ y1 = upper_left.y;
+ if (ecb->priv->x2 >= 0 && lower_right.x < x2)
+ x2 = lower_right.x;
+ if (ecb->priv->y2 >= 0 && lower_right.y < y2)
+ y2 = lower_right.y;
+
+ gdk_draw_rectangle (drawable, ecb->priv->gc, TRUE,
+ x1, y1, x2 - x1, y2 - y1);
+}
+
+static double
+ecb_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
+ GnomeCanvasItem **actual_item)
+{
+ ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item);
+
+ if (ecb->priv->x1 >= 0 && ecb->priv->x1 > x)
+ return 1.0;
+ if (ecb->priv->x2 >= 0 && ecb->priv->x2 < x)
+ return 1.0;
+ if (ecb->priv->y1 >= 0 && ecb->priv->y1 > y)
+ return 1.0;
+ if (ecb->priv->y2 >= 0 && ecb->priv->y2 < y)
+ return 1.0;
+ *actual_item = item;
+
+ return 0.0;
+}
+
+static void
+ecb_class_init (GtkObjectClass *object_class)
+{
+ GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
+
+ parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
+
+ object_class->destroy = ecb_destroy;
+ object_class->set_arg = ecb_set_arg;
+ object_class->get_arg = ecb_get_arg;
+
+ item_class->update = ecb_update;
+ item_class->realize = ecb_realize;
+ item_class->unrealize = ecb_unrealize;
+ item_class->draw = ecb_draw;
+ item_class->point = ecb_point;
+
+ gtk_object_add_arg_type ("ECanvasBackground::fill_color", GTK_TYPE_STRING,
+ GTK_ARG_WRITABLE, ARG_FILL_COLOR);
+ gtk_object_add_arg_type ("ECanvasBackground::fill_color_gdk", GTK_TYPE_GDK_COLOR,
+ GTK_ARG_READWRITE, ARG_FILL_COLOR_GDK);
+ gtk_object_add_arg_type ("ECanvasBackground::fill_color_rgba", GTK_TYPE_UINT,
+ GTK_ARG_READWRITE, ARG_FILL_COLOR_RGBA);
+ gtk_object_add_arg_type ("ECanvasBackground::fill_stipple", GTK_TYPE_GDK_WINDOW,
+ GTK_ARG_READWRITE, ARG_FILL_STIPPLE);
+ gtk_object_add_arg_type ("ECanvasBackground::x1", GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE, ARG_X1);
+ gtk_object_add_arg_type ("ECanvasBackground::x2", GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE, ARG_X2);
+ gtk_object_add_arg_type ("ECanvasBackground::y1", GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE, ARG_Y1);
+ gtk_object_add_arg_type ("ECanvasBackground::y2", GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE, ARG_Y2);
+}
+
+GtkType
+e_canvas_background_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ECanvasBackground",
+ sizeof (ECanvasBackground),
+ sizeof (ECanvasBackgroundClass),
+ (GtkClassInitFunc) ecb_class_init,
+ (GtkObjectInitFunc) ecb_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
+ }
+
+ return type;
+}
diff --git a/widgets/misc/e-canvas-background.h b/widgets/misc/e-canvas-background.h
new file mode 100644
index 0000000000..b0c28e099f
--- /dev/null
+++ b/widgets/misc/e-canvas-background.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-canvas-background.h - background color for canvas.
+ * Copyright 2001, Ximian, Inc.
+ *
+ * Authors:
+ * Chris Lahey <clahey@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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_CANVAS_BACKGROUND_H
+#define E_CANVAS_BACKGROUND_H
+
+#include <libgnome/gnome-defs.h>
+#include <libgnomeui/gnome-canvas.h>
+
+BEGIN_GNOME_DECLS
+
+/*
+ * name type read/write description
+ * ------------------------------------------------------------------------------------------
+ * fill_color string W X color specification for fill color,
+ * or NULL pointer for no color (transparent)
+ * fill_color_gdk GdkColor* RW Allocated GdkColor for fill
+ * fill_stipple GdkBitmap* RW Stipple pattern for fill
+ * x1 double RW Coordinates for edges of background rectangle
+ * x2 double RW Default is all of them = -1.
+ * y1 double RW Which means that the entire space is shown.
+ * y2 double RW If you need the rectangle to have negative coordinates, use an affine.
+ */
+
+
+#define E_CANVAS_BACKGROUND_TYPE (e_canvas_background_get_type ())
+#define E_CANVAS_BACKGROUND(obj) (GTK_CHECK_CAST ((obj), E_CANVAS_BACKGROUND_TYPE, ECanvasBackground))
+#define E_CANVAS_BACKGROUND_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_CANVAS_BACKGROUND_TYPE, ECanvasBackgroundClass))
+#define E_IS_CANVAS_BACKGROUND(obj) (GTK_CHECK_TYPE ((obj), E_CANVAS_BACKGROUND_TYPE))
+#define E_IS_CANVAS_BACKGROUND_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_CANVAS_BACKGROUND_TYPE))
+
+typedef struct _ECanvasBackground ECanvasBackground;
+typedef struct _ECanvasBackgroundClass ECanvasBackgroundClass;
+typedef struct _ECanvasBackgroundPrivate ECanvasBackgroundPrivate;
+
+struct _ECanvasBackground {
+ GnomeCanvasItem item;
+
+ ECanvasBackgroundPrivate *priv;
+};
+
+struct _ECanvasBackgroundClass {
+ GnomeCanvasItemClass parent_class;
+};
+
+
+/* Standard Gtk function */
+GtkType e_canvas_background_get_type (void);
+
+END_GNOME_DECLS
+
+#endif
+
+
+
+
+
+
+
+
+
+
diff --git a/widgets/table/e-cell-progress.c b/widgets/table/e-cell-progress.c
new file mode 100644
index 0000000000..41edac7ef3
--- /dev/null
+++ b/widgets/table/e-cell-progress.c
@@ -0,0 +1,450 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-cell-progress.c - Progress display cell object.
+ * Copyright 1999-2002, Ximian, Inc.
+ * Copyright 2001, 2002, Krisztian Pifko <monsta@users.sourceforge.net>
+ *
+ * Authors:
+ * Krisztian Pifko <monsta@users.sourceforge.net>
+ *
+ * A cell type for displaying progress bars.
+ *
+ * Derived from ECellToggle of Miguel de Icaza <miguel@ximian.com>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 <gtk/gtkenums.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell-progress.h"
+#include "gal/util/e-util.h"
+#include "e-table-item.h"
+
+#define PARENT_TYPE e_cell_get_type ()
+
+typedef struct {
+ ECellView cell_view;
+ GdkGC *gc;
+ GnomeCanvas *canvas;
+} ECellProgressView;
+
+static ECellClass *parent_class;
+
+static void
+eprog_queue_redraw (ECellProgressView *text_view, int view_col, int view_row)
+{
+ e_table_item_redraw_range (
+ text_view->cell_view.e_table_item_view,
+ view_col, view_row, view_col, view_row);
+}
+
+/*
+ * ECell::realize method
+ */
+static ECellView *
+eprog_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view)
+{
+ ECellProgressView *progress_view = g_new0 (ECellProgressView, 1);
+ ETableItem *eti = E_TABLE_ITEM (e_table_item_view);
+ GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
+
+ progress_view->cell_view.ecell = ecell;
+ progress_view->cell_view.e_table_model = table_model;
+ progress_view->cell_view.e_table_item_view = e_table_item_view;
+ progress_view->canvas = canvas;
+
+ return (ECellView *) progress_view;
+}
+
+static void
+eprog_kill_view (ECellView *ecell_view)
+{
+ g_free (ecell_view);
+}
+
+static void
+eprog_realize (ECellView *ecell_view)
+{
+ ECellProgressView *progress_view = (ECellProgressView *) ecell_view;
+
+ progress_view->gc = gdk_gc_new (GTK_WIDGET (progress_view->canvas)->window);
+}
+
+/*
+ * ECell::unrealize method
+ */
+static void
+eprog_unrealize (ECellView *ecv)
+{
+ ECellProgressView *progress_view = (ECellProgressView *) ecv;
+
+ gdk_gc_unref (progress_view->gc);
+ progress_view->gc = NULL;
+}
+
+static void
+eprog_clear (ECellProgress *progress)
+{
+ memset(progress->buffer,0x00,progress->width*progress->height*4);
+}
+
+static void
+eprog_draw_border (ECellProgress *progress, guchar red, guchar green, guchar blue)
+{
+ gint i, j, w4, p4, pw4, wpb4, hp1;
+
+/*
+ * some speedup
+ */
+ w4=progress->width*4;
+ p4=progress->padding*4;
+ pw4=w4*progress->padding;
+ wpb4=(progress->width-progress->padding-progress->border)*4;
+ hp1=(progress->height-progress->padding-1);
+
+ for (i=progress->padding*4;i<(progress->width-progress->padding)*4;i+=4){
+ for (j=0;j<progress->border;j++){
+ progress->buffer[pw4+j*w4+i]=red;
+ progress->buffer[pw4+j*w4+i+1]=green;
+ progress->buffer[pw4+j*w4+i+2]=blue;
+ progress->buffer[pw4+j*w4+i+3]=255;
+ progress->buffer[(progress->height-1-progress->padding)*w4-j*w4+i]=red;
+ progress->buffer[(progress->height-1-progress->padding)*w4-j*w4+i+1]=green;
+ progress->buffer[(progress->height-1-progress->padding)*w4-j*w4+i+2]=blue;
+ progress->buffer[(progress->height-1-progress->padding)*w4-j*w4+i+3]=255;
+ }
+ }
+ for (i=progress->padding+progress->border;i<progress->height-progress->padding-progress->border;i++){
+ for (j=0;j<4*progress->border;j+=4){
+ progress->buffer[p4+i*w4+j]=red;
+ progress->buffer[p4+i*w4+j+1]=green;
+ progress->buffer[p4+i*w4+j+2]=blue;
+ progress->buffer[p4+i*w4+j+3]=255;
+ progress->buffer[i*w4+wpb4+j]=red;
+ progress->buffer[i*w4+wpb4+j+1]=green;
+ progress->buffer[i*w4+wpb4+j+2]=blue;
+ progress->buffer[i*w4+wpb4+j+3]=255;
+ }
+ }
+}
+
+static void
+eprog_draw_bar (ECellProgress *progress, guchar red, guchar green, guchar blue, gint value)
+{
+ gint i, j, w;
+
+ w=value*(progress->width-2*(progress->padding+progress->border+1))/progress->max;
+ for (i=(progress->padding+progress->border+1)*4;i<(progress->padding+progress->border+1+w)*4;i+=4){
+ for (j=0;j<progress->height-2*(progress->padding+progress->border+1);j++){
+ progress->buffer[(progress->width*(progress->padding+progress->border+1)*4)+j*progress->width*4+i]=red;
+ progress->buffer[(progress->width*(progress->padding+progress->border+1)*4)+j*progress->width*4+i+1]=green;
+ progress->buffer[(progress->width*(progress->padding+progress->border+1)*4)+j*progress->width*4+i+2]=blue;
+ progress->buffer[(progress->width*(progress->padding+progress->border+1)*4)+j*progress->width*4+i+3]=255;
+ }
+ }
+}
+
+/*
+ * ECell::draw method
+ */
+static void
+eprog_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int model_col, int view_col, int row, ECellFlags flags,
+ int x1, int y1, int x2, int y2)
+{
+ ECellProgress *progress = E_CELL_PROGRESS (ecell_view->ecell);
+ gboolean selected;
+ GdkPixbuf *image;
+ int x, y, width, height;
+
+ const int value = GPOINTER_TO_INT (
+ e_table_model_value_at (ecell_view->e_table_model, model_col, row));
+
+ selected = flags & E_CELL_SELECTED;
+
+ if ((value > progress->max)||(value < progress->min)){
+ g_warning ("Value from the table model is %d, the states we support are [%d..%d]\n",
+ value, progress->min, progress->max);
+ return;
+ }
+
+ image = progress->image;
+
+ if ((x2 - x1) < progress->width){
+ x = x1;
+ width = x2 - x1;
+ } else {
+ x = x1 + ((x2 - x1) - progress->width) / 2;
+ width = progress->width;
+ }
+
+ if ((y2 - y1) < progress->height){
+ y = y1;
+ height = y2 - y1;
+ } else {
+ y = y1 + ((y2 - y1) - progress->height) / 2;
+ height = progress->height;
+ }
+
+ eprog_clear(progress);
+
+ eprog_draw_border(progress, progress->red, progress->green, progress->blue);
+
+ eprog_draw_bar(progress, progress->red, progress->green, progress->blue, value);
+
+ gdk_pixbuf_render_to_drawable_alpha (progress->image, drawable,
+ 0, 0,
+ x, y,
+ progress->width, progress->height,
+ GDK_PIXBUF_ALPHA_BILEVEL,
+ 128,
+ GDK_RGB_DITHER_NORMAL,
+ x, y);
+}
+
+static void
+eprog_set_value (ECellProgressView *progress_view, int model_col, int view_col, int row, int value)
+{
+ ECell *ecell = progress_view->cell_view.ecell;
+ ECellProgress *progress = E_CELL_PROGRESS (ecell);
+
+ if (value > progress->max){
+ value = progress->max;
+ }else if (value < progress->min){
+ value = progress->min;
+ }
+ e_table_model_set_value_at (progress_view->cell_view.e_table_model,
+ model_col, row, GINT_TO_POINTER (value));
+ eprog_queue_redraw (progress_view, view_col, row);
+}
+
+/*
+ * ECell::event method
+ */
+static gint
+eprog_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row, ECellFlags flags, ECellActions *actions)
+{
+ ECellProgressView *progress_view = (ECellProgressView *) ecell_view;
+ void *_value = e_table_model_value_at (ecell_view->e_table_model, model_col, row);
+ const int value = GPOINTER_TO_INT (_value);
+
+#if 0
+ if (!(flags & E_CELL_EDITING))
+ return FALSE;
+#endif
+
+ switch (event->type){
+ case GDK_KEY_PRESS:
+ if (event->key.keyval != GDK_space)
+ return FALSE;
+ /* Fall through */
+ case GDK_BUTTON_PRESS:
+ if (!e_table_model_is_cell_editable(ecell_view->e_table_model, model_col, row))
+ return FALSE;
+
+ eprog_set_value (progress_view, model_col, view_col, row, value + 1);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * ECell::height method
+ */
+static int
+eprog_height (ECellView *ecell_view, int model_col, int view_col, int row)
+{
+ ECellProgress *progress = E_CELL_PROGRESS (ecell_view->ecell);
+
+ return progress->height;
+}
+
+/*
+ * ECell::max_width method
+ */
+static int
+eprog_max_width (ECellView *ecell_view, int model_col, int view_col)
+{
+ ECellProgress *progress = E_CELL_PROGRESS (ecell_view->ecell);
+
+ return progress->width;
+}
+
+static void
+eprog_destroy (GtkObject *object)
+{
+ ECellProgress *eprog = E_CELL_PROGRESS (object);
+
+ gdk_pixbuf_unref (eprog->image);
+ g_free (eprog->image);
+ g_free (eprog->buffer);
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+e_cell_progress_class_init (GtkObjectClass *object_class)
+{
+ ECellClass *ecc = (ECellClass *) object_class;
+
+ object_class->destroy = eprog_destroy;
+
+ ecc->new_view = eprog_new_view;
+ ecc->kill_view = eprog_kill_view;
+ ecc->realize = eprog_realize;
+ ecc->unrealize = eprog_unrealize;
+ ecc->draw = eprog_draw;
+ ecc->event = eprog_event;
+ ecc->height = eprog_height;
+ ecc->max_width = eprog_max_width;
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+}
+
+E_MAKE_TYPE(e_cell_progress, "ECellProgress", ECellProgress, e_cell_progress_class_init, NULL, PARENT_TYPE);
+
+/**
+ * e_cell_progress_construct:
+ * @eprog: a fresh ECellProgress object
+ * @padding: number of pixels used as a padding
+ * @border: number of pixels used as a border
+ * @min: the minimum value
+ * @max: the maximum value
+ * @width: the width of the progress bar in pixels
+ * @height: the height of the progress bar in pixels
+ * @red: the red component of the progress bars rgb color
+ * @green: the green component of the progress bars rgb color
+ * @blue: the blue component of the progress bars rgb color
+ *
+ * Constructs the @eprog object with the arguments
+ */
+void
+e_cell_progress_construct (ECellProgress *eprog, int padding, int border, int min, int max, int width, int height, guchar red, guchar green, guchar blue)
+{
+ eprog->padding = padding;
+ eprog->border = border;
+ eprog->min = min;
+ eprog->max = max;
+ eprog->red = red;
+ eprog->green = green;
+ eprog->blue = blue;
+
+ eprog->width = (width<((padding+border)*2+5)) ? ((padding+border)*2+5) : width;
+ eprog->height = (height<((padding+border)*2+5)) ? ((padding+border)*2+5) : height;
+
+ eprog->buffer=g_new(guchar, eprog->width*eprog->height*4);
+
+ eprog_clear(eprog);
+ eprog_draw_border(eprog, red, green, blue);
+
+ eprog->image = gdk_pixbuf_new_from_data (eprog->buffer,GDK_COLORSPACE_RGB, TRUE, 8, eprog->width, eprog->height, eprog->width*4, NULL, NULL);
+}
+
+/**
+ * e_cell_progress_new:
+ * @min: the minimum value
+ * @max: the maximum value
+ * @width: the width of the progress bar in pixels
+ * @height: the height of the progress bar in pixels
+ *
+ * Creates a new ECell renderer that can be used to render progress
+ * bars displaying the percentage of the current value between min
+ * and max.
+ *
+ * Returns: an ECell object that can be used to render progress cells.
+ */
+ECell *
+e_cell_progress_new (int min, int max, int width, int height)
+{
+ ECellProgress *eprog = gtk_type_new (e_cell_progress_get_type ());
+
+ e_cell_progress_construct (eprog, 1, 1, min, max, (width<9) ? 9 : width, (height<9) ? 9 : height, 0x00, 0x00, 0x00);
+
+ return (ECell *) eprog;
+}
+
+/**
+ * e_cell_progress_set_padding:
+ * @eprog: an ECellProgress object
+ * @padding: number of pixels used as a padding
+ *
+ * Sets the padding around the progress bar in the cell.
+ */
+void
+e_cell_progress_set_padding (ECellProgress *eprog, int padding)
+{
+ eprog->padding = padding;
+
+ eprog->width = (eprog->width<((padding+eprog->border)*2+5)) ? ((padding+eprog->border)*2+5) : eprog->width;
+ eprog->height = (eprog->height<((padding+eprog->border)*2+5)) ? ((padding+eprog->border)*2+5) : eprog->height;
+
+ g_free (eprog->buffer);
+ eprog->buffer=g_new (guchar, eprog->width*eprog->height*4);
+
+ eprog_clear (eprog);
+ eprog_draw_border (eprog, eprog->red, eprog->green, eprog->blue);
+
+ eprog->image = gdk_pixbuf_new_from_data (eprog->buffer,GDK_COLORSPACE_RGB, TRUE, 8, eprog->width, eprog->height, eprog->width*4, NULL, NULL);
+}
+
+/**
+ * e_cell_progress_set_border:
+ * @eprog: an ECellProgress object
+ * @border: number of pixels used as a border
+ *
+ * Sets the border around the progress bar in the cell.
+ */
+void
+e_cell_progress_set_border (ECellProgress *eprog, int border)
+{
+ eprog->border = border;
+
+ eprog->width = (eprog->width<((eprog->padding+border)*2+5)) ? ((eprog->padding+border)*2+5) : eprog->width;
+ eprog->height = (eprog->height<((eprog->padding+border)*2+5)) ? ((eprog->padding+border)*2+5) : eprog->height;
+
+ g_free (eprog->buffer);
+ eprog->buffer=g_new (guchar, eprog->width*eprog->height*4);
+
+ eprog_clear (eprog);
+ eprog_draw_border (eprog, eprog->red, eprog->green, eprog->blue);
+
+ eprog->image = gdk_pixbuf_new_from_data (eprog->buffer,GDK_COLORSPACE_RGB, TRUE, 8, eprog->width, eprog->height, eprog->width*4, NULL, NULL);
+}
+
+/**
+ * e_cell_progress_set_color:
+ * @eprog: a fresh ECellProgress object
+ * @red: the red component of the progress bars rgb color
+ * @green: the green component of the progress bars rgb color
+ * @blue: the blue component of the progress bars rgb color
+ */
+void
+e_cell_progress_set_color (ECellProgress *eprog, guchar red, guchar green, guchar blue)
+{
+ eprog->red = red;
+ eprog->green = green;
+ eprog->blue = blue;
+
+ eprog_clear (eprog);
+ eprog_draw_border (eprog, red, green, blue);
+}
diff --git a/widgets/table/e-cell-progress.h b/widgets/table/e-cell-progress.h
new file mode 100644
index 0000000000..4cd09ed0de
--- /dev/null
+++ b/widgets/table/e-cell-progress.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-cell-progress.h - Progress display cell object.
+ * Copyright 1999-2002, Ximian, Inc.
+ * Copyright 2001, 2002, Krisztian Pifko <monsta@users.sourceforge.net>
+ *
+ * Authors:
+ * Krisztian Pifko <monsta@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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_CELL_PROGRESS_H_
+#define _E_CELL_PROGRESS_H_
+
+#include <libgnomeui/gnome-canvas.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gal/e-table/e-cell.h>
+
+BEGIN_GNOME_DECLS
+
+#define E_CELL_PROGRESS_TYPE (e_cell_progress_get_type ())
+#define E_CELL_PROGRESS(o) (GTK_CHECK_CAST ((o), E_CELL_PROGRESS_TYPE, ECellProgress))
+#define E_CELL_PROGRESS_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_PROGRESS_TYPE, ECellProgressClass))
+#define E_IS_CELL_PROGRESS(o) (GTK_CHECK_TYPE ((o), E_CELL_PROGRESS_TYPE))
+#define E_IS_CELL_PROGRESS_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_PROGRESS_TYPE))
+
+typedef struct {
+ ECell parent;
+
+ int padding;
+ int border;
+ int min;
+ int max;
+ guchar red;
+ guchar green;
+ guchar blue;
+
+ guchar *buffer;
+ GdkPixbuf *image;
+
+ int width;
+ int height;
+} ECellProgress;
+
+typedef struct {
+ ECellClass parent_class;
+} ECellProgressClass;
+
+GtkType e_cell_progress_get_type (void);
+ECell *e_cell_progress_new (int min, int max, int width, int height);
+void e_cell_progress_construct (ECellProgress *eprog, int padding, int border,
+ int min, int max, int width, int height, guchar red, guchar green, guchar blue);
+void e_cell_progress_set_padding (ECellProgress *eprog, int padding);
+void e_cell_progress_set_border (ECellProgress *eprog, int border);
+void e_cell_progress_set_color (ECellProgress *eprog, guchar red, guchar green, guchar blue);
+
+END_GNOME_DECLS
+
+#endif /* _E_CELL_PROGRESS_H_ */
+
+