2 * Copyright (C) 2013 FooProject
3 * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
6 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9 You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
13 using System.Threading.Tasks;
14 using System.Runtime.InteropServices;
16 using System.Windows.Input;
17 using System.Windows.Media;
18 using System.Windows.Controls;
19 using System.Windows.Controls.Primitives;
20 using System.Windows.Documents;
21 using System.Windows.Interop;
22 using System.Windows.Threading;
23 using DotNetTextStore;
24 using DotNetTextStore.UnmanagedAPI.TSF;
25 using DotNetTextStore.UnmanagedAPI.WinDef;
26 using Microsoft.Win32;
28 namespace FooEditEngine.WPF
31 /// オートインデントを行うためのデリゲートを表す
33 /// <param name="sender">イベント発生元のオブジェクト</param>
34 /// <param name="e">イベントデーター</param>
35 public delegate void AutoIndentHookerHandler(object sender,EventArgs e);
38 /// WPFでのFooTextBoxの実装
40 public sealed class FooTextBox : Control, IDisposable
42 const double MaxFontSize = 72.0f;
43 const double MinFontSize = 1;
46 Controller _Controller;
49 ScrollBar verticalScrollBar, horizontalScrollBar;
51 DispatcherTimer timer;
52 bool disposed = false;
53 FooTextBoxAutomationPeer peer;
54 bool nowCaretMove = false;
58 DefaultStyleKeyProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(typeof(FooTextBox)));
59 KeyboardNavigation.IsTabStopProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(true));
60 KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(KeyboardNavigationMode.None));
68 this.image = new Image();
69 this.image.Stretch = Stretch.Fill;
70 this.image.HorizontalAlignment = HorizontalAlignment.Left;
71 this.image.VerticalAlignment = VerticalAlignment.Top;
73 this.textStore = new TextStore();
74 this.textStore.IsLoading += textStore_IsLoading;
75 this.textStore.IsReadOnly += textStore_IsReadOnly;
76 this.textStore.GetStringLength += () => this.Document.Length;
77 this.textStore.GetString += _textStore_GetString;
78 this.textStore.GetSelectionIndex += _textStore_GetSelectionIndex;
79 this.textStore.SetSelectionIndex += _textStore_SetSelectionIndex;
80 this.textStore.InsertAtSelection += _textStore_InsertAtSelection;
81 this.textStore.GetHWnd += _textStore_GetHWnd;
82 this.textStore.GetScreenExtent += _textStore_GetScreenExtent;
83 this.textStore.GetStringExtent += _textStore_GetStringExtent;
84 this.textStore.CompositionStarted += textStore_CompositionStarted;
85 this.textStore.CompositionUpdated += textStore_CompositionUpdated;
86 this.textStore.CompositionEnded += textStore_CompositionEnded;
88 this.Render = new D2DRender(this, 200, 200,this.image);
89 this.Render.ShowFullSpace = this.ShowFullSpace;
90 this.Render.ShowHalfSpace = this.ShowHalfSpace;
91 this.Render.ShowTab = this.ShowTab;
93 this.Document = new Document();
94 this.Document.LayoutLines.Render = this.Render;
96 this.View = new EditView(this.Document, this.Render, new Padding(5, 5, 5, 5));
97 this.View.SrcChanged += View_SrcChanged;
98 this.View.InsertMode = this.InsertMode;
99 this.Document.DrawLineNumber = this.DrawLineNumber;
100 this.View.HideCaret = !this.DrawCaret;
101 this.View.HideLineMarker = !this.DrawCaretLine;
102 this.Document.HideRuler = !this.DrawRuler;
103 this.Document.UrlMark = this.MarkURL;
104 this.Document.TabStops = this.TabChars;
106 this._Controller = new Controller(this.Document, this.View);
107 this._Controller.SelectionChanged += new EventHandler(Controller_SelectionChanged);
109 //Viewを作成した後に追加しないと例外が発生する
110 this.Document.Update += new DocumentUpdateEventHandler(Document_Update);
112 this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Copy, CopyCommand, CanExecute));
113 this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Cut, CutCommand, CanExecute));
114 this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, PasteCommand, CanExecute));
115 this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete, DeleteCommand, CanExecute));
116 this.CommandBindings.Add(new CommandBinding(ApplicationCommands.SelectAll, SelectAllCommand, CanExecute));
117 this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, UndoCommand, CanExecute));
118 this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, RedoCommand, CanExecute));
119 this.CommandBindings.Add(new CommandBinding(EditingCommands.ToggleInsert, ToggleInsertCommand, CanExecute));
120 this.CommandBindings.Add(new CommandBinding(FooTextBoxCommands.ToggleRectSelectMode, ToggleRectSelectCommand, CanExecute));
121 this.CommandBindings.Add(new CommandBinding(FooTextBoxCommands.ToggleFlowDirection, ToggleFlowDirectionCommand, CanExecute));
122 this.CommandBindings.Add(new CommandBinding(FooTextBoxCommands.ToggleCodePoint, ToggleCodePointCommand, CanExecute));
124 this.InputBindings.Add(new InputBinding(ApplicationCommands.Copy, new KeyGesture(Key.C, ModifierKeys.Control)));
125 this.InputBindings.Add(new InputBinding(ApplicationCommands.Cut, new KeyGesture(Key.X, ModifierKeys.Control)));
126 this.InputBindings.Add(new InputBinding(ApplicationCommands.Paste, new KeyGesture(Key.V, ModifierKeys.Control)));
127 this.InputBindings.Add(new InputBinding(ApplicationCommands.Delete, new KeyGesture(Key.Delete, ModifierKeys.None)));
128 this.InputBindings.Add(new InputBinding(ApplicationCommands.SelectAll, new KeyGesture(Key.A, ModifierKeys.Control)));
129 this.InputBindings.Add(new InputBinding(ApplicationCommands.Undo, new KeyGesture(Key.Z, ModifierKeys.Control)));
130 this.InputBindings.Add(new InputBinding(ApplicationCommands.Redo, new KeyGesture(Key.Y, ModifierKeys.Control)));
131 this.InputBindings.Add(new InputBinding(EditingCommands.ToggleInsert, new KeyGesture(Key.Insert, ModifierKeys.None)));
132 this.InputBindings.Add(new InputBinding(FooTextBoxCommands.ToggleCodePoint, new KeyGesture(Key.X, ModifierKeys.Alt)));
134 this.timer = new DispatcherTimer();
135 this.timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
136 this.timer.Tick += new EventHandler(timer_Tick);
138 this.Loaded += new RoutedEventHandler(FooTextBox_Loaded);
140 this.AutoIndentHooker = (s,e)=>{};
142 SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
144 this.SystemEvents_UserPreferenceChanged(null, new UserPreferenceChangedEventArgs(UserPreferenceCategory.Keyboard));
146 this.CaretMoved += (s, e) => { };
154 //Dispose(false)を呼び出すと落ちる
159 /// オートインデントを行うためのイベント
161 public AutoIndentHookerHandler AutoIndentHooker;
166 public override void OnApplyTemplate()
168 base.OnApplyTemplate();
170 Grid grid = this.GetTemplateChild("PART_Grid") as Grid;
173 Grid.SetRow(this.image, 0);
174 Grid.SetColumn(this.image, 0);
175 grid.Children.Add(this.image);
178 this.horizontalScrollBar = this.GetTemplateChild("PART_HorizontalScrollBar") as ScrollBar;
179 if (this.horizontalScrollBar != null)
181 this.horizontalScrollBar.SmallChange = 10;
182 this.horizontalScrollBar.LargeChange = 100;
183 this.horizontalScrollBar.Maximum = this.horizontalScrollBar.LargeChange + 1;
184 this.horizontalScrollBar.Scroll += new ScrollEventHandler(horizontalScrollBar_Scroll);
186 this.verticalScrollBar = this.GetTemplateChild("PART_VerticalScrollBar") as ScrollBar;
187 if (this.verticalScrollBar != null)
189 this.verticalScrollBar.SmallChange = 1;
190 this.verticalScrollBar.LargeChange = 10;
191 this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;
192 this.verticalScrollBar.Scroll += new ScrollEventHandler(verticalScrollBar_Scroll);
199 /// <param name="start">開始インデックス</param>
200 /// <param name="length">長さ</param>
201 public void Select(int start, int length)
203 this._Controller.Select(start, length);
204 this.textStore.NotifySelectionChanged();
208 /// キャレットを指定した行に移動させます
210 /// <param name="index">インデックス</param>
211 /// <remarks>このメソッドを呼び出すと選択状態は解除されます</remarks>
212 public void JumpCaret(int index)
214 this._Controller.JumpCaret(index);
217 /// キャレットを指定した行と桁に移動させます
219 /// <param name="row">行番号</param>
220 /// <param name="col">桁</param>
221 /// <remarks>このメソッドを呼び出すと選択状態は解除されます</remarks>
222 public void JumpCaret(int row, int col)
224 this._Controller.JumpCaret(row, col);
228 /// 選択中のテキストをクリップボードにコピーします
232 string text = this._Controller.SelectedText;
233 if (text != null && text != string.Empty)
234 Clipboard.SetText(text);
238 /// 選択中のテキストをクリップボードに切り取ります
242 string text = this._Controller.SelectedText;
243 if (text != null && text != string.Empty)
245 Clipboard.SetText(text);
246 this._Controller.SelectedText = "";
255 if (Clipboard.ContainsText() == false)
257 string text = Clipboard.GetText();
258 this._Controller.SelectedText = text;
264 public void DeSelectAll()
266 this._Controller.DeSelectAll();
267 this.textStore.NotifySelectionChanged();
273 /// <param name="tp">テキストポイント</param>
274 /// <returns>座標</returns>
275 /// <remarks>テキストポイントがクライアント領域の原点より外にある場合、返される値は原点に丸められます</remarks>
276 public System.Windows.Point GetPostionFromTextPoint(TextPoint tp)
278 if (this.Document.FireUpdateEvent == false)
279 throw new InvalidOperationException("");
280 return this.View.GetPostionFromTextPoint(tp);
284 /// 対応するテキストポイントを返します
286 /// <param name="p">クライアント領域の原点を左上とする座標</param>
287 /// <returns>テキストポイント</returns>
288 public TextPoint GetTextPointFromPostion(System.Windows.Point p)
290 if (this.Document.FireUpdateEvent == false)
291 throw new InvalidOperationException("");
292 return this.View.GetTextPointFromPostion(p);
298 /// <param name="row">レイアウト行</param>
299 /// <returns>行の高さ</returns>
300 public double GetLineHeight(int row)
302 if (this.Document.FireUpdateEvent == false)
303 throw new InvalidOperationException("");
304 return this.View.LayoutLines.GetLayout(row).Height;;
308 /// インデックスに対応する座標を得ます
310 /// <param name="index">インデックス</param>
311 /// <returns>座標を返す</returns>
312 public System.Windows.Point GetPostionFromIndex(int index)
314 if (this.Document.FireUpdateEvent == false)
315 throw new InvalidOperationException("");
316 TextPoint tp = this.View.GetLayoutLineFromIndex(index);
317 return this.View.GetPostionFromTextPoint(tp);
323 /// <param name="p">座標</param>
324 /// <returns>インデックスを返す</returns>
325 public int GetIndexFromPostion(System.Windows.Point p)
327 if (this.Document.FireUpdateEvent == false)
328 throw new InvalidOperationException("");
329 TextPoint tp = this.View.GetTextPointFromPostion(p);
330 return this.View.GetIndexFromLayoutLine(tp);
336 public void Refresh()
338 this.Refresh(this.View.PageBound);
342 /// レイアウト行をすべて破棄し、再度レイアウトを行う
344 public void PerfomLayouts()
346 this.View.PerfomLayouts();
352 /// <param name="row">行</param>
353 /// <param name="alignTop">指定行を画面上に置くなら真。そうでないなら偽</param>
354 public void ScrollIntoView(int row, bool alignTop)
356 this.View.ScrollIntoView(row, alignTop);
360 /// ストリームからドキュメントを構築する
362 /// <param name="tr">TextReader</param>
363 /// <param name="token">キャンセル用トークン</param>
364 /// <returns>Taskオブジェクト</returns>
365 public async Task LoadAsync(System.IO.TextReader tr, System.Threading.CancellationTokenSource token)
367 WinFileReader fs = new WinFileReader(tr);
368 await this.LoadAsyncImpl(fs, token);
372 /// ファイルからドキュメントを構築する
374 /// <param name="filepath">ファイルパス</param>
375 /// <param name="enc">エンコード</param>
376 /// <param name="token">キャンセル用トークン</param>
377 /// <returns>Taskオブジェクト</returns>
378 public async Task LoadFileAsync(string filepath, Encoding enc,System.Threading.CancellationTokenSource token)
380 WinFileReader fs = new WinFileReader(filepath, enc);
381 await this.LoadAsyncImpl(fs, token);
385 async Task LoadAsyncImpl(WinFileReader fs,System.Threading.CancellationTokenSource token)
387 this.IsEnabled = false;
388 this.View.LayoutLines.IsFrozneDirtyFlag = true;
389 await this.Document.LoadAsync(fs, token);
390 this.View.LayoutLines.IsFrozneDirtyFlag = false;
391 TextStoreHelper.NotifyTextChanged(this.textStore, 0, 0, this.Document.Length);
392 if (this.verticalScrollBar != null)
393 this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;
394 this.View.CalculateLineCountOnScreen();
395 this.IsEnabled = true;
399 /// ドキュメントの内容をファイルに保存する
401 /// <param name="filepath">ファイルパス</param>
402 /// <param name="newLine">改行コード</param>
403 /// <param name="enc">エンコード</param>
404 /// <returns>Taskオブジェクト</returns>
405 public async Task SaveFile(string filepath, Encoding enc,string newLine, System.Threading.CancellationTokenSource token)
407 WinFileWriter fs = new WinFileWriter(filepath, enc);
408 fs.NewLine = newLine;
409 await this.Document.SaveAsync(fs, token);
416 public void Dispose()
421 GC.SuppressFinalize(this);
422 this.disposed = true;
428 /// <param name="disposing">真ならマネージドリソースも開放し、そうでないならアンマネージドリソースのみを開放する</param>
429 void Dispose(bool disposing)
433 this.textStore.Dispose();
436 this.Render.Dispose();
438 SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
441 void Refresh(Rectangle updateRect)
443 if (this.disposed || this.Visibility == Visibility.Collapsed)
446 this.Render.BegineDraw();
448 this.View.Draw(updateRect);
450 this.Render.FillBackground(updateRect);
451 this.Render.EndDraw();
455 void CanExecute(object sender, CanExecuteRoutedEventArgs e)
457 e.CanExecute = this.IsEnabled;
460 void ToggleCodePointCommand(object sender, RoutedEventArgs e)
462 if (!this._Controller.ConvertToChar())
463 this._Controller.ConvertToCodePoint();
467 void CopyCommand(object sender, RoutedEventArgs e)
472 void CutCommand(object sender, RoutedEventArgs e)
478 void PasteCommand(object sender, RoutedEventArgs e)
484 void DeleteCommand(object sender, RoutedEventArgs e)
486 int oldLength = this.Document.Length;
487 this._Controller.DoDeleteAction();
491 void SelectAllCommand(object sender, RoutedEventArgs e)
493 this.Select(0, this.Document.Length);
497 void UndoCommand(object sender, RoutedEventArgs e)
499 int oldLength = this.Document.Length;
500 this.Document.UndoManager.undo();
504 void RedoCommand(object sender, RoutedEventArgs e)
506 int oldLength = this.Document.Length;
507 this.Document.UndoManager.redo();
511 void ToggleInsertCommand(object sender, RoutedEventArgs e)
514 this.InsertMode = false;
516 this.InsertMode = true;
520 void ToggleRectSelectCommand(object sender, RoutedEventArgs e)
522 if (this.RectSelectMode)
523 this.RectSelectMode = false;
525 this.RectSelectMode = true;
528 void ToggleFlowDirectionCommand(object sender, RoutedEventArgs e)
530 if (this.FlowDirection == System.Windows.FlowDirection.LeftToRight)
531 this.FlowDirection = System.Windows.FlowDirection.RightToLeft;
533 this.FlowDirection = System.Windows.FlowDirection.LeftToRight;
538 internal TextStore TextStore
540 get { return this.textStore; }
543 bool textStore_IsReadOnly()
548 bool textStore_IsLoading()
553 void textStore_CompositionEnded()
555 TextStoreHelper.EndCompostion(this.Document);
559 void textStore_CompositionUpdated(int start, int end)
561 if (TextStoreHelper.ScrollToCompstionUpdated(this.textStore, this.View, start, end))
564 bool textStore_CompositionStarted()
566 bool result = TextStoreHelper.StartCompstion(this.Document);
568 System.Media.SystemSounds.Beep.Play();
572 string _textStore_GetString(int start, int length)
574 return this.Document.ToString(start, length);
577 IntPtr _textStore_GetHWnd()
579 var hwndSource = HwndSource.FromVisual(this) as HwndSource;
580 if (hwndSource != null)
581 return hwndSource.Handle;
586 void _textStore_GetStringExtent(
590 out POINT o_bottomRight
593 Point startPos, endPos;
594 TextStoreHelper.GetStringExtent(this.Document, this.View, i_startIndex, i_endIndex, out startPos, out endPos);
596 double scale = this.Render.GetScale();
598 startPos = PointToScreen(this.TranslatePoint(startPos.Scale(scale), this));
599 endPos = PointToScreen(this.TranslatePoint(endPos.Scale(scale), this));
601 o_topLeft = new POINT((int)startPos.X, (int)startPos.Y);
602 o_bottomRight = new POINT((int)endPos.X, (int)endPos.Y);
605 void _textStore_GetScreenExtent(out POINT o_topLeft, out POINT o_bottomRight)
607 var pointTopLeft = new Point(0, 0);
608 var pointBottomRight = new Point(this.RenderSize.Width, this.RenderSize.Height);
610 pointTopLeft = PointToScreen(pointTopLeft);
611 pointBottomRight = PointToScreen(pointBottomRight);
613 o_topLeft = new POINT((int)pointTopLeft.X, (int)pointTopLeft.Y);
614 o_bottomRight = new POINT((int)pointBottomRight.X, (int)pointBottomRight.Y);
617 void _textStore_GetSelectionIndex(out int o_startIndex, out int o_endIndex)
619 TextStoreHelper.GetSelection(this._Controller, this.View.Selections, out o_startIndex, out o_endIndex);
622 void _textStore_SetSelectionIndex(int i_startIndex, int i_endIndex)
624 TextStoreHelper.SetSelectionIndex(this._Controller, this.View, i_startIndex, i_endIndex);
628 void _textStore_InsertAtSelection(string i_value, ref int o_startIndex, ref int o_endIndex)
630 TextStoreHelper.InsertTextAtSelection(this._Controller, i_value);
635 /// キーボードフォーカスが取得されたときに呼ばれます
637 /// <param name="e">イベントデーター</param>
638 protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
640 base.OnGotKeyboardFocus(e);
641 this.textStore.SetFocus();
642 this.View.IsFocused = true;
647 /// キーボードフォーカスが失われたときに呼ばれます
649 /// <param name="e">イベントデーター</param>
650 protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
652 base.OnLostKeyboardFocus(e);
653 this.View.IsFocused = false;
659 /// キャレットが移動したときに通知されるイベント
661 public event EventHandler CaretMoved;
664 protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
666 this.peer = new FooTextBoxAutomationPeer(this);
672 protected override void OnTextInput(TextCompositionEventArgs e)
676 this._Controller.DoEnterAction();
677 this.AutoIndentHooker(this, null);
679 else if (e.Text == "\b")
681 this._Controller.DoBackSpaceAction();
685 if(this.IsInputString(e.Text))
686 this._Controller.DoInputString(e.Text);
693 bool IsInputString(string s)
695 foreach (char charCode in s)
697 if ((0x20 <= charCode && charCode <= 0x7e)
705 protected override void OnKeyDown(KeyEventArgs e)
707 if (this.textStore.IsLocked())
710 ModifierKeys modiferKeys = e.KeyboardDevice.Modifiers;
711 bool movedCaret = false;
715 this._Controller.MoveCaretVertical(-1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));
721 this._Controller.MoveCaretVertical(+1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));
727 this._Controller.MoveCaretHorizontical(-1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift), this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control));
733 this._Controller.MoveCaretHorizontical(1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift), this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control));
739 this._Controller.Scroll(ScrollDirection.Up,this.View.LineCountOnScreen, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift),true);
744 this._Controller.Scroll(ScrollDirection.Down,this.View.LineCountOnScreen, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift),true);
749 if (this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control))
750 this._Controller.JumpToHead(this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));
752 this._Controller.JumpToLineHead(this.Document.CaretPostion.row, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));
757 if (this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control))
758 this._Controller.JumpToEnd(this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));
760 this._Controller.JumpToLineEnd(this.Document.CaretPostion.row, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift));
765 int oldLength = this.Document.Length;
766 if (this.Selection.Length == 0)
767 this._Controller.DoInputChar('\t');
768 else if(this.IsPressedModifierKey(modiferKeys,ModifierKeys.Shift))
769 this._Controller.DownIndent();
771 this._Controller.UpIndent();
776 if (movedCaret && this.peer != null)
777 this.peer.OnNotifyCaretChanged();
781 bool IsPressedModifierKey(ModifierKeys keys, ModifierKeys pressed)
785 if ((keys & pressed) == pressed)
791 /// ダブルクリックされたときに呼ばれます
793 /// <param name="e">イベントパラメーター</param>
795 /// イベントパラメーターはFooMouseEventArgsにキャスト可能です。
796 /// e.Handledを真にした場合、単語単位の選択が行われなくなります
798 protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
800 var p = this.GetDipFromPoint(e.GetPosition(this));
801 TextPoint tp = this.View.GetTextPointFromPostion(p);
802 if (tp == TextPoint.Null)
804 int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);
806 FooMouseButtonEventArgs newEventArgs = new FooMouseButtonEventArgs(e.MouseDevice,
811 newEventArgs.RoutedEvent = e.RoutedEvent;
812 base.OnMouseDoubleClick(newEventArgs);
814 if (newEventArgs.Handled)
817 if (e.LeftButton == MouseButtonState.Pressed)
820 this._Controller.SelectWord(index);
821 this.textStore.NotifySelectionChanged();
822 if(this.peer != null)
823 this.peer.OnNotifyCaretChanged();
829 /// マウスボタンが押されたときに呼ばれます
831 /// <param name="e">イベントパラメーター</param>
833 /// イベントパラメーターはFooMouseEventArgsにキャスト可能です。
834 /// e.Handledを真にした場合、キャレットの移動処理が行われなくなります
836 protected override void OnMouseDown(MouseButtonEventArgs e)
838 var p = this.GetDipFromPoint(e.GetPosition(this));
839 TextPoint tp = this.View.GetTextPointFromPostion(p);
840 if (tp == TextPoint.Null)
842 int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);
844 FooMouseButtonEventArgs newEventArgs = new FooMouseButtonEventArgs(e.MouseDevice,
849 newEventArgs.RoutedEvent = e.RoutedEvent;
850 base.OnMouseDown(newEventArgs);
852 if (newEventArgs.Handled)
855 if (e.LeftButton == MouseButtonState.Pressed)
857 FoldingItem foldingData = this.View.HitFoldingData(p.X,tp.row);
858 if (foldingData != null)
860 if (foldingData.Expand)
861 this.View.LayoutLines.FoldingCollection.Collapse(foldingData);
863 this.View.LayoutLines.FoldingCollection.Expand(foldingData);
864 this._Controller.JumpCaret(foldingData.Start,false);
868 this._Controller.JumpCaret(tp.row, tp.col, false);
870 if (this.peer != null)
871 this.peer.OnNotifyCaretChanged();
872 this.View.IsFocused = true;
881 /// <param name="e">イベントパラメーター</param>
883 /// イベントパラメーターはFooMouseEventArgsにキャスト可能です。
884 /// e.Handledを真にした場合、選択処理と状況に応じたカーソルの変化が行われなくなります
886 protected override void OnMouseMove(MouseEventArgs e)
888 var p = this.GetDipFromPoint(e.GetPosition(this));
889 TextPoint tp = this.View.GetTextPointFromPostion(p);
890 if (tp == TextPoint.Null)
895 int index = this.View.GetIndexFromLayoutLine(tp);
897 FooMouseEventArgs newEventArgs = new FooMouseEventArgs(e.MouseDevice, e.Timestamp, e.StylusDevice, index);
898 newEventArgs.RoutedEvent = e.RoutedEvent;
899 base.OnMouseMove(newEventArgs);
901 if (newEventArgs.Handled)
904 if (this.View.HitTextArea(p.X,p.Y))
906 if (this._Controller.IsMarker(tp, HilightType.Url))
907 this.Cursor = Cursors.Hand;
909 this.Cursor = Cursors.IBeam;
911 if (e.LeftButton == MouseButtonState.Pressed)
913 this._Controller.MoveCaretAndSelect(tp);
914 if (this.peer != null)
915 this.peer.OnNotifyCaretChanged();
921 this.Cursor = Cursors.Arrow;
925 private Point GetDipFromPoint(Point p)
928 this.Render.GetDpi(out dpi,out dpi);
929 double scale = dpi / 96.0;
930 return p.Scale(1 / scale);
934 protected override void OnMouseWheel(MouseWheelEventArgs e)
936 if(Keyboard.Modifiers == ModifierKeys.None)
939 this._Controller.Scroll(ScrollDirection.Up, SystemParameters.WheelScrollLines, false, false);
941 this._Controller.Scroll(ScrollDirection.Down, SystemParameters.WheelScrollLines, false, false);
943 else if (Keyboard.Modifiers == ModifierKeys.Control)
945 double newFontSize = this.Render.FontSize;
950 if (newFontSize > MaxFontSize)
952 else if (newFontSize < MinFontSize)
954 this.Render.FontSize = newFontSize;
955 SetValue(MagnificationPowerPropertyKey, this.Render.FontSize / this.FontSize);
958 base.OnMouseWheel(e);
961 void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
963 if (e.Category == UserPreferenceCategory.Keyboard)
965 int blinkTime = (int)NativeMethods.GetCaretBlinkTime();
966 this.View.CaretBlink = blinkTime >= 0;
967 this.View.CaretBlinkTime = blinkTime * 2;
969 if (e.Category == UserPreferenceCategory.General)
971 this.View.CaretWidthOnInsertMode = SystemParameters.CaretWidth;
975 void Document_Update(object sender, DocumentUpdateEventArgs e)
977 if (this.textStore.IsLocked())
979 if(e.type == UpdateType.Replace)
980 TextStoreHelper.NotifyTextChanged(this.textStore, e.startIndex, e.removeLength, e.insertLength);
983 void timer_Tick(object sender, EventArgs e)
985 if (this.image.ActualWidth == 0 || this.image.ActualHeight == 0)
987 if (this.Resize(this.image.ActualWidth, this.image.ActualHeight))
993 bool updateAll = this.View.LayoutLines.HilightAll() || this.View.LayoutLines.GenerateFolding();
995 ITextLayout layout = this.View.LayoutLines.GetLayout(this.Document.CaretPostion.row);
996 double width = layout.GetWidthFromIndex(this.Document.CaretPostion.col);
998 width = this.View.CaretWidthOnInsertMode;
999 double height = layout.Height;
1000 Rectangle updateRect = new Rectangle(
1001 this.View.CaretLocation.X,
1002 this.View.CaretLocation.Y,
1009 this.Refresh(updateRect);
1012 void horizontalScrollBar_Scroll(object sender, ScrollEventArgs e)
1014 if (this.horizontalScrollBar == null)
1017 if (this.FlowDirection == System.Windows.FlowDirection.LeftToRight)
1018 toX = this.horizontalScrollBar.Value;
1020 toX = -this.horizontalScrollBar.Value;
1021 this._Controller.Scroll(toX, this.View.Src.Row, false, false);
1025 void verticalScrollBar_Scroll(object sender, ScrollEventArgs e)
1027 if (this.verticalScrollBar == null)
1029 int newRow = (int)this.verticalScrollBar.Value;
1030 if (newRow >= this.View.LayoutLines.Count)
1032 this._Controller.Scroll(this.View.Src.X,newRow, false, false);
1036 void View_SrcChanged(object sender, EventArgs e)
1038 if (this.horizontalScrollBar == null || this.verticalScrollBar == null)
1040 EditView view = this.View;
1041 if (view.Src.Row > this.verticalScrollBar.Maximum)
1042 this.verticalScrollBar.Maximum = view.Src.Row + view.LineCountOnScreen + 1;
1043 double absoulteX = Math.Abs(view.Src.X);
1044 if(absoulteX > this.horizontalScrollBar.Maximum)
1045 this.horizontalScrollBar.Maximum = absoulteX + view.PageBound.Width + 1;
1046 if(view.Src.Row != this.verticalScrollBar.Value)
1047 this.verticalScrollBar.Value = view.Src.Row;
1048 if (view.Src.X != this.horizontalScrollBar.Value)
1049 this.horizontalScrollBar.Value = Math.Abs(view.Src.X);
1052 void Controller_SelectionChanged(object sender, EventArgs e)
1054 this.View.CaretBlink = this.View.CaretBlink;
1055 this.CaretMoved(this, null);
1056 //こうしないと選択できなくなってしまう
1057 this.nowCaretMove = true;
1058 SetValue(SelectionProperty, new TextRange(this._Controller.SelectionStart, this._Controller.SelectionLength));
1059 SetValue(CaretPostionProperty, this.Document.CaretPostion);
1060 this.nowCaretMove = false;
1061 if(this.textStore.IsLocked() == false)
1062 this.textStore.NotifySelectionChanged();
1065 void FooTextBox_Loaded(object sender, RoutedEventArgs e)
1067 this.Resize(this.image.ActualWidth, this.image.ActualHeight);
1072 bool Resize(double width, double height)
1074 if (width == 0 || height == 0)
1075 throw new ArgumentOutOfRangeException();
1076 if (this.Render.Resize(width, height))
1078 double scale = this.Render.GetScale();
1079 // RenderはレタリングはDIPだが、widthとheightの値はDPI依存なのでDIPに変換する
1080 this.View.PageBound = new Rectangle(0, 0, width / scale, height / scale);
1082 if (this.horizontalScrollBar != null)
1084 this.horizontalScrollBar.LargeChange = this.View.PageBound.Width;
1085 this.horizontalScrollBar.Maximum = this.View.LongestWidth + this.horizontalScrollBar.LargeChange + 1;
1087 if (this.verticalScrollBar != null)
1089 this.verticalScrollBar.LargeChange = this.View.LineCountOnScreen;
1090 this.verticalScrollBar.Maximum = this.View.LayoutLines.Count + this.verticalScrollBar.LargeChange + 1;
1098 /// プロパティーが変更されたときに呼ばれます
1100 /// <param name="e">イベントパラメーター</param>
1101 protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
1103 switch (e.Property.Name)
1106 this._Controller.IndentMode = this.IndentMode;
1109 if(!this.nowCaretMove)
1110 this.Select(this.Selection.Index, this.Selection.Length);
1112 case "CaretPostion":
1113 if (!this.nowCaretMove)
1114 this.JumpCaret(this.CaretPostion.row, this.CaretPostion.col);
1116 case "LineBreakMethod":
1117 this.Document.LineBreak = this.LineBreakMethod;
1119 case "LineBreakCharCount":
1120 this.Document.LineBreakCharCount = this.LineBreakCharCount;
1123 this.View.InsertMode = this.InsertMode;
1126 this.Document.TabStops = this.TabChars;
1128 case "RectSelectMode":
1129 this._Controller.RectSelection = this.RectSelectMode;
1132 this.View.HideCaret = !this.DrawCaret;
1134 case "DrawCaretLine":
1135 this.View.HideLineMarker = !this.DrawCaretLine;
1137 case "DrawLineNumber":
1138 this.Document.DrawLineNumber = this.DrawLineNumber;
1139 this._Controller.JumpCaret(this.Document.CaretPostion.row, this.Document.CaretPostion.col);
1142 this.Render.FontFamily = this.FontFamily;
1145 this.Render.FontSize = this.FontSize;
1148 this.Render.FontStyle = this.FontStyle;
1151 this.Render.FontWeigth = this.FontWeight;
1154 this.Render.Foreground = D2DRender.ToColor4(this.Foreground);
1157 this.Render.Background = D2DRender.ToColor4(this.Background);
1160 this.Render.ControlChar =D2DRender.ToColor4( this.ControlChar);
1163 this.Render.Hilight = D2DRender.ToColor4(this.Hilight);
1166 this.Render.Keyword1 = D2DRender.ToColor4(this.Keyword1);
1169 this.Render.Keyword2 = D2DRender.ToColor4(this.Keyword2);
1172 this.Render.Comment = D2DRender.ToColor4(this.Comment);
1175 this.Render.Literal = D2DRender.ToColor4(this.Literal);
1178 this.Render.Url = D2DRender.ToColor4(this.URL);
1181 this.Render.InsertCaret = D2DRender.ToColor4(this.InsertCaret);
1183 case "OverwriteCaret":
1184 this.Render.OverwriteCaret = D2DRender.ToColor4(this.OverwriteCaret);
1187 this.View.Padding = new Padding((int)this.Padding.Left, (int)this.Padding.Top, (int)this.Padding.Right, (int)this.Padding.Bottom);
1190 this.Render.LineMarker = D2DRender.ToColor4(this.LineMarker);
1193 this.Document.UrlMark = this.MarkURL;
1195 case "ShowFullSpace":
1196 this.Document.ShowFullSpace = this.ShowFullSpace;
1198 case "ShowHalfSpace":
1199 this.Document.ShowHalfSpace = this.ShowHalfSpace;
1202 this.Document.ShowTab = this.ShowTab;
1204 case "ShowLineBreak":
1205 this.Document.ShowLineBreak = this.ShowLineBreak;
1207 case "FlowDirection":
1208 this.Document.RightToLeft = this.FlowDirection == System.Windows.FlowDirection.RightToLeft;
1209 this.horizontalScrollBar.FlowDirection = this.FlowDirection;
1212 this.Document.HideRuler = !this.DrawRuler;
1213 this._Controller.JumpCaret(this.Document.CaretPostion.row, this.Document.CaretPostion.col);
1216 this.Render.UpdateArea = D2DRender.ToColor4(this.UpdateArea);
1219 this.Render.LineNumber = D2DRender.ToColor4(this.LineNumber);
1222 base.OnPropertyChanged(e);
1227 internal Controller Controller
1231 return this._Controller;
1236 /// 文字列の描写に使用されるアンチエイリアシング モードを表します
1238 public TextAntialiasMode TextAntialiasMode
1242 return this.Render.TextAntialiasMode;
1246 this.Render.TextAntialiasMode = value;
1253 public IHilighter Hilighter
1257 return this.View.Hilighter;
1261 this.View.Hilighter = value;
1262 this.View.LayoutLines.ClearLayoutCache();
1267 /// フォールティングを作成するインターフェイスを表す
1269 public IFoldingStrategy FoldingStrategy
1273 return this.View.LayoutLines.FoldingStrategy;
1277 this.View.LayoutLines.FoldingStrategy = value;
1279 this.View.LayoutLines.FoldingCollection.Clear();
1286 public MarkerPatternSet MarkerPatternSet
1290 return this.Document.MarkerPatternSet;
1297 public Document Document
1306 public LineToIndexTable LayoutLineCollection
1308 get { return this.View.LayoutLines; }
1314 public string SelectedText
1318 return this._Controller.SelectedText;
1322 int oldLength = this.Document.Length;
1323 this._Controller.SelectedText = value;
1330 public IndentMode IndentMode
1332 get { return (IndentMode)GetValue(IndentModeProperty); }
1333 set { SetValue(IndentModeProperty, value); }
1337 /// IndentModeの依存プロパティを表す
1339 public static readonly DependencyProperty IndentModeProperty =
1340 DependencyProperty.Register("IndentMode", typeof(IndentMode), typeof(FooTextBox), new PropertyMetadata(IndentMode.Tab));
1346 /// Lengthが0の場合はキャレット位置を表します。
1347 /// 矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります
1349 public TextRange Selection
1351 get { return (TextRange)GetValue(SelectionProperty); }
1352 set { SetValue(SelectionProperty, value); }
1356 /// Selectionの依存プロパティを表す
1358 public static readonly DependencyProperty SelectionProperty =
1359 DependencyProperty.Register("Selection", typeof(TextRange), typeof(FooTextBox), new PropertyMetadata(TextRange.Null));
1364 public double MagnificationPower
1366 get { return (double)GetValue(MagnificationPowerPropertyKey.DependencyProperty); }
1372 public static readonly DependencyPropertyKey MagnificationPowerPropertyKey =
1373 DependencyProperty.RegisterReadOnly("MagnificationPower", typeof(double), typeof(FooTextBox), new PropertyMetadata(1.0));
1378 public new FlowDirection FlowDirection
1380 get { return (FlowDirection)GetValue(FlowDirectionProperty); }
1381 set { SetValue(FlowDirectionProperty, value); }
1385 /// レタリング方向を表す。これは依存プロパティです
1387 public new static readonly DependencyProperty FlowDirectionProperty =
1388 DependencyProperty.Register("FlowDirection", typeof(FlowDirection), typeof(FooTextBox), new PropertyMetadata(FlowDirection.LeftToRight));
1391 /// キャレット位置を表す。これは依存プロパティです
1393 public TextPoint CaretPostion
1395 get { return (TextPoint)GetValue(CaretPostionProperty); }
1396 set { SetValue(CaretPostionProperty, value); }
1400 /// CaretPostionの依存プロパティを表す
1402 public static readonly DependencyProperty CaretPostionProperty =
1403 DependencyProperty.Register("CaretPostion", typeof(TextPoint), typeof(FooTextBox), new PropertyMetadata(TextPoint.Null));
1406 /// デフォルトの文字色を表す。これは依存プロパティです
1408 public new System.Windows.Media.Color Foreground
1410 get { return (System.Windows.Media.Color)GetValue(ForegroundProperty); }
1411 set { SetValue(ForegroundProperty, value); }
1415 /// Foregroundの依存プロパティを表す
1417 public new static readonly DependencyProperty ForegroundProperty =
1418 DependencyProperty.Register("Foreground", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowTextColor));
1421 /// 背景色を表す。これは依存プロパティです
1423 public new System.Windows.Media.Color Background
1425 get { return (System.Windows.Media.Color)GetValue(BackgroundProperty); }
1426 set { SetValue(BackgroundProperty, value); }
1430 /// Backgroundの依存プロパティを表す
1432 public new static readonly DependencyProperty BackgroundProperty =
1433 DependencyProperty.Register("Background", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowColor));
1436 /// コントロールコードの文字色を表す。これは依存プロパティです
1438 public System.Windows.Media.Color ControlChar
1440 get { return (System.Windows.Media.Color)GetValue(ControlCharProperty); }
1441 set { SetValue(ControlCharProperty, value); }
1445 /// ControlCharの依存プロパティを表す
1447 public static readonly DependencyProperty ControlCharProperty =
1448 DependencyProperty.Register("ControlChar", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Gray));
1451 /// 選択時の背景色を表す。これは依存プロパティです
1453 public System.Windows.Media.Color Hilight
1455 get { return (System.Windows.Media.Color)GetValue(HilightProperty); }
1456 set { SetValue(HilightProperty, value); }
1460 /// Hilightの依存プロパティを表す
1462 public static readonly DependencyProperty HilightProperty =
1463 DependencyProperty.Register("Hilight", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.DeepSkyBlue));
1466 /// キーワード1の文字色を表す。これは依存プロパティです
1468 public System.Windows.Media.Color Keyword1
1470 get { return (System.Windows.Media.Color)GetValue(Keyword1Property); }
1471 set { SetValue(Keyword1Property, value); }
1475 /// Keyword1の依存プロパティを表す
1477 public static readonly DependencyProperty Keyword1Property =
1478 DependencyProperty.Register("Keyword1", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Blue));
1481 /// キーワード2の文字色を表す。これは依存プロパティです
1483 public System.Windows.Media.Color Keyword2
1485 get { return (System.Windows.Media.Color)GetValue(Keyword2Property); }
1486 set { SetValue(Keyword2Property, value); }
1490 /// Keyword2の依存プロパティを表す
1492 public static readonly DependencyProperty Keyword2Property =
1493 DependencyProperty.Register("Keyword2", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.DarkCyan));
1496 /// コメントの文字色を表す。これは依存プロパティです
1498 public System.Windows.Media.Color Comment
1500 get { return (System.Windows.Media.Color)GetValue(CommentProperty); }
1501 set { SetValue(CommentProperty, value); }
1505 /// Commentの依存プロパティを表す
1507 public static readonly DependencyProperty CommentProperty =
1508 DependencyProperty.Register("Comment", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Green));
1511 /// 文字リテラルの文字色を表す。これは依存プロパティです
1513 public System.Windows.Media.Color Literal
1515 get { return (System.Windows.Media.Color)GetValue(LiteralProperty); }
1516 set { SetValue(LiteralProperty, value); }
1520 /// Literalの依存プロパティを表す
1522 public static readonly DependencyProperty LiteralProperty =
1523 DependencyProperty.Register("Literal", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Brown));
1526 /// URLの文字色を表す。これは依存プロパティです
1528 public System.Windows.Media.Color URL
1530 get { return (System.Windows.Media.Color)GetValue(URLProperty); }
1531 set { SetValue(URLProperty, value); }
1537 public static readonly DependencyProperty URLProperty =
1538 DependencyProperty.Register("URL", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Blue));
1544 public System.Windows.Media.Color LineMarker
1546 get { return (System.Windows.Media.Color)GetValue(LineMarkerProperty); }
1547 set { SetValue(LineMarkerProperty, value); }
1551 /// LineMarkerの依存プロパティを表す
1553 public static readonly DependencyProperty LineMarkerProperty =
1554 DependencyProperty.Register("LineMarker", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Silver));
1557 /// 挿入モード時のキャレットの色を表す
1559 public System.Windows.Media.Color InsertCaret
1561 get { return (System.Windows.Media.Color)GetValue(InsertCaretProperty); }
1562 set { SetValue(InsertCaretProperty, value); }
1566 /// InsertCaretの依存プロパティを表す
1568 public static readonly DependencyProperty InsertCaretProperty =
1569 DependencyProperty.Register("InsertCaret", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowTextColor));
1574 public System.Windows.Media.Color UpdateArea
1576 get { return (System.Windows.Media.Color)GetValue(UpdateAreaProperty); }
1577 set { SetValue(UpdateAreaProperty, value); }
1581 /// UpdateAreaの依存プロパティを表す
1583 public static readonly DependencyProperty UpdateAreaProperty =
1584 DependencyProperty.Register("UpdateArea", typeof(System.Windows.Media.Color), typeof(FooTextBox), new PropertyMetadata(Colors.MediumSeaGreen));
1587 /// 上書きモード時のキャレット職を表す
1589 public System.Windows.Media.Color OverwriteCaret
1591 get { return (System.Windows.Media.Color)GetValue(OverwriteCaretProperty); }
1592 set { SetValue(OverwriteCaretProperty, value); }
1596 /// OverwriteCaretの依存プロパティを表す
1598 public static readonly DependencyProperty OverwriteCaretProperty =
1599 DependencyProperty.Register("OverwriteCaret", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowTextColor));
1604 public System.Windows.Media.Color LineNumber
1606 get { return (System.Windows.Media.Color)GetValue(LineNumberProperty); }
1607 set { SetValue(LineNumberProperty, value); }
1611 /// Using a DependencyProperty as the backing store for LineNumber. This enables animation, styling, binding, etc...
1613 public static readonly DependencyProperty LineNumberProperty =
1614 DependencyProperty.Register("LineNumber", typeof(System.Windows.Media.Color), typeof(FooTextBox), new PropertyMetadata(Colors.DimGray));
1617 /// 挿入モードなら真を返し、そうでないなら、偽を返す。これは依存プロパティです
1619 public bool InsertMode
1621 get { return (bool)GetValue(InsertModeProperty); }
1622 set { SetValue(InsertModeProperty, value); }
1626 /// InsertModeの依存プロパティを表す
1628 public static readonly DependencyProperty InsertModeProperty =
1629 DependencyProperty.Register("InsertMode",
1632 new FrameworkPropertyMetadata(true));
1635 /// タブの文字数を表す。これは依存プロパティです
1639 get { return (int)GetValue(TabCharsProperty); }
1640 set { SetValue(TabCharsProperty, value); }
1644 /// TabCharsの依存プロパティを表す
1646 public static readonly DependencyProperty TabCharsProperty =
1647 DependencyProperty.Register("TabChars",
1650 new FrameworkPropertyMetadata(4));
1653 /// 矩形選択モードなら真を返し、そうでないなら偽を返す。これは依存プロパティです
1655 public bool RectSelectMode
1657 get { return (bool)GetValue(RectSelectModeProperty); }
1658 set { SetValue(RectSelectModeProperty, value); }
1662 /// RectSelectModeの依存プロパティを表す
1664 public static readonly DependencyProperty RectSelectModeProperty =
1665 DependencyProperty.Register("RectSelectMode", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false));
1671 /// 変更した場合、レイアウトの再構築を行う必要があります
1673 public LineBreakMethod LineBreakMethod
1675 get { return (LineBreakMethod)GetValue(LineBreakProperty); }
1676 set { SetValue(LineBreakProperty, value); }
1680 /// LineBreakMethodの依存プロパティを表す
1682 public static readonly DependencyProperty LineBreakProperty =
1683 DependencyProperty.Register("LineBreakMethod", typeof(LineBreakMethod), typeof(FooTextBox), new PropertyMetadata(LineBreakMethod.None));
1687 /// 折り返しの幅を指定する。LineBreakMethod.CharUnit以外の時は無視されます
1690 /// 変更した場合、レイアウトの再構築を行う必要があります
1692 public int LineBreakCharCount
1694 get { return (int)GetValue(LineBreakCharCountProperty); }
1695 set { SetValue(LineBreakCharCountProperty, value); }
1699 /// LineBreakCharCountの依存プロパティを表す
1701 public static readonly DependencyProperty LineBreakCharCountProperty =
1702 DependencyProperty.Register("LineBreakCharCount", typeof(int), typeof(FooTextBox), new PropertyMetadata(80));
1705 /// キャレットを描くなら真。そうでないなら偽を返す。これは依存プロパティです
1707 public bool DrawCaret
1709 get { return (bool)GetValue(DrawCaretProperty); }
1710 set { SetValue(DrawCaretProperty, value); }
1714 /// DrawCaretの依存プロパティを表す
1716 public static readonly DependencyProperty DrawCaretProperty =
1717 DependencyProperty.Register("DrawCaret", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(true));
1721 /// キャレットラインを描くなら真。そうでないなら偽を返す。これは依存プロパティです
1723 public bool DrawCaretLine
1725 get { return (bool)GetValue(DrawCaretLineProperty); }
1726 set { SetValue(DrawCaretLineProperty, value); }
1730 /// DrawCaretLineの依存プロパティを表す
1732 public static readonly DependencyProperty DrawCaretLineProperty =
1733 DependencyProperty.Register("DrawCaretLine", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false));
1736 /// 行番号を描くなら真。そうでなければ偽。これは依存プロパティです
1738 public bool DrawLineNumber
1740 get { return (bool)GetValue(DrawLineNumberProperty); }
1741 set { SetValue(DrawLineNumberProperty, value); }
1745 /// ルーラーを描くなら真。そうでなければ偽。これは依存プロパティです
1747 public bool DrawRuler
1749 get { return (bool)GetValue(DrawRulerProperty); }
1750 set { SetValue(DrawRulerProperty, value); }
1754 /// DrawRulerの依存プロパティを表す
1756 public static readonly DependencyProperty DrawRulerProperty =
1757 DependencyProperty.Register("DrawRuler", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false));
1761 /// DrawLineNumberの依存プロパティを表す
1763 public static readonly DependencyProperty DrawLineNumberProperty =
1764 DependencyProperty.Register("DrawLineNumber", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false));
1767 /// URLに下線を引くなら真。そうでないなら偽を表す。これは依存プロパティです
1771 get { return (bool)GetValue(MarkURLProperty); }
1772 set { SetValue(MarkURLProperty, value); }
1776 /// MarkURLの依存プロパティを表す
1778 public static readonly DependencyProperty MarkURLProperty =
1779 DependencyProperty.Register("MarkURL", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false));
1782 /// 全角スペースを表示するなら真。そうでないなら偽
1784 public bool ShowFullSpace
1786 get { return (bool)GetValue(ShowFullSpaceProperty); }
1787 set { SetValue(ShowFullSpaceProperty, value); }
1791 /// ShowFullSpaceの依存プロパティを表す
1793 public static readonly DependencyProperty ShowFullSpaceProperty =
1794 DependencyProperty.Register("ShowFullSpace", typeof(bool), typeof(FooTextBox), new UIPropertyMetadata(false));
1797 /// 半角スペースを表示するなら真。そうでないなら偽
1799 public bool ShowHalfSpace
1801 get { return (bool)GetValue(ShowHalfSpaceProperty); }
1802 set { SetValue(ShowHalfSpaceProperty, value); }
1806 /// ShowHalfSpaceの依存プロパティを表す
1808 public static readonly DependencyProperty ShowHalfSpaceProperty =
1809 DependencyProperty.Register("ShowHalfSpace", typeof(bool), typeof(FooTextBox), new UIPropertyMetadata(false));
1812 /// タブを表示するなら真。そうでないなら偽
1816 get { return (bool)GetValue(ShowTabProperty); }
1817 set { SetValue(ShowTabProperty, value); }
1821 /// ShowTabの依存プロパティを表す
1823 public static readonly DependencyProperty ShowTabProperty =
1824 DependencyProperty.Register("ShowTab", typeof(bool), typeof(FooTextBox), new UIPropertyMetadata(false));
1827 /// 改行マークを表示するなら真。そうでないなら偽
1829 public bool ShowLineBreak
1831 get { return (bool)GetValue(ShowLineBreakProperty); }
1832 set { SetValue(ShowLineBreakProperty, value); }
1836 /// ShowLineBreakの依存プロパティを表す
1838 public static readonly DependencyProperty ShowLineBreakProperty =
1839 DependencyProperty.Register("ShowLineBreak", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false));
1844 /// マウスボタン関連のイベントクラス
1846 public sealed class FooMouseButtonEventArgs : MouseButtonEventArgs
1849 /// イベントが発生したドキュメントのインデックス
1860 /// <param name="mouse">マウスデバイス</param>
1861 /// <param name="timestamp">タイムスタンプ</param>
1862 /// <param name="button">ボタン</param>
1863 /// <param name="stylusDevice">スタイラスデバイス</param>
1864 /// <param name="index">インデックス</param>
1865 public FooMouseButtonEventArgs(MouseDevice mouse, int timestamp, MouseButton button, StylusDevice stylusDevice, int index)
1866 : base(mouse, timestamp, button, stylusDevice)
1874 public sealed class FooMouseEventArgs : MouseEventArgs
1877 /// イベントが発生したドキュメントのインデックス
1888 /// <param name="mouse">マウスデバイス</param>
1889 /// <param name="timestamp">タイムスタンプ</param>
1890 /// <param name="stylusDevice">スタイラスデバイス</param>
1891 /// <param name="index">インデックス</param>
1892 public FooMouseEventArgs(MouseDevice mouse,
1894 StylusDevice stylusDevice,
1896 : base(mouse, timestamp, stylusDevice)