gnm-validation-combo-view.c 6.7 KB
Newer Older
Jody Goldberg's avatar
Jody Goldberg committed
1 2 3
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
4 5
 * gnm-validation-combo-view.c: A canvas object for Validate from list
 * 				in cell combos
Jody Goldberg's avatar
Jody Goldberg committed
6 7 8 9
 *
 * Copyright (C) 2006 Jody Goldberg (jody@gnome.org)
 *
 * This program is free software; you can redistribute it and/or
10 11 12
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) version 3.
Jody Goldberg's avatar
Jody Goldberg committed
13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

#include <gnumeric-config.h>
26 27
#include "gnm-validation-combo-view.h"
#include "gnm-cell-combo-view-impl.h"
Jody Goldberg's avatar
Jody Goldberg committed
28

29
#include "validation-combo.h"
Jody Goldberg's avatar
Jody Goldberg committed
30 31 32 33 34 35 36 37 38 39 40
#include "commands.h"
#include "gnm-format.h"
#include "workbook-control.h"
#include "workbook.h"
#include "sheet-control-gui.h"
#include "sheet-view.h"
#include "sheet.h"
#include "cell.h"
#include "expr.h"
#include "value.h"

41
#include "gnumeric.h"
42
#include <goffice/goffice.h>
Jody Goldberg's avatar
Jody Goldberg committed
43
#include <gsf/gsf-impl-utils.h>
44
#include <gtk/gtk.h>
Jody Goldberg's avatar
Jody Goldberg committed
45 46 47
#include <glib/gi18n-lib.h>
#include <string.h>

48
static gboolean
Jody Goldberg's avatar
Jody Goldberg committed
49 50
vcombo_activate (SheetObject *so, GtkTreeView *list, WBCGtk *wbcg,
		 G_GNUC_UNUSED gboolean button)
Jody Goldberg's avatar
Jody Goldberg committed
51
{
52 53
	GnmValidationCombo *vcombo = GNM_VALIDATION_COMBO (so);
	GtkTreeIter	    iter;
Jody Goldberg's avatar
Jody Goldberg committed
54

55
	if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (list), NULL, &iter)) {
56
		SheetView	*sv  = vcombo->parent.sv;
57
		char		*strval;
Jody Goldberg's avatar
Jody Goldberg committed
58 59 60
		gtk_tree_model_get (gtk_tree_view_get_model (list), &iter,
			1, &strval,
			-1);
Morten Welinder's avatar
Morten Welinder committed
61
		cmd_set_text (GNM_WBC (wbcg),
62
			      sv_sheet (sv), &sv->edit_pos, strval, NULL, TRUE);
63
		g_free (strval);
Jody Goldberg's avatar
Jody Goldberg committed
64
	}
65
	return TRUE;
Jody Goldberg's avatar
Jody Goldberg committed
66 67 68 69 70 71 72 73 74 75 76 77
}

typedef struct {
	GHashTable *hash;
	GODateConventions const *date_conv;
} UniqueCollection;

static GnmValue *
cb_collect_unique (GnmValueIter const *iter, UniqueCollection *uc)
{
	GOFormat const *fmt = (NULL != iter->cell_iter)
		? gnm_cell_get_format (iter->cell_iter->cell) : NULL;
78
	g_hash_table_replace (uc->hash,
79
		value_dup (iter->v),
80
		format_value (fmt, iter->v, -1, uc->date_conv));
Jody Goldberg's avatar
Jody Goldberg committed
81 82 83 84 85 86 87 88 89
	return NULL;
}

static void
cb_hash_domain (GnmValue *key, gpointer value, gpointer accum)
{
	g_ptr_array_add (accum, key);
}

90
static GtkWidget *
Jody Goldberg's avatar
Jody Goldberg committed
91 92
vcombo_create_list (SheetObject *so,
		    GtkTreePath **clip, GtkTreePath **select, gboolean *make_buttons)
Jody Goldberg's avatar
Jody Goldberg committed
93
{
94
	GnmValidationCombo *vcombo = GNM_VALIDATION_COMBO (so);
Jody Goldberg's avatar
Jody Goldberg committed
95 96 97 98
	unsigned	 i;
	UniqueCollection uc;
	GnmEvalPos	 ep;
	GtkTreeIter	 iter;
99
	GtkWidget	*list;
Jody Goldberg's avatar
Jody Goldberg committed
100 101 102 103 104
	GPtrArray	*sorted;
	GtkListStore	*model;
	GnmValue	*v;
	GnmValue const	*cur_val;
	GnmValidation const *val = vcombo->validation;
105
	SheetView const *sv = vcombo->parent.sv;
Jody Goldberg's avatar
Jody Goldberg committed
106

107
	g_return_val_if_fail (val != NULL, NULL);
Andreas J. Guelzow 's avatar
Andreas J. Guelzow committed
108
	g_return_val_if_fail (val->type == GNM_VALIDATION_TYPE_IN_LIST, NULL);
109
	g_return_val_if_fail (val->deps[0].texpr != NULL, NULL);
110
	g_return_val_if_fail (sv != NULL, NULL);
Jody Goldberg's avatar
Jody Goldberg committed
111

112
	eval_pos_init_editpos (&ep, sv);
113
	v = gnm_expr_top_eval (val->deps[0].texpr, &ep,
114 115 116
			       GNM_EXPR_EVAL_PERMIT_NON_SCALAR |
			       GNM_EXPR_EVAL_PERMIT_EMPTY |
			       GNM_EXPR_EVAL_ARRAY_CONTEXT);
Jody Goldberg's avatar
Jody Goldberg committed
117
	if (NULL == v)
118
		return NULL;
Jody Goldberg's avatar
Jody Goldberg committed
119

120
	uc.date_conv = sheet_date_conv (sv->sheet);
121 122
	uc.hash = g_hash_table_new_full ((GHashFunc)value_hash, (GEqualFunc)value_equal,
		(GDestroyNotify)value_release, (GDestroyNotify)g_free);
Jody Goldberg's avatar
Jody Goldberg committed
123 124 125 126 127 128
	value_area_foreach (v, &ep, CELL_ITER_IGNORE_BLANK,
		 (GnmValueIterFunc) cb_collect_unique, &uc);
	value_release (v);

	sorted = g_ptr_array_new ();
	g_hash_table_foreach (uc.hash, (GHFunc)cb_hash_domain, sorted);
129
	g_ptr_array_sort (sorted, value_cmp);
Jody Goldberg's avatar
Jody Goldberg committed
130

131 132 133
	model = gtk_list_store_new (3,
		G_TYPE_STRING, G_TYPE_STRING, gnm_value_get_type ());

Jody Goldberg's avatar
Jody Goldberg committed
134 135 136 137
	cur_val = sheet_cell_get_value (ep.sheet, ep.eval.col, ep.eval.row);
	for (i = 0; i < sorted->len ; i++) {
		char *label = NULL;
		unsigned const max = 50;
138 139 140
		char const *str = g_hash_table_lookup (uc.hash,
			(v = g_ptr_array_index (sorted, i)));
		gsize len = g_utf8_strlen (str, -1);
Jody Goldberg's avatar
Jody Goldberg committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154

		if (len > max + 3) {
			label = g_strdup (str);
			strcpy (g_utf8_offset_to_pointer (label, max), "...");
		}

		gtk_list_store_append (model, &iter);
		gtk_list_store_set (model, &iter,
				    0, label ? label : str, /* Menu text */
				    1, str, /* Actual string selected on.  */
				    -1);
		g_free (label);
		if (i == 10)
			*clip = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
155
		if (cur_val != NULL && v != NULL && value_equal	(cur_val, v)) {
Jody Goldberg's avatar
Jody Goldberg committed
156 157 158 159 160 161 162 163
			gtk_tree_path_free (*select);
			*select = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
		}
	}

	g_hash_table_destroy (uc.hash);
	g_ptr_array_free (sorted, TRUE);

164 165 166 167 168 169 170
	list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
	g_object_unref (model);
	gtk_tree_view_append_column (GTK_TREE_VIEW (list),
		gtk_tree_view_column_new_with_attributes ("ID",
			gtk_cell_renderer_text_new (), "text", 0,
			NULL));
	return list;
Jody Goldberg's avatar
Jody Goldberg committed
171 172
}

173 174
static GtkWidget *
vcombo_create_arrow (G_GNUC_UNUSED SheetObject *so)
Jody Goldberg's avatar
Jody Goldberg committed
175
{
176
	return gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
Jody Goldberg's avatar
Jody Goldberg committed
177 178
}

179 180
/*******************************************************************************/

181 182 183 184 185
/* Somewhat magic.
 * We do not honour all of the anchor flags.  All that is used is the far corner. */
static void
vcombo_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
{
Jody Goldberg's avatar
Jody Goldberg committed
186
	GocGroup *view = GOC_GROUP (sov);
187 188

	if (visible) {
189
		double scale = goc_canvas_get_pixels_per_unit (GOC_ITEM (view)->canvas);
190
		double h = (coords[3] - coords[1]) + 1.;
191 192
		if (h > 20.)	/* clip vertically */
			h = 20.;
193
		h /= scale;
Jody Goldberg's avatar
Jody Goldberg committed
194
		goc_item_set (GOC_ITEM (view->children->data),
195
			/* put it outside the cell */
196 197
			"x",	  ((coords[2] >= 0.)? coords[2] / scale: (coords[0] / scale - h + 1.)),
			"y",	  coords [3] / scale - h + 1.,
198 199 200
			"width",  h,	/* force a square, use h for width too */
			"height", h,
			NULL);
Jody Goldberg's avatar
Jody Goldberg committed
201
		goc_item_show (GOC_ITEM (view));
202
	} else
Jody Goldberg's avatar
Jody Goldberg committed
203
		goc_item_hide (GOC_ITEM (view));
204
}
205 206 207

/****************************************************************************/

208
static void
209
gnm_validation_view_class_init (GnmCComboViewClass *ccombo_class)
210
{
211 212 213 214 215
	SheetObjectViewClass *sov_class = (SheetObjectViewClass *) ccombo_class;
	ccombo_class->create_list	= vcombo_create_list;
	ccombo_class->create_arrow	= vcombo_create_arrow;
	ccombo_class->activate		= vcombo_activate;
	sov_class->set_bounds		= vcombo_set_bounds;
216
}
217

218 219 220 221 222
typedef GnmCComboView		GnmValidationComboView;
typedef GnmCComboViewClass	GnmValidationComboViewClass;
GSF_CLASS (GnmValidationComboView, gnm_validation_combo_view,
	gnm_validation_view_class_init, NULL,
	GNM_CCOMBO_VIEW_TYPE)
223