1
0
mirror of https://github.com/gryf/wmdocklib.git synced 2025-12-18 20:10:23 +01:00

1595052: writing strings

I've added the class pywmgeneral.Drawable, offering an interface to pixmaps.

this way a wmdocklib application can have more than one drawable: not only
the main window, but as many pixmaps as are necessary.

the first use of pywmgeneral.Drawable is to hold the graphical
representation of the labels in an application.  Labels are also new to the
library and the intention is that they substitute the putString methods.

Application.addLabel() is used to create a new named label.  the label takes
care of the specified area, or of the area necessary to show the specified
string.

Application.setLabelText() is used to specify a new text for a label.  if
necessary, a new pixmap is created.  the area taken care of by a label
cannot be modified.

during the update cycle, labels that span an area which is too small for
their text are scrolled a pixel at a time.

pywmradio.py uses this functionality.
This commit is contained in:
mfrasca
2007-05-21 12:32:16 +00:00
parent 195b5f7db6
commit 6d70762f4a
5 changed files with 227 additions and 11 deletions

View File

@@ -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)

View File

@@ -9,4 +9,4 @@ help(wmdocklib.<name>)
from pywmgeneral import *
from pywmhelpers import *
__all__ = []
__all__ = ['wmoo']

View File

@@ -30,6 +30,7 @@
*/
#include <Python.h>
#include "structmember.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -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);
}

View File

@@ -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):

View File

@@ -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):