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

Small improvements to the “Show parent folder name in tab title” option #7930

Merged

Conversation

troizet
Copy link
Collaborator

@troizet troizet commented Oct 31, 2024

Small improvements to the “Show parent folder name in tab title” option:

  • parent folder name is displayed in opened documents list;
  • parent folder name is displayed in a different color from the file name.

Before:
before_2

After:
after_3

After dark theme:
after_dark_3

@troizet troizet added UI User Interface Platform [ci] enable platform tests (platform/*) labels Oct 31, 2024
@troizet troizet requested a review from mbien November 6, 2024 11:04
@mbien
Copy link
Member

mbien commented Nov 7, 2024

I think visually distinguishing file name from path could be useful, but it will be probably tricky to find a color which works on active/inactive tabs for both light and dark themes. (e.g the FlatLaf light screenshot is a bit hard to read for me at least)

The test output window reduces the contrast for less important stack frames for example (#6695 has screenshots).

This is how it computes the color:

private static String hiddenColor() {
// note: the tree adjusts the color automatically if the contrast is too low
// which would have the opposite effect of what we are trying to achieve here
float a = 0.6f;
Color f = UIManager.getColor("Tree.foreground");
Color b = UIManager.getColor("Tree.background");
return String.format("#%02x%02x%02x",
(int)(b.getRed() + a * (f.getRed() - b.getRed())),
(int)(b.getGreen() + a * (f.getGreen() - b.getGreen())),
(int)(b.getBlue() + a * (f.getBlue() - b.getBlue())));
}

It does also use the colors from the actual component as input instead of using a hardcoded value.

@mbien
Copy link
Member

mbien commented Nov 7, 2024

It does also use the colors from the actual component as input instead of using a hardcoded value.

btw If you can't access the actual tab component, this might help to figure out what the key is - if it has one:

    UIManager.getLookAndFeelDefaults().entrySet().stream()
            .filter( t -> t.getValue() instanceof Color)
            .sorted((o1, o2) -> o1.getKey().toString().compareTo(o2.getKey().toString()))
            .forEach(t -> System.out.println(t.getKey()+ ": " + t.getValue()));

@troizet troizet force-pushed the improvements_show_parent_folder_name_in_tab_title branch from 1591db6 to 7136c44 Compare November 16, 2024 17:30
@troizet
Copy link
Collaborator Author

troizet commented Nov 16, 2024

@mbien thanks for the example. Made the changes and updated the screenshots.

@mbien
Copy link
Member

mbien commented Dec 5, 2024

html-color-invert

what you see here is the html renderer noticing that the contrast is too low and trying to fix it to set the color to the complementary white or black. This is the opposite of what the intention is since it is now highlighting the folder instead of the file.

As previously mentioned the tricky part is to make it work on different background / foregrounds - its used on different components and component states.

I reduced the fade value to 0.7f and computed it for the tabs and tabs-switcher separately, since both have different colors.

faded-folders

Tested on all supported themes and it looks ok I think. The "same background color for same projects" mode is still not working very well, esp on dark themes, but making both decorators work well together won't be easy.

here the commit c4ea291, feel free to squash it with your PR

@troizet troizet force-pushed the improvements_show_parent_folder_name_in_tab_title branch from 7136c44 to 8fa82e7 Compare December 8, 2024 07:31
@troizet
Copy link
Collaborator Author

troizet commented Dec 8, 2024

@mbien, thank you so much for your help!
Sorry, git rebase did not save your authorship. Can you tell me how to get this information back?

@mbien
Copy link
Member

mbien commented Dec 8, 2024

@mbien, thank you so much for your help! Sorry, git rebase did not save your authorship. Can you tell me how to get this information back?

@troizet not a problem with me. But you can add co-authors to commits by appending this to the commit message:

bla bla bla.

Co-authored-by: Duke <[email protected]>

https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors

@troizet troizet force-pushed the improvements_show_parent_folder_name_in_tab_title branch from 8fa82e7 to 913d29c Compare December 8, 2024 13:50
@troizet
Copy link
Collaborator Author

troizet commented Dec 8, 2024

@mbien, thank you!
Updated the commit and rebased to the latest master.

@mbien mbien added the ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) label Jan 6, 2025
@mbien
Copy link
Member

mbien commented Jan 6, 2025

@troizet while looking through other code, I noticed NB has a boolean property for dark themes, we can use that for having a different blend value based on dark/light themes:

diff --git a/platform/core.multitabs/src/org/netbeans/core/multitabs/impl/FolderNameTabDecorator.java b/platform/core.multitabs/src/org/netbeans/core/multitabs/impl/FolderNameTabDecorator.java
index 421cdc9..f1a64fd 100644
--- a/platform/core.multitabs/src/org/netbeans/core/multitabs/impl/FolderNameTabDecorator.java
+++ b/platform/core.multitabs/src/org/netbeans/core/multitabs/impl/FolderNameTabDecorator.java
@@ -124,10 +124,14 @@
     }
 
     private String fadeColor(Color f, Color b) {
-        float a = 0.7f;
+        float a = isDarkLaF() ? 0.7f : 0.6f;
         return String.format("#%02x%02x%02x", //NOI18N
                  (int)(b.getRed()   + a * (f.getRed()   - b.getRed())),
                  (int)(b.getGreen() + a * (f.getGreen() - b.getGreen())),
                  (int)(b.getBlue()  + a * (f.getBlue()  - b.getBlue())));
     }
+    
+    private static boolean isDarkLaF() {
+        return UIManager.getBoolean("nb.dark.theme"); //NOI18N 
+    }
 }

I could force push into this PR if you want since I have it locally already anyway.

@troizet
Copy link
Collaborator Author

troizet commented Jan 7, 2025

I could force push into this PR if you want since I have it locally already anyway.

Yes, please do. Thank you!

@mbien mbien force-pushed the improvements_show_parent_folder_name_in_tab_title branch from 913d29c to 2a6a4f0 Compare January 7, 2025 17:39
@mbien mbien added this to the NB25 milestone Jan 15, 2025
@mbien
Copy link
Member

mbien commented Jan 16, 2025

I do like this, however, the main reason I am reluctant to approve this is because this might make the "colored tabs" situation worse (#8029).

image

we probably should wait with this until we have an idea how to fix the colored tabs? cc @neilcsmith-net @eirikbakke

edit: or we could simply not apply the contrast reduction to the parent folder if colored tabs are enabled?
edit2: we could also slightly increase the foreground color on the dark theme to get more wiggle room e.g @foreground=#d1d1d1
edit3: the dropdown background should probably be the same color of context menus?

image

@eirikbakke
Copy link
Contributor

eirikbakke commented Jan 17, 2025

we probably should wait with this until we have an idea how to fix the colored tabs?

You can usually make text blend in with any background color by using transparency (alpha channel) instead of reduced saturation. For example, to make 50% "grey" text, you would use black with 50% transparency on light themes, and white with 50% transparency on dark themes. I.e. use #FFFFFF88 and #00000088 instead of #888888FF.

(If that works, we don't have to wait for improvements in the background color before making improvements to the text color.)

@mbien
Copy link
Member

mbien commented Jan 20, 2025

@eirikbakke I don't think the html renderer supports alpha. It seems to ignore the fourth value even if I set it to 0.

(the underlying issue is that the contrast is already so low, that blending it will make it hard to read on some components, esp when features like colored tabs come in and swap out the background without adjusting the foreground color - but using alpha would be still nice)

@eirikbakke
Copy link
Contributor

@mbien Alpha blending might be useful enough to make HtmlRenderer.findColor aware of it. It saves clients from having to query and blend background colors themselves.

@mbien mbien force-pushed the improvements_show_parent_folder_name_in_tab_title branch from 2a6a4f0 to 013a28c Compare January 21, 2025 20:55
Comment on lines -57 to +89
String folderName = folder.getNameExt() + pathSeparator;
String defaultText = tab.getText();

return merge( folderName, defaultText );
String folderName = folder.getNameExt() + File.separator;
// don't use faded colors in tabs when colored tabs are active
// since it is difficult to get right with so many colors and shades involved
// the switcher uses a line as marker instead of bg change and can continue using fade colors
if (!(isTab && settings.isSameProjectSameColor())) {
folderName = "<font color=\"" + fadeColor + "\">" + folderName + "</font>"; //NOI18N
}
return merge(folderName, tab.getText());
Copy link
Member

@mbien mbien Jan 21, 2025

Choose a reason for hiding this comment

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

the path decoration will now disable itself on tabs if colored tabs are active, the switcher will keep using the faded color since its colored tabs impl is different

an attempt to fix some contrast problems mentioned in #7930 (comment) is pending at #8175

Copy link
Member

Choose a reason for hiding this comment

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

project tab colors off:
image

project tab colors on:
image

@mbien mbien force-pushed the improvements_show_parent_folder_name_in_tab_title branch from 013a28c to 892234d Compare January 21, 2025 21:00
- parent folder name is displayed in opened documents list
- parent folder name is displayed in a different color from the file name

Co-authored-by: Michael Bien <[email protected]>
@mbien
Copy link
Member

mbien commented Jan 22, 2025

rebasing on top of #8175

@mbien mbien force-pushed the improvements_show_parent_folder_name_in_tab_title branch from 892234d to ad776db Compare January 22, 2025 16:12
@neilcsmith-net
Copy link
Member

As I was asked for review, I'm not going to request changes (at least at this point), but I think the approach to colouring is wrong and over complicated. We should be looking to move all colouring code like this out of components. This should be a UI key. Something like a tab secondary foreground colour, that can use FlatLaf support for mixing and contrast, and the defaults on other LaFs. And would also ideally be used for the problematic versioning info.

@neilcsmith-net neilcsmith-net removed their request for review January 23, 2025 09:37
@eirikbakke
Copy link
Contributor

eirikbakke commented Jan 23, 2025

@neilcsmith-net Your main objection is with the fadeColor method that has a hard-coded alpha value in it, right?

Is there any reason the alpha value cannot come from one of the parameterized Color instances instead?

Here is a more general "blend" function that takes alpha values into account, in the same way as when you paint one semitransparent color on top of a solid (or itself semitransparent) background color:

public static Color blendOver(final Color src, final Color dest, float extraSourceAlpha) {
  Preconditions.checkArgument(extraSourceAlpha >= 0.0f && extraSourceAlpha <= 1.0f);
  // Small optimization.
  if (src.getAlpha() == 0 || extraSourceAlpha == 0.0f)
    return dest;
  /* Based on the formulas from the Porter and Duff paper, as presented in the Javadoc for
  java.awt.AlphaComposite. */
  // "The 'extra' alpha component from the AlphaComposite instance"
  final float Aac = extraSourceAlpha;

  final float Csr[] = src.getRGBComponents(null);
  final float Cdr[] = dest.getRGBComponents(null);
  final float Asr = Csr[3];
  final float Adr = Cdr[3];

  final float As = Asr * Aac;
  final float Ad = Adr;

  // Use the functions for SRC_OVER.
  final float Fs = 1.0f;
  final float Fd = 1.0f - As;

  final float Ar = As * Fs + Ad * Fd;
  final float Adf = Ar;

  // Avoid division by zero below.
  if (Adf == 0.0f)
    return new Color(0, 0, 0, 0);

  final float Cdf[] = new float[3];
  for (int i = 0; i < 3; i++) {
    /* The zero check ensures correct behavior in the case of a zero-alpha Color with NaN color
    components. */
    final float Cs = (As == 0.0f) ? 0.0f : Csr[i] * As;
    final float Cd = (Ad == 0.0f) ? 0.0f : Cdr[i] * Ad;
    final float Cr = Cs * Fs + Cd * Fd;
    Cdf[i] = Cr / Ar;
  }
  return new Color(Cdf[0], Cdf[1], Cdf[2], Adf);
}

If useful, I could add it to org.openide.util.Utilities. I've been using it for several years.

@neilcsmith-net
Copy link
Member

@neilcsmith-net Your main objection is with the fadeColor method that has a hard-coded alpha value in it, right?

No, my main objection is that the faded colour is not coming from a UI key (ideally a shared one), probably with a suitable fallback to an existing key. That could be looked at for NB 26.

I have a whole bunch of similar blending code functions I could contribute. But so does FlatLaf, and I firmly believe this belongs in the LaF configuration. LaFs without overridable accent colours, etc. can have a fixed value / use an existing key anyway. Think separation of concerns like HTML and CSS.

@eirikbakke
Copy link
Contributor

eirikbakke commented Jan 23, 2025

@neilcsmith-net I agree, it's always nice to have these constants separated out. Though often it can be useful to experiment for a bit to figure out what the constants should be and what color differences we need to express, before factoring them out as constants and making them part of an official API contract.

(Though "API contract" probably means a less strong promise of forward compatibility when it comes to cosmetic UI properties, than when it comes to classes and method signatures.)

@mbien
Copy link
Member

mbien commented Jan 23, 2025

No, my main objection is that the faded colour is not coming from a UI key

agreed. see #8175 (comment), as mentioned we will also need a separate value for dark/light themes.

(and it likely won't be just a color or blend factor, it will probably have to be a computed color based on usage conditions, similar to the selection foreground color)

@mbien
Copy link
Member

mbien commented Jan 23, 2025

are there concerns outside of the hardcoded blend function + factors?

Copy link
Contributor

@eirikbakke eirikbakke left a comment

Choose a reason for hiding this comment

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

Tested the latest version on Light and Dark themes, with and without "Show parent folder name in tab title" enabled, and also testing with the "Sort opened documents list by project" in some cases. Nothing breaks or is unreadable in this version. Thanks for the PR!

@mbien mbien merged commit cbfd047 into apache:master Jan 23, 2025
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) Platform [ci] enable platform tests (platform/*) UI User Interface
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants