This is the code of where Im up to.
The unbind still doesnt work with whatever I try. If I use a .UnBindAll() on the movinggroup, it doesnt let other objects bind to it, if I dont use .UnBindAll() the moving group persists and will still respond to hits. As an example I've put the 'ungrouping' condition after the moving group has been moved. Any ideas?
Thanks
Astan

Astan Chee wrote:
Christopher Barker wrote:
keep us informed.
Will do. I'll post it up once i get the ungrouping to work.
maybe -- as I said there may be a need for some re-factoring -- maybe a way to have multiple bindings, so you can add one "on top" that will take over, then when that one is removed, the old binding remains.
I dont understand this because I did it and it didnt work.
I did an .UnBindAll() on the group and then looped trough all the existing non-group objects and set their bindings via the .bind() methods. This not only took away the group and its bindings, it didnt bind the non-group objects. I can post my code if necessary.
Well, I don't know your application, but it's very common for mouse actions to have different effects at different times. Any sort of drawing program has modes to zoom in and out, select objeccts, edit objects, create particular objects, etc.
I know what you mean, i just wanted to add more functionality on the "select" mode :)
In general, you'll want to know if the line itself has been hit. There are various way to do that, and as I think about it, it's probably pretty easy to leverage the existing infrastructure so that you can "bind" and object to a None event, then it will be "hitable", and then we can make a method:

FloatCanvas.GetHitObject((x, y))

And it will return the object hit (of those that have been bound to something -- hmmmm.
This sounds like an adventure! Im guessing it would require some sort of inherited BBox class that would do a partial .Inside()?
Cheers
Astan
_______________________________________________
FloatCanvas mailing list
[email protected]
http://mail.mithis.com/cgi-bin/mailman/listinfo/floatcanvas

#!/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       

        Canvas.Bind(FC.EVT_MOTION, self.OnMove )
        Canvas.Bind(FC.EVT_LEFT_UP, self.OnLeftUp )
        Canvas.Bind(FC.EVT_LEFT_DOWN, self.OnLeftDown )
        Canvas.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown ) #debugging purposes
            
        
        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)            
            Canvas.AddObject(Tri)
            Tri.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
            self.objects.append(Tri)

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

        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:            
            Canvas.AddObject(bmp)
            bmp.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
            self.objects.append(bmp)

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

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

        self.G = None
        self.selected_objects = []

        return None

    def OnKeyDown(self,event):
        print self.selected_objects
        print self.G
        print self.MovingObject
        print "========="

    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:                
                self.selected_objects = []
                self.O = []
                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 hitTest above. BBox.Inside is cleaner but long. I like Short.
                        self.selected_objects.append(object)
                        self.O.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
            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)
            #How do I unbind and reset everything to normal?
            if self.G is not None:
                print "unbind here:"
                print "removing "
                print self.G
                self.Canvas.RemoveObject(self.G)
                self.MovingObject = None
                self.MoveObject = None
                self.Moving = False
                #without self.G.UnBindAll() it doesnt release the groups
                #with self.G.UnBindAll() it wont let other objects bind it.
                self.G.UnBindAll()
                del self.G
                self.G = None
                self.Refresh()
                self.Canvas.Refresh()
                self.Canvas.Draw(True)
                self.selected_objects = []
                for idx in range(0,len(self.objects)):
                    print self.objects[idx]
                    self.Canvas.RemoveObject(self.objects[idx])
                    self.Canvas.AddObject(self.objects[idx])
                    self.objects[idx].Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
                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