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