[pygtk] Selecting and moving objects on a layout
Loic BERTHE
loic.berthe at free.fr
Sat Mar 25 06:00:19 WST 2006
Hi,
I'm trying to make a canvas where I can put objects, move them by
drag'n'drop,
and select them by drawing a box with the mouse or by clicking on them.
But :
- I've no idea how to draw a box with the mouse and how to deal with
selection
- My first try to implement moving by drag'n'drop seems pretty ugly,
As a little example is better than a long description, you can find the
code below
Have you any idea or link that could help me ?
Critics and comments on the code would be very welcome.
Regards,
--
Elby
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
#
# A first try to make a Canvas where you can move objects by drag'n'drop
#
import pygtk
pygtk.require('2.0')
import gtk
# Drag'n'Drop
TARGET_TYPE_NDDE = 80
fromNode = [ ( "node_move", 0, TARGET_TYPE_NDDE ),]
toCanvas = [ ( "node_move", 0, TARGET_TYPE_NDDE ),]
#-------------------------------------------------------------------------------
class Node:
counter = 1
tiny_pixbuf = gtk.gdk.pixbuf_new_from_xpm_data([
"26 26 5 1",
" c black",
". c grey",
"o c yellow",
"X c blue",
"- c None",
"--------- ---------",
"------- oooooo -------",
"----- oooooooooo -----",
"---- oooooooooooooo ----",
"--- oooooooooooooooo ---",
"-- oooooooooooooooooo --",
"-- oooooooooooooooooooo -",
"- ooooooooooooooooooooo -",
"- oooooooooooooooooooooo ",
" ooooo oooooo. .ooo ",
" ooooo XXX oooo. XXXX ooo ",
" ooooo XXX oooo XXXXXX oo ",
" ooooo. X .oooo XXXXXX oo ",
" oooooo. .ooooo XXXXXX oo ",
" oooooooooooooo. XXXX ooo ",
" ooooooooooooooo. .ooo ",
" ooooooooooooooooooooooo ",
"- ooo.oooooooooooooooooo ",
"- oo. .oooooooooo. ooo -",
"-- ooo .ooooooo. ooo -",
"-- ooo XX .oo --",
"--- ooo XXXXXXX .oo ---",
"---- oooo ooo ----",
"----- oooooooooo -----",
"------ oooooo ------",
"-------- --------"
])
def __init__(self,name=None,Type='Data',x=50, y=50):
self.Type = Type
self.x = x
self.y = y
self.name = name or "%s%d" % (Type,self.counter)
self.__class__.counter += 1
# image
self.Image_EventBox = gtk.EventBox()
self.Image_EventBox.set_border_width(0)
self.Image = gtk.Image()
self.Image.set_from_pixbuf(self.tiny_pixbuf)
self.Image_EventBox.add(self.Image)
self.Image.show()
self.Image_EventBox.show()
# Label
self.Label_EventBox = gtk.EventBox()
self.Label_EventBox.set_border_width(0)
self.Label = gtk.Label(self.name)
self.Label.set_justify(gtk.JUSTIFY_CENTER)
self.Label.set_size_request(width=66, height=-1)
self.Label.set_line_wrap(True)
self.Label_EventBox.add(self.Label)
# Drag'n'drop
self.Image_EventBox.connect("drag_begin", self.begin_Callback)
self.Image_EventBox.connect("drag_data_get", self.send_Callback)
self.Image_EventBox.drag_source_set(gtk.gdk.BUTTON1_MASK,fromNode,
gtk.gdk.ACTION_COPY)
self.Label.show()
self.Label_EventBox.show()
def begin_Callback(self, widget, context):
widget.drag_source_set_icon_pixbuf(self.tiny_pixbuf)
def send_Callback(self, widget, context, selection, targetType, time):
if targetType == TARGET_TYPE_NDDE:
selection.set(selection.target, 8, str(id(self)))
def put_on_layout(self,layout):
layout.put(self.Image_EventBox, self.x, self.y)
layout.put(self.Label_EventBox, self.x-15, self.y+28)
def move_on_layout(self,layout, x,y):
self.x = int(x + layout.get_hadjustment().value)
self.y = int(y + layout.get_vadjustment().value)
layout.move(self.Image_EventBox, self.x , self.y)
layout.move(self.Label_EventBox, self.x-15, self.y+28)
def __repr__(self):
return self.name
#-------------------------------------------------------------------------------
class My_App:
HEIGHT = 600
WIDTH = 600
def __init__(self):
self.NodeList =[]
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_default_size(400, 400)
window.connect("destroy", lambda w: gtk.main_quit())
window.add(self.makeLayout())
window.show()
def layout_resize(self, widget, event):
x, y, width, height = widget.get_allocation()
if width > self.lwidth or height > self.lheight:
self.lwidth = max(width, self.lwidth)
self.lheight = max(height, self.lheight)
widget.set_size(self.lwidth, self.lheight)
def makeLayout(self):
self.lwidth = self.WIDTH
self.lheight = self.HEIGHT
table = gtk.Table(2, 2, False)
table.show()
layout = gtk.Layout()
self.layout = layout
layout.set_size(self.lwidth, self.lheight)
layout.connect("size-allocate", self.layout_resize)
layout.show()
table.attach(layout, 0, 1, 0, 1, gtk.FILL|gtk.EXPAND,
gtk.FILL|gtk.EXPAND, 0, 0)
# create the scrollbars and pack into the table
vScrollbar = gtk.VScrollbar(None)
vScrollbar.show()
table.attach(vScrollbar, 1, 2, 0, 1, gtk.FILL|gtk.SHRINK,
gtk.FILL|gtk.SHRINK, 0, 0)
hScrollbar = gtk.HScrollbar(None)
hScrollbar.show()
table.attach(hScrollbar, 0, 1, 1, 2, gtk.FILL|gtk.SHRINK,
gtk.FILL|gtk.SHRINK,
0, 0)
# tell the scrollbars to use the layout widget's adjustments
vAdjust = layout.get_vadjustment()
vScrollbar.set_adjustment(vAdjust)
hAdjust = layout.get_hadjustment()
hScrollbar.set_adjustment(hAdjust)
# drag n drop signals
layout.connect("drag_data_received", self.receiveCallback)
layout.drag_dest_set(gtk.DEST_DEFAULT_MOTION |
gtk.DEST_DEFAULT_HIGHLIGHT |
gtk.DEST_DEFAULT_DROP,
toCanvas, gtk.gdk.ACTION_COPY)
return table
def receiveCallback(self, widget, context, x, y, selection, targetType,
time):
if targetType == TARGET_TYPE_NDDE:
node_id = int(selection.data)
for node in self.NodeList :
if id(node) == node_id :
node.move_on_layout(self.layout,x,y)
def add_node(self, node):
self.NodeList.append(node)
node.put_on_layout(self.layout)
if __name__ == "__main__":
app = My_App()
NodeList = [
Node(name = "very very very very happy ", Type='Data' , x=50 ,
y=50),
Node(name='happy',Type='App', x=150, y=100),
Node(Type='Data', x=250, y=200),
Node(Type='Data', x=50, y=200),
]
for node in NodeList :
app.add_node(node)
gtk.main()
# vim: set et sts=4 sw=4:
More information about the pygtk
mailing list