mirror of
https://github.com/gryf/wmdocklib.git
synced 2025-12-19 04:20:17 +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:
@@ -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)
|
||||
|
||||
|
||||
@@ -9,4 +9,4 @@ help(wmdocklib.<name>)
|
||||
from pywmgeneral import *
|
||||
from pywmhelpers import *
|
||||
|
||||
__all__ = []
|
||||
__all__ = ['wmoo']
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user