diff options
author | jaberg <james@localhost.localdomain> | 2007-01-07 21:24:04 (GMT) |
---|---|---|
committer | jaberg <james@localhost.localdomain> | 2007-01-07 21:24:04 (GMT) |
commit | 1becac24dfa6bd0cee4ae46f4c0b8630bfbb6269 (patch) | |
tree | 70d602342d546fd8c268143b54d46b8ca580a7ed /Edit/NoteInterface.py | |
parent | 2a940a71469b2b5964e8deab3ed6db0254424671 (diff) |
unify_edit init
Diffstat (limited to 'Edit/NoteInterface.py')
-rw-r--r-- | Edit/NoteInterface.py | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/Edit/NoteInterface.py b/Edit/NoteInterface.py new file mode 100644 index 0000000..93ffed3 --- /dev/null +++ b/Edit/NoteInterface.py @@ -0,0 +1,279 @@ +import pygtk +pygtk.require( '2.0' ) +import gtk + +from Framework.Constants import Constants +from GUI.GUIConstants import GUIConstants + +class NoteInterface: + + def __init__( self, parent, page, track, note, pitch, onset, duration, amplitude): + self.parent = parent + self.page = page + self.track = track + self.note = note # note id, not csnote! + + self.x = 0 + self.y = 0 + self.width = 1 + self.height = GUIConstants.NOTE_HEIGHT + + self.updateParams( pitch, onset, duration, amplitude ) + + self.selected = False + self.potentialDeselect = False + + self.lastDragO = 0 + self.lastDragP = 0 + self.lastDragD = 0 + + def destroy( self ): + # nothing to do? + return + + def updateParams( self, pitch, onset, duration, amplitude): + self.pitch = pitch + self.onset = onset + self.duration = duration + self.end = onset + duration + + self.amplitude = amplitude + self.bgColour = 1 - ( ( self.amplitude * 0.7 ) + 0.3 ) + + self.updateTransform( False ) + + def getId( self ): + return self.note + + def getStartTick( self ): + return self.onset + + def getEndTick( self ): + return self.end + + def testOnset( self, start, stop ): + return self.onset >= start and self.onset < stop + + def updateTransform( self, onlyX ): + if self.page == self.parent.curPage: + oldX = self.x + oldY = self.y + oldEndX = self.x + self.width + + origin = self.parent.getTrackOrigin( self.track ) + self.x = self.parent.ticksToPixels( self.onset ) + self.width = self.parent.ticksToPixels( self.end ) - self.x + self.x += origin[0] + if not onlyX: + self.y = self.parent.pitchToPixels( self.pitch ) + origin[1] + + if self.page == self.parent.curPage: + x = min( self.x, oldX ) + y = min( self.y, oldY ) + endx = max( self.x + self.width, oldEndX ) + endy = max( self.y, oldY ) + self.height + self.parent.invalidate_rect( x, y, endx-x, endy-y ) + + def updateDragLimits( self, dragLimits, leftBound, rightBound, widthBound ): + left = leftBound - self.onset + right = rightBound - self.duration - self.onset + up = Constants.MAXIMUM_PITCH - self.pitch + down = Constants.MINIMUM_PITCH - self.pitch + short = Constants.MINIMUM_NOTE_DURATION - self.duration + long = widthBound - self.duration - self.onset + + if dragLimits[0][0] < left: dragLimits[0][0] = left + if dragLimits[0][1] > right: dragLimits[0][1] = right + if dragLimits[1][0] < down: dragLimits[1][0] = down + if dragLimits[1][1] > up: dragLimits[1][1] = up + 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.onset + self.basePitch = self.pitch + self.baseDuration = self.duration + + def updateSampleNote( self, pitch ): + return + + def clearSampleNote( self ): + return + + #======================================================= + # Events + + # handleButtonPress returns: + # -2, not a hit but there was X overlap + # -1, event occurs before us so don't bother checking any later notes + # 0, event didn't hit + # 1, event was handled + def handleButtonPress( self, emitter, event ): + eX = event.x - self.x + if eX < 0: + return -1 # event occurs before us, no point in checking further + if eX > self.width: + return 0 # no X overlap + + eY = event.y - self.y + if eY < 0 or eY > self.height: + return -2 # not a hit, but it was in our X range + + if event.button == 3: + print "Show some note parameters!?!" + #self.noteParameters = NoteParametersWindow( self.note, self.getNoteParameters ) + return 1 # handled + + if event.type == gtk.gdk._2BUTTON_PRESS: # select bar + self.potentialDeselect = False + start = 0 + check = self.onset - Constants.TICKS_PER_BEAT + while start <= check: start += Constants.TICKS_PER_BEAT + stop = start + Constants.TICKS_PER_BEAT + check += self.duration + while stop < check: stop += Constants.TICKS_PER_BEAT + emitter.selectNotesByBar( self.track, start, stop ) + elif event.type == gtk.gdk._3BUTTON_PRESS: # select track + self.potentialDeselect = False + emitter.selectNotesByTrack( self.track ) + else: + if self.getSelected(): # we already selected, might want to delected + self.potentialDeselect = True + else: + emitter.selectNotes( { self.track: [ self ] } ) + self.updateSampleNote( self.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 ) + + return 1 + + def handleButtonRelease( self, emitter, event, buttonPressCount ): + + if self.potentialDeselect: + self.potentialDeselect = False + emitter.deselectNotes( { self.track: [ self ] } ) + + self.clearSampleNote() + + emitter.doneCurrentAction() + + return True + + def noteDrag( self, emitter, do, dp, dd ): + self.potentialDeselect = False + + if do != self.lastDragO: + self.lastDragO = do + self.onset = self.baseOnset + do + self.end = self.onset + self.duration + + if dp != self.lastDragP: + self.lastDragP = dp + newPitch = self.basePitch + dp + self.pitch = newPitch + self.updateSampleNote( newPitch ) + + if dd != self.lastDragD: + self.lastDragD = dd + self.duration = self.baseDuration + dd + self.end = self.onset + self.duration + + self.updateTransform( False ) + + return (self.note, self.pitch, self.onset, self.duration) + + def doneNoteDrag( self, emitter ): + self.baseOnset = self.onset + self.basePitch = self.pitch + self.baseDuration = self.duration + + self.lastDragO = 0 + self.lastDragP = 0 + self.lastDragD = 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 + + # updateTooltip returns: + # -2, not a hit but there was X overlap + # -1, event occurs before us so don't bother checking any later notes + # 0, event didn't hit + # 1, event was handled + def updateTooltip( self, emitter, event ): + eX = event.x - self.x + if eX < 0: + return -1 # event occurs before us, no point in checking further + if eX > self.width: + return 0 # no X overlap + + eY = event.y - self.y + if eY < 0 or eY > self.height: + return -2 # not a hit, but it was in our X range + + percent = eX/self.width + if percent < 0.3: emitter.setCursor("drag-onset") + elif percent > 0.7: emitter.setCursor("drag-duration") + else: emitter.setCursor("drag-pitch") + + return 1 # we handled it + + #======================================================= + # Selection + + def setSelected( self, state ): + if self.selected != state: + self.selected = state + if self.page == self.parent.curPage: + self.parent.invalidate_rect( self.x, self.y, self.width, self.height ) + return True # state changed + return False # state is the same + + def getSelected( self ): + return self.selected + + #======================================================= + # Selection + + def draw( self, context, startX, stopX ): + if stopX < self.x: return False # we don't need to draw and no one after us will draw + if startX > self.x + self.width: return True # we don't need to draw, but maybe a later note does + + + if False: + context.set_line_width( GUIConstants.NOTE_BORDER_SIZE ) + + context.move_to( self.x + GUIConstants.NOTE_BORDER_SIZE_DIV2, self.y + GUIConstants.NOTE_BORDER_SIZE_DIV2 ) + context.rel_line_to( self.width - GUIConstants.NOTE_BORDER_SIZE, 0 ) + context.rel_line_to( 0, self.height - GUIConstants.NOTE_BORDER_SIZE ) + context.rel_line_to( -self.width + GUIConstants.NOTE_BORDER_SIZE, 0 ) + context.close_path() + + context.rectangle(self.x, self.y, self.width, self.height ) + + #background + context.set_source_rgb( self.bgColour, self.bgColour, self.bgColour ) + #context.fill_preserve() + context.fill() + return True + + #border + if self.selected: context.set_source_rgb( 1, 1, 1 ) + else: context.set_source_rgb( 0, 0, 0 ) + context.stroke() + + return True # we drew something + |