OSDN Git Service

起動時にキャレットを表示させるようにした。これにともないタイマー起動タイミングを変更した
[fooeditengine/FooEditEngine.git] / Common / MarkerCollection.cs
1 /*\r
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
5 \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
8 \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
10  */\r
11 using System;\r
12 using System.Linq;\r
13 using System.Collections.Generic;\r
14 \r
15 namespace FooEditEngine\r
16 {\r
17     /// <summary>\r
18     /// 既定のIDリスト\r
19     /// </summary>\r
20     public static class MarkerIDs\r
21     {\r
22         /// <summary>\r
23         /// デフォルトIDを表す\r
24         /// </summary>\r
25         public static int Defalut = 0;\r
26         /// <summary>\r
27         /// URLを表す\r
28         /// </summary>\r
29         public static int URL = 1;\r
30     }\r
31     /// <summary>\r
32     /// マーカーのタイプを表す列挙体\r
33     /// </summary>\r
34     public enum HilightType\r
35     {\r
36         /// <summary>\r
37         /// マーカーとして表示しないことを表す\r
38         /// </summary>\r
39         None,\r
40         /// <summary>\r
41         /// 選択状態を表す\r
42         /// </summary>\r
43         Select,\r
44         /// <summary>\r
45         /// URLを表す\r
46         /// </summary>\r
47         Url,\r
48         /// <summary>\r
49         /// 実線を表す\r
50         /// </summary>\r
51         Sold,\r
52         /// <summary>\r
53         /// 破線を表す\r
54         /// </summary>\r
55         Dash,\r
56         /// <summary>\r
57         /// 一点鎖線を表す\r
58         /// </summary>\r
59         DashDot,\r
60         /// <summary>\r
61         /// 二点鎖線を表す\r
62         /// </summary>\r
63         DashDotDot,\r
64         /// <summary>\r
65         /// 点線を表す\r
66         /// </summary>\r
67         Dot,\r
68         /// <summary>\r
69         /// 波線を表す\r
70         /// </summary>\r
71         Squiggle,\r
72     }\r
73 \r
74     /// <summary>\r
75     /// マーカー自身を表します\r
76     /// </summary>\r
77     public struct Marker : IRange, IEqualityComparer<Marker>\r
78     {\r
79         #region IRange メンバー\r
80 \r
81         /// <summary>\r
82         /// 開始位置\r
83         /// </summary>\r
84         public int start\r
85         {\r
86             get;\r
87             set;\r
88         }\r
89 \r
90         /// <summary>\r
91         /// 長さ\r
92         /// </summary>\r
93         public int length\r
94         {\r
95             get;\r
96             set;\r
97         }\r
98 \r
99         #endregion\r
100 \r
101         /// <summary>\r
102         /// マーカーのタイプ\r
103         /// </summary>\r
104         public HilightType hilight;\r
105 \r
106         /// <summary>\r
107         /// 色を指定する\r
108         /// </summary>\r
109         public Color color;\r
110 \r
111         /// <summary>\r
112         /// マーカーを作成します\r
113         /// </summary>\r
114         /// <param name="start">開始インデックス</param>\r
115         /// <param name="length">長さ</param>\r
116         /// <param name="hilight">タイプ</param>\r
117         /// <returns>マーカー</returns>\r
118         public static Marker Create(int start, int length, HilightType hilight)\r
119         {\r
120             return new Marker { start = start, length = length, hilight = hilight, color = new Color()};\r
121         }\r
122 \r
123         /// <summary>\r
124         /// マーカーを作成します\r
125         /// </summary>\r
126         /// <param name="start">開始インデックス</param>\r
127         /// <param name="length">長さ</param>\r
128         /// <param name="hilight">タイプ</param>\r
129         /// <param name="color">色</param>\r
130         /// <returns>マーカー</returns>\r
131         public static Marker Create(int start, int length, HilightType hilight,Color color)\r
132         {\r
133             return new Marker { start = start, length = length, hilight = hilight ,color = color};\r
134         }\r
135 \r
136         /// <summary>\r
137         /// 等しいかどうかを調べます\r
138         /// </summary>\r
139         /// <param name="x">比較されるマーカー</param>\r
140         /// <param name="y">比較するマーカー</param>\r
141         /// <returns>等しいなら真。そうでなければ偽</returns>\r
142         public bool Equals(Marker x, Marker y)\r
143         {\r
144             return x.hilight == y.hilight && x.length == y.length && x.start == y.start;\r
145         }\r
146 \r
147         /// <summary>\r
148         /// ハッシュを得ます\r
149         /// </summary>\r
150         /// <param name="obj">マーカー</param>\r
151         /// <returns>ハッシュ</returns>\r
152         public int GetHashCode(Marker obj)\r
153         {\r
154             return this.start ^ this.length ^ (int)this.hilight;\r
155         }\r
156     }\r
157 \r
158     /// <summary>\r
159     /// マーカークラスのコレクションを表します\r
160     /// </summary>\r
161     public sealed class MarkerCollection\r
162     {\r
163         Dictionary<int, RangeCollection<Marker>> collection = new Dictionary<int, RangeCollection<Marker>>();\r
164 \r
165         internal MarkerCollection(Document doc)\r
166         {\r
167             doc.UpdateCalledAlways += new DocumentUpdateEventHandler(doc_Update);\r
168             this.Updated +=new EventHandler((s,e)=>{});\r
169         }\r
170 \r
171         /// <summary>\r
172         /// 更新されたことを通知します\r
173         /// </summary>\r
174         public event EventHandler Updated;\r
175 \r
176         internal void Add(int id,Marker m)\r
177         {\r
178             this.AddImpl(id, m);\r
179             this.Updated(this, null);\r
180         }\r
181 \r
182         void AddImpl(int id, Marker m)\r
183         {\r
184             RangeCollection<Marker> markers;\r
185             if (this.collection.TryGetValue(id, out markers))\r
186             {\r
187                 markers.Remove(m.start, m.length);\r
188                 markers.Add(m);\r
189             }\r
190             else\r
191             {\r
192                 markers = new RangeCollection<Marker>();\r
193                 markers.Add(m);\r
194                 this.collection.Add(id, markers);\r
195             }\r
196         }\r
197 \r
198         internal void AddRange(int id, IEnumerable<Marker> collection)\r
199         {\r
200             foreach (Marker m in collection)\r
201                 this.AddImpl(id, m);\r
202             this.Updated(this, null);\r
203         }\r
204 \r
205         internal void RemoveAll(int id,int start, int length)\r
206         {\r
207             RangeCollection<Marker> markers;\r
208             if (this.collection.TryGetValue(id, out markers))\r
209             {\r
210                 markers.Remove(start, length);\r
211             }\r
212             this.Updated(this, null);\r
213         }\r
214 \r
215         internal void RemoveAll(int id, HilightType type)\r
216         {\r
217             RangeCollection<Marker> markers;\r
218             if (this.collection.TryGetValue(id, out markers))\r
219             {\r
220                 for (int i = 0; i < markers.Count; i++)\r
221                 {\r
222                     if (markers[i].hilight == type)\r
223                         markers.RemoveAt(i);\r
224                 }\r
225             }\r
226             this.Updated(this, null);\r
227         }\r
228 \r
229         internal IEnumerable<int> IDs\r
230         {\r
231             get\r
232             {\r
233                 return this.collection.Keys;\r
234             }\r
235         }\r
236 \r
237         internal IEnumerable<Marker> Get(int id)\r
238         {\r
239             RangeCollection<Marker> markers;\r
240             if (this.collection.TryGetValue(id, out markers))\r
241             {\r
242                 foreach (var m in markers)\r
243                     yield return m;\r
244             }\r
245             yield break;\r
246         }\r
247 \r
248         internal IEnumerable<Marker> Get(int id, int index)\r
249         {\r
250             RangeCollection<Marker> markers;\r
251             if (this.collection.TryGetValue(id, out markers))\r
252             {\r
253                 foreach (var m in markers.Get(index))\r
254                     yield return m;\r
255             }\r
256             yield break;\r
257         }\r
258 \r
259         internal IEnumerable<Marker> Get(int id, int index, int length)\r
260         {\r
261             RangeCollection<Marker> markers;\r
262             if (this.collection.TryGetValue(id, out markers))\r
263             {\r
264                 foreach (var m in markers.Get(index, length))\r
265                     yield return m;\r
266             }\r
267             yield break;\r
268         }\r
269 \r
270         /// <summary>\r
271         /// マーカーをすべて削除します\r
272         /// </summary>\r
273         /// <param name="id">マーカーID</param>\r
274         public void Clear(int id)\r
275         {\r
276             RangeCollection<Marker> markers;\r
277             if (this.collection.TryGetValue(id, out markers))\r
278                 markers.Clear();\r
279             this.Updated(this, null);\r
280         }\r
281 \r
282         /// <summary>\r
283         /// マーカーをすべて削除します\r
284         /// </summary>\r
285         public void Clear()\r
286         {\r
287             this.collection.Clear();\r
288             this.Updated(this, null);\r
289         }\r
290 \r
291         void doc_Update(object sender, DocumentUpdateEventArgs e)\r
292         {\r
293             int deltaLength = 0;\r
294             switch (e.type)\r
295             {\r
296                 case UpdateType.Replace:\r
297                     deltaLength = e.insertLength - e.removeLength;\r
298                     foreach (RangeCollection<Marker> markers in this.collection.Values)\r
299                     {\r
300                         for (int i = 0; i < markers.Count; i++)\r
301                         {\r
302                             Marker m = markers[i];\r
303                             if (m.start + m.length - 1 < e.startIndex)\r
304                             {\r
305                                 continue;\r
306                             }\r
307                             else\r
308                             {\r
309                                 m.start += deltaLength;\r
310                             }\r
311                             markers[i] = m;\r
312                         }\r
313                     }\r
314                     break;\r
315                 default:\r
316                     return;\r
317             }\r
318         }\r
319 \r
320     }\r
321 }\r