1.12.42
[gnumeric.git] / src / dialogs / dialog-stf-preview.c
blobd27c4f45675b4b5ece76156e67d785cab7c1df4b
1 /*
2 * dialog-stf-preview.c : by utilizing the stf-parse engine this unit can
3 * render sheet previews and offers
4 * functions for making this preview more interactive.
6 * Copyright 2001 Almer S. Tigelaar <almer@gnome.org>
7 * Copyright 2003 Morten Welinder <terra@gnome.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <https://www.gnu.org/licenses/>.
22 #include <gnumeric-config.h>
23 #include <glib/gi18n-lib.h>
24 #include <gnumeric.h>
25 #include <dialogs/dialog-stf-preview.h>
26 #include <dialogs/dialog-stf.h>
28 #include <gnm-format.h>
29 #include <number-match.h>
30 #include <value.h>
31 #include <style.h>
32 #include <string.h>
34 /******************************************************************************************************************
35 * ADVANCED DRAWING FUNCTIONS
36 ******************************************************************************************************************/
38 enum { ITEM_LINENO };
40 static void
41 line_renderer_func (GtkTreeViewColumn *tvc,
42 GtkCellRenderer *cr,
43 GtkTreeModel *model,
44 GtkTreeIter *iter,
45 gpointer user_data)
47 RenderData_t *renderdata = user_data;
48 unsigned row, col;
49 GPtrArray *line;
50 const char *text;
52 gtk_tree_model_get (model, iter, ITEM_LINENO, &row, -1);
53 col = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (tvc), "col-no"));
55 line = (renderdata->lines && row < renderdata->lines->len)
56 ? g_ptr_array_index (renderdata->lines, row)
57 : NULL;
58 text = (line && col < line->len)
59 ? g_ptr_array_index (line, col)
60 : NULL;
62 if (text) {
63 char *copy = NULL;
64 char *tab = strchr (text, '\t');
65 if (tab) {
66 copy = g_strdup (text);
67 tab = copy + (tab - text);
68 do {
69 *tab = ' ';
70 tab = strchr (tab + 1, '\t');
71 } while (tab);
72 text = copy;
76 * Throwing really long strings at Gtk+ is known to cause
77 * trouble, so cut long strings and hope no-one notices.
79 if (g_utf8_strlen (text, -1) > STF_LINE_LENGTH_LIMIT) {
80 char *cut = g_strdup (text);
81 strcpy (g_utf8_offset_to_pointer (cut, STF_LINE_LENGTH_LIMIT - 3),
82 "...");
83 g_free (copy);
84 text = copy = cut;
87 g_object_set (cr, "text", text, NULL);
88 g_free (copy);
89 } else
90 g_object_set (cr, "text", "", NULL);
93 static GtkTreeModel *
94 make_model (GPtrArray *lines)
96 GtkListStore *list_store = gtk_list_store_new (1, G_TYPE_UINT);
97 unsigned ui;
98 unsigned count = lines ? MIN (lines->len, STF_LINE_DISPLAY_LIMIT) : 0;
100 for (ui = 0; ui < count; ui++) {
101 GtkTreeIter iter;
102 gtk_list_store_append (list_store, &iter);
103 gtk_list_store_set (list_store, &iter, ITEM_LINENO, ui, -1);
106 return GTK_TREE_MODEL (list_store);
111 /******************************************************************************************************************
112 * STRUCTURE MANIPULATION FUNCTIONS
113 ******************************************************************************************************************/
116 * stf_preview_new: (skip)
117 * @data_container: a container in which to put a treeview.
119 * returns : a new renderdata struct
121 RenderData_t *
122 stf_preview_new (GtkWidget *data_container,
123 GODateConventions const *date_conv)
125 RenderData_t* renderdata;
126 GtkTreeModel *model;
128 g_return_val_if_fail (data_container != NULL, NULL);
130 renderdata = g_new (RenderData_t, 1);
132 renderdata->data_container = data_container;
133 renderdata->startrow = 1;
134 renderdata->colformats = g_ptr_array_new ();
135 renderdata->ignore_formats = FALSE;
136 renderdata->lines_chunk = NULL;
137 renderdata->lines = NULL;
139 renderdata->date_conv = date_conv;
141 model = make_model (NULL);
142 renderdata->tree_view =
143 GTK_TREE_VIEW (gtk_tree_view_new_with_model (model));
144 gtk_tree_view_set_grid_lines (renderdata->tree_view,
145 GTK_TREE_VIEW_GRID_LINES_VERTICAL);
146 g_object_ref (renderdata->tree_view);
147 g_object_unref (model);
149 renderdata->colcount = 0;
152 GtkWidget *w = GTK_WIDGET (renderdata->tree_view);
153 int width, height, vertical_separator;
154 PangoLayout *layout =
155 gtk_widget_create_pango_layout (w, "Mg19");
157 gtk_widget_style_get (w,
158 "vertical_separator", &vertical_separator,
159 NULL);
161 pango_layout_get_pixel_size (layout, &width, &height);
163 * Make room for about 80 characters and about 7 lines of data.
164 * (The +2 allows room for the headers and the h-scrollbar.
166 gtk_widget_set_size_request (renderdata->data_container,
167 width * 20, /* About 80 chars. */
168 (height + vertical_separator) * (7 + 2));
169 g_object_unref (layout);
172 gtk_container_add (GTK_CONTAINER (renderdata->data_container),
173 GTK_WIDGET (renderdata->tree_view));
174 gtk_widget_show_all (GTK_WIDGET (renderdata->tree_view));
176 return renderdata;
180 * stf_preview_free: (skip)
181 * @data: a renderdata struct
183 * This will free the @renderdata
185 void
186 stf_preview_free (RenderData_t *renderdata)
188 g_return_if_fail (renderdata != NULL);
190 stf_preview_colformats_clear (renderdata);
191 g_ptr_array_free (renderdata->colformats, TRUE);
193 stf_preview_set_lines (renderdata, NULL, NULL);
195 g_object_unref (renderdata->tree_view);
197 g_free (renderdata);
201 * stf_preview_set_lines: (skip)
203 void
204 stf_preview_set_lines (RenderData_t *renderdata,
205 GStringChunk *lines_chunk,
206 GPtrArray *lines)
208 unsigned int i;
209 int colcount = 1;
210 GtkTreeModel *model;
211 gboolean hidden;
213 g_return_if_fail (renderdata != NULL);
215 /* Empty the table. */
216 gtk_tree_view_set_model (renderdata->tree_view, NULL);
218 if (renderdata->lines != lines) {
219 if (renderdata->lines)
220 stf_parse_general_free (renderdata->lines);
221 renderdata->lines = lines;
224 if (renderdata->lines_chunk != lines_chunk) {
225 if (renderdata->lines_chunk)
226 g_string_chunk_free (renderdata->lines_chunk);
227 renderdata->lines_chunk = lines_chunk;
230 if (lines == NULL)
231 return;
233 for (i = 0; i < lines->len; i++) {
234 GPtrArray *line = g_ptr_array_index (lines, i);
235 colcount = MAX (colcount, (int)line->len);
239 * If we are making large changes we need to hide the treeview
240 * because performance otherwise suffers a lot.
242 hidden = gtk_widget_get_visible (GTK_WIDGET (renderdata->tree_view)) &&
243 (colcount < renderdata->colcount - 1 ||
244 colcount > renderdata->colcount + 10);
245 if (hidden)
246 gtk_widget_hide (GTK_WIDGET (renderdata->tree_view));
248 while (renderdata->colcount > colcount)
249 gtk_tree_view_remove_column
250 (renderdata->tree_view,
251 gtk_tree_view_get_column (renderdata->tree_view,
252 --(renderdata->colcount)));
254 while (renderdata->colcount < colcount) {
255 char *text = g_strdup_printf (_(COLUMN_CAPTION),
256 renderdata->colcount + 1);
257 GtkCellRenderer *cr = gtk_cell_renderer_text_new ();
258 GtkTreeViewColumn *tvc = gtk_tree_view_column_new ();
260 g_object_set (cr, "single_paragraph_mode", TRUE, NULL);
262 gtk_tree_view_column_set_title (tvc, text);
263 gtk_tree_view_column_set_cell_data_func
264 (tvc, cr,
265 line_renderer_func,
266 renderdata, NULL);
267 gtk_tree_view_column_pack_start (tvc, cr, TRUE);
269 g_object_set_data (G_OBJECT (tvc), "col-no",
270 GUINT_TO_POINTER (renderdata->colcount));
271 gtk_tree_view_append_column (renderdata->tree_view, tvc);
272 g_free (text);
273 renderdata->colcount++;
276 model = make_model (lines);
277 gtk_tree_view_set_model (renderdata->tree_view, model);
278 g_object_unref (model);
280 if (hidden)
281 gtk_widget_show (GTK_WIDGET (renderdata->tree_view));
285 * stf_preview_colformats_clear: (skip)
286 * @renderdata: a struct containing rendering information
288 * This will clear the @renderdata->colformats array which contains the format of
289 * each column.
291 void
292 stf_preview_colformats_clear (RenderData_t *renderdata)
294 guint i;
295 g_return_if_fail (renderdata != NULL);
297 for (i = 0; i < renderdata->colformats->len; i++)
298 go_format_unref (g_ptr_array_index (renderdata->colformats, i));
299 g_ptr_array_free (renderdata->colformats, TRUE);
300 renderdata->colformats = g_ptr_array_new ();
304 * stf_preview_colformats_add: (skip)
305 * @renderdata: a struct containing rendering information
306 * @format: the format of the column
308 * This will add an entry to the @renderdata->colformats array.
309 * The widths of the columns will be set to at least have the width of
310 * the @format.
312 * returns : nothing
314 void
315 stf_preview_colformats_add (RenderData_t *renderdata, GOFormat *format)
318 g_return_if_fail (renderdata != NULL);
319 g_return_if_fail (format != NULL);
321 g_ptr_array_add (renderdata->colformats, go_format_ref (format));
325 * stf_preview_get_column: (skip)
327 GtkTreeViewColumn *
328 stf_preview_get_column (RenderData_t *renderdata, int col)
330 return gtk_tree_view_get_column (renderdata->tree_view, col);
334 * stf_preview_get_cell_renderer: (skip)
336 GtkCellRenderer *
337 stf_preview_get_cell_renderer (RenderData_t *renderdata, int col)
339 GtkCellRenderer *res = NULL;
340 GtkTreeViewColumn *column = stf_preview_get_column (renderdata, col);
341 if (column) {
342 GList *renderers = gtk_cell_layout_get_cells
343 (GTK_CELL_LAYOUT(column));
344 if (renderers) {
345 res = renderers->data;
346 g_list_free (renderers);
349 return res;
352 void
353 stf_preview_find_column (RenderData_t *renderdata, int x, int *pcol, int *dx)
355 int col;
357 *dx = 0;
359 /* Figure out what column we pressed in. */
360 for (col = 0; TRUE; col++) {
361 int cx, cw;
362 GtkTreeViewColumn *column =
363 stf_preview_get_column (renderdata, col);
364 GtkCellRenderer *cell =
365 stf_preview_get_cell_renderer (renderdata, col);
366 int padx;
368 if (!column || !cell)
369 break;
371 gtk_cell_renderer_get_padding (cell, &padx, NULL);
372 cx = gtk_tree_view_column_get_x_offset (column);
373 cw = gtk_tree_view_column_get_width (column);
375 if (x < (cx + padx) + cw) {
376 *dx = x - (cx + padx);
377 break;
381 *pcol = col;