Refactored, enhanced and added capabilites for the DrawXXXList

functions, inspired by code from Chris Barker.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@19373 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2003-02-28 00:15:29 +00:00
parent 616538882e
commit c74807054b
6 changed files with 791 additions and 221 deletions

350
wxPython/src/drawlist.cpp Normal file
View File

@@ -0,0 +1,350 @@
/////////////////////////////////////////////////////////////////////////////
// Name: drawlist.cpp
// Purpose: Helper functions for optimized list drawing on a wxDC
//
// Author: Robin Dunn Chris Barker
//
// Created:
// RCS-ID: $Id$
// Copyright: (c) 2003 by Total Control Software
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#undef DEBUG
#include <Python.h>
#include "helpers.h"
//----------------------------------------------------------------------
PyObject* wxPyDrawXXXList(wxDC& dc, wxPyDrawListOp_t doDraw,
PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes) {
wxPyBeginBlockThreads(); // _DrawXXXList
bool isFastSeq = PyList_Check(pyCoords) || PyTuple_Check(pyCoords);
bool isFastPens = PyList_Check(pyPens) || PyTuple_Check(pyPens);
bool isFastBrushes = PyList_Check(pyBrushes) || PyTuple_Check(pyBrushes);
int numObjs = 0;
int numPens = 0;
int numBrushes = 0;
wxPen* pen;
wxBrush* brush;
PyObject* obj;
PyObject* coords;
int x1, x2, x3, x4;
int i = 0;
PyObject* retval;
if (!PySequence_Check(pyCoords)) {
goto err0;
}
if (!PySequence_Check(pyPens)) {
goto err1;
}
if (!PySequence_Check(pyBrushes)) {
goto err2;
}
numObjs = PySequence_Length(pyCoords);
numPens = PySequence_Length(pyPens);
numBrushes = PySequence_Length(pyBrushes);
for (i = 0; i < numObjs; i++) {
// Use a new pen?
if (i < numPens) {
if (isFastPens) {
obj = PySequence_Fast_GET_ITEM(pyPens, i);
}
else {
obj = PySequence_GetItem(pyPens, i);
}
if (SWIG_GetPtrObj(obj, (void **) &pen, "_wxPen_p")) {
if (!isFastPens)
Py_DECREF(obj);
goto err1;
}
dc.SetPen(*pen);
if (!isFastPens)
Py_DECREF(obj);
}
// Use a new brush?
if (i < numBrushes) {
if (isFastBrushes) {
obj = PySequence_Fast_GET_ITEM(pyBrushes, i);
}
else {
obj = PySequence_GetItem(pyBrushes, i);
}
if (SWIG_GetPtrObj(obj, (void **) &brush, "_wxBrush_p")) {
if (!isFastBrushes)
Py_DECREF(obj);
goto err2;
}
dc.SetBrush(*brush);
if (!isFastBrushes)
Py_DECREF(obj);
}
// Get the Coordinates
if (isFastSeq) {
coords = PySequence_Fast_GET_ITEM(pyCoords, i);
}
else {
coords = PySequence_GetItem(pyCoords, i);
}
// call the drawOp
bool success = doDraw(dc, coords);
if (!isFastSeq)
Py_DECREF(coords);
if (! success) {
retval = NULL;
goto exit;
}
} // end of main for loop
Py_INCREF(Py_None);
retval = Py_None;
goto exit;
err0:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of coordinates");
retval = NULL;
goto exit;
err1:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of wxPens");
retval = NULL;
goto exit;
err2:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of wxBrushes");
retval = NULL;
goto exit;
exit:
wxPyEndBlockThreads();
return retval;
}
bool wxPyDrawXXXPoint(wxDC& dc, PyObject* coords) {
int x, y;
if (! wxPy2int_seq_helper(coords, &x, &y)) {
PyErr_SetString(PyExc_TypeError, "Expected a sequence of (x,y) sequences.");
return FALSE;
}
dc.DrawPoint(x, y);
return TRUE;
}
bool wxPyDrawXXXLine(wxDC& dc, PyObject* coords) {
int x1, y1, x2, y2;
if (! wxPy4int_seq_helper(coords, &x1, &y1, &x2, &y2)) {
PyErr_SetString(PyExc_TypeError, "Expected a sequence of (x1,y1, x1,y2) sequences.");
return FALSE;
}
dc.DrawLine(x1,y1, x2,y2);
return TRUE;
}
bool wxPyDrawXXXRectangle(wxDC& dc, PyObject* coords) {
int x, y, w, h;
if (! wxPy4int_seq_helper(coords, &x, &y, &w, &h)) {
PyErr_SetString(PyExc_TypeError, "Expected a sequence of (x,y, w,h) sequences.");
return FALSE;
}
dc.DrawRectangle(x, y, w, h);
return TRUE;
}
bool wxPyDrawXXXEllipse(wxDC& dc, PyObject* coords) {
int x, y, w, h;
if (! wxPy4int_seq_helper(coords, &x, &y, &w, &h)) {
PyErr_SetString(PyExc_TypeError, "Expected a sequence of (x,y, w,h) sequences.");
return FALSE;
}
dc.DrawEllipse(x, y, w, h);
return TRUE;
}
bool wxPyDrawXXXPolygon(wxDC& dc, PyObject* coords) {
wxPoint* points;
int numPoints;
points = wxPoint_LIST_helper(coords, &numPoints);
if (! points) {
PyErr_SetString(PyExc_TypeError, "Expected a sequence of sequences of (x,y) sequences.");
return FALSE;
}
dc.DrawPolygon(numPoints, points);
return TRUE;
}
//----------------------------------------------------------------------
PyObject* wxPyDrawTextList(wxDC& dc, PyObject* textList, PyObject* pyPoints, PyObject* foregroundList, PyObject* backgroundList) {
wxPyBeginBlockThreads();
bool isFastSeq = PyList_Check(pyPoints) || PyTuple_Check(pyPoints);
bool isFastText = PyList_Check(textList) || PyTuple_Check(textList);
bool isFastForeground = PyList_Check(foregroundList) || PyTuple_Check(foregroundList);
bool isFastBackground = PyList_Check(backgroundList) || PyTuple_Check(backgroundList);
int numText = 0;
int numPoints = 0;
int numForeground = 0;
int numBackground = 0;
PyObject* obj;
int x1, y1;
int i = 0;
wxColor* color;
PyObject* retval;
wxString string;
if (!PySequence_Check(pyPoints)) {
goto err0;
}
if (!PySequence_Check(textList)) {
goto err1;
}
if (!PySequence_Check(foregroundList)) {
goto err2;
}
if (!PySequence_Check(backgroundList)) {
goto err3;
}
numPoints = PySequence_Length(pyPoints);
numText = PySequence_Length(textList);
numForeground = PySequence_Length(foregroundList);
numBackground = PySequence_Length(backgroundList);
for (i = 0; i < numPoints; i++) {
// Use a new string ?
if (i < numText) {
if ( isFastText ) {
obj = PySequence_Fast_GET_ITEM(textList, i);
}
else {
obj = PySequence_GetItem(textList, i);
}
if (! PyString_Check(obj) ) {
Py_DECREF(obj);
goto err1;
}
string = Py2wxString(obj);
if ( !isFastText )
Py_DECREF(obj);
}
if (i < numForeground) {
// Use a new foreground ?
if ( isFastForeground ) {
obj = PySequence_Fast_GET_ITEM(foregroundList, i);
}
else {
obj = PySequence_GetItem(foregroundList, i);
}
if (SWIG_GetPtrObj(obj, (void **) &color, "_wxColour_p")) {
if (!isFastForeground)
Py_DECREF(obj);
goto err2;
}
dc.SetTextForeground(*color);
if ( !isFastForeground )
Py_DECREF(obj);
}
if (i < numBackground) {
// Use a new background ?
if ( isFastBackground ) {
obj = PySequence_Fast_GET_ITEM(backgroundList, i);
}
else {
obj = PySequence_GetItem(backgroundList, i);
}
if (SWIG_GetPtrObj(obj, (void **) &color, "_wxColour_p")) {
if (!isFastBackground)
Py_DECREF(obj);
goto err3;
}
dc.SetTextBackground(*color);
if ( !isFastBackground )
Py_DECREF(obj);
}
// Get the point coordinates
if (isFastSeq) {
obj = PySequence_Fast_GET_ITEM(pyPoints, i);
}
else {
obj = PySequence_GetItem(pyPoints, i);
}
if (! wxPy2int_seq_helper(obj, &x1, &y1)) {
if (! isFastSeq)
Py_DECREF(obj);
goto err0;
}
if (PyErr_Occurred()) {
retval = NULL;
if (!isFastSeq)
Py_DECREF(obj);
goto exit;
}
// Now draw the text
dc.DrawText(string, x1, y1);
if (!isFastText)
Py_DECREF(obj);
}
Py_INCREF(Py_None);
retval = Py_None;
goto exit;
err0:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of (x,y) sequences.");
retval = NULL;
goto exit;
err1:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of strings");
retval = NULL;
goto exit;
err2:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of wxColours for foregrounds");
retval = NULL;
goto exit;
err3:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of wxColours for backgrounds");
retval = NULL;
goto exit;
exit:
wxPyEndBlockThreads();
return retval;
}
//----------------------------------------------------------------------

View File

@@ -712,210 +712,134 @@ public:
#endif
%addmethods {
// NOTE: These methods are VERY SIMILAR in implentation. It would be
// nice to factor out common code and or turn them into a set of
// template-like macros.
%addmethods { // See drawlist.cpp for impplementaion of these...
// Draw a point for every set of coordinants in pyPoints, optionally
// setting a new pen for each
PyObject* _DrawPointList(PyObject* pyPoints, PyObject* pyPens) {
wxPyBeginBlockThreads();
bool isFastSeq = PyList_Check(pyPoints) || PyTuple_Check(pyPoints);
bool isFastPens = PyList_Check(pyPens) || PyTuple_Check(pyPens);
int numObjs = 0;
int numPens = 0;
wxPen* pen;
PyObject* obj;
int x1, y1;
int i = 0;
PyObject* retval;
if (!PySequence_Check(pyPoints)) {
goto err0;
}
if (!PySequence_Check(pyPens)) {
goto err1;
}
numObjs = PySequence_Length(pyPoints);
numPens = PySequence_Length(pyPens);
for (i = 0; i < numObjs; i++) {
// Use a new pen?
if (i < numPens) {
if (isFastPens) {
obj = PySequence_Fast_GET_ITEM(pyPens, i);
}
else {
obj = PySequence_GetItem(pyPens, i);
}
if (SWIG_GetPtrObj(obj, (void **) &pen, "_wxPen_p")) {
if (!isFastPens)
Py_DECREF(obj);
goto err1;
}
self->SetPen(*pen);
if (!isFastPens)
Py_DECREF(obj);
}
// Get the point coordinants
if (isFastSeq) {
obj = PySequence_Fast_GET_ITEM(pyPoints, i);
}
else {
obj = PySequence_GetItem(pyPoints, i);
}
if (! wxPy2int_seq_helper(obj, &x1, &y1)) {
if (!isFastPens)
Py_DECREF(obj);
goto err0;
}
if (PyErr_Occurred()) {
retval = NULL;
if (!isFastPens)
Py_DECREF(obj);
goto exit;
}
// Now draw the point
self->DrawPoint(x1, y1);
if (!isFastSeq)
Py_DECREF(obj);
}
Py_INCREF(Py_None);
retval = Py_None;
goto exit;
err1:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of wxPens");
retval = NULL;
goto exit;
err0:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of (x,y) sequences.");
retval = NULL;
goto exit;
exit:
wxPyEndBlockThreads();
return retval;
PyObject* _DrawPointList(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)
{
return wxPyDrawXXXList(*self, wxPyDrawXXXPoint, pyCoords, pyPens, pyBrushes);
}
PyObject* _DrawLineList(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)
{
return wxPyDrawXXXList(*self, wxPyDrawXXXLine, pyCoords, pyPens, pyBrushes);
}
// Draw a line for every set of coordinants in pyLines, optionally
// setting a new pen for each
PyObject* _DrawLineList(PyObject* pyLines, PyObject* pyPens) {
wxPyBeginBlockThreads();
PyObject* _DrawRectangleList(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)
{
return wxPyDrawXXXList(*self, wxPyDrawXXXRectangle, pyCoords, pyPens, pyBrushes);
}
bool isFastSeq = PyList_Check(pyLines) || PyTuple_Check(pyLines);
bool isFastPens = PyList_Check(pyPens) || PyTuple_Check(pyPens);
int numObjs = 0;
int numPens = 0;
wxPen* pen;
PyObject* obj;
int x1, y1, x2, y2;
int i = 0;
PyObject* retval;
PyObject* _DrawEllipseList(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)
{
return wxPyDrawXXXList(*self, wxPyDrawXXXEllipse, pyCoords, pyPens, pyBrushes);
}
if (!PySequence_Check(pyLines)) {
goto err0;
}
if (!PySequence_Check(pyPens)) {
goto err1;
}
numObjs = PySequence_Length(pyLines);
numPens = PySequence_Length(pyPens);
PyObject* _DrawPolygonList(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)
{
return wxPyDrawXXXList(*self, wxPyDrawXXXPolygon, pyCoords, pyPens, pyBrushes);
}
for (i = 0; i < numObjs; i++) {
// Use a new pen?
if (i < numPens) {
if (isFastPens) {
obj = PySequence_Fast_GET_ITEM(pyPens, i);
}
else {
obj = PySequence_GetItem(pyPens, i);
}
if (SWIG_GetPtrObj(obj, (void **) &pen, "_wxPen_p")) {
if (!isFastPens)
Py_DECREF(obj);
goto err1;
}
self->SetPen(*pen);
if (!isFastPens)
Py_DECREF(obj);
}
// Get the line coordinants
if (isFastSeq) {
obj = PySequence_Fast_GET_ITEM(pyLines, i);
}
else {
obj = PySequence_GetItem(pyLines, i);
}
if (! wxPy4int_seq_helper(obj, &x1, &y1, &x2, &y2)) {
if (!isFastPens)
Py_DECREF(obj);
goto err0;
}
if (PyErr_Occurred()) {
retval = NULL;
if (!isFastPens)
Py_DECREF(obj);
goto exit;
}
// Now draw the line
self->DrawLine(x1, y1, x2, y2);
if (!isFastSeq)
Py_DECREF(obj);
}
Py_INCREF(Py_None);
retval = Py_None;
goto exit;
err1:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of wxPens");
retval = NULL;
goto exit;
err0:
PyErr_SetString(PyExc_TypeError, "Expected a sequence of (x1,y1, x2,y2) sequences.");
retval = NULL;
goto exit;
exit:
wxPyEndBlockThreads();
return retval;
PyObject* _DrawTextList(PyObject* textList, PyObject* pyPoints,
PyObject* foregroundList, PyObject* backgroundList) {
return wxPyDrawTextList(*self, textList, pyPoints, foregroundList, backgroundList);
}
}
%pragma(python) addtoclass = "
def DrawPointList(self, points, pens=None):
if pens is None:
pens = []
elif wx.wxPy_isinstance(pens, (wxPen, wxPenPtr)):
elif isinstance(pens, wxPenPtr):
pens = [pens]
elif len(pens) != len(points):
raise ValueError('points and pens must have same length')
return self._DrawPointList(points, pens)
return self._DrawPointList(points, pens, [])
def DrawLineList(self, lines, pens=None):
if pens is None:
pens = []
elif wx.wxPy_isinstance(pens, (wxPen, wxPenPtr)):
elif isinstance(pens, wxPenPtr):
pens = [pens]
elif len(pens) != len(lines):
raise ValueError('lines and pens must have same length')
return self._DrawLineList(lines, pens)
return self._DrawLineList(lines, pens, [])
def DrawRectangleList(self, rectangles, pens=None, brushes=None):
if pens is None:
pens = []
elif isinstance(pens, wxPenPtr):
pens = [pens]
elif len(pens) != len(rectangles):
raise ValueError('rectangles and pens must have same length')
if brushes is None:
brushes = []
elif isinstance(brushes, wxBrushPtr):
brushes = [brushes]
elif len(brushes) != len(rectangles):
raise ValueError('rectangles and brushes must have same length')
return self._DrawRectangleList(rectangles, pens, brushes)
def DrawEllipseList(self, ellipses, pens=None, brushes=None):
if pens is None:
pens = []
elif isinstance(pens, wxPenPtr):
pens = [pens]
elif len(pens) != len(ellipses):
raise ValueError('ellipses and pens must have same length')
if brushes is None:
brushes = []
elif isinstance(brushes, wxBrushPtr):
brushes = [brushes]
elif len(brushes) != len(ellipses):
raise ValueError('ellipses and brushes must have same length')
return self._DrawEllipseList(ellipses, pens, brushes)
def DrawPolygonList(self, polygons, pens=None, brushes=None):
## Note: This does not currently support fill style or offset
## you can always use the non-List version if need be.
## I really would like to support fill-style, however,
## but wxODDEVEN_RULE does not appear to be defined at the Python level
## [It's in wx.py... --Robin]
if pens is None:
pens = []
elif isinstance(pens, wxPenPtr):
pens = [pens]
elif len(pens) != len(polygons):
raise ValueError('polygons and pens must have same length')
if brushes is None:
brushes = []
elif isinstance(brushes, wxBrushPtr):
brushes = [brushes]
elif len(brushes) != len(polygons):
raise ValueError('polygons and brushes must have same length')
return self._DrawPolygonList(polygons, pens, brushes)
def DrawTextList(self, textList, coords, foregrounds = None, backgrounds = None, fonts = None):
## NOTE: this does not currently support changing the font
## Make sure you set Background mode to wxSolid (DC.SetBackgroundMode)
## If you want backgounds to do anything.
if type(textList) == type(''):
textList = [textList]
elif len(textList) != len(coords):
raise ValueError('textlist and coords must have same length')
if foregrounds is None:
foregrounds = []
elif isinstance(foregrounds, wxColourPtr):
foregrounds = [foregrounds]
elif len(foregrounds) != len(coords):
raise ValueError('foregrounds and coords must have same length')
if backgrounds is None:
backgrounds = []
elif isinstance(backgrounds, wxColourPtr):
backgrounds = [backgrounds]
elif len(backgrounds) != len(coords):
raise ValueError('backgrounds and coords must have same length')
return self._DrawTextList(textList, coords, foregrounds, backgrounds)
"

View File

@@ -109,6 +109,21 @@ PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr);
#define DECLARE_DEF_STRING(name) static const wxString wxPy##name(wx##name)
#define DECLARE_DEF_STRING2(name,val) static const wxString wxPy##name(val)
//----------------------------------------------------------------------
// functions used by the DrawXXXList enhancements added to wxDC
typedef bool (*wxPyDrawListOp_t)(wxDC& dc, PyObject* coords);
PyObject* wxPyDrawXXXList(wxDC& dc, wxPyDrawListOp_t doDraw,
PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes);
bool wxPyDrawXXXPoint(wxDC& dc, PyObject* coords);
bool wxPyDrawXXXLine(wxDC& dc, PyObject* coords);
bool wxPyDrawXXXRectangle(wxDC& dc, PyObject* coords);
bool wxPyDrawXXXEllipse(wxDC& dc, PyObject* coords);
bool wxPyDrawXXXPolygon(wxDC& dc, PyObject* coords);
PyObject* wxPyDrawTextList(wxDC& dc, PyObject* textList, PyObject* pyPoints,
PyObject* foregroundList, PyObject* backgroundList);
//----------------------------------------------------------------------
#ifndef SWIGCODE