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             this.Refresh();
1178         }
1179
1180         bool IsModiferKeyPressed(VirtualKey key)
1181         {
1182             CoreVirtualKeyStates state = Window.Current.CoreWindow.GetKeyState(key);
1183             return (state & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
1184         }
1185         void Refresh(Rectangle updateRect)
1186         {
1187             if (this.rectangle.ActualWidth == 0 || this.rectangle.ActualHeight == 0 || this.Visibility == Windows.UI.Xaml.Visibility.Collapsed)
1188                 return;
1189
1190             this.Render.DrawContent(this.View, this.IsEnabled, updateRect);
1191
1192             this.Document.IsRequestRedraw = false;
1193         }
1194
1195
1196         bool Resize(double width, double height)
1197         {
1198             if (width == 0 || height == 0)
1199                 throw new ArgumentOutOfRangeException();
1200             if (this.Render.Resize(this.rectangle, width, height))
1201             {
1202                 this.View.PageBound = new Rectangle(0, 0, width, height);
1203
1204                 if (this.horizontalScrollBar != null)
1205                 {
1206                     this.horizontalScrollBar.LargeChange = this.View.PageBound.Width;
1207                     this.horizontalScrollBar.Maximum = this.View.LongestWidth + this.horizontalScrollBar.LargeChange + 1;
1208                 }
1209                 if (this.verticalScrollBar != null)
1210                 {
1211                     this.verticalScrollBar.LargeChange = this.View.LineCountOnScreen;
1212                     this.verticalScrollBar.Maximum = this.View.LayoutLines.Count + this.verticalScrollBar.LargeChange + 1;
1213                 }
1214                 return true;
1215             }
1216             return false;
1217         }
1218
1219         void View_SrcChanged(object sender, EventArgs e)
1220         {
1221             if (this.horizontalScrollBar == null || this.verticalScrollBar == null)
1222                 return;
1223             EditView view = this.View;
1224             if (view.Src.Row > this.verticalScrollBar.Maximum)
1225                 this.verticalScrollBar.Maximum = view.Src.Row + view.LineCountOnScreen + 1;
1226             double absoulteX = Math.Abs(view.Src.X);
1227             if (absoulteX > this.horizontalScrollBar.Maximum)
1228                 this.horizontalScrollBar.Maximum = absoulteX + view.PageBound.Width + 1;
1229             if (view.Src.Row != this.verticalScrollBar.Value)
1230                 this.verticalScrollBar.Value = view.Src.Row;
1231             if (view.Src.X != this.horizontalScrollBar.Value)
1232                 this.horizontalScrollBar.Value = Math.Abs(view.Src.X);
1233         }
1234
1235         void FooTextBox_SizeChanged(object sender, SizeChangedEventArgs e)
1236         {
1237             //LostFocusやGotFocusなどと競合するとDirect2Dでエラーが起きるので、timer_tickイベントでサイズ変更を行うことにした
1238             this.requestSizeChange = true;
1239         }
1240
1241         void horizontalScrollBar_Scroll(object sender, ScrollEventArgs e)
1242         {
1243             if (this.horizontalScrollBar == null)
1244                 return;
1245             double toX;
1246             if (this.FlowDirection == FlowDirection.LeftToRight)
1247                 toX = this.horizontalScrollBar.Value;
1248             else
1249                 toX = -this.horizontalScrollBar.Value;
1250             this._Controller.Scroll(toX, this.View.Src.Row, false, false);
1251             this.Refresh();
1252         }
1253
1254         void verticalScrollBar_Scroll(object sender, ScrollEventArgs e)
1255         {
1256             if (this.verticalScrollBar == null)
1257                 return;
1258             int newRow = (int)this.verticalScrollBar.Value;
1259             if (newRow >= this.View.LayoutLines.Count)
1260                 return;
1261             this._Controller.Scroll(this.View.Src.X, newRow, false, false);
1262             this.Refresh();
1263         }
1264
1265         void Document_Update(object sender, DocumentUpdateEventArgs e)
1266         {
1267             if (e.type == UpdateType.Replace && !this.nowCompstion)
1268             {
1269                 CoreTextRange oldTextRange = new CoreTextRange();
1270                 oldTextRange.StartCaretPosition = e.startIndex;
1271                 oldTextRange.EndCaretPosition = e.startIndex;
1272                 //削除する範囲が1以上の場合、ドキュメントを飛び越えることはできない
1273                 //https://msdn.microsoft.com/en-us/windows/uwp/input-and-devices/custom-text-input
1274                 if (e.removeLength > 0)
1275                     oldTextRange.EndCaretPosition += e.removeLength;
1276
1277                 TextRange currentSelection = new TextRange();
1278                 TextStoreHelper.GetSelection(this._Controller, this.View.Selections, out currentSelection);
1279
1280                 CoreTextRange newSelection = new CoreTextRange();
1281                 newSelection.StartCaretPosition = e.startIndex;
1282                 newSelection.EndCaretPosition = e.startIndex;
1283
1284                 //置き換え後の長さを指定する
1285                 //(注意:削除された文字数のほうが多い場合は0を指定しないいけない)
1286                 int newTextLength = e.insertLength;
1287
1288                 System.Diagnostics.Debug.WriteLine("notify text change (modify start:{0} end:{1}) newlength:{2} (new sel start:{3} end:{4})",
1289                     oldTextRange.StartCaretPosition, oldTextRange.EndCaretPosition, newTextLength, newSelection.StartCaretPosition, newSelection.EndCaretPosition);
1290                 //変換中に呼び出してはいけない
1291                 if(this.textEditContext != null)
1292                     this.textEditContext.NotifyTextChanged(oldTextRange, newTextLength, newSelection);
1293             }
1294 #if ENABLE_AUTMATION
1295             if (this.peer != null)
1296                 this.peer.OnNotifyTextChanged();
1297 #endif
1298         }
1299
1300         void FooTextBox_Loaded(object sender, RoutedEventArgs e)
1301         {
1302             this.Focus(FocusState.Programmatic);
1303         }
1304
1305         void timer_Tick(object sender, object e)
1306         {
1307             this.timer.Stop();
1308             if(this.requestSizeChange)
1309             {
1310                 if (this.Resize(this.rectangle.ActualWidth, this.rectangle.ActualHeight))
1311                 {
1312                     //普通に再描写するとちらつく
1313                     this.Refresh(this.View.PageBound);
1314                 }
1315                 this.requestSizeChange = false;
1316             }
1317             else if (this.View.LayoutLines.HilightAll() || this.View.LayoutLines.GenerateFolding() || this.Document.IsRequestRedraw)
1318             {
1319                 this.Refresh(this.View.PageBound);
1320             }
1321             this.timer.Start();
1322         }
1323
1324         private void SetDocument(Document value)
1325         {
1326             if (value == null)
1327                 return;
1328
1329             Document old_doc = this._Document;
1330
1331             if (this._Document != null)
1332             {
1333                 old_doc.Update -= new DocumentUpdateEventHandler(Document_Update);
1334                 this._Document.SelectionChanged -= Controller_SelectionChanged;
1335                 this._Document.LoadProgress -= Document_LoadProgress;
1336                 this._Document.AutoCompleteChanged -= _Document_AutoCompleteChanged;
1337                 if (this._Document.AutoComplete != null)
1338                 {
1339                     this._Document.AutoComplete.GetPostion = null;
1340                     this._Document.AutoComplete = null;
1341                 }
1342
1343                 //NotifyTextChanged()を呼び出すと落ちるのでTextConextをごっそり作り替える
1344                 this.RemoveTextContext();
1345             }
1346
1347             System.Diagnostics.Debug.WriteLine("document switched");
1348
1349             this._Document = value;
1350             this._Document.LayoutLines.Render = this.Render;
1351             this._Document.Update += new DocumentUpdateEventHandler(Document_Update);
1352             this._Document.LoadProgress += Document_LoadProgress;
1353             this._Document.AutoCompleteChanged += _Document_AutoCompleteChanged;
1354             if (this._Document.AutoComplete != null && this._Document.AutoComplete.GetPostion == null)
1355                 this._Document_AutoCompleteChanged(this._Document, null);
1356             //初期化が終わっていればすべて存在する
1357             if (this.Controller != null && this.View != null)
1358             {
1359                 this.Controller.Document = value;
1360                 this.View.Document = value;
1361
1362                 this.Controller.AdjustCaret();
1363
1364                 this.CreateTextContext();
1365
1366                 //依存プロパティとドキュメント内容が食い違っているので再設定する
1367                 this.ShowFullSpace = value.ShowFullSpace;
1368                 this.ShowHalfSpace = value.ShowHalfSpace;
1369                 this.ShowLineBreak = value.ShowLineBreak;
1370                 this.ShowTab = value.ShowTab;
1371                 this.FlowDirection = value.RightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
1372                 this.IndentMode = value.IndentMode;
1373                 this.DrawCaretLine = !value.HideLineMarker;
1374                 this.InsertMode = value.InsertMode;
1375                 this.DrawRuler = !value.HideRuler;
1376                 this.DrawLineNumber = value.DrawLineNumber;
1377                 this.MarkURL = value.UrlMark;
1378                 this.LineBreakMethod = value.LineBreak;
1379                 this.LineBreakCharCount = value.LineBreakCharCount;
1380                 this.TabChars = value.TabStops;
1381
1382                 this.Refresh();
1383             }
1384             //TextEditContext作成後に設定しないと落ちることがある
1385             this._Document.SelectionChanged += Controller_SelectionChanged;
1386         }
1387
1388         private void _Document_AutoCompleteChanged(object sender, EventArgs e)
1389         {
1390             Document doc = (Document)sender;
1391             doc.AutoComplete.GetPostion = (tp, e_doc) =>
1392             {
1393                 var p = this.View.GetPostionFromTextPoint(tp);
1394                 int height = (int)e_doc.LayoutLines.GetLayout(e_doc.CaretPostion.row).Height;
1395
1396                 if (p.Y + AutoCompleteBox.CompleteListBoxHeight + height > e_doc.LayoutLines.Render.TextArea.Height)
1397                     p.Y -= AutoCompleteBox.CompleteListBoxHeight;
1398                 else
1399                     p.Y += height;
1400                 //AutoCompleteBox内ではCanvasで位置を指定しているので変換する必要がある
1401                 var pointInWindow = Util.GetPointInWindow(p, this);
1402                 return pointInWindow;
1403             };
1404         }
1405
1406         /// <inheritdoc/>
1407         public static void OnPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
1408         {
1409             FooTextBox source = (FooTextBox)sender;
1410             if(e.Property.Equals(SelectedTextProperty) && !source.nowCaretMove)
1411                 source._Controller.SelectedText = source.SelectedText;
1412             if (e.Property.Equals(DocumentProperty))
1413                 source.SetDocument(source.Document);
1414             if(e.Property.Equals(HilighterProperty))
1415                 source.View.Hilighter = source.Hilighter;
1416             if (e.Property.Equals(FoldingStrategyProperty))
1417                 source.View.LayoutLines.FoldingStrategy = source.FoldingStrategy;
1418             if (e.Property.Equals(IndentModeProperty))
1419                 source.Controller.IndentMode = source.IndentMode;
1420             if (e.Property.Equals(SelectionProperty) && !source.nowCaretMove)
1421                 source.Document.Select(source.Selection.Index,source.Selection.Length);
1422             if (e.Property.Equals(CaretPostionPropertyKey) && !source.nowCaretMove)
1423                 source.JumpCaret(source.CaretPostion.row, source.CaretPostion.col);
1424             if (e.Property.Equals(InsertModeProperty))
1425                 source.View.InsertMode = source.InsertMode;
1426             if (e.Property.Equals(TabCharsProperty))
1427                 source.Document.TabStops = source.TabChars;
1428             if (e.Property.Equals(RectSelectModeProperty))
1429                 source._Controller.RectSelection = source.RectSelectMode;
1430             if (e.Property.Equals(DrawCaretProperty))
1431                 source.View.HideCaret = !source.DrawCaret;
1432             if (e.Property.Equals(DrawCaretLineProperty))
1433                 source.View.HideLineMarker = !source.DrawCaretLine;
1434             if (e.Property.Equals(DrawLineNumberProperty))
1435                 source.Document.DrawLineNumber = source.DrawLineNumber;
1436             if (e.Property.Equals(MarkURLProperty))
1437                 source.Document.UrlMark = source.MarkURL;
1438             if (e.Property.Equals(LineBreakProperty))
1439                 source.Document.LineBreak = source.LineBreakMethod;
1440             if (e.Property.Equals(LineBreakCharCountProperty))
1441                 source.Document.LineBreakCharCount = source.LineBreakCharCount;
1442             if (e.Property.Equals(FlowDirectionProperty))
1443             {
1444                 source.Document.RightToLeft = source.FlowDirection == Windows.UI.Xaml.FlowDirection.RightToLeft;
1445                 if (source.horizontalScrollBar != null)
1446                     source.horizontalScrollBar.FlowDirection = source.FlowDirection;
1447             }
1448             if (e.Property.Equals(DrawRulerProperty))
1449             {
1450                 source.Document.HideRuler = !source.DrawRuler;
1451                 source._Controller.JumpCaret(source.Document.CaretPostion.row, source.Document.CaretPostion.col);
1452             }
1453 #if !DUMMY_RENDER
1454             if (e.Property.Equals(TextAntialiasModeProperty))
1455                 source.Render.TextAntialiasMode = source.TextAntialiasMode;
1456             if(e.Property.Equals(MagnificationPowerPropertyKey))
1457                 source.Render.FontSize = source.FontSize * source.MagnificationPower;
1458             if (e.Property.Equals(FontFamilyProperty))
1459                 source.Render.FontFamily = source.FontFamily;
1460             if (e.Property.Equals(FontStyleProperty))
1461                 source.Render.FontStyle = source.FontStyle;
1462             if (e.Property.Equals(FontWeightProperty))
1463                 source.Render.FontWeigth = source.FontWeight;
1464             if (e.Property.Equals(FontSizeProperty))
1465                 source.Render.FontSize = source.FontSize;
1466             if (e.Property.Equals(ForegroundProperty))
1467                 source.Render.Foreground = D2DRenderBase.ToColor4(source.Foreground);
1468             if (e.Property.Equals(HilightForegroundProperty))
1469                 source.Render.HilightForeground = D2DRenderBase.ToColor4(source.HilightForeground);
1470             if (e.Property.Equals(BackgroundProperty))
1471                 source.Render.Background = D2DRenderBase.ToColor4(source.Background);
1472             if (e.Property.Equals(ControlCharProperty))
1473                 source.Render.ControlChar = D2DRenderBase.ToColor4(source.ControlChar);
1474             if (e.Property.Equals(HilightProperty))
1475                 source.Render.Hilight = D2DRenderBase.ToColor4(source.Hilight);
1476             if (e.Property.Equals(Keyword1Property))
1477                 source.Render.Keyword1 = D2DRenderBase.ToColor4(source.Keyword1);
1478             if (e.Property.Equals(Keyword2Property))
1479                 source.Render.Keyword2 = D2DRenderBase.ToColor4(source.Keyword2);
1480             if (e.Property.Equals(CommentProperty))
1481                 source.Render.Comment = D2DRenderBase.ToColor4(source.Comment);
1482             if (e.Property.Equals(LiteralProperty))
1483                 source.Render.Literal = D2DRenderBase.ToColor4(source.Literal);
1484             if (e.Property.Equals(URLProperty))
1485                 source.Render.Url = D2DRenderBase.ToColor4(source.URL);
1486             if (e.Property.Equals(InsertCaretProperty))
1487                 source.Render.InsertCaret = D2DRenderBase.ToColor4(source.InsertCaret);
1488             if (e.Property.Equals(OverwriteCaretProperty))
1489                 source.Render.OverwriteCaret = D2DRenderBase.ToColor4(source.OverwriteCaret);
1490             if (e.Property.Equals(PaddingProperty))
1491                 source.View.Padding = new Padding((int)source.Padding.Left, (int)source.Padding.Top, (int)source.Padding.Right, (int)source.Padding.Bottom);
1492             if (e.Property.Equals(LineMarkerProperty))
1493                 source.Render.LineMarker = D2DRenderBase.ToColor4(source.LineMarker);
1494             if (e.Property.Equals(ShowFullSpaceProperty))
1495                 source.Render.ShowFullSpace = source.ShowFullSpace;
1496             if (e.Property.Equals(ShowHalfSpaceProperty))
1497                 source.Render.ShowHalfSpace = source.ShowHalfSpace;
1498             if (e.Property.Equals(ShowTabProperty))
1499                 source.Render.ShowTab = source.ShowTab;
1500             if (e.Property.Equals(ShowLineBreakProperty))
1501                 source.Render.ShowLineBreak = source.ShowLineBreak;
1502             if (e.Property.Equals(UpdateAreaProperty))
1503                 source.Render.UpdateArea = D2DRenderBase.ToColor4(source.UpdateArea);
1504             if (e.Property.Equals(LineNumberProperty))
1505                 source.Render.LineNumber = D2DRenderBase.ToColor4(source.LineNumber);
1506 #endif
1507         }
1508         #endregion
1509
1510         #region event
1511
1512         /// <summary>
1513         /// コンテキストメニューが表示されるときに呼び出されます
1514         /// </summary>
1515         public event EventHandler<FooContextMenuEventArgs> ContextMenuOpening;
1516
1517 #endregion
1518
1519 #region property
1520
1521         internal Controller Controller
1522         {
1523             get
1524             {
1525                 return this._Controller;
1526             }
1527         }
1528
1529         /// <summary>
1530         /// 文字列の描写に使用されるアンチエイリアシング モードを表します
1531         /// </summary>
1532         public TextAntialiasMode TextAntialiasMode
1533         {
1534             get { return (TextAntialiasMode)GetValue(TextAntialiasModeProperty); }
1535             set { SetValue(TextAntialiasModeProperty, value); }
1536         }
1537
1538         /// <summary>
1539         /// TextAntialiasModeの依存プロパティを表す
1540         /// </summary>
1541         public static readonly DependencyProperty TextAntialiasModeProperty =
1542             DependencyProperty.Register("TextAntialiasMode", typeof(TextAntialiasMode), typeof(FooTextBox), new PropertyMetadata(TextAntialiasMode.Default, OnPropertyChanged));
1543
1544         /// <summary>
1545         /// シンタックスハイライターを表す
1546         /// </summary>
1547         public IHilighter Hilighter
1548         {
1549             get { return (IHilighter)GetValue(HilighterProperty); }
1550             set { SetValue(HilighterProperty, value); }
1551         }
1552
1553         /// <summary>
1554         /// Hilighterの依存プロパティを表す
1555         /// </summary>
1556         public static readonly DependencyProperty HilighterProperty =
1557             DependencyProperty.Register("Hilighter", typeof(IHilighter), typeof(FooTextBox), new PropertyMetadata(null, OnPropertyChanged));
1558
1559         /// <summary>
1560         /// フォールティングを作成するインターフェイスを表す
1561         /// </summary>
1562         public IFoldingStrategy FoldingStrategy
1563         {
1564             get { return (IFoldingStrategy)GetValue(FoldingStrategyProperty); }
1565             set { SetValue(FoldingStrategyProperty, value); }
1566         }
1567
1568         /// <summary>
1569         /// FoldingStrategyの依存プロパティ
1570         /// </summary>
1571         public static readonly DependencyProperty FoldingStrategyProperty =
1572             DependencyProperty.Register("FoldingStrategy", typeof(IFoldingStrategy), typeof(FooTextBox), new PropertyMetadata(null,OnPropertyChanged));
1573
1574         /// <summary>
1575         /// マーカーパターンセットを表す
1576         /// </summary>
1577         public MarkerPatternSet MarkerPatternSet
1578         {
1579             get
1580             {
1581                 return this.Document.MarkerPatternSet;
1582             }
1583         }
1584
1585         /// <summary>
1586         /// ドキュメントを表す
1587         /// </summary>
1588         /// <remarks>切り替え後に再描写が行われます</remarks>
1589         public Document Document
1590         {
1591             get { return (Document)GetValue(DocumentProperty); }
1592             set { SetValue(DocumentProperty, value); }
1593         }
1594
1595         // Using a DependencyProperty as the backing store for Document.  This enables animation, styling, binding, etc...
1596         public static readonly DependencyProperty DocumentProperty =
1597             DependencyProperty.Register("Document", typeof(Document), typeof(FooTextBox), new PropertyMetadata(null, OnPropertyChanged));
1598
1599
1600
1601         /// <summary>
1602         /// レイアウト行を表す
1603         /// </summary>
1604         public LineToIndexTable LayoutLineCollection
1605         {
1606             get { return this.View.LayoutLines; }
1607         }
1608
1609         /// <summary>
1610         /// 選択中の文字列を表す
1611         /// </summary>
1612         public string SelectedText
1613         {
1614             get { return (string)GetValue(SelectedTextProperty); }
1615             set { SetValue(SelectedTextProperty, value); }
1616         }
1617
1618         /// <summary>
1619         /// SelectedTextの依存プロパティを表す
1620         /// </summary>
1621         public static readonly DependencyProperty SelectedTextProperty =
1622             DependencyProperty.Register("SelectedText", typeof(string), typeof(FooTextBox), new PropertyMetadata(null, OnPropertyChanged));
1623
1624         /// <summary>
1625         /// インデントの方法を表す
1626         /// </summary>
1627         public IndentMode IndentMode
1628         {
1629             get { return (IndentMode)GetValue(IndentModeProperty); }
1630             set { SetValue(IndentModeProperty, value); }
1631         }
1632
1633         /// <summary>
1634         /// IndentModeの依存プロパティを表す
1635         /// </summary>
1636         public static readonly DependencyProperty IndentModeProperty =
1637             DependencyProperty.Register("IndentMode", typeof(IndentMode), typeof(FooTextBox), new PropertyMetadata(IndentMode.Tab,OnPropertyChanged));
1638
1639         /// <summary>
1640         /// 選択範囲を表す
1641         /// </summary>
1642         /// <remarks>
1643         /// Lengthが0の場合はキャレット位置を表します。
1644         /// 矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります
1645         /// </remarks>
1646         public TextRange Selection
1647         {
1648             get { return (TextRange)GetValue(SelectionProperty); }
1649             set { SetValue(SelectionProperty, value); }
1650         }
1651
1652         /// <summary>
1653         /// Selectionの依存プロパティを表す
1654         /// </summary>
1655         public static readonly DependencyProperty SelectionProperty =
1656             DependencyProperty.Register("Selection", typeof(TextRange), typeof(FooTextBox), new PropertyMetadata(TextRange.Null, OnPropertyChanged));
1657
1658         /// <summary>
1659         /// 拡大率を表す
1660         /// </summary>
1661         public double MagnificationPower
1662         {
1663             get { return (double)GetValue(MagnificationPowerPropertyKey); }
1664             set { SetValue(MagnificationPowerPropertyKey, value); }
1665         }
1666
1667         /// <summary>
1668         /// 拡大率を表す依存プロパティ
1669         /// </summary>
1670         public static readonly DependencyProperty MagnificationPowerPropertyKey =
1671             DependencyProperty.Register("MagnificationPower", typeof(double), typeof(FooTextBox), new PropertyMetadata(1.0, OnPropertyChanged));
1672
1673         /// <summary>
1674         /// キャレット位置を表す
1675         /// </summary>
1676         public TextPoint CaretPostion
1677         {
1678             get { return (TextPoint)GetValue(CaretPostionPropertyKey); }
1679             set { SetValue(CaretPostionPropertyKey, value); }
1680         }
1681
1682         static readonly DependencyProperty CaretPostionPropertyKey =
1683             DependencyProperty.Register("CaretPostion", typeof(TextPoint), typeof(FooTextBox), new PropertyMetadata(new TextPoint(), OnPropertyChanged));
1684
1685         /// <summary>
1686         /// レタリング方向を表す
1687         /// </summary>
1688         public new FlowDirection FlowDirection
1689         {
1690             get { return (FlowDirection)GetValue(FlowDirectionProperty); }
1691             set { SetValue(FlowDirectionProperty, value); }
1692         }
1693
1694         /// <summary>
1695         /// レタリング方向を表す。これは依存プロパティです
1696         /// </summary>
1697         public new static readonly DependencyProperty FlowDirectionProperty =
1698             DependencyProperty.Register("FlowDirection", typeof(FlowDirection), typeof(FooTextBox), new PropertyMetadata(FlowDirection.LeftToRight,OnPropertyChanged));
1699
1700         /// <summary>
1701         /// フォントファミリーを表す
1702         /// </summary>
1703         public new FontFamily FontFamily
1704         {
1705             get { return (FontFamily)GetValue(FontFamilyProperty); }
1706             set { SetValue(FontFamilyProperty, value); }
1707         }
1708
1709         /// <summary>
1710         /// FontFamilyの依存プロパティを表す
1711         /// </summary>
1712         public new static readonly DependencyProperty FontFamilyProperty =
1713             DependencyProperty.Register("FontFamily", typeof(FontFamily), typeof(FooTextBox), new PropertyMetadata(new FontFamily("Cambria"), OnPropertyChanged));
1714
1715         /// <summary>
1716         /// フォントサイズを表す
1717         /// </summary>
1718         public new double FontSize
1719         {
1720             get { return (double)GetValue(FontSizeProperty); }
1721             set { SetValue(FontSizeProperty, value); }
1722         }
1723
1724         /// <summary>
1725         /// FontSizeの依存プロパティを表す
1726         /// </summary>
1727         public new static readonly DependencyProperty FontSizeProperty =
1728             DependencyProperty.Register("FontSize", typeof(double), typeof(FooTextBox), new PropertyMetadata(12.0,OnPropertyChanged));
1729
1730         /// <summary>
1731         /// フォントスタイルを表す
1732         /// </summary>
1733         public new FontStyle FontStyle
1734         {
1735             get { return (FontStyle)GetValue(FontStyleProperty); }
1736             set { SetValue(FontStyleProperty, value); }
1737         }
1738
1739         /// <summary>
1740         /// FontStyleの依存プロパティを表す
1741         /// </summary>
1742         public new static readonly DependencyProperty FontStyleProperty =
1743             DependencyProperty.Register("FontStyle", typeof(FontStyle), typeof(FooTextBox), new PropertyMetadata(FontStyle.Normal,OnPropertyChanged));
1744
1745         /// <summary>
1746         /// フォントの幅を表す
1747         /// </summary>
1748         public new FontWeight FontWeight
1749         {
1750             get { return (FontWeight)GetValue(FontWeightProperty); }
1751             set { SetValue(FontWeightProperty, value); }
1752         }
1753
1754         /// <summary>
1755         /// FontWeigthの依存プロパティを表す
1756         /// </summary>
1757         public new static readonly DependencyProperty FontWeightProperty =
1758             DependencyProperty.Register("FontWeigth", typeof(FontWeight), typeof(FooTextBox), new PropertyMetadata(FontWeights.Normal,OnPropertyChanged));
1759
1760         /// <summary>
1761         /// デフォルトの文字色を表す。これは依存プロパティです
1762         /// </summary>
1763         public new Windows.UI.Color Foreground
1764         {
1765             get { return (Windows.UI.Color)GetValue(ForegroundProperty); }
1766             set { SetValue(ForegroundProperty, value); }
1767         }
1768
1769         /// <summary>
1770         /// Foregroundの依存プロパティを表す
1771         /// </summary>
1772         public new static readonly DependencyProperty ForegroundProperty =
1773             DependencyProperty.Register("Foreground", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Black, OnPropertyChanged));
1774
1775         /// <summary>
1776         /// 選択時の文字色を表す。これは依存プロパティです
1777         /// </summary>
1778         public Windows.UI.Color HilightForeground
1779         {
1780             get { return (Windows.UI.Color)GetValue(HilightForegroundProperty); }
1781             set { SetValue(HilightForegroundProperty, value); }
1782         }
1783
1784         /// <summary>
1785         /// HilightForegroundForegroundの依存プロパティを表す
1786         /// </summary>
1787         public static readonly DependencyProperty HilightForegroundProperty =
1788             DependencyProperty.Register("HilightForeground", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.White, OnPropertyChanged));
1789
1790         /// <summary>
1791         /// 背景色を表す。これは依存プロパティです
1792         /// </summary>
1793         public new Windows.UI.Color Background
1794         {
1795             get { return (Windows.UI.Color)GetValue(BackgroundProperty); }
1796             set { SetValue(BackgroundProperty, value); }
1797         }
1798
1799         /// <summary>
1800         /// Backgroundの依存プロパティを表す
1801         /// </summary>
1802         public new static readonly DependencyProperty BackgroundProperty =
1803             DependencyProperty.Register("Background", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.White, OnPropertyChanged));
1804
1805         /// <summary>
1806         /// コントロールコードの文字色を表す。これは依存プロパティです
1807         /// </summary>
1808         public Windows.UI.Color ControlChar
1809         {
1810             get { return (Windows.UI.Color)GetValue(ControlCharProperty); }
1811             set { SetValue(ControlCharProperty, value); }
1812         }
1813
1814         /// <summary>
1815         /// ControlCharの依存プロパティを表す
1816         /// </summary>
1817         public static readonly DependencyProperty ControlCharProperty =
1818             DependencyProperty.Register("ControlChar", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Gray, OnPropertyChanged));
1819
1820         /// <summary>
1821         /// 選択時の背景色を表す。これは依存プロパティです
1822         /// </summary>
1823         public Windows.UI.Color Hilight
1824         {
1825             get { return (Windows.UI.Color)GetValue(HilightProperty); }
1826             set { SetValue(HilightProperty, value); }
1827         }
1828
1829         /// <summary>
1830         /// Hilightの依存プロパティを表す
1831         /// </summary>
1832         public static readonly DependencyProperty HilightProperty =
1833             DependencyProperty.Register("Hilight", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.DodgerBlue, OnPropertyChanged));
1834
1835         /// <summary>
1836         /// キーワード1の文字色を表す。これは依存プロパティです
1837         /// </summary>
1838         public Windows.UI.Color Keyword1
1839         {
1840             get { return (Windows.UI.Color)GetValue(Keyword1Property); }
1841             set { SetValue(Keyword1Property, value); }
1842         }
1843
1844         /// <summary>
1845         /// Keyword1の依存プロパティを表す
1846         /// </summary>
1847         public static readonly DependencyProperty Keyword1Property =
1848             DependencyProperty.Register("Keyword1", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Blue, OnPropertyChanged));
1849
1850         /// <summary>
1851         /// キーワード2の文字色を表す。これは依存プロパティです
1852         /// </summary>
1853         public Windows.UI.Color Keyword2
1854         {
1855             get { return (Windows.UI.Color)GetValue(Keyword2Property); }
1856             set { SetValue(Keyword2Property, value); }
1857         }
1858
1859         /// <summary>
1860         /// Keyword2の依存プロパティを表す
1861         /// </summary>
1862         public static readonly DependencyProperty Keyword2Property =
1863             DependencyProperty.Register("Keyword2", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.DarkCyan, OnPropertyChanged));
1864
1865         /// <summary>
1866         /// コメントの文字色を表す。これは依存プロパティです
1867         /// </summary>
1868         public Windows.UI.Color Comment
1869         {
1870             get { return (Windows.UI.Color)GetValue(CommentProperty); }
1871             set { SetValue(CommentProperty, value); }
1872         }
1873
1874         /// <summary>
1875         /// Commentの依存プロパティを表す
1876         /// </summary>
1877         public static readonly DependencyProperty CommentProperty =
1878             DependencyProperty.Register("Comment", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Green, OnPropertyChanged));
1879
1880         /// <summary>
1881         /// 文字リテラルの文字色を表す。これは依存プロパティです
1882         /// </summary>
1883         public Windows.UI.Color Literal
1884         {
1885             get { return (Windows.UI.Color)GetValue(LiteralProperty); }
1886             set { SetValue(LiteralProperty, value); }
1887         }
1888
1889         /// <summary>
1890         /// Literalの依存プロパティを表す
1891         /// </summary>
1892         public static readonly DependencyProperty LiteralProperty =
1893             DependencyProperty.Register("Literal", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Brown, OnPropertyChanged));
1894
1895         /// <summary>
1896         /// URLの文字色を表す。これは依存プロパティです
1897         /// </summary>
1898         public Windows.UI.Color URL
1899         {
1900             get { return (Windows.UI.Color)GetValue(URLProperty); }
1901             set { SetValue(URLProperty, value); }
1902         }
1903
1904         /// <summary>
1905         /// URLの依存プロパティを表す
1906         /// </summary>
1907         public static readonly DependencyProperty URLProperty =
1908             DependencyProperty.Register("URL", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Blue, OnPropertyChanged));
1909
1910         /// <summary>
1911         /// 行更新フラグの色を表す
1912         /// </summary>
1913         public Windows.UI.Color UpdateArea
1914         {
1915             get { return (Windows.UI.Color)GetValue(UpdateAreaProperty); }
1916             set { SetValue(UpdateAreaProperty, value); }
1917         }
1918
1919         /// <summary>
1920         /// UpdateAreaの依存プロパティを表す
1921         /// </summary>
1922         public static readonly DependencyProperty UpdateAreaProperty =
1923             DependencyProperty.Register("UpdateArea", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.MediumSeaGreen, OnPropertyChanged));
1924
1925         /// <summary>
1926         /// ラインマーカーの色を表す
1927         /// </summary>
1928         public Windows.UI.Color LineMarker
1929         {
1930             get { return (Windows.UI.Color)GetValue(LineMarkerProperty); }
1931             set { SetValue(LineMarkerProperty, value); }
1932         }
1933
1934         /// <summary>
1935         /// LineMarkerの依存プロパティを表す
1936         /// </summary>
1937         public static readonly DependencyProperty LineMarkerProperty =
1938             DependencyProperty.Register("LineMarker", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Gray, OnPropertyChanged));
1939
1940         /// <summary>
1941         /// 挿入モード時のキャレットの色を表す
1942         /// </summary>
1943         public Windows.UI.Color InsertCaret
1944         {
1945             get { return (Windows.UI.Color)GetValue(InsertCaretProperty); }
1946             set { SetValue(InsertCaretProperty, value); }
1947         }
1948
1949         /// <summary>
1950         /// InsertCaretの依存プロパティを表す
1951         /// </summary>
1952         public static readonly DependencyProperty InsertCaretProperty =
1953             DependencyProperty.Register("InsertCaret", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Black, OnPropertyChanged));
1954
1955         /// <summary>
1956         /// 上書きモード時のキャレット職を表す
1957         /// </summary>
1958         public Windows.UI.Color OverwriteCaret
1959         {
1960             get { return (Windows.UI.Color)GetValue(OverwriteCaretProperty); }
1961             set { SetValue(OverwriteCaretProperty, value); }
1962         }
1963
1964         /// <summary>
1965         /// OverwriteCaretの依存プロパティを表す
1966         /// </summary>
1967         public static readonly DependencyProperty OverwriteCaretProperty =
1968             DependencyProperty.Register("OverwriteCaret", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.Black, OnPropertyChanged));
1969
1970         /// <summary>
1971         /// 行番号の色を表す
1972         /// </summary>
1973         public Windows.UI.Color LineNumber
1974         {
1975             get { return (Windows.UI.Color)GetValue(LineNumberProperty); }
1976             set { SetValue(LineNumberProperty, value); }
1977         }
1978
1979         /// <summary>
1980         /// Using a DependencyProperty as the backing store for LineNumber.  This enables animation, styling, binding, etc...
1981         /// </summary>
1982         public static readonly DependencyProperty LineNumberProperty =
1983             DependencyProperty.Register("LineNumber", typeof(Windows.UI.Color), typeof(FooTextBox), new PropertyMetadata(Colors.DimGray,OnPropertyChanged));
1984
1985         /// <summary>
1986         /// 余白を表す
1987         /// </summary>
1988         public new Thickness Padding
1989         {
1990             get { return (Thickness)GetValue(PaddingProperty); }
1991             set { SetValue(PaddingProperty, value); }
1992         }
1993
1994         /// <summary>
1995         /// Paddingの依存プロパティを表す
1996         /// </summary>
1997         public new static readonly DependencyProperty PaddingProperty =
1998             DependencyProperty.Register("Padding", typeof(Thickness), typeof(FooTextBox), new PropertyMetadata(new Thickness(),OnPropertyChanged));        
1999
2000         /// <summary>
2001         /// 挿入モードなら真を返し、そうでないなら、偽を返す。これは依存プロパティです
2002         /// </summary>
2003         public bool InsertMode
2004         {
2005             get { return (bool)GetValue(InsertModeProperty); }
2006             set { SetValue(InsertModeProperty, value); }
2007         }
2008
2009         /// <summary>
2010         /// InsertModeの依存プロパティを表す
2011         /// </summary>
2012         public static readonly DependencyProperty InsertModeProperty =
2013             DependencyProperty.Register("InsertMode",
2014             typeof(bool),
2015             typeof(FooTextBox),
2016             new PropertyMetadata(true, OnPropertyChanged));
2017
2018         /// <summary>
2019         /// タブの文字数を表す。これは依存プロパティです
2020         /// </summary>
2021         public int TabChars
2022         {
2023             get { return (int)GetValue(TabCharsProperty); }
2024             set { SetValue(TabCharsProperty, value); }
2025         }
2026
2027         /// <summary>
2028         /// TabCharsの依存プロパティを表す
2029         /// </summary>
2030         public static readonly DependencyProperty TabCharsProperty =
2031             DependencyProperty.Register("TabChars",
2032             typeof(int),
2033             typeof(FooTextBox),
2034             new PropertyMetadata(4, OnPropertyChanged));
2035
2036         /// <summary>
2037         /// 矩形選択モードなら真を返し、そうでないなら偽を返す。これは依存プロパティです
2038         /// </summary>
2039         public bool RectSelectMode
2040         {
2041             get { return (bool)GetValue(RectSelectModeProperty); }
2042             set { SetValue(RectSelectModeProperty, value); }
2043         }
2044
2045         /// <summary>
2046         /// RectSelectModeの依存プロパティを表す
2047         /// </summary>
2048         public static readonly DependencyProperty RectSelectModeProperty =
2049             DependencyProperty.Register("RectSelectMode", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2050
2051         /// <summary>
2052         /// 折り返しの方法を指定する
2053         /// </summary>
2054         /// <remarks>
2055         /// 変更した場合、レイアウトの再構築を行う必要があります
2056         /// </remarks>
2057         public LineBreakMethod LineBreakMethod
2058         {
2059             get { return (LineBreakMethod)GetValue(LineBreakProperty); }
2060             set { SetValue(LineBreakProperty, value); }
2061         }
2062
2063         /// <summary>
2064         /// LineBreakMethodの依存プロパティを表す
2065         /// </summary>
2066         public static readonly DependencyProperty LineBreakProperty =
2067             DependencyProperty.Register("LineBreakMethod", typeof(LineBreakMethod), typeof(FooTextBox), new PropertyMetadata(LineBreakMethod.None, OnPropertyChanged));
2068
2069
2070         /// <summary>
2071         /// 折り返しの幅を指定する。LineBreakMethod.CharUnit以外の時は無視されます
2072         /// </summary>
2073         /// <remarks>
2074         /// 変更した場合、レイアウトの再構築を行う必要があります
2075         /// </remarks>
2076         public int LineBreakCharCount
2077         {
2078             get { return (int)GetValue(LineBreakCharCountProperty); }
2079             set { SetValue(LineBreakCharCountProperty, value); }
2080         }
2081
2082         /// <summary>
2083         /// LineBreakCharCountの依存プロパティを表す
2084         /// </summary>
2085         public static readonly DependencyProperty LineBreakCharCountProperty =
2086             DependencyProperty.Register("LineBreakCharCount", typeof(int), typeof(FooTextBox), new PropertyMetadata(80, OnPropertyChanged));        
2087
2088         /// <summary>
2089         /// キャレットを描くなら真。そうでないなら偽を返す。これは依存プロパティです
2090         /// </summary>
2091         public bool DrawCaret
2092         {
2093             get { return (bool)GetValue(DrawCaretProperty); }
2094             set { SetValue(DrawCaretProperty, value); }
2095         }
2096
2097         /// <summary>
2098         /// DrawCaretの依存プロパティを表す
2099         /// </summary>
2100         public static readonly DependencyProperty DrawCaretProperty =
2101             DependencyProperty.Register("DrawCaret", typeof(bool), typeof(FooTextBox), new PropertyMetadata(true, OnPropertyChanged));
2102
2103
2104         /// <summary>
2105         /// キャレットラインを描くなら真。そうでないなら偽を返す。これは依存プロパティです
2106         /// </summary>
2107         public bool DrawCaretLine
2108         {
2109             get { return (bool)GetValue(DrawCaretLineProperty); }
2110             set { SetValue(DrawCaretLineProperty, value); }
2111         }
2112
2113         /// <summary>
2114         /// DrawCaretLineの依存プロパティを表す
2115         /// </summary>
2116         public static readonly DependencyProperty DrawCaretLineProperty =
2117             DependencyProperty.Register("DrawCaretLine", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2118
2119         /// <summary>
2120         /// 行番号を描くなら真。そうでなければ偽。これは依存プロパティです
2121         /// </summary>
2122         public bool DrawLineNumber
2123         {
2124             get { return (bool)GetValue(DrawLineNumberProperty); }
2125             set { SetValue(DrawLineNumberProperty, value); }
2126         }
2127
2128         /// <summary>
2129         /// ルーラーを描くなら真。そうでなければ偽。これは依存プロパティです
2130         /// </summary>
2131         public bool DrawRuler
2132         {
2133             get { return (bool)GetValue(DrawRulerProperty); }
2134             set { SetValue(DrawRulerProperty, value); }
2135         }
2136
2137         /// <summary>
2138         /// DrawRulerの依存プロパティを表す
2139         /// </summary>
2140         public static readonly DependencyProperty DrawRulerProperty =
2141             DependencyProperty.Register("DrawRuler", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2142
2143
2144         /// <summary>
2145         /// DrawLineNumberの依存プロパティを表す
2146         /// </summary>
2147         public static readonly DependencyProperty DrawLineNumberProperty =
2148             DependencyProperty.Register("DrawLineNumber", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2149
2150         /// <summary>
2151         /// URLに下線を引くなら真。そうでないなら偽を表す。これは依存プロパティです
2152         /// </summary>
2153         public bool MarkURL
2154         {
2155             get { return (bool)GetValue(MarkURLProperty); }
2156             set { SetValue(MarkURLProperty, value); }
2157         }
2158
2159         /// <summary>
2160         /// MarkURLの依存プロパティを表す
2161         /// </summary>
2162         public static readonly DependencyProperty MarkURLProperty =
2163             DependencyProperty.Register("MarkURL", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2164
2165         /// <summary>
2166         /// 全角スペースを表示するなら真。そうでないなら偽
2167         /// </summary>
2168         public bool ShowFullSpace
2169         {
2170             get { return (bool)GetValue(ShowFullSpaceProperty); }
2171             set { SetValue(ShowFullSpaceProperty, value); }
2172         }
2173
2174         /// <summary>
2175         /// ShowFullSpaceの依存プロパティを表す
2176         /// </summary>
2177         public static readonly DependencyProperty ShowFullSpaceProperty =
2178             DependencyProperty.Register("ShowFullSpace", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2179
2180         /// <summary>
2181         /// 半角スペースを表示するなら真。そうでないなら偽
2182         /// </summary>
2183         public bool ShowHalfSpace
2184         {
2185             get { return (bool)GetValue(ShowHalfSpaceProperty); }
2186             set { SetValue(ShowHalfSpaceProperty, value); }
2187         }
2188
2189         /// <summary>
2190         /// ShowHalfSpaceの依存プロパティを表す
2191         /// </summary>
2192         public static readonly DependencyProperty ShowHalfSpaceProperty =
2193             DependencyProperty.Register("ShowHalfSpace", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2194
2195         /// <summary>
2196         /// タブを表示するなら真。そうでないなら偽
2197         /// </summary>
2198         public bool ShowTab
2199         {
2200             get { return (bool)GetValue(ShowTabProperty); }
2201             set { SetValue(ShowTabProperty, value); }
2202         }
2203
2204         /// <summary>
2205         /// ShowTabの依存プロパティを表す
2206         /// </summary>
2207         public static readonly DependencyProperty ShowTabProperty =
2208             DependencyProperty.Register("ShowTab", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false, OnPropertyChanged));
2209
2210         /// <summary>
2211         /// 改行マークを表示するなら真。そうでないなら偽
2212         /// </summary>
2213         public bool ShowLineBreak
2214         {
2215             get { return (bool)GetValue(ShowLineBreakProperty); }
2216             set { SetValue(ShowLineBreakProperty, value); }
2217         }
2218
2219         /// <summary>
2220         /// ShowLineBreakの依存プロパティを表す
2221         /// </summary>
2222         public static readonly DependencyProperty ShowLineBreakProperty =
2223             DependencyProperty.Register("ShowLineBreak", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false,OnPropertyChanged));
2224
2225         
2226 #endregion
2227     }
2228     /// <summary>
2229     /// コンテキストメニューのイベントデーターを表す
2230     /// </summary>
2231     public class FooContextMenuEventArgs
2232     {
2233         /// <summary>
2234         /// 処理済みなら真。そうでないなら偽
2235         /// </summary>
2236         public bool Handled = false;
2237         /// <summary>
2238         /// コンテキストメニューを表示すべき座標を表す
2239         /// </summary>
2240         public Windows.Foundation.Point Postion;
2241         /// <summary>
2242         /// コンストラクター
2243         /// </summary>
2244         /// <param name="pos"></param>
2245         public FooContextMenuEventArgs(Windows.Foundation.Point pos)
2246         {
2247             this.Postion = pos;
2248         }
2249     }
2250 }