Skip to content

Commit

Permalink
Window decorations: added client property to mark components in embed…
Browse files Browse the repository at this point in the history
…ded menu bar as "caption" (issue #569)
  • Loading branch information
DevCharly committed Aug 20, 2022
1 parent fee7cf6 commit 16f3f9e
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 26 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,9 @@ FlatLaf Change Log

- TabbedPane: New option to disable tab run rotation in wrap layout. Set UI
value `TabbedPane.rotateTabRuns` to `false`. (issue #574)
- Native window decorations (Windows 10/11 only): Added client property to mark
components in embedded menu bar as "caption" (allow moving window). (issue
#569)

#### Fixed bugs

Expand Down
Expand Up @@ -253,6 +253,19 @@ public interface FlatClientProperties
*/
String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner";

/**
* Specifies whether a component in a embedded menu bar should behave as caption
* (left-click allows moving window, right-click shows window system menu).
* The component does not receive mouse pressed/released/clicked/dragged events,
* but it gets mouse entered/exited/moved events.
* <p>
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*
* @since 2.5
*/
String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption";

//---- Popup --------------------------------------------------------------

/**
Expand Down
Expand Up @@ -861,26 +861,32 @@ protected void updateNativeTitleBarHeightAndHitTestSpots() {
r.height -= resizeHeight;
}

Component horizontalGlue = findHorizontalGlue( menuBar );
if( horizontalGlue != null ) {
// If menu bar is embedded and contains a horizontal glue component,
// then split the hit test spot into two spots so that
// the glue component area can be used to move the window.

Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window );
int x2 = glueLocation.x + horizontalGlue.getWidth();
Rectangle r2;
if( getComponentOrientation().isLeftToRight() ) {
r2 = new Rectangle( x2, r.y, (r.x + r.width) - x2, r.height );

r.width = glueLocation.x - r.x;
} else {
r2 = new Rectangle( r.x, r.y, glueLocation.x - r.x, r.height );

r.width = (r.x + r.width) - x2;
r.x = x2;
int count = menuBar.getComponentCount();
for( int i = count - 1; i >= 0; i-- ) {
Component c = menuBar.getComponent( i );
if( c instanceof Box.Filler ||
(c instanceof JComponent && clientPropertyBoolean( (JComponent) c, COMPONENT_TITLE_BAR_CAPTION, false ) ) )
{
// If menu bar is embedded and contains a horizontal glue or caption component,
// then split the hit test spot so that
// the glue/caption component area can be used to move the window.

Point glueLocation = SwingUtilities.convertPoint( c, 0, 0, window );
int x2 = glueLocation.x + c.getWidth();
Rectangle r2;
if( getComponentOrientation().isLeftToRight() ) {
r2 = new Rectangle( x2, r.y, (r.x + r.width) - x2, r.height );

r.width = glueLocation.x - r.x;
} else {
r2 = new Rectangle( r.x, r.y, glueLocation.x - r.x, r.height );

r.width = (r.x + r.width) - x2;
r.x = x2;
}
if( r2.width > 0 )
hitTestSpots.add( r2 );
}
hitTestSpots.add( r2 );
}

hitTestSpots.add( r );
Expand Down
Expand Up @@ -262,6 +262,16 @@ protected void paintComponent( Graphics g ) {
menuBar.revalidate();
}

private void addCaption() {
JLabel caption = new JLabel( "Caption" );
caption.setBackground( Color.green );
caption.setOpaque( true );
caption.putClientProperty( FlatClientProperties.COMPONENT_TITLE_BAR_CAPTION, true );

menuBar.add( caption );
menuBar.revalidate();
}

private void removeMenu() {
int menuCount = menuBar.getMenuCount();
if( menuCount <= 0 )
Expand Down Expand Up @@ -445,6 +455,7 @@ private void initComponents() {
JPanel panel3 = new JPanel();
addMenuButton = new JButton();
addGlueButton = new JButton();
addCaptionButton = new JButton();
removeMenuButton = new JButton();
changeMenuButton = new JButton();
changeTitleButton = new JButton();
Expand Down Expand Up @@ -547,6 +558,7 @@ private void initComponents() {
"[]" +
"[]" +
"[]" +
"[]" +
"[]unrel" +
"[]"));

Expand All @@ -560,20 +572,25 @@ private void initComponents() {
addGlueButton.addActionListener(e -> addGlue());
panel3.add(addGlueButton, "cell 0 1");

//---- addCaptionButton ----
addCaptionButton.setText("Add caption");
addCaptionButton.addActionListener(e -> addCaption());
panel3.add(addCaptionButton, "cell 0 2");

//---- removeMenuButton ----
removeMenuButton.setText("Remove menu");
removeMenuButton.addActionListener(e -> removeMenu());
panel3.add(removeMenuButton, "cell 0 2");
panel3.add(removeMenuButton, "cell 0 3");

//---- changeMenuButton ----
changeMenuButton.setText("Change menu");
changeMenuButton.addActionListener(e -> changeMenu());
panel3.add(changeMenuButton, "cell 0 3");
panel3.add(changeMenuButton, "cell 0 4");

//---- changeTitleButton ----
changeTitleButton.setText("Change title");
changeTitleButton.addActionListener(e -> changeTitle());
panel3.add(changeTitleButton, "cell 0 4");
panel3.add(changeTitleButton, "cell 0 5");
}
add(panel3, "cell 2 0 1 8,aligny top,growy 0");

Expand Down Expand Up @@ -961,6 +978,7 @@ private void initComponents() {
private JCheckBox rightCompCheckBox;
private JButton addMenuButton;
private JButton addGlueButton;
private JButton addCaptionButton;
private JButton removeMenuButton;
private JButton changeMenuButton;
private JButton changeTitleButton;
Expand Down
Expand Up @@ -36,7 +36,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[fill]"
"$rowConstraints": "[][][][]unrel[]"
"$rowConstraints": "[][][][][]unrel[]"
} ) {
name: "panel3"
add( new FormComponent( "javax.swing.JButton" ) {
Expand All @@ -59,6 +59,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "addCaptionButton"
"text": "Add caption"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addCaption", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "removeMenuButton"
"text": "Remove menu"
Expand All @@ -67,7 +77,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "removeMenu", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
"value": "cell 0 3"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "changeMenuButton"
Expand All @@ -77,7 +87,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeMenu", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3"
"value": "cell 0 4"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "changeTitleButton"
Expand All @@ -87,7 +97,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeTitle", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4"
"value": "cell 0 5"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 8,aligny top,growy 0"
Expand Down

0 comments on commit 16f3f9e

Please sign in to comment.