OSDN Git Service

WPF版でDPIを96より大きな値にするとクリック位置がずれる問題を修正した
[fooeditengine/FooEditEngine.git] / WPF / FooEditEngine / FooTextBox.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.Text;\r
13 using System.Threading.Tasks;\r
14 using System.Runtime.InteropServices;\r
15 using System.Windows;\r
16 using System.Windows.Input;\r
17 using System.Windows.Media;\r
18 using System.Windows.Controls;\r
19 using System.Windows.Controls.Primitives;\r
20 using System.Windows.Documents;\r
21 using System.Windows.Interop;\r
22 using System.Windows.Threading;\r
23 using DotNetTextStore;\r
24 using DotNetTextStore.UnmanagedAPI.TSF;\r
25 using DotNetTextStore.UnmanagedAPI.WinDef;\r
26 using Microsoft.Win32;\r
27 \r
28 namespace FooEditEngine.WPF\r
29 {\r
30     /// <summary>\r
31     /// オートインデントを行うためのデリゲートを表す\r
32     /// </summary>\r
33     /// <param name="sender">イベント発生元のオブジェクト</param>\r
34     /// <param name="e">イベントデーター</param>\r
35     public delegate void AutoIndentHookerHandler(object sender,EventArgs e);\r
36 \r
37     /// <summary>\r
38     /// WPFでのFooTextBoxの実装\r
39     /// </summary>\r
40     public sealed class FooTextBox : Control, IDisposable\r
41     {\r
42         const double MaxFontSize = 72.0f;\r
43         const double MinFontSize = 1;\r
44 \r
45         EditView View;\r
46         Controller _Controller;\r
47         D2DRender Render;\r
48         Image image;\r
49         ScrollBar verticalScrollBar, horizontalScrollBar;\r
50         TextStore textStore;\r
51         DispatcherTimer timer;\r
52         bool disposed = false;\r
53         FooTextBoxAutomationPeer peer;\r
54         bool nowCaretMove = false;\r
55         \r
56         static FooTextBox()\r
57         {\r
58             DefaultStyleKeyProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(typeof(FooTextBox)));\r
59             KeyboardNavigation.IsTabStopProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(true));\r
60             KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(KeyboardNavigationMode.None));\r
61         }\r
62 \r
63         /// <summary>\r
64         /// コンストラクター\r
65         /// </summary>\r
66         public FooTextBox()\r
67         {\r
68             this.image = new Image();\r
69             this.image.Stretch = Stretch.Fill;\r
70             this.image.HorizontalAlignment = HorizontalAlignment.Left;\r
71             this.image.VerticalAlignment = VerticalAlignment.Top;\r
72 \r
73             this.textStore = new TextStore();\r
74             this.textStore.IsLoading += textStore_IsLoading;\r
75             this.textStore.IsReadOnly += textStore_IsReadOnly;\r
76             this.textStore.GetStringLength += () => this.Document.Length;\r
77             this.textStore.GetString += _textStore_GetString;\r
78             this.textStore.GetSelectionIndex += _textStore_GetSelectionIndex;\r
79             this.textStore.SetSelectionIndex += _textStore_SetSelectionIndex;\r
80             this.textStore.InsertAtSelection += _textStore_InsertAtSelection;\r
81             this.textStore.GetHWnd += _textStore_GetHWnd;\r
82             this.textStore.GetScreenExtent += _textStore_GetScreenExtent;\r
83             this.textStore.GetStringExtent += _textStore_GetStringExtent;\r
84             this.textStore.CompositionStarted += textStore_CompositionStarted;\r
85             this.textStore.CompositionUpdated += textStore_CompositionUpdated;\r
86             this.textStore.CompositionEnded += textStore_CompositionEnded;\r
87 \r
88             this.Render = new D2DRender(this, 200, 200,this.image);\r
89             this.Render.ShowFullSpace = this.ShowFullSpace;\r
90             this.Render.ShowHalfSpace = this.ShowHalfSpace;\r
91             this.Render.ShowTab = this.ShowTab;\r
92 \r
93             this.Document = new Document();\r
94             this.Document.LayoutLines.Render = this.Render;\r
95 \r
96             this.View = new EditView(this.Document, this.Render, new Padding(5, 5, 5, 5));\r
97             this.View.SrcChanged += View_SrcChanged;\r
98             this.View.InsertMode = this.InsertMode;\r
99             this.View.DrawLineNumber = this.DrawLineNumber;\r
100             this.View.HideCaret = !this.DrawCaret;\r
101             this.View.HideLineMarker = !this.DrawCaretLine;\r
102             this.View.HideRuler = !this.DrawRuler;\r
103             this.View.UrlMark = this.MarkURL;\r
104             this.View.TabStops = this.TabChars;\r
105 \r
106             this._Controller = new Controller(this.Document, this.View);\r
107             this._Controller.SelectionChanged += new EventHandler(Controller_SelectionChanged);\r
108 \r
109             //Viewを作成した後に追加しないと例外が発生する\r
110             this.Document.Update += new DocumentUpdateEventHandler(Document_Update);\r
111 \r
112             this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Copy, CopyCommand, CanExecute));\r
113             this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Cut, CutCommand, CanExecute));\r
114             this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, PasteCommand, CanExecute));\r
115             this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete, DeleteCommand, CanExecute));\r
116             this.CommandBindings.Add(new CommandBinding(ApplicationCommands.SelectAll, SelectAllCommand, CanExecute));\r
117             this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, UndoCommand, CanExecute));\r
118             this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, RedoCommand, CanExecute));\r
119             this.CommandBindings.Add(new CommandBinding(EditingCommands.ToggleInsert, ToggleInsertCommand, CanExecute));\r
120             this.CommandBindings.Add(new CommandBinding(FooTextBoxCommands.ToggleRectSelectMode, ToggleRectSelectCommand, CanExecute));\r
121             this.CommandBindings.Add(new CommandBinding(FooTextBoxCommands.ToggleFlowDirection, ToggleFlowDirectionCommand, CanExecute));\r
122             this.CommandBindings.Add(new CommandBinding(FooTextBoxCommands.ToggleCodePoint, ToggleCodePointCommand, CanExecute));\r
123 \r
124             this.InputBindings.Add(new InputBinding(ApplicationCommands.Copy, new KeyGesture(Key.C, ModifierKeys.Control)));\r
125             this.InputBindings.Add(new InputBinding(ApplicationCommands.Cut, new KeyGesture(Key.X, ModifierKeys.Control)));\r
126             this.InputBindings.Add(new InputBinding(ApplicationCommands.Paste, new KeyGesture(Key.V, ModifierKeys.Control)));\r
127             this.InputBindings.Add(new InputBinding(ApplicationCommands.Delete, new KeyGesture(Key.Delete, ModifierKeys.None)));\r
128             this.InputBindings.Add(new InputBinding(ApplicationCommands.SelectAll, new KeyGesture(Key.A, ModifierKeys.Control)));\r
129             this.InputBindings.Add(new InputBinding(ApplicationCommands.Undo, new KeyGesture(Key.Z, ModifierKeys.Control)));\r
130             this.InputBindings.Add(new InputBinding(ApplicationCommands.Redo, new KeyGesture(Key.Y, ModifierKeys.Control)));\r
131             this.InputBindings.Add(new InputBinding(EditingCommands.ToggleInsert, new KeyGesture(Key.Insert, ModifierKeys.None)));\r
132             this.InputBindings.Add(new InputBinding(FooTextBoxCommands.ToggleCodePoint, new KeyGesture(Key.X, ModifierKeys.Alt)));\r
133 \r
134             this.timer = new DispatcherTimer();\r
135             this.timer.Interval = new TimeSpan(0, 0, 0, 0, 100);\r
136             this.timer.Tick += new EventHandler(timer_Tick);\r
137 \r
138             this.Loaded += new RoutedEventHandler(FooTextBox_Loaded);\r
139 \r
140             this.AutoIndentHooker = (s,e)=>{};\r
141 \r
142             SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);\r
143 \r
144             this.SystemEvents_UserPreferenceChanged(null, new UserPreferenceChangedEventArgs(UserPreferenceCategory.Keyboard));\r
145 \r
146             this.CaretMoved += (s, e) => { };\r
147         }\r
148 \r
149         /// <summary>\r
150         /// ファイナライザー\r
151         /// </summary>\r
152         ~FooTextBox()\r
153         {\r
154             //Dispose(false)を呼び出すと落ちる\r
155             this.Dispose(false);\r
156         }\r
157 \r
158         /// <summary>\r
159         /// オートインデントを行うためのイベント\r
160         /// </summary>\r
161         public AutoIndentHookerHandler AutoIndentHooker;\r
162 \r
163         /// <summary>\r
164         /// テンプレートを適用します\r
165         /// </summary>\r
166         public override void OnApplyTemplate()\r
167         {\r
168             base.OnApplyTemplate();\r
169 \r
170             Grid grid = this.GetTemplateChild("PART_Grid") as Grid;\r
171             if (grid != null)\r
172             {\r
173                 Grid.SetRow(this.image, 0);\r
174                 Grid.SetColumn(this.image, 0);\r
175                 grid.Children.Add(this.image);\r
176             }\r
177 \r
178             this.horizontalScrollBar = this.GetTemplateChild("PART_HorizontalScrollBar") as ScrollBar;\r
179             if (this.horizontalScrollBar != null)\r
180             {\r
181                 this.horizontalScrollBar.SmallChange = 10;\r
182                 this.horizontalScrollBar.LargeChange = 100;\r
183                 this.horizontalScrollBar.Maximum = this.horizontalScrollBar.LargeChange + 1;\r
184                 this.horizontalScrollBar.Scroll += new ScrollEventHandler(horizontalScrollBar_Scroll);\r
185             }\r
186             this.verticalScrollBar = this.GetTemplateChild("PART_VerticalScrollBar") as ScrollBar;\r
187             if (this.verticalScrollBar != null)\r
188             {\r
189                 this.verticalScrollBar.SmallChange = 1;\r
190                 this.verticalScrollBar.LargeChange = 10;\r
191                 this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;\r
192                 this.verticalScrollBar.Scroll += new ScrollEventHandler(verticalScrollBar_Scroll);\r
193             }\r
194         }\r
195 \r
196         /// <summary>\r
197         /// ドキュメントを選択する\r
198         /// </summary>\r
199         /// <param name="start">開始インデックス</param>\r
200         /// <param name="length">長さ</param>\r
201         public void Select(int start, int length)\r
202         {\r
203             this._Controller.Select(start, length);\r
204             this.textStore.NotifySelectionChanged();\r
205         }\r
206 \r
207         /// <summary>\r
208         /// キャレットを指定した行に移動させます\r
209         /// </summary>\r
210         /// <param name="index">インデックス</param>\r
211         /// <remarks>このメソッドを呼び出すと選択状態は解除されます</remarks>\r
212         public void JumpCaret(int index)\r
213         {\r
214             this._Controller.JumpCaret(index);\r
215         }\r
216         /// <summary>\r
217         /// キャレットを指定した行と桁に移動させます\r
218         /// </summary>\r
219         /// <param name="row">行番号</param>\r
220         /// <param name="col">桁</param>\r
221         /// <remarks>このメソッドを呼び出すと選択状態は解除されます</remarks>\r
222         public void JumpCaret(int row, int col)\r
223         {\r
224             this._Controller.JumpCaret(row, col);\r
225         }\r
226 \r
227         /// <summary>\r
228         /// 選択中のテキストをクリップボードにコピーします\r
229         /// </summary>\r
230         public void Copy()\r
231         {\r
232             string text = this._Controller.SelectedText;\r
233             if (text != null && text != string.Empty)\r
234                 Clipboard.SetText(text);\r
235         }\r
236 \r
237         /// <summary>\r
238         /// 選択中のテキストをクリップボードに切り取ります\r
239         /// </summary>\r
240         public void Cut()\r
241         {\r
242             string text = this._Controller.SelectedText;\r
243             if (text != null && text != string.Empty)\r
244             {\r
245                 Clipboard.SetText(text);\r
246                 this._Controller.SelectedText = "";\r
247             }\r
248         }\r
249 \r
250         /// <summary>\r
251         /// 選択中のテキストを貼り付けます\r
252         /// </summary>\r
253         public void Paste()\r
254         {\r
255             if (Clipboard.ContainsText() == false)\r
256                 return;\r
257             string text = Clipboard.GetText();\r
258             this._Controller.SelectedText = text;\r
259         }\r
260 \r
261         /// <summary>\r
262         /// 選択を解除する\r
263         /// </summary>\r
264         public void DeSelectAll()\r
265         {\r
266             this._Controller.DeSelectAll();\r
267             this.textStore.NotifySelectionChanged();\r
268         }\r
269 \r
270         /// <summary>\r
271         /// 対応する座標を返します\r
272         /// </summary>\r
273         /// <param name="tp">テキストポイント</param>\r
274         /// <returns>座標</returns>\r
275         /// <remarks>テキストポイントがクライアント領域の原点より外にある場合、返される値は原点に丸められます</remarks>\r
276         public System.Windows.Point GetPostionFromTextPoint(TextPoint tp)\r
277         {\r
278             if (this.Document.FireUpdateEvent == false)\r
279                 throw new InvalidOperationException("");\r
280             return this.View.GetPostionFromTextPoint(tp);\r
281         }\r
282 \r
283         /// <summary>\r
284         /// 対応するテキストポイントを返します\r
285         /// </summary>\r
286         /// <param name="p">クライアント領域の原点を左上とする座標</param>\r
287         /// <returns>テキストポイント</returns>\r
288         public TextPoint GetTextPointFromPostion(System.Windows.Point p)\r
289         {\r
290             if (this.Document.FireUpdateEvent == false)\r
291                 throw new InvalidOperationException("");\r
292             return this.View.GetTextPointFromPostion(p);\r
293         }\r
294 \r
295         /// <summary>\r
296         /// 行の高さを取得します\r
297         /// </summary>\r
298         /// <param name="row">レイアウト行</param>\r
299         /// <returns>行の高さ</returns>\r
300         public double GetLineHeight(int row)\r
301         {\r
302             if (this.Document.FireUpdateEvent == false)\r
303                 throw new InvalidOperationException("");\r
304             return this.View.LayoutLines.GetLayout(row).Height;;\r
305         }\r
306 \r
307         /// <summary>\r
308         /// インデックスに対応する座標を得ます\r
309         /// </summary>\r
310         /// <param name="index">インデックス</param>\r
311         /// <returns>座標を返す</returns>\r
312         public System.Windows.Point GetPostionFromIndex(int index)\r
313         {\r
314             if (this.Document.FireUpdateEvent == false)\r
315                 throw new InvalidOperationException("");\r
316             TextPoint tp = this.View.GetLayoutLineFromIndex(index);\r
317             return this.View.GetPostionFromTextPoint(tp);\r
318         }\r
319 \r
320         /// <summary>\r
321         /// 座標からインデックスに変換します\r
322         /// </summary>\r
323         /// <param name="p">座標</param>\r
324         /// <returns>インデックスを返す</returns>\r
325         public int GetIndexFromPostion(System.Windows.Point p)\r
326         {\r
327             if (this.Document.FireUpdateEvent == false)\r
328                 throw new InvalidOperationException("");\r
329             TextPoint tp = this.View.GetTextPointFromPostion(p);\r
330             return this.View.GetIndexFromLayoutLine(tp);\r
331         }\r
332 \r
333         /// <summary>\r
334         /// 再描写する\r
335         /// </summary>\r
336         public void Refresh()\r
337         {\r
338             this.Refresh(this.View.PageBound);\r
339         }\r
340 \r
341         /// <summary>\r
342         /// レイアウト行をすべて破棄し、再度レイアウトを行う\r
343         /// </summary>\r
344         public void PerfomLayouts()\r
345         {\r
346             this.View.PerfomLayouts();\r
347         }\r
348 \r
349         /// <summary>\r
350         /// 指定行までスクロールする\r
351         /// </summary>\r
352         /// <param name="row">行</param>\r
353         /// <param name="alignTop">指定行を画面上に置くなら真。そうでないなら偽</param>\r
354         public void ScrollIntoView(int row, bool alignTop)\r
355         {\r
356             this.View.ScrollIntoView(row, alignTop);\r
357         }\r
358 \r
359         /// <summary>\r
360         /// ストリームからドキュメントを構築する\r
361         /// </summary>\r
362         /// <param name="tr">TextReader</param>\r
363         /// <param name="token">キャンセル用トークン</param>\r
364         /// <returns>Taskオブジェクト</returns>\r
365         public async Task LoadAsync(System.IO.TextReader tr, System.Threading.CancellationTokenSource token)\r
366         {\r
367             WinFileReader fs = new WinFileReader(tr);\r
368             await this.LoadAsyncImpl(fs, token);\r
369         }\r
370 \r
371         /// <summary>\r
372         /// ファイルからドキュメントを構築する\r
373         /// </summary>\r
374         /// <param name="filepath">ファイルパス</param>\r
375         /// <param name="enc">エンコード</param>\r
376         /// <param name="token">キャンセル用トークン</param>\r
377         /// <returns>Taskオブジェクト</returns>\r
378         public async Task LoadFileAsync(string filepath, Encoding enc,System.Threading.CancellationTokenSource token)\r
379         {\r
380             WinFileReader fs = new WinFileReader(filepath, enc);\r
381             await this.LoadAsyncImpl(fs, token);\r
382             fs.Close();\r
383         }\r
384 \r
385         async Task LoadAsyncImpl(WinFileReader fs,System.Threading.CancellationTokenSource token)\r
386         {\r
387             this.IsEnabled = false;\r
388             this.View.LayoutLines.IsFrozneDirtyFlag = true;\r
389             await this.Document.LoadAsync(fs, token);\r
390             this.View.LayoutLines.IsFrozneDirtyFlag = false;\r
391             TextStoreHelper.NotifyTextChanged(this.textStore, 0, 0, this.Document.Length);\r
392             if (this.verticalScrollBar != null)\r
393                 this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;\r
394             this.View.CalculateLineCountOnScreen();\r
395             this.IsEnabled = true;\r
396         }\r
397 \r
398         /// <summary>\r
399         /// ドキュメントの内容をファイルに保存する\r
400         /// </summary>\r
401         /// <param name="filepath">ファイルパス</param>\r
402         /// <param name="newLine">改行コード</param>\r
403         /// <param name="enc">エンコード</param>\r
404         /// <returns>Taskオブジェクト</returns>\r
405         public async Task SaveFile(string filepath, Encoding enc,string newLine, System.Threading.CancellationTokenSource token)\r
406         {\r
407             WinFileWriter fs = new WinFileWriter(filepath, enc);\r
408             fs.NewLine = newLine;\r
409             await this.Document.SaveAsync(fs, token);\r
410             fs.Close();\r
411         }\r
412 \r
413         /// <summary>\r
414         /// アンマネージドリソースを開放する\r
415         /// </summary>\r
416         public void Dispose()\r
417         {\r
418             if (this.disposed)\r
419                 return;\r
420             this.Dispose(true);\r
421             GC.SuppressFinalize(this);\r
422             this.disposed = true;\r
423         }\r
424 \r
425         /// <summary>\r
426         /// リソースを開放する\r
427         /// </summary>\r
428         /// <param name="disposing">真ならマネージドリソースも開放し、そうでないならアンマネージドリソースのみを開放する</param>\r
429         void Dispose(bool disposing)\r
430         {\r
431             if (disposing)\r
432             {\r
433                 this.textStore.Dispose();\r
434                 this.timer.Stop();\r
435                 this.View.Dispose();\r
436                 this.Render.Dispose();\r
437             }\r
438             SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);\r
439         }\r
440         \r
441         void Refresh(Rectangle updateRect)\r
442         {\r
443             if (this.disposed || this.Visibility == Visibility.Collapsed)\r
444                 return;\r
445 \r
446             this.Render.BegineDraw();\r
447             if (this.IsEnabled)\r
448                 this.View.Draw(updateRect);\r
449             else\r
450                 this.Render.FillBackground(updateRect);\r
451             this.Render.EndDraw();\r
452         }\r
453 \r
454         #region Commands\r
455         void CanExecute(object sender, CanExecuteRoutedEventArgs e)\r
456         {\r
457             e.CanExecute = this.IsEnabled;\r
458         }\r
459 \r
460         void ToggleCodePointCommand(object sender, RoutedEventArgs e)\r
461         {\r
462             if (!this._Controller.ConvertToChar())\r
463                 this._Controller.ConvertToCodePoint();\r
464             this.Refresh();\r
465         }\r
466 \r
467         void CopyCommand(object sender, RoutedEventArgs e)\r
468         {\r
469             this.Copy();\r
470         }\r
471 \r
472         void CutCommand(object sender, RoutedEventArgs e)\r
473         {\r
474             this.Cut();\r
475             this.Refresh();\r
476         }\r
477 \r
478         void PasteCommand(object sender, RoutedEventArgs e)\r
479         {\r
480             this.Paste();\r
481             this.Refresh();\r
482         }\r
483 \r
484         void DeleteCommand(object sender, RoutedEventArgs e)\r
485         {\r
486             int oldLength = this.Document.Length;\r
487             this._Controller.DoDeleteAction();\r
488             this.Refresh();\r
489         }\r
490 \r
491         void SelectAllCommand(object sender, RoutedEventArgs e)\r
492         {\r
493             this.Select(0, this.Document.Length);\r
494             this.Refresh();\r
495         }\r
496 \r
497         void UndoCommand(object sender, RoutedEventArgs e)\r
498         {\r
499             int oldLength = this.Document.Length;\r
500             this.Document.UndoManager.undo();\r
501             this.Refresh();\r
502         }\r
503 \r
504         void RedoCommand(object sender, RoutedEventArgs e)\r
505         {\r
506             int oldLength = this.Document.Length;\r
507             this.Document.UndoManager.redo();\r
508             this.Refresh();\r
509         }\r
510 \r
511         void ToggleInsertCommand(object sender, RoutedEventArgs e)\r
512         {\r
513             if (this.InsertMode)\r
514                 this.InsertMode = false;\r
515             else\r
516                 this.InsertMode = true;\r
517             this.Refresh();\r
518         }\r
519 \r
520         void ToggleRectSelectCommand(object sender, RoutedEventArgs e)\r
521         {\r
522             if (this.RectSelectMode)\r
523                 this.RectSelectMode = false;\r
524             else\r
525                 this.RectSelectMode = true;\r
526             this.Refresh();\r
527         }\r
528         void ToggleFlowDirectionCommand(object sender, RoutedEventArgs e)\r
529         {\r
530             if (this.FlowDirection == System.Windows.FlowDirection.LeftToRight)\r
531                 this.FlowDirection = System.Windows.FlowDirection.RightToLeft;\r
532             else\r
533                 this.FlowDirection = System.Windows.FlowDirection.LeftToRight;\r
534             this.Refresh();\r
535         }\r
536         #endregion\r
537         #region TSF\r
538         internal TextStore TextStore\r
539         {\r
540             get { return this.textStore; }\r
541         }\r
542 \r
543         bool textStore_IsReadOnly()\r
544         {\r
545             return false;\r
546         }\r
547 \r
548         bool textStore_IsLoading()\r
549         {\r
550             return false;\r
551         }\r
552 \r
553         void textStore_CompositionEnded()\r
554         {\r
555             TextStoreHelper.EndCompostion(this.Document);\r
556             this.Refresh();\r
557         }\r
558 \r
559         void textStore_CompositionUpdated(int start, int end)\r
560         {\r
561             if (TextStoreHelper.ScrollToCompstionUpdated(this.textStore, this.View, start, end))\r
562                 this.Refresh();\r
563         }\r
564         bool textStore_CompositionStarted()\r
565         {\r
566             bool result = TextStoreHelper.StartCompstion(this.Document);\r
567             if (!result)\r
568                 System.Media.SystemSounds.Beep.Play();\r
569             return result;\r
570         }\r
571 \r
572         string _textStore_GetString(int start, int length)\r
573         {\r
574             return this.Document.ToString(start, length);\r
575         }\r
576 \r
577         IntPtr _textStore_GetHWnd()\r
578         {\r
579             var hwndSource = HwndSource.FromVisual(this) as HwndSource;\r
580             if (hwndSource != null)\r
581                 return hwndSource.Handle;\r
582             else\r
583                 return IntPtr.Zero;\r
584         }\r
585 \r
586         void _textStore_GetStringExtent(\r
587             int i_startIndex,\r
588             int i_endIndex,\r
589             out POINT o_topLeft,\r
590             out POINT o_bottomRight\r
591         )\r
592         {\r
593             Point startPos, endPos;\r
594             TextStoreHelper.GetStringExtent(this.Document, this.View, i_startIndex, i_endIndex, out startPos, out endPos);\r
595 \r
596             float dpi;\r
597             this.Render.GetDpi(out dpi, out dpi);\r
598             double scale = dpi / 96.0;\r
599             \r
600             startPos = PointToScreen(this.TranslatePoint(startPos.Scale(scale), this));\r
601             endPos = PointToScreen(this.TranslatePoint(endPos.Scale(scale), this));\r
602             \r
603             o_topLeft = new POINT((int)startPos.X, (int)startPos.Y);\r
604             o_bottomRight = new POINT((int)endPos.X, (int)endPos.Y);\r
605         }\r
606 \r
607         void _textStore_GetScreenExtent(out POINT o_topLeft, out POINT o_bottomRight)\r
608         {\r
609             var pointTopLeft = new Point(0, 0);\r
610             var pointBottomRight = new Point(this.RenderSize.Width, this.RenderSize.Height);\r
611 \r
612             pointTopLeft = PointToScreen(pointTopLeft);\r
613             pointBottomRight = PointToScreen(pointBottomRight);\r
614 \r
615             o_topLeft = new POINT((int)pointTopLeft.X, (int)pointTopLeft.Y);\r
616             o_bottomRight = new POINT((int)pointBottomRight.X, (int)pointBottomRight.Y);\r
617         }\r
618 \r
619         void _textStore_GetSelectionIndex(out int o_startIndex, out int o_endIndex)\r
620         {\r
621             TextStoreHelper.GetSelection(this._Controller, this.View.Selections, out o_startIndex, out o_endIndex);\r
622         }\r
623 \r
624         void _textStore_SetSelectionIndex(int i_startIndex, int i_endIndex)\r
625         {\r
626             TextStoreHelper.SetSelectionIndex(this._Controller, this.View, i_startIndex, i_endIndex);\r
627             this.Refresh();\r
628         }\r
629 \r
630         void _textStore_InsertAtSelection(string i_value, ref int o_startIndex, ref int o_endIndex)\r
631         {\r
632             TextStoreHelper.InsertTextAtSelection(this._Controller, i_value);\r
633             this.Refresh();\r
634         }\r
635 \r
636         /// <summary>\r
637         /// キーボードフォーカスが取得されたときに呼ばれます\r
638         /// </summary>\r
639         /// <param name="e">イベントデーター</param>\r
640         protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)\r
641         {\r
642             base.OnGotKeyboardFocus(e);\r
643             this.textStore.SetFocus();\r
644             this.View.IsFocused = true;\r
645             this.Refresh();\r
646         }\r
647 \r
648         /// <summary>\r
649         /// キーボードフォーカスが失われたときに呼ばれます\r
650         /// </summary>\r
651         /// <param name="e">イベントデーター</param>\r
652         protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)\r
653         {\r
654             base.OnLostKeyboardFocus(e);\r
655             this.View.IsFocused = false;\r
656             this.Refresh();\r
657         }\r
658         #endregion\r
659         #region Event\r
660         /// <summary>\r
661         /// キャレットが移動したときに通知されるイベント\r
662         /// </summary>\r
663         public event EventHandler CaretMoved;\r
664 \r
665         /// <inheritdoc/>\r
666         protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()\r
667         {\r
668             this.peer = new FooTextBoxAutomationPeer(this);\r
669             return this.peer;\r
670         }\r
671 \r
672 \r
673         /// <inheritdoc/>\r
674         protected override void OnTextInput(TextCompositionEventArgs e)\r
675         {\r
676             if (e.Text == "\r")\r
677             {\r
678                 this._Controller.DoEnterAction();\r
679                 this.AutoIndentHooker(this, null);\r
680             }\r
681             else if (e.Text == "\b")\r
682             {\r
683                 this._Controller.DoBackSpaceAction();\r
684             }\r
685             else\r
686             {\r
687                 if(this.IsInputString(e.Text))\r
688                     this._Controller.DoInputString(e.Text);\r
689             }\r
690             this.Refresh();\r
691             base.OnTextInput(e);\r
692             e.Handled = true;\r
693         }\r
694 \r
695         bool IsInputString(string s)\r
696         {\r
697             foreach (char charCode in s)\r
698             {\r
699                 if ((0x20 <= charCode && charCode <= 0x7e)\r
700                     || 0x7f < charCode)\r
701                     return true;\r
702             }\r
703             return false;\r
704         }\r
705 \r
706         /// <inheritdoc/>\r
707         protected override void OnKeyDown(KeyEventArgs e)\r
708         {\r
709             if (this.textStore.IsLocked())\r
710                 return;\r
711 \r
712             ModifierKeys modiferKeys = e.KeyboardDevice.Modifiers;\r
713             bool movedCaret = false;\r
714             switch (e.Key)\r
715             {\r
716                 case Key.Up:\r
717                     this._Controller.MoveCaretVertical(-1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));\r
718                     this.Refresh();\r
719                     e.Handled = true;\r
720                     movedCaret = true;\r
721                     break;\r
722                 case Key.Down:\r
723                     this._Controller.MoveCaretVertical(+1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));\r
724                     this.Refresh();\r
725                     e.Handled = true;\r
726                     movedCaret = true;\r
727                     break;\r
728                 case Key.Left:\r
729                     this._Controller.MoveCaretHorizontical(-1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift), this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control));\r
730                     this.Refresh();\r
731                     e.Handled = true;\r
732                     movedCaret = true;\r
733                     break;\r
734                 case Key.Right:\r
735                     this._Controller.MoveCaretHorizontical(1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift), this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control));\r
736                     this.Refresh();\r
737                     e.Handled = true;\r
738                     movedCaret = true;\r
739                     break;\r
740                 case Key.PageUp:\r
741                     this._Controller.Scroll(ScrollDirection.Up,this.View.LineCountOnScreen, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift),true);\r
742                     this.Refresh();\r
743                     movedCaret = true;\r
744                     break;\r
745                 case Key.PageDown:\r
746                     this._Controller.Scroll(ScrollDirection.Down,this.View.LineCountOnScreen, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift),true);\r
747                     this.Refresh();\r
748                     movedCaret = true;\r
749                     break;\r
750                 case Key.Home:\r
751                     if (this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control))\r
752                         this._Controller.JumpToHead(this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));\r
753                     else\r
754                         this._Controller.JumpToLineHead(this.View.CaretPostion.row, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));\r
755                     this.Refresh();\r
756                     movedCaret = true;\r
757                     break;\r
758                 case Key.End:\r
759                     if (this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control))\r
760                         this._Controller.JumpToEnd(this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));\r
761                     else\r
762                         this._Controller.JumpToLineEnd(this.View.CaretPostion.row, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));\r
763                     this.Refresh();\r
764                     movedCaret = true;\r
765                     break;\r
766                 case Key.Tab:\r
767                     int oldLength = this.Document.Length;\r
768                     if (this.Selection.Length == 0)\r
769                         this._Controller.DoInputChar('\t');\r
770                     else if(this.IsPressedModifierKey(modiferKeys,ModifierKeys.Shift))\r
771                         this._Controller.DownIndent();\r
772                     else\r
773                         this._Controller.UpIndent();\r
774                     this.Refresh();\r
775                     e.Handled = true;\r
776                     break;\r
777             }\r
778             if (movedCaret && this.peer != null)\r
779                 this.peer.OnNotifyCaretChanged();\r
780             base.OnKeyDown(e);\r
781         }\r
782 \r
783         bool IsPressedModifierKey(ModifierKeys keys, ModifierKeys pressed)\r
784         {\r
785             if (keys == pressed)\r
786                 return true;\r
787             if ((keys & pressed) == pressed)\r
788                 return true;\r
789             return false;\r
790         }\r
791 \r
792         /// <summary>\r
793         /// ダブルクリックされたときに呼ばれます\r
794         /// </summary>\r
795         /// <param name="e">イベントパラメーター</param>\r
796         /// <remarks>\r
797         /// イベントパラメーターはFooMouseEventArgsにキャスト可能です。\r
798         /// e.Handledを真にした場合、単語単位の選択が行われなくなります\r
799         /// </remarks>\r
800         protected override void OnMouseDoubleClick(MouseButtonEventArgs e)\r
801         {\r
802             System.Windows.Point p = e.GetPosition(this);\r
803             TextPoint tp = this.View.GetTextPointFromPostion(p);\r
804             if (tp == TextPoint.Null)\r
805                 return;\r
806             int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);\r
807 \r
808             FooMouseButtonEventArgs newEventArgs = new FooMouseButtonEventArgs(e.MouseDevice,\r
809                 e.Timestamp,\r
810                 e.ChangedButton,\r
811                 e.StylusDevice,\r
812                 index);\r
813             newEventArgs.RoutedEvent = e.RoutedEvent;\r
814             base.OnMouseDoubleClick(newEventArgs);\r
815 \r
816             if (newEventArgs.Handled)\r
817                 return;\r
818 \r
819             if (e.LeftButton == MouseButtonState.Pressed)\r
820             {\r
821 \r
822                 this._Controller.SelectWord(index);\r
823                 this.textStore.NotifySelectionChanged();\r
824                 if(this.peer != null)\r
825                     this.peer.OnNotifyCaretChanged();\r
826                 this.Refresh();\r
827             }\r
828         }\r
829 \r
830         /// <summary>\r
831         /// マウスボタンが押されたときに呼ばれます\r
832         /// </summary>\r
833         /// <param name="e">イベントパラメーター</param>\r
834         /// <remarks>\r
835         /// イベントパラメーターはFooMouseEventArgsにキャスト可能です。\r
836         /// e.Handledを真にした場合、キャレットの移動処理が行われなくなります\r
837         /// </remarks>\r
838         protected override void OnMouseDown(MouseButtonEventArgs e)\r
839         {\r
840             var p = this.GetDipFromPoint(e.GetPosition(this));\r
841             TextPoint tp = this.View.GetTextPointFromPostion(p);\r
842             if (tp == TextPoint.Null)\r
843                 return;\r
844             int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);\r
845 \r
846             FooMouseButtonEventArgs newEventArgs = new FooMouseButtonEventArgs(e.MouseDevice,\r
847                 e.Timestamp,\r
848                 e.ChangedButton,\r
849                 e.StylusDevice,\r
850                 index);\r
851             newEventArgs.RoutedEvent = e.RoutedEvent;\r
852             base.OnMouseDown(newEventArgs);\r
853 \r
854             if (newEventArgs.Handled)\r
855                 return;\r
856 \r
857             if (e.LeftButton == MouseButtonState.Pressed)\r
858             {\r
859                 FoldingItem foldingData = this.View.HitFoldingData(p.X,tp.row);\r
860                 if (foldingData != null)\r
861                 {\r
862                     if (foldingData.Expand)\r
863                         this.View.LayoutLines.FoldingCollection.Collapse(foldingData);\r
864                     else\r
865                         this.View.LayoutLines.FoldingCollection.Expand(foldingData);\r
866                     this._Controller.JumpCaret(foldingData.Start,false);\r
867                 }\r
868                 else\r
869                 {\r
870                     this._Controller.JumpCaret(tp.row, tp.col, false);\r
871                 }\r
872                 if (this.peer != null)\r
873                     this.peer.OnNotifyCaretChanged();\r
874                 this.View.IsFocused = true;\r
875                 this.Focus();\r
876                 this.Refresh();\r
877             }\r
878         }\r
879 \r
880         /// <summary>\r
881         /// マウスが移動したときに呼ばれます\r
882         /// </summary>\r
883         /// <param name="e">イベントパラメーター</param>\r
884         /// <remarks>\r
885         /// イベントパラメーターはFooMouseEventArgsにキャスト可能です。\r
886         /// e.Handledを真にした場合、選択処理と状況に応じたカーソルの変化が行われなくなります\r
887         /// </remarks>\r
888         protected override void  OnMouseMove(MouseEventArgs e)\r
889         {\r
890             var p = this.GetDipFromPoint(e.GetPosition(this));\r
891             TextPoint tp = this.View.GetTextPointFromPostion(p);\r
892             if (tp == TextPoint.Null)\r
893             {\r
894                 base.OnMouseMove(e);\r
895                 return;\r
896             }\r
897             int index = this.View.GetIndexFromLayoutLine(tp);\r
898 \r
899             FooMouseEventArgs newEventArgs = new FooMouseEventArgs(e.MouseDevice, e.Timestamp, e.StylusDevice, index);\r
900             newEventArgs.RoutedEvent = e.RoutedEvent;\r
901             base.OnMouseMove(newEventArgs);\r
902 \r
903             if (newEventArgs.Handled)\r
904                 return;\r
905 \r
906             if (this.View.HitTextArea(p.X,p.Y))\r
907             {\r
908                 if (this._Controller.IsMarker(tp, HilightType.Url))\r
909                     this.Cursor = Cursors.Hand;\r
910                 else\r
911                     this.Cursor = Cursors.IBeam;\r
912 \r
913                 if (e.LeftButton == MouseButtonState.Pressed)\r
914                 {\r
915                     this._Controller.MoveCaretAndSelect(tp);\r
916                     if (this.peer != null)\r
917                         this.peer.OnNotifyCaretChanged();\r
918                     this.Refresh();\r
919                 }\r
920             }\r
921             else\r
922             {\r
923                 this.Cursor = Cursors.Arrow;\r
924             }\r
925         }\r
926 \r
927         private Point GetDipFromPoint(Point p)\r
928         {\r
929             float dpi;\r
930             this.Render.GetDpi(out dpi,out dpi);\r
931             double scale = dpi / 96.0;\r
932             return p.Scale(1 / scale);\r
933         }\r
934 \r
935         /// <inheritdoc/>\r
936         protected override void OnMouseWheel(MouseWheelEventArgs e)\r
937         {\r
938             if(Keyboard.Modifiers == ModifierKeys.None)\r
939             {\r
940                 if (e.Delta > 0)\r
941                     this._Controller.Scroll(ScrollDirection.Up, SystemParameters.WheelScrollLines, false, false);\r
942                 else\r
943                     this._Controller.Scroll(ScrollDirection.Down, SystemParameters.WheelScrollLines, false, false);\r
944             }\r
945             else if (Keyboard.Modifiers == ModifierKeys.Control)\r
946             {\r
947                 double newFontSize = this.Render.FontSize;\r
948                 if (e.Delta > 0)\r
949                     newFontSize++;\r
950                 else\r
951                     newFontSize--;\r
952                 if (newFontSize > MaxFontSize)\r
953                     newFontSize = 72;\r
954                 else if (newFontSize < MinFontSize)\r
955                     newFontSize = 1;\r
956                 this.Render.FontSize = newFontSize;\r
957                 SetValue(MagnificationPowerPropertyKey, this.Render.FontSize / this.FontSize);\r
958             }\r
959             this.Refresh();\r
960             base.OnMouseWheel(e);\r
961         }\r
962 \r
963         void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)\r
964         {\r
965             if (e.Category == UserPreferenceCategory.Keyboard)\r
966             {\r
967                 int blinkTime = (int)NativeMethods.GetCaretBlinkTime();\r
968                 this.View.CaretBlink = blinkTime >= 0;\r
969                 this.View.CaretBlinkTime = blinkTime * 2;\r
970             }\r
971             if (e.Category == UserPreferenceCategory.General)\r
972             {\r
973                 this.View.CaretWidthOnInsertMode = SystemParameters.CaretWidth;\r
974             }\r
975         }\r
976 \r
977         void Document_Update(object sender, DocumentUpdateEventArgs e)\r
978         {\r
979             if (this.textStore.IsLocked())\r
980                 return;\r
981             TextStoreHelper.NotifyTextChanged(this.textStore, e.startIndex, e.removeLength, e.insertLength);\r
982         }\r
983 \r
984         void timer_Tick(object sender, EventArgs e)\r
985         {\r
986             if (this.image.ActualWidth == 0 || this.image.ActualHeight == 0)\r
987                 return;\r
988             if (this.Resize(this.image.ActualWidth, this.image.ActualHeight))\r
989             {\r
990                 this.Refresh();\r
991                 return;\r
992             } \r
993             \r
994             ITextLayout layout = this.View.LayoutLines.GetLayout(this.View.CaretPostion.row);\r
995             double width = layout.GetWidthFromIndex(this.View.CaretPostion.col);\r
996             if (width == 0.0)\r
997                 width = this.View.CaretWidthOnInsertMode;\r
998             double height = layout.Height;\r
999             Rectangle updateRect = new Rectangle(\r
1000                 this.View.CaretLocation.X,\r
1001                 this.View.CaretLocation.Y,\r
1002                 width,\r
1003                 height);\r
1004 \r
1005             this.Refresh(updateRect);\r
1006         }\r
1007 \r
1008         void horizontalScrollBar_Scroll(object sender, ScrollEventArgs e)\r
1009         {\r
1010             if (this.horizontalScrollBar == null)\r
1011                 return;\r
1012             double toX;\r
1013             if (this.FlowDirection == System.Windows.FlowDirection.LeftToRight)\r
1014                 toX = this.horizontalScrollBar.Value;\r
1015             else\r
1016                 toX = -this.horizontalScrollBar.Value;\r
1017             this._Controller.Scroll(toX, this.View.Src.Row, false, false);\r
1018             this.Refresh();\r
1019         }\r
1020 \r
1021         void verticalScrollBar_Scroll(object sender, ScrollEventArgs e)\r
1022         {\r
1023             if (this.verticalScrollBar == null)\r
1024                 return;\r
1025             int newRow = (int)this.verticalScrollBar.Value;\r
1026             if (newRow >= this.View.LayoutLines.Count)\r
1027                 return;\r
1028             this._Controller.Scroll(this.View.Src.X,newRow, false, false);\r
1029             this.Refresh();\r
1030         }\r
1031 \r
1032         void View_SrcChanged(object sender, EventArgs e)\r
1033         {\r
1034             if (this.horizontalScrollBar == null || this.verticalScrollBar == null)\r
1035                 return;\r
1036             EditView view = this.View;\r
1037             if (view.Src.Row > this.verticalScrollBar.Maximum)\r
1038                 this.verticalScrollBar.Maximum = view.Src.Row + view.LineCountOnScreen + 1;\r
1039             double absoulteX = Math.Abs(view.Src.X);\r
1040             if(absoulteX > this.horizontalScrollBar.Maximum)\r
1041                 this.horizontalScrollBar.Maximum = absoulteX + view.PageBound.Width + 1;\r
1042             if(view.Src.Row != this.verticalScrollBar.Value)\r
1043                 this.verticalScrollBar.Value = view.Src.Row;\r
1044             if (view.Src.X != this.horizontalScrollBar.Value)\r
1045                 this.horizontalScrollBar.Value = Math.Abs(view.Src.X);\r
1046         }\r
1047 \r
1048         void Controller_SelectionChanged(object sender, EventArgs e)\r
1049         {\r
1050             this.View.CaretBlink = this.View.CaretBlink;\r
1051             this.CaretMoved(this, null);\r
1052             //こうしないと選択できなくなってしまう\r
1053             this.nowCaretMove = true;\r
1054             SetValue(SelectionProperty, new TextRange(this._Controller.SelectionStart, this._Controller.SelectionLength));\r
1055             SetValue(CaretPostionProperty, this.View.CaretPostion);\r
1056             this.nowCaretMove = false;            \r
1057             if(this.textStore.IsLocked() == false)\r
1058                 this.textStore.NotifySelectionChanged();\r
1059         }\r
1060 \r
1061         void FooTextBox_Loaded(object sender, RoutedEventArgs e)\r
1062         {\r
1063             this.Resize(this.image.ActualWidth, this.image.ActualHeight);\r
1064             this.Focus();\r
1065             this.timer.Start();\r
1066         }\r
1067 \r
1068         bool Resize(double width, double height)\r
1069         {\r
1070             if (width == 0 || height == 0)\r
1071                 throw new ArgumentOutOfRangeException();\r
1072             if (this.Render.Resize(width, height))\r
1073             {\r
1074                 this.View.PageBound = new Rectangle(0, 0, width, height);\r
1075 \r
1076                 if (this.horizontalScrollBar != null)\r
1077                 {\r
1078                     this.horizontalScrollBar.LargeChange = this.View.PageBound.Width;\r
1079                     this.horizontalScrollBar.Maximum = this.View.LongestWidth + this.horizontalScrollBar.LargeChange + 1;\r
1080                 }\r
1081                 if (this.verticalScrollBar != null)\r
1082                 {\r
1083                     this.verticalScrollBar.LargeChange = this.View.LineCountOnScreen;\r
1084                     this.verticalScrollBar.Maximum = this.View.LayoutLines.Count + this.verticalScrollBar.LargeChange + 1;\r
1085                 }\r
1086                 return true;\r
1087             }\r
1088             return false;\r
1089         }\r
1090 \r
1091         /// <summary>\r
1092         /// プロパティーが変更されたときに呼ばれます\r
1093         /// </summary>\r
1094         /// <param name="e">イベントパラメーター</param>\r
1095         protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r
1096         {\r
1097             switch (e.Property.Name)\r
1098             {\r
1099                 case "IndentMode":\r
1100                     this._Controller.IndentMode = this.IndentMode;\r
1101                     break;\r
1102                 case "Selection":\r
1103                     if(!this.nowCaretMove)\r
1104                         this.Select(this.Selection.Index, this.Selection.Length);\r
1105                     break;\r
1106                 case "CaretPostion":\r
1107                     if (!this.nowCaretMove)\r
1108                         this.JumpCaret(this.CaretPostion.row, this.CaretPostion.col);\r
1109                     break;\r
1110                 case "LineBreakMethod":\r
1111                     this.View.LineBreak = this.LineBreakMethod;\r
1112                     break;\r
1113                 case "LineBreakCharCount":\r
1114                     this.View.LineBreakCharCount = this.LineBreakCharCount;\r
1115                     break;\r
1116                 case "InsertMode":\r
1117                     this.View.InsertMode = this.InsertMode;\r
1118                     break;\r
1119                 case "TabChars":\r
1120                     this.View.TabStops = this.TabChars;\r
1121                     break;\r
1122                 case "RectSelectMode":\r
1123                     this._Controller.RectSelection = this.RectSelectMode;\r
1124                     break;\r
1125                 case "DrawCaret":\r
1126                     this.View.HideCaret = !this.DrawCaret;\r
1127                     break;\r
1128                 case "DrawCaretLine":\r
1129                     this.View.HideLineMarker = !this.DrawCaretLine;\r
1130                     break;\r
1131                 case "DrawLineNumber":\r
1132                     this.View.DrawLineNumber = this.DrawLineNumber;\r
1133                     this._Controller.JumpCaret(this.View.CaretPostion.row, this.View.CaretPostion.col);\r
1134                     break;\r
1135                 case "FontFamily":\r
1136                     this.Render.FontFamily = this.FontFamily;\r
1137                     break;\r
1138                 case "FontSize":\r
1139                     this.Render.FontSize = this.FontSize;\r
1140                     break;\r
1141                 case "FontStyle":\r
1142                     this.Render.FontStyle = this.FontStyle;\r
1143                     break;\r
1144                 case "FontWeight":\r
1145                     this.Render.FontWeigth = this.FontWeight;\r
1146                     break;\r
1147                 case "Foreground":\r
1148                     this.Render.Foreground = D2DRender.ToColor4(this.Foreground);\r
1149                     break;\r
1150                 case "Background":\r
1151                     this.Render.Background = D2DRender.ToColor4(this.Background);\r
1152                     break;\r
1153                 case "ControlChar":\r
1154                     this.Render.ControlChar =D2DRender.ToColor4( this.ControlChar);\r
1155                     break;\r
1156                 case "Hilight":\r
1157                     this.Render.Hilight = D2DRender.ToColor4(this.Hilight);\r
1158                     break;\r
1159                 case "Keyword1":\r
1160                     this.Render.Keyword1 = D2DRender.ToColor4(this.Keyword1);\r
1161                     break;\r
1162                 case "Keyword2":\r
1163                     this.Render.Keyword2 = D2DRender.ToColor4(this.Keyword2);\r
1164                     break;\r
1165                 case "Comment":\r
1166                     this.Render.Comment = D2DRender.ToColor4(this.Comment);\r
1167                     break;\r
1168                 case "Literal":\r
1169                     this.Render.Literal = D2DRender.ToColor4(this.Literal);\r
1170                     break;\r
1171                 case "URL":\r
1172                     this.Render.Url = D2DRender.ToColor4(this.URL);\r
1173                     break;\r
1174                 case "InsertCaret":\r
1175                     this.Render.InsertCaret = D2DRender.ToColor4(this.InsertCaret);\r
1176                     break;\r
1177                 case "OverwriteCaret":\r
1178                     this.Render.OverwriteCaret = D2DRender.ToColor4(this.OverwriteCaret);\r
1179                     break;\r
1180                 case "Padding":\r
1181                     this.View.Padding = new Padding((int)this.Padding.Left, (int)this.Padding.Top, (int)this.Padding.Right, (int)this.Padding.Bottom);\r
1182                     break;\r
1183                 case "LineMarker":\r
1184                     this.Render.LineMarker = D2DRender.ToColor4(this.LineMarker);\r
1185                     break;\r
1186                 case "MarkURL":\r
1187                     this.View.UrlMark = this.MarkURL;\r
1188                     break;\r
1189                 case "ShowFullSpace":\r
1190                     this.Render.ShowFullSpace = this.ShowFullSpace;\r
1191                     break;\r
1192                 case "ShowHalfSpace":\r
1193                     this.Render.ShowHalfSpace = this.ShowHalfSpace;\r
1194                     break;\r
1195                 case "ShowTab":\r
1196                     this.Render.ShowTab = this.ShowTab;\r
1197                     break;\r
1198                 case "ShowLineBreak":\r
1199                     this.Render.ShowLineBreak = this.ShowLineBreak;\r
1200                     break;\r
1201                 case "FlowDirection":\r
1202                     this.Render.RightToLeft = this.FlowDirection == System.Windows.FlowDirection.RightToLeft;\r
1203                     this.horizontalScrollBar.FlowDirection = this.FlowDirection;\r
1204                     break;\r
1205                 case "DrawRuler":\r
1206                     this.View.HideRuler = !this.DrawRuler;\r
1207                     this._Controller.JumpCaret(this.View.CaretPostion.row, this.View.CaretPostion.col);\r
1208                     break;\r
1209                 case "UpdateArea":\r
1210                     this.Render.UpdateArea = D2DRender.ToColor4(this.UpdateArea);\r
1211                     break;\r
1212                 case "LineNumber":\r
1213                     this.Render.LineNumber = D2DRender.ToColor4(this.LineNumber);\r
1214                     break;\r
1215             }\r
1216             base.OnPropertyChanged(e);\r
1217         }\r
1218         #endregion\r
1219         #region property\r
1220 \r
1221         internal Controller Controller\r
1222         {\r
1223             get\r
1224             {\r
1225                 return this._Controller;\r
1226             }\r
1227         }\r
1228 \r
1229         /// <summary>\r
1230         /// 文字列の描写に使用されるアンチエイリアシング モードを表します\r
1231         /// </summary>\r
1232         public TextAntialiasMode TextAntialiasMode\r
1233         {\r
1234             get\r
1235             {\r
1236                 return this.Render.TextAntialiasMode;\r
1237             }\r
1238             set\r
1239             {\r
1240                 this.Render.TextAntialiasMode = value;\r
1241             }\r
1242         }\r
1243 \r
1244         /// <summary>\r
1245         /// シンタックスハイライターを表す\r
1246         /// </summary>\r
1247         public IHilighter Hilighter\r
1248         {\r
1249             get\r
1250             {\r
1251                 return this.View.Hilighter;\r
1252             }\r
1253             set\r
1254             {\r
1255                 this.View.Hilighter = value;\r
1256                 this.View.LayoutLines.ClearLayoutCache();\r
1257             }\r
1258         }\r
1259 \r
1260         /// <summary>\r
1261         /// フォールティングを作成するインターフェイスを表す\r
1262         /// </summary>\r
1263         public IFoldingStrategy FoldingStrategy\r
1264         {\r
1265             get\r
1266             {\r
1267                 return this.View.LayoutLines.FoldingStrategy;\r
1268             }\r
1269             set\r
1270             {\r
1271                 this.View.LayoutLines.FoldingStrategy = value;\r
1272                 if (value == null)\r
1273                     this.View.LayoutLines.FoldingCollection.Clear();\r
1274             }\r
1275         }\r
1276 \r
1277         /// <summary>\r
1278         /// マーカーパターンセット\r
1279         /// </summary>\r
1280         public MarkerPatternSet MarkerPatternSet\r
1281         {\r
1282             get\r
1283             {\r
1284                 return this.View.MarkerPatternSet;\r
1285             }\r
1286         }\r
1287 \r
1288         /// <summary>\r
1289         /// ドキュメントを表す\r
1290         /// </summary>\r
1291         public Document Document\r
1292         {\r
1293             get;\r
1294             private set;\r
1295         }\r
1296 \r
1297         /// <summary>\r
1298         /// レイアウト行を表す\r
1299         /// </summary>\r
1300         public LineToIndexTable LayoutLineCollection\r
1301         {\r
1302             get { return this.View.LayoutLines; }\r
1303         }\r
1304 \r
1305         /// <summary>\r
1306         /// 選択中の文字列を表す\r
1307         /// </summary>\r
1308         public string SelectedText\r
1309         {\r
1310             get\r
1311             {\r
1312                 return this._Controller.SelectedText;\r
1313             }\r
1314             set\r
1315             {\r
1316                 int oldLength = this.Document.Length;\r
1317                 this._Controller.SelectedText = value;\r
1318             }\r
1319         }\r
1320 \r
1321         /// <summary>\r
1322         /// インデントの方法を表す\r
1323         /// </summary>\r
1324         public IndentMode IndentMode\r
1325         {\r
1326             get { return (IndentMode)GetValue(IndentModeProperty); }\r
1327             set { SetValue(IndentModeProperty, value); }\r
1328         }\r
1329 \r
1330         /// <summary>\r
1331         /// IndentModeの依存プロパティを表す\r
1332         /// </summary>\r
1333         public static readonly DependencyProperty IndentModeProperty =\r
1334             DependencyProperty.Register("IndentMode", typeof(IndentMode), typeof(FooTextBox), new PropertyMetadata(IndentMode.Tab));\r
1335 \r
1336         /// <summary>\r
1337         /// 選択範囲を表す\r
1338         /// </summary>\r
1339         /// <remarks>\r
1340         /// Lengthが0の場合はキャレット位置を表します。\r
1341         /// 矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります\r
1342         /// </remarks>\r
1343         public TextRange Selection\r
1344         {\r
1345             get { return (TextRange)GetValue(SelectionProperty); }\r
1346             set { SetValue(SelectionProperty, value); }\r
1347         }\r
1348 \r
1349         /// <summary>\r
1350         /// Selectionの依存プロパティを表す\r
1351         /// </summary>\r
1352         public static readonly DependencyProperty SelectionProperty =\r
1353             DependencyProperty.Register("Selection", typeof(TextRange), typeof(FooTextBox), new PropertyMetadata(TextRange.Null));\r
1354 \r
1355         /// <summary>\r
1356         /// 拡大率を表す\r
1357         /// </summary>\r
1358         public double MagnificationPower\r
1359         {\r
1360             get { return (double)GetValue(MagnificationPowerPropertyKey.DependencyProperty); }\r
1361         }\r
1362 \r
1363         /// <summary>\r
1364         /// 拡大率を表す依存プロパティ\r
1365         /// </summary>\r
1366         public static readonly DependencyPropertyKey MagnificationPowerPropertyKey =\r
1367             DependencyProperty.RegisterReadOnly("MagnificationPower", typeof(double), typeof(FooTextBox), new PropertyMetadata(1.0));\r
1368 \r
1369         /// <summary>\r
1370         /// レタリング方向を表す\r
1371         /// </summary>\r
1372         public new FlowDirection FlowDirection\r
1373         {\r
1374             get { return (FlowDirection)GetValue(FlowDirectionProperty); }\r
1375             set { SetValue(FlowDirectionProperty, value); }\r
1376         }\r
1377 \r
1378         /// <summary>\r
1379         /// レタリング方向を表す。これは依存プロパティです\r
1380         /// </summary>\r
1381         public new static readonly DependencyProperty FlowDirectionProperty =\r
1382             DependencyProperty.Register("FlowDirection", typeof(FlowDirection), typeof(FooTextBox), new PropertyMetadata(FlowDirection.LeftToRight));        \r
1383 \r
1384         /// <summary>\r
1385         /// キャレット位置を表す。これは依存プロパティです\r
1386         /// </summary>\r
1387         public TextPoint CaretPostion\r
1388         {\r
1389             get { return (TextPoint)GetValue(CaretPostionProperty); }\r
1390             set { SetValue(CaretPostionProperty, value); }\r
1391         }\r
1392 \r
1393         /// <summary>\r
1394         /// CaretPostionの依存プロパティを表す\r
1395         /// </summary>\r
1396         public static readonly DependencyProperty CaretPostionProperty =\r
1397             DependencyProperty.Register("CaretPostion", typeof(TextPoint), typeof(FooTextBox), new PropertyMetadata(TextPoint.Null));\r
1398         \r
1399         /// <summary>\r
1400         /// デフォルトの文字色を表す。これは依存プロパティです\r
1401         /// </summary>\r
1402         public new System.Windows.Media.Color Foreground\r
1403         {\r
1404             get { return (System.Windows.Media.Color)GetValue(ForegroundProperty); }\r
1405             set { SetValue(ForegroundProperty, value); }\r
1406         }\r
1407 \r
1408         /// <summary>\r
1409         /// Foregroundの依存プロパティを表す\r
1410         /// </summary>\r
1411         public new static readonly DependencyProperty ForegroundProperty =\r
1412             DependencyProperty.Register("Foreground", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowTextColor));\r
1413 \r
1414         /// <summary>\r
1415         /// 背景色を表す。これは依存プロパティです\r
1416         /// </summary>\r
1417         public new System.Windows.Media.Color Background\r
1418         {\r
1419             get { return (System.Windows.Media.Color)GetValue(BackgroundProperty); }\r
1420             set { SetValue(BackgroundProperty, value); }\r
1421         }\r
1422 \r
1423         /// <summary>\r
1424         /// Backgroundの依存プロパティを表す\r
1425         /// </summary>\r
1426         public new static readonly DependencyProperty BackgroundProperty =\r
1427             DependencyProperty.Register("Background", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowColor));\r
1428         \r
1429         /// <summary>\r
1430         /// コントロールコードの文字色を表す。これは依存プロパティです\r
1431         /// </summary>\r
1432         public System.Windows.Media.Color ControlChar\r
1433         {\r
1434             get { return (System.Windows.Media.Color)GetValue(ControlCharProperty); }\r
1435             set { SetValue(ControlCharProperty, value); }\r
1436         }\r
1437 \r
1438         /// <summary>\r
1439         /// ControlCharの依存プロパティを表す\r
1440         /// </summary>\r
1441         public static readonly DependencyProperty ControlCharProperty =\r
1442             DependencyProperty.Register("ControlChar", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Gray));\r
1443         \r
1444         /// <summary>\r
1445         /// 選択時の背景色を表す。これは依存プロパティです\r
1446         /// </summary>\r
1447         public System.Windows.Media.Color Hilight\r
1448         {\r
1449             get { return (System.Windows.Media.Color)GetValue(HilightProperty); }\r
1450             set { SetValue(HilightProperty, value); }\r
1451         }\r
1452 \r
1453         /// <summary>\r
1454         /// Hilightの依存プロパティを表す\r
1455         /// </summary>\r
1456         public static readonly DependencyProperty HilightProperty =\r
1457             DependencyProperty.Register("Hilight", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.DeepSkyBlue));\r
1458         \r
1459         /// <summary>\r
1460         /// キーワード1の文字色を表す。これは依存プロパティです\r
1461         /// </summary>\r
1462         public System.Windows.Media.Color Keyword1\r
1463         {\r
1464             get { return (System.Windows.Media.Color)GetValue(Keyword1Property); }\r
1465             set { SetValue(Keyword1Property, value); }\r
1466         }\r
1467 \r
1468         /// <summary>\r
1469         /// Keyword1の依存プロパティを表す\r
1470         /// </summary>\r
1471         public static readonly DependencyProperty Keyword1Property =\r
1472             DependencyProperty.Register("Keyword1", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Blue));\r
1473 \r
1474         /// <summary>\r
1475         /// キーワード2の文字色を表す。これは依存プロパティです\r
1476         /// </summary>\r
1477         public System.Windows.Media.Color Keyword2\r
1478         {\r
1479             get { return (System.Windows.Media.Color)GetValue(Keyword2Property); }\r
1480             set { SetValue(Keyword2Property, value); }\r
1481         }\r
1482 \r
1483         /// <summary>\r
1484         /// Keyword2の依存プロパティを表す\r
1485         /// </summary>\r
1486         public static readonly DependencyProperty Keyword2Property =\r
1487             DependencyProperty.Register("Keyword2", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.DarkCyan));\r
1488 \r
1489         /// <summary>\r
1490         /// コメントの文字色を表す。これは依存プロパティです\r
1491         /// </summary>\r
1492         public System.Windows.Media.Color Comment\r
1493         {\r
1494             get { return (System.Windows.Media.Color)GetValue(CommentProperty); }\r
1495             set { SetValue(CommentProperty, value); }\r
1496         }\r
1497 \r
1498         /// <summary>\r
1499         /// Commentの依存プロパティを表す\r
1500         /// </summary>\r
1501         public static readonly DependencyProperty CommentProperty =\r
1502             DependencyProperty.Register("Comment", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Green));\r
1503 \r
1504         /// <summary>\r
1505         /// 文字リテラルの文字色を表す。これは依存プロパティです\r
1506         /// </summary>\r
1507         public System.Windows.Media.Color Literal\r
1508         {\r
1509             get { return (System.Windows.Media.Color)GetValue(LiteralProperty); }\r
1510             set { SetValue(LiteralProperty, value); }\r
1511         }\r
1512 \r
1513         /// <summary>\r
1514         /// Literalの依存プロパティを表す\r
1515         /// </summary>\r
1516         public static readonly DependencyProperty LiteralProperty =\r
1517             DependencyProperty.Register("Literal", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Brown));\r
1518 \r
1519         /// <summary>\r
1520         /// URLの文字色を表す。これは依存プロパティです\r
1521         /// </summary>\r
1522         public System.Windows.Media.Color URL\r
1523         {\r
1524             get { return (System.Windows.Media.Color)GetValue(URLProperty); }\r
1525             set { SetValue(URLProperty, value); }\r
1526         }\r
1527 \r
1528         /// <summary>\r
1529         /// URLの依存プロパティを表す\r
1530         /// </summary>\r
1531         public static readonly DependencyProperty URLProperty =\r
1532             DependencyProperty.Register("URL", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Blue));\r
1533 \r
1534 \r
1535         /// <summary>\r
1536         /// ラインマーカーの色を表す\r
1537         /// </summary>\r
1538         public System.Windows.Media.Color LineMarker\r
1539         {\r
1540             get { return (System.Windows.Media.Color)GetValue(LineMarkerProperty); }\r
1541             set { SetValue(LineMarkerProperty, value); }\r
1542         }\r
1543 \r
1544         /// <summary>\r
1545         /// LineMarkerの依存プロパティを表す\r
1546         /// </summary>\r
1547         public static readonly DependencyProperty LineMarkerProperty =\r
1548             DependencyProperty.Register("LineMarker", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Silver));\r
1549 \r
1550         /// <summary>\r
1551         /// 挿入モード時のキャレットの色を表す\r
1552         /// </summary>\r
1553         public System.Windows.Media.Color InsertCaret\r
1554         {\r
1555             get { return (System.Windows.Media.Color)GetValue(InsertCaretProperty); }\r
1556             set { SetValue(InsertCaretProperty, value); }\r
1557         }\r
1558 \r
1559         /// <summary>\r
1560         /// InsertCaretの依存プロパティを表す\r
1561         /// </summary>\r
1562         public static readonly DependencyProperty InsertCaretProperty =\r
1563             DependencyProperty.Register("InsertCaret", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowTextColor));\r
1564 \r
1565         /// <summary>\r
1566         /// 行更新フラグの色を表す\r
1567         /// </summary>\r
1568         public System.Windows.Media.Color UpdateArea\r
1569         {\r
1570             get { return (System.Windows.Media.Color)GetValue(UpdateAreaProperty); }\r
1571             set { SetValue(UpdateAreaProperty, value); }\r
1572         }\r
1573 \r
1574         /// <summary>\r
1575         /// UpdateAreaの依存プロパティを表す\r
1576         /// </summary>\r
1577         public static readonly DependencyProperty UpdateAreaProperty =\r
1578             DependencyProperty.Register("UpdateArea", typeof(System.Windows.Media.Color), typeof(FooTextBox), new PropertyMetadata(Colors.MediumSeaGreen));        \r
1579 \r
1580         /// <summary>\r
1581         /// 上書きモード時のキャレット職を表す\r
1582         /// </summary>\r
1583         public System.Windows.Media.Color OverwriteCaret\r
1584         {\r
1585             get { return (System.Windows.Media.Color)GetValue(OverwriteCaretProperty); }\r
1586             set { SetValue(OverwriteCaretProperty, value); }\r
1587         }\r
1588         \r
1589         /// <summary>\r
1590         /// OverwriteCaretの依存プロパティを表す\r
1591         /// </summary>\r
1592         public static readonly DependencyProperty OverwriteCaretProperty =\r
1593             DependencyProperty.Register("OverwriteCaret", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowTextColor));\r
1594 \r
1595         /// <summary>\r
1596         /// 行番号の色を表す\r
1597         /// </summary>\r
1598         public System.Windows.Media.Color LineNumber\r
1599         {\r
1600             get { return (System.Windows.Media.Color)GetValue(LineNumberProperty); }\r
1601             set { SetValue(LineNumberProperty, value); }\r
1602         }\r
1603 \r
1604         /// <summary>\r
1605         /// Using a DependencyProperty as the backing store for LineNumber.  This enables animation, styling, binding, etc...\r
1606         /// </summary>\r
1607         public static readonly DependencyProperty LineNumberProperty =\r
1608             DependencyProperty.Register("LineNumber", typeof(System.Windows.Media.Color), typeof(FooTextBox), new PropertyMetadata(Colors.DimGray));\r
1609 \r
1610         /// <summary>\r
1611         /// 挿入モードなら真を返し、そうでないなら、偽を返す。これは依存プロパティです\r
1612         /// </summary>\r
1613         public bool InsertMode\r
1614         {\r
1615             get { return (bool)GetValue(InsertModeProperty); }\r
1616             set { SetValue(InsertModeProperty, value); }\r
1617         }\r
1618 \r
1619         /// <summary>\r
1620         /// InsertModeの依存プロパティを表す\r
1621         /// </summary>\r
1622         public static readonly DependencyProperty InsertModeProperty =\r
1623             DependencyProperty.Register("InsertMode",\r
1624             typeof(bool),\r
1625             typeof(FooTextBox),\r
1626             new FrameworkPropertyMetadata(true));\r
1627 \r
1628         /// <summary>\r
1629         /// タブの文字数を表す。これは依存プロパティです\r
1630         /// </summary>\r
1631         public int TabChars\r
1632         {\r
1633             get { return (int)GetValue(TabCharsProperty); }\r
1634             set { SetValue(TabCharsProperty, value); }\r
1635         }\r
1636 \r
1637         /// <summary>\r
1638         /// TabCharsの依存プロパティを表す\r
1639         /// </summary>\r
1640         public static readonly DependencyProperty TabCharsProperty =\r
1641             DependencyProperty.Register("TabChars",\r
1642             typeof(int),\r
1643             typeof(FooTextBox),\r
1644             new FrameworkPropertyMetadata(4));\r
1645 \r
1646         /// <summary>\r
1647         /// 矩形選択モードなら真を返し、そうでないなら偽を返す。これは依存プロパティです\r
1648         /// </summary>\r
1649         public bool RectSelectMode\r
1650         {\r
1651             get { return (bool)GetValue(RectSelectModeProperty); }\r
1652             set { SetValue(RectSelectModeProperty, value); }\r
1653         }\r
1654 \r
1655         /// <summary>\r
1656         /// RectSelectModeの依存プロパティを表す\r
1657         /// </summary>\r
1658         public static readonly DependencyProperty RectSelectModeProperty =\r
1659             DependencyProperty.Register("RectSelectMode", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false));\r
1660 \r
1661         /// <summary>\r
1662         /// 折り返しの方法を指定する\r
1663         /// </summary>\r
1664         /// <remarks>\r
1665         /// 変更した場合、レイアウトの再構築を行う必要があります\r
1666         /// </remarks>\r
1667         public LineBreakMethod LineBreakMethod\r
1668         {\r
1669             get { return (LineBreakMethod)GetValue(LineBreakProperty); }\r
1670             set { SetValue(LineBreakProperty, value); }\r
1671         }\r
1672 \r
1673         /// <summary>\r
1674         /// LineBreakMethodの依存プロパティを表す\r
1675         /// </summary>\r
1676         public static readonly DependencyProperty LineBreakProperty =\r
1677             DependencyProperty.Register("LineBreakMethod", typeof(LineBreakMethod), typeof(FooTextBox), new PropertyMetadata(LineBreakMethod.None));\r
1678 \r
1679 \r
1680         /// <summary>\r
1681         /// 折り返しの幅を指定する。LineBreakMethod.CharUnit以外の時は無視されます\r
1682         /// </summary>\r
1683         /// <remarks>\r
1684         /// 変更した場合、レイアウトの再構築を行う必要があります\r
1685         /// </remarks>\r
1686         public int LineBreakCharCount\r
1687         {\r
1688             get { return (int)GetValue(LineBreakCharCountProperty); }\r
1689             set { SetValue(LineBreakCharCountProperty, value); }\r
1690         }\r
1691 \r
1692         /// <summary>\r
1693         /// LineBreakCharCountの依存プロパティを表す\r
1694         /// </summary>\r
1695         public static readonly DependencyProperty LineBreakCharCountProperty =\r
1696             DependencyProperty.Register("LineBreakCharCount", typeof(int), typeof(FooTextBox), new PropertyMetadata(80));\r
1697 \r
1698         /// <summary>\r
1699         /// キャレットを描くなら真。そうでないなら偽を返す。これは依存プロパティです\r
1700         /// </summary>\r
1701         public bool DrawCaret\r
1702         {\r
1703             get { return (bool)GetValue(DrawCaretProperty); }\r
1704             set { SetValue(DrawCaretProperty, value); }\r
1705         }\r
1706 \r
1707         /// <summary>\r
1708         /// DrawCaretの依存プロパティを表す\r
1709         /// </summary>\r
1710         public static readonly DependencyProperty DrawCaretProperty =\r
1711             DependencyProperty.Register("DrawCaret", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(true));\r
1712 \r
1713         \r
1714         /// <summary>\r
1715         /// キャレットラインを描くなら真。そうでないなら偽を返す。これは依存プロパティです\r
1716         /// </summary>\r
1717         public bool DrawCaretLine\r
1718         {\r
1719             get { return (bool)GetValue(DrawCaretLineProperty); }\r
1720             set { SetValue(DrawCaretLineProperty, value); }\r
1721         }\r
1722 \r
1723         /// <summary>\r
1724         /// DrawCaretLineの依存プロパティを表す\r
1725         /// </summary>\r
1726         public static readonly DependencyProperty DrawCaretLineProperty =\r
1727             DependencyProperty.Register("DrawCaretLine", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false));\r
1728 \r
1729         /// <summary>\r
1730         /// 行番号を描くなら真。そうでなければ偽。これは依存プロパティです\r
1731         /// </summary>\r
1732         public bool DrawLineNumber\r
1733         {\r
1734             get { return (bool)GetValue(DrawLineNumberProperty); }\r
1735             set { SetValue(DrawLineNumberProperty, value); }\r
1736         }\r
1737 \r
1738         /// <summary>\r
1739         /// ルーラーを描くなら真。そうでなければ偽。これは依存プロパティです\r
1740         /// </summary>\r
1741         public bool DrawRuler\r
1742         {\r
1743             get { return (bool)GetValue(DrawRulerProperty); }\r
1744             set { SetValue(DrawRulerProperty, value); }\r
1745         }\r
1746 \r
1747         /// <summary>\r
1748         /// DrawRulerの依存プロパティを表す\r
1749         /// </summary>\r
1750         public static readonly DependencyProperty DrawRulerProperty =\r
1751             DependencyProperty.Register("DrawRuler", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false));\r
1752 \r
1753         \r
1754         /// <summary>\r
1755         /// DrawLineNumberの依存プロパティを表す\r
1756         /// </summary>\r
1757         public static readonly DependencyProperty DrawLineNumberProperty =\r
1758             DependencyProperty.Register("DrawLineNumber", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false));\r
1759 \r
1760         /// <summary>\r
1761         /// URLに下線を引くなら真。そうでないなら偽を表す。これは依存プロパティです\r
1762         /// </summary>\r
1763         public bool MarkURL\r
1764         {\r
1765             get { return (bool)GetValue(MarkURLProperty); }\r
1766             set { SetValue(MarkURLProperty, value); }\r
1767         }\r
1768 \r
1769         /// <summary>\r
1770         /// MarkURLの依存プロパティを表す\r
1771         /// </summary>\r
1772         public static readonly DependencyProperty MarkURLProperty =\r
1773             DependencyProperty.Register("MarkURL", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false));\r
1774 \r
1775         /// <summary>\r
1776         /// 全角スペースを表示するなら真。そうでないなら偽\r
1777         /// </summary>\r
1778         public bool ShowFullSpace\r
1779         {\r
1780             get { return (bool)GetValue(ShowFullSpaceProperty); }\r
1781             set { SetValue(ShowFullSpaceProperty, value); }\r
1782         }\r
1783 \r
1784         /// <summary>\r
1785         /// ShowFullSpaceの依存プロパティを表す\r
1786         /// </summary>\r
1787         public static readonly DependencyProperty ShowFullSpaceProperty =\r
1788             DependencyProperty.Register("ShowFullSpace", typeof(bool), typeof(FooTextBox), new UIPropertyMetadata(false));\r
1789 \r
1790         /// <summary>\r
1791         /// 半角スペースを表示するなら真。そうでないなら偽\r
1792         /// </summary>\r
1793         public bool ShowHalfSpace\r
1794         {\r
1795             get { return (bool)GetValue(ShowHalfSpaceProperty); }\r
1796             set { SetValue(ShowHalfSpaceProperty, value); }\r
1797         }\r
1798 \r
1799         /// <summary>\r
1800         /// ShowHalfSpaceの依存プロパティを表す\r
1801         /// </summary>\r
1802         public static readonly DependencyProperty ShowHalfSpaceProperty =\r
1803             DependencyProperty.Register("ShowHalfSpace", typeof(bool), typeof(FooTextBox), new UIPropertyMetadata(false));\r
1804 \r
1805         /// <summary>\r
1806         /// タブを表示するなら真。そうでないなら偽\r
1807         /// </summary>\r
1808         public bool ShowTab\r
1809         {\r
1810             get { return (bool)GetValue(ShowTabProperty); }\r
1811             set { SetValue(ShowTabProperty, value); }\r
1812         }\r
1813 \r
1814         /// <summary>\r
1815         /// ShowTabの依存プロパティを表す\r
1816         /// </summary>\r
1817         public static readonly DependencyProperty ShowTabProperty =\r
1818             DependencyProperty.Register("ShowTab", typeof(bool), typeof(FooTextBox), new UIPropertyMetadata(false));\r
1819 \r
1820         /// <summary>\r
1821         /// 改行マークを表示するなら真。そうでないなら偽\r
1822         /// </summary>\r
1823         public bool ShowLineBreak\r
1824         {\r
1825             get { return (bool)GetValue(ShowLineBreakProperty); }\r
1826             set { SetValue(ShowLineBreakProperty, value); }\r
1827         }\r
1828 \r
1829         /// <summary>\r
1830         /// ShowLineBreakの依存プロパティを表す\r
1831         /// </summary>\r
1832         public static readonly DependencyProperty ShowLineBreakProperty =\r
1833             DependencyProperty.Register("ShowLineBreak", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false));\r
1834         \r
1835         #endregion\r
1836     }\r
1837     /// <summary>\r
1838     /// マウスボタン関連のイベントクラス\r
1839     /// </summary>\r
1840     public sealed class FooMouseButtonEventArgs : MouseButtonEventArgs\r
1841     {\r
1842         /// <summary>\r
1843         /// イベントが発生したドキュメントのインデックス\r
1844         /// </summary>\r
1845         public int Index\r
1846         {\r
1847             get;\r
1848             private set;\r
1849         }\r
1850 \r
1851         /// <summary>\r
1852         /// コンストラクター\r
1853         /// </summary>\r
1854         /// <param name="mouse">マウスデバイス</param>\r
1855         /// <param name="timestamp">タイムスタンプ</param>\r
1856         /// <param name="button">ボタン</param>\r
1857         /// <param name="stylusDevice">スタイラスデバイス</param>\r
1858         /// <param name="index">インデックス</param>\r
1859         public FooMouseButtonEventArgs(MouseDevice mouse, int timestamp, MouseButton button, StylusDevice stylusDevice, int index)\r
1860             : base(mouse, timestamp, button, stylusDevice)\r
1861         {\r
1862             this.Index = index;\r
1863         }\r
1864     }\r
1865     /// <summary>\r
1866     /// マウス関連のイベントクラス\r
1867     /// </summary>\r
1868     public sealed class FooMouseEventArgs : MouseEventArgs\r
1869     {\r
1870         /// <summary>\r
1871         /// イベントが発生したドキュメントのインデックス\r
1872         /// </summary>\r
1873         public int Index\r
1874         {\r
1875             get;\r
1876             private set;\r
1877         }\r
1878 \r
1879         /// <summary>\r
1880         /// コンストラクター\r
1881         /// </summary>\r
1882         /// <param name="mouse">マウスデバイス</param>\r
1883         /// <param name="timestamp">タイムスタンプ</param>\r
1884         /// <param name="stylusDevice">スタイラスデバイス</param>\r
1885         /// <param name="index">インデックス</param>\r
1886         public FooMouseEventArgs(MouseDevice mouse,\r
1887             int timestamp,\r
1888             StylusDevice stylusDevice,\r
1889             int index)\r
1890             : base(mouse, timestamp, stylusDevice)\r
1891         {\r
1892             this.Index = index;\r
1893         }\r
1894     }\r
1895 }\r