JFormDesigner / FlatLaf

FlatLaf - Swing Look and Feel (with Darcula/IntelliJ themes support)
https://www.formdev.com/flatlaf/
Apache License 2.0
3.34k stars 266 forks source link

FlatLaf in WinPE #279

Closed PicoMitchell closed 3 years ago

PicoMitchell commented 3 years ago

My testing app, which uses FlatLaf, is also run within WinPE.

I have noticed some quirks in WinPE which affect FlatLaf. Since this has been such a minor issue with an easy fix on my side (as well as a pretty rare use-case), I haven't bothered filing a report about this stuff up until now.

If dealing with WinPE, is outside of your scope, I totally understand that.

The following comments about the frame and font issues are also within the code block (which I use in my app) that I have included below. There may be more efficient ways of checking for WinPE that I am not aware of as well.

Decorated Frame Issue: In WinPE, FlatLaf Decorated window looks funky (the default left, right, and bottom frames are still shown) and is unnecessary since the default style fits in better with WinPE than the Win 10 Decorated style. NOTE: Prior to FlatLaf 1.1, the whole Decorated frame was drawn correctly, but if the windows was minimized, it could not be restored back from the bottom of the screen when clicking the restore button in the titlebar. I double checked that behavior with FlatLaf 1.1 and that is no longer an issue. I suspect your recent work with a more with the native Decorated titlebar is what fixed that. Still, the default Windows style fits in better in WinPE.

Default Font Issue: The regular "Segoe" system font is not included by default (only bold and italic "Segoe" is included in WinPE), so font Font.PLAIN (when using "Segoe" system font) is rendered as bold, making all text bold. My solution has been to use "Tahoma" in WinPE instead since it is included by default, and looks good. It is possible to install "segoeui.ttf" into "\Windows\Fonts\" in WinPE, but when I tried this it didn't really render very well in WinPE, regular text still looked slightly bold and a little off and "Tahoma" looks better than "Segoe" did. "Microsoft Sans Serif" is also available in WinPE, and doesn't look too bad, but I liked the look of "Tahoma" better (notaably the kerning and letter spacing of bold text).

I will try to grab some screenshots of these issues later today to show you if you don't have easy access to WinPE.

if (isWindows) {
    Boolean isWindowsPE = ((new File("\\Windows\\System32\\startnet.cmd").exists() || new File("\\Windows\\System32\\winpeshl.ini").exists()) && !new CommandReader("reg query HKLM\\SYSTEM\\Setup /v FactoryPreInstallInProgress").getFirstOutputLineContaining("0x1").isEmpty());

    if (isWindowsPE) {
        // In WinPE, FlatLaf Decorated window looks funky (the default left, right, and bottom frames are still shown) and is unnecessary since the default style fits in better with WinPE than the Win 10 Decorated style.
        UIManager.put("TitlePane.useWindowDecorations", false);

        if ((defaultFont == null) || !defaultFont.getFamily().equals("Tahoma")) {
            if (new File("\\Windows\\Fonts\\tahoma.ttf").exists()) {
                // Use "Tahoma" in WinPE because the regular "Segoe" system font is not included by default (only bold and italic "Segoe" is included in WinPE), so font Font.PLAIN (when using "Segoe" system font) is rendered as bold, making all text bold.
                // It is possible to install "segoeui.ttf" into "\Windows\Fonts\" in WinPE, but when I tried this it didn't really render very well in WinPE, regular text still looked slightly bold and a little off and "Tahoma" looks better than "Segoe" did.
                // "Microsoft Sans Serif" is also available in WinPE, and doesn't look too bad, but I liked the look of "Tahoma" better (notaably the kerning and letter spacing of bold text).
                defaultFont = StyleContext.getDefaultStyleContext().getFont("Tahoma", ((defaultFont == null) ? Font.PLAIN : defaultFont.getStyle()), ((defaultFont == null) ? 12 : defaultFont.getSize()));
            } else if (defaultFont != null) {
                // If somehow "Tahoma" isn't available in WinPE (which should never actually happen), set default font to Font.ITALIC so there it at least some differentiation between intentionally bolded and "regular" text (which will now be italic).
                defaultFont = StyleContext.getDefaultStyleContext().getFont(defaultFont.getFamily(), Font.ITALIC, defaultFont.getSize());
            }
        }
    }
}
PicoMitchell commented 3 years ago

Here are some screenshots. Sorry if they are a bit artifacty, these were taken over VNC.

FlatFat 1.1 Default (Decorations Enabled with Segoe Font):

Screen Shot 2021-03-23 at 10 59 40 AM

Decorations Disabled with Tahoma Font (What I Prefer in WinPE):

Screen Shot 2021-03-23 at 10 58 10 AM

Decorations Disabled with Segoe Italic (Fallback Option if Tahoma Doesn't Exist Somehow):

Screen Shot 2021-03-23 at 11 03 10 AM

If it wasn't clear before, all other windows opened in WinPE (such as PowerShell or Command Prompt and other apps) get this older style windows frame, which is why I think NOT using the FlatLaf Decorated style fits in better in WinPE. In full Windows 10, the Decorated style in fantastic!

DevCharly commented 3 years ago

If there is an easy way to detect whether running on WinPE, I can disable window decoration and change default font to Tahoma (or Dialog).

I don't have WinPE. Could you run following Java snippet, which outputs all Java system properties, and post the output? Maybe there is something useful to detect WinPE.

Properties properties = System.getProperties();
properties.keySet().stream().sorted().forEach( key -> {
    System.out.println( key + " = '" + properties.getProperty( (String) key ) + "'" );
});

BTW have you tried to set font family to "Dialog"? This is usually mapped (in Java) to Tahoma on Windows.

PicoMitchell commented 3 years ago

I will get those properties for you later today.

The "Dialog" font sounds familiar, but I can't remember if I tried using that. I did all of this font manipulation quite a while back now. I will run another test to see what happens in WinPE if I set the font to "Dialog".

PicoMitchell commented 3 years ago

None of these properties look perfect for detecting WinPE to me (the stuff above this scroll point is all specific to the Java version or my Jar):

Screen Shot 2021-03-23 at 2 51 39 PM

The closest thing may be the user.dir, user.home, and possibly user.name. And the boot drive will always be "X:" in WinPE. If you think that is trustworthy enough, it could work. Let me know if there is anything else I can check.

Also, it appears that using the "Dialog" font DOES NOT map to Tahoma in WinPE. I originally wrote that it did, but I double checked at it appears another all bold font (it is not Segoe though) gets used when set to Dialog, I must have messed up my timing and loaded an old version when I did the first test. I could dig deeper to try to figure out which font it actually is, but it doesn't seem worth it.

PicoMitchell commented 3 years ago

If file existence is an acceptable test, it could make sense to just check for "\Windows\Fonts\segoeui.ttf" and simply fallback to Tahoma if it doesn't exist. No need to worry whether or not you're actually running in WinPE with that check.

For the Decorated frame, do you have any way to detect the width/height of the native frame components? If so, thinking you could check the width of the left, right, or bottom frame and if it's more than 0px or 1px (of whatever it is in full Windows 10), then you could not Decorate by default. Not sure if that is a workable solution, but maybe there is some other property of the windows itself that can be checked to determine if it's the Windows 10 style frame or the older WinPE style frame.

DevCharly commented 3 years ago

No, file existence is not a acceptable test. And Segoe UI is not the hardcoded default font for FlatLaf. This information comes from a Java desktop property. Could be also another font.

I think checking "user.dir" is a good and simple way.

Regarding the font: I wonder what Java fonts are returned by Java desktop properties. Could you run following app on WinPE and post the output?

import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import javax.swing.SwingUtilities;

public class DesktopPropertiesDump
{
    public static void main( String[] args ) {
        SwingUtilities.invokeLater( () -> {
            System.out.println( "Java version:   " + System.getProperty( "java.version" ) );

            GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
                .getDefaultScreenDevice().getDefaultConfiguration();
            double javaScale = gc.getDefaultTransform().getScaleX();
            System.out.println( "Java scale:     " + javaScale );

            Toolkit toolkit = Toolkit.getDefaultToolkit();
            String[] winPropNames = (String[]) toolkit.getDesktopProperty( "win.propNames" );
            for( String propName : winPropNames ) {
                Object value = toolkit.getDesktopProperty( propName );
                System.out.printf( "%-40s %s\n", propName, String.valueOf( value ) );
            }
        } );
    }
}
PicoMitchell commented 3 years ago

Sorry I didn't have a chance to get these to you yesterday. Here are the Java Properties from WinPE:

Java version:   16
Java scale:     1.0
DnD.gestureMotionThreshold: 2
awt.dynamicLayoutSupported: true
awt.file.showAttribCol: false
awt.file.showHiddenFiles: false
awt.font.desktophints: {Text-specific antialiasing enable key=LCD HRGB antialiasing text mode, Text-specific LCD contrast key=120}
awt.mouse.numButtons: 5
awt.multiClickInterval: 500
awt.wheelMousePresent: true
win.3d.backgroundColor: java.awt.Color[r=240,g=240,b=240]
win.3d.darkShadowColor: java.awt.Color[r=105,g=105,b=105]
win.3d.highlightColor: java.awt.Color[r=255,g=255,b=255]
win.3d.lightColor: java.awt.Color[r=227,g=227,b=227]
win.3d.shadowColor: java.awt.Color[r=160,g=160,b=160]
win.ansiFixed.font: java.awt.Font[family=Consolas,name=Consolas,style=plain,size=10]
win.ansiFixed.font.height: 10
win.ansiVar.font: java.awt.Font[family=Microsoft Sans Serif,name=Microsoft Sans Serif,style=plain,size=9]
win.ansiVar.font.height: 9
win.button.textColor: java.awt.Color[r=0,g=0,b=0]
win.caret.width: 1
win.defaultGUI.font: java.awt.Font[family=Tahoma,name=Tahoma,style=plain,size=11]
win.defaultGUI.font.height: 11
win.desktop.backgroundColor: java.awt.Color[r=0,g=0,b=0]
win.deviceDefault.font: java.awt.Font[family=Dialog,name=Dialog,style=bold,size=13]
win.deviceDefault.font.height: 13
win.drag.height: 4
win.drag.width: 4
win.frame.activeBorderColor: java.awt.Color[r=180,g=180,b=180]
win.frame.activeCaptionColor: java.awt.Color[r=153,g=180,b=209]
win.frame.activeCaptionGradientColor: java.awt.Color[r=185,g=209,b=234]
win.frame.backgroundColor: java.awt.Color[r=255,g=255,b=255]
win.frame.captionButtonHeight: 22
win.frame.captionButtonWidth: 36
win.frame.captionFont: java.awt.Font[family=Segoe UI,name=Segoe UI,style=plain,size=12]
win.frame.captionFont.height: 12
win.frame.captionGradientsOn: true
win.frame.captionHeight: 22
win.frame.captionTextColor: java.awt.Color[r=0,g=0,b=0]
win.frame.color: java.awt.Color[r=100,g=100,b=100]
win.frame.fullWindowDragsOn: true
win.frame.inactiveBorderColor: java.awt.Color[r=244,g=247,b=252]
win.frame.inactiveCaptionColor: java.awt.Color[r=191,g=205,b=219]
win.frame.inactiveCaptionGradientColor: java.awt.Color[r=215,g=228,b=242]
win.frame.inactiveCaptionTextColor: java.awt.Color[r=0,g=0,b=0]
win.frame.sizingBorderWidth: 1
win.frame.smallCaptionButtonHeight: 22
win.frame.smallCaptionButtonWidth: 22
win.frame.smallCaptionFont: java.awt.Font[family=Segoe UI,name=Segoe UI,style=plain,size=12]
win.frame.smallCaptionFont.height: 12
win.frame.smallCaptionHeight: 22
win.frame.textColor: java.awt.Color[r=0,g=0,b=0]
win.highContrast.on: false
win.icon.font: java.awt.Font[family=Segoe UI,name=Segoe UI,style=plain,size=12]
win.icon.font.height: 12
win.icon.hspacing: 75
win.icon.titleWrappingOn: true
win.icon.vspacing: 75
win.item.highlightColor: java.awt.Color[r=0,g=120,b=215]
win.item.highlightTextColor: java.awt.Color[r=255,g=255,b=255]
win.item.hotTrackedColor: java.awt.Color[r=0,g=102,b=204]
win.item.hotTrackingOn: true
win.mdi.backgroundColor: java.awt.Color[r=171,g=171,b=171]
win.menu.backgroundColor: java.awt.Color[r=240,g=240,b=240]
win.menu.buttonWidth: 19
win.menu.font: java.awt.Font[family=Segoe UI,name=Segoe UI,style=plain,size=12]
win.menu.font.height: 12
win.menu.height: 19
win.menu.keyboardCuesOn: false
win.menu.textColor: java.awt.Color[r=0,g=0,b=0]
win.menubar.backgroundColor: java.awt.Color[r=240,g=240,b=240]
win.messagebox.font: java.awt.Font[family=Segoe UI,name=Segoe UI,style=plain,size=12]
win.messagebox.font.height: 12
win.oemFixed.font: java.awt.Font[family=Dialog,name=Dialog,style=plain,size=12]
win.oemFixed.font.height: 12
win.properties.version: 3
win.scrollbar.backgroundColor: java.awt.Color[r=200,g=200,b=200]
win.scrollbar.height: 17
win.scrollbar.width: 17
win.sound.asterisk: WinPlaySound(SystemAsterisk)
win.sound.close: WinPlaySound(Close)
win.sound.default: WinPlaySound(.Default)
win.sound.exclamation: WinPlaySound(SystemExclamation)
win.sound.exit: WinPlaySound(SystemExit)
win.sound.hand: WinPlaySound(SystemHand)
win.sound.maximize: WinPlaySound(Maximize)
win.sound.menuCommand: WinPlaySound(MenuCommand)
win.sound.menuPopup: WinPlaySound(MenuPopup)
win.sound.minimize: WinPlaySound(Minimize)
win.sound.open: WinPlaySound(Open)
win.sound.question: WinPlaySound(SystemQuestion)
win.sound.restoreDown: WinPlaySound(RestoreDown)
win.sound.restoreUp: WinPlaySound(RestoreUp)
win.sound.start: WinPlaySound(SystemStart)
win.status.font: java.awt.Font[family=Segoe UI,name=Segoe UI,style=plain,size=12]
win.status.font.height: 12
win.system.font: java.awt.Font[family=Dialog,name=Dialog,style=bold,size=13]
win.system.font.height: 13
win.systemFixed.font: java.awt.Font[family=Dialog,name=Fixedsys,style=plain,size=12]
win.systemFixed.font.height: 12
win.text.fontSmoothingContrast: 1200
win.text.fontSmoothingOn: true
win.text.fontSmoothingOrientation: 1
win.text.fontSmoothingType: 2
win.text.grayedTextColor: java.awt.Color[r=109,g=109,b=109]
win.tooltip.backgroundColor: java.awt.Color[r=255,g=255,b=225]
win.tooltip.font: java.awt.Font[family=Segoe UI,name=Segoe UI,style=plain,size=12]
win.tooltip.font.height: 12
win.tooltip.textColor: java.awt.Color[r=0,g=0,b=0]
win.xpstyle.colorName: NormalColor
win.xpstyle.dllName: X:\windows\resources\themes\Aero\Aero.msstyles
win.xpstyle.sizeName: NormalSize
win.xpstyle.themeActive: true
DevCharly commented 3 years ago

Thx for the info.

FlatLaf now uses win.defaultGUI.font on WinPE, which is BTW the same desktop property that the Java Windows L&F uses.

Implemented in main branch and available in latest snapshot: https://github.com/JFormDesigner/FlatLaf#snapshots

FlatLaf 1.1.1 release follows the next days... Thanks.

PicoMitchell commented 3 years ago

I haven't had a chance to test this in WinPE yet, but I noticed using "win.defaultGUI.font" will set the size to 11 while "win.messagebox.font" is 12.

Would it be possible to use the defaultGUI family with the messagebox size in WinPE?

PicoMitchell commented 3 years ago

Tested and confirmed with FlatLaf 1.1.1 that the text is now smaller in WinPE, since it's using the size 11 specified in "win.defaultGUI.font". It doesn't look bad, but I think size 12 from "win.messagebox.font" would be a better default.

Hoping you're still seeing these messages even though this issue is now closed. I don't think I can reopen the issue since I wasn't the one to close it.

DevCharly commented 3 years ago

Thanks for the feedback. I've changed it in main branch.