#---------------------------------------------------------------------------
-W = 1000
-H = 1000
+W = 3000
+H = 3000
SW = 150
SH = 150
-SHAPE_COUNT = 100
-MOVING_COUNT = 10
+SHAPE_COUNT = 5000
+hitradius = 5
#---------------------------------------------------------------------------
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)
-
- 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
+ # 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 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)
# 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()
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
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
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()
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
#---------------------------------------------------------------------------
#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
//----------------------------------------------------------------------------
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() {}
};
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
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
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;
};
{
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
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;
};
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;
};
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:
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:
{
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;
};
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:
{
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
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:
{
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:
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;}
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;}
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;}
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:
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;}
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:
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;
};
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)
{
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++)
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)
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;}
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;
};
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;}
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;
{
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;
};
{
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;
};
{
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();}
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);
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
};
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
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
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.", "");
/////////////////////////////////////////////////////////////////////////////
// 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
// ============================================================================
pdcOpList::Node *node = m_oplist.GetFirst();
while(node)
{
- node->GetData()->DrawToDC(dc);
+ node->GetData()->DrawToDC(dc, m_greyedout);
node = node->GetNext();
}
}
}
}
+// ----------------------------------------------------------------------------
+// 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
// ============================================================================
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