/*
* GChemPaint GOffice component
* gchempaint.cc
*
* Copyright (C) 2005-2006 Jean Bréfort <jean.brefort@normalesup.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "gchempaint-config.h"
#include "gchempaint-priv.h"
#include "gofficeapp.h"
#include "lib/theme.h"
#include <gsf/gsf-impl-utils.h>
#include <goffice/app/module-plugin-defs.h>
#include <goffice/component/go-component-factory.h>
#include <libgnomecanvas/gnome-canvas.h>
#include <openbabel/mol.h>
#include <math.h>
#include <libintl.h>
gcpGOfficeApplication *app;
extern "C"
{
extern GOPluginModuleDepend const go_plugin_depends [] = {
{ "goffice", GOFFICE_API_VERSION }
};
extern GOPluginModuleHeader const go_plugin_header =
{ GOFFICE_MODULE_PLUGIN_MAGIC_NUMBER, G_N_ELEMENTS (go_plugin_depends) };
static GObjectClass *gogcp_parent_klass;
static gboolean
go_gchempaint_component_get_data (GOComponent *component, gpointer *data, int *length,
void (**clearfunc) (gpointer), gpointer *user_data)
{
GOGChemPaintComponent *gogcp = GO_GCHEMPAINT_COMPONENT (component);
xmlDocPtr xml = NULL;
char *old_num_locale, *old_time_locale;
bool result;
if (!gogcp->document || !gogcp->document->HasChildren ()) {
*data = NULL;
*length = 0;
* clearfunc = NULL;
return true;
}
old_num_locale = g_strdup (setlocale (LC_NUMERIC, NULL));
setlocale(LC_NUMERIC, "C");
old_time_locale = g_strdup (setlocale (LC_TIME, NULL));
setlocale (LC_TIME, "C");
try {
xml = gogcp->document->BuildXMLTree ();
xmlChar *mem;
int size;
xmlDocDumpMemory (xml, &mem, &size);
xmlFreeDoc (xml);
*data = mem;
*length = size;
*clearfunc = xmlFree;
result = true;
}
catch (int) {
if (xml)
xmlFreeDoc (xml);
xml = NULL;
// Error (SAVE);
result = false;
}
setlocale (LC_NUMERIC, old_num_locale);
g_free (old_num_locale);
setlocale (LC_TIME, old_time_locale);
g_free (old_time_locale);
return result;
}
static void
go_gchempaint_component_set_data (GOComponent *component)
{
GOGChemPaintComponent *gogcp = GO_GCHEMPAINT_COMPONENT (component);
gogcp->document = app->ImportDocument (component->mime_type, component->data, component->length);
gcpTheme *pTheme = gogcp->document->GetTheme ();
GtkWidget *w = gogcp->document->GetWidget ();
gnome_canvas_update_now (GNOME_CANVAS (w));
ArtDRect rect;
gcpWidgetData *pData = (gcpWidgetData*)g_object_get_data(G_OBJECT(w), "data");
pData->GetObjectBounds (gogcp->document, &rect);
double y = gogcp->document->GetYAlign ();
y += gogcp->document->GetView ()->GetBaseLineOffset ();
y *= pTheme->GetZoomFactor ();
if (rect.x0 || rect.y0)
gogcp->document->Move (- rect.x0 / pTheme->GetZoomFactor (), - rect.y0 / pTheme->GetZoomFactor ());
gogcp->document->GetView ()->Update (gogcp->document);
if (y < rect.y0)
y = rect.y1;
component->ascent = (y - rect.y0) / 96.;
component->descent = (rect.y1 - y) / 96.;
component->width = (rect.x1 - rect.x0) / 96.;
}
static void
go_gchempaint_component_draw (GOComponent *component, int width_pixels, int height_pixels)
{
GOGChemPaintComponent *gogcp = GO_GCHEMPAINT_COMPONENT (component);
// GnomeCanvas does not support alpha channel, so we must use a 24bits pixbuf
// and then copy the pixels.
int i = gdk_pixbuf_get_width (component->pixbuf),
j = gdk_pixbuf_get_height (component->pixbuf), k;
GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, i, j);
int srowstride = gdk_pixbuf_get_rowstride (pixbuf),
drowstride = gdk_pixbuf_get_rowstride (component->pixbuf);
guint32 *dest;
guint8 *src, *sline, *dline = gdk_pixbuf_get_pixels (component->pixbuf);
if (!gogcp->document) {
gdk_pixbuf_fill (component->pixbuf, 0);
return;
}
gdk_pixbuf_fill (pixbuf, 0xffffffff);
GtkWidget *w = gogcp->document->GetWidget ();
gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (w), (double) width_pixels / component->width / 96.);
gnome_canvas_update_now (GNOME_CANVAS (w));
gcpWidgetData *pData = (gcpWidgetData*)g_object_get_data(G_OBJECT(w), "data");
GnomeCanvasBuf buf;
buf.buf = sline = gdk_pixbuf_get_pixels (pixbuf);
buf.rect.x0 = 0;
buf.rect.x1 = i;
buf.rect.y0 = 0;
buf.rect.y1 = j;
buf.buf_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
buf.bg_color = 0xffffff;
buf.is_buf = 1;
(* GNOME_CANVAS_ITEM_GET_CLASS (pData->Group)->render) (GNOME_CANVAS_ITEM (pData->Group), &buf);
while (j-- > 0) {
k = i;
dest = (guint32*) dline;
src = sline;
while (k-- > 0) {
*dest = *((guint32*) src);
*dest |=0xff000000;
dest++;
src += 3;
}
sline += srowstride;
dline += drowstride;
}
}
static void
go_gchempaint_component_print (GOComponent *component, GnomePrintContext *gpc,
double width, double height)
{
GOGChemPaintComponent *gogcp = GO_GCHEMPAINT_COMPONENT (component);
if (!gogcp->document)
return;
GtkWidget *w = gogcp->document->GetWidget ();
gnome_canvas_update_now (GNOME_CANVAS (w));
gogcp->document->Print(gpc, width, height);
}
static gboolean
go_gchempaint_component_edit (GOComponent *component)
{
GOGChemPaintComponent *gogcp = GO_GCHEMPAINT_COMPONENT (component);
if (!gogcp->document) {
component->ascent = 1.;
component->descent = 0.;
component->width = 1.;
}
if (gogcp->window) {
gogcp->window->Show ();
return true;
}
return app->EditDocument (gogcp);
}
static void
go_gchempaint_component_finalize (GObject *obj)
{
GOGChemPaintComponent *gogcp = GO_GCHEMPAINT_COMPONENT (obj);
if (gogcp->window)
gogcp->window->Destroy ();
G_OBJECT_CLASS (gogcp_parent_klass)->finalize (obj);
}
static void
go_gchempaint_component_init (GOComponent *component)
{
component->resizable = false;
component->editable = true;
component->window = NULL;
component->ascent = 1.;
component->descent = 0.;
component->width = 1.;
}
static void
go_gchempaint_component_class_init (GOComponentClass *klass)
{
GObjectClass *obj_klass = (GObjectClass *) klass;
obj_klass->finalize = go_gchempaint_component_finalize;
gogcp_parent_klass = (GObjectClass*) g_type_class_peek_parent (klass);
klass->get_data = go_gchempaint_component_get_data;
klass->set_data = go_gchempaint_component_set_data;
klass->draw = go_gchempaint_component_draw;
klass->print = go_gchempaint_component_print;
klass->edit = go_gchempaint_component_edit;
}
GSF_DYNAMIC_CLASS (GOGChemPaintComponent, go_gchempaint_component,
go_gchempaint_component_class_init, go_gchempaint_component_init,
GO_COMPONENT_TYPE)
/*************************************************************************************/
G_MODULE_EXPORT void
go_plugin_init (GOPlugin *plugin, GOCmdContext *cc)
{
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
#ifdef ENABLE_NLS
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif
GTypeModule *module = go_plugin_get_type_module (plugin);
go_gchempaint_component_register_type (module);
go_components_set_mime_suffix ("application/x-gchempaint", "*.gchempaint");
app = new gcpGOfficeApplication ();
}
G_MODULE_EXPORT void
go_plugin_shutdown (GOPlugin *plugin, GOCmdContext *cc)
{
delete app;
}
} // extern "C"
syntax highlighted by Code2HTML, v. 0.9.1