From 6b4fa39fc1190150a917fb8e15bf700401e6b663 Mon Sep 17 00:00:00 2001 From: Vsevolod Kukol Date: Mon, 28 Jul 2014 15:47:12 +0200 Subject: [PATCH 01/11] add new TextArea widget for multi-line text input * mark TextEntry.MultiLine obsolete Some toolkits (like Gtk) have different widgets for single- and multi-lined text input. This makes it possible to implement multi line text enty backend for those toolkits in a clean way. --- TestApps/Samples/Samples/TextEntries.cs | 48 +++++++++++----- Xwt/Xwt.Backends/ITextAreaBackend.cs | 35 ++++++++++++ Xwt/Xwt.Backends/ITextEntryBackend.cs | 25 ++++++++- Xwt/Xwt.csproj | 2 + Xwt/Xwt/TextArea.cs | 50 +++++++++++++++++ Xwt/Xwt/TextEntry.cs | 73 +++++++++++++++++-------- 6 files changed, 192 insertions(+), 41 deletions(-) create mode 100644 Xwt/Xwt.Backends/ITextAreaBackend.cs create mode 100644 Xwt/Xwt/TextArea.cs diff --git a/TestApps/Samples/Samples/TextEntries.cs b/TestApps/Samples/Samples/TextEntries.cs index 992fdc7a6..6b710df60 100644 --- a/TestApps/Samples/Samples/TextEntries.cs +++ b/TestApps/Samples/Samples/TextEntries.cs @@ -106,22 +106,42 @@ public TextEntries () te5.PlaceholderText = "Placeholder text"; PackStart (te5); - TextEntry te6 = new TextEntry (); - te6.Text = "I should have" + Environment.NewLine + "multiple lines!"; - te6.PlaceholderText = "Placeholder text"; - te6.MultiLine = true; - te6.MinHeight = 40; - PackStart (te6); + HBox hbox1 = new HBox (); + + TextArea ta1 = new TextArea (); + ta1.Text = "I should have" + Environment.NewLine + "multiple lines and be centered!"; + ta1.PlaceholderText = "Placeholder text"; + ta1.TextAlignment = Alignment.Center; + ta1.MinHeight = 40; + ta1.Activated += (sender, e) => MessageDialog.ShowMessage ("Activated"); + hbox1.PackStart (ta1, true); + + TextArea ta2 = new TextArea (); + ta2.Text = "I should have multiple lines," + Environment.NewLine + "no frame and should wrap on words!"; + ta2.PlaceholderText = "Placeholder text"; + ta2.ShowFrame = false; + ta2.Wrap = WrapMode.Word; + hbox1.PackStart (ta2, true); + + PackStart (hbox1); + + TextArea ta3 = new TextArea (); + ta3.Text = "I should have\nmultiple lines,\nwrap on words,\n and scroll\nvertically "; + ta3.PlaceholderText = "Placeholder text"; + ta3.Wrap = WrapMode.Word; + var scrollTa3 = new ScrollView (ta3); + scrollTa3.HorizontalScrollPolicy = ScrollPolicy.Never; + PackStart (scrollTa3); try { - SearchTextEntry te7 = new SearchTextEntry (); - te7.PlaceholderText = "Type to search ..."; - PackStart (te7); - - SearchTextEntry te8 = new SearchTextEntry (); - te8.PlaceholderText = "I should have no frame"; - te8.ShowFrame = false; - PackStart (te8); + SearchTextEntry ts1 = new SearchTextEntry (); + ts1.PlaceholderText = "Type to search ..."; + PackStart (ts1); + + SearchTextEntry ts2 = new SearchTextEntry (); + ts2.PlaceholderText = "I should have no frame"; + ts2.ShowFrame = false; + PackStart (ts2); } catch (InvalidOperationException ex) { Console.WriteLine (ex); } diff --git a/Xwt/Xwt.Backends/ITextAreaBackend.cs b/Xwt/Xwt.Backends/ITextAreaBackend.cs new file mode 100644 index 000000000..15d557a97 --- /dev/null +++ b/Xwt/Xwt.Backends/ITextAreaBackend.cs @@ -0,0 +1,35 @@ +// +// ITextBoxBackend.cs +// +// Author: +// Vsevolod Kukol +// +// Copyright (c) 2014 Vsevolod Kukol +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace Xwt.Backends +{ + public interface ITextAreaBackend: ITextBoxBackend + { + WrapMode Wrap { get; set; } + } +} + diff --git a/Xwt/Xwt.Backends/ITextEntryBackend.cs b/Xwt/Xwt.Backends/ITextEntryBackend.cs index c99ae2456..bbab86a6c 100644 --- a/Xwt/Xwt.Backends/ITextEntryBackend.cs +++ b/Xwt/Xwt.Backends/ITextEntryBackend.cs @@ -27,14 +27,23 @@ namespace Xwt.Backends { - public interface ITextEntryBackend: IWidgetBackend + public interface ITextEntryBackend: ITextBoxBackend + { + [Obsolete("Use ITextAreaBackend instead")] + bool MultiLine { get; set; } + } + + public interface ITextEntryEventSink: ITextBoxEventSink + { + } + + public interface ITextBoxBackend: IWidgetBackend { string Text { get; set; } Alignment TextAlignment { get; set; } string PlaceholderText { get; set; } bool ReadOnly { get; set; } bool ShowFrame { get; set; } - bool MultiLine { get; set; } int CursorPosition { get; set; } int SelectionStart { get; set; } int SelectionLength { get; set; } @@ -44,17 +53,27 @@ public interface ITextEntryBackend: IWidgetBackend void SetCompletionMatchFunc (Func matchFunc); } - public interface ITextEntryEventSink: IWidgetEventSink + public interface ITextBoxEventSink: IWidgetEventSink { void OnChanged (); void OnActivated (); void OnSelectionChanged (); } + public enum TextBoxEvent + { + Changed, + Activated, + SelectionChanged + } + public enum TextEntryEvent { + [Obsolete("Use Xwt.Backends.TextBoxEvent.Changed instead")] Changed, + [Obsolete("Use Xwt.Backends.TextBoxEvent.Activated instead")] Activated, + [Obsolete("Use Xwt.Backends.TextBoxEvent.SelectionChanged instead")] SelectionChanged } } diff --git a/Xwt/Xwt.csproj b/Xwt/Xwt.csproj index a4cfa9f37..106d6e0b8 100644 --- a/Xwt/Xwt.csproj +++ b/Xwt/Xwt.csproj @@ -363,6 +363,8 @@ + + diff --git a/Xwt/Xwt/TextArea.cs b/Xwt/Xwt/TextArea.cs new file mode 100644 index 000000000..e506d8355 --- /dev/null +++ b/Xwt/Xwt/TextArea.cs @@ -0,0 +1,50 @@ +// +// TextBox.cs +// +// Author: +// Vsevolod Kukol +// +// Copyright (c) 2014 Vsevolod Kukol +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Xwt.Backends; +using System.ComponentModel; + +namespace Xwt +{ + [BackendType (typeof(ITextAreaBackend))] + public class TextArea: TextBox + { + public TextArea () + { + } + + ITextAreaBackend Backend { + get { return (ITextAreaBackend) BackendHost.Backend; } + } + + [DefaultValue (WrapMode.None)] + public WrapMode Wrap { + get { return Backend.Wrap; } + set { Backend.Wrap = value; } + } + } +} + diff --git a/Xwt/Xwt/TextEntry.cs b/Xwt/Xwt/TextEntry.cs index 73dbe6ce2..79cfdd3a2 100644 --- a/Xwt/Xwt/TextEntry.cs +++ b/Xwt/Xwt/TextEntry.cs @@ -30,32 +30,63 @@ namespace Xwt { [BackendType (typeof(ITextEntryBackend))] - public class TextEntry: Widget + public class TextEntry: TextBox + { + public TextEntry () + { + // TODO: DEPRECATED! Safe to remove? + MapEvent (TextEntryEvent.Changed, typeof(TextBox), "OnChanged"); + MapEvent (TextEntryEvent.Activated, typeof(TextBox), "OnActivated"); + MapEvent (TextEntryEvent.SelectionChanged, typeof(TextBox), "OnSelectionChanged"); + } + + protected new class WidgetBackendHost: TextBox.WidgetBackendHost, ITextEntryEventSink + { + } + + protected override BackendHost CreateBackendHost () + { + return new WidgetBackendHost (); + } + + ITextEntryBackend Backend { + get { return (ITextEntryBackend) BackendHost.Backend; } + } + + [Obsolete("Use TextArea widget instead")] + [DefaultValue (false)] + public bool MultiLine { + get { return Backend.MultiLine; } + set { Backend.MultiLine = value; } + } + } + + public abstract class TextBox: Widget { EventHandler changed, activated, selectionChanged; - static TextEntry () + static TextBox () { - MapEvent (TextEntryEvent.Changed, typeof(TextEntry), "OnChanged"); - MapEvent (TextEntryEvent.Activated, typeof(TextEntry), "OnActivated"); - MapEvent (TextEntryEvent.SelectionChanged, typeof(TextEntry), "OnSelectionChanged"); + MapEvent (TextBoxEvent.Changed, typeof(TextBox), "OnChanged"); + MapEvent (TextBoxEvent.Activated, typeof(TextBox), "OnActivated"); + MapEvent (TextBoxEvent.SelectionChanged, typeof(TextBox), "OnSelectionChanged"); } - protected new class WidgetBackendHost: Widget.WidgetBackendHost, ITextEntryEventSink + protected new class WidgetBackendHost: Widget.WidgetBackendHost, ITextBoxEventSink { public void OnChanged () { - ((TextEntry)Parent).OnChanged (EventArgs.Empty); + ((TextBox)Parent).OnChanged (EventArgs.Empty); } public void OnActivated () { - ((TextEntry)Parent).OnActivated (EventArgs.Empty); + ((TextBox)Parent).OnActivated (EventArgs.Empty); } public void OnSelectionChanged () { - ((TextEntry)Parent).OnSelectionChanged (EventArgs.Empty); + ((TextBox)Parent).OnSelectionChanged (EventArgs.Empty); } public override Size GetDefaultNaturalSize () @@ -64,7 +95,7 @@ public override Size GetDefaultNaturalSize () } } - public TextEntry () + public TextBox () { } @@ -73,8 +104,8 @@ protected override BackendHost CreateBackendHost () return new WidgetBackendHost (); } - ITextEntryBackend Backend { - get { return (ITextEntryBackend) BackendHost.Backend; } + ITextBoxBackend Backend { + get { return (ITextBoxBackend) BackendHost.Backend; } } [DefaultValue ("")] @@ -129,12 +160,6 @@ public string SelectedText { get { return Backend.SelectedText; } set { Backend.SelectedText = value; } } - - [DefaultValue (true)] - public bool MultiLine { - get { return Backend.MultiLine; } - set { Backend.MultiLine = value; } - } [DefaultValue (false)] public bool HasCompletions { @@ -159,12 +184,12 @@ protected virtual void OnChanged (EventArgs e) public event EventHandler Changed { add { - BackendHost.OnBeforeEventAdd (TextEntryEvent.Changed, changed); + BackendHost.OnBeforeEventAdd (TextBoxEvent.Changed, changed); changed += value; } remove { changed -= value; - BackendHost.OnAfterEventRemove (TextEntryEvent.Changed, changed); + BackendHost.OnAfterEventRemove (TextBoxEvent.Changed, changed); } } @@ -176,12 +201,12 @@ protected virtual void OnSelectionChanged (EventArgs e) public event EventHandler SelectionChanged { add { - BackendHost.OnBeforeEventAdd (TextEntryEvent.SelectionChanged, selectionChanged); + BackendHost.OnBeforeEventAdd (TextBoxEvent.SelectionChanged, selectionChanged); selectionChanged += value; } remove { selectionChanged -= value; - BackendHost.OnAfterEventRemove (TextEntryEvent.SelectionChanged, selectionChanged); + BackendHost.OnAfterEventRemove (TextBoxEvent.SelectionChanged, selectionChanged); } } @@ -193,12 +218,12 @@ protected virtual void OnActivated (EventArgs e) public event EventHandler Activated { add { - BackendHost.OnBeforeEventAdd (TextEntryEvent.Activated, activated); + BackendHost.OnBeforeEventAdd (TextBoxEvent.Activated, activated); activated += value; } remove { activated -= value; - BackendHost.OnAfterEventRemove (TextEntryEvent.Activated, activated); + BackendHost.OnAfterEventRemove (TextBoxEvent.Activated, activated); } } } From cbe21a8b8f447bae3f6469384ee740e31b49d777 Mon Sep 17 00:00:00 2001 From: Vsevolod Kukol Date: Mon, 28 Jul 2014 16:31:39 +0200 Subject: [PATCH 02/11] [WPF] track API changes (add TextArea) --- .../Xwt.WPFBackend/PlaceholderTextAdorner.cs | 4 +- Xwt.WPF/Xwt.WPFBackend/TextEntryBackend.cs | 72 ++++++++++++------- Xwt.WPF/Xwt.WPFBackend/WPFEngine.cs | 1 + 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/Xwt.WPF/Xwt.WPFBackend/PlaceholderTextAdorner.cs b/Xwt.WPF/Xwt.WPFBackend/PlaceholderTextAdorner.cs index 16b3c7d3b..dec0a0d4e 100644 --- a/Xwt.WPF/Xwt.WPFBackend/PlaceholderTextAdorner.cs +++ b/Xwt.WPF/Xwt.WPFBackend/PlaceholderTextAdorner.cs @@ -30,8 +30,8 @@ PasswordBox AdornedPasswordBox { get { return AdornedElement as PasswordBox; } } - TextBox AdornedTextBox { - get { return AdornedElement as TextBox; } + System.Windows.Controls.TextBox AdornedTextBox { + get { return AdornedElement as System.Windows.Controls.TextBox; } } System.Windows.Controls.ComboBox AdornedComboBox { diff --git a/Xwt.WPF/Xwt.WPFBackend/TextEntryBackend.cs b/Xwt.WPF/Xwt.WPFBackend/TextEntryBackend.cs index 02ec54700..8b42537ee 100644 --- a/Xwt.WPF/Xwt.WPFBackend/TextEntryBackend.cs +++ b/Xwt.WPF/Xwt.WPFBackend/TextEntryBackend.cs @@ -36,7 +36,7 @@ namespace Xwt.WPFBackend { public class TextEntryBackend - : WidgetBackend, ITextEntryBackend + : WidgetBackend, ITextAreaBackend, ITextEntryBackend { bool multiline; string placeholderText; @@ -56,8 +56,16 @@ public TextEntryBackend() if (!String.IsNullOrEmpty(placeholderText)) Adorner.PlaceholderText = placeholderText; }; - TextBox.VerticalContentAlignment = VerticalAlignment.Center; - } + } + + public override void InitializeBackend (object frontend, ApplicationContext context) + { + base.InitializeBackend (frontend, context); + if (Frontend is TextArea) + MultiLine = true; + else + MultiLine = false; + } protected override double DefaultNaturalWidth { @@ -93,6 +101,20 @@ public bool ReadOnly set { TextBox.IsReadOnly = value; } } + public WrapMode Wrap { + get { + if (TextBox.TextWrapping == TextWrapping.NoWrap) + return WrapMode.None; + else + return WrapMode.Word; + } set { + if (value == WrapMode.None) + TextBox.TextWrapping = TextWrapping.NoWrap; + else + TextBox.TextWrapping = TextWrapping.Wrap; + } + } + public bool ShowFrame { get { return TextBox.ShowFrame; } @@ -140,17 +162,15 @@ public string SelectedText { public bool MultiLine { get { return multiline; } set { - if (multiline != value) { - multiline = value; - if (multiline) { - TextBox.VerticalContentAlignment = VerticalAlignment.Top; - TextBox.AcceptsReturn = true; - TextBox.TextWrapping = TextWrapping.Wrap; - } else { - TextBox.VerticalContentAlignment = VerticalAlignment.Center; - TextBox.AcceptsReturn = false; - TextBox.TextWrapping = TextWrapping.NoWrap; - } + multiline = value; + if (multiline) { + TextBox.VerticalContentAlignment = VerticalAlignment.Top; + TextBox.AcceptsReturn = true; + TextBox.TextWrapping = TextWrapping.Wrap; + } else { + TextBox.VerticalContentAlignment = VerticalAlignment.Center; + TextBox.AcceptsReturn = false; + TextBox.TextWrapping = TextWrapping.NoWrap; } } } @@ -171,18 +191,18 @@ public override void EnableEvent (object eventId) { base.EnableEvent (eventId); - if (eventId is TextEntryEvent) + if (eventId is TextBoxEvent) { - switch ((TextEntryEvent)eventId) + switch ((TextBoxEvent)eventId) { // TODO: Should we ignore this for placeholder changes? - case TextEntryEvent.Changed: + case TextBoxEvent.Changed: TextBox.TextChanged += OnTextChanged; break; - case TextEntryEvent.Activated: + case TextBoxEvent.Activated: TextBox.KeyDown += OnActivated; break; - case TextEntryEvent.SelectionChanged: + case TextBoxEvent.SelectionChanged: TextBox.SelectionChanged += OnSelectionChanged; break; } @@ -193,17 +213,17 @@ public override void DisableEvent (object eventId) { base.DisableEvent (eventId); - if (eventId is TextEntryEvent) + if (eventId is TextBoxEvent) { - switch ((TextEntryEvent)eventId) + switch ((TextBoxEvent)eventId) { - case TextEntryEvent.Changed: + case TextBoxEvent.Changed: TextBox.TextChanged -= OnTextChanged; break; - case TextEntryEvent.Activated: + case TextBoxEvent.Activated: TextBox.KeyDown -= OnActivated; break; - case TextEntryEvent.SelectionChanged: + case TextBoxEvent.SelectionChanged: TextBox.SelectionChanged -= OnSelectionChanged; break; } @@ -215,8 +235,8 @@ protected ExTextBox TextBox get { return (ExTextBox) Widget; } } - protected new ITextEntryEventSink EventSink { - get { return (ITextEntryEventSink)base.EventSink; } + protected new ITextBoxEventSink EventSink { + get { return (ITextBoxEventSink)base.EventSink; } } private void OnActivated(object sender, System.Windows.Input.KeyEventArgs e) diff --git a/Xwt.WPF/Xwt.WPFBackend/WPFEngine.cs b/Xwt.WPF/Xwt.WPFBackend/WPFEngine.cs index 5d983123f..24a9d6b3b 100644 --- a/Xwt.WPF/Xwt.WPFBackend/WPFEngine.cs +++ b/Xwt.WPF/Xwt.WPFBackend/WPFEngine.cs @@ -71,6 +71,7 @@ public override void InitializeApplication () RegisterBackend (); RegisterBackend (); RegisterBackend (); + RegisterBackend (); RegisterBackend (); RegisterBackend (); RegisterBackend (); From 3f823d968c71144aeac54c9aa01df784e386c93d Mon Sep 17 00:00:00 2001 From: Vsevolod Kukol Date: Mon, 28 Jul 2014 16:36:23 +0200 Subject: [PATCH 03/11] [GTK] add Xwt.Alignment to Gtk conversions --- Xwt.Gtk/Xwt.GtkBackend/Conversion.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Xwt.Gtk/Xwt.GtkBackend/Conversion.cs b/Xwt.Gtk/Xwt.GtkBackend/Conversion.cs index f6168ee7b..7b5f8196c 100644 --- a/Xwt.Gtk/Xwt.GtkBackend/Conversion.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/Conversion.cs @@ -177,6 +177,26 @@ public static GridLines ToXwtValue (this Gtk.TreeViewGridLines value) throw new InvalidOperationException("Invalid TreeViewGridLines value: " + value); } + public static Gtk.Justification ToGtkJustification (this Alignment value) + { + switch (value) { + case Alignment.Start: return Gtk.Justification.Left; + case Alignment.Center: return Gtk.Justification.Center; + case Alignment.End: return Gtk.Justification.Right; + } + throw new InvalidOperationException("Invalid Alignment value: " + value); + } + + public static Alignment ToXwtValue (this Gtk.Justification value) + { + switch (value) { + case Gtk.Justification.Left: return Alignment.Start; + case Gtk.Justification.Center: return Alignment.Center; + case Gtk.Justification.Right: return Alignment.End; + } + return Alignment.Start; // return Start for unknown and Fill + } + public static float ToGtkAlignment(this Alignment alignment) { switch(alignment) { From f3526cae68c32a1c09524fe75d8ae36f576e9592 Mon Sep 17 00:00:00 2001 From: Vsevolod Kukol Date: Mon, 28 Jul 2014 16:39:47 +0200 Subject: [PATCH 04/11] [GTK] track API changes --- Xwt.Gtk/Xwt.GtkBackend/TextEntryBackend.cs | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Xwt.Gtk/Xwt.GtkBackend/TextEntryBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/TextEntryBackend.cs index 0e434b795..e3e3f8abc 100644 --- a/Xwt.Gtk/Xwt.GtkBackend/TextEntryBackend.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/TextEntryBackend.cs @@ -47,8 +47,8 @@ protected virtual Gtk.Entry TextEntry { set { base.Widget = value; } } - protected new ITextEntryEventSink EventSink { - get { return (ITextEntryEventSink)base.EventSink; } + protected new ITextBoxEventSink EventSink { + get { return (ITextBoxEventSink)base.EventSink; } } public string Text { @@ -234,11 +234,11 @@ Gtk.EntryCompletion CreateCompletion () public override void EnableEvent (object eventId) { base.EnableEvent (eventId); - if (eventId is TextEntryEvent) { - switch ((TextEntryEvent)eventId) { - case TextEntryEvent.Changed: Widget.Changed += HandleChanged; break; - case TextEntryEvent.Activated: Widget.Activated += HandleActivated; break; - case TextEntryEvent.SelectionChanged: + if (eventId is TextBoxEvent) { + switch ((TextBoxEvent)eventId) { + case TextBoxEvent.Changed: Widget.Changed += HandleChanged; break; + case TextBoxEvent.Activated: Widget.Activated += HandleActivated; break; + case TextBoxEvent.SelectionChanged: enableSelectionChangedEvent = true; Widget.MoveCursor += HandleMoveCursor; Widget.ButtonPressEvent += HandleButtonPressEvent; @@ -252,11 +252,11 @@ public override void EnableEvent (object eventId) public override void DisableEvent (object eventId) { base.DisableEvent (eventId); - if (eventId is TextEntryEvent) { - switch ((TextEntryEvent)eventId) { - case TextEntryEvent.Changed: Widget.Changed -= HandleChanged; break; - case TextEntryEvent.Activated: Widget.Activated -= HandleActivated; break; - case TextEntryEvent.SelectionChanged: + if (eventId is TextBoxEvent) { + switch ((TextBoxEvent)eventId) { + case TextBoxEvent.Changed: Widget.Changed -= HandleChanged; break; + case TextBoxEvent.Activated: Widget.Activated -= HandleActivated; break; + case TextBoxEvent.SelectionChanged: enableSelectionChangedEvent = false; Widget.MoveCursor -= HandleMoveCursor; Widget.ButtonPressEvent -= HandleButtonPressEvent; From a610e24995ab250d99b89b6b52e8a7146371f612 Mon Sep 17 00:00:00 2001 From: Vsevolod Kukol Date: Mon, 28 Jul 2014 16:42:59 +0200 Subject: [PATCH 05/11] [GTK] add ITextAreaBackend impl. using Gtk.TextView as backend --- Xwt.Gtk/Xwt.Gtk.csproj | 2 + Xwt.Gtk/Xwt.Gtk3.csproj | 2 + Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs | 1 + Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs | 332 ++++++++++++++++++ Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs | 95 +++++ Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs | 89 +++++ 6 files changed, 521 insertions(+) create mode 100644 Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs create mode 100644 Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs create mode 100644 Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs diff --git a/Xwt.Gtk/Xwt.Gtk.csproj b/Xwt.Gtk/Xwt.Gtk.csproj index e090656d1..582bcda35 100644 --- a/Xwt.Gtk/Xwt.Gtk.csproj +++ b/Xwt.Gtk/Xwt.Gtk.csproj @@ -164,6 +164,8 @@ + + diff --git a/Xwt.Gtk/Xwt.Gtk3.csproj b/Xwt.Gtk/Xwt.Gtk3.csproj index 6801595c0..04990d5f6 100644 --- a/Xwt.Gtk/Xwt.Gtk3.csproj +++ b/Xwt.Gtk/Xwt.Gtk3.csproj @@ -165,6 +165,8 @@ + + diff --git a/Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs b/Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs index bea2e437f..e72742758 100755 --- a/Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs @@ -72,6 +72,7 @@ public override void InitializeBackends () RegisterBackend (); RegisterBackend (); RegisterBackend (); + RegisterBackend (); RegisterBackend (); RegisterBackend (); RegisterBackend (); diff --git a/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs new file mode 100644 index 000000000..961899f5f --- /dev/null +++ b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs @@ -0,0 +1,332 @@ +// +// TextAreaBackend.cs +// +// Author: +// Vsevolod Kukol +// Lytico (http://www.limada.org) +// +// Copyright (c) 2014 Vsevolod Kukol +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Xwt.Backends; +using Xwt.Drawing; + + +namespace Xwt.GtkBackend +{ + public partial class TextAreaBackend : WidgetBackend, ITextAreaBackend + { + public override void Initialize () + { + textView = new Gtk.TextView (); + textView.Indent = 3; + Widget = new Gtk.Frame (); + ((Gtk.Frame)Widget).Add (textView); + ShowFrame = true; + Wrap = WrapMode.None; + Widget.ShowAll (); + } + + Gtk.TextView textView; + protected virtual Gtk.TextView TextView { + get { return textView; } + } + + protected new ITextBoxEventSink EventSink { + get { return (ITextBoxEventSink)base.EventSink; } + } + + public string Text { + get { return TextView.Buffer.Text; } + set { TextView.Buffer.Text = value; } + } + + public Alignment TextAlignment { + get { return TextView.Justification.ToXwtValue (); } + set { TextView.Justification = value.ToGtkJustification (); } + } + + public override Color BackgroundColor { + get { + return base.BackgroundColor; + } + set { + base.BackgroundColor = value; + TextView.ModifyBase (Gtk.StateType.Normal, value.ToGtkValue ()); + } + } + + Pango.Layout layout; + public override object Font { + get { return base.Font; } + set { + base.Font = value; + TextView.ModifyFont ((Pango.FontDescription)value); + layout = null; + } + } + + public bool ReadOnly { + get { + return TextView.Editable; + } + set { + TextView.Editable = value; + TextView.CursorVisible = !value; + } + } + + public WrapMode Wrap { + get { + switch (TextView.WrapMode) { + case Gtk.WrapMode.Char: + return WrapMode.Character; + case Gtk.WrapMode.Word: + return WrapMode.Word; + case Gtk.WrapMode.WordChar: + return WrapMode.WordAndCharacter; + default: + return WrapMode.None; + } + } + set { + switch (value) { + case WrapMode.Character: + TextView.WrapMode = Gtk.WrapMode.Char; + break; + case WrapMode.Word: + TextView.WrapMode = Gtk.WrapMode.Word; + break; + case WrapMode.WordAndCharacter: + TextView.WrapMode = Gtk.WrapMode.WordChar; + break; + default: + TextView.WrapMode = Gtk.WrapMode.None; + break; + } + } + } + + public bool ShowFrame { + get { return ((Gtk.Frame)Widget).ShadowType != Gtk.ShadowType.None; } + set { + if (value) { + ((Gtk.Frame)Widget).ShadowType = Gtk.ShadowType.In; + ((Gtk.Frame)Widget).BorderWidth = 2; + } else { + ((Gtk.Frame)Widget).ShadowType = Gtk.ShadowType.None; + ((Gtk.Frame)Widget).BorderWidth = 0; + } + } + } + + public int CursorPosition { + get { + var iter = TextView.Buffer.GetIterAtMark (TextView.Buffer.InsertMark); + return iter.Offset; + } + set { + var iter = TextView.Buffer.GetIterAtOffset (value); + TextView.Buffer.PlaceCursor (iter); + } + } + + public int SelectionStart { + get { + Gtk.TextIter start, end; + TextView.Buffer.GetSelectionBounds (out start, out end); + return start.Offset; + } + set { + Gtk.TextIter start, end; + TextView.Buffer.GetSelectionBounds (out start, out end); + var cacheLength = end.Offset - start.Offset; + start.Offset = value; + end.Offset = value + cacheLength; + TextView.GrabFocus (); + TextView.Buffer.SelectRange (start, end); + HandleSelectionChanged (); + } + } + + public int SelectionLength { + get { + Gtk.TextIter start, end; + if (!TextView.Buffer.GetSelectionBounds (out start, out end)) + return 0; + return end.Offset - start.Offset; + + } + set { + Gtk.TextIter start, end; + if (!TextView.Buffer.GetSelectionBounds (out start, out end)) { + start = TextView.Buffer.GetIterAtMark (TextView.Buffer.InsertMark); + end = start; + } + end.Offset = start.Offset + value; + TextView.GrabFocus (); + TextView.Buffer.SelectRange (start, end); + HandleSelectionChanged (); + } + } + + public string SelectedText { + get { + Gtk.TextIter start, end; + if (!TextView.Buffer.GetSelectionBounds (out start, out end)) + return String.Empty; + return TextView.Buffer.GetText (start, end, true); + } + set { + Gtk.TextIter start, end; + int cachedOffset; + if (!TextView.Buffer.GetSelectionBounds (out start, out end)) { + start = TextView.Buffer.GetIterAtMark (TextView.Buffer.InsertMark); + cachedOffset = start.Offset; + } else { + cachedOffset = start.Offset; + TextView.Buffer.DeleteSelection (true, true); + start = TextView.Buffer.GetIterAtOffset (cachedOffset); + } + TextView.Buffer.Insert (ref start, value); + start.Offset = cachedOffset; + end = start; + end.Offset = start.Offset + value.Length; + TextView.GrabFocus (); + TextView.Buffer.SelectRange (start, end); + } + } + + public override void EnableEvent (object eventId) + { + base.EnableEvent (eventId); + if (eventId is TextBoxEvent) { + switch ((TextBoxEvent)eventId) { + case TextBoxEvent.Changed: TextView.Buffer.Changed += HandleChanged; break; + case TextBoxEvent.Activated: TextView.KeyPressEvent += HandleKeyPress; break; + case TextBoxEvent.SelectionChanged: + enableSelectionChangedEvent = true; + TextView.MoveCursor += HandleMoveCursor; + TextView.ButtonPressEvent += HandleButtonPressEvent; + TextView.ButtonReleaseEvent += HandleButtonReleaseEvent; + TextView.MotionNotifyEvent += HandleMotionNotifyEvent; + break; + } + } + } + + public override void DisableEvent (object eventId) + { + base.DisableEvent (eventId); + if (eventId is TextBoxEvent) { + switch ((TextBoxEvent)eventId) { + case TextBoxEvent.Changed: TextView.Buffer.Changed -= HandleChanged; break; + case TextBoxEvent.Activated: TextView.KeyPressEvent -= HandleKeyPress; break; + case TextBoxEvent.SelectionChanged: + enableSelectionChangedEvent = false; + TextView.MoveCursor -= HandleMoveCursor; + TextView.ButtonPressEvent -= HandleButtonPressEvent; + TextView.ButtonReleaseEvent -= HandleButtonReleaseEvent; + TextView.MotionNotifyEvent -= HandleMotionNotifyEvent; + break; + } + } + } + + void HandleChanged (object sender, EventArgs e) + { + ApplicationContext.InvokeUserCode (delegate { + EventSink.OnChanged (); + EventSink.OnSelectionChanged (); + }); + } + + [GLib.ConnectBefore] + void HandleKeyPress (object sender, Gtk.KeyPressEventArgs e) + { + if (e.Event.Key == Gdk.Key.Return || + e.Event.Key == Gdk.Key.ISO_Enter || + e.Event.Key == Gdk.Key.KP_Enter) + ApplicationContext.InvokeUserCode (delegate { + EventSink.OnActivated (); + }); + } + + bool enableSelectionChangedEvent; + void HandleSelectionChanged () + { + if (enableSelectionChangedEvent) + ApplicationContext.InvokeUserCode (delegate { + EventSink.OnSelectionChanged (); + }); + } + + void HandleMoveCursor (object sender, EventArgs e) + { + HandleSelectionChanged (); + } + + int cacheSelectionStart, cacheSelectionLength; + bool isMouseSelection; + + [GLib.ConnectBefore] + void HandleButtonPressEvent (object o, Gtk.ButtonPressEventArgs args) + { + if (args.Event.Button == 1) { + HandleSelectionChanged (); + cacheSelectionStart = SelectionStart; + cacheSelectionLength = SelectionLength; + isMouseSelection = true; + } + } + + [GLib.ConnectBefore] + void HandleMotionNotifyEvent (object o, Gtk.MotionNotifyEventArgs args) + { + if (isMouseSelection) + if (cacheSelectionStart != SelectionStart || cacheSelectionLength != SelectionLength) + HandleSelectionChanged (); + cacheSelectionStart = SelectionStart; + cacheSelectionLength = SelectionLength; + } + + [GLib.ConnectBefore] + void HandleButtonReleaseEvent (object o, Gtk.ButtonReleaseEventArgs args) + { + if (args.Event.Button == 1) { + isMouseSelection = false; + HandleSelectionChanged (); + } + } + + protected override void Dispose (bool disposing) + { + if (disposing) { + var l = layout; + if (l != null) { + l.Dispose (); + layout = null; + } + } + base.Dispose (disposing); + } + } +} + diff --git a/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs new file mode 100644 index 000000000..c0c04483d --- /dev/null +++ b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs @@ -0,0 +1,95 @@ +// +// TextAreaBackendGtk2.cs +// +// Author: +// Vsevolod Kukol +// +// Copyright (c) 2014 Vsevolod Kukol +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace Xwt.GtkBackend +{ + public partial class TextAreaBackend + { + string placeHolderText; + + public string PlaceholderText { + get { return placeHolderText; } + set { + if (placeHolderText != value) { + if (placeHolderText == null) + TextView.ExposeEvent += HandleWidgetExposeEvent; + else if (value == null) + TextView.ExposeEvent -= HandleWidgetExposeEvent; + } + placeHolderText = value; + } + } + + void HandleWidgetExposeEvent (object o, Gtk.ExposeEventArgs args) + { + RenderPlaceholderText (TextView, args, placeHolderText, ref layout); + } + + public static void RenderPlaceholderText (Gtk.TextView widget, Gtk.ExposeEventArgs args, string placeHolderText, ref Pango.Layout layout) + { + if (args.Event.Window != widget.GetWindow (Gtk.TextWindowType.Text)) + return; + + if (widget.Buffer.Text.Length > 0) + return; + + float xalign = 0; + float yalign = 0; + + switch (widget.Justification) { + case Gtk.Justification.Center: xalign = 0.5f; break; + case Gtk.Justification.Right: xalign = 1; break; + } + + if (layout == null) { + layout = new Pango.Layout (widget.PangoContext); + layout.FontDescription = widget.PangoContext.FontDescription.Copy (); + } + + int wh, ww; + int xpad = 3; + int ypad = 0; + args.Event.Window.GetSize (out ww, out wh); + + int width, height; + layout.SetText (placeHolderText); + layout.GetPixelSize (out width, out height); + + int x = xpad + (int)((ww - width) * xalign); + int y = ypad + (int)((wh - height) * yalign); + + using (var gc = new Gdk.GC (args.Event.Window)) { + gc.Copy (widget.Style.TextGC (Gtk.StateType.Normal)); + Xwt.Drawing.Color color_a = widget.Style.Base (Gtk.StateType.Normal).ToXwtValue (); + Xwt.Drawing.Color color_b = widget.Style.Text (Gtk.StateType.Normal).ToXwtValue (); + gc.RgbFgColor = color_b.BlendWith (color_a, 0.5).ToGtkValue (); + + args.Event.Window.DrawLayout (gc, x, y, layout); + } + } + } +} + diff --git a/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs new file mode 100644 index 000000000..8520272c9 --- /dev/null +++ b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs @@ -0,0 +1,89 @@ +// +// TextAreaBackendGtk3.cs +// +// Author: +// Vsevolod Kukol +// +// Copyright (c) 2014 Vsevolod Kukol +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Pango; +using Xwt.CairoBackend; + +namespace Xwt.GtkBackend +{ + public partial class TextAreaBackend + { + string placeHolderText; + + public string PlaceholderText { + get { return placeHolderText; } + set { + if (placeHolderText != value) { + if (placeHolderText == null) + TextView.Drawn += HandleDrawn; + else if (value == null) + TextView.Drawn -= HandleDrawn; + } + placeHolderText = value; + } + } + + void HandleDrawn (object o, Gtk.DrawnArgs args) + { + if (TextView.HasFocus) + return; + + if (TextView.Buffer.Text.Length > 0) + return; + + float xalign = 0; + float yalign = 0; + + switch (TextView.Justification) { + case Gtk.Justification.Center: xalign = 0.5f; break; + case Gtk.Justification.Right: xalign = 1; break; + } + + if (layout == null) { + layout = new Pango.Layout (TextView.PangoContext); + layout.FontDescription = TextView.PangoContext.FontDescription.Copy (); + } + + int xpad = 3; + int ypad = 0; + + int width, height; + layout.SetText (placeHolderText); + layout.GetPixelSize (out width, out height); + + int x = xpad + (int)((TextView.AllocatedWidth - width) * xalign); + int y = ypad + (int)((TextView.AllocatedHeight - height) * yalign); + args.Cr.MoveTo (x, y); + + Xwt.Drawing.Color color_a = TextView.Style.Base (Gtk.StateType.Normal).ToXwtValue (); + Xwt.Drawing.Color color_b = TextView.Style.Text (Gtk.StateType.Normal).ToXwtValue (); + args.Cr.SetSourceColor (color_b.BlendWith (color_a, 0.5).ToCairoColor()); + + Pango.CairoHelper.ShowLayout (args.Cr, layout); + } + } +} + From 34f89e17d9982ff62cc490090e27926d92c43620 Mon Sep 17 00:00:00 2001 From: Vsevolod Kukol Date: Mon, 28 Jul 2014 07:58:39 -0700 Subject: [PATCH 06/11] [MAC] track API changes (add TextArea), fix TextEntryBacked wrapping --- Xwt.Mac/Xwt.Mac/TextEntryBackend.cs | 311 +++++++++++++++++++++ Xwt.XamMac/Xwt.Mac/ComboBoxEntryBackend.cs | 4 +- Xwt.XamMac/Xwt.Mac/MacEngine.cs | 1 + 3 files changed, 314 insertions(+), 2 deletions(-) create mode 100644 Xwt.Mac/Xwt.Mac/TextEntryBackend.cs diff --git a/Xwt.Mac/Xwt.Mac/TextEntryBackend.cs b/Xwt.Mac/Xwt.Mac/TextEntryBackend.cs new file mode 100644 index 000000000..189d63509 --- /dev/null +++ b/Xwt.Mac/Xwt.Mac/TextEntryBackend.cs @@ -0,0 +1,311 @@ +// +// TextEntryBackend.cs +// +// Author: +// Lluis Sanchez +// +// Copyright (c) 2011 Xamarin Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Xwt.Backends; +using MonoMac.AppKit; + + +namespace Xwt.Mac +{ + public class TextEntryBackend: ViewBackend, ITextEntryBackend, ITextAreaBackend + { + int cacheSelectionStart, cacheSelectionLength; + bool checkMouseSelection; + + public TextEntryBackend () + { + } + + internal TextEntryBackend (MacComboBox field) + { + ViewObject = field; + } + + public override void Initialize () + { + base.Initialize (); + if (ViewObject is MacComboBox) { + ((MacComboBox)ViewObject).SetEntryEventSink (EventSink); + } else { + var view = new CustomTextField (EventSink, ApplicationContext); + ViewObject = new CustomAlignedContainer (EventSink, ApplicationContext, (NSView)view); + if (Frontend is Xwt.TextArea) + MultiLine = true; + else + MultiLine = false; + Wrap = WrapMode.None; + } + + Frontend.MouseEntered += delegate { + checkMouseSelection = true; + }; + Frontend.MouseExited += delegate { + checkMouseSelection = false; + HandleSelectionChanged (); + }; + Frontend.MouseMoved += delegate { + if (checkMouseSelection) + HandleSelectionChanged (); + }; + } + + protected override void OnSizeToFit () + { + Container.SizeToFit (); + } + + CustomAlignedContainer Container { + get { return base.Widget as CustomAlignedContainer; } + } + + public new NSTextField Widget { + get { return (ViewObject is MacComboBox) ? (NSTextField)ViewObject : (NSTextField) Container.Child; } + } + + protected override Size GetNaturalSize () + { + var s = base.GetNaturalSize (); + return new Size (EventSink.GetDefaultNaturalSize ().Width, s.Height); + } + + #region ITextEntryBackend implementation + public string Text { + get { + return Widget.StringValue; + } + set { + Widget.StringValue = value ?? string.Empty; + } + } + + public Alignment TextAlignment { + get { + return Widget.Alignment.ToAlignment (); + } + set { + Widget.Alignment = value.ToNSTextAlignment (); + } + } + + public bool ReadOnly { + get { + return !Widget.Editable; + } + set { + Widget.Editable = !value; + } + } + + public bool ShowFrame { + get { + return Widget.Bordered; + } + set { + Widget.Bordered = value; + } + } + + public string PlaceholderText { + get { + return ((NSTextFieldCell) Widget.Cell).PlaceholderString; + } + set { + ((NSTextFieldCell) Widget.Cell).PlaceholderString = value; + } + } + + public bool MultiLine { + get { + if (Widget is MacComboBox) + return false; + return Widget.Cell.UsesSingleLineMode; + } + set { + if (Widget is MacComboBox) + return; + if (value) { + Widget.Cell.UsesSingleLineMode = false; + Widget.Cell.Scrollable = false; + } else { + Widget.Cell.UsesSingleLineMode = true; + Widget.Cell.Scrollable = true; + } + Container.ExpandVertically = value; + } + } + + public WrapMode Wrap { + get { + if (!Widget.Cell.Wraps) + return WrapMode.None; + switch (Widget.Cell.LineBreakMode) { + case NSLineBreakMode.ByWordWrapping: + return WrapMode.Word; + case NSLineBreakMode.CharWrapping: + return WrapMode.Character; + default: + return WrapMode.None; + } + } + set { + if (value == WrapMode.None) { + Widget.Cell.Wraps = false; + } else { + Widget.Cell.Wraps = true; + switch (value) { + case WrapMode.Word: + case WrapMode.WordAndCharacter: + Widget.Cell.LineBreakMode = NSLineBreakMode.ByWordWrapping; + break; + case WrapMode.Character: + Widget.Cell.LineBreakMode = NSLineBreakMode.CharWrapping; + break; + } + } + } + } + + 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 { + 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 { + 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 { + 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 () + { + Widget.BecomeFirstResponder (); + } + #endregion + } + + class CustomTextField: NSTextField, IViewObject + { + ITextBoxEventSink eventSink; + ApplicationContext context; + + public CustomTextField (ITextBoxEventSink eventSink, ApplicationContext context) + { + this.context = context; + this.eventSink = eventSink; + } + + public NSView View { + get { + return this; + } + } + + public ViewBackend Backend { get; set; } + + public override void DidChange (MonoMac.Foundation.NSNotification notification) + { + 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; + } + } +} + diff --git a/Xwt.XamMac/Xwt.Mac/ComboBoxEntryBackend.cs b/Xwt.XamMac/Xwt.Mac/ComboBoxEntryBackend.cs index 16fd0e458..2a4a79851 100644 --- a/Xwt.XamMac/Xwt.Mac/ComboBoxEntryBackend.cs +++ b/Xwt.XamMac/Xwt.Mac/ComboBoxEntryBackend.cs @@ -96,7 +96,7 @@ public void SetTextColumn (int column) class MacComboBox : NSComboBox, IViewObject, INSComboBoxDelegate { IComboBoxEventSink eventSink; - ITextEntryEventSink entryEventSink; + ITextBoxEventSink entryEventSink; ApplicationContext context; int cacheSelectionStart, cacheSelectionLength; @@ -109,7 +109,7 @@ public MacComboBox (IComboBoxEventSink eventSink, ApplicationContext context) Delegate = this; } - public void SetEntryEventSink (ITextEntryEventSink entryEventSink) + public void SetEntryEventSink (ITextBoxEventSink entryEventSink) { this.entryEventSink = entryEventSink; } diff --git a/Xwt.XamMac/Xwt.Mac/MacEngine.cs b/Xwt.XamMac/Xwt.Mac/MacEngine.cs index bc6c19caa..80899fd89 100644 --- a/Xwt.XamMac/Xwt.Mac/MacEngine.cs +++ b/Xwt.XamMac/Xwt.Mac/MacEngine.cs @@ -91,6 +91,7 @@ public override void InitializeBackends () RegisterBackend (); RegisterBackend (); RegisterBackend (); + RegisterBackend (); RegisterBackend (); RegisterBackend (); RegisterBackend (); From 1deb0ca46022db3f1fb59555097c9c05b65e0aca Mon Sep 17 00:00:00 2001 From: Vsevolod Kukol Date: Thu, 8 Jan 2015 13:26:40 +0100 Subject: [PATCH 07/11] [Gtk] fix TextArea PlaceholderText rendering * Gtk2: use interal RenderPlaceholderText extension like TextEntry * Gtk3: use new RenderPlaceholderText extension for Gtk3 --- Xwt.Gtk/Xwt.GtkBackend/Gtk2Extensions.cs | 14 ++++++ Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs | 31 +++++++++++++ Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs | 45 +------------------ Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs | 36 +-------------- 4 files changed, 47 insertions(+), 79 deletions(-) diff --git a/Xwt.Gtk/Xwt.GtkBackend/Gtk2Extensions.cs b/Xwt.Gtk/Xwt.GtkBackend/Gtk2Extensions.cs index 8abab839b..ecac16375 100644 --- a/Xwt.Gtk/Xwt.GtkBackend/Gtk2Extensions.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/Gtk2Extensions.cs @@ -206,6 +206,20 @@ public static void RenderPlaceholderText (this Gtk.Entry entry, Gtk.ExposeEventA RenderPlaceholderText_internal (entry, args, placeHolderText, ref layout, entry.Xalign, 0.5f, 1, 0); } + public static void RenderPlaceholderText (this Gtk.TextView textView, Gtk.ExposeEventArgs args, string placeHolderText, ref Pango.Layout layout) + { + if (args.Event.Window != textView.GetWindow (Gtk.TextWindowType.Text)) + return; + if (textView.Buffer.Text.Length > 0) + return; + float xalign = 0; + switch (textView.Justification) { + case Gtk.Justification.Center: xalign = 0.5f; break; + case Gtk.Justification.Right: xalign = 1; break; + } + RenderPlaceholderText_internal (textView, args, placeHolderText, ref layout, xalign, 0.0f, 3, 0); + } + static void RenderPlaceholderText_internal (Gtk.Widget widget, Gtk.ExposeEventArgs args, string placeHolderText, ref Pango.Layout layout, float xalign, float yalign, int xpad, int ypad) { if (layout == null) { diff --git a/Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs b/Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs index 42e47d637..40fa79657 100644 --- a/Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using Xwt.Backends; +using Xwt.CairoBackend; using System; using System.Runtime.InteropServices; using Gtk; @@ -239,6 +240,36 @@ public static double GetSliderPosition (this Gtk.Scale scale) scale.GetSliderRange (out start, out end); return start + ((end - start) / 2); } + + public static void RenderPlaceholderText (this Gtk.TextView textView, Cairo.Context cr, string placeHolderText, ref Pango.Layout layout) + { + if (textView.Buffer.Text.Length > 0) + return; + float xalign = 0; + switch (textView.Justification) { + case Gtk.Justification.Center: xalign = 0.5f; break; + case Gtk.Justification.Right: xalign = 1; break; + } + RenderPlaceholderText_internal (textView, cr, placeHolderText, ref layout, xalign, 0.0f, 3, 0); + } + + static void RenderPlaceholderText_internal (Gtk.Widget widget, Cairo.Context cr, string placeHolderText, ref Pango.Layout layout, float xalign, float yalign, int xpad, int ypad) + { + if (layout == null) { + layout = new Pango.Layout (widget.PangoContext); + layout.FontDescription = widget.PangoContext.FontDescription.Copy (); + } + int width, height; + layout.SetText (placeHolderText); + layout.GetPixelSize (out width, out height); + int x = xpad + (int)((widget.AllocatedWidth - width) * xalign); + int y = ypad + (int)((widget.AllocatedHeight - height) * yalign); + Xwt.Drawing.Color color_a = widget.StyleContext.GetBackgroundColor (Gtk.StateFlags.Normal).ToXwtValue (); + Xwt.Drawing.Color color_b = widget.StyleContext.GetColor (Gtk.StateFlags.Normal).ToXwtValue (); + cr.SetSourceColor (color_b.BlendWith (color_a, 0.5).ToCairoColor ()); + cr.MoveTo (x, y); + Pango.CairoHelper.ShowLayout (cr, layout); + } } } diff --git a/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs index c0c04483d..395924b75 100644 --- a/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk2.cs @@ -45,50 +45,7 @@ public string PlaceholderText { void HandleWidgetExposeEvent (object o, Gtk.ExposeEventArgs args) { - RenderPlaceholderText (TextView, args, placeHolderText, ref layout); - } - - public static void RenderPlaceholderText (Gtk.TextView widget, Gtk.ExposeEventArgs args, string placeHolderText, ref Pango.Layout layout) - { - if (args.Event.Window != widget.GetWindow (Gtk.TextWindowType.Text)) - return; - - if (widget.Buffer.Text.Length > 0) - return; - - float xalign = 0; - float yalign = 0; - - switch (widget.Justification) { - case Gtk.Justification.Center: xalign = 0.5f; break; - case Gtk.Justification.Right: xalign = 1; break; - } - - if (layout == null) { - layout = new Pango.Layout (widget.PangoContext); - layout.FontDescription = widget.PangoContext.FontDescription.Copy (); - } - - int wh, ww; - int xpad = 3; - int ypad = 0; - args.Event.Window.GetSize (out ww, out wh); - - int width, height; - layout.SetText (placeHolderText); - layout.GetPixelSize (out width, out height); - - int x = xpad + (int)((ww - width) * xalign); - int y = ypad + (int)((wh - height) * yalign); - - using (var gc = new Gdk.GC (args.Event.Window)) { - gc.Copy (widget.Style.TextGC (Gtk.StateType.Normal)); - Xwt.Drawing.Color color_a = widget.Style.Base (Gtk.StateType.Normal).ToXwtValue (); - Xwt.Drawing.Color color_b = widget.Style.Text (Gtk.StateType.Normal).ToXwtValue (); - gc.RgbFgColor = color_b.BlendWith (color_a, 0.5).ToGtkValue (); - - args.Event.Window.DrawLayout (gc, x, y, layout); - } + TextView.RenderPlaceholderText (args, placeHolderText, ref layout); } } } diff --git a/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs index 8520272c9..599750512 100644 --- a/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackendGtk3.cs @@ -48,41 +48,7 @@ public string PlaceholderText { void HandleDrawn (object o, Gtk.DrawnArgs args) { - if (TextView.HasFocus) - return; - - if (TextView.Buffer.Text.Length > 0) - return; - - float xalign = 0; - float yalign = 0; - - switch (TextView.Justification) { - case Gtk.Justification.Center: xalign = 0.5f; break; - case Gtk.Justification.Right: xalign = 1; break; - } - - if (layout == null) { - layout = new Pango.Layout (TextView.PangoContext); - layout.FontDescription = TextView.PangoContext.FontDescription.Copy (); - } - - int xpad = 3; - int ypad = 0; - - int width, height; - layout.SetText (placeHolderText); - layout.GetPixelSize (out width, out height); - - int x = xpad + (int)((TextView.AllocatedWidth - width) * xalign); - int y = ypad + (int)((TextView.AllocatedHeight - height) * yalign); - args.Cr.MoveTo (x, y); - - Xwt.Drawing.Color color_a = TextView.Style.Base (Gtk.StateType.Normal).ToXwtValue (); - Xwt.Drawing.Color color_b = TextView.Style.Text (Gtk.StateType.Normal).ToXwtValue (); - args.Cr.SetSourceColor (color_b.BlendWith (color_a, 0.5).ToCairoColor()); - - Pango.CairoHelper.ShowLayout (args.Cr, layout); + TextView.RenderPlaceholderText (args.Cr, placeHolderText, ref layout); } } } From eba74d324def4a642308a89fe8c5b26fb6c14714 Mon Sep 17 00:00:00 2001 From: Vsevolod Kukol Date: Thu, 8 Jan 2015 13:47:15 +0100 Subject: [PATCH 08/11] [Gtk3] hide PlaceholderText when TextArea focused Makes the TextArea placeholder text behave like Gtk3 TextEntry.PlaceholderText, which is to hide it, when the text area is focused. --- Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs b/Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs index 40fa79657..66f392dcc 100644 --- a/Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/Gtk3Extensions.cs @@ -243,7 +243,7 @@ public static double GetSliderPosition (this Gtk.Scale scale) public static void RenderPlaceholderText (this Gtk.TextView textView, Cairo.Context cr, string placeHolderText, ref Pango.Layout layout) { - if (textView.Buffer.Text.Length > 0) + if (textView.Buffer.Text.Length > 0 || textView.HasFocus) return; float xalign = 0; switch (textView.Justification) { From 73c7778c7f96d3c3b58241ccbb3c1c1ce3270baf Mon Sep 17 00:00:00 2001 From: Claudio Rodrigo Pereyra Diaz Date: Thu, 28 Feb 2019 12:28:20 -0300 Subject: [PATCH 09/11] Resolve conflict between System.Windows.Controls.TextBox and Xwt.TextBox --- Xwt.WPF/Xwt.WPFBackend/ComboBoxTextEntryBackend.cs | 2 +- Xwt.WPF/Xwt.WPFBackend/ExComboBox.cs | 4 ++-- Xwt.WPF/Xwt.WPFBackend/PlaceholderTextAdorner.cs | 2 +- Xwt.WPF/Xwt.WPFBackend/WindowsSpinButton.xaml.cs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Xwt.WPF/Xwt.WPFBackend/ComboBoxTextEntryBackend.cs b/Xwt.WPF/Xwt.WPFBackend/ComboBoxTextEntryBackend.cs index 13e57c7f2..695ae7fdc 100644 --- a/Xwt.WPF/Xwt.WPFBackend/ComboBoxTextEntryBackend.cs +++ b/Xwt.WPF/Xwt.WPFBackend/ComboBoxTextEntryBackend.cs @@ -110,7 +110,7 @@ public bool ShowFrame } } - protected TextBox TextBox { + protected System.Windows.Controls.TextBox TextBox { get { return combobox.TextBox; } } diff --git a/Xwt.WPF/Xwt.WPFBackend/ExComboBox.cs b/Xwt.WPF/Xwt.WPFBackend/ExComboBox.cs index e1c7fd1c3..9ceacf469 100644 --- a/Xwt.WPF/Xwt.WPFBackend/ExComboBox.cs +++ b/Xwt.WPF/Xwt.WPFBackend/ExComboBox.cs @@ -47,7 +47,7 @@ public WidgetBackend Backend set; } - public TextBox TextBox { get; private set; } + public System.Windows.Controls.TextBox TextBox { get; private set; } protected override SW.Size MeasureOverride (SW.Size constraint) { @@ -57,7 +57,7 @@ protected override SW.Size MeasureOverride (SW.Size constraint) void UpdateTextBox () { - var newTextBox = GetTemplateChild(TextBoxTemplateName) as TextBox; + var newTextBox = GetTemplateChild(TextBoxTemplateName) as System.Windows.Controls.TextBox; if (TextBox == newTextBox) // no change return; if (TextBox != null) diff --git a/Xwt.WPF/Xwt.WPFBackend/PlaceholderTextAdorner.cs b/Xwt.WPF/Xwt.WPFBackend/PlaceholderTextAdorner.cs index dec0a0d4e..51142d1d3 100644 --- a/Xwt.WPF/Xwt.WPFBackend/PlaceholderTextAdorner.cs +++ b/Xwt.WPF/Xwt.WPFBackend/PlaceholderTextAdorner.cs @@ -103,7 +103,7 @@ protected override void OnRender(System.Windows.Media.DrawingContext drawingCont } else if (AdornedTextBox != null) { multiline = AdornedTextBox.AcceptsReturn; - alignment = AdornedTextBox.ReadLocalValue (TextBox.TextAlignmentProperty) !=DependencyProperty.UnsetValue ? AdornedTextBox.TextAlignment : ConvertAlignment (AdornedTextBox.HorizontalContentAlignment); + alignment = AdornedTextBox.ReadLocalValue (System.Windows.Controls.TextBox.TextAlignmentProperty) !=DependencyProperty.UnsetValue ? AdornedTextBox.TextAlignment : ConvertAlignment (AdornedTextBox.HorizontalContentAlignment); flowDirection = AdornedTextBox.FlowDirection; fontSize = AdornedTextBox.FontSize; typeFace = AdornedTextBox.FontFamily.GetTypefaces ().FirstOrDefault (); diff --git a/Xwt.WPF/Xwt.WPFBackend/WindowsSpinButton.xaml.cs b/Xwt.WPF/Xwt.WPFBackend/WindowsSpinButton.xaml.cs index 5adf6bb5d..c02251bfa 100644 --- a/Xwt.WPF/Xwt.WPFBackend/WindowsSpinButton.xaml.cs +++ b/Xwt.WPF/Xwt.WPFBackend/WindowsSpinButton.xaml.cs @@ -247,7 +247,7 @@ private void UpdateTextbox() } } - public TextBox TextBox => textBox; + public System.Windows.Controls.TextBox TextBox => textBox; private void UserControl_Loaded(object sender, RoutedEventArgs e) { @@ -465,7 +465,7 @@ protected override AutomationPeer OnCreateAutomationPeer () return new WindowsSpinButtonAutomationPeer (this); } - class SpinButtonTextBox : TextBox + class SpinButtonTextBox : System.Windows.Controls.TextBox { WindowsSpinButton spinButton; From 33aa37177b5eaa69e6ed0744354d6a28e079de34 Mon Sep 17 00:00:00 2001 From: Claudio Rodrigo Pereyra Diaz Date: Thu, 28 Feb 2019 12:28:52 -0300 Subject: [PATCH 10/11] Replace TextEntryEvent with TextBoxEvent --- Xwt/Xwt/TextEntry.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Xwt/Xwt/TextEntry.cs b/Xwt/Xwt/TextEntry.cs index 79cfdd3a2..a78c1a165 100644 --- a/Xwt/Xwt/TextEntry.cs +++ b/Xwt/Xwt/TextEntry.cs @@ -35,9 +35,9 @@ public class TextEntry: TextBox public TextEntry () { // TODO: DEPRECATED! Safe to remove? - MapEvent (TextEntryEvent.Changed, typeof(TextBox), "OnChanged"); - MapEvent (TextEntryEvent.Activated, typeof(TextBox), "OnActivated"); - MapEvent (TextEntryEvent.SelectionChanged, typeof(TextBox), "OnSelectionChanged"); + MapEvent (TextBoxEvent.Changed, typeof(TextBox), "OnChanged"); + MapEvent (TextBoxEvent.Activated, typeof(TextBox), "OnActivated"); + MapEvent (TextBoxEvent.SelectionChanged, typeof(TextBox), "OnSelectionChanged"); } protected new class WidgetBackendHost: TextBox.WidgetBackendHost, ITextEntryEventSink From 0bd91230aca7c756c0fd2892e9bc03d5f703ec0f Mon Sep 17 00:00:00 2001 From: Claudio Rodrigo Pereyra Diaz Date: Thu, 28 Feb 2019 12:51:39 -0300 Subject: [PATCH 11/11] Add SetCompletation empty method --- Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs index 961899f5f..54de0e7ff 100644 --- a/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/TextAreaBackend.cs @@ -214,7 +214,15 @@ public string SelectedText { } } - public override void EnableEvent (object eventId) + public bool HasCompletions + { + get + { + throw new NotImplementedException(); + } + } + + public override void EnableEvent (object eventId) { base.EnableEvent (eventId); if (eventId is TextBoxEvent) { @@ -327,6 +335,16 @@ protected override void Dispose (bool disposing) } base.Dispose (disposing); } - } + + public void SetCompletions(string[] completions) + { + throw new NotImplementedException(); + } + + public void SetCompletionMatchFunc(Func matchFunc) + { + throw new NotImplementedException(); + } + } }