PageRenderTime 41ms CodeModel.GetById 17ms app.highlight 17ms RepoModel.GetById 2ms app.codeStats 0ms

/AvalonEdit/ICSharpCode.AvalonEdit/Document/ISegment.cs

http://github.com/icsharpcode/ILSpy
C# | 219 lines | 133 code | 27 blank | 59 comment | 15 complexity | 94d8d1f69c862f5fa623e612f0a1e7c2 MD5 | raw file
  1// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
  2// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
  3
  4using System;
  5using System.Diagnostics;
  6using ICSharpCode.AvalonEdit.Utils;
  7using System.Globalization;
  8
  9namespace ICSharpCode.AvalonEdit.Document
 10{
 11	/// <summary>
 12	/// An (Offset,Length)-pair.
 13	/// </summary>
 14	/// <seealso cref="TextSegment"/>
 15	/// <seealso cref="AnchorSegment"/>
 16	public interface ISegment
 17	{
 18		/// <summary>
 19		/// Gets the start offset of the segment.
 20		/// </summary>
 21		int Offset { get; }
 22		
 23		/// <summary>
 24		/// Gets the length of the segment.
 25		/// </summary>
 26		/// <remarks>Must not be negative.</remarks>
 27		int Length { get; }
 28		
 29		/// <summary>
 30		/// Gets the end offset of the segment.
 31		/// </summary>
 32		/// <remarks>EndOffset = Offset + Length;</remarks>
 33		int EndOffset { get; }
 34	}
 35	
 36	static class SegmentExtensions
 37	{
 38		/// <summary>
 39		/// Gets whether the segment contains the offset.
 40		/// </summary>
 41		/// <returns>
 42		/// True, if offset is between segment.Start and segment.End (inclusive); otherwise, false.
 43		/// </returns>
 44		public static bool Contains(this ISegment segment, int offset)
 45		{
 46			int start = segment.Offset;
 47			int end = start + segment.Length;
 48			return offset >= start && offset <= end;
 49		}
 50		
 51		/// <summary>
 52		/// Gets the overlapping portion of the segments.
 53		/// Returns SimpleSegment.Invalid if the segments don't overlap.
 54		/// </summary>
 55		public static SimpleSegment GetOverlap(this ISegment segment, ISegment other)
 56		{
 57			int start = Math.Max(segment.Offset, other.Offset);
 58			int end = Math.Min(segment.EndOffset, other.EndOffset);
 59			if (end < start)
 60				return SimpleSegment.Invalid;
 61			else
 62				return new SimpleSegment(start, end - start);
 63		}
 64	}
 65	
 66	/// <summary>
 67	/// Represents a simple segment (Offset,Length pair) that is not automatically updated
 68	/// on document changes.
 69	/// </summary>
 70	struct SimpleSegment : IEquatable<SimpleSegment>, ISegment
 71	{
 72		public static readonly SimpleSegment Invalid = new SimpleSegment(-1, -1);
 73		
 74		public readonly int Offset, Length;
 75		
 76		int ISegment.Offset {
 77			get { return Offset; }
 78		}
 79		
 80		int ISegment.Length {
 81			get { return Length; }
 82		}
 83		
 84		public int EndOffset {
 85			get {
 86				return Offset + Length;
 87			}
 88		}
 89		
 90		public SimpleSegment(int offset, int length)
 91		{
 92			this.Offset = offset;
 93			this.Length = length;
 94		}
 95		
 96		public SimpleSegment(ISegment segment)
 97		{
 98			Debug.Assert(segment != null);
 99			this.Offset = segment.Offset;
100			this.Length = segment.Length;
101		}
102		
103		public override int GetHashCode()
104		{
105			unchecked {
106				return Offset + 10301 * Length;
107			}
108		}
109		
110		public override bool Equals(object obj)
111		{
112			return (obj is SimpleSegment) && Equals((SimpleSegment)obj);
113		}
114		
115		public bool Equals(SimpleSegment other)
116		{
117			return this.Offset == other.Offset && this.Length == other.Length;
118		}
119		
120		public static bool operator ==(SimpleSegment left, SimpleSegment right)
121		{
122			return left.Equals(right);
123		}
124		
125		public static bool operator !=(SimpleSegment left, SimpleSegment right)
126		{
127			return !left.Equals(right);
128		}
129		
130		public override string ToString()
131		{
132			return "[Offset=" + Offset.ToString(CultureInfo.InvariantCulture) + ", Length=" + Length.ToString(CultureInfo.InvariantCulture) + "]";
133		}
134	}
135	
136	/// <summary>
137	/// A segment using <see cref="TextAnchor"/>s as start and end positions.
138	/// </summary>
139	/// <remarks>
140	/// <para>
141	/// For the constructors creating new anchors, the start position will be AfterInsertion and the end position will be BeforeInsertion.
142	/// Should the end position move before the start position, the segment will have length 0.
143	/// </para>
144	/// </remarks>
145	/// <seealso cref="ISegment"/>
146	/// <seealso cref="TextSegment"/>
147	public sealed class AnchorSegment : ISegment
148	{
149		readonly TextAnchor start, end;
150		
151		/// <inheritdoc/>
152		public int Offset {
153			get { return start.Offset; }
154		}
155		
156		/// <inheritdoc/>
157		public int Length {
158			get {
159				// Math.Max takes care of the fact that end.Offset might move before start.Offset.
160				return Math.Max(0, end.Offset - start.Offset);
161			}
162		}
163		
164		/// <inheritdoc/>
165		public int EndOffset {
166			get {
167				// Math.Max takes care of the fact that end.Offset might move before start.Offset.
168				return Math.Max(start.Offset, end.Offset);
169			}
170		}
171		
172		/// <summary>
173		/// Creates a new AnchorSegment using the specified anchors.
174		/// The anchors must have <see cref="TextAnchor.SurviveDeletion"/> set to true.
175		/// </summary>
176		public AnchorSegment(TextAnchor start, TextAnchor end)
177		{
178			if (start == null)
179				throw new ArgumentNullException("start");
180			if (end == null)
181				throw new ArgumentNullException("end");
182			if (!start.SurviveDeletion)
183				throw new ArgumentException("Anchors for AnchorSegment must use SurviveDeletion", "start");
184			if (!end.SurviveDeletion)
185				throw new ArgumentException("Anchors for AnchorSegment must use SurviveDeletion", "end");
186			this.start = start;
187			this.end = end;
188		}
189		
190		/// <summary>
191		/// Creates a new AnchorSegment that creates new anchors.
192		/// </summary>
193		public AnchorSegment(TextDocument document, ISegment segment)
194			: this(document, ThrowUtil.CheckNotNull(segment, "segment").Offset, segment.Length)
195		{
196		}
197		
198		/// <summary>
199		/// Creates a new AnchorSegment that creates new anchors.
200		/// </summary>
201		public AnchorSegment(TextDocument document, int offset, int length)
202		{
203			if (document == null)
204				throw new ArgumentNullException("document");
205			this.start = document.CreateAnchor(offset);
206			this.start.SurviveDeletion = true;
207			this.start.MovementType = AnchorMovementType.AfterInsertion;
208			this.end = document.CreateAnchor(offset + length);
209			this.end.SurviveDeletion = true;
210			this.end.MovementType = AnchorMovementType.BeforeInsertion;
211		}
212		
213		/// <inheritdoc/>
214		public override string ToString()
215		{
216			return "[Offset=" + Offset.ToString(CultureInfo.InvariantCulture) + ", EndOffset=" + EndOffset.ToString(CultureInfo.InvariantCulture) + "]";
217		}
218	}
219}