OSDN Git Service

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