Alright. Thanks for those pointers. Here is what I'm up to. I can group them but ungrouping becomes a little wonky as it wont release all of the objects. How do I get the to ungroup properly? I tried unbindall but it seems that it has to go trough all of the objects and bind them again. I can do this, Im just worried it will chew up resources. Also I wanted to do a BBox.Inside for the hit test but I couldnt think of a short way of doing it.
Thanks for the help so far.
Cheers
Astan
#!/usr/bin/env python
"""

This is a small demo, showing how to make an object that can be moved around.

It also contains a simple prototype for a "Connector" object
  -- a line connecting two other objects

"""

import wx

ver = 'local'
#ver = 'installed'

if ver == 'installed': ## import the installed version
    from wx.lib.floatcanvas import NavCanvas, Resources
    from wx.lib.floatcanvas import FloatCanvas as FC
    print "using installed version:", wx.lib.floatcanvas.__version__
elif ver == 'local':
    ## import a local version
    import sys
    sys.path.append("..")
    from floatcanvas import NavCanvas,  Resources
    from floatcanvas import FloatCanvas as FC
    from floatcanvas.Utilities import BBox

import numpy as N

## here we create some new mixins:

class MovingObjectMixin:
    """
    Methods required for a Moving object
    
    """

    def GetOutlinePoints(self):
        BB = self.BoundingBox
        OutlinePoints = N.array( ( (BB[0,0], BB[0,1]),
                                    (BB[0,0], BB[1,1]),
                                    (BB[1,0], BB[1,1]),
                                    (BB[1,0], BB[0,1]),
                                 )
                               )

        return OutlinePoints
        

class ConnectorObjectMixin:
    """
    Mixin class for DrawObjects that can be connected with lines
    
    NOte that this versionony works for Objects that have an "XY" attribute:
      that is, one that is derived from XHObjectMixin.
    
    """
    
    def GetConnectPoint(self):
        return self.XY
        
class MovingBitmap(FC.ScaledBitmap, MovingObjectMixin, ConnectorObjectMixin):
    """
    ScaledBitmap Object that can be moved
    """
    ## All we need to do is is inherit from:
    ##  ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
    pass
    
class MovingCircle(FC.Circle, MovingObjectMixin, ConnectorObjectMixin):
    """
    ScaledBitmap Object that can be moved
    """
    ## All we need to do is is inherit from:
    ##  ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
    pass
    
class MovingArc(FC.Arc, MovingObjectMixin, ConnectorObjectMixin):
    """
    ScaledBitmap Object that can be moved
    """
    ## All we need to do is is inherit from:
    ##  ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
    pass

class MovingGroup(FC.Group, MovingObjectMixin):
     def GetConnectPoint(self):
        return self.BoundingBox.Center
       
    
class TriangleShape1(FC.Polygon, MovingObjectMixin):

    def __init__(self, XY, L):

        """
        An equilateral triangle object
        XY is the middle of the triangle
        L is the length of one side of the Triangle
        """

        XY = N.asarray(XY)
        XY.shape = (2,)

        Points = self.CompPoints(XY, L)

        FC.Polygon.__init__(self, Points,
                                  LineColor = "Black",
                                  LineStyle = "Solid",
                                  LineWidth    = 2,
                                  FillColor    = "Red",
                                  FillStyle    = "Solid")
    ## Override the default OutlinePoints
    def GetOutlinePoints(self):
        return self.Points
        
    def CompPoints(self, XY, L):
        c = L/ N.sqrt(3) 

        Points = N.array(((0, c),
                          ( L/2.0, -c/2.0),
                          (-L/2.0, -c/2.0)),
                          N.float_)

        Points += XY
        return Points


class DrawFrame(wx.Frame):

    """
    A simple frame used for the Demo

    """

    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.CreateStatusBar()            
        # Add the Canvas
        Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
                                          ProjectionFun = None,
                                          Debug = 0,
                                          BackgroundColor = "DARK SLATE BLUE",
                                          ).Canvas
        
        self.Canvas = Canvas

        Canvas.Bind(FC.EVT_MOTION, self.OnMove )
        Canvas.Bind(FC.EVT_LEFT_UP, self.OnLeftUp )
        Canvas.Bind(FC.EVT_LEFT_DOWN, self.OnLeftDown )
        
        self.objects = [] #this contains objects on the canvas

        Points = N.array(((0,0),
                          (1,0),
                          (0.5, 1)),
                         N.float)
        
        data  = (( (0,0),  1),
                 ( (3,3),  2),
                 ( (-2,3), 2.5 ),
                  )

        for p, L in data:
            Tri = TriangleShape1(p, 1)
            self.objects.append(Tri)
            Canvas.AddObject(Tri)
            Tri.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)

        Circle = MovingCircle( (1, 3), 2, FillColor="Blue")
        self.objects.append(Circle)
        Canvas.AddObject(Circle)
        Circle.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)

        Bitmaps = []
        ## create the bitmaps first
        for Point in ((1,1), (-4,3)):
            Bitmaps.append(MovingBitmap(Resources.getMondrianImage(),
                                  Point,
                                  Height=1,
                                  Position='cc')
                           )       
        
        ## then add them to the Canvas, so they are on top of the line
        for bmp in Bitmaps:
            self.objects.append(bmp)
            Canvas.AddObject(bmp)
            bmp.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)

        self.Show(True)
        self.Canvas.ZoomToBB()

        self.MoveObject = None
        self.Moving = False
        self.Tol = 5
    
        self.Drawing = False
        self.RBRect = None
        self.StartPointWorld = None

        self.G = None


        return None


    def ObjectHit(self, object):
        if not self.Moving:
            self.Moving = True
            self.StartPoint = object.HitCoordsPixel
            self.StartObject = self.Canvas.WorldToPixel(object.GetOutlinePoints())
            self.MoveObject = None
            self.MovingObject = object     

    def OnMove(self, event):
        """
        Updates the status bar with the world coordinates
        and moves the object it is clicked on

        """
        self.SetStatusText("%.4f, %.4f"%tuple(event.Coords))

        if self.Moving:
            dxy = event.GetPosition() - self.StartPoint
            # Draw the Moving Object:
            dc = wx.ClientDC(self.Canvas)
            dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
            dc.SetBrush(wx.TRANSPARENT_BRUSH)
            dc.SetLogicalFunction(wx.XOR)
            if self.MoveObject is not None:
                dc.DrawPolygon(self.MoveObject)
            self.MoveObject = self.StartObject + dxy
            dc.DrawPolygon(self.MoveObject)
            
        if self.Drawing:
            x, y = self.StartPoint
            Cornerx, Cornery = event.GetPosition()
            w, h = ( Cornerx - x, Cornery - y)
            if abs(w) > self.Tol and abs(h) > self.Tol:
                # draw the RB box
                dc = wx.ClientDC(self.Canvas)
                dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
                dc.SetBrush(wx.TRANSPARENT_BRUSH)
                dc.SetLogicalFunction(wx.XOR)
                if self.RBRect:
                    dc.DrawRectangle(*self.RBRect)
                self.RBRect = (x, y, w, h )
                dc.DrawRectangle(*self.RBRect)
            
    def OnLeftDown(self,event):
        self.Drawing = True
        self.StartPoint = event.GetPosition()
        self.StartPointWorld = event.Coords       
                  

    def OnLeftUp(self, event):                    
        if self.Drawing:
            self.Drawing = False
            if self.RBRect:
                WH = event.Coords - self.StartPointWorld #do I even need this?
                self.selected_objects = []
                if self.G:
                    self.Canvas.RemoveObject(self.G)
                    self.G = None 
                for object in self.objects:
                    objp = object.GetOutlinePoints()[0]   #how do i get position of an object? BBox.Inside is cleaner but long. I like Short.             
                    if  self.StartPointWorld[0] < objp[0] and self.StartPointWorld[1] > objp[1] and event.Coords[0] > objp[0] and event.Coords[1] < objp[1]:
                        #insert better hitText above. BBox.Inside is cleaner but long. I like Short.
                        self.selected_objects.append(object)            
                if len(self.selected_objects) > 0:        
                    self.G = MovingGroup(self.selected_objects)
                    self.Canvas.AddObject(self.G)
                    self.G.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
                    
            self.Canvas.Draw(True)
        self.RBRect = None
        self.StartPointWorld = None   
        if self.Moving:
            self.Moving = False
            self.selected_objects = []
            if self.G:
                self.Canvas.RemoveObject(self.G)
                self.G = None 
            if self.MoveObject is not None:
                dxy = event.GetPosition() - self.StartPoint
                dxy = self.Canvas.ScalePixelToWorld(dxy)
                self.selected_objects = [self.MovingObject]
                self.G = MovingGroup(self.selected_objects)
                self.Canvas.AddObject(self.G)
                self.G.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
                self.MovingObject.Move(dxy) 
                self.MoveTri = None
            self.Canvas.Draw(True)            

app = wx.PySimpleApp(0)
DrawFrame(None, -1, "FloatCanvas Moving Group Object App", wx.DefaultPosition, (700,700) )
app.MainLoop()
_______________________________________________
FloatCanvas mailing list
[email protected]
http://mail.mithis.com/cgi-bin/mailman/listinfo/floatcanvas

Reply via email to