Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Colors: ColorSchemes refactor - Should honor terminal color settings etc... #2381

Open
3 tasks
tig opened this issue Feb 26, 2023 · 7 comments
Open
3 tasks
Labels
v2 For discussions, issues, etc... relavant for v2
Milestone

Comments

@tig
Copy link
Collaborator

tig commented Feb 26, 2023

Developers (like me) love tweaking their terminal colors/themes.

Terminal.Gui, today, overrides all this, defining it's own themes.

This means that when I run a TUI app, the effect is glaring and doesn't honor all the hard work I put into tweaking my terminal theme. E.g.:

JiQYZBw 1

In addition we always clear the Toplevel background vs, letting any bitmap the user has set show through.

For v2, I'd like to see Terminal.Gui pick up the colors theme of the Terminal and use it, by default.

Of course, this implies we nail #48 too.

I think this means a Tenet for v2:

  • Honor The Terminal Theme - To the extent possible, Terminal.Gui will use terminal color, keyboard, and other themes vs defining it's own.

Other things that should be addressed as part of this:

@tig tig added the v2 For discussions, issues, etc... relavant for v2 label Feb 26, 2023
@tig tig moved this to 📋 Backlog in Terminal.Gui V2 Beta Mar 3, 2023
@tig tig moved this from 📋 Backlog to 🏗 In progress in Terminal.Gui V2 Beta Apr 16, 2023
@tig tig moved this from 🏗 In progress to 📋 Backlog in Terminal.Gui V2 Beta Apr 16, 2023
@tig tig changed the title ColorSchemes should honor terminal color settings Colors: ColorSchemes should honor terminal color settings Apr 16, 2023
@tig tig moved this from 📋 Backlog to 🔖 Ready in Terminal.Gui V2 Beta Apr 16, 2023
@Nutzzz
Copy link
Contributor

Nutzzz commented May 26, 2023

I was thinking about how a default theme could be dynamically created based only on an inherited foreground and background. This is quite difficult. FWIW, I thought I'd lay down my ideas.

.Normal would just use the current colors, of course:

fg = defFore;  bg = defBack;

.Focus would just swap background and foreground [EDIT: though this collides with selection]:

fg = defBack;  bg = defFore;

.Disabled, I think, should compute a grayscale foreground color based on the background, adjusted for Luma. See Luma() below. We could use the following for RGB colors, or round to the nearest grayscale ConsoleColor (though see NB below):

fg = Luma(defBack) > 0.5 ? Gray(255 * Luma(defBack) - 63) : Gray(255 * Luma(defBack) + 63);
bg = defBack;

.HotNormal is where things get tough:

fg = AccentColor(defFore);  bg = defBack;

To get an accent color, my first thought was to use an inverse of the RGB of the foreground color. However, this wouldn't work for middle-grayish colors, would often result in ugly combinations, and it wouldn't take Luma into account. It's somewhat easy to handpick a color for each of the 16 ConsoleColors like my AccentColor() implementation below, though this is obviously a matter of taste, and taking both foreground and background into consideration does complicate things quite a bit.

AccentColor() would be somewhat more complicated using RGB (TrueColor or not), but I suppose the suggestions I offer below could still be used if we approximate numerically 16 zones of "reddish" or "dark-blueish" or "blackish" colors [something like the existing Color.ToConsoleColor()], but then we could adjust the accent result based on the calculated saturation and brightness.

.HotFocus is similar, but swapping background and foreground:

fg = AccentColorAdjusted(defFore);  bg = defFore;

However, we probably don't want to introduce another color which might clash with HotNormal, so we wouldn't just use fg = AccentColor(defBack); So my thought is to either re-use the AccentColor(defFore) when there is sufficient difference in Luma between foreground and background, otherwise flip the accent ConsoleColor from dark to bright or bright to dark (or a similar approximation for RGB values).

NB: On the other hand, since each of the ConsoleColors can be set by the user and might even have little bearing on the actual color, it's dangerous to make assumptions. Even assuming the defaults were kept, there's variance between platforms and terminal emulations, e.g., whether bright colors are allowed as backgrounds. Under Windows, depending on the upgrade path the user might still be using legacy colors or the newer Campbell colors.

However, is it even possible to programmatically determine the RGB values of the currently used colors? E.g., using Windows Terminal, we'd have to find and read the appropriate .json file; using Windows conhost, in some circumstances these values would be in the registry, and in some circumstances they'd be in the .lnk file used to launch it; with a multitude of implementations for other shells and platforms and terminal emulations.

EDIT: Also, how is this supposed to work with the bitmap background? How do we ensure a transparent color is used so the bitmap isn't hidden when we've drawn spaces after, e.g., a window is dragged around? Does it just draw the bitmap anywhere the current background color exists? And I assume these implementation details could differ between shells...
EDIT 2: It appears that my assumption was correct, for WT at least, so no need to worry about transparency there.

float Luma(Color c) {
   return 0.2126 * c.ScR + 0.7152 * c.ScG + 0.0722 * c.ScB; }

Color Gray(int x) {
   return Color(x, x, x); }

static ConsoleColor AccentColor(ConsoleColor fg, ConsoleColor bg) {
   ConsoleColor newc = new();
   switch (fg) {
      case ConsoleColor.Gray:
      case ConsoleColor.White:
         newc = bg == ConsoleColor.DarkGreen ? ConsoleColor.Black : ConsoleColor.DarkGreen; break;
      case ConsoleColor.DarkGreen:
         newc = bg == ConsoleColor.White ? ConsoleColor.Green : ConsoleColor.White; break;
      case ConsoleColor.DarkGray:
      case ConsoleColor.Black:
         newc = bg == ConsoleColor.Green ? ConsoleColor.White : ConsoleColor.Green; break;
      case ConsoleColor.Green:
         newc = bg == ConsoleColor.Black ? ConsoleColor.DarkCyan : ConsoleColor.Black; break;
      case ConsoleColor.DarkBlue:
         newc = bg == ConsoleColor.Cyan ? ConsoleColor.Yellow : ConsoleColor.Cyan; break;
      case ConsoleColor.Cyan:
         newc = bg == ConsoleColor.DarkBlue ? ConsoleColor.DarkGray : ConsoleColor.DarkBlue; break;
      case ConsoleColor.DarkRed:
      case ConsoleColor.DarkMagenta:
         newc = bg == ConsoleColor.White ? ConsoleColor.Yellow : ConsoleColor.White; break;
      case ConsoleColor.Magenta:
      case ConsoleColor.Red:
         newc = bg == ConsoleColor.Black ? ConsoleColor.DarkYellow : ConsoleColor.Black; break;
      case ConsoleColor.Yellow:
         newc = bg == ConsoleColor.DarkBlue ? ConsoleColor.Black : ConsoleColor.DarkBlue; break;
      case ConsoleColor.DarkCyan:
      case ConsoleColor.Blue:
         newc = bg == ConsoleColor.Yellow ? ConsoleColor.White : ConsoleColor.Yellow; break; }
   return newc; }

@BDisp
Copy link
Collaborator

BDisp commented May 26, 2023

.Focus would just swap background and foreground:

Normally inverted colors is used for selection, like used in TextField and TextView. Usually it can be fg = other color; bg = Normal Fore;

@Nutzzz
Copy link
Contributor

Nutzzz commented May 26, 2023

Normally inverted colors is used for selection, like used in TextField and TextView. Usually it can be fg = other color; bg = Normal Fore;

I was hoping to limit the number of accent colors to compute, but that's true.

@tig
Copy link
Collaborator Author

tig commented Aug 9, 2023

See PowerShell/ConsoleGuiTools#211

This request argues for being able to use PowerShell's $PSSytyle as a source for settings.

@tig tig changed the title Colors: ColorSchemes should honor terminal color settings Colors: ColorSchemes refactor - Should honor terminal color settings etc... Jan 13, 2024
@tig
Copy link
Collaborator Author

tig commented Jan 14, 2024

Proposal for expanded ColorScheme members

(Just notes for now - please ignore)

  • Normal - The attribute for normal text in a view when the view has focus.
  • NormalNotFocused - The attribute for normal text when the view has the focus.
  • Hot - The attribute for text in a focused view that indicates aa hot key or shortcut.
  • HotNotFocused - The attribute for text in a non-focused view that indicates a hot key or shortcut.
  • Selected - The attribute for text of something selected in a focused view.
  • SelectedNotFocused - The attribute for text of something selected in a not focused view.
  • Editable - The attribute for normal text in a view when the view has focus.
  • EditableNotFocused - The attribute for normal text when the view has the focus.
  • Disabled - The default foreground and background color for text when the view is disabled. Also used for normally editable content that is readonly.

@tig
Copy link
Collaborator Author

tig commented Jan 30, 2024

Relevant / informational:

https://chadaustin.me/2024/01/truecolor-terminal-emacs/

@dodexahedron
Copy link
Collaborator

I think I mentioned it in the color discussion I started but in the spirit of that link, I'll link this project here, as well, as a potential resource for whatever we end up with:

https://github.com/koszeggy/KGySoft.Drawing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v2 For discussions, issues, etc... relavant for v2
Projects
Status: 📋 Approved - Need Owner
Status: 📋 Approved - Need Owner
Development

No branches or pull requests

4 participants