/* Python plug-in for dia * Copyright (C) 1999 James Henstridge * Copyright (C) 2000 Hans Breuer * * 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 #include "pydia-object.h" #include "pydia-diagramdata.h" #include "pydia-geometry.h" #include "pydia-layer.h" #include "pydia-color.h" #include "app/diagram.h" PyObject * PyDiaDiagramData_New(DiagramData *dd) { PyDiaDiagramData *self; self = PyObject_NEW(PyDiaDiagramData, &PyDiaDiagramData_Type); if (!self) return NULL; g_object_ref (dd); self->data = dd; return (PyObject *)self; } static void PyDiaDiagramData_Dealloc(PyDiaDiagramData *self) { g_object_unref (self->data); PyObject_DEL(self); } static int PyDiaDiagramData_Compare(PyDiaDiagramData *self, PyDiaDiagramData *other) { if (self->data == other->data) return 0; if (self->data > other->data) return -1; return 1; } static long PyDiaDiagramData_Hash(PyDiaDiagramData *self) { return (long)self->data; } static PyObject * PyDiaDiagramData_Str(PyDiaDiagramData *self) { PyObject* py_s; gchar* s = g_strdup_printf ("", self); py_s = PyString_FromString(s); g_free(s); return py_s; } /* * "real" member function implementaion ? */ static PyObject * PyDiaDiagramData_UpdateExtents(PyDiaDiagramData *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":DiagramData.update_extents")) return NULL; data_update_extents(self->data); Py_INCREF(Py_None); return Py_None; } static PyObject * PyDiaDiagramData_GetSortedSelected(PyDiaDiagramData *self, PyObject *args) { GList *list, *tmp; PyObject *ret; guint i, len; if (!PyArg_ParseTuple(args, ":DiagramData.get_sorted_selected")) return NULL; list = tmp = data_get_sorted_selected(self->data); len = g_list_length (self->data->selected); ret = PyTuple_New(len); for (i = 0, tmp = self->data->selected; tmp; i++, tmp = tmp->next) PyTuple_SetItem(ret, i, PyDiaObject_New((DiaObject *)tmp->data)); g_list_free(list); return ret; } static PyObject * PyDiaDiagramData_AddLayer(PyDiaDiagramData *self, PyObject *args) { gchar *name; int pos = -1; Layer *layer; if (!PyArg_ParseTuple(args, "s|i:DiagramData.add_layer", &name, &pos)) return NULL; layer = new_layer(g_strdup(name),self->data); if (pos != -1) data_add_layer_at(self->data, layer, pos); else data_add_layer(self->data, layer); return PyDiaLayer_New(layer); } static PyObject * PyDiaDiagramData_RaiseLayer(PyDiaDiagramData *self, PyObject *args) { PyDiaLayer *layer; if (!PyArg_ParseTuple(args, "O!:DiagramData.raise_layer", &PyDiaLayer_Type, &layer)) return NULL; data_raise_layer(self->data, layer->layer); Py_INCREF(Py_None); return Py_None; } static PyObject * PyDiaDiagramData_LowerLayer(PyDiaDiagramData *self, PyObject *args) { PyDiaLayer *layer; if (!PyArg_ParseTuple(args, "O!:DiagramData.lower_layer", &PyDiaLayer_Type, &layer)) return NULL; data_lower_layer(self->data, layer->layer); Py_INCREF(Py_None); return Py_None; } static PyObject * PyDiaDiagramData_SetActiveLayer(PyDiaDiagramData *self, PyObject *args) { PyDiaLayer *layer; if (!PyArg_ParseTuple(args, "O!:DiagramData.set_active_layer", &PyDiaLayer_Type, &layer)) return NULL; data_set_active_layer(self->data, layer->layer); Py_INCREF(Py_None); return Py_None; } static PyObject * PyDiaDiagramData_DeleteLayer(PyDiaDiagramData *self, PyObject *args) { PyDiaLayer *layer; if (!PyArg_ParseTuple(args, "O!:DiagramData.delete_layer", &PyDiaLayer_Type, &layer)) return NULL; data_delete_layer(self->data, layer->layer); layer_destroy(layer->layer); layer->layer = NULL; Py_INCREF(Py_None); return Py_None; } /* * Callback for "object_add" and "object_remove "signal, used by the connect_after method, * it's a proxy for the python function, creating the values it needs. * Params are those of the signals on the Diagram object. * @param dia The DiagramData that emitted the signal * @param layer The Layer that the object is removed or added to. * @param obj The DiaObject that the signal is about. * @param user_data The python function to be called by the callback. */ static void PyDiaDiagramData_CallbackObject(DiagramData *dia,Layer *layer,DiaObject *obj,void *user_data) { PyObject *pydata,*pylayer,*pyobj,*res,*arg; PyObject *func = user_data; /* Check that we got a function */ if (!func || !PyCallable_Check (func)) { g_warning ("Callback called without valid callback function."); return; } /* Create a new PyDiaDiagramData object. */ if (dia) pydata = PyDiaDiagramData_New (dia); else { pydata = Py_None; Py_INCREF (pydata); } /* * Create PyDiaLayer */ if (layer) pylayer = PyDiaLayer_New (layer); else { pylayer = Py_None; Py_INCREF (pylayer); } /* * Create PyDiaObject */ if (layer) pyobj = PyDiaObject_New (obj); else { pyobj = Py_None; Py_INCREF (pyobj); } Py_INCREF(func); /* Call the callback. */ arg = Py_BuildValue ("(OOO)", pydata,pylayer,pyobj); if (arg) { res = PyEval_CallObject (func, arg); /*ON_RES(res, TRUE);*/ } /* Cleanup */ Py_XDECREF (arg); Py_DECREF(func); Py_XDECREF(pydata); Py_XDECREF(pylayer); Py_XDECREF(pyobj); } /** Connects a python function to a signal. * @param self The PyDiaDiagramData this is a method of. * @param args A tuple containing the arguments, a str for signal name * and a callable object (like a function) */ static PyObject * PyDiaDiagramData_ConnectAfter(PyDiaDiagramData *self, PyObject *args) { PyObject *func; char *signal; /* Check arguments */ if (!PyArg_ParseTuple(args, "sO:DiagramData.connect_after",&signal,&func)) return NULL; /* Check that the arg is callable */ if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "Second parameter must be callable"); return NULL; } /* check if the signals name is valid */ if ( strcmp("object_remove",signal) == 0 || strcmp("object_add",signal) == 0) { Py_INCREF(func); /* stay alive, where to kill ?? */ /* connect to signal */ g_signal_connect_after(DIA_DIAGRAM_DATA(self->data),signal,G_CALLBACK(PyDiaDiagramData_CallbackObject), func); Py_INCREF(Py_None); return Py_None; } else { PyErr_SetString(PyExc_TypeError, "Wrong signal name"); return NULL; } } static PyMethodDef PyDiaDiagramData_Methods[] = { {"update_extents", (PyCFunction)PyDiaDiagramData_UpdateExtents, 1}, {"get_sorted_selected", (PyCFunction)PyDiaDiagramData_GetSortedSelected, 1}, {"add_layer", (PyCFunction)PyDiaDiagramData_AddLayer, 1}, {"raise_layer", (PyCFunction)PyDiaDiagramData_RaiseLayer, 1}, {"lower_layer", (PyCFunction)PyDiaDiagramData_LowerLayer, 1}, {"set_active_layer", (PyCFunction)PyDiaDiagramData_SetActiveLayer, 1}, {"delete_layer", (PyCFunction)PyDiaDiagramData_DeleteLayer, 1}, {"connect_after", (PyCFunction)PyDiaDiagramData_ConnectAfter, 1}, {NULL, 0, 0, NULL} }; static PyObject * PyDiaDiagramData_GetAttr(PyDiaDiagramData *self, gchar *attr) { Diagram *diagram = DIA_DIAGRAM(self->data); if (!strcmp(attr, "__members__")) return Py_BuildValue("[ssssssssssss]", "extents", "bg_color", "paper", "layers", "active_layer", "grid_width", "grid_visible", "hguides", "vguides", "layers", "active_layer", "selected" ); else if (!strcmp(attr, "extents")) return PyDiaRectangle_New(&self->data->extents, NULL); else if (!strcmp(attr, "bg_color")) { return PyDiaColor_New (&(self->data->bg_color)); } else if (!strcmp(attr, "layers")) { guint i, len = self->data->layers->len; PyObject *ret = PyTuple_New(len); for (i = 0; i < len; i++) PyTuple_SetItem(ret, i, PyDiaLayer_New( g_ptr_array_index(self->data->layers, i))); return ret; } else if (!strcmp(attr, "active_layer")) { return PyDiaLayer_New(self->data->active_layer); } else if (!strcmp(attr, "paper")) { /* XXX */ Py_INCREF(Py_None); return Py_None; } else if (diagram && !strcmp(attr, "grid_width")) return Py_BuildValue("(dd)", diagram->grid.width_x, diagram->grid.width_y); else if (diagram && !strcmp(attr, "grid_visible")) return Py_BuildValue("(ii)", diagram->grid.visible_x, diagram->grid.visible_y); else if (diagram && !strcmp(attr, "hguides")) { int len = diagram->guides.nhguides; PyObject *ret = PyTuple_New(len); int i; for (i = 0; i < len; i++) PyTuple_SetItem(ret, i, PyFloat_FromDouble(diagram->guides.hguides[i])); return ret; } else if (diagram && !strcmp(attr, "vguides")) { int len = diagram->guides.nvguides; PyObject *ret = PyTuple_New(len); int i; for (i = 0; i < len; i++) PyTuple_SetItem(ret, i, PyFloat_FromDouble(diagram->guides.vguides[i])); return ret; } else if (!strcmp(attr, "layers")) { guint i, len = self->data->layers->len; PyObject *ret = PyTuple_New(len); for (i = 0; i < len; i++) PyTuple_SetItem(ret, i, PyDiaLayer_New( g_ptr_array_index(self->data->layers, i))); return ret; } else if (!strcmp(attr, "active_layer")) { return PyDiaLayer_New(self->data->active_layer); } else if (!strcmp(attr, "selected")) { PyObject *ret; GList *tmp; gint i; ret = PyTuple_New(g_list_length(self->data->selected)); for (i = 0, tmp = self->data->selected; tmp; i++, tmp = tmp->next) PyTuple_SetItem(ret, i, PyDiaObject_New((DiaObject *)tmp->data)); return ret; } return Py_FindMethod(PyDiaDiagramData_Methods, (PyObject *)self, attr); } PyTypeObject PyDiaDiagramData_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, "dia.DiagramData", sizeof(PyDiaDiagramData), 0, (destructor)PyDiaDiagramData_Dealloc, (printfunc)0, (getattrfunc)PyDiaDiagramData_GetAttr, (setattrfunc)0, (cmpfunc)PyDiaDiagramData_Compare, (reprfunc)0, 0, 0, 0, (hashfunc)PyDiaDiagramData_Hash, (ternaryfunc)0, (reprfunc)PyDiaDiagramData_Str, (getattrofunc)0, (setattrofunc)0, (PyBufferProcs *)0, 0L, /* Flags */ "The 'low level' diagram object. It contains everything to manipulate diagrams from im- and export " "filters as well as from the UI. It does not provide any access to GUI elements related to the diagram." "Use the subclass dia.Diagram object for such matters." };