1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Gnumeric GOffice component
6 * Copyright (C) 2006-2010
8 * Developed by Jean Bréfort <jean.brefort@normalesup.org>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <https://www.gnu.org/licenses/>
24 #include <gnumeric-config.h>
25 #include <application.h>
27 #include <gnm-plugin.h>
28 #include <gnumeric-conf.h>
32 #include <print-cell.h>
35 #include <selection.h>
37 #include <wbc-gtk-impl.h>
38 #include <workbook-view.h>
41 #include <goffice/goffice.h>
42 #include <goffice/component/goffice-component.h>
43 #include <goffice/component/go-component-factory.h>
44 #include <goffice/component/go-component.h>
45 #include <goffice/app/module-plugin-defs.h>
46 #include <gsf/gsf-impl-utils.h>
47 #include <gsf/gsf-input-memory.h>
48 #include <gsf/gsf-output-memory.h>
52 #include <glib/gi18n-lib.h>
54 #include <pango/pangocairo.h>
56 GOPluginModuleDepend
const go_plugin_depends
[] = {
57 { "goffice", GOFFICE_API_VERSION
}
59 GOPluginModuleHeader
const go_plugin_header
=
60 { GOFFICE_MODULE_PLUGIN_MAGIC_NUMBER
, G_N_ELEMENTS (go_plugin_depends
) };
62 G_MODULE_EXPORT
void go_plugin_init (GOPlugin
*plugin
, GOCmdContext
*cc
);
63 G_MODULE_EXPORT
void go_plugin_shutdown (GOPlugin
*plugin
, GOCmdContext
*cc
);
72 int col_start
, col_end
, row_start
, row_end
;
76 typedef GOComponentClass GOGnmComponentClass
;
78 #define GO_TYPE_GNM_COMPONENT (go_gnm_component_get_type ())
79 #define GO_GNM_COMPONENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GO_TYPE_GNM_COMPONENT, GOGnmComponent))
80 #define GO_IS_GNM_COMPONENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GO_TYPE_GNM_COMPONENT))
82 GType
go_gnm_component_get_type (void);
84 static GObjectClass
*gognm_parent_klass
;
87 go_gnm_component_get_data (GOComponent
*component
, gpointer
*data
, int *length
,
88 void (**clearfunc
) (gpointer
), gpointer
*user_data
)
90 GOGnmComponent
*gognm
= GO_GNM_COMPONENT (component
);
92 GOCmdContext
*cc
= go_component_get_command_context (component
);
93 GOIOContext
*io_context
= go_io_context_new (cc
);
94 GsfOutput
*output
= gsf_output_memory_new ();
95 GOFileSaver
*gfs
= workbook_get_file_saver (gognm
->wb
);
97 gfs
= go_file_saver_get_default ();
98 workbook_view_save_to_output (gognm
->wv
, gfs
, output
,
100 *data
= (gpointer
) gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (output
));
101 *length
= gsf_output_size (output
);
102 *clearfunc
= g_object_unref
;
104 g_object_unref (io_context
);
111 go_gnm_component_update_data (GOGnmComponent
*gognm
)
114 GnmRange
const *range
;
115 gognm
->sheet
= wb_view_cur_sheet (gognm
->wv
);
116 sv
= sheet_get_view (gognm
->sheet
, gognm
->wv
);
117 range
= selection_first_range (sv
, NULL
, NULL
);
118 gognm
->col_start
= range
->start
.col
;
119 gognm
->row_start
= range
->start
.row
;
120 gognm
->col_end
= range
->end
.col
;
121 gognm
->row_end
= range
->end
.row
;
122 gognm
->width
= sheet_col_get_distance_pts (
123 gognm
->sheet
, gognm
->col_start
, gognm
->col_end
+ 1);
124 gognm
->parent
.width
= gognm
->width
/ 72.;
125 gognm
->parent
.descent
= 0.;
126 gognm
->height
= sheet_row_get_distance_pts (
127 gognm
->sheet
, gognm
->row_start
, gognm
->row_end
+ 1);
128 gognm
->parent
.ascent
= gognm
->parent
.height
= gognm
->height
/ 72.;
132 go_gnm_component_set_data (GOComponent
*component
)
134 GOGnmComponent
*gognm
= GO_GNM_COMPONENT (component
);
135 GOCmdContext
*cc
= go_component_get_command_context (component
);
136 GOIOContext
*io_context
= go_io_context_new (cc
);
137 GsfInput
*input
= gsf_input_memory_new (component
->data
, component
->length
, FALSE
);
139 g_object_set (G_OBJECT (io_context
), "exec-main-loop", FALSE
, NULL
);
140 if (gognm
->wv
!= NULL
) {
141 g_object_unref (gognm
->wv
);
142 g_object_unref (gognm
->wb
);
144 gognm
->wv
= workbook_view_new_from_input (input
, NULL
, NULL
, io_context
, NULL
);
145 gognm
->wb
= wb_view_get_workbook (gognm
->wv
);
146 gnm_app_workbook_list_remove (gognm
->wb
);
147 g_object_unref (io_context
);
148 go_gnm_component_update_data (gognm
);
152 go_gnm_component_render (GOComponent
*component
, cairo_t
*cr
, double width_pixels
, double height_pixels
)
154 GOGnmComponent
*gognm
= GO_GNM_COMPONENT (component
);
158 go_gnm_component_update_data (gognm
);
160 range_init (&range
, gognm
->col_start
, gognm
->row_start
, gognm
->col_end
, gognm
->row_end
);
162 cairo_set_line_cap (cr
, CAIRO_LINE_CAP_BUTT
);
163 cairo_scale (cr
, ((double) width_pixels
) / gognm
->width
, ((double) height_pixels
) / gognm
->height
);
164 cairo_rectangle (cr
, 0., 0., gognm
->width
, gognm
->height
);
165 cairo_clip (cr
); /* not sure it is necessary */
166 gnm_gtk_print_cell_range (cr
, gognm
->sheet
, &range
, 0., 0.,
167 gognm
->sheet
->print_info
);
168 /* Now render objects */
169 gnm_print_sheet_objects (cr
, gognm
->sheet
, &range
, 0., 0.);
174 cb_gognm_save (G_GNUC_UNUSED GtkAction
*a
, WBCGtk
*wbcg
)
176 gpointer data
= g_object_get_data (G_OBJECT (wbcg
), "component");
177 if (GO_IS_COMPONENT (data
)) {
178 GOComponent
*component
= GO_COMPONENT (data
);
179 /* update the component data since not all clients will call set_data */
180 GOGnmComponent
*gognm
= GO_GNM_COMPONENT (component
);
181 WorkbookView
*wv
= wb_control_view (GNM_WBC (wbcg
));
182 if (wv
!= gognm
->wv
) {
183 if (gognm
->wv
!= NULL
) {
184 g_object_unref (gognm
->wv
);
185 g_object_unref (gognm
->wb
);
187 gognm
->wv
= g_object_ref (wv
);
188 gognm
->wb
= wb_view_get_workbook (wv
);
189 gnm_app_workbook_list_remove (gognm
->wb
); /* no need to have this one in the list */
191 go_doc_set_dirty (GO_DOC (gognm
->wb
), FALSE
);
192 go_gnm_component_update_data (gognm
);
193 go_component_emit_changed (component
);
195 gui_file_save (wbcg
, wb_control_view (GNM_WBC (wbcg
)));
198 static GtkActionEntry
const actions
[] = {
200 { "FileSaveEmbed", GNM_N_STOCK_SAVE
, NULL
,
201 NULL
, N_("Save the embedded workbook"),
202 G_CALLBACK (cb_gognm_save
) }
206 cb_editor_destroyed (GOGnmComponent
*gognm
)
208 if (gognm
->edited
&& G_OBJECT (gognm
->edited
)->ref_count
> 0)
209 g_object_unref (gognm
->edited
);
210 gognm
->edited
= NULL
;
214 go_gnm_component_edit (GOComponent
*component
)
216 GOGnmComponent
*gognm
= GO_GNM_COMPONENT (component
);
219 gdk_window_raise (gtk_widget_get_parent_window (GTK_WIDGET (wbcg_toplevel (gognm
->edited
))));
220 return wbcg_toplevel (gognm
->edited
);
223 component
->ascent
= 0.;
224 component
->descent
= 0.;
225 component
->width
= 0.;
226 wv
= workbook_view_new (workbook_new_with_sheets (1));
228 GOCmdContext
*cc
= go_component_get_command_context (component
);
229 GOIOContext
*io_context
= GO_IS_IO_CONTEXT (cc
)? GO_IO_CONTEXT (g_object_ref (cc
)): go_io_context_new (cc
);
230 GsfInput
*input
= gsf_input_memory_new (component
->data
, component
->length
, FALSE
);
232 g_object_set (G_OBJECT (io_context
), "exec-main-loop", FALSE
, NULL
);
233 wv
= workbook_view_new_from_input (input
, NULL
, NULL
, io_context
, NULL
);
234 g_object_unref (io_context
);
236 set_uifilename ("Gnumeric-embed.xml", actions
, G_N_ELEMENTS (actions
));
237 gognm
->edited
= wbc_gtk_new (wv
, NULL
, NULL
, NULL
);
239 g_object_set_data (G_OBJECT (gognm
->edited
), "component", gognm
);
240 g_signal_connect_swapped (gognm
->edited
->toplevel
, "destroy",
241 G_CALLBACK (cb_editor_destroyed
), gognm
);
242 return wbcg_toplevel (gognm
->edited
);
246 go_gnm_component_finalize (GObject
*obj
)
248 GOGnmComponent
*gognm
= GO_GNM_COMPONENT (obj
);
249 if (gognm
->wv
!= NULL
) {
250 g_object_unref (gognm
->wv
);
251 g_object_unref (gognm
->wb
);
254 if (gognm
->edited
!= NULL
) {
255 g_object_unref (wb_control_view (GNM_WBC (gognm
->edited
)));
256 gognm
->edited
= NULL
;
258 G_OBJECT_CLASS (gognm_parent_klass
)->finalize (obj
);
262 go_gnm_component_init (GOComponent
*component
)
264 GOGnmComponent
*gognm
= GO_GNM_COMPONENT (component
);
265 component
->resizable
= FALSE
;
266 component
->editable
= TRUE
;
267 component
->snapshot_type
= GO_SNAPSHOT_SVG
;
268 gognm
->row_start
= gognm
->col_start
= 0;
275 go_gnm_component_class_init (GOComponentClass
*klass
)
277 GObjectClass
*obj_klass
= (GObjectClass
*) klass
;
278 obj_klass
->finalize
= go_gnm_component_finalize
;
280 gognm_parent_klass
= (GObjectClass
*) g_type_class_peek_parent (klass
);
282 klass
->get_data
= go_gnm_component_get_data
;
283 klass
->set_data
= go_gnm_component_set_data
;
284 klass
->render
= go_gnm_component_render
;
285 klass
->edit
= go_gnm_component_edit
;
288 GSF_DYNAMIC_CLASS (GOGnmComponent
, go_gnm_component
,
289 go_gnm_component_class_init
, go_gnm_component_init
,
292 /*************************************************************************************/
295 go_plugin_init (GOPlugin
*plugin
, G_GNUC_UNUSED GOCmdContext
*cc
)
300 const char *usr_dir
= gnm_usr_dir (TRUE
);
302 bindtextdomain (GETTEXT_PACKAGE
, gnm_locale_dir ());
303 bindtextdomain (GETTEXT_PACKAGE
"-functions", gnm_locale_dir ());
305 bind_textdomain_codeset (GETTEXT_PACKAGE
, "UTF-8");
307 module
= go_plugin_get_type_module (plugin
);
308 go_gnm_component_register_type (module
);
310 if (!gnm_sys_data_dir ())
312 dir_list
= go_slist_create (
313 g_build_filename (gnm_sys_lib_dir (), PLUGIN_SUBDIR
, NULL
),
314 (usr_dir
== NULL
? NULL
:
315 g_build_filename (usr_dir
, PLUGIN_SUBDIR
, NULL
)),
317 dir_list
= g_slist_concat
319 go_string_slist_copy (gnm_conf_get_autoformat_extra_dirs ()));
321 env_var
= g_getenv ("GNUMERIC_PLUGIN_PATH");
323 GO_SLIST_CONCAT (dir_list
, go_strsplit_to_slist (env_var
, G_SEARCHPATH_SEPARATOR
));
325 go_components_set_mime_suffix ("application/x-gnumeric", "*.gnumeric");
327 go_plugins_init (go_component_get_command_context (NULL
),
328 gnm_conf_get_plugins_file_states (),
329 gnm_conf_get_plugins_active (),
331 gnm_conf_get_plugins_activate_newplugins (),
332 gnm_plugin_loader_module_get_type ());
336 go_plugin_shutdown (G_GNUC_UNUSED GOPlugin
*plugin
,
337 G_GNUC_UNUSED GOCmdContext
*cc
)