Updates from Paul

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41648 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2006-10-05 23:53:44 +00:00
parent b7a0abc732
commit 6f67d53729
4 changed files with 519 additions and 122 deletions

View File

@@ -5,12 +5,12 @@ import random
#---------------------------------------------------------------------------
W = 1000
H = 1000
W = 3000
H = 3000
SW = 150
SH = 150
SHAPE_COUNT = 100
MOVING_COUNT = 10
SHAPE_COUNT = 5000
hitradius = 5
#---------------------------------------------------------------------------
@@ -65,66 +65,59 @@ class MyCanvas(wx.ScrolledWindow):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x:None)
self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
# use timer to move one of the objects around
self.timer = wx.Timer()
self.timer.SetOwner(self)
self.Bind(wx.EVT_TIMER, self.OnTimer)
self.timer.Start(50)
self.movingids = random.sample(self.objids, MOVING_COUNT)
self.velocitydict = {}
for id in self.movingids:
vx = random.randint(1,5) * random.choice([-1,1])
vy = random.randint(1,5) * random.choice([-1,1])
self.velocitydict[id] = (vx,vy)
# vars for handling mouse clicks
self.dragid = -1
self.lastpos = (0,0)
def ConvertEventCoords(self, event):
xView, yView = self.GetViewStart()
xDelta, yDelta = self.GetScrollPixelsPerUnit()
return (event.GetX() + (xView * xDelta),
event.GetY() + (yView * yDelta))
def OnTimer(self, event):
# get the current position
xv, yv = self.GetViewStart()
dx, dy = self.GetScrollPixelsPerUnit()
x, y = (xv * dx, yv * dy)
w, h = self.GetClientSizeTuple()
clip = wx.Rect(x,y,w,h)
refreshed = False
for id in self.movingids:
r = self.pdc.GetIdBounds(id)
# get new object position
(vx,vy) = self.velocitydict[id]
x = r.x + vx
y = r.y + vy
# check for bounce
if x < 0:
x = -x
vx = -vx
if x >= W:
x = W - (x - W)
vx = -vx
if y < 0:
y = -y
vy = -vy
if y >= H:
y = H - (y - H)
vy = -vy
self.velocitydict[id] = (vx,vy)
# get change
dx = x - r.x
dy = y - r.y
# translate the object
self.pdc.TranslateId(id, dx, dy)
# redraw
r.x -= 20
if dx < 0:
r.x = x
r.y -= 20
if dy < 0:
r.y = y
r.width += abs(dx) + 40
r.height += abs(dy) + 40
if r.Intersects(clip):
r.x -= clip.x
r.y -= clip.y
refreshed = True
def OffsetRect(self, r):
xView, yView = self.GetViewStart()
xDelta, yDelta = self.GetScrollPixelsPerUnit()
r.OffsetXY(-(xView*xDelta),-(yView*yDelta))
def OnMouse(self, event):
global hitradius
if event.LeftDown():
x,y = self.ConvertEventCoords(event)
#l = self.pdc.FindObjectsByBBox(x, y)
l = self.pdc.FindObjects(x, y, hitradius)
for id in l:
if not self.pdc.GetIdGreyedOut(id):
self.dragid = id
self.lastpos = (event.GetX(),event.GetY())
break
elif event.RightDown():
x,y = self.ConvertEventCoords(event)
#l = self.pdc.FindObjectsByBBox(x, y)
l = self.pdc.FindObjects(x, y, hitradius)
if l:
self.pdc.SetIdGreyedOut(l[0], not self.pdc.GetIdGreyedOut(l[0]))
r = self.pdc.GetIdBounds(l[0])
r.Inflate(4,4)
self.OffsetRect(r)
self.RefreshRect(r, False)
elif event.Dragging() or event.LeftUp():
if self.dragid != -1:
x,y = self.lastpos
dx = event.GetX() - x
dy = event.GetY() - y
r = self.pdc.GetIdBounds(self.dragid)
self.pdc.TranslateId(self.dragid, dx, dy)
r2 = self.pdc.GetIdBounds(self.dragid)
r = r.Union(r2)
r.Inflate(4,4)
self.OffsetRect(r)
self.RefreshRect(r, False)
self.lastpos = (event.GetX(),event.GetY())
if event.LeftUp():
self.dragid = -1
def RandomPen(self):
c = random.choice(colours)
@@ -150,12 +143,12 @@ class MyCanvas(wx.ScrolledWindow):
# wx.PaintDC and then blit the bitmap to it when dc is
# deleted.
dc = wx.BufferedPaintDC(self)
# use PrepateDC to set position correctly
self.PrepareDC(dc)
# we need to clear the dc BEFORE calling PrepareDC
bg = wx.Brush(self.GetBackgroundColour())
dc.SetBackground(bg)
dc.Clear()
# use PrepateDC to set position correctly
self.PrepareDC(dc)
# create a clipping rect from our position and size
# and the Update Region
xv, yv = self.GetViewStart()
@@ -179,26 +172,35 @@ class MyCanvas(wx.ScrolledWindow):
if choice in (0,1):
x = random.randint(0, W)
y = random.randint(0, H)
dc.SetPen(self.RandomPen())
pen = self.RandomPen()
dc.SetPen(pen)
dc.DrawPoint(x,y)
dc.SetIdBounds(id,wx.Rect(x,y,1,1))
r = wx.Rect(x,y,1,1)
r.Inflate(pen.GetWidth(),pen.GetWidth())
dc.SetIdBounds(id,r)
elif choice in (2,3):
x1 = random.randint(0, W-SW)
y1 = random.randint(0, H-SH)
x2 = random.randint(x1, x1+SW)
y2 = random.randint(y1, y1+SH)
dc.SetPen(self.RandomPen())
pen = self.RandomPen()
dc.SetPen(pen)
dc.DrawLine(x1,y1,x2,y2)
dc.SetIdBounds(id,wx.Rect(x1,y1,x2-x1,y2-y1))
r = wx.Rect(x1,y1,x2-x1,y2-y1)
r.Inflate(pen.GetWidth(),pen.GetWidth())
dc.SetIdBounds(id,r)
elif choice in (4,5):
w = random.randint(10, SW)
h = random.randint(10, SH)
x = random.randint(0, W - w)
y = random.randint(0, H - h)
dc.SetPen(self.RandomPen())
pen = self.RandomPen()
dc.SetPen(pen)
dc.SetBrush(self.RandomBrush())
dc.DrawRectangle(x,y,w,h)
dc.SetIdBounds(id,wx.Rect(x,y,w,h))
r = wx.Rect(x,y,w,h)
r.Inflate(pen.GetWidth(),pen.GetWidth())
dc.SetIdBounds(id,r)
self.objids.append(id)
elif choice == 6:
Np = 8 # number of characters in text
@@ -210,10 +212,13 @@ class MyCanvas(wx.ScrolledWindow):
w,h = self.GetFullTextExtent(word)[0:2]
x = random.randint(0, W-w)
y = random.randint(0, H-h)
dc.SetFont(self.GetFont())
dc.SetTextForeground(self.RandomColor())
dc.SetTextBackground(self.RandomColor())
dc.DrawText(word, x, y)
dc.SetIdBounds(id,wx.Rect(x,y,w,h))
r = wx.Rect(x,y,w,h)
r.Inflate(2,2)
dc.SetIdBounds(id, r)
self.objids.append(id)
elif choice == 7:
Np = 8 # number of points per polygon
@@ -232,10 +237,13 @@ class MyCanvas(wx.ScrolledWindow):
poly.append(wx.Point(x,y))
x = random.randint(0, W-SW)
y = random.randint(0, H-SH)
dc.SetPen(self.RandomPen())
pen = self.RandomPen()
dc.SetPen(pen)
dc.SetBrush(self.RandomBrush())
dc.DrawPolygon(poly, x,y)
dc.SetIdBounds(id,wx.Rect(minx+x,miny+y,maxx-minx+x,maxy-miny+y))
r = wx.Rect(minx+x,miny+y,maxx-minx,maxy-miny)
r.Inflate(pen.GetWidth(),pen.GetWidth())
dc.SetIdBounds(id,r)
self.objids.append(id)
elif choice == 8:
w,h = self.bmp.GetSize()
@@ -246,15 +254,42 @@ class MyCanvas(wx.ScrolledWindow):
self.objids.append(id)
dc.EndDrawing()
def ShutdownDemo(self):
self.timer.Stop()
del self.timer
class ControlPanel(wx.Panel):
def __init__(self, parent, id, pos=wx.DefaultPosition,
size=wx.DefaultSize, style = wx.TAB_TRAVERSAL):
wx.Panel.__init__(self,parent,id,pos,size,style)
lbl = wx.StaticText(self, wx.ID_ANY, "Hit Test Radius: ")
lbl2 = wx.StaticText(self, wx.ID_ANY, "Left Click to drag, Right Click to enable/disable")
sc = wx.SpinCtrl(self, wx.ID_ANY, "5")
sc.SetRange(0,100)
global hitradius
sc.SetValue(hitradius)
self.sc = sc
sz = wx.BoxSizer(wx.HORIZONTAL)
sz.Add(lbl,0,wx.EXPAND)
sz.Add(sc,0)
sz.Add(lbl2,0,wx.LEFT,5)
sz.Add((10,10),1,wx.EXPAND)
self.SetSizerAndFit(sz)
sc.Bind(wx.EVT_SPINCTRL,self.OnChange)
sc.Bind(wx.EVT_TEXT,self.OnChange)
def OnChange(self, event):
global hitradius
hitradius = self.sc.GetValue()
#---------------------------------------------------------------------------
def runTest(frame, nb, log):
win = MyCanvas(nb, wx.ID_ANY, log)
return win
pnl = wx.Panel(nb, wx.ID_ANY,size=(200,30))
pnl2 = ControlPanel(pnl,wx.ID_ANY)
win = MyCanvas(pnl, wx.ID_ANY, log)
sz = wx.BoxSizer(wx.VERTICAL)
sz.Add(pnl2,0,wx.EXPAND|wx.ALL,5)
sz.Add(win,1,wx.EXPAND)
pnl.SetSizerAndFit(sz)
return pnl
#---------------------------------------------------------------------------

View File

@@ -11,9 +11,6 @@
#ifndef _WX_PSUEDO_DC_H_BASE_
#define _WX_PSUEDO_DC_H_BASE_
#include "wx/wx.h"
#include "wx/dc.h"
//----------------------------------------------------------------------------
// Base class for all pdcOp classes
//----------------------------------------------------------------------------
@@ -25,8 +22,9 @@ class pdcOp
virtual ~pdcOp() {}
// Virtual Drawing Methods
virtual void DrawToDC(wxDC *dc)=0;
virtual void DrawToDC(wxDC *dc, bool grey=false)=0;
virtual void Translate(wxCoord WXUNUSED(dx), wxCoord WXUNUSED(dy)) {}
virtual void CacheGrey() {}
};
//----------------------------------------------------------------------------
@@ -34,6 +32,16 @@ class pdcOp
//----------------------------------------------------------------------------
WX_DECLARE_LIST(pdcOp, pdcOpList);
//----------------------------------------------------------------------------
// Helper functions used for drawing greyed out versions of objects
//----------------------------------------------------------------------------
wxColour &MakeColourGrey(const wxColour &c);
wxBrush &GetGreyBrush(wxBrush &brush);
wxPen &GetGreyPen(wxPen &pen);
wxIcon &GetGreyIcon(wxIcon &icon);
wxBitmap &GetGreyBitmap(wxBitmap &bmp);
//----------------------------------------------------------------------------
// Classes derived from pdcOp
// There is one class for each method mirrored from wxDC to wxPseudoDC
@@ -43,7 +51,7 @@ class pdcSetFontOp : public pdcOp
public:
pdcSetFontOp(const wxFont& font)
{m_font=font;}
virtual void DrawToDC(wxDC *dc) {dc->SetFont(m_font);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetFont(m_font);}
protected:
wxFont m_font;
};
@@ -52,30 +60,48 @@ class pdcSetBrushOp : public pdcOp
{
public:
pdcSetBrushOp(const wxBrush& brush)
{m_brush=brush;}
virtual void DrawToDC(wxDC *dc) {dc->SetBrush(m_brush);}
{m_greybrush=m_brush=brush;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetBrush(m_brush);
else dc->SetBrush(m_greybrush);
}
virtual void CacheGrey() {m_greybrush=GetGreyBrush(m_brush);}
protected:
wxBrush m_brush;
wxBrush m_greybrush;
};
class pdcSetBackgroundOp : public pdcOp
{
public:
pdcSetBackgroundOp(const wxBrush& brush)
{m_brush=brush;}
virtual void DrawToDC(wxDC *dc) {dc->SetBackground(m_brush);}
{m_greybrush=m_brush=brush;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetBackground(m_brush);
else dc->SetBackground(m_greybrush);
}
virtual void CacheGrey() {m_greybrush=GetGreyBrush(m_brush);}
protected:
wxBrush m_brush;
wxBrush m_greybrush;
};
class pdcSetPenOp : public pdcOp
{
public:
pdcSetPenOp(const wxPen& pen)
{m_pen=pen;}
virtual void DrawToDC(wxDC *dc) {dc->SetPen(m_pen);}
{m_greypen=m_pen=pen;}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetPen(m_pen);
else dc->SetPen(m_greypen);
}
virtual void CacheGrey() {m_greypen=GetGreyPen(m_pen);}
protected:
wxPen m_pen;
wxPen m_greypen;
};
class pdcSetTextBackgroundOp : public pdcOp
@@ -83,7 +109,11 @@ class pdcSetTextBackgroundOp : public pdcOp
public:
pdcSetTextBackgroundOp(const wxColour& colour)
{m_colour=colour;}
virtual void DrawToDC(wxDC *dc) {dc->SetTextBackground(m_colour);}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetTextBackground(m_colour);
else dc->SetTextBackground(MakeColourGrey(m_colour));
}
protected:
wxColour m_colour;
};
@@ -93,7 +123,11 @@ class pdcSetTextForegroundOp : public pdcOp
public:
pdcSetTextForegroundOp(const wxColour& colour)
{m_colour=colour;}
virtual void DrawToDC(wxDC *dc) {dc->SetTextForeground(m_colour);}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->SetTextForeground(m_colour);
else dc->SetTextForeground(MakeColourGrey(m_colour));
}
protected:
wxColour m_colour;
};
@@ -103,7 +137,7 @@ class pdcDrawRectangleOp : public pdcOp
public:
pdcDrawRectangleOp(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
{m_x=x; m_y=y; m_w=w; m_h=h;}
virtual void DrawToDC(wxDC *dc) {dc->DrawRectangle(m_x,m_y,m_w,m_h);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawRectangle(m_x,m_y,m_w,m_h);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx;m_y+=dy;}
protected:
@@ -115,7 +149,7 @@ class pdcDrawLineOp : public pdcOp
public:
pdcDrawLineOp(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
{m_x1=x1; m_y1=y1; m_x2=x2; m_y2=y2;}
virtual void DrawToDC(wxDC *dc) {dc->DrawLine(m_x1,m_y1,m_x2,m_y2);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawLine(m_x1,m_y1,m_x2,m_y2);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x1+=dx; m_y1+=dy; m_x2+=dx; m_y2+=dy;}
protected:
@@ -126,7 +160,7 @@ class pdcSetBackgroundModeOp : public pdcOp
{
public:
pdcSetBackgroundModeOp(int mode) {m_mode=mode;}
virtual void DrawToDC(wxDC *dc) {dc->SetBackgroundMode(m_mode);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetBackgroundMode(m_mode);}
protected:
int m_mode;
};
@@ -136,7 +170,7 @@ class pdcDrawTextOp : public pdcOp
public:
pdcDrawTextOp(const wxString& text, wxCoord x, wxCoord y)
{m_text=text; m_x=x; m_y=y;}
virtual void DrawToDC(wxDC *dc) {dc->DrawText(m_text, m_x, m_y);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawText(m_text, m_x, m_y);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
@@ -148,21 +182,21 @@ class pdcClearOp : public pdcOp
{
public:
pdcClearOp() {}
virtual void DrawToDC(wxDC *dc) {dc->Clear();}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->Clear();}
};
class pdcBeginDrawingOp : public pdcOp
{
public:
pdcBeginDrawingOp() {}
virtual void DrawToDC(wxDC *) {}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->BeginDrawing();}
};
class pdcEndDrawingOp : public pdcOp
{
public:
pdcEndDrawingOp() {}
virtual void DrawToDC(wxDC *) {}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->EndDrawing();}
};
class pdcFloodFillOp : public pdcOp
@@ -170,7 +204,11 @@ class pdcFloodFillOp : public pdcOp
public:
pdcFloodFillOp(wxCoord x, wxCoord y, const wxColour& col,
int style) {m_x=x; m_y=y; m_col=col; m_style=style;}
virtual void DrawToDC(wxDC *dc) {dc->FloodFill(m_x,m_y,m_col,m_style);}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (!grey) dc->FloodFill(m_x,m_y,m_col,m_style);
else dc->FloodFill(m_x,m_y,MakeColourGrey(m_col),m_style);
}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
@@ -183,7 +221,7 @@ class pdcCrossHairOp : public pdcOp
{
public:
pdcCrossHairOp(wxCoord x, wxCoord y) {m_x=x; m_y=y;}
virtual void DrawToDC(wxDC *dc) {dc->CrossHair(m_x,m_y);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->CrossHair(m_x,m_y);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
@@ -196,7 +234,7 @@ class pdcDrawArcOp : public pdcOp
pdcDrawArcOp(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
wxCoord xc, wxCoord yc)
{m_x1=x1; m_y1=y1; m_x2=x2; m_y2=y2; m_xc=xc; m_yc=yc;}
virtual void DrawToDC(wxDC *dc)
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawArc(m_x1,m_y1,m_x2,m_y2,m_xc,m_yc);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x1+=dx; m_x2+=dx; m_y1+=dy; m_y2+=dy;}
@@ -211,7 +249,7 @@ class pdcDrawCheckMarkOp : public pdcOp
pdcDrawCheckMarkOp(wxCoord x, wxCoord y,
wxCoord width, wxCoord height)
{m_x=x; m_y=y; m_w=width; m_h=height;}
virtual void DrawToDC(wxDC *dc)
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawCheckMark(m_x,m_y,m_w,m_h);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
@@ -225,7 +263,7 @@ class pdcDrawEllipticArcOp : public pdcOp
pdcDrawEllipticArcOp(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
double sa, double ea)
{m_x=x; m_y=y; m_w=w; m_h=h; m_sa=sa; m_ea=ea;}
virtual void DrawToDC(wxDC *dc)
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawEllipticArc(m_x,m_y,m_w,m_h,m_sa,m_ea);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
@@ -239,7 +277,7 @@ class pdcDrawPointOp : public pdcOp
public:
pdcDrawPointOp(wxCoord x, wxCoord y)
{m_x=x; m_y=y;}
virtual void DrawToDC(wxDC *dc) {dc->DrawPoint(m_x,m_y);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawPoint(m_x,m_y);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
@@ -252,7 +290,7 @@ class pdcDrawRoundedRectangleOp : public pdcOp
pdcDrawRoundedRectangleOp(wxCoord x, wxCoord y, wxCoord width,
wxCoord height, double radius)
{m_x=x; m_y=y; m_w=width; m_h=height; m_r=radius;}
virtual void DrawToDC(wxDC *dc)
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawRoundedRectangle(m_x,m_y,m_w,m_h,m_r);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
@@ -266,7 +304,7 @@ class pdcDrawEllipseOp : public pdcOp
public:
pdcDrawEllipseOp(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
{m_x=x; m_y=y; m_w=width; m_h=height;}
virtual void DrawToDC(wxDC *dc) {dc->DrawEllipse(m_x,m_y,m_w,m_h);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawEllipse(m_x,m_y,m_w,m_h);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
@@ -278,11 +316,17 @@ class pdcDrawIconOp : public pdcOp
public:
pdcDrawIconOp(const wxIcon& icon, wxCoord x, wxCoord y)
{m_icon=icon; m_x=x; m_y=y;}
virtual void DrawToDC(wxDC *dc) {dc->DrawIcon(m_icon,m_x,m_y);}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (grey) dc->DrawIcon(m_greyicon,m_x,m_y);
else dc->DrawIcon(m_icon,m_x,m_y);
}
virtual void CacheGrey() {m_greyicon=GetGreyIcon(m_icon);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxIcon m_icon;
wxIcon m_greyicon;
wxCoord m_x,m_y;
};
@@ -292,7 +336,7 @@ class pdcDrawLinesOp : public pdcOp
pdcDrawLinesOp(int n, wxPoint points[],
wxCoord xoffset = 0, wxCoord yoffset = 0);
virtual ~pdcDrawLinesOp();
virtual void DrawToDC(wxDC *dc)
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawLines(m_n,m_points,m_xoffset,m_yoffset);}
virtual void Translate(wxCoord dx, wxCoord dy)
{
@@ -315,9 +359,9 @@ class pdcDrawPolygonOp : public pdcOp
wxCoord xoffset = 0, wxCoord yoffset = 0,
int fillStyle = wxODDEVEN_RULE);
virtual ~pdcDrawPolygonOp();
virtual void DrawToDC(wxDC *dc)
{ dc->DrawPolygon(m_n,m_points,m_xoffset,m_yoffset,m_fillStyle); }
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawPolygon(m_n,m_points,m_xoffset,m_yoffset,m_fillStyle);}
virtual void Translate(wxCoord dx, wxCoord dy)
{
for(int i=0; i<m_n; i++)
@@ -340,7 +384,7 @@ class pdcDrawPolyPolygonOp : public pdcOp
wxCoord xoffset = 0, wxCoord yoffset = 0,
int fillStyle = wxODDEVEN_RULE);
virtual ~pdcDrawPolyPolygonOp();
virtual void DrawToDC(wxDC *dc)
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawPolyPolygon(m_n,m_count,m_points,
m_xoffset,m_yoffset,m_fillStyle);}
virtual void Translate(wxCoord dx, wxCoord dy)
@@ -365,7 +409,7 @@ class pdcDrawRotatedTextOp : public pdcOp
public:
pdcDrawRotatedTextOp(const wxString& text, wxCoord x, wxCoord y, double angle)
{m_text=text; m_x=x; m_y=y; m_angle=angle;}
virtual void DrawToDC(wxDC *dc)
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawRotatedText(m_text,m_x,m_y,m_angle);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
@@ -381,11 +425,17 @@ class pdcDrawBitmapOp : public pdcOp
pdcDrawBitmapOp(const wxBitmap &bmp, wxCoord x, wxCoord y,
bool useMask = false)
{m_bmp=bmp; m_x=x; m_y=y; m_useMask=useMask;}
virtual void DrawToDC(wxDC *dc) {dc->DrawBitmap(m_bmp,m_x,m_y,m_useMask);}
virtual void DrawToDC(wxDC *dc, bool grey=false)
{
if (grey) dc->DrawBitmap(m_greybmp,m_x,m_y,m_useMask);
else dc->DrawBitmap(m_bmp,m_x,m_y,m_useMask);
}
virtual void CacheGrey() {m_greybmp=GetGreyBitmap(m_bmp);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_x+=dx; m_y+=dy;}
protected:
wxBitmap m_bmp;
wxBitmap m_greybmp;
wxCoord m_x,m_y;
bool m_useMask;
};
@@ -400,7 +450,7 @@ class pdcDrawLabelOp : public pdcOp
int indexAccel = -1)
{m_text=text; m_image=image; m_rect=rect;
m_align=alignment; m_iAccel=indexAccel;}
virtual void DrawToDC(wxDC *dc)
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false)
{dc->DrawLabel(m_text,m_image,m_rect,m_align,m_iAccel);}
virtual void Translate(wxCoord dx, wxCoord dy)
{m_rect.x+=dx; m_rect.y+=dy;}
@@ -418,7 +468,7 @@ class pdcDrawSplineOp : public pdcOp
public:
pdcDrawSplineOp(int n, wxPoint points[]);
virtual ~pdcDrawSplineOp();
virtual void DrawToDC(wxDC *dc) {dc->DrawSpline(m_n,m_points);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->DrawSpline(m_n,m_points);}
virtual void Translate(wxCoord dx, wxCoord dy)
{
int i;
@@ -436,7 +486,7 @@ class pdcSetPaletteOp : public pdcOp
{
public:
pdcSetPaletteOp(const wxPalette& palette) {m_palette=palette;}
virtual void DrawToDC(wxDC *dc) {dc->SetPalette(m_palette);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetPalette(m_palette);}
protected:
wxPalette m_palette;
};
@@ -446,7 +496,7 @@ class pdcSetLogicalFunctionOp : public pdcOp
{
public:
pdcSetLogicalFunctionOp(int function) {m_function=function;}
virtual void DrawToDC(wxDC *dc) {dc->SetLogicalFunction(m_function);}
virtual void DrawToDC(wxDC *dc, bool WXUNUSED(grey)=false) {dc->SetLogicalFunction(m_function);}
protected:
int m_function;
};
@@ -458,7 +508,8 @@ class pdcObject
{
public:
pdcObject(int id)
{m_id=id; m_bounded=false; m_oplist.DeleteContents(true);}
{m_id=id; m_bounded=false; m_oplist.DeleteContents(true);
m_greyedout=false;}
virtual ~pdcObject() {m_oplist.Clear();}
@@ -469,10 +520,16 @@ class pdcObject
wxRect GetBounds() {return m_bounds;}
void SetBounded(bool bounded) {m_bounded=bounded;}
bool IsBounded() {return m_bounded;}
void SetGreyedOut(bool greyout=true);
bool GetGreyedOut() {return m_greyedout;}
// Op List Management Methods
void Clear() {m_oplist.Clear();}
void AddOp(pdcOp *op) {m_oplist.Append(op);}
void AddOp(pdcOp *op)
{
m_oplist.Append(op);
if (m_greyedout) op->CacheGrey();
}
int GetLen() {return m_oplist.GetCount();}
virtual void Translate(wxCoord dx, wxCoord dy);
@@ -484,6 +541,7 @@ class pdcObject
wxRect m_bounds; // bounding rect of this object
bool m_bounded; // true if bounds is valid, false by default
pdcOpList m_oplist; // list of operations for this object
bool m_greyedout; // if true then draw this object in greys only
};
@@ -531,6 +589,16 @@ public:
void GetIdBounds(int id, wxRect& rect);
// Translate all the operations for this id
void TranslateId(int id, wxCoord dx, wxCoord dy);
// Grey-out an object
void SetIdGreyedOut(int id, bool greyout=true);
bool GetIdGreyedOut(int id);
// Find Objects at a point. Returns Python list of id's
// sorted in reverse drawing order (result[0] is top object)
// This version looks at drawn pixels
PyObject *FindObjects(wxCoord x, wxCoord y,
wxCoord radius=1, const wxColor& bg=*wxWHITE);
// This version only looks at bounding boxes
PyObject *FindObjectsByBBox(wxCoord x, wxCoord y);
// ------------------------------------------------------------------------
// Playback Methods
@@ -545,6 +613,16 @@ public:
void DrawToDC(wxDC *dc);
// draw a single object to the dc
void DrawIdToDC(int id, wxDC *dc);
// ------------------------------------------------------------------------
// Hit Detection Methods
//
// returns list of object with a drawn pixel within radius pixels of (x,y)
// the list is in reverse draw order so last drawn is first in list
// PyObject *HitTest(wxCoord x, wxCoord y, double radius)
// returns list of objects whose bounding boxes include (x,y)
// PyObject *HitTestBB(wxCoord x, wxCoord y)
// ------------------------------------------------------------------------
// Methods mirrored from wxDC

View File

@@ -64,6 +64,26 @@ current platform.", "");
DocDeclStr(
void, TranslateId(int id, wxCoord dx, wxCoord dy),
"Translate the operations of id by dx,dy.", "");
DocDeclStr(
void, SetIdGreyedOut(int id, bool greyout=true),
"Set whether an object is drawn greyed out or not.", "");
DocDeclStr(
bool, GetIdGreyedOut(int id),
"Get whether an object is drawn greyed out or not.", "");
KeepGIL(FindObjects);
DocDeclStr(
PyObject*, FindObjects(wxCoord x, wxCoord y,
wxCoord radius=1, const wxColor& bg=*wxWHITE),
"Returns a list of all the id's that draw a pixel with color
not equal to bg within radius of (x,y).
Returns an empty list if nothing is found. The list is in
reverse drawing order so list[0] is the top id.","");
KeepGIL(FindObjectsByBBox);
DocDeclStr(
PyObject*, FindObjectsByBBox(wxCoord x, wxCoord y),
"Returns a list of all the id's whose bounding boxes include (x,y).
Returns an empty list if nothing is found. The list is in
reverse drawing order so list[0] is the top id.","");
DocDeclStr(
void, DrawIdToDC(int id, wxDC *dc),
"Draw recorded operations of id to dc.", "");

View File

@@ -10,16 +10,101 @@
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
//include "wx/wxprec.h"
#undef DEBUG
#include <Python.h>
#include "wx/wxPython/wxPython.h"
#include "wx/wxPython/pseudodc.h"
#include <stdio.h>
// wxList based class definitions
#include <wx/listimpl.cpp>
WX_DEFINE_LIST(pdcOpList);
WX_DEFINE_LIST(pdcObjectList);
//----------------------------------------------------------------------------
// Helper functions used for drawing greyed out versions of objects
//----------------------------------------------------------------------------
wxColour &MakeColourGrey(const wxColour &c)
{
static wxColour rval;
rval.Set(byte((230-c.Red())*0.7+c.Red()),
byte((230-c.Green())*0.7+c.Green()),
byte((230-c.Blue())*0.7+c.Blue()));
return rval;
}
wxBrush &GetGreyBrush(wxBrush &brush)
{
static wxBrush b;
wxColour c;
b = brush;
c = MakeColourGrey(brush.GetColour());
b.SetColour(c);
return b;
}
wxPen &GetGreyPen(wxPen &pen)
{
static wxPen p;
wxColour c;
p = pen;
c = MakeColourGrey(pen.GetColour());
p.SetColour(c);
return p;
}
void GreyOutImage(wxImage &img)
{
unsigned char *data = img.GetData();
unsigned char r,g,b;
unsigned char mr,mg,mb;
int i, tst;
int len = img.GetHeight()*img.GetWidth()*3;
if (img.HasMask())
{
mr = img.GetMaskRed();
mg = img.GetMaskGreen();
mb = img.GetMaskBlue();
}
tst=0;
for (i=0;i<len;i+=3)
{
r=data[i]; g=data[i+1]; b=data[i+2];
if (!img.HasMask() ||
r!=mr || g!=mg || b!=mb)
{
if (!tst)
{
tst=1;
}
r = (unsigned char)((230.0-r)*0.7+r);
g = (unsigned char)((230.0-g)*0.7+g);
b = (unsigned char)((230.0-b)*0.7+b);
data[i]=r; data[i+1]=g; data[i+2]=b;
}
}
}
wxIcon &GetGreyIcon(wxIcon &icon)
{
wxBitmap bmp;
bmp.CopyFromIcon(icon);
wxImage img = bmp.ConvertToImage();
GreyOutImage(img);
wxBitmap bmp2(img,32);
static wxIcon rval;
rval.CopyFromBitmap(bmp2);
return rval;
}
wxBitmap &GetGreyBitmap(wxBitmap &bmp)
{
wxImage img = bmp.ConvertToImage();
GreyOutImage(img);
static wxBitmap rval(img,32);
return rval;
}
// ============================================================================
// various pdcOp class implementation methods
// ============================================================================
@@ -154,7 +239,7 @@ void pdcObject::DrawToDC(wxDC *dc)
pdcOpList::Node *node = m_oplist.GetFirst();
while(node)
{
node->GetData()->DrawToDC(dc);
node->GetData()->DrawToDC(dc, m_greyedout);
node = node->GetNext();
}
}
@@ -177,6 +262,27 @@ void pdcObject::Translate(wxCoord dx, wxCoord dy)
}
}
// ----------------------------------------------------------------------------
// SetGreyedOut - set the greyout member and cache grey versions of everything
// if greyout is true
// ----------------------------------------------------------------------------
void pdcObject::SetGreyedOut(bool greyout)
{
m_greyedout=greyout;
if (greyout)
{
pdcOpList::Node *node = m_oplist.GetFirst();
pdcOp *obj;
while(node)
{
obj = node->GetData();
obj->CacheGrey();
node = node->GetNext();
}
}
}
// ============================================================================
// wxPseudoDC implementation
// ============================================================================
@@ -321,6 +427,164 @@ void wxPseudoDC::DrawIdToDC(int id, wxDC *dc)
if (pt) pt->GetData()->DrawToDC(dc);
}
// ----------------------------------------------------------------------------
// SetIdGreyedOut - Set the greyedout member of id
// ----------------------------------------------------------------------------
void wxPseudoDC::SetIdGreyedOut(int id, bool greyout)
{
pdcObjectList::Node *pt = FindObjNode(id);
if (pt) pt->GetData()->SetGreyedOut(greyout);
}
// ----------------------------------------------------------------------------
// GetIdGreyedOut - Get the greyedout member of id
// ----------------------------------------------------------------------------
bool wxPseudoDC::GetIdGreyedOut(int id)
{
pdcObjectList::Node *pt = FindObjNode(id);
if (pt) return pt->GetData()->GetGreyedOut();
else return false;
}
// ----------------------------------------------------------------------------
// FindObjectsByBBox - Return a list of all the ids whose bounding boxes
// contain (x,y)
// ----------------------------------------------------------------------------
PyObject *wxPseudoDC::FindObjectsByBBox(wxCoord x, wxCoord y)
{
//wxPyBlock_t blocked = wxPyBeginBlockThreads();
pdcObjectList::Node *pt = m_objectlist.GetFirst();
pdcObject *obj;
PyObject* pyList = NULL;
pyList = PyList_New(0);
wxRect r;
while (pt)
{
obj = pt->GetData();
r = obj->GetBounds();
if (obj->IsBounded() && r.Contains(x,y))
{
PyObject* pyObj = PyInt_FromLong((long)obj->GetId());
PyList_Insert(pyList, 0, pyObj);
Py_DECREF(pyObj);
}
pt = pt->GetNext();
}
//wxPyEndBlockThreads(blocked);
return pyList;
}
// ----------------------------------------------------------------------------
// FindObjects - Return a list of all the ids that draw to (x,y)
// ----------------------------------------------------------------------------
PyObject *wxPseudoDC::FindObjects(wxCoord x, wxCoord y,
wxCoord radius, const wxColor& bg)
{
//wxPyBlock_t blocked = wxPyBeginBlockThreads();
pdcObjectList::Node *pt = m_objectlist.GetFirst();
pdcObject *obj;
PyObject* pyList = NULL;
pyList = PyList_New(0);
wxBrush bgbrush(bg);
wxPen bgpen(bg);
// special case radius = 0
if (radius == 0)
{
wxBitmap bmp(4,4,24);
wxMemoryDC memdc;
wxColor pix;
wxRect viewrect(x-2,y-2,4,4);
// setup the memdc for rendering
memdc.SelectObject(bmp);
memdc.SetBackground(bgbrush);
memdc.Clear();
memdc.SetDeviceOrigin(2-x,2-y);
while (pt)
{
obj = pt->GetData();
if (obj->IsBounded() && obj->GetBounds().Contains(x,y))
{
// start clean
memdc.SetBrush(bgbrush);
memdc.SetPen(bgpen);
memdc.DrawRectangle(viewrect);
// draw the object
obj->DrawToDC(&memdc);
memdc.GetPixel(x,y,&pix);
// clear and update rgn2
if (pix != bg)
{
PyObject* pyObj = PyInt_FromLong((long)obj->GetId());
PyList_Insert(pyList, 0, pyObj);
Py_DECREF(pyObj);
}
}
pt = pt->GetNext();
}
memdc.SelectObject(wxNullBitmap);
}
else
{
wxRect viewrect(x-radius,y-radius,2*radius,2*radius);
wxBitmap maskbmp(2*radius,2*radius,24);
wxMemoryDC maskdc;
// create bitmap with circle for masking
maskdc.SelectObject(maskbmp);
maskdc.SetBackground(*wxBLACK_BRUSH);
maskdc.Clear();
maskdc.SetBrush(*wxWHITE_BRUSH);
maskdc.SetPen(*wxWHITE_PEN);
maskdc.DrawCircle(radius,radius,radius);
// now setup a memdc for rendering our object
wxBitmap bmp(2*radius,2*radius,24);
wxMemoryDC memdc;
memdc.SelectObject(bmp);
// set the origin so (x,y) is in the bmp center
memdc.SetDeviceOrigin(radius-x,radius-y);
// a region will be used to see if the result is empty
wxRegion rgn2;
while (pt)
{
obj = pt->GetData();
if (obj->IsBounded() && viewrect.Intersects(obj->GetBounds()))
{
// start clean
//memdc.Clear();
memdc.SetBrush(bgbrush);
memdc.SetPen(bgpen);
memdc.DrawRectangle(viewrect);
// draw the object
obj->DrawToDC(&memdc);
// remove background color
memdc.SetLogicalFunction(wxXOR);
memdc.SetBrush(bgbrush);
memdc.SetPen(bgpen);
memdc.DrawRectangle(viewrect);
memdc.SetLogicalFunction(wxCOPY);
// AND with circle bitmap
memdc.Blit(x-radius,y-radius,2*radius,2*radius,&maskdc,0,0,wxAND);
// clear and update rgn2
memdc.SelectObject(wxNullBitmap);
rgn2.Clear();
rgn2.Union(bmp, *wxBLACK);
//rgn2.Intersect(rgn);
memdc.SelectObject(bmp);
if (!rgn2.IsEmpty())
{
PyObject* pyObj = PyInt_FromLong((long)obj->GetId());
PyList_Insert(pyList, 0, pyObj);
Py_DECREF(pyObj);
}
}
pt = pt->GetNext();
}
maskdc.SelectObject(wxNullBitmap);
memdc.SelectObject(wxNullBitmap);
}
//wxPyEndBlockThreads(blocked);
return pyList;
}
// ----------------------------------------------------------------------------
// DrawToDCClipped - play back the op list to the DC but clip any objects
// known to be not in rect. This is a coarse level of