OSDN Git Service

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