[dia] PyDia: some more reflection support



commit b58dba38c702abd84693311d1421e46c959d7bf1
Author: Hans Breuer <hans breuer org>
Date:   Tue Jul 26 21:26:55 2011 +0200

    PyDia: some more reflection support
    
    Define the return value of Object.get_object_menu() to allow
    some more reflection, i.e. checking for object specific menu
    items. Also expose some more information of properties.

 plug-ins/python/Makefile.am      |    2 +
 plug-ins/python/diamodule.c      |    4 +
 plug-ins/python/makefile.msc     |    1 +
 plug-ins/python/pydia-error.c    |   16 +++-
 plug-ins/python/pydia-menuitem.c |  181 ++++++++++++++++++++++++++++++++++++++
 plug-ins/python/pydia-menuitem.h |   17 ++++
 plug-ins/python/pydia-object.c   |   32 +++++++
 plug-ins/python/pydia-property.c |    6 +-
 8 files changed, 256 insertions(+), 3 deletions(-)
---
diff --git a/plug-ins/python/Makefile.am b/plug-ins/python/Makefile.am
index 96e54c1..6c38acc 100644
--- a/plug-ins/python/Makefile.am
+++ b/plug-ins/python/Makefile.am
@@ -41,6 +41,8 @@ libpython_plugin_la_SOURCES = \
 	pydia-image.h \
 	pydia-layer.c \
 	pydia-layer.h \
+	pydia-menuitem.c \
+	pydia-menuitem.h \
 	pydia-object.c \
 	pydia-object.h \
 	pydia-paperinfo.c \
diff --git a/plug-ins/python/diamodule.c b/plug-ins/python/diamodule.c
index 491ff8d..01a0b2e 100644
--- a/plug-ins/python/diamodule.c
+++ b/plug-ins/python/diamodule.c
@@ -38,6 +38,7 @@
 #include "pydia-error.h"
 #include "pydia-text.h"
 #include "pydia-paperinfo.h"
+#include "pydia-menuitem.h"
 
 #include "lib/dialib.h"
 #include "lib/object.h"
@@ -578,6 +579,7 @@ initdia(void)
     PyDiaMatrix_Type.ob_type = &PyType_Type;
     PyDiaText_Type.ob_type = &PyType_Type;
     PyDiaPaperinfo_Type.ob_type = &PyType_Type;
+    PyDiaMenuitem_Type.ob_type = &PyType_Type;
 #endif
 
     m = Py_InitModule3("dia", dia_methods, dia_module_doc);
@@ -637,6 +639,8 @@ initdia(void)
 			 (void *)&PyDiaText_Type);
     PyDict_SetItemString(d, "Paperinfo",
 			 (void *)&PyDiaPaperinfo_Type);
+    PyDict_SetItemString(d, "Menuitem",
+			 (void *)&PyDiaMenuitem_Type);
 
     if (PyErr_Occurred())
 	Py_FatalError("can't initialise module dia");
diff --git a/plug-ins/python/makefile.msc b/plug-ins/python/makefile.msc
index a76ef50..8612e1c 100644
--- a/plug-ins/python/makefile.msc
+++ b/plug-ins/python/makefile.msc
@@ -35,6 +35,7 @@ OBJECTS = \
 	pydia-handle.obj \
 	pydia-image.obj \
 	pydia-layer.obj \
+	pydia-menuitem.obj \
 	pydia-object.obj \
 	pydia-paperinfo.obj \
 	pydia-properties.obj \
diff --git a/plug-ins/python/pydia-error.c b/plug-ins/python/pydia-error.c
index 52654a0..bef2447 100644
--- a/plug-ins/python/pydia-error.c
+++ b/plug-ins/python/pydia-error.c
@@ -177,6 +177,18 @@ PyTypeObject PyDiaError_Type = {
     (hashfunc)PyDiaError_Hash,
     (ternaryfunc)0,
     (reprfunc)PyDiaError_Str,
-    0L,0L,0L,0L,
-    NULL
+    (getattrofunc)0L,
+    (setattrofunc)0L,
+    (PyBufferProcs *)0L,
+    0L, /* Flags */
+    "The error object is just a helper to redirect errors to messages",
+    (traverseproc)0,
+    (inquiry)0,
+    (richcmpfunc)0,
+    0, /* tp_weakliszoffset */
+    (getiterfunc)0,
+    (iternextfunc)0,
+    PyDiaError_Methods, /* tp_methods */
+    NULL, /* tp_members */
+    0
 };
diff --git a/plug-ins/python/pydia-menuitem.c b/plug-ins/python/pydia-menuitem.c
new file mode 100644
index 0000000..31b0b04
--- /dev/null
+++ b/plug-ins/python/pydia-menuitem.c
@@ -0,0 +1,181 @@
+/* Python plug-in for dia
+ * Copyright (C) 1999  James Henstridge
+ * Copyright (C) 2011  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 <config.h>
+
+#include "pydia-menuitem.h"
+#include "pydia-object.h" /* for PyObject_HEAD_INIT */
+
+#include <structmember.h> /* PyMemberDef */
+
+/*
+ * New
+ */
+PyObject* PyDiaMenuitem_New (const DiaMenuItem *menuitem)
+{
+  PyDiaMenuitem *self;
+  
+  self = PyObject_NEW(PyDiaMenuitem, &PyDiaMenuitem_Type);
+  if (!self) return NULL;
+  
+  self->menuitem = menuitem;
+
+  return (PyObject *)self;
+}
+
+/*
+ * Dealloc
+ */
+static void
+PyDiaMenuitem_Dealloc(PyDiaMenuitem *self)
+{
+  /* we dont own the object */
+  PyObject_DEL(self);
+}
+
+/*
+ * Compare
+ */
+static int
+PyDiaMenuitem_Compare(PyDiaMenuitem *self,
+                      PyDiaMenuitem *other)
+{
+  return (self->menuitem == other->menuitem);
+}
+
+/*
+ * Hash
+ */
+static long
+PyDiaMenuitem_Hash(PyObject *self)
+{
+  return (long)self;
+}
+
+/*
+ * GetAttr
+ */
+static PyObject *
+PyDiaMenuitem_GetAttr(PyDiaMenuitem *self, gchar *attr)
+{
+  if (!strcmp(attr, "__members__"))
+    return Py_BuildValue("[ss]", "text", "active");
+  else if (!strcmp(attr, "text"))
+    return PyString_FromString(self->menuitem->text);
+  else if (!strcmp(attr, "active"))
+    return PyInt_FromLong(self->menuitem->active);
+
+  PyErr_SetString(PyExc_AttributeError, attr);
+  return NULL;
+}
+
+
+static PyObject *
+PyDiaMenuitem_Call(PyDiaMenuitem *self, PyObject *args)
+{
+  const DiaMenuItem *mi;
+  ObjectChange *oc;
+  DiaObject *obj;
+  Point clicked;
+
+  if (!PyArg_ParseTuple(args, "O!(dd)|ii:Menuitem.callback",
+                        &PyDiaObject_Type, &obj, &clicked.x, &clicked.y))
+    return NULL;
+    
+  mi = self->menuitem;
+
+  oc = mi->callback (obj, &clicked, mi->callback_data);
+  /* Throw away the undo information */
+  if (oc) {
+    if (oc->free)
+      oc->free(oc);
+    g_free (oc);
+  }
+
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+/*
+ * Repr / _Str
+ */
+static PyObject *
+PyDiaMenuitem_Str(PyDiaMenuitem *self)
+{
+  PyObject* py_s;
+  gchar* s = g_strdup_printf("%s - %s,%s,%s",
+                             self->menuitem->text, 
+			     self->menuitem->active & DIAMENU_ACTIVE ? "active" : "inactive",
+			     self->menuitem->active & DIAMENU_TOGGLE ? "toggle" : "",
+			     self->menuitem->active & DIAMENU_TOGGLE_ON ? "on" : "");
+  py_s = PyString_FromString(s);
+  g_free (s);
+  return py_s;
+}
+
+static PyMethodDef PyDiaMenuitem_Methods[] = {
+    { "call", (PyCFunction)PyDiaMenuitem_Call, METH_VARARGS,
+      "call() -> None."
+      "  Invoke the menuitem callback on object." },
+    { NULL, 0, 0, NULL }
+};
+
+#define T_INVALID -1 /* can't allow direct access due to pyobject->menuitem indirection */
+static PyMemberDef PyDiaMenuitem_Members[] = {
+    { "text", T_INVALID, 0, RESTRICTED|READONLY,
+      "string: what would be written in the menu" },
+    { "active", T_INVALID, 0, RESTRICTED|READONLY,
+      "boolean: if it is callable" },
+    { NULL }
+};
+/*
+ * Python objetcs
+ */
+PyTypeObject PyDiaMenuitem_Type = {
+    PyObject_HEAD_INIT(&PyType_Type)
+    0,
+    "dia.Menuitem",
+    sizeof(PyDiaMenuitem),
+    0,
+    (destructor)PyDiaMenuitem_Dealloc,
+    (printfunc)0,
+    (getattrfunc)PyDiaMenuitem_GetAttr,
+    (setattrfunc)0,
+    (cmpfunc)PyDiaMenuitem_Compare,
+    (reprfunc)0,
+    0,
+    0,
+    0,
+    (hashfunc)PyDiaMenuitem_Hash,
+    (ternaryfunc)0,
+    (reprfunc)PyDiaMenuitem_Str,
+    (getattrofunc)0,
+    (setattrofunc)0,
+    (PyBufferProcs *)0,
+    0L, /* Flags */
+    "dia.Menuitem is holding menu functions for dia.Object",
+    (traverseproc)0,
+    (inquiry)0,
+    (richcmpfunc)0,
+    0, /* tp_weakliszoffset */
+    (getiterfunc)0,
+    (iternextfunc)0,
+    PyDiaMenuitem_Methods, /* tp_methods */
+    PyDiaMenuitem_Members, /* tp_members */
+    0
+};
diff --git a/plug-ins/python/pydia-menuitem.h b/plug-ins/python/pydia-menuitem.h
new file mode 100644
index 0000000..56e8122
--- /dev/null
+++ b/plug-ins/python/pydia-menuitem.h
@@ -0,0 +1,17 @@
+#ifndef PYDIA_MENUITEM_H
+#define PYDIA_MENUITEM_H
+
+#include <Python.h>
+#include "object.h"
+
+typedef struct {
+    PyObject_HEAD
+    const DiaMenuItem *menuitem;
+} PyDiaMenuitem;
+
+
+extern PyTypeObject PyDiaMenuitem_Type;
+
+PyObject *PyDiaMenuitem_New(const DiaMenuItem *layer);
+
+#endif /* PYDIA_MENUITEM_H */
diff --git a/plug-ins/python/pydia-object.c b/plug-ins/python/pydia-object.c
index d9d289e..afceb6e 100644
--- a/plug-ins/python/pydia-object.c
+++ b/plug-ins/python/pydia-object.c
@@ -25,6 +25,7 @@
 #include "pydia-geometry.h"
 #include "pydia-properties.h"
 #include "pydia-render.h"
+#include "pydia-menuitem.h"
 
 #include <structmember.h> /* PyMemberDef */
 
@@ -157,6 +158,35 @@ PyDiaObject_Copy(PyDiaObject *self, PyObject *args)
 }
 
 static PyObject *
+PyDiaObject_GetMenu(PyDiaObject *self, PyObject *args)
+{
+    PyObject *ret, *items;
+    Point clicked = { 0, 0 };
+    DiaMenu *m;
+    int i;
+    
+
+    if (!PyArg_ParseTuple(args, ":Object.get_object_menu"))
+	return NULL;
+	
+    if (!self->object->ops->get_object_menu ||
+        !(m = self->object->ops->get_object_menu (self->object, &clicked))) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }    ;
+
+    ret = PyTuple_New (2);
+    PyTuple_SetItem(ret, 0, PyString_FromString (m->title ? m->title : ""));
+    items = PyList_New(0);
+    for (i = 0; i < m->num_items; ++i) {
+        DiaMenuItem *mi = &m->items[i];
+	if (mi->text && mi->callback)
+	  PyList_Append(items, PyDiaMenuitem_New (mi));
+    }
+    PyTuple_SetItem(ret, 1, items);
+    return ret;
+}
+static PyObject *
 PyDiaObject_Move(PyDiaObject *self, PyObject *args)
 {
     Point point;
@@ -219,6 +249,8 @@ static PyMethodDef PyDiaObject_Methods[] = {
     { "draw", (PyCFunction)PyDiaObject_Draw, METH_VARARGS,
       "draw(dia.Renderer: r) -> None."
       "  Draw the object with the given renderer" },
+    { "get_object_menu", (PyCFunction)PyDiaObject_GetMenu, METH_VARARGS,
+      "get_object_menu() -> Tuple.  Returns a named list of Menuitem(s)." },
     { "move", (PyCFunction)PyDiaObject_Move, METH_VARARGS,
       "move(real: x, real: y) -> None."
       "  Move the entire object. The given point is the new object.obj_pos." },
diff --git a/plug-ins/python/pydia-property.c b/plug-ins/python/pydia-property.c
index 009b643..04efbe4 100644
--- a/plug-ins/python/pydia-property.c
+++ b/plug-ins/python/pydia-property.c
@@ -805,11 +805,15 @@ PyDiaProperty_GetAttr(PyDiaProperty *self, gchar *attr)
 {
 
   if (!strcmp(attr, "__members__"))
-    return Py_BuildValue("[ssss]", "name", "type", "value", "visible");
+    return Py_BuildValue("[ssss]", "name", "type", "value", "visible", "description", "tooltip");
   else if (!strcmp(attr, "name"))
     return PyString_FromString(self->property->descr->name);
   else if (!strcmp(attr, "type"))
     return PyString_FromString(self->property->descr->type);
+  else if (!strcmp(attr, "description"))
+    return PyString_FromString(self->property->descr->description);
+  else if (!strcmp(attr, "tooltip"))
+    return PyString_FromString(self->property->descr->tooltip);
   else if (!strcmp(attr, "visible"))
     return PyInt_FromLong(0 != (self->property->descr->flags & PROP_FLAG_VISIBLE));
   else if (!strcmp(attr, "value")) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]