]> git.saurik.com Git - wxWidgets.git/commitdiff
Updates from Paul
authorRobin Dunn <robin@alldunn.com>
Thu, 5 Oct 2006 23:53:44 +0000 (23:53 +0000)
committerRobin Dunn <robin@alldunn.com>
Thu, 5 Oct 2006 23:53:44 +0000 (23:53 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41648 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

wxPython/demo/PseudoDC.py
wxPython/include/wx/wxPython/pseudodc.h
wxPython/src/_pseudodc.i
wxPython/src/pseudodc.cpp

index a871b25d0134f7c451cc9342434584fa3b5ccdfc..964c196fec5fd651dcfc1a0d7defbb8736507199 100644 (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)
-
-    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
 
 #---------------------------------------------------------------------------
 
index d8e0548e4bf5fe842a142f06f3f0091be445c6d5..b27d98876c1a53d712735df25cb5397f92641335 100644 (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
index d027df3ed0c4551d22a8e1871fafcec258be743f..1fd1cc1ca1e0297354a17fa832aedf943359a4d8 100644 (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.", "");
index dc2d2eb1af03653d8cc5b47c66912b34ba097978..b904cef98d817294fc8fcb22b1c6a27e6285d09d 100644 (file)
 /////////////////////////////////////////////////////////////////////////////
 
 // 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