From: gdkhd812 Date: Sun, 25 Oct 2015 11:21:28 +0000 (+0530) Subject: MVVM対応準備のため、RightToLeftプロパティをDocumentに移動させた X-Git-Url: http://git.osdn.net/view?p=fooeditengine%2FFooEditEngine.git;a=commitdiff_plain;h=87e063089bac24c2e2686d612afaa5f853a98f5b MVVM対応準備のため、RightToLeftプロパティをDocumentに移動させた --- diff --git a/Core/Controller.cs b/Core/Controller.cs index fd16593..4d35f5f 100644 --- a/Core/Controller.cs +++ b/Core/Controller.cs @@ -55,8 +55,11 @@ namespace FooEditEngine { this.Document = doc; this.Document.Update += new DocumentUpdateEventHandler(Document_Update); + this.Document.RightToLeftChanged += (s, e) => + { + this.AdjustCaret(); + }; this.View = view; - this.View.render.ChangedRightToLeft += render_ChangedRightToLeft; this.View.render.ChangedRenderResource += render_ChangedRenderResource; this.View.PerformLayouted += View_LineBreakChanged; this.View.PageBoundChanged += View_PageBoundChanged; @@ -532,7 +535,7 @@ namespace FooEditEngine for (int i = Math.Abs(realLength); i > 0; i--) { bool MoveFlow = realLength > 0; - if (this.View.render.RightToLeft) + if (this.Document.RightToLeft) MoveFlow = !MoveFlow; this.MoveCaretHorizontical(MoveFlow); @@ -1230,11 +1233,6 @@ namespace FooEditEngine } } - void render_ChangedRightToLeft(object sender, EventArgs e) - { - this.AdjustCaret(); - } - void Document_Update(object sender, DocumentUpdateEventArgs e) { switch (e.type) diff --git a/Core/Document.cs b/Core/Document.cs index 62b9668..9252ed2 100644 --- a/Core/Document.cs +++ b/Core/Document.cs @@ -138,7 +138,7 @@ namespace FooEditEngine Match match; StringBuffer buffer; LineToIndexTable _LayoutLines; - bool _EnableFireUpdateEvent = true,_UrlMark = false, _DrawLineNumber = false, _HideRuler = true; + bool _EnableFireUpdateEvent = true,_UrlMark = false, _DrawLineNumber = false, _HideRuler = true, _RightToLeft = false; SemaphoreSlim Semaphore = new SemaphoreSlim(MaxSemaphoreCount); LineBreakMethod _LineBreak; int _TabStops, _LineBreakCharCount = 80; @@ -190,6 +190,23 @@ namespace FooEditEngine } /// + /// HideRulerの値が変わったときに通知します + /// + public event EventHandler RightToLeftChanged; + + /// + /// 右から左に表示するなら真 + /// + public bool RightToLeft { + get { return this._RightToLeft; } + set + { + this._RightToLeft = value; + this.RightToLeftChanged(this, null); + } + } + + /// /// 矩形選択モードなら真を返し、そうでない場合は偽を返す /// public bool RectSelection diff --git a/Core/EditView.cs b/Core/EditView.cs index 04283f3..f489762 100644 --- a/Core/EditView.cs +++ b/Core/EditView.cs @@ -335,7 +335,7 @@ namespace FooEditEngine Rectangle clipRect = this.render.TextArea; int count = 0; double markerHeight = emSize.Height / 2; - if (this.render.RightToLeft) + if (this.Document.RightToLeft) { pos = new Point(clipRect.TopRight.X, clipRect.TopRight.Y - emSize.Height - LineMarkerThickness); for (; pos.X >= clipRect.TopLeft.X; pos.X -= emSize.Width, count++) @@ -662,7 +662,7 @@ namespace FooEditEngine else if (x > right) //xは表示領域の右側にある { this._Src.X = x - this.render.TextArea.Width + this.ScrollMarginWidth; - if (this.render.RightToLeft && this._Src.X > 0) + if (this.Document.RightToLeft && this._Src.X > 0) { System.Diagnostics.Debug.Assert(x > 0); this._Src.X = 0; @@ -676,7 +676,7 @@ namespace FooEditEngine else if (x < left) //xは表示領域の左側にある { this._Src.X = x - this.ScrollMarginWidth; - if (!this.render.RightToLeft && this._Src.X < this.render.TextArea.X) + if (!this.Document.RightToLeft && this._Src.X < this.render.TextArea.X) { this._Src.X = 0; } @@ -849,7 +849,7 @@ namespace FooEditEngine if (this.DrawLineNumber) { - if (this.render.RightToLeft) + if (this.Document.RightToLeft) x = this.Padding.Left; else x = this.Padding.Left + UpdateAreaTotalWidth + this.render.LineNemberWidth + this.LineNumberMargin + render.FoldingWidth; @@ -857,7 +857,7 @@ namespace FooEditEngine } else { - if (this.render.RightToLeft) + if (this.Document.RightToLeft) x = this.Padding.Left; else x = this.Padding.Left + UpdateAreaTotalWidth + render.FoldingWidth; @@ -946,14 +946,14 @@ namespace FooEditEngine switch (type) { case AreaType.UpdateArea: - if (this.render.RightToLeft) + if (this.Document.RightToLeft) return this.PageBound.TopRight.X - UpdateAreaTotalWidth; if (this.DrawLineNumber) return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth - UpdateAreaTotalWidth; else return this.render.TextArea.X - render.FoldingWidth - UpdateAreaTotalWidth; case AreaType.FoldingArea: - if (this.render.RightToLeft) + if (this.Document.RightToLeft) return this.PageBound.TopRight.X - render.FoldingWidth; if (this.DrawLineNumber) return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin - render.FoldingWidth; @@ -962,7 +962,7 @@ namespace FooEditEngine case AreaType.LineNumberArea: if (this.DrawLineNumber == false) throw new InvalidOperationException(); - if (this.render.RightToLeft) + if (this.Document.RightToLeft) return this.PageBound.TopRight.X - UpdateAreaTotalWidth - render.FoldingWidth - this.render.LineNemberWidth; else return this.render.TextArea.X - this.render.LineNemberWidth - this.LineNumberMargin; diff --git a/Core/ViewBase.cs b/Core/ViewBase.cs index 1c2fdf8..010dc9f 100644 --- a/Core/ViewBase.cs +++ b/Core/ViewBase.cs @@ -110,6 +110,10 @@ namespace FooEditEngine { CalculateClipRect(); }; + this.Document.RightToLeftChanged += (s, e) => + { + this.render.RightToLeft = this.Document.RightToLeft; + }; } protected LineToIndexTable _LayoutLines @@ -272,7 +276,7 @@ namespace FooEditEngine this._Padding = value; CalculateClipRect(); CalculateLineCountOnScreen(); - if (this.render.RightToLeft) + if (this.Document.RightToLeft) this._LayoutLines.ClearLayoutCache(); this.PageBoundChanged(this, null); } @@ -291,7 +295,7 @@ namespace FooEditEngine this._Rect = value; CalculateClipRect(); CalculateLineCountOnScreen(); - if (this.render.RightToLeft) + if (this.Document.RightToLeft) this._LayoutLines.ClearLayoutCache(); this.PageBoundChanged(this, null); } diff --git a/Metro/FooEditEngine/FooTextBox.cs b/Metro/FooEditEngine/FooTextBox.cs index f01a8a4..f489db0 100644 --- a/Metro/FooEditEngine/FooTextBox.cs +++ b/Metro/FooEditEngine/FooTextBox.cs @@ -1174,7 +1174,7 @@ namespace FooEditEngine.Metro source.Render.LineNumber = D2DRenderBase.ToColor4(source.LineNumber); if (e.Property.Equals(FlowDirectionProperty)) { - source.Render.RightToLeft = source.FlowDirection == Windows.UI.Xaml.FlowDirection.RightToLeft; + source.Document.RightToLeft = source.FlowDirection == Windows.UI.Xaml.FlowDirection.RightToLeft; if(source.horizontalScrollBar != null) source.horizontalScrollBar.FlowDirection = source.FlowDirection; } diff --git a/WPF/FooEditEngine/FooTextBox.cs b/WPF/FooEditEngine/FooTextBox.cs index 07cb538..57d2c53 100644 --- a/WPF/FooEditEngine/FooTextBox.cs +++ b/WPF/FooEditEngine/FooTextBox.cs @@ -1205,7 +1205,7 @@ namespace FooEditEngine.WPF this.Render.ShowLineBreak = this.ShowLineBreak; break; case "FlowDirection": - this.Render.RightToLeft = this.FlowDirection == System.Windows.FlowDirection.RightToLeft; + this.Document.RightToLeft = this.FlowDirection == System.Windows.FlowDirection.RightToLeft; this.horizontalScrollBar.FlowDirection = this.FlowDirection; break; case "DrawRuler": diff --git a/Windows/FooEditEngine/FooTextBox.cs b/Windows/FooEditEngine/FooTextBox.cs index ba7b95f..a6baa0d 100644 --- a/Windows/FooEditEngine/FooTextBox.cs +++ b/Windows/FooEditEngine/FooTextBox.cs @@ -1,1562 +1,1562 @@ -/* - * Copyright (C) 2013 FooProject - * * 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 - * the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with this program. If not, see . - */ -using System; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; -using System.Drawing; -using System.ComponentModel; -using Microsoft.Win32; - -namespace FooEditEngine.Windows -{ - /// - /// タブの幅が変更されたときに呼びされるデリゲート - /// - /// 送り主が属するクラス - /// イベントデータ - public delegate void TabStopChangeEventHandler(object sender, EventArgs e); - - /// - /// InsetModeが変更されたときに呼び出されるデリゲート - /// - /// 送り主が属するクラス - /// イベントデータ - public delegate void InsertModeChangeEventHandler(object sender, EventArgs e); - - /// - /// FooEditEngineを表します - /// - public class FooTextBox : Control - { - EditView View; - Controller Controller; - D2DTextRender render; - BorderStyle _BoderStyle; - HScrollBar HScrollBar; - VScrollBar VScrollBar; - WinIME Ime; - System.Windows.Forms.Timer Timer; - - const int Interval = 100; - - /// - /// コンストラクター - /// - public FooTextBox() - { - this.VScrollBar = new VScrollBar(); - this.VScrollBar.Scroll += new ScrollEventHandler(VScrollBar_Scroll); - this.VScrollBar.Dock = DockStyle.Right; - this.VScrollBar.Visible = true; - this.Controls.Add(this.VScrollBar); - - this.HScrollBar = new HScrollBar(); - this.HScrollBar.Scroll += new ScrollEventHandler(HScrollBar_Scroll); - this.HScrollBar.Dock = DockStyle.Bottom; - this.HScrollBar.Visible = true; - this.Controls.Add(this.HScrollBar); - - this.SetStyle(ControlStyles.ResizeRedraw, true); - this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); - this.SetStyle(ControlStyles.UserPaint, true); - this.SetStyle(ControlStyles.Opaque, true); - - this.render = new D2DTextRender(this); - this.Document = new Document(); - this.Document.LayoutLines.Render = this.render; - this.View = new EditView(this.Document, this.render, new FooEditEngine.Padding(5, 5, 5, 5)); - this.View.SrcChanged += View_SrcChanged; - - this.Controller = new Controller(this.Document, this.View); - this.Controller.SelectionChanged += new EventHandler(Controller_CaretMoved); - - this.Ime = new WinIME(this); - this.Ime.ImeCompstion += new ImeCompstionEventHandeler(Ime_ImeCompstion); - this.Ime.StartCompstion += new StartCompstionEventHandeler(Ime_StartCompstion); - this.Ime.EndCompstion += new EndCompstionEventHandeler(Ime_EndCompstion); - this.Ime.ImeDocumentFeed += new ImeDocumentFeedEventHandler(Ime_ImeDocumentFeed); - this.Ime.ImeReconvert += new ImeReconvertStringEventHandler(Ime_ImeReconvert); - this.Ime.ImeQueryReconvert += new ImeQueryReconvertStringEventHandler(Ime_ImeQueryReconvert); - - this.Timer = new System.Windows.Forms.Timer(); - this.Timer.Tick += new EventHandler(this.Timer_Tick); - this.Timer.Interval = Interval; - this.SetSystemParamaters(); - - this.TabStopChange += new TabStopChangeEventHandler((s, e) => { }); - this.InsetModeChange += new InsertModeChangeEventHandler((s, e) => { }); - this.SelectionChanged +=new EventHandler((s,e)=>{}); - - this.RightToLeftChanged += FooTextBox_RightToLeftChanged; - - SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged); - - } - - /// - /// キャレットが移動したときに通知されるイベント - /// - public event EventHandler SelectionChanged; - - /// - /// タブの幅が変更された時に発生するイベント - /// - public event TabStopChangeEventHandler TabStopChange; - - /// - /// InsertModeが変更されたときに呼び出されるイベント - /// - public event InsertModeChangeEventHandler InsetModeChange; - - /// - /// インデントモードを表す - /// - [DefaultValue(IndentMode.Tab)] - public IndentMode IndentMode - { - get - { - return this.Controller.IndentMode; - } - set - { - this.Controller.IndentMode = value; - } - } - - /// - /// テキスト描写に使用するアンチエイリアシングモードを表す - /// - [BrowsableAttribute(false)] - public TextAntialiasMode TextAntialiasMode - { - get - { - return this.render.TextAntialiasMode; - } - set - { - this.render.TextAntialiasMode = value; - } - } - - /// - /// マーカーパターンセットを表す - /// - [BrowsableAttribute(false)] - public MarkerPatternSet MarkerPatternSet - { - get - { - return this.View.MarkerPatternSet; - } - } - - /// - /// 保持しているドキュメント - /// - [BrowsableAttribute(false)] - public Document Document - { - get; - private set; - } - - /// - /// 保持しているレイアウト行 - /// - [BrowsableAttribute(false)] - public LineToIndexTable LayoutLines - { - get { return this.View.LayoutLines; } - } - - /// - /// シンタックスハイライター - /// - [BrowsableAttribute(false)] - public IHilighter Hilighter - { - get { return this.View.Hilighter; } - set { this.View.Hilighter = value; this.View.LayoutLines.ClearLayoutCache(); } - } - - /// - /// フォールティングを作成するインターフェイスを表す - /// - [BrowsableAttribute(false)] - public IFoldingStrategy FoldingStrategy - { - get - { - return this.View.LayoutLines.FoldingStrategy; - } - set - { - this.View.LayoutLines.FoldingStrategy = value; - if (value == null) - this.View.LayoutLines.FoldingCollection.Clear(); - } - } - - /// - /// 境界線のスタイルを指定します - /// - public BorderStyle BorderStyle - { - get { return this._BoderStyle; } - set { this._BoderStyle = value; this.UpdateStyles(); } - } - - - /// - /// 行番号を表示するかどうか - /// - [DefaultValue(false)] - public bool DrawLineNumber - { - get - { - return this.View.DrawLineNumber; - } - set - { - this.View.DrawLineNumber = value; - this.JumpCaret(this.CaretPostion.row,this.CaretPostion.col); - } - } - - /// - /// ルーラーを表示するかどうか - /// - [DefaultValue(false)] - public bool DrawRuler - { - get - { - return !this.View.HideRuler; - } - set - { - this.View.HideRuler = !value; - this.JumpCaret(this.CaretPostion.row, this.CaretPostion.col); - } - } - - /// - /// 桁折りを行う方法を指定する - /// - /// - /// 反映させるためにはレイアウト行の再構築を行う必要があります - /// - [DefaultValue(LineBreakMethod.None)] - public LineBreakMethod LineBreakMethod - { - get - { - return this.View.LineBreak; - } - set - { - this.View.LineBreak = value; - } - } - - /// - /// 桁折り時の文字数を指定する。 - /// - /// - /// 反映させるためにはレイアウト行の再構築を行う必要があります - /// - [DefaultValue(80)] - public int LineBreakCharCount - { - get - { - return this.View.LineBreakCharCount; - } - set - { - this.View.LineBreakCharCount = value; - } - } - - /// - /// URLをマークするかどうか - /// - [DefaultValue(false)] - public bool UrlMark - { - get - { - return this.View.UrlMark; - } - set - { - this.View.UrlMark = value; - } - } - - /// - /// タブストップの幅 - /// - [DefaultValue(4)] - public int TabStops - { - get { return this.View.TabStops; } - set { - this.View.TabStops = value; - this.View.AdjustCaretAndSrc(); - this.TabStopChange(this, null); - } - } - - /// - /// 全角スペースを表示するなら真。そうでないなら偽 - /// - [DefaultValue(false)] - public bool ShowFullSpace - { - get - { - return this.render.ShowFullSpace; - } - set - { - this.render.ShowFullSpace = value; - } - } - - /// - /// 半角スペースを表示するなら真。そうでないなら偽 - /// - [DefaultValue(false)] - public bool ShowHalfSpace - { - get - { - return this.render.ShowHalfSpace; - } - set - { - this.render.ShowHalfSpace = value; - } - } - - /// - /// タブを表示するなら真。そうでないなら偽 - /// - [DefaultValue(false)] - public bool ShowTab - { - get - { - return this.render.ShowTab; - } - set - { - this.render.ShowTab = value; - } - } - - /// - /// 改行マークを表示するなら真。そうでないなら偽 - /// - [DefaultValue(false)] - public bool ShowLineBreak - { - get - { - return this.render.ShowLineBreak; - } - set - { - this.render.ShowLineBreak = value; - } - } - - /// - /// 選択中の文字列 - /// - /// - /// 未選択状態で文字列を代入した場合、キャレット位置に挿入され、そうでないときは置き換えられます。 - /// - [BrowsableAttribute(false)] - public string SelectedText - { - get { return this.Controller.SelectedText; } - set { this.Controller.SelectedText = value; } - } - - /// - /// キャレット位置を表す - /// - [BrowsableAttribute(false)] - public TextPoint CaretPostion - { - get { return this.View.CaretPostion; } - } - - /// - /// 選択範囲を表す - /// - /// - /// Lengthが0の場合はキャレット位置を表します - /// 矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります - /// - [BrowsableAttribute(false)] - public TextRange Selection - { - get { return new TextRange(this.Controller.SelectionStart,this.Controller.SelectionLength); } - set - { - this.Controller.Select(value.Index, value.Length); - } - } - - /// - /// 挿入モードかどうか - /// - [DefaultValue(true)] - public bool InsertMode - { - get { return this.View.InsertMode; } - set - { - this.View.InsertMode = value; - this.InsetModeChange(this, null); - } - } - - /// - /// 矩形選択を行うかどうか - /// - [DefaultValue(false)] - public bool RectSelection - { - get { return this.Controller.RectSelection; } - set { this.Controller.RectSelection = value; } - } - - System.Drawing.Color ForegroundColor = SystemColors.ControlText, - BackgroundColor = SystemColors.Control, - HilightColor = System.Drawing.Color.DeepSkyBlue, - Keyword1Color = System.Drawing.Color.Blue, - Keyword2Color = System.Drawing.Color.DarkCyan, - LiteralColor = System.Drawing.Color.Brown, - UrlColor = System.Drawing.Color.Blue, - ControlCharColor = System.Drawing.Color.Gray, - CommentColor = System.Drawing.Color.Green, - InsertCaretColor = System.Drawing.Color.Black, - OverwriteCaretColor = System.Drawing.Color.Black, - LineMarkerColor = System.Drawing.Color.WhiteSmoke, - UpdateAreaColor = System.Drawing.Color.MediumSeaGreen, - LineNumberColor = System.Drawing.Color.DimGray; - - /// - /// 前景色 - /// - public System.Drawing.Color Foreground - { - get - { - return this.ForegroundColor; - } - set - { - this.render.Foreground = D2DTextRender.ToColor4(value); - this.ForegroundColor = value; - } - } - - /// - /// 背景色 - /// - public System.Drawing.Color Background - { - get - { - return this.BackgroundColor; - } - set - { - this.render.Background = D2DTextRender.ToColor4(value); - this.BackgroundColor = value; - } - } - - /// - /// 挿入モード時のキャレット色 - /// - public System.Drawing.Color InsertCaret - { - get - { - return this.InsertCaretColor; - } - set - { - this.InsertCaretColor = value; - this.render.InsertCaret = D2DTextRender.ToColor4(value); - } - } - - /// - /// 上書きモード時のキャレット色 - /// - public System.Drawing.Color OverwriteCaret - { - get - { - return this.OverwriteCaretColor; - } - set - { - this.OverwriteCaretColor = value; - this.render.OverwriteCaret = D2DTextRender.ToColor4(value); - } - } - - /// - /// ラインマーカーの色 - /// - public System.Drawing.Color LineMarker - { - get - { - return this.LineMarkerColor; - } - set - { - this.LineMarkerColor = value; - this.render.LineMarker = D2DTextRender.ToColor4(value); - } - } - - /// - /// コントロールの色 - /// - public System.Drawing.Color ControlChar - { - get - { - return this.ControlCharColor; - } - set - { - this.ControlCharColor = value; - this.render.ControlChar = D2DTextRender.ToColor4(value); - } - } - - /// - /// 編集行フラグの色 - /// - public System.Drawing.Color UpdateArea - { - get - { - return this.UpdateAreaColor; - } - set - { - this.UpdateAreaColor = value; - this.render.UpdateArea = D2DTextRender.ToColor4(value); - } - } - - /// - /// 行番号の色 - /// - public System.Drawing.Color LineNumber - { - get - { - return this.LineNumber; - } - set - { - this.LineNumber = value; - this.render.LineNumber = D2DTextRender.ToColor4(value); - } - } - - /// - /// URLの色 - /// - public System.Drawing.Color Url - { - get - { - return this.UrlColor; - } - set - { - this.UrlColor = value; - this.render.Url = D2DTextRender.ToColor4(value); - } - } - - /// - /// 選択領域の色 - /// - public System.Drawing.Color Hilight - { - get - { - return this.HilightColor; - } - set - { - this.HilightColor = value; - this.render.Hilight = D2DTextRender.ToColor4(value); - } - } - - /// - /// コメントの色 - /// - public System.Drawing.Color Comment - { - get - { - return this.CommentColor; - } - set - { - this.CommentColor = value; - this.render.Comment = D2DTextRender.ToColor4(value); - } - } - - /// - /// 文字リテラルの色 - /// - public System.Drawing.Color Literal - { - get - { - return this.LiteralColor; - } - set - { - this.LiteralColor = value; - this.render.Literal = D2DTextRender.ToColor4(value); - } - } - - /// - /// キーワード1の色 - /// - public System.Drawing.Color Keyword1 - { - get - { - return this.Keyword1Color; - } - set - { - this.Keyword1Color = value; - this.render.Keyword1 = D2DTextRender.ToColor4(value); - } - } - - /// - /// キーワード2の色 - /// - public System.Drawing.Color Keyword2 - { - get - { - return this.Keyword2Color; - } - set - { - this.Keyword2Color = value; - this.render.Keyword2 = D2DTextRender.ToColor4(value); - } - } - - /// - /// キャレットに下線を描くかどうか - /// - [DefaultValue(false)] - public bool DrawCaretLine - { - get { return !this.View.HideLineMarker; } - set { this.View.HideLineMarker = !value; } - } - - /// - /// ドキュメントを選択する - /// - /// 開始インデックス - /// 長さ - public void Select(int start, int length) - { - this.Controller.Select(start, length); - this.HScrollBar.Value = (int)this.View.Src.X; - this.VScrollBar.Value = this.View.Src.Row; - } - - /// - /// ドキュメント全体を選択する - /// - public void SelectAll() - { - this.Controller.Select(0, this.Document.Length - 1); - } - - /// - /// 選択を解除する - /// - public void DeSelectAll() - { - this.Controller.DeSelectAll(); - } - - /// - /// クリップボードにコピーする - /// - public void Copy() - { - string text = this.SelectedText; - if(text != null && text != string.Empty) - Clipboard.SetText(text); - } - - /// - /// クリップボードにコピーし、指定した範囲にある文字列をすべて削除します - /// - public void Cut() - { - string text = this.SelectedText; - if (text != null && text != string.Empty) - { - Clipboard.SetText(text); - this.Controller.SelectedText = ""; - } - } - - /// - /// クリップボードの内容をペーストします - /// - public void Paste() - { - if (Clipboard.ContainsText() == false) - return; - this.Controller.SelectedText = Clipboard.GetText(); - } - - /// - /// キャレットを指定した行に移動させます - /// - /// インデックス - /// このメソッドを呼び出すと選択状態は解除されます - public void JumpCaret(int index) - { - this.Controller.JumpCaret(index); - } - /// - /// キャレットを指定した行と桁に移動させます - /// - /// 行番号 - /// 桁 - /// このメソッドを呼び出すと選択状態は解除されます - public void JumpCaret(int row, int col) - { - this.Controller.JumpCaret(row, col); - } - - /// - /// 再描写します - /// - public new void Refresh() - { - if (this.Document.FireUpdateEvent == false) - throw new InvalidOperationException(""); - if(this.View.CaretBlink) - this.View.CaretBlink = true; - this.Invalidate(); - this.Update(); - } - - /// - /// 行の高さを取得する - /// - /// 行 - /// 高さ - public double GetLineHeight(int row) - { - if (this.Document.FireUpdateEvent == false) - throw new InvalidOperationException(""); - return this.View.LayoutLines.GetLayout(row).Height; - } - - /// - /// 対応する座標を返す - /// - /// テキストポイント - /// 座標 - /// テキストポイントがクライアント領域の原点より外にある場合、返される値は原点に丸められます - public System.Drawing.Point GetPostionFromTextPoint(TextPoint tp) - { - if (this.Document.FireUpdateEvent == false) - throw new InvalidOperationException(""); - return this.View.GetPostionFromTextPoint(tp); - } - - /// - /// 対応するテキストポイントを返す - /// - /// クライアント領域の原点を左上とする座標 - /// テキストポイント - public TextPoint GetTextPointFromPostion(System.Drawing.Point p) - { - if (this.Document.FireUpdateEvent == false) - throw new InvalidOperationException(""); - return this.View.GetTextPointFromPostion(p); - } - - /// - /// インデックスに対応する座標を得ます - /// - /// インデックス - /// 座標を返す - public System.Drawing.Point GetPostionFromIndex(int index) - { - if (this.Document.FireUpdateEvent == false) - throw new InvalidOperationException(""); - TextPoint tp = this.View.GetLayoutLineFromIndex(index); - return this.View.GetPostionFromTextPoint(tp); - } - - /// - /// 座標からインデックスに変換します - /// - /// 座標 - /// インデックスを返す - public int GetIndexFromPostion(System.Drawing.Point p) - { - if (this.Document.FireUpdateEvent == false) - throw new InvalidOperationException(""); - TextPoint tp = this.View.GetTextPointFromPostion(p); - return this.View.GetIndexFromLayoutLine(tp); - } - - /// - /// レイアウト行をすべて破棄し、再度レイアウトを行う - /// - public void PerfomLayouts() - { - this.View.PerfomLayouts(); - initScrollBars(); - } - - /// - /// ストリームからドキュメントを構築する - /// - /// TextReader - /// キャンセル用トークン - /// Taskオブジェクト - public async Task LoadAsync(System.IO.TextReader tr, System.Threading.CancellationTokenSource token) - { - WinFileReader fs = new WinFileReader(tr); - await this.LoadAsyncImpl(fs, token); - } - - /// - /// ファイルからドキュメントを構築する - /// - /// ファイルパス - /// エンコード - /// キャンセル用トークン - /// Taskオブジェクト - public async Task LoadFileAsync(string filepath, Encoding enc, System.Threading.CancellationTokenSource token) - { - WinFileReader fs = new WinFileReader(filepath, enc); - await this.LoadAsyncImpl(fs, token); - fs.Close(); - } - - async Task LoadAsyncImpl(WinFileReader fs, System.Threading.CancellationTokenSource token) - { - this.Enabled = false; - this.View.LayoutLines.IsFrozneDirtyFlag = true; - await this.Document.LoadAsync(fs, token); - this.View.LayoutLines.IsFrozneDirtyFlag = false; - this.initScrollBars(); - this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, MousePosition.X, MousePosition.Y, 0)); - this.View.CalculateLineCountOnScreen(); - this.Enabled = true; - } - - /// - /// ドキュメントの内容をファイルに保存する - /// - /// ファイルパス - /// 改行コード - /// エンコード - /// Taskオブジェクト - public async Task SaveFile(string filepath, Encoding enc, string newLine, System.Threading.CancellationTokenSource token) - { - WinFileWriter fs = new WinFileWriter(filepath, enc); - fs.NewLine = newLine; - await this.Document.SaveAsync(fs, token); - fs.Close(); - } - - /// - /// マウスカーソルを指定します - /// - public override Cursor Cursor - { - get - { - return base.Cursor; - } - set - { - base.Cursor = value; - this.VScrollBar.Cursor = DefaultCursor; - this.HScrollBar.Cursor = DefaultCursor; - } - } - - private const int WS_BORDER = 0x00800000; - private const int WS_EX_CLIENTEDGE = 0x00000200; - /// - /// コントロールの外観を指定します - /// - protected override CreateParams CreateParams - { - get - { - CreateParams cp = base.CreateParams; - switch (this.BorderStyle) - { - case BorderStyle.Fixed3D: - cp.ExStyle |= WS_EX_CLIENTEDGE; - break; - case BorderStyle.FixedSingle: - cp.Style |= WS_BORDER; - break; - } - return cp; - } - } - - /// - /// コマンド キーを処理します - /// - /// メッセージ - /// キーデータ - /// 文字がコントロールによって処理された場合は true。それ以外の場合は false。 - protected override bool ProcessCmdKey(ref Message msg, Keys keyData) - { - const int WM_KEYDOWN = 0x100; - if (msg.Msg != WM_KEYDOWN) - return base.ProcessCmdKey(ref msg, keyData); - switch (keyData) - { - case Keys.Control | Keys.C: - this.Copy(); - break; - case Keys.Control | Keys.V: - this.Paste(); - this.Refresh(); - break; - case Keys.Control | Keys.X: - this.Cut(); - this.Refresh(); - break; - case Keys.Control | Keys.Z: - this.Document.UndoManager.undo(); - this.Refresh(); - break; - case Keys.Control | Keys.Y: - this.Document.UndoManager.redo(); - this.Refresh(); - break; - case Keys.Control | Keys.B: - if (this.Controller.RectSelection) - this.Controller.RectSelection = false; - else - this.Controller.RectSelection = true; - break; - default: - return base.ProcessCmdKey(ref msg,keyData); - } - return true; - } - - /// - /// インスタンスを破棄します - /// - /// マネージ リソースとアンマネージ リソースの両方を解放する場合は true。アンマネージ リソースだけを解放する場合は false。 - protected override void Dispose(bool disposing) - { - SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(this.SystemEvents_UserPreferenceChanged); - this.render.Dispose(); - this.Timer.Dispose(); - base.Dispose(disposing); - } - - /// - /// 入力可能な文字かチェックします - /// - /// 入力しようとした文字 - /// 可能なら真。そうでなければ偽 - protected override bool IsInputChar(char charCode) - { - if ((0x20 <= charCode && charCode <= 0x7e) - || charCode == '\r' - || charCode == '\n' - || charCode == ' ' - || charCode == '\t' - || charCode == ' ' - || 0x7f < charCode) - { - return true; - } - - return false; - } - - /// - /// PaddingChangedイベントを発生させます - /// - /// インベントデータ - protected override void OnPaddingChanged(EventArgs e) - { - base.OnPaddingChanged(e); - this.View.Padding = new Padding(this.Padding.Left, this.Padding.Top, this.Padding.Right, this.Padding.Bottom); - } - - /// - /// GotFocusイベントを発生させます - /// - /// インベントデータ - protected override void OnGotFocus(EventArgs e) - { - base.OnGotFocus(e); - this.View.IsFocused = true; - this.Refresh(); - } - - /// - /// LostFocusイベントを発生させます - /// - /// インベントデータ - protected override void OnLostFocus(EventArgs e) - { - base.OnLostFocus(e); - this.View.IsFocused = false; - this.Refresh(); - } - - /// - /// FontChangedイベントを発生させます - /// - /// インベントデータ - protected override void OnFontChanged(EventArgs e) - { - if (this.DesignMode) - return; - base.OnFontChanged(e); - initScrollBars(); - } - - /// - /// MouseDownイベントを発生させます - /// - /// インベントデータ - protected override void OnMouseDown(MouseEventArgs e) - { - TextPoint tp = this.View.GetTextPointFromPostion(e.Location); - if (tp == TextPoint.Null) - return; - int index = this.View.LayoutLines.GetIndexFromTextPoint(tp); - - FooMouseEventArgs mouseEvent = new FooMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); - - base.OnMouseDown(mouseEvent); - - if (mouseEvent.Handled) - return; - - if (e.Button == MouseButtons.Left) - { - FoldingItem foldingData = this.View.HitFoldingData(e.Location.X, tp.row); - if (foldingData != null) - { - if (foldingData.Expand) - this.View.LayoutLines.FoldingCollection.Collapse(foldingData); - else - this.View.LayoutLines.FoldingCollection.Expand(foldingData); - this.Controller.JumpCaret(foldingData.Start, false); - } - else - { - this.Controller.JumpCaret(tp.row, tp.col, false); - } - this.View.IsFocused = true; - this.Focus(); - this.Refresh(); - } - } - - /// - /// MouseClickイベントを発生させます - /// - /// インベントデータ - protected override void OnMouseClick(MouseEventArgs e) - { - int index = this.GetIndexFromPostion(e.Location); - - FooMouseEventArgs mouseEvent = new FooMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); - - base.OnMouseClick(mouseEvent); - } - - /// - /// MouseDoubleClickイベントを発生させます - /// - /// インベントデータ - protected override void OnMouseDoubleClick(MouseEventArgs e) - { - TextPoint tp = this.View.GetTextPointFromPostion(e.Location); - if (tp == TextPoint.Null) - return; - int index = this.View.LayoutLines.GetIndexFromTextPoint(tp); - - FooMouseEventArgs mouseEvent = new FooMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); - - base.OnMouseDoubleClick(mouseEvent); - - if (mouseEvent.Handled) - return; - - this.Controller.SelectWord(index); - - this.Refresh(); - } - - /// - /// MouseMoveイベントを発生させます - /// - /// インベントデータ - protected override void OnMouseMove(MouseEventArgs e) - { - if (this.Focused == false) - return; - - base.OnMouseMove(e); - - if (this.View.HitTextArea(e.Location.X, e.Location.Y)) - { - TextPoint tp = this.View.GetTextPointFromPostion(e.Location); - if (this.Controller.IsMarker(tp, HilightType.Url)) - this.Cursor = Cursors.Hand; - else - this.Cursor = Cursors.IBeam; - - if (e.Button == MouseButtons.Left) - { - this.Controller.MoveCaretAndSelect(tp); - this.Refresh(); - } - } - else - { - this.Cursor = Cursors.Arrow; - } - } - - /// - /// MouseWheelイベントを発生させます - /// - /// インベントデータ - protected override void OnMouseWheel(MouseEventArgs e) - { - base.OnMouseWheel(e); - - ScrollDirection dir = e.Delta > 0 ? ScrollDirection.Up : ScrollDirection.Down; - this.Controller.Scroll(dir, SystemInformation.MouseWheelScrollLines, false, false); - this.Refresh(); - } - - /// - /// Paintイベントを発生させます - /// - /// インベントデータ - protected override void OnPaint(PaintEventArgs e) - { - if (DesignMode) - { - SolidBrush brush = new SolidBrush(this.BackColor); - e.Graphics.FillRectangle(brush, this.ClientRectangle); - brush.Dispose(); - }else if (this.Document.FireUpdateEvent){ - this.render.BegineDraw(); - this.View.Draw(e.ClipRectangle); - this.render.EndDraw(); - } - base.OnPaint(e); - } - - /// - /// PaintBackgroundイベントを発生させます - /// - /// インベントデータ - protected override void OnPaintBackground(PaintEventArgs e) - { - } - - /// - /// PreviewKeyDownイベントを発生させます - /// - /// インベントデータ - protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e) - { - base.OnPreviewKeyDown(e); - switch (e.KeyCode) - { - case Keys.Up: - case Keys.Down: - case Keys.Left: - case Keys.Right: - case Keys.Tab: - e.IsInputKey = true; - break; - } - } - - /// - /// KeyDownイベントを発生させます - /// - /// インベントデータ - protected override void OnKeyDown(KeyEventArgs e) - { - base.OnKeyDown(e); - - if (e.Handled) - return; - - switch (e.KeyCode) - { - case Keys.Up: - this.Controller.MoveCaretVertical(-1, e.Shift); - this.Refresh(); - break; - case Keys.Down: - this.Controller.MoveCaretVertical(+1, e.Shift); - this.Refresh(); - break; - case Keys.Left: - this.Controller.MoveCaretHorizontical(-1, e.Shift, e.Control); - this.Refresh(); - break; - case Keys.Right: - this.Controller.MoveCaretHorizontical(1, e.Shift, e.Control); - this.Refresh(); - break; - case Keys.PageUp: - this.Controller.Scroll(ScrollDirection.Up, this.VScrollBar.LargeChange,e.Shift,true); - this.Refresh(); - break; - case Keys.PageDown: - this.Controller.Scroll(ScrollDirection.Down, this.VScrollBar.LargeChange,e.Shift,true); - this.Refresh(); - break; - case Keys.Insert: - if (this.InsertMode) - this.InsertMode = false; - else - this.InsertMode = true; - break; - case Keys.Delete: - this.Controller.DoDeleteAction(); - this.Refresh(); - break; - case Keys.Back: - this.Controller.DoBackSpaceAction(); - this.Refresh(); - break; - case Keys.Home: - if (e.Control) - this.Controller.JumpToHead(e.Shift); - else - this.Controller.JumpToLineHead(this.View.CaretPostion.row, e.Shift); - this.Refresh(); - break; - case Keys.End: - if (e.Control) - this.Controller.JumpToEnd(e.Shift); - else - this.Controller.JumpToLineEnd(this.View.CaretPostion.row, e.Shift); - this.Refresh(); - break; - case Keys.Tab: - if (this.Controller.SelectionLength == 0) - this.Controller.DoInputChar('\t'); - else if (e.Shift) - this.Controller.DownIndent(); - else - this.Controller.UpIndent(); - this.Refresh(); - break; - } - } - - /// - /// KeyPressイベントを発生させます - /// - /// インベントデータ - protected override void OnKeyPress(KeyPressEventArgs e) - { - base.OnKeyPress(e); - - if (e.Handled) - return; - - switch (e.KeyChar) - { - case '\r': - this.Controller.DoEnterAction(); - this.Refresh(); - break; - case '\t': - break; //OnKeyDownで処理しているので不要 - default: - if (IsInputChar(e.KeyChar) == false) - break; - this.Controller.DoInputChar(e.KeyChar); - this.Refresh(); - break; - } - } - - /// - /// ClientSizeChangedイベントを発生させます - /// - /// インベントデータ - protected override void OnClientSizeChanged(EventArgs e) - { - if (this.DesignMode) - return; - base.OnClientSizeChanged(e); - - this.View.PageBound = new Rectangle(0, - 0, - Math.Max(this.ClientRectangle.Width - this.VScrollBar.Width,0), - Math.Max(this.ClientRectangle.Height - this.HScrollBar.Height, 0)); - - initScrollBars(); - this.Refresh(); - } - - void View_SrcChanged(object sender, EventArgs e) - { - if (this.View.Src.Row > this.VScrollBar.Maximum) - this.VScrollBar.Maximum = this.View.Src.Row + this.View.LineCountOnScreen + 1; - - int srcX = (int)Math.Abs(this.View.Src.X); - if (srcX > this.HScrollBar.Maximum) - this.HScrollBar.Maximum = srcX + (int)this.View.PageBound.Width + 1; - - this.HScrollBar.Value = srcX; - - this.VScrollBar.Value = this.View.Src.Row; - } - - void FooTextBox_RightToLeftChanged(object sender, EventArgs e) - { - this.render.RightToLeft = this.RightToLeft == System.Windows.Forms.RightToLeft.Yes; - } - - void VScrollBar_Scroll(object sender, ScrollEventArgs e) - { - this.View.TryScroll(this.View.Src.X, e.NewValue); - this.Refresh(); - } - - void HScrollBar_Scroll(object sender, ScrollEventArgs e) - { - int toX; - if (this.RightToLeft == System.Windows.Forms.RightToLeft.Yes) - toX = -e.NewValue; - else - toX = e.NewValue; - this.View.TryScroll(toX, this.View.Src.Row); - this.Refresh(); - } - - void Ime_StartCompstion(object sender, StartCompstionEventArgs e) - { - this.Ime.Font = this.Font; - System.Drawing.Point p = this.GetPostionFromIndex(this.Controller.SelectionStart); - float dpi; - this.render.GetDpi(out dpi, out dpi); - p.X = (int)(p.X * dpi / 96); - p.Y = (int)(p.Y * dpi / 96); - this.Ime.Location = p; - this.View.HideCaret = true; - } - - void Ime_EndCompstion(object sender, EndCompstionEventArgs e) - { - this.View.HideCaret = false; - } - - void Ime_ImeCompstion(object sender, ImeCompstionEventArgs e) - { - this.Controller.DoInputString(e.InputText); - this.Refresh(); - } - - void Ime_ImeDocumentFeed(object sender, ImeDocumentFeedEventArgs e) - { - TextPoint tp = this.CaretPostion; - e.Pragraph = this.LayoutLines[tp.row]; - e.pos = tp.col; - } - - void Ime_ImeReconvert(object sender, ImeReconvertStringEventArgs e) - { - if (this.RectSelection) - return; - if (this.Controller.SelectionLength == 0) - { - TextPoint tp = this.LayoutLines.GetTextPointFromIndex(this.Controller.SelectionStart); - e.TargetString = this.LayoutLines[tp.row]; - e.AutoAdjust = true; - } - else - { - e.TargetString = this.SelectedText; - if (e.TargetString.Length > 40) - e.TargetString.Remove(40); - } - e.CaretPostion = this.View.CaretLocation; - } - - void Ime_ImeQueryReconvert(object sender, ImeQueryRecovertStringEventArgs e) - { - TextPoint tp = this.LayoutLines.GetTextPointFromIndex(this.Controller.SelectionStart); - tp.col = e.offset; - - int index = this.View.GetIndexFromLayoutLine(tp); - - this.Select(index, index + e.length); - } - - void Controller_CaretMoved(object sender, EventArgs e) - { - this.SelectionChanged(this, null); - } - - void initScrollBars() - { - this.VScrollBar.SmallChange = 1; - this.VScrollBar.LargeChange = this.View.LineCountOnScreen; - this.VScrollBar.Maximum = this.View.LayoutLines.Count + this.View.LineCountOnScreen + 1; - this.HScrollBar.SmallChange = 10; - this.HScrollBar.LargeChange = (int)this.View.PageBound.Width; - this.HScrollBar.Maximum = this.HScrollBar.LargeChange + 1; - } - - void Timer_Tick(object sender,EventArgs e) - { - if (this.View.CaretPostion.row >= this.View.LayoutLines.Count || DesignMode) - return; - - ITextLayout layout = this.View.LayoutLines.GetLayout(this.View.CaretPostion.row); - - Size redrawSize = new Size(); - redrawSize.Width = layout.GetWidthFromIndex(this.View.CaretPostion.col); - if (redrawSize.Width == 0.0) - redrawSize.Width = this.View.CaretWidthOnInsertMode; - redrawSize.Height = layout.Height; - - bool updateAll = this.View.LayoutLines.HilightAll() || this.View.LayoutLines.GenerateFolding(); - - if (updateAll) - this.Invalidate(); - else - this.Invalidate(new System.Drawing.Rectangle(this.View.CaretLocation, redrawSize)); - } - - void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) - { - this.SetSystemParamaters(); - this.Refresh(); - } - - void SetSystemParamaters() - { - int CaretBlinkTime = SystemInformation.CaretBlinkTime; - if (CaretBlinkTime == -1) - { - this.View.CaretBlink = false; - if (this.IsHandleCreated) - this.BeginInvoke(new Action(() => - { - this.Timer.Stop(); - })); - } - else - { - this.View.CaretBlink = true; - this.View.CaretBlinkTime = CaretBlinkTime * 2; - if(this.IsHandleCreated) - this.BeginInvoke(new Action(() => - { - this.Timer.Start(); - })); - } - this.View.CaretWidthOnInsertMode = SystemInformation.CaretWidth; - } - - } - - /// - /// FooEditEngineで使用するマウスイベント - /// - public class FooMouseEventArgs : MouseEventArgs - { - /// - /// イベントが発生したインデックス - /// - public int index; - /// - /// 既定の処理を省略するなら真。そうでなければ偽 - /// - public bool Handled; - /// - /// コンストラクター - /// - /// インデックス - /// 押されているボタン - /// ボタンが押された回数 - /// マウスカーソルがあるX座標 - /// マウスカーソルがあるY座標 - /// ホイールの回転方向 - public FooMouseEventArgs(int index, MouseButtons button, int clicks, int x, int y, int delta) - : base(button, clicks, x, y, delta) - { - this.index = index; - } - } - -} +/* + * Copyright (C) 2013 FooProject + * * 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 + * the Free Software Foundation; either version 3 of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. If not, see . + */ +using System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Drawing; +using System.ComponentModel; +using Microsoft.Win32; + +namespace FooEditEngine.Windows +{ + /// + /// タブの幅が変更されたときに呼びされるデリゲート + /// + /// 送り主が属するクラス + /// イベントデータ + public delegate void TabStopChangeEventHandler(object sender, EventArgs e); + + /// + /// InsetModeが変更されたときに呼び出されるデリゲート + /// + /// 送り主が属するクラス + /// イベントデータ + public delegate void InsertModeChangeEventHandler(object sender, EventArgs e); + + /// + /// FooEditEngineを表します + /// + public class FooTextBox : Control + { + EditView View; + Controller Controller; + D2DTextRender render; + BorderStyle _BoderStyle; + HScrollBar HScrollBar; + VScrollBar VScrollBar; + WinIME Ime; + System.Windows.Forms.Timer Timer; + + const int Interval = 100; + + /// + /// コンストラクター + /// + public FooTextBox() + { + this.VScrollBar = new VScrollBar(); + this.VScrollBar.Scroll += new ScrollEventHandler(VScrollBar_Scroll); + this.VScrollBar.Dock = DockStyle.Right; + this.VScrollBar.Visible = true; + this.Controls.Add(this.VScrollBar); + + this.HScrollBar = new HScrollBar(); + this.HScrollBar.Scroll += new ScrollEventHandler(HScrollBar_Scroll); + this.HScrollBar.Dock = DockStyle.Bottom; + this.HScrollBar.Visible = true; + this.Controls.Add(this.HScrollBar); + + this.SetStyle(ControlStyles.ResizeRedraw, true); + this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); + this.SetStyle(ControlStyles.UserPaint, true); + this.SetStyle(ControlStyles.Opaque, true); + + this.render = new D2DTextRender(this); + this.Document = new Document(); + this.Document.LayoutLines.Render = this.render; + this.View = new EditView(this.Document, this.render, new FooEditEngine.Padding(5, 5, 5, 5)); + this.View.SrcChanged += View_SrcChanged; + + this.Controller = new Controller(this.Document, this.View); + this.Controller.SelectionChanged += new EventHandler(Controller_CaretMoved); + + this.Ime = new WinIME(this); + this.Ime.ImeCompstion += new ImeCompstionEventHandeler(Ime_ImeCompstion); + this.Ime.StartCompstion += new StartCompstionEventHandeler(Ime_StartCompstion); + this.Ime.EndCompstion += new EndCompstionEventHandeler(Ime_EndCompstion); + this.Ime.ImeDocumentFeed += new ImeDocumentFeedEventHandler(Ime_ImeDocumentFeed); + this.Ime.ImeReconvert += new ImeReconvertStringEventHandler(Ime_ImeReconvert); + this.Ime.ImeQueryReconvert += new ImeQueryReconvertStringEventHandler(Ime_ImeQueryReconvert); + + this.Timer = new System.Windows.Forms.Timer(); + this.Timer.Tick += new EventHandler(this.Timer_Tick); + this.Timer.Interval = Interval; + this.SetSystemParamaters(); + + this.TabStopChange += new TabStopChangeEventHandler((s, e) => { }); + this.InsetModeChange += new InsertModeChangeEventHandler((s, e) => { }); + this.SelectionChanged +=new EventHandler((s,e)=>{}); + + this.RightToLeftChanged += FooTextBox_RightToLeftChanged; + + SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged); + + } + + /// + /// キャレットが移動したときに通知されるイベント + /// + public event EventHandler SelectionChanged; + + /// + /// タブの幅が変更された時に発生するイベント + /// + public event TabStopChangeEventHandler TabStopChange; + + /// + /// InsertModeが変更されたときに呼び出されるイベント + /// + public event InsertModeChangeEventHandler InsetModeChange; + + /// + /// インデントモードを表す + /// + [DefaultValue(IndentMode.Tab)] + public IndentMode IndentMode + { + get + { + return this.Controller.IndentMode; + } + set + { + this.Controller.IndentMode = value; + } + } + + /// + /// テキスト描写に使用するアンチエイリアシングモードを表す + /// + [BrowsableAttribute(false)] + public TextAntialiasMode TextAntialiasMode + { + get + { + return this.render.TextAntialiasMode; + } + set + { + this.render.TextAntialiasMode = value; + } + } + + /// + /// マーカーパターンセットを表す + /// + [BrowsableAttribute(false)] + public MarkerPatternSet MarkerPatternSet + { + get + { + return this.View.MarkerPatternSet; + } + } + + /// + /// 保持しているドキュメント + /// + [BrowsableAttribute(false)] + public Document Document + { + get; + private set; + } + + /// + /// 保持しているレイアウト行 + /// + [BrowsableAttribute(false)] + public LineToIndexTable LayoutLines + { + get { return this.View.LayoutLines; } + } + + /// + /// シンタックスハイライター + /// + [BrowsableAttribute(false)] + public IHilighter Hilighter + { + get { return this.View.Hilighter; } + set { this.View.Hilighter = value; this.View.LayoutLines.ClearLayoutCache(); } + } + + /// + /// フォールティングを作成するインターフェイスを表す + /// + [BrowsableAttribute(false)] + public IFoldingStrategy FoldingStrategy + { + get + { + return this.View.LayoutLines.FoldingStrategy; + } + set + { + this.View.LayoutLines.FoldingStrategy = value; + if (value == null) + this.View.LayoutLines.FoldingCollection.Clear(); + } + } + + /// + /// 境界線のスタイルを指定します + /// + public BorderStyle BorderStyle + { + get { return this._BoderStyle; } + set { this._BoderStyle = value; this.UpdateStyles(); } + } + + + /// + /// 行番号を表示するかどうか + /// + [DefaultValue(false)] + public bool DrawLineNumber + { + get + { + return this.View.DrawLineNumber; + } + set + { + this.View.DrawLineNumber = value; + this.JumpCaret(this.CaretPostion.row,this.CaretPostion.col); + } + } + + /// + /// ルーラーを表示するかどうか + /// + [DefaultValue(false)] + public bool DrawRuler + { + get + { + return !this.View.HideRuler; + } + set + { + this.View.HideRuler = !value; + this.JumpCaret(this.CaretPostion.row, this.CaretPostion.col); + } + } + + /// + /// 桁折りを行う方法を指定する + /// + /// + /// 反映させるためにはレイアウト行の再構築を行う必要があります + /// + [DefaultValue(LineBreakMethod.None)] + public LineBreakMethod LineBreakMethod + { + get + { + return this.View.LineBreak; + } + set + { + this.View.LineBreak = value; + } + } + + /// + /// 桁折り時の文字数を指定する。 + /// + /// + /// 反映させるためにはレイアウト行の再構築を行う必要があります + /// + [DefaultValue(80)] + public int LineBreakCharCount + { + get + { + return this.View.LineBreakCharCount; + } + set + { + this.View.LineBreakCharCount = value; + } + } + + /// + /// URLをマークするかどうか + /// + [DefaultValue(false)] + public bool UrlMark + { + get + { + return this.View.UrlMark; + } + set + { + this.View.UrlMark = value; + } + } + + /// + /// タブストップの幅 + /// + [DefaultValue(4)] + public int TabStops + { + get { return this.View.TabStops; } + set { + this.View.TabStops = value; + this.View.AdjustCaretAndSrc(); + this.TabStopChange(this, null); + } + } + + /// + /// 全角スペースを表示するなら真。そうでないなら偽 + /// + [DefaultValue(false)] + public bool ShowFullSpace + { + get + { + return this.render.ShowFullSpace; + } + set + { + this.render.ShowFullSpace = value; + } + } + + /// + /// 半角スペースを表示するなら真。そうでないなら偽 + /// + [DefaultValue(false)] + public bool ShowHalfSpace + { + get + { + return this.render.ShowHalfSpace; + } + set + { + this.render.ShowHalfSpace = value; + } + } + + /// + /// タブを表示するなら真。そうでないなら偽 + /// + [DefaultValue(false)] + public bool ShowTab + { + get + { + return this.render.ShowTab; + } + set + { + this.render.ShowTab = value; + } + } + + /// + /// 改行マークを表示するなら真。そうでないなら偽 + /// + [DefaultValue(false)] + public bool ShowLineBreak + { + get + { + return this.render.ShowLineBreak; + } + set + { + this.render.ShowLineBreak = value; + } + } + + /// + /// 選択中の文字列 + /// + /// + /// 未選択状態で文字列を代入した場合、キャレット位置に挿入され、そうでないときは置き換えられます。 + /// + [BrowsableAttribute(false)] + public string SelectedText + { + get { return this.Controller.SelectedText; } + set { this.Controller.SelectedText = value; } + } + + /// + /// キャレット位置を表す + /// + [BrowsableAttribute(false)] + public TextPoint CaretPostion + { + get { return this.View.CaretPostion; } + } + + /// + /// 選択範囲を表す + /// + /// + /// Lengthが0の場合はキャレット位置を表します + /// 矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります + /// + [BrowsableAttribute(false)] + public TextRange Selection + { + get { return new TextRange(this.Controller.SelectionStart,this.Controller.SelectionLength); } + set + { + this.Controller.Select(value.Index, value.Length); + } + } + + /// + /// 挿入モードかどうか + /// + [DefaultValue(true)] + public bool InsertMode + { + get { return this.View.InsertMode; } + set + { + this.View.InsertMode = value; + this.InsetModeChange(this, null); + } + } + + /// + /// 矩形選択を行うかどうか + /// + [DefaultValue(false)] + public bool RectSelection + { + get { return this.Controller.RectSelection; } + set { this.Controller.RectSelection = value; } + } + + System.Drawing.Color ForegroundColor = SystemColors.ControlText, + BackgroundColor = SystemColors.Control, + HilightColor = System.Drawing.Color.DeepSkyBlue, + Keyword1Color = System.Drawing.Color.Blue, + Keyword2Color = System.Drawing.Color.DarkCyan, + LiteralColor = System.Drawing.Color.Brown, + UrlColor = System.Drawing.Color.Blue, + ControlCharColor = System.Drawing.Color.Gray, + CommentColor = System.Drawing.Color.Green, + InsertCaretColor = System.Drawing.Color.Black, + OverwriteCaretColor = System.Drawing.Color.Black, + LineMarkerColor = System.Drawing.Color.WhiteSmoke, + UpdateAreaColor = System.Drawing.Color.MediumSeaGreen, + LineNumberColor = System.Drawing.Color.DimGray; + + /// + /// 前景色 + /// + public System.Drawing.Color Foreground + { + get + { + return this.ForegroundColor; + } + set + { + this.render.Foreground = D2DTextRender.ToColor4(value); + this.ForegroundColor = value; + } + } + + /// + /// 背景色 + /// + public System.Drawing.Color Background + { + get + { + return this.BackgroundColor; + } + set + { + this.render.Background = D2DTextRender.ToColor4(value); + this.BackgroundColor = value; + } + } + + /// + /// 挿入モード時のキャレット色 + /// + public System.Drawing.Color InsertCaret + { + get + { + return this.InsertCaretColor; + } + set + { + this.InsertCaretColor = value; + this.render.InsertCaret = D2DTextRender.ToColor4(value); + } + } + + /// + /// 上書きモード時のキャレット色 + /// + public System.Drawing.Color OverwriteCaret + { + get + { + return this.OverwriteCaretColor; + } + set + { + this.OverwriteCaretColor = value; + this.render.OverwriteCaret = D2DTextRender.ToColor4(value); + } + } + + /// + /// ラインマーカーの色 + /// + public System.Drawing.Color LineMarker + { + get + { + return this.LineMarkerColor; + } + set + { + this.LineMarkerColor = value; + this.render.LineMarker = D2DTextRender.ToColor4(value); + } + } + + /// + /// コントロールの色 + /// + public System.Drawing.Color ControlChar + { + get + { + return this.ControlCharColor; + } + set + { + this.ControlCharColor = value; + this.render.ControlChar = D2DTextRender.ToColor4(value); + } + } + + /// + /// 編集行フラグの色 + /// + public System.Drawing.Color UpdateArea + { + get + { + return this.UpdateAreaColor; + } + set + { + this.UpdateAreaColor = value; + this.render.UpdateArea = D2DTextRender.ToColor4(value); + } + } + + /// + /// 行番号の色 + /// + public System.Drawing.Color LineNumber + { + get + { + return this.LineNumber; + } + set + { + this.LineNumber = value; + this.render.LineNumber = D2DTextRender.ToColor4(value); + } + } + + /// + /// URLの色 + /// + public System.Drawing.Color Url + { + get + { + return this.UrlColor; + } + set + { + this.UrlColor = value; + this.render.Url = D2DTextRender.ToColor4(value); + } + } + + /// + /// 選択領域の色 + /// + public System.Drawing.Color Hilight + { + get + { + return this.HilightColor; + } + set + { + this.HilightColor = value; + this.render.Hilight = D2DTextRender.ToColor4(value); + } + } + + /// + /// コメントの色 + /// + public System.Drawing.Color Comment + { + get + { + return this.CommentColor; + } + set + { + this.CommentColor = value; + this.render.Comment = D2DTextRender.ToColor4(value); + } + } + + /// + /// 文字リテラルの色 + /// + public System.Drawing.Color Literal + { + get + { + return this.LiteralColor; + } + set + { + this.LiteralColor = value; + this.render.Literal = D2DTextRender.ToColor4(value); + } + } + + /// + /// キーワード1の色 + /// + public System.Drawing.Color Keyword1 + { + get + { + return this.Keyword1Color; + } + set + { + this.Keyword1Color = value; + this.render.Keyword1 = D2DTextRender.ToColor4(value); + } + } + + /// + /// キーワード2の色 + /// + public System.Drawing.Color Keyword2 + { + get + { + return this.Keyword2Color; + } + set + { + this.Keyword2Color = value; + this.render.Keyword2 = D2DTextRender.ToColor4(value); + } + } + + /// + /// キャレットに下線を描くかどうか + /// + [DefaultValue(false)] + public bool DrawCaretLine + { + get { return !this.View.HideLineMarker; } + set { this.View.HideLineMarker = !value; } + } + + /// + /// ドキュメントを選択する + /// + /// 開始インデックス + /// 長さ + public void Select(int start, int length) + { + this.Controller.Select(start, length); + this.HScrollBar.Value = (int)this.View.Src.X; + this.VScrollBar.Value = this.View.Src.Row; + } + + /// + /// ドキュメント全体を選択する + /// + public void SelectAll() + { + this.Controller.Select(0, this.Document.Length - 1); + } + + /// + /// 選択を解除する + /// + public void DeSelectAll() + { + this.Controller.DeSelectAll(); + } + + /// + /// クリップボードにコピーする + /// + public void Copy() + { + string text = this.SelectedText; + if(text != null && text != string.Empty) + Clipboard.SetText(text); + } + + /// + /// クリップボードにコピーし、指定した範囲にある文字列をすべて削除します + /// + public void Cut() + { + string text = this.SelectedText; + if (text != null && text != string.Empty) + { + Clipboard.SetText(text); + this.Controller.SelectedText = ""; + } + } + + /// + /// クリップボードの内容をペーストします + /// + public void Paste() + { + if (Clipboard.ContainsText() == false) + return; + this.Controller.SelectedText = Clipboard.GetText(); + } + + /// + /// キャレットを指定した行に移動させます + /// + /// インデックス + /// このメソッドを呼び出すと選択状態は解除されます + public void JumpCaret(int index) + { + this.Controller.JumpCaret(index); + } + /// + /// キャレットを指定した行と桁に移動させます + /// + /// 行番号 + /// 桁 + /// このメソッドを呼び出すと選択状態は解除されます + public void JumpCaret(int row, int col) + { + this.Controller.JumpCaret(row, col); + } + + /// + /// 再描写します + /// + public new void Refresh() + { + if (this.Document.FireUpdateEvent == false) + throw new InvalidOperationException(""); + if(this.View.CaretBlink) + this.View.CaretBlink = true; + this.Invalidate(); + this.Update(); + } + + /// + /// 行の高さを取得する + /// + /// 行 + /// 高さ + public double GetLineHeight(int row) + { + if (this.Document.FireUpdateEvent == false) + throw new InvalidOperationException(""); + return this.View.LayoutLines.GetLayout(row).Height; + } + + /// + /// 対応する座標を返す + /// + /// テキストポイント + /// 座標 + /// テキストポイントがクライアント領域の原点より外にある場合、返される値は原点に丸められます + public System.Drawing.Point GetPostionFromTextPoint(TextPoint tp) + { + if (this.Document.FireUpdateEvent == false) + throw new InvalidOperationException(""); + return this.View.GetPostionFromTextPoint(tp); + } + + /// + /// 対応するテキストポイントを返す + /// + /// クライアント領域の原点を左上とする座標 + /// テキストポイント + public TextPoint GetTextPointFromPostion(System.Drawing.Point p) + { + if (this.Document.FireUpdateEvent == false) + throw new InvalidOperationException(""); + return this.View.GetTextPointFromPostion(p); + } + + /// + /// インデックスに対応する座標を得ます + /// + /// インデックス + /// 座標を返す + public System.Drawing.Point GetPostionFromIndex(int index) + { + if (this.Document.FireUpdateEvent == false) + throw new InvalidOperationException(""); + TextPoint tp = this.View.GetLayoutLineFromIndex(index); + return this.View.GetPostionFromTextPoint(tp); + } + + /// + /// 座標からインデックスに変換します + /// + /// 座標 + /// インデックスを返す + public int GetIndexFromPostion(System.Drawing.Point p) + { + if (this.Document.FireUpdateEvent == false) + throw new InvalidOperationException(""); + TextPoint tp = this.View.GetTextPointFromPostion(p); + return this.View.GetIndexFromLayoutLine(tp); + } + + /// + /// レイアウト行をすべて破棄し、再度レイアウトを行う + /// + public void PerfomLayouts() + { + this.View.PerfomLayouts(); + initScrollBars(); + } + + /// + /// ストリームからドキュメントを構築する + /// + /// TextReader + /// キャンセル用トークン + /// Taskオブジェクト + public async Task LoadAsync(System.IO.TextReader tr, System.Threading.CancellationTokenSource token) + { + WinFileReader fs = new WinFileReader(tr); + await this.LoadAsyncImpl(fs, token); + } + + /// + /// ファイルからドキュメントを構築する + /// + /// ファイルパス + /// エンコード + /// キャンセル用トークン + /// Taskオブジェクト + public async Task LoadFileAsync(string filepath, Encoding enc, System.Threading.CancellationTokenSource token) + { + WinFileReader fs = new WinFileReader(filepath, enc); + await this.LoadAsyncImpl(fs, token); + fs.Close(); + } + + async Task LoadAsyncImpl(WinFileReader fs, System.Threading.CancellationTokenSource token) + { + this.Enabled = false; + this.View.LayoutLines.IsFrozneDirtyFlag = true; + await this.Document.LoadAsync(fs, token); + this.View.LayoutLines.IsFrozneDirtyFlag = false; + this.initScrollBars(); + this.OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, MousePosition.X, MousePosition.Y, 0)); + this.View.CalculateLineCountOnScreen(); + this.Enabled = true; + } + + /// + /// ドキュメントの内容をファイルに保存する + /// + /// ファイルパス + /// 改行コード + /// エンコード + /// Taskオブジェクト + public async Task SaveFile(string filepath, Encoding enc, string newLine, System.Threading.CancellationTokenSource token) + { + WinFileWriter fs = new WinFileWriter(filepath, enc); + fs.NewLine = newLine; + await this.Document.SaveAsync(fs, token); + fs.Close(); + } + + /// + /// マウスカーソルを指定します + /// + public override Cursor Cursor + { + get + { + return base.Cursor; + } + set + { + base.Cursor = value; + this.VScrollBar.Cursor = DefaultCursor; + this.HScrollBar.Cursor = DefaultCursor; + } + } + + private const int WS_BORDER = 0x00800000; + private const int WS_EX_CLIENTEDGE = 0x00000200; + /// + /// コントロールの外観を指定します + /// + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + switch (this.BorderStyle) + { + case BorderStyle.Fixed3D: + cp.ExStyle |= WS_EX_CLIENTEDGE; + break; + case BorderStyle.FixedSingle: + cp.Style |= WS_BORDER; + break; + } + return cp; + } + } + + /// + /// コマンド キーを処理します + /// + /// メッセージ + /// キーデータ + /// 文字がコントロールによって処理された場合は true。それ以外の場合は false。 + protected override bool ProcessCmdKey(ref Message msg, Keys keyData) + { + const int WM_KEYDOWN = 0x100; + if (msg.Msg != WM_KEYDOWN) + return base.ProcessCmdKey(ref msg, keyData); + switch (keyData) + { + case Keys.Control | Keys.C: + this.Copy(); + break; + case Keys.Control | Keys.V: + this.Paste(); + this.Refresh(); + break; + case Keys.Control | Keys.X: + this.Cut(); + this.Refresh(); + break; + case Keys.Control | Keys.Z: + this.Document.UndoManager.undo(); + this.Refresh(); + break; + case Keys.Control | Keys.Y: + this.Document.UndoManager.redo(); + this.Refresh(); + break; + case Keys.Control | Keys.B: + if (this.Controller.RectSelection) + this.Controller.RectSelection = false; + else + this.Controller.RectSelection = true; + break; + default: + return base.ProcessCmdKey(ref msg,keyData); + } + return true; + } + + /// + /// インスタンスを破棄します + /// + /// マネージ リソースとアンマネージ リソースの両方を解放する場合は true。アンマネージ リソースだけを解放する場合は false。 + protected override void Dispose(bool disposing) + { + SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(this.SystemEvents_UserPreferenceChanged); + this.render.Dispose(); + this.Timer.Dispose(); + base.Dispose(disposing); + } + + /// + /// 入力可能な文字かチェックします + /// + /// 入力しようとした文字 + /// 可能なら真。そうでなければ偽 + protected override bool IsInputChar(char charCode) + { + if ((0x20 <= charCode && charCode <= 0x7e) + || charCode == '\r' + || charCode == '\n' + || charCode == ' ' + || charCode == '\t' + || charCode == ' ' + || 0x7f < charCode) + { + return true; + } + + return false; + } + + /// + /// PaddingChangedイベントを発生させます + /// + /// インベントデータ + protected override void OnPaddingChanged(EventArgs e) + { + base.OnPaddingChanged(e); + this.View.Padding = new Padding(this.Padding.Left, this.Padding.Top, this.Padding.Right, this.Padding.Bottom); + } + + /// + /// GotFocusイベントを発生させます + /// + /// インベントデータ + protected override void OnGotFocus(EventArgs e) + { + base.OnGotFocus(e); + this.View.IsFocused = true; + this.Refresh(); + } + + /// + /// LostFocusイベントを発生させます + /// + /// インベントデータ + protected override void OnLostFocus(EventArgs e) + { + base.OnLostFocus(e); + this.View.IsFocused = false; + this.Refresh(); + } + + /// + /// FontChangedイベントを発生させます + /// + /// インベントデータ + protected override void OnFontChanged(EventArgs e) + { + if (this.DesignMode) + return; + base.OnFontChanged(e); + initScrollBars(); + } + + /// + /// MouseDownイベントを発生させます + /// + /// インベントデータ + protected override void OnMouseDown(MouseEventArgs e) + { + TextPoint tp = this.View.GetTextPointFromPostion(e.Location); + if (tp == TextPoint.Null) + return; + int index = this.View.LayoutLines.GetIndexFromTextPoint(tp); + + FooMouseEventArgs mouseEvent = new FooMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); + + base.OnMouseDown(mouseEvent); + + if (mouseEvent.Handled) + return; + + if (e.Button == MouseButtons.Left) + { + FoldingItem foldingData = this.View.HitFoldingData(e.Location.X, tp.row); + if (foldingData != null) + { + if (foldingData.Expand) + this.View.LayoutLines.FoldingCollection.Collapse(foldingData); + else + this.View.LayoutLines.FoldingCollection.Expand(foldingData); + this.Controller.JumpCaret(foldingData.Start, false); + } + else + { + this.Controller.JumpCaret(tp.row, tp.col, false); + } + this.View.IsFocused = true; + this.Focus(); + this.Refresh(); + } + } + + /// + /// MouseClickイベントを発生させます + /// + /// インベントデータ + protected override void OnMouseClick(MouseEventArgs e) + { + int index = this.GetIndexFromPostion(e.Location); + + FooMouseEventArgs mouseEvent = new FooMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); + + base.OnMouseClick(mouseEvent); + } + + /// + /// MouseDoubleClickイベントを発生させます + /// + /// インベントデータ + protected override void OnMouseDoubleClick(MouseEventArgs e) + { + TextPoint tp = this.View.GetTextPointFromPostion(e.Location); + if (tp == TextPoint.Null) + return; + int index = this.View.LayoutLines.GetIndexFromTextPoint(tp); + + FooMouseEventArgs mouseEvent = new FooMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); + + base.OnMouseDoubleClick(mouseEvent); + + if (mouseEvent.Handled) + return; + + this.Controller.SelectWord(index); + + this.Refresh(); + } + + /// + /// MouseMoveイベントを発生させます + /// + /// インベントデータ + protected override void OnMouseMove(MouseEventArgs e) + { + if (this.Focused == false) + return; + + base.OnMouseMove(e); + + if (this.View.HitTextArea(e.Location.X, e.Location.Y)) + { + TextPoint tp = this.View.GetTextPointFromPostion(e.Location); + if (this.Controller.IsMarker(tp, HilightType.Url)) + this.Cursor = Cursors.Hand; + else + this.Cursor = Cursors.IBeam; + + if (e.Button == MouseButtons.Left) + { + this.Controller.MoveCaretAndSelect(tp); + this.Refresh(); + } + } + else + { + this.Cursor = Cursors.Arrow; + } + } + + /// + /// MouseWheelイベントを発生させます + /// + /// インベントデータ + protected override void OnMouseWheel(MouseEventArgs e) + { + base.OnMouseWheel(e); + + ScrollDirection dir = e.Delta > 0 ? ScrollDirection.Up : ScrollDirection.Down; + this.Controller.Scroll(dir, SystemInformation.MouseWheelScrollLines, false, false); + this.Refresh(); + } + + /// + /// Paintイベントを発生させます + /// + /// インベントデータ + protected override void OnPaint(PaintEventArgs e) + { + if (DesignMode) + { + SolidBrush brush = new SolidBrush(this.BackColor); + e.Graphics.FillRectangle(brush, this.ClientRectangle); + brush.Dispose(); + }else if (this.Document.FireUpdateEvent){ + this.render.BegineDraw(); + this.View.Draw(e.ClipRectangle); + this.render.EndDraw(); + } + base.OnPaint(e); + } + + /// + /// PaintBackgroundイベントを発生させます + /// + /// インベントデータ + protected override void OnPaintBackground(PaintEventArgs e) + { + } + + /// + /// PreviewKeyDownイベントを発生させます + /// + /// インベントデータ + protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e) + { + base.OnPreviewKeyDown(e); + switch (e.KeyCode) + { + case Keys.Up: + case Keys.Down: + case Keys.Left: + case Keys.Right: + case Keys.Tab: + e.IsInputKey = true; + break; + } + } + + /// + /// KeyDownイベントを発生させます + /// + /// インベントデータ + protected override void OnKeyDown(KeyEventArgs e) + { + base.OnKeyDown(e); + + if (e.Handled) + return; + + switch (e.KeyCode) + { + case Keys.Up: + this.Controller.MoveCaretVertical(-1, e.Shift); + this.Refresh(); + break; + case Keys.Down: + this.Controller.MoveCaretVertical(+1, e.Shift); + this.Refresh(); + break; + case Keys.Left: + this.Controller.MoveCaretHorizontical(-1, e.Shift, e.Control); + this.Refresh(); + break; + case Keys.Right: + this.Controller.MoveCaretHorizontical(1, e.Shift, e.Control); + this.Refresh(); + break; + case Keys.PageUp: + this.Controller.Scroll(ScrollDirection.Up, this.VScrollBar.LargeChange,e.Shift,true); + this.Refresh(); + break; + case Keys.PageDown: + this.Controller.Scroll(ScrollDirection.Down, this.VScrollBar.LargeChange,e.Shift,true); + this.Refresh(); + break; + case Keys.Insert: + if (this.InsertMode) + this.InsertMode = false; + else + this.InsertMode = true; + break; + case Keys.Delete: + this.Controller.DoDeleteAction(); + this.Refresh(); + break; + case Keys.Back: + this.Controller.DoBackSpaceAction(); + this.Refresh(); + break; + case Keys.Home: + if (e.Control) + this.Controller.JumpToHead(e.Shift); + else + this.Controller.JumpToLineHead(this.View.CaretPostion.row, e.Shift); + this.Refresh(); + break; + case Keys.End: + if (e.Control) + this.Controller.JumpToEnd(e.Shift); + else + this.Controller.JumpToLineEnd(this.View.CaretPostion.row, e.Shift); + this.Refresh(); + break; + case Keys.Tab: + if (this.Controller.SelectionLength == 0) + this.Controller.DoInputChar('\t'); + else if (e.Shift) + this.Controller.DownIndent(); + else + this.Controller.UpIndent(); + this.Refresh(); + break; + } + } + + /// + /// KeyPressイベントを発生させます + /// + /// インベントデータ + protected override void OnKeyPress(KeyPressEventArgs e) + { + base.OnKeyPress(e); + + if (e.Handled) + return; + + switch (e.KeyChar) + { + case '\r': + this.Controller.DoEnterAction(); + this.Refresh(); + break; + case '\t': + break; //OnKeyDownで処理しているので不要 + default: + if (IsInputChar(e.KeyChar) == false) + break; + this.Controller.DoInputChar(e.KeyChar); + this.Refresh(); + break; + } + } + + /// + /// ClientSizeChangedイベントを発生させます + /// + /// インベントデータ + protected override void OnClientSizeChanged(EventArgs e) + { + if (this.DesignMode) + return; + base.OnClientSizeChanged(e); + + this.View.PageBound = new Rectangle(0, + 0, + Math.Max(this.ClientRectangle.Width - this.VScrollBar.Width,0), + Math.Max(this.ClientRectangle.Height - this.HScrollBar.Height, 0)); + + initScrollBars(); + this.Refresh(); + } + + void View_SrcChanged(object sender, EventArgs e) + { + if (this.View.Src.Row > this.VScrollBar.Maximum) + this.VScrollBar.Maximum = this.View.Src.Row + this.View.LineCountOnScreen + 1; + + int srcX = (int)Math.Abs(this.View.Src.X); + if (srcX > this.HScrollBar.Maximum) + this.HScrollBar.Maximum = srcX + (int)this.View.PageBound.Width + 1; + + this.HScrollBar.Value = srcX; + + this.VScrollBar.Value = this.View.Src.Row; + } + + void FooTextBox_RightToLeftChanged(object sender, EventArgs e) + { + this.Document.RightToLeft = this.RightToLeft == System.Windows.Forms.RightToLeft.Yes; + } + + void VScrollBar_Scroll(object sender, ScrollEventArgs e) + { + this.View.TryScroll(this.View.Src.X, e.NewValue); + this.Refresh(); + } + + void HScrollBar_Scroll(object sender, ScrollEventArgs e) + { + int toX; + if (this.RightToLeft == System.Windows.Forms.RightToLeft.Yes) + toX = -e.NewValue; + else + toX = e.NewValue; + this.View.TryScroll(toX, this.View.Src.Row); + this.Refresh(); + } + + void Ime_StartCompstion(object sender, StartCompstionEventArgs e) + { + this.Ime.Font = this.Font; + System.Drawing.Point p = this.GetPostionFromIndex(this.Controller.SelectionStart); + float dpi; + this.render.GetDpi(out dpi, out dpi); + p.X = (int)(p.X * dpi / 96); + p.Y = (int)(p.Y * dpi / 96); + this.Ime.Location = p; + this.View.HideCaret = true; + } + + void Ime_EndCompstion(object sender, EndCompstionEventArgs e) + { + this.View.HideCaret = false; + } + + void Ime_ImeCompstion(object sender, ImeCompstionEventArgs e) + { + this.Controller.DoInputString(e.InputText); + this.Refresh(); + } + + void Ime_ImeDocumentFeed(object sender, ImeDocumentFeedEventArgs e) + { + TextPoint tp = this.CaretPostion; + e.Pragraph = this.LayoutLines[tp.row]; + e.pos = tp.col; + } + + void Ime_ImeReconvert(object sender, ImeReconvertStringEventArgs e) + { + if (this.RectSelection) + return; + if (this.Controller.SelectionLength == 0) + { + TextPoint tp = this.LayoutLines.GetTextPointFromIndex(this.Controller.SelectionStart); + e.TargetString = this.LayoutLines[tp.row]; + e.AutoAdjust = true; + } + else + { + e.TargetString = this.SelectedText; + if (e.TargetString.Length > 40) + e.TargetString.Remove(40); + } + e.CaretPostion = this.View.CaretLocation; + } + + void Ime_ImeQueryReconvert(object sender, ImeQueryRecovertStringEventArgs e) + { + TextPoint tp = this.LayoutLines.GetTextPointFromIndex(this.Controller.SelectionStart); + tp.col = e.offset; + + int index = this.View.GetIndexFromLayoutLine(tp); + + this.Select(index, index + e.length); + } + + void Controller_CaretMoved(object sender, EventArgs e) + { + this.SelectionChanged(this, null); + } + + void initScrollBars() + { + this.VScrollBar.SmallChange = 1; + this.VScrollBar.LargeChange = this.View.LineCountOnScreen; + this.VScrollBar.Maximum = this.View.LayoutLines.Count + this.View.LineCountOnScreen + 1; + this.HScrollBar.SmallChange = 10; + this.HScrollBar.LargeChange = (int)this.View.PageBound.Width; + this.HScrollBar.Maximum = this.HScrollBar.LargeChange + 1; + } + + void Timer_Tick(object sender,EventArgs e) + { + if (this.View.CaretPostion.row >= this.View.LayoutLines.Count || DesignMode) + return; + + ITextLayout layout = this.View.LayoutLines.GetLayout(this.View.CaretPostion.row); + + Size redrawSize = new Size(); + redrawSize.Width = layout.GetWidthFromIndex(this.View.CaretPostion.col); + if (redrawSize.Width == 0.0) + redrawSize.Width = this.View.CaretWidthOnInsertMode; + redrawSize.Height = layout.Height; + + bool updateAll = this.View.LayoutLines.HilightAll() || this.View.LayoutLines.GenerateFolding(); + + if (updateAll) + this.Invalidate(); + else + this.Invalidate(new System.Drawing.Rectangle(this.View.CaretLocation, redrawSize)); + } + + void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) + { + this.SetSystemParamaters(); + this.Refresh(); + } + + void SetSystemParamaters() + { + int CaretBlinkTime = SystemInformation.CaretBlinkTime; + if (CaretBlinkTime == -1) + { + this.View.CaretBlink = false; + if (this.IsHandleCreated) + this.BeginInvoke(new Action(() => + { + this.Timer.Stop(); + })); + } + else + { + this.View.CaretBlink = true; + this.View.CaretBlinkTime = CaretBlinkTime * 2; + if(this.IsHandleCreated) + this.BeginInvoke(new Action(() => + { + this.Timer.Start(); + })); + } + this.View.CaretWidthOnInsertMode = SystemInformation.CaretWidth; + } + + } + + /// + /// FooEditEngineで使用するマウスイベント + /// + public class FooMouseEventArgs : MouseEventArgs + { + /// + /// イベントが発生したインデックス + /// + public int index; + /// + /// 既定の処理を省略するなら真。そうでなければ偽 + /// + public bool Handled; + /// + /// コンストラクター + /// + /// インデックス + /// 押されているボタン + /// ボタンが押された回数 + /// マウスカーソルがあるX座標 + /// マウスカーソルがあるY座標 + /// ホイールの回転方向 + public FooMouseEventArgs(int index, MouseButtons button, int clicks, int x, int y, int delta) + : base(button, clicks, x, y, delta) + { + this.index = index; + } + } + +}