diff options
author | nobody <nobody@localhost> | 2002-02-09 05:58:21 +0800 |
---|---|---|
committer | nobody <nobody@localhost> | 2002-02-09 05:58:21 +0800 |
commit | 9d6c701bffc3ea0a9a62dfb69cebec830c4be22c (patch) | |
tree | 69ab7e75c9309b442dd034df4d8cccc53124a0d1 | |
parent | 8df67e73f012204264933c4bb3b32a97af54acd3 (diff) | |
download | gsoc2013-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.c | 458 | ||||
-rw-r--r-- | e-util/e-iconv.h | 44 | ||||
-rw-r--r-- | widgets/menus/gal-view-instance-save-as-dialog.glade | 269 | ||||
-rw-r--r-- | widgets/menus/gal-view-instance-save-as-dialog.h | 89 | ||||
-rw-r--r-- | widgets/menus/gal-view-instance.c | 481 | ||||
-rw-r--r-- | widgets/menus/gal-view-instance.h | 115 | ||||
-rw-r--r-- | widgets/misc/e-canvas-background.c | 464 | ||||
-rw-r--r-- | widgets/misc/e-canvas-background.h | 82 | ||||
-rw-r--r-- | widgets/table/e-cell-progress.c | 450 | ||||
-rw-r--r-- | widgets/table/e-cell-progress.h | 74 |
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_ */ + + |