Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.AvalonEdit/5.0.1/AvalonEdit-5.0.1/Rendering/VisualLineElement.cs @ 11700

Last change on this file since 11700 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 11.1 KB
Line 
1// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Collections.Generic;
21using System.Windows.Documents;
22using System.Windows.Input;
23using System.Windows.Media;
24using System.Windows.Media.TextFormatting;
25
26using ICSharpCode.AvalonEdit.Document;
27
28namespace ICSharpCode.AvalonEdit.Rendering
29{
30  /// <summary>
31  /// Represents a visual element in the document.
32  /// </summary>
33  public abstract class VisualLineElement
34  {
35    /// <summary>
36    /// Creates a new VisualLineElement.
37    /// </summary>
38    /// <param name="visualLength">The length of the element in VisualLine coordinates. Must be positive.</param>
39    /// <param name="documentLength">The length of the element in the document. Must be non-negative.</param>
40    protected VisualLineElement(int visualLength, int documentLength)
41    {
42      if (visualLength < 1)
43        throw new ArgumentOutOfRangeException("visualLength", visualLength, "Value must be at least 1");
44      if (documentLength < 0)
45        throw new ArgumentOutOfRangeException("documentLength", documentLength, "Value must be at least 0");
46      this.VisualLength = visualLength;
47      this.DocumentLength = documentLength;
48    }
49   
50    /// <summary>
51    /// Gets the length of this element in visual columns.
52    /// </summary>
53    public int VisualLength { get; private set; }
54   
55    /// <summary>
56    /// Gets the length of this element in the text document.
57    /// </summary>
58    public int DocumentLength { get; private set; }
59   
60    /// <summary>
61    /// Gets the visual column where this element starts.
62    /// </summary>
63    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods",
64                                                     Justification = "This property holds the start visual column, use GetVisualColumn to get inner visual columns.")]
65    public int VisualColumn { get; internal set; }
66   
67    /// <summary>
68    /// Gets the text offset where this element starts, relative to the start text offset of the visual line.
69    /// </summary>
70    public int RelativeTextOffset { get; internal set; }
71   
72    /// <summary>
73    /// Gets the text run properties.
74    /// A unique <see cref="VisualLineElementTextRunProperties"/> instance is used for each
75    /// <see cref="VisualLineElement"/>; colorizing code may assume that modifying the
76    /// <see cref="VisualLineElementTextRunProperties"/> will affect only this
77    /// <see cref="VisualLineElement"/>.
78    /// </summary>
79    public VisualLineElementTextRunProperties TextRunProperties { get; private set; }
80   
81    /// <summary>
82    /// Gets/sets the brush used for the background of this <see cref="VisualLineElement" />.
83    /// </summary>
84    public Brush BackgroundBrush { get; set; }
85   
86    internal void SetTextRunProperties(VisualLineElementTextRunProperties p)
87    {
88      this.TextRunProperties = p;
89    }
90   
91    /// <summary>
92    /// Creates the TextRun for this line element.
93    /// </summary>
94    /// <param name="startVisualColumn">
95    /// The visual column from which the run should be constructed.
96    /// Normally the same value as the <see cref="VisualColumn"/> property is used to construct the full run;
97    /// but when word-wrapping is active, partial runs might be created.
98    /// </param>
99    /// <param name="context">
100    /// Context object that contains information relevant for text run creation.
101    /// </param>
102    public abstract TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context);
103   
104    /// <summary>
105    /// Retrieves the text span immediately before the visual column.
106    /// </summary>
107    /// <remarks>This method is used for word-wrapping in bidirectional text.</remarks>
108    public virtual TextSpan<CultureSpecificCharacterBufferRange> GetPrecedingText(int visualColumnLimit, ITextRunConstructionContext context)
109    {
110      return null;
111    }
112   
113    /// <summary>
114    /// Gets if this VisualLineElement can be split.
115    /// </summary>
116    public virtual bool CanSplit {
117      get { return false; }
118    }
119   
120    /// <summary>
121    /// Splits the element.
122    /// </summary>
123    /// <param name="splitVisualColumn">Position inside this element at which it should be broken</param>
124    /// <param name="elements">The collection of line elements</param>
125    /// <param name="elementIndex">The index at which this element is in the elements list.</param>
126    public virtual void Split(int splitVisualColumn, IList<VisualLineElement> elements, int elementIndex)
127    {
128      throw new NotSupportedException();
129    }
130   
131    /// <summary>
132    /// Helper method for splitting this line element into two, correctly updating the
133    /// <see cref="VisualLength"/>, <see cref="DocumentLength"/>, <see cref="VisualColumn"/>
134    /// and <see cref="RelativeTextOffset"/> properties.
135    /// </summary>
136    /// <param name="firstPart">The element before the split position.</param>
137    /// <param name="secondPart">The element after the split position.</param>
138    /// <param name="splitVisualColumn">The split position as visual column.</param>
139    /// <param name="splitRelativeTextOffset">The split position as text offset.</param>
140    protected void SplitHelper(VisualLineElement firstPart, VisualLineElement secondPart, int splitVisualColumn, int splitRelativeTextOffset)
141    {
142      if (firstPart == null)
143        throw new ArgumentNullException("firstPart");
144      if (secondPart == null)
145        throw new ArgumentNullException("secondPart");
146      int relativeSplitVisualColumn = splitVisualColumn - VisualColumn;
147      int relativeSplitRelativeTextOffset = splitRelativeTextOffset - RelativeTextOffset;
148     
149      if (relativeSplitVisualColumn <= 0 || relativeSplitVisualColumn >= VisualLength)
150        throw new ArgumentOutOfRangeException("splitVisualColumn", splitVisualColumn, "Value must be between " + (VisualColumn + 1) + " and " + (VisualColumn + VisualLength - 1));
151      if (relativeSplitRelativeTextOffset < 0 || relativeSplitRelativeTextOffset > DocumentLength)
152        throw new ArgumentOutOfRangeException("splitRelativeTextOffset", splitRelativeTextOffset, "Value must be between " + (RelativeTextOffset) + " and " + (RelativeTextOffset + DocumentLength));
153      int oldVisualLength = VisualLength;
154      int oldDocumentLength = DocumentLength;
155      int oldVisualColumn = VisualColumn;
156      int oldRelativeTextOffset = RelativeTextOffset;
157      firstPart.VisualColumn = oldVisualColumn;
158      secondPart.VisualColumn = oldVisualColumn + relativeSplitVisualColumn;
159      firstPart.RelativeTextOffset = oldRelativeTextOffset;
160      secondPart.RelativeTextOffset = oldRelativeTextOffset + relativeSplitRelativeTextOffset;
161      firstPart.VisualLength = relativeSplitVisualColumn;
162      secondPart.VisualLength = oldVisualLength - relativeSplitVisualColumn;
163      firstPart.DocumentLength = relativeSplitRelativeTextOffset;
164      secondPart.DocumentLength = oldDocumentLength - relativeSplitRelativeTextOffset;
165      if (firstPart.TextRunProperties == null)
166        firstPart.TextRunProperties = TextRunProperties.Clone();
167      if (secondPart.TextRunProperties == null)
168        secondPart.TextRunProperties = TextRunProperties.Clone();
169    }
170   
171    /// <summary>
172    /// Gets the visual column of a text location inside this element.
173    /// The text offset is given relative to the visual line start.
174    /// </summary>
175    public virtual int GetVisualColumn(int relativeTextOffset)
176    {
177      if (relativeTextOffset >= this.RelativeTextOffset + DocumentLength)
178        return VisualColumn + VisualLength;
179      else
180        return VisualColumn;
181    }
182   
183    /// <summary>
184    /// Gets the text offset of a visual column inside this element.
185    /// </summary>
186    /// <returns>A text offset relative to the visual line start.</returns>
187    public virtual int GetRelativeOffset(int visualColumn)
188    {
189      if (visualColumn >= this.VisualColumn + VisualLength)
190        return RelativeTextOffset + DocumentLength;
191      else
192        return RelativeTextOffset;
193    }
194   
195    /// <summary>
196    /// Gets the next caret position inside this element.
197    /// </summary>
198    /// <param name="visualColumn">The visual column from which the search should be started.</param>
199    /// <param name="direction">The search direction (forwards or backwards).</param>
200    /// <param name="mode">Whether to stop only at word borders.</param>
201    /// <returns>The visual column of the next caret position, or -1 if there is no next caret position.</returns>
202    /// <remarks>
203    /// In the space between two line elements, it is sufficient that one of them contains a caret position;
204    /// though in many cases, both of them contain one.
205    /// </remarks>
206    public virtual int GetNextCaretPosition(int visualColumn, LogicalDirection direction, CaretPositioningMode mode)
207    {
208      int stop1 = this.VisualColumn;
209      int stop2 = this.VisualColumn + this.VisualLength;
210      if (direction == LogicalDirection.Backward) {
211        if (visualColumn > stop2 && mode != CaretPositioningMode.WordStart && mode != CaretPositioningMode.WordStartOrSymbol)
212          return stop2;
213        else if (visualColumn > stop1)
214          return stop1;
215      } else {
216        if (visualColumn < stop1)
217          return stop1;
218        else if (visualColumn < stop2 && mode != CaretPositioningMode.WordStart && mode != CaretPositioningMode.WordStartOrSymbol)
219          return stop2;
220      }
221      return -1;
222    }
223   
224    /// <summary>
225    /// Gets whether the specified offset in this element is considered whitespace.
226    /// </summary>
227    public virtual bool IsWhitespace(int visualColumn)
228    {
229      return false;
230    }
231   
232    /// <summary>
233    /// Gets whether the <see cref="GetNextCaretPosition"/> implementation handles line borders.
234    /// If this property returns false, the caller of GetNextCaretPosition should handle the line
235    /// borders (i.e. place caret stops at the start and end of the line).
236    /// This property has an effect only for VisualLineElements that are at the start or end of a
237    /// <see cref="VisualLine"/>.
238    /// </summary>
239    public virtual bool HandlesLineBorders {
240      get { return false; }
241    }
242   
243    /// <summary>
244    /// Queries the cursor over the visual line element.
245    /// </summary>
246    protected internal virtual void OnQueryCursor(QueryCursorEventArgs e)
247    {
248    }
249   
250    /// <summary>
251    /// Allows the visual line element to handle a mouse event.
252    /// </summary>
253    protected internal virtual void OnMouseDown(MouseButtonEventArgs e)
254    {
255    }
256   
257    /// <summary>
258    /// Allows the visual line element to handle a mouse event.
259    /// </summary>
260    protected internal virtual void OnMouseUp(MouseButtonEventArgs e)
261    {
262    }
263  }
264}
Note: See TracBrowser for help on using the repository browser.