public SequencerViewModel(Timeline model) { this.model = model; ActionManager = new GuiLabs.Undo.ActionManager(); SelectedBlocks = new ObservableCollection <BlockViewModel>(); SelectionData = new SelectionProperties(this); Tracks = model.Tracks.Select(g => new TrackViewModel(this, g)); MusicSegments = model.MusicSegments.Select(seg => new MusicSegmentViewModel(this, seg)); AllBlocks = model.Blocks.Select(b => BlockViewModel.FromModel(this, b)); if (Tracks.Count > 0) { SelectedTrack = Tracks[0]; } ActiveMusicSegment = MusicSegments[model.DefaultMusicSegment.GetIndex()]; Playback = new PlaybackViewModel(this); Visualization = new VisualizationViewModel(this); Notes = new NotesViewModel(this); if (model.MusicFileName != null) { Playback.LoadFileAsync(model.MusicFileName).Forget(); } Action <BlockViewModel> fn_SubscribeToBlock = bvm => ForwardPropertyEvents(nameof(bvm.EndTimeOccupied), bvm, nameof(TimelineLength)); AllBlocks.ToList().ForEach(fn_SubscribeToBlock); AllBlocks.CollectionChanged += (_, e) => { if (e.NewItems != null) { e.NewItems.Cast <BlockViewModel>().ToList().ForEach(fn_SubscribeToBlock); } Notify(nameof(TimelineLength)); }; ForwardPropertyEvents(nameof(PipetteTarget), this, nameof(IsPipetteActive)); ForwardPropertyEvents(nameof(CursorPosition), this, nameof(CursorPixelPosition), nameof(CursorPixelPositionOnViewport)); ForwardPropertyEvents(nameof(TimePixelScale), this, nameof(CursorPixelPosition), nameof(CursorPixelPositionOnViewport), nameof(CurrentViewLeftPositionTime), nameof(CurrentViewRightPositionTime), nameof(TimelineWidth), nameof(GridInterval)); ForwardPropertyEvents(nameof(ActiveMusicSegment), this, nameof(GridInterval)); ForwardPropertyEvents(nameof(Playback.MusicDuration), Playback, nameof(TimelineLength)); ForwardPropertyEvents(nameof(TimelineLength), this, nameof(TimelineWidth)); ForwardCollectionEvents(SelectedBlocks, nameof(CanConvertToColor), nameof(CanConvertToRamp), nameof(CanConvertToAutoDeduced), nameof(ConvertAutoDeduceGestureText)); Tracks.CollectionChanged += (_, e) => { foreach (var b in AllBlocks) { b.OnTracksCollectionChanged(); } }; // Disable pipette whenever the selection is modified. SelectedBlocks.CollectionChanged += (_, __) => PipetteTarget = null; }
public void InsertBlock(string type) { // inherit color and tracks from previous block, if applicable GloColor prevColor = GloColor.White; Track[] prevTracks = { _selectedTrack.GetModel() }; if (EnableSmartInsert) { Func <BlockViewModel, bool> fnIsBlockApplicable = (bl => bl.StartTime < CursorPosition && (bl is ColorBlockViewModel || bl is RampBlockViewModel)); var prevBlocks = ((IEnumerable <BlockViewModel>)_selectedTrack.Blocks).Where(fnIsBlockApplicable); if (prevBlocks.Any()) { BlockViewModel prevBlock = prevBlocks.MaxBy(bl => bl.EndTimeOccupied); // inherit color if (prevBlock is ColorBlockViewModel) { prevColor = ((ColorBlockViewModel)prevBlock).GetModel().Color; } else { prevColor = ((RampBlockViewModel)prevBlock).GetModel().EndColor; } // inherit tracks, but only if the last block on the selected track is also the last block on all other tracks of the block bool lastOfAllTracks = prevBlock.GetModel().Tracks.All(t => t.Blocks .Select(bl => BlockViewModel.FromModel(this, bl)) .Where(fnIsBlockApplicable) .MaxBy(bl => bl.EndTimeOccupied) == prevBlock); if (lastOfAllTracks) { prevTracks = prevBlock.GetModel().Tracks.ToArray(); } } } Block b; switch (type) { case "color": b = new ColorBlock(model, prevTracks) { Color = prevColor }; break; case "ramp": b = new RampBlock(model, prevTracks) { StartColor = prevColor, EndColor = (prevColor == GloColor.White ? GloColor.Black : GloColor.White) }; break; default: throw new ArgumentException("unsupported block type " + type); } b.SegmentContext = ActiveMusicSegment.GetModel(); b.StartTime = CursorPosition; b.Duration = GridInterval; ActionManager.RecordAdd(model.Blocks, b); }
protected GroupBlockViewModel(SequencerViewModel sequencer, Model.GroupBlock model, string typeLabel) : base(sequencer, model, typeLabel) { this.model = model; _children = model.Children.Select(b => BlockViewModel.FromModel(sequencer, b)); }