diff --git a/CHANGELOG.md b/CHANGELOG.md index e911fb46..a1c2cd3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ FlatLaf Change Log - ComboBox: Fixed issues with NetBeans `org.openide.awt.ColorComboBox` component. - Hex color values in `.properties` files now must start with a `#` character. +- SwingX: Support `JXTitledPanel`. (issue #22) - SwingX: Fixed too wide border when using date picker as table cell editor. (issue #24) - JIDE Common Layer: Fixed `JidePopup` border. diff --git a/flatlaf-swingx/README.md b/flatlaf-swingx/README.md index ad8d2ecd..4cae7a66 100644 --- a/flatlaf-swingx/README.md +++ b/flatlaf-swingx/README.md @@ -16,6 +16,7 @@ this addon: - `JXMonthView` - `JXTaskPaneContainer` - `JXTaskPane` +- `JXTitledPanel` ![Flat Light SwingX Demo](../images/FlatLightSwingXTest.png) diff --git a/flatlaf-swingx/src/main/java/com/formdev/flatlaf/swingx/ui/FlatTaskPaneUI.java b/flatlaf-swingx/src/main/java/com/formdev/flatlaf/swingx/ui/FlatTaskPaneUI.java index 3452d281..5897438e 100644 --- a/flatlaf-swingx/src/main/java/com/formdev/flatlaf/swingx/ui/FlatTaskPaneUI.java +++ b/flatlaf-swingx/src/main/java/com/formdev/flatlaf/swingx/ui/FlatTaskPaneUI.java @@ -84,7 +84,7 @@ public class FlatTaskPaneUI public void uninstallUI( JComponent c ) { if( group.getContentPane() instanceof JComponent ) { // uninstall our content border, because it does not implement UIResource, - // to alloy other LaF to install its own border + // to allow other LaF to install its own border JComponent content = (JComponent) group.getContentPane(); if( content.getBorder() instanceof FlatContentPaneBorder ) content.setBorder( null ); diff --git a/flatlaf-swingx/src/main/java/com/formdev/flatlaf/swingx/ui/FlatTitledPanelUI.java b/flatlaf-swingx/src/main/java/com/formdev/flatlaf/swingx/ui/FlatTitledPanelUI.java new file mode 100644 index 00000000..104d2694 --- /dev/null +++ b/flatlaf-swingx/src/main/java/com/formdev/flatlaf/swingx/ui/FlatTitledPanelUI.java @@ -0,0 +1,96 @@ +/* + * Copyright 2019 FormDev Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.formdev.flatlaf.swingx.ui; + +import static com.formdev.flatlaf.util.UIScale.scale; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.geom.Rectangle2D; +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import org.jdesktop.swingx.JXTitledPanel; +import org.jdesktop.swingx.SwingXUtilities; +import org.jdesktop.swingx.painter.MattePainter; +import org.jdesktop.swingx.plaf.PainterUIResource; +import org.jdesktop.swingx.plaf.basic.BasicTitledPanelUI; +import com.formdev.flatlaf.ui.FlatLineBorder; +import com.formdev.flatlaf.util.UIScale; + +/** + * Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXTitledPanel}. + * + * @author Karl Tauber + */ +public class FlatTitledPanelUI + extends BasicTitledPanelUI +{ + public static ComponentUI createUI( JComponent c ) { + return new FlatTitledPanelUI(); + } + + @Override + protected void installDefaults( JXTitledPanel titledPanel ) { + super.installDefaults( titledPanel ); + + // replace gradient background + installProperty( titledPanel, "titlePainter", new PainterUIResource<>( + new TitlePainter( UIManager.getColor( "JXTitledPanel.titleBackground" ), + UIManager.getColor( "JXTitledPanel.borderColor" ) ) ) ); + + // make title bold + installProperty( titledPanel, "titleFont", UIManager.getFont( "JXTitledPanel.titleFont" ).deriveFont( Font.BOLD ) ); + } + + @Override + protected void installComponents( JXTitledPanel titledPanel ) { + super.installComponents( titledPanel ); + + if (SwingXUtilities.isUIInstallable(titledPanel.getBorder())) + titledPanel.setBorder( new FlatLineBorder( new Insets( 1, 1, 1, 1 ), + UIManager.getColor( "JXTitledPanel.borderColor" ) ) ); + } + + @Override + protected Insets getCaptionInsets() { + return UIScale.scale( super.getCaptionInsets() ); + } + + //---- class TitlePainter ------------------------------------------------- + + private static class TitlePainter + extends MattePainter + { + private final Color borderColor; + + TitlePainter( Color color, Color borderColor ) { + super( color ); + this.borderColor = borderColor; + } + + @Override + protected void doPaint( Graphics2D g, Object component, int width, int height ) { + super.doPaint( g, component, width, height ); + + float h = scale( 1f ); + g.setColor( borderColor ); + g.fill( new Rectangle2D.Float( 0, height - h, width, h ) ); + } + } +} diff --git a/flatlaf-swingx/src/main/resources/com/formdev/flatlaf/swingx/FlatLaf.properties b/flatlaf-swingx/src/main/resources/com/formdev/flatlaf/swingx/FlatLaf.properties index be3c451f..36050a91 100644 --- a/flatlaf-swingx/src/main/resources/com/formdev/flatlaf/swingx/FlatLaf.properties +++ b/flatlaf-swingx/src/main/resources/com/formdev/flatlaf/swingx/FlatLaf.properties @@ -22,6 +22,7 @@ HeaderUI=com.formdev.flatlaf.swingx.ui.FlatHeaderUI HyperlinkUI=com.formdev.flatlaf.swingx.ui.FlatHyperlinkUI MonthViewUI=com.formdev.flatlaf.swingx.ui.FlatMonthViewUI swingx/TaskPaneUI=com.formdev.flatlaf.swingx.ui.FlatTaskPaneUI +TitledPanelUI=com.formdev.flatlaf.swingx.ui.FlatTitledPanelUI #---- DatePicker ---- @@ -33,3 +34,11 @@ JXDatePicker.border=com.formdev.flatlaf.swingx.ui.FlatDatePickerBorder JXMonthView.monthDownFileName={icon}com.formdev.flatlaf.swingx.ui.FlatMonthDownIcon JXMonthView.monthUpFileName={icon}com.formdev.flatlaf.swingx.ui.FlatMonthUpIcon + + +#---- TitledPanel ---- + +JXTitledPanel.borderColor=@@Button.borderColor +JXTitledPanel.titleBackground=@@TaskPane.titleBackgroundGradientStart +JXTitledPanel.titleForeground=@@TaskPane.titleForeground +JXTitledPanel.captionInsets=4,10,4,10 diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/swingx/FlatSwingXTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/swingx/FlatSwingXTest.java index 14e543f5..7b982cc5 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/swingx/FlatSwingXTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/swingx/FlatSwingXTest.java @@ -36,6 +36,12 @@ public class FlatSwingXTest public static void main( String[] args ) { SwingUtilities.invokeLater( () -> { FlatTestFrame frame = FlatTestFrame.create( args, "FlatSwingXTest" ); + + // without this, painting becomes very slow as soon as JXTitledPanel + // is used, because JXTitledPanel sets opaque to false and JXPanel + // then installs its own repaint manager + UIManager.put( "JXPanel.patch", true ); + frame.useApplyComponentOrientation = true; frame.showFrame( FlatSwingXTest::new ); } ); @@ -107,6 +113,19 @@ public class FlatSwingXTest table = new JTable(); JLabel headerLabel = new JLabel(); JXHeader xHeader1 = new JXHeader(); + JXTitledPanel xTitledPanel1 = new JXTitledPanel(); + JLabel label7 = new JLabel(); + JTextField textField1 = new JTextField(); + JLabel label8 = new JLabel(); + JTextField textField2 = new JTextField(); + JLabel titledPanelLabel = new JLabel(); + JXTitledPanel xTitledPanel2 = new JXTitledPanel(); + JLabel label9 = new JLabel(); + JTextField textField3 = new JTextField(); + JLabel label10 = new JLabel(); + JTextField textField4 = new JTextField(); + JButton button1 = new JButton(); + JButton button2 = new JButton(); //======== this ======== setLayout(new MigLayout( @@ -125,7 +144,9 @@ public class FlatSwingXTest "[]" + "[]" + "[]" + - "[]")); + "[]" + + "[]" + + "[37]")); //---- label1 ---- label1.setText("enabled"); @@ -345,6 +366,70 @@ public class FlatSwingXTest xHeader1.setDescription("Description\nMore description"); xHeader1.setIcon(new ImageIcon(getClass().getResource("/org/jdesktop/swingx/plaf/windows/resources/tipoftheday.png"))); add(xHeader1, "cell 1 7 3 1,width 200"); + + //======== xTitledPanel1 ======== + { + xTitledPanel1.setTitle("Title"); + xTitledPanel1.setOpaque(true); + Container xTitledPanel1ContentContainer = xTitledPanel1.getContentContainer(); + xTitledPanel1ContentContainer.setLayout(new MigLayout( + "hidemode 3", + // columns + "[fill]" + + "[100,fill]", + // rows + "[]" + + "[]")); + + //---- label7 ---- + label7.setText("text"); + xTitledPanel1ContentContainer.add(label7, "cell 0 0"); + xTitledPanel1ContentContainer.add(textField1, "cell 1 0"); + + //---- label8 ---- + label8.setText("text"); + xTitledPanel1ContentContainer.add(label8, "cell 0 1"); + xTitledPanel1ContentContainer.add(textField2, "cell 1 1"); + } + add(xTitledPanel1, "cell 1 8 2 1,grow"); + + //---- titledPanelLabel ---- + titledPanelLabel.setText("JXTitledPanel:"); + add(titledPanelLabel, "cell 0 8,aligny top,growy 0"); + + //======== xTitledPanel2 ======== + { + xTitledPanel2.setTitle("Title"); + xTitledPanel2.setOpaque(true); + xTitledPanel2.setLeftDecoration(button1); + xTitledPanel2.setRightDecoration(button2); + Container xTitledPanel2ContentContainer = xTitledPanel2.getContentContainer(); + xTitledPanel2ContentContainer.setLayout(new MigLayout( + "hidemode 3", + // columns + "[fill]" + + "[100,fill]", + // rows + "[]" + + "[]")); + + //---- label9 ---- + label9.setText("text"); + xTitledPanel2ContentContainer.add(label9, "cell 0 0"); + xTitledPanel2ContentContainer.add(textField3, "cell 1 0"); + + //---- label10 ---- + label10.setText("text"); + xTitledPanel2ContentContainer.add(label10, "cell 0 1"); + xTitledPanel2ContentContainer.add(textField4, "cell 1 1"); + } + add(xTitledPanel2, "cell 3 8,grow"); + + //---- button1 ---- + button1.setText("<"); + + //---- button2 ---- + button2.setText(">"); // JFormDesigner - End of component initialization //GEN-END:initComponents xDatePicker1.setDate( new Date() ); diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/swingx/FlatSwingXTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/swingx/FlatSwingXTest.jfd index ef3942f2..567d0e87 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/swingx/FlatSwingXTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/swingx/FlatSwingXTest.jfd @@ -9,7 +9,7 @@ new FormModel { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "ltr,insets dialog,hidemode 3" "$columnConstraints": "[left][][][][fill]" - "$rowConstraints": "[]0[][]0[top][][][][]" + "$rowConstraints": "[]0[][]0[top][][][][][][37]" } ) { name: "this" add( new FormComponent( "javax.swing.JLabel" ) { @@ -280,9 +280,95 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 7 3 1,width 200" } ) + add( new FormContainer( "org.jdesktop.swingx.JXTitledPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "hidemode 3" + "$columnConstraints": "[fill][100,fill]" + "$rowConstraints": "[][]" + } ) { + name: "xTitledPanel1" + "title": "Title" + "opaque": true + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label7" + "text": "text" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JTextField" ) { + name: "textField1" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label8" + "text": "text" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1" + } ) + add( new FormComponent( "javax.swing.JTextField" ) { + name: "textField2" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 1" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 8 2 1,grow" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "titledPanelLabel" + "text": "JXTitledPanel:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 8,aligny top,growy 0" + } ) + add( new FormContainer( "org.jdesktop.swingx.JXTitledPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "hidemode 3" + "$columnConstraints": "[fill][100,fill]" + "$rowConstraints": "[][]" + } ) { + name: "xTitledPanel2" + "title": "Title" + "opaque": true + "leftDecoration": new FormReference( "button1" ) + "rightDecoration": new FormReference( "button2" ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label9" + "text": "text" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JTextField" ) { + name: "textField3" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label10" + "text": "text" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1" + } ) + add( new FormComponent( "javax.swing.JTextField" ) { + name: "textField4" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 1" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 3 8,grow" + } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) "size": new java.awt.Dimension( 700, 600 ) } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "button1" + "text": "<" + }, new FormLayoutConstraints( null ) { + "location": new java.awt.Point( 5, 650 ) + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "button2" + "text": ">" + }, new FormLayoutConstraints( null ) { + "location": new java.awt.Point( 75, 650 ) + } ) } } diff --git a/images/FlatDarkSwingXTest.png b/images/FlatDarkSwingXTest.png index 99e21d12..10cfc939 100644 Binary files a/images/FlatDarkSwingXTest.png and b/images/FlatDarkSwingXTest.png differ diff --git a/images/FlatLightSwingXTest.png b/images/FlatLightSwingXTest.png index de69f76e..a2b57212 100644 Binary files a/images/FlatLightSwingXTest.png and b/images/FlatLightSwingXTest.png differ