OSDN Git Service

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