From 4acb6bfbda5e60b7770feaf6dfb4a0d0197f8cc8 Mon Sep 17 00:00:00 2001 From: amartin Date: Tue, 11 Sep 2007 07:07:37 +0000 Subject: jam shortcuts --- (limited to 'Jam') diff --git a/Jam/Block.py b/Jam/Block.py index 53048c2..f0789fd 100644 --- a/Jam/Block.py +++ b/Jam/Block.py @@ -23,7 +23,6 @@ class Block(): PAD = 4 KEYSIZE = 26 - KEYOFFSET = HEIGHT - PAD - PAD - KEYSIZE KEYMASK_START = 309 def __init__( self, owner, data ): @@ -157,6 +156,9 @@ class Block(): if self.parent: return self.parent.getRoot() return self + def isActive( self ): + return self.active + def setActive( self, state ): self.active = state self.invalidate_rect( not self.dragging ) @@ -168,7 +170,16 @@ class Block(): self.data[ key ] = value def testMouseOver( self, event ): - if self.child: return self.child.testMouseOver( event ) + if self.child: + ret = self.child.testMouseOver( event ) + if ret: return ret + + x = event.x - self.x + y = event.y - self.y + + if 0 <= x <= self.width and 0 <= y <= self.height: + return -1 + return False def button_press( self, event ): @@ -348,9 +359,12 @@ class Instrument(Block): class Drum(Block): MASK_START = 100 - + + KEYRECT = [ Block.PAD - 1, Block.HEIGHT + 1 - Block.PAD - Block.KEYSIZE, Block.KEYSIZE, Block.KEYSIZE ] + KEYRECT += [ KEYRECT[0]+KEYRECT[2], KEYRECT[1]+KEYRECT[3] ] + #::: data format: - # { "name": name, "id": instrumentId [ , "page": pageId, "volume": 0-1, "reverb": 0-1, "beats": 2-12, "regularity": 0-1 ] } + # { "name": name, "id": instrumentId [ , "page": pageId, "volume": 0-1, "reverb": 0-1, "beats": 2-12, "regularity": 0-1, "key": shortcut ] } #::: def __init__( self, owner, data ): Block.__init__( self, owner, data ) @@ -369,6 +383,13 @@ class Drum(Block): self.data["beats"] = random.randint(2, 12) if not "regularity" in self.data.keys(): self.data["regularity"] = random.random() + if "key" not in self.data.keys(): + self.data["key"] = None + + self.owner.mapKey( self.data["key"], self ) + self.keyImage = [ self.owner.getKeyImage( self.data["key"], False ), + self.owner.getKeyImage( self.data["key"], True ) ] + self.img = [ self.owner.getInstrumentImage( self.data["id"], False ), self.owner.getInstrumentImage( self.data["id"], True ) ] @@ -377,13 +398,26 @@ class Drum(Block): self.regenerate() def destroy( self ): + self.owner.mapKey( None, self, self.data["key"] ) self.owner.noteDB.deletePages( [ self.data["page"] ] ) Block.destroy( self ) def setData( self, key, value ): - self.data[key] = value if key == "beats": + self.data["beats"] = value self.owner.noteDB.updatePage( self.data["page"], PARAMETER.PAGE_BEATS, value ) + + elif key == "key": + oldKey = self.data["key"] + self.data["key"] = value + self.keyImage = [ self.owner.getKeyImage( value, False ), + self.owner.getKeyImage( value, True ) ] + self.invalidate_rect() + self.owner.mapKey( value, self, oldKey ) + + else: + self.data[key] = value + if self.active: self.owner.updateDrum( self ) @@ -415,6 +449,27 @@ class Drum(Block): return False + def testMouseOver( self, event ): + ret = self.testWithinKey( event ) + if ret: return ret + + x = event.x - self.x + y = event.y - self.y + + if 0 <= x <= self.width and 0 <= y <= self.height: + return -1 + + return False + + def testWithinKey( self, event ): + x = event.x - self.x + y = event.y - self.y + + if Drum.KEYRECT[0] <= x <= Drum.KEYRECT[4] and Drum.KEYRECT[1] <= y <= Drum.KEYRECT[5]: + return self + + return False + def _doButtonPress( self, event ): # we were hit with a button press pass @@ -443,13 +498,22 @@ class Drum(Block): # draw block self.gc.set_clip_origin( self.x-Drum.MASK_START, self.y-self.height ) pixmap.draw_drawable( self.gc, self.img[self.active], x-self.x, y-self.y, x, y, width, height ) - + + # draw key + self.gc.set_clip_origin( self.x+Drum.KEYRECT[0]-Block.KEYMASK_START, self.y+Drum.KEYRECT[1] ) + pixmap.draw_drawable( self.gc, self.keyImage[ self.active ], 0, 0, self.x+Drum.KEYRECT[0], self.y+Drum.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE ) + def drawHighlight( self, startX, startY, stopX, stopY, pixmap ): self.gc.foreground = self.owner.colors["Border_Highlight"] self.gc.set_clip_origin( self.x-Drum.MASK_START, self.y ) pixmap.draw_rectangle( self.gc, True, self.x, self.y, self.width, self.height ) + def drawKeyHighlight( self, pixmap ): + self.gc.foreground = self.owner.colors["Border_Highlight"] + self.gc.set_clip_origin( self.x+Drum.KEYRECT[0]-Block.KEYMASK_START, self.y+Drum.KEYRECT[1]-Block.KEYSIZE ) + pixmap.draw_rectangle( self.gc, True, self.x+Drum.KEYRECT[0], self.y+Drum.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE ) + def regenerate( self ): self.data["page"] = self.owner.owner._generateDrumLoop( self.data["id"], self.data["beats"], self.data["regularity"], self.data["reverb"], self.data["page"] ) if self.active: @@ -472,7 +536,7 @@ class Loop(Block): MASK_BEAT = MASK_START + HEAD MASK_TAIL = MASK_START + HEAD + BEAT*3 - KEYRECT = [ HEAD + Block.PAD, Block.KEYOFFSET, Block.KEYSIZE, Block.KEYSIZE ] + KEYRECT = [ HEAD + Block.PAD, Block.HEIGHT - 2*Block.PAD - Block.KEYSIZE, Block.KEYSIZE, Block.KEYSIZE ] KEYRECT += [ KEYRECT[0]+KEYRECT[2], KEYRECT[1]+KEYRECT[3] ] #::: data format: @@ -505,6 +569,8 @@ class Loop(Block): self.owner.getLoopImage( self.data["id"], True ) ] def destroy( self ): + if self.keyActive: + self.owner.mapKey( None, self, self.data["key"] ) self.owner.noteDB.deletePages( [ self.data["id"] ] ) Block.destroy( self ) @@ -535,16 +601,24 @@ class Loop(Block): self.owner.getLoopImage( self.data["id"], True ) ] def setData( self, key, value ): - self.data[key] = value if key == "beats": self.owner.noteDB.updatePage( self.data["id"], PARAMETER.PAGE_BEATS, value ) self._updateWidth() self.updateLoop() + self.data["beats"] = value + elif key == "key": + oldKey = self.data["key"] + self.data["key"] = value self.keyImage = [ self.owner.getKeyImage( value, False ), self.owner.getKeyImage( value, True ) ] self.invalidate_rect() + if self.keyActive: + self.owner.mapKey( value, self, oldKey ) + + else: + self.data[key] = value def substitute( self, block ): self.invalidateBranch( True ) @@ -611,6 +685,7 @@ class Loop(Block): if self.parent.type == Instrument: self.keyActive = True + self.owner.mapKey( self.data["key"], self ) else: root = self.getRoot() if root.type == Instrument: @@ -627,6 +702,7 @@ class Loop(Block): loopRoot = None self.keyActive = False + self.owner.mapKey( None, self, self.data["key"] ) Block._removeParent( self ) @@ -638,7 +714,16 @@ class Loop(Block): self.owner.updateLoop( loopRoot ) def testMouseOver( self, event ): - return self.testWithinKey( event ) + ret = self.testWithinKey( event ) + if ret: return ret + + x = event.x - self.x + y = event.y - self.y + + if 0 <= x <= self.width and 0 <= y <= self.height: + return -1 + + return False def testWithinKey( self, event ): if not self.keyActive: diff --git a/Jam/Desktop.py b/Jam/Desktop.py index e8a8afd..7b1acba 100644 --- a/Jam/Desktop.py +++ b/Jam/Desktop.py @@ -144,6 +144,9 @@ class Desktop( gtk.EventBox ): for i in range( len(self.blocks)-1, -1, -1 ): self.deleteBlock( self.blocks[i] ) + def mapKey( self, key, block, oldKey = None ): + self.owner.mapKey( key, block, oldKey ) + def getInstrumentImage( self, id, active = False ): return self.owner.getInstrumentImage( id, active ) @@ -321,6 +324,8 @@ class Desktop( gtk.EventBox ): return for i in range(blockCount-1, -1, -1): over = self.blocks[i].testMouseOver( event ) + if over == -1: + break # over block but no hotspot if over: if self.overKey != self.blocks[i]: if self.overKey: diff --git a/Jam/JamMain.py b/Jam/JamMain.py index 012aa21..c339ae6 100644 --- a/Jam/JamMain.py +++ b/Jam/JamMain.py @@ -2,6 +2,7 @@ import pygtk pygtk.require( '2.0' ) import gtk +import pango from SubActivity import SubActivity @@ -33,6 +34,8 @@ import xdrlib import time import gobject import Util.Network as Net +from sugar.presence import presenceservice +from sugar.graphics.xocolor import XoColor from math import sqrt @@ -60,6 +63,9 @@ class JamMain(SubActivity): self.paused = False + presenceService = presenceservice.get_instance() + self.xoOwner = presenceService.get_owner() + #-- Drawing ------------------------------------------- def darken( colormap, hex ): hexToDec = { "0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9, "A":10, "B":11, "C":12, "D":13, "E":14, "F":15, "a":10, "b":11, "c":12, "d":13, "e":14, "f":15 } @@ -74,20 +80,25 @@ class JamMain(SubActivity): b = 255 - int( 0.7*(255-(16*hexToDec[hex[5]] + hexToDec[hex[6]])) ) return colormap.alloc_color( r*256, g*256, b*256 ) + xoColorKey = self.xoOwner.props.color + if not xoColorKey: + xoColorKey = ( "#8D8D8D,#FFDDEA" ) + xoColor = XoColor( xoColorKey ) + win = gtk.gdk.get_default_root_window() self.gc = gtk.gdk.GC( win ) colormap = gtk.gdk.colormap_get_system() self.colors = { "bg": colormap.alloc_color( Config.PANEL_BCK_COLOR ), "black": colormap.alloc_color( style.COLOR_BLACK.get_html() ), - "Picker_Bg": colormap.alloc_color( "#404040" ), - "Picker_Bg_Inactive": colormap.alloc_color( "#808080" ), - #"Picker_Bg": colormap.alloc_color( style.COLOR_TOOLBAR_GREY.get_html() ), - #"Picker_Bg_Inactive": colormap.alloc_color( style.COLOR_BUTTON_GREY.get_html() ), + #"Picker_Bg": colormap.alloc_color( "#404040" ), + #"Picker_Bg_Inactive": colormap.alloc_color( "#808080" ), + "Picker_Bg": colormap.alloc_color( style.COLOR_TOOLBAR_GREY.get_html() ), + "Picker_Bg_Inactive": colormap.alloc_color( style.COLOR_BUTTON_GREY.get_html() ), "Picker_Fg": colormap.alloc_color( style.COLOR_WHITE.get_html() ), - "Border_Active": colormap.alloc_color( "#590000" ), + "Border_Active": colormap.alloc_color( xoColor.get_stroke_color() ), #colormap.alloc_color( "#590000" ), "Border_Inactive": colormap.alloc_color( "#8D8D8D" ), "Border_Highlight": colormap.alloc_color( "#FFFFFF" ), - "Bg_Active": colormap.alloc_color( "#FFDDEA" ), + "Bg_Active": colormap.alloc_color( xoColor.get_fill_color() ), #colormap.alloc_color( "#FFDDEA" ), "Bg_Inactive": colormap.alloc_color( "#DBDBDB" ), "Preview_Note_Fill": colormap.alloc_color( Config.BG_COLOR ), "Preview_Note_Border": colormap.alloc_color( Config.FG_COLOR ), @@ -176,7 +187,7 @@ class JamMain(SubActivity): # use hardware key codes to work on any keyboard layout (hopefully) self.valid_shortcuts = { 18:"9", 19:"0", 20:"-", 21:"=", 32:"O", 33:"P", 34:"[", 35:"]", - 48:";", 51:"'", + 47:";", 48:"'", 51:"\\", 60:".", 61:"/", None:" " } for key in self.valid_shortcuts.keys(): @@ -248,6 +259,8 @@ class JamMain(SubActivity): self.keyboardListener = None self.recordingNote = None + self.keyMap = {} + # default instrument self._updateInstrument( Config.INSTRUMENTS["kalimba"].instrumentId, 0.5 ) self.instrumentStack = [] @@ -326,6 +339,24 @@ class JamMain(SubActivity): def onKeyPress( self, widget, event ): key = event.hardware_keycode + if key in self.keyMap.keys(): + activate = True + for block in self.keyMap[key]: + if block.isActive(): + activate = False + break + if activate: + for block in self.keyMap[key]: + if not block.isActive(): + if block.type == Block.Drum: self.desktop.activateDrum( block ) + elif block.type == Block.Loop: self.desktop.activateLoop( block ) + else: + for block in self.keyMap[key]: + if block.isActive(): + if block.type == Block.Drum: self.desktop.deactivateDrum( block ) + elif block.type == Block.Loop: self.desktop.deactivateLoop( block ) + return + if self.key_dict.has_key( key ): # repeated press return @@ -732,6 +763,19 @@ class JamMain(SubActivity): def setKeyboardListener( self, listener ): self.keyboardListener = listener + def mapKey( self, key, block, oldKey = None ): + if oldKey != None and block in self.keyMap[oldKey]: + self.keyMap[oldKey].remove( block ) + + if key == None: + return + + if key not in self.keyMap.keys(): + self.keyMap[key] = [] + + if block not in self.keyMap[key]: + self.keyMap[key].append( block ) + #========================================================== # Pixmaps @@ -788,6 +832,8 @@ class JamMain(SubActivity): def prepareKeyImage( self, key ): win = gtk.gdk.get_default_root_window() pangolayout = self.create_pango_layout( _(self.valid_shortcuts[key]) ) + fontDesc = pango.FontDescription( "bold" ) + pangolayout.set_font_description( fontDesc ) extents = pangolayout.get_pixel_extents() x = ( Block.Block.KEYSIZE - extents[1][2] ) // 2 y = ( Block.Block.KEYSIZE - extents[1][3] ) // 2 @@ -925,7 +971,8 @@ class JamMain(SubActivity): except: print "bad ip4_address" if self.network.isHost(): - # TODO how do I figure out if this buddy is me? + if buddy == self.xoOwner: + return if buddy.props.ip4_address: self.network.introducePeer( buddy.props.ip4_address ) else: diff --git a/Jam/Popup.py b/Jam/Popup.py index 8bca64c..3d21e7f 100644 --- a/Jam/Popup.py +++ b/Jam/Popup.py @@ -1297,7 +1297,7 @@ class Shortcut( Popup ): # match keycodes from JamMain.valid_shortcuts layout = [ [ 0.0, [ 18, 19, 20, 21 ] ], [ 0.3, [ 32, 33, 34, 35 ] ], - [ 1.6, [ 48, 51 ] ], + [ 1.7, [ 47, 48, 51 ] ], [ 1.1, [ 60, 61 ] ] ] self.GUI["keyBox"] = gtk.VBox() @@ -1335,10 +1335,7 @@ class Shortcut( Popup ): self.key = None def setBlock( self, block ): - self.settingBlock = True - - if self.key != None: - self.GUI[self.key].set_active( False ) + self.ignoreToggle = True self.block = block self.key = self.block.getData( "key" ) @@ -1346,10 +1343,23 @@ class Shortcut( Popup ): if self.key != None: self.GUI[self.key].set_active( True ) - self.settingBlock = False + self.ignoreToggle = False Popup.setBlock( self, block ) + def on_key_press( self, widget, event ): + key = event.hardware_keycode + if key in self.owner.valid_shortcuts.keys(): + self.block.setData( "key", key ) + if self.key != None: # clear old key + self.ignoreToggle = True + self.GUI[self.key].set_active( False ) + self.key = None + self.ignoreToggle = False + self.popdown( True ) + else: + self.owner.onKeyPress( widget, event ) + def keyExpose( self, widget, event ): self.gc.set_clip_mask( self.owner.blockMask ) self.gc.set_clip_origin( event.area.x - Block.Block.KEYMASK_START, event.area.y ) @@ -1357,20 +1367,31 @@ class Shortcut( Popup ): return True def keyToggled( self, widget ): - if widget.get_active() and not self.settingBlock: - if self.key != None: + if self.ignoreToggle: + return + + if widget.get_active(): + self.block.setData( "key", widget.key ) + + self.ignoreToggle = True + + if self.key != None: # clear old key self.GUI[self.key].set_active( False ) + self.key = None - self.key = widget.key + widget.set_active( False ) - self.block.setData( "key", self.key ) - - self.popdown( True ) + self.ignoreToggle = False + + self.popdown( True ) def handleNone( self, widget ): if self.key != None: + self.ignoreToggle = True self.GUI[self.key].set_active( False ) self.key = None - self.block.setData( "key", self.key ) + self.ignoreToggle = False + + self.block.setData( "key", None ) self.popdown( True ) -- cgit v0.9.1