Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TamTamEdit.activity/Edit/rm
diff options
context:
space:
mode:
Diffstat (limited to 'TamTamEdit.activity/Edit/rm')
-rw-r--r--TamTamEdit.activity/Edit/rm/BackgroundView.py501
-rw-r--r--TamTamEdit.activity/Edit/rm/NoteView.py253
-rw-r--r--TamTamEdit.activity/Edit/rm/PageBankView.py85
-rw-r--r--TamTamEdit.activity/Edit/rm/PageView.py65
-rw-r--r--TamTamEdit.activity/Edit/rm/PositionIndicator.py47
-rw-r--r--TamTamEdit.activity/Edit/rm/TrackView.py263
-rw-r--r--TamTamEdit.activity/Edit/rm/TunePageView.py17
-rw-r--r--TamTamEdit.activity/Edit/rm/TuneView.py123
8 files changed, 1354 insertions, 0 deletions
diff --git a/TamTamEdit.activity/Edit/rm/BackgroundView.py b/TamTamEdit.activity/Edit/rm/BackgroundView.py
new file mode 100644
index 0000000..ff6e75f
--- /dev/null
+++ b/TamTamEdit.activity/Edit/rm/BackgroundView.py
@@ -0,0 +1,501 @@
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+from math import floor
+
+from Framework.Constants import Constants
+from GUI.GUIConstants import GUIConstants
+from GUI.Core.NoteParametersWindow import NoteParametersWindow
+
+from Framework.Core.Profiler import TP
+
+class SELECTNOTES:
+ ALL = -1
+ NONE = 0
+ ADD = 1
+ REMOVE = 2
+ EXCLUSIVE = 3
+
+#-------------------------------------------------------------
+# This is a TEMPORARY implementaion of the BackgroundView,
+# it was written quickly to get track selections working
+#-------------------------------------------------------------
+
+# TODO: Do I really have to subclass gtk.EventBox to get the button-press-event?
+# (I wasn't getting it subclassing directly from DrawingArea)
+class BackgroundView( gtk.EventBox ):
+ #-----------------------------------
+ # initialization
+ #-----------------------------------
+ def __init__( self, trackIDs, selectedTrackIDs, selectionChangedCallback, mutedTrackIDs, beatsPerPageAdjustment, trackDictionary, selectedPageIDs, updatePageCallback ):
+ gtk.EventBox.__init__( self )
+
+ self.drawingArea = gtk.DrawingArea()
+ self.add( self.drawingArea )
+
+ self.sizeInitialized = False
+
+ self.trackViews = {}
+ self.trackIDs = trackIDs
+ self.selectedTrackIDs = selectedTrackIDs
+ self.selectionChangedCallback = selectionChangedCallback
+ self.mutedTrackIDs = mutedTrackIDs
+ self.beatsPerPageAdjustment = beatsPerPageAdjustment
+ self.trackDictionary = trackDictionary
+ self.selectedPageIDs = selectedPageIDs
+ self.updatePageCallback = updatePageCallback
+
+ self.curAction = False # stores the current mouse action
+ self.curActionObject = False # stores the object that in handling the action
+
+ self.buttonPressCount = 1 # used on release events to indicate double/triple releases
+ self.clickLoc = [0,0] # location of the last click
+ self.marqueeLoc = False # current drag location of the marquee
+
+ self.drawingArea.connect( "expose-event", self.draw )
+ self.connect( "button-press-event", self.handleButtonPress )
+ self.connect( "button-release-event", self.handleButtonRelease )
+ self.connect( "motion-notify-event", self.handleMotion )
+
+ #-----------------------------------
+ # access methods
+ #-----------------------------------
+ def getTrackRect( self, trackID ):
+ return gtk.gdk.Rectangle( GUIConstants.BORDER_SIZE,
+ self.getTrackYLocation( trackID ),
+ self.getTrackWidth(),
+ self.getTrackHeight() )
+
+ def getTrackWidth( self ):
+ return self.get_allocation().width - 2 * ( GUIConstants.BORDER_SIZE + 2 )
+
+ def getFullHeight( self ):
+ return int( floor( self.get_allocation().height / len( self.trackIDs ) ) )
+
+ def getTrackHeight( self ):
+ return int( self.getFullHeight() - 2 * self.getTrackSpacing() )
+
+ #TODO-> trackIDs should probably be ordered!
+ # we're just using trackID as an index here (this will only work until you can remove tracks)
+ def getTrackYLocation( self, trackID ):
+ if self.getTrackHeight() < 0:
+ return 0
+ else:
+ trackIndex = trackID
+
+ trackHeight = int( floor( self.get_allocation().height / len( self.trackIDs ) ) )
+ trackBackgroundYValue = trackHeight * trackIndex
+ return trackBackgroundYValue + GUIConstants.BORDER_SIZE
+
+ def getTrackSpacing( self ):
+ return GUIConstants.TRACK_SPACING
+
+ #-----------------------------------
+ # callback methods
+ #-----------------------------------
+ def set_size_request( self, width, height ):
+ self.sizeInitialized = True
+ self.drawingArea.set_size_request( width, height )
+ self.height = height
+ self.width = width
+
+ numTracks = len(self.trackIDs)
+ trackSpacing = self.getTrackSpacing()
+ if numTracks: self.trackHeight = int( floor( (height - trackSpacing*(numTracks-1)) / numTracks ) )
+ else: self.trackHeight = 1
+ self.trackWidth = width
+
+ trackCount = 0
+ for trackID in self.trackIDs:
+ self.trackViews[trackID].set_size_request( self.trackWidth, self.trackHeight )
+ self.trackViews[trackID].setPositionOffset( (0, trackCount*(self.trackHeight+trackSpacing)) )
+ trackCount += 1
+
+ def setCurrentTracks( self, trackViews ):
+
+ oldLen = len(self.trackViews)
+
+ if oldLen and trackViews != self.trackViews: self.clearSelectedNotes() # clear all the currently selected notes
+
+ self.trackViews = trackViews
+
+ numTracks = len(self.trackViews)
+ if oldLen != numTracks and self.sizeInitialized:
+ trackSpacing = self.getTrackSpacing()
+ if numTracks: self.trackHeight = int( floor( (self.height - trackSpacing*(numTracks-1)) / numTracks ) )
+ else: self.trackHeight = 1
+ trackCount = 0
+ for trackID in self.trackIDs:
+ self.trackViews[trackID].set_size_request( self.trackWidth, self.trackHeight )
+ self.trackViews[trackID].setPositionOffset( (0, trackCount*(self.trackHeight+trackSpacing)) )
+ trackCount += 1
+
+ self.dirty()
+
+
+ def getNoteParameters( self ):
+ for trackID in self.selectedTrackIDs:
+ for pageID in self.selectedPageIDs:
+ for note in self.trackDictionary[ trackID ][ pageID ]:
+ newPitch = note.pitch + self.noteParameters.pitchAdjust.value
+ newAmplitude = note.amplitude * self.noteParameters.amplitudeAdjust.value
+ newPan = self.noteParameters.panAdjust.value
+ newReverbSend = note.reverbSend * self.noteParameters.reverbSendAdjust.value
+ newAttack = self.noteParameters.attackAdjust.value
+ newDecay = self.noteParameters.decayAdjust.value
+ newFilterType = self.noteParameters.filterType
+ newFilterCutoff = self.noteParameters.filterCutoff
+ newTied = self.noteParameters.tied
+ newOverlap = self.noteParameters.overlap
+
+ note.pitch = self.noteParametersBoundaries( newPitch, note.pitch, Constants.MINIMUM_PITCH, Constants.MAXIMUM_PITCH )
+ note.amplitude = self.noteParametersBoundaries( newAmplitude, note.amplitude, Constants.MINIMUM_AMPLITUDE, Constants.MAXIMUM_AMPLITUDE )
+ note.reverbSend = self.noteParametersBoundaries( newReverbSend, note.reverbSend, Constants.MINIMUM_AMPLITUDE,
+ Constants.MAXIMUM_AMPLITUDE )
+ if newPan != note.pan:
+ note.pan = newPan
+
+ if newAttack != note.attack:
+ note.attack = newAttack
+
+ if newDecay != note.decay:
+ note.decay = newDecay
+
+ if newFilterType != note.filterType:
+ note.filterType = newFilterType
+
+ if newFilterCutoff != note.filterCutoff:
+ note.filterCutoff = newFilterCutoff
+
+ if newTied != note.tied:
+ note.tied = newTied
+
+ if newOverlap != note.overlap:
+ note.overlap = newOverlap
+
+ self.updatePageCallback()
+
+ def noteParametersBoundaries( self, newValue, noteValue, minBoundary, maxBoundary ):
+ if newValue != noteValue:
+ if newValue >= minBoundary and newValue <= maxBoundary:
+ return newValue
+ elif newValue < minBoundary:
+ return minBoundary
+ elif newValue > maxBoundary:
+ return maxBoundary
+ else:
+ return noteValue
+
+ #-----------------------------------
+ # action and event methods
+ #-----------------------------------
+ def setCurrentAction( self, action, obj ):
+ if self.curAction:
+ print "BackgroundView - Action already in progress!"
+
+ self.curAction = action
+ self.curActionObject = obj
+
+ if action == "note-drag-onset": self.updateDragLimits()
+ elif action == "note-drag-duration": self.updateDragLimits()
+ elif action == "note-drag-pitch": self.updateDragLimits()
+
+ def doneCurrentAction( self ):
+ if self.curAction == "note-drag-onset": self.doneNoteDrag()
+ elif self.curAction == "note-drag-duration": self.doneNoteDrag()
+ elif self.curAction == "note-drag-pitch": self.doneNoteDrag()
+
+ self.curAction = False
+ self.curActionObject = False
+
+ def toggleTrack( self, trackID, exclusive ):
+ if exclusive:
+ self.selectedTrackIDs.clear()
+ self.selectedTrackIDs.add( trackID )
+ else:
+ if trackID in self.selectedTrackIDs:
+ self.selectedTrackIDs.discard( trackID )
+ else:
+ self.selectedTrackIDs.add( trackID )
+
+ def selectionChanged( self ):
+ if self.curAction == "note-drag-onset": self.updateDragLimits()
+ elif self.curAction == "note-drag-duration": self.updateDragLimits()
+ elif self.curAction == "note-drag-pitch": self.updateDragLimits()
+ self.dirty()
+
+ def selectNotesByBar( self, selID, startX, stopX ):
+ beatCount = int(round( self.beatsPerPageAdjustment.value, 0 ))
+ for trackID in self.trackIDs:
+ if trackID == selID:
+ notes = self.trackViews[trackID].getNotesByBar( beatCount, startX, stopX )
+ self.trackViews[trackID].selectNotes( SELECTNOTES.EXCLUSIVE, notes )
+ else:
+ self.trackViews[trackID].selectNotes( SELECTNOTES.NONE, [] )
+ self.selectionChanged()
+
+ def selectNotesByTrack( self, selID ):
+ for trackID in self.trackIDs:
+ if trackID == selID: self.trackViews[trackID].selectNotes( SELECTNOTES.ALL, [] )
+ else: self.trackViews[trackID].selectNotes( SELECTNOTES.NONE, [] )
+ self.selectionChanged()
+
+ def selectNotes( self, noteDic ):
+ for trackID in self.trackIDs:
+ if trackID in noteDic: self.trackViews[trackID].selectNotes( SELECTNOTES.EXCLUSIVE, noteDic[trackID] )
+ else: self.trackViews[trackID].selectNotes( SELECTNOTES.NONE, [] )
+ self.selectionChanged()
+
+ def addNotesToSelection( self, noteDic ):
+ for trackID in self.trackIDs:
+ if trackID in noteDic: self.trackViews[trackID].selectNotes( SELECTNOTES.ADD, noteDic[trackID] )
+ self.selectionChanged()
+
+ def deselectNotes( self, noteDic ):
+ for trackID in self.trackIDs:
+ if trackID in noteDic: self.trackViews[trackID].selectNotes( SELECTNOTES.REMOVE, noteDic[trackID] )
+ self.selectionChanged()
+
+ def clearSelectedNotes( self ):
+ for trackID in self.trackIDs:
+ self.trackViews[trackID].selectNotes( SELECTNOTES.NONE, [] )
+ self.selectionChanged()
+
+ def updateDragLimits( self ):
+ self.dragLimits = [ [-9999,9999], [-9999,9999], [-9999,9999] ] # initialize to big numbers!
+ for trackID in self.trackIDs:
+ self.trackViews[trackID].updateDragLimits( self.dragLimits )
+
+ def noteDragOnset( self, event ):
+ dx = event.x - self.clickLoc[0]
+ dx = min( self.dragLimits[0][1], max( self.dragLimits[0][0], dx ) )
+ dy = 0
+ dw = 0
+
+ for trackID in self.trackIDs:
+ self.trackViews[trackID].noteDrag( self, dx, dy, dw )
+ self.dirty()
+
+ def noteDragDuration( self, event ):
+ dx = 0
+ dy = 0
+ dw = event.x - self.clickLoc[0]
+ dw = min( self.dragLimits[2][1], max( self.dragLimits[2][0], dw ) )
+
+ for trackID in self.trackIDs:
+ self.trackViews[trackID].noteDrag( self, dx, dy, dw )
+ self.dirty()
+
+ def noteDragPitch( self, event ):
+ dx = 0
+ dy = event.y - self.clickLoc[1]
+ dy = min( self.dragLimits[1][1], max( self.dragLimits[1][0], dy ) )
+ dw = 0
+
+ for trackID in self.trackIDs:
+ self.trackViews[trackID].noteDrag( self, dx, dy, dw )
+ self.dirty()
+
+ def doneNoteDrag( self ):
+ for trackID in self.trackIDs:
+ self.trackViews[trackID].doneNoteDrag( self )
+
+ def updateMarquee( self, event ):
+ self.marqueeLoc = [ event.x, event.y ]
+ parentRect = self.get_allocation()
+ if self.marqueeLoc[0] < 0: self.marqueeLoc[0] = 0
+ elif self.marqueeLoc[0] > parentRect.width: self.marqueeLoc[0] = parentRect.width
+ if self.marqueeLoc[1] < 0: self.marqueeLoc[1] = 0
+ elif self.marqueeLoc[1] > parentRect.height: self.marqueeLoc[1] = parentRect.height
+
+ self.dirty()
+
+ def doneMarquee( self, event ):
+ if self.marqueeLoc:
+ start = [ min(self.clickLoc[0],self.marqueeLoc[0]), \
+ min(self.clickLoc[1],self.marqueeLoc[1]) ]
+ stop = [ max(self.clickLoc[0],self.marqueeLoc[0]), \
+ max(self.clickLoc[1],self.marqueeLoc[1]) ]
+
+ select = {}
+
+ trackSpacing = self.getTrackSpacing()
+ trackTop = 0
+ for trackID in self.trackIDs:
+ notes = self.trackViews[trackID].handleMarqueeSelect( self, start, stop )
+ if notes: select[trackID] = notes
+ trackTop += self.trackHeight + trackSpacing
+ if trackTop > stop[1]: break
+
+ self.selectNotes( select )
+
+ self.marqueeLoc = False
+ self.doneCurrentAction()
+
+ self.dirty()
+
+ def handleButtonPress( self, drawingArea, event ):
+
+ TP.ProfileBegin( "BV::handleButtonPress" )
+
+ if event.type == gtk.gdk._2BUTTON_PRESS: self.buttonPressCount = 2
+ elif event.type == gtk.gdk._3BUTTON_PRESS: self.buttonPressCount = 3
+ else: self.buttonPressCount = 1
+
+ self.clickLoc = [ event.x, event.y ]
+
+ trackSpacing = self.getTrackSpacing()
+ trackTop = 0
+ for trackID in self.trackIDs:
+ handled = self.trackViews[trackID].handleButtonPress( self, event )
+ trackTop += self.trackHeight + trackSpacing
+ if handled or trackTop > event.y: break
+
+ if handled:
+ if not self.curAction: self.curAction = True # it was handled maybe no action was declared, set curAction to True anyway
+ TP.ProfileEnd( "BV::handleButtonPress" )
+ return
+
+ if event.button == 3:
+ self.noteParameters = NoteParametersWindow( self.trackDictionary, self.getNoteParameters )
+ self.setCurrentAction( "noteParameters", False )
+
+ TP.ProfileEnd( "BV::handleButtonPress" )
+
+
+ def handleButtonRelease( self, drawingArea, event ):
+ TP.ProfileBegin( "BV::handleButtonRelease" )
+
+ if not self.curAction: #do track selection stuff here so that we can also handle marquee selection
+ trackSpacing = self.getTrackSpacing()
+ trackTop = 0
+ for trackID in self.trackIDs:
+ handled = self.trackViews[trackID].handleButtonRelease( self, event, self.buttonPressCount )
+ trackTop += self.trackHeight + trackSpacing
+ if handled or trackTop > event.y: break
+
+ if handled: self.dirty()
+
+ TP.ProfileEnd( "BV::handleButtonRelease" )
+ return
+
+ if not self.curActionObject: # there was no real action to carry out
+ self.curAction = False
+ TP.ProfileEnd( "BV::handleButtonRelease" )
+ return
+
+ if self.curActionObject != self:
+ if self.curActionObject.handleButtonRelease( self, event, self.buttonPressCount ):
+ self.dirty()
+ TP.ProfileEnd( "BV::handleButtonRelease" )
+ return
+
+
+ # we're doing the action ourselves
+
+ if self.curAction == "marquee": self.doneMarquee( event )
+
+ TP.ProfileEnd( "BV::handleButtonRelease" )
+ return
+
+ def handleMotion( self, drawingArea, event ):
+ TP.ProfileBegin( "BV::handleMotion" )
+
+ if not self.curAction: # no action is in progress yet we're dragging, start a marquee
+ self.setCurrentAction( "marquee", self )
+
+ if self.curAction == "note-drag-onset":
+ self.noteDragOnset( event )
+ TP.ProfileEnd( "BV::handleMotion" )
+ return
+
+ if self.curAction == "note-drag-duration":
+ self.noteDragDuration( event )
+ TP.ProfileEnd( "BV::handleMotion" )
+ return
+
+ if self.curAction == "note-drag-pitch":
+ self.noteDragPitch( event )
+ TP.ProfileEnd( "BV::handleMotion" )
+ return
+
+ # we're doing the action ourselves
+
+ if self.curAction == "marquee": self.updateMarquee( event )
+
+ TP.ProfileEnd( "BV::handleMotion" )
+ return
+
+ def TEMPOLDSTUFF(self):
+
+ #TODO change this to accomodate the space between tracks
+ trackHeight = ( drawingArea.get_allocation().height - 1 ) / len( self.trackIDs )
+ trackID = int( floor( event.y / trackHeight ) )
+
+ if event.type == gtk.gdk.BUTTON_PRESS:
+ #single click toggles track selection
+ if trackID in self.selectedTrackIDs:
+ self.selectedTrackIDs.discard( trackID )
+ else:
+ self.selectedTrackIDs.add( trackID )
+ elif event.type == gtk.gdk._2BUTTON_PRESS:
+ #double click selects a single track
+ self.selectedTrackIDs.clear()
+ self.selectedTrackIDs.add( trackID )
+
+ self.drawingArea.queue_draw()
+ self.selectionChangedCallback()
+ if event.button == 3:
+ self.noteParameters = NoteParametersWindow( self.trackDictionary, self.getNoteParameters )
+
+ #-----------------------------------
+ # drawing methods
+ #-----------------------------------
+ def draw( self, drawingArea, event ):
+ TP.ProfileBegin( "BackgroundView::draw" )
+
+ context = drawingArea.window.cairo_create()
+ context.set_antialias(0) # I don't know what to set this to to turn it off, and it doesn't seem to work anyway!?
+
+ #parentRect = self.get_allocation()
+
+ beatCount = int(round( self.beatsPerPageAdjustment.value, 0 ))
+
+ for trackID in self.trackIDs:
+ self.trackViews[trackID].draw( context,
+ beatCount,
+ trackID in self.selectedTrackIDs )
+
+ # if self.curAction == "note-drag": # draw a cross at clickLoc
+ # lineW = 1
+ # context.set_line_width( lineW )
+ # lineWDIV2 = lineW/2.0
+ # context.set_source_rgb( 1, 1, 1 )
+
+ # context.move_to( self.clickLoc[0] + lineWDIV2 - 3, self.clickLoc[1] + lineWDIV2 )
+ # context.rel_line_to( 6, 0 )
+ # context.stroke()
+ # context.move_to( self.clickLoc[0] + lineWDIV2, self.clickLoc[1] + lineWDIV2 - 3)
+ # context.rel_line_to( 0, 6 )
+ # context.stroke()
+
+ if self.marqueeLoc: # draw the selection rect
+ lineW = 1
+ context.set_line_width( lineW )
+ lineWDIV2 = lineW/2.0
+
+ context.move_to( self.clickLoc[0] + lineWDIV2, self.clickLoc[1] + lineWDIV2 )
+ context.line_to( self.marqueeLoc[0] + lineWDIV2, self.clickLoc[1] + lineWDIV2 )
+ context.line_to( self.marqueeLoc[0] + lineWDIV2, self.marqueeLoc[1] + lineWDIV2 )
+ context.line_to( self.clickLoc[0] + lineWDIV2, self.marqueeLoc[1] + lineWDIV2 )
+ context.close_path()
+ context.set_source_rgb( 1, 1, 1 )
+ context.stroke()
+
+ TP.ProfileEnd( "BackgroundView::draw" )
+
+ def dirty( self ):
+ self.queue_draw()
+
+
diff --git a/TamTamEdit.activity/Edit/rm/NoteView.py b/TamTamEdit.activity/Edit/rm/NoteView.py
new file mode 100644
index 0000000..ac139a1
--- /dev/null
+++ b/TamTamEdit.activity/Edit/rm/NoteView.py
@@ -0,0 +1,253 @@
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+from Framework.Constants import Constants
+from Framework.CSound.CSoundConstants import CSoundConstants
+from GUI.GUIConstants import GUIConstants
+from GUI.Core.NoteParametersWindow import NoteParametersWindow
+
+from BackgroundView import SELECTNOTES
+
+#----------------------------------------------------------------------
+# TODO: currently we are only using CSoundNotes,
+# - this should updated to handle generic Note objects
+#----------------------------------------------------------------------
+
+#----------------------------------------------------------------------
+# A view for the (CSound)Note class
+#----------------------------------------------------------------------
+class NoteView:
+ #-----------------------------------
+ # initialization
+ # TODO: not sure if passing in beatsPerPageAdjustment is the best way to go about it
+ #-----------------------------------
+ def __init__( self, note, track, beatsPerPageAdjustment ):
+ self.note = note
+
+ self.track = track
+ self.beatsPerPageAdjustment = beatsPerPageAdjustment
+ self.posOffset = (0,0)
+
+ self.baseOnset = self.basePitch = self.baseDuration = self.lastDragX = self.lastDragY = self.lastDragW = 0 # note dragging properties
+
+ self.sampleNote = None
+
+ self.parentSize = False
+
+ self.selected = False
+ self.potentialDeselect = False
+
+
+ def getNoteParameters( self ):
+ self.note.pitch = self.noteParameters.pitchAdjust.value
+ self.note.amplitude = self.noteParameters.amplitudeAdjust.value
+ self.note.pan = self.noteParameters.panAdjust.value
+ self.note.attack = self.noteParameters.attackAdjust.value
+ self.note.decay = self.noteParameters.decayAdjust.value
+ self.note.reverbSend = self.noteParameters.reverbSendAdjust.value
+ self.note.filterType = self.noteParameters.filterType
+ self.note.filterCutoff = self.noteParameters.filterCutoff
+ self.note.tied = self.noteParameters.tied
+ self.note.overlap = self.noteParameters.overlap
+
+ def handleButtonPress( self, emitter, event ):
+ eX = event.x - self.x
+ eY = event.y - self.y
+
+ if eX < 0 or eX > self.width \
+ or eY < 0 or eY > self.height:
+ return False
+
+ if event.button == 3:
+ self.noteParameters = NoteParametersWindow( self.note, self.getNoteParameters )
+ return True
+
+ if event.type == gtk.gdk._2BUTTON_PRESS: # select bar
+ self.potentialDeselect = False
+ emitter.selectNotesByBar( self.track.getID(), self.x, self.x+self.width )
+ elif event.type == gtk.gdk._3BUTTON_PRESS: # select track
+ self.potentialDeselect = False
+ emitter.selectNotesByTrack( self.track.getID() )
+ else:
+ if self.getSelected(): # we already selected, might want to delected
+ self.potentialDeselect = True
+ else:
+ emitter.selectNotes( { self.track.getID(): [ self ] } )
+ self.updateSampleNote( self.note.pitch )
+
+ percent = eX/self.width
+ if percent < 0.3: emitter.setCurrentAction( "note-drag-onset", self )
+ elif percent > 0.7: emitter.setCurrentAction( "note-drag-duration", self )
+ else: emitter.setCurrentAction( "note-drag-pitch", self )
+
+
+ emitter.dirty()
+
+ return True
+
+ def handleButtonRelease( self, emitter, event, buttonPressCount ):
+
+ if self.potentialDeselect:
+ self.potentialDeselect = False
+ emitter.deselectNotes( { self.track.getID(): [ self ] } )
+
+ self.clearSampleNote()
+
+ emitter.doneCurrentAction()
+
+ return True
+
+ def noteDrag( self, emitter, dx, dy, dw ):
+ self.potentialDeselect = False
+
+ ticksPerPixel = (round( self.beatsPerPageAdjustment.value, 0 ) * Constants.TICKS_PER_BEAT) / self.parentSize[0]
+ stepPerPixel = (Constants.NUMBER_OF_POSSIBLE_PITCHES-1) / (self.parentSize[1] - self.height)
+ pitchPerStep = (Constants.MAXIMUM_PITCH-Constants.MINIMUM_PITCH)/(Constants.NUMBER_OF_POSSIBLE_PITCHES-1)
+
+ if dx != self.lastDragX:
+ self.lastDragX = dx
+ self.note.onset = self.baseOnset + int(dx*ticksPerPixel)
+
+ if dy != self.lastDragY:
+ self.lastDragY = dy
+ newPitch = self.basePitch + round(-dy*stepPerPixel)*pitchPerStep
+ self.note.pitch = newPitch
+ self.updateSampleNote( newPitch )
+
+ if dw != self.lastDragW:
+ self.lastDragW = dw
+ self.note.duration = self.baseDuration + int(dw*ticksPerPixel)
+
+ self.updateTransform( False )
+
+ def doneNoteDrag( self, emitter ):
+ self.baseOnset = self.note.onset
+ self.basePitch = self.note.pitch
+ self.baseDuration = self.note.duration
+
+ self.lastDragX = 0
+ self.lastDragY = 0
+ self.lastDragW = 0
+
+ self.clearSampleNote()
+
+
+ def handleMarqueeSelect( self, emitter, start, stop ):
+ intersectionY = [ max(start[1],self.y), min(stop[1],self.y+self.height) ]
+ if intersectionY[0] > intersectionY[1]:
+ return False
+
+ intersectionX = [ max(start[0],self.x), min(stop[0],self.x+self.width) ]
+ if intersectionX[0] > intersectionX[1]:
+ return False
+
+ return True
+
+ #-----------------------------------
+ # draw
+ #-----------------------------------
+
+ def setPositionOffset( self, offset ):
+ self.posOffset = offset
+ if self.parentSize: self.updateTransform( False )
+
+ def draw( self, context ):
+ lineW = GUIConstants.NOTE_BORDER_SIZE
+ lineWDIV2 = lineW/2.0
+ context.set_line_width( lineW )
+
+ context.move_to( self.x + lineWDIV2, self.y + lineWDIV2 )
+ context.rel_line_to( self.width - lineW, 0 )
+ context.rel_line_to( 0, self.height - lineW )
+ context.rel_line_to( -self.width + lineW, 0 )
+ context.close_path()
+
+ #background
+ colour = 1 - ( ( self.note.amplitude * 0.7 ) + 0.3 )
+ context.set_source_rgb( colour, colour, colour )
+ context.fill_preserve()
+
+ #border
+ if self.selected: context.set_source_rgb( 1, 1, 1 )
+ else: context.set_source_rgb( 0, 0, 0 )
+ context.stroke()
+
+ #-----------------------------------
+ # update
+ #-----------------------------------
+
+ def updateTransform( self, parentSize ):
+ if parentSize: self.parentSize = parentSize
+ self.width = int( self.parentSize[0] * self.note.duration / (round( self.beatsPerPageAdjustment.value, 0 ) * Constants.TICKS_PER_BEAT) )
+ self.height = round( max( GUIConstants.MINIMUM_NOTE_HEIGHT, self.parentSize[1] / (Constants.NUMBER_OF_POSSIBLE_PITCHES-1) ) )
+ self.x = int( self.parentSize[0] * self.note.onset / (round( self.beatsPerPageAdjustment.value, 0 ) * Constants.TICKS_PER_BEAT) ) \
+ + self.posOffset[0]
+ self.y = round( (self.parentSize[1]-self.height) * ( Constants.MAXIMUM_PITCH - self.note.pitch ) / (Constants.NUMBER_OF_POSSIBLE_PITCHES-1) ) \
+ + self.posOffset[1]
+
+ def checkX( self, startx, stopx ):
+ if self.x >= startx and self.x < stopx: return True
+ else: return False
+
+ def getStartTick( self ):
+ return self.note.onset
+
+ def getEndTick( self ):
+ return self.note.onset + self.note.duration
+
+ def updateDragLimits( self, dragLimits, leftBound, rightBound, widthBound ):
+ pixelsPerTick = self.parentSize[0] / (round( self.beatsPerPageAdjustment.value, 0 ) * Constants.TICKS_PER_BEAT)
+ pixelsPerPitch = (self.parentSize[1] - self.height) / (Constants.MAXIMUM_PITCH - Constants.MINIMUM_PITCH)
+ left = (leftBound - self.note.onset) * pixelsPerTick
+ right = (rightBound - self.note.duration - self.note.onset) * pixelsPerTick
+ up = (self.note.pitch - Constants.MAXIMUM_PITCH) * pixelsPerPitch
+ down = (self.note.pitch - Constants.MINIMUM_PITCH) * pixelsPerPitch
+ short = (Constants.MINIMUM_NOTE_DURATION - self.note.duration) * pixelsPerTick
+ long = (widthBound - self.note.duration - self.note.onset) * pixelsPerTick
+
+ if dragLimits[0][0] < left: dragLimits[0][0] = left
+ if dragLimits[0][1] > right: dragLimits[0][1] = right
+ if dragLimits[1][0] < up: dragLimits[1][0] = up
+ if dragLimits[1][1] > down: dragLimits[1][1] = down
+ if dragLimits[2][0] < short: dragLimits[2][0] = short
+ if dragLimits[2][1] > long: dragLimits[2][1] = long
+
+ # store the current loc as a reference point
+ self.baseOnset = self.note.onset
+ self.basePitch = self.note.pitch
+ self.baseDuration = self.note.duration
+
+ def updateSampleNote( self, pitch ):
+ if self.sampleNote == None:
+ self.sampleNote = self.note.clone()
+ #TODO clean this up:
+ if CSoundConstants.INSTRUMENTS[ self.sampleNote.instrumentFlag ].csoundInstrumentID == 103:
+ self.sampleNote.duration = 100
+ else:
+ self.sampleNote.duration = -1
+ self.sampleNote.play()
+
+ elif self.sampleNote.pitch != pitch:
+ self.sampleNote.pitch = pitch
+ self.sampleNote.play()
+
+ def clearSampleNote( self ):
+ if self.sampleNote != None:
+ self.sampleNote.duration = 0
+ self.sampleNote.play()
+ del self.sampleNote
+ self.sampleNote = None
+
+ #-----------------------------------
+ # Selection
+ #-----------------------------------
+
+ def setSelected( self, state ):
+ if self.selected != state:
+ self.selected = state
+ return True # state changed
+ return False # state is the same
+
+ def getSelected( self ):
+ return self.selected
diff --git a/TamTamEdit.activity/Edit/rm/PageBankView.py b/TamTamEdit.activity/Edit/rm/PageBankView.py
new file mode 100644
index 0000000..fedadef
--- /dev/null
+++ b/TamTamEdit.activity/Edit/rm/PageBankView.py
@@ -0,0 +1,85 @@
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+from GUI.GUIConstants import GUIConstants
+from GUI.Core.PageView import PageView
+
+class PageBankView( gtk.Frame ):
+
+ NO_PAGE = -1
+
+ def __init__( self, selectPageCallback, pageDropCallback ):
+ gtk.Frame.__init__( self )
+ self.table = gtk.Table( 1, GUIConstants.NUMBER_OF_PAGE_BANK_COLUMNS )
+ self.add( self.table )
+ self.drag_dest_set( gtk.DEST_DEFAULT_ALL, [ ( "tune page", gtk.TARGET_SAME_APP, 11 )], gtk.gdk.ACTION_COPY|gtk.gdk.ACTION_MOVE )
+ self.connect( "drag_data_received", self.dragDataReceived )
+ self.selectPageCallback = selectPageCallback
+ self.pageDropCallback = pageDropCallback
+ self.selectedPageIds = set([])
+ self.pageIndexDictionary = {}
+ self.pageViews = {}
+
+ def dragDataReceived( self, widget, context, x, y, selectionData, info, time):
+ self.pageDropCallback( selectionData.data )
+
+ def addPage( self, pageId, invokeCallback = True ):
+ pageIndex = len( self.pageViews.keys() )
+ self.pageIndexDictionary[ pageIndex ] = pageId
+
+ #TODO: resize table to suit number of pages?
+ #if pageIndex > ( self.table.n-rows * self.table.n_columns ):
+ # self.table.resize( self.table.n_rows + 1, self.table.n_columns )
+
+ pageView = PageView( pageIndex, self.selectPage, True )
+ self.pageViews[ pageIndex ] = pageView
+
+ columnIndex = pageIndex % GUIConstants.NUMBER_OF_PAGE_BANK_COLUMNS
+ rowIndex = int( pageIndex / GUIConstants.NUMBER_OF_PAGE_BANK_COLUMNS )
+ self.table.attach( pageView, columnIndex, columnIndex + 1, rowIndex, rowIndex + 1, gtk.SHRINK, gtk.SHRINK )
+
+ self.updateSize( pageView )
+
+ pageView.drag_source_set( gtk.gdk.BUTTON1_MASK,
+ [ ( "bank page", gtk.TARGET_SAME_APP, 10 ) ],
+ gtk.gdk.ACTION_COPY )
+
+ self.selectPage( pageId, True, invokeCallback )
+
+ pageView.show()
+
+ def set_size_request( self, width, height ):
+ gtk.Frame.set_size_request( self, width, height )
+ self.table.set_size_request( width, height )
+ for pageId in self.pageViews.keys():
+ self.updateSize( self.pageViews[ pageId ] )
+
+ def updateSize( self, pageView ):
+ pageView.set_size_request( self.get_allocation().width / GUIConstants.NUMBER_OF_PAGE_BANK_COLUMNS,
+ GUIConstants.PAGE_HEIGHT - 1 )
+
+ def selectPage( self, selectedPageId, invokeCallback = True, deselectOthers = True ):
+ if deselectOthers:
+ for pageId in self.pageViews.keys():
+ self.pageViews[ pageId ].setSelected( pageId == selectedPageId )
+ if pageId != selectedPageId:
+ self.selectedPageIds.discard( pageId )
+ else:
+ self.selectedPageIds.add( pageId )
+ #nb: pageId might be NO_PAGE, and selectedPageIds can be empty here
+
+ else:
+ self.pageViews[ selectedPageId ].toggleSelected()
+ if self.pageViews[ selectedPageId ].selected:
+ self.selectedPageIds.add( selectedPageId )
+ else:
+ self.selectedPageIds.discard( selectedPageId )
+
+ if invokeCallback:
+ self.selectPageCallback( selectedPageId )
+
+ def getSelectedPageIds( self ):
+ rval = filter( lambda id: self.pageViews[id].selected == True, self.pageViews.keys())
+ return rval
+
diff --git a/TamTamEdit.activity/Edit/rm/PageView.py b/TamTamEdit.activity/Edit/rm/PageView.py
new file mode 100644
index 0000000..00b650b
--- /dev/null
+++ b/TamTamEdit.activity/Edit/rm/PageView.py
@@ -0,0 +1,65 @@
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+import pango
+
+from GUI.GUIConstants import GUIConstants
+
+class PageView( gtk.DrawingArea ):
+ def __init__( self, pageID, selectPageCallback, selected = False ):
+ gtk.DrawingArea.__init__( self )
+
+ self.pageID = pageID
+ self.selectPageCallback = selectPageCallback
+ self.selected = selected
+
+ self.add_events( gtk.gdk.BUTTON_PRESS_MASK )
+
+ self.connect( "expose-event", self.handleExposeEvent )
+ self.connect( "button-press-event", self.handleButtonPress )
+ self.connect( "drag_data_get", self.getData )
+
+ def handleButtonPress( self, widget, event ):
+ if event.button == 1 or event.button == 3:
+ self.selectPageCallback( self.pageID, event.button == 1 )
+
+ def getData( self, widget, context, selection, targetType, eventTime ):
+ return selection.set( gtk.gdk.SELECTION_PRIMARY, 32, "p %d" % self.pageID )
+
+ def toggleSelected( self ):
+ self.selected = not self.selected
+ self.queue_draw()
+
+ def setSelected( self, selected ):
+ if self.selected != selected:
+ self.selected = selected
+ self.queue_draw()
+
+ # TODO: this is temporary: replace with a visual representation of the page
+ def handleExposeEvent( self, drawingArea, event ):
+ size = self.get_allocation()
+ context = self.window.cairo_create()
+
+ if self.selected:
+ context.set_line_width( GUIConstants.PAGE_SELECTED_BORDER_SIZE )
+ else:
+ context.set_line_width( GUIConstants.PAGE_BORDER_SIZE )
+ context.move_to( 0, 0 )
+ context.rel_line_to( size.width, 0 )
+ context.rel_line_to( 0, size.height )
+ context.rel_line_to( -size.width, 0 )
+ context.close_path()
+
+ #blue background
+ context.set_source_rgb( 0.75, 0.75, 0.75 )
+ context.fill_preserve()
+
+ #black border
+ context.set_source_rgb( 0, 0, 0 )
+ context.stroke()
+
+ #text
+ layout = self.create_pango_layout( "%d" % ( self.pageID + 1 ) )
+ layout.set_font_description( pango.FontDescription( 'Sans 10' ) )
+ self.window.draw_layout( self.window.new_gc(), 5, 5, layout )
diff --git a/TamTamEdit.activity/Edit/rm/PositionIndicator.py b/TamTamEdit.activity/Edit/rm/PositionIndicator.py
new file mode 100644
index 0000000..aadc4f4
--- /dev/null
+++ b/TamTamEdit.activity/Edit/rm/PositionIndicator.py
@@ -0,0 +1,47 @@
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+#----------------------------------------------------------------------
+# A verical bar used to show the current point in time on a page
+# TODO: modify this class to change the current point in time
+# on click and drag
+#----------------------------------------------------------------------
+class PositionIndicator( gtk.DrawingArea ):
+ #-----------------------------------
+ # initialization
+ #-----------------------------------
+ def __init__( self, trackIDs, selectedTrackIDs, mutedTrackIDs ):
+ gtk.DrawingArea.__init__( self )
+
+ self.trackIDs = trackIDs
+ self.selectedTrackIDs = selectedTrackIDs
+ self.mutedTrackIDs = mutedTrackIDs
+
+ self.connect( "expose-event", self.draw )
+
+ def draw( self, drawingArea, event ):
+ indicatorSize = self.get_allocation()
+ trackHeight = indicatorSize.height / len( self.trackIDs )
+
+ context = drawingArea.window.cairo_create()
+
+ trackIndex = 0
+ for trackID in self.trackIDs:
+ height = trackIndex * trackHeight
+
+ context.move_to( 0, height )
+ context.rel_line_to( indicatorSize.width, 0 )
+ context.rel_line_to( 0, height + trackHeight )
+ context.rel_line_to( -indicatorSize.width, 0 )
+ context.close_path()
+
+ if trackID not in self.mutedTrackIDs:
+ context.set_source_rgb( 0, 0, 0 ) #black
+ else:
+ context.set_source_rgb( 0.6, 0.6, 0.6 ) #grey
+
+ context.fill_preserve()
+ context.stroke()
+
+ trackIndex += 1 \ No newline at end of file
diff --git a/TamTamEdit.activity/Edit/rm/TrackView.py b/TamTamEdit.activity/Edit/rm/TrackView.py
new file mode 100644
index 0000000..0b66abd
--- /dev/null
+++ b/TamTamEdit.activity/Edit/rm/TrackView.py
@@ -0,0 +1,263 @@
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+from Framework.Constants import Constants
+from GUI.GUIConstants import GUIConstants
+
+from BackgroundView import SELECTNOTES
+from NoteView import NoteView
+
+
+#----------------------------------------------------------------------
+# This view class is used to show the contents of a NoteTrack
+# i.e. a Collection of Note objects
+#----------------------------------------------------------------------
+class TrackView:
+ #-----------------------------------
+ # initialization functions
+ #-----------------------------------
+ def __init__( self, trackID, beatsPerPageAdjustment ):
+ self.trackID = trackID
+ self.beatsPerPageAdjustment = beatsPerPageAdjustment
+ self.noteViews = []
+ self.posOffset = (0,0)
+ self.selectedNotes = []
+
+ def getID( self ):
+ return self.trackID
+
+ #-----------------------------------
+ # modification methods
+ #-----------------------------------
+ def setNotes( self, notes ):
+ self.clearNotes()
+
+ lineW = self.getBorderWidth()
+
+ for note in notes:
+ noteView = NoteView( note, self, self.beatsPerPageAdjustment )
+ self.noteViews.append( noteView )
+ noteView.setPositionOffset( (self.posOffset[0]+lineW, self.posOffset[1]+lineW ) )
+
+ self.updateNoteTransforms()
+
+ def clearNotes( self ):
+ del self.noteViews
+ self.noteViews = []
+ self.selectedNotes = []
+
+ def selectNotes( self, mode, which ):
+ if mode == SELECTNOTES.ALL:
+ for note in self.noteViews: note.setSelected( True )
+ self.selectedNotes = self.noteViews[:]
+ elif mode == SELECTNOTES.NONE:
+ for note in self.noteViews: note.setSelected( False )
+ self.selectedNotes = []
+ elif mode == SELECTNOTES.ADD:
+ for note in which:
+ if note.setSelected( True ):
+ self.selectedNotes.insert( 0, note )
+ elif mode == SELECTNOTES.REMOVE:
+ for note in which:
+ if note.setSelected( False ):
+ self.selectedNotes.remove( note )
+ elif mode == SELECTNOTES.EXCLUSIVE:
+ for note in self.noteViews:
+ if note in which:
+ if note.setSelected( True ):
+ self.selectedNotes.insert( 0, note )
+ else:
+ if note.setSelected( False ):
+ self.selectedNotes.remove( note )
+
+ def updateDragLimits( self, dragLimits ):
+ if not len(self.selectedNotes): return # no selected notes here
+
+ leftBound = 0
+ maxRightBound = round( self.beatsPerPageAdjustment.value, 0 ) * Constants.TICKS_PER_BEAT
+ last = len(self.noteViews)-1
+ for i in range(0,last):
+ if not self.noteViews[i].getSelected():
+ leftBound = self.noteViews[i].getEndTick()
+ else:
+ if not self.noteViews[i+1].getSelected():
+ rightBound = min( self.noteViews[i+1].getStartTick(), maxRightBound )
+ widthBound = rightBound
+ else:
+ rightBound = maxRightBound
+ widthBound = min( self.noteViews[i+1].getStartTick(), maxRightBound )
+ self.noteViews[i].updateDragLimits( dragLimits, leftBound, rightBound, widthBound )
+ if self.noteViews[last].getSelected():
+ self.noteViews[last].updateDragLimits( dragLimits, leftBound, maxRightBound, maxRightBound )
+
+ def getNotesByBar( self, beatCount, startX, stopX ):
+ beatWidth = self.getBeatLineSpacing( beatCount )
+ beatStart = self.getBeatLineStart()
+ while beatStart+beatWidth <= startX:
+ beatStart += beatWidth
+ beatStop = beatStart + beatWidth
+ while beatStop+beatWidth < stopX:
+ beatStop += beatWidth
+
+ notes = []
+ for note in self.noteViews:
+ if note.checkX( beatStart, beatStop ):
+ notes.insert(0,note)
+ return notes
+
+ #-----------------------------------
+ # event methods
+ #-----------------------------------
+
+ def handleButtonPress( self, emitter, event ):
+ eX = event.x - self.posOffset[0]
+ eY = event.y - self.posOffset[1]
+ if eX < 0 or eX > self.width or eY < 0 or eY > self.height:
+ return False
+
+ for note in self.noteViews:
+ handled = note.handleButtonPress( emitter, event )
+ if handled: return handled
+
+ return False
+
+ def handleButtonRelease( self, emitter, event, buttonPressCount ):
+ eX = event.x - self.posOffset[0]
+ eY = event.y - self.posOffset[1]
+
+ if eX < 0 or eX > self.width or eY < 0 or eY > self.height:
+ return False
+
+ if event.button == 1:
+ if buttonPressCount == 1: emitter.toggleTrack( self.trackID, False )
+ else: emitter.toggleTrack( self.trackID, True )
+
+ return True
+
+ def handleMarqueeSelect( self, emitter, start, stop ):
+ intersectionY = [ max(start[1],self.posOffset[1]), min(stop[1],self.posOffset[1]+self.height) ]
+ if intersectionY[0] > intersectionY[1]:
+ return False
+
+ intersectionX = [ max(start[0],self.posOffset[0]), min(stop[0],self.posOffset[0]+self.width) ]
+ if intersectionX[0] > intersectionX[1]:
+ return False
+
+
+ hits = []
+ for note in self.noteViews:
+ hit = note.handleMarqueeSelect( emitter,
+ [ intersectionX[0], intersectionY[0] ], \
+ [ intersectionX[1], intersectionY[1] ] )
+ if hit: hits.insert(0,note)
+
+ if len(hits): return hits
+
+ return False
+
+ def noteDrag( self, emitter, dx, dy, dw ):
+ for note in self.selectedNotes:
+ note.noteDrag( emitter, dx, dy, dw )
+
+ def doneNoteDrag( self, emitter ):
+ for note in self.selectedNotes:
+ note.doneNoteDrag( emitter )
+
+ #-----------------------------------
+ # drawing methods
+ #-----------------------------------
+
+ def getBorderWidth( self ): #should return a constant value, otherwise we have to recalculate sizing and positioning everyframe!
+ return GUIConstants.BORDER_SIZE
+
+ def getBeatLineWidth( self ):
+ return GUIConstants.BEAT_LINE_SIZE #should return a constant value, otherwise we have to recalculate sizing and positioning everyframe!
+
+ def getBeatLineSpacing( self, beatCount ):
+ return (self.width - 2*self.getBorderWidth() + self.getBeatLineWidth())/beatCount
+
+ def getBeatLineStart( self ):
+ return self.posOffset[0] + self.getBorderWidth() - self.getBeatLineWidth()/2.0
+
+ def setPositionOffset( self, offset ):
+ self.posOffset = offset
+
+ lineW = self.getBorderWidth()
+ for note in self.noteViews:
+ note.setPositionOffset( ( self.posOffset[0]+lineW, self.posOffset[1]+lineW ) )
+
+ def draw( self, context, beatCount, selected ):
+ #if selected: lineW = GUIConstants.SELECTED_BORDER_SIZE
+ #else: lineW = GUIConstants.BORDER_SIZE
+ lineW = self.getBorderWidth()
+ context.set_line_width( lineW )
+ lineWDIV2 = lineW/2.0
+
+ context.move_to( self.posOffset[0] + lineWDIV2, self.posOffset[1] + lineWDIV2 )
+ context.rel_line_to( self.width - lineW, 0 )
+ context.rel_line_to( 0, self.height - lineW )
+ context.rel_line_to( -self.width + lineW, 0 )
+ context.close_path()
+
+ #draw the background
+ context.set_source_rgb( 0.75, 0.75, 0.75 )
+ context.fill_preserve()
+
+ #draw the border
+ if selected: context.set_source_rgb( 1, 1, 1 )
+ else: context.set_source_rgb( 0, 0, 0 )
+ context.stroke()
+
+ #draw the beat lines
+ beatLineWidth = self.getBeatLineWidth()
+ context.set_line_width( beatLineWidth )
+ beatWidth = self.getBeatLineSpacing( beatCount )
+ beatStart = self.getBeatLineStart()
+ context.set_source_rgb( 0, 0, 0 )
+ for i in range(1,beatCount):
+ context.move_to( beatStart + i*beatWidth, self.posOffset[1] + lineW )
+ context.rel_line_to( 0, self.height - 2*lineW )
+ context.stroke()
+
+ #draw the notes
+ for note in self.noteViews:
+ note.draw( context )
+
+ #-----------------------------------
+ # sizing methods
+ #-----------------------------------
+
+ def updateNoteTransforms( self ):
+ width = self.width - 2*self.getBorderWidth()
+ height = self.height - 2*self.getBorderWidth() # adjust for actual note drawing area
+ for noteView in self.noteViews:
+ noteView.updateTransform( (width, height) )
+
+ def set_size_request( self, width, height ):
+ self.width = width
+ self.height = height
+ self.updateNoteTransforms()
+
+
+#unused for now...
+class NoteViewPool:
+ def __init__( self, parentContainer, beatsPerPageAdjustment ):
+ self.parentContainer = parentContainer
+ self.beatsPerPageAdjustment = beatsPerPageAdjustment
+ self.pool = []
+
+ def addNoteView( self, noteView ):
+ #noteView.hide()
+ self.pool.append( noteView )
+
+ def addNoteViews( self, noteViews ):
+ for noteView in noteViews:
+ self.addNoteView( noteView )
+
+ def getNoteView( self ):
+ poolSize = len( pool )
+ if poolSize != 0:
+ return pool.pop( poolSize )
+
+ return NoteView( None, self.parentContainer, self.beatsPerPageAdjustment )
diff --git a/TamTamEdit.activity/Edit/rm/TunePageView.py b/TamTamEdit.activity/Edit/rm/TunePageView.py
new file mode 100644
index 0000000..501504f
--- /dev/null
+++ b/TamTamEdit.activity/Edit/rm/TunePageView.py
@@ -0,0 +1,17 @@
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+from PageView import PageView
+
+class TunePageView( PageView ):
+ def __init__( self, pageID, tuneIndex, selectPageCallback, selected = False ):
+ PageView.__init__( self, pageID, selectPageCallback, selected )
+
+ self.pageIndex = tuneIndex
+
+ def handleButtonPress( self, widget, data ):
+ self.selectPageCallback( self.tuneIndex )
+
+ def getData( self, widget, context, selection, targetType, eventTime ):
+ return selection.set( gtk.gdk.SELECTION_PRIMARY, 32, "t %d %d" % (self.pageID,self.pageIndex) )
diff --git a/TamTamEdit.activity/Edit/rm/TuneView.py b/TamTamEdit.activity/Edit/rm/TuneView.py
new file mode 100644
index 0000000..63cf468
--- /dev/null
+++ b/TamTamEdit.activity/Edit/rm/TuneView.py
@@ -0,0 +1,123 @@
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+from GUI.GUIConstants import GUIConstants
+from GUI.Core.TunePageView import TunePageView
+
+def swap(l,i,j):
+ e = l[i]
+ l[i] = l[j]
+ l[j] = e
+
+class TuneView( gtk.ScrolledWindow ):
+
+ NO_PAGE = -1
+
+ def _page_width(self):
+ return self.pageContainer.get_allocation().width / GUIConstants.NUMBER_OF_PAGE_BANK_COLUMNS
+
+ def __init__( self, selectPageCallback ):
+ gtk.ScrolledWindow.__init__( self )
+
+ #selectPageCallback(): currently connected to pagePlayer.setPlayTune, which skips to a given page of the tune.
+ self.selectPageCallback = selectPageCallback
+ self.selectedPageIndex = self.NO_PAGE
+
+ self.set_policy( gtk.POLICY_ALWAYS, gtk.POLICY_AUTOMATIC )
+ self.set_placement( gtk.CORNER_TOP_LEFT )
+
+ #self.pageViews: list of our custom PageView widgets
+ self.pageViews = []
+ self.pageContainer = gtk.HBox( False )
+ self.add_with_viewport( self.pageContainer )
+
+ #the old part
+ self.pageContainer.drag_dest_set( gtk.DEST_DEFAULT_ALL,
+ [ ( "bank page", gtk.TARGET_SAME_APP, 10 ),
+ ( "tune page", gtk.TARGET_SAME_APP, 11 )],
+ gtk.gdk.ACTION_COPY|gtk.gdk.ACTION_MOVE )
+
+ self.pageContainer.connect( "drag_data_received", self.dragDataReceived )
+
+ #private method: called by gtk when pages get dragged onto the tune-view
+ def dragDataReceived( self, widget, context, x, y, selectionData, info, time ):
+ print 'dragDataReceived: ', selectionData.data, info, selectionData.data
+ recv = selectionData.data.split()
+ if recv[0] == 'p':
+ pageId = int( recv[1] )
+ self.addPage( pageId, min( x / self._page_width(), len( self.pageViews )) )
+ elif recv[0] == 't':
+ self.moveSelectedPage( min( x / self._page_width(), len( self.pageViews ) -1))
+ else:
+ raise 'ERROR'
+
+ #public method: called by MainWindow on file load
+ def syncFromPagePlayer(self):
+ raise 'never call this'
+ map( lambda pv:pv.destroy(), self.pageViews )
+ self.pageViews = []
+ tunePages = self.tunePagesCallback()
+ for i in range( len(tunePages)):
+ self.addPage( tunePages[i], i, False)
+
+
+ def addPage( self, pageID, position ):
+ #create a new widget
+ pageView = TunePageView( pageID, position, self.selectPage )
+ self.pageViews.insert( position, pageView )
+ self.pageContainer.pack_start( pageView, False )
+ self.pageContainer.reorder_child( pageView, position )
+
+ pageView.set_size_request( self.pageContainer.get_allocation().width / GUIConstants.NUMBER_OF_PAGE_BANK_COLUMNS,
+ GUIConstants.PAGE_HEIGHT )
+ pageView.show()
+
+ for i in range( len(self.pageViews)) :
+ self.pageViews[i].tuneIndex = i
+ self.pageViews[i].setSelected( i == position)
+ self.selectPageCallback( pageID, position )
+ pageView.drag_source_set(
+ gtk.gdk.BUTTON1_MASK,
+ [ ( "tune page", gtk.TARGET_SAME_APP, 11 ) ],
+ gtk.gdk.ACTION_COPY|gtk.gdk.ACTION_MOVE )
+
+ def moveSelectedPage( self, position):
+ self.pageContainer.reorder_child( self.pageViews[self.selectedPageIndex], position )
+ swap( self.pageViews, self.selectedPageIndex, position )
+ self.selectedPageIndex = position
+ for i in range( len(self.pageViews) ) :
+ self.pageViews[i].tuneIndex = i
+ self.pageViews[i].setSelected( i == position)
+
+ def removePage( self, position ):
+ pv = self.pageViews[position]
+ self.pageViews[position:position+1] = []
+ if self.selectedPageIndex >= position : self.selectedPageIndex -= 1
+ for i in range( len(self.pageViews)) :
+ self.pageViews[i].tuneIndex = i
+ self.pageViews[i].setSelected( i == position)
+ self.pageContainer.remove(pv)
+ del pv
+
+ def selectPage( self, selectedPageIndex, invokeCallback = True ):
+ if selectedPageIndex >= len( self.pageViews ): selectedPageIndex = self.NO_PAGE
+ self.selectedPageIndex = selectedPageIndex
+ if selectedPageIndex == self.NO_PAGE:
+ for pv in self.pageViews: pv.setSelected(False)
+ if invokeCallback: self.selectPageCallback( -1, -1 )
+ else:
+ if not self.pageViews[ selectedPageIndex ].selected:
+ map( lambda pv: pv.setSelected( pv.tuneIndex == selectedPageIndex), self.pageViews)
+ if invokeCallback: self.selectPageCallback( self.pageViews[selectedPageIndex].pageID, selectedPageIndex )
+
+ def set_size_request( self, width, height ):
+ gtk.ScrolledWindow.set_size_request( self, width, height )
+ map( lambda pv: pv.set_size_request( width / GUIConstants.NUMBER_OF_PAGE_BANK_COLUMNS, GUIConstants.PAGE_HEIGHT ), self.pageViews)
+
+ def getPageId( self, idx):
+ return self.pageViews[idx].pageID
+
+ def getTune( self ):
+ return [ p.pageID for p in self.pageViews ]
+