From 7a6dd4d9c0b071cd00caf85790314fc3bc25e6ae Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 28 Aug 2019 16:48:59 +0200 Subject: [PATCH] TabbedPane basic implementation --- flatlaf-core/build.gradle.kts | 1 + .../formdev/flatlaf/ui/FlatTabbedPaneUI.java | 269 +++++++++++++++++ .../formdev/flatlaf/FlatDarkLaf.properties | 10 + .../com/formdev/flatlaf/FlatLaf.properties | 13 + .../formdev/flatlaf/FlatLightLaf.properties | 10 + .../formdev/flatlaf/FlatContainerTest.java | 270 ++++++++++++++++++ .../com/formdev/flatlaf/FlatContainerTest.jfd | 211 ++++++++++++++ .../com/formdev/flatlaf/FlatTestFrame.java | 41 ++- .../formdev/flatlaf/FlatTestLaf.properties | 10 + 9 files changed, 823 insertions(+), 12 deletions(-) create mode 100644 flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java create mode 100644 flatlaf-core/src/test/java/com/formdev/flatlaf/FlatContainerTest.java create mode 100644 flatlaf-core/src/test/java/com/formdev/flatlaf/FlatContainerTest.jfd diff --git a/flatlaf-core/build.gradle.kts b/flatlaf-core/build.gradle.kts index 3f1e4002..a455aceb 100644 --- a/flatlaf-core/build.gradle.kts +++ b/flatlaf-core/build.gradle.kts @@ -26,6 +26,7 @@ repositories { dependencies { testCompile( "com.miglayout:miglayout-swing:5.2" ) + testCompile( "com.jgoodies:jgoodies-forms:1.9.0" ) } java { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java new file mode 100644 index 00000000..ff7d3be2 --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java @@ -0,0 +1,269 @@ +/* + * 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.ui; + +import static com.formdev.flatlaf.util.UIScale.scale; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicTabbedPaneUI; +import javax.swing.text.View; +import sun.swing.SwingUtilities2; + +/** + * Provides the Flat LaF UI delegate for {@link javax.swing.JTabbedPane}. + * + * @clientProperty JTabbedPane.hasFullBorder boolean + * + * @uiDefault TabbedPane.font Font + * @uiDefault TabbedPane.background Color + * @uiDefault TabbedPane.foreground Color + * @uiDefault TabbedPane.disabledForeground Color + * @uiDefault TabbedPane.selectedForeground Color + * @uiDefault TabbedPane.underlineColor Color + * @uiDefault TabbedPane.disabledUnderlineColor Color + * @uiDefault TabbedPane.hoverColor Color + * @uiDefault TabbedPane.focusColor Color + * @uiDefault TabbedPane.textIconGap int + * @uiDefault TabbedPane.tabInsets Insets + * @uiDefault TabbedPane.tabAreaInsets Insets + * @uiDefault TabbedPane.tabHeight int + * @uiDefault TabbedPane.tabSelectionHeight int + * @uiDefault TabbedPane.contentSeparatorWidth int + * + * @author Karl Tauber + */ +public class FlatTabbedPaneUI + extends BasicTabbedPaneUI +{ + protected Color disabledForeground; + protected Color selectedForeground; + protected Color underlineColor; + protected Color disabledUnderlineColor; + protected Color hoverColor; + protected Color focusColor; + + protected int tabHeight; + protected int tabSelectionHeight; + protected int contentSeparatorHeight; + + public static ComponentUI createUI( JComponent c ) { + return new FlatTabbedPaneUI(); + } + + @Override + protected void installDefaults() { + super.installDefaults(); + + disabledForeground = UIManager.getColor( "TabbedPane.disabledForeground" ); + selectedForeground = UIManager.getColor( "TabbedPane.selectedForeground" ); + underlineColor = UIManager.getColor( "TabbedPane.underlineColor" ); + disabledUnderlineColor = UIManager.getColor( "TabbedPane.disabledUnderlineColor" ); + hoverColor = UIManager.getColor( "TabbedPane.hoverColor" ); + focusColor = UIManager.getColor( "TabbedPane.focusColor" ); + + tabHeight = UIManager.getInt( "TabbedPane.tabHeight" ); + tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" ); + contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" ); + + // scale + textIconGap = scale( textIconGap ); + tabInsets = scale( tabInsets ); + selectedTabPadInsets = scale( selectedTabPadInsets ); + tabAreaInsets = scale( tabAreaInsets ); + tabHeight = scale( tabHeight ); + tabSelectionHeight = scale( tabSelectionHeight ); + contentSeparatorHeight = scale( contentSeparatorHeight ); + } + + @Override + protected PropertyChangeListener createPropertyChangeListener() { + return new BasicTabbedPaneUI.PropertyChangeHandler() { + @Override + public void propertyChange( PropertyChangeEvent e ) { + super.propertyChange( e ); + + if( "JTabbedPane.hasFullBorder".equals( e.getPropertyName() ) ) { + tabPane.revalidate(); + tabPane.repaint(); + } + } + }; + } + + @Override + protected void setRolloverTab( int index ) { + int oldIndex = getRolloverTab(); + super.setRolloverTab( index ); + + if( index == oldIndex ) + return; + + // repaint old and new hover tabs + repaintTab( oldIndex ); + repaintTab( index ); + } + + private void repaintTab( int tabIndex ) { + if( tabIndex < 0 || tabIndex >= tabPane.getTabCount() ) + return; + + Rectangle r = getTabBounds( tabPane, tabIndex ); + if( r != null ) + tabPane.repaint( r ); + } + + @Override + protected int calculateTabWidth( int tabPlacement, int tabIndex, FontMetrics metrics ) { + return super.calculateTabWidth( tabPlacement, tabIndex, metrics ) - 3; + } + + @Override + protected int calculateTabHeight( int tabPlacement, int tabIndex, int fontHeight ) { + return Math.max( super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2, tabHeight ); + } + + /** + * The content border insets are used to create a separator line between tabs and content. + */ + @Override + protected Insets getContentBorderInsets( int tabPlacement ) { + boolean hasFullBorder = (tabPane.getClientProperty( "JTabbedPane.hasFullBorder" ) == Boolean.TRUE); + Insets insets = hasFullBorder + ? new Insets( contentSeparatorHeight, contentSeparatorHeight, contentSeparatorHeight, contentSeparatorHeight ) + : new Insets( contentSeparatorHeight, 0, 0, 0 ); + rotateInsets( insets, contentBorderInsets, tabPlacement ); + return contentBorderInsets; + } + + @Override + protected int getTabLabelShiftX( int tabPlacement, int tabIndex, boolean isSelected ) { + return 0; + } + + @Override + protected int getTabLabelShiftY( int tabPlacement, int tabIndex, boolean isSelected ) { + return 0; + } + + @Override + protected void paintText( Graphics g, int tabPlacement, Font font, FontMetrics metrics, + int tabIndex, String title, Rectangle textRect, boolean isSelected ) + { + g.setFont( font ); + + // html + View view = getTextViewForTab( tabIndex ); + if( view != null ) { + view.paint( g, textRect ); + return; + } + + // plain text + Color color; + if( tabPane.isEnabled() && tabPane.isEnabledAt( tabIndex ) ) { + color = tabPane.getForegroundAt( tabIndex ); + if( isSelected && (color instanceof UIResource) && selectedForeground != null ) + color = selectedForeground; + } else + color = disabledForeground; + + int mnemIndex = tabPane.getDisplayedMnemonicIndexAt( tabIndex ); + + g.setColor( color ); + SwingUtilities2.drawStringUnderlineCharAt( tabPane, g, title, mnemIndex, + textRect.x, textRect.y + metrics.getAscent() ); + } + + @Override + protected void paintTabBackground( Graphics g, int tabPlacement, int tabIndex, + int x, int y, int w, int h, boolean isSelected ) + { + boolean enabled = tabPane.isEnabled(); + g.setColor( enabled && getRolloverTab() == tabIndex + ? hoverColor + : (enabled && isSelected && tabPane.hasFocus() + ? focusColor + : tabPane.getBackgroundAt( tabIndex )) ); + g.fillRect( x, y, w, h ); + } + + @Override + protected void paintTabBorder( Graphics g, int tabPlacement, int tabIndex, + int x, int y, int w, int h, boolean isSelected ) + { + if( !isSelected ) + return; + + g.setColor( tabPane.isEnabled() ? underlineColor : disabledUnderlineColor ); + + Insets contentInsets = getContentBorderInsets( tabPlacement ); + + // paint underline selection + switch( tabPlacement ) { + case TOP: + default: + int sy = y + h + contentInsets.top - tabSelectionHeight; + g.fillRect( x, sy, w, tabSelectionHeight ); + break; + + case BOTTOM: + g.fillRect( x, y - contentInsets.bottom, w, tabSelectionHeight ); + break; + + case LEFT: + int sx = x + w + contentInsets.left - tabSelectionHeight; + g.fillRect( sx, y, tabSelectionHeight, h ); + break; + + case RIGHT: + g.fillRect( x - contentInsets.right, y, tabSelectionHeight, h ); + break; + } + } + + @Override + protected void paintContentBorderTopEdge( Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h ) { + } + + @Override + protected void paintContentBorderLeftEdge( Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h ) { + } + + @Override + protected void paintContentBorderBottomEdge( Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h ) { + } + + @Override + protected void paintContentBorderRightEdge( Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h ) { + } + + @Override + protected void paintFocusIndicator( Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, + Rectangle iconRect, Rectangle textRect, boolean isSelected ) + { + } +} diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties index 004782e0..75adf1cf 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties @@ -130,3 +130,13 @@ Slider.disabledForeground=4c5052 #---- SplitPane ---- SplitPaneDivider.draggingColor=646464 + + +#---- TabbedPane ---- + +TabbedPane.disabledForeground=777777 +TabbedPane.underlineColor=4A88C7 +TabbedPane.disabledUnderlineColor=7a7a7a +TabbedPane.hoverColor=2e3133 +TabbedPane.focusColor=3d4b5c +TabbedPane.contentAreaColor=323232 diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties index 3de6dcde..14cd5081 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -30,6 +30,7 @@ ScrollPaneUI=com.formdev.flatlaf.ui.FlatScrollPaneUI SeparatorUI=com.formdev.flatlaf.ui.FlatSeparatorUI SliderUI=com.formdev.flatlaf.ui.FlatSliderUI SplitPaneUI=com.formdev.flatlaf.ui.FlatSplitPaneUI +TabbedPaneUI=com.formdev.flatlaf.ui.FlatTabbedPaneUI TextAreaUI=com.formdev.flatlaf.ui.FlatTextAreaUI TextFieldUI=com.formdev.flatlaf.ui.FlatTextFieldUI TextPaneUI=com.formdev.flatlaf.ui.FlatTextPaneUI @@ -124,6 +125,18 @@ SplitPane.border=null SplitPaneDivider.border=null +#---- TabbedPane ---- + +TabbedPane.tabHeight=32 +TabbedPane.tabSelectionHeight=3 +TabbedPane.contentSeparatorHeight=1 +TabbedPane.tabInsets=0,12,0,12 +TabbedPane.tabAreaInsets=0,0,0,0 +TabbedPane.selectedTabPadInsets=0,0,0,0 +TabbedPane.tabRunOverlay=0 +TabbedPane.tabsOverlapBorder=true + + #---- TextArea ---- TextArea.border=com.formdev.flatlaf.ui.FlatMarginBorder diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties index e9683e48..f4864401 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties @@ -130,3 +130,13 @@ Slider.disabledForeground=c0c0c0 #---- SplitPane ---- SplitPaneDivider.draggingColor=c4c4c4 + + +#---- TabbedPane ---- + +TabbedPane.disabledForeground=999999 +TabbedPane.underlineColor=4083C9 +TabbedPane.disabledUnderlineColor=ababab +TabbedPane.hoverColor=d9d9d9 +TabbedPane.focusColor=dae4ed +TabbedPane.contentAreaColor=bfbfbf diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatContainerTest.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatContainerTest.java new file mode 100644 index 00000000..8d44d6bb --- /dev/null +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatContainerTest.java @@ -0,0 +1,270 @@ +/* + * Created by JFormDesigner on Tue Aug 27 21:47:02 CEST 2019 + */ + +package com.formdev.flatlaf; + +import java.awt.*; +import javax.swing.*; +import javax.swing.border.*; +import com.jgoodies.forms.layout.*; +import net.miginfocom.swing.*; + +/** + * @author Karl Tauber + */ +public class FlatContainerTest + extends JPanel +{ + public static void main( String[] args ) { + FlatTestFrame frame = FlatTestFrame.create( args, "FlatContainerTest" ); + frame.showFrame( new FlatContainerTest() ); + } + + public FlatContainerTest() { + initComponents(); + } + + private void tabScrollChanged() { + int tabLayoutPolicy = tabScrollCheckBox.isSelected() ? JTabbedPane.SCROLL_TAB_LAYOUT : JTabbedPane.WRAP_TAB_LAYOUT; + tabbedPane1.setTabLayoutPolicy( tabLayoutPolicy ); + tabbedPane2.setTabLayoutPolicy( tabLayoutPolicy ); + tabbedPane3.setTabLayoutPolicy( tabLayoutPolicy ); + tabbedPane4.setTabLayoutPolicy( tabLayoutPolicy ); + } + + private void hasFullBorderChanged() { + Boolean hasFullBorder = hasFullBorderCheckBox.isSelected() ? true : null; + tabbedPane1.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder ); + tabbedPane2.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder ); + tabbedPane3.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder ); + tabbedPane4.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder ); + } + + private void moreTabsChanged() { + boolean moreTabs = moreTabsCheckBox.isSelected(); + addRemoveMoreTabs( tabbedPane1, moreTabs ); + addRemoveMoreTabs( tabbedPane2, moreTabs ); + addRemoveMoreTabs( tabbedPane3, moreTabs ); + addRemoveMoreTabs( tabbedPane4, moreTabs ); + } + + private void addRemoveMoreTabs( JTabbedPane tabbedPane, boolean add ) { + if( add ) { + tabbedPane.addTab( "Tab 4", new JLabel( "tab 4" ) ); + tabbedPane.addTab( "Tab 5", new JLabel( "tab 5" ) ); + } else { + int tabCount = tabbedPane.getTabCount(); + if( tabCount > 3 ) { + for( int i = 0; i < 2; i++ ) + tabbedPane.removeTabAt( tabbedPane.getTabCount() - 1 ); + } + } + } + + private void enabledChanged() { + boolean enabled = enabledCheckBox.isSelected(); + tabbedPane1.setEnabled( enabled ); + tabbedPane2.setEnabled( enabled ); + tabbedPane3.setEnabled( enabled ); + tabbedPane4.setEnabled( enabled ); + } + + private void initComponents() { + // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents + JPanel panel9 = new JPanel(); + JLabel tabbedPaneLabel = new JLabel(); + tabbedPane1 = new JTabbedPane(); + JPanel panel1 = new JPanel(); + JLabel label1 = new JLabel(); + JPanel panel2 = new JPanel(); + JLabel label2 = new JLabel(); + tabbedPane3 = new JTabbedPane(); + JPanel panel5 = new JPanel(); + JLabel label5 = new JLabel(); + JPanel panel6 = new JPanel(); + JLabel label6 = new JLabel(); + tabbedPane2 = new JTabbedPane(); + JPanel panel3 = new JPanel(); + JLabel label3 = new JLabel(); + JPanel panel4 = new JPanel(); + JLabel label4 = new JLabel(); + tabbedPane4 = new JTabbedPane(); + JPanel panel7 = new JPanel(); + JLabel label7 = new JLabel(); + JPanel panel8 = new JPanel(); + JLabel label8 = new JLabel(); + tabScrollCheckBox = new JCheckBox(); + hasFullBorderCheckBox = new JCheckBox(); + moreTabsCheckBox = new JCheckBox(); + enabledCheckBox = new JCheckBox(); + CellConstraints cc = new CellConstraints(); + + //======== this ======== + setLayout(new MigLayout( + "insets 0,hidemode 3", + // columns + "[grow,fill]" + + "[fill]", + // rows + "[grow,fill]" + + "[]")); + + //======== panel9 ======== + { + panel9.setLayout(new FormLayout( + "70dlu:grow, $lcgap, 70dlu:grow", + "pref, 2*($lgap, fill:70dlu:grow), 2*($lgap, pref)")); + + //---- tabbedPaneLabel ---- + tabbedPaneLabel.setText("JTabbedPane:"); + panel9.add(tabbedPaneLabel, cc.xy(1, 1)); + + //======== tabbedPane1 ======== + { + + //======== panel1 ======== + { + panel1.setLayout(new FlowLayout()); + + //---- label1 ---- + label1.setText("TOP"); + panel1.add(label1); + } + tabbedPane1.addTab("Tab 1", panel1); + + //======== panel2 ======== + { + panel2.setBorder(new LineBorder(Color.magenta)); + panel2.setLayout(new FlowLayout()); + } + tabbedPane1.addTab("Tab 2", panel2); + + //---- label2 ---- + label2.setText("text"); + tabbedPane1.addTab("Tab 3", label2); + } + panel9.add(tabbedPane1, cc.xy(1, 3)); + + //======== tabbedPane3 ======== + { + tabbedPane3.setTabPlacement(SwingConstants.LEFT); + + //======== panel5 ======== + { + panel5.setLayout(new FlowLayout()); + + //---- label5 ---- + label5.setText("LEFT"); + panel5.add(label5); + } + tabbedPane3.addTab("Tab 1", panel5); + + //======== panel6 ======== + { + panel6.setBorder(new LineBorder(Color.magenta)); + panel6.setLayout(new FlowLayout()); + } + tabbedPane3.addTab("Tab 2", panel6); + + //---- label6 ---- + label6.setText("text"); + tabbedPane3.addTab("Tab 3", label6); + } + panel9.add(tabbedPane3, cc.xy(3, 3)); + + //======== tabbedPane2 ======== + { + tabbedPane2.setTabPlacement(SwingConstants.BOTTOM); + + //======== panel3 ======== + { + panel3.setLayout(new FlowLayout()); + + //---- label3 ---- + label3.setText("BOTTOM"); + panel3.add(label3); + } + tabbedPane2.addTab("Tab 1", panel3); + + //======== panel4 ======== + { + panel4.setBorder(new LineBorder(Color.magenta)); + panel4.setLayout(new FlowLayout()); + } + tabbedPane2.addTab("Tab 2", panel4); + tabbedPane2.setEnabledAt(1, false); + + //---- label4 ---- + label4.setText("text"); + tabbedPane2.addTab("Tab 3", label4); + } + panel9.add(tabbedPane2, cc.xy(1, 5)); + + //======== tabbedPane4 ======== + { + tabbedPane4.setTabPlacement(SwingConstants.RIGHT); + + //======== panel7 ======== + { + panel7.setLayout(new FlowLayout()); + + //---- label7 ---- + label7.setText("RIGHT"); + panel7.add(label7); + } + tabbedPane4.addTab("Tab 1", panel7); + + //======== panel8 ======== + { + panel8.setBorder(new LineBorder(Color.magenta)); + panel8.setLayout(new FlowLayout()); + } + tabbedPane4.addTab("Tab 2", panel8); + + //---- label8 ---- + label8.setText("text"); + tabbedPane4.addTab("Tab 3", label8); + } + panel9.add(tabbedPane4, cc.xy(3, 5)); + + //---- tabScrollCheckBox ---- + tabScrollCheckBox.setText("tabLayoutPolicy = SCROLL"); + tabScrollCheckBox.setMnemonic('S'); + tabScrollCheckBox.addActionListener(e -> tabScrollChanged()); + panel9.add(tabScrollCheckBox, cc.xy(1, 7, CellConstraints.LEFT, CellConstraints.DEFAULT)); + + //---- hasFullBorderCheckBox ---- + hasFullBorderCheckBox.setText("JTabbedPane.hasFullBorder"); + hasFullBorderCheckBox.setMnemonic('F'); + hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged()); + panel9.add(hasFullBorderCheckBox, cc.xy(3, 7, CellConstraints.LEFT, CellConstraints.DEFAULT)); + + //---- moreTabsCheckBox ---- + moreTabsCheckBox.setText("more tabs"); + moreTabsCheckBox.setMnemonic('M'); + moreTabsCheckBox.addActionListener(e -> moreTabsChanged()); + panel9.add(moreTabsCheckBox, cc.xy(1, 9, CellConstraints.LEFT, CellConstraints.DEFAULT)); + + //---- enabledCheckBox ---- + enabledCheckBox.setText("enabled"); + enabledCheckBox.setSelected(true); + enabledCheckBox.setMnemonic('E'); + enabledCheckBox.addActionListener(e -> enabledChanged()); + panel9.add(enabledCheckBox, cc.xy(3, 9, CellConstraints.LEFT, CellConstraints.DEFAULT)); + } + add(panel9, "cell 0 0"); + // JFormDesigner - End of component initialization //GEN-END:initComponents + } + + // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + private JTabbedPane tabbedPane1; + private JTabbedPane tabbedPane3; + private JTabbedPane tabbedPane2; + private JTabbedPane tabbedPane4; + private JCheckBox tabScrollCheckBox; + private JCheckBox hasFullBorderCheckBox; + private JCheckBox moreTabsCheckBox; + private JCheckBox enabledCheckBox; + // JFormDesigner - End of variables declaration //GEN-END:variables +} diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatContainerTest.jfd b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatContainerTest.jfd new file mode 100644 index 00000000..7ad1cb56 --- /dev/null +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatContainerTest.jfd @@ -0,0 +1,211 @@ +JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8" + +new FormModel { + contentType: "form/swing" + root: new FormRoot { + auxiliary() { + "JavaCodeGenerator.defaultVariableLocal": true + } + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "insets 0,hidemode 3" + "$columnConstraints": "[grow,fill][fill]" + "$rowConstraints": "[grow,fill][]" + } ) { + name: "this" + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class com.jgoodies.forms.layout.FormLayout ) { + "$columnSpecs": "70dlu:grow, labelcompgap, 70dlu:grow" + "$rowSpecs": "pref, linegap, fill:70dlu:grow, linegap, fill:70dlu:grow, linegap, pref, linegap, pref" + } ) { + name: "panel9" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tabbedPaneLabel" + "text": "JTabbedPane:" + }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { + "gridX": 1 + "gridY": 1 + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "tabbedPane1" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { + name: "panel1" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label1" + "text": "TOP" + } ) + }, new FormLayoutConstraints( null ) { + "title": "Tab 1" + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { + name: "panel2" + "border": &LineBorder0 new javax.swing.border.LineBorder( sfield java.awt.Color magenta, 1, false ) + }, new FormLayoutConstraints( null ) { + "title": "Tab 2" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label2" + "text": "text" + }, new FormLayoutConstraints( null ) { + "title": "Tab 3" + } ) + }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { + "gridX": 1 + "gridY": 3 + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "tabbedPane3" + "tabPlacement": 2 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { + name: "panel5" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label5" + "text": "LEFT" + } ) + }, new FormLayoutConstraints( null ) { + "title": "Tab 1" + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { + name: "panel6" + "border": #LineBorder0 + }, new FormLayoutConstraints( null ) { + "title": "Tab 2" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label6" + "text": "text" + }, new FormLayoutConstraints( null ) { + "title": "Tab 3" + } ) + }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { + "gridX": 3 + "gridY": 3 + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "tabbedPane2" + "tabPlacement": 3 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { + name: "panel3" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label3" + "text": "BOTTOM" + } ) + }, new FormLayoutConstraints( null ) { + "title": "Tab 1" + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { + name: "panel4" + "border": #LineBorder0 + }, new FormLayoutConstraints( null ) { + "title": "Tab 2" + "enabled": false + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label4" + "text": "text" + }, new FormLayoutConstraints( null ) { + "title": "Tab 3" + } ) + }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { + "gridY": 5 + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "tabbedPane4" + "tabPlacement": 4 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { + name: "panel7" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label7" + "text": "RIGHT" + } ) + }, new FormLayoutConstraints( null ) { + "title": "Tab 1" + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { + name: "panel8" + "border": #LineBorder0 + }, new FormLayoutConstraints( null ) { + "title": "Tab 2" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label8" + "text": "text" + }, new FormLayoutConstraints( null ) { + "title": "Tab 3" + } ) + }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { + "gridX": 3 + "gridY": 5 + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "tabScrollCheckBox" + "text": "tabLayoutPolicy = SCROLL" + "mnemonic": 83 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabScrollChanged", false ) ) + }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { + "gridX": 1 + "gridY": 7 + "hAlign": sfield com.jgoodies.forms.layout.CellConstraints LEFT + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "hasFullBorderCheckBox" + "text": "JTabbedPane.hasFullBorder" + "mnemonic": 70 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) ) + }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { + "gridX": 3 + "gridY": 7 + "hAlign": sfield com.jgoodies.forms.layout.CellConstraints LEFT + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "moreTabsCheckBox" + "text": "more tabs" + "mnemonic": 77 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "moreTabsChanged", false ) ) + }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { + "gridX": 1 + "gridY": 9 + "hAlign": sfield com.jgoodies.forms.layout.CellConstraints LEFT + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "enabledCheckBox" + "text": "enabled" + "selected": true + "mnemonic": 69 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "enabledChanged", false ) ) + }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { + "gridX": 3 + "gridY": 9 + "hAlign": sfield com.jgoodies.forms.layout.CellConstraints LEFT + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + }, new FormLayoutConstraints( null ) { + "location": new java.awt.Point( 0, 0 ) + "size": new java.awt.Dimension( 400, 300 ) + } ) + } +} diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatTestFrame.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatTestFrame.java index a4fb42dc..3c5b84bb 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatTestFrame.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatTestFrame.java @@ -170,18 +170,7 @@ public class FlatTestFrame boolean explicit = explicitColorsCheckBox.isSelected(); ColorUIResource restoreColor = new ColorUIResource( Color.white ); - for( Component c : content.getComponents() ) { - c.setForeground( explicit ? Color.blue : restoreColor ); - c.setBackground( explicit ? Color.red : restoreColor ); - - if( c instanceof JScrollPane ) { - Component view = ((JScrollPane)c).getViewport().getView(); - if( view != null ) { - view.setForeground( explicit ? Color.magenta : restoreColor ); - view.setBackground( explicit ? Color.orange : restoreColor ); - } - } - } + explicitColors( content, explicit, restoreColor ); // because colors may depend on state (e.g. disabled JTextField) // it is best to update all UI delegates to get correct result @@ -190,6 +179,34 @@ public class FlatTestFrame } ); } + private void explicitColors( Container container, boolean explicit, ColorUIResource restoreColor ) { + for( Component c : container.getComponents() ) { + c.setForeground( explicit ? Color.blue : restoreColor ); + c.setBackground( explicit ? Color.red : restoreColor ); + + if( c instanceof JPanel ) + explicitColors( (JPanel) c, explicit, restoreColor ); + else if( c instanceof JScrollPane ) { + Component view = ((JScrollPane)c).getViewport().getView(); + if( view != null ) { + view.setForeground( explicit ? Color.magenta : restoreColor ); + view.setBackground( explicit ? Color.orange : restoreColor ); + } + } else if( c instanceof JTabbedPane ) { + JTabbedPane tabPane = (JTabbedPane)c; + int tabCount = tabPane.getTabCount(); + for( int i = 0; i < tabCount; i++ ) { + Component tab = tabPane.getComponentAt( i ); + if( tab != null ) { + tab.setForeground( explicit ? Color.magenta : restoreColor ); + tab.setBackground( explicit ? Color.orange : restoreColor ); + } + } + } + } + + } + private void rightToLeftChanged() { contentPanel.applyComponentOrientation( rightToLeftCheckBox.isSelected() ? ComponentOrientation.RIGHT_TO_LEFT diff --git a/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties b/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties index 2c088791..2f340412 100644 --- a/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties +++ b/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties @@ -123,3 +123,13 @@ Slider.disabledForeground=000088 #---- SplitPane ---- SplitPaneDivider.draggingColor=880000 + + +#---- TabbedPane ---- + +TabbedPane.disabledForeground=777777 +TabbedPane.underlineColor=4A88C7 +TabbedPane.disabledUnderlineColor=7a7a7a +TabbedPane.hoverColor=eeeeee +TabbedPane.focusColor=dddddd +TabbedPane.contentAreaColor=bbbbbb