Skip to content

8354795: DialogPane show details button wipes out base style class "hyperlink" #1779

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

hjohn
Copy link
Collaborator

@hjohn hjohn commented Apr 16, 2025

The "show details" hyperlink button in an alert dialog that has an expandable detail area wipes out its base style class by overwriting all styles. This means styling in modena.css that targets .hyperlink is no longer applied, like the default text fill colors.

The culprit is this code in DialogPane:

    InvalidationListener expandedListener = o -> {
        final boolean isExpanded = isExpanded();
        detailsButton.setText(isExpanded ? lessText : moreText);
        detailsButton.getStyleClass().setAll("details-button", (isExpanded ? "less" : "more")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    };

Here it uses setAll to set styles, wiping out the default .hyperlink style from "Hyperlink detailsButton = new HyperLink()"


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed (2 reviews required, with at least 1 Reviewer, 1 Author)

Issue

  • JDK-8354795: DialogPane show details button wipes out base style class "hyperlink" (Bug - P4)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jfx.git pull/1779/head:pull/1779
$ git checkout pull/1779

Update a local copy of the PR:
$ git checkout pull/1779
$ git pull https://git.openjdk.org/jfx.git pull/1779/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 1779

View PR using the GUI difftool:
$ git pr show -t 1779

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jfx/pull/1779.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Apr 16, 2025

👋 Welcome back jhendrikx! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Apr 16, 2025

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk openjdk bot changed the title JDK-8354795 DialogPane show details button wipes out base style class "hyperlink" 8354795: DialogPane show details button wipes out base style class "hyperlink" Apr 16, 2025
@openjdk openjdk bot added the rfr Ready for review label Apr 16, 2025
@mlbridge
Copy link

mlbridge bot commented Apr 16, 2025

Webrevs

@kevinrushforth
Copy link
Member

/reviewers 2

@openjdk
Copy link

openjdk bot commented Apr 16, 2025

@kevinrushforth
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 2 (with at least 1 Reviewer, 1 Author).

detailsButton.setText(isExpanded ? lessText : moreText);
detailsButton.getStyleClass().setAll("details-button", (isExpanded ? "less" : "more")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
};
styleClasses.add("details-button"); //$NON-NLS-1$
Copy link
Contributor

Choose a reason for hiding this comment

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

do we use these //$NON-NLS-1$ in jfx?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I do not know if we do, as there is also non-public code that I don't have access to. I've kept them as-is to make sure the change is focused and doesn't break anything else.

If I had to guess then probably not, if you can ask around and find out I'll be happy to remove them.

Copy link
Contributor

@andy-goryachev-oracle andy-goryachev-oracle Apr 16, 2025

Choose a reason for hiding this comment

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

I'll double check and will let you know tomorrow.

A code search shows that these are only used in 5 classes: ButtonBar, ButtonBarSkin, Dialog, DialogPane, Properties, so chances are it's a digital fossil.

Copy link
Contributor

Choose a reason for hiding this comment

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

I can confirm that we don't use these //$NON-NLS-* comments in javaFX.

<rant>
These comments were invented as a way to solve the localization problem. The problem is real, but the "solution" was exactly the opposite. Instead of marking the strings that don't need to be localized, what should have happened is to mark the string that need to be localized - with the information containing the context!

example:

// verb, as in "execute this test"
String run = "Run";

What I've done with some other projects was

String run = TXT.get("Class.LocalizedResourceID.verb, as in execute this test", "Run");

</rant>

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Okay, I can remove them.

Copy link
Contributor

Choose a reason for hiding this comment

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

line 822 should be

styleClasses.setAll("details-button");

@andy-goryachev-oracle
Copy link
Contributor

andy-goryachev-oracle commented Apr 16, 2025

An SCCE would have been nice, to help with the review/testing.

edit: alternatively, I'll add the (missing) Dialog/DialogPane page to the monkey tester.
🐒🔬

@hjohn
Copy link
Collaborator Author

hjohn commented Apr 16, 2025

An SCCE would have been nice, to help with the review/testing.

edit: alternatively, I'll add the (missing) Dialog/DialogPane page to the monkey tester. 🐒🔬

If you still need one, I can provide a bit of code. It basically is just changing the hyperlink style, and then seeing it doesn't affect the Alert dialog when it has an extended area. After the change, it should affect it. I did include a screenshot -- I may find more of these bugs as I continue developing with modena.css with dark theme colors :)

@andy-goryachev-oracle
Copy link
Contributor

If you still need one, I can provide a bit of code.

Thanks, that's ok, I would rather add the Dialog page to the MT, as it will allow for more extensive testing.

@andy-goryachev-oracle
Copy link
Contributor

I've added the Dialog page to the monkey tester
https://github.com/andy-goryachev-oracle/MonkeyTest

Looking at the stock behavior, I don't really see the problem. The .details-button should not look a hyperlink (despite being implemented using Hyperlink control), so the code seems to be correct in that it replaces the hyperlink style with something else.

What we probably need for the dark mode is to update the stylesheet as you described in the ticket.

What do you think?

@andy-goryachev-oracle
Copy link
Contributor

Screenshot 2025-04-17 at 08 59 10

@hjohn
Copy link
Collaborator Author

hjohn commented Apr 17, 2025

I've added the Dialog page to the monkey tester https://github.com/andy-goryachev-oracle/MonkeyTest

Looking at the stock behavior, I don't really see the problem. The .details-button should not look a hyperlink (despite being implemented using Hyperlink control), so the code seems to be correct in that it replaces the hyperlink style with something else.

What we probably need for the dark mode is to update the stylesheet as you described in the ticket.

What do you think?

I think it should look like a hyperlink, as the choices of potential clickable controls that users will recognize as such is limited; it can be either a button, checkbox or hyperlink. You can't just define something new and expect users to understand it at a glance; and why even do so for an alert dialog? This is clearly intended to mimic other standard alert dialogs that use the same kind of button to display details.

There are so many things dependent on the base style in modena, not having a base style is highly unusual and in this case IMHO a clear mistake in how the styles are being applied. It just wasn't caught in testing as the default color matches close enough, but becomes rather obvious when changing the base colors significantly.

@andy-goryachev-oracle
Copy link
Contributor

I think it should look like a hyperlink

It might look like a hyperlink, but it has a different semantics (semantics of a hyperlink is to navigate to some other place). When application wants to change the hyperlink styling, we don't want this to propagate to unrelated controls such as dialog buttons, or we get this:

https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExN29yNmd3dGRlNW0wNXMxaWpmM25pdTUyOGZrcmV1dm9oemFkaWZucSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/13FrpeVH09Zrb2/giphy.gif

@hjohn
Copy link
Collaborator Author

hjohn commented Apr 17, 2025

In Windows, and also our color chooser, hyperlinks are used with some regularity to avoid a button where it would look out of place -- in small windows, buttons often are seen as a "closing" action, which show details clearly is not intended to be. The Windows copy dialog for example has a show details text that's clickable, and when keyboard focused displays the classic hyperlink dashed rectangular border.

I've looked in FX code, and wiping out the base style is AFAICS not done anywhere. There are of course many cases of getStyleClass().setAll( ... ) but all of the ones I checked do this on non-Controls (StackPane most often). The big difference here is that such containers like StackPane don't have a default style so there is nothing that would be overwritten. Only controls have these, and wiping it out is, and I'm repeating myself, highly unusual as it will kill many lines of default styling in modena leaving you to have to repeat all those lines. That didn't happen, and neither was this code commented as "intentionally removing the default style class for this control".

If this indeed was the intent, then it would have made much more sense to not wipe out the base style, and only make adjustments specifically for hyperlinks that are also styled with .details-button.

@mstr2
Copy link
Collaborator

mstr2 commented Apr 17, 2025

It seems a bit unusual to remove the default style class of a control. If you use a Hyperlink control, you also want the result to be hyperlinky and inherit all the hyperlinky styles. This is probably the reason why this control was used here in the first place.

If you don't want your control to be hyperlinky (and also not buttony), the cleaner solution would be to not use Hyperlink, but derive a new control from the look-less ButtonBase instead, which doesn't come with default styling.

@andy-goryachev-oracle
Copy link
Contributor

If you use a Hyperlink control, you also want the result to be hyperlinky and inherit all the hyperlinky styles

not necessarily, if you want all the functionality but different visuals.

BTW, the circular button in the DialogPane looks nothing like other modena buttons. I suspect the code was transplanted from some other project. May be the DialogPane should have used the TitledPane for the expandable content, to be visually consistent with the rest of javaFX?

In any case, I think it is wrong to retain the hyperlink style in this case. What I agree with is that it should not use setAll() to wipe out the existing styles, because the createDetailsButton() is a protected method and the application can override it to set some other base style.

So my suggestion would be:

  • remove the hyperlink style
  • set details-button style
  • add/remove less/more styles as proposed in this PR

@mstr2
Copy link
Collaborator

mstr2 commented Apr 17, 2025

If you use a Hyperlink control, you also want the result to be hyperlinky and inherit all the hyperlinky styles

not necessarily, if you want all the functionality but different visuals.

Yes, but the only thing Hyperlink adds from a functionality standpoint is the visited property, and that's not even used in this case.

@andy-goryachev-oracle
Copy link
Contributor

visited property,

agree. 2014 was like, ten thousand years ago ;-)

@hjohn
Copy link
Collaborator Author

hjohn commented Apr 18, 2025

If you use a Hyperlink control, you also want the result to be hyperlinky and inherit all the hyperlinky styles

not necessarily, if you want all the functionality but different visuals.

BTW, the circular button in the DialogPane looks nothing like other modena buttons. I suspect the code was transplanted from some other project. May be the DialogPane should have used the TitledPane for the expandable content, to be visually consistent with the rest of javaFX?

In any case, I think it is wrong to retain the hyperlink style in this case. What I agree with is that it should not use setAll() to wipe out the existing styles, because the createDetailsButton() is a protected method and the application can override it to set some other base style.

So my suggestion would be:

  • remove the hyperlink style
  • set details-button style
  • add/remove less/more styles as proposed in this PR

So... you want me to add more styles so it then ends up looking like a correctly colored hyperlink?

Wouldn't it be easier to do this the other way around, leave the hyperlink style, then apply any specific styling that is needed to make a details-button?

@andy-goryachev-oracle
Copy link
Contributor

So... you want me to add more styles so it then ends up looking like a correctly colored hyperlink?

No. I would like to retain the existing functionality where the styles alternate between
[ "details-button", "less" ] and [ "details-button", "more" ]

If you look at the existing code, the setAll() in line 825 gets invoked at the moment the details button is created because the listener gets called in line 829.

So basically, your new code needs one change in (new) line 822:

styleClasses.setAll("details-button");

the rest is good.

@hjohn
Copy link
Collaborator Author

hjohn commented Apr 24, 2025

So... you want me to add more styles so it then ends up looking like a correctly colored hyperlink?

No. I would like to retain the existing functionality where the styles alternate between [ "details-button", "less" ] and [ "details-button", "more" ]

If you look at the existing code, the setAll() in line 825 gets invoked at the moment the details button is created because the listener gets called in line 829.

So basically, your new code needs one change in (new) line 822:

styleClasses.setAll("details-button");

the rest is good.

Then we can close this, as that's what the original code does already.

@andy-goryachev-oracle
Copy link
Contributor

Then we can close this, as that's what the original code does already.

Exactly (but I like the changes you made to add/remove "more"/"less" styles, since they won't erase any styles that the application might add during construction).

Let me ask about the original problem, which I read is difficulty to implement the dark theme. Should we make any changes to modena.css in this PR instead (with or without the style manipulation)?

@hjohn
Copy link
Collaborator Author

hjohn commented Apr 24, 2025

Then we can close this, as that's what the original code does already.

Exactly (but I like the changes you made to add/remove "more"/"less" styles, since they won't erase any styles that the application might add during construction).

The details button is private and not documented, so it is hard to reach, and even if you could it would be unsupported.

Let me ask about the original problem, which I read is difficulty to implement the dark theme. Should we make any changes to modena.css in this PR instead (with or without the style manipulation)?

The only change needed is to not wipe out the hyperlink style, then it will correctly follow the Modena specified colors which can be set to support a dark theme, see here how I do that:

.root {
    -fx-accent: #165693;
    -fx-focus-color: -fx-accent;
    -fx-base: #16181c;
    -fx-background: #22252b;
    -fx-control-inner-background: derive(-fx-base, 20%);
    -fx-control-inner-background-alt: -fx-control-inner-background;

    -fx-outer-border: derive(-fx-color, 23%);
    -fx-selection-bar-non-focused: -fx-base;

    /* Lighter than -fx-background and used to provide a small highlight when
     * needed on top of -fx-background. This is never a shadow in Modena but
     * keep -fx-shadow-highlight-color name to be compatible with Caspian.
     */
    -fx-shadow-highlight-color: ladder(
        -fx-background,
        rgba(0,0,0,0.07) 0%,
        rgba(0,0,0,0.07) 20%,
        rgba(0,0,0,0.07) 70%,
        rgba(0,0,0,0.7) 90%,
        rgba(0,0,0,0.75) 100%
      );

    /* A gradient that goes from a bit lighter than -fx-color on the top to
     * a little darker at the bottom.  Typically is the third color in the
     * -fx-background-color list as a thin highlight inside the outer border.
     * Insets are typically 1.
     */
    -fx-inner-border: linear-gradient(to bottom,
                ladder(
                    -fx-color,
                    derive(-fx-color,-30%) 0%,
                    derive(-fx-color,-20%) 40%,
                    derive(-fx-color,-25%) 60%,
                    derive(-fx-color,-55%) 80%,
                    derive(-fx-color,-55%) 90%,
                    derive(-fx-color,-75%) 100%
                ),
                ladder(
                    -fx-color,
                    derive(-fx-color,-20%) 0%,
                    derive(-fx-color,-10%) 20%,
                    derive(-fx-color,-5%) 40%,
                    derive(-fx-color,2%) 60%,
                    derive(-fx-color,5%) 100%
                ));
}

This can be combined with a native API call (on Windows) to give your Window a dark title bar as well (if you want that code, let me know).

Because the style is wiped out however, I have to work-around it and copy the hyperlink styles specifically for details-button, like so:

/* copied from .hyperlink styles for each pseudo state */
.dialog-pane > .button-bar > .container > .details-button {
    -fx-text-fill: -fx-accent;
}
.dialog-pane > .button-bar > .container > .details-button:armed,
.dialog-pane > .button-bar > .container > .details-button:visited,
.dialog-pane > .button-bar > .container > .details-button:hover:armed {
    -fx-text-fill: -fx-text-background-color;
}

@andy-goryachev-oracle
Copy link
Contributor

The details button is private and not documented

it is not private: the method that creates it in the DialogPane:817 is protected, so the application can override it and get a pointer to the button, set styles, etc.

protected Node createDetailsButton()

@andy-goryachev-oracle
Copy link
Contributor

I have to work-around it and copy the hyperlink styles specifically for details-button

Adding these styles to modena.css seems to be a better fix. What do you think?

@hjohn
Copy link
Collaborator Author

hjohn commented Apr 25, 2025

The details button is private and not documented

it is not private: the method that creates it in the DialogPane:817 is protected, so the application can override it and get a pointer to the button, set styles, etc.

protected Node createDetailsButton()

Sorry, I missed that. So its returning a Hyperlink that has been mangled to not be a hyperlink anymore.

Adding these styles to modena.css seems to be a better fix. What do you think?

Unfortunately, I think we're going in circles now. I've already given my opinion on this several times and how to most correctly resolve this.

Anyone else have an opinion on how this should be resolved?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rfr Ready for review
Development

Successfully merging this pull request may close these issues.

4 participants