3

avalon editを使用してカスタムソフトウェアを作成しており、行間のスペース(高さ)を大きくする方法を探しています。現時点では、ユーザーが行の書き込みを終了して別の行を書きたいと思うたびに、空の行を追加する必要があります。

defaultLineHeightが計算されているように見えるクラスを調べ始めましたTextViewが、影響を与えることができたのは、コンテンツ自体ではなく、ビジュアルカレットの高さだけです。

現在、すべてのペアラインを非表示にすることを検討していますが、ライン間にスペースを追加するという簡単な操作を実現するためのより簡単な方法があることを望んでいます。

TextViewこれが私が現在調べているクラスのメソッドです。ヒントやヒントは大歓迎です。

void CalculateDefaultTextMetrics()
{
    if (defaultTextMetricsValid)
    {
        return;
    }

    defaultTextMetricsValid = true;
    if (formatter != null)
    {
        var textRunProperties = CreateGlobalTextRunProperties();
        using (
            var line = formatter.FormatLine(
                new SimpleTextSource("x", textRunProperties),
                0,
                32000,
                new VisualLineTextParagraphProperties { defaultTextRunProperties = textRunProperties },
                null))
        {
            wideSpaceWidth = Math.Max(1, line.WidthIncludingTrailingWhitespace);
            defaultBaseline = Math.Max(1, line.Baseline);
            defaultLineHeight = Math.Max(1, line.Height);
        }
    }
    else
    {
        wideSpaceWidth = FontSize / 2;
        defaultBaseline = FontSize;
        **defaultLineHeight = FontSize + 3; // bigger value only affects caret height :(**
    }

    // Update heightTree.DefaultLineHeight, if a document is loaded.
    if (heightTree != null)
    {
        heightTree.DefaultLineHeight = defaultLineHeight;
    }
}

ありがとう

4

4 に答える 4

5

これDefaultLineHeightは、デフォルトフォントの行の高さであり、各行の高さの最初の仮定として使用されます。(たとえば、スクロールバーの位置を計算するため)

線が実際に測定されるたびに(TextView.BuildVisualLine)、測定された高さは高さツリーに保存され、デフォルトの高さを上書きします。これは、ワードラップ(またはフォントサイズを変更する行トランスフォーマー)によって、各行の高さが異なる可能性があるためです。

現時点では、行間の間隔は実際にはサポートされていません。これを追加したい場合は、の高さの計算を変更してみてください。VisualLineたとえば、を変更しVisualLine.SetTextLines()ます。

于 2012-08-31T18:44:50.320 に答える
3

@PeterMooreが言ったことを含みます。テキストを強制的に正しくレンダリングするには、もう1つの手順が必要です。

一番下にあるのVisualLine.csVisualLineDrawingVisual、実際のテキストの描画を担当しているが、クラスにアクセスできないTextViewクラスです。

コンストラクターを変更しdouble lineSpacingて、パラメーターとして含め、のすべてのインスタンスにを掛けtextLine.HeightますlineSpacing

で、現在変更されているコンストラクターの2次パラメーターとして。VisualLine.Render()を渡します。この後、すべてが正しく描画されます。textView.LineSpacingVisualLineDrawingVisual

変更されたコードの全体像は次のとおりです。

TextView.cs

public static readonly DependencyProperty LineSpacingProperty =
    DependencyProperty.Register("LineSpacing", typeof(double), typeof(TextView),
                                new FrameworkPropertyMetadata(1.0));

public double LineSpacing {
    get { return (double) GetValue(LineSpacingProperty); }
    set { SetValue(LineSpacingProperty, value); }
}

VisualLine.cs

269行目

internal void SetTextLines(List<TextLine> textLines) {
    this.textLines = textLines.AsReadOnly();
    Height = 0;
    foreach (TextLine line in textLines)
        Height += line.Height * textView.LineSpacing;
}

335行目

public double GetTextLineVisualYPosition(TextLine textLine, VisualYPosition yPositionMode) {
    if (textLine == null)
        throw new ArgumentNullException("textLine");
    double pos = VisualTop;
    foreach (TextLine tl in TextLines) {
        if (tl == textLine) {
            switch (yPositionMode) {
            case VisualYPosition.LineTop:
                return pos;
            case VisualYPosition.LineMiddle:
                return pos + tl.Height / 2 * textView.LineSpacing;
            case VisualYPosition.LineBottom:
                return pos + tl.Height * textView.LineSpacing;
            case VisualYPosition.TextTop:
                return pos + tl.Baseline - textView.DefaultBaseline;
            case VisualYPosition.TextBottom:
                return pos + tl.Baseline - textView.DefaultBaseline + textView.DefaultLineHeight;
            case VisualYPosition.TextMiddle:
                return pos + tl.Baseline - textView.DefaultBaseline + textView.DefaultLineHeight / 2;
            case VisualYPosition.Baseline:
                return pos + tl.Baseline;
            default:
                throw new ArgumentException("Invalid yPositionMode:" + yPositionMode);
            }
        }
        else {
            pos += tl.Height * textView.LineSpacing;
        }
    }
    throw new ArgumentException("textLine is not a line in this VisualLine");
}

386行目

public TextLine GetTextLineByVisualYPosition(double visualTop) {
    const double epsilon = 0.0001;
    double pos = this.VisualTop;
    foreach (TextLine tl in TextLines) {
        pos += tl.Height * textView.LineSpacing;
        if (visualTop + epsilon < pos)
            return tl;
    }
    return TextLines[TextLines.Count - 1];
}

701行目

internal VisualLineDrawingVisual Render() {
    Debug.Assert(phase == LifetimePhase.Live);
    if (visual == null)
        visual = new VisualLineDrawingVisual(this, textView.LineSpacing);
    return visual;
}

714行目

public VisualLineDrawingVisual(VisualLine visualLine, double lineSpacing) {
    this.VisualLine = visualLine;
    var drawingContext = RenderOpen();
    double pos = 0;
    foreach (TextLine textLine in visualLine.TextLines) {
        textLine.Draw(drawingContext, new Point(0, pos), InvertAxes.None);
        pos += textLine.Height * lineSpacing;
    }
    this.Height = pos;
    drawingContext.Close();
}
于 2017-12-20T01:54:01.797 に答える
2

これが古い投稿であることは知っていますが、同じ質問に出くわしました。次の変更を加えることで、行間隔を非常に簡単に追加できました。

  1. デフォルト値の呼び出しに新しいdouble依存関係プロパティを追加しますTextViewLineSpacing1.0
  2. で、をVisualLine.SetTextLines掛けるline.HeighttextView.LineSpacing
  3. VisualLine.GetTextLineVisualYPositionとで、VisualLine.GetTextLineByVisualYPositionの各出現を乗算tl.HeightしますtextView.LineSpacing

次にTextView.LineSpacing、コードで直接設定するか、カスタムXAMLスタイルなどを使用して設定できます。

必要なのはそれだけのようでした。

PS-AvalonEditは素晴らしいです!

于 2016-09-09T17:45:30.580 に答える
1

@Robert Jordanが言ったことに加えて、満足のいく結果を得るために私がしなければならなかったいくつかの変更があります。

まず、行の高さ全体をカバーするようにテキストマーキングオーバーレイを作成するには、BackgroundGeometryBuilder.csで次の行を変更します

ProcessTextLinesメソッド、196行目:

215行目:

yield return new Rect(pos, y, 1, line.Height * textView.LineSpacing);

259行目:

lastRect = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height * textView.LineSpacing);

259行目:

Rect extendSelection = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height * textView.LineSpacing);

私が抱えていた2番目の問題は、テキストが、現在拡張されている行の高さの下部ではなく、上部にレンダリングされることでした。これを修正するには、行がレンダリングされた後ではなく、レンダリングされる前に余分なスペースを追加する必要があります。したがって、次の変更を行います。

VisualLine.cs、行714

public VisualLineDrawingVisual(VisualLine visualLine, double lineSpacing) {
    this.VisualLine = visualLine;
    var drawingContext = RenderOpen();
    double pos = 0;
    foreach (TextLine textLine in visualLine.TextLines) {
        pos +=(textLine.Height * lineSpacing)-textLine.Height
        textLine.Draw(drawingContext, new Point(0, pos), InvertAxes.None);
        pos += textLine.Height;
    }
    this.Height = pos;
    drawingContext.Close();
}

さらに、動的な行ごとの行間隔をサポートするためにこれを変換するのは簡単であることがわかりました。LineSpacingプロパティをVisualLineに移動してから、次のようなVisualLineTransformerを追加します。

class LinePaddingTransformer : IVisualLineTransformer
{
    public LinePaddingTransformer()
    {

    }
    public void Transform(ITextRunConstructionContext context, IList<VisualLineElement> elements)
    {
        int index = context.VisualLine.FirstDocumentLine.LineNumber - 1;
       //You need to calculate your padding from the line index somehow.
       //for example create a list of objects with the spacing in them and pass to this transformer.
        double spacing= MyCalculateLinePaddingMethod(index);  
        context.VisualLine.LineSpacing= spacing;
    }
}

テキストを折り返す場合にスペースを最初の行にのみ追加する必要がある場合は、以前にLineSpacingプロパティで乗算したすべての場所を調べて、TextLineがコレクションの最初の行であるかどうかを確認する必要があります。

于 2017-12-20T18:39:47.947 に答える