/* * 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.Runtime.InteropServices; using System.Windows; using System.Windows.Input; using System.Windows.Media; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Documents; using System.Windows.Interop; using System.Windows.Threading; using DotNetTextStore; using DotNetTextStore.UnmanagedAPI.TSF; using DotNetTextStore.UnmanagedAPI.WinDef; using Microsoft.Win32; namespace FooEditEngine.WPF { /// /// オートインデントを行うためのデリゲートを表す /// /// イベント発生元のオブジェクト /// イベントデーター public delegate void AutoIndentHookerHandler(object sender,EventArgs e); /// /// WPFでのFooTextBoxの実装 /// public sealed class FooTextBox : Control, IDisposable { const double MaxFontSize = 72.0f; const double MinFontSize = 1; EditView View; Controller _Controller; D2DRender Render; Image image; ScrollBar verticalScrollBar, horizontalScrollBar; TextStore textStore; DispatcherTimer timer; bool disposed = false; FooTextBoxAutomationPeer peer; bool nowCaretMove = false; static FooTextBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(typeof(FooTextBox))); KeyboardNavigation.IsTabStopProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(true)); KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(FooTextBox), new FrameworkPropertyMetadata(KeyboardNavigationMode.None)); } /// /// コンストラクター /// public FooTextBox() { this.image = new Image(); this.image.Stretch = Stretch.Fill; this.image.HorizontalAlignment = HorizontalAlignment.Left; this.image.VerticalAlignment = VerticalAlignment.Top; this.textStore = new TextStore(); this.textStore.IsLoading += textStore_IsLoading; this.textStore.IsReadOnly += textStore_IsReadOnly; this.textStore.GetStringLength += () => this.Document.Length; this.textStore.GetString += _textStore_GetString; this.textStore.GetSelectionIndex += _textStore_GetSelectionIndex; this.textStore.SetSelectionIndex += _textStore_SetSelectionIndex; this.textStore.InsertAtSelection += _textStore_InsertAtSelection; this.textStore.GetHWnd += _textStore_GetHWnd; this.textStore.GetScreenExtent += _textStore_GetScreenExtent; this.textStore.GetStringExtent += _textStore_GetStringExtent; this.textStore.CompositionStarted += textStore_CompositionStarted; this.textStore.CompositionUpdated += textStore_CompositionUpdated; this.textStore.CompositionEnded += textStore_CompositionEnded; this.Document = new Document(); DocumentExtend.Progress += new EventHandler(Document_Progress); this.Render = new D2DRender(this, 200, 200,this.image); this.Render.ShowFullSpace = this.ShowFullSpace; this.Render.ShowHalfSpace = this.ShowHalfSpace; this.Render.ShowTab = this.ShowTab; this.View = new EditView(this.Document, this.Render,new Padding(5,5,5,5)); this.View.SrcChanged += View_SrcChanged; this.View.InsertMode = this.InsertMode; this.View.DrawLineNumber = this.DrawLineNumber; this.View.HideCaret = !this.DrawCaret; this.View.HideLineMarker = !this.DrawCaretLine; this.View.HideRuler = !this.DrawRuler; this.View.UrlMark = this.MarkURL; this.View.TabStops = this.TabChars; this._Controller = new Controller(this.Document, this.View); this._Controller.SelectionChanged += new EventHandler(Controller_SelectionChanged); //Viewを作成した後に追加しないと例外が発生する this.Document.Update += new DocumentUpdateEventHandler(Document_Update); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Copy, CopyCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Cut, CutCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, PasteCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete, DeleteCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.SelectAll, SelectAllCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, UndoCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, RedoCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(EditingCommands.ToggleInsert, ToggleInsertCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(FooTextBoxCommands.ToggleRectSelectMode, ToggleRectSelectCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(FooTextBoxCommands.ToggleFlowDirection, ToggleFlowDirectionCommand, CanExecute)); this.CommandBindings.Add(new CommandBinding(FooTextBoxCommands.ToggleCodePoint, ToggleCodePointCommand, CanExecute)); this.InputBindings.Add(new InputBinding(ApplicationCommands.Copy, new KeyGesture(Key.C, ModifierKeys.Control))); this.InputBindings.Add(new InputBinding(ApplicationCommands.Cut, new KeyGesture(Key.X, ModifierKeys.Control))); this.InputBindings.Add(new InputBinding(ApplicationCommands.Paste, new KeyGesture(Key.V, ModifierKeys.Control))); this.InputBindings.Add(new InputBinding(ApplicationCommands.Delete, new KeyGesture(Key.Delete, ModifierKeys.None))); this.InputBindings.Add(new InputBinding(ApplicationCommands.SelectAll, new KeyGesture(Key.A, ModifierKeys.Control))); this.InputBindings.Add(new InputBinding(ApplicationCommands.Undo, new KeyGesture(Key.Z, ModifierKeys.Control))); this.InputBindings.Add(new InputBinding(ApplicationCommands.Redo, new KeyGesture(Key.Y, ModifierKeys.Control))); this.InputBindings.Add(new InputBinding(EditingCommands.ToggleInsert, new KeyGesture(Key.Insert, ModifierKeys.None))); this.InputBindings.Add(new InputBinding(FooTextBoxCommands.ToggleCodePoint, new KeyGesture(Key.X, ModifierKeys.Alt))); this.timer = new DispatcherTimer(); this.timer.Interval = new TimeSpan(0, 0, 0, 0, 100); this.timer.Tick += new EventHandler(timer_Tick); this.Loaded += new RoutedEventHandler(FooTextBox_Loaded); this.AutoIndentHooker = (s,e)=>{}; SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged); this.SystemEvents_UserPreferenceChanged(null, new UserPreferenceChangedEventArgs(UserPreferenceCategory.Keyboard)); this.CaretMoved += (s, e) => { }; } /// /// ファイナライザー /// ~FooTextBox() { //Dispose(false)を呼び出すと落ちる this.Dispose(false); } /// /// オートインデントを行うためのイベント /// public AutoIndentHookerHandler AutoIndentHooker; /// /// テンプレートを適用します /// public override void OnApplyTemplate() { base.OnApplyTemplate(); Grid grid = this.GetTemplateChild("PART_Grid") as Grid; if (grid != null) { Grid.SetRow(this.image, 0); Grid.SetColumn(this.image, 0); grid.Children.Add(this.image); } this.horizontalScrollBar = this.GetTemplateChild("PART_HorizontalScrollBar") as ScrollBar; if (this.horizontalScrollBar != null) { this.horizontalScrollBar.SmallChange = 10; this.horizontalScrollBar.LargeChange = 100; this.horizontalScrollBar.Maximum = this.horizontalScrollBar.LargeChange + 1; this.horizontalScrollBar.Scroll += new ScrollEventHandler(horizontalScrollBar_Scroll); } this.verticalScrollBar = this.GetTemplateChild("PART_VerticalScrollBar") as ScrollBar; if (this.verticalScrollBar != null) { this.verticalScrollBar.SmallChange = 1; this.verticalScrollBar.LargeChange = 10; this.verticalScrollBar.Maximum = this.View.LayoutLines.Count; this.verticalScrollBar.Scroll += new ScrollEventHandler(verticalScrollBar_Scroll); } } /// /// ドキュメントを選択する /// /// 開始インデックス /// 長さ public void Select(int start, int length) { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); this._Controller.Select(start, length); this.textStore.NotifySelectionChanged(); } /// /// キャレットを指定した行に移動させます /// /// インデックス /// このメソッドを呼び出すと選択状態は解除されます public void JumpCaret(int index) { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); this._Controller.JumpCaret(index); } /// /// キャレットを指定した行と桁に移動させます /// /// 行番号 /// 桁 /// このメソッドを呼び出すと選択状態は解除されます public void JumpCaret(int row, int col) { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); this._Controller.JumpCaret(row, col); } /// /// 選択中のテキストをクリップボードにコピーします /// public void Copy() { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); string text = this._Controller.SelectedText; if (text != null && text != string.Empty) Clipboard.SetText(text); } /// /// 選択中のテキストをクリップボードに切り取ります /// public void Cut() { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); string text = this._Controller.SelectedText; if (text != null && text != string.Empty) { Clipboard.SetText(text); this._Controller.SelectedText = ""; } } /// /// 選択中のテキストを貼り付けます /// public void Paste() { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); if (Clipboard.ContainsText() == false) return; string text = Clipboard.GetText(); this._Controller.SelectedText = text; } /// /// 選択を解除する /// public void DeSelectAll() { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); this._Controller.DeSelectAll(); this.textStore.NotifySelectionChanged(); } /// /// 対応する座標を返します /// /// テキストポイント /// 座標 /// テキストポイントがクライアント領域の原点より外にある場合、返される値は原点に丸められます public System.Windows.Point GetPostionFromTextPoint(TextPoint tp) { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); if (this.Document.FireUpdateEvent == false) throw new InvalidOperationException(""); return this.View.GetPostionFromTextPoint(tp); } /// /// 対応するテキストポイントを返します /// /// クライアント領域の原点を左上とする座標 /// テキストポイント public TextPoint GetTextPointFromPostion(System.Windows.Point p) { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); if (this.Document.FireUpdateEvent == false) throw new InvalidOperationException(""); return this.View.GetTextPointFromPostion(p); } /// /// 行の高さを取得します /// /// レイアウト行 /// 行の高さ public double GetLineHeight(int row) { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); if (this.Document.FireUpdateEvent == false) throw new InvalidOperationException(""); return this.View.LayoutLines.GetLayout(row).Height;; } /// /// インデックスに対応する座標を得ます /// /// インデックス /// 座標を返す public System.Windows.Point GetPostionFromIndex(int index) { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); if (this.Document.FireUpdateEvent == false) throw new InvalidOperationException(""); TextPoint tp = this.View.GetLayoutLineFromIndex(index); return this.View.GetPostionFromTextPoint(tp); } /// /// 座標からインデックスに変換します /// /// 座標 /// インデックスを返す public int GetIndexFromPostion(System.Windows.Point p) { if (this.Document.State == AsyncState.Loading) throw new InvalidOperationException(); if (this.Document.FireUpdateEvent == false) throw new InvalidOperationException(""); TextPoint tp = this.View.GetTextPointFromPostion(p); return this.View.GetIndexFromLayoutLine(tp); } /// /// 再描写する /// public void Refresh() { this.Refresh(this.View.PageBound); } /// /// レイアウト行をすべて破棄し、再度レイアウトを行う /// public void PerfomLayouts() { this.View.PerfomLayouts(); } /// /// アンマネージドリソースを開放する /// public void Dispose() { if (this.disposed) return; this.Dispose(true); GC.SuppressFinalize(this); this.disposed = true; } /// /// リソースを開放する /// /// 真ならマネージドリソースも開放し、そうでないならアンマネージドリソースのみを開放する void Dispose(bool disposing) { if (disposing) { this.textStore.Dispose(); this.timer.Stop(); this.View.Dispose(); this.Render.Dispose(); } SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged); DocumentExtend.Progress -= this.Document_Progress; } void Refresh(Rectangle updateRect) { if (this.disposed) return; this.timer.Stop(); this.Render.BegineDraw(); if (this.Document.State != AsyncState.Loading) this.View.Draw(updateRect); else this.Render.FillBackground(updateRect); this.Render.EndDraw(); this.timer.Start(); } #region Commands void CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = this.Document.State != FooEditEngine.AsyncState.Loading; } void ToggleCodePointCommand(object sender, RoutedEventArgs e) { if (!this._Controller.ConvertToChar()) this._Controller.ConvertToCodePoint(); this.Refresh(); } void CopyCommand(object sender, RoutedEventArgs e) { this.Copy(); } void CutCommand(object sender, RoutedEventArgs e) { this.Cut(); this.Refresh(); } void PasteCommand(object sender, RoutedEventArgs e) { this.Paste(); this.Refresh(); } void DeleteCommand(object sender, RoutedEventArgs e) { int oldLength = this.Document.Length; this._Controller.DoDeleteAction(); this.Refresh(); } void SelectAllCommand(object sender, RoutedEventArgs e) { this.Select(0, this.Document.Length); this.Refresh(); } void UndoCommand(object sender, RoutedEventArgs e) { int oldLength = this.Document.Length; this.Document.UndoManager.undo(); this.Refresh(); } void RedoCommand(object sender, RoutedEventArgs e) { int oldLength = this.Document.Length; this.Document.UndoManager.redo(); this.Refresh(); } void ToggleInsertCommand(object sender, RoutedEventArgs e) { if (this.InsertMode) this.InsertMode = false; else this.InsertMode = true; this.Refresh(); } void ToggleRectSelectCommand(object sender, RoutedEventArgs e) { if (this.RectSelectMode) this.RectSelectMode = false; else this.RectSelectMode = true; this.Refresh(); } void ToggleFlowDirectionCommand(object sender, RoutedEventArgs e) { if (this.FlowDirection == System.Windows.FlowDirection.LeftToRight) this.FlowDirection = System.Windows.FlowDirection.RightToLeft; else this.FlowDirection = System.Windows.FlowDirection.LeftToRight; this.Refresh(); } #endregion #region TSF internal TextStore TextStore { get { return this.textStore; } } bool textStore_IsReadOnly() { return false; } bool textStore_IsLoading() { return this.Document.State == AsyncState.Loading; } void textStore_CompositionEnded() { TextStoreHelper.EndCompostion(this.Document); this.Refresh(); } void textStore_CompositionUpdated(int start, int end) { if (TextStoreHelper.ScrollToCompstionUpdated(this.textStore, this.View, start, end)) this.Refresh(); } bool textStore_CompositionStarted() { bool result = TextStoreHelper.StartCompstion(this.Document); if (!result) System.Media.SystemSounds.Beep.Play(); return result; } string _textStore_GetString(int start, int length) { return this.Document.ToString(start, length); } IntPtr _textStore_GetHWnd() { var hwndSource = HwndSource.FromVisual(this) as HwndSource; if (hwndSource != null) return hwndSource.Handle; else return IntPtr.Zero; } void _textStore_GetStringExtent( int i_startIndex, int i_endIndex, out POINT o_topLeft, out POINT o_bottomRight ) { Point startPos, endPos; TextStoreHelper.GetStringExtent(this.Document, this.View, i_startIndex, i_endIndex, out startPos, out endPos); startPos = PointToScreen(this.TranslatePoint(startPos, this)); endPos = PointToScreen(this.TranslatePoint(endPos, this)); o_topLeft = new POINT((int)startPos.X, (int)startPos.Y); o_bottomRight = new POINT((int)endPos.X, (int)endPos.Y); } void _textStore_GetScreenExtent(out POINT o_topLeft, out POINT o_bottomRight) { var pointTopLeft = new Point(0, 0); var pointBottomRight = new Point(this.RenderSize.Width, this.RenderSize.Height); pointTopLeft = PointToScreen(pointTopLeft); pointBottomRight = PointToScreen(pointBottomRight); o_topLeft = new POINT((int)pointTopLeft.X, (int)pointTopLeft.Y); o_bottomRight = new POINT((int)pointBottomRight.X, (int)pointBottomRight.Y); } void _textStore_GetSelectionIndex(out int o_startIndex, out int o_endIndex) { TextStoreHelper.GetSelection(this._Controller, this.View.Selections, out o_startIndex, out o_endIndex); } void _textStore_SetSelectionIndex(int i_startIndex, int i_endIndex) { if (this.Document.State == AsyncState.Loading) return; TextStoreHelper.SetSelectionIndex(this._Controller, this.View, i_startIndex, i_endIndex); this.Refresh(); } void _textStore_InsertAtSelection(string i_value) { TextStoreHelper.InsertTextAtSelection(this._Controller, i_value); this.Refresh(); } /// /// キーボードフォーカスが取得されたときに呼ばれます /// /// イベントデーター protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) { base.OnGotKeyboardFocus(e); this.textStore.SetFocus(); this.View.IsFocused = true; this.Refresh(); } /// /// キーボードフォーカスが失われたときに呼ばれます /// /// イベントデーター protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) { base.OnLostKeyboardFocus(e); this.View.IsFocused = false; this.Refresh(); } #endregion #region Event /// /// キャレットが移動したときに通知されるイベント /// public event EventHandler CaretMoved; /// protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { this.peer = new FooTextBoxAutomationPeer(this); return this.peer; } /// protected override void OnTextInput(TextCompositionEventArgs e) { if (this.Document.State == AsyncState.Loading) return; if (e.Text == "\r") { this._Controller.DoEnterAction(); this.AutoIndentHooker(this, null); } else if (e.Text == "\b") { this._Controller.DoBackSpaceAction(); } else { if(this.IsInputString(e.Text)) this._Controller.DoInputString(e.Text); } this.Refresh(); base.OnTextInput(e); e.Handled = true; } bool IsInputString(string s) { foreach (char charCode in s) { if ((0x20 <= charCode && charCode <= 0x7e) || 0x7f < charCode) return true; } return false; } /// protected override void OnKeyDown(KeyEventArgs e) { if (this.Document.State == AsyncState.Loading) return; if (this.textStore.IsLocked()) return; ModifierKeys modiferKeys = e.KeyboardDevice.Modifiers; bool movedCaret = false; switch (e.Key) { case Key.Up: this._Controller.MoveCaretVertical(-1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift)); this.Refresh(); e.Handled = true; movedCaret = true; break; case Key.Down: this._Controller.MoveCaretVertical(+1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift)); this.Refresh(); e.Handled = true; movedCaret = true; break; case Key.Left: this._Controller.MoveCaretHorizontical(-1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift), this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control)); this.Refresh(); e.Handled = true; movedCaret = true; break; case Key.Right: this._Controller.MoveCaretHorizontical(1, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift), this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control)); this.Refresh(); e.Handled = true; movedCaret = true; break; case Key.PageUp: this._Controller.Scroll(ScrollDirection.Up,this.View.LineCountOnScreen, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift),true); this.Refresh(); movedCaret = true; break; case Key.PageDown: this._Controller.Scroll(ScrollDirection.Down,this.View.LineCountOnScreen, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift),true); this.Refresh(); movedCaret = true; break; case Key.Home: if (this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control)) this._Controller.JumpToHead(this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift)); else this._Controller.JumpToLineHead(this.View.CaretPostion.row, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift)); this.Refresh(); movedCaret = true; break; case Key.End: if (this.IsPressedModifierKey(modiferKeys, ModifierKeys.Control)) this._Controller.JumpToEnd(this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift)); else this._Controller.JumpToLineEnd(this.View.CaretPostion.row, this.IsPressedModifierKey(modiferKeys, ModifierKeys.Shift)); this.Refresh(); movedCaret = true; break; case Key.Tab: int oldLength = this.Document.Length; if (this.Selection.Length == 0) this._Controller.DoInputChar('\t'); else if(this.IsPressedModifierKey(modiferKeys,ModifierKeys.Shift)) this._Controller.DownIndent(); else this._Controller.UpIndent(); this.Refresh(); e.Handled = true; break; } if (movedCaret && this.peer != null) this.peer.OnNotifyCaretChanged(); base.OnKeyDown(e); } bool IsPressedModifierKey(ModifierKeys keys, ModifierKeys pressed) { if (keys == pressed) return true; if ((keys & pressed) == pressed) return true; return false; } /// /// ダブルクリックされたときに呼ばれます /// /// イベントパラメーター /// /// イベントパラメーターはFooMouseEventArgsにキャスト可能です。 /// e.Handledを真にした場合、単語単位の選択が行われなくなります /// protected override void OnMouseDoubleClick(MouseButtonEventArgs e) { if (this.Document.State == AsyncState.Loading) return; System.Windows.Point p = e.GetPosition(this); TextPoint tp = this.View.GetTextPointFromPostion(p); if (tp == TextPoint.Null) return; int index = this.View.LayoutLines.GetIndexFromTextPoint(tp); FooMouseButtonEventArgs newEventArgs = new FooMouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton, e.StylusDevice, index); newEventArgs.RoutedEvent = e.RoutedEvent; base.OnMouseDoubleClick(newEventArgs); if (newEventArgs.Handled) return; if (e.LeftButton == MouseButtonState.Pressed) { this._Controller.SelectWord(index); this.textStore.NotifySelectionChanged(); if(this.peer != null) this.peer.OnNotifyCaretChanged(); this.Refresh(); } } /// /// マウスボタンが押されたときに呼ばれます /// /// イベントパラメーター /// /// イベントパラメーターはFooMouseEventArgsにキャスト可能です。 /// e.Handledを真にした場合、キャレットの移動処理が行われなくなります /// protected override void OnMouseDown(MouseButtonEventArgs e) { if (this.Document.State == AsyncState.Loading) return; System.Windows.Point p = e.GetPosition(this); TextPoint tp = this.View.GetTextPointFromPostion(p); if (tp == TextPoint.Null) return; int index = this.View.LayoutLines.GetIndexFromTextPoint(tp); FooMouseButtonEventArgs newEventArgs = new FooMouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton, e.StylusDevice, index); newEventArgs.RoutedEvent = e.RoutedEvent; base.OnMouseDown(newEventArgs); if (newEventArgs.Handled) return; if (e.LeftButton == MouseButtonState.Pressed) { FoldingItem foldingData = this.View.HitFoldingData(p.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); } if (this.peer != null) this.peer.OnNotifyCaretChanged(); this.View.IsFocused = true; this.Refresh(); } } /// /// マウスが移動したときに呼ばれます /// /// イベントパラメーター /// /// イベントパラメーターはFooMouseEventArgsにキャスト可能です。 /// e.Handledを真にした場合、選択処理と状況に応じたカーソルの変化が行われなくなります /// protected override void OnMouseMove(MouseEventArgs e) { if (this.Document.State == AsyncState.Loading) { this.Cursor = Cursors.Wait; base.OnMouseMove(e); return; } System.Windows.Point p = e.GetPosition(this); TextPoint tp = this.View.GetTextPointFromPostion(p); if (tp == TextPoint.Null) { base.OnMouseMove(e); return; } int index = this.View.GetIndexFromLayoutLine(tp); FooMouseEventArgs newEventArgs = new FooMouseEventArgs(e.MouseDevice, e.Timestamp, e.StylusDevice, index); newEventArgs.RoutedEvent = e.RoutedEvent; base.OnMouseMove(newEventArgs); if (newEventArgs.Handled) return; if (this.View.HitTextArea(p.X,p.Y)) { if (this._Controller.IsMarker(tp, HilightType.Url)) this.Cursor = Cursors.Hand; else this.Cursor = Cursors.IBeam; if (e.LeftButton == MouseButtonState.Pressed) { this._Controller.MoveCaretAndSelect(tp); if (this.peer != null) this.peer.OnNotifyCaretChanged(); this.Refresh(); } } else { this.Cursor = Cursors.Arrow; } } /// protected override void OnMouseWheel(MouseWheelEventArgs e) { if (this.Document.State == AsyncState.Loading) return; if(Keyboard.Modifiers == ModifierKeys.None) { if (e.Delta > 0) this._Controller.Scroll(ScrollDirection.Up, SystemParameters.WheelScrollLines, false, false); else this._Controller.Scroll(ScrollDirection.Down, SystemParameters.WheelScrollLines, false, false); } else if (Keyboard.Modifiers == ModifierKeys.Control) { double newFontSize = this.Render.FontSize; if (e.Delta > 0) newFontSize++; else newFontSize--; if (newFontSize > MaxFontSize) newFontSize = 72; else if (newFontSize < MinFontSize) newFontSize = 1; this.Render.FontSize = newFontSize; SetValue(MagnificationPowerPropertyKey, this.Render.FontSize / this.FontSize); } this.Refresh(); base.OnMouseWheel(e); } void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) { if (e.Category == UserPreferenceCategory.Keyboard) { int blinkTime = (int)NativeMethods.GetCaretBlinkTime(); this.View.CaretBlink = blinkTime >= 0; this.View.CaretBlinkTime = blinkTime * 2; } if (e.Category == UserPreferenceCategory.General) { this.View.CaretWidthOnInsertMode = SystemParameters.CaretWidth; } } void Document_Update(object sender, DocumentUpdateEventArgs e) { if (this.textStore.IsLocked() || e.type == UpdateType.Clear) return; TextStoreHelper.NotifyTextChanged(this.textStore, this.Document); } void Document_Progress(object sender, ProgressEventArgs e) { if (this.Document.State == AsyncState.Loading) return; switch (e.state) { case ProgressState.Start: TextStoreHelper.NotifyTextChanged(this.textStore, this.Document); break; case ProgressState.Complete: TextStoreHelper.NotifyTextChanged(this.textStore, this.Document); this.OnMouseMove(new MouseEventArgs(Mouse.PrimaryDevice, new TimeSpan(DateTime.Now.Ticks).Milliseconds)); if(this.verticalScrollBar != null) this.verticalScrollBar.Maximum = this.View.LayoutLines.Count; this.View.CalculateLineCountOnScreen(); break; } } void timer_Tick(object sender, EventArgs e) { if (this.image.ActualWidth == 0 || this.image.ActualHeight == 0) return; if (this.Document.State == AsyncState.Loading || this.Resize(this.image.ActualWidth, this.image.ActualHeight)) { this.Refresh(); return; } ITextLayout layout = this.View.LayoutLines.GetLayout(this.View.CaretPostion.row); double width = layout.GetWidthFromIndex(this.View.CaretPostion.col); if (width == 0.0) width = this.View.CaretWidthOnInsertMode; double height = layout.Height; Rectangle updateRect = new Rectangle( this.View.CaretLocation.X, this.View.CaretLocation.Y, width, height); this.Refresh(updateRect); } void horizontalScrollBar_Scroll(object sender, ScrollEventArgs e) { if (this.Document.State == AsyncState.Loading) return; if (this.horizontalScrollBar == null) return; double toX; if (this.FlowDirection == System.Windows.FlowDirection.LeftToRight) toX = this.horizontalScrollBar.Value; else toX = -this.horizontalScrollBar.Value; this._Controller.Scroll(toX, this.View.Src.Row, false, false); this.Refresh(); } void verticalScrollBar_Scroll(object sender, ScrollEventArgs e) { if (this.Document.State == AsyncState.Loading) return; if (this.verticalScrollBar == null) return; int newRow = (int)this.verticalScrollBar.Value; if (newRow >= this.View.LayoutLines.Count) return; this._Controller.Scroll(this.View.Src.X,newRow, false, false); this.Refresh(); } void View_SrcChanged(object sender, EventArgs e) { if (this.horizontalScrollBar == null || this.verticalScrollBar == null) return; EditView view = this.View; if (view.Src.Row > this.verticalScrollBar.Maximum) this.verticalScrollBar.Maximum = view.Src.Row + view.LineCountOnScreen + 1; double absoulteX = Math.Abs(view.Src.X); if(absoulteX > this.horizontalScrollBar.Maximum) this.horizontalScrollBar.Maximum = absoulteX + view.PageBound.Width + 1; if(view.Src.Row != this.verticalScrollBar.Value) this.verticalScrollBar.Value = view.Src.Row; if (view.Src.X != this.horizontalScrollBar.Value) this.horizontalScrollBar.Value = Math.Abs(view.Src.X); } void Controller_SelectionChanged(object sender, EventArgs e) { this.View.CaretBlink = this.View.CaretBlink; this.CaretMoved(this, null); //こうしないと選択できなくなってしまう this.nowCaretMove = true; SetValue(SelectionProperty, new TextRange(this._Controller.SelectionStart, this._Controller.SelectionLength)); SetValue(CaretPostionProperty, this.View.CaretPostion); this.nowCaretMove = false; if(this.textStore.IsLocked() == false) this.textStore.NotifySelectionChanged(); } void FooTextBox_Loaded(object sender, RoutedEventArgs e) { this.Resize(this.image.ActualWidth, this.image.ActualHeight); } bool Resize(double width, double height) { if (width == 0 || height == 0) throw new ArgumentOutOfRangeException(); if (this.Render.Resize(width, height) && this.Document.State != AsyncState.Loading) { this.View.PageBound = new Rectangle(0, 0, width, height); if (this.horizontalScrollBar != null) { this.horizontalScrollBar.LargeChange = this.View.PageBound.Width; this.horizontalScrollBar.Maximum = this.View.LongestWidth + this.horizontalScrollBar.LargeChange + 1; } if (this.verticalScrollBar != null) { this.verticalScrollBar.LargeChange = this.View.LineCountOnScreen; this.verticalScrollBar.Maximum = this.View.LayoutLines.Count + this.verticalScrollBar.LargeChange + 1; } return true; } return false; } /// /// プロパティーが変更されたときに呼ばれます /// /// イベントパラメーター protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { switch (e.Property.Name) { case "Selection": if(!this.nowCaretMove) this.Select(this.Selection.Index, this.Selection.Length); break; case "CaretPostion": if (!this.nowCaretMove) this.JumpCaret(this.CaretPostion.row, this.CaretPostion.col); break; case "LineBreakMethod": this.View.LineBreak = this.LineBreakMethod; break; case "LineBreakCharCount": this.View.LineBreakCharCount = this.LineBreakCharCount; break; case "InsertMode": this.View.InsertMode = this.InsertMode; break; case "TabChars": this.View.TabStops = this.TabChars; break; case "RectSelectMode": this._Controller.RectSelection = this.RectSelectMode; break; case "DrawCaret": this.View.HideCaret = !this.DrawCaret; break; case "DrawCaretLine": this.View.HideLineMarker = !this.DrawCaretLine; break; case "DrawLineNumber": this.View.DrawLineNumber = this.DrawLineNumber; this._Controller.JumpCaret(this.View.CaretPostion.row, this.View.CaretPostion.col); break; case "FontFamily": this.Render.FontFamily = this.FontFamily; break; case "FontSize": this.Render.FontSize = this.FontSize; break; case "FontStyle": this.Render.FontStyle = this.FontStyle; break; case "FontWeight": this.Render.FontWeigth = this.FontWeight; break; case "Foreground": this.Render.Foreground = this.Foreground; break; case "Background": this.Render.Background = this.Background; break; case "ControlChar": this.Render.ControlChar = this.ControlChar; break; case "Hilight": this.Render.Hilight = this.Hilight; break; case "Keyword1": this.Render.Keyword1 = this.Keyword1; break; case "Keyword2": this.Render.Keyword2 = this.Keyword2; break; case "Comment": this.Render.Comment = this.Comment; break; case "Literal": this.Render.Literal = this.Literal; break; case "URL": this.Render.Url = this.URL; break; case "InsertCaret": this.Render.InsertCaret = this.InsertCaret; break; case "OverwriteCaret": this.Render.OverwriteCaret = this.OverwriteCaret; break; case "LineMarker": this.Render.LineMarker = this.LineMarker; break; case "MarkURL": this.View.UrlMark = this.MarkURL; break; case "ShowFullSpace": this.Render.ShowFullSpace = this.ShowFullSpace; break; case "ShowHalfSpace": this.Render.ShowHalfSpace = this.ShowHalfSpace; break; case "ShowTab": this.Render.ShowTab = this.ShowTab; break; case "ShowLineBreak": this.Render.ShowLineBreak = this.ShowLineBreak; break; case "FlowDirection": this.Render.RightToLeft = this.FlowDirection == System.Windows.FlowDirection.RightToLeft; this.horizontalScrollBar.FlowDirection = this.FlowDirection; break; case "DrawRuler": this.View.HideRuler = !this.DrawRuler; this._Controller.JumpCaret(this.View.CaretPostion.row, this.View.CaretPostion.col); break; } base.OnPropertyChanged(e); } #endregion #region property internal Controller Controller { get { return this._Controller; } } /// /// 文字列の描写に使用されるアンチエイリアシング モードを表します /// public TextAntialiasMode TextAntialiasMode { get { return this.Render.TextAntialiasMode; } set { this.Render.TextAntialiasMode = value; } } /// /// シンタックスハイライターを表す /// public IHilighter Hilighter { get { return this.View.Hilighter; } set { this.View.Hilighter = value; this.View.LayoutLines.ClearLayoutCache(); } } /// /// フォールティングを作成するインターフェイスを表す /// public IFoldingStrategy FoldingStrategy { get { return this.View.LayoutLines.FoldingStrategy; } set { this.View.LayoutLines.FoldingStrategy = value; if (value == null) this.View.LayoutLines.FoldingCollection.Clear(); } } /// /// マーカーパターンセット /// public MarkerPatternSet MarkerPatternSet { get { return this.View.MarkerPatternSet; } } /// /// ドキュメントを表す /// public Document Document { get; private set; } /// /// レイアウト行を表す /// public LineToIndexTable LayoutLineCollection { get { return this.View.LayoutLines; } } /// /// 選択中の文字列を表す /// public string SelectedText { get { return this._Controller.SelectedText; } set { int oldLength = this.Document.Length; this._Controller.SelectedText = value; } } /// /// 選択範囲を表す /// /// /// Lengthが0の場合はキャレット位置を表します。 /// 矩形選択モードの場合、選択範囲の文字数ではなく、開始位置から終了位置までの長さとなります /// public TextRange Selection { get { return (TextRange)GetValue(SelectionProperty); } set { SetValue(SelectionProperty, value); } } /// /// Selectionの依存プロパティを表す /// public static readonly DependencyProperty SelectionProperty = DependencyProperty.Register("Selection", typeof(TextRange), typeof(FooTextBox), new PropertyMetadata(TextRange.Null)); /// /// 拡大率を表す /// public double MagnificationPower { get { return (double)GetValue(MagnificationPowerPropertyKey.DependencyProperty); } } /// /// 拡大率を表す依存プロパティ /// public static readonly DependencyPropertyKey MagnificationPowerPropertyKey = DependencyProperty.RegisterReadOnly("MagnificationPower", typeof(double), typeof(FooTextBox), new PropertyMetadata(1.0)); /// /// レタリング方向を表す /// public new FlowDirection FlowDirection { get { return (FlowDirection)GetValue(FlowDirectionProperty); } set { SetValue(FlowDirectionProperty, value); } } /// /// レタリング方向を表す。これは依存プロパティです /// public new static readonly DependencyProperty FlowDirectionProperty = DependencyProperty.Register("FlowDirection", typeof(FlowDirection), typeof(FooTextBox), new PropertyMetadata(FlowDirection.LeftToRight)); /// /// キャレット位置を表す。これは依存プロパティです /// public TextPoint CaretPostion { get { return (TextPoint)GetValue(CaretPostionProperty); } set { SetValue(CaretPostionProperty, value); } } /// /// CaretPostionの依存プロパティを表す /// public static readonly DependencyProperty CaretPostionProperty = DependencyProperty.Register("CaretPostion", typeof(TextPoint), typeof(FooTextBox), new PropertyMetadata(TextPoint.Null)); /// /// デフォルトの文字色を表す。これは依存プロパティです /// public new System.Windows.Media.Color Foreground { get { return (System.Windows.Media.Color)GetValue(ForegroundProperty); } set { SetValue(ForegroundProperty, value); } } /// /// Foregroundの依存プロパティを表す /// public new static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register("Foreground", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowTextColor)); /// /// 背景色を表す。これは依存プロパティです /// public new System.Windows.Media.Color Background { get { return (System.Windows.Media.Color)GetValue(BackgroundProperty); } set { SetValue(BackgroundProperty, value); } } /// /// Backgroundの依存プロパティを表す /// public new static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register("Background", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowColor)); /// /// コントロールコードの文字色を表す。これは依存プロパティです /// public System.Windows.Media.Color ControlChar { get { return (System.Windows.Media.Color)GetValue(ControlCharProperty); } set { SetValue(ControlCharProperty, value); } } /// /// ControlCharの依存プロパティを表す /// public static readonly DependencyProperty ControlCharProperty = DependencyProperty.Register("ControlChar", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Gray)); /// /// 選択時の背景色を表す。これは依存プロパティです /// public System.Windows.Media.Color Hilight { get { return (System.Windows.Media.Color)GetValue(HilightProperty); } set { SetValue(HilightProperty, value); } } /// /// Hilightの依存プロパティを表す /// public static readonly DependencyProperty HilightProperty = DependencyProperty.Register("Hilight", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.DeepSkyBlue)); /// /// キーワード1の文字色を表す。これは依存プロパティです /// public System.Windows.Media.Color Keyword1 { get { return (System.Windows.Media.Color)GetValue(Keyword1Property); } set { SetValue(Keyword1Property, value); } } /// /// Keyword1の依存プロパティを表す /// public static readonly DependencyProperty Keyword1Property = DependencyProperty.Register("Keyword1", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Blue)); /// /// キーワード2の文字色を表す。これは依存プロパティです /// public System.Windows.Media.Color Keyword2 { get { return (System.Windows.Media.Color)GetValue(Keyword2Property); } set { SetValue(Keyword2Property, value); } } /// /// Keyword2の依存プロパティを表す /// public static readonly DependencyProperty Keyword2Property = DependencyProperty.Register("Keyword2", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.DarkCyan)); /// /// コメントの文字色を表す。これは依存プロパティです /// public System.Windows.Media.Color Comment { get { return (System.Windows.Media.Color)GetValue(CommentProperty); } set { SetValue(CommentProperty, value); } } /// /// Commentの依存プロパティを表す /// public static readonly DependencyProperty CommentProperty = DependencyProperty.Register("Comment", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Green)); /// /// 文字リテラルの文字色を表す。これは依存プロパティです /// public System.Windows.Media.Color Literal { get { return (System.Windows.Media.Color)GetValue(LiteralProperty); } set { SetValue(LiteralProperty, value); } } /// /// Literalの依存プロパティを表す /// public static readonly DependencyProperty LiteralProperty = DependencyProperty.Register("Literal", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Brown)); /// /// URLの文字色を表す。これは依存プロパティです /// public System.Windows.Media.Color URL { get { return (System.Windows.Media.Color)GetValue(URLProperty); } set { SetValue(URLProperty, value); } } /// /// URLの依存プロパティを表す /// public static readonly DependencyProperty URLProperty = DependencyProperty.Register("URL", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Blue)); /// /// ラインマーカーの色を表す /// public System.Windows.Media.Color LineMarker { get { return (System.Windows.Media.Color)GetValue(LineMarkerProperty); } set { SetValue(LineMarkerProperty, value); } } /// /// LineMarkerの依存プロパティを表す /// public static readonly DependencyProperty LineMarkerProperty = DependencyProperty.Register("LineMarker", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(Colors.Silver)); /// /// 挿入モード時のキャレットの色を表す /// public System.Windows.Media.Color InsertCaret { get { return (System.Windows.Media.Color)GetValue(InsertCaretProperty); } set { SetValue(InsertCaretProperty, value); } } /// /// InsertCaretの依存プロパティを表す /// public static readonly DependencyProperty InsertCaretProperty = DependencyProperty.Register("InsertCaret", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowTextColor)); /// /// 上書きモード時のキャレット職を表す /// public System.Windows.Media.Color OverwriteCaret { get { return (System.Windows.Media.Color)GetValue(OverwriteCaretProperty); } set { SetValue(OverwriteCaretProperty, value); } } /// /// OverwriteCaretの依存プロパティを表す /// public static readonly DependencyProperty OverwriteCaretProperty = DependencyProperty.Register("OverwriteCaret", typeof(System.Windows.Media.Color), typeof(FooTextBox), new FrameworkPropertyMetadata(SystemColors.WindowTextColor)); /// /// 挿入モードなら真を返し、そうでないなら、偽を返す。これは依存プロパティです /// public bool InsertMode { get { return (bool)GetValue(InsertModeProperty); } set { SetValue(InsertModeProperty, value); } } /// /// InsertModeの依存プロパティを表す /// public static readonly DependencyProperty InsertModeProperty = DependencyProperty.Register("InsertMode", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(true)); /// /// タブの文字数を表す。これは依存プロパティです /// public int TabChars { get { return (int)GetValue(TabCharsProperty); } set { SetValue(TabCharsProperty, value); } } /// /// TabCharsの依存プロパティを表す /// public static readonly DependencyProperty TabCharsProperty = DependencyProperty.Register("TabChars", typeof(int), typeof(FooTextBox), new FrameworkPropertyMetadata(4)); /// /// 矩形選択モードなら真を返し、そうでないなら偽を返す。これは依存プロパティです /// public bool RectSelectMode { get { return (bool)GetValue(RectSelectModeProperty); } set { SetValue(RectSelectModeProperty, value); } } /// /// RectSelectModeの依存プロパティを表す /// public static readonly DependencyProperty RectSelectModeProperty = DependencyProperty.Register("RectSelectMode", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false)); /// /// 折り返しの方法を指定する /// /// /// 変更した場合、レイアウトの再構築を行う必要があります /// public LineBreakMethod LineBreakMethod { get { return (LineBreakMethod)GetValue(LineBreakProperty); } set { SetValue(LineBreakProperty, value); } } /// /// LineBreakMethodの依存プロパティを表す /// public static readonly DependencyProperty LineBreakProperty = DependencyProperty.Register("LineBreakMethod", typeof(LineBreakMethod), typeof(FooTextBox), new PropertyMetadata(LineBreakMethod.None)); /// /// 折り返しの幅を指定する。LineBreakMethod.CharUnit以外の時は無視されます /// /// /// 変更した場合、レイアウトの再構築を行う必要があります /// public int LineBreakCharCount { get { return (int)GetValue(LineBreakCharCountProperty); } set { SetValue(LineBreakCharCountProperty, value); } } /// /// LineBreakCharCountの依存プロパティを表す /// public static readonly DependencyProperty LineBreakCharCountProperty = DependencyProperty.Register("LineBreakCharCount", typeof(int), typeof(FooTextBox), new PropertyMetadata(80)); /// /// キャレットを描くなら真。そうでないなら偽を返す。これは依存プロパティです /// public bool DrawCaret { get { return (bool)GetValue(DrawCaretProperty); } set { SetValue(DrawCaretProperty, value); } } /// /// DrawCaretの依存プロパティを表す /// public static readonly DependencyProperty DrawCaretProperty = DependencyProperty.Register("DrawCaret", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(true)); /// /// キャレットラインを描くなら真。そうでないなら偽を返す。これは依存プロパティです /// public bool DrawCaretLine { get { return (bool)GetValue(DrawCaretLineProperty); } set { SetValue(DrawCaretLineProperty, value); } } /// /// DrawCaretLineの依存プロパティを表す /// public static readonly DependencyProperty DrawCaretLineProperty = DependencyProperty.Register("DrawCaretLine", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false)); /// /// 行番号を描くなら真。そうでなければ偽。これは依存プロパティです /// public bool DrawLineNumber { get { return (bool)GetValue(DrawLineNumberProperty); } set { SetValue(DrawLineNumberProperty, value); } } /// /// ルーラーを描くなら真。そうでなければ偽。これは依存プロパティです /// public bool DrawRuler { get { return (bool)GetValue(DrawRulerProperty); } set { SetValue(DrawRulerProperty, value); } } /// /// DrawRulerの依存プロパティを表す /// public static readonly DependencyProperty DrawRulerProperty = DependencyProperty.Register("DrawRuler", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false)); /// /// DrawLineNumberの依存プロパティを表す /// public static readonly DependencyProperty DrawLineNumberProperty = DependencyProperty.Register("DrawLineNumber", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false)); /// /// URLに下線を引くなら真。そうでないなら偽を表す。これは依存プロパティです /// public bool MarkURL { get { return (bool)GetValue(MarkURLProperty); } set { SetValue(MarkURLProperty, value); } } /// /// MarkURLの依存プロパティを表す /// public static readonly DependencyProperty MarkURLProperty = DependencyProperty.Register("MarkURL", typeof(bool), typeof(FooTextBox), new FrameworkPropertyMetadata(false)); /// /// 全角スペースを表示するなら真。そうでないなら偽 /// public bool ShowFullSpace { get { return (bool)GetValue(ShowFullSpaceProperty); } set { SetValue(ShowFullSpaceProperty, value); } } /// /// ShowFullSpaceの依存プロパティを表す /// public static readonly DependencyProperty ShowFullSpaceProperty = DependencyProperty.Register("ShowFullSpace", typeof(bool), typeof(FooTextBox), new UIPropertyMetadata(false)); /// /// 半角スペースを表示するなら真。そうでないなら偽 /// public bool ShowHalfSpace { get { return (bool)GetValue(ShowHalfSpaceProperty); } set { SetValue(ShowHalfSpaceProperty, value); } } /// /// ShowHalfSpaceの依存プロパティを表す /// public static readonly DependencyProperty ShowHalfSpaceProperty = DependencyProperty.Register("ShowHalfSpace", typeof(bool), typeof(FooTextBox), new UIPropertyMetadata(false)); /// /// タブを表示するなら真。そうでないなら偽 /// public bool ShowTab { get { return (bool)GetValue(ShowTabProperty); } set { SetValue(ShowTabProperty, value); } } /// /// ShowTabの依存プロパティを表す /// public static readonly DependencyProperty ShowTabProperty = DependencyProperty.Register("ShowTab", typeof(bool), typeof(FooTextBox), new UIPropertyMetadata(false)); /// /// 改行マークを表示するなら真。そうでないなら偽 /// public bool ShowLineBreak { get { return (bool)GetValue(ShowLineBreakProperty); } set { SetValue(ShowLineBreakProperty, value); } } /// /// ShowLineBreakの依存プロパティを表す /// public static readonly DependencyProperty ShowLineBreakProperty = DependencyProperty.Register("ShowLineBreak", typeof(bool), typeof(FooTextBox), new PropertyMetadata(false)); #endregion } /// /// マウスボタン関連のイベントクラス /// public sealed class FooMouseButtonEventArgs : MouseButtonEventArgs { /// /// イベントが発生したドキュメントのインデックス /// public int Index { get; private set; } /// /// コンストラクター /// /// マウスデバイス /// タイムスタンプ /// ボタン /// スタイラスデバイス /// インデックス public FooMouseButtonEventArgs(MouseDevice mouse, int timestamp, MouseButton button, StylusDevice stylusDevice, int index) : base(mouse, timestamp, button, stylusDevice) { this.Index = index; } } /// /// マウス関連のイベントクラス /// public sealed class FooMouseEventArgs : MouseEventArgs { /// /// イベントが発生したドキュメントのインデックス /// public int Index { get; private set; } /// /// コンストラクター /// /// マウスデバイス /// タイムスタンプ /// スタイラスデバイス /// インデックス public FooMouseEventArgs(MouseDevice mouse, int timestamp, StylusDevice stylusDevice, int index) : base(mouse, timestamp, stylusDevice) { this.Index = index; } } }