|  | @@ -87,6 +87,7 @@ export class MusicPartManagerIterator {
 | 
	
		
			
				|  |  |      private currentBpm: number;
 | 
	
		
			
				|  |  |      private activeDynamicExpressions: AbstractExpression[] = [];
 | 
	
		
			
				|  |  |      private activeTempoExpression: MultiTempoExpression;
 | 
	
		
			
				|  |  | +    public SkipInvisibleNotes: boolean = true;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public get EndReached(): boolean {
 | 
	
		
			
				|  |  |          return this.endReached;
 | 
	
	
		
			
				|  | @@ -247,9 +248,33 @@ export class MusicPartManagerIterator {
 | 
	
		
			
				|  |  |      public currentPlaybackSettings(): PlaybackSettings {
 | 
	
		
			
				|  |  |         return this.musicSheet.SheetPlaybackSetting;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // move to previous
 | 
	
		
			
				|  |  | +    public moveToPrevious(): void {
 | 
	
		
			
				|  |  | +        // this.forwardJumpOccurred = this.backJumpOccurred = false;
 | 
	
		
			
				|  |  | +        if (this.frontReached) { return; }
 | 
	
		
			
				|  |  | +        if (this.currentVoiceEntries) {
 | 
	
		
			
				|  |  | +            this.currentVoiceEntries = [];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (this.currentTimeStamp.RealValue < this.musicSheet.SourceMeasures.length) {
 | 
	
		
			
				|  |  | +            this.recursiveMoveBack();
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public moveToPreviousVisibleVoiceEntry(notesOnly: boolean): void {
 | 
	
		
			
				|  |  | +        while (!this.frontReached) {
 | 
	
		
			
				|  |  | +            this.moveToPrevious();
 | 
	
		
			
				|  |  | +            if (this.checkEntries(notesOnly)) {
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      public moveToNext(): void {
 | 
	
		
			
				|  |  |          this.forwardJumpOccurred = this.backJumpOccurred = false;
 | 
	
		
			
				|  |  |          if (this.endReached) { return; }
 | 
	
		
			
				|  |  | +        if (this.frontReached) { this.frontReached = false; }
 | 
	
		
			
				|  |  |          if (this.currentVoiceEntries) {
 | 
	
		
			
				|  |  |              this.currentVoiceEntries.length = 0;
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -516,6 +541,33 @@ export class MusicPartManagerIterator {
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private recursiveMoveBack(): void {
 | 
	
		
			
				|  |  | +       if (this.currentVoiceEntryIndex > 0 ) {
 | 
	
		
			
				|  |  | +            this.currentVoiceEntryIndex--;
 | 
	
		
			
				|  |  | +            const currentContainer: VerticalSourceStaffEntryContainer = this.currentMeasure.VerticalSourceStaffEntryContainers[this.currentVoiceEntryIndex];
 | 
	
		
			
				|  |  | +            this.currentVoiceEntries = this.getVoiceEntries(currentContainer);
 | 
	
		
			
				|  |  | +            this.currentVerticalContainerInMeasureTimestamp = currentContainer.Timestamp;
 | 
	
		
			
				|  |  | +            this.currentTimeStamp = Fraction.plus(this.currentMeasure.AbsoluteTimestamp, this.currentVerticalContainerInMeasureTimestamp);
 | 
	
		
			
				|  |  | +            this.activateCurrentDynamicOrTempoInstructions();
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else if (this.currentVoiceEntryIndex === 0  && this.currentMeasureIndex !== 0) {
 | 
	
		
			
				|  |  | +            const m: SourceMeasure = this.musicSheet.SourceMeasures[this.currentMeasureIndex-1];
 | 
	
		
			
				|  |  | +            this.currentMeasureIndex--;
 | 
	
		
			
				|  |  | +            this.currentMeasure = this.musicSheet.SourceMeasures[this.currentMeasureIndex];
 | 
	
		
			
				|  |  | +            const currentContainer: VerticalSourceStaffEntryContainer = m.VerticalSourceStaffEntryContainers[m.VerticalSourceStaffEntryContainers.length-1];
 | 
	
		
			
				|  |  | +            this.currentVoiceEntries = this.getVoiceEntries(currentContainer);
 | 
	
		
			
				|  |  | +            this.currentVerticalContainerInMeasureTimestamp = currentContainer.Timestamp;
 | 
	
		
			
				|  |  | +            this.currentVoiceEntryIndex = m.VerticalSourceStaffEntryContainers.length-1;
 | 
	
		
			
				|  |  | +            this.currentTimeStamp = currentContainer.Timestamp;
 | 
	
		
			
				|  |  | +            this.activateCurrentDynamicOrTempoInstructions();
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // we reached the beginning
 | 
	
		
			
				|  |  | +        this.frontReached = true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      private recursiveMove(): void {
 | 
	
		
			
				|  |  |          this.currentVoiceEntryIndex++; // TODO handle hidden part: skip hidden voice if requested by parameter
 | 
	
		
			
				|  |  |          if (this.currentVoiceEntryIndex === 0) {
 | 
	
	
		
			
				|  | @@ -570,6 +622,16 @@ export class MusicPartManagerIterator {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      private getVisibleEntries(entry: VoiceEntry, visibleEntries: VoiceEntry[]): void {
 | 
	
		
			
				|  |  |          if (entry.ParentVoice.Visible) {
 | 
	
		
			
				|  |  | +            let anyNoteVisible: boolean = false;
 | 
	
		
			
				|  |  | +            for (const note of entry.Notes) {
 | 
	
		
			
				|  |  | +                if (note.PrintObject) {
 | 
	
		
			
				|  |  | +                    anyNoteVisible = true;
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if (!anyNoteVisible && this.SkipInvisibleNotes) {
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |              visibleEntries.push(entry);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 |