OSDN Git Service

ファイル読み込み後の再描写はすぐ行わなくても構わない
[fooeditengine/FooEditEngine.git] / UWP / FooEditEngine.UWP / FooTextBox.cs
1 /*
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.
5
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.
8
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/>.
10  */
11
12 using System;
13 using System.Text;
14 using System.ComponentModel;
15 using System.Threading.Tasks;
16 using Windows.ApplicationModel.Resources.Core;
17 using Windows.Devices.Input;
18 using Windows.System;
19 using Windows.ApplicationModel.DataTransfer;
20 using Windows.Foundation;
21 using Windows.UI;
22 using Windows.UI.Input;
23 using Windows.UI.Core;
24 using Windows.UI.Popups;
25 using Windows.UI.Text;
26 using Windows.UI.Xaml.Media;
27 using Windows.UI.Xaml;
28 using Windows.UI.Xaml.Controls;
29 using Windows.UI.Xaml.Controls.Primitives;
30 using Windows.UI.Xaml.Input;
31 using Windows.UI.Text.Core;
32
33 // テンプレート コントロールのアイテム テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=234235 を参照してください
34 namespace FooEditEngine.UWP
35 {
36     /// <summary>
37     /// テキストボックスコントロール
38     /// </summary>
39     public sealed class FooTextBox : Control,IDisposable
40     {
41         EditView View;
42         Controller _Controller;
43 #if !DUMMY_RENDER
44         D2DRender Render;
45 #else
46         DummyRender Render;
47 #endif
48         ScrollBar horizontalScrollBar, verticalScrollBar;
49         Windows.UI.Xaml.Shapes.Rectangle rectangle;
50         GestureRecognizer gestureRecongnizer = new GestureRecognizer();
51         CoreTextEditContext textEditContext;
52         CoreTextServicesManager textServiceManager;
53 #if ENABLE_AUTMATION
54         FooTextBoxAutomationPeer peer;
55 #endif
56         bool nowCaretMove = false;
57         bool nowCompstion = false;
58         bool requestSizeChange = false;
59         Document _Document;
60         DispatcherTimer timer = new DispatcherTimer();
61
62         const int Interval = 32;
63         const int IntervalWhenLostFocus = 160;
64
65         /// <summary>
66         /// コンストラクター
67         /// </summary>
68         public FooTextBox()
69         {
70             this.DefaultStyleKey = typeof(FooTextBox);
71             
72             this.rectangle = new Windows.UI.Xaml.Shapes.Rectangle();
73             this.rectangle.Margin = this.Padding;
74 #if !DUMMY_RENDER
75             this.Render = new D2DRender(this,this.rectangle);
76 #else
77             this.Render = new DummyRender();
78 #endif
79
80             this.Document = new Document();
81
82             this.View = new EditView(this.Document, this.Render, new Padding(5, 5, Gripper.HitAreaWidth / 2, Gripper.HitAreaWidth));
83             this.View.SrcChanged += View_SrcChanged;
84             this.View.InsertMode = this.InsertMode;
85             this.Document.DrawLineNumber = this.DrawLineNumber;
86             this.View.HideCaret = !this.DrawCaret;
87             this.View.HideLineMarker = !this.DrawCaretLine;
88             this.Document.HideRuler = !this.DrawRuler;
89             this.Document.UrlMark = this.MarkURL;
90             this.Document.TabStops = this.TabChars;
91
92             this._Controller = new Controller(this.Document, this.View);
93
94             this.gestureRecongnizer.GestureSettings = GestureSettings.Drag | 
95                 GestureSettings.RightTap | 
96                 GestureSettings.Tap | 
97                 GestureSettings.DoubleTap |
98                 GestureSettings.ManipulationTranslateX | 
99                 GestureSettings.ManipulationTranslateY |
100                 GestureSettings.ManipulationScale |
101                 GestureSettings.ManipulationTranslateInertia |
102                 GestureSettings.ManipulationScaleInertia;
103             this.gestureRecongnizer.RightTapped += gestureRecongnizer_RightTapped;
104             this.gestureRecongnizer.Tapped += gestureRecongnizer_Tapped;
105             this.gestureRecongnizer.Dragging += gestureRecongnizer_Dragging;
106             this.gestureRecongnizer.ManipulationInertiaStarting += GestureRecongnizer_ManipulationInertiaStarting; ;
107             this.gestureRecongnizer.ManipulationStarted += gestureRecongnizer_ManipulationStarted;
108             this.gestureRecongnizer.ManipulationUpdated += gestureRecongnizer_ManipulationUpdated;
109             this.gestureRecongnizer.ManipulationCompleted += gestureRecongnizer_ManipulationCompleted;
110
111             this.timer.Interval = new TimeSpan(0, 0, 0, 0, Interval);
112             this.timer.Tick += this.timer_Tick;
113             this.timer.Start();
114
115             this.GettingFocus += FooTextBox_GettingFocus;
116             this.LosingFocus += FooTextBox_LosingFocus;
117
118             this.SizeChanged += FooTextBox_SizeChanged;
119
120             this.Loaded += FooTextBox_Loaded;
121         }
122
123         /// <summary>
124         /// ファイナライザー
125         /// </summary>
126         ~FooTextBox()
127         {
128             this.Dispose(false);
129         }
130
131         /// <summary>
132         /// アンマネージドリソースを解放する
133         /// </summary>
134         public void Dispose()
135         {
136             this.Dispose(true);
137             GC.SuppressFinalize(this);
138         }
139
140         bool Disposed = false;
141         private void Dispose(bool disposing)
142         {
143             if (this.Disposed)
144                 return;
145             if (disposing)
146             {
147                 this.View.Dispose();
148                 this.Render.Dispose();
149             }
150         }
151
152         /// <summary>
153         /// ドキュメントを選択する
154         /// </summary>
155         /// <param name="start">開始インデックス</param>
156         /// <param name="length">長さ</param>
157         public void Select(int start, int length)
158         {
159             this.Document.Select(start, length);
160         }
161
162         /// <summary>
163         /// キャレットを指定した行に移動させます
164         /// </summary>
165         /// <param name="index">インデックス</param>
166         /// <remarks>このメソッドを呼び出すと選択状態は解除されます</remarks>
167         public void JumpCaret(int index)
168         {
169             this._Controller.JumpCaret(index);
170         }
171         /// <summary>
172         /// キャレットを指定した行と桁に移動させます
173         /// </summary>
174         /// <param name="row">行番号</param>
175         /// <param name="col">桁</param>
176         /// <remarks>このメソッドを呼び出すと選択状態は解除されます</remarks>
177         public void JumpCaret(int row, int col)
178         {
179             this._Controller.JumpCaret(row, col);
180         }
181
182         /// <summary>
183         /// 選択中のテキストをクリップボードにコピーします
184         /// </summary>
185         public void Copy()
186         {
187             string text = this._Controller.SelectedText;
188             if (text != null && text != string.Empty)
189             {
190                 DataPackage dataPackage = new DataPackage();
191                 dataPackage.RequestedOperation = DataPackageOperation.Copy;
192                 dataPackage.SetText(text);
193
194                 Clipboard.SetContent(dataPackage); 
195             }
196         }
197
198         /// <summary>
199         /// 選択中のテキストをクリップボードに切り取ります
200         /// </summary>
201         public void Cut()
202         {
203             string text = this._Controller.SelectedText;
204             if (text != null && text != string.Empty)
205             {
206                 DataPackage dataPackage = new DataPackage();
207                 dataPackage.RequestedOperation = DataPackageOperation.Copy;
208                 dataPackage.SetText(text);
209
210                 Clipboard.SetContent(dataPackage);
211                 
212                 this._Controller.SelectedText = "";
213             }
214         }
215
216         /// <summary>
217         /// 選択中のテキストを貼り付けます
218         /// </summary>
219         public async Task PasteAsync()
220         {
221             var dataPackageView = Clipboard.GetContent();
222             if (dataPackageView.Contains(StandardDataFormats.Text))
223             {
224                 try
225                 {
226                     this._Controller.SelectedText = await dataPackageView.GetTextAsync();
227                 }catch(Exception e)
228                 {
229                     System.Diagnostics.Debug.WriteLine("past error:" + e.Message);
230                 }
231             }
232         }
233
234         /// <summary>
235         /// すべて選択する
236         /// </summary>
237         public void SelectAll()
238         {
239             this.Document.Select(0, this.Document.Length);
240         }
241
242         /// <summary>
243         /// 選択を解除する
244         /// </summary>
245         public void DeSelectAll()
246         {
247             this._Controller.DeSelectAll();
248         }
249
250         /// <summary>
251         /// 対応する座標を返します
252         /// </summary>
253         /// <param name="tp">テキストポイント</param>
254         /// <returns>座標</returns>
255         /// <remarks>テキストポイントがクライアント領域の原点より外にある場合、返される値は原点に丸められます</remarks>
256         public Windows.Foundation.Point GetPostionFromTextPoint(TextPoint tp)
257         {
258             if (this.Document.FireUpdateEvent == false)
259                 throw new InvalidOperationException("");
260             return this.View.GetPostionFromTextPoint(tp);
261         }
262
263         /// <summary>
264         /// 対応するテキストポイントを返します
265         /// </summary>
266         /// <param name="p">クライアント領域の原点を左上とする座標</param>
267         /// <returns>テキストポイント</returns>
268         public TextPoint GetTextPointFromPostion(Windows.Foundation.Point p)
269         {
270             if (this.Document.FireUpdateEvent == false)
271                 throw new InvalidOperationException("");
272             return this.View.GetTextPointFromPostion(p);
273         }
274
275         /// <summary>
276         /// 行の高さを取得します
277         /// </summary>
278         /// <param name="row">レイアウト行</param>
279         /// <returns>行の高さ</returns>
280         public double GetLineHeight(int row)
281         {
282             if (this.Document.FireUpdateEvent == false)
283                 throw new InvalidOperationException("");
284             return this.View.LayoutLines.GetLayout(row).Height; ;
285         }
286
287         /// <summary>
288         /// インデックスに対応する座標を得ます
289         /// </summary>
290         /// <param name="index">インデックス</param>
291         /// <returns>座標を返す</returns>
292         public Windows.Foundation.Point GetPostionFromIndex(int index)
293         {
294             if (this.Document.FireUpdateEvent == false)
295                 throw new InvalidOperationException("");
296             TextPoint tp = this.View.GetLayoutLineFromIndex(index);
297             return this.View.GetPostionFromTextPoint(tp);
298         }
299
300         /// <summary>
301         /// 座標からインデックスに変換します
302         /// </summary>
303         /// <param name="p">座標</param>
304         /// <returns>インデックスを返す</returns>
305         public int GetIndexFromPostion(Windows.Foundation.Point p)
306         {
307             if (this.Document.FireUpdateEvent == false)
308                 throw new InvalidOperationException("");
309             TextPoint tp = this.View.GetTextPointFromPostion(p);
310             return this.View.GetIndexFromLayoutLine(tp);
311         }
312         
313
314         /// <summary>
315         /// 再描写する
316         /// </summary>
317         public void Refresh(bool immidately=true)
318         {
319             if(immidately)
320                 this.Refresh(this.View.PageBound);
321             else
322                 this.Document.RequestRedraw();
323         }
324
325         /// <summary>
326         /// レイアウト行をすべて破棄し、再度レイアウトを行う
327         /// </summary>
328         public void PerfomLayouts()
329         {
330             this.Document.PerformLayout();
331         }
332
333         /// <summary>
334         /// 指定行までスクロールする
335         /// </summary>
336         /// <param name="row">行</param>
337         /// <param name="alignTop">指定行を画面上に置くなら真。そうでないなら偽</param>
338         public void ScrollIntoView(int row, bool alignTop)
339         {
340             this.View.ScrollIntoView(row, alignTop);
341         }
342
343         /// <summary>
344         /// ファイルからドキュメントを構築する
345         /// </summary>
346         /// <param name="sr">StremReader</param>
347         /// <returns>Taskオブジェクト</returns>
348         public async Task LoadFileAsync(System.IO.StreamReader sr, System.Threading.CancellationTokenSource token)
349         {
350             await this.Document.LoadAsync(sr, token);
351         }
352
353         private void Document_LoadProgress(object sender, ProgressEventArgs e)
354         {
355             if(e.state == ProgressState.Start)
356             {
357                 this.IsEnabled = false;
358             }
359             else if(e.state == ProgressState.Complete)
360             {
361                 CoreTextRange modified_range = new CoreTextRange();
362                 modified_range.StartCaretPosition = 0;
363                 modified_range.EndCaretPosition = 0;
364                 //キャレット位置はロード前と同じにしないと違和感を感じる
365                 if (this.textEditContext != null)
366                     this.textEditContext.NotifyTextChanged(modified_range, this.Document.Length, modified_range);
367
368                 if (this.verticalScrollBar != null)
369                     this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;
370                 this.IsEnabled = true;
371                 this.Refresh(false);
372             }
373         }
374
375         /// <summary>
376         /// ドキュメントの内容をファイルに保存する
377         /// </summary>
378         /// <param name="sw">StreamWriter</param>
379         /// <param name="enc">エンコード</param>
380         /// <returns>Taskオブジェクト</returns>
381         public async Task SaveFile(System.IO.StreamWriter sw, System.Threading.CancellationTokenSource token)
382         {
383             await this.Document.SaveAsync(sw, token);
384         }
385
386 #region command
387         void CopyCommand()
388         {
389             this.Copy();
390         }
391
392         void CutCommand()
393         {
394             this.Cut();
395             this.Refresh();
396         }
397
398         async Task PasteCommand()
399         {
400             await this.PasteAsync();
401             this.Refresh();
402         }
403
404 #endregion
405
406 #region event
407
408 #if ENABLE_AUTMATION
409         /// <inheritdoc/>
410         protected override Windows.UI.Xaml.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
411         {
412             this.peer = new FooTextBoxAutomationPeer(this);
413             return this.peer;
414         }
415 #endif
416         /// <inheritdoc/>
417         protected override void OnApplyTemplate()
418         {
419             base.OnApplyTemplate();
420
421             Grid grid = this.GetTemplateChild("PART_Grid") as Grid;
422             if (grid != null)
423             {
424                 Grid.SetRow(this.rectangle, 0);
425                 Grid.SetColumn(this.rectangle, 0);
426                 grid.Children.Add(this.rectangle);
427             }
428
429             this.horizontalScrollBar = this.GetTemplateChild("PART_HorizontalScrollBar") as ScrollBar;
430             if (this.horizontalScrollBar != null)
431             {
432                 this.horizontalScrollBar.SmallChange = 10;
433                 this.horizontalScrollBar.LargeChange = 100;
434                 this.horizontalScrollBar.Maximum = this.horizontalScrollBar.LargeChange + 1;
435                 this.horizontalScrollBar.Scroll += new ScrollEventHandler(horizontalScrollBar_Scroll);
436             }
437             this.verticalScrollBar = this.GetTemplateChild("PART_VerticalScrollBar") as ScrollBar;
438             if (this.verticalScrollBar != null)
439             {
440                 this.verticalScrollBar.SmallChange = 1;
441                 this.verticalScrollBar.LargeChange = 10;
442                 this.verticalScrollBar.Maximum = this.View.LayoutLines.Count;
443                 this.verticalScrollBar.Scroll += new ScrollEventHandler(verticalScrollBar_Scroll);
444             }
445         }
446
447         private void FooTextBox_LosingFocus(UIElement sender, LosingFocusEventArgs args)
448         {
449             this.RemoveTextContext();
450             
451             if (this.textServiceManager != null)
452             {
453                 this.textServiceManager.InputLanguageChanged -= TextServiceManager_InputLanguageChanged;
454                 this.textServiceManager = null;
455             }
456
457             System.Diagnostics.Debug.WriteLine("losing focus");
458         }
459
460         private async void FooTextBox_GettingFocus(UIElement sender, GettingFocusEventArgs args)
461         {
462             System.Diagnostics.Debug.WriteLine("getting focus");
463             if (this.textServiceManager == null)
464             {
465                 await Task.Delay(500);
466                 this.textServiceManager = CoreTextServicesManager.GetForCurrentView();
467                 this.textServiceManager.InputLanguageChanged += TextServiceManager_InputLanguageChanged;
468             }
469
470             this.CreateTextContext();
471         }
472
473         /// <inheritdoc/>
474         protected override void OnGotFocus(RoutedEventArgs e)
475         {
476             base.OnGotFocus(e);
477
478             System.Diagnostics.Debug.WriteLine("got focus");
479
480             this.View.IsFocused = true;
481             this.timer.Interval = new TimeSpan(0, 0, 0, 0, Interval);
482             this.Refresh(false);
483         }
484
485         private void TextServiceManager_InputLanguageChanged(CoreTextServicesManager sender, object args)
486         {
487             System.Diagnostics.Debug.WriteLine("input language changed input script:"+  this.textServiceManager.InputLanguage.Script);
488         }
489
490        /// <inheritdoc/>
491         protected override void OnLostFocus(RoutedEventArgs e)
492         {
493             base.OnLostFocus(e);
494
495             System.Diagnostics.Debug.WriteLine("lost focus");
496             
497             this.View.IsFocused = false;
498             this.Refresh(false);
499             this.timer.Interval = new TimeSpan(0, 0, 0, 0, IntervalWhenLostFocus);
500         }
501
502         private void CreateTextContext()
503         {
504             if(this.textServiceManager != null)
505             {
506                 this.textEditContext = this.textServiceManager.CreateEditContext();
507                 this.textEditContext.InputScope = CoreTextInputScope.Text;
508                 this.textEditContext.CompositionStarted += TextEditContext_CompositionStarted;
509                 this.textEditContext.CompositionCompleted += TextEditContext_CompositionCompleted;
510                 this.textEditContext.LayoutRequested += TextEditContext_LayoutRequested;
511                 this.textEditContext.TextUpdating += TextEditContext_TextUpdating;
512                 this.textEditContext.TextRequested += TextEditContext_TextRequested;
513                 this.textEditContext.SelectionRequested += TextEditContext_SelectionRequested;
514                 this.textEditContext.SelectionUpdating += TextEditContext_SelectionUpdating;
515                 this.textEditContext.FormatUpdating += TextEditContext_FormatUpdating;
516                 this.textEditContext.FocusRemoved += TextEditContext_FocusRemoved;
517                 this.textEditContext.NotifyFocusLeaveCompleted += TextEditContext_NotifyFocusLeaveCompleted;
518                 this.textEditContext.NotifyFocusEnter();
519             }
520         }
521
522         private void RemoveTextContext()
523         {
524             if(this.textEditContext != null)
525             {
526                 this.textEditContext.NotifyFocusLeave();
527                 this.textEditContext.CompositionStarted -= TextEditContext_CompositionStarted;
528                 this.textEditContext.CompositionCompleted -= TextEditContext_CompositionCompleted;
529                 this.textEditContext.LayoutRequested -= TextEditContext_LayoutRequested;
530                 this.textEditContext.TextUpdating -= TextEditContext_TextUpdating;
531                 this.textEditContext.TextRequested -= TextEditContext_TextRequested;
532                 this.textEditContext.SelectionRequested -= TextEditContext_SelectionRequested;
533                 this.textEditContext.SelectionUpdating -= TextEditContext_SelectionUpdating;
534                 this.textEditContext.FormatUpdating -= TextEditContext_FormatUpdating;
535                 this.textEditContext.FocusRemoved -= TextEditContext_FocusRemoved;
536                 this.textEditContext.NotifyFocusLeaveCompleted -= TextEditContext_NotifyFocusLeaveCompleted;
537                 this.textEditContext = null;
538             }
539         }
540
541         /// <inheritdoc/>
542         protected override async void OnKeyDown(KeyRoutedEventArgs e)
543         {
544             bool isControlPressed = this.IsModiferKeyPressed(VirtualKey.Control);
545             bool isShiftPressed = this.IsModiferKeyPressed(VirtualKey.Shift);
546             bool isMovedCaret = false;
547
548             var autocomplete = this.Document.AutoComplete as AutoCompleteBox;
549             if (autocomplete != null && autocomplete.ProcessKeyDown(this, e, isControlPressed, isShiftPressed))
550                 return;
551
552             switch (e.Key)
553             {
554                 case VirtualKey.Up:
555                     this._Controller.MoveCaretVertical(-1, isShiftPressed);
556                     this.Refresh();
557                     e.Handled = true;
558                     isMovedCaret = true;
559                     break;
560                 case VirtualKey.Down:
561                     this._Controller.MoveCaretVertical(+1, isShiftPressed);
562                     this.Refresh();
563                     e.Handled = true;
564                     isMovedCaret = true;
565                     break;
566                 case VirtualKey.Left:
567                     this._Controller.MoveCaretHorizontical(-1, isShiftPressed, isControlPressed);
568                     this.Refresh();
569                     e.Handled = true;
570                     isMovedCaret = true;
571                     break;
572                 case VirtualKey.Right:
573                     this._Controller.MoveCaretHorizontical(1, isShiftPressed, isControlPressed);
574                     this.Refresh();
575                     e.Handled = true;
576                     isMovedCaret = true;
577                     break;
578                 case VirtualKey.PageUp:
579                     this._Controller.Scroll(ScrollDirection.Up, this.View.LineCountOnScreen, isShiftPressed, true);
580                     this.Refresh();
581                     isMovedCaret = true;
582                     break;
583                 case VirtualKey.PageDown:
584                     this._Controller.Scroll(ScrollDirection.Down, this.View.LineCountOnScreen, isShiftPressed, true);
585                     this.Refresh();
586                     isMovedCaret = true;
587                     break;
588                 case VirtualKey.Home:
589                     if (isControlPressed)
590                         this._Controller.JumpToHead(isShiftPressed);
591                     else
592                         this.Controller.JumpToLineHead(this.Document.CaretPostion.row,isShiftPressed);
593                     this.Refresh();
594                     isMovedCaret = true;
595                     break;
596                 case VirtualKey.End:
597                     if (isControlPressed)
598                         this._Controller.JumpToEnd(isShiftPressed);
599                     else
600                         this.Controller.JumpToLineEnd(this.Document.CaretPostion.row,isShiftPressed);
601                     this.Refresh();
602                     isMovedCaret = true;
603                     break;
604                 case VirtualKey.Tab:
605                     if (!isControlPressed)
606                     {
607                         if (this._Controller.SelectionLength == 0)
608                             this._Controller.DoInputChar('\t');
609                         else if (isShiftPressed)
610                             this._Controller.DownIndent();
611                         else
612                             this._Controller.UpIndent();
613                         this.Refresh();
614                         e.Handled = true;
615                     }
616                     break;
617                 case VirtualKey.Enter:
618                     this._Controller.DoEnterAction();
619                     this.Refresh();
620                     e.Handled = true;
621                     break;
622                 case VirtualKey.Insert:
623                     if(this.View.InsertMode)
624                         this.View.InsertMode = false;
625                     else
626                         this.View.InsertMode = true;
627                     this.Refresh();
628                     e.Handled = true;
629                     break;
630                 case VirtualKey.A:
631                     if (isControlPressed)
632                     {
633                         this.SelectAll();
634                         this.Refresh();
635                         e.Handled = true;
636                     }
637                     break;
638                 case VirtualKey.B:
639                     if (isControlPressed)
640                     {
641                         if (this._Controller.RectSelection)
642                             this._Controller.RectSelection = false;
643                         else
644                             this._Controller.RectSelection = true;
645                         this.Refresh();
646                         e.Handled = true;
647                     }
648                     break;
649                 case VirtualKey.C:
650                     if (isControlPressed)
651                     {
652                         this.CopyCommand();
653                         e.Handled = true;
654                     }
655                     break;
656                 case VirtualKey.X:
657                     if (isControlPressed)
658                     {
659                         this.CutCommand();
660                         e.Handled = true;
661                     }
662                     break;
663                 case VirtualKey.V:
664                     if (isControlPressed)
665                     {
666                         await this.PasteCommand();
667                         e.Handled = true;
668                     }
669                     break;
670                 case VirtualKey.Y:
671                     if (isControlPressed)
672                     {
673                         this.Document.UndoManager.redo();
674                         this.Refresh();
675                         e.Handled = true;
676                     }
677                     break;
678                 case VirtualKey.Z:
679                     if (isControlPressed)
680                     {
681                         this.Document.UndoManager.undo();
682                         this.Refresh();
683                         e.Handled = true;
684                     }
685                     break;
686                 case VirtualKey.Back:
687                     this._Controller.DoBackSpaceAction();
688                     this.Refresh();
689                     e.Handled = true;
690                     break;
691                 case VirtualKey.Delete:
692                     this._Controller.DoDeleteAction();
693                     this.Refresh();
694                     e.Handled = true;
695                     break;
696             }
697 #if ENABLE_AUTMATION
698             if (isMovedCaret && this.peer != null)
699                 this.peer.OnNotifyCaretChanged();
700 #endif
701             base.OnKeyDown(e);
702         }
703
704         /// <inheritdoc/>
705         protected override void OnPointerPressed(PointerRoutedEventArgs e)
706         {
707             System.Diagnostics.Debug.WriteLine("pointer pressed");
708             this.CapturePointer(e.Pointer);
709             this.gestureRecongnizer.ProcessDownEvent(e.GetCurrentPoint(this));
710             e.Handled = true;
711         }
712
713         /// <inheritdoc/>
714         protected override void OnPointerMoved(PointerRoutedEventArgs e)
715         {
716             System.Diagnostics.Debug.WriteLine("pointer moved");
717             try
718             {
719                 this.gestureRecongnizer.ProcessMoveEvents(e.GetIntermediatePoints(this));
720             }catch(System.Runtime.InteropServices.COMException ex)
721             {
722                 //ピンチズームでこの例外が発生するが、回避できない
723                 System.Diagnostics.Debug.WriteLine("expection:" + ex);
724             }
725             e.Handled = true;
726
727             if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse)
728             {
729                 Point p = e.GetCurrentPoint(this).Position;
730                 if (this.View.HitTextArea(p.X, p.Y))
731                 {
732                     TextPoint tp = this.View.GetTextPointFromPostion(p);
733                     if (this._Controller.IsMarker(tp, HilightType.Url))
734                         Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Hand, 101);
735                     else
736                         Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.IBeam, 101);
737                 }
738                 else
739                 {
740                     Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Arrow, 101);
741                 }
742             }
743         }
744
745         /// <inheritdoc/>
746         protected override void OnPointerReleased(PointerRoutedEventArgs e)
747         {
748             System.Diagnostics.Debug.WriteLine("pointer released");
749             this.gestureRecongnizer.ProcessUpEvent(e.GetCurrentPoint(this));
750             e.Handled = true;
751         }
752
753         /// <inheritdoc/>
754         protected override void OnPointerCanceled(PointerRoutedEventArgs e)
755         {
756             System.Diagnostics.Debug.WriteLine("pointer canceled");
757             this.gestureRecongnizer.CompleteGesture();
758             e.Handled = true;
759         }
760
761         /// <inheritdoc/>
762         protected override void OnPointerWheelChanged(PointerRoutedEventArgs e)
763         {
764             System.Diagnostics.Debug.WriteLine("pointer wheelchanged");
765             bool shift = (e.KeyModifiers & Windows.System.VirtualKeyModifiers.Shift) ==
766                 Windows.System.VirtualKeyModifiers.Shift;
767             bool ctrl = (e.KeyModifiers & Windows.System.VirtualKeyModifiers.Control) ==
768                 Windows.System.VirtualKeyModifiers.Control;
769             this.gestureRecongnizer.ProcessMouseWheelEvent(e.GetCurrentPoint(this), shift, ctrl);
770             e.Handled = true;
771         }
772
773         private void TextEditContext_FormatUpdating(CoreTextEditContext sender, CoreTextFormatUpdatingEventArgs args)
774         {
775             if (this.Document.Length == 0 || args.IsCanceled)
776             {
777                 args.Result = CoreTextFormatUpdatingResult.Failed;
778                 return;
779             }
780             System.Diagnostics.Debug.WriteLine("core text format updating range({0}-{1}) underline type:{2} underline color:{3} reason:{4} textcolor:{5} background:{6}",
781                 args.Range.StartCaretPosition,
782                 args.Range.EndCaretPosition,
783                 args.UnderlineType,
784                 args.UnderlineColor,
785                 args.Reason,
786                 args.TextColor,
787                 args.BackgroundColor
788                 );
789             HilightType type = HilightType.None;
790             Color color = new Color(this.Foreground.A,this.Foreground.R,this.Foreground.G,this.Foreground.R);
791             bool isBoldLine = false;
792             switch (args.UnderlineType)
793             {
794                 case UnderlineType.Dotted:
795                     type = HilightType.Dot;
796                     break;
797                 case UnderlineType.Single:
798                     type = HilightType.Sold;
799                     break;
800                 case UnderlineType.Dash:
801                     type = HilightType.Dash;
802                     break;
803                 case UnderlineType.Wave:
804                     type = HilightType.Squiggle;
805                     break;
806                 case UnderlineType.Thin:
807                     type = HilightType.Sold;
808                     break;
809                 case UnderlineType.Thick:
810                     type = HilightType.Sold;
811                     isBoldLine = true;
812                     break;
813             }
814             int start = args.Range.StartCaretPosition;
815             int lengt = args.Range.EndCaretPosition - args.Range.StartCaretPosition;
816             this.Document.SetMarker(MarkerIDs.IME, Marker.Create(start, lengt, type, color, isBoldLine));
817
818             if (args.Reason == CoreTextFormatUpdatingReason.CompositionTargetConverted)
819             {
820                 this.View.AdjustSrc(args.Range.StartCaretPosition);
821             }
822             this.Refresh();
823
824             args.Result = CoreTextFormatUpdatingResult.Succeeded;
825         }
826
827         private void TextEditContext_TextRequested(CoreTextEditContext sender, CoreTextTextRequestedEventArgs args)
828         {
829             CoreTextTextRequest req = args.Request;
830
831             if (this.Document.Length == 0 || req.IsCanceled)
832             {
833                 return;
834             }
835
836             int start = req.Range.StartCaretPosition;
837             int end = req.Range.EndCaretPosition;
838             if (end > this.Document.Length)
839                 end = this.Document.Length;
840
841             int length = end - start;
842
843             System.Diagnostics.Debug.WriteLine("req text start:{0} length:{1}", start, length);
844
845             //キャレット位置も含むので+1する必要はない
846             req.Text = this.Document.ToString(start,length);
847         }
848
849         private void TextEditContext_LayoutRequested(CoreTextEditContext sender, CoreTextLayoutRequestedEventArgs args)
850         {
851             //変換候補の範囲を取得する
852             Point startPos, endPos;
853             int i_startIndex = args.Request.Range.StartCaretPosition;
854             int i_endIndex = args.Request.Range.EndCaretPosition;
855
856             if(args.Request.IsCanceled)
857             {
858                 return;
859             }
860
861             System.Diagnostics.Debug.WriteLine("core text layoutreq range({0}-{1})",i_startIndex,i_endIndex);
862
863             if (i_startIndex != -1 && i_endIndex != -1)
864             {
865                 TextStoreHelper.GetStringExtent(this.Document, this.View, i_startIndex, i_endIndex, out startPos, out endPos);
866
867                 double scale = Util.GetScale();
868
869                 //Core.Textはスクリーン座標に変換してくれないので自前で変換する(しかも、デバイス依存の座標で返さないといけない)
870                 var screenStartPos = Util.GetScreentPoint(startPos, this).Scale(scale);
871                 var screenEndPos = Util.GetScreentPoint(endPos, this).Scale(scale);
872                 args.Request.LayoutBounds.TextBounds = new Rect(
873                     screenStartPos.X,
874                     screenStartPos.Y,
875                     Math.Max(0,screenEndPos.X - screenStartPos.X),  //折り返されている場合、負になることがある
876                     screenEndPos.Y - screenStartPos.Y);
877             }
878
879             //コントロールの範囲を取得する
880             var controlTopLeft = new Point(0, 0);
881             var controlBottomRight = new Point(this.RenderSize.Width, this.RenderSize.Height);
882
883             var gt = this.TransformToVisual(Window.Current.Content);
884             controlTopLeft = gt.TransformPoint(controlTopLeft);
885             controlBottomRight = gt.TransformPoint(controlBottomRight);
886
887             args.Request.LayoutBounds.ControlBounds = new Rect(
888                 controlTopLeft.X,
889                 controlTopLeft.Y,
890                 controlBottomRight.X - controlTopLeft.X,
891                 controlBottomRight.Y - controlTopLeft.Y
892                 );
893         }
894
895         private void TextEditContext_SelectionRequested(CoreTextEditContext sender, CoreTextSelectionRequestedEventArgs args)
896         {
897             if(args.Request.IsCanceled || this.Document.Length == 0)
898             {
899                 return;
900             }
901             TextRange currentSelection = new TextRange();
902             TextStoreHelper.GetSelection(this._Controller, this.View.Selections, out currentSelection);
903
904             CoreTextRange currentSelectionRange = new CoreTextRange();
905             currentSelectionRange.StartCaretPosition = currentSelection.Index;
906             currentSelectionRange.EndCaretPosition = currentSelection.Index + currentSelection.Length;
907             args.Request.Selection = currentSelectionRange;
908             System.Diagnostics.Debug.WriteLine("req selection start:{0} end:{1}", currentSelectionRange.StartCaretPosition, currentSelectionRange.EndCaretPosition);
909         }
910
911         private void TextEditContext_SelectionUpdating(CoreTextEditContext sender, CoreTextSelectionUpdatingEventArgs args)
912         {
913             if(this.Document.Length == 0 || args.IsCanceled)
914             {
915                 args.Result = CoreTextSelectionUpdatingResult.Failed;
916                 return;
917             }
918             CoreTextRange sel = args.Selection;
919             System.Diagnostics.Debug.WriteLine("update selection start:{0} end:{1}", sel.StartCaretPosition, sel.EndCaretPosition);
920             TextStoreHelper.SetSelectionIndex(this.Controller, this.View, sel.StartCaretPosition, sel.EndCaretPosition);
921             args.Result = CoreTextSelectionUpdatingResult.Succeeded;
922             this.Refresh();
923         }
924
925         private void TextEditContext_TextUpdating(CoreTextEditContext sender, CoreTextTextUpdatingEventArgs args)
926         {
927             this.nowCompstion = true;
928
929             System.Diagnostics.Debug.WriteLine("update text (modify start:{0} end:{1}) text:{2} (new sel start:{0} end:{1})",
930                 args.Range.StartCaretPosition, 
931                 args.Range.EndCaretPosition, 
932                 args.Text, 
933                 args.NewSelection.StartCaretPosition, 
934                 args.NewSelection.EndCaretPosition);
935             bool isTip = args.InputLanguage.Script == "Latan";
936             CoreTextRange sel = args.Range;
937             TextStoreHelper.SetSelectionIndex(this.Controller, this.View, sel.StartCaretPosition, sel.EndCaretPosition);
938             TextStoreHelper.InsertTextAtSelection(this._Controller, args.Text, isTip);
939             this.Refresh();
940             args.Result = CoreTextTextUpdatingResult.Succeeded;
941
942             this.nowCompstion = false;
943         }
944
945         private void TextEditContext_CompositionCompleted(CoreTextEditContext sender, CoreTextCompositionCompletedEventArgs args)
946         {
947             System.Diagnostics.Debug.WriteLine("end compostion");
948             TextStoreHelper.EndCompostion(this.Document);
949             this.Document.RemoveAllMarker(MarkerIDs.IME);
950             this.Refresh();
951         }
952
953         private void TextEditContext_CompositionStarted(CoreTextEditContext sender, CoreTextCompositionStartedEventArgs args)
954         {
955             System.Diagnostics.Debug.WriteLine("start compstion");
956             TextStoreHelper.StartCompstion(this.Document);
957         }
958
959         private void TextEditContext_NotifyFocusLeaveCompleted(CoreTextEditContext sender, object args)
960         {
961             System.Diagnostics.Debug.WriteLine("notify focus leaved");
962         }
963
964         private void TextEditContext_FocusRemoved(CoreTextEditContext sender, object args)
965         {
966             System.Diagnostics.Debug.WriteLine("focus leaved");
967         }
968
969         void Controller_SelectionChanged(object sender, EventArgs e)
970         {
971             if (this._Controller == null)
972                 return;
973
974             //こうしないと選択できなくなってしまう
975             this.nowCaretMove = true;
976             SetValue(SelectedTextProperty, this._Controller.SelectedText);
977             SetValue(CaretPostionPropertyKey, this.Document.CaretPostion);
978             this.nowCaretMove = false;
979
980             if(!this.nowCompstion)
981             {
982                 TextRange currentSelection = new TextRange();
983                 TextStoreHelper.GetSelection(this._Controller, this.View.Selections, out currentSelection);
984
985                 CoreTextRange currentSelectionRange = new CoreTextRange();
986                 currentSelectionRange.StartCaretPosition = currentSelection.Index;
987                 currentSelectionRange.EndCaretPosition = currentSelection.Index + currentSelection.Length;
988
989                 System.Diagnostics.Debug.WriteLine("notify selection start:{0} end:{1}", currentSelectionRange.StartCaretPosition, currentSelectionRange.EndCaretPosition);
990                 //変換中に呼び出してはいけない
991                 if (this.textEditContext != null)
992                     this.textEditContext.NotifySelectionChanged(currentSelectionRange);
993             }
994         }
995
996         Gripper hittedGripper;
997         void gestureRecongnizer_ManipulationStarted(GestureRecognizer sender, ManipulationStartedEventArgs e)
998         {
999             //Updateedの段階でヒットテストしてしまうとグリッパーを触ってもヒットしないことがある
1000             this.hittedGripper = this.View.HitGripperFromPoint(e.Position);
1001         }
1002
1003         private void GestureRecongnizer_ManipulationInertiaStarting(GestureRecognizer sender, ManipulationInertiaStartingEventArgs args)
1004         {
1005             //sender.InertiaTranslationDeceleration = 0.001f;
1006             //sender.InertiaExpansionDeceleration = 100.0f * 96.0f / 1000.0f;
1007             //sender.InertiaRotationDeceleration = 720.0f / (1000.0f * 1000.0f);
1008         }
1009
1010         void gestureRecongnizer_ManipulationUpdated(GestureRecognizer sender, ManipulationUpdatedEventArgs e)
1011         {
1012             if (e.Delta.Scale < 1)
1013             {
1014                 double newSize = this.Render.FontSize - 1;
1015                 if (newSize < 1)
1016                     newSize = 1;
1017                 this.Render.FontSize = newSize;
1018                 this.Refresh();
1019                 SetValue(MagnificationPowerPropertyKey, this.Render.FontSize / this.FontSize);
1020                 return;
1021             }
1022
1023             if (e.Delta.Scale > 1)
1024             {
1025                 double newSize = this.Render.FontSize + 1;
1026                 if (newSize > 72)
1027                     newSize = 72;
1028                 this.Render.FontSize = newSize;
1029                 this.Refresh();
1030                 SetValue(MagnificationPowerPropertyKey, this.Render.FontSize / this.FontSize);
1031                 return;
1032             }
1033
1034             if (this._Controller.MoveCaretAndGripper(e.Position, this.hittedGripper))
1035             {
1036 #if ENABLE_AUTMATION
1037                 if (this.peer != null)
1038                     this.peer.OnNotifyCaretChanged();
1039 #endif
1040                 this.Refresh();                
1041                 return;
1042             }
1043             
1044             Point translation = e.Delta.Translation;
1045
1046             //Xの絶対値が大きければ横方向のスクロールで、そうでなければ縦方向らしい
1047             if (Math.Abs(e.Cumulative.Translation.X) < Math.Abs(e.Cumulative.Translation.Y))
1048             {
1049                 int deltay = (int)Math.Abs(Math.Ceiling(translation.Y));
1050                 if (translation.Y < 0)
1051                     this._Controller.ScrollByPixel(ScrollDirection.Down, deltay, false, false);
1052                 else
1053                     this._Controller.ScrollByPixel(ScrollDirection.Up, deltay, false, false);
1054                 this.Refresh();
1055                 return;
1056             }
1057
1058             int deltax = (int)Math.Abs(Math.Ceiling(translation.X));
1059             if (deltax != 0)
1060             {
1061                 if (translation.X < 0)
1062                     this._Controller.Scroll(ScrollDirection.Left, deltax, false, false);
1063                 else
1064                     this._Controller.Scroll(ScrollDirection.Right, deltax, false, false);
1065                 this.Refresh();
1066             }
1067         }
1068
1069         void gestureRecongnizer_ManipulationCompleted(GestureRecognizer sender, ManipulationCompletedEventArgs e)
1070         {
1071         }
1072
1073         async void gestureRecongnizer_RightTapped(GestureRecognizer sender, RightTappedEventArgs e)
1074         {
1075             ResourceMap map = ResourceManager.Current.MainResourceMap.GetSubtree("FooEditEngine.UWP/Resources");
1076             ResourceContext context = ResourceContext.GetForCurrentView();
1077             if (this.View.HitTextArea(e.Position.X, e.Position.Y))
1078             {
1079                 FooContextMenuEventArgs args = new FooContextMenuEventArgs(e.Position);
1080                 if (this.ContextMenuOpening != null)
1081                     this.ContextMenuOpening(this, args);
1082                 if (!args.Handled)
1083                 {
1084                     PopupMenu ContextMenu = new PopupMenu();
1085                     ContextMenu.Commands.Add(new UICommand(map.GetValue("CopyMenuName", context).ValueAsString, (command) =>
1086                     {
1087                         this.CopyCommand();
1088                     }));
1089                     ContextMenu.Commands.Add(new UICommand(map.GetValue("CutMenuName", context).ValueAsString, (command) =>
1090                     {
1091                         this.CutCommand();
1092                     }));
1093                     ContextMenu.Commands.Add(new UICommand(map.GetValue("PasteMenuName", context).ValueAsString, async (command) =>
1094                     {
1095                         await this.PasteCommand();
1096                     }));
1097                     if (this._Controller.RectSelection)
1098                     {
1099                         ContextMenu.Commands.Add(new UICommand(map.GetValue("LineSelectMenuName", context).ValueAsString, (command) =>
1100                         {
1101                             this._Controller.RectSelection = false;
1102                         }));
1103                     }
1104                     else
1105                     {
1106                         ContextMenu.Commands.Add(new UICommand(map.GetValue("RectSelectMenuName", context).ValueAsString, (command) =>
1107                         {
1108                             this._Controller.RectSelection = true;
1109                         }));
1110                     }
1111                     var windowStartPos = Util.GetPointInWindow(e.Position, this);
1112                     await ContextMenu.ShowAsync(windowStartPos);
1113                 }
1114             }
1115         }
1116
1117         long lastDouleTapTick;
1118         const long allowTripleTapTimeSpan = 500;
1119         void gestureRecongnizer_Tapped(GestureRecognizer sender, TappedEventArgs e)
1120         {
1121             bool touched = e.PointerDeviceType == PointerDeviceType.Touch;
1122             this.Document.SelectGrippers.BottomLeft.Enabled = false;
1123             this.Document.SelectGrippers.BottomRight.Enabled = touched;
1124             this.JumpCaret(e.Position);
1125             if(e.TapCount == 1 && System.DateTime.Now.Ticks - lastDouleTapTick < allowTripleTapTimeSpan * 10000)    //トリプルタップ
1126             {
1127                 //タッチスクリーンで行選択した場合、アンカーインデックスを単語の先頭にしないとバグる
1128                 this.Document.SelectGrippers.BottomLeft.Enabled = touched;
1129                 this.Document.SelectLine(this.Controller.SelectionStart, touched);
1130                 this.Refresh();
1131             }
1132             else  if(e.TapCount == 2)   //ダブルタップ
1133             {
1134                 //タッチスクリーンで単語選択した場合、アンカーインデックスを単語の先頭にしないとバグる
1135                 this.Document.SelectGrippers.BottomLeft.Enabled = touched;
1136                 if (e.Position.X < this.Render.TextArea.X)
1137                     this.Document.SelectLine(this.Controller.SelectionStart, touched);
1138                 else
1139                     this.Document.SelectWord(this.Controller.SelectionStart, touched);
1140                 this.lastDouleTapTick = System.DateTime.Now.Ticks;
1141                 this.Refresh();
1142             }
1143         }
1144
1145         void JumpCaret(Point p)
1146         {
1147             TextPoint tp = this.View.GetTextPointFromPostion(p);
1148             if (tp == TextPoint.Null)
1149                 return;
1150
1151             int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);
1152
1153             FoldingItem foldingData = this.View.HitFoldingData(p.X, tp.row);
1154             if (foldingData != null)
1155             {
1156                 if (foldingData.Expand)
1157                     this.View.LayoutLines.FoldingCollection.Collapse(foldingData);
1158                 else
1159                     this.View.LayoutLines.FoldingCollection.Expand(foldingData);
1160                 this._Controller.JumpCaret(foldingData.Start, false);
1161             }
1162             else
1163             {
1164                 this._Controller.JumpCaret(tp.row, tp.col, false);
1165             }
1166 #if ENABLE_AUTMATION
1167             if (this.peer != null)
1168                 this.peer.OnNotifyCaretChanged();
1169 #endif
1170             this.View.IsFocused = true;
1171             this.Focus(FocusState.Programmatic);
1172             this.Refresh();
1173         }
1174
1175         void gestureRecongnizer_Dragging(GestureRecognizer sender, DraggingEventArgs e)
1176         {
1177             Point p = e.Position;
1178             TextPointSearchRange searchRange;
1179             if (this.View.HitTextArea(p.X, p.Y))
1180                 searchRange = TextPointSearchRange.TextAreaOnly;
1181             else if (this._Controller.SelectionLength > 0)
1182                 searchRange = TextPointSearchRange.Full;
1183             else
1184                 return;
1185             TextPoint tp = this.View.GetTextPointFromPostion(p, searchRange);
1186             this._Controller.MoveCaretAndSelect(tp, this.IsModiferKeyPressed(VirtualKey.LeftControl));
1187 #if ENABLE_AUTMATION
1188             if (this.peer != null)
1189                 this.peer.OnNotifyCaretChanged();
1190 #endif
1191             this.Refresh();
1192         }
1193
1194         bool IsModiferKeyPressed(VirtualKey key)
1195         {
1196             CoreVirtualKeyStates state = Window.Current.CoreWindow.GetKeyState(key);
1197             return (state & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
1198         }
1199         void Refresh(Rectangle updateRect)
1200         {
1201             if (this.rectangle.ActualWidth == 0 || this.rectangle.ActualHeight == 0 || this.Visibility == Windows.UI.Xaml.Visibility.Collapsed)
1202                 return;
1203
1204             this.Render.DrawContent(this.View, this.IsEnabled, updateRect);
1205
1206             this.Document.IsRequestRedraw = false;
1207         }
1208
1209
1210         bool Resize(double width, double height)
1211         {
1212             if (width == 0 || height == 0)
1213                 throw new ArgumentOutOfRangeException();
1214             if (this.Render.Resize(this.rectangle, width, height))
1215             {
1216                 this.View.PageBound = new Rectangle(0, 0, width, height);
1217
1218                 if (this.horizontalScrollBar != null)
1219                 {
1220                     this.horizontalScrollBar.LargeChange = this.View.PageBound.Width;
1221                     this.horizontalScrollBar.Maximum = this.View.LongestWidth + this.horizontalScrollBar.LargeChange + 1;
1222                 }
1223                 if (this.verticalScrollBar != null)
1224                 {
1225                     this.verticalScrollBar.LargeChange = this.View.LineCountOnScreen;
1226                     this.verticalScrollBar.Maximum = this.View.LayoutLines.Count + this.verticalScrollBar.LargeChange + 1;
1227                 }
1228                 return true;
1229             }
1230             return false;
1231         }
1232
1233         void View_SrcChanged(object sender, EventArgs e)
1234         {
1235             if (this.horizontalScrollBar == null || this.verticalScrollBar == null)
1236                 return;
1237             EditView view = this.View;
1238             if (view.Src.Row > this.verticalScrollBar.Maximum)
1239                 this.verticalScrollBar.Maximum = view.Src.Row + view.LineCountOnScreen + 1;
1240             double absoulteX = Math.Abs(view.Src.X);
1241             if (absoulteX > this.horizontalScrollBar.Maximum)
1242                 this.horizontalScrollBar.Maximum = absoulteX + view.PageBound.Width + 1;
1243             if (view.Src.Row != this.verticalScrollBar.Value)
1244                 this.verticalScrollBar.Value = view.Src.Row;
1245             if (view.Src.X != this.horizontalScrollBar.Value)
1246                 this.horizontalScrollBar.Value = Math.Abs(view.Src.X);
1247         }
1248
1249         void FooTextBox_SizeChanged(object sender, SizeChangedEventArgs e)
1250         {
1251             //LostFocusやGotFocusなどと競合するとDirect2Dでエラーが起きるので、timer_tickイベントでサイズ変更を行うことにした
1252             this.requestSizeChange = true;
1253         }
1254
1255         void horizontalScrollBar_Scroll(object sender, ScrollEventArgs e)
1256         {
1257             if (this.horizontalScrollBar == null)
1258                 return;
1259             double toX;
1260             if (this.FlowDirection == FlowDirection.LeftToRight)
1261                 toX = this.horizontalScrollBar.Value;
1262             else
1263                 toX = -this.horizontalScrollBar.Value;
1264             this._Controller.Scroll(toX, this.View.Src.Row, false, false);
1265             this.Refresh();
1266         }
1267
1268         void verticalScrollBar_Scroll(object sender, ScrollEventArgs e)
1269         {
1270             if (this.verticalScrollBar == null)
1271                 return;
1272             int newRow = (int)this.verticalScrollBar.Value;
1273             if (newRow >= this.View.LayoutLines.Count)
1274                 return;
1275             this._Controller.Scroll(this.View.Src.X, newRow, false, false);
1276             this.Refresh();
1277         }
1278
1279         void Document_Update(object sender, DocumentUpdateEventArgs e)
1280         {
1281             if (e.type == UpdateType.Replace && !this.nowCompstion)
1282             {
1283                 CoreTextRange oldTextRange = new CoreTextRange();
1284                 oldTextRange.StartCaretPosition = e.startIndex;
1285                 oldTextRange.EndCaretPosition = e.startIndex;
1286                 //削除する範囲が1以上の場合、ドキュメントを飛び越えることはできない
1287                 //https://msdn.microsoft.com/en-us/windows/uwp/input-and-devices/custom-text-input
1288                 if (e.removeLength > 0)
1289                     oldTextRange.EndCaretPosition += e.removeLength;
1290
1291                 TextRange currentSelection = new TextRange();
1292                 TextStoreHelper.GetSelection(this._Controller, this.View.Selections, out currentSelection);
1293
1294                 CoreTextRange newSelection = new CoreTextRange();
1295                 newSelection.StartCaretPosition = e.startIndex;
1296                 newSelection.EndCaretPosition = e.startIndex;
1297
1298                 //置き換え後の長さを指定する
1299                 //(注意:削除された文字数のほうが多い場合は0を指定しないいけない)
1300                 int newTextLength = e.insertLength;
1301
1302                 System.Diagnostics.Debug.WriteLine("notify text change (modify start:{0} end:{1}) newlength:{2} (new sel start:{3} end:{4})",
1303                     oldTextRange.StartCaretPosition, oldTextRange.EndCaretPosition, newTextLength, newSelection.StartCaretPosition, newSelection.EndCaretPosition);
1304                 //変換中に呼び出してはいけない
1305                 if(this.textEditContext != null)
1306                     this.textEditContext.NotifyTextChanged(oldTextRange, newTextLength, newSelection);
1307             }
1308 #if ENABLE_AUTMATION
1309             if (this.peer != null)
1310                 this.peer.OnNotifyTextChanged();
1311 #endif
1312         }
1313
1314         void FooTextBox_Loaded(object sender, RoutedEventArgs e)
1315         {
1316             this.Focus(FocusState.Programmatic);
1317         }
1318
1319         void timer_Tick(object sender, object e)
1320         {
1321             this.timer.Stop();
1322             if(this.requestSizeChange)
1323             {
1324                 if (this.Resize(this.rectangle.ActualWidth, this.rectangle.ActualHeight))
1325                 {
1326                     //普通に再描写するとちらつく
1327                     this.Refresh(this.View.PageBound);
1328                 }
1329                 this.requestSizeChange = false;
1330             }
1331             else if (this.View.LayoutLines.HilightAll() || this.View.LayoutLines.GenerateFolding() || this.Document.IsRequestRedraw)
1332             {
1333                 this.Refresh(this.View.PageBound);
1334             }
1335             this.timer.Start();
1336         }
1337
1338         private void SetDocument(Document value)
1339         {
1340             if (value == null)
1341                 return;
1342
1343             Document old_doc = this._Document;
1344
1345             if (this._Document != null)
1346             {
1347                 old_doc.Update -= new DocumentUpdateEventHandler(Document_Update);
1348                 this._Document.SelectionChanged -= Controller_SelectionChanged;
1349                 this._Document.LoadProgress -= Document_LoadProgress;
1350                 this._Document.AutoCompleteChanged -= _Document_AutoCompleteChanged;
1351                 if (this._Document.AutoComplete != null)
1352                 {
1353                     this._Document.AutoComplete.GetPostion = null;
1354                     this._Document.AutoComplete = null;
1355                 }
1356
1357                 //NotifyTextChanged()を呼び出すと落ちるのでTextConextをごっそり作り替える
1358                 this.RemoveTextContext();
1359             }
1360
1361             System.Diagnostics.Debug.WriteLine("document switched");
1362
1363             this._Document = value;
1364             this._Document.LayoutLines.Render = this.Render;
1365             this._Document.Update += new DocumentUpdateEventHandler(Document_Update);
1366             this._Document.LoadProgress += Document_LoadProgress;
1367             this._Document.AutoCompleteChanged += _Document_AutoCompleteChanged;
1368             if (this._Document.AutoComplete != null && this._Document.AutoComplete.GetPostion == null)
1369                 this._Document_AutoCompleteChanged(this._Document, null);
1370             //初期化が終わっていればすべて存在する
1371             if (this.Controller != null && this.View != null)
1372             {
1373                 this.Controller.Document = value;
1374                 this.View.Document = value;
1375
1376                 this.Controller.AdjustCaret();
1377
1378                 this.CreateTextContext();
1379
1380                 //依存プロパティとドキュメント内容が食い違っているので再設定する
1381                 this.ShowFullSpace = value.ShowFullSpace;
1382                 this.ShowHalfSpace = value.ShowHalfSpace;
1383                 this.ShowLineBreak = value.ShowLineBreak;
1384                 this.ShowTab = value.ShowTab;
1385                 this.FlowDirection = value.RightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
1386                 this.IndentMode = value.IndentMode;
1387                 this.DrawCaretLine = !value.HideLineMarker;
1388                 this.InsertMode = value.InsertMode;
1389                 this.DrawRuler = !value.HideRuler;
1390                 this.DrawLineNumber = value.DrawLineNumber;
1391                 this.MarkURL = value.UrlMark;
1392                 this.LineBreakMethod = value.LineBreak;
1393                 this.LineBreakCharCount = value.LineBreakCharCount;
1394                 this.TabChars = value.TabStops;
1395
1396                 this.Refresh();
1397             }
1398             //TextEditContext作成後に設定しないと落ちることがある
1399             this._Document.SelectionChanged += Controller_SelectionChanged;
1400         }
1401
1402         private void _Document_AutoCompleteChanged(object sender, EventArgs e)
1403         {
1404             Document doc = (Document)sender;
1405             doc.AutoComplete.GetPostion = (tp, e_doc) =>
1406             {
1407                 var p = this.View.GetPostionFromTextPoint(tp);
1408                 int height = (int)e_doc.LayoutLines.GetLayout(e_doc.CaretPostion.row).Height;
1409
1410                 if (p.Y + AutoCompleteBox.CompleteListBoxHeight + height > e_doc.LayoutLines.Render.TextArea.Height)
1411                     p.Y -= AutoCompleteBox.CompleteListBoxHeight;
1412                 else
1413                     p.Y += height;
1414                 //AutoCompleteBox内ではCanvasで位置を指定しているので変換する必要がある
1415                 var pointInWindow = Util.GetPointInWindow(p, this);
1416                 return pointInWindow;
1417             };
1418         }
1419
1420         /// <inheritdoc/>
1421         public static void OnPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
1422         {
1423             FooTextBox source = (FooTextBox)sender;
1424             if(e.Property.Equals(SelectedTextProperty) && !source.nowCaretMove)
1425                 source._Controller.SelectedText = source.SelectedText;
1426             if (e.Property.Equals(DocumentProperty))
1427                 source.SetDocument(source.Document);
1428             if(e.Property.Equals(HilighterProperty))
1429                 source.View.Hilighter = source.Hilighter;
1430             if (e.Property.Equals(FoldingStrategyProperty))
1431                 source.View.LayoutLines.FoldingStrategy = source.FoldingStrategy;
1432             if (e.Property.Equals(IndentModeProperty))
1433                 source.Controller.IndentMode = source.IndentMode;
1434             if (e.Property.Equals(SelectionProperty) && !source.nowCaretMove)
1435                 source.Document.Select(source.Selection.Index,source.Selection.Length);
1436             if (e.Property.Equals(CaretPostionPropertyKey) && !source.nowCaretMove)
1437                 source.JumpCaret(source.CaretPostion.row, source.CaretPostion.col);
1438             if (e.Property.Equals(InsertModeProperty))
1439                 source.View.InsertMode = source.InsertMode;
1440             if (e.Property.Equals(TabCharsProperty))
1441                 source.Document.TabStops = source.TabChars;
1442             if (e.Property.Equals(RectSelectModeProperty))
1443                 source._Controller.RectSelection = source.RectSelectMode;
1444             if (e.Property.Equals(DrawCaretProperty))
1445                 source.View.HideCaret = !source.DrawCaret;
1446             if (e.Property.Equals(DrawCaretLineProperty))
1447                 source.View.HideLineMarker = !source.DrawCaretLine;
1448             if (e.Property.Equals(DrawLineNumberProperty))
1449                 source.Document.DrawLineNumber = source.DrawLineNumber;
1450             if (e.Property.Equals(MarkURLProperty))
1451                 source.Document.UrlMark = source.MarkURL;
1452             if (e.Property.Equals(LineBreakProperty))
1453                 source.Document.LineBreak = source.LineBreakMethod;
1454             if (e.Property.Equals(LineBreakCharCountProperty))
1455                 source.Document.LineBreakCharCount = source.LineBreakCharCount;
1456             if (e.Property.Equals(FlowDirectionProperty))
1457             {
1458                 source.Document.RightToLeft = source.FlowDirection == Windows.UI.Xaml.FlowDirection.RightToLeft;
1459                 if (source.horizontalScrollBar != null)
1460                     source.horizontalScrollBar.FlowDirection = source.FlowDirection;
1461             }
1462             if (e.Property.Equals(DrawRulerProperty))
1463             {
1464                 source.Document.HideRuler = !source.DrawRuler;
1465                 source._Controller.JumpCaret(source.Document.CaretPostion.row, source.Document.CaretPostion.col);
1466             }
1467 #if !DUMMY_RENDER
1468             if (e.Property.Equals(TextAntialiasModeProperty))
1469                 source.Render.TextAntialiasMode = source.TextAntialiasMode;
1470             if(e.Property.Equals(MagnificationPowerPropertyKey))
1471                 source.Render.FontSize = source.FontSize * source.MagnificationPower;
1472             if (e.Property.Equals(FontFamilyProperty))
1473                 source.Render.FontFamily = source.FontFamily;
1474             if (e.Property.Equals(FontStyleProperty))
1475                 source.Render.FontStyle = source.FontStyle;
1476             if (e.Property.Equals(FontWeightProperty))
1477                 source.Render.FontWeigth = source.FontWeight;
1478             if (e.Property.Equals(FontSizeProperty))
1479                 source.Render.FontSize = source.FontSize;
1480             if (e.Property.Equals(ForegroundProperty))
1481                 source.Render.Foreground = D2DRenderBase.ToColor4(source.Foreground);
1482             if (e.Property.Equals(HilightForegroundProperty))
1483                 source.Render.HilightForeground = D2DRenderBase.ToColor4(source.HilightForeground);
1484             if (e.Property.Equals(BackgroundProperty))
1485                 source.Render.Background = D2DRenderBase.ToColor4(source.Background);
1486             if (e.Property.Equals(ControlCharProperty))
1487                 source.Render.ControlChar = D2DRenderBase.ToColor4(source.ControlChar);
1488             if (e.Property.Equals(HilightProperty))
1489                 source.Render.Hilight = D2DRenderBase.ToColor4(source.Hilight);
1490             if (e.Property.Equals(Keyword1Property))
1491                 source.Render.Keyword1 = D2DRenderBase.ToColor4(source.Keyword1);
1492             if (e.Property.Equals(Keyword2Property))
1493                 source.Render.Keyword2 = D2DRenderBase.ToColor4(source.Keyword2);
1494             if (e.Property.Equals(CommentProperty))
1495                 source.Render.Comment = D2DRenderBase.ToColor4(source.Comment);
1496             if (e.Property.Equals(LiteralProperty))
1497                 source.Render.Literal = D2DRenderBase.ToColor4(source.Literal);
1498             if (e.Property.Equals(URLProperty))
1499                 source.Render.Url = D2DRenderBase.ToColor4(source.URL);
1500             if (e.Property.Equals(InsertCaretProperty))
1501                 source.Render.InsertCaret = D2DRenderBase.ToColor4(source.InsertCaret);
1502             if (e.Property.Equals(OverwriteCaretProperty))
1503                 source.Render.OverwriteCaret = D2DRenderBase.ToColor4(source.OverwriteCaret);
1504             if (e.Property.Equals(PaddingProperty))
1505                 source.View.Padding = new Padding((int)source.Padding.Left, (int)source.Padding.Top, (int)source.Padding.Right, (int)source.Padding.Bottom);
1506             if (e.Property.Equals(LineMarkerProperty))
1507                 source.Render.LineMarker = D2DRenderBase.ToColor4(source.LineMarker);
1508             if (e.Property.Equals(ShowFullSpaceProperty))
1509                 source.Render.ShowFullSpace = source.ShowFullSpace;
1510             if (e.Property.Equals(ShowHalfSpaceProperty))
1511                 source.Render.ShowHalfSpace = source.ShowHalfSpace;
1512             if (e.Property.Equals(ShowTabProperty))
1513                 source.Render.ShowTab = source.ShowTab;
1514             if (e.Property.Equals(ShowLineBreakProperty))
1515                 source.Render.ShowLineBreak = source.ShowLineBreak;
1516             if (e.Property.Equals(UpdateAreaProperty))
1517                 source.Render.UpdateArea = D2DRenderBase.ToColor4(source.UpdateArea);
1518             if (e.Property.Equals(LineNumberProperty))
1519                 source.Render.LineNumber = D2DRenderBase.ToColor4(source.LineNumber);
1520 #endif
1521         }
1522         #endregion
1523
1524         #region event
1525
1526         /// <summary>
1527         /// コンテキストメニューが表示されるときに呼び出されます
1528         /// </summary>
1529         public event EventHandler<FooContextMenuEventArgs> ContextMenuOpening;
1530
1531 #endregion
1532
1533 #region property
1534
1535         internal Controller Controller
1536         {
1537             get
1538             {
1539                 return this._Controller;
1540             }
1541         }
1542
1543         /// <summary>
1544         /// 文字列の描写に使用されるアンチエイリアシング モードを表します
1545         /// </summary>
1546         public TextAntialiasMode TextAntialiasMode
1547         {
1548             get { return (TextAntialiasMode)GetValue(TextAntialiasModeProperty); }
1549             set { SetValue(TextAntialiasModeProperty, value); }
1550         }
1551
1552         /// <summary>
1553         /// TextAntialiasModeの依存プロパティを表す
1554         /// </summary>
1555         public static readonly DependencyProperty TextAntialiasModeProperty =
1556             DependencyProperty.Register("TextAntialiasMode", typeof(TextAntialiasMode), typeof(FooTextBox), new PropertyMetadata(TextAntialiasMode.Default, OnPropertyChanged));
1557
1558         /// <summary>
1559         /// シンタックスハイライターを表す
1560         /// </summary>
1561         public IHilighter Hilighter
1562         {
1563             get { return (IHilighter)GetValue(HilighterProperty); }
1564             set { SetValue(HilighterProperty, value); }
1565         }
1566
1567         /// <summary>
1568         /// Hilighterの依存プロパティを表す
1569         /// </summary>
1570         public static readonly DependencyProperty HilighterProperty =
1571             DependencyProperty.Register("Hilighter", typeof(IHilighter), typeof(FooTextBox), new PropertyMetadata(null, OnPropertyChanged));
1572
1573         /// <summary>
1574         /// フォールティングを作成するインターフェイスを表す
1575         /// </summary>
1576         public IFoldingStrategy FoldingStrategy
1577         {
1578             get { return (IFoldingStrategy)GetValue(FoldingStrategyProperty); }
1579             set { SetValue(FoldingStrategyProperty, value); }
1580         }
1581
1582         /// <summary>
1583         /// FoldingStrategyの依存プロパティ
1584         /// </summary>
1585         public static readonly DependencyProperty FoldingStrategyProperty =
1586             DependencyProperty.Register("FoldingStrategy", typeof(IFoldingStrategy), typeof(FooTextBox), new PropertyMetadata(null,OnPropertyChanged));
1587
1588         /// <summary>
1589         /// マーカーパターンセットを表す
1590         /// </summary>
1591         public MarkerPatternSet MarkerPatternSet
1592         {
1593             get
1594             {
1595                 return this.Document.MarkerPatternSet;
1596             }
1597         }
1598
1599         /// <summary>
1600         /// ドキュメントを表す
1601         /// </summary>
1602         /// <remarks>切り替え後に再描写が行われます</remarks>
1603         public Document Document
1604         {
1605             get { return (Document)GetValue(DocumentProperty); }
1606             set { SetValue(DocumentProperty, value); }
1607         }
1608
1609         // Using a DependencyProperty as the backing store for Document.  This enables animation, styling, binding, etc...
1610         public static readonly DependencyProperty DocumentProperty =
1611             DependencyProperty.Register("Document", typeof(Document), typeof(FooTextBox), new PropertyMetadata(null, OnPropertyChanged));
1612
1613
1614
1615         /// <summary>
1616         /// レイアウト行を表す
1617         /// </summary>
1618         public LineToIndexTable LayoutLineCollection
1619         {
1620             get { return this.View.LayoutLines; }
1621         }
1622
1623         /// <summary>
1624         /// 選択中の文字列を表す
1625         /// </summary>
1626         public string SelectedText
1627         {
1628             get { return (string)GetValue(SelectedTextProperty); }
1629             set { SetValue(SelectedTextProperty, value); }
1630         }
1631
1632         /// <summary>
1633         /// SelectedTextの依存プロパティを表す
1634         /// </summary>
1635         public static readonly DependencyProperty SelectedTextProperty =
1636             DependencyProperty.Register("SelectedText", typeof(string), typeof(FooTextBox), new PropertyMetadata(null, OnPropertyChanged));
1637
1638         /// <summary>
1639         /// インデントの方法を表す
1640         /// </summary>
1641         public IndentMode IndentMode
1642         {
1643             get { return (IndentMode)GetValue(IndentModeProperty); }
1644             set { SetValue(IndentModeProperty, value); }
1645         }
1646
1647         /// <summary>
1648         /// IndentModeの依存プロパティを表す
1649         /// </summary>
1650         public static readonly DependencyProperty IndentModeProperty =
1651             DependencyProperty.Register("IndentMode", typeof(IndentMode), typeof(FooTextBox), new PropertyMetadata(IndentMode.Tab,OnPropertyChanged));
1652
1653         /// <summary>
1654         /// 選択範囲を表す
1655         /// </summary>
1656         /// <remarks>
1657         /// Lengthが0の場合はキャレット位置を表します。
1658         /// 矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります
1659         /// </remarks>
1660         public TextRange Selection
1661         {
1662             get { return (TextRange)GetValue(SelectionProperty); }
1663             set { SetValue(SelectionProperty, value); }
1664         }
1665
1666         /// <summary>
1667         /// Selectionの依存プロパティを表す
1668         /// </summary>
1669         public static readonly DependencyProperty SelectionProperty =
1670             DependencyProperty.Register("Selection", typeof(TextRange), typeof(FooTextBox), new PropertyMetadata(TextRange.Null, OnPropertyChanged));
1671
1672         /// <summary>
1673         /// 拡大率を表す
1674         /// </summary>
1675         public double MagnificationPower
1676         {
1677             get { return (double)GetValue(MagnificationPowerPropertyKey); }
1678             set { SetValue(MagnificationPowerPropertyKey, value); }
1679         }
1680
1681         /// <summary>
1682         /// 拡大率を表す依存プロパティ
1683         /// </summary>
1684         public static readonly DependencyProperty MagnificationPowerPropertyKey =
1685             DependencyProperty.Register("MagnificationPower", typeof(double), typeof(FooTextBox), new PropertyMetadata(1.0, OnPropertyChanged));
1686
1687         /// <summary>
1688         /// キャレット位置を表す
1689         /// </summary>
1690         public TextPoint CaretPostion
1691         {
1692             get { return (TextPoint)GetValue(CaretPostionPropertyKey); }
1693             set { SetValue(CaretPostionPropertyKey, value); }
1694         }
1695
1696         static readonly DependencyProperty CaretPostionPropertyKey =
1697             DependencyProperty.Register("CaretPostion", typeof(TextPoint), typeof(FooTextBox), new PropertyMetadata(new TextPoint(), OnPropertyChanged));
1698
1699         /// <summary>
1700         /// レタリング方向を表す
1701         /// </summary>
1702         public new FlowDirection FlowDirection
1703         {
1704             get { return (FlowDirection)GetValue(FlowDirectionProperty); }
1705             set { SetValue(FlowDirectionProperty, value); }
1706         }
1707
1708         /// <summary>
1709         /// レタリング方向を表す。これは依存プロパティです
1710         /// </summary>
1711         public new static readonly DependencyProperty FlowDirectionProperty =
1712             DependencyProperty.Register("FlowDirection", typeof(FlowDirection), typeof(FooTextBox), new PropertyMetadata(FlowDirection.LeftToRight,OnPropertyChanged));
1713
1714         /// <summary>
1715         /// フォントファミリーを表す
1716         /// </summary>
1717         public new FontFamily FontFamily
1718         {
1719             get { return (FontFamily)GetValue(FontFamilyProperty); }
1720             set { SetValue(FontFamilyProperty, value); }
1721         }
1722
1723         /// <summary>
1724         /// FontFamilyの依存プロパティを表す
1725         /// </summary>
1726         public new static readonly DependencyProperty FontFamilyProperty =
1727             DependencyProperty.Register("FontFamily", typeof(FontFamily), typeof(FooTextBox), new PropertyMetadata(new FontFamily("Cambria"), OnPropertyChanged));
1728
1729         /// <summary>
1730         /// フォントサイズを表す
1731         /// </summary>
1732         public new double FontSize
1733         {
1734             get { return (double)GetValue(FontSizeProperty); }
1735             set { SetValue(FontSizeProperty, value); }
1736         }
1737
1738         /// <summary>
1739         /// FontSizeの依存プロパティを表す
1740         /// </summary>
1741         public new static readonly DependencyProperty FontSizeProperty =
1742             DependencyProperty.Register("FontSize", typeof(double), typeof(FooTextBox), new PropertyMetadata(12.0,OnPropertyChanged));
1743
1744         /// <summary>
1745         /// フォントスタイルを表す
1746         /// </summary>
1747         public new FontStyle FontStyle
1748         {
1749             get { return (FontStyle)GetValue(FontStyleProperty); }
1750             set { SetValue(FontStyleProperty, value); }
1751         }
1752
1753         /// <summary>
1754         /// FontStyleの依存プロパティを表す
1755         /// </summary>
1756         public new static readonly DependencyProperty FontStyleProperty =
1757             DependencyProperty.Register("FontStyle", typeof(FontStyle), typeof(FooTextBox), new PropertyMetadata(FontStyle.Normal,OnPropertyChanged));
1758
1759         /// <summary>
1760         /// フォントの幅を表す
1761         /// </summary>
1762         public new FontWeight FontWeight
1763         {
1764             get { return (FontWeight)GetValue(FontWeightProperty); }
1765             set { SetValue(FontWeightProperty, value); }
1766         }
1767
1768         /// <summary>
1769         /// FontWeigthの依存プロパティを表す
1770         /// </summary>
1771         public new static readonly DependencyProperty FontWeightProperty =
1772             DependencyProperty.Register("FontWeigth", typeof(FontWeight), typeof(FooTextBox), new PropertyMetadata(FontWeights.Normal,OnPropertyChanged));
1773
1774         /// <summary>
1775         /// デフォルトの文字色を表す。これは依存プロパティです
1776         /// </summary>
1777         public new Windows.UI.Color Foreground
1778         {
1779             get { return (Windows.UI.Color)GetValue(ForegroundProperty); }
1780             set { SetValue(ForegroundProperty, value); }
1781         }
1782
1783         /// <summary>
1784         /// Foregroundの依存プロパティを表す
1785         /// </summary>
1786         public new static readonly DependencyProperty ForegroundProperty =
1787             DependencyProperty.Register("Foreground", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Black, OnPropertyChanged));
1788
1789         /// <summary>
1790         /// 選択時の文字色を表す。これは依存プロパティです
1791         /// </summary>
1792         public Windows.UI.Color HilightForeground
1793         {
1794             get { return (Windows.UI.Color)GetValue(HilightForegroundProperty); }
1795             set { SetValue(HilightForegroundProperty, value); }
1796         }
1797
1798         /// <summary>
1799         /// HilightForegroundForegroundの依存プロパティを表す
1800         /// </summary>
1801         public static readonly DependencyProperty HilightForegroundProperty =
1802             DependencyProperty.Register("HilightForeground", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.White, OnPropertyChanged));
1803
1804         /// <summary>
1805         /// 背景色を表す。これは依存プロパティです
1806         /// </summary>
1807         public new Windows.UI.Color Background
1808         {
1809             get { return (Windows.UI.Color)GetValue(BackgroundProperty); }
1810             set { SetValue(BackgroundProperty, value); }
1811         }
1812
1813         /// <summary>
1814         /// Backgroundの依存プロパティを表す
1815         /// </summary>
1816         public new static readonly DependencyProperty BackgroundProperty =
1817             DependencyProperty.Register("Background", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.White, OnPropertyChanged));
1818
1819         /// <summary>
1820         /// コントロールコードの文字色を表す。これは依存プロパティです
1821         /// </summary>
1822         public Windows.UI.Color ControlChar
1823         {
1824             get { return (Windows.UI.Color)GetValue(ControlCharProperty); }
1825             set { SetValue(ControlCharProperty, value); }
1826         }
1827
1828         /// <summary>
1829         /// ControlCharの依存プロパティを表す
1830         /// </summary>
1831         public static readonly DependencyProperty ControlCharProperty =
1832             DependencyProperty.Register("ControlChar", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Gray, OnPropertyChanged));
1833
1834         /// <summary>
1835         /// 選択時の背景色を表す。これは依存プロパティです
1836         /// </summary>
1837         public Windows.UI.Color Hilight
1838         {
1839             get { return (Windows.UI.Color)GetValue(HilightProperty); }
1840             set { SetValue(HilightProperty, value); }
1841         }
1842
1843         /// <summary>
1844         /// Hilightの依存プロパティを表す
1845         /// </summary>
1846         public static readonly DependencyProperty HilightProperty =
1847             DependencyProperty.Register("Hilight", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.DodgerBlue, OnPropertyChanged));
1848
1849         /// <summary>
1850         /// キーワード1の文字色を表す。これは依存プロパティです
1851         /// </summary>
1852         public Windows.UI.Color Keyword1
1853         {
1854             get { return (Windows.UI.Color)GetValue(Keyword1Property); }
1855             set { SetValue(Keyword1Property, value); }
1856         }
1857
1858         /// <summary>
1859         /// Keyword1の依存プロパティを表す
1860         /// </summary>
1861         public static readonly DependencyProperty Keyword1Property =
1862             DependencyProperty.Register("Keyword1", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Blue, OnPropertyChanged));
1863
1864         /// <summary>
1865         /// キーワード2の文字色を表す。これは依存プロパティです
1866         /// </summary>
1867         public Windows.UI.Color Keyword2
1868         {
1869             get { return (Windows.UI.Color)GetValue(Keyword2Property); }
1870             set { SetValue(Keyword2Property, value); }
1871         }
1872
1873         /// <summary>
1874         /// Keyword2の依存プロパティを表す
1875         /// </summary>
1876         public static readonly DependencyProperty Keyword2Property =
1877             DependencyProperty.Register("Keyword2", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.DarkCyan, OnPropertyChanged));
1878
1879         /// <summary>
1880         /// コメントの文字色を表す。これは依存プロパティです
1881         /// </summary>
1882         public Windows.UI.Color Comment
1883         {
1884             get { return (Windows.UI.Color)GetValue(CommentProperty); }
1885             set { SetValue(CommentProperty, value); }
1886         }
1887
1888         /// <summary>
1889         /// Commentの依存プロパティを表す
1890         /// </summary>
1891         public static readonly DependencyProperty CommentProperty =
1892             DependencyProperty.Register("Comment", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Green, OnPropertyChanged));
1893
1894         /// <summary>
1895         /// 文字リテラルの文字色を表す。これは依存プロパティです
1896         /// </summary>
1897         public Windows.UI.Color Literal
1898         {
1899             get { return (Windows.UI.Color)GetValue(LiteralProperty); }
1900             set { SetValue(LiteralProperty, value); }
1901         }
1902
1903         /// <summary>
1904         /// Literalの依存プロパティを表す
1905         /// </summary>
1906         public static readonly DependencyProperty LiteralProperty =
1907             DependencyProperty.Register("Literal", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Brown, OnPropertyChanged));
1908
1909         /// <summary>
1910         /// URLの文字色を表す。これは依存プロパティです
1911         /// </summary>
1912         public Windows.UI.Color URL
1913         {
1914             get { return (Windows.UI.Color)GetValue(URLProperty); }
1915             set { SetValue(URLProperty, value); }
1916         }
1917
1918         /// <summary>
1919         /// URLの依存プロパティを表す
1920         /// </summary>
1921         public static readonly DependencyProperty URLProperty =
1922             DependencyProperty.Register("URL", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Blue, OnPropertyChanged));
1923
1924         /// <summary>
1925         /// 行更新フラグの色を表す
1926         /// </summary>
1927         public Windows.UI.Color UpdateArea
1928         {
1929             get { return (Windows.UI.Color)GetValue(UpdateAreaProperty); }
1930             set { SetValue(UpdateAreaProperty, value); }
1931         }
1932
1933         /// <summary>
1934         /// UpdateAreaの依存プロパティを表す
1935         /// </summary>
1936         public static readonly DependencyProperty UpdateAreaProperty =
1937             DependencyProperty.Register("UpdateArea", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.MediumSeaGreen, OnPropertyChanged));
1938
1939         /// <summary>
1940         /// ラインマーカーの色を表す
1941         /// </summary>
1942         public Windows.UI.Color LineMarker
1943         {
1944             get { return (Windows.UI.Color)GetValue(LineMarkerProperty); }
1945             set { SetValue(LineMarkerProperty, value); }
1946         }
1947
1948         /// <summary>
1949         /// LineMarkerの依存プロパティを表す
1950         /// </summary>
1951         public static readonly DependencyProperty LineMarkerProperty =
1952             DependencyProperty.Register("LineMarker", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Gray, OnPropertyChanged));
1953
1954         /// <summary>
1955         /// 挿入モード時のキャレットの色を表す
1956         /// </summary>
1957         public Windows.UI.Color InsertCaret
1958         {
1959             get { return (Windows.UI.Color)GetValue(InsertCaretProperty); }
1960             set { SetValue(InsertCaretProperty, value); }
1961         }
1962
1963         /// <summary>
1964         /// InsertCaretの依存プロパティを表す
1965         /// </summary>
1966         public static readonly DependencyProperty InsertCaretProperty =
1967             DependencyProperty.Register("InsertCaret", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Black, OnPropertyChanged));
1968
1969         /// <summary>
1970         /// 上書きモード時のキャレット職を表す
1971         /// </summary>
1972         public Windows.UI.Color OverwriteCaret
1973         {
1974             get { return (Windows.UI.Color)GetValue(OverwriteCaretProperty); }
1975             set { SetValue(OverwriteCaretProperty, value); }
1976         }
1977
1978         /// <summary>
1979         /// OverwriteCaretの依存プロパティを表す
1980         /// </summary>
1981         public static readonly DependencyProperty OverwriteCaretProperty =
1982             DependencyProperty.Register("OverwriteCaret", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Black, OnPropertyChanged));
1983
1984         /// <summary>
1985         /// 行番号の色を表す
1986         /// </summary>
1987         public Windows.UI.Color LineNumber
1988         {
1989             get { return (Windows.UI.Color)GetValue(LineNumberProperty); }
1990             set { SetValue(LineNumberProperty, value); }
1991         }
1992
1993         /// <summary>
1994         /// Using a DependencyProperty as the backing store for LineNumber.  This enables animation, styling, binding, etc...
1995         /// </summary>
1996         public static readonly DependencyProperty LineNumberProperty =
1997             DependencyProperty.Register("LineNumber", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.DimGray,OnPropertyChanged));
1998
1999         /// <summary>
2000         /// 余白を表す
2001         /// </summary>
2002         public new Thickness Padding
2003         {
2004             get { return (Thickness)GetValue(PaddingProperty); }
2005             set { SetValue(PaddingProperty, value); }
2006         }
2007
2008         /// <summary>
2009         /// Paddingの依存プロパティを表す
2010         /// </summary>
2011         public new static readonly DependencyProperty PaddingProperty =
2012             DependencyProperty.Register("Padding", typeof(Thickness), typeof(FooTextBox), new PropertyMetadata(new Thickness(),OnPropertyChanged));        
2013
2014         /// <summary>
2015         /// 挿入モードなら真を返し、そうでないなら、偽を返す。これは依存プロパティです
2016         /// </summary>
2017         public bool InsertMode
2018         {
2019             get { return (bool)GetValue(InsertModeProperty); }
2020             set { SetValue(InsertModeProperty, value); }
2021         }
2022
2023         /// <summary>
2024         /// InsertModeの依存プロパティを表す
2025         /// </summary>
2026         public static readonly DependencyProperty InsertModeProperty =
2027             DependencyProperty.Register("InsertMode",
2028             typeof(bool),
2029             typeof(FooTextBox),
2030             new PropertyMetadata(true, OnPropertyChanged));
2031
2032         /// <summary>
2033         /// タブの文字数を表す。これは依存プロパティです
2034         /// </summary>
2035         public int TabChars
2036         {
2037             get { return (int)GetValue(TabCharsProperty); }
2038             set { SetValue(TabCharsProperty, value); }
2039         }
2040
2041         /// <summary>
2042         /// TabCharsの依存プロパティを表す
2043         /// </summary>
2044         public static readonly DependencyProperty TabCharsProperty =
2045             DependencyProperty.Register("TabChars",
2046             typeof(int),
2047             typeof(FooTextBox),
2048             new PropertyMetadata(4, OnPropertyChanged));
2049
2050         /// <summary>
2051         /// 矩形選択モードなら真を返し、そうでないなら偽を返す。これは依存プロパティです
2052         /// </summary>
2053         public bool RectSelectMode
2054         {
2055             get { return (bool)GetValue(RectSelectModeProperty); }
2056             set { SetValue(RectSelectModeProperty, value); }
2057         }
2058
2059         /// <summary>
2060         /// RectSelectModeの依存プロパティを表す
2061         /// </summary>
2062         public static readonly DependencyProperty RectSelectModeProperty =
2063             DependencyProperty.Register("RectSelectMode", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2064
2065         /// <summary>
2066         /// 折り返しの方法を指定する
2067         /// </summary>
2068         /// <remarks>
2069         /// 変更した場合、レイアウトの再構築を行う必要があります
2070         /// </remarks>
2071         public LineBreakMethod LineBreakMethod
2072         {
2073             get { return (LineBreakMethod)GetValue(LineBreakProperty); }
2074             set { SetValue(LineBreakProperty, value); }
2075         }
2076
2077         /// <summary>
2078         /// LineBreakMethodの依存プロパティを表す
2079         /// </summary>
2080         public static readonly DependencyProperty LineBreakProperty =
2081             DependencyProperty.Register("LineBreakMethod", typeof(LineBreakMethod), typeof(FooTextBox), new PropertyMetadata(LineBreakMethod.None, OnPropertyChanged));
2082
2083
2084         /// <summary>
2085         /// 折り返しの幅を指定する。LineBreakMethod.CharUnit以外の時は無視されます
2086         /// </summary>
2087         /// <remarks>
2088         /// 変更した場合、レイアウトの再構築を行う必要があります
2089         /// </remarks>
2090         public int LineBreakCharCount
2091         {
2092             get { return (int)GetValue(LineBreakCharCountProperty); }
2093             set { SetValue(LineBreakCharCountProperty, value); }
2094         }
2095
2096         /// <summary>
2097         /// LineBreakCharCountの依存プロパティを表す
2098         /// </summary>
2099         public static readonly DependencyProperty LineBreakCharCountProperty =
2100             DependencyProperty.Register("LineBreakCharCount", typeof(int), typeof(FooTextBox), new PropertyMetadata(80, OnPropertyChanged));        
2101
2102         /// <summary>
2103         /// キャレットを描くなら真。そうでないなら偽を返す。これは依存プロパティです
2104         /// </summary>
2105         public bool DrawCaret
2106         {
2107             get { return (bool)GetValue(DrawCaretProperty); }
2108             set { SetValue(DrawCaretProperty, value); }
2109         }
2110
2111         /// <summary>
2112         /// DrawCaretの依存プロパティを表す
2113         /// </summary>
2114         public static readonly DependencyProperty DrawCaretProperty =
2115             DependencyProperty.Register("DrawCaret", typeof(bool), typeof(FooTextBox), new PropertyMetadata(true, OnPropertyChanged));
2116
2117
2118         /// <summary>
2119         /// キャレットラインを描くなら真。そうでないなら偽を返す。これは依存プロパティです
2120         /// </summary>
2121         public bool DrawCaretLine
2122         {
2123             get { return (bool)GetValue(DrawCaretLineProperty); }
2124             set { SetValue(DrawCaretLineProperty, value); }
2125         }
2126
2127         /// <summary>
2128         /// DrawCaretLineの依存プロパティを表す
2129         /// </summary>
2130         public static readonly DependencyProperty DrawCaretLineProperty =
2131             DependencyProperty.Register("DrawCaretLine", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2132
2133         /// <summary>
2134         /// 行番号を描くなら真。そうでなければ偽。これは依存プロパティです
2135         /// </summary>
2136         public bool DrawLineNumber
2137         {
2138             get { return (bool)GetValue(DrawLineNumberProperty); }
2139             set { SetValue(DrawLineNumberProperty, value); }
2140         }
2141
2142         /// <summary>
2143         /// ルーラーを描くなら真。そうでなければ偽。これは依存プロパティです
2144         /// </summary>
2145         public bool DrawRuler
2146         {
2147             get { return (bool)GetValue(DrawRulerProperty); }
2148             set { SetValue(DrawRulerProperty, value); }
2149         }
2150
2151         /// <summary>
2152         /// DrawRulerの依存プロパティを表す
2153         /// </summary>
2154         public static readonly DependencyProperty DrawRulerProperty =
2155             DependencyProperty.Register("DrawRuler", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2156
2157
2158         /// <summary>
2159         /// DrawLineNumberの依存プロパティを表す
2160         /// </summary>
2161         public static readonly DependencyProperty DrawLineNumberProperty =
2162             DependencyProperty.Register("DrawLineNumber", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2163
2164         /// <summary>
2165         /// URLに下線を引くなら真。そうでないなら偽を表す。これは依存プロパティです
2166         /// </summary>
2167         public bool MarkURL
2168         {
2169             get { return (bool)GetValue(MarkURLProperty); }
2170             set { SetValue(MarkURLProperty, value); }
2171         }
2172
2173         /// <summary>
2174         /// MarkURLの依存プロパティを表す
2175         /// </summary>
2176         public static readonly DependencyProperty MarkURLProperty =
2177             DependencyProperty.Register("MarkURL", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2178
2179         /// <summary>
2180         /// 全角スペースを表示するなら真。そうでないなら偽
2181         /// </summary>
2182         public bool ShowFullSpace
2183         {
2184             get { return (bool)GetValue(ShowFullSpaceProperty); }
2185             set { SetValue(ShowFullSpaceProperty, value); }
2186         }
2187
2188         /// <summary>
2189         /// ShowFullSpaceの依存プロパティを表す
2190         /// </summary>
2191         public static readonly DependencyProperty ShowFullSpaceProperty =
2192             DependencyProperty.Register("ShowFullSpace", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2193
2194         /// <summary>
2195         /// 半角スペースを表示するなら真。そうでないなら偽
2196         /// </summary>
2197         public bool ShowHalfSpace
2198         {
2199             get { return (bool)GetValue(ShowHalfSpaceProperty); }
2200             set { SetValue(ShowHalfSpaceProperty, value); }
2201         }
2202
2203         /// <summary>
2204         /// ShowHalfSpaceの依存プロパティを表す
2205         /// </summary>
2206         public static readonly DependencyProperty ShowHalfSpaceProperty =
2207             DependencyProperty.Register("ShowHalfSpace", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2208
2209         /// <summary>
2210         /// タブを表示するなら真。そうでないなら偽
2211         /// </summary>
2212         public bool ShowTab
2213         {
2214             get { return (bool)GetValue(ShowTabProperty); }
2215             set { SetValue(ShowTabProperty, value); }
2216         }
2217
2218         /// <summary>
2219         /// ShowTabの依存プロパティを表す
2220         /// </summary>
2221         public static readonly DependencyProperty ShowTabProperty =
2222             DependencyProperty.Register("ShowTab", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2223
2224         /// <summary>
2225         /// 改行マークを表示するなら真。そうでないなら偽
2226         /// </summary>
2227         public bool ShowLineBreak
2228         {
2229             get { return (bool)GetValue(ShowLineBreakProperty); }
2230             set { SetValue(ShowLineBreakProperty, value); }
2231         }
2232
2233         /// <summary>
2234         /// ShowLineBreakの依存プロパティを表す
2235         /// </summary>
2236         public static readonly DependencyProperty ShowLineBreakProperty =
2237             DependencyProperty.Register("ShowLineBreak", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false,OnPropertyChanged));
2238
2239         
2240 #endregion
2241     }
2242     /// <summary>
2243     /// コンテキストメニューのイベントデーターを表す
2244     /// </summary>
2245     public class FooContextMenuEventArgs
2246     {
2247         /// <summary>
2248         /// 処理済みなら真。そうでないなら偽
2249         /// </summary>
2250         public bool Handled = false;
2251         /// <summary>
2252         /// コンテキストメニューを表示すべき座標を表す
2253         /// </summary>
2254         public Windows.Foundation.Point Postion;
2255         /// <summary>
2256         /// コンストラクター
2257         /// </summary>
2258         /// <param name="pos"></param>
2259         public FooContextMenuEventArgs(Windows.Foundation.Point pos)
2260         {
2261             this.Postion = pos;
2262         }
2263     }
2264 }