diff --git a/wxPython/CHANGES.txt b/wxPython/CHANGES.txt index fd96ee1cb5..3d96896504 100644 --- a/wxPython/CHANGES.txt +++ b/wxPython/CHANGES.txt @@ -63,6 +63,10 @@ always call them. The functions are: wxApp_SetMacExitMenuItemId wxApp_SetMacHelpMenuTitleName +Refactored, enhanced and added capabilites for the DrawXXXList +functions, inspired by code from Chris Barker. + + 2.4.0.2 diff --git a/wxPython/demo/DrawXXXList.py b/wxPython/demo/DrawXXXList.py index 1783ef76e9..16456f9e3d 100644 --- a/wxPython/demo/DrawXXXList.py +++ b/wxPython/demo/DrawXXXList.py @@ -46,6 +46,43 @@ def makeRandomLines(num, w, h): return pnts +def makeRandomRectangles(num, W, H): + rects = [] + for i in range(num): + w = whrandom.randint(10, W/2) + h = whrandom.randint(10, H/2) + x = whrandom.randint(0, W - w) + y = whrandom.randint(0, H - h) + rects.append( (x, y, w, h) ) + return rects + + +def makeRandomText(num): + Np = 8 # number of charcters in text + text = [] + for i in range(num): + word = [] + for i in range(Np): + c = chr( whrandom.randint(48, 122) ) + word.append( c ) + text.append( "".join(word) ) + return text + + +def makeRandomPolygons(num, W, H): + Np = 8 # number of points per polygon + polys = [] + for i in range(num): + poly = [] + for i in range(Np): + x = whrandom.randint(0, W) + y = whrandom.randint(0, H) + poly.append( (x,y) ) + polys.append( poly ) + return polys + + + def makeRandomPens(num, cache): pens = [] for i in range(num): @@ -57,62 +94,275 @@ def makeRandomPens(num, cache): return pens -class TestPanel(wxPanel): - def __init__(self, parent, size, log): - wxPanel.__init__(self, parent, -1, size=size) +def makeRandomBrushes(num, cache): + brushes = [] + for i in range(num): + c = whrandom.choice(colours) + if not cache.has_key(c): + cache[c] = wxBrush(c) + brushes.append( cache[c] ) + return brushes + + +def makeRandomColors(num): + colors = [] + for i in range(num): + c = whrandom.choice(colours) + colors.append(wxNamedColor(c)) + return colors + + + +pencache = {} +brushcache = {} +points = None +lines = None +rectangles = None +polygons = None +text = None +pens = None +brushes = None +colors1 = None +colors2 = None + + +def Init(w, h, n): + global pencache + global brushcache + global points + global lines + global rectangles + global polygons + global text + global pens + global brushes + global colors1 + global colors2 + + # make some lists of random shapes + points = makeRandomPoints(n, w, h) + try: + import Numeric + Apoints = Numeric.array(points) + except: + pass + lines = makeRandomLines(n, w, h) + rectangles = makeRandomRectangles(n, w, h) + polygons = makeRandomPolygons(n, w, h) + text = makeRandomText(n) + + # make some random pens and brushes + pens = makeRandomPens(n, pencache) + brushes = makeRandomBrushes(n, brushcache) + # make some random color lists + colors1 = makeRandomColors(n) + colors2 = makeRandomColors(n) + + + +def TestPoints(dc,log): + dc.BeginDrawing() + start = time.time() + dc.SetPen(wxPen("BLACK", 4)) + + dc.DrawPointList(points) + dc.DrawPointList(points, wxPen("RED", 2)) + dc.DrawPointList(points, pens) + + dc.EndDrawing() + log.write("DrawTime: %s seconds with DrawPointList\n" % (time.time() - start)) + + +def TestArrayPoints(dc,log): + try: + import Numeric + + dc.BeginDrawing() + start = time.time() + dc.SetPen(wxPen("BLACK", 1)) + for i in range(1): + dc.DrawPointList(Apoints) + #dc.DrawPointList(Apoints, wxPen("RED", 2)) + #dc.DrawPointList(Apoints, pens) + dc.EndDrawing() + log.write("DrawTime: %s seconds with DrawPointList an Numpy Array\n" % (time.time() - start)) + except ImportError: + log.write("Couldn't import Numeric") + pass + + +def TestLines(dc,log): + dc.BeginDrawing() + start = time.time() + + dc.SetPen(wxPen("BLACK", 2)) + dc.DrawLineList(lines) + dc.DrawLineList(lines, wxPen("RED", 2)) + dc.DrawLineList(lines, pens) + + dc.EndDrawing() + log.write("DrawTime: %s seconds with DrawLineList\n" % (time.time() - start)) + + +def TestRectangles(dc,log): + dc.BeginDrawing() + start = time.time() + + dc.SetPen( wxPen("BLACK",1) ) + dc.SetBrush( wxBrush("RED") ) + + dc.DrawRectangleList(rectangles) + dc.DrawRectangleList(rectangles,pens) + dc.DrawRectangleList(rectangles,pens[0],brushes) + dc.DrawRectangleList(rectangles,pens,brushes[0]) + dc.DrawRectangleList(rectangles,None,brushes) +## for i in range(10): +## #dc.DrawRectangleList(rectangles,pens,brushes) +## dc.DrawRectangleList(rectangles) + + dc.EndDrawing() + log.write("DrawTime: %s seconds with DrawRectanglesList\n" % (time.time() - start)) + + +def TestEllipses(dc,log): + dc.BeginDrawing() + start = time.time() + + dc.SetPen( wxPen("BLACK",1) ) + dc.SetBrush( wxBrush("RED") ) + + dc.DrawEllipseList(rectangles) + dc.DrawEllipseList(rectangles,pens) + dc.DrawEllipseList(rectangles,pens[0],brushes) + dc.DrawEllipseList(rectangles,pens,brushes[0]) + dc.DrawEllipseList(rectangles,None,brushes) + dc.DrawEllipseList(rectangles,pens,brushes) + + dc.EndDrawing() + log.write("DrawTime: %s seconds with DrawEllipsesList\n" % (time.time() - start)) + + +def TestRectanglesArray(dc,log): + try: + import Numeric + Apoints = Numeric.array(rectangles) + + dc.BeginDrawing() + start = time.time() + dc.SetPen(wxPen("BLACK", 1)) + dc.DrawRectangleList(rectangles) + dc.DrawRectangleList(rectangles,pens) + dc.DrawRectangleList(rectangles,pens[0],brushes) + dc.DrawRectangleList(rectangles,pens,brushes[0]) + dc.DrawRectangleList(rectangles,None,brushes) +## for i in range(10): +## #dc.DrawRectangleList(rectangles,pens,brushes) +## dc.DrawRectangleList(rectangles) + + dc.EndDrawing() + log.write("DrawTime: %s seconds with DrawRectangleList and Numpy Array\n" % (time.time() - start)) + except ImportError: + log.write("Couldn't import Numeric") + pass + + +def TestRectanglesLoop(dc,log): + dc.BeginDrawing() + + start = time.time() + dc.DrawRectangleList(rectangles,pens,brushes) + log.write("DrawTime: %s seconds with DrawRectanglesList\n" % (time.time() - start)) + + start = time.time() + for i in range(len(rectangles)): + dc.SetPen( pens[i] ) + dc.SetBrush( brushes[i] ) + dc.DrawRectangle(rectangles[i][0],rectangles[i][1],rectangles[i][2],rectangles[i][3]) + dc.EndDrawing() + log.write("DrawTime: %s seconds with Python loop\n" % (time.time() - start)) + + +def TestPolygons(dc,log): + dc.BeginDrawing() + + start = time.time() + dc.SetPen(wxPen("BLACK", 1)) + dc.DrawPolygonList(polygons) + dc.DrawPolygonList(polygons,pens) + dc.DrawPolygonList(polygons,pens[0],brushes) + dc.DrawPolygonList(polygons,pens,brushes[0]) + dc.DrawPolygonList(polygons,None,brushes) + log.write("DrawTime: %s seconds with DrawPolygonList\n" % (time.time() - start)) + + dc.EndDrawing() + + +def TestText(dc,log): + dc.BeginDrawing() + + start = time.time() + + # NOTE: you need to set BackgroundMode for the background colors to be used. + dc.SetBackgroundMode(wxSOLID) + foreground = colors1 + background = colors2 + dc.DrawTextList(text, points, foreground, background) + + log.write("DrawTime: %s seconds with DrawTextList\n" % (time.time() - start)) + + dc.EndDrawing() + + + +class TestNB(wxNotebook): + def __init__(self, parent, id, log): + wxNotebook.__init__(self, parent, id, style=wxNB_BOTTOM) self.log = log + + win = DrawPanel(self, TestEllipses, log) + self.AddPage(win, 'Ellipses') + + win = DrawPanel(self, TestText, log) + self.AddPage(win, 'Text') + + win = DrawPanel(self, TestPolygons, log) + self.AddPage(win, 'Polygons') + + win = DrawPanel(self, TestPoints, log) + self.AddPage(win, 'Points') + + win = DrawPanel(self, TestLines, log) + self.AddPage(win, 'Lines') + + win = DrawPanel(self, TestRectangles, log) + self.AddPage(win, 'Rectangles') + + +class DrawPanel(wxPanel): + def __init__(self, parent, drawFun, log): + wxPanel.__init__(self, parent, -1) self.SetBackgroundColour(wxWHITE) - w = size.width - h = size.height - pencache = {} - - # make some lists of random points - self.pnts1 = makeRandomPoints(1000, w, h) - self.pnts2 = makeRandomPoints(1000, w, h) - self.pnts3 = makeRandomPoints(1000, w, h) - self.pens1 = makeRandomPens(1000, pencache) - - # and now some lines - self.lines1 = makeRandomLines(500, w, h) - self.lines2 = makeRandomLines(500, w, h) - self.lines3 = makeRandomLines(500, w, h) - self.pens2 = makeRandomPens(500, pencache) - + self.log = log + self.drawFun = drawFun EVT_PAINT(self, self.OnPaint) def OnPaint(self, evt): dc = wxPaintDC(self) - dc.BeginDrawing() - start = time.time() + dc.Clear() + self.drawFun(dc,self.log) - dc.SetPen(wxPen("BLACK", 1)) - dc.DrawPointList(self.pnts1) - dc.DrawPointList(self.pnts2, wxPen("RED", 2)) - dc.DrawPointList(self.pnts3, self.pens1) - - dc.SetPen(wxPen("BLACK", 1)) - dc.DrawLineList(self.lines1) - dc.DrawLineList(self.lines2, wxPen("RED", 2)) - dc.DrawLineList(self.lines3, self.pens2) - - dc.EndDrawing() - self.log.write("DrawTime: %s seconds\n" % (time.time() - start)) - self.log.write("GetBoundingBox: %s\n" % (dc.GetBoundingBox(), )) #---------------------------------------------------------------------- def runTest(frame, nb, log): w = nb.GetClientSize().width h = nb.GetClientSize().height - if w < 300: w = 300 - if h < 300: h = 300 - win = wxPanel(nb, -1) - tp = TestPanel(win, wxSize(w, h), log) - def OnPanelSize(evt, tp=tp): - tp.SetSize(evt.GetSize()) - EVT_SIZE(win, OnPanelSize) + if w < 600: w = 600 + if h < 400: h = 400 + Init(w, h, 500) + win = TestNB(nb, -1, log) return win #---------------------------------------------------------------------- @@ -136,4 +386,30 @@ drawing routines. Currently they are: (x1,y1, x2,y2) andd pens is either None, a single pen or a list of pens. +
+    DrawRectangleList(rectangles, pens=None, brushes=None)
+
+ + +
+    DrawEllipseList(ellipses, pens=None, brushes=None)
+
+ + +
+    DrawPolygonList(polygons, pens=None, brushes=None)
+
+ + +
+    DrawTextList(textList, coords, foregrounds = None, backgrounds = None)
+
+ """ + + +if __name__ == '__main__': + import sys,os + import run + run.main(['', os.path.basename(sys.argv[0])]) + diff --git a/wxPython/setup.py b/wxPython/setup.py index f7e64a4c43..618865914e 100755 --- a/wxPython/setup.py +++ b/wxPython/setup.py @@ -517,6 +517,7 @@ else: ext = Extension('wxc', ['src/helpers.cpp', + 'src/drawlist.cpp', 'src/libpy.c', ] + rc_file + swig_sources, diff --git a/wxPython/src/drawlist.cpp b/wxPython/src/drawlist.cpp new file mode 100644 index 0000000000..cba7952b24 --- /dev/null +++ b/wxPython/src/drawlist.cpp @@ -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 +#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; +} + + + +//---------------------------------------------------------------------- diff --git a/wxPython/src/gdi.i b/wxPython/src/gdi.i index 295513a21a..75429b90b2 100644 --- a/wxPython/src/gdi.i +++ b/wxPython/src/gdi.i @@ -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) " diff --git a/wxPython/src/helpers.h b/wxPython/src/helpers.h index e1c3a98e11..75e3f1b36b 100644 --- a/wxPython/src/helpers.h +++ b/wxPython/src/helpers.h @@ -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