OSDN Git Service

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