OSDN Git Service

DrawLineNumberでしていることは同じなのでコントローラーに書くことにした
[fooeditengine/FooEditEngine.git] / Windows / FooEditEngine / 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 using System;
12 using System.Text;
13 using System.Threading;
14 using System.Threading.Tasks;
15 using System.Windows.Forms;
16 using System.Drawing;
17 using System.ComponentModel;
18 using Microsoft.Win32;
19
20 namespace FooEditEngine.Windows
21 {
22     /// <summary>
23     /// タブの幅が変更されたときに呼びされるデリゲート
24     /// </summary>
25     /// <param name="sender">送り主が属するクラス</param>
26     /// <param name="e">イベントデータ</param>
27     public delegate void TabStopChangeEventHandler(object sender, EventArgs e);
28
29     /// <summary>
30     /// InsetModeが変更されたときに呼び出されるデリゲート
31     /// </summary>
32     /// <param name="sender">送り主が属するクラス</param>
33     /// <param name="e">イベントデータ</param>
34     public delegate void InsertModeChangeEventHandler(object sender, EventArgs e);
35
36     /// <summary>
37     /// FooEditEngineを表します
38     /// </summary>
39     public class FooTextBox : Control
40     {
41         EditView View;
42         Controller Controller;
43         D2DTextRender render;
44         BorderStyle _BoderStyle;
45         HScrollBar HScrollBar;
46         VScrollBar VScrollBar;
47         WinIME Ime;
48         System.Windows.Forms.Timer Timer;
49
50         const int Interval = 100;
51
52         /// <summary>
53         /// コンストラクター
54         /// </summary>
55         public FooTextBox()
56         {
57             this.VScrollBar = new VScrollBar();
58             this.VScrollBar.Scroll += new ScrollEventHandler(VScrollBar_Scroll);
59             this.VScrollBar.Dock = DockStyle.Right;
60             this.VScrollBar.Visible = true;
61             this.Controls.Add(this.VScrollBar);
62
63             this.HScrollBar = new HScrollBar();
64             this.HScrollBar.Scroll += new ScrollEventHandler(HScrollBar_Scroll);
65             this.HScrollBar.Dock = DockStyle.Bottom;
66             this.HScrollBar.Visible = true;
67             this.Controls.Add(this.HScrollBar);
68
69             this.SetStyle(ControlStyles.ResizeRedraw, true);
70             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
71             this.SetStyle(ControlStyles.UserPaint, true);
72             this.SetStyle(ControlStyles.Opaque, true);
73
74             this.render = new D2DTextRender(this);
75             this.Document = new Document();
76             this.Document.LayoutLines.Render = this.render;
77             this.View = new EditView(this.Document, this.render, new FooEditEngine.Padding(5, 5, 5, 5));
78             this.View.SrcChanged += View_SrcChanged;
79             
80             this.Controller = new Controller(this.Document, this.View);
81             this.Controller.SelectionChanged += new EventHandler(Controller_CaretMoved);
82
83             this.Ime = new WinIME(this);
84             this.Ime.ImeCompstion += new ImeCompstionEventHandeler(Ime_ImeCompstion);
85             this.Ime.StartCompstion += new StartCompstionEventHandeler(Ime_StartCompstion);
86             this.Ime.EndCompstion += new EndCompstionEventHandeler(Ime_EndCompstion);
87             this.Ime.ImeDocumentFeed += new ImeDocumentFeedEventHandler(Ime_ImeDocumentFeed);
88             this.Ime.ImeReconvert += new ImeReconvertStringEventHandler(Ime_ImeReconvert);
89             this.Ime.ImeQueryReconvert += new ImeQueryReconvertStringEventHandler(Ime_ImeQueryReconvert);
90
91             this.Timer = new System.Windows.Forms.Timer();
92             this.Timer.Tick += new EventHandler(this.Timer_Tick);
93             this.Timer.Interval = Interval;
94             this.SetSystemParamaters();
95
96             this.TabStopChange += new TabStopChangeEventHandler((s, e) => { });
97             this.InsetModeChange += new InsertModeChangeEventHandler((s, e) => { });
98             this.SelectionChanged +=new EventHandler((s,e)=>{});
99
100             this.RightToLeftChanged += FooTextBox_RightToLeftChanged;
101
102             SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
103
104         }
105
106         /// <summary>
107         /// キャレットが移動したときに通知されるイベント
108         /// </summary>
109         public event EventHandler SelectionChanged;
110
111         /// <summary>
112         /// タブの幅が変更された時に発生するイベント
113         /// </summary>
114         public event TabStopChangeEventHandler TabStopChange;
115
116         /// <summary>
117         /// InsertModeが変更されたときに呼び出されるイベント
118         /// </summary>
119         public event InsertModeChangeEventHandler InsetModeChange;
120
121         /// <summary>
122         /// インデントモードを表す
123         /// </summary>
124         [DefaultValue(IndentMode.Tab)]
125         public IndentMode IndentMode
126         {
127             get
128             {
129                 return this.Controller.IndentMode;
130             }
131             set
132             {
133                 this.Controller.IndentMode = value;
134             }
135         }
136
137         /// <summary>
138         /// テキスト描写に使用するアンチエイリアシングモードを表す
139         /// </summary>
140         [BrowsableAttribute(false)]
141         public TextAntialiasMode TextAntialiasMode
142         {
143             get
144             {
145                 return this.render.TextAntialiasMode;
146             }
147             set
148             {
149                 this.render.TextAntialiasMode = value;
150             }
151         }
152
153         /// <summary>
154         /// マーカーパターンセットを表す
155         /// </summary>
156         [BrowsableAttribute(false)]
157         public MarkerPatternSet MarkerPatternSet
158         {
159             get
160             {
161                 return this.Document.MarkerPatternSet;
162             }
163         }
164
165         /// <summary>
166         /// 保持しているドキュメント
167         /// </summary>
168         [BrowsableAttribute(false)]
169         public Document Document
170         {
171             get;
172             private set;
173         }
174
175         /// <summary>
176         /// 保持しているレイアウト行
177         /// </summary>
178         [BrowsableAttribute(false)]
179         public LineToIndexTable LayoutLines
180         {
181             get { return this.View.LayoutLines; }
182         }
183
184         /// <summary>
185         /// シンタックスハイライター
186         /// </summary>
187         [BrowsableAttribute(false)]
188         public IHilighter Hilighter
189         {
190             get { return this.View.Hilighter; }
191             set { this.View.Hilighter = value; this.View.LayoutLines.ClearLayoutCache(); }
192         }
193
194         /// <summary>
195         /// フォールティングを作成するインターフェイスを表す
196         /// </summary>
197         [BrowsableAttribute(false)]
198         public IFoldingStrategy FoldingStrategy
199         {
200             get
201             {
202                 return this.View.LayoutLines.FoldingStrategy;
203             }
204             set
205             {
206                 this.View.LayoutLines.FoldingStrategy = value;
207                 if (value == null)
208                     this.View.LayoutLines.FoldingCollection.Clear();
209             }
210         }
211
212         /// <summary>
213         /// 境界線のスタイルを指定します
214         /// </summary>
215         public BorderStyle BorderStyle
216         {
217             get { return this._BoderStyle; }
218             set { this._BoderStyle = value; this.UpdateStyles(); }
219         }
220
221
222         /// <summary>
223         /// 行番号を表示するかどうか
224         /// </summary>
225         [DefaultValue(false)]
226         public bool DrawLineNumber
227         {
228             get
229             {
230                 return this.Document.DrawLineNumber;
231             }
232             set
233             {
234                 this.Document.DrawLineNumber = value;
235             }
236         }
237         
238         /// <summary>
239         /// ルーラーを表示するかどうか
240         /// </summary>
241         [DefaultValue(false)]
242         public bool DrawRuler
243         {
244             get
245             {
246                 return !this.Document.HideRuler;
247             }
248             set
249             {
250                 this.Document.HideRuler = !value;
251                 this.JumpCaret(this.CaretPostion.row, this.CaretPostion.col);
252             }
253         }
254
255         /// <summary>
256         /// 桁折りを行う方法を指定する
257         /// </summary>
258         /// <remarks>
259         /// 反映させるためにはレイアウト行の再構築を行う必要があります
260         /// </remarks>
261         [DefaultValue(LineBreakMethod.None)]
262         public LineBreakMethod LineBreakMethod
263         {
264             get
265             {
266                 return this.Document.LineBreak;
267             }
268             set
269             {
270                 this.Document.LineBreak = value;
271             }
272         }
273
274         /// <summary>
275         /// 桁折り時の文字数を指定する。
276         /// </summary>
277         /// <remarks>
278         /// 反映させるためにはレイアウト行の再構築を行う必要があります
279         /// </remarks>
280         [DefaultValue(80)]
281         public int LineBreakCharCount
282         {
283             get
284             {
285                 return this.Document.LineBreakCharCount;
286             }
287             set
288             {
289                 this.Document.LineBreakCharCount = value;
290             }
291         }
292
293         /// <summary>
294         /// URLをマークするかどうか
295         /// </summary>
296         [DefaultValue(false)]
297         public bool UrlMark
298         {
299             get
300             {
301                 return this.Document.UrlMark;
302             }
303             set
304             {
305                 this.Document.UrlMark = value;
306             }
307         }
308
309         /// <summary>
310         /// タブストップの幅
311         /// </summary>
312         [DefaultValue(4)]
313         public int TabStops
314         {
315             get { return this.Document.TabStops; }
316             set {
317                 this.Document.TabStops = value;
318                 this.View.AdjustCaretAndSrc();
319                 this.TabStopChange(this, null);
320             }
321         }
322
323         /// <summary>
324         /// 全角スペースを表示するなら真。そうでないなら偽
325         /// </summary>
326         [DefaultValue(false)]
327         public bool ShowFullSpace
328         {
329             get
330             {
331                 return this.Document.ShowFullSpace;
332             }
333             set
334             {
335                 this.Document.ShowFullSpace = value;
336             }
337         }
338
339         /// <summary>
340         /// 半角スペースを表示するなら真。そうでないなら偽
341         /// </summary>
342         [DefaultValue(false)]
343         public bool ShowHalfSpace
344         {
345             get
346             {
347                 return this.Document.ShowHalfSpace;
348             }
349             set
350             {
351                 this.Document.ShowHalfSpace = value;
352             }
353         }
354
355         /// <summary>
356         /// タブを表示するなら真。そうでないなら偽
357         /// </summary>
358         [DefaultValue(false)]
359         public bool ShowTab
360         {
361             get
362             {
363                 return this.Document.ShowTab;
364             }
365             set
366             {
367                 this.Document.ShowTab = value;
368             }
369         }
370
371         /// <summary>
372         /// 改行マークを表示するなら真。そうでないなら偽
373         /// </summary>
374         [DefaultValue(false)]
375         public bool ShowLineBreak
376         {
377             get
378             {
379                 return this.Document.ShowLineBreak;
380             }
381             set
382             {
383                 this.Document.ShowLineBreak = value;
384             }
385         }
386
387         /// <summary>
388         /// 選択中の文字列
389         /// </summary>
390         /// <remarks>
391         /// 未選択状態で文字列を代入した場合、キャレット位置に挿入され、そうでないときは置き換えられます。
392         /// </remarks>
393         [BrowsableAttribute(false)]
394         public string SelectedText
395         {
396             get { return this.Controller.SelectedText; }
397             set { this.Controller.SelectedText = value; }
398         }
399
400         /// <summary>
401         /// キャレット位置を表す
402         /// </summary>
403         [BrowsableAttribute(false)]
404         public TextPoint CaretPostion
405         {
406             get { return this.Document.CaretPostion; }
407         }
408
409         /// <summary>
410         /// 選択範囲を表す
411         /// </summary>
412         /// <remarks>
413         /// Lengthが0の場合はキャレット位置を表します
414         /// 矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります
415         /// </remarks>
416         [BrowsableAttribute(false)]
417         public TextRange Selection
418         {
419             get { return new TextRange(this.Controller.SelectionStart,this.Controller.SelectionLength); }
420             set
421             {
422                 this.Controller.Select(value.Index, value.Length);
423             }
424         }
425
426         /// <summary>
427         /// 挿入モードかどうか
428         /// </summary>
429         [DefaultValue(true)]
430         public bool InsertMode
431         {
432             get { return this.View.InsertMode; }
433             set
434             {
435                 this.View.InsertMode = value;
436                 this.InsetModeChange(this, null);
437             }
438         }
439
440         /// <summary>
441         /// 矩形選択を行うかどうか
442         /// </summary>
443         [DefaultValue(false)]
444         public bool RectSelection
445         {
446             get { return this.Controller.RectSelection; }
447             set { this.Controller.RectSelection = value; }
448         }
449
450         System.Drawing.Color ForegroundColor = SystemColors.ControlText,
451             BackgroundColor = SystemColors.Control,
452             HilightColor = System.Drawing.Color.DeepSkyBlue,
453             Keyword1Color = System.Drawing.Color.Blue,
454             Keyword2Color = System.Drawing.Color.DarkCyan,
455             LiteralColor = System.Drawing.Color.Brown,
456             UrlColor = System.Drawing.Color.Blue,
457             ControlCharColor = System.Drawing.Color.Gray,
458             CommentColor = System.Drawing.Color.Green,
459             InsertCaretColor = System.Drawing.Color.Black,
460             OverwriteCaretColor = System.Drawing.Color.Black,
461             LineMarkerColor = System.Drawing.Color.WhiteSmoke,
462             UpdateAreaColor = System.Drawing.Color.MediumSeaGreen,
463             LineNumberColor = System.Drawing.Color.DimGray;
464
465         /// <summary>
466         /// 前景色
467         /// </summary>
468         public System.Drawing.Color Foreground
469         {
470             get
471             {
472                 return this.ForegroundColor;
473             }
474             set
475             {
476                 this.render.Foreground = D2DTextRender.ToColor4(value);
477                 this.ForegroundColor = value;
478             }
479         }
480
481         /// <summary>
482         /// 背景色
483         /// </summary>
484         public System.Drawing.Color Background
485         {
486             get
487             {
488                 return this.BackgroundColor;
489             }
490             set
491             {
492                 this.render.Background = D2DTextRender.ToColor4(value);
493                 this.BackgroundColor = value;
494             }
495         }
496
497         /// <summary>
498         /// 挿入モード時のキャレット色
499         /// </summary>
500         public System.Drawing.Color InsertCaret
501         {
502             get
503             {
504                 return this.InsertCaretColor;
505             }
506             set
507             {
508                 this.InsertCaretColor = value;
509                 this.render.InsertCaret = D2DTextRender.ToColor4(value);
510             }
511         }
512
513         /// <summary>
514         /// 上書きモード時のキャレット色
515         /// </summary>
516         public System.Drawing.Color OverwriteCaret
517         {
518             get
519             {
520                 return this.OverwriteCaretColor;
521             }
522             set
523             {
524                 this.OverwriteCaretColor = value;
525                 this.render.OverwriteCaret = D2DTextRender.ToColor4(value);
526             }
527         }
528
529         /// <summary>
530         /// ラインマーカーの色
531         /// </summary>
532         public System.Drawing.Color LineMarker
533         {
534             get
535             {
536                 return this.LineMarkerColor;
537             }
538             set
539             {
540                 this.LineMarkerColor = value;
541                 this.render.LineMarker = D2DTextRender.ToColor4(value);
542             }
543         }
544
545         /// <summary>
546         /// コントロールの色
547         /// </summary>
548         public System.Drawing.Color ControlChar
549         {
550             get
551             {
552                 return this.ControlCharColor;
553             }
554             set
555             {
556                 this.ControlCharColor = value;
557                 this.render.ControlChar = D2DTextRender.ToColor4(value);
558             }
559         }
560
561         /// <summary>
562         /// 編集行フラグの色
563         /// </summary>
564         public System.Drawing.Color UpdateArea
565         {
566             get
567             {
568                 return this.UpdateAreaColor;
569             }
570             set
571             {
572                 this.UpdateAreaColor = value;
573                 this.render.UpdateArea = D2DTextRender.ToColor4(value);
574             }
575         }
576
577         /// <summary>
578         /// 行番号の色
579         /// </summary>
580         public System.Drawing.Color LineNumber
581         {
582             get
583             {
584                 return this.LineNumber;
585             }
586             set
587             {
588                 this.LineNumber = value;
589                 this.render.LineNumber = D2DTextRender.ToColor4(value);
590             }
591         }
592
593         /// <summary>
594         /// URLの色
595         /// </summary>
596         public System.Drawing.Color Url
597         {
598             get
599             {
600                 return this.UrlColor;
601             }
602             set
603             {
604                 this.UrlColor = value;
605                 this.render.Url = D2DTextRender.ToColor4(value);
606             }
607         }
608
609         /// <summary>
610         /// 選択領域の色
611         /// </summary>
612         public System.Drawing.Color Hilight
613         {
614             get
615             {
616                 return this.HilightColor;
617             }
618             set
619             {
620                 this.HilightColor = value;
621                 this.render.Hilight = D2DTextRender.ToColor4(value);
622             }
623         }
624
625         /// <summary>
626         /// コメントの色
627         /// </summary>
628         public System.Drawing.Color Comment
629         {
630             get
631             {
632                 return this.CommentColor;
633             }
634             set
635             {
636                 this.CommentColor = value;
637                 this.render.Comment = D2DTextRender.ToColor4(value);
638             }
639         }
640
641         /// <summary>
642         /// 文字リテラルの色
643         /// </summary>
644         public System.Drawing.Color Literal
645         {
646             get
647             {
648                 return this.LiteralColor;
649             }
650             set
651             {
652                 this.LiteralColor = value;
653                 this.render.Literal = D2DTextRender.ToColor4(value);
654             }
655         }
656
657         /// <summary>
658         /// キーワード1の色
659         /// </summary>
660         public System.Drawing.Color Keyword1
661         {
662             get
663             {
664                 return this.Keyword1Color;
665             }
666             set
667             {
668                 this.Keyword1Color = value;
669                 this.render.Keyword1 = D2DTextRender.ToColor4(value);
670             }
671         }
672
673         /// <summary>
674         /// キーワード2の色
675         /// </summary>
676         public System.Drawing.Color Keyword2
677         {
678             get
679             {
680                 return this.Keyword2Color;
681             }
682             set
683             {
684                 this.Keyword2Color = value;
685                 this.render.Keyword2 = D2DTextRender.ToColor4(value);
686             }
687         }
688
689         /// <summary>
690         /// キャレットに下線を描くかどうか
691         /// </summary>
692         [DefaultValue(false)]
693         public bool DrawCaretLine
694         {
695             get { return !this.View.HideLineMarker; }
696             set { this.View.HideLineMarker = !value; }
697         }
698
699         /// <summary>
700         /// ドキュメントを選択する
701         /// </summary>
702         /// <param name="start">開始インデックス</param>
703         /// <param name="length">長さ</param>
704         public void Select(int start, int length)
705         {
706             this.Controller.Select(start, length);
707             this.HScrollBar.Value = (int)this.View.Src.X;
708             this.VScrollBar.Value = this.View.Src.Row;
709         }
710
711         /// <summary>
712         /// ドキュメント全体を選択する
713         /// </summary>
714         public void SelectAll()
715         {
716             this.Controller.Select(0, this.Document.Length - 1);
717         }
718
719         /// <summary>
720         /// 選択を解除する
721         /// </summary>
722         public void DeSelectAll()
723         {
724             this.Controller.DeSelectAll();
725         }
726
727         /// <summary>
728         /// クリップボードにコピーする
729         /// </summary>
730         public void Copy()
731         {
732             string text = this.SelectedText;
733             if(text != null && text != string.Empty)
734                 Clipboard.SetText(text);
735         }
736
737         /// <summary>
738         /// クリップボードにコピーし、指定した範囲にある文字列をすべて削除します
739         /// </summary>
740         public void Cut()
741         {
742             string text = this.SelectedText;
743             if (text != null && text != string.Empty)
744             {
745                 Clipboard.SetText(text);
746                 this.Controller.SelectedText = "";
747             }
748         }
749
750         /// <summary>
751         /// クリップボードの内容をペーストします
752         /// </summary>
753         public void Paste()
754         {
755             if (Clipboard.ContainsText() == false)
756                 return;
757             this.Controller.SelectedText = Clipboard.GetText();
758         }
759
760         /// <summary>
761         /// キャレットを指定した行に移動させます
762         /// </summary>
763         /// <param name="index">インデックス</param>
764         /// <remarks>このメソッドを呼び出すと選択状態は解除されます</remarks>
765         public void JumpCaret(int index)
766         {
767             this.Controller.JumpCaret(index);
768         }
769         /// <summary>
770         /// キャレットを指定した行と桁に移動させます
771         /// </summary>
772         /// <param name="row">行番号</param>
773         /// <param name="col">桁</param>
774         /// <remarks>このメソッドを呼び出すと選択状態は解除されます</remarks>
775         public void JumpCaret(int row, int col)
776         {
777             this.Controller.JumpCaret(row, col);
778         }
779
780         /// <summary>
781         /// 再描写します
782         /// </summary>
783         public new void Refresh()
784         {
785             if (this.Document.FireUpdateEvent == false)
786                 throw new InvalidOperationException("");
787             if(this.View.CaretBlink)
788                 this.View.CaretBlink = true;
789             this.Invalidate();
790             this.Update();
791         }
792
793         /// <summary>
794         /// 行の高さを取得する
795         /// </summary>
796         /// <param name="row">行</param>
797         /// <returns>高さ</returns>
798         public double GetLineHeight(int row)
799         {
800             if (this.Document.FireUpdateEvent == false)
801                 throw new InvalidOperationException("");
802             return this.View.LayoutLines.GetLayout(row).Height;
803         }
804
805         /// <summary>
806         /// 対応する座標を返す
807         /// </summary>
808         /// <param name="tp">テキストポイント</param>
809         /// <returns>座標</returns>
810         /// <remarks>テキストポイントがクライアント領域の原点より外にある場合、返される値は原点に丸められます</remarks>
811         public System.Drawing.Point GetPostionFromTextPoint(TextPoint tp)
812         {
813             if (this.Document.FireUpdateEvent == false)
814                 throw new InvalidOperationException("");
815             return this.View.GetPostionFromTextPoint(tp);
816         }
817
818         /// <summary>
819         /// 対応するテキストポイントを返す
820         /// </summary>
821         /// <param name="p">クライアント領域の原点を左上とする座標</param>
822         /// <returns>テキストポイント</returns>
823         public TextPoint GetTextPointFromPostion(System.Drawing.Point p)
824         {
825             if (this.Document.FireUpdateEvent == false)
826                 throw new InvalidOperationException("");
827             return this.View.GetTextPointFromPostion(p);
828         }
829
830         /// <summary>
831         /// インデックスに対応する座標を得ます
832         /// </summary>
833         /// <param name="index">インデックス</param>
834         /// <returns>座標を返す</returns>
835         public System.Drawing.Point GetPostionFromIndex(int index)
836         {
837             if (this.Document.FireUpdateEvent == false)
838                 throw new InvalidOperationException("");
839             TextPoint tp = this.View.GetLayoutLineFromIndex(index);
840             return this.View.GetPostionFromTextPoint(tp);
841         }
842
843         /// <summary>
844         /// 座標からインデックスに変換します
845         /// </summary>
846         /// <param name="p">座標</param>
847         /// <returns>インデックスを返す</returns>
848         public int GetIndexFromPostion(System.Drawing.Point p)
849         {
850             if (this.Document.FireUpdateEvent == false)
851                 throw new InvalidOperationException("");
852             TextPoint tp = this.View.GetTextPointFromPostion(p);
853             return this.View.GetIndexFromLayoutLine(tp);
854         }
855
856         /// <summary>
857         /// レイアウト行をすべて破棄し、再度レイアウトを行う
858         /// </summary>
859         public void PerfomLayouts()
860         {
861             this.View.PerfomLayouts();
862             initScrollBars();
863         }
864
865         /// <summary>
866         /// ストリームからドキュメントを構築する
867         /// </summary>
868         /// <param name="tr">TextReader</param>
869         /// <param name="token">キャンセル用トークン</param>
870         /// <returns>Taskオブジェクト</returns>
871         public async Task LoadAsync(System.IO.TextReader tr, System.Threading.CancellationTokenSource token)
872         {
873             WinFileReader fs = new WinFileReader(tr);
874             await this.LoadAsyncImpl(fs, token);
875         }
876
877         /// <summary>
878         /// ファイルからドキュメントを構築する
879         /// </summary>
880         /// <param name="filepath">ファイルパス</param>
881         /// <param name="enc">エンコード</param>
882         /// <param name="token">キャンセル用トークン</param>
883         /// <returns>Taskオブジェクト</returns>
884         public async Task LoadFileAsync(string filepath, Encoding enc, System.Threading.CancellationTokenSource token)
885         {
886             WinFileReader fs = new WinFileReader(filepath, enc);
887             await this.LoadAsyncImpl(fs, token);
888             fs.Close();
889         }
890
891         async Task LoadAsyncImpl(WinFileReader fs, System.Threading.CancellationTokenSource token)
892         {
893             this.Enabled = false;
894             this.View.LayoutLines.IsFrozneDirtyFlag = true;
895             await this.Document.LoadAsync(fs, token);
896             this.View.LayoutLines.IsFrozneDirtyFlag = false;
897             this.initScrollBars();
898             this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, MousePosition.X, MousePosition.Y, 0));
899             this.View.CalculateLineCountOnScreen();
900             this.Enabled = true;
901         }
902
903         /// <summary>
904         /// ドキュメントの内容をファイルに保存する
905         /// </summary>
906         /// <param name="filepath">ファイルパス</param>
907         /// <param name="newLine">改行コード</param>
908         /// <param name="enc">エンコード</param>
909         /// <returns>Taskオブジェクト</returns>
910         public async Task SaveFile(string filepath, Encoding enc, string newLine, System.Threading.CancellationTokenSource token)
911         {
912             WinFileWriter fs = new WinFileWriter(filepath, enc);
913             fs.NewLine = newLine;
914             await this.Document.SaveAsync(fs, token);
915             fs.Close();
916         }
917
918         /// <summary>
919         /// マウスカーソルを指定します
920         /// </summary>
921         public override Cursor Cursor
922         {
923             get
924             {
925                 return base.Cursor;
926             }
927             set
928             {
929                 base.Cursor = value;
930                 this.VScrollBar.Cursor = DefaultCursor;
931                 this.HScrollBar.Cursor = DefaultCursor;
932             }
933         }
934
935         private const int WS_BORDER = 0x00800000;
936         private const int WS_EX_CLIENTEDGE = 0x00000200;
937         /// <summary>
938         /// コントロールの外観を指定します
939         /// </summary>
940         protected override CreateParams CreateParams
941         {
942             get
943             {
944                 CreateParams cp = base.CreateParams;
945                 switch (this.BorderStyle)
946                 {
947                     case BorderStyle.Fixed3D:
948                         cp.ExStyle |= WS_EX_CLIENTEDGE;
949                         break;
950                     case BorderStyle.FixedSingle:
951                         cp.Style |= WS_BORDER;
952                         break;
953                 }
954                 return cp;
955             }
956         }
957
958         /// <summary>
959         /// コマンド キーを処理します
960         /// </summary>
961         /// <param name="msg">メッセージ</param>
962         /// <param name="keyData">キーデータ</param>
963         /// <returns>文字がコントロールによって処理された場合は true。それ以外の場合は false。 </returns>
964         protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
965         {
966             const int WM_KEYDOWN = 0x100;
967             if (msg.Msg != WM_KEYDOWN)
968                 return base.ProcessCmdKey(ref msg, keyData);
969             switch (keyData)
970             {
971                 case Keys.Control | Keys.C:
972                     this.Copy();
973                     break;
974                 case Keys.Control | Keys.V:
975                     this.Paste();
976                     this.Refresh();
977                     break;
978                 case Keys.Control | Keys.X:
979                     this.Cut();
980                     this.Refresh();
981                     break;
982                 case Keys.Control | Keys.Z:
983                     this.Document.UndoManager.undo();
984                     this.Refresh();
985                     break;
986                 case Keys.Control | Keys.Y:
987                     this.Document.UndoManager.redo();
988                     this.Refresh();
989                     break;
990                 case Keys.Control | Keys.B:
991                     if (this.Controller.RectSelection)
992                         this.Controller.RectSelection = false;
993                     else
994                         this.Controller.RectSelection = true;
995                     break;
996                 default:
997                     return base.ProcessCmdKey(ref msg,keyData);
998             }
999             return true;
1000         }
1001
1002         /// <summary>
1003         /// インスタンスを破棄します
1004         /// </summary>
1005         /// <param name="disposing">マネージ リソースとアンマネージ リソースの両方を解放する場合は true。アンマネージ リソースだけを解放する場合は false。</param>
1006         protected override void Dispose(bool disposing)
1007         {
1008             SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(this.SystemEvents_UserPreferenceChanged);
1009             this.render.Dispose();
1010             this.Timer.Dispose();
1011             base.Dispose(disposing);
1012         }
1013
1014         /// <summary>
1015         /// 入力可能な文字かチェックします
1016         /// </summary>
1017         /// <param name="charCode">入力しようとした文字</param>
1018         /// <returns>可能なら真。そうでなければ偽</returns>
1019         protected override bool IsInputChar(char charCode)
1020         {
1021             if ((0x20 <= charCode && charCode <= 0x7e)
1022                 || charCode == '\r'
1023                 || charCode == '\n'
1024                 || charCode == ' '
1025                 || charCode == '\t'
1026                 || charCode == ' '
1027                 || 0x7f < charCode)
1028             {
1029                 return true;
1030             }
1031
1032             return false;
1033         }
1034
1035         /// <summary>
1036         /// PaddingChangedイベントを発生させます
1037         /// </summary>
1038         /// <param name="e">インベントデータ</param>
1039         protected override void OnPaddingChanged(EventArgs e)
1040         {
1041             base.OnPaddingChanged(e);
1042             this.View.Padding = new Padding(this.Padding.Left, this.Padding.Top, this.Padding.Right, this.Padding.Bottom);
1043         }
1044
1045         /// <summary>
1046         /// GotFocusイベントを発生させます
1047         /// </summary>
1048         /// <param name="e">インベントデータ</param>
1049         protected override void OnGotFocus(EventArgs e)
1050         {
1051             base.OnGotFocus(e);
1052             this.View.IsFocused = true;
1053             this.Refresh();
1054         }
1055
1056         /// <summary>
1057         /// LostFocusイベントを発生させます
1058         /// </summary>
1059         /// <param name="e">インベントデータ</param>
1060         protected override void OnLostFocus(EventArgs e)
1061         {
1062             base.OnLostFocus(e);
1063             this.View.IsFocused = false;
1064             this.Refresh();
1065         }
1066
1067         /// <summary>
1068         /// FontChangedイベントを発生させます
1069         /// </summary>
1070         /// <param name="e">インベントデータ</param>
1071         protected override void OnFontChanged(EventArgs e)
1072         {
1073             if (this.DesignMode)
1074                 return;
1075             base.OnFontChanged(e);
1076             initScrollBars();
1077         }
1078
1079         /// <summary>
1080         /// MouseDownイベントを発生させます
1081         /// </summary>
1082         /// <param name="e">インベントデータ</param>
1083         protected override void OnMouseDown(MouseEventArgs e)
1084         {
1085             TextPoint tp = this.View.GetTextPointFromPostion(e.Location);
1086             if (tp == TextPoint.Null)
1087                 return;
1088             int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);
1089             
1090             FooMouseEventArgs mouseEvent = new FooMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta);
1091             
1092             base.OnMouseDown(mouseEvent);
1093             
1094             if (mouseEvent.Handled)
1095                 return;
1096
1097             if (e.Button == MouseButtons.Left)
1098             {
1099                 FoldingItem foldingData = this.View.HitFoldingData(e.Location.X, tp.row);
1100                 if (foldingData != null)
1101                 {
1102                     if (foldingData.Expand)
1103                         this.View.LayoutLines.FoldingCollection.Collapse(foldingData);
1104                     else
1105                         this.View.LayoutLines.FoldingCollection.Expand(foldingData);
1106                     this.Controller.JumpCaret(foldingData.Start, false);
1107                 }
1108                 else
1109                 {
1110                     this.Controller.JumpCaret(tp.row, tp.col, false);
1111                 }
1112                 this.View.IsFocused = true;
1113                 this.Focus();
1114                 this.Refresh();
1115             }
1116         }
1117
1118         /// <summary>
1119         /// MouseClickイベントを発生させます
1120         /// </summary>
1121         /// <param name="e">インベントデータ</param>
1122         protected override void OnMouseClick(MouseEventArgs e)
1123         {
1124             int index = this.GetIndexFromPostion(e.Location);
1125
1126             FooMouseEventArgs mouseEvent = new FooMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta);
1127
1128             base.OnMouseClick(mouseEvent);
1129         }
1130
1131         /// <summary>
1132         /// MouseDoubleClickイベントを発生させます
1133         /// </summary>
1134         /// <param name="e">インベントデータ</param>
1135         protected override void OnMouseDoubleClick(MouseEventArgs e)
1136         {
1137             TextPoint tp = this.View.GetTextPointFromPostion(e.Location);
1138             if (tp == TextPoint.Null)
1139                 return;
1140             int index = this.View.LayoutLines.GetIndexFromTextPoint(tp);
1141
1142             FooMouseEventArgs mouseEvent = new FooMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta);
1143             
1144             base.OnMouseDoubleClick(mouseEvent);
1145
1146             if (mouseEvent.Handled)
1147                 return;
1148
1149             this.Controller.SelectWord(index);
1150             
1151             this.Refresh();
1152         }
1153
1154         /// <summary>
1155         /// MouseMoveイベントを発生させます
1156         /// </summary>
1157         /// <param name="e">インベントデータ</param>
1158         protected override void OnMouseMove(MouseEventArgs e)
1159         {
1160             if (this.Focused == false)
1161                 return;
1162
1163             base.OnMouseMove(e);
1164
1165             if (this.View.HitTextArea(e.Location.X, e.Location.Y))
1166             {
1167                 TextPoint tp = this.View.GetTextPointFromPostion(e.Location);
1168                 if (this.Controller.IsMarker(tp, HilightType.Url))
1169                     this.Cursor = Cursors.Hand;
1170                 else
1171                     this.Cursor = Cursors.IBeam;
1172
1173                 if (e.Button == MouseButtons.Left)
1174                 {
1175                     this.Controller.MoveCaretAndSelect(tp);
1176                     this.Refresh();
1177                 }
1178             }
1179             else
1180             {
1181                 this.Cursor = Cursors.Arrow;
1182             }
1183         }
1184
1185         /// <summary>
1186         /// MouseWheelイベントを発生させます
1187         /// </summary>
1188         /// <param name="e">インベントデータ</param>
1189         protected override void OnMouseWheel(MouseEventArgs e)
1190         {
1191             base.OnMouseWheel(e);
1192
1193             ScrollDirection dir = e.Delta > 0 ? ScrollDirection.Up : ScrollDirection.Down;
1194             this.Controller.Scroll(dir, SystemInformation.MouseWheelScrollLines, false, false);
1195             this.Refresh();
1196         }
1197
1198         /// <summary>
1199         /// Paintイベントを発生させます
1200         /// </summary>
1201         /// <param name="e">インベントデータ</param>
1202         protected override void OnPaint(PaintEventArgs e)
1203         {
1204             if (DesignMode)
1205             {
1206                 SolidBrush brush = new SolidBrush(this.BackColor);
1207                 e.Graphics.FillRectangle(brush, this.ClientRectangle);
1208                 brush.Dispose();
1209             }else if (this.Document.FireUpdateEvent){
1210                 this.render.BegineDraw();
1211                 this.View.Draw(e.ClipRectangle);
1212                 this.render.EndDraw();
1213             }
1214             base.OnPaint(e);
1215         }
1216
1217         /// <summary>
1218         /// PaintBackgroundイベントを発生させます
1219         /// </summary>
1220         /// <param name="e">インベントデータ</param>
1221         protected override void OnPaintBackground(PaintEventArgs e)
1222         {
1223         }
1224
1225         /// <summary>
1226         /// PreviewKeyDownイベントを発生させます
1227         /// </summary>
1228         /// <param name="e">インベントデータ</param>
1229         protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
1230         {
1231             base.OnPreviewKeyDown(e);
1232             switch (e.KeyCode)
1233             {
1234                 case Keys.Up:
1235                 case Keys.Down:
1236                 case Keys.Left:
1237                 case Keys.Right:
1238                 case Keys.Tab:
1239                     e.IsInputKey = true;
1240                     break;
1241             }
1242         }
1243
1244         /// <summary>
1245         /// KeyDownイベントを発生させます
1246         /// </summary>
1247         /// <param name="e">インベントデータ</param>
1248         protected override void OnKeyDown(KeyEventArgs e)
1249         {
1250             base.OnKeyDown(e);
1251             
1252             if (e.Handled)
1253                 return;
1254
1255             switch (e.KeyCode)
1256             {
1257                 case Keys.Up:
1258                     this.Controller.MoveCaretVertical(-1, e.Shift);
1259                     this.Refresh();
1260                     break;
1261                 case Keys.Down:
1262                     this.Controller.MoveCaretVertical(+1, e.Shift);
1263                     this.Refresh();
1264                     break;
1265                 case Keys.Left:
1266                     this.Controller.MoveCaretHorizontical(-1, e.Shift, e.Control);
1267                     this.Refresh();
1268                     break;
1269                 case Keys.Right:
1270                     this.Controller.MoveCaretHorizontical(1, e.Shift, e.Control);
1271                     this.Refresh();
1272                     break;
1273                 case Keys.PageUp:
1274                     this.Controller.Scroll(ScrollDirection.Up, this.VScrollBar.LargeChange,e.Shift,true);
1275                     this.Refresh();
1276                     break;
1277                 case Keys.PageDown:
1278                     this.Controller.Scroll(ScrollDirection.Down, this.VScrollBar.LargeChange,e.Shift,true);
1279                     this.Refresh();
1280                     break;
1281                 case Keys.Insert:
1282                     if (this.InsertMode)
1283                         this.InsertMode = false;
1284                     else
1285                         this.InsertMode = true;
1286                     break;
1287                 case Keys.Delete:
1288                     this.Controller.DoDeleteAction();
1289                     this.Refresh();
1290                     break;
1291                 case Keys.Back:
1292                     this.Controller.DoBackSpaceAction();
1293                     this.Refresh();
1294                     break;
1295                 case Keys.Home:
1296                     if (e.Control)
1297                         this.Controller.JumpToHead(e.Shift);
1298                     else
1299                         this.Controller.JumpToLineHead(this.Document.CaretPostion.row, e.Shift);
1300                     this.Refresh();
1301                     break;
1302                 case Keys.End:
1303                     if (e.Control)
1304                         this.Controller.JumpToEnd(e.Shift);
1305                     else
1306                         this.Controller.JumpToLineEnd(this.Document.CaretPostion.row, e.Shift);
1307                     this.Refresh();
1308                     break;
1309                 case Keys.Tab:
1310                     if (this.Controller.SelectionLength == 0)
1311                         this.Controller.DoInputChar('\t');
1312                     else if (e.Shift)
1313                         this.Controller.DownIndent();
1314                     else
1315                         this.Controller.UpIndent();
1316                     this.Refresh();
1317                     break;
1318             }
1319         }
1320
1321         /// <summary>
1322         /// KeyPressイベントを発生させます
1323         /// </summary>
1324         /// <param name="e">インベントデータ</param>
1325         protected override void OnKeyPress(KeyPressEventArgs e)
1326         {
1327             base.OnKeyPress(e);
1328
1329             if (e.Handled)
1330                 return;
1331             
1332             switch (e.KeyChar)
1333             {
1334                 case '\r':
1335                     this.Controller.DoEnterAction();
1336                     this.Refresh();
1337                     break;
1338                 case '\t':
1339                     break;  //OnKeyDownで処理しているので不要
1340                 default:
1341                     if (IsInputChar(e.KeyChar) == false)
1342                         break;
1343                     this.Controller.DoInputChar(e.KeyChar);
1344                     this.Refresh();
1345                     break;
1346             }
1347         }
1348
1349         /// <summary>
1350         /// ClientSizeChangedイベントを発生させます
1351         /// </summary>
1352         /// <param name="e">インベントデータ</param>
1353         protected override void OnClientSizeChanged(EventArgs e)
1354         {
1355             if (this.DesignMode)
1356                 return;
1357             base.OnClientSizeChanged(e);
1358             
1359             this.View.PageBound = new Rectangle(0,
1360                 0,
1361                 Math.Max(this.ClientRectangle.Width - this.VScrollBar.Width,0),
1362                 Math.Max(this.ClientRectangle.Height - this.HScrollBar.Height, 0));
1363
1364             initScrollBars();
1365             this.Refresh();
1366         }
1367
1368         void View_SrcChanged(object sender, EventArgs e)
1369         {
1370             if (this.View.Src.Row > this.VScrollBar.Maximum)
1371                 this.VScrollBar.Maximum = this.View.Src.Row + this.View.LineCountOnScreen + 1;
1372
1373             int srcX = (int)Math.Abs(this.View.Src.X);
1374             if (srcX > this.HScrollBar.Maximum)
1375                 this.HScrollBar.Maximum = srcX + (int)this.View.PageBound.Width + 1;
1376
1377             this.HScrollBar.Value = srcX;
1378
1379             this.VScrollBar.Value = this.View.Src.Row;
1380         }
1381
1382         void FooTextBox_RightToLeftChanged(object sender, EventArgs e)
1383         {
1384             this.Document.RightToLeft = this.RightToLeft == System.Windows.Forms.RightToLeft.Yes;
1385         }
1386
1387         void VScrollBar_Scroll(object sender, ScrollEventArgs e)
1388         {
1389             this.View.TryScroll(this.View.Src.X, e.NewValue);
1390             this.Refresh();
1391         }
1392
1393         void HScrollBar_Scroll(object sender, ScrollEventArgs e)
1394         {
1395             int toX;
1396             if (this.RightToLeft == System.Windows.Forms.RightToLeft.Yes)
1397                 toX = -e.NewValue;
1398             else
1399                 toX = e.NewValue;
1400             this.View.TryScroll(toX, this.View.Src.Row);
1401             this.Refresh();
1402         }
1403
1404         void Ime_StartCompstion(object sender, StartCompstionEventArgs e)
1405         {
1406             this.Ime.Font = this.Font;
1407             System.Drawing.Point p = this.GetPostionFromIndex(this.Controller.SelectionStart);
1408             float dpi;
1409             this.render.GetDpi(out dpi, out dpi);
1410             p.X = (int)(p.X * dpi / 96);
1411             p.Y = (int)(p.Y * dpi / 96);
1412             this.Ime.Location = p;
1413             this.View.HideCaret = true;
1414         }
1415
1416         void Ime_EndCompstion(object sender, EndCompstionEventArgs e)
1417         {
1418             this.View.HideCaret = false;
1419         }
1420
1421         void Ime_ImeCompstion(object sender, ImeCompstionEventArgs e)
1422         {
1423             this.Controller.DoInputString(e.InputText);
1424             this.Refresh();
1425         }
1426
1427         void Ime_ImeDocumentFeed(object sender, ImeDocumentFeedEventArgs e)
1428         {
1429             TextPoint tp = this.CaretPostion;
1430             e.Pragraph = this.LayoutLines[tp.row];
1431             e.pos = tp.col;
1432         }
1433
1434         void Ime_ImeReconvert(object sender, ImeReconvertStringEventArgs e)
1435         {
1436             if (this.RectSelection)
1437                 return;
1438             if (this.Controller.SelectionLength == 0)
1439             {
1440                 TextPoint tp = this.LayoutLines.GetTextPointFromIndex(this.Controller.SelectionStart);
1441                 e.TargetString = this.LayoutLines[tp.row];
1442                 e.AutoAdjust = true;
1443             }
1444             else
1445             {
1446                 e.TargetString = this.SelectedText;
1447                 if (e.TargetString.Length > 40)
1448                     e.TargetString.Remove(40);
1449             }
1450             e.CaretPostion = this.View.CaretLocation;
1451         }
1452
1453         void Ime_ImeQueryReconvert(object sender, ImeQueryRecovertStringEventArgs e)
1454         {
1455             TextPoint tp = this.LayoutLines.GetTextPointFromIndex(this.Controller.SelectionStart);
1456             tp.col = e.offset;
1457
1458             int index = this.View.GetIndexFromLayoutLine(tp);
1459
1460             this.Select(index, index + e.length);
1461         }
1462
1463         void Controller_CaretMoved(object sender, EventArgs e)
1464         {
1465             this.SelectionChanged(this, null);
1466         }
1467
1468         void initScrollBars()
1469         {
1470             this.VScrollBar.SmallChange = 1;
1471             this.VScrollBar.LargeChange = this.View.LineCountOnScreen;
1472             this.VScrollBar.Maximum = this.View.LayoutLines.Count + this.View.LineCountOnScreen + 1;
1473             this.HScrollBar.SmallChange = 10;
1474             this.HScrollBar.LargeChange = (int)this.View.PageBound.Width;
1475             this.HScrollBar.Maximum = this.HScrollBar.LargeChange + 1;
1476         }
1477
1478         void Timer_Tick(object sender,EventArgs e)
1479         {
1480             if (this.Document.CaretPostion.row >= this.View.LayoutLines.Count || DesignMode)
1481                 return;
1482
1483             ITextLayout layout = this.View.LayoutLines.GetLayout(this.Document.CaretPostion.row);
1484
1485             Size redrawSize = new Size();
1486             redrawSize.Width = layout.GetWidthFromIndex(this.Document.CaretPostion.col);
1487             if (redrawSize.Width == 0.0)
1488                 redrawSize.Width = this.View.CaretWidthOnInsertMode;
1489             redrawSize.Height = layout.Height;
1490
1491             bool updateAll = this.View.LayoutLines.HilightAll() || this.View.LayoutLines.GenerateFolding();
1492
1493             if (updateAll)
1494                 this.Invalidate();
1495             else
1496                 this.Invalidate(new System.Drawing.Rectangle(this.View.CaretLocation, redrawSize));
1497         }
1498
1499         void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
1500         {
1501             this.SetSystemParamaters();
1502             this.Refresh();
1503         }
1504
1505         void SetSystemParamaters()
1506         {
1507             int CaretBlinkTime = SystemInformation.CaretBlinkTime;
1508             if (CaretBlinkTime == -1)
1509             {
1510                 this.View.CaretBlink = false;
1511                 if (this.IsHandleCreated)
1512                     this.BeginInvoke(new Action(() =>
1513                     {
1514                     this.Timer.Stop();
1515                     }));
1516             }
1517             else
1518             {
1519                 this.View.CaretBlink = true;
1520                 this.View.CaretBlinkTime = CaretBlinkTime * 2;
1521                 if(this.IsHandleCreated)
1522                     this.BeginInvoke(new Action(() =>
1523                     {
1524                         this.Timer.Start();
1525                     }));
1526             }
1527             this.View.CaretWidthOnInsertMode = SystemInformation.CaretWidth;
1528         }
1529
1530     }
1531
1532     /// <summary>
1533     /// FooEditEngineで使用するマウスイベント
1534     /// </summary>
1535     public class FooMouseEventArgs : MouseEventArgs
1536     {
1537         /// <summary>
1538         /// イベントが発生したインデックス
1539         /// </summary>
1540         public int index;
1541         /// <summary>
1542         /// 既定の処理を省略するなら真。そうでなければ偽
1543         /// </summary>
1544         public bool Handled;
1545         /// <summary>
1546         /// コンストラクター
1547         /// </summary>
1548         /// <param name="index">インデックス</param>
1549         /// <param name="button">押されているボタン</param>
1550         /// <param name="clicks">ボタンが押された回数</param>
1551         /// <param name="x">マウスカーソルがあるX座標</param>
1552         /// <param name="y">マウスカーソルがあるY座標</param>
1553         /// <param name="delta">ホイールの回転方向</param>
1554         public FooMouseEventArgs(int index, MouseButtons button, int clicks, int x, int y, int delta)
1555             : base(button, clicks, x, y, delta)
1556         {
1557             this.index = index;
1558         }
1559     }
1560
1561 }