mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Improved a better clipped screen. Fixes some bugs with ScrollView, Menu. Added some virtual methods. (#410)
* Improved a better clipped screen. Fixes some bugs with ScrollView, Menu. Added some virtual methods. * Added some more key features, like shift. Cleaning and updating some stuffs .Added more features to TextField. * Closes the menu even in a button pressed in another view than menu. * Added a OnKeyPress action. Now all the keys events are properly mapped to the keys modifiers. Fixed a issue which keys like (ã, á, â) aren't correctly written. * Fixed an issue with the shift flag for keys ControlA_Z. * Ensures quiting the terminal if no other option is provided by pressing Ctrl-Q * Ensures the exception is thrown before ordered.Reverse. * Changed Button4 To Button3 for CursesDriver compatibility. * Added support for word selection through keyboard and the mouse. With triple click all text is selected. * Changed AllowNewLine to AllowWrap. * Fix topological sort in view class (#413) * AllowWrap removed and keys issues fixed. * Removing ordered.Reverse (); Something went wrong. * Fixes FrameView title. * Reverted some MapKeyModifiers that prevented the display of some characters. * Avoiding open the menu-bar every time we typing (€@£§). Alt key now only highlight the menu-bar without open it. * Fixes hot-key issue preventing menu closing after opened. * Curses now supports hot-keys and simulates AltMask with Alt+Space. Also supports shift and ctrl combinations to use with text selection. * Maintains the menu highlighted while focused. * Removed the IsOutBounds method. This feature is for a future presentation. Co-authored-by: En3Tho <37334640+En3Tho@users.noreply.github.com>
This commit is contained in:
@@ -15,19 +15,45 @@ namespace Designer {
|
||||
MessageBox.ErrorQuery (50, 7, "Error", "There is nothing to close", "Ok");
|
||||
}
|
||||
|
||||
static void Copy ()
|
||||
{
|
||||
TextField textField = menu.LastFocused as TextField;
|
||||
if (textField != null && textField.SelectedLength != 0) {
|
||||
textField.Copy ();
|
||||
}
|
||||
}
|
||||
|
||||
static void Cut ()
|
||||
{
|
||||
TextField textField = menu.LastFocused as TextField;
|
||||
if (textField != null && textField.SelectedLength != 0) {
|
||||
textField.Cut ();
|
||||
}
|
||||
}
|
||||
|
||||
static void Paste ()
|
||||
{
|
||||
TextField textField = menu.LastFocused as TextField;
|
||||
if (textField != null) {
|
||||
textField.Paste ();
|
||||
}
|
||||
}
|
||||
|
||||
public static MenuBar menu;
|
||||
|
||||
public static void Main (string [] args)
|
||||
{
|
||||
Application.Init ();
|
||||
|
||||
var menu = new MenuBar (new MenuBarItem [] {
|
||||
menu = new MenuBar (new MenuBarItem [] {
|
||||
new MenuBarItem ("_File", new MenuItem [] {
|
||||
new MenuItem ("_Close", "", () => Close ()),
|
||||
new MenuItem ("_Quit", "", () => { Application.RequestStop (); })
|
||||
}),
|
||||
new MenuBarItem ("_Edit", new MenuItem [] {
|
||||
new MenuItem ("_Copy", "", null),
|
||||
new MenuItem ("C_ut", "", null),
|
||||
new MenuItem ("_Paste", "", null)
|
||||
new MenuItem ("_Copy", "", Copy),
|
||||
new MenuItem ("C_ut", "", Cut),
|
||||
new MenuItem ("_Paste", "", Paste)
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -36,18 +62,22 @@ namespace Designer {
|
||||
X = Pos.Left (login),
|
||||
Y = Pos.Bottom (login) + 1
|
||||
};
|
||||
var test = new Label ("Test: ") {
|
||||
X = Pos.Left (login),
|
||||
Y = Pos.Bottom (password) + 1
|
||||
};
|
||||
|
||||
var surface = new Surface () {
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Width = Dim.Percent (80),
|
||||
Height = Dim.Fill ()
|
||||
Width = Dim.Percent (50),
|
||||
Height = Dim.Percent (50)
|
||||
};
|
||||
|
||||
var loginText = new TextField("") {
|
||||
X = Pos.Right(password),
|
||||
Y = Pos.Top(login),
|
||||
Width = 40,
|
||||
Width = Dim.Percent(90),
|
||||
ColorScheme = new ColorScheme() {
|
||||
Focus = Attribute.Make(Color.BrightYellow, Color.DarkGray),
|
||||
Normal = Attribute.Make(Color.Green, Color.BrightYellow),
|
||||
@@ -55,6 +85,10 @@ namespace Designer {
|
||||
HotNormal = Attribute.Make(Color.Red, Color.BrightRed),
|
||||
},
|
||||
};
|
||||
loginText.MouseEnter += LoginText_MouseEnter;
|
||||
loginText.MouseLeave += LoginText_MouseLeave;
|
||||
loginText.Enter += LoginText_Enter;
|
||||
loginText.Leave += LoginText_Leave;
|
||||
|
||||
var passText = new TextField ("") {
|
||||
Secret = true,
|
||||
@@ -63,9 +97,35 @@ namespace Designer {
|
||||
Width = Dim.Width (loginText)
|
||||
};
|
||||
|
||||
surface.Add (login, password, loginText, passText);
|
||||
var testText = new TextField ("") {
|
||||
X = Pos.Left (loginText),
|
||||
Y = Pos.Top (test),
|
||||
Width = Dim.Width (loginText)
|
||||
};
|
||||
|
||||
surface.Add (login, password, test, loginText, passText, testText);
|
||||
Application.Top.Add (menu, surface);
|
||||
Application.Run ();
|
||||
}
|
||||
|
||||
private static void LoginText_Leave (object sender, EventArgs e)
|
||||
{
|
||||
((TextField)sender).Text = $"Leaving from: {sender}";
|
||||
}
|
||||
|
||||
private static void LoginText_Enter (object sender, EventArgs e)
|
||||
{
|
||||
((TextField)sender).Text = $"Entering in: {sender}";
|
||||
}
|
||||
|
||||
private static void LoginText_MouseLeave (object sender, MouseEvent e)
|
||||
{
|
||||
((TextField)sender).Text = $"Mouse leave at X: {e.X}; Y: {e.Y} HasFocus: {e.View.HasFocus}";
|
||||
}
|
||||
|
||||
private static void LoginText_MouseEnter (object sender, MouseEvent e)
|
||||
{
|
||||
((TextField)sender).Text = $"Mouse enter at X: {e.X}; Y: {e.Y} HasFocus: {e.View.HasFocus}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,11 +413,11 @@ static class Demo {
|
||||
#endregion
|
||||
|
||||
|
||||
#region OnKeyDown / OnKeyUp Demo
|
||||
private static void OnKeyDownUpDemo ()
|
||||
#region OnKeyDown / OnKeyPress / OnKeyUp Demo
|
||||
private static void OnKeyDownPressUpDemo ()
|
||||
{
|
||||
var container = new Dialog (
|
||||
"OnKeyDown & OnKeyUp demo", 80, 20,
|
||||
"OnKeyDown & OnKeyPress & OnKeyUp demo", 80, 20,
|
||||
new Button ("Close") { Clicked = () => { Application.RequestStop (); } }) {
|
||||
Width = Dim.Fill (),
|
||||
Height = Dim.Fill (),
|
||||
@@ -433,20 +433,45 @@ static class Demo {
|
||||
listView.ColorScheme = Colors.TopLevel;
|
||||
container.Add (listView);
|
||||
|
||||
void KeyUpDown (KeyEvent keyEvent, string updown)
|
||||
void KeyDownPressUp (KeyEvent keyEvent, string updown)
|
||||
{
|
||||
if ((keyEvent.Key & Key.CtrlMask) != 0) {
|
||||
list.Add ($"Key{updown,-4}: Ctrl ");
|
||||
} else if ((keyEvent.Key & Key.AltMask) != 0) {
|
||||
list.Add ($"Key{updown,-4}: Alt ");
|
||||
} else {
|
||||
list.Add ($"Key{updown,-4}: {(((uint)keyEvent.KeyValue & (uint)Key.CharMask) > 26 ? $"{(char)keyEvent.KeyValue}" : $"{keyEvent.Key}")}");
|
||||
const int ident = -5;
|
||||
switch (updown) {
|
||||
case "Down":
|
||||
case "Up":
|
||||
case "Press":
|
||||
var msg = $"Key{updown,ident}: ";
|
||||
if ((keyEvent.Key & Key.ShiftMask) != 0)
|
||||
msg += "Shift ";
|
||||
if ((keyEvent.Key & Key.CtrlMask) != 0)
|
||||
msg += "Ctrl ";
|
||||
if ((keyEvent.Key & Key.AltMask) != 0)
|
||||
msg += "Alt ";
|
||||
msg += $"{(((uint)keyEvent.KeyValue & (uint)Key.CharMask) > 26 ? $"{(char)keyEvent.KeyValue}" : $"{keyEvent.Key}")}";
|
||||
list.Add (msg);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((keyEvent.Key & Key.ShiftMask) != 0) {
|
||||
list.Add ($"Key{updown,ident}: Shift ");
|
||||
} else if ((keyEvent.Key & Key.CtrlMask) != 0) {
|
||||
list.Add ($"Key{updown,ident}: Ctrl ");
|
||||
} else if ((keyEvent.Key & Key.AltMask) != 0) {
|
||||
list.Add ($"Key{updown,ident}: Alt ");
|
||||
} else {
|
||||
list.Add ($"Key{updown,ident}: {(((uint)keyEvent.KeyValue & (uint)Key.CharMask) > 26 ? $"{(char)keyEvent.KeyValue}" : $"{keyEvent.Key}")}");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
listView.MoveDown ();
|
||||
}
|
||||
|
||||
container.OnKeyDown += (KeyEvent keyEvent) => KeyUpDown (keyEvent, "Down");
|
||||
container.OnKeyUp += (KeyEvent keyEvent) => KeyUpDown (keyEvent, "Up");
|
||||
|
||||
container.OnKeyDown += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Down");
|
||||
container.OnKeyPress += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Press");
|
||||
container.OnKeyUp += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Up");
|
||||
Application.Run (container);
|
||||
}
|
||||
#endregion
|
||||
@@ -518,7 +543,7 @@ static class Demo {
|
||||
}),
|
||||
new MenuBarItem ("A_ssorted", new MenuItem [] {
|
||||
new MenuItem ("_Show text alignments", "", () => ShowTextAlignments ()),
|
||||
new MenuItem ("_OnKeyDown/Up", "", () => OnKeyDownUpDemo ())
|
||||
new MenuItem ("_OnKeyDown/Press/Up", "", () => OnKeyDownPressUpDemo ())
|
||||
}),
|
||||
new MenuBarItem ("_Test Menu and SubMenus", new MenuItem [] {
|
||||
new MenuItem ("SubMenu1Item_1",
|
||||
@@ -565,7 +590,7 @@ static class Demo {
|
||||
new StatusItem(Key.F1, "~F1~ Help", () => Help()),
|
||||
new StatusItem(Key.F2, "~F2~ Load", null),
|
||||
new StatusItem(Key.F3, "~F3~ Save", null),
|
||||
new StatusItem(Key.ControlX, "~^X~ Quit", () => { if (Quit ()) top.Running = false; }),
|
||||
new StatusItem(Key.ControlQ, "~^Q~ Quit", () => { if (Quit ()) top.Running = false; }),
|
||||
}) {
|
||||
Parent = null,
|
||||
};
|
||||
|
||||
@@ -111,7 +111,7 @@ class Demo {
|
||||
Y = Pos.Top (password),
|
||||
Width = Dim.Width (loginText)
|
||||
};
|
||||
|
||||
|
||||
// Add some content
|
||||
container.Add (
|
||||
login,
|
||||
@@ -162,7 +162,7 @@ class Demo {
|
||||
|
||||
static void Close ()
|
||||
{
|
||||
MessageBox.ErrorQuery (50, 5, "Error", "There is nothing to close", "Ok");
|
||||
MessageBox.ErrorQuery (50, 7, "Error", "There is nothing to close", "Ok");
|
||||
}
|
||||
|
||||
public static Label ml;
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Terminal.Gui" Version="0.17.0" />
|
||||
<PackageReference Include="Terminal.Gui" Version="0.81.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
25
StandaloneExample/StandaloneExample.sln
Normal file
25
StandaloneExample/StandaloneExample.sln
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30011.22
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneExample", "StandaloneExample.csproj", "{8DC768EF-530D-4261-BD35-FC41E13B041E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8DC768EF-530D-4261-BD35-FC41E13B041E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8DC768EF-530D-4261-BD35-FC41E13B041E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8DC768EF-530D-4261-BD35-FC41E13B041E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8DC768EF-530D-4261-BD35-FC41E13B041E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C9C434AC-B7E4-43AB-834A-F9489766FDFF}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -151,6 +151,44 @@ namespace Terminal.Gui {
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method invoked when a mouse event is generated for the first time.
|
||||
/// </summary>
|
||||
/// <param name="mouseEvent"></param>
|
||||
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
|
||||
public virtual bool OnMouseEnter (MouseEvent mouseEvent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method invoked when a mouse event is generated for the last time.
|
||||
/// </summary>
|
||||
/// <param name="mouseEvent"></param>
|
||||
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
|
||||
public virtual bool OnMouseLeave (MouseEvent mouseEvent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method invoked when a view gets focus.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
|
||||
public virtual bool OnEnter ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method invoked when a view loses focus.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
|
||||
public virtual bool OnLeave ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -253,12 +291,22 @@ namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// Event fired when the view get focus.
|
||||
/// </summary>
|
||||
public event EventHandler OnEnter;
|
||||
public event EventHandler Enter;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the view lost focus.
|
||||
/// </summary>
|
||||
public event EventHandler OnLeave;
|
||||
public event EventHandler Leave;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the view receives the mouse event for the first time.
|
||||
/// </summary>
|
||||
public event EventHandler<MouseEvent> MouseEnter;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the view loses mouse event for the last time.
|
||||
/// </summary>
|
||||
public event EventHandler<MouseEvent> MouseLeave;
|
||||
|
||||
internal Direction FocusDirection {
|
||||
get => SuperView?.FocusDirection ?? focusDirection;
|
||||
@@ -308,6 +356,10 @@ namespace Terminal.Gui {
|
||||
/// <value><c>true</c> if want mouse position reports; otherwise, <c>false</c>.</value>
|
||||
public virtual bool WantMousePositionReports { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.View"/> want continuous button pressed event.
|
||||
/// </summary>
|
||||
public virtual bool WantContinuousButtonPressed { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Gets or sets the frame for the view.
|
||||
/// </summary>
|
||||
@@ -857,22 +909,34 @@ namespace Terminal.Gui {
|
||||
}
|
||||
internal set {
|
||||
if (base.HasFocus != value)
|
||||
if (value == true)
|
||||
OnEnter?.Invoke (this, new EventArgs ());
|
||||
if (value)
|
||||
OnEnter ();
|
||||
else
|
||||
OnLeave?.Invoke (this, new EventArgs ());
|
||||
OnLeave ();
|
||||
SetNeedsDisplay ();
|
||||
base.HasFocus = value;
|
||||
|
||||
// Remove focus down the chain of subviews if focus is removed
|
||||
if (value == false && focused != null) {
|
||||
OnLeave?.Invoke (focused, new EventArgs ());
|
||||
if (!value && focused != null) {
|
||||
focused.OnLeave ();
|
||||
focused.HasFocus = false;
|
||||
focused = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnEnter ()
|
||||
{
|
||||
Enter?.Invoke (this, new EventArgs ());
|
||||
return base.OnEnter ();
|
||||
}
|
||||
|
||||
public override bool OnLeave ()
|
||||
{
|
||||
Leave?.Invoke (this, new EventArgs ());
|
||||
return base.OnLeave ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the currently focused view inside this view, or null if nothing is focused.
|
||||
/// </summary>
|
||||
@@ -958,6 +1022,7 @@ namespace Terminal.Gui {
|
||||
// FIXED: optimize this by computing the intersection of region and view.Bounds
|
||||
if (view.layoutNeeded)
|
||||
view.LayoutSubviews ();
|
||||
Application.CurrentView = view;
|
||||
view.Redraw (view.Bounds);
|
||||
}
|
||||
view.NeedDisplay = Rect.Empty;
|
||||
@@ -1001,9 +1066,15 @@ namespace Terminal.Gui {
|
||||
SuperView?.SetFocus(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a character key is pressed and occurs after the key down event.
|
||||
/// </summary>
|
||||
public Action<KeyEvent> OnKeyPress;
|
||||
|
||||
/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
|
||||
public override bool ProcessKey (KeyEvent keyEvent)
|
||||
{
|
||||
OnKeyPress?.Invoke (keyEvent);
|
||||
if (Focused?.ProcessKey (keyEvent) == true)
|
||||
return true;
|
||||
|
||||
@@ -1013,6 +1084,7 @@ namespace Terminal.Gui {
|
||||
/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
|
||||
public override bool ProcessHotKey (KeyEvent keyEvent)
|
||||
{
|
||||
OnKeyPress?.Invoke (keyEvent);
|
||||
if (subviews == null || subviews.Count == 0)
|
||||
return false;
|
||||
foreach (var view in subviews)
|
||||
@@ -1024,6 +1096,7 @@ namespace Terminal.Gui {
|
||||
/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
|
||||
public override bool ProcessColdKey (KeyEvent keyEvent)
|
||||
{
|
||||
OnKeyPress?.Invoke (keyEvent);
|
||||
if (subviews == null || subviews.Count == 0)
|
||||
return false;
|
||||
foreach (var view in subviews)
|
||||
@@ -1345,6 +1418,24 @@ namespace Terminal.Gui {
|
||||
{
|
||||
return $"{GetType ().Name}({Id})({Frame})";
|
||||
}
|
||||
|
||||
public override bool OnMouseEnter (MouseEvent mouseEvent)
|
||||
{
|
||||
if (!base.OnMouseEnter (mouseEvent)) {
|
||||
MouseEnter?.Invoke (this, mouseEvent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnMouseLeave (MouseEvent mouseEvent)
|
||||
{
|
||||
if (!base.OnMouseLeave (mouseEvent)) {
|
||||
MouseLeave?.Invoke (this, mouseEvent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1444,8 +1535,9 @@ namespace Terminal.Gui {
|
||||
return true;
|
||||
|
||||
switch (keyEvent.Key) {
|
||||
case Key.ControlC:
|
||||
// TODO: stop current execution of this container
|
||||
case Key.ControlQ:
|
||||
// FIXED: stop current execution of this container
|
||||
Application.RequestStop ();
|
||||
break;
|
||||
case Key.ControlZ:
|
||||
Driver.Suspend ();
|
||||
@@ -1460,6 +1552,7 @@ namespace Terminal.Gui {
|
||||
case Key.Tab:
|
||||
case Key.CursorRight:
|
||||
case Key.CursorDown:
|
||||
case Key.ControlI: // Unix
|
||||
var old = Focused;
|
||||
if (!FocusNext ())
|
||||
FocusNext ();
|
||||
@@ -1565,6 +1658,8 @@ namespace Terminal.Gui {
|
||||
|
||||
public override void Redraw (Rect region)
|
||||
{
|
||||
Application.CurrentView = this;
|
||||
|
||||
if (this == Application.Top) {
|
||||
if (!NeedDisplay.IsEmpty) {
|
||||
Driver.SetAttribute (Colors.TopLevel.Normal);
|
||||
@@ -1698,9 +1793,9 @@ namespace Terminal.Gui {
|
||||
return contentView.GetEnumerator ();
|
||||
}
|
||||
|
||||
void DrawFrame ()
|
||||
void DrawFrame (bool fill = true)
|
||||
{
|
||||
DrawFrame (new Rect (0, 0, Frame.Width, Frame.Height), padding, fill: true);
|
||||
DrawFrame (new Rect (0, 0, Frame.Width, Frame.Height), padding, fill: fill);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1745,23 +1840,31 @@ namespace Terminal.Gui {
|
||||
|
||||
public override void Redraw (Rect bounds)
|
||||
{
|
||||
Application.CurrentView = this;
|
||||
|
||||
if (!NeedDisplay.IsEmpty) {
|
||||
DrawFrameWindow ();
|
||||
}
|
||||
contentView.Redraw (contentView.Bounds);
|
||||
ClearNeedsDisplay ();
|
||||
DrawFrameWindow (false);
|
||||
|
||||
void DrawFrameWindow (bool fill = true)
|
||||
{
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
DrawFrame ();
|
||||
DrawFrame (fill);
|
||||
if (HasFocus)
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
var width = Frame.Width;
|
||||
Driver.SetAttribute (ColorScheme.HotNormal);
|
||||
var width = Frame.Width - (padding + 2) * 2;
|
||||
if (Title != null && width > 4) {
|
||||
Move (1+padding, padding);
|
||||
Move (1 + padding, padding);
|
||||
Driver.AddRune (' ');
|
||||
var str = Title.Length > width ? Title [0, width-4] : Title;
|
||||
var str = Title.Length >= width ? Title [0, width - 2] : Title;
|
||||
Driver.AddStr (str);
|
||||
Driver.AddRune (' ');
|
||||
}
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
}
|
||||
contentView.Redraw (contentView.Bounds);
|
||||
ClearNeedsDisplay ();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1778,7 +1881,7 @@ namespace Terminal.Gui {
|
||||
|
||||
int nx, ny;
|
||||
if ((mouseEvent.Flags == (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition) ||
|
||||
mouseEvent.Flags == MouseFlags.Button4Pressed)) {
|
||||
mouseEvent.Flags == MouseFlags.Button3Pressed)) {
|
||||
if (dragPosition.HasValue) {
|
||||
if (SuperView == null) {
|
||||
Application.Top.SetNeedsDisplay (Frame);
|
||||
@@ -1856,11 +1959,17 @@ namespace Terminal.Gui {
|
||||
public static Toplevel Top { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current toplevel object. This is updated when Application.Run enters and leaves and points to the current toplevel.
|
||||
/// The current toplevel object. This is updated when Application.Run enters and leaves and points to the current toplevel.
|
||||
/// </summary>
|
||||
/// <value>The current.</value>
|
||||
public static Toplevel Current { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// TThe current view object being redrawn.
|
||||
/// </summary>
|
||||
/// /// <value>The current.</value>
|
||||
public static View CurrentView { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The mainloop driver for the applicaiton
|
||||
/// </summary>
|
||||
@@ -1960,6 +2069,7 @@ namespace Terminal.Gui {
|
||||
SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext (MainLoop));
|
||||
Top = topLevelFactory ();
|
||||
Current = Top;
|
||||
CurrentView = Top;
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
@@ -2003,7 +2113,7 @@ namespace Terminal.Gui {
|
||||
|
||||
static void ProcessKeyEvent (KeyEvent ke)
|
||||
{
|
||||
|
||||
|
||||
var chain = toplevels.ToList();
|
||||
foreach (var topLevel in chain) {
|
||||
if (topLevel.ProcessHotKey (ke))
|
||||
@@ -2039,7 +2149,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ProcessKeyUpEvent (KeyEvent ke)
|
||||
{
|
||||
var chain = toplevels.ToList ();
|
||||
@@ -2111,9 +2221,18 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
static public Action<MouseEvent> RootMouseEvent;
|
||||
|
||||
internal static View wantContinuousButtonPressedView;
|
||||
static View lastMouseOwnerView;
|
||||
|
||||
static void ProcessMouseEvent (MouseEvent me)
|
||||
{
|
||||
var view = FindDeepestView (Current, me.X, me.Y, out int rx, out int ry);
|
||||
|
||||
if (view != null && view.WantContinuousButtonPressed)
|
||||
wantContinuousButtonPressedView = view;
|
||||
else
|
||||
wantContinuousButtonPressedView = null;
|
||||
|
||||
RootMouseEvent?.Invoke (me);
|
||||
if (mouseGrabView != null) {
|
||||
var newxy = mouseGrabView.ScreenToView (me.X, me.Y);
|
||||
@@ -2130,9 +2249,6 @@ namespace Terminal.Gui {
|
||||
}
|
||||
|
||||
if (view != null) {
|
||||
if (!view.WantMousePositionReports && me.Flags == MouseFlags.ReportMousePosition)
|
||||
return;
|
||||
|
||||
var nme = new MouseEvent () {
|
||||
X = rx,
|
||||
Y = ry,
|
||||
@@ -2141,6 +2257,24 @@ namespace Terminal.Gui {
|
||||
OfY = ry,
|
||||
View = view
|
||||
};
|
||||
|
||||
if (lastMouseOwnerView == null) {
|
||||
lastMouseOwnerView = view;
|
||||
view.OnMouseEnter (nme);
|
||||
} else if (lastMouseOwnerView != view) {
|
||||
lastMouseOwnerView.OnMouseLeave (nme);
|
||||
view.OnMouseEnter (nme);
|
||||
lastMouseOwnerView = view;
|
||||
}
|
||||
|
||||
if (!view.WantMousePositionReports && me.Flags == MouseFlags.ReportMousePosition)
|
||||
return;
|
||||
|
||||
if (view.WantContinuousButtonPressed)
|
||||
wantContinuousButtonPressedView = view;
|
||||
else
|
||||
wantContinuousButtonPressedView = null;
|
||||
|
||||
// Should we bubbled up the event, if it is not handled?
|
||||
view.MouseEvent (nme);
|
||||
}
|
||||
@@ -2217,6 +2351,8 @@ namespace Terminal.Gui {
|
||||
|
||||
static void Redraw (View view)
|
||||
{
|
||||
Application.CurrentView = view;
|
||||
|
||||
view.Redraw (view.Bounds);
|
||||
Driver.Refresh ();
|
||||
}
|
||||
|
||||
@@ -540,47 +540,73 @@ namespace Terminal.Gui {
|
||||
Move (region.X, region.Y);
|
||||
if (padding > 0) {
|
||||
for (int l = 0; l < padding; l++)
|
||||
for (b = 0; b < width; b++)
|
||||
for (b = region.X; b < region.X + width; b++) {
|
||||
AddRune (' ');
|
||||
Move (b + 1, region.Y);
|
||||
}
|
||||
}
|
||||
Move (region.X, region.Y + padding);
|
||||
for (int c = 0; c < padding; c++)
|
||||
for (int c = 0; c < padding; c++) {
|
||||
AddRune (' ');
|
||||
Move (region.X + 1, region.Y + padding);
|
||||
}
|
||||
AddRune (ULCorner);
|
||||
for (b = 0; b < fwidth - 2; b++)
|
||||
for (b = region.X; b < region.X + fwidth - 2; b++) {
|
||||
AddRune (HLine);
|
||||
Move (b + (padding > 0 ? padding + 2 : 2), region.Y + padding);
|
||||
}
|
||||
AddRune (URCorner);
|
||||
for (int c = 0; c < padding; c++)
|
||||
for (int c = 0; c < padding; c++) {
|
||||
AddRune (' ');
|
||||
|
||||
Move (region.X + 1, region.Y + padding);
|
||||
}
|
||||
for (b = 1 + padding; b < fheight; b++) {
|
||||
Move (region.X, region.Y + b);
|
||||
for (int c = 0; c < padding; c++)
|
||||
for (int c = 0; c < padding; c++) {
|
||||
AddRune (' ');
|
||||
Move (region.X + 1, region.Y + b);
|
||||
}
|
||||
AddRune (VLine);
|
||||
if (fill) {
|
||||
for (int x = 1; x < fwidth - 1; x++)
|
||||
for (int x = region.X + 1; x < region.X + fwidth - 1; x++) {
|
||||
AddRune (' ');
|
||||
} else
|
||||
Move (region.X + fwidth - 1, region.Y + b);
|
||||
Move (x + (padding > 0 ? padding + 1 : 1), region.Y + b);
|
||||
}
|
||||
} else {
|
||||
if (padding > 0)
|
||||
Move (region.X + fwidth, region.Y + b);
|
||||
else
|
||||
Move (region.X + fwidth - 1, region.Y + b);
|
||||
}
|
||||
AddRune (VLine);
|
||||
for (int c = 0; c < padding; c++)
|
||||
for (int c = 0; c < padding; c++) {
|
||||
AddRune (' ');
|
||||
Move (region.X + 1, region.Y + b);
|
||||
}
|
||||
}
|
||||
Move (region.X, region.Y + fheight);
|
||||
for (int c = 0; c < padding; c++)
|
||||
for (int c = 0; c < padding; c++) {
|
||||
AddRune (' ');
|
||||
Move (region.X + 1, region.Y + b);
|
||||
}
|
||||
AddRune (LLCorner);
|
||||
for (b = 0; b < fwidth - 2; b++)
|
||||
for (b = region.X; b < region.X + fwidth - 2; b++) {
|
||||
AddRune (HLine);
|
||||
Move (b + (padding > 0 ? padding + 2 : 2), region.Y + fheight);
|
||||
}
|
||||
AddRune (LRCorner);
|
||||
for (int c = 0; c < padding; c++)
|
||||
for (int c = 0; c < padding; c++) {
|
||||
AddRune (' ');
|
||||
Move (region.X + 1, region.Y);
|
||||
}
|
||||
if (padding > 0) {
|
||||
Move (region.X, region.Y + height - padding);
|
||||
for (int l = 0; l < padding; l++)
|
||||
for (b = 0; b < width; b++)
|
||||
for (int l = 0; l < padding; l++) {
|
||||
for (b = region.X; b < region.X + width; b++) {
|
||||
AddRune (' ');
|
||||
Move (b + 1, region.Y + height - padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,38 @@ namespace Terminal.Gui {
|
||||
case Curses.KeyInsertChar: return Key.InsertChar;
|
||||
case Curses.KeyBackTab: return Key.BackTab;
|
||||
case Curses.KeyBackspace: return Key.Backspace;
|
||||
case Curses.ShiftKeyUp: return Key.CursorUp | Key.ShiftMask;
|
||||
case Curses.ShiftKeyDown: return Key.CursorDown | Key.ShiftMask;
|
||||
case Curses.ShiftKeyLeft: return Key.CursorLeft | Key.ShiftMask;
|
||||
case Curses.ShiftKeyRight: return Key.CursorRight | Key.ShiftMask;
|
||||
case Curses.ShiftKeyHome: return Key.Home | Key.ShiftMask;
|
||||
case Curses.ShiftKeyEnd: return Key.End | Key.ShiftMask;
|
||||
case Curses.ShiftKeyNPage: return Key.PageDown | Key.ShiftMask;
|
||||
case Curses.ShiftKeyPPage: return Key.PageUp | Key.ShiftMask;
|
||||
case Curses.AltKeyUp: return Key.CursorUp | Key.AltMask;
|
||||
case Curses.AltKeyDown: return Key.CursorDown | Key.AltMask;
|
||||
case Curses.AltKeyLeft: return Key.CursorLeft | Key.AltMask;
|
||||
case Curses.AltKeyRight: return Key.CursorRight | Key.AltMask;
|
||||
case Curses.AltKeyHome: return Key.Home | Key.AltMask;
|
||||
case Curses.AltKeyEnd: return Key.End | Key.AltMask;
|
||||
case Curses.AltKeyNPage: return Key.PageDown | Key.AltMask;
|
||||
case Curses.AltKeyPPage: return Key.PageUp | Key.AltMask;
|
||||
case Curses.CtrlKeyUp: return Key.CursorUp | Key.CtrlMask;
|
||||
case Curses.CtrlKeyDown: return Key.CursorDown | Key.CtrlMask;
|
||||
case Curses.CtrlKeyLeft: return Key.CursorLeft | Key.CtrlMask;
|
||||
case Curses.CtrlKeyRight: return Key.CursorRight | Key.CtrlMask;
|
||||
case Curses.CtrlKeyHome: return Key.Home | Key.CtrlMask;
|
||||
case Curses.CtrlKeyEnd: return Key.End | Key.CtrlMask;
|
||||
case Curses.CtrlKeyNPage: return Key.PageDown | Key.CtrlMask;
|
||||
case Curses.CtrlKeyPPage: return Key.PageUp | Key.CtrlMask;
|
||||
case Curses.ShiftCtrlKeyUp: return Key.CursorUp | Key.ShiftMask | Key.CtrlMask;
|
||||
case Curses.ShiftCtrlKeyDown: return Key.CursorDown | Key.ShiftMask | Key.CtrlMask;
|
||||
case Curses.ShiftCtrlKeyLeft: return Key.CursorLeft | Key.ShiftMask | Key.CtrlMask;
|
||||
case Curses.ShiftCtrlKeyRight: return Key.CursorRight | Key.ShiftMask | Key.CtrlMask;
|
||||
case Curses.ShiftCtrlKeyHome: return Key.Home | Key.ShiftMask | Key.CtrlMask;
|
||||
case Curses.ShiftCtrlKeyEnd: return Key.End | Key.ShiftMask | Key.CtrlMask;
|
||||
case Curses.ShiftCtrlKeyNPage: return Key.PageDown | Key.ShiftMask | Key.CtrlMask;
|
||||
case Curses.ShiftCtrlKeyPPage: return Key.PageUp | Key.ShiftMask | Key.CtrlMask;
|
||||
default: return Key.Unknown;
|
||||
}
|
||||
}
|
||||
@@ -188,7 +220,12 @@ namespace Terminal.Gui {
|
||||
KeyEvent key;
|
||||
|
||||
// The ESC-number handling, debatable.
|
||||
if (wch >= '1' && wch <= '9')
|
||||
// Simulates the AltMask itself by pressing Alt + Space.
|
||||
if (wch == (int)Key.Space)
|
||||
key = new KeyEvent (Key.AltMask);
|
||||
else if (wch - (int)Key.Space >= 'A' && wch - (int)Key.Space <= 'Z')
|
||||
key = new KeyEvent ((Key)((uint)Key.AltMask + (wch - (int)Key.Space)));
|
||||
else if (wch >= '1' && wch <= '9')
|
||||
key = new KeyEvent ((Key)((int)Key.F1 + (wch - '0' - 1)));
|
||||
else if (wch == '0')
|
||||
key = new KeyEvent (Key.F10);
|
||||
|
||||
@@ -81,11 +81,11 @@ namespace Terminal.Gui {
|
||||
} else
|
||||
needMove = true;
|
||||
ccol++;
|
||||
if (ccol == Cols) {
|
||||
ccol = 0;
|
||||
if (crow + 1 < Rows)
|
||||
crow++;
|
||||
}
|
||||
//if (ccol == Cols) {
|
||||
// ccol = 0;
|
||||
// if (crow + 1 < Rows)
|
||||
// crow++;
|
||||
//}
|
||||
if (sync)
|
||||
UpdateScreen ();
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace Terminal.Gui {
|
||||
var newConsoleMode = originalConsoleMode;
|
||||
newConsoleMode |= (uint)(ConsoleModes.EnableMouseInput | ConsoleModes.EnableExtendedFlags);
|
||||
newConsoleMode &= ~(uint)ConsoleModes.EnableQuickEditMode;
|
||||
newConsoleMode &= ~(uint)ConsoleModes.EnableProcessedInput;
|
||||
ConsoleMode = newConsoleMode;
|
||||
}
|
||||
|
||||
@@ -124,6 +125,7 @@ namespace Terminal.Gui {
|
||||
|
||||
[Flags]
|
||||
public enum ConsoleModes : uint {
|
||||
EnableProcessedInput = 1,
|
||||
EnableMouseInput = 16,
|
||||
EnableQuickEditMode = 64,
|
||||
EnableExtendedFlags = 128,
|
||||
@@ -552,7 +554,6 @@ namespace Terminal.Gui {
|
||||
this.mouseHandler = mouseHandler;
|
||||
}
|
||||
|
||||
|
||||
void IMainLoopDriver.MainIteration ()
|
||||
{
|
||||
if (result == null)
|
||||
@@ -563,19 +564,50 @@ namespace Terminal.Gui {
|
||||
case WindowsConsole.EventType.Key:
|
||||
var map = MapKey (ToConsoleKeyInfoEx (inputEvent.KeyEvent));
|
||||
if (map == (Key)0xffffffff) {
|
||||
KeyEvent key;
|
||||
KeyEvent key = default;
|
||||
// Shift = VK_SHIFT = 0x10
|
||||
// Ctrl = VK_CONTROL = 0x11
|
||||
// Alt = VK_MENU = 0x12
|
||||
switch (inputEvent.KeyEvent.wVirtualKeyCode) {
|
||||
case 0x11:
|
||||
key = new KeyEvent (Key.CtrlMask);
|
||||
|
||||
switch (inputEvent.KeyEvent.dwControlKeyState) {
|
||||
case WindowsConsole.ControlKeyState.RightAltPressed:
|
||||
case WindowsConsole.ControlKeyState.RightAltPressed |
|
||||
WindowsConsole.ControlKeyState.LeftControlPressed |
|
||||
WindowsConsole.ControlKeyState.EnhancedKey:
|
||||
case WindowsConsole.ControlKeyState.EnhancedKey:
|
||||
key = new KeyEvent (Key.CtrlMask | Key.AltMask);
|
||||
break;
|
||||
case 0x12:
|
||||
case WindowsConsole.ControlKeyState.LeftAltPressed:
|
||||
key = new KeyEvent (Key.AltMask);
|
||||
break;
|
||||
case WindowsConsole.ControlKeyState.RightControlPressed:
|
||||
case WindowsConsole.ControlKeyState.LeftControlPressed:
|
||||
key = new KeyEvent (Key.CtrlMask);
|
||||
break;
|
||||
case WindowsConsole.ControlKeyState.ShiftPressed:
|
||||
key = new KeyEvent (Key.ShiftMask);
|
||||
break;
|
||||
case WindowsConsole.ControlKeyState.NumlockOn:
|
||||
break;
|
||||
case WindowsConsole.ControlKeyState.ScrolllockOn:
|
||||
break;
|
||||
case WindowsConsole.ControlKeyState.CapslockOn:
|
||||
break;
|
||||
default:
|
||||
key = new KeyEvent (Key.Unknown);
|
||||
switch (inputEvent.KeyEvent.wVirtualKeyCode) {
|
||||
case 0x10:
|
||||
key = new KeyEvent (Key.ShiftMask);
|
||||
break;
|
||||
case 0x11:
|
||||
key = new KeyEvent (Key.CtrlMask);
|
||||
break;
|
||||
case 0x12:
|
||||
key = new KeyEvent (Key.AltMask);
|
||||
break;
|
||||
default:
|
||||
key = new KeyEvent (Key.Unknown);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -652,7 +684,7 @@ namespace Terminal.Gui {
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.RightmostButtonPressed:
|
||||
mouseFlag = MouseFlags.Button4Pressed;
|
||||
mouseFlag = MouseFlags.Button3Pressed;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -679,6 +711,9 @@ namespace Terminal.Gui {
|
||||
Flags = mouseFlag
|
||||
};
|
||||
|
||||
var view = Application.wantContinuousButtonPressedView;
|
||||
if (view == null)
|
||||
break;
|
||||
if (IsButtonPressed && (mouseFlag & MouseFlags.ReportMousePosition) == 0) {
|
||||
mouseHandler (me);
|
||||
mainLoop.Driver.Wakeup ();
|
||||
@@ -699,7 +734,7 @@ namespace Terminal.Gui {
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.RightmostButtonPressed:
|
||||
mouseFlag = MouseFlags.Button4Released;
|
||||
mouseFlag = MouseFlags.Button3Released;
|
||||
break;
|
||||
}
|
||||
IsButtonPressed = false;
|
||||
@@ -721,7 +756,7 @@ namespace Terminal.Gui {
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.RightmostButtonPressed:
|
||||
mouseFlag = MouseFlags.Button4Clicked;
|
||||
mouseFlag = MouseFlags.Button3Clicked;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -740,7 +775,7 @@ namespace Terminal.Gui {
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.RightmostButtonPressed:
|
||||
mouseFlag = MouseFlags.Button4DoubleClicked;
|
||||
mouseFlag = MouseFlags.Button3DoubleClicked;
|
||||
break;
|
||||
}
|
||||
IsButtonDoubleClicked = true;
|
||||
@@ -755,7 +790,7 @@ namespace Terminal.Gui {
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.RightmostButtonPressed:
|
||||
mouseFlag = MouseFlags.Button4TripleClicked;
|
||||
mouseFlag = MouseFlags.Button3TripleClicked;
|
||||
break;
|
||||
}
|
||||
IsButtonDoubleClicked = false;
|
||||
@@ -817,33 +852,35 @@ namespace Terminal.Gui {
|
||||
var keyInfo = keyInfoEx.consoleKeyInfo;
|
||||
switch (keyInfo.Key) {
|
||||
case ConsoleKey.Escape:
|
||||
return Key.Esc;
|
||||
return MapKeyModifiers (keyInfo, Key.Esc);
|
||||
case ConsoleKey.Tab:
|
||||
return keyInfo.Modifiers == ConsoleModifiers.Shift ? Key.BackTab : Key.Tab;
|
||||
case ConsoleKey.Home:
|
||||
return Key.Home;
|
||||
return MapKeyModifiers (keyInfo, Key.Home);
|
||||
case ConsoleKey.End:
|
||||
return Key.End;
|
||||
return MapKeyModifiers (keyInfo, Key.End);
|
||||
case ConsoleKey.LeftArrow:
|
||||
return Key.CursorLeft;
|
||||
return MapKeyModifiers (keyInfo, Key.CursorLeft);
|
||||
case ConsoleKey.RightArrow:
|
||||
return Key.CursorRight;
|
||||
return MapKeyModifiers (keyInfo, Key.CursorRight);
|
||||
case ConsoleKey.UpArrow:
|
||||
return Key.CursorUp;
|
||||
return MapKeyModifiers (keyInfo, Key.CursorUp);
|
||||
case ConsoleKey.DownArrow:
|
||||
return Key.CursorDown;
|
||||
return MapKeyModifiers (keyInfo, Key.CursorDown);
|
||||
case ConsoleKey.PageUp:
|
||||
return Key.PageUp;
|
||||
return MapKeyModifiers (keyInfo, Key.PageUp);
|
||||
case ConsoleKey.PageDown:
|
||||
return Key.PageDown;
|
||||
return MapKeyModifiers (keyInfo, Key.PageDown);
|
||||
case ConsoleKey.Enter:
|
||||
return Key.Enter;
|
||||
return MapKeyModifiers (keyInfo, Key.Enter);
|
||||
case ConsoleKey.Spacebar:
|
||||
return Key.Space;
|
||||
return MapKeyModifiers (keyInfo, Key.Space);
|
||||
case ConsoleKey.Backspace:
|
||||
return Key.Backspace;
|
||||
return MapKeyModifiers (keyInfo, Key.Backspace);
|
||||
case ConsoleKey.Delete:
|
||||
return Key.DeleteChar;
|
||||
return MapKeyModifiers (keyInfo, Key.DeleteChar);
|
||||
case ConsoleKey.Insert:
|
||||
return MapKeyModifiers (keyInfo, Key.InsertChar);
|
||||
|
||||
case ConsoleKey.NumPad0:
|
||||
return keyInfoEx.NumLock ? (Key)(uint)'0' : Key.InsertChar;
|
||||
@@ -883,7 +920,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
|
||||
var key = keyInfo.Key;
|
||||
var alphaBase = ((keyInfo.Modifiers == ConsoleModifiers.Shift) ^ (keyInfoEx.CapsLock)) ? 'A' : 'a';
|
||||
//var alphaBase = ((keyInfo.Modifiers == ConsoleModifiers.Shift) ^ (keyInfoEx.CapsLock)) ? 'A' : 'a';
|
||||
|
||||
if (key >= ConsoleKey.A && key <= ConsoleKey.Z) {
|
||||
var delta = key - ConsoleKey.A;
|
||||
@@ -897,7 +934,8 @@ namespace Terminal.Gui {
|
||||
else
|
||||
return (Key)((uint)keyInfo.KeyChar);
|
||||
}
|
||||
return (Key)((uint)alphaBase + delta);
|
||||
//return (Key)((uint)alphaBase + delta);
|
||||
return (Key)((uint)keyInfo.KeyChar);
|
||||
}
|
||||
if (key >= ConsoleKey.D0 && key <= ConsoleKey.D9) {
|
||||
var delta = key - ConsoleKey.D0;
|
||||
@@ -915,6 +953,19 @@ namespace Terminal.Gui {
|
||||
return (Key)(0xffffffff);
|
||||
}
|
||||
|
||||
private static Key MapKeyModifiers (ConsoleKeyInfo keyInfo, Key key)
|
||||
{
|
||||
Key keyMod = new Key ();
|
||||
if (keyInfo.Modifiers.HasFlag (ConsoleModifiers.Shift))
|
||||
keyMod = Key.ShiftMask;
|
||||
if (keyInfo.Modifiers.HasFlag (ConsoleModifiers.Control))
|
||||
keyMod |= Key.CtrlMask;
|
||||
if (keyInfo.Modifiers.HasFlag (ConsoleModifiers.Alt))
|
||||
keyMod |= Key.AltMask;
|
||||
|
||||
return keyMod != Key.ControlSpace ? keyMod | key : key;
|
||||
}
|
||||
|
||||
public override void Init (Action terminalResized)
|
||||
{
|
||||
TerminalResized = terminalResized;
|
||||
@@ -1006,11 +1057,11 @@ namespace Terminal.Gui {
|
||||
AddStr (" ");
|
||||
}
|
||||
}
|
||||
if (ccol == Cols) {
|
||||
ccol = 0;
|
||||
if (crow + 1 < Rows)
|
||||
crow++;
|
||||
}
|
||||
//if (ccol == Cols) {
|
||||
// ccol = 0;
|
||||
// if (crow + 1 < Rows)
|
||||
// crow++;
|
||||
//}
|
||||
if (sync)
|
||||
UpdateScreen ();
|
||||
}
|
||||
|
||||
@@ -24,9 +24,10 @@ namespace Terminal.Gui {
|
||||
/// Unicode runes are also stored here, the letter 'A" for example is encoded as a value 65 (not surfaced in the enum).
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Flags]
|
||||
public enum Key : uint {
|
||||
/// <summary>
|
||||
/// Mask that indictes that this is a character value, values outside this range
|
||||
/// Mask that indicates that this is a character value, values outside this range
|
||||
/// indicate special characters like Alt-key combinations or special keys on the
|
||||
/// keyboard like function keys, arrows keys and so on.
|
||||
/// </summary>
|
||||
@@ -42,7 +43,7 @@ namespace Terminal.Gui {
|
||||
/// The key code for the user pressing Control-spacebar
|
||||
/// </summary>
|
||||
ControlSpace = 0,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The key code for the user pressing Control-A
|
||||
/// </summary>
|
||||
@@ -80,10 +81,6 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
ControlI,
|
||||
/// <summary>
|
||||
/// The key code for the user pressing the tab key (same as pressing Control-I).
|
||||
/// </summary>
|
||||
Tab = ControlI,
|
||||
/// <summary>
|
||||
/// The key code for the user pressing Control-J
|
||||
/// </summary>
|
||||
ControlJ,
|
||||
@@ -151,7 +148,7 @@ namespace Terminal.Gui {
|
||||
/// The key code for the user pressing Control-Z
|
||||
/// </summary>
|
||||
ControlZ,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The key code for the user pressing the escape key
|
||||
/// </summary>
|
||||
@@ -172,6 +169,11 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
Delete = 127,
|
||||
|
||||
/// <summary>
|
||||
/// When this value is set, the Key encodes the sequence Shift-KeyValue.
|
||||
/// </summary>
|
||||
ShiftMask = 0x10000000,
|
||||
|
||||
/// <summary>
|
||||
/// When this value is set, the Key encodes the sequence Alt-KeyValue.
|
||||
/// And the actual value must be extracted by removing the AltMask.
|
||||
@@ -270,6 +272,10 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
F10,
|
||||
/// <summary>
|
||||
/// The key code for the user pressing the tab key (forwards tab key).
|
||||
/// </summary>
|
||||
Tab,
|
||||
/// <summary>
|
||||
/// Shift-tab key (backwards tab key).
|
||||
/// </summary>
|
||||
BackTab,
|
||||
@@ -290,12 +296,18 @@ namespace Terminal.Gui {
|
||||
public Key Key;
|
||||
|
||||
/// <summary>
|
||||
/// The key value cast to an integer, you will typicall use this for
|
||||
/// The key value cast to an integer, you will typical use this for
|
||||
/// extracting the Unicode rune value out of a key, when none of the
|
||||
/// symbolic options are in use.
|
||||
/// </summary>
|
||||
public int KeyValue => (int)Key;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the Shift key was pressed.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if is shift; otherwise, <c>false</c>.</value>
|
||||
public bool IsShift => (Key & Key.ShiftMask) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the Alt key was pressed (real or synthesized)
|
||||
/// </summary>
|
||||
@@ -306,7 +318,8 @@ namespace Terminal.Gui {
|
||||
/// Determines whether the value is a control key (and NOT just the ctrl key)
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if is ctrl; otherwise, <c>false</c>.</value>
|
||||
public bool IsCtrl => ((uint)Key >= 1) && ((uint)Key <= 26);
|
||||
//public bool IsCtrl => ((uint)Key >= 1) && ((uint)Key <= 26);
|
||||
public bool IsCtrl => (Key & Key.CtrlMask) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new KeyEvent from the provided Key value - can be a rune cast into a Key value
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is autogenerated by the attrib.c program, do not edit
|
||||
* This file is autogenerated by the attrib.c program, do not edit
|
||||
*/
|
||||
|
||||
using System;
|
||||
@@ -101,6 +101,38 @@ namespace Unix.Terminal {
|
||||
public const int KeyF9 = unchecked((int)0x111);
|
||||
public const int KeyF10 = unchecked((int)0x112);
|
||||
public const int KeyResize = unchecked((int)0x19a);
|
||||
public const int ShiftKeyUp = unchecked((int)0x151);
|
||||
public const int ShiftKeyDown = unchecked((int)0x150);
|
||||
public const int ShiftKeyLeft = unchecked((int)0x189);
|
||||
public const int ShiftKeyRight = unchecked((int)0x192);
|
||||
public const int ShiftKeyNPage = unchecked((int)0x18c);
|
||||
public const int ShiftKeyPPage = unchecked((int)0x18e);
|
||||
public const int ShiftKeyHome = unchecked((int)0x187);
|
||||
public const int ShiftKeyEnd = unchecked((int)0x182);
|
||||
public const int AltKeyUp = unchecked((int)0x234);
|
||||
public const int AltKeyDown = unchecked((int)0x20b);
|
||||
public const int AltKeyLeft = unchecked((int)0x21f);
|
||||
public const int AltKeyRight = unchecked((int)0x22e);
|
||||
public const int AltKeyNPage = unchecked((int)0x224);
|
||||
public const int AltKeyPPage = unchecked((int)0x229);
|
||||
public const int AltKeyHome = unchecked((int)0x215);
|
||||
public const int AltKeyEnd = unchecked((int)0x210);
|
||||
public const int CtrlKeyUp = unchecked((int)0x236);
|
||||
public const int CtrlKeyDown = unchecked((int)0x20d);
|
||||
public const int CtrlKeyLeft = unchecked((int)0x221);
|
||||
public const int CtrlKeyRight = unchecked((int)0x230);
|
||||
public const int CtrlKeyNPage = unchecked((int)0x226);
|
||||
public const int CtrlKeyPPage = unchecked((int)0x22b);
|
||||
public const int CtrlKeyHome = unchecked((int)0x217);
|
||||
public const int CtrlKeyEnd = unchecked((int)0x212);
|
||||
public const int ShiftCtrlKeyUp = unchecked((int)0x237);
|
||||
public const int ShiftCtrlKeyDown = unchecked((int)0x20e);
|
||||
public const int ShiftCtrlKeyLeft = unchecked((int)0x222);
|
||||
public const int ShiftCtrlKeyRight = unchecked((int)0x231);
|
||||
public const int ShiftCtrlKeyNPage = unchecked((int)0x227);
|
||||
public const int ShiftCtrlKeyPPage = unchecked((int)0x22c);
|
||||
public const int ShiftCtrlKeyHome = unchecked((int)0x218);
|
||||
public const int ShiftCtrlKeyEnd = unchecked((int)0x213);
|
||||
|
||||
public const int LC_ALL = 6;
|
||||
static public int ColorPair(int n){
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace Terminal.Gui {
|
||||
public FrameView (Rect frame, ustring title) : base (frame)
|
||||
{
|
||||
var cFrame = new Rect (1, 1 , frame.Width - 2, frame.Height - 2);
|
||||
this.title = title;
|
||||
contentView = new ContentView (cFrame);
|
||||
Initialize ();
|
||||
}
|
||||
@@ -69,6 +70,7 @@ namespace Terminal.Gui {
|
||||
/// <param name="title">Title.</param>
|
||||
public FrameView (ustring title)
|
||||
{
|
||||
this.title = title;
|
||||
contentView = new ContentView () {
|
||||
X = 1,
|
||||
Y = 1,
|
||||
@@ -81,7 +83,6 @@ namespace Terminal.Gui {
|
||||
void Initialize ()
|
||||
{
|
||||
base.Add (contentView);
|
||||
Title = title;
|
||||
}
|
||||
|
||||
void DrawFrame ()
|
||||
|
||||
@@ -343,6 +343,29 @@ namespace Terminal.Gui {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public override bool KeyDown (KeyEvent keyEvent)
|
||||
{
|
||||
if (keyEvent.IsAlt) {
|
||||
host.CloseAllMenus ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ProcessHotKey (KeyEvent keyEvent)
|
||||
{
|
||||
// To ncurses simulate a AltMask key pressing Alt+Space because
|
||||
// it can<61>t detect an alone special key down was pressed.
|
||||
if (keyEvent.IsAlt && keyEvent.Key == Key.AltMask) {
|
||||
KeyDown (keyEvent);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ProcessKey (KeyEvent kb)
|
||||
{
|
||||
bool disabled;
|
||||
@@ -445,7 +468,8 @@ namespace Terminal.Gui {
|
||||
Run (barItems.Children [meY].Action);
|
||||
return true;
|
||||
} else if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked ||
|
||||
me.Flags == MouseFlags.ReportMousePosition) {
|
||||
me.Flags == MouseFlags.ReportMousePosition ||
|
||||
me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition)) {
|
||||
disabled = false;
|
||||
if (me.Y < 1)
|
||||
return true;
|
||||
@@ -534,9 +558,12 @@ namespace Terminal.Gui {
|
||||
isMenuClosed = true;
|
||||
}
|
||||
|
||||
bool openedByAltKey;
|
||||
public override bool KeyDown (KeyEvent keyEvent)
|
||||
{
|
||||
if (keyEvent.IsAlt) {
|
||||
openedByAltKey = true;
|
||||
SetNeedsDisplay ();
|
||||
openedByHotKey = false;
|
||||
}
|
||||
return false;
|
||||
@@ -544,29 +571,45 @@ namespace Terminal.Gui {
|
||||
|
||||
/// <summary>
|
||||
/// Track Alt key-up events. On Windows, when a user releases Alt (without another key), the menu gets focus but doesn't open.
|
||||
/// We mimic that behavior here.
|
||||
/// We mimic that behavior here.
|
||||
/// </summary>
|
||||
/// <param name="keyEvent"></param>
|
||||
/// <returns></returns>
|
||||
public override bool KeyUp (KeyEvent keyEvent)
|
||||
{
|
||||
if (keyEvent.IsAlt) {
|
||||
// User pressed Alt - this may be a precursor to a menu accellerator (e.g. Alt-F)
|
||||
if (openMenu == null) {
|
||||
// There's no open menu, the first menu item should be highlight.
|
||||
// The right way to do this is to SetFocus(MenuBar), but for some reason
|
||||
// User pressed Alt - this may be a precursor to a menu accelerator (e.g. Alt-F)
|
||||
if (!keyEvent.IsCtrl && openedByAltKey && isMenuClosed && openMenu == null && ((uint)keyEvent.Key & (uint)Key.CharMask) == 0) {
|
||||
// There's no open menu, the first menu item should be highlight.
|
||||
// The right way to do this is to SetFocus(MenuBar), but for some reason
|
||||
// that faults.
|
||||
|
||||
Activate (0);
|
||||
//Activate (0);
|
||||
//StartMenu ();
|
||||
isMenuClosed = false;
|
||||
selected = 0;
|
||||
CanFocus = true;
|
||||
lastFocused = SuperView.MostFocused;
|
||||
SuperView.SetFocus (this);
|
||||
SetNeedsDisplay ();
|
||||
} else {
|
||||
// There's an open menu. If this Alt key-up is a pre-cursor to an acellerator
|
||||
Application.GrabMouse (this);
|
||||
} else if (!openedByHotKey) {
|
||||
// There's an open menu. If this Alt key-up is a pre-cursor to an accelerator
|
||||
// we don't want to close the menu because it'll flash.
|
||||
// How to deal with that?
|
||||
if (!openedByHotKey) {
|
||||
|
||||
if (openMenu != null)
|
||||
CloseAllMenus ();
|
||||
}
|
||||
openedByAltKey = false;
|
||||
isMenuClosed = true;
|
||||
selected = -1;
|
||||
CanFocus = false;
|
||||
if (lastFocused != null)
|
||||
SuperView?.SetFocus (lastFocused);
|
||||
SetNeedsDisplay ();
|
||||
Application.UngrabMouse ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -589,9 +632,12 @@ namespace Terminal.Gui {
|
||||
if (i == selected) {
|
||||
hotColor = i == selected ? ColorScheme.HotFocus : ColorScheme.HotNormal;
|
||||
normalColor = i == selected ? ColorScheme.Focus : ColorScheme.Normal;
|
||||
} else {
|
||||
} else if (openedByAltKey) {
|
||||
hotColor = ColorScheme.HotNormal;
|
||||
normalColor = ColorScheme.Normal;
|
||||
} else {
|
||||
hotColor = ColorScheme.Normal;
|
||||
normalColor = ColorScheme.Normal;
|
||||
}
|
||||
DrawHotString ($" {menu.Title} ", hotColor, normalColor);
|
||||
pos += 1 + menu.TitleLength + 2;
|
||||
@@ -815,6 +861,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
isMenuClosed = true;
|
||||
openedByHotKey = false;
|
||||
openedByAltKey = false;
|
||||
}
|
||||
|
||||
View FindDeepestMenu (View view, ref int count)
|
||||
@@ -890,7 +937,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
bool openedByHotKey = false;
|
||||
bool openedByHotKey;
|
||||
internal bool FindAndOpenMenuByHotkey (KeyEvent kb)
|
||||
{
|
||||
int pos = 0;
|
||||
@@ -901,15 +948,7 @@ namespace Terminal.Gui {
|
||||
int p = mi.Title.IndexOf ('_');
|
||||
if (p != -1 && p + 1 < mi.Title.Length) {
|
||||
if (Char.ToUpperInvariant ((char)mi.Title [p + 1]) == c) {
|
||||
if (mi.IsTopLevel) {
|
||||
var menu = new Menu (this, i, 0, mi);
|
||||
menu.Run (mi.Action);
|
||||
} else {
|
||||
openedByHotKey = true;
|
||||
Application.GrabMouse (this);
|
||||
selected = i;
|
||||
OpenMenu (i);
|
||||
}
|
||||
ProcessMenu (i, mi);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -917,6 +956,19 @@ namespace Terminal.Gui {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ProcessMenu (int i, MenuBarItem mi)
|
||||
{
|
||||
if (mi.IsTopLevel) {
|
||||
var menu = new Menu (this, i, 0, mi);
|
||||
menu.Run (mi.Action);
|
||||
} else {
|
||||
openedByHotKey = true;
|
||||
Application.GrabMouse (this);
|
||||
selected = i;
|
||||
OpenMenu (i);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ProcessHotKey (KeyEvent kb)
|
||||
{
|
||||
if (kb.Key == Key.F9) {
|
||||
@@ -927,10 +979,16 @@ namespace Terminal.Gui {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (kb.IsAlt) {
|
||||
// To ncurses simulate a AltMask key pressing Alt+Space because
|
||||
// it can<61>t detect an alone special key down was pressed.
|
||||
if (kb.IsAlt && kb.Key == Key.AltMask && openMenu == null) {
|
||||
KeyDown (kb);
|
||||
KeyUp (kb);
|
||||
return true;
|
||||
} else if (kb.IsAlt) {
|
||||
if (FindAndOpenMenuByHotkey (kb)) return true;
|
||||
}
|
||||
var kc = kb.KeyValue;
|
||||
//var kc = kb.KeyValue;
|
||||
|
||||
return base.ProcessHotKey (kb);
|
||||
}
|
||||
@@ -951,6 +1009,15 @@ namespace Terminal.Gui {
|
||||
case Key.ControlC:
|
||||
//TODO: Running = false;
|
||||
CloseMenu ();
|
||||
if (openedByAltKey) {
|
||||
openedByAltKey = false;
|
||||
LastFocused.SuperView?.SetFocus (LastFocused);
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.CursorDown:
|
||||
case Key.Enter:
|
||||
ProcessMenu (selected, Menus [selected]);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -958,10 +1025,12 @@ namespace Terminal.Gui {
|
||||
if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') || (key >= '0' && key <= '9')) {
|
||||
char c = Char.ToUpper ((char)key);
|
||||
|
||||
if (Menus [selected].IsTopLevel)
|
||||
if (selected == -1 || Menus [selected].IsTopLevel)
|
||||
return false;
|
||||
|
||||
foreach (var mi in Menus [selected].Children) {
|
||||
if (mi == null)
|
||||
continue;
|
||||
int p = mi.Title.IndexOf ('_');
|
||||
if (p != -1 && p + 1 < mi.Title.Length) {
|
||||
if (mi.Title [p + 1] == c) {
|
||||
@@ -985,14 +1054,15 @@ namespace Terminal.Gui {
|
||||
}
|
||||
handled = false;
|
||||
|
||||
if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked ||
|
||||
(me.Flags == MouseFlags.ReportMousePosition && selected > -1)) {
|
||||
if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1Clicked || me.Flags == MouseFlags.Button1DoubleClicked ||
|
||||
(me.Flags == MouseFlags.ReportMousePosition && selected > -1) ||
|
||||
(me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition) && selected > -1)) {
|
||||
int pos = 1;
|
||||
int cx = me.X;
|
||||
for (int i = 0; i < Menus.Length; i++) {
|
||||
if (cx > pos && me.X < pos + 1 + Menus [i].TitleLength) {
|
||||
if (selected == i && (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) &&
|
||||
!isMenuClosed) {
|
||||
!isMenuClosed) {
|
||||
Application.UngrabMouse ();
|
||||
if (Menus [i].IsTopLevel) {
|
||||
var menu = new Menu (this, i, 0, Menus [i]);
|
||||
@@ -1036,8 +1106,8 @@ namespace Terminal.Gui {
|
||||
Application.GrabMouse (me.View);
|
||||
me.View.MouseEvent (me);
|
||||
}
|
||||
} else if (!(me.View is MenuBar || me.View is Menu) && (me.Flags.HasFlag (MouseFlags.Button1Pressed) ||
|
||||
me.Flags == MouseFlags.Button1DoubleClicked)) {
|
||||
} else if (!(me.View is MenuBar || me.View is Menu) && (me.Flags.HasFlag (MouseFlags.Button1Clicked) ||
|
||||
me.Flags == MouseFlags.Button1DoubleClicked || me.Flags == MouseFlags.Button1Pressed)) {
|
||||
Application.UngrabMouse ();
|
||||
CloseAllMenus ();
|
||||
handled = false;
|
||||
@@ -1046,7 +1116,8 @@ namespace Terminal.Gui {
|
||||
handled = false;
|
||||
return false;
|
||||
}
|
||||
} else if (isMenuClosed && (me.Flags.HasFlag (MouseFlags.Button1Pressed) || me.Flags == MouseFlags.Button1DoubleClicked)) {
|
||||
} else if (isMenuClosed && (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked ||
|
||||
me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition))) {
|
||||
Application.GrabMouse (current);
|
||||
} else {
|
||||
handled = false;
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace Terminal.Gui {
|
||||
vertical = isVertical;
|
||||
this.position = position;
|
||||
this.size = size;
|
||||
WantContinuousButtonPressed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -78,15 +78,16 @@ namespace Terminal.Gui {
|
||||
CanFocus = true;
|
||||
Used = true;
|
||||
WantMousePositionReports = true;
|
||||
OnLeave += TextField_OnLeave;
|
||||
}
|
||||
|
||||
void TextField_OnLeave (object sender, EventArgs e)
|
||||
public override bool OnLeave ()
|
||||
{
|
||||
if (Application.mouseGrabView != null && Application.mouseGrabView == this)
|
||||
Application.UngrabMouse ();
|
||||
if (SelectedLength != 0 && !(Application.mouseGrabView is MenuBar))
|
||||
ClearAllSelection ();
|
||||
|
||||
return base.OnLeave ();
|
||||
}
|
||||
|
||||
public override Rect Frame {
|
||||
@@ -94,10 +95,15 @@ namespace Terminal.Gui {
|
||||
set {
|
||||
base.Frame = value;
|
||||
var w = base.Frame.Width;
|
||||
first = point > w ? point - w : 0;
|
||||
//first = point > w ? point - w : 0;
|
||||
Adjust ();
|
||||
}
|
||||
}
|
||||
|
||||
List<ustring> historyText;
|
||||
int idxhistoryText;
|
||||
bool isFromHistory;
|
||||
|
||||
/// <summary>
|
||||
/// Sets or gets the text in the entry.
|
||||
/// </summary>
|
||||
@@ -109,15 +115,24 @@ namespace Terminal.Gui {
|
||||
}
|
||||
|
||||
set {
|
||||
ustring oldText = ustring.Make (text);
|
||||
var oldText = ustring.Make (text);
|
||||
text = TextModel.ToRunes (value);
|
||||
if (!Secret && !isFromHistory) {
|
||||
if (historyText == null)
|
||||
historyText = new List<ustring> () { oldText };
|
||||
if (idxhistoryText > 0 && idxhistoryText + 1 < historyText.Count)
|
||||
historyText.RemoveRange (idxhistoryText + 1, historyText.Count - idxhistoryText - 1);
|
||||
historyText.Add (ustring.Make (text));
|
||||
idxhistoryText++;
|
||||
}
|
||||
Changed?.Invoke (this, oldText);
|
||||
|
||||
if (point > text.Count)
|
||||
point = Math.Max (text.Count-1, 0);
|
||||
point = Math.Max (DisplaySize (text, 0) - 1, 0);
|
||||
|
||||
// FIXME: this needs to be updated to use Rune.ColumnWidth
|
||||
first = point > Frame.Width ? point - Frame.Width : 0;
|
||||
//first = point > Frame.Width ? point - Frame.Width : 0;
|
||||
Adjust ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
}
|
||||
@@ -171,14 +186,14 @@ namespace Terminal.Gui {
|
||||
var tcount = text.Count;
|
||||
for (int idx = 0; idx < tcount; idx++){
|
||||
var rune = text [idx];
|
||||
if (idx < first)
|
||||
if (idx < p)
|
||||
continue;
|
||||
var cols = Rune.ColumnWidth (rune);
|
||||
if (col == point && HasFocus && !Used && SelectedLength == 0)
|
||||
Driver.SetAttribute (Colors.Menu.HotFocus);
|
||||
else
|
||||
Driver.SetAttribute (idx >= start && length > 0 && idx < start + length ? color.Focus : ColorScheme.Focus);
|
||||
if (col + cols < width)
|
||||
if (col + cols <= width)
|
||||
Driver.AddRune ((Rune)(Secret ? '*' : rune));
|
||||
col += cols;
|
||||
}
|
||||
@@ -204,10 +219,13 @@ namespace Terminal.Gui {
|
||||
|
||||
void Adjust ()
|
||||
{
|
||||
int offB = 0;
|
||||
if (SuperView != null && SuperView.Frame.Right - Frame.Right < 0)
|
||||
offB = SuperView.Frame.Right - Frame.Right - 1;
|
||||
if (point < first)
|
||||
first = point;
|
||||
else if (first + point >= Frame.Width) {
|
||||
first = point - (Frame.Width - 1);
|
||||
else if (first + point >= Frame.Width + offB) {
|
||||
first = point - (Frame.Width - 1 + offB);
|
||||
}
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
@@ -269,6 +287,22 @@ namespace Terminal.Gui {
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.Home | Key.ShiftMask:
|
||||
if (point > 0) {
|
||||
int x = point;
|
||||
point = 0;
|
||||
PrepareSelection (x, point - x);
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.End | Key.ShiftMask:
|
||||
if (point < text.Count) {
|
||||
int x = point;
|
||||
point = text.Count;
|
||||
PrepareSelection (x, point - x);
|
||||
}
|
||||
break;
|
||||
|
||||
// Home, C-A
|
||||
case Key.Home:
|
||||
case Key.ControlA:
|
||||
@@ -277,6 +311,42 @@ namespace Terminal.Gui {
|
||||
Adjust ();
|
||||
break;
|
||||
|
||||
case Key.CursorLeft | Key.ShiftMask:
|
||||
case Key.CursorUp | Key.ShiftMask:
|
||||
if (point > 0) {
|
||||
PrepareSelection (point--, -1);
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.CursorRight | Key.ShiftMask:
|
||||
case Key.CursorDown | Key.ShiftMask:
|
||||
if (point < text.Count) {
|
||||
PrepareSelection (point++, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.CursorLeft | Key.ShiftMask | Key.CtrlMask:
|
||||
case Key.CursorUp | Key.ShiftMask | Key.CtrlMask:
|
||||
if (point > 0) {
|
||||
int x = start > -1 ? start : point;
|
||||
int sbw = WordBackward (point);
|
||||
if (sbw != -1)
|
||||
point = sbw;
|
||||
PrepareSelection (x, sbw - x);
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.CursorRight | Key.ShiftMask | Key.CtrlMask:
|
||||
case Key.CursorDown | Key.ShiftMask | Key.CtrlMask:
|
||||
if (point < text.Count) {
|
||||
int x = start > -1 ? start : point;
|
||||
int sfw = WordForward (point);
|
||||
if (sfw != -1)
|
||||
point = sfw;
|
||||
PrepareSelection (x, sfw - x);
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.CursorLeft:
|
||||
case Key.ControlB:
|
||||
ClearAllSelection ();
|
||||
@@ -311,23 +381,53 @@ namespace Terminal.Gui {
|
||||
Adjust ();
|
||||
break;
|
||||
|
||||
case Key.ControlY: // Control-y, yank
|
||||
if (Clipboard.Contents == null)
|
||||
return true;
|
||||
var clip = TextModel.ToRunes (Clipboard.Contents);
|
||||
if (clip == null)
|
||||
return true;
|
||||
|
||||
if (point == text.Count) {
|
||||
// Undo
|
||||
case Key.ControlZ:
|
||||
if (historyText != null && historyText.Count > 0) {
|
||||
isFromHistory = true;
|
||||
if (idxhistoryText > 0)
|
||||
idxhistoryText--;
|
||||
if (idxhistoryText > -1)
|
||||
Text = historyText [idxhistoryText];
|
||||
point = text.Count;
|
||||
SetText(text.Concat(clip).ToList());
|
||||
} else {
|
||||
point += clip.Count;
|
||||
SetText(text.GetRange(0, oldCursorPos).Concat(clip).Concat(text.GetRange(oldCursorPos, text.Count - oldCursorPos)));
|
||||
isFromHistory = false;
|
||||
}
|
||||
Adjust ();
|
||||
break;
|
||||
|
||||
//Redo
|
||||
case Key.ControlY: // Control-y, yank
|
||||
if (historyText != null && historyText.Count > 0) {
|
||||
isFromHistory = true;
|
||||
if (idxhistoryText < historyText.Count - 1) {
|
||||
idxhistoryText++;
|
||||
if (idxhistoryText < historyText.Count) {
|
||||
Text = historyText [idxhistoryText];
|
||||
} else if (idxhistoryText == historyText.Count - 1) {
|
||||
Text = historyText [historyText.Count - 1];
|
||||
}
|
||||
point = text.Count;
|
||||
}
|
||||
isFromHistory = false;
|
||||
}
|
||||
|
||||
//if (Clipboard.Contents == null)
|
||||
// return true;
|
||||
//var clip = TextModel.ToRunes (Clipboard.Contents);
|
||||
//if (clip == null)
|
||||
// return true;
|
||||
|
||||
//if (point == text.Count) {
|
||||
// point = text.Count;
|
||||
// SetText(text.Concat(clip).ToList());
|
||||
//} else {
|
||||
// point += clip.Count;
|
||||
// SetText(text.GetRange(0, oldCursorPos).Concat(clip).Concat(text.GetRange(oldCursorPos, text.Count - oldCursorPos)));
|
||||
//}
|
||||
//Adjust ();
|
||||
|
||||
break;
|
||||
|
||||
case Key.CursorLeft | Key.CtrlMask:
|
||||
case (Key)((int)'b' + Key.AltMask):
|
||||
ClearAllSelection ();
|
||||
int bw = WordBackward (point);
|
||||
@@ -336,6 +436,7 @@ namespace Terminal.Gui {
|
||||
Adjust ();
|
||||
break;
|
||||
|
||||
case Key.CursorRight | Key.CtrlMask:
|
||||
case (Key)((int)'f' + Key.AltMask):
|
||||
ClearAllSelection ();
|
||||
int fw = WordForward (point);
|
||||
@@ -344,20 +445,20 @@ namespace Terminal.Gui {
|
||||
Adjust ();
|
||||
break;
|
||||
|
||||
case Key.AltMask | Key.ControlI:
|
||||
case Key.InsertChar:
|
||||
Used = !Used;
|
||||
SetNeedsDisplay ();
|
||||
break;
|
||||
|
||||
case Key.AltMask | Key.ControlC:
|
||||
case Key.ControlC:
|
||||
Copy ();
|
||||
break;
|
||||
|
||||
case Key.AltMask | Key.ControlX:
|
||||
case Key.ControlX:
|
||||
Cut ();
|
||||
break;
|
||||
|
||||
case Key.AltMask | Key.ControlV:
|
||||
case Key.ControlV:
|
||||
Paste ();
|
||||
break;
|
||||
|
||||
@@ -378,7 +479,7 @@ namespace Terminal.Gui {
|
||||
var kbstr = TextModel.ToRunes (ustring.Make ((uint)kb.Key));
|
||||
if (used) {
|
||||
point++;
|
||||
if (point == text.Count) {
|
||||
if (point == text.Count + 1) {
|
||||
SetText (text.Concat (kbstr).ToList ());
|
||||
} else {
|
||||
SetText (text.GetRange (0, oldCursorPos).Concat (kbstr).Concat (text.GetRange (oldCursorPos, Math.Min (text.Count - oldCursorPos, text.Count))));
|
||||
@@ -476,7 +577,8 @@ namespace Terminal.Gui {
|
||||
public override bool MouseEvent (MouseEvent ev)
|
||||
{
|
||||
if (!ev.Flags.HasFlag (MouseFlags.Button1Pressed) && !ev.Flags.HasFlag (MouseFlags.ReportMousePosition) &&
|
||||
!ev.Flags.HasFlag (MouseFlags.Button1Released))
|
||||
!ev.Flags.HasFlag (MouseFlags.Button1Released) && !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked) &&
|
||||
!ev.Flags.HasFlag (MouseFlags.Button1TripleClicked))
|
||||
return false;
|
||||
|
||||
if (ev.Flags == MouseFlags.Button1Pressed) {
|
||||
@@ -493,13 +595,25 @@ namespace Terminal.Gui {
|
||||
if (Application.mouseGrabView == null) {
|
||||
Application.GrabMouse (this);
|
||||
}
|
||||
} else if (ev.Flags == MouseFlags.Button1Pressed) {
|
||||
int x = PositionCursor (ev);
|
||||
if (SelectedLength != 0)
|
||||
ClearAllSelection ();
|
||||
} else if (ev.Flags == MouseFlags.Button1Released) {
|
||||
isButtonReleased = true;
|
||||
Application.UngrabMouse ();
|
||||
} else if (ev.Flags == MouseFlags.Button1DoubleClicked) {
|
||||
int x = PositionCursor (ev);
|
||||
int sbw = x;
|
||||
if (x > 0 && (char)Text [x - 1] != ' ')
|
||||
sbw = WordBackward (x);
|
||||
if (sbw != -1) {
|
||||
x = sbw;
|
||||
PositionCursor (x);
|
||||
}
|
||||
int sfw = WordForward (x);
|
||||
ClearAllSelection ();
|
||||
PrepareSelection (sbw, sfw - sbw);
|
||||
} else if (ev.Flags == MouseFlags.Button1TripleClicked) {
|
||||
PositionCursor (0);
|
||||
ClearAllSelection ();
|
||||
PrepareSelection (0, text.Count);
|
||||
}
|
||||
|
||||
SetNeedsDisplay ();
|
||||
@@ -510,12 +624,16 @@ namespace Terminal.Gui {
|
||||
{
|
||||
// We could also set the cursor position.
|
||||
int x;
|
||||
if (Application.mouseGrabView == null) {
|
||||
if (text.Count == 0)
|
||||
x = ev.X - ev.OfX;
|
||||
else
|
||||
x = ev.X;
|
||||
} else {
|
||||
x = ev.X;// - (text.Count > Frame.Width ? text.Count - Frame.Width : 0);
|
||||
}
|
||||
|
||||
return PositionCursor (x);
|
||||
}
|
||||
|
||||
private int PositionCursor (int x)
|
||||
{
|
||||
point = first + x;
|
||||
if (point > text.Count)
|
||||
point = text.Count;
|
||||
@@ -524,12 +642,12 @@ namespace Terminal.Gui {
|
||||
return x;
|
||||
}
|
||||
|
||||
void PrepareSelection (int x)
|
||||
void PrepareSelection (int x, int direction = 0)
|
||||
{
|
||||
x = x + first < 0 ? 0 : x + first;
|
||||
x = x + first < 0 ? 0 : x;
|
||||
SelectedStart = SelectedStart == -1 && text.Count > 0 && x >= 0 && x <= text.Count ? x : SelectedStart;
|
||||
if (SelectedStart > -1) {
|
||||
SelectedLength = x <= text.Count ? x - SelectedStart : text.Count - SelectedStart;
|
||||
SelectedLength = x + direction <= text.Count ? x + direction - SelectedStart : text.Count - SelectedStart;
|
||||
SetSelectedStartSelectedLength ();
|
||||
SelectedText = length > 0 ? ustring.Make (text).ToString ().Substring (
|
||||
start < 0 ? 0 : start, length > text.Count ? text.Count : length) : "";
|
||||
@@ -542,7 +660,7 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
public void ClearAllSelection ()
|
||||
{
|
||||
if (SelectedLength == 0)
|
||||
if (SelectedStart == -1 && SelectedLength == 0)
|
||||
return;
|
||||
SelectedStart = -1;
|
||||
SelectedLength = 0;
|
||||
@@ -601,10 +719,13 @@ namespace Terminal.Gui {
|
||||
{
|
||||
string actualText = Text.ToString ();
|
||||
int start = SelectedStart == -1 ? CursorPosition : SelectedStart;
|
||||
ustring cbTxt = Clipboard.Contents?.ToString () ?? "";
|
||||
Text = actualText.Substring (0, start) +
|
||||
Clipboard.Contents?.ToString () +
|
||||
cbTxt +
|
||||
actualText.Substring (start + SelectedLength, actualText.Length - start - SelectedLength);
|
||||
point = start + cbTxt.Length;
|
||||
SelectedLength = 0;
|
||||
ClearAllSelection ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user