-
Notifications
You must be signed in to change notification settings - Fork 696
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
Add 3D Shadow Effect for Button
and other views
#2144
Comments
I agree that this would be a great core feature for the library. But in the mean time here is what you can do with the current release and overriding the Button redraw method. using Terminal.Gui;
Application.Init();
var win = new Window("Example App (Ctrl+Q to quit)");
win.Add(new ShadowButton("Button 1"){
X = 2,
Y = 1
});
win.Add(new ShadowButton("Button 2")
{
X = 20,
Y = 1
});
Application.Run(win);
Application.Shutdown();
class ShadowButton : Button
{
public ShadowButton(string text):base(text + " ") /*put a space on to leave 'shadow' room*/
{
Height = 2;
}
public override void Redraw(Rect bounds)
{
// draw regular button
base.Redraw(bounds);
// draw the 'end' button symbol one in
AddRune(bounds.Width - 2,0, ']');
// shadow color
Driver.SetAttribute(new Terminal.Gui.Attribute(Color.Black,
Colors.Base.Normal.Background));
// end shadow (right)
AddRune(bounds.Width - 1, 0, '▄');
// leave whitespace in lower left in parent/default background color
Driver.SetAttribute(new Terminal.Gui.Attribute(Color.Black,
Colors.Base.Normal.Background));
AddRune(0, 1, ' ');
// The color for rendering shadow is 'black' + parent/default background color
Driver.SetAttribute(new Terminal.Gui.Attribute(Colors.Base.Normal.Background,
Color.Black));
// underline shadow
for (int x = 1;x<bounds.Width;x++)
{
AddRune(x,1, '▄');
}
}
} UPDATE: From a little quick experimenting the 'three quarter block' Theres also a little 'bleed' on the right of the button where 1 pixel of terminal is black. Don't know if that is a font thing or a bug in powershell/visual studio console. |
For reference these are the blocks available (not all of which are supported by all terminals) Block elements |
I think setting the |
Button3 uses the Effect3D while Button1 and Button2 use the
Also the win.Add(new Button("Button 3")
{
X = 40,
Y = 1,
Border = new Border
{
Effect3D = true,
Effect3DBrush = new Attribute(Color.Black,Color.Black),
}
}); Heres what the shadows look like when theres a background that isn't just solid color. You can see the eye expects to see half an 'x' where that half shadow ends. |
I have to say the Norton Commander query box in OP does look awesome. I'm getting inspired to ressurect this failed PR in the Designer gui-cs/TerminalGuiDesigner#111 I like the grey/white and yellow/red (focus). |
I agree the Norton style looks great. I'd love to see us tackle a new visual style as part of v2. See #1940 |
The ShadowButton already looks pretty good! If just the 1 pixel black line wasn't there 😑 |
I think printing half of a letter or digit on a terminal is impossible. |
Yeah haha sorry I didn't mean it as a solution. Was just weighing up the pros and cons of each of them. The half height shadow looks wierd when hovering over background stuff but theres not much that can be done about it. I guess if we add it we should make it feature toggle. Thick or thin shadows. As theres not likely to always be a clear 'best' |
Its so wierd! when you zoom in it doesn't get any bigger and it's there on |
I confirm that doesn't appears on "Windows Terminal". Only with Windows Host Console that line artifact appears. |
It only go down on click and not on button pressed. So if you press the mouse button and move it before released, the button click will not be fired. |
How about this? Works with keyboard or mouse because it responds to the Click event not the mouse down. I think it looks a little off since it drops lower than the shadow indicates but I think that is the best your going to get with the limitations of console column height/resolution. Making the shadow thicker will make the buttons look worse. Its also going to be tough for the 'depressed' button to reveal any background View content (at the moment it draws Heres the code: using Terminal.Gui;
using Attribute = Terminal.Gui.Attribute;
Application.Init();
var win = new Window("Example App (Ctrl+Q to quit)");
win.Add(new ShadowButton("Button 1")
{
X = 2,
Y = 1
});
win.Add(new ShadowButton("Button 2")
{
X = 20,
Y = 1
});
win.Add(new Button("Button 3")
{
X = 40,
Y = 1,
Border = new Border
{
Effect3D = true,
Effect3DBrush = new Attribute(Color.Black, Color.Black),
}
});
Application.Run(win);
Application.Shutdown();
class ShadowButton : Button
{
public ShadowButton(string text) : base(text + " ") /*put a space on to leave 'shadow' room*/
{
Height = 2;
}
public bool Depressed { get; private set; }
public override void OnClicked()
{
base.OnClicked();
Depressed = true;
SetNeedsDisplay();
Application.MainLoop.AddTimeout(TimeSpan.FromMilliseconds(500), (m) =>
{
Depressed = false;
Application.MainLoop.Invoke(() =>
{
SetNeedsDisplay();
});
return false;
});
}
public override void Redraw(Rect bounds)
{
if (Depressed)
{
DrawDepressed(bounds);
}
else
{
DrawRegular(bounds);
}
}
private void DrawRegular(Rect bounds)
{
// draw regular button
base.Redraw(bounds);
// draw the 'end' button symbol one in
AddRune(bounds.Width - 2, 0, ']');
// shadow color
Driver.SetAttribute(new Terminal.Gui.Attribute(Color.Black, Colors.Base.Normal.Background));
// end shadow (right)
AddRune(bounds.Width - 1, 0, '▄');
Driver.SetAttribute(new Terminal.Gui.Attribute(Color.Black, Colors.Base.Normal.Background));
AddRune(0, 1, ' ');
Driver.SetAttribute(new Terminal.Gui.Attribute(Colors.Base.Normal.Background, Color.Black));
// underline shadow
for (int x = 1; x < bounds.Width; x++)
{
AddRune(x, 1, '▄');
}
}
private void DrawDepressed(Rect bounds)
{
// area revealed on the background control by pushing Button down
Driver.SetAttribute(
new Terminal.Gui.Attribute(Colors.Base.Normal.Foreground,
Colors.Base.Normal.Background));
// clear top line so button sinks to bottom line
for (int x = 0; x < bounds.Width; x++)
{
AddRune(x,0,' ');
}
// render button as down
Driver.SetAttribute(
HasFocus ?
new Terminal.Gui.Attribute(ColorScheme.Focus.Foreground,
Colors.Base.Focus.Background):
new Terminal.Gui.Attribute(ColorScheme.Normal.Foreground,
Colors.Base.Normal.Background));
var buttonRenderText = TextFormatter.Text;
var textWidth = buttonRenderText.Length;
for (int x = 1; x < textWidth; x++)
{
AddRune(x, 1, buttonRenderText[x-1]);
}
AddRune(textWidth-1, 1, ']');
}
} |
Ah ok sorry, you were meaning about visually effect. |
While googling for Norton Commander button animations I came across this repo: https://github.com/magiblot/tvision - there is a screenshot of a button also showing those vertical lines in the button shadow, but between the shadow blocks. On purpose? Maybe another block type? |
I have sometimes seen those appear when resizing or moving terminal around. I think we shouldn't worry about these artifacts (bleed, seperation lines etc). They are pretty minor and are not really our responsibility to resolve. |
You are right. With |
Sounds reasonable. I'm nevertheless curious how the actual animation looks in either Turbo Vision or Norton Commander. They must have had the same challenges. Couldn't find something so far. |
@tznind and how about only hide the shadows when the button go down, instead of redraw the button bellow? How will be the effect? |
@BDisp Your suggestion looks pretty nice. The button still moves one to the right, giving good visual feedback: ShadowButton.mp4(The gray text appears because I disable the button when being clicked. This might require more tuning with regard to timing.) And the button does not retain its focus color, yet. It flickers, then it's gone. Focus is still on the button, though.
|
Thanks. I almost have an half border implementation in the Border class when the height is equal to 1. I think there is no sense to make it if the width is equal to 1. Let's me know. |
Very nice effect @heinrich-ulbricht . Definetly better than jumping down a line 🎉 |
@tznind Cannot get enough of it :D ShadowButton2.mp4 |
I only removed the shadow but this effects is better. I'm leverage the existing Border class to make it more reused to another views. So, this additional move must be implemented in each view that want to implement it. |
Unfortunately the focus color seems lost after selecting the button. Is this expected in this proof of concept stage or should it be there? |
Just thought I'd mention that we can do this without subclassing using the I know @BDisp is creating a border style that will do most of the drawing work in this. Hopefullly after that, we can create a simple 5/10 line class |
Note: removing the start and end rune from the 3D button seems to reduce the visual noise a bit. Experimenting how it feels. |
Question for y'all: Is it realistic to think this could be done/tested before next Tuesday for inclusion in v1.9.0 (https://github.com/gui-cs/Terminal.Gui/milestone/5)? |
I think it depends on @BDisp availability as his PR #2166 is adding the functionality. I think if we can squeeze it in that would be great as its a great 'killer feature' for the patch. |
I'll try to add at least the functionality to work on whatever border size, but only using the current glyphs, ok? |
The 2588 █ FULL BLOCK isn't print, but it print in the Character Map. @tznind can you test please. Thanks. |
@tig Greetings! You removed this from the v2.0 milestone - is this shadow-for-button feature being scrapped or just included in another feature? |
@heinrich-ulbricht with the new |
@BDisp Wonderful ❤️ |
I'm interested in how it will work in the new API so I had an experiment. You can do this: Application.Init();
var w = new Window();
var btn = new Button("Click me"){
X = 2,
Y = 2
};
btn.Margin.Thickness = new Thickness{
Bottom = 1,
Right = 1,
};
btn.Margin.ColorScheme = new ColorScheme(){
Normal = new Attribute(Color.Black)
};
w.Add(btn);
Application.Run(w);
Application.Shutdown(); But if you want half height effect you need to do a bit more work in Draw. I did try adding draw code to btn.DrawContentComplete += (s,e)=>
{
Application.Driver.SetAttribute(
new Attribute(
Color.Black,
w.ColorScheme.Normal.Background
));
for(int x = 0 ; x <= btn.Margin.Bounds.Width ;x++)
btn.AddRune(x,1,'▀');
}; |
Button
and other views
I am addressing this issue in |
@tig Looking at my older videos above I notice that in those the button just slightly moves to the right, but stays in the same "row", not moving down. At the same time the shadow disappears. Overall this gives the illusion of movement. You chose a different approach and the button moves a "row" down to where the shadow was. Is this a deliberate choice (because it looks better in your eyes), or is there a technical necessity? For my eye it looks more pleasing if the button stays right where the mouse is and doesn't move a "row" down, although this might not be physically correct. Somehow with your approach I expect the mouse cursor to stick to the button and move as well - as it would be when pressing a button with the finger. Hope it's clear what I mean :D |
Much better! Thanks for pointing that out. |
Is your feature request related to a problem? Please describe.
Nope, just feature request I guess
Describe the solution you'd like
I'd like to add buttons like Norton Commander used back in the day. They had a half-height shadow at the bottom. But currently with Terminal.GUI it only seems to be possible to add a full-height shadow at the bottom. This is kind of fat for a small button. The shadow also needs to be set off vertically only half-height (or is it like 1/3?) on the right.
Here's what it should look like:
I looked at all the border samples in UICatalog but did not see such a feature. It might be impossible. Or is there some rune to configure? I'm not so deep in the code.
I'm currently playing around with color schemes and the 3D effect - not very shadowy for a small button:
Describe alternatives you've considered
Using no shadow for buttons.
The text was updated successfully, but these errors were encountered: