+class ScaledBitmap2(TextObjectMixin, DrawObject, ):
+    """
+
+    An alternative scaled bitmap that only scaled the required amount of
+    the main bitmap when zoomed in: EXPERIMENTAL!
+
+    """
+
+    def __init__(self,
+                 Bitmap,
+                 XY,
+                 Height,
+                 Width=None,
+                 Position = 'tl',
+                 InForeground = False):
+
+        DrawObject.__init__(self,InForeground)
+
+        if type(Bitmap) == wx._gdi.Bitmap:
+            self.Image = Bitmap.ConvertToImage()
+        elif type(Bitmap) == wx._core.Image:
+            self.Image = Bitmap
+
+        self.XY = N.array(XY, N.float)
+        self.Height = Height
+        (self.bmpWidth, self.bmpHeight) = self.Image.GetWidth(), self.Image.GetHeight()
+        self.bmpWH = N.array((self.bmpWidth, self.bmpHeight), N.int32)
+        ## fixme: this should all accommodate different scales for X and Y
+        if Width is None:
+            self.BmpScale = float(self.bmpHeight) / Height
+            self.Width = self.bmpWidth / self.BmpScale
+        self.WH = N.array((self.Width, Height), N.float)
+        ##fixme: should this have a y = -1 to shift to y-up?
+        self.BmpScale = self.bmpWH / self.WH
+
+        print "bmpWH:", self.bmpWH
+        print "Width, Height:", self.WH
+        print "self.BmpScale", self.BmpScale
+        self.ShiftFun = self.ShiftFunDict[Position]
+        self.CalcBoundingBox()
+        self.ScaledBitmap = None # cache of the last existing scaled bitmap
+
+    def CalcBoundingBox(self):
+        ## this isn't exact, as fonts don't scale exactly.
+        w,h = self.Width, self.Height
+        x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1)
+        self.BoundingBox = BBox.asBBox( ((x, y-h ), (x + w, y)) )
+
+    def WorldToBitmap(self, Pw):
+        """
+        computes bitmap coords from World coords
+        """
+        delta = Pw - self.XY
+        Pb = delta * self.BmpScale
+        Pb *= (1, -1) ##fixme: this may only works for Yup projection!
+                      ##       and may only work for top left position
+
+        return Pb.astype(N.int_)
+
+    def _DrawEntireBitmap(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
+        """
+        this is pretty much the old code
+
+        Scales and Draws the entire bitmap.
+
+        """
+        XY = WorldToPixel(self.XY)
+        H = ScaleWorldToPixel(self.Height)[0]
+        W = H * (self.bmpWidth / self.bmpHeight)
+        if (self.ScaledBitmap is None) or (self.ScaledBitmap[0] != (0, 0, self.bmpWidth, self.bmpHeight, W, H) ):
+        #if True: #fixme: (self.ScaledBitmap is None) or (H <> self.ScaledHeight) :
+            self.ScaledHeight = H
+            print "Scaling to:", W, H
+            Img = self.Image.Scale(W, H)
+            bmp = wx.BitmapFromImage(Img)
+            self.ScaledBitmap = ((0, 0, self.bmpWidth, self.bmpHeight , W, H), bmp)# this defines the cached bitmap
+        else:
+            print "Using Cached bitmap"
+            bmp = self.ScaledBitmap[1]
+        XY = self.ShiftFun(XY[0], XY[1], W, H)
+        dc.DrawBitmapPoint(bmp, XY, True)
+        if HTdc and self.HitAble:
+            HTdc.SetPen(self.HitPen)
+            HTdc.SetBrush(self.HitBrush)
+            HTdc.DrawRectanglePointSize(XY, (W, H) )
+
+    def _DrawSubBitmap(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
+        """
+        Subsets just the part of the bitmap that is visible
+        then scales and draws that.
+
+        """
+        BBworld = BBox.asBBox(self._Canvas.ViewPortBB)
+        BBbitmap = BBox.fromPoints(self.WorldToBitmap(BBworld))
+
+        XYs = WorldToPixel(self.XY)
+        # figure out subimage:
+        # fixme: this should be able to be done more succinctly!
+
+        if BBbitmap[0,0] < 0:
+            Xb = 0
+        elif BBbitmap[0,0] >  self.bmpWH[0]: # off the bitmap
+            Xb = 0
+        else:
+            Xb = BBbitmap[0,0]
+            XYs[0] = 0 # draw at origin
+
+        if BBbitmap[0,1] < 0:
+            Yb = 0
+        elif BBbitmap[0,1] >  self.bmpWH[1]: # off the bitmap
+            Yb = 0
+            ShouldDraw = False
+        else:
+            Yb = BBbitmap[0,1]
+            XYs[1] = 0 # draw at origin
+
+        if BBbitmap[1,0] < 0:
+            #off the screen --  This should never happen!
+            Wb = 0
+        elif BBbitmap[1,0] > self.bmpWH[0]:
+            Wb = self.bmpWH[0] - Xb
+        else:
+            Wb = BBbitmap[1,0] - Xb
+
+        if BBbitmap[1,1] < 0:
+            # off the screen --  This should never happen!
+            Hb = 0
+            ShouldDraw = False
+        elif BBbitmap[1,1] > self.bmpWH[1]:
+            Hb = self.bmpWH[1] - Yb
+        else:
+            Hb = BBbitmap[1,1] - Yb
+
+        FullHeight = ScaleWorldToPixel(self.Height)[0]
+        scale = FullHeight / self.bmpWH[1]
+        Ws = int(scale * Wb + 0.5) # add the 0.5 to  round
+        Hs = int(scale * Hb + 0.5)
+        if (self.ScaledBitmap is None) or (self.ScaledBitmap[0] != (Xb, Yb, Wb, Hb, Ws, Ws) ):
+            Img = self.Image.GetSubImage(wx.Rect(Xb, Yb, Wb, Hb))
+            Img.Rescale(Ws, Hs)
+            bmp = wx.BitmapFromImage(Img)
+            self.ScaledBitmap = ((Xb, Yb, Wb, Hb, Ws, Ws), bmp)# this defines the cached bitmap
+            #XY = self.ShiftFun(XY[0], XY[1], W, H)
+            #fixme: get the shiftfun working!
+        else:
+            print "Using cached bitmap"
+            ##fixme: The cached bitmap could be used if the one needed is the same scale, but
+            ##       a subset of the cached one.
+            bmp = self.ScaledBitmap[1]
+        dc.DrawBitmapPoint(bmp, XYs, True)
+
+        if HTdc and self.HitAble:
+            HTdc.SetPen(self.HitPen)
+            HTdc.SetBrush(self.HitBrush)
+            HTdc.DrawRectanglePointSize(XYs, (Ws, Hs) )
+
+    def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+        BBworld = BBox.asBBox(self._Canvas.ViewPortBB)
+        ## first see if entire bitmap is displayed:
+        if  BBworld.Inside(self.BoundingBox):
+            print "Drawing entire bitmap with old code"
+            self._DrawEntireBitmap(dc , WorldToPixel, ScaleWorldToPixel, HTdc)
+            return None
+        elif BBworld.Overlaps(self.BoundingBox):
+            #BBbitmap = BBox.fromPoints(self.WorldToBitmap(BBworld))
+            print "Drawing a sub-bitmap"
+            self._DrawSubBitmap(dc , WorldToPixel, ScaleWorldToPixel, HTdc)
+        else:
+            print "Not Drawing -- no part of image is showing"
+
+class DotGrid:
+    """
+    An example of a Grid Object -- it is set on teh FloatCAnvas with one of: 
+    
+    FloatCanvas.GridUnder = Grid
+    FloatCanvas.GridOver = Grid
+    
+    It will be drawn every time, regardless of the viewport.
+    
+    In its _Draw method, it computes what to draw, given the ViewPortBB
+    of the Canvas it's being drawn on.
+    
+    """
+    def __init__(self, Spacing, Size = 2, Color = "Black", Cross=False, CrossThickness = 1):
+
+        self.Spacing = N.array(Spacing, N.float)
+        self.Spacing.shape = (2,)
+        self.Size = Size
+        self.Color = Color
+        self.Cross = Cross
+        self.CrossThickness = CrossThickness
+
+    def CalcPoints(self, Canvas):
+        ViewPortBB = Canvas.ViewPortBB
+
+        Spacing = self.Spacing
+
+        minx, miny = N.floor(ViewPortBB[0] / Spacing) * Spacing
+        maxx, maxy = N.ceil(ViewPortBB[1] / Spacing) * Spacing
+
+        ##fixme: this could use vstack or something with numpy
+        x = N.arange(minx, maxx+Spacing[0], Spacing[0]) # making sure to get the last point
+        y = N.arange(miny, maxy+Spacing[1], Spacing[1]) # an extra is OK
+        Points = N.zeros((len(y), len(x), 2), N.float)
+        x.shape = (1,-1)
+        y.shape = (-1,1)
+        Points[:,:,0] += x
+        Points[:,:,1] += y
+        Points.shape = (-1,2)
+
+        return Points
+
+    def _Draw(self, dc, Canvas):
+        Points = self.CalcPoints(Canvas)
+
+        Points = Canvas.WorldToPixel(Points)
+
+        dc.SetPen(wx.Pen(self.Color,self.CrossThickness))
+
+        if self.Cross: # Use cross shaped markers
+            #Horizontal lines
+            LinePoints = N.concatenate((Points + (self.Size,0),Points + (-self.Size,0)),1)
+            dc.DrawLineList(LinePoints)
+            # Vertical Lines
+            LinePoints = N.concatenate((Points + (0,self.Size),Points + (0,-self.Size)),1)
+            dc.DrawLineList(LinePoints)
+            pass
+        else: # use dots
+            ## Note: this code borrowed from Pointset -- itreally shouldn't be repeated here!.
+            if self.Size <= 1:
+                dc.DrawPointList(Points)
+            elif self.Size <= 2:
+                dc.DrawPointList(Points + (0,-1))
+                dc.DrawPointList(Points + (0, 1))
+                dc.DrawPointList(Points + (1, 0))
+                dc.DrawPointList(Points + (-1,0))
+            else:
+                dc.SetBrush(wx.Brush(self.Color))
+                radius = int(round(self.Size/2))
+                ##fixme: I really should add a DrawCircleList to wxPython
+                if len(Points) > 100:
+                    xy = Points
+                    xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Size ), 1 )
+                    dc.DrawEllipseList(xywh)
+                else:
+                    for xy in Points:
+                        dc.DrawCircle(xy[0],xy[1], radius)
+
+