diff options
author | amartin <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) |
commit | 29e22f05090827be14e2d9cfd29c73a5d0ec9239 (patch) | |
tree | ae55826ea3c9c0ee0d09a96a7bde00e865e0fa18 /Jam/Desktop.py | |
parent | 65f1c3491a68fcf892987d8cba6485054694f4f7 (diff) |
Jam Desktop
Diffstat (limited to 'Jam/Desktop.py')
-rw-r--r-- | Jam/Desktop.py | 244 |
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 + |