2 * Copyright (C) 2013 FooProject
\r
3 * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
\r
4 * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
\r
6 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
\r
9 You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
\r
12 using System.Collections.Generic;
\r
15 using System.Threading.Tasks;
\r
17 namespace FooEditEngine
\r
20 /// 新しく作成されるフォールティングアイテムを表す
\r
22 public class FoldingItem : IRangeProvider<int>
\r
31 return this.Range.From;
\r
42 return this.Range.To;
\r
47 /// 展開されているなら真。そうでないなら偽
\r
56 /// 内部で使用しているメンバーです。外部から参照しないでください
\r
58 public Range<int> Range
\r
64 internal FoldingItem Parent;
\r
69 /// <param name="start">開始インデックス</param>
\r
70 /// <param name="end">終了インデックス</param>
\r
71 public FoldingItem(int start, int end)
\r
74 throw new ArgumentException("start < endである必要があります");
\r
75 this.Range = new Range<int>(start, end);
\r
79 internal bool IsParentHidden()
\r
81 if (this.Parent != null && !this.Parent.Expand)
\r
87 internal bool IsHidden(int index)
\r
89 if (this.Parent != null && !this.Parent.Expand)
\r
91 if (!this.Expand && index > this.Start && index <= this.End)
\r
96 internal bool IsFirstLine(LineToIndexTable layoutLines, int row)
\r
98 int firstRow = layoutLines.GetLineNumberFromIndex(this.Start);
\r
99 return row == firstRow;
\r
103 sealed class RangeItemComparer : IComparer<FoldingItem>
\r
105 public int Compare(FoldingItem x, FoldingItem y)
\r
107 return x.Range.CompareTo(y.Range);
\r
114 public sealed class FoldingItemStatusChangedEventArgs : EventArgs
\r
119 public FoldingItem Item;
\r
123 /// <param name="item">FoldingItemオブジェクト</param>
\r
124 public FoldingItemStatusChangedEventArgs(FoldingItem item)
\r
131 /// 折り畳み関係のコレクションを表す
\r
133 public sealed class FoldingCollection
\r
135 RangeTree<int, FoldingItem> collection = new RangeTree<int, FoldingItem>(new RangeItemComparer());
\r
137 internal FoldingCollection()
\r
139 this.collection.AutoRebuild = false;
\r
140 this.StatusChanged += (s, e) => { };
\r
143 internal void UpdateData(Document doc,int startIndex,int insertLength,int removeLength)
\r
145 if (this.collection.Count == 0)
\r
147 int delta = insertLength - removeLength;
\r
148 foreach (FoldingItem item in this.collection.Items)
\r
150 int endIndex = startIndex + removeLength - 1;
\r
151 if (startIndex <= item.Start)
\r
153 if ((endIndex >= item.Start && endIndex <= item.End) || endIndex > item.End)
\r
154 item.Range = new Range<int>(item.Start, item.Start); //ここで削除すると例外が発生する
\r
156 item.Range = new Range<int>(item.Start + delta, item.End + delta);
\r
158 else if (startIndex >= item.Start && startIndex <= item.End)
\r
160 if (endIndex > item.End)
\r
161 item.Range = new Range<int>(item.Start, item.Start); //ここで削除すると例外が発生する
\r
163 item.Range = new Range<int>(item.Start, item.End + delta);
\r
166 this.collection.Rebuild();
\r
172 public event EventHandler<FoldingItemStatusChangedEventArgs> StatusChanged;
\r
177 /// <param name="data">FoldingItemオブジェクト</param>
\r
178 public void Add(FoldingItem data)
\r
180 foreach (FoldingItem item in this.collection.Items)
\r
182 if (item.Start == data.Start && item.End == data.End)
\r
184 if (item.Parent != null && data.Start < item.Parent.Start && data.End >= item.Parent.End)
\r
186 else if (item.Start < data.Start && item.End > data.End)
\r
187 data.Parent = item;
\r
188 else if (item.Start > data.Start && item.End <= data.End)
\r
189 item.Parent = data;
\r
191 this.collection.Add(data);
\r
197 /// <param name="collection">FoldingItemのコレクション</param>
\r
198 public void AddRange(IEnumerable<FoldingItem> collection)
\r
200 foreach (FoldingItem data in collection)
\r
209 /// <param name="data">FoldingItemオブジェクト</param>
\r
210 public void Remove(FoldingItem data)
\r
212 this.collection.Remove(data);
\r
216 /// 指定した範囲の折り畳みを取得する
\r
218 /// <param name="index">開始インデックス</param>
\r
219 /// <param name="length">長さ</param>
\r
220 /// <returns>FoldingItemイテレーター</returns>
\r
221 public IEnumerable<FoldingItem> GetRange(int index, int length)
\r
223 if (this.collection.Count == 0)
\r
226 this.collection.Rebuild();
\r
228 List<FoldingItem> items = this.collection.Query(new Range<int>(index, index + length - 1));
\r
229 foreach (FoldingItem item in items)
\r
234 /// 指定した範囲に最も近い折り畳みを取得する
\r
236 /// <param name="index">開始インデックス</param>
\r
237 /// <param name="length">長さ</param>
\r
238 /// <returns>FoldingItemオブジェクト</returns>
\r
239 public FoldingItem Get(int index, int length)
\r
241 if (this.collection.Count == 0)
\r
244 this.collection.Rebuild();
\r
246 List<FoldingItem> items = this.collection.Query(new Range<int>(index, index + length - 1));
\r
248 int minLength = Int32.MaxValue;
\r
249 FoldingItem minItem = null;
\r
250 foreach (FoldingItem item in items)
\r
251 if (index - item.Start < minLength)
\r
259 public void Clear()
\r
261 this.collection.Clear();
\r
267 /// <param name="foldingData">foldingItemオブジェクト</param>
\r
268 /// <remarks>親ノードも含めてすべて展開されます</remarks>
\r
269 public void Expand(FoldingItem foldingData)
\r
271 while (foldingData != null)
\r
273 foldingData.Expand = true;
\r
274 if (foldingData.Parent == null || foldingData.Parent.Expand)
\r
277 foldingData = foldingData.Parent;
\r
279 this.StatusChanged(this, new FoldingItemStatusChangedEventArgs(foldingData));
\r
285 /// <param name="foldingData">foldingItemオブジェクト</param>
\r
286 /// <remarks>全ての子ノードは折りたたまれます</remarks>
\r
287 public void Collapse(FoldingItem foldingData)
\r
289 if (foldingData == null)
\r
291 this.collection.Rebuild();
\r
292 List<FoldingItem> items = this.collection.Query(foldingData.Range);
\r
293 foldingData.Expand = false;
\r
294 foreach (FoldingItem item in items)
\r
295 if (item.Start > foldingData.Start && item.End <= foldingData.End)
\r
296 item.Expand = false;
\r
297 this.StatusChanged(this, new FoldingItemStatusChangedEventArgs(foldingData));
\r
301 /// 指定した範囲に属する親ノードを取得する
\r
303 /// <param name="index">開始インデックス</param>
\r
304 /// <param name="length">長さ</param>
\r
305 /// <returns>FoldingItemオブジェクト</returns>
\r
306 /// <remarks>指定した範囲には属する中で隠された親ノードだけが取得される</remarks>
\r
307 public FoldingItem GetFarestHiddenFoldingData(int index, int length)
\r
309 FoldingItem foldingData = this.Get(index, length);
\r
310 if (foldingData == null)
\r
312 while (foldingData.Parent != null)
\r
314 if (foldingData.Parent.Expand)
\r
317 foldingData = foldingData.Parent;
\r
319 return foldingData;
\r