GUI: Dead kittens.
[gnumeric.git] / src / dialogs / dialog-stf-preview.c
blob907f78aa422df36bc231f9a62619c36b83f65e5f
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 "dialog-stf-preview.h"
26 #include "dialog-stf.h"
28 #include <gnm-format.h>
29 #include <number-match.h>
30 #include <value.h>
31 #include <style.h>
32 #include <gtk/gtk.h>
33 #include <widgets/gnumeric-lazy-list.h>
34 #include <string.h>
36 /******************************************************************************************************************
37 * ADVANCED DRAWING FUNCTIONS
38 ******************************************************************************************************************/
40 static void
41 render_get_value (gint row, gint column, gpointer _rd, GValue *value)
43 RenderData_t *rd = (RenderData_t *)_rd;
44 GnumericLazyList *ll = GNM_LAZY_LIST (gtk_tree_view_get_model (rd->tree_view));
45 GPtrArray *lines = rd->lines;
46 GPtrArray *line = (row < (int)lines->len)
47 ? g_ptr_array_index (lines, row)
48 : NULL;
49 const char *text = (line && column < (int)line->len)
50 ? g_ptr_array_index (line, column)
51 : NULL;
53 g_value_init (value, ll->column_headers[column]);
55 if (text) {
56 char *copy = NULL;
57 char *tab = strchr (text, '\t');
58 if (tab) {
59 copy = g_strdup (text);
60 tab = copy + (tab - text);
61 do {
62 *tab = ' ';
63 tab = strchr (tab + 1, '\t');
64 } while (tab);
65 text = copy;
69 * Throwing really long strings at Gtk+ is known to cause
70 * trouble, so cut long strings and hope no-one notices.
72 if (g_utf8_strlen (text, -1) > STF_LINE_LENGTH_LIMIT) {
73 char *cut = g_strdup (text);
74 strcpy (g_utf8_offset_to_pointer (cut, STF_LINE_LENGTH_LIMIT - 3),
75 "...");
76 g_free (copy);
77 text = copy = cut;
80 g_value_set_string (value, text);
81 g_free (copy);
86 /******************************************************************************************************************
87 * STRUCTURE MANIPULATION FUNCTIONS
88 ******************************************************************************************************************/
90 /**
91 * stf_preview_new
92 * @data_container: a container in which to put a treeview.
94 * returns : a new renderdata struct
95 **/
96 RenderData_t*
97 stf_preview_new (GtkWidget *data_container,
98 GODateConventions const *date_conv)
100 RenderData_t* renderdata;
101 GnumericLazyList *ll;
103 g_return_val_if_fail (data_container != NULL, NULL);
105 renderdata = g_new (RenderData_t, 1);
107 renderdata->data_container = data_container;
108 renderdata->startrow = 1;
109 renderdata->colformats = g_ptr_array_new ();
110 renderdata->ignore_formats = FALSE;
111 renderdata->lines_chunk = NULL;
112 renderdata->lines = NULL;
114 renderdata->date_conv = date_conv;
116 ll = gnumeric_lazy_list_new (render_get_value, renderdata, 0, 1, G_TYPE_STRING);
117 renderdata->tree_view =
118 GTK_TREE_VIEW (gtk_tree_view_new_with_model (GTK_TREE_MODEL (ll)));
119 gtk_tree_view_set_grid_lines (renderdata->tree_view,
120 GTK_TREE_VIEW_GRID_LINES_VERTICAL);
121 g_object_ref (renderdata->tree_view);
122 g_object_unref (ll);
124 renderdata->colcount = 0;
127 GtkWidget *w = GTK_WIDGET (renderdata->tree_view);
128 int width, height, vertical_separator;
129 PangoLayout *layout =
130 gtk_widget_create_pango_layout (w, "Mg19");
132 gtk_widget_style_get (w,
133 "vertical_separator", &vertical_separator,
134 NULL);
136 pango_layout_get_pixel_size (layout, &width, &height);
138 * Make room for about 80 characters and about 7 lines of data.
139 * (The +2 allows room for the headers and the h-scrollbar.
141 gtk_widget_set_size_request (renderdata->data_container,
142 width * 20, /* About 80 chars. */
143 (height + vertical_separator) * (7 + 2));
144 g_object_unref (layout);
147 gtk_container_add (GTK_CONTAINER (renderdata->data_container),
148 GTK_WIDGET (renderdata->tree_view));
149 gtk_widget_show_all (GTK_WIDGET (renderdata->tree_view));
151 return renderdata;
155 * stf_preview_free
156 * @renderdata: a renderdata struct
158 * This will free the @renderdata
160 * returns : nothing
162 void
163 stf_preview_free (RenderData_t *renderdata)
165 g_return_if_fail (renderdata != NULL);
167 stf_preview_colformats_clear (renderdata);
168 g_ptr_array_free (renderdata->colformats, TRUE);
170 stf_preview_set_lines (renderdata, NULL, NULL);
172 g_object_unref (renderdata->tree_view);
174 g_free (renderdata);
177 void
178 stf_preview_set_lines (RenderData_t *renderdata,
179 GStringChunk *lines_chunk,
180 GPtrArray *lines)
182 unsigned int i;
183 int colcount = 1;
184 GnumericLazyList *ll;
185 gboolean hidden;
187 g_return_if_fail (renderdata != NULL);
189 /* Empty the table. */
190 gtk_tree_view_set_model (renderdata->tree_view, NULL);
192 if (renderdata->lines != lines) {
193 if (renderdata->lines)
194 stf_parse_general_free (renderdata->lines);
195 renderdata->lines = lines;
198 if (renderdata->lines_chunk != lines_chunk) {
199 if (renderdata->lines_chunk)
200 g_string_chunk_free (renderdata->lines_chunk);
201 renderdata->lines_chunk = lines_chunk;
204 if (lines == NULL)
205 return;
207 for (i = 0; i < lines->len; i++) {
208 GPtrArray *line = g_ptr_array_index (lines, i);
209 colcount = MAX (colcount, (int)line->len);
213 * If we are making large changes we need to hide the treeview
214 * because performance otherwise suffers a lot.
216 hidden = gtk_widget_get_visible (GTK_WIDGET (renderdata->tree_view)) &&
217 (colcount < renderdata->colcount - 1 ||
218 colcount > renderdata->colcount + 10);
219 if (hidden)
220 gtk_widget_hide (GTK_WIDGET (renderdata->tree_view));
222 while (renderdata->colcount > colcount)
223 gtk_tree_view_remove_column
224 (renderdata->tree_view,
225 gtk_tree_view_get_column (renderdata->tree_view,
226 --(renderdata->colcount)));
228 while (renderdata->colcount < colcount) {
229 char *text = g_strdup_printf (_(COLUMN_CAPTION),
230 renderdata->colcount + 1);
231 GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
232 GtkTreeViewColumn *column =
233 gtk_tree_view_column_new_with_attributes
234 (text, cell,
235 "text", renderdata->colcount,
236 NULL);
237 g_object_set (cell,
238 "single_paragraph_mode", TRUE,
239 NULL);
240 gtk_tree_view_append_column (renderdata->tree_view, column);
241 g_free (text);
242 renderdata->colcount++;
245 ll = gnumeric_lazy_list_new (render_get_value, renderdata,
246 MIN (lines->len, STF_LINE_DISPLAY_LIMIT),
248 gnumeric_lazy_list_add_column (ll, colcount, G_TYPE_STRING);
249 gtk_tree_view_set_model (renderdata->tree_view, GTK_TREE_MODEL (ll));
250 g_object_unref (ll);
252 if (hidden)
253 gtk_widget_show (GTK_WIDGET (renderdata->tree_view));
257 * stf_preview_colformats_clear
258 * @renderdata: a struct containing rendering information
260 * This will clear the @renderdata->colformats array which contains the format of
261 * each column.
263 * returns : nothing
265 void
266 stf_preview_colformats_clear (RenderData_t *renderdata)
268 guint i;
269 g_return_if_fail (renderdata != NULL);
271 for (i = 0; i < renderdata->colformats->len; i++)
272 go_format_unref (g_ptr_array_index (renderdata->colformats, i));
273 g_ptr_array_free (renderdata->colformats, TRUE);
274 renderdata->colformats = g_ptr_array_new ();
278 * stf_preview_colformats_add
279 * @renderdata: a struct containing rendering information
280 * @format: the format of the column
282 * This will add an entry to the @renderdata->colformats array.
283 * The widths of the columns will be set to at least have the width of
284 * the @format.
286 * returns : nothing
288 void
289 stf_preview_colformats_add (RenderData_t *renderdata, GOFormat *format)
292 g_return_if_fail (renderdata != NULL);
293 g_return_if_fail (format != NULL);
295 g_ptr_array_add (renderdata->colformats, go_format_ref (format));
299 GtkTreeViewColumn *
300 stf_preview_get_column (RenderData_t *renderdata, int col)
302 return gtk_tree_view_get_column (renderdata->tree_view, col);
305 GtkCellRenderer *
306 stf_preview_get_cell_renderer (RenderData_t *renderdata, int col)
308 GtkCellRenderer *res = NULL;
309 GtkTreeViewColumn *column = stf_preview_get_column (renderdata, col);
310 if (column) {
311 GList *renderers = gtk_cell_layout_get_cells
312 (GTK_CELL_LAYOUT(column));
313 if (renderers) {
314 res = renderers->data;
315 g_list_free (renderers);
318 return res;
321 void
322 stf_preview_find_column (RenderData_t *renderdata, int x, int *pcol, int *dx)
324 int col;
326 *dx = 0;
328 /* Figure out what column we pressed in. */
329 for (col = 0; TRUE; col++) {
330 int cx, cw;
331 GtkTreeViewColumn *column =
332 stf_preview_get_column (renderdata, col);
333 GtkCellRenderer *cell =
334 stf_preview_get_cell_renderer (renderdata, col);
335 int padx;
337 if (!column || !cell)
338 break;
340 gtk_cell_renderer_get_padding (cell, &padx, NULL);
341 cx = gtk_tree_view_column_get_x_offset (column);
342 cw = gtk_tree_view_column_get_width (column);
344 if (x < (cx + padx) + cw) {
345 *dx = x - (cx + padx);
346 break;
350 *pcol = col;