diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs
index 0b9582efc..7168eba1e 100644
--- a/Terminal.Gui/Core.cs
+++ b/Terminal.Gui/Core.cs
@@ -1545,12 +1545,12 @@ namespace Terminal.Gui {
///
/// Check id current toplevel has menu bar
///
- public bool HasMenuBar { get; set; }
+ public MenuBar MenuBar { get; set; }
///
/// Check id current toplevel has status bar
///
- public bool HasStatusBar { get; set; }
+ public StatusBar StatusBar { get; set; }
///
public override bool ProcessKey (KeyEvent keyEvent)
@@ -1609,9 +1609,9 @@ namespace Terminal.Gui {
{
if (this == Application.Top) {
if (view is MenuBar)
- HasMenuBar = true;
+ MenuBar = view as MenuBar;
if (view is StatusBar)
- HasStatusBar = true;
+ StatusBar = view as StatusBar;
}
base.Add (view);
}
@@ -1621,9 +1621,9 @@ namespace Terminal.Gui {
{
if (this == Application.Top) {
if (view is MenuBar)
- HasMenuBar = true;
+ MenuBar = null;
if (view is StatusBar)
- HasStatusBar = true;
+ StatusBar = null;
}
base.Remove (view);
}
@@ -1632,8 +1632,8 @@ namespace Terminal.Gui {
public override void RemoveAll ()
{
if (this == Application.Top) {
- HasMenuBar = false;
- HasStatusBar = false;
+ MenuBar = null;
+ StatusBar = null;
}
base.RemoveAll ();
}
@@ -1643,16 +1643,16 @@ namespace Terminal.Gui {
nx = Math.Max (x, 0);
nx = nx + top.Frame.Width > Driver.Cols ? Math.Max (Driver.Cols - top.Frame.Width, 0) : nx;
bool m, s;
- if (SuperView == null || SuperView.GetType() != typeof(Toplevel))
- m = Application.Top.HasMenuBar;
+ if (SuperView == null)
+ m = Application.Top.MenuBar != null;
else
- m = ((Toplevel)SuperView).HasMenuBar;
+ m = ((Toplevel)SuperView).MenuBar != null;
int l = m ? 1 : 0;
ny = Math.Max (y, l);
if (SuperView == null)
- s = Application.Top.HasStatusBar;
+ s = Application.Top.StatusBar != null;
else
- s = ((Toplevel)SuperView).HasStatusBar;
+ s = ((Toplevel)SuperView).StatusBar != null;
l = s ? Driver.Rows - 1 : Driver.Rows;
ny = Math.Min (ny, l);
ny = ny + top.Frame.Height > l ? Math.Max (l - top.Frame.Height, m ? 1 : 0) : ny;
@@ -1674,9 +1674,15 @@ namespace Terminal.Gui {
top.X = nx;
top.Y = ny;
}
- if (HasStatusBar && ny + top.Frame.Height > Driver.Rows - 1) {
- if (top.Height is Dim.DimFill)
- top.Height = Dim.Fill () - 1;
+ if (StatusBar != null) {
+ if (ny + top.Frame.Height > Driver.Rows - 1) {
+ if (top.Height is Dim.DimFill)
+ top.Height = Dim.Fill () - 1;
+ }
+ if (StatusBar.Frame.Y != Driver.Rows - 1) {
+ StatusBar.Y = Driver.Rows - 1;
+ SetNeedsDisplay ();
+ }
}
}
}
@@ -1688,7 +1694,7 @@ namespace Terminal.Gui {
{
Application.CurrentView = this;
- if (this == Application.Top) {
+ if (this == Application.Top || this == Application.Current) {
if (!NeedDisplay.IsEmpty) {
Driver.SetAttribute (Colors.TopLevel.Normal);
Clear (region);
diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs
index 309c408e0..7262fa478 100644
--- a/Terminal.Gui/Views/ListView.cs
+++ b/Terminal.Gui/Views/ListView.cs
@@ -63,6 +63,12 @@ namespace Terminal.Gui {
/// Item index.
/// If set to true value.
void SetMark (int item, bool value);
+
+ ///
+ /// Return the source as IList.
+ ///
+ ///
+ IList ToList ();
}
///
@@ -257,7 +263,7 @@ namespace Terminal.Gui {
/// Redraws the ListView
///
/// Region.
- public override void Redraw(Rect region)
+ public override void Redraw (Rect region)
{
var current = ColorScheme.Focus;
Driver.SetAttribute (current);
@@ -279,12 +285,12 @@ namespace Terminal.Gui {
Move (0, row);
if (source == null || item >= source.Count) {
for (int c = 0; c < f.Width; c++)
- Driver.AddRune(' ');
+ Driver.AddRune (' ');
} else {
if (allowsMarking) {
Driver.AddStr (source.IsMarked (item) ? (AllowsMultipleSelection ? "[x] " : "(o)") : (AllowsMultipleSelection ? "[ ] " : "( )"));
}
- Source.Render(this, Driver, isSelected, item, col, row, f.Width-col);
+ Source.Render (this, Driver, isSelected, item, col, row, f.Width - col);
}
}
}
@@ -292,12 +298,12 @@ namespace Terminal.Gui {
///
/// This event is raised when the cursor selection has changed.
///
- public event Action SelectedChanged;
+ public event EventHandler SelectedChanged;
///
/// This event is raised on Enter key or Double Click to open the selected item.
///
- public event EventHandler OpenSelectedItem;
+ public event EventHandler OpenSelectedItem;
///
/// Handles cursor movement for this view, passes all other events.
@@ -312,27 +318,27 @@ namespace Terminal.Gui {
switch (kb.Key) {
case Key.CursorUp:
case Key.ControlP:
- return MoveUp();
+ return MoveUp ();
case Key.CursorDown:
case Key.ControlN:
- return MoveDown();
+ return MoveDown ();
case Key.ControlV:
case Key.PageDown:
- return MovePageDown();
+ return MovePageDown ();
case Key.PageUp:
- return MovePageUp();
+ return MovePageUp ();
case Key.Space:
- if (MarkUnmarkRow())
+ if (MarkUnmarkRow ())
return true;
else
break;
case Key.Enter:
- OpenSelectedItem?.Invoke (this, new EventArgs ());
+ OnOpenSelectedItem ();
break;
}
@@ -340,7 +346,7 @@ namespace Terminal.Gui {
}
///
- ///
+ /// Prevents marking if it's not allowed mark and if it's not allows multiple selection.
///
///
public virtual bool AllowsAll ()
@@ -359,13 +365,14 @@ namespace Terminal.Gui {
}
///
- ///
+ /// Marks an unmarked row.
///
///
- public virtual bool MarkUnmarkRow(){
+ public virtual bool MarkUnmarkRow ()
+ {
if (AllowsAll ()) {
- Source.SetMark(SelectedItem, !Source.IsMarked(SelectedItem));
- SetNeedsDisplay();
+ Source.SetMark (SelectedItem, !Source.IsMarked (SelectedItem));
+ SetNeedsDisplay ();
return true;
}
@@ -373,84 +380,114 @@ namespace Terminal.Gui {
}
///
- ///
+ /// Moves to the next page.
///
///
- public virtual bool MovePageUp(){
+ public virtual bool MovePageUp ()
+ {
int n = (selected - Frame.Height);
if (n < 0)
n = 0;
- if (n != selected){
+ if (n != selected) {
selected = n;
top = selected;
- if (SelectedChanged != null)
- SelectedChanged();
- SetNeedsDisplay();
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
}
return true;
}
///
- ///
+ /// Moves to the previous page.
///
///
- public virtual bool MovePageDown(){
+ public virtual bool MovePageDown ()
+ {
var n = (selected + Frame.Height);
if (n > source.Count)
n = source.Count - 1;
- if (n != selected){
+ if (n != selected) {
selected = n;
if (source.Count >= Frame.Height)
top = selected;
else
top = 0;
- if (SelectedChanged != null)
- SelectedChanged();
- SetNeedsDisplay();
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
}
return true;
}
///
- ///
+ /// Moves to the next row.
///
///
- public virtual bool MoveDown(){
- if (selected + 1 < source.Count){
+ public virtual bool MoveDown ()
+ {
+ if (selected + 1 < source.Count) {
selected++;
if (selected >= top + Frame.Height)
top++;
- if (SelectedChanged != null)
- SelectedChanged();
- SetNeedsDisplay();
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
}
return true;
}
///
- ///
+ /// Moves to the previous row.
///
///
- public virtual bool MoveUp(){
- if (selected > 0){
+ public virtual bool MoveUp ()
+ {
+ if (selected > 0) {
selected--;
if (selected < top)
top = selected;
- if (SelectedChanged != null)
- SelectedChanged();
- SetNeedsDisplay();
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
}
return true;
}
+ int lastSelectedItem = -1;
+
+ ///
+ /// Invokes the SelectedChanged event if it is defined.
+ ///
+ ///
+ public virtual bool OnSelectedChanged ()
+ {
+ if (selected != lastSelectedItem) {
+ var value = source.ToList () [selected];
+ SelectedChanged?.Invoke (this, new ListViewItemEventArgs (selected, value));
+ lastSelectedItem = selected;
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Invokes the OnOpenSelectedItem event if it is defined.
+ ///
+ ///
+ public virtual bool OnOpenSelectedItem ()
+ {
+ var value = source.ToList () [selected];
+ OpenSelectedItem?.Invoke (this, new ListViewItemEventArgs (selected, value));
+
+ return true;
+ }
+
///
/// Positions the cursor in this view
///
- public override void PositionCursor()
+ public override void PositionCursor ()
{
if (allowsMarking)
Move (1, selected - top);
@@ -461,7 +498,8 @@ namespace Terminal.Gui {
///
public override bool MouseEvent(MouseEvent me)
{
- if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
+ if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked) &&
+ me.Flags != MouseFlags.WheeledDown && me.Flags != MouseFlags.WheeledUp)
return false;
if (!HasFocus)
@@ -470,6 +508,14 @@ namespace Terminal.Gui {
if (source == null)
return false;
+ if (me.Flags == MouseFlags.WheeledDown) {
+ MoveDown ();
+ return true;
+ } else if (me.Flags == MouseFlags.WheeledUp) {
+ MoveUp ();
+ return true;
+ }
+
if (me.Y + top >= source.Count)
return true;
@@ -479,10 +525,10 @@ namespace Terminal.Gui {
SetNeedsDisplay ();
return true;
}
- SelectedChanged?.Invoke ();
+ OnSelectedChanged ();
SetNeedsDisplay ();
if (me.Flags == MouseFlags.Button1DoubleClicked)
- OpenSelectedItem?.Invoke (this, new EventArgs ());
+ OnOpenSelectedItem ();
return true;
}
}
@@ -497,7 +543,7 @@ namespace Terminal.Gui {
int count;
///
- /// constructor
+ /// Constructor based on a source.
///
///
public ListWrapper (IList source)
@@ -508,7 +554,7 @@ namespace Terminal.Gui {
}
///
- /// Count of items.
+ /// Returns the amount of items in the source.
///
public int Count => src.Count;
@@ -519,7 +565,7 @@ namespace Terminal.Gui {
for (int i = 0; i < byteLen;) {
(var rune, var size) = Utf8.DecodeRune (ustr, i, i - byteLen);
var count = Rune.ColumnWidth (rune);
- if (used+count >= width)
+ if (used + count >= width)
break;
driver.AddRune (rune);
used += count;
@@ -531,15 +577,15 @@ namespace Terminal.Gui {
}
///
- /// Renders an item in the the list.
+ /// Method that render to the appropriate type based on the type of the item passed to it.
///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
+ /// The ListView.
+ /// The driver used by the caller.
+ /// Informs if it's marked or not.
+ /// The item.
+ /// The col where to move.
+ /// The line where to move.
+ /// The item width.
public void Render (ListView container, ConsoleDriver driver, bool marked, int item, int col, int line, int width)
{
container.Move (col, line);
@@ -553,10 +599,10 @@ namespace Terminal.Gui {
}
///
- /// Returns true of the item is marked. false if not.
+ /// Returns true if the item is marked, false otherwise.
///
- ///
- ///
+ /// The item.
+ /// trueIf is marked.falseotherwise.
public bool IsMarked (int item)
{
if (item >= 0 && item < count)
@@ -565,14 +611,48 @@ namespace Terminal.Gui {
}
///
- /// Sets the marked state of an item.
+ /// Sets the item as marked or unmarked based on the value is true or false, respectively.
///
- ///
- ///
+ /// The item
+ /// Marks the item.Unmarked the item.The value.
public void SetMark (int item, bool value)
{
if (item >= 0 && item < count)
marks [item] = value;
}
+
+ ///
+ /// Returns the source as IList.
+ ///
+ ///
+ public IList ToList ()
+ {
+ return src;
+ }
+ }
+
+ ///
+ /// Gets the item and value to use in an event handler.
+ ///
+ public class ListViewItemEventArgs : EventArgs {
+ ///
+ /// The item.
+ ///
+ public int Item { get; }
+ ///
+ /// The item value.
+ ///
+ public object Value { get; }
+
+ ///
+ /// Constructor to sets the item and value passed from.
+ ///
+ /// The item.
+ /// The item value
+ public ListViewItemEventArgs (int item, object value)
+ {
+ Item = item;
+ Value = value;
+ }
}
}
diff --git a/Terminal.Gui/Views/StatusBar.cs b/Terminal.Gui/Views/StatusBar.cs
index e204f97e5..789781815 100644
--- a/Terminal.Gui/Views/StatusBar.cs
+++ b/Terminal.Gui/Views/StatusBar.cs
@@ -107,6 +107,10 @@ namespace Terminal.Gui {
Items = items;
CanFocus = false;
ColorScheme = Colors.Menu;
+ X = 0;
+ Y = Driver.Rows - 1;
+ Width = Dim.Fill ();
+ Height = 1;
Application.Loaded += (sender, e) => {
X = 0;
@@ -141,11 +145,11 @@ namespace Terminal.Gui {
///
public override void Redraw (Rect region)
{
- if (Frame.Y != Driver.Rows - 1) {
- Frame = new Rect (Frame.X, Driver.Rows - 1, Frame.Width, Frame.Height);
- Y = Driver.Rows - 1;
- SetNeedsDisplay ();
- }
+ //if (Frame.Y != Driver.Rows - 1) {
+ // Frame = new Rect (Frame.X, Driver.Rows - 1, Frame.Width, Frame.Height);
+ // Y = Driver.Rows - 1;
+ // SetNeedsDisplay ();
+ //}
Move (0, 0);
Driver.SetAttribute (ColorScheme.Normal);
diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs
index 781866ef5..71a53ccd7 100644
--- a/Terminal.Gui/Views/TextField.cs
+++ b/Terminal.Gui/Views/TextField.cs
@@ -28,6 +28,11 @@ namespace Terminal.Gui {
///
public bool Used { get => used; set { used = value; } }
+ ///
+ /// If set to true its not allow any changes in the text.
+ ///
+ public bool ReadOnly { get; set; } = false;
+
///
/// Changed event, raised when the text has clicked.
///
@@ -95,7 +100,7 @@ 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 ();
}
}
@@ -115,6 +120,9 @@ namespace Terminal.Gui {
}
set {
+ if (ReadOnly)
+ return;
+
var oldText = ustring.Make (text);
text = TextModel.ToRunes (value);
if (!Secret && !isFromHistory) {
@@ -184,13 +192,16 @@ namespace Terminal.Gui {
int col = 0;
int width = Frame.Width;
var tcount = text.Count;
+ var roc = new Attribute (Color.DarkGray, Color.Gray);
for (int idx = 0; idx < tcount; idx++){
var rune = text [idx];
if (idx < p)
continue;
var cols = Rune.ColumnWidth (rune);
- if (col == point && HasFocus && !Used && SelectedLength == 0)
+ if (col == point && HasFocus && !Used && SelectedLength == 0 && !ReadOnly)
Driver.SetAttribute (Colors.Menu.HotFocus);
+ else if (ReadOnly)
+ Driver.SetAttribute (idx >= start && length > 0 && idx < start + length ? color.Focus : roc);
else
Driver.SetAttribute (idx >= start && length > 0 && idx < start + length ? color.Focus : ColorScheme.Focus);
if (col + cols <= width)
@@ -261,6 +272,9 @@ namespace Terminal.Gui {
switch (kb.Key) {
case Key.DeleteChar:
case Key.ControlD:
+ if (ReadOnly)
+ return true;
+
if (SelectedLength == 0) {
if (text.Count == 0 || text.Count == point)
return true;
@@ -275,6 +289,9 @@ namespace Terminal.Gui {
case Key.Delete:
case Key.Backspace:
+ if (ReadOnly)
+ return true;
+
if (SelectedLength == 0) {
if (point == 0)
return true;
@@ -373,6 +390,9 @@ namespace Terminal.Gui {
break;
case Key.ControlK: // kill-to-end
+ if (ReadOnly)
+ return true;
+
ClearAllSelection ();
if (point >= text.Count)
return true;
@@ -383,6 +403,9 @@ namespace Terminal.Gui {
// Undo
case Key.ControlZ:
+ if (ReadOnly)
+ return true;
+
if (historyText != null && historyText.Count > 0) {
isFromHistory = true;
if (idxhistoryText > 0)
@@ -396,6 +419,9 @@ namespace Terminal.Gui {
//Redo
case Key.ControlY: // Control-y, yank
+ if (ReadOnly)
+ return true;
+
if (historyText != null && historyText.Count > 0) {
isFromHistory = true;
if (idxhistoryText < historyText.Count - 1) {
@@ -455,6 +481,9 @@ namespace Terminal.Gui {
break;
case Key.ControlX:
+ if (ReadOnly)
+ return true;
+
Cut ();
break;
@@ -472,6 +501,9 @@ namespace Terminal.Gui {
if (kb.Key < Key.Space || kb.Key > Key.CharMask)
return false;
+ if (ReadOnly)
+ return true;
+
if (SelectedLength != 0) {
DeleteSelectedText ();
oldCursorPos = point;
@@ -639,7 +671,7 @@ namespace Terminal.Gui {
point = text.Count;
if (point < first)
point = 0;
- return x;
+ return point;
}
void PrepareSelection (int x, int direction = 0)
@@ -682,8 +714,11 @@ namespace Terminal.Gui {
///
/// Copy the selected text to the clipboard.
///
- public void Copy ()
+ public virtual void Copy ()
{
+ if (Secret)
+ return;
+
if (SelectedLength != 0) {
Clipboard.Contents = SelectedText;
}
@@ -692,7 +727,7 @@ namespace Terminal.Gui {
///
/// Cut the selected text to the clipboard.
///
- public void Cut ()
+ public virtual void Cut ()
{
if (SelectedLength != 0) {
Clipboard.Contents = SelectedText;
@@ -715,8 +750,11 @@ namespace Terminal.Gui {
///
/// Paste the selected text from the clipboard.
///
- public void Paste ()
+ public virtual void Paste ()
{
+ if (ReadOnly)
+ return;
+
string actualText = Text.ToString ();
int start = SelectedStart == -1 ? CursorPosition : SelectedStart;
ustring cbTxt = Clipboard.Contents?.ToString () ?? "";
diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs
index 0d6f35a5c..738a6f35f 100644
--- a/Terminal.Gui/Views/TextView.cs
+++ b/Terminal.Gui/Views/TextView.cs
@@ -39,6 +39,7 @@ namespace Terminal.Gui {
if (file == null)
throw new ArgumentNullException (nameof (file));
try {
+ FilePath = file;
var stream = File.OpenRead (file);
} catch {
return false;
@@ -47,6 +48,19 @@ namespace Terminal.Gui {
return true;
}
+ public bool CloseFile ()
+ {
+ if (FilePath == null)
+ throw new ArgumentNullException (nameof (FilePath));
+ try {
+ FilePath = null;
+ lines = new List> ();
+ } catch {
+ return false;
+ }
+ return true;
+ }
+
// Turns the ustring into runes, this does not split the
// contents on a newline if it is present.
internal static List ToRunes (ustring str)
@@ -120,6 +134,8 @@ namespace Terminal.Gui {
return sb.ToString ();
}
+ public string FilePath { get; set; }
+
///
/// The number of text lines in the model
///
@@ -351,6 +367,18 @@ namespace Terminal.Gui {
SetNeedsDisplay ();
}
+ ///
+ /// Closes the contents of the stream into the TextView.
+ ///
+ /// true, if stream was closed, false otherwise.
+ public bool CloseFile()
+ {
+ ResetPosition ();
+ var res = model.CloseFile ();
+ SetNeedsDisplay ();
+ return res;
+ }
+
///
/// The current cursor row.
///
diff --git a/UICatalog/Program.cs b/UICatalog/Program.cs
index 3a4c1054d..3cb1c866f 100644
--- a/UICatalog/Program.cs
+++ b/UICatalog/Program.cs
@@ -1,5 +1,6 @@
using NStack;
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
@@ -119,7 +120,7 @@ namespace UICatalog {
_rightPane.Add (_scenarioListView);
_categoryListView.SelectedItem = 0;
- CategoryListView_SelectedChanged ();
+ _categoryListView.OnSelectedChanged ();
_statusBar = new StatusBar (new StatusItem [] {
//new StatusItem(Key.F1, "~F1~ Help", () => Help()),
@@ -150,6 +151,7 @@ namespace UICatalog {
_top = Application.Top;
_top.KeyUp += KeyUpHandler;
+
_top.Add (_menu);
_top.Add (_leftPane);
_top.Add (_rightPane);
@@ -228,6 +230,12 @@ namespace UICatalog {
used++;
}
}
+
+ public IList ToList ()
+ {
+ return Scenarios;
+ }
+
}
///
@@ -245,7 +253,7 @@ namespace UICatalog {
// break;
//case Key.Enter:
// break;
- //}
+ //}<
} else if (a.KeyEvent.Key == Key.Tab || a.KeyEvent.Key == Key.BackTab) {
// BUGBUG: Work around Issue #434 by implementing our own TAB navigation
if (_top.MostFocused == _categoryListView)
@@ -255,7 +263,7 @@ namespace UICatalog {
}
}
- private static void CategoryListView_SelectedChanged ()
+ private static void CategoryListView_SelectedChanged (object sender, ListViewItemEventArgs e)
{
var item = _categories [_categoryListView.SelectedItem];
List newlist;