FlatLaf
FlatLaf copied to clipboard
Window title bar title alignment / FlatTitlePane
[Enhancement]
Would be nice to have a property to set set window title alignment explicitly. Currently the only option is to center the title. If the option is set to false the position of the title depends on the current component orientation. Especially for small windows with embedded menubar it would be nice to push the title as far away from the menu as possible.
Current Properties
TitlePane.centerTitle (Boolean) TitlePane.centerTitleIfMenuBarEmbedded (Boolean)
Possible new Properties
TitlePane.titleAlignment (String) TitlePane.titleAlignmentIfMenuBarEmbedded (String)
Possible values:
"Left" "Center" "Right" null/empty for default alignment according to component orientation
Hmm, right aligned title looks weird to me 😕
Have you tried to increase the value of TitlePane.menuBarTitleGap to get a larger gap between menu bar and title?
E.g.
UIManager.put( "TitlePane.menuBarTitleGap", 100 );
UIManager.put( "TitlePane.centerTitleIfMenuBarEmbedded", false );
I agree that it might look unexpected on otherwise empty titlebars, but as I said above: In a small window with a embedded (left aligned) menubar it makes totally sense imho. Increasing TitlePane.menuBarTitleGap to a large value as a workaround might also end up looking weird (misaligned) in some scenarios. For left aligned titles it might even make sense to have some sort of separator between an embedded menu and the title itself as the tiny font color difference between the two is hardly noticeable.
Hi,
I agree that on small windows the centered title may look a bit of when used with an embedded menubar.
May I suggest as an alternative to have an option where the title is placed in front of the embedded menubar if this is technically possible?
Your thoughts?
Thanks
I also was looking for the way to customize position of the window title text, however in my case I would like to get following layout:
[icon] Window Title | Menu-1 ... Menu-N
(i.e. window title is left aligned)
I would be able to create such layout myself, but unfortunatelly flatlaf's code has hardcorded logic to look for the component in JMenubar which is supposed to be a placeholder for title text:
https://github.com/JFormDesigner/FlatLaf/blob/main/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java#L252
// If menu bar is embedded and contains a horizontal glue component,
// then move the title label to the same location as the glue component
// and give it the same width.
// This allows placing any component on the trailing side of the title pane.
JMenuBar menuBar = rootPane.getJMenuBar();
if( hasVisibleEmbeddedMenuBar( menuBar ) ) {
Component horizontalGlue = findHorizontalGlue( menuBar );
if( horizontalGlue != null ) {
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, titleLabel );
titleLabel.setBounds( titleLabel.getX() + glueLocation.x, titleLabel.getY(),
horizontalGlue.getWidth(), titleLabel.getHeight() );
}
}
https://github.com/JFormDesigner/FlatLaf/blob/main/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java#L533
protected Component findHorizontalGlue( JMenuBar menuBar ) {
if( menuBar == null )
return null;
int count = menuBar.getComponentCount();
for( int i = count - 1; i >= 0; i-- ) {
Component c = menuBar.getComponent( i );
if( c instanceof Box.Filler && c.getMaximumSize().width >= Short.MAX_VALUE )
return c;
}
return null;
}
What about adding code to also match component by a specific name? For example I could add a pre-formatted label (or other component) like following:
JMenuBar menuBar = new JMenuBar();
...
JLabel titleLabel = new JLabel();
titleLabel.setName("flatLaf.titleComponent");
menuBar.add(titleLabel);
...
window.setJMenuBar(menuBar);
protected Component findHorizontalGlue( JMenuBar menuBar ) {
if( menuBar == null )
return null;
int count = menuBar.getComponentCount();
for( int i = count - 1; i >= 0; i-- ) {
Component c = menuBar.getComponent( i );
if( "flatLaf.titleComponent".equals(c.getName()) )
return c;
if( c instanceof Box.Filler && c.getMaximumSize().width >= Short.MAX_VALUE )
return c;
}
return null;
}