From 897af2eb79d0cbddd94a67c6eaa55662d63ddb8c Mon Sep 17 00:00:00 2001 From: Vsevolod Kukol Date: Mon, 16 Jun 2014 13:57:36 +0200 Subject: [PATCH] [MAC] add missing cursor position and selection support to TextEntryBackend --- Xwt.Mac/Xwt.Mac/ComboBoxEntryBackend.cs | 124 +++++++++++++++++++++++- Xwt.Mac/Xwt.Mac/TextEntryBackend.cs | 100 ++++++++++++++++++- 2 files changed, 219 insertions(+), 5 deletions(-) diff --git a/Xwt.Mac/Xwt.Mac/ComboBoxEntryBackend.cs b/Xwt.Mac/Xwt.Mac/ComboBoxEntryBackend.cs index fd1c5a89..90a5476b 100644 --- a/Xwt.Mac/Xwt.Mac/ComboBoxEntryBackend.cs +++ b/Xwt.Mac/Xwt.Mac/ComboBoxEntryBackend.cs @@ -101,7 +101,10 @@ namespace Xwt.Mac IComboBoxEventSink eventSink; ITextEntryEventSink entryEventSink; ApplicationContext context; - + + int cacheSelectionStart, cacheSelectionLength; + bool checkMouseMovement; + public MacComboBox (IComboBoxEventSink eventSink, ApplicationContext context) { this.context = context; @@ -127,6 +130,125 @@ namespace Xwt.Mac if (entryEventSink != null) { context.InvokeUserCode (delegate { entryEventSink.OnChanged (); + entryEventSink.OnSelectionChanged (); + }); + } + } + public override void KeyUp (NSEvent theEvent) + { + base.KeyUp (theEvent); + HandleSelectionChanged (); + } + + + NSTrackingArea trackingArea; + public override void UpdateTrackingAreas () + { + if (trackingArea != null) { + RemoveTrackingArea (trackingArea); + trackingArea.Dispose (); + } + System.Drawing.RectangleF viewBounds = this.Bounds; + var options = NSTrackingAreaOptions.MouseMoved | NSTrackingAreaOptions.ActiveInKeyWindow | NSTrackingAreaOptions.MouseEnteredAndExited; + trackingArea = new NSTrackingArea (viewBounds, options, this, null); + AddTrackingArea (trackingArea); + } + + public override void RightMouseDown (NSEvent theEvent) + { + base.RightMouseDown (theEvent); + var p = ConvertPointFromView (theEvent.LocationInWindow, null); + ButtonEventArgs args = new ButtonEventArgs (); + args.X = p.X; + args.Y = p.Y; + args.Button = PointerButton.Right; + context.InvokeUserCode (delegate { + eventSink.OnButtonPressed (args); + }); + } + + public override void RightMouseUp (NSEvent theEvent) + { + base.RightMouseUp (theEvent); + var p = ConvertPointFromView (theEvent.LocationInWindow, null); + ButtonEventArgs args = new ButtonEventArgs (); + args.X = p.X; + args.Y = p.Y; + args.Button = PointerButton.Right; + context.InvokeUserCode (delegate { + eventSink.OnButtonReleased (args); + }); + } + + public override void MouseDown (NSEvent theEvent) + { + base.MouseDown (theEvent); + var p = ConvertPointFromView (theEvent.LocationInWindow, null); + ButtonEventArgs args = new ButtonEventArgs (); + args.X = p.X; + args.Y = p.Y; + args.Button = PointerButton.Left; + context.InvokeUserCode (delegate { + eventSink.OnButtonPressed (args); + }); + } + + public override void MouseUp (NSEvent theEvent) + { + base.MouseUp (theEvent); + var p = ConvertPointFromView (theEvent.LocationInWindow, null); + ButtonEventArgs args = new ButtonEventArgs (); + args.X = p.X; + args.Y = p.Y; + args.Button = (PointerButton) theEvent.ButtonNumber + 1; + context.InvokeUserCode (delegate { + eventSink.OnButtonReleased (args); + }); + } + + public override void MouseEntered (NSEvent theEvent) + { + base.MouseEntered (theEvent); + checkMouseMovement = true; + context.InvokeUserCode (delegate { + eventSink.OnMouseEntered (); + }); + } + + public override void MouseExited (NSEvent theEvent) + { + base.MouseExited (theEvent); + context.InvokeUserCode (delegate { + eventSink.OnMouseExited (); + }); + checkMouseMovement = false; + HandleSelectionChanged (); + } + + public override void MouseMoved (NSEvent theEvent) + { + base.MouseMoved (theEvent); + if (!checkMouseMovement) + return; + var p = ConvertPointFromView (theEvent.LocationInWindow, null); + MouseMovedEventArgs args = new MouseMovedEventArgs ((long) TimeSpan.FromSeconds (theEvent.Timestamp).TotalMilliseconds, p.X, p.Y); + context.InvokeUserCode (delegate { + eventSink.OnMouseMoved (args); + }); + if (checkMouseMovement) + HandleSelectionChanged (); + } + + void HandleSelectionChanged () + { + if (entryEventSink == null || CurrentEditor == null) + return; + if (cacheSelectionStart != CurrentEditor.SelectedRange.Location || + cacheSelectionLength != CurrentEditor.SelectedRange.Length) { + cacheSelectionStart = CurrentEditor.SelectedRange.Location; + cacheSelectionLength = CurrentEditor.SelectedRange.Length; + context.InvokeUserCode (delegate { + entryEventSink.OnSelectionChanged (); }); } } diff --git a/Xwt.Mac/Xwt.Mac/TextEntryBackend.cs b/Xwt.Mac/Xwt.Mac/TextEntryBackend.cs index 5c98c80b..d23520b1 100644 --- a/Xwt.Mac/Xwt.Mac/TextEntryBackend.cs +++ b/Xwt.Mac/Xwt.Mac/TextEntryBackend.cs @@ -32,6 +32,9 @@ namespace Xwt.Mac { public class TextEntryBackend: ViewBackend, ITextEntryBackend { + int cacheSelectionStart, cacheSelectionLength; + bool checkMouseSelection; + public TextEntryBackend () { } @@ -51,6 +54,18 @@ namespace Xwt.Mac ViewObject = new CustomAlignedContainer (EventSink, ApplicationContext, (NSView)view); MultiLine = false; } + + Frontend.MouseEntered += delegate { + checkMouseSelection = true; + }; + Frontend.MouseExited += delegate { + checkMouseSelection = false; + HandleSelectionChanged (); + }; + Frontend.MouseMoved += delegate { + if (checkMouseSelection) + HandleSelectionChanged (); + }; } protected override void OnSizeToFit () @@ -140,13 +155,78 @@ namespace Xwt.Mac } } - public int CursorPosition { get; set; } + public int CursorPosition { + get { + if (Widget.CurrentEditor == null) + return 0; + return Widget.CurrentEditor.SelectedRange.Location; + } + set { + Widget.CurrentEditor.SelectedRange = new MonoMac.Foundation.NSRange (value, SelectionLength); + HandleSelectionChanged (); + } + } - public int SelectionStart { get; set; } + public int SelectionStart { + get { + if (Widget.CurrentEditor == null) + return 0; + return Widget.CurrentEditor.SelectedRange.Location; + } + set { + Widget.CurrentEditor.SelectedRange = new MonoMac.Foundation.NSRange (value, SelectionLength); + HandleSelectionChanged (); + } + } - public int SelectionLength { get; set; } + public int SelectionLength { + get { + if (Widget.CurrentEditor == null) + return 0; + return Widget.CurrentEditor.SelectedRange.Length; + } + set { + Widget.CurrentEditor.SelectedRange = new MonoMac.Foundation.NSRange (SelectionStart, value); + HandleSelectionChanged (); + } + } - public string SelectedText { get; set; } + public string SelectedText { + get { + if (Widget.CurrentEditor == null) + return String.Empty; + int start = SelectionStart; + int end = start + SelectionLength; + if (start == end) return String.Empty; + try { + return Text.Substring (start, end - start); + } catch { + return String.Empty; + } + } + set { + int cacheSelStart = SelectionStart; + int pos = cacheSelStart; + if (SelectionLength > 0) { + Text = Text.Remove (pos, SelectionLength).Insert (pos, value); + } + SelectionStart = pos; + SelectionLength = value.Length; + HandleSelectionChanged (); + } + } + + void HandleSelectionChanged () + { + if (cacheSelectionStart != SelectionStart || + cacheSelectionLength != SelectionLength) { + cacheSelectionStart = SelectionStart; + cacheSelectionLength = SelectionLength; + ApplicationContext.InvokeUserCode (delegate { + EventSink.OnSelectionChanged (); + }); + } + } public override void SetFocus () { @@ -179,8 +259,20 @@ namespace Xwt.Mac base.DidChange (notification); context.InvokeUserCode (delegate { eventSink.OnChanged (); + eventSink.OnSelectionChanged (); }); } + + int cachedCursorPosition; + public override void KeyUp (NSEvent theEvent) + { + base.KeyUp (theEvent); + if (cachedCursorPosition != CurrentEditor.SelectedRange.Location) + context.InvokeUserCode (delegate { + eventSink.OnSelectionChanged (); + }); + cachedCursorPosition = CurrentEditor.SelectedRange.Location; + } } }