diff --git a/ReactiveExample/ReactiveExample.csproj b/ReactiveExample/ReactiveExample.csproj
index 0c174f748b..c2ce6640cc 100644
--- a/ReactiveExample/ReactiveExample.csproj
+++ b/ReactiveExample/ReactiveExample.csproj
@@ -3,7 +3,7 @@
Exe
net6.0
-
+
1.0
1.0
diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
index 4a8858abf0..c915db6e44 100644
--- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
@@ -74,14 +74,14 @@ public override void AddRune (Rune rune)
var c = sn [0];
Curses.mvaddch (crow, ccol - 1, (int)(uint)c);
contents [crow, ccol - 1, 0] = c;
- contents [crow, ccol - 1, 1] = currentAttribute;
+ contents [crow, ccol - 1, 1] = CurrentAttribute;
contents [crow, ccol - 1, 2] = 1;
} else {
if (runeWidth < 2 && ccol > 0
&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
- var curAtttib = currentAttribute;
+ var curAtttib = CurrentAttribute;
Curses.attrset (contents [crow, ccol - 1, 1]);
Curses.mvaddch (crow, ccol - 1, (int)(uint)' ');
contents [crow, ccol - 1, 0] = (int)(uint)' ';
@@ -91,7 +91,7 @@ public override void AddRune (Rune rune)
} else if (runeWidth < 2 && ccol <= Clip.Right - 1
&& Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
- var curAtttib = currentAttribute;
+ var curAtttib = CurrentAttribute;
Curses.attrset (contents [crow, ccol + 1, 1]);
Curses.mvaddch (crow, ccol + 1, (int)(uint)' ');
contents [crow, ccol + 1, 0] = (int)(uint)' ';
@@ -106,25 +106,28 @@ public override void AddRune (Rune rune)
Curses.addch ((int)(uint)rune);
contents [crow, ccol, 0] = (int)(uint)rune;
}
- contents [crow, ccol, 1] = currentAttribute;
+ contents [crow, ccol, 1] = CurrentAttribute;
contents [crow, ccol, 2] = 1;
}
- } else
+ } else {
needMove = true;
+ }
if (runeWidth < 0 || runeWidth > 0) {
ccol++;
}
+
if (runeWidth > 1) {
if (validClip && ccol < Clip.Right) {
- contents [crow, ccol, 1] = currentAttribute;
+ contents [crow, ccol, 1] = CurrentAttribute;
contents [crow, ccol, 2] = 0;
}
ccol++;
}
- if (sync)
+ if (sync) {
UpdateScreen ();
+ }
}
public override void AddStr (ustring str)
@@ -179,13 +182,10 @@ public override void End ()
public override void UpdateScreen () => window.redrawwin ();
- Attribute currentAttribute = new Attribute (Color.White, Color.Black);
-
public override void SetAttribute (Attribute c)
{
base.SetAttribute (c);
- currentAttribute = c;
- Curses.attrset (currentAttribute);
+ Curses.attrset (CurrentAttribute);
}
public Curses.Window window;
@@ -897,34 +897,18 @@ public override void Init (Action terminalResized)
if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition))
StartReportingMouseMoves ();
- ResizeScreen ();
- UpdateOffScreen ();
-
- //HLine = Curses.ACS_HLINE;
- //VLine = Curses.ACS_VLINE;
- //Stipple = Curses.ACS_CKBOARD;
- //Diamond = Curses.ACS_DIAMOND;
- //ULCorner = Curses.ACS_ULCORNER;
- //LLCorner = Curses.ACS_LLCORNER;
- //URCorner = Curses.ACS_URCORNER;
- //LRCorner = Curses.ACS_LRCORNER;
- //LeftTee = Curses.ACS_LTEE;
- //RightTee = Curses.ACS_RTEE;
- //TopTee = Curses.ACS_TTEE;
- //BottomTee = Curses.ACS_BTEE;
- //RightArrow = Curses.ACS_RARROW;
- //LeftArrow = Curses.ACS_LARROW;
- //UpArrow = Curses.ACS_UARROW;
- //DownArrow = Curses.ACS_DARROW;
+ CurrentAttribute = MakeColor (Color.White, Color.Black);
if (Curses.HasColors) {
Curses.StartColor ();
Curses.UseDefaultColors ();
- CreateColors ();
+ InitalizeColorSchemes ();
} else {
- CreateColors (false);
+ InitalizeColorSchemes (false);
+ // BUGBUG: This is a hack to make the colors work on the Mac?
+ // The new Theme support overwrites these colors, so this is not needed?
Colors.TopLevel.Normal = Curses.COLOR_GREEN;
Colors.TopLevel.Focus = Curses.COLOR_WHITE;
Colors.TopLevel.HotNormal = Curses.COLOR_YELLOW;
@@ -951,6 +935,10 @@ public override void Init (Action terminalResized)
Colors.Error.HotFocus = Curses.A_REVERSE;
Colors.Error.Disabled = Curses.A_BOLD | Curses.COLOR_GRAY;
}
+
+ ResizeScreen ();
+ UpdateOffScreen ();
+
}
public override void ResizeScreen ()
@@ -1025,6 +1013,8 @@ static int MapColor (Color color)
return Curses.COLOR_YELLOW | Curses.A_BOLD | Curses.COLOR_GRAY;
case Color.White:
return Curses.COLOR_WHITE | Curses.A_BOLD | Curses.COLOR_GRAY;
+ case Color.Invalid:
+ return Curses.COLOR_BLACK;
}
throw new ArgumentException ("Invalid color code");
}
@@ -1115,11 +1105,6 @@ public override void CookMouse ()
//Curses.mouseinterval (lastMouseInterval);
}
- public override Attribute GetAttribute ()
- {
- return currentAttribute;
- }
-
///
public override bool GetCursorVisibility (out CursorVisibility visibility)
{
diff --git a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
index e9ae11a425..661daaca47 100644
--- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
@@ -142,7 +142,7 @@ public override void AddRune (Rune rune)
}
var c = sn [0];
contents [crow, ccol - 1, 0] = c;
- contents [crow, ccol - 1, 1] = currentAttribute;
+ contents [crow, ccol - 1, 1] = CurrentAttribute;
contents [crow, ccol - 1, 2] = 1;
} else {
@@ -163,20 +163,22 @@ public override void AddRune (Rune rune)
} else {
contents [crow, ccol, 0] = (int)(uint)rune;
}
- contents [crow, ccol, 1] = currentAttribute;
+ contents [crow, ccol, 1] = CurrentAttribute;
contents [crow, ccol, 2] = 1;
dirtyLine [crow] = true;
}
- } else
+ } else {
needMove = true;
+ }
if (runeWidth < 0 || runeWidth > 0) {
ccol++;
}
+
if (runeWidth > 1) {
if (validClip && ccol < Clip.Right) {
- contents [crow, ccol, 1] = currentAttribute;
+ contents [crow, ccol, 1] = CurrentAttribute;
contents [crow, ccol, 2] = 0;
}
ccol++;
@@ -187,8 +189,9 @@ public override void AddRune (Rune rune)
// if (crow + 1 < Rows)
// crow++;
//}
- if (sync)
+ if (sync) {
UpdateScreen ();
+ }
}
public override void AddStr (ustring str)
@@ -226,8 +229,9 @@ public override void Init (Action terminalResized)
rows = FakeConsole.WindowHeight = FakeConsole.BufferHeight = FakeConsole.HEIGHT;
FakeConsole.Clear ();
ResizeScreen ();
- // Call CreateColors before UpdateOffScreen as it references Colors
- CreateColors ();
+ // Call InitalizeColorSchemes before UpdateOffScreen as it references Colors
+ CurrentAttribute = MakeColor (Color.White, Color.Black);
+ InitalizeColorSchemes ();
UpdateOffScreen ();
}
@@ -299,11 +303,9 @@ public override void Refresh ()
UpdateCursor ();
}
- Attribute currentAttribute = new Attribute (Color.White, Color.Black);
public override void SetAttribute (Attribute c)
{
base.SetAttribute (c);
- currentAttribute = c;
}
public ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
@@ -492,11 +494,6 @@ void ProcessInput (ConsoleKeyInfo consoleKey)
keyUpHandler (new KeyEvent (map, keyModifiers));
}
- public override Attribute GetAttribute ()
- {
- return currentAttribute;
- }
-
///
public override bool GetCursorVisibility (out CursorVisibility visibility)
{
diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
index 5f3e560ec6..9ae4eb20e5 100644
--- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
@@ -1252,7 +1252,7 @@ public override void AddRune (Rune rune)
}
var c = sn [0];
contents [crow, ccol - 1, 0] = c;
- contents [crow, ccol - 1, 1] = currentAttribute;
+ contents [crow, ccol - 1, 1] = CurrentAttribute;
contents [crow, ccol - 1, 2] = 1;
} else {
@@ -1273,7 +1273,7 @@ public override void AddRune (Rune rune)
} else {
contents [crow, ccol, 0] = (int)(uint)rune;
}
- contents [crow, ccol, 1] = currentAttribute;
+ contents [crow, ccol, 1] = CurrentAttribute;
contents [crow, ccol, 2] = 1;
}
@@ -1283,9 +1283,10 @@ public override void AddRune (Rune rune)
if (runeWidth < 0 || runeWidth > 0) {
ccol++;
}
+
if (runeWidth > 1) {
if (validClip && ccol < Clip.Right) {
- contents [crow, ccol, 1] = currentAttribute;
+ contents [crow, ccol, 1] = CurrentAttribute;
contents [crow, ccol, 2] = 0;
}
ccol++;
@@ -1358,12 +1359,14 @@ public override void Init (Action terminalResized)
cols = Console.WindowWidth;
rows = Console.WindowHeight;
+ CurrentAttribute = MakeColor (Color.White, Color.Black);
+ InitalizeColorSchemes ();
+
ResizeScreen ();
UpdateOffScreen ();
StartReportingMouseMoves ();
- CreateColors ();
Clear ();
}
@@ -1631,12 +1634,10 @@ public override void Suspend ()
{
}
- Attribute currentAttribute = new Attribute (Color.White, Color.Black);
public override void SetAttribute (Attribute c)
{
base.SetAttribute (c);
- currentAttribute = c;
}
public ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
@@ -1954,11 +1955,6 @@ MouseEvent ToDriverMouse (NetEvents.MouseEvent me)
};
}
- public override Attribute GetAttribute ()
- {
- return currentAttribute;
- }
-
///
public override bool GetCursorVisibility (out CursorVisibility visibility)
{
diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
index e03ff1b9ce..8a7502c265 100644
--- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
@@ -1455,13 +1455,13 @@ public override void Init (Action terminalResized)
var winSize = WinConsole.GetConsoleOutputWindow (out Point pos);
cols = winSize.Width;
rows = winSize.Height;
-
WindowsConsole.SmallRect.MakeEmpty (ref damageRegion);
+ CurrentAttribute = MakeColor (Color.White, Color.Black);
+ InitalizeColorSchemes ();
+
ResizeScreen ();
UpdateOffScreen ();
-
- CreateColors ();
} catch (Win32Exception e) {
throw new InvalidOperationException ("The Windows Console output window is not available.", e);
}
@@ -1530,8 +1530,8 @@ public override void AddRune (Rune rune)
var prevPosition = crow * Cols + (ccol - 1);
OutputBuffer [prevPosition].Char.UnicodeChar = c;
contents [crow, ccol - 1, 0] = c;
- OutputBuffer [prevPosition].Attributes = (ushort)currentAttribute;
- contents [crow, ccol - 1, 1] = currentAttribute;
+ OutputBuffer [prevPosition].Attributes = (ushort)CurrentAttribute;
+ contents [crow, ccol - 1, 1] = CurrentAttribute;
contents [crow, ccol - 1, 2] = 1;
WindowsConsole.SmallRect.Update (ref damageRegion, (short)(ccol - 1), (short)crow);
} else {
@@ -1557,8 +1557,8 @@ public override void AddRune (Rune rune)
OutputBuffer [position].Char.UnicodeChar = (char)rune;
contents [crow, ccol, 0] = (int)(uint)rune;
}
- OutputBuffer [position].Attributes = (ushort)currentAttribute;
- contents [crow, ccol, 1] = currentAttribute;
+ OutputBuffer [position].Attributes = (ushort)CurrentAttribute;
+ contents [crow, ccol, 1] = CurrentAttribute;
contents [crow, ccol, 2] = 1;
WindowsConsole.SmallRect.Update (ref damageRegion, (short)ccol, (short)crow);
}
@@ -1567,20 +1567,22 @@ public override void AddRune (Rune rune)
if (runeWidth < 0 || runeWidth > 0) {
ccol++;
}
+
if (runeWidth > 1) {
if (validClip && ccol < Clip.Right) {
position = GetOutputBufferPosition ();
- OutputBuffer [position].Attributes = (ushort)currentAttribute;
+ OutputBuffer [position].Attributes = (ushort)CurrentAttribute;
OutputBuffer [position].Char.UnicodeChar = (char)0x00;
contents [crow, ccol, 0] = (int)(uint)0x00;
- contents [crow, ccol, 1] = currentAttribute;
+ contents [crow, ccol, 1] = CurrentAttribute;
contents [crow, ccol, 2] = 0;
}
ccol++;
}
- if (sync)
+ if (sync) {
UpdateScreen ();
+ }
}
public override void AddStr (ustring str)
@@ -1589,12 +1591,9 @@ public override void AddStr (ustring str)
AddRune (rune);
}
- Attribute currentAttribute = new Attribute (Color.White, Color.Black);
-
public override void SetAttribute (Attribute c)
{
base.SetAttribute (c);
- currentAttribute = c;
}
public override Attribute MakeColor (Color foreground, Color background)
@@ -1696,11 +1695,6 @@ public override void End ()
WinConsole = null;
}
- public override Attribute GetAttribute ()
- {
- return currentAttribute;
- }
-
///
public override bool GetCursorVisibility (out CursorVisibility visibility)
{
diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs
index b5f6e5984d..681a4733af 100644
--- a/Terminal.Gui/Core/Application.cs
+++ b/Terminal.Gui/Core/Application.cs
@@ -57,7 +57,7 @@ namespace Terminal.Gui {
///
///
public static class Application {
- static Stack toplevels = new Stack ();
+ static readonly Stack toplevels = new Stack ();
///
/// The current in use.
@@ -111,28 +111,33 @@ public static Toplevel MdiTop {
///
public static View WantContinuousButtonPressedView { get; private set; }
+ private static bool? _heightAsBuffer;
+
///
/// The current used in the terminal.
///
+ ///
public static bool HeightAsBuffer {
get {
if (Driver == null) {
- throw new ArgumentNullException ("The driver must be initialized first.");
+ return _heightAsBuffer.HasValue && _heightAsBuffer.Value;
}
return Driver.HeightAsBuffer;
}
set {
+ _heightAsBuffer = value;
if (Driver == null) {
- throw new ArgumentNullException ("The driver must be initialized first.");
+ return;
}
- Driver.HeightAsBuffer = value;
+
+ Driver.HeightAsBuffer = _heightAsBuffer.Value;
}
}
static Key alternateForwardKey = Key.PageDown | Key.CtrlMask;
///
- /// Alternative key to navigate forwards through all views. Ctrl+Tab is always used.
+ /// Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.
///
public static Key AlternateForwardKey {
get => alternateForwardKey;
@@ -147,7 +152,7 @@ public static Key AlternateForwardKey {
static void OnAlternateForwardKeyChanged (Key oldKey)
{
- foreach (var top in toplevels) {
+ foreach (var top in toplevels.ToArray()) {
top.OnAlternateForwardKeyChanged (oldKey);
}
}
@@ -155,7 +160,7 @@ static void OnAlternateForwardKeyChanged (Key oldKey)
static Key alternateBackwardKey = Key.PageUp | Key.CtrlMask;
///
- /// Alternative key to navigate backwards through all views. Shift+Ctrl+Tab is always used.
+ /// Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.
///
public static Key AlternateBackwardKey {
get => alternateBackwardKey;
@@ -170,7 +175,7 @@ public static Key AlternateBackwardKey {
static void OnAlternateBackwardKeyChanged (Key oldKey)
{
- foreach (var top in toplevels) {
+ foreach (var top in toplevels.ToArray()) {
top.OnAlternateBackwardKeyChanged (oldKey);
}
}
@@ -200,7 +205,8 @@ public static Key QuitKey {
static void OnQuitKeyChanged (Key oldKey)
{
- foreach (var top in toplevels) {
+ // Duplicate the list so if it changes during enumeration we're safe
+ foreach (var top in toplevels.ToArray()) {
top.OnQuitKeyChanged (oldKey);
}
}
@@ -212,7 +218,7 @@ static void OnQuitKeyChanged (Key oldKey)
public static MainLoop MainLoop { get; private set; }
///
- /// Disable or enable the mouse in this
+ /// Disable or enable the mouse. The mouse is enabled by default.
///
public static bool IsMouseDisabled { get; set; }
@@ -266,7 +272,7 @@ public static Rect MakeCenteredRect (Size size)
// users use async/await on their code
//
class MainLoopSyncContext : SynchronizationContext {
- MainLoop mainLoop;
+ readonly MainLoop mainLoop;
public MainLoopSyncContext (MainLoop mainLoop)
{
@@ -305,9 +311,9 @@ public override void Send (SendOrPostCallback d, object state)
}
///
- /// If set, it forces the use of the System.Console-based driver.
+ /// If , forces the use of the System.Console-based (see ) driver. The default is .
///
- public static bool UseSystemConsole;
+ public static bool UseSystemConsole { get; set; } = false;
// For Unit testing - ignores UseSystemConsole
internal static bool ForceFakeConsole;
@@ -422,6 +428,7 @@ internal static void InternalInit (Func topLevelFactory, ConsoleDriver
MainLoop = new MainLoop (mainLoopDriver);
try {
+ Driver.HeightAsBuffer = HeightAsBuffer;
Driver.Init (TerminalResized);
} catch (InvalidOperationException ex) {
// This is a case where the driver is unable to initialize the console.
@@ -986,9 +993,7 @@ public static RunState Begin (Toplevel toplevel)
toplevel.PositionToplevels ();
toplevel.WillPresent ();
if (refreshDriver) {
- if (MdiTop != null) {
- MdiTop.OnChildLoaded (toplevel);
- }
+ MdiTop?.OnChildLoaded (toplevel);
toplevel.OnLoaded ();
Redraw (toplevel);
toplevel.PositionCursor ();
@@ -1111,12 +1116,6 @@ static void Redraw (View view)
Driver.Refresh ();
}
- static void Refresh (View view)
- {
- view.Redraw (view.Bounds);
- Driver.Refresh ();
- }
-
///
/// Triggers a refresh of the entire display.
///
diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs
index 4fd2dd6f95..bc3856289a 100644
--- a/Terminal.Gui/Core/ConsoleDriver.cs
+++ b/Terminal.Gui/Core/ConsoleDriver.cs
@@ -17,7 +17,6 @@ namespace Terminal.Gui {
///
/// The value indicates either no-color has been set or the color is invalid.
///
- [DefaultValue(Invalid)]
public enum Color {
///
/// The black color.
@@ -82,13 +81,91 @@ public enum Color {
///
/// The White color.
///
- White,
+ White,
///
/// Indicates an invalid or un-set color value.
///
Invalid = -1
}
+ ///
+ ///
+ ///
+ public class TrueColor {
+ ///
+ /// Red color component.
+ ///
+ public int Red { get; }
+ ///
+ /// Green color component.
+ ///
+ public int Green { get; }
+ ///
+ /// Blue color component.
+ ///
+ public int Blue { get; }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ ///
+ ///
+ ///
+ public TrueColor (int red, int green, int blue)
+ {
+ Red = red;
+ Green = green;
+ Blue = blue;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public Color ToConsoleColor ()
+ {
+ var trueColorMap = new Dictionary () {
+ { new TrueColor (0,0,0),Color.Black},
+ { new TrueColor (0, 0, 0x80),Color.Blue},
+ { new TrueColor (0, 0x80, 0),Color.Green},
+ { new TrueColor (0, 0x80, 0x80),Color.Cyan},
+ { new TrueColor (0x80, 0, 0),Color.Red},
+ { new TrueColor (0x80, 0, 0x80),Color.Magenta},
+ { new TrueColor (0xC1, 0x9C, 0x00),Color.Brown}, // TODO confirm this
+ { new TrueColor (0xC0, 0xC0, 0xC0),Color.Gray},
+ { new TrueColor (0x80, 0x80, 0x80),Color.DarkGray},
+ { new TrueColor (0, 0, 0xFF),Color.BrightBlue},
+ { new TrueColor (0, 0xFF, 0),Color.BrightGreen},
+ { new TrueColor (0, 0xFF, 0xFF),Color.BrightCyan},
+ { new TrueColor (0xFF, 0, 0),Color.BrightRed},
+ { new TrueColor (0xFF, 0, 0xFF),Color.BrightMagenta },
+ { new TrueColor (0xFF, 0xFF, 0),Color.BrightYellow},
+ { new TrueColor (0xFF, 0xFF, 0xFF),Color.White},
+ };
+ // Iterate over all colors in the map
+ var distances = trueColorMap.Select (
+ k => Tuple.Create (
+ // the candidate we are considering matching against (RGB)
+ k.Key,
+
+ CalculateDistance (k.Key, this)
+ ));
+
+ // get the closest
+ var match = distances.OrderBy (t => t.Item2).First ();
+ return trueColorMap [match.Item1];
+ }
+
+ private float CalculateDistance (TrueColor color1, TrueColor color2)
+ {
+ // use RGB distance
+ return
+ Math.Abs (color1.Red - color2.Red) +
+ Math.Abs (color1.Green - color2.Green) +
+ Math.Abs (color1.Blue - color2.Blue);
+ }
+ }
+
///
/// Attributes are used as elements that contain both a foreground and a background or platform specific features.
///
@@ -123,7 +200,7 @@ public struct Attribute {
public Attribute (int value)
{
Color foreground = Color.Invalid;
- Color background = Color.Invalid;
+ Color background = Color.Invalid;
Initialized = false;
if (Application.Driver != null) {
@@ -156,8 +233,9 @@ public Attribute (int value, Color foreground, Color background)
/// Background
public Attribute (Color foreground = new Color (), Color background = new Color ())
{
- Initialized = false;
- Value = Make (foreground, background).Value;
+ var make = Make (foreground, background);
+ Initialized = make.Initialized;
+ Value = make.Value;
Foreground = foreground;
Background = background;
}
@@ -175,10 +253,10 @@ public Attribute (Color color) : this (color, color) { }
///
/// The driver-specific color value stored in the attribute.
/// The attribute to convert
- public static implicit operator int (Attribute c) {
- Debug.WriteLineIf (!c.Initialized, "ConsoleDriver.SetAttribute: Attributes must be initialized by a driver before use.");
- //if (!c.IsInitialized) throw new InvalidOperationException ("Attributes must be initialized by driver before use.");
- return c.Value;
+ public static implicit operator int (Attribute c)
+ {
+ if (!c.Initialized) throw new InvalidOperationException ("Attribute: Attributes must be initialized by a driver before use.");
+ return c.Value;
}
///
@@ -251,11 +329,11 @@ public bool HasValidColors {
/// See also: .
///
public class ColorScheme : IEquatable {
- Attribute _normal;
- Attribute _focus;
- Attribute _hotNormal;
- Attribute _hotFocus;
- Attribute _disabled;
+ Attribute _normal = new Attribute(Color.White, Color.Black);
+ Attribute _focus = new Attribute (Color.White, Color.Black);
+ Attribute _hotNormal = new Attribute (Color.White, Color.Black);
+ Attribute _hotFocus = new Attribute (Color.White, Color.Black);
+ Attribute _disabled = new Attribute (Color.White, Color.Black);
///
/// Used by and to track which ColorScheme
@@ -269,7 +347,6 @@ public class ColorScheme : IEquatable {
public Attribute Normal {
get { return _normal; }
set {
-
if (!value.HasValidColors) {
return;
}
@@ -390,20 +467,67 @@ public override int GetHashCode ()
{
return !(left == right);
}
+
+ internal void Initialize ()
+ {
+ // If the new scheme was created before a driver was loaded, we need to re-make
+ // the attributes
+ if (!_normal.Initialized) {
+ _normal = new Attribute (_normal.Foreground, _normal.Background);
+ }
+ if (!_focus.Initialized) {
+ _focus = new Attribute (_focus.Foreground, _focus.Background);
+ }
+ if (!_hotNormal.Initialized) {
+ _hotNormal = new Attribute (_hotNormal.Foreground, _hotNormal.Background);
+ }
+ if (!_hotFocus.Initialized) {
+ _hotFocus = new Attribute (_hotFocus.Foreground, _hotFocus.Background);
+ }
+ if (!_disabled.Initialized) {
+ _disabled = new Attribute (_disabled.Foreground, _disabled.Background);
+ }
+ }
}
///
/// The default s for the application.
///
+ ///
+ /// This property can be set in a Theme to change the default for the application.
+ ///
public static class Colors {
+ private class SchemeNameComparerIgnoreCase : IEqualityComparer {
+ public bool Equals (string x, string y)
+ {
+ if (x != null && y != null) {
+ return x.ToLowerInvariant () == y.ToLowerInvariant ();
+ }
+ return false;
+ }
+
+ public int GetHashCode (string obj)
+ {
+ return obj.ToLowerInvariant ().GetHashCode ();
+ }
+ }
+
static Colors ()
+ {
+ ColorSchemes = Create ();
+ }
+
+ ///
+ /// Creates a new dictionary of new objects.
+ ///
+ public static Dictionary Create ()
{
// Use reflection to dynamically create the default set of ColorSchemes from the list defined
// by the class.
- ColorSchemes = typeof (Colors).GetProperties ()
+ return typeof (Colors).GetProperties ()
.Where (p => p.PropertyType == typeof (ColorScheme))
- .Select (p => new KeyValuePair (p.Name, new ColorScheme ())) // (ColorScheme)p.GetValue (p)))
- .ToDictionary (t => t.Key, t => t.Value);
+ .Select (p => new KeyValuePair (p.Name, new ColorScheme()))
+ .ToDictionary (t => t.Key, t => t.Value, comparer: new SchemeNameComparerIgnoreCase ());
}
///
@@ -470,7 +594,7 @@ static void SetColorScheme (ColorScheme colorScheme, [CallerMemberName] string s
///
/// Provides the defined s.
///
- public static Dictionary ColorSchemes { get; }
+ public static Dictionary ColorSchemes { get; private set; }
}
///
@@ -753,6 +877,22 @@ public bool IsValidContent (int col, int row, Rect clip) =>
///
public abstract void UpdateScreen ();
+ ///
+ /// The current attribute the driver is using.
+ ///
+ public virtual Attribute CurrentAttribute {
+ get => currentAttribute;
+ set {
+ if (!value.Initialized && value.HasValidColors && Application.Driver != null) {
+ CurrentAttribute = Application.Driver.MakeAttribute (value.Foreground, value.Background);
+ return;
+ }
+ if (!value.Initialized) Debug.WriteLine ("ConsoleDriver.CurrentAttribute: Attributes must be initialized before use.");
+
+ currentAttribute = value;
+ }
+ }
+
///
/// Selects the specified attribute as the attribute to use for future calls to AddRune and AddString.
///
@@ -762,7 +902,7 @@ public bool IsValidContent (int col, int row, Rect clip) =>
/// C.
public virtual void SetAttribute (Attribute c)
{
- Debug.WriteLineIf(!c.Initialized, "ConsoleDriver.SetAttribute: Attributes must be initialized before use.");
+ CurrentAttribute = c;
}
///
@@ -1298,6 +1438,7 @@ public Rect Clip {
/// Lower right rounded corner
///
public Rune LRRCorner = '\u256f';
+ private Attribute currentAttribute;
///
/// Make the attribute for the foreground and background colors.
@@ -1311,7 +1452,7 @@ public Rect Clip {
/// Gets the current .
///
/// The current attribute.
- public abstract Attribute GetAttribute ();
+ public Attribute GetAttribute () => CurrentAttribute;
///
/// Make the for the .
@@ -1322,17 +1463,16 @@ public Rect Clip {
public abstract Attribute MakeColor (Color foreground, Color background);
///
- /// Create all with the for the console driver.
+ /// Ensures all s in are correclty
+ /// initalized by the driver.
///
- /// Flag indicating if colors are supported.
- public void CreateColors (bool supportsColors = true)
+ /// Flag indicating if colors are supported (not used).
+ public void InitalizeColorSchemes (bool supportsColors = true)
{
- // BUGBUG: No need to create these instances here as they are created in constructor
- //Colors.TopLevel = new ColorScheme ();
- //Colors.Base = new ColorScheme ();
- //Colors.Dialog = new ColorScheme ();
- //Colors.Menu = new ColorScheme ();
- //Colors.Error = new ColorScheme ();
+ // Ensure all Attributes are initlaized by the driver
+ foreach (var s in Colors.ColorSchemes) {
+ s.Value.Initialize ();
+ }
if (!supportsColors) {
return;
diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs
index fddabb692e..1346244a0c 100644
--- a/Terminal.Gui/Core/Toplevel.cs
+++ b/Terminal.Gui/Core/Toplevel.cs
@@ -821,7 +821,6 @@ public override bool MouseEvent (MouseEvent mouseEvent)
if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) && dragPosition.HasValue) {
Application.UngrabMouse ();
- Driver.UncookMouse ();
dragPosition = null;
}
diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index 8734261c0b..36ce60d5ee 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -1447,8 +1447,9 @@ public View MostFocused {
///
public virtual ColorScheme ColorScheme {
get {
- if (colorScheme == null)
+ if (colorScheme == null) {
return SuperView?.ColorScheme;
+ }
return colorScheme;
}
set {
diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj
index ce22fd3cd0..e92806346d 100644
--- a/Terminal.Gui/Terminal.Gui.csproj
+++ b/Terminal.Gui/Terminal.Gui.csproj
@@ -10,9 +10,10 @@
- 1.9
- 1.9
- 1.9
+ 1.0
+ 1.0
+ 1.0
+ 1.0
diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs
index 14cd47ecec..4c8f19eee8 100644
--- a/UICatalog/UICatalog.cs
+++ b/UICatalog/UICatalog.cs
@@ -164,7 +164,7 @@ class UICatalogTopLevel : Toplevel {
public UICatalogTopLevel ()
{
- ColorScheme = _colorScheme;
+ ColorScheme = _colorScheme = Colors.Base;
MenuBar = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_File", new MenuItem [] {
new MenuItem ("_Quit", "Quit UI Catalog", () => RequestStop(), null, null, Key.Q | Key.CtrlMask)
diff --git a/UICatalog/UICatalog.csproj b/UICatalog/UICatalog.csproj
index 40d346438f..6320c1e996 100644
--- a/UICatalog/UICatalog.csproj
+++ b/UICatalog/UICatalog.csproj
@@ -5,7 +5,7 @@
8.0
UICatalog.UICatalogApp
-
+
1.0
1.0
diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs
index b7ef1d8dbd..7228d8ad6e 100644
--- a/UnitTests/Application/ApplicationTests.cs
+++ b/UnitTests/Application/ApplicationTests.cs
@@ -24,7 +24,6 @@ void Pre_Init_State ()
Assert.Null (Application.Driver);
Assert.Null (Application.Top);
Assert.Null (Application.Current);
- Assert.Throws (() => Application.HeightAsBuffer == true);
Assert.Null (Application.MainLoop);
Assert.Null (Application.Iteration);
Assert.Null (Application.RootMouseEvent);
diff --git a/UnitTests/Drivers/ConsoleDriverTests.cs b/UnitTests/Drivers/ConsoleDriverTests.cs
index a77d5f5a67..8289e9737a 100644
--- a/UnitTests/Drivers/ConsoleDriverTests.cs
+++ b/UnitTests/Drivers/ConsoleDriverTests.cs
@@ -319,7 +319,7 @@ public void HeightAsBuffer_Is_True_Top_Cannot_Be_Greater_Than_BufferHeight_Minus
Application.Shutdown ();
}
-
+
[Fact, AutoInitShutdown]
public void AddRune_On_Clip_Left_Or_Right_Replace_Previous_Or_Next_Wide_Rune_With_Space ()
{
@@ -441,7 +441,7 @@ public void MakePrintable_Does_Not_Convert_Ansi_Chars_To_Unicode (uint code)
}
private static object packetLock = new object ();
-
+
///
/// Sometimes when using remote tools EventKeyRecord sends 'virtual keystrokes'.
/// These are indicated with the wVirtualKeyCode of 231. When we see this code
@@ -487,6 +487,7 @@ public void TestVKPacket (uint unicodeCharacter, bool shift, bool alt, bool cont
if (iterations == 0) Application.Driver.SendKeys ((char)mappedConsoleKey, ConsoleKey.Packet, shift, alt, control);
};
+
lock (packetLock) {
Application.Run ();
Application.Shutdown ();
diff --git a/UnitTests/Drivers/KeyTests.cs b/UnitTests/Drivers/KeyTests.cs
index 3d4d8606e3..3116c86285 100644
--- a/UnitTests/Drivers/KeyTests.cs
+++ b/UnitTests/Drivers/KeyTests.cs
@@ -1,4 +1,5 @@
using System;
+using Terminal.Gui;
using Xunit;
namespace Terminal.Gui.DriverTests {
diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj
index 68da4e1d00..ae37662441 100644
--- a/UnitTests/UnitTests.csproj
+++ b/UnitTests/UnitTests.csproj
@@ -7,12 +7,12 @@
false
-
+
- 1.0
- 1.0
- 1.0
- 1.0
+ 2.0
+ 2.0
+ 2.0
+ 2.0
TRACE