2 * Copyright (C) 2013 FooProject
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
4 * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
6 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
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/>.
12 using System.Collections.Generic;
14 using D2D = SharpDX.Direct2D1;
15 using DW = SharpDX.DirectWrite;
17 namespace FooEditEngine
19 sealed class InlineManager
22 DW.TextFormat _Format;
24 MultiSet<char, InlineChar> InlineChars = new MultiSet<char, InlineChar>();
25 MultiSet<double, InlineTab> InlineTabs = null;
26 ColorBrushCollection Brushes;
28 const int DuplicateCount = 2; //1だとDirectWriteが一つにまとめてしまう
30 public InlineManager(DW.Factory factory, DW.TextFormat format, Color4 fore, ColorBrushCollection brushes)
32 this.Factory = factory;
33 this._Format = format;
35 this.Brushes = brushes;
36 this.Brushes.RenderChanged += Brushes_RenderChanged;
39 public bool ContainsSymbol(char c)
41 if (c == '\t' && (this.InlineTabs == null || this.InlineTabs.Count > 0))
43 return this.InlineChars.ContainsKey(c);
46 public void AddSymbol(char c, char alt)
50 this.InlineTabs = new MultiSet<double,InlineTab>();
54 D2D.SolidColorBrush brush = this.Brushes.Get(this.Fore);
55 for (int i = 0; i < DuplicateCount; i++)
57 this.InlineChars.Add(c, new InlineChar(this.Factory, this.Format, brush, alt));
62 public void RemoveSymbol(char c)
65 this.InlineTabs = null;
67 this.InlineChars.Remove(c);
79 this.Format = this._Format;
83 public DW.TextFormat Format
93 this.TabWidth = this._TabWidth;
99 public double TabWidth
103 return this._TabWidth;
107 this._TabWidth = value;
108 if(this.InlineTabs != null)
109 this.InlineTabs.Clear();
113 public DW.InlineObject Get(MyTextLayout layout,int index, string str)
115 if (str[index] == '\t')
117 if (this.InlineTabs == null)
119 double x = layout.GetColPostionFromIndex(index);
120 if (layout.RightToLeft)
121 x = layout.MaxWidth - x;
123 if (index > 0 && str[index - 1] == '\t')
124 width = this._TabWidth;
126 width = this._TabWidth - x % this._TabWidth;
127 List<InlineTab> collection;
128 if (!this.InlineTabs.TryGet(width, out collection))
130 collection = new List<InlineTab>();
131 D2D.SolidColorBrush brush = this.Brushes.Get(this.Fore);
132 for (int i = 0; i < DuplicateCount; i++)
133 collection.Add(new InlineTab(brush, width,layout.Height));
134 this.InlineTabs.Add(width, collection);
136 return collection[index % DuplicateCount];
141 if (this.InlineChars.ContainsKey(c) == false)
143 return this.InlineChars.Get(c, index % DuplicateCount);
149 if(this.InlineChars != null)
150 this.InlineChars.Clear();
151 if(this.InlineTabs != null)
152 this.InlineTabs.Clear();
157 List<KeyValuePair<char, char>> list = new List<KeyValuePair<char, char>>(this.InlineChars.Count);
158 foreach (KeyValuePair<char, InlineChar> kv in this.InlineChars.EnumrateKeyAndFirstValue())
159 list.Add(new KeyValuePair<char, char>(kv.Key, kv.Value.AlternativeChar));
161 this.InlineChars.Clear();
163 if (this.InlineTabs == null)
166 this.InlineTabs.Clear();
168 D2D.SolidColorBrush brush = this.Brushes.Get(this.Fore);
169 foreach (KeyValuePair<char, char> kv in list)
170 for (int i = 0; i < DuplicateCount; i++)
171 this.InlineChars.Add(kv.Key, new InlineChar(this.Factory, this.Format, brush, kv.Value));
174 void Brushes_RenderChanged(object sender, EventArgs e)
179 sealed class MultiSet<T, J>
180 where J : IDisposable
182 Dictionary<T, List<J>> Collection = new Dictionary<T, List<J>>();
184 public void Add(T key, List<J> collection)
186 if (this.Collection.ContainsKey(key) == false)
187 this.Collection.Add(key, collection);
190 public void Add(T key, J value)
192 if (this.Collection.ContainsKey(key) == false)
193 this.Collection.Add(key, new List<J>());
194 this.Collection[key].Add(value);
201 return this.Collection.Count;
205 public bool ContainsKey(T key)
207 return this.Collection.ContainsKey(key);
210 public bool TryGet(T key, out List<J> value)
212 return this.Collection.TryGetValue(key, out value);
215 public J Get(T key,int index)
217 return this.Collection[key][index];
220 public void Remove(T key)
222 if (this.Collection.ContainsKey(key) == false)
224 foreach (J value in this.Collection[key])
226 this.Collection.Remove(key);
231 foreach (List<J> list in this.Collection.Values)
232 foreach (J value in list)
234 this.Collection.Clear();
237 public IEnumerable<KeyValuePair<T, J>> EnumrateKeyAndFirstValue()
239 foreach (KeyValuePair<T, List<J>> kv in this.Collection)
240 yield return new KeyValuePair<T, J>(kv.Key, kv.Value[0]);