protected override void AddLayoutLine(LayoutLine line, VisualElementType elementType, LineExportConfig lineConfig) { switch (elementType) { case VisualElementType.Fret: AddDxfLine("Frets", line, lineConfig); break; case VisualElementType.String: AddDxfLine("Strings", line, lineConfig); break; case VisualElementType.FingerboardEdge: case VisualElementType.FingerboardMargin: case VisualElementType.FingerboardContinuation: AddDxfLine("Fingerboard", line, lineConfig); break; case VisualElementType.CenterLine: case VisualElementType.GuideLine: case VisualElementType.StringMidline: AddDxfLine("Layout", line, lineConfig); break; } }
/// <summary> /// Moves the position to the end of wrapped line. /// </summary> /// <param name="displayContext">The display context.</param> public static TextPosition ToEndOfWrappedLine( this TextPosition bufferPosition, IDisplayContext displayContext) { // Get the wrapped line and layout. Layout layout; int wrappedLineIndex; LayoutLine wrappedLine = bufferPosition.GetWrappedLine( displayContext, out layout, out wrappedLineIndex); // Move to the end of the wrapped line. If this isn't the last, we // need to shift back one character. int unicodeIndex = wrappedLine.StartIndex + wrappedLine.Length; if (wrappedLineIndex != layout.LineCount - 1) { unicodeIndex--; } // Because the wrappedLine works with UTF-8 encoding, we need to // convert it back to a C# string. string lineText = displayContext.LineBuffer.GetLineText(bufferPosition.LinePosition); int characterIndex = PangoUtility.TranslatePangoToStringIndex( lineText, unicodeIndex); // Create a new buffer position from the elements and return it. return(new TextPosition(bufferPosition.LinePosition, characterIndex)); }
private SvgLine CreateSvgLine(SvgElement owner, LayoutLine line, LineExportConfig lineConfig) { return CreateSvgLine(owner, line.P1, line.P2, GetLineThickness(lineConfig), lineConfig.Color, lineConfig.IsDashed ? LineDashPattern : null); }
public SkiaTextLayout( string value, RectangleF rect, ITextAttributes textAttributes, LayoutLine callback, TextFlow textFlow = TextFlow.ClipBounds, SKPaint paint = null) { _value = value; _textAttributes = textAttributes; _rect = rect; _callback = callback; _textFlow = textFlow; _paint = paint; if (paint == null) { _paint = new SKPaint() { Typeface = SkiaDelegatingFontService.Instance.GetTypeface(_textAttributes.FontName), TextSize = _textAttributes.FontSize }; _disposePaint = true; } var metrics = _paint.FontMetrics; _descent = metrics.Descent; _lineHeight = _paint.FontSpacing; }
public static void PageUp(EditorViewController controller) { // Extract a number of useful variable for this method. IDisplayContext displayContext = controller.DisplayContext; TextPosition position = displayContext.Caret.Position; // Figure out the layout and wrapped line we are currently on. Layout layout; int wrappedLineIndex; LayoutLine wrappedLine = position.GetWrappedLine( displayContext, out layout, out wrappedLineIndex); // Figure out where in the buffer we're located. int lineHeight; PointD point = position.ToScreenCoordinates(displayContext, out lineHeight); // Shift down the buffer a full page size and clamp it to the actual // buffer size. double bufferY = Math.Max(point.Y - displayContext.VerticalAdjustment.PageSize, 0); // Figure out the X coordinate of the line. If there is an action context, // use that. Otherwise, calculate it from the character index of the position. int pixels = Units.ToPixels(GetLineX(controller, wrappedLine, position)); int lineX = pixels; // Move to the calculated point. var newPoint = new PointD(lineX, bufferY - displayContext.BufferOffsetY); Point(controller, newPoint); }
/// <summary> /// Gets the line X coordinates from either the state if we have one /// or calculate it from the buffer position's X coordinate. /// </summary> /// <param name="controller">The action context.</param> /// <param name="wrappedLine">The wrapped line.</param> /// <param name="position">The position.</param> /// <returns></returns> private static int GetLineX( EditorViewController controller, LayoutLine wrappedLine, TextPosition position) { int lineX; var state = controller.States.Get <VerticalMovementActionState>(); if (state == null) { // Calculate the line state from the caret position. The cursor // is always to the left of the character unless we're at the // end, and then it's considered trailing of the previous // character. LineBuffer lineBuffer = controller.DisplayContext.LineBuffer; int lineIndex = position.LinePosition.GetLineIndex(lineBuffer.LineCount); string lineText = lineBuffer.GetLineText(lineIndex); int characterIndex = position.CharacterPosition.GetCharacterIndex(lineText); bool trailing = false; if (characterIndex == lineText.Length && lineText.Length > 0) { characterIndex--; trailing = true; } // Because Pango works with UTF-8-based indexes, we need to // convert the C# character index into that index to properly // identify the character. characterIndex = NormalizeEmptyStrings(lineText, characterIndex); int unicodeIndex = PangoUtility.TranslateStringToPangoIndex( lineText, characterIndex); lineX = wrappedLine.IndexToX(unicodeIndex, trailing); // We need the line's style since it may have left passing // which will change our columns. LineBlockStyle style = controller.DisplayContext.Renderer.GetLineStyle( lineIndex, LineContexts.CurrentLine); var pixelPadding = (int)style.Padding.Left.GetValueOrDefault(0); lineX += Units.FromPixels(pixelPadding); // Save a new state into the states. state = new VerticalMovementActionState(lineX); controller.States.Add(state); } else { // Get the line coordinate from the state. lineX = state.LayoutLineX; } return(lineX); }
/// <summary> /// Gets the string index for an X coordinate. /// </summary> /// <param name="layoutLine">The layout line.</param> /// <param name="stringIndex">Index of the string.</param> /// <param name="trailing">if set to <c>true</c> [trailing].</param> /// <returns></returns> public static int TranslatedIndexToX( this LayoutLine layoutLine, int stringIndex, bool trailing) { int pangoIndex = PangoUtility.TranslateStringToPangoIndex( layoutLine.Layout.Text, stringIndex); return(layoutLine.IndexToX(pangoIndex, trailing)); }
/// <summary> /// Gets the string index for a given X coordinate (in Pango units). /// </summary> /// <param name="layoutLine">The layout line.</param> /// <param name="x">The x.</param> /// <param name="stringIndex">Index of the string.</param> /// <param name="trailing">The trailing.</param> /// <returns></returns> public static bool XToTranslatedIndex( this LayoutLine layoutLine, int x, out int stringIndex, out int trailing) { int pangoIndex; bool results = layoutLine.XToIndex(x, out pangoIndex, out trailing); stringIndex = PangoUtility.TranslatePangoToStringIndex( layoutLine.Layout.Text, pangoIndex); return(results); }
/// <summary> /// Gets the X ranges from the given string indexes. /// </summary> /// <param name="layoutLine">The layout line.</param> /// <param name="startStringIndex">Start index of the string.</param> /// <param name="endStringIndex">End index of the string.</param> /// <param name="ranges">The ranges.</param> public static void GetTranslatedXRanges( this LayoutLine layoutLine, int startStringIndex, int endStringIndex, out int[][] ranges) { int startPangoIndex = PangoUtility.TranslateStringToPangoIndex( layoutLine.Layout.Text, startStringIndex); int endPangoIndex = PangoUtility.TranslateStringToPangoIndex( layoutLine.Layout.Text, endStringIndex); layoutLine.GetXRanges(startPangoIndex, endPangoIndex, out ranges); }
private Line AddDxfLine(string layerName, LayoutLine line, LineExportConfig lineConfig) { var dxfLine = new Line(PointToVector(line.P1), PointToVector(line.P2)) { Layer = GetLayer(layerName), Color = GetColor(lineConfig.Color) }; if (lineConfig.IsDashed) { dxfLine.Linetype = Linetype.Dashed; } Document.AddEntity(dxfLine); return(dxfLine); }
/// <summary> /// Gets the index of the layout line inside the layout. /// </summary> /// <param name="layoutLine">The layout line.</param> /// <returns></returns> public static int GetLayoutLineIndex(this LayoutLine layoutLine) { // Go through all the lines in the layout and find the index. for (int index = 0; index < layoutLine.Layout.LineCount; index++) { if (layoutLine.Layout.Lines[index].StartIndex == layoutLine.StartIndex) { return(index); } } // We can't find this layout line inside the layout. throw new Exception("Cannot find layout line inside layout"); }
protected override void AddLayoutLine(LayoutLine line, VisualElementType elementType, LineExportConfig lineConfig) { switch (elementType) { case VisualElementType.Fret: { var svgLine = CreateSvgLine(GetLayer("Frets"), line, lineConfig); if (line.Tag is FretLine fretLine) { if (fretLine.IsNut) svgLine.CustomAttributes.Add("Fret", "Nut"); else svgLine.CustomAttributes.Add("Fret", fretLine.FretIndex.ToString()); } break; } case VisualElementType.FingerboardEdge: case VisualElementType.FingerboardMargin: case VisualElementType.FingerboardContinuation: CreateSvgLine(GetLayer("Fingerboard"), line, lineConfig); break; case VisualElementType.CenterLine: case VisualElementType.StringMidline: case VisualElementType.GuideLine: CreateSvgLine(GetLayer("Layout"), line, lineConfig); break; case VisualElementType.String: { var stringInfo = line as StringLine; SvgLine svgLine; if (Options.UseStringGauge && !stringInfo.String.Gauge.IsEmpty) { var lineThickness = GetRelativeUnit(stringInfo.String.Gauge); svgLine = CreateSvgLine(GetLayer("Strings"), line, lineThickness, Options.Strings.Color); } else svgLine = CreateSvgLine(GetLayer("Strings"), line, lineConfig); svgLine.CustomAttributes.Add("Index", stringInfo.Index.ToString()); break; } } }
private void GenerateFingerboard() { foreach (var fingerboardEdge in Layout.VisualElements.OfType <FingerboardSideEdge>()) { AddLayoutLine(fingerboardEdge, VisualElementType.FingerboardEdge, Options.FingerboardEdges); } foreach (var fingerboardEdge in Layout.VisualElements.OfType <FingerboardEdge>()) { if (fingerboardEdge.Points.Count == 2) { var layoutLine = new LayoutLine(fingerboardEdge.Points.First(), fingerboardEdge.Points.Last()); AddLayoutLine(layoutLine, VisualElementType.FingerboardEdge, Options.FingerboardEdges); } else if (fingerboardEdge.Spline != null) { AddLayoutSpline(fingerboardEdge, VisualElementType.FingerboardEdge, Options.FingerboardEdges); } else { AddLayoutPolyLine(fingerboardEdge, VisualElementType.FingerboardEdge, Options.FingerboardEdges); } } if (!Options.ExportFrets) { var nutLines = Layout.GetElements <FretLine>(x => x.IsNut); foreach (var line in nutLines) { if (line.IsStraight) { var layoutLine = new LayoutLine(line.Points.First(), line.Points.Last()); AddLayoutLine(layoutLine, VisualElementType.FingerboardEdge, Options.FingerboardEdges); } else if (line.Spline != null) { AddLayoutSpline(line, VisualElementType.FingerboardEdge, Options.FingerboardEdges); } else { AddLayoutPolyLine(line, VisualElementType.FingerboardEdge, Options.FingerboardEdges); } } } }
internal LayoutLine GetStringBoundaryLine(SIString str, FingerboardSide dir) { LayoutLine boundary = null; if (dir == FingerboardSide.Bass) { boundary = VisualElements.OfType <StringCenter>().FirstOrDefault(c => c.Right.Index == str.Index); } else { boundary = VisualElements.OfType <StringCenter>().FirstOrDefault(c => c.Left.Index == str.Index); } if (boundary == null) { return(VisualElements.OfType <FingerboardSideEdge>().First(e => e.Side == dir)); } return(boundary); }
/// <summary> /// Moves the position to the beginning of wrapped line. /// </summary> /// <param name="displayContext">The display context.</param> public static TextPosition ToBeginningOfWrappedLine( this TextPosition bufferPosition, IDisplayContext displayContext) { // Wrapped lines (via Pango) work with UTF-8 encoding, not the // normal C# string indexes. We need to get the index and convert // it to a character string since that is what this library uses. LayoutLine wrappedLine = bufferPosition.GetWrappedLine(displayContext); int unicodeIndex = wrappedLine.StartIndex; // Because the wrappedLine works with UTF-8 encoding, we need to // convert it back to a C# string. string lineText = displayContext.LineBuffer.GetLineText(bufferPosition.LinePosition); int characterIndex = PangoUtility.TranslatePangoToStringIndex( lineText, unicodeIndex); // Create a new buffer position from the elements and return it. return(new TextPosition(bufferPosition.LinePosition, characterIndex)); }
/// <summary> /// Determines whether the position is at the end of a wrapped line. /// </summary> /// <param name="displayContext">The display context.</param> /// <returns> /// <c>true</c> if [is end of wrapped line] [the specified display context]; otherwise, <c>false</c>. /// </returns> public static bool IsEndOfWrappedLine( this TextPosition bufferPosition, IDisplayContext displayContext) { // Get the wrapped line and layout. Layout layout; int wrappedLineIndex; LayoutLine wrappedLine = bufferPosition.GetWrappedLine( displayContext, out layout, out wrappedLineIndex); // Move to the end of the wrapped line. If this isn't the last, we // need to shift back one character. int wrappedCharacterIndex = wrappedLine.StartIndex + wrappedLine.Length; if (wrappedLineIndex != layout.LineCount - 1) { wrappedCharacterIndex--; } // Return if these are equal. return(bufferPosition.CharacterPosition == wrappedCharacterIndex); }
/// <summary> /// Gets the size of the wrapped line in pixels and relative to the layout. /// </summary> /// <param name="layoutLine">The layout line.</param> /// <param name="size">The size.</param> public static void GetPixelExtents( this LayoutLine layoutLine, out Rectangle size) { // Go through and populate the size regions. size = new Rectangle(); size.X = 0; size.Width = layoutLine.Layout.Width; // Build up the Y coordinates of all the lines before it. int layoutLineIndex = layoutLine.GetLayoutLineIndex(); int y = 0; for (int index = 0; index < layoutLineIndex; index++) { LayoutLine preceedingLayoutLine = layoutLine.Layout.Lines[index]; var ink = new Rectangle(); var logical = new Rectangle(); preceedingLayoutLine.GetPixelExtents(ref ink, ref logical); y += logical.Height; } size.Y = y; // Figure out the height of the given wrapped line. var ink2 = new Rectangle(); var logical2 = new Rectangle(); layoutLine.GetPixelExtents(ref ink2, ref logical2); size.Height = logical2.Height; }
private void DrawLine(Graphics g, LayoutLine line, Pen pen) { DrawLine(g, pen, line.P1, line.P2); }
private void CreateFingerboardEdges() { //apply margin perpendicularly to the treble string var trebleLine = FirstString.LayoutLine; var trebleOffset = Measure.Zero; if (Margins.CompensateStringGauge && !FirstString.Gauge.IsEmpty) { trebleOffset += FirstString.Gauge / 2; } var trebleFretboardEdge = AddVisualElement(new FingerboardSideEdge( trebleLine.GetPerpendicularPoint(trebleLine.P1, Margins.TrebleMargins[FingerboardEnd.Nut] + trebleOffset), trebleLine.GetPerpendicularPoint(trebleLine.P2, Margins.TrebleMargins[FingerboardEnd.Bridge] + trebleOffset), FingerboardSide.Treble)); //apply margin perpendicularly to the bass string var bassLine = LastString.LayoutLine; var bassOffset = Measure.Zero; if (Margins.CompensateStringGauge && !LastString.Gauge.IsEmpty) { bassOffset += LastString.Gauge / 2; } var bassFretboardEdge = AddVisualElement(new FingerboardSideEdge( bassLine.GetPerpendicularPoint(bassLine.P1, (Margins.BassMargins[FingerboardEnd.Nut] + bassOffset) * -1), //*-1 to offset towards left bassLine.GetPerpendicularPoint(bassLine.P2, (Margins.BassMargins[FingerboardEnd.Bridge] + bassOffset) * -1), FingerboardSide.Bass)); //adjust the end points of each edges so that they are "inline" with the strings if (NumberOfStrings >= 2) { var trebOpp = GetStringBoundaryLine(FirstString, FingerboardSide.Bass) as StringCenter; var tp = trebOpp.GetRelativePoint(trebleLine, trebleLine.P1); var trebNutLine = new LayoutLine(tp, trebleLine.P1); var trebBriLine = new LayoutLine(trebOpp.P2, trebleLine.P2); trebleFretboardEdge.P1 = trebleFretboardEdge.GetIntersection(trebNutLine); trebleFretboardEdge.P2 = trebleFretboardEdge.GetIntersection(trebBriLine); var bassOpp = GetStringBoundaryLine(LastString, FingerboardSide.Treble) as StringCenter; var bp = bassOpp.GetRelativePoint(bassLine, bassLine.P1); var bassNutLine = new LayoutLine(bp, bassLine.P1); var bassBriLine = new LayoutLine(bassOpp.P2, bassLine.P2); bassFretboardEdge.P1 = bassFretboardEdge.GetIntersection(bassNutLine); bassFretboardEdge.P2 = bassFretboardEdge.GetIntersection(bassBriLine); } //else if(/*ScaleLengthMode != ScaleLengthType.Individual && */NumberOfStrings > 1) //{ // var nutLine = new LayoutLine(trebleLine.FretZero, bassLine.FretZero); // var bridgeLine = new LayoutLine(trebleLine.P2, bassLine.P2); // if (FirstString.StartingFret == 0) // trebleFretboardEdge.P1 = nutLine.GetIntersection(trebleFretboardEdge); // else // trebleFretboardEdge.P1 = trebleFretboardEdge.SnapToLine(trebleLine.P1, true); // if (LastString.StartingFret == 0) // bassFretboardEdge.P1 = nutLine.GetIntersection(bassFretboardEdge); // else // bassFretboardEdge.P1 = bassFretboardEdge.SnapToLine(bassLine.P1, true); // trebleFretboardEdge.P2 = bridgeLine.GetIntersection(trebleFretboardEdge); // bassFretboardEdge.P2 = bridgeLine.GetIntersection(bassFretboardEdge); //} else { trebleFretboardEdge.P1 = trebleFretboardEdge.SnapToLine(trebleLine.P1, LineSnapDirection.Horizontal); trebleFretboardEdge.P2 = trebleFretboardEdge.SnapToLine(trebleLine.P2, LineSnapDirection.Horizontal); bassFretboardEdge.P1 = bassFretboardEdge.SnapToLine(bassLine.P1, LineSnapDirection.Horizontal); bassFretboardEdge.P2 = bassFretboardEdge.SnapToLine(bassLine.P2, LineSnapDirection.Horizontal); } }
private SvgLine CreateSvgLine(SvgElement owner, LayoutLine line, SvgUnit stroke, Color color) { return CreateSvgLine(owner, line.P1, line.P2, stroke, color, null); }
/// <summary> /// Called when the widget is exposed or drawn. /// </summary> /// <param name="e">The e.</param> /// <returns></returns> protected override bool OnExposeEvent(EventExpose e) { // Figure out the area we are rendering into. Gdk.Rectangle area = e.Region.Clipbox; var cairoArea = new Rectangle(area.X, area.Y, area.Width, area.Height); using (Context cairoContext = CairoHelper.Create(e.Window)) { // Create a render context. var renderContext = new RenderContext(cairoContext); renderContext.RenderRegion = cairoArea; // If we don't have a buffer at this point, don't render anything. if (Renderer == null || LineBuffer == null) { return(true); } // Paint the background color of the window. RegionBlockStyle backgroundStyle = Theme.RegionStyles[Theme.BackgroundRegionStyleName]; DrawingUtility.DrawLayout(this, renderContext, cairoArea, backgroundStyle); // Reset the layout and its properties. Renderer.Width = area.Width - margins.Width; // Figure out the viewport area we'll be drawing. int offsetY = 0; if (verticalAdjustment != null) { offsetY += (int)verticalAdjustment.Value; } var viewArea = new Rectangle( area.X, area.Y + offsetY, area.Width, area.Height); // Determine the line range visible in the given area. int startLine, endLine; Renderer.GetLineLayoutRange(viewArea, out startLine, out endLine); // Determine where the first line actually starts. int startLineY = 0; if (startLine > 0) { startLineY = Renderer.GetLineLayoutHeight(0, startLine - 1); } // Go through the lines and draw each one in the correct position. double currentY = startLineY - offsetY; for (int lineIndex = startLine; lineIndex <= endLine; lineIndex++) { // Figure out if we are on the current line. var lineContexts = LineContexts.None; bool currentLine = false; if (lineIndex == caret.Position.LinePosition) { // Add the curent line to the context. lineContexts |= LineContexts.CurrentLine; currentLine = true; } // Pull out the layout and style since we'll use it. Layout layout = Renderer.GetLineLayout(lineIndex, lineContexts); LineBlockStyle style = Renderer.GetLineStyle(lineIndex, lineContexts); // Get the extents for that line. int layoutWidth, layoutHeight; layout.GetPixelSize(out layoutWidth, out layoutHeight); // Figure out the height of the line including padding. double height = layoutHeight + style.Height; if (currentLine) { // If we have a full-line background color, display it. RegionBlockStyle currentLineStyle = Theme.RegionStyles[Theme.CurrentLineRegionStyleName]; if (currentLineStyle != null) { var lineArea = new Rectangle(TextX, currentY, TextWidth, height); DrawingUtility.DrawLayout( this, renderContext, lineArea, currentLineStyle); } // If we have a wrapped line background color, draw it. RegionBlockStyle currentWrappedLineStyle = Theme.RegionStyles[Theme.CurrentWrappedLineRegionStyleName]; if (currentWrappedLineStyle != null) { // Get the wrapped line for the caret's position. LayoutLine wrappedLine = caret.Position.GetWrappedLine(this); Pango.Rectangle wrappedLineExtents; wrappedLine.GetPixelExtents(out wrappedLineExtents); // Draw the current wrapped line index. var wrappedLineArea = new Rectangle( TextX, currentY + wrappedLineExtents.Y + style.Top, TextWidth, wrappedLineExtents.Height); DrawingUtility.DrawLayout( this, renderContext, wrappedLineArea, currentWrappedLineStyle); } } // Draw the current line along with wrapping and padding. DrawingUtility.DrawLayout( this, renderContext, new Rectangle(TextX, currentY, TextWidth, height), layout, style); // Render out the margin renderers. margins.Draw( this, renderContext, lineIndex, new PointD(0, currentY), height, style); // Move down a line. currentY += height; } // Draw the caret on the screen, but only if we have focus. if (IsFocus) { caret.Draw(renderContext); } // Show the scroll region, if requested. if (editorViewSettings.ShowScrollPadding) { cairoContext.Color = new Color(1, 0.5, 0.5); cairoContext.Rectangle(scrollPaddingRegion); cairoContext.Stroke(); } } return(true); }
/// <summary> /// Determines whether this layout line is the last line in the layout. /// </summary> /// <param name="layoutLine">The layout line.</param> /// <returns> /// <c>true</c> if [is last line] [the specified layout line]; otherwise, <c>false</c>. /// </returns> public static bool IsLastLineInLayout(this LayoutLine layoutLine) { Layout layout = layoutLine.Layout; return(layout.Lines[layout.LineCount - 1].StartIndex == layoutLine.StartIndex); }
private void measureChildren() { if (!invalidSizes) { return; } invalidSizes = false; float width = 0, height = 0; // Prepare preferred lengths var innerSizeWidth = flowWidth - padding.Horizontal; lines = new List <LayoutLine>(); { LayoutLine line = null; foreach (var child in Children) { if (child.AnchorTarget != null) { continue; } var preferredSize = child.PreferredSize; var minSize = child.MinSize; var maxSize = child.MaxSize; var itemWidth = preferredSize.X; if (line == null || (flowWidth != 0 && innerSizeWidth < line.GetTotalWidth(spacing) + itemWidth + (line.Items.Count > 0 ? lineSpacing : 0))) { lines.Add(line = new LayoutLine()); } line.Items.Add(new LayoutItem() { Widget = child, PreferredSize = preferredSize, MinSize = minSize, MaxSize = maxSize, Width = itemWidth, Scalable = true, }); line.Width += itemWidth; line.Height = Math.Max(line.Height, preferredSize.Y); } } // Distribute the remaining/missing space var firstLine = true; foreach (var line in lines) { var scalableItems = line.Items.Count; while (scalableItems > 0 && Math.Abs(innerSizeWidth - line.Width) > 0.001f) { var remainingWidth = innerSizeWidth - line.Width; if (!fill && remainingWidth > 0) { break; } var adjustment = remainingWidth / scalableItems; line.Width = line.GetTotalSpacing(spacing); scalableItems = 0; foreach (var item in line.Items) { if (!item.Widget.CanGrow && adjustment > 0) { item.Scalable = false; } if (item.Scalable) { item.Width += adjustment; if (item.Width < item.MinSize.Y) { item.Width = item.MinSize.Y; item.Scalable = false; } else if (item.MaxSize.Y > 0 && item.Width >= item.MaxSize.Y) { item.Width = item.MaxSize.Y; item.Scalable = false; } else { scalableItems++; } } line.Width += item.Width; } } width = Math.Max(width, line.Width); height += firstLine ? line.Height : line.Height + lineSpacing; firstLine = false; } flowWidth = Math.Max(flowWidth, width + padding.Horizontal); preferredSize = new Vector2(flowWidth, height + padding.Vertical); }
private void PaintLine(LayoutLine line, Graphics g) { foreach (var span in line.Spans) { var text = span.Text; var font = GetFont(span.Style); var fg = GetForeground(span.Style); var bg = GetBackground(span.Style); g.FillRectangle(bg, span.Extent); g.DrawString(text, font, fg, span.Extent, stringFormat); } }
private LayoutSpan FindSpan(Point ptMouse, LayoutLine line) { foreach (var span in line.Spans) { if (span.Extent.Contains(ptMouse)) return span; } return null; }
private void GenerateFrets() { foreach (var fretLine in Layout.VisualElements.OfType <FretLine>()) { if (Options.ExtendFretSlots && !fretLine.IsNut) { var extendedFretLine = fretLine.GetExtendedFretLine(Options.Frets.ExtensionAmount); if (extendedFretLine is LayoutLine line) { line.Tag = fretLine; AddLayoutLine(line, VisualElementType.Fret, Options.Frets); continue; } else if (extendedFretLine is LayoutPolyLine polyline) { polyline.Tag = fretLine; if (polyline.Spline != null) { AddLayoutSpline(polyline, VisualElementType.Fret, Options.Frets); } else { AddLayoutPolyLine(polyline, VisualElementType.Fret, Options.Frets); } continue; } } if (fretLine.IsStraight) { var layoutLine = new LayoutLine(fretLine.Points.First(), fretLine.Points.Last()); layoutLine.Tag = fretLine; AddLayoutLine(layoutLine, VisualElementType.Fret, Options.Frets); } else { fretLine.RebuildSpline(); if (fretLine.Spline != null) { AddLayoutSpline(fretLine, VisualElementType.Fret, Options.Frets); } else { AddLayoutPolyLine(fretLine, VisualElementType.Fret, Options.Frets); } } } if (Options.ExportBridgeLine) { var bridgeLine = Layout.GetElement <LayoutPolyLine>(x => x.ElementType == VisualElementType.BridgeLine); if (bridgeLine != null) { var tmpConfig = new LineExportConfig() { Color = System.Drawing.Color.Black, LineThickness = 1d, LineUnit = LineUnit.Points }; AddLayoutPolyLine(bridgeLine, VisualElementType.BridgeLine, tmpConfig); } } }
private void GenerateLayoutLines() { if (Options.ExportCenterLine) { bool centerExist = false; var centerLine = Layout.VisualElements.OfType <LayoutLine>().First(x => x.ElementType == VisualElementType.CenterLine); if (Options.ExportMidlines && Layout.NumberOfStrings % 2 == 0)//even number of strings { var stringCenter = Layout.GetStringsCenter(Layout.Strings[(Layout.NumberOfStrings / 2) - 1], Layout.Strings[Layout.NumberOfStrings / 2]); if (stringCenter.Equation.IsVertical && stringCenter.Equation.X == 0) { centerExist = true; } } else if (Options.ExportStrings && Layout.NumberOfStrings % 2 == 1)//odd number of strings { var middleString = Layout.Strings[(Layout.NumberOfStrings - 1) / 2]; if (middleString.LayoutLine.Equation.IsVertical && middleString.LayoutLine.Equation.X == 0) { centerExist = true; } } if (!centerExist) { AddLayoutLine(centerLine, VisualElementType.CenterLine, Options.CenterLine); } } if (Options.ExportMidlines) { foreach (var stringCenter in Layout.GetElements <StringCenter>()) { AddLayoutLine(stringCenter, VisualElementType.StringMidline, Options.Midlines); } } if (!Options.ExportStrings && Options.ExportFingerboardMargins)//export first & last string to show fingerboard margin { var margins = Layout.GetElements <LayoutLine>(x => x.ElementType == VisualElementType.FingerboardMargin); if (margins.Any()) { foreach (var marginLine in margins) { AddLayoutLine(marginLine, VisualElementType.FingerboardMargin, Options.FingerboardMargins); } } //else //{ // var firstString = Layout.FirstString.LayoutLine; // var lastString = Layout.LastString.LayoutLine; // var trebleEdge = Layout.GetStringBoundaryLine(Layout.FirstString, FingerboardSide.Treble); // var bassEdge = Layout.GetStringBoundaryLine(Layout.LastString, FingerboardSide.Bass); // var trebleMargin = new LayoutLine(firstString.P1, firstString.SnapToLine(trebleEdge.P2, LineSnapDirection.Horizontal)); // AddLayoutLine(trebleMargin, VisualElementType.FingerboardMargin, Options.FingerboardMargins); // if (firstString != lastString) // { // var bassMargin = new LayoutLine(lastString.P1, lastString.SnapToLine(bassEdge.P2, LineSnapDirection.Horizontal)); // AddLayoutLine(bassMargin, VisualElementType.FingerboardMargin, Options.FingerboardMargins); // } //} } if (Options.ExportFingerboardEdges && Options.FingerboardEdges.ContinueLines) { var endPoints = new List <PointM>(); foreach (var guideLine in Layout.GetElements <LayoutLine>(l => l.ElementType == VisualElementType.FingerboardContinuation)) { endPoints.Add(guideLine.P2); AddLayoutLine(guideLine, VisualElementType.FingerboardContinuation, Options.GuideLines); } var pt1 = endPoints.OrderBy(pt => pt.X).First(); var pt2 = endPoints.OrderByDescending(pt => pt.X).First(); var bridgeLine = new LayoutLine(pt1, pt2); AddLayoutLine(bridgeLine, VisualElementType.FingerboardContinuation, Options.GuideLines); } }
public static void Up(EditorViewController controller) { // Extract a number of useful variable for this method. IDisplayContext displayContext = controller.DisplayContext; TextPosition position = displayContext.Caret.Position; EditorViewRenderer buffer = displayContext.Renderer; // Figure out the layout and wrapped line we are currently on. Layout layout; int wrappedLineIndex; LayoutLine wrappedLine = position.GetWrappedLine( displayContext, out layout, out wrappedLineIndex); // Figure out the X coordinate of the line. If there is an action context, // use that. Otherwise, calculate it from the character index of the position. int lineX = GetLineX(controller, wrappedLine, position); // Figure out which wrapped line we'll be moving the caret to. LinePosition linePosition = position.LinePosition; int lineIndex = linePosition.GetLineIndex(buffer.LineBuffer); if (wrappedLineIndex == 0) { // If we are the last line in the buffer, just do nothing. if (linePosition == 0) { return; } // Move to the next line. lineIndex--; layout = buffer.GetLineLayout(lineIndex, LineContexts.None); wrappedLineIndex = layout.LineCount - 1; wrappedLine = layout.Lines[wrappedLineIndex]; } else { // Just move down in the layout. wrappedLineIndex--; wrappedLine = layout.Lines[wrappedLineIndex]; } // Adjust the X coordinate for the current line. lineX -= GetLeftStylePaddingPango(controller, lineIndex); // The wrapped line has the current wrapped line, so use the lineX // to figure out which character to use. int trailing; int unicodeIndex; wrappedLine.XToIndex(lineX, out unicodeIndex, out trailing); // Calculate the character position, but we have to map UTF-8 // characters because Pango uses that instead of C# strings. string lineText = controller.DisplayContext.LineBuffer.GetLineText(lineIndex); unicodeIndex = NormalizeEmptyStrings(lineText, unicodeIndex); int characterIndex = PangoUtility.TranslateStringToPangoIndex( lineText, unicodeIndex); if (lineText.Length > 0 && trailing > 0) { characterIndex++; } // Draw the new location of the caret. var caretPosition = new TextPosition(lineIndex, characterIndex); displayContext.ScrollToCaret(caretPosition); }
protected virtual void AddLayoutLine(LayoutLine line, VisualElementType elementType, LineExportConfig lineConfig) { }
/// <summary> /// Computes the layout of all visibile text spans and stores them the /// member variable 'visibleLines'. /// </summary> /// <param name="g"></param> protected void ComputeLayout(Graphics g) { float cyLine = GetLineHeight(); this.visibleLines = new SortedList<float, LayoutLine>(); SizeF szClient = new SizeF(ClientSize); var rcLine = new RectangleF(0, 0, szClient.Width, cyLine); // Get the lines. int cVisibleLines = (int) Math.Ceiling(szClient.Height / cyLine); var lines = model != null ? model.GetLineSpans(cVisibleLines) : new TextSpan[0][]; int iLine = 0; while (rcLine.Top < szClient.Height && iLine < lines.Length) { var line = lines[iLine]; var ll = new LayoutLine { Extent = rcLine, Spans = ComputeSpanLayouts(line, rcLine, g) }; this.visibleLines.Add(rcLine.Top, ll); ++iLine; rcLine.Offset(0, cyLine); } }
public void LayoutText(PathF path, string text, ITextAttributes textAttributes, LayoutLine callback) { // Do nothing }
private void LayoutStrings(Measure[] nutStringPos, Measure[] bridgeStringPos) { var stringLines = VisualElements.OfType <StringLine>(); if (NumberOfStrings == 1) { ConstructString(Strings[0], nutStringPos[0], bridgeStringPos[0]); } else if (ScaleLengthMode != ScaleLengthType.Multiple) { var trebleStr = ConstructString(Strings[0], nutStringPos[0], bridgeStringPos[0]); var bassStr = ConstructString(Strings[NumberOfStrings - 1], nutStringPos[NumberOfStrings - 1], bridgeStringPos[NumberOfStrings - 1]); var maxHeight = Measure.Max(trebleStr.Bounds.Height, bassStr.Bounds.Height); AdjustStringVerticalPosition(trebleStr, maxHeight); AdjustStringVerticalPosition(bassStr, maxHeight); var nutLine = Line.FromPoints(trebleStr.P1.ToVector(), bassStr.P1.ToVector()); var bridgeLine = Line.FromPoints(trebleStr.P2.ToVector(), bassStr.P2.ToVector()); var twelfthFret = new LayoutLine(PointM.Average(trebleStr.P1, trebleStr.P2), PointM.Average(bassStr.P1, bassStr.P2)); //create the remaining strings by distributing them equally between the outer strings for (int i = 1; i < NumberOfStrings - 1; i++) { var nutPos = nutLine.GetPointForX(nutStringPos[i].NormalizedValue); var bridgePos = bridgeLine.GetPointForX(bridgeStringPos[i].NormalizedValue); var createdString = AddVisualElement(new StringLine(Strings[i], PointM.FromVector(nutPos, nutStringPos[i].Unit), PointM.FromVector(bridgePos, bridgeStringPos[i].Unit))); //strings distributed equally between the outer strings (which are tapered/angled) do not have their centers aligned //so we correct the string length (at bridge) so that its center is aligned with the twelfth fret var middle = createdString.GetIntersection(twelfthFret); var distFromNut = PointM.Distance(createdString.P1, middle); var distFromBridge = PointM.Distance(createdString.P2, middle); var stringCenterOffset = Measure.Abs(distFromNut - distFromBridge); if (!CompensateFretPositions && stringCenterOffset > Measure.Mm(0.05)) { //adjust the end of the string so that it's center is above the 12th fret createdString.P2 = createdString.P1 + (createdString.Direction * distFromNut * 2); } Strings[i].RecalculateLengths();//store the physical length of the string } } else { for (int i = 0; i < NumberOfStrings; i++) { ConstructString(Strings[i], nutStringPos[i], bridgeStringPos[i]); } //*** Adjust strings position for multiscale var maxPerpHeight = Measure.FromNormalizedValue(stringLines.Max(l => l.Bounds.Height.NormalizedValue), UnitOfMeasure.Mm); foreach (var strLine in stringLines) { AdjustStringVerticalPosition(strLine, maxPerpHeight); } } //calculate starting fret position if different from 0 (nut) foreach (var str in Strings) { if (str.StartingFret != 0) { var startingFretPosRatio = GetEqualTemperedFretPosition(str.StartingFret); var stringVector = str.PlaceFretsRelativeToString ? str.LayoutLine.Direction * -1 : new Vector(0, 1); var startingFretPos = str.LayoutLine.P2 + (stringVector * str.CalculatedLength * startingFretPosRatio); if (!str.PlaceFretsRelativeToString) { startingFretPos = str.LayoutLine.SnapToLine(startingFretPos, LineSnapDirection.Horizontal); } str.LayoutLine.P1 = startingFretPos; str.RecalculateLengths(); } } for (int i = 0; i < NumberOfStrings - 1; i++) { AddVisualElement(new StringCenter(Strings[i + 1].LayoutLine, Strings[i].LayoutLine)); } }