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

Fixes #2114. Adds View.ShadowStyle - Enabled but not turned on by default #3376

Merged
merged 71 commits into from
Jun 26, 2024

Conversation

tig
Copy link
Collaborator

@tig tig commented Apr 2, 2024

Fixes

Todo

  • Extend Margin to have a "Shadow" Style - When enabled draws the correct half-height block glyphs in the right places
  • Extend HighlightStyle to support shadow animation on Pressed
  • Enable Button to use Margin.EnableShadow
  • Figure out how to make Button with shadow work reliably and automatically.
  • Figure out how to have the shadow account for whatever was drawn below. Right now, it blindly overwrites and thus doesn't look right in some situations. I think the right design is to have Margin.Draw get called by Application, not the View's SuperView.
  • Test & Enable EnableShadow on other Views where it may make sense visually.

Background

When I created Frames (now Adornments) i had a vision that Margin could be used to enable the 3D effect that we had mostly working in v1, but got negated with all the changes to v2.

I had a shower thought recently on this and decided to quickly code a prototype up to see if my instincts were right.

This PR demonstrates that I was. The concept is leveraging Margin like this:

 var button = new Button
 {
     X = Pos.Center (),
     Y = Pos.Center (), Text = "Press me!"
 };
 button.Margin.Thickness = new Thickness (0, 0, 1, 1);
 button.Margin.Add (
                    new View ()
                    {
                        X = Pos.AnchorEnd (1),
                        Y = 1,
                        Width = 1,
                        Height = Dim.Fill (),
                        ColorScheme = new ColorScheme (new Attribute (ColorName.DarkGray))
                    },
                    new View ()
                    {
                        X = 1,
                        Y = Pos.AnchorEnd (1),
                        Width = Dim.Fill(),
                        Height = 1,
                        ColorScheme = new ColorScheme (new Attribute (ColorName.DarkGray))
                    }
                    );

 bool pressed = false;
 button.Accept += (s, e) =>
                  {
                      pressed = !pressed;

                      if (pressed)
                      {
                          button.Margin.Thickness = new Thickness (1, 1, 0, 0);
                      }
                      else
                      {
                          button.Margin.Thickness = new Thickness (0, 0, 1, 1);
                      }
                  };

XZjxkvE 1

Pull Request checklist:

  • I've named my PR in the form of "Fixes #issue. Terse description."
  • My code follows the style guidelines of Terminal.Gui - if you use Visual Studio, hit CTRL-K-D to automatically reformat your files before committing.
  • My code follows the Terminal.Gui library design guidelines
  • I ran dotnet test before commit
  • I have made corresponding changes to the API documentation (using /// style comments)
  • My changes generate no new warnings
  • I have checked my code and corrected any poor grammar or misspellings
  • I conducted basic QA to assure all features are working

@tig
Copy link
Collaborator Author

tig commented May 21, 2024

Latest:

Vqghso7 1

It's this easy:

        var button = new Button
        {
            X = Pos.Center (),
            Y = Pos.Center (), Text = "Press me!",
        };
        button.Margin.Shadow = true;

Of course, the animation will only work on WindowsDriver, because it's the only one that supports distinct mouse up/down events.

@tig tig changed the title 3D Effect Prototype (may Fix #2144). Fixes #2114. 3D Effect May 21, 2024
@tig
Copy link
Collaborator Author

tig commented May 22, 2024

Latest

  • Enables Window.DefaultShadow and Button.DefaultShadow to be configured via Config Manager.
  • The UI Catalog theme sets both to true.
  • AdornmentsEditor now has a Shadow checkbox

xT7e2hE 1

(Since the Default theme doesn't explicitly set either they stay set even after changing back to the Default theme).

@tig
Copy link
Collaborator Author

tig commented May 26, 2024

@dodexahedron Can you please look at this PR and help me out? I mentioned a similar issue the other day.

This PR was originally rebased with #3415.

#3415 was just merged into v2_develop.

I then rebased this PR on to v2_develop

v2_2144-3D-effect> git rebase --onto v2_develop
v2_2144-3D-effect> git pull
v2_2144-3D-effect> git push
Everything up-to-date

However, if you look at the "Files Changed" in this PR on Github it is comparing to an old v2_develop. For example, it things Aligner.cs is a new file:

image

I am sure I'm doing something wrong with how I'm rebasing. Do you see anything?

@tig
Copy link
Collaborator Author

tig commented May 26, 2024

FWIW, here's how "AdornmentEditor" has evolved in this PR.

Note the new "Expander" on the Border.

y0uGNZO 1

@tig
Copy link
Collaborator Author

tig commented May 27, 2024

@dodexahedron did you see my question to you above?

@tig
Copy link
Collaborator Author

tig commented May 27, 2024

This illustrates an issue with my current design here:

OXKUNLd 1

Need to figure out how to have the shadow account for whatever was drawn below. Right now, it blindly overwrites and thus doesn't look right in some situations. I think the right design is to have Margin.Draw get called by Application, not the View's SuperView.

tig added a commit to tig/Terminal.Gui that referenced this pull request May 27, 2024
tig added a commit to tig/Terminal.Gui that referenced this pull request May 27, 2024
@dodexahedron
Copy link
Collaborator

That's kinda been a long-standing conundrum, hasn't it?

What order to draw things in, I mean.

Since we don't have an explicit concept of Z index, it's all just order dependent, which is something that can change at runtime as views are created and destroyed.

As far as what color to use, I've got blend code that's aimed at true color but works for lame color too. I may have even put at least some of it in when I did that work on the Color type a while back. 🤔

@tig tig marked this pull request as ready for review June 25, 2024 20:18
@tig
Copy link
Collaborator Author

tig commented Jun 25, 2024

I have these effects turned off by default and plan on merging it that way...

Why? Because we have so many fragile unit tests that can't deal with

a) Button not being 1 row high.
b) Margin.Thickness != Empty.

Same thing goes for BorderStyle != Single.

Please, please, please, lets not write any more unit tests that depend on visual styling and if you're in a unit test as part of a PR that does this re-write it!

@tig tig requested a review from BDisp June 25, 2024 20:56
@tig tig changed the title Fixes #2114. 3D Effect Fixes #2114. Adds View.ShadowStyle - Enabled but not turned on by default Jun 25, 2024
Copy link
Collaborator

@BDisp BDisp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work.

@tig
Copy link
Collaborator Author

tig commented Jun 26, 2024

Off by default, but both the UI Catalog and NEW Hot Dog Stand themes enable for Button and Dialog.

IobTegt 1

@tig tig merged commit 61699d6 into gui-cs:v2_develop Jun 26, 2024
1 check passed
Copy link
Collaborator

@dodexahedron dodexahedron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A tip for test cases you need to skip.

// " C 0 A "
[InlineData (-1, 0, 0)]
[InlineData (0, 1, 1)]
[InlineData (1, 0, 1)] // BUGBUG: This should be 1,1,1. We need to fix the logic in the Shortcut class.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned here (re-posting here in case the commit comment is not easily visible):

tig@5cf556c#r143586671

When you want to skip a test temporarily, feed a string to the Skip property, in the attribute constructor, as shown below and in the linked commit comment.

It's something attribute constructors can do that normal ones can't, and is basically like using an initializer.

For this one, this code, instead of the line with the comment and altered data to make it pass, will instead skip and print a message, without failing and without having to feed it a fake value that may or may not continue to pass if other things change:

[InlineData (1, 1, 1, Skip = "// BUGBUG: We need to fix the logic in the Shortcut class.")]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And it doesn't lie about the test results, either. 😅

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that was there til just when I looked at this.

But it occurred to me that NUnit has that capability, and it isn't exactly an uncommon thing to need to do, so surely xUnit must have it?

And sure enough, it does. :)

Copy link
Collaborator

@dodexahedron dodexahedron Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, you know what?

I'll make a tag for the todo list specifically for skipped tests that looks for something like

\[\((?:.*Skip *\= *\")(.*)\" *\)\]

(or whatever I have to tweak that to, to make it just match the string in the actual regex).

That'll give them their own category so they don't add noise to the others.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Booooooo. The ToDo list feature does not support matching in generic code elements, so even though this pattern quite nicely matches the string after a Skip = ", it doesn't work to tag it because it isn't a comment, identifier, or string.

That said, I can just make it look for a specific string in them, like "Skipping".

Oh well.

I'll just let strings match then. Same tags available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants