diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java index d98150ae..3e1ea586 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java @@ -32,6 +32,7 @@ import java.util.ServiceLoader; import java.util.function.Function; import java.util.logging.Level; import javax.swing.UIDefaults; +import javax.swing.UIManager; import javax.swing.UIDefaults.ActiveValue; import javax.swing.UIDefaults.LazyValue; import javax.swing.plaf.ColorUIResource; @@ -227,6 +228,15 @@ class UIDefaultsLoader case "true": return true; } + // check for function "lazy" + // Syntax: lazy(uiKey) + if( value.startsWith( "lazy(" ) && value.endsWith( ")" ) ) { + String uiKey = value.substring( 5, value.length() - 1 ).trim(); + return (LazyValue) t -> { + return lazyUIManagerGet( uiKey ); + }; + } + ValueType valueType = ValueType.UNKNOWN; // check whether value type is specified in the value @@ -281,7 +291,7 @@ class UIDefaultsLoader case UNKNOWN: default: // colors - ColorUIResource color = parseColorOrFunction( value, resolver, false ); + Object color = parseColorOrFunction( value, resolver, false ); if( color != null ) return color; @@ -301,7 +311,7 @@ class UIDefaultsLoader List parts = split( value, ',' ); Insets insets = parseInsets( value ); ColorUIResource lineColor = (parts.size() == 5) - ? parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver, true ) + ? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver, true ) : null; return (LazyValue) t -> { @@ -377,7 +387,7 @@ class UIDefaultsLoader } } - private static ColorUIResource parseColorOrFunction( String value, Function resolver, boolean reportError ) { + private static Object parseColorOrFunction( String value, Function resolver, boolean reportError ) { if( value.endsWith( ")" ) ) return parseColorFunctions( value, resolver, reportError ); @@ -447,7 +457,7 @@ class UIDefaultsLoader : (((n >> 8) & 0xffffff) | ((n & 0xff) << 24)); // move alpha from lowest to highest byte } - private static ColorUIResource parseColorFunctions( String value, Function resolver, boolean reportError ) { + private static Object parseColorFunctions( String value, Function resolver, boolean reportError ) { int paramsStart = value.indexOf( '(' ); if( paramsStart < 0 ) { if( reportError ) @@ -511,9 +521,9 @@ class UIDefaultsLoader * Syntax: lighten([color,]amount[,options]) or darken([color,]amount[,options]) * - color: a color (e.g. #f00) or a color function * - amount: percentage 0-100% - * - options: [relative] [autoInverse] + * - options: [relative] [autoInverse] [lazy] */ - private static ColorUIResource parseColorLightenOrDarken( boolean lighten, List params, + private static Object parseColorLightenOrDarken( boolean lighten, List params, Function resolver, boolean reportError ) { boolean isDerived = params.get( 0 ).endsWith( "%" ); @@ -522,11 +532,13 @@ class UIDefaultsLoader int amount = parsePercentage( params.get( nextParam++ ) ); boolean relative = false; boolean autoInverse = false; + boolean lazy = false; if( params.size() > nextParam ) { String options = params.get( nextParam++ ); relative = options.contains( "relative" ); autoInverse = options.contains( "autoInverse" ); + lazy = options.contains( "lazy" ); } ColorFunctions.ColorFunction function = lighten @@ -536,7 +548,16 @@ class UIDefaultsLoader if( isDerived ) return new DerivedColor( function ); - ColorUIResource color = parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError ); + if( lazy ) { + return (LazyValue) t -> { + Object color = lazyUIManagerGet( colorStr ); + return (color instanceof Color) + ? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) ) + : null; + }; + } + + ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError ); return new ColorUIResource( ColorFunctions.applyFunctions( color, function ) ); } @@ -618,4 +639,21 @@ class UIDefaultsLoader return strs; } + + /** + * For use in LazyValue to get value for given key from UIManager and report error + * if not found. If key is prefixed by '?', then no error is reported. + */ + private static Object lazyUIManagerGet( String uiKey ) { + boolean optional = false; + if( uiKey.startsWith( OPTIONAL_PREFIX ) ) { + uiKey = uiKey.substring( OPTIONAL_PREFIX.length() ); + optional = true; + } + + Object value = UIManager.get( uiKey ); + if( value == null && !optional ) + FlatLaf.LOG.log( Level.SEVERE, "FlatLaf: '" + uiKey + "' not found in UI defaults." ); + return value; + } } 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 9abd79e0..c66fb7f6 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties @@ -35,6 +35,12 @@ @buttonHoverBackground=lighten(3%,autoInverse) @buttonPressedBackground=lighten(6%,autoInverse) +# Drop (use lazy colors for IntelliJ platform themes, which usually do not specify these colors) +@dropCellBackground=darken(List.selectionBackground,10%,lazy) +@dropCellForeground=lazy(List.selectionForeground) +@dropLineColor=lighten(List.selectionBackground,10%,lazy) +@dropLineShortColor=lighten(List.selectionBackground,30%,lazy) + #---- globals ---- 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 12304c0c..c4f72247 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -203,6 +203,9 @@ List.focusCellHighlightBorder=com.formdev.flatlaf.ui.FlatListCellBorder$Focused List.focusSelectedCellHighlightBorder=com.formdev.flatlaf.ui.FlatListCellBorder$Selected List.selectionInactiveBackground=@selectionInactiveBackground List.selectionInactiveForeground=@selectionInactiveForeground +List.dropCellBackground=@dropCellBackground +List.dropCellForeground=@dropCellForeground +List.dropLineColor=@dropLineColor #---- Menu ---- @@ -376,6 +379,10 @@ Table.cellNoFocusBorder=2,3,2,3 Table.focusSelectedCellHighlightBorder=2,3,2,3,@cellFocusColor Table.selectionInactiveBackground=@selectionInactiveBackground Table.selectionInactiveForeground=@selectionInactiveForeground +Table.dropCellBackground=@dropCellBackground +Table.dropCellForeground=@dropCellForeground +Table.dropLineColor=@dropLineColor +Table.dropLineShortColor=@dropLineShortColor #---- TableHeader ---- @@ -455,6 +462,9 @@ Tree.selectionInactiveBackground=@selectionInactiveBackground Tree.selectionInactiveForeground=@selectionInactiveForeground Tree.textBackground=null Tree.selectionBorderColor=@cellFocusColor +Tree.dropCellBackground=@dropCellBackground +Tree.dropCellForeground=@dropCellForeground +Tree.dropLineColor=@dropLineColor Tree.rendererMargins=1,2,1,2 Tree.wideSelection=true Tree.paintLines=false 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 174ddfaf..9733a667 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties @@ -35,6 +35,12 @@ @buttonHoverBackground=darken(3%,autoInverse) @buttonPressedBackground=darken(10%,autoInverse) +# Drop (use lazy colors for IntelliJ platform themes, which usually do not specify these colors) +@dropCellBackground=lighten(List.selectionBackground,10%,lazy) +@dropCellForeground=lazy(List.selectionForeground) +@dropLineColor=lighten(List.selectionBackground,20%,lazy) +@dropLineShortColor=darken(List.selectionBackground,20%,lazy) + #---- globals ---- diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.java index baa911f3..c46a0622 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.java @@ -16,6 +16,9 @@ package com.formdev.flatlaf.demo; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; import javax.swing.*; import javax.swing.table.*; import net.miginfocom.swing.*; @@ -30,22 +33,53 @@ class DataComponentsPanel initComponents(); } + private void dndChanged() { + boolean dnd = dndCheckBox.isSelected(); + list1.setDragEnabled( dnd ); + list2.setDragEnabled( dnd ); + tree1.setDragEnabled( dnd ); + tree2.setDragEnabled( dnd ); + table1.setDragEnabled( dnd ); + + DropMode dropMode = dnd ? DropMode.ON_OR_INSERT : DropMode.USE_SELECTION; + list1.setDropMode( dropMode ); + tree1.setDropMode( dropMode ); + table1.setDropMode( dropMode ); + + String key = "FlatLaf.oldTransferHandler"; + if( dnd ) { + list1.putClientProperty( key, list1.getTransferHandler() ); + list1.setTransferHandler( new DummyTransferHandler() ); + + tree1.putClientProperty( key, tree1.getTransferHandler() ); + tree1.setTransferHandler( new DummyTransferHandler() ); + + table1.putClientProperty( key, table1.getTransferHandler() ); + table1.setTransferHandler( new DummyTransferHandler() ); + } else { + list1.setTransferHandler( (TransferHandler) list1.getClientProperty( key ) ); + tree1.setTransferHandler( (TransferHandler) tree1.getClientProperty( key ) ); + table1.setTransferHandler( (TransferHandler) table1.getClientProperty( key ) ); + } + } + @SuppressWarnings( { "unchecked", "rawtypes" } ) private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents JLabel listLabel = new JLabel(); JScrollPane scrollPane1 = new JScrollPane(); - JList list1 = new JList<>(); + list1 = new JList<>(); JScrollPane scrollPane2 = new JScrollPane(); - JList list2 = new JList<>(); + list2 = new JList<>(); JLabel treeLabel = new JLabel(); JScrollPane scrollPane3 = new JScrollPane(); - JTree tree1 = new JTree(); + tree1 = new JTree(); JScrollPane scrollPane4 = new JScrollPane(); - JTree tree2 = new JTree(); + tree2 = new JTree(); JLabel tableLabel = new JLabel(); JScrollPane scrollPane5 = new JScrollPane(); - JTable table1 = new JTable(); + table1 = new JTable(); + dndCheckBox = new JCheckBox(); //======== this ======== setLayout(new MigLayout( @@ -57,7 +91,8 @@ class DataComponentsPanel // rows "[]" + "[::200]" + - "[::150]")); + "[::150]" + + "[]")); //---- listLabel ---- listLabel.setText("JList:"); @@ -65,15 +100,25 @@ class DataComponentsPanel //======== scrollPane1 ======== { - scrollPane1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - scrollPane1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); //---- list1 ---- list1.setModel(new AbstractListModel() { String[] values = { - "abc", - "de", - "f" + "item 1", + "item 2", + "item 3", + "item 4", + "item 5", + "item 6", + "item 7", + "item 8", + "item 9", + "item 10", + "item 11", + "item 12", + "item 13", + "item 14", + "item 15" }; @Override public int getSize() { return values.length; } @@ -86,15 +131,25 @@ class DataComponentsPanel //======== scrollPane2 ======== { - scrollPane2.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - scrollPane2.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); //---- list2 ---- list2.setModel(new AbstractListModel() { String[] values = { - "abc", - "de", - "f" + "item 1", + "item 2", + "item 3", + "item 4", + "item 5", + "item 6", + "item 7", + "item 8", + "item 9", + "item 10", + "item 11", + "item 12", + "item 13", + "item 14", + "item 15" }; @Override public int getSize() { return values.length; } @@ -115,6 +170,7 @@ class DataComponentsPanel //---- tree1 ---- tree1.setShowsRootHandles(true); + tree1.setEditable(true); scrollPane3.setViewportView(tree1); } add(scrollPane3, "cell 1 1,growx"); @@ -138,8 +194,18 @@ class DataComponentsPanel //---- table1 ---- table1.setModel(new DefaultTableModel( new Object[][] { - {"Item 1a", "Item 2a", "January", "July", 123, null}, - {"Item 1b", "Item 2b", "February", "August", 456, true}, + {"item 1", "item 1b", "January", "July", 123, null}, + {"item 2", "item 2b", "February", "August", 456, true}, + {"item 3", null, "March", null, null, null}, + {"item 4", null, "April", null, null, null}, + {"item 5", null, "May", null, null, null}, + {"item 6", null, "June", null, null, null}, + {"item 7", null, "July", null, null, null}, + {"item 8", null, "August", null, null, null}, + {"item 9", null, "September", null, null, null}, + {"item 10", null, "October", null, null, null}, + {"item 11", null, "November", null, null, null}, + {"item 12", null, "December", null, null, null}, }, new String[] { "Not editable", "Text", "Combo", "Combo Editable", "Integer", "Boolean" @@ -197,11 +263,60 @@ class DataComponentsPanel scrollPane5.setViewportView(table1); } add(scrollPane5, "cell 1 2 2 1,growx,width 300"); + + //---- dndCheckBox ---- + dndCheckBox.setText("enable drag and drop"); + dndCheckBox.setMnemonic('D'); + dndCheckBox.addActionListener(e -> dndChanged()); + add(dndCheckBox, "cell 0 3 3 1"); // JFormDesigner - End of component initialization //GEN-END:initComponents ((JComboBox)((DefaultCellEditor)table1.getColumnModel().getColumn( 3 ).getCellEditor()).getComponent()).setEditable( true ); } // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + private JList list1; + private JList list2; + private JTree tree1; + private JTree tree2; + private JTable table1; + private JCheckBox dndCheckBox; // JFormDesigner - End of variables declaration //GEN-END:variables + + //---- class DummyTransferHandler ----------------------------------------- + + private static class DummyTransferHandler + extends TransferHandler + { + @Override + protected Transferable createTransferable( JComponent c ) { + if( c instanceof JList && ((JList)c).isSelectionEmpty() ) + return null; + if( c instanceof JTree && ((JTree)c).isSelectionEmpty() ) + return null; + if( c instanceof JTable && ((JTable)c).getSelectionModel().isSelectionEmpty() ) + return null; + + return new StringSelection( "dummy" ); + } + + @Override + public int getSourceActions( JComponent c ) { + return COPY; + } + + @Override + public boolean canImport( TransferSupport support ) { + return support.isDataFlavorSupported( DataFlavor.stringFlavor ); + } + + @Override + public boolean importData( TransferSupport support ) { + String message = String.valueOf( support.getDropLocation() ); + SwingUtilities.invokeLater( () -> { + JOptionPane.showMessageDialog( null, message, "Drop", JOptionPane.PLAIN_MESSAGE ); + } ); + return false; + } + } } diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.jfd b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.jfd index 529ac308..42599f18 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.jfd +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.jfd @@ -9,7 +9,7 @@ new FormModel { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "hidemode 3" "$columnConstraints": "[][200][200]" - "$rowConstraints": "[][::200][::150]" + "$rowConstraints": "[][::200][::150][]" } ) { name: "this" add( new FormComponent( "javax.swing.JLabel" ) { @@ -20,17 +20,28 @@ new FormModel { } ) add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { name: "scrollPane1" - "verticalScrollBarPolicy": 21 - "horizontalScrollBarPolicy": 31 add( new FormComponent( "javax.swing.JList" ) { name: "list1" - "model": &DefaultListModel0 new javax.swing.DefaultListModel { - addElement( "abc" ) - addElement( "de" ) - addElement( "f" ) + "model": new javax.swing.DefaultListModel { + addElement( "item 1" ) + addElement( "item 2" ) + addElement( "item 3" ) + addElement( "item 4" ) + addElement( "item 5" ) + addElement( "item 6" ) + addElement( "item 7" ) + addElement( "item 8" ) + addElement( "item 9" ) + addElement( "item 10" ) + addElement( "item 11" ) + addElement( "item 12" ) + addElement( "item 13" ) + addElement( "item 14" ) + addElement( "item 15" ) } auxiliary() { "JavaCodeGenerator.typeParameters": "String" + "JavaCodeGenerator.variableLocal": false } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { @@ -38,14 +49,29 @@ new FormModel { } ) add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { name: "scrollPane2" - "verticalScrollBarPolicy": 21 - "horizontalScrollBarPolicy": 31 add( new FormComponent( "javax.swing.JList" ) { name: "list2" - "model": #DefaultListModel0 + "model": new javax.swing.DefaultListModel { + addElement( "item 1" ) + addElement( "item 2" ) + addElement( "item 3" ) + addElement( "item 4" ) + addElement( "item 5" ) + addElement( "item 6" ) + addElement( "item 7" ) + addElement( "item 8" ) + addElement( "item 9" ) + addElement( "item 10" ) + addElement( "item 11" ) + addElement( "item 12" ) + addElement( "item 13" ) + addElement( "item 14" ) + addElement( "item 15" ) + } "enabled": false auxiliary() { "JavaCodeGenerator.typeParameters": "String" + "JavaCodeGenerator.variableLocal": false } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { @@ -62,6 +88,10 @@ new FormModel { add( new FormComponent( "javax.swing.JTree" ) { name: "tree1" "showsRootHandles": true + "editable": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 1,growx" @@ -71,6 +101,9 @@ new FormModel { add( new FormComponent( "javax.swing.JTree" ) { name: "tree2" "enabled": false + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 1,growx" @@ -87,21 +120,101 @@ new FormModel { name: "table1" "model": new com.jformdesigner.model.SwingTableModel( new java.util.Vector { add( new java.util.Vector { - add( "Item 1a" ) - add( "Item 2a" ) + add( "item 1" ) + add( "item 1b" ) add( "January" ) add( "July" ) add( 123 ) add( null ) } ) add( new java.util.Vector { - add( "Item 1b" ) - add( "Item 2b" ) + add( "item 2" ) + add( "item 2b" ) add( "February" ) add( "August" ) add( 456 ) add( true ) } ) + add( new java.util.Vector { + add( "item 3" ) + add( null ) + add( "March" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 4" ) + add( null ) + add( "April" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 5" ) + add( null ) + add( "May" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 6" ) + add( null ) + add( "June" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 7" ) + add( null ) + add( "July" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 8" ) + add( null ) + add( "August" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 9" ) + add( null ) + add( "September" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 10" ) + add( null ) + add( "October" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 11" ) + add( null ) + add( "November" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 12" ) + add( null ) + add( "December" ) + add( null ) + add( null ) + add( null ) + } ) }, new java.util.Vector { add( "Not editable" ) add( "Text" ) @@ -132,10 +245,24 @@ new FormModel { add( null ) } ) "autoCreateRowSorter": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 2 2 1,growx,width 300" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "dndCheckBox" + "text": "enable drag and drop" + "mnemonic": 68 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "dndChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 3 3 1" + } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) "size": new java.awt.Dimension( 790, 715 ) diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.java index 74093cfa..f050e511 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.java @@ -16,6 +16,9 @@ package com.formdev.flatlaf.testing; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; import javax.swing.*; import javax.swing.table.*; import net.miginfocom.swing.*; @@ -37,28 +40,56 @@ public class FlatComponents2Test initComponents(); } + private void dndChanged() { + boolean dnd = dndCheckBox.isSelected(); + list1.setDragEnabled( dnd ); + list2.setDragEnabled( dnd ); + tree1.setDragEnabled( dnd ); + tree2.setDragEnabled( dnd ); + table1.setDragEnabled( dnd ); + + DropMode dropMode = dnd ? DropMode.ON_OR_INSERT : DropMode.USE_SELECTION; + list1.setDropMode( dropMode ); + tree1.setDropMode( dropMode ); + table1.setDropMode( dropMode ); + + String key = "FlatLaf.oldTransferHandler"; + if( dnd ) { + list1.putClientProperty( key, list1.getTransferHandler() ); + list1.setTransferHandler( new DummyTransferHandler() ); + + tree1.putClientProperty( key, tree1.getTransferHandler() ); + tree1.setTransferHandler( new DummyTransferHandler() ); + + table1.putClientProperty( key, table1.getTransferHandler() ); + table1.setTransferHandler( new DummyTransferHandler() ); + } else { + list1.setTransferHandler( (TransferHandler) list1.getClientProperty( key ) ); + tree1.setTransferHandler( (TransferHandler) tree1.getClientProperty( key ) ); + table1.setTransferHandler( (TransferHandler) table1.getClientProperty( key ) ); + } + } + @SuppressWarnings( { "unchecked", "rawtypes" } ) private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents - JLabel labelLabel = new JLabel(); - JLabel label1 = new JLabel(); - JLabel label2 = new JLabel(); JLabel textFieldLabel = new JLabel(); JTextField textField1 = new JTextField(); JTextField textField2 = new JTextField(); JLabel listLabel = new JLabel(); JScrollPane scrollPane1 = new JScrollPane(); - JList list1 = new JList<>(); + list1 = new JList<>(); JScrollPane scrollPane2 = new JScrollPane(); - JList list2 = new JList<>(); + list2 = new JList<>(); JLabel treeLabel = new JLabel(); JScrollPane scrollPane3 = new JScrollPane(); - JTree tree1 = new JTree(); + tree1 = new JTree(); JScrollPane scrollPane4 = new JScrollPane(); - JTree tree2 = new JTree(); + tree2 = new JTree(); JLabel tableLabel = new JLabel(); JScrollPane scrollPane5 = new JScrollPane(); - JTable table1 = new JTable(); + table1 = new JTable(); + dndCheckBox = new JCheckBox(); //======== this ======== setLayout(new MigLayout( @@ -70,53 +101,48 @@ public class FlatComponents2Test // rows "[]" + "[]" + - "[]" + "[::200]" + - "[::150]")); - - //---- labelLabel ---- - labelLabel.setText("JLabel:"); - add(labelLabel, "cell 0 0"); - - //---- label1 ---- - label1.setText("enabled"); - label1.setDisplayedMnemonic('E'); - add(label1, "cell 1 0"); - - //---- label2 ---- - label2.setText("disabled"); - label2.setDisplayedMnemonic('D'); - label2.setEnabled(false); - add(label2, "cell 2 0"); + "[::150]" + + "[]")); //---- textFieldLabel ---- textFieldLabel.setText("JTextField:"); - add(textFieldLabel, "cell 0 1"); + add(textFieldLabel, "cell 0 0"); //---- textField1 ---- textField1.setText("editable"); - add(textField1, "cell 1 1,growx"); + add(textField1, "cell 1 0,growx"); //---- textField2 ---- textField2.setText("disabled"); textField2.setEnabled(false); - add(textField2, "cell 2 1,growx"); + add(textField2, "cell 2 0,growx"); //---- listLabel ---- listLabel.setText("JList:"); - add(listLabel, "cell 0 2"); + add(listLabel, "cell 0 1"); //======== scrollPane1 ======== { - scrollPane1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - scrollPane1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); //---- list1 ---- list1.setModel(new AbstractListModel() { String[] values = { - "abc", - "de", - "f" + "item 1", + "item 2", + "item 3", + "item 4", + "item 5", + "item 6", + "item 7", + "item 8", + "item 9", + "item 10", + "item 11", + "item 12", + "item 13", + "item 14", + "item 15" }; @Override public int getSize() { return values.length; } @@ -125,19 +151,29 @@ public class FlatComponents2Test }); scrollPane1.setViewportView(list1); } - add(scrollPane1, "cell 1 2,growx"); + add(scrollPane1, "cell 1 1,growx"); //======== scrollPane2 ======== { - scrollPane2.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - scrollPane2.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); //---- list2 ---- list2.setModel(new AbstractListModel() { String[] values = { - "abc", - "de", - "f" + "item 1", + "item 2", + "item 3", + "item 4", + "item 5", + "item 6", + "item 7", + "item 8", + "item 9", + "item 10", + "item 11", + "item 12", + "item 13", + "item 14", + "item 15" }; @Override public int getSize() { return values.length; } @@ -147,11 +183,11 @@ public class FlatComponents2Test list2.setEnabled(false); scrollPane2.setViewportView(list2); } - add(scrollPane2, "cell 2 2,growx"); + add(scrollPane2, "cell 2 1,growx"); //---- treeLabel ---- treeLabel.setText("JTree:"); - add(treeLabel, "cell 0 3"); + add(treeLabel, "cell 0 2"); //======== scrollPane3 ======== { @@ -161,7 +197,7 @@ public class FlatComponents2Test tree1.setEditable(true); scrollPane3.setViewportView(tree1); } - add(scrollPane3, "cell 1 3,growx"); + add(scrollPane3, "cell 1 2,growx"); //======== scrollPane4 ======== { @@ -170,11 +206,11 @@ public class FlatComponents2Test tree2.setEnabled(false); scrollPane4.setViewportView(tree2); } - add(scrollPane4, "cell 2 3,growx"); + add(scrollPane4, "cell 2 2,growx"); //---- tableLabel ---- tableLabel.setText("JTable:"); - add(tableLabel, "cell 0 4"); + add(tableLabel, "cell 0 3"); //======== scrollPane5 ======== { @@ -182,8 +218,18 @@ public class FlatComponents2Test //---- table1 ---- table1.setModel(new DefaultTableModel( new Object[][] { - {"Item 1a", "Item 2a", "January", "July", 123, null}, - {"Item 1b", "Item 2b", "February", "August", 456, true}, + {"item 1", "item 1b", "January", "July", 123, null}, + {"item 2", "item 2b", "February", "August", 456, true}, + {"item 3", null, "March", null, null, null}, + {"item 4", null, "April", null, null, null}, + {"item 5", null, "May", null, null, null}, + {"item 6", null, "June", null, null, null}, + {"item 7", null, "July", null, null, null}, + {"item 8", null, "August", null, null, null}, + {"item 9", null, "September", null, null, null}, + {"item 10", null, "October", null, null, null}, + {"item 11", null, "November", null, null, null}, + {"item 12", null, "December", null, null, null}, }, new String[] { "Not editable", "Text", "Combo", "Combo Editable", "Integer", "Boolean" @@ -240,12 +286,58 @@ public class FlatComponents2Test table1.setAutoCreateRowSorter(true); scrollPane5.setViewportView(table1); } - add(scrollPane5, "cell 1 4 2 1,growx,width 300"); + add(scrollPane5, "cell 1 3 2 1,growx,width 300"); + + //---- dndCheckBox ---- + dndCheckBox.setText("enable drag and drop"); + dndCheckBox.setMnemonic('D'); + dndCheckBox.addActionListener(e -> dndChanged()); + add(dndCheckBox, "cell 0 4 3 1"); // JFormDesigner - End of component initialization //GEN-END:initComponents ((JComboBox)((DefaultCellEditor)table1.getColumnModel().getColumn( 3 ).getCellEditor()).getComponent()).setEditable( true ); } // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + private JList list1; + private JList list2; + private JTree tree1; + private JTree tree2; + private JTable table1; + private JCheckBox dndCheckBox; // JFormDesigner - End of variables declaration //GEN-END:variables + + //---- class DummyTransferHandler ----------------------------------------- + + private static class DummyTransferHandler + extends TransferHandler + { + @Override + protected Transferable createTransferable( JComponent c ) { + if( c instanceof JList && ((JList)c).isSelectionEmpty() ) + return null; + if( c instanceof JTree && ((JTree)c).isSelectionEmpty() ) + return null; + if( c instanceof JTable && ((JTable)c).getSelectionModel().isSelectionEmpty() ) + return null; + + return new StringSelection( "dummy" ); + } + + @Override + public int getSourceActions( JComponent c ) { + return COPY; + } + + @Override + public boolean canImport( TransferSupport support ) { + return support.isDataFlavorSupported( DataFlavor.stringFlavor ); + } + + @Override + public boolean importData( TransferSupport support ) { + System.out.println( support.getDropLocation() ); + return false; + } + } } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.jfd index bd6dd617..62f281b8 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.jfd @@ -9,93 +9,98 @@ new FormModel { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "ltr,insets dialog,hidemode 3" "$columnConstraints": "[][200][200]" - "$rowConstraints": "[][][][::200][::150]" + "$rowConstraints": "[][][::200][::150][]" } ) { name: "this" - add( new FormComponent( "javax.swing.JLabel" ) { - name: "labelLabel" - "text": "JLabel:" - }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 0" - } ) - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label1" - "text": "enabled" - "displayedMnemonic": 69 - }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 0" - } ) - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label2" - "text": "disabled" - "displayedMnemonic": 68 - "enabled": false - }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 0" - } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "textFieldLabel" "text": "JTextField:" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 1" + "value": "cell 0 0" } ) add( new FormComponent( "javax.swing.JTextField" ) { name: "textField1" "text": "editable" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 1,growx" + "value": "cell 1 0,growx" } ) add( new FormComponent( "javax.swing.JTextField" ) { name: "textField2" "text": "disabled" "enabled": false }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 1,growx" + "value": "cell 2 0,growx" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "listLabel" "text": "JList:" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 2" + "value": "cell 0 1" } ) add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { name: "scrollPane1" - "verticalScrollBarPolicy": 21 - "horizontalScrollBarPolicy": 31 add( new FormComponent( "javax.swing.JList" ) { name: "list1" - "model": &DefaultListModel0 new javax.swing.DefaultListModel { - addElement( "abc" ) - addElement( "de" ) - addElement( "f" ) + "model": new javax.swing.DefaultListModel { + addElement( "item 1" ) + addElement( "item 2" ) + addElement( "item 3" ) + addElement( "item 4" ) + addElement( "item 5" ) + addElement( "item 6" ) + addElement( "item 7" ) + addElement( "item 8" ) + addElement( "item 9" ) + addElement( "item 10" ) + addElement( "item 11" ) + addElement( "item 12" ) + addElement( "item 13" ) + addElement( "item 14" ) + addElement( "item 15" ) } auxiliary() { "JavaCodeGenerator.typeParameters": "String" + "JavaCodeGenerator.variableLocal": false } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 2,growx" + "value": "cell 1 1,growx" } ) add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { name: "scrollPane2" - "verticalScrollBarPolicy": 21 - "horizontalScrollBarPolicy": 31 add( new FormComponent( "javax.swing.JList" ) { name: "list2" - "model": #DefaultListModel0 + "model": new javax.swing.DefaultListModel { + addElement( "item 1" ) + addElement( "item 2" ) + addElement( "item 3" ) + addElement( "item 4" ) + addElement( "item 5" ) + addElement( "item 6" ) + addElement( "item 7" ) + addElement( "item 8" ) + addElement( "item 9" ) + addElement( "item 10" ) + addElement( "item 11" ) + addElement( "item 12" ) + addElement( "item 13" ) + addElement( "item 14" ) + addElement( "item 15" ) + } "enabled": false auxiliary() { "JavaCodeGenerator.typeParameters": "String" + "JavaCodeGenerator.variableLocal": false } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 2,growx" + "value": "cell 2 1,growx" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "treeLabel" "text": "JTree:" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 3" + "value": "cell 0 2" } ) add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { name: "scrollPane3" @@ -103,24 +108,30 @@ new FormModel { name: "tree1" "showsRootHandles": true "editable": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 3,growx" + "value": "cell 1 2,growx" } ) add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { name: "scrollPane4" add( new FormComponent( "javax.swing.JTree" ) { name: "tree2" "enabled": false + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 3,growx" + "value": "cell 2 2,growx" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "tableLabel" "text": "JTable:" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 4" + "value": "cell 0 3" } ) add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { name: "scrollPane5" @@ -128,21 +139,101 @@ new FormModel { name: "table1" "model": new com.jformdesigner.model.SwingTableModel( new java.util.Vector { add( new java.util.Vector { - add( "Item 1a" ) - add( "Item 2a" ) + add( "item 1" ) + add( "item 1b" ) add( "January" ) add( "July" ) add( 123 ) add( null ) } ) add( new java.util.Vector { - add( "Item 1b" ) - add( "Item 2b" ) + add( "item 2" ) + add( "item 2b" ) add( "February" ) add( "August" ) add( 456 ) add( true ) } ) + add( new java.util.Vector { + add( "item 3" ) + add( null ) + add( "March" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 4" ) + add( null ) + add( "April" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 5" ) + add( null ) + add( "May" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 6" ) + add( null ) + add( "June" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 7" ) + add( null ) + add( "July" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 8" ) + add( null ) + add( "August" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 9" ) + add( null ) + add( "September" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 10" ) + add( null ) + add( "October" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 11" ) + add( null ) + add( "November" ) + add( null ) + add( null ) + add( null ) + } ) + add( new java.util.Vector { + add( "item 12" ) + add( null ) + add( "December" ) + add( null ) + add( null ) + add( null ) + } ) }, new java.util.Vector { add( "Not editable" ) add( "Text" ) @@ -173,9 +264,23 @@ new FormModel { add( null ) } ) "autoCreateRowSorter": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 4 2 1,growx,width 300" + "value": "cell 1 3 2 1,growx,width 300" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "dndCheckBox" + "text": "enable drag and drop" + "mnemonic": 68 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "dndChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 4 3 1" } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties index aedae037..f3fa729e 100644 --- a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties +++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties @@ -27,6 +27,11 @@ @cellFocusColor=#ff0000 @icon=#afafaf +@dropCellBackground=#f00 +@dropCellForeground=#0f0 +@dropLineColor=#00f +@dropLineShortColor=#ff0 + #---- globals ----