Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Jam/Desktop.py
diff options
context:
space:
mode:
authoramartin <olpc@xo-05-28-21.localdomain>2007-08-01 11:26:00 (GMT)
committer amartin <olpc@xo-05-28-21.localdomain>2007-08-01 11:26:00 (GMT)
commit29e22f05090827be14e2d9cfd29c73a5d0ec9239 (patch)
treeae55826ea3c9c0ee0d09a96a7bde00e865e0fa18 /Jam/Desktop.py
parent65f1c3491a68fcf892987d8cba6485054694f4f7 (diff)
Jam Desktop
Diffstat (limited to 'Jam/Desktop.py')
-rw-r--r--Jam/Desktop.py244
1 files changed, 244 insertions, 0 deletions
diff --git a/Jam/Desktop.py b/Jam/Desktop.py
new file mode 100644
index 0000000..89c890b
--- /dev/null
+++ b/Jam/Desktop.py
@@ -0,0 +1,244 @@
+
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+import Config
+
+import Jam.Block as Block
+
+class Desktop( gtk.EventBox ):
+
+ def __init__( self, owner ):
+ gtk.EventBox.__init__( self )
+
+ self.owner = owner
+
+ self.drawingArea = gtk.DrawingArea()
+ self.add( self.drawingArea )
+
+ win = gtk.gdk.get_default_root_window()
+ self.gc = gtk.gdk.GC( win )
+ colormap = self.drawingArea.get_colormap()
+ self.colors = { "bg": colormap.alloc_color( Config.BG_COLOR, True, True ), \
+ "tempWhite": colormap.alloc_color( "#FFFFFF", True, True ), \
+ "tempBlock1": colormap.alloc_color( "#227733", True, True ), \
+ "tempBlock2": colormap.alloc_color( "#837399", True, True ), \
+ "tempBlock3": colormap.alloc_color( "#111177", True, True ), \
+ "tempBlock4": colormap.alloc_color( "#99AA22", True, True ), \
+ "tempBlock5": colormap.alloc_color( "#449977", True, True ) }
+
+ self.dirtyRectToAdd = gtk.gdk.Rectangle() # used by the invalidate_rect function
+ self.screenBuf = None
+ self.screenBufDirty = False
+ self.screenBufDirtyRect = gtk.gdk.Rectangle()
+
+ self.blocks = [] # items on the desktop
+
+ # TEMP
+ self.addBlock( Block.Instrument, [], ( 100, 100 ) )
+
+ self.add_events(gtk.gdk.POINTER_MOTION_MASK|gtk.gdk.POINTER_MOTION_HINT_MASK)
+
+ self.connect( "size-allocate", self.size_allocate )
+ self.connect( "button-press-event", self.button_press )
+ self.connect( "button-release-event", self.button_release )
+ self.connect( "motion-notify-event", self.motion_notify )
+ self.drawingArea.connect( "expose-event", self.expose )
+
+ self.clickedBlock = None
+ self.possibleParent = None
+ self.dragging = False
+ self.possibleDelete = False
+
+ def size_allocate( self, widget, allocation ):
+ if self.screenBuf == None or self.alloc.width != allocation.width or self.alloc.height != allocation.height:
+ win = gtk.gdk.get_default_root_window()
+ self.screenBuf = gtk.gdk.Pixmap( win, allocation.width, allocation.height )
+ self.invalidate_rect( 0, 0, allocation.width, allocation.height )
+ self.alloc = allocation
+ self.absoluteLoc = [0,0]
+ parent = self.get_parent()
+ while parent:
+ alloc = parent.get_allocation()
+ self.absoluteLoc[0] += alloc.x
+ self.absoluteLoc[1] += alloc.y
+ parent = parent.get_parent()
+ return False
+
+ #==========================================================
+ # Blocks
+
+ def addBlock( self, blockClass, blockData, loc = (-1,-1), drag = False ):
+
+ block = blockClass( self, self.gc )
+
+ if loc[0] != -1: x = loc[0]
+ else: x = self.alloc.width//2 - blockClass.WIDTH_DIV2
+ if loc[1] != -1: y = loc[1]
+ elif drag: y = self.alloc.height - blockClass.HEIGHT
+ else: y = self.alloc.height//2 - blockClass.HEIGHT_DIV2
+
+ if drag:
+ win = gtk.gdk.get_default_root_window()
+ display = win.get_display()
+ screen = display.get_default_screen()
+ display.warp_pointer( screen, self.absoluteLoc[0] + x + blockClass.WIDTH_DIV2, self.absoluteLoc[1] + y + blockClass.HEIGHT_DIV2 )
+ self._beginDrag( block )
+ block.setLoc( x, y )
+ else:
+ self.blocks.append( block )
+ block.setLoc( x, y )
+
+
+
+ #==========================================================
+ # Mouse
+
+ def button_press( self, widget, event ):
+
+ hit = False
+ for i in range(len(self.blocks)-1, -1, -1):
+ hit = self.blocks[i].button_press( event )
+ if hit:
+ self.clickedBlock = hit
+ break
+
+ def button_release( self, widget, event ):
+
+ if self.possibleDelete:
+ self.possibleDelete = False
+ self.clickedBlock.destroy()
+ self.clickedBlock = None
+ self.possibleParent = None
+ self.dragging = False
+
+ if self.dragging:
+ self.dragging = False
+
+ if self.possibleParent:
+ self.possibleParent.invalidate_rect( False )
+ self.possibleParent.addChild( self.clickedBlock )
+ root = self.possibleParent.getRoot()
+ self.blocks.remove(root)
+ self.blocks.append(root)
+ self.possibleParent = None
+ else:
+ self.blocks.append( self.clickedBlock )
+
+ if self.clickedBlock:
+ self.clickedBlock.button_release( event )
+ self.clickedBlock = None
+
+
+ def motion_notify( self, widget, event ):
+
+ if not self.clickedBlock:
+ return
+
+ if event.is_hint or widget != self:
+ x, y, state = self.window.get_pointer()
+ event.x = float(x)
+ event.y = float(y)
+ event.state = state
+
+ self.dragging = True
+
+ if self.clickedBlock.motion_notify( event ): # first drag of root block, remove from self.blocks
+ self.blocks.remove( self.clickedBlock )
+
+ if event.y < 0 or event.y > self.alloc.height:
+ self.possibleDelete = True
+ return
+ else:
+ self.possibleDelete = False
+
+ if self.clickedBlock.canChild and len(self.blocks):
+ for i in range(len(self.blocks)-1, -1, -1):
+ handled = self.blocks[i].testChild( self.clickedBlock.getLoc() )
+ if handled:
+ if self.possibleParent != handled:
+ if self.possibleParent:
+ self.possibleParent.invalidate_rect( False )
+ self.possibleParent = handled
+ self.possibleParent.invalidate_rect( False )
+ break
+ if not handled and self.possibleParent:
+ self.possibleParent.invalidate_rect( False )
+ self.possibleParent = None
+
+ def _beginDrag( self, block ):
+ block._beginDrag()
+ self.clickedBlock = block
+ self.dragging = True
+
+ #==========================================================
+ # Drawing
+
+ def draw( self ):
+
+ startX = self.screenBufDirtyRect.x
+ startY = self.screenBufDirtyRect.y
+ stopX = startX + self.screenBufDirtyRect.width
+ stopY = startY + self.screenBufDirtyRect.height
+
+ self.gc.set_clip_rectangle( self.screenBufDirtyRect )
+
+ # draw background
+ self.gc.foreground = self.colors["bg"]
+ self.screenBuf.draw_rectangle( self.gc, True, startX, startY, self.screenBufDirtyRect.width, self.screenBufDirtyRect.height )
+
+ # draw blocks
+ for block in self.blocks:
+ block.draw( startX, startY, stopX, stopY, self.screenBuf )
+
+ self.screenBufDirty = False
+
+ def expose( self, DA, event ):
+
+ if self.screenBufDirty:
+ self.draw()
+
+ self.drawingAreaDirty = False
+
+ startX = event.area.x
+ startY = event.area.y
+ stopX = event.area.x + event.area.width
+ stopY = event.area.y + event.area.height
+
+ self.gc.set_clip_rectangle( event.area )
+
+ # draw base
+ DA.window.draw_drawable( self.gc, self.screenBuf, startX, startY, startX, startY, event.area.width, event.area.height )
+
+ if self.possibleDelete:
+ return
+
+ # draw possible parent
+ if self.possibleParent:
+ self.possibleParent.drawHighlight( startX, startY, stopX, stopY, DA.window )
+
+ # draw dragged objects
+ if self.dragging:
+ self.clickedBlock.draw( startX, startY, stopX, stopY, DA.window )
+
+ def invalidate_rect( self, x, y, width, height, base = True ):
+ self.dirtyRectToAdd.x = x
+ self.dirtyRectToAdd.y = y
+ self.dirtyRectToAdd.width = width
+ self.dirtyRectToAdd.height = height
+
+ #print "dirty %d %d %d %d %d %d" % (x, y, width, height, x+width, y+height)
+ if base: # the base image has been dirtied
+ if not self.screenBufDirty:
+ self.screenBufDirtyRect.x = x
+ self.screenBufDirtyRect.y = y
+ self.screenBufDirtyRect.width = width
+ self.screenBufDirtyRect.height = height
+ else:
+ self.screenBufDirtyRect = self.screenBufDirtyRect.union( self.dirtyRectToAdd )
+ self.screenBufDirty = True
+ if self.drawingArea.window != None:
+ self.drawingArea.window.invalidate_rect( self.dirtyRectToAdd, True )
+ self.drawingAreaDirty = True
+