/*
* Gnome Chemisty Utils
* chem-viewer.c
*
* Copyright (C) 2005-2006
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA
*/
#include "config.h"
#include <gcu/element.h>
#include <gcu/gtkchem3dviewer.h>
#include <gcu/gtkcrystalviewer.h>
#include <gcu/chem3ddoc.h>
#include <gdk/gdkx.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkplug.h>
#include <libgnomevfs/gnome-vfs.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>
#include <cstring>
using namespace std;
using namespace gcu;
static bool loaded_radii = false;
class ChemComp
{
public:
ChemComp (void* instance, string& mime_type);
~ChemComp ();
void SetWindow (XID xid);
void SetFilename (string& filename);
void SetProperty (string& name, char const *value) {Params[name] = value;}
private:
void* Instance;
XID Xid;
string Filename, MimeType;
GtkWidget *Plug, *Viewer;
GdkWindow *Parent;
map<string, string> Params;
};
ChemComp::ChemComp (void* instance, string& mime_type)
{
Instance = instance;
MimeType = mime_type;
Xid = 0;
Plug = NULL;
}
ChemComp::~ChemComp ()
{
gtk_widget_unrealize (Plug);
gtk_widget_destroy (Plug);
g_object_unref (Parent);
}
void ChemComp::SetWindow (XID xid)
{
int width, height;
if (Xid == xid) {
//just resize and redraw
gdk_window_get_geometry (Parent, NULL, NULL, &width, &height, NULL);
gtk_window_resize (GTK_WINDOW (Plug), width, height);
} else {
if (Plug) // does this happen ?
return;
Xid = xid;
Plug = gtk_plug_new (xid);
Parent = gdk_window_foreign_new (xid);
gdk_window_get_geometry (Parent, NULL, NULL, &width, &height, NULL);
gtk_window_set_default_size (GTK_WINDOW (Plug), width, height);
gtk_widget_realize (Plug);
XReparentWindow (GDK_WINDOW_XDISPLAY (Plug->window),
GDK_WINDOW_XID (Plug->window), xid, 0, 0);
XMapWindow (GDK_WINDOW_XDISPLAY (Plug->window),
GDK_WINDOW_XID (Plug->window));
if (MimeType == "application/x-gcrystal")
Viewer = gtk_crystal_viewer_new (NULL);
else
Viewer = gtk_chem3d_viewer_new (NULL);
gtk_container_add (GTK_CONTAINER (Plug), Viewer);
gtk_widget_show_all (Plug);
}
}
void ChemComp::SetFilename (string& filename)
{
Filename = filename;
if (MimeType == "application/x-gcrystal") {
if (!loaded_radii) {
Element::LoadRadii ();
loaded_radii = true;
}
xmlDocPtr xml = xmlParseFile (filename.c_str ());
if (!xml || !xml->children || strcmp ((char*) xml->children->name, "crystal"))
return;
gtk_crystal_viewer_set_data (GTK_CRYSTAL_VIEWER (Viewer), xml->children);
} else {
gtk_chem3d_viewer_set_uri_with_mime_type (GTK_CHEM3D_VIEWER (Viewer),
filename.c_str (), MimeType.c_str ());
map<string, string>::iterator i, iend = Params.end ();
for (i = Params.begin (); i != iend; i++) {
if ((*i).first == "display3d") {
if ((*i).second == "ball&stick")
g_object_set (G_OBJECT (Viewer), "display3d", BALL_AND_STICK, NULL);
else if ((*i).second == "spacefill")
g_object_set (G_OBJECT (Viewer), "display3d", SPACEFILL, NULL);
}
else
g_object_set (G_OBJECT (Viewer), (*i).first.c_str (), (*i).second.c_str (), NULL);
}
Params.clear ();
}
}
GIOChannel *in_channel;
map<void*, ChemComp*> components;
static gboolean
io_func (GIOChannel *source, GIOCondition condition, gpointer data)
{
string buf, strinst;
void *instance;
char *str;
gsize length;
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
buf = str;
g_free (str);
if (buf == "new") {
string mime_type;
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
strinst = str;
g_free (str);
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
mime_type = str;
g_free (str);
istringstream iss (strinst);
iss >> hex >> instance;
if (components[instance] != NULL) // this should not occur
delete components[instance];
components[instance] = new ChemComp (instance, mime_type);
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
buf = str;
g_free (str);
while (buf != "end") {
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
components[instance]->SetProperty (buf, str);
g_free (str);
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
buf = str;
g_free (str);
}
} else if (buf == "win") {
string strwin;
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
strinst = str;
g_free (str);
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
strwin = str;
g_free (str);
istringstream iss (strinst), iss_ (strwin);
XID xid;
iss >> hex >> instance;
iss_ >> hex >> xid;
if (components[instance] != NULL)
components[instance]->SetWindow (xid);
} else if (buf == "file") {
string filename;
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
strinst = str;
g_free (str);
istringstream iss (strinst);
iss >> hex >> instance;
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
filename = str;
g_free (str);
ifstream ifs (filename.c_str ());
if (components[instance] != NULL)
components[instance]->SetFilename (filename);
} else if (buf == "kill") {
string filename;
g_io_channel_read_line (source, &str, &length, NULL, NULL);
str[length - 1] = 0;
strinst = str;
g_free (str);
istringstream iss (strinst);
iss >> hex >> instance;
if (components[instance] != NULL)
delete components[instance];
components.erase (instance);
} else if (buf == "halt") {
gtk_main_quit ();
}
return true;
}
int main (int argc, char *argv[])
{
GError *error = NULL;
gtk_init (&argc, &argv);
if (!gnome_vfs_init ()) {
cerr << "Could not initialize GnomeVFS\n" << endl;
return 1;
}
in_channel = g_io_channel_unix_new (fileno (stdin));
g_io_add_watch (in_channel, G_IO_IN, io_func, &error);
gtk_main ();
g_io_channel_unref (in_channel);
map <void*, ChemComp*>::iterator i, end = components.end ();
for (i = components.begin (); i != end; i++)
delete (*i).second;
components.clear ();
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1