diff --git a/examples/pywmradio.py b/examples/pywmradio.py index d7aec68..4bf263b 100755 --- a/examples/pywmradio.py +++ b/examples/pywmradio.py @@ -53,7 +53,7 @@ class Application(wmoo.Application): globals()[radiodef[1]] = radiodef[2] pass else: - self.radioList.append( (radioname+' '*24, radiodef[1], radiodef[2]) ) + self.radioList.append( (radioname, radiodef[1], radiodef[2]) ) def handler(self, num, frame): @@ -106,7 +106,7 @@ class Application(wmoo.Application): def previousRadio(self, event): if self.currentRadio == 0: self.currentRadio = len(self.radioList) self.currentRadio -= 1 - self.putString(0, 10, self.radioList[self.currentRadio][0]) + self.setLabelText('name', self.radioList[self.currentRadio][0]) if self.child: self.stopPlayer() self.startPlayer() @@ -114,7 +114,7 @@ class Application(wmoo.Application): def nextRadio(self, event): self.currentRadio += 1 if self.currentRadio == len(self.radioList): self.currentRadio = 0 - self.putString(0, 10, self.radioList[self.currentRadio][0]) + self.setLabelText('name', self.radioList[self.currentRadio][0]) if self.child: self.stopPlayer() self.startPlayer() @@ -158,6 +158,7 @@ class Application(wmoo.Application): self.putPattern(54, 0, 3, 1, 52, 54-i) def update(self): + wmoo.Application.update(self) self._count += 1 if self._count <= 3: return @@ -285,7 +286,7 @@ def main(): background = background, patterns = patterns) # maxCharsPerLine = (width-2*xOffset) / char width - app.putString(0, 10, app.radioList[app.currentRadio][0]) + app.addLabel('name', (3, 13), (58, 10), app.radioList[app.currentRadio][0]) # app.addCallback(printevent) diff --git a/wmdocklib/__init__.py b/wmdocklib/__init__.py index ca4fe51..4102204 100644 --- a/wmdocklib/__init__.py +++ b/wmdocklib/__init__.py @@ -9,4 +9,4 @@ help(wmdocklib.) from pywmgeneral import * from pywmhelpers import * -__all__ = [] +__all__ = ['wmoo'] diff --git a/wmdocklib/pywmgeneral.c b/wmdocklib/pywmgeneral.c index de5b5ac..457dd42 100644 --- a/wmdocklib/pywmgeneral.c +++ b/wmdocklib/pywmgeneral.c @@ -30,6 +30,7 @@ */ #include +#include "structmember.h" #include #include #include @@ -254,10 +255,155 @@ static PyMethodDef PyWmgeneralMethods[] = { {NULL, NULL, 0, NULL} }; -void initpywmgeneral(void) { - Py_InitModule("pywmgeneral", PyWmgeneralMethods); +typedef struct { + PyObject_HEAD + /* Type-specific fields go here. */ + int has_drawable; + Pixmap drawable; + int width, height; +} drawable_DrawableObject; + +static PyObject * +Drawable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + drawable_DrawableObject *self; + + self = (drawable_DrawableObject *)type->tp_alloc(type, 0); + if (self != NULL) { + self->has_drawable = 0; + self->width = 0; + self->height = 0; + } + + return (PyObject *)self; } +static int +Drawable_init(drawable_DrawableObject *self, PyObject *args, PyObject *kwds) +{ + unsigned int w, h; + if (! PyArg_ParseTuple(args, "ii", &w, &h)) + return -1; + if (!wmgen.attributes.depth) { + PyErr_SetString(PyExc_RuntimeError, "X client must be initialized first."); + return -1; + } + + if (self->has_drawable) + XFreePixmap(display, self->drawable); + self->has_drawable = 1; + self->width = w; + self->height = h; + self->drawable = XCreatePixmap(display, wmgen.pixmap, + w, h, wmgen.attributes.depth); + + return 0; +} + +static void +Drawable_dealloc(drawable_DrawableObject *self) +{ + if (self->has_drawable) + XFreePixmap(display, self->drawable); +} + +static PyObject * +Drawable_xCopyAreaToWindow(drawable_DrawableObject *self, PyObject *args, PyObject *kwds) +{ + unsigned int src_x, src_y, width, height, dst_x, dst_y; + if (! PyArg_ParseTuple(args, "iiiiii", &src_x, &src_y, &width, &height, &dst_x, &dst_y)) + return NULL; + + XCopyArea(display, self->drawable, wmgen.pixmap, NormalGC, + src_x, src_y, width, height, dst_x, dst_y); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +Drawable_xClear(drawable_DrawableObject *self, PyObject *args, PyObject *kwds) +{ + XFillRectangle(display, self->drawable, NormalGC, + 0, 0, self->width, self->height); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +Drawable_xCopyAreaFromWindow(drawable_DrawableObject *self, PyObject *args, PyObject *kwds) +{ + unsigned int src_x, src_y, width, height, dst_x, dst_y; + if (! PyArg_ParseTuple(args, "iiiiii", &src_x, &src_y, &width, &height, &dst_x, &dst_y)) + return NULL; + + XCopyArea(display, wmgen.pixmap, self->drawable, NormalGC, + src_x, src_y, width, height, dst_x, dst_y); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyMemberDef Drawable_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef Drawable_methods[] = { + {"xCopyAreaFromWindow", (PyCFunction)Drawable_xCopyAreaFromWindow, METH_VARARGS, + "copy from the drawable to the global pixmap" + }, + {"xCopyAreaToWindow", (PyCFunction)Drawable_xCopyAreaToWindow, METH_VARARGS, + "copy from the global pixmap into the drawable" + }, + {"xClear", (PyCFunction)Drawable_xClear, METH_NOARGS, + "clears the pixmap" + }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject drawable_DrawableType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "pyywmgeneral.Drawable", /*tp_name*/ + sizeof(drawable_DrawableObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)Drawable_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "Drawable objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Drawable_methods, /* tp_methods */ + Drawable_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Drawable_init, /* tp_init */ + 0, /* tp_alloc */ + Drawable_new, /* tp_new */ +}; + /*****************************************************************************/ /* Original C sources (With some modifications) */ /*****************************************************************************/ @@ -299,6 +445,7 @@ static void GetXPM(XpmIcon *wmgen, char *pixmap_bytes[]) { XGetWindowAttributes(display, Root, &attributes); wmgen->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions); + wmgen->attributes.depth = attributes.depth; err = XpmCreatePixmapFromData(display, Root, pixmap_bytes, &(wmgen->pixmap), &(wmgen->mask), &(wmgen->attributes)); @@ -639,3 +786,24 @@ void openXwindow(int argc, char *argv[], char *pixmap_bytes[], char *pixmask_bit XMoveWindow(display, win, wx, wy); } } + +#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ +#define PyMODINIT_FUNC void +#endif + +PyMODINIT_FUNC +initpywmgeneral(void) { + PyObject* m; + + drawable_DrawableType.tp_new = PyType_GenericNew; + if (PyType_Ready(&drawable_DrawableType) < 0) + return; + + m = Py_InitModule3("pywmgeneral", PyWmgeneralMethods, + "base C module for wmdocklib"); + if (m == NULL) + return; + + Py_INCREF(&drawable_DrawableType); + PyModule_AddObject(m, "Drawable", (PyObject *)&drawable_DrawableType); +} diff --git a/wmdocklib/pywmhelpers.py b/wmdocklib/pywmhelpers.py index 93adbd2..1ea50d5 100644 --- a/wmdocklib/pywmhelpers.py +++ b/wmdocklib/pywmhelpers.py @@ -77,7 +77,7 @@ def getCenterStartPos(s, areaWidth, offset): textArea = areaWidth - offset * 2 - 1 return (textArea - w) / 2 -def addChar(ch, x, y, xOffset, yOffset, width, height): +def addChar(ch, x, y, xOffset, yOffset, width, height, drawable=None): """Paint the character ch at position x, y in the window. Return the (width, height) of the character painted. (will be useful if @@ -109,17 +109,21 @@ def addChar(ch, x, y, xOffset, yOffset, width, height): chW = char_width if ch in "',.:;": chW = char_twidth - pywmgeneral.copyXPMArea(chX, chY, chW, char_height, targX, targY) + if drawable is None: + pywmgeneral.copyXPMArea(chX, chY, chW, char_height, targX, targY) + else: + drawable.xCopyAreaFromWindow(chX, chY, chW, char_height, targX, targY) return (chW, char_height) -def addString(s, x, y, xOffset, yOffset, width, height): +def addString(s, x, y, xOffset=0, yOffset=0, width=None, height=None, drawable=None): """Add a string at the given x and y positions. Call addChar repeatedely, so the same exception rules apply.""" lastW = 0 for letter in s: w, h = addChar(letter, x + lastW, y, - xOffset, yOffset, width, height) + xOffset, yOffset, width, height, + drawable) lastW += w def getVertSpacing(numLines, margin, height, yOffset): diff --git a/wmdocklib/wmoo.py b/wmdocklib/wmoo.py index 7e00102..13a96bd 100644 --- a/wmdocklib/wmoo.py +++ b/wmdocklib/wmoo.py @@ -14,8 +14,10 @@ class Application: 'area': if the pointer is here, the event is considered, """ + self._elements = {} self._events = [] self._sleep = 0.1 + self._cycle = 0 self._offset_x = self._offset_y = 3 self._char_width, self._char_height = pywmhelpers.initPixmap(*args, **kwargs) @@ -31,7 +33,48 @@ class Application: pywmhelpers.copyXPMArea(sourceX, sourceY+64, width, height, targetX, targetY) + def addLabel(self, labelId, orig, size=None, text=None): + """a label is a tuple with a + text: string; mutable + viewport: (orig: int, int, size: int, int); inmutable + pixmap: drawable; not user mutable, large enough to contain the text + + if size is not given, it is inferred from text. + """ + if size is None: + size = (self._char_width * len(text), self._char_height) + pixmapwidth = self._char_width * len(text) + import pywmgeneral + labelPixmap = pywmgeneral.Drawable(pixmapwidth, self._char_height) + self._elements[labelId] = [orig, size, pixmapwidth, 0, labelPixmap] + self.setLabelText(labelId, text) + + def setLabelText(self, labelId, text): + """updates the drawable associated with labelId + """ + (orig_x,orig_y), (size_x, size_y), width, offset, pixmap = self._elements[labelId] + newwidth = self._char_width * len(text) + if newwidth > width: + import pywmgeneral + pixmap = pywmgeneral.Drawable(newwidth, self._char_height) + self._elements[labelId][4] = pixmap + self._elements[labelId][2] = newwidth + self._elements[labelId][3] = 0 + pixmap.xClear() + pywmhelpers.addString(text, 0, 0, drawable=pixmap) + pixmap.xCopyAreaToWindow(0, 0, size_x, size_y, orig_x, orig_y) + def update(self): + for labelId in self._elements: + (orig_x,orig_y), (size_x, size_y), width, offset, pixmap = self._elements[labelId] + if size_x < width: + pixmap.xCopyAreaToWindow(offset, 0, size_x, size_y, orig_x, orig_y) + if offset == width: + offset = -size_x + else: + offset += 1 + self._elements[labelId][3] = offset + pass def redraw(self):