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>
25 #include <dialogs/dialog-stf-preview.h>
26 #include <dialogs/dialog-stf.h>
28 #include <gnm-format.h>
29 #include <number-match.h>
34 /******************************************************************************************************************
35 * ADVANCED DRAWING FUNCTIONS
36 ******************************************************************************************************************/
41 line_renderer_func (GtkTreeViewColumn
*tvc
,
47 RenderData_t
*renderdata
= user_data
;
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
)
58 text
= (line
&& col
< line
->len
)
59 ? g_ptr_array_index (line
, col
)
64 char *tab
= strchr (text
, '\t');
66 copy
= g_strdup (text
);
67 tab
= copy
+ (tab
- text
);
70 tab
= strchr (tab
+ 1, '\t');
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),
87 g_object_set (cr
, "text", text
, NULL
);
90 g_object_set (cr
, "text", "", NULL
);
94 make_model (GPtrArray
*lines
)
96 GtkListStore
*list_store
= gtk_list_store_new (1, G_TYPE_UINT
);
98 unsigned count
= lines
? MIN (lines
->len
, STF_LINE_DISPLAY_LIMIT
) : 0;
100 for (ui
= 0; ui
< count
; ui
++) {
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
122 stf_preview_new (GtkWidget
*data_container
,
123 GODateConventions
const *date_conv
)
125 RenderData_t
* renderdata
;
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
,
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
));
180 * stf_preview_free: (skip)
181 * @data: a renderdata struct
183 * This will free the @renderdata
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
);
201 * stf_preview_set_lines: (skip)
204 stf_preview_set_lines (RenderData_t
*renderdata
,
205 GStringChunk
*lines_chunk
,
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
;
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);
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
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
);
273 renderdata
->colcount
++;
276 model
= make_model (lines
);
277 gtk_tree_view_set_model (renderdata
->tree_view
, model
);
278 g_object_unref (model
);
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
292 stf_preview_colformats_clear (RenderData_t
*renderdata
)
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
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)
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)
337 stf_preview_get_cell_renderer (RenderData_t
*renderdata
, int col
)
339 GtkCellRenderer
*res
= NULL
;
340 GtkTreeViewColumn
*column
= stf_preview_get_column (renderdata
, col
);
342 GList
*renderers
= gtk_cell_layout_get_cells
343 (GTK_CELL_LAYOUT(column
));
345 res
= renderers
->data
;
346 g_list_free (renderers
);
353 stf_preview_find_column (RenderData_t
*renderdata
, int x
, int *pcol
, int *dx
)
359 /* Figure out what column we pressed in. */
360 for (col
= 0; TRUE
; col
++) {
362 GtkTreeViewColumn
*column
=
363 stf_preview_get_column (renderdata
, col
);
364 GtkCellRenderer
*cell
=
365 stf_preview_get_cell_renderer (renderdata
, col
);
368 if (!column
|| !cell
)
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
);