From 6f67d53729164f54dd65540d4622eee47d47c6fe Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Thu, 5 Oct 2006 23:53:44 +0000 Subject: [PATCH] Updates from Paul git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41648 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- wxPython/demo/PseudoDC.py | 191 ++++++++++------- wxPython/include/wx/wxPython/pseudodc.h | 162 ++++++++++---- wxPython/src/_pseudodc.i | 20 ++ wxPython/src/pseudodc.cpp | 270 +++++++++++++++++++++++- 4 files changed, 520 insertions(+), 123 deletions(-) diff --git a/wxPython/demo/PseudoDC.py b/wxPython/demo/PseudoDC.py index a871b25d01..964c196fec 100644 --- a/wxPython/demo/PseudoDC.py +++ b/wxPython/demo/PseudoDC.py @@ -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) - - 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) @@ -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 #--------------------------------------------------------------------------- diff --git a/wxPython/include/wx/wxPython/pseudodc.h b/wxPython/include/wx/wxPython/pseudodc.h index d8e0548e4b..b27d98876c 100644 --- a/wxPython/include/wx/wxPython/pseudodc.h +++ b/wxPython/include/wx/wxPython/pseudodc.h @@ -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; iDrawPolyPolygon(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 diff --git a/wxPython/src/_pseudodc.i b/wxPython/src/_pseudodc.i index d027df3ed0..1fd1cc1ca1 100644 --- a/wxPython/src/_pseudodc.i +++ b/wxPython/src/_pseudodc.i @@ -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.", ""); diff --git a/wxPython/src/pseudodc.cpp b/wxPython/src/pseudodc.cpp index dc2d2eb1af..b904cef98d 100644 --- a/wxPython/src/pseudodc.cpp +++ b/wxPython/src/pseudodc.cpp @@ -10,16 +10,101 @@ ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx.h". -#include "wx/wxprec.h" +//include "wx/wxprec.h" +#undef DEBUG +#include +#include "wx/wxPython/wxPython.h" #include "wx/wxPython/pseudodc.h" -#include // wxList based class definitions #include 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;iGetData()->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 -- 2.47.2