private static void DrawNoteGroupOutline(ScoreRendererBase renderer, Quadrangle noteGroupBounds, NoteOrRest element) { renderer.DrawLine(noteGroupBounds.NW, noteGroupBounds.NE, new Pen(Color.Red), element); renderer.DrawLine(noteGroupBounds.NE, noteGroupBounds.SE, new Pen(Color.Red), element); renderer.DrawLine(noteGroupBounds.SE, noteGroupBounds.SW, new Pen(Color.Red), element); renderer.DrawLine(noteGroupBounds.SW, noteGroupBounds.NW, new Pen(Color.Red), element); }
/// <summary> /// Draws of performs additional logic at slur end /// </summary> /// <param name="renderer">Score renderer</param> /// <param name="slur">Slur</param> /// <param name="element">Element with a slur</param> /// <param name="notePositionY">Y position of element with a slur</param> /// <param name="slurStartInfo">Information about slur start point</param> /// <param name="slurPlacement">Information about slur placement</param> protected override void ProcessSlurEnd(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY, SlurInfo slurStartInfo, VerticalPlacement slurPlacement) { Point endPoint; var noteheadWidth = element.GetNoteheadWidthPx(renderer); if (slurStartInfo.StartPlacement == VerticalPlacement.Above) { var xShiftConcerningStemDirectionEnd = noteheadWidth / 2; bool hasFlagOrBeam = element.BaseDuration.Denominator > 4; endPoint = new Point(scoreService.CursorPositionX + xShiftConcerningStemDirectionEnd, (element.StemDirection == VerticalDirection.Up ? element.StemEndLocation.Y + (hasFlagOrBeam ? -2 : 0) : notePositionY - 7)); } else if (slurStartInfo.StartPlacement == VerticalPlacement.Below) { var xShiftConcerningStemDirectionEnd = noteheadWidth / 2; endPoint = new Point(scoreService.CursorPositionX + xShiftConcerningStemDirectionEnd, notePositionY + 5); } else { throw new Exception("Unsupported placement type."); } var slurHeight = DetermineSlurHeight(element, slur, slurStartInfo, endPoint); for (int i = 0; i < 3; i++) //Draw a few curves one by one to simulate a curve with variable thickness. It will be replaced by a path in future releases. { var controlPoints = GetBezierControlPoints(slurStartInfo.StartPoint, endPoint, slurStartInfo.StartPlacement, slurHeight + i); renderer.DrawBezier(slurStartInfo.StartPoint, controlPoints.Item1, controlPoints.Item2, endPoint, element); } //DrawSlurFrame(renderer, startPoint, controlPoints.Item1, controlPoints.Item2, endPoint, element); }
/// <summary> /// Draws a slur /// </summary> /// <param name="renderer"></param> /// <param name="slur"></param> /// <param name="element"></param> /// <param name="notePositionY"></param> public void Draw(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY) { VerticalPlacement slurPlacement; if (slur.Placement.HasValue) { slurPlacement = slur.Placement.Value; } else { slurPlacement = element.StemDirection == VerticalDirection.Up ? VerticalPlacement.Below : VerticalPlacement.Above; } if (slur.Type == NoteSlurType.Start) { ProcessSlurStart(renderer, slur, element, notePositionY, GetSlurInfoForWriting(slur.Number), slurPlacement); } if (slur.Type == NoteSlurType.Stop) { var slurInfo = GetSlurInfoForReading(slur.Number); if (slurInfo == null) { return; //There is no slur with that number. MusicXml file might be malformed (like in DWOK tom 1, s. 315, nr 24.xml) } ProcessSlurEnd(renderer, slur, element, notePositionY, slurInfo, slurPlacement); measurementService.Slurs.Remove(slur.Number); } }
public static Quadrangle GetBounds(this IEnumerable <Note> notes, ScoreRendererBase renderer) { if (!notes.Any()) { return(default(Quadrangle)); } var boundsCollection = notes.Select(n => n.GetBounds(renderer)).ToArray(); var bounds = new Quadrangle( boundsCollection.Last().NE, boundsCollection.First().NW, boundsCollection.Last().SE, boundsCollection.First().SW); var lowestB = bounds.SW.Y > bounds.SE.Y ? bounds.SW.Y : bounds.SE.Y; var highestB = bounds.NW.Y < bounds.NE.Y ? bounds.NW.Y : bounds.NE.Y; var lowest = boundsCollection.Max(b => b.SW.Y); var highest = boundsCollection.Min(b => b.NW.Y); var deltaYL = lowest - lowestB; var deltaYH = highest - highestB; return(new Quadrangle( new Point(bounds.NE.X, bounds.NE.Y + deltaYH), new Point(bounds.NW.X, bounds.NW.Y + deltaYH), new Point(bounds.SE.X, bounds.SE.Y + deltaYL), new Point(bounds.SW.X, bounds.SW.Y + deltaYL))); }
/// <summary> /// For debug purposes. It will be used in slur edit mode in the future. /// </summary> private void DrawSlurFrame(ScoreRendererBase renderer, Point p1, Point p2, Point p3, Point p4, MusicalSymbol owner) { renderer.DrawLine(p1, p2, owner); renderer.DrawLine(p2, p3, owner); renderer.DrawLine(p3, p4, owner); renderer.DrawLine(p4, p1, owner); }
public override void Render(PrintSuggestion element, ScoreRendererBase renderer) { if (element.IsSystemBreak && renderer.Settings.RenderingMode != ScoreRenderingModes.Panorama) { renderer.BreakSystem(renderer.TenthsToPixels(element.SystemDistance ?? scoreService.CurrentScore.DefaultPageSettings.DefaultSystemDistance ?? 0), element.IsPageBreak); MusicalSymbolRenderStrategyBase strategy = new ClefRenderStrategy(scoreService) { WasSystemChanged = true }; strategy.Render(scoreService.CurrentClef, renderer); strategy = new KeyRenderStrategy(scoreService); strategy.Render(scoreService.CurrentKey, renderer); //Time signature is not rendered in new line. //Render measure number: renderer.DrawString((scoreService.CurrentMeasureNo).ToString(), MusicFontStyles.LyricsFont, new Primitives.Point(0, scoreService.CurrentLinePositions[0] - 25), scoreService.CurrentStaff); } //Issue #44: Jeśli jesteśmy w trybie panoramy, to trzeba uzupełnić line positions dla pozostałych systemów: if (renderer.Settings.RenderingMode == ScoreRenderingModes.Panorama) { var firstSystem = scoreService.Systems.First(); foreach (var system in scoreService.Systems) { system.BuildStaffFragments(firstSystem.LinePositions.ToDictionary(p => scoreService.CurrentScore.Staves[p.Key - 1], p => p.Value)); } } }
protected override void DragInternal(ScoreRendererBase renderer, Direction draggedElement, DraggingState draggingState, double delta, double smallDelta) { draggedElement.SuppressEvents = true; draggedElement.Placement = DirectionPlacementType.Custom; draggedElement.SuppressEvents = false; draggedElement.DefaultYPosition += renderer.PixelsToTenths(smallDelta); }
/// <summary> /// Draws of performs additional logic at slur end /// </summary> /// <param name="renderer">Score renderer</param> /// <param name="slur">Slur</param> /// <param name="element">Element with a slur</param> /// <param name="notePositionY">Y position of element with a slur</param> /// <param name="slurStartInfo">Information about slur start point</param> /// <param name="slurPlacement">Information about slur placement</param> protected override void ProcessSlurEnd(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY, SlurInfo slurStartInfo, VerticalPlacement slurPlacement) { var absoluteControlPoint = RelativeToAbsolute(renderer, renderer.TenthsToPixels(slur.BezierStartOrEndPoint), notePositionY); var absoluteEndPoint = RelativeToAbsolute(renderer, renderer.TenthsToPixels(slur.BezierControlPoint), notePositionY); renderer.DrawBezier(slurStartInfo.StartPoint.X, slurStartInfo.StartPoint.Y, slurStartInfo.BezierStartControlPoint.X, slurStartInfo.BezierStartControlPoint.Y, absoluteControlPoint.X, absoluteControlPoint.Y, absoluteEndPoint.X, absoluteEndPoint.Y, element); }
protected override void DragInternal(ScoreRendererBase renderer, Rest draggedElement, DraggingState draggingState, double delta, double smallDelta) { if (!draggedElement.DefaultYPosition.HasValue) { draggedElement.SuppressEvents = true; draggedElement.DefaultYPosition = 0; draggedElement.SuppressEvents = false; } draggedElement.DefaultYPosition -= renderer.PixelsToTenths(smallDelta); }
private void Draw(Staff staff, ScoreRendererBase renderer, StaffFragment staffFragment, StaffSystem system) { renderer.DrawLine(0, staffFragment.LinePositions[0], 0, staffFragment.LinePositions[4], staffFragment); foreach (double position in staffFragment.LinePositions) { Point startPoint = new Point(0, position); Point endPoint = new Point(system.Width, position); renderer.DrawLine(startPoint, endPoint, new Pen(renderer.Settings.DefaultColor, 1, -1), staffFragment); } }
public void PerformOnMeasure(Measure measure, ScoreRendererBase renderer) { var beamGroupsForThisMeasure = measure.Staff.BeamGroups.Where(bg => bg.Members.Any(m => m.Measure == measure)); foreach (var beamGroup in beamGroupsForThisMeasure) { beamGroup.Start = beamGroup.Members.OfType <Note>().First().StemEndLocation; beamGroup.End = beamGroup.Members.OfType <Note>().Last().StemEndLocation; } PerformOnBeamGroups(beamGroupsForThisMeasure, renderer); }
protected override void DragInternal(ScoreRendererBase renderer, Lyrics draggedElement, DraggingState draggingState, double delta, double smallDelta) { draggedElement.SuppressEvents = true; if (!draggedElement.DefaultYPosition.HasValue) { draggedElement.DefaultYPosition = renderer.PixelsToTenths(-30); } draggedElement.DefaultYPosition += renderer.PixelsToTenths(smallDelta); draggedElement.SuppressEvents = false; draggedElement.InvalidateMeasure(); }
public void PerformOnStaff(Staff staff, ScoreRendererBase renderer) { foreach (var system in scoreService.Systems) { if (system.LinePositions == null) { continue; } var staffFragment = system.Staves[scoreService.CurrentStaffNo - 1]; Draw(staff, renderer, staffFragment, system); } }
private void Draw(Staff staff, ScoreRendererBase renderer, StaffFragment staffFragment, StaffSystem system, Pen staffLinePen, double?staffLineWidth) { renderer.DrawLine(0, staffFragment.LinePositions[0], 0, staffFragment.LinePositions[4], staffLinePen, staffFragment); var endPositionX = staffLineWidth ?? CalculateStaffLineWidth(staff, system, renderer.Settings); foreach (double linePositionY in staffFragment.LinePositions) { Point startPoint = new Point(0, linePositionY); Point endPoint = new Point(endPositionX, linePositionY); renderer.DrawLine(startPoint, endPoint, staffLinePen, staffFragment); } }
public void PerformOnScore(Score score, ScoreRendererBase renderer) { #if DemoVersion foreach (var location in new[] { new Point(0, 0), new Point(renderer.ScoreInformation.Systems.Max(s => s.Width) - 30, 0) }) { renderer.DrawString("DEMO", MusicFontStyles.LyricsFont, location, Color.Red, MusicalSymbol.Null); } #endif }
private void DrawBracket(StaffSystem system, Part part, ScoreRendererBase renderer) { if (system.LinePositions == null) { return; } var location = new Point(-30, system.LinePositions[1][0]); var size = new Size(25, system.LinePositions[part.Staves.Count][4] - system.LinePositions[1][0]); renderer.DrawStringInBounds(renderer.Settings.CurrentFont.LeftBracket, Model.Fonts.MusicFontStyles.MusicFont, location, size, renderer.Settings.DefaultColor, part.Staves.First()); }
protected override void DragInternal(ScoreRendererBase renderer, Note draggedElement, DraggingState draggingState, double delta, double smallDelta) { int midiPitch = draggingState.MidiPitchOnStartDragging + (int)(delta / 2); draggedElement.SuppressEvents = true; draggedElement.ApplyMidiPitch(midiPitch); //TODO: Wstawianie kasownika, jeśli jest znak przykluczowy, a obniżyliśmy o pół tonu //TODO: Ustalanie kierunku ogonka. Sprawdzić czy gdzieś to nie jest już zrobione, np. w PSAMie DetermineStemDirection(draggedElement); draggedElement.SuppressEvents = false; draggedElement.InvalidateMeasure(); }
private Tuple <double, double> GetBraceLocationXAndWidth(ScoreRendererBase renderer) { if (renderer.IsSMuFLFont && renderer.Settings.MusicFontProfile.SMuFLMetadata != null) { var bounds = renderer.Settings.MusicFontProfile.SMuFLMetadata.GlyphBBoxes.Brace; var width = (bounds.BBoxNe[0] + bounds.BBoxSw[0]) * 3; //TODO: Sprawdzić czemu Brace ma tak mały bounding box w SMuFL return(new Tuple <double, double>(renderer.LinespacesToPixels(bounds.BBoxSw[0] * -3 - width), renderer.LinespacesToPixels(width))); } else { return(new Tuple <double, double>(-17.5, 15)); } }
public double GetNoteheadWidthLs(ScoreRendererBase renderer) { if (renderer.IsSMuFLFont) { if (renderer.Settings.MusicFontProfile.SMuFLMetadata == null) { return(1.18); } var bounds = GetSMuFLNoteheadBounds(this, renderer.Settings.MusicFontProfile.SMuFLMetadata); return(bounds.BBoxNe[0] - bounds.BBoxSw[0]); } return(IsGraceNote || IsCueNote ? 0.6 : 1.1); }
/// <summary> /// Applies AddBracketsFinishingTouch to the score. /// </summary> /// <param name="score">Score</param> /// <param name="renderer">Score renderer</param> public void PerformOnScore(Score score, ScoreRendererBase renderer) { foreach (var part in score.Parts) { if (part.Staves.Count < 2) { continue; } foreach (var system in score.Systems) { DrawBracket(system, part, renderer); } } }
private void DrawBracket(StaffSystem system, Part part, ScoreRendererBase renderer) { if (system.LinePositions == null) { return; } var locationXAndWidth = GetBraceLocationXAndWidth(renderer); var location = new Point(locationXAndWidth.Item1, system.LinePositions[1][0]); var size = new Size(locationXAndWidth.Item2, system.LinePositions[part.Staves.Count][4] - system.LinePositions[1][0]); renderer.DrawCharacterInBounds(renderer.Settings.MusicFontProfile.MusicFont.BraceLeft, Model.Fonts.MusicFontStyles.MusicFont, location, size, renderer.Settings.DefaultColor, part.Staves.First()); }
/// <summary> /// Applies DrawLinesBetweenStavesFinishingTouch to the score. /// </summary> /// <param name="score">Score</param> /// <param name="renderer">Score renderer</param> public void PerformOnScore(Score score, ScoreRendererBase renderer) { var lightPen = new Pen(renderer.Settings.DefaultColor, 1); var thickPen = new Pen(renderer.Settings.DefaultColor, 3); var defaultPen = new Pen(renderer.Settings.DefaultColor, renderer.Settings.DefaultStaffLineThickness); for (var i = 0; i < scoreService.CurrentScore.Staves.Count - 1; i++) { var staff = scoreService.CurrentScore.Staves[i]; var barlinePen = renderer.CreatePenFromDefaults(staff, "thinBarlineThickness", s => s.DefaultBarlineThickness); foreach (var system in scoreService.CurrentScore.Systems) { if (renderer.Settings.RenderingMode == ScoreRenderingModes.SinglePage) { var page = staff.Score.Pages.FirstOrDefault(p => p.Systems.Contains(system)); var pageNumber = page == null ? -1 : staff.Score.Pages.IndexOf(page) + 1; if (pageNumber != renderer.Settings.CurrentPage) { continue; } } if (system.LinePositions == null) { continue; } var staffFragment = system.Staves[i]; if (!system.LinePositions.ContainsKey(i + 1) || !system.LinePositions.ContainsKey(i + 2)) { continue; } renderer.DrawLine(0, system.LinePositions[i + 1][4], 0, system.LinePositions[i + 2][0], barlinePen, staffFragment); foreach (var measure in staff.Measures.Where(m => m.Barline != null && m.System == system)) { if (measure.Barline?.Style == BarlineStyle.LightHeavy) { renderer.DrawLine(measure.BarlineLocationX - 6, system.LinePositions[i + 1][4], measure.BarlineLocationX - 6, system.LinePositions[i + 2][0], lightPen, measure.Barline); renderer.DrawLine(measure.BarlineLocationX - 1.5, system.LinePositions[i + 1][4], measure.BarlineLocationX - 1.5, system.LinePositions[i + 2][0], thickPen, measure.Barline); } else if (measure.Barline?.Style != BarlineStyle.None) { renderer.DrawLine(measure.BarlineLocationX, system.LinePositions[i + 1][4], measure.BarlineLocationX, system.LinePositions[i + 2][0], barlinePen, measure.Barline); } } } } }
/// <summary> /// Draws or performs additional logic at slur start /// </summary> /// <param name="renderer">Score renderer</param> /// <param name="slur">Slur</param> /// <param name="element">Element with a slur</param> /// <param name="notePositionY"></param> /// <param name="slurStartInfo">Information about slur start point</param> /// <param name="slurPlacement">Information about slur placement</param> protected override void ProcessSlurStart(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY, SlurInfo slurStartInfo, VerticalPlacement slurPlacement) { slurStartInfo.StartPlacement = slurPlacement; slurStartInfo.StartPointStemDirection = element.StemDirection; var polihymniaFix = renderer.LinespacesToPixels(element.GetNoteheadWidthLs(renderer) * 0.5); if (slurPlacement == VerticalPlacement.Above) { bool hasFlagOrBeam = element.BaseDuration.Denominator > 4; //If note has a flag or beam start the slur above the note. If not, start a bit to the right and down. var xShiftConcerningStemDirectionStart = slurStartInfo.StartPointStemDirection == VerticalDirection.Up ? (hasFlagOrBeam ? 5 : 10) : 1; slurStartInfo.StartPoint = new Point(scoreService.CursorPositionX + xShiftConcerningStemDirectionStart + polihymniaFix, element.StemDirection == VerticalDirection.Down ? notePositionY - 7 : element.StemEndLocation.Y + (hasFlagOrBeam ? -3 : 8)); } else { slurStartInfo.StartPoint = new Point(scoreService.CursorPositionX + 3 + polihymniaFix, notePositionY + 5); } }
private void PerformOnBeamGroups(IEnumerable <BeamGroup> beamGroups, ScoreRendererBase renderer) { foreach (var beamGroup in beamGroups) { Note previousNote = null; foreach (var member in beamGroup.Members) { var currentNote = member as Note; if (currentNote == null) { continue; } var beamPen = renderer.CreatePenFromDefaults(currentNote, "beamThickness", s => s.DefaultBeamThickness); beamPen.Color = currentNote.CoalesceColor(renderer); var beamSpacing = renderer.GetEngravingDefault("beamSpacing") ?? beamPen.Thickness * 0.6; var beamNumber = 1; foreach (var beamType in currentNote.BeamList) { var beamOffset = (beamPen.Thickness + beamSpacing) * (beamNumber - 1) * (currentNote.StemDirection == VerticalDirection.Up ? 1 : -1); var stemEnd = beamGroup.Start.TranslateHorizontallyAndMaintainAngle(beamGroup.Angle, currentNote.StemEndLocation.X - beamGroup.Start.X); currentNote.StemStartLocation = stemEnd; if (beamType == NoteBeamType.ForwardHook || beamType == NoteBeamType.BackwardHook) { var hookLength = beamType == NoteBeamType.ForwardHook ? 6 : -6; var hookEnd = stemEnd.TranslateByAngleOld(beamGroup.Angle, hookLength); renderer.DrawLine(stemEnd.Translate(0, beamOffset), hookEnd.Translate(0, beamOffset), beamPen, beamGroup); } else if (previousNote != null && beamType != NoteBeamType.Single && previousNote.BeamList.Count >= beamNumber) { var stemEnd1 = beamGroup.Start.TranslateHorizontallyAndMaintainAngle(beamGroup.Angle, previousNote.StemEndLocation.X - beamGroup.Start.X); renderer.DrawLine(stemEnd1.Translate(0, beamOffset), stemEnd.Translate(0, beamOffset), beamPen, beamGroup); } beamNumber++; } previousNote = currentNote; } } }
public void PerformOnScore(Score score, ScoreRendererBase renderer) { if (!Debugger.IsAttached) { return; } foreach (var system in score.Systems) { foreach (var staffFragment in system.Staves) { var elementsOnThisFragment = staffFragment.Staff?.Elements?.Where(e => e.Measure.System == system).ToArray() ?? new MusicalSymbol[0]; if (elementsOnThisFragment.Length > 0) { staffFragment.ActualRenderingTime = TimeSpan.FromTicks(elementsOnThisFragment.Sum(e => e.ActualRenderingTime.Ticks)); } } } }
public void PerformOnStaff(Staff staff, ScoreRendererBase renderer) { var staffLinePen = renderer.CreatePenFromDefaults(staff, "staffLineThickness", s => s.DefaultStaffLineThickness); staffLinePen.ZIndex = -1; var staffLineWidth = renderer.Settings.IsMusicPaperMode && scoreService.Systems.Any() ? (double?)scoreService.Systems.Max(s => CalculateStaffLineWidth(staff, s, renderer.Settings)) : null; foreach (var system in scoreService.Systems) { if (system.LinePositions == null) { continue; } var staffFragment = system.Staves[scoreService.CurrentStaffNo - 1]; Draw(staff, renderer, staffFragment, system, staffLinePen, staffLineWidth); } }
public Quadrangle GetBounds(ScoreRendererBase renderer) { var upperY = TextBlockLocation.Y < StemEndLocation.Y || StemEndLocation.Y == 0 ? TextBlockLocation.Y : StemEndLocation.Y; var lowerY = TextBlockLocation.Y > StemEndLocation.Y || StemEndLocation.Y == 0 ? TextBlockLocation.Y : StemEndLocation.Y; var leftX = TextBlockLocation.X < StemEndLocation.X || StemEndLocation.X == 0 ? TextBlockLocation.X : StemEndLocation.X; var rightX = TextBlockLocation.X > StemEndLocation.X || StemEndLocation.X == 0 ? TextBlockLocation.X : StemEndLocation.X; if (StemDirection == VerticalDirection.Down) { rightX += GetNoteheadWidthPx(renderer); } return(new Quadrangle( new Point(rightX, upperY), new Point(leftX, upperY), new Point(rightX, lowerY), new Point(leftX, lowerY) )); }
private void PerformOnBeamGroups(IEnumerable <BeamGroup> beamGroups, ScoreRendererBase renderer) { foreach (var beamGroup in beamGroups) { Note previousNote = null; foreach (var member in beamGroup.Members) { var currentNote = member as Note; if (currentNote == null) { continue; } var beamNumber = 1; foreach (var beamType in currentNote.BeamList) { var beamOffset = 28 + 4 * (beamNumber - 1) * (currentNote.StemDirection == VerticalDirection.Up ? 1 : -1); var stemEnd = beamGroup.Start.TranslateHorizontallyAndMaintainAngle(beamGroup.Angle, currentNote.StemEndLocation.X - beamGroup.Start.X); currentNote.StemStartLocation = stemEnd; if (beamType == NoteBeamType.ForwardHook || beamType == NoteBeamType.BackwardHook) { var hookLength = beamType == NoteBeamType.ForwardHook ? 6 : -6; var hookEnd = stemEnd.TranslateByAngle(beamGroup.Angle, hookLength); renderer.DrawLine(stemEnd.Translate(0, beamOffset), hookEnd.Translate(0, beamOffset), new Pen { Thickness = 2, Color = currentNote.CoalesceColor(renderer) }, beamGroup); } else if (previousNote != null && beamType != NoteBeamType.Single && previousNote.BeamList.Count >= beamNumber) { var stemEnd1 = beamGroup.Start.TranslateHorizontallyAndMaintainAngle(beamGroup.Angle, previousNote.StemEndLocation.X - beamGroup.Start.X); renderer.DrawLine(stemEnd1.Translate(0, beamOffset), stemEnd.Translate(0, beamOffset), new Pen { Thickness = 2, Color = currentNote.CoalesceColor(renderer) }, beamGroup); } beamNumber++; } previousNote = currentNote; } } }
private void DiscoverBeamGroups(Staff staff, ScoreRendererBase renderer) { staff.BeamGroups.Clear(); BeamGroup beamGroup = null; foreach (var nr in staff.Elements.OfType <NoteOrRest>()) { var note = nr as Note; if (note != null && note.BeamList.Any()) { if (note.BeamList.Count == 1 && note.BeamList[0] == NoteBeamType.Single) { continue; //Problem with beams in chords } if (note.BeamList.First() == NoteBeamType.Start) { beamGroup = new BeamGroup(staff); beamGroup.Start = note.StemEndLocation; staff.BeamGroups.Add(beamGroup); } if (beamGroup != null) { beamGroup.Members.Add(nr); } if (note.BeamList.First() == NoteBeamType.End) { if (beamGroup == null) { renderer.Exceptions.Add(new ScoreException(note, $"Encountered beam group end without corresponding beam group start.")); } else { beamGroup.End = note.StemEndLocation; beamGroup = null; } } } } }
protected override void DragInternal(ScoreRendererBase renderer, BeamGroup draggedElement, DraggingState draggingState, double delta, double smallDelta) { if (draggedElement.Members.OfType <Note>().Count() < 2) { return; } var firstElement = draggedElement.Members.OfType <Note>().First(); var lastElement = draggedElement.Members.OfType <Note>().Last(); firstElement.SuppressEvents = true; lastElement.SuppressEvents = true; if (!firstElement.HasCustomStemEndPosition) { firstElement.StemDefaultY = renderer.PixelsToTenths(firstElement.StemEndLocation.Y - firstElement.TextBlockLocation.Y); firstElement.HasCustomStemEndPosition = true; } if (!lastElement.HasCustomStemEndPosition) { lastElement.StemDefaultY = renderer.PixelsToTenths(lastElement.StemEndLocation.Y - firstElement.TextBlockLocation.Y); lastElement.HasCustomStemEndPosition = true; } firstElement.StemDefaultY -= smallDelta; lastElement.StemDefaultY -= smallDelta; foreach (var element in draggedElement.Members.OfType <Note>()) { element.SuppressEvents = true; NoteDraggingStrategy.DetermineStemDirection(element); element.SuppressEvents = false; } firstElement.SuppressEvents = false; lastElement.SuppressEvents = false; draggedElement.InvalidateMeasure(); }