Compilation: don't compile dialogs separately.
[gnumeric.git] / src / dialogs / dialog-stf-preview.c
bloba130a008cca9fe32fc06e4dbf81b037614558d1c
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: (skip)
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: (skip)
156 * @data: a renderdata struct
158 * This will free the @renderdata
160 void
161 stf_preview_free (RenderData_t *renderdata)
163 g_return_if_fail (renderdata != NULL);
165 stf_preview_colformats_clear (renderdata);
166 g_ptr_array_free (renderdata->colformats, TRUE);
168 stf_preview_set_lines (renderdata, NULL, NULL);
170 g_object_unref (renderdata->tree_view);
172 g_free (renderdata);
176 * stf_preview_set_lines: (skip)
178 void
179 stf_preview_set_lines (RenderData_t *renderdata,
180 GStringChunk *lines_chunk,
181 GPtrArray *lines)
183 unsigned int i;
184 int colcount = 1;
185 GnumericLazyList *ll;
186 gboolean hidden;
188 g_return_if_fail (renderdata != NULL);
190 /* Empty the table. */
191 gtk_tree_view_set_model (renderdata->tree_view, NULL);
193 if (renderdata->lines != lines) {
194 if (renderdata->lines)
195 stf_parse_general_free (renderdata->lines);
196 renderdata->lines = lines;
199 if (renderdata->lines_chunk != lines_chunk) {
200 if (renderdata->lines_chunk)
201 g_string_chunk_free (renderdata->lines_chunk);
202 renderdata->lines_chunk = lines_chunk;
205 if (lines == NULL)
206 return;
208 for (i = 0; i < lines->len; i++) {
209 GPtrArray *line = g_ptr_array_index (lines, i);
210 colcount = MAX (colcount, (int)line->len);
214 * If we are making large changes we need to hide the treeview
215 * because performance otherwise suffers a lot.
217 hidden = gtk_widget_get_visible (GTK_WIDGET (renderdata->tree_view)) &&
218 (colcount < renderdata->colcount - 1 ||
219 colcount > renderdata->colcount + 10);
220 if (hidden)
221 gtk_widget_hide (GTK_WIDGET (renderdata->tree_view));
223 while (renderdata->colcount > colcount)
224 gtk_tree_view_remove_column
225 (renderdata->tree_view,
226 gtk_tree_view_get_column (renderdata->tree_view,
227 --(renderdata->colcount)));
229 while (renderdata->colcount < colcount) {
230 char *text = g_strdup_printf (_(COLUMN_CAPTION),
231 renderdata->colcount + 1);
232 GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
233 GtkTreeViewColumn *column =
234 gtk_tree_view_column_new_with_attributes
235 (text, cell,
236 "text", renderdata->colcount,
237 NULL);
238 g_object_set (cell,
239 "single_paragraph_mode", TRUE,
240 NULL);
241 gtk_tree_view_append_column (renderdata->tree_view, column);
242 g_free (text);
243 renderdata->colcount++;
246 ll = gnumeric_lazy_list_new (render_get_value, renderdata,
247 MIN (lines->len, STF_LINE_DISPLAY_LIMIT),
249 gnumeric_lazy_list_add_column (ll, colcount, G_TYPE_STRING);
250 gtk_tree_view_set_model (renderdata->tree_view, GTK_TREE_MODEL (ll));
251 g_object_unref (ll);
253 if (hidden)
254 gtk_widget_show (GTK_WIDGET (renderdata->tree_view));
258 * stf_preview_colformats_clear: (skip)
259 * @renderdata: a struct containing rendering information
261 * This will clear the @renderdata->colformats array which contains the format of
262 * each column.
264 void
265 stf_preview_colformats_clear (RenderData_t *renderdata)
267 guint i;
268 g_return_if_fail (renderdata != NULL);
270 for (i = 0; i < renderdata->colformats->len; i++)
271 go_format_unref (g_ptr_array_index (renderdata->colformats, i));
272 g_ptr_array_free (renderdata->colformats, TRUE);
273 renderdata->colformats = g_ptr_array_new ();
277 * stf_preview_colformats_add: (skip)
278 * @renderdata: a struct containing rendering information
279 * @format: the format of the column
281 * This will add an entry to the @renderdata->colformats array.
282 * The widths of the columns will be set to at least have the width of
283 * the @format.
285 * returns : nothing
287 void
288 stf_preview_colformats_add (RenderData_t *renderdata, GOFormat *format)
291 g_return_if_fail (renderdata != NULL);
292 g_return_if_fail (format != NULL);
294 g_ptr_array_add (renderdata->colformats, go_format_ref (format));
298 * stf_preview_get_column: (skip)
300 GtkTreeViewColumn *
301 stf_preview_get_column (RenderData_t *renderdata, int col)
303 return gtk_tree_view_get_column (renderdata->tree_view, col);
307 * stf_preview_get_cell_renderer: (skip)
309 GtkCellRenderer *
310 stf_preview_get_cell_renderer (RenderData_t *renderdata, int col)
312 GtkCellRenderer *res = NULL;
313 GtkTreeViewColumn *column = stf_preview_get_column (renderdata, col);
314 if (column) {
315 GList *renderers = gtk_cell_layout_get_cells
316 (GTK_CELL_LAYOUT(column));
317 if (renderers) {
318 res = renderers->data;
319 g_list_free (renderers);
322 return res;
325 void
326 stf_preview_find_column (RenderData_t *renderdata, int x, int *pcol, int *dx)
328 int col;
330 *dx = 0;
332 /* Figure out what column we pressed in. */
333 for (col = 0; TRUE; col++) {
334 int cx, cw;
335 GtkTreeViewColumn *column =
336 stf_preview_get_column (renderdata, col);
337 GtkCellRenderer *cell =
338 stf_preview_get_cell_renderer (renderdata, col);
339 int padx;
341 if (!column || !cell)
342 break;
344 gtk_cell_renderer_get_padding (cell, &padx, NULL);
345 cx = gtk_tree_view_column_get_x_offset (column);
346 cw = gtk_tree_view_column_get_width (column);
348 if (x < (cx + padx) + cw) {
349 *dx = x - (cx + padx);
350 break;
354 *pcol = col;