diff --git a/CHANGELOG.md b/CHANGELOG.md index d55a88a4..80f6ba98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ FlatLaf Change Log box in IntelliJ/Darcula themes. - TableHeader: Fixed exception when changing table structure (e.g. removing column) from a table header popup menu action. (issue #532) +- `HiDPIUtils.paintAtScale1x()` now supports rotated graphics. (issue #557) ## 2.3 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/HiDPIUtils.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/HiDPIUtils.java index 858f1954..c4671518 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/HiDPIUtils.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/HiDPIUtils.java @@ -48,30 +48,55 @@ public class HiDPIUtils */ public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height, Painter painter ) { // save original transform - AffineTransform transform = g.getTransform(); + AffineTransform t = g.getTransform(); + + // get scale X/Y and shear X/Y + double scaleX = t.getScaleX(); + double scaleY = t.getScaleY(); + double shearX = t.getShearX(); + double shearY = t.getShearY(); + + // check whether rotated + // (also check for negative scale X/Y because shear X/Y are zero for 180 degrees rotation) + boolean rotated = (shearX != 0 || shearY != 0 || scaleX <= 0 || scaleY <= 0); + if( rotated ) { + // resulting scale X/Y values are always positive + scaleX = Math.hypot( scaleX, shearX ); + scaleY = Math.hypot( scaleY, shearY ); + } else { + // make scale X/Y positive + scaleX = Math.abs( scaleX ); + scaleY = Math.abs( scaleY ); + } // check whether scaled - if( transform.getScaleX() == 1 && transform.getScaleY() == 1 ) { + if( scaleX == 1 && scaleY == 1 ) { painter.paint( g, x, y, width, height, 1 ); return; } // scale rectangle - Rectangle2D.Double scaledRect = scale( transform, x, y, width, height ); + Rectangle2D.Double scaledRect = scale( scaleX, scaleY, t, x, y, width, height ); try { - // unscale to factor 1.0 and move origin (to whole numbers) - g.setTransform( new AffineTransform( 1, 0, 0, 1, - Math.floor( scaledRect.x ), Math.floor( scaledRect.y ) ) ); + // unscale to factor 1.0, keep rotation and move origin (to whole numbers) + AffineTransform t1x; + if( rotated ) { + t1x = new AffineTransform( t.getScaleX(), t.getShearY(), t.getShearX(), t.getScaleY(), + Math.floor( scaledRect.x ), Math.floor( scaledRect.y ) ); + t1x.scale( 1. / scaleX, 1. / scaleY ); + } else + t1x = new AffineTransform( 1, 0, 0, 1, Math.floor( scaledRect.x ), Math.floor( scaledRect.y ) ); + g.setTransform( t1x ); int swidth = (int) scaledRect.width; int sheight = (int) scaledRect.height; // paint - painter.paint( g, 0, 0, swidth, sheight, transform.getScaleX() ); + painter.paint( g, 0, 0, swidth, sheight, scaleX ); } finally { // restore original transform - g.setTransform( transform ); + g.setTransform( t ); } } @@ -80,12 +105,9 @@ public class HiDPIUtils * sun.java2d.pipe.PixelToParallelogramConverter.fillRectangle(), * which is used by Graphics.fillRect(). */ - private static Rectangle2D.Double scale( AffineTransform transform, int x, int y, int width, int height ) { - double scaleX = transform.getScaleX(); - double scaleY = transform.getScaleY(); - - double px = (x * scaleX) + transform.getTranslateX(); - double py = (y * scaleY) + transform.getTranslateY(); + private static Rectangle2D.Double scale( double scaleX, double scaleY, AffineTransform t, int x, int y, int width, int height ) { + double px = (x * scaleX) + t.getTranslateX(); + double py = (y * scaleY) + t.getTranslateY(); double newX = normalize( px ); double newY = normalize( py ); diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingHiDPITest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingHiDPITest.java new file mode 100644 index 00000000..20fc53c5 --- /dev/null +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingHiDPITest.java @@ -0,0 +1,376 @@ +/* + * Copyright 2022 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 + * + * https://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.testing; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import javax.swing.*; +import com.formdev.flatlaf.ui.FlatUIUtils; +import com.formdev.flatlaf.util.HiDPIUtils; +import net.miginfocom.swing.*; + +/** + * @author Karl Tauber + */ +public class FlatPaintingHiDPITest + extends JPanel +{ + public static void main( String[] args ) { + SwingUtilities.invokeLater( () -> { + FlatTestFrame frame = FlatTestFrame.create( args, "FlatPaintingHiDPITest" ); + frame.showFrame( FlatPaintingHiDPITest::new ); + } ); + } + + FlatPaintingHiDPITest() { + initComponents(); + sliderChanged(); + } + + private void sliderChanged() { + painter.translateX = translateXSlider.getValue(); + painter.translateY = translateYSlider.getValue(); + painter.scaleX = scaleXSlider.getValue(); + painter.scaleY = scaleYSlider.getValue(); + painter.rotate = rotateSlider.getValue(); + painter.repaint(); + + AffineTransform t = new AffineTransform(); + t.translate( painter.translateX, painter.translateY ); + t.scale( painter.scaleX / 100., painter.scaleY / 100. ); + t.rotate( Math.toRadians( painter.rotate ) ); + + tScaleXLabel.setText( Double.toString( t.getScaleX() ) ); + tScaleYLabel.setText( Double.toString( t.getScaleY() ) ); + tShearXLabel.setText( Double.toString( t.getShearX() ) ); + tShearYLabel.setText( Double.toString( t.getShearY() ) ); + tTranslateXLabel.setText( Double.toString( t.getTranslateX() ) ); + tTranslateYLabel.setText( Double.toString( t.getTranslateY() ) ); + + double scaleX = Math.hypot( t.getScaleX(), t.getShearX() ); + double scaleY = Math.hypot( t.getScaleY(), t.getShearY() ); + if( t.getScaleX() < 0 ) + scaleX = -scaleX; + if( t.getScaleY() < 0 ) + scaleY = -scaleY; + + double rotation = Math.atan2( t.getShearY(), t.getScaleY() ); + double rotationDegrees = Math.toDegrees( rotation ); + cScaleXLabel.setText( Double.toString( scaleX ) ); + cScaleYLabel.setText( Double.toString( scaleY ) ); + cRotationDegreesLabel.setText( Double.toString( rotationDegrees ) ); + } + + private void reset() { + translateXSlider.setValue( 100 ); + translateYSlider.setValue( 100 ); + scaleXSlider.setValue( 100 ); + scaleYSlider.setValue( 100 ); + rotateSlider.setValue( 0 ); + } + + private void initComponents() { + // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents + JLabel translateXLabel = new JLabel(); + translateXSlider = new JSlider(); + JLabel translateYLabel = new JLabel(); + translateYSlider = new JSlider(); + JLabel scaleXLabel = new JLabel(); + scaleXSlider = new JSlider(); + JLabel scaleYLabel = new JLabel(); + scaleYSlider = new JSlider(); + JLabel rotateLabel = new JLabel(); + rotateSlider = new JSlider(); + JPanel panel1 = new JPanel(); + JLabel tLabel = new JLabel(); + JLabel xLabel = new JLabel(); + JLabel yLabel = new JLabel(); + JLabel tScaleLabel = new JLabel(); + tScaleXLabel = new JLabel(); + tScaleYLabel = new JLabel(); + JLabel tShearLabel = new JLabel(); + tShearXLabel = new JLabel(); + tShearYLabel = new JLabel(); + JLabel tTranslateLabel = new JLabel(); + tTranslateXLabel = new JLabel(); + tTranslateYLabel = new JLabel(); + JLabel cLabel = new JLabel(); + JLabel cScaleLabel = new JLabel(); + cScaleXLabel = new JLabel(); + cScaleYLabel = new JLabel(); + JLabel cRotationLabel = new JLabel(); + cRotationDegreesLabel = new JLabel(); + JButton resetButton = new JButton(); + painter = new FlatPaintingHiDPITest.HiDPI1xPainter(); + + //======== this ======== + setBorder(null); + setLayout(new MigLayout( + "hidemode 3", + // columns + "[fill]" + + "[400,fill]para" + + "[grow,fill]", + // rows + "[fill]" + + "[]" + + "[]" + + "[]" + + "[]" + + "[grow]")); + + //---- translateXLabel ---- + translateXLabel.setText("TranslateX:"); + add(translateXLabel, "cell 0 0"); + + //---- translateXSlider ---- + translateXSlider.setMaximum(500); + translateXSlider.setPaintLabels(true); + translateXSlider.setPaintTicks(true); + translateXSlider.setMajorTickSpacing(100); + translateXSlider.setMinorTickSpacing(25); + translateXSlider.setValue(100); + translateXSlider.addChangeListener(e -> sliderChanged()); + add(translateXSlider, "cell 1 0"); + + //---- translateYLabel ---- + translateYLabel.setText("TranslateY:"); + add(translateYLabel, "cell 0 1"); + + //---- translateYSlider ---- + translateYSlider.setMaximum(500); + translateYSlider.setPaintLabels(true); + translateYSlider.setPaintTicks(true); + translateYSlider.setMajorTickSpacing(100); + translateYSlider.setMinorTickSpacing(25); + translateYSlider.setValue(100); + translateYSlider.addChangeListener(e -> sliderChanged()); + add(translateYSlider, "cell 1 1"); + + //---- scaleXLabel ---- + scaleXLabel.setText("ScaleX:"); + add(scaleXLabel, "cell 0 2"); + + //---- scaleXSlider ---- + scaleXSlider.setMaximum(300); + scaleXSlider.setValue(100); + scaleXSlider.setPaintTicks(true); + scaleXSlider.setPaintLabels(true); + scaleXSlider.setMajorTickSpacing(50); + scaleXSlider.setSnapToTicks(true); + scaleXSlider.setMinorTickSpacing(10); + scaleXSlider.setMinimum(-100); + scaleXSlider.addChangeListener(e -> sliderChanged()); + add(scaleXSlider, "cell 1 2"); + + //---- scaleYLabel ---- + scaleYLabel.setText("ScaleY:"); + add(scaleYLabel, "cell 0 3"); + + //---- scaleYSlider ---- + scaleYSlider.setMaximum(300); + scaleYSlider.setValue(100); + scaleYSlider.setPaintTicks(true); + scaleYSlider.setPaintLabels(true); + scaleYSlider.setMajorTickSpacing(50); + scaleYSlider.setSnapToTicks(true); + scaleYSlider.setMinorTickSpacing(10); + scaleYSlider.setMinimum(-100); + scaleYSlider.addChangeListener(e -> sliderChanged()); + add(scaleYSlider, "cell 1 3"); + + //---- rotateLabel ---- + rotateLabel.setText("Rotate:"); + add(rotateLabel, "cell 0 4"); + + //---- rotateSlider ---- + rotateSlider.setMaximum(360); + rotateSlider.setMinimum(-360); + rotateSlider.setValue(0); + rotateSlider.setMajorTickSpacing(90); + rotateSlider.setPaintLabels(true); + rotateSlider.setPaintTicks(true); + rotateSlider.addChangeListener(e -> sliderChanged()); + add(rotateSlider, "cell 1 4"); + + //======== panel1 ======== + { + panel1.setLayout(new MigLayout( + "hidemode 3", + // columns + "[fill]" + + "[50,fill]" + + "[50,fill]", + // rows + "[]" + + "[]0" + + "[]0" + + "[]para" + + "[]" + + "[]0" + + "[]")); + + //---- tLabel ---- + tLabel.setText("AffineTransform:"); + panel1.add(tLabel, "cell 0 0"); + + //---- xLabel ---- + xLabel.setText("X"); + panel1.add(xLabel, "cell 1 0,alignx center,growx 0"); + + //---- yLabel ---- + yLabel.setText("Y"); + panel1.add(yLabel, "cell 2 0,alignx center,growx 0"); + + //---- tScaleLabel ---- + tScaleLabel.setText("Scale:"); + panel1.add(tScaleLabel, "cell 0 1,gapx indent"); + + //---- tScaleXLabel ---- + tScaleXLabel.setText("text"); + panel1.add(tScaleXLabel, "cell 1 1"); + + //---- tScaleYLabel ---- + tScaleYLabel.setText("text"); + panel1.add(tScaleYLabel, "cell 2 1"); + + //---- tShearLabel ---- + tShearLabel.setText("Shear:"); + panel1.add(tShearLabel, "cell 0 2,gapx indent"); + + //---- tShearXLabel ---- + tShearXLabel.setText("text"); + panel1.add(tShearXLabel, "cell 1 2"); + + //---- tShearYLabel ---- + tShearYLabel.setText("text"); + panel1.add(tShearYLabel, "cell 2 2"); + + //---- tTranslateLabel ---- + tTranslateLabel.setText("Translate:"); + panel1.add(tTranslateLabel, "cell 0 3,gapx indent"); + + //---- tTranslateXLabel ---- + tTranslateXLabel.setText("text"); + panel1.add(tTranslateXLabel, "cell 1 3"); + + //---- tTranslateYLabel ---- + tTranslateYLabel.setText("text"); + panel1.add(tTranslateYLabel, "cell 2 3"); + + //---- cLabel ---- + cLabel.setText("Computed:"); + panel1.add(cLabel, "cell 0 4"); + + //---- cScaleLabel ---- + cScaleLabel.setText("Scale:"); + panel1.add(cScaleLabel, "cell 0 5,gapx indent"); + + //---- cScaleXLabel ---- + cScaleXLabel.setText("text"); + panel1.add(cScaleXLabel, "cell 1 5"); + + //---- cScaleYLabel ---- + cScaleYLabel.setText("text"); + panel1.add(cScaleYLabel, "cell 2 5"); + + //---- cRotationLabel ---- + cRotationLabel.setText("Rotation:"); + panel1.add(cRotationLabel, "cell 0 6,gapx indent"); + + //---- cRotationDegreesLabel ---- + cRotationDegreesLabel.setText("text"); + panel1.add(cRotationDegreesLabel, "cell 1 6"); + } + add(panel1, "cell 2 0 1 4"); + + //---- resetButton ---- + resetButton.setText("Reset"); + resetButton.addActionListener(e -> reset()); + add(resetButton, "cell 2 4,align left bottom,grow 0 0"); + add(painter, "cell 0 5 3 1,grow,width 600,height 400"); + // JFormDesigner - End of component initialization //GEN-END:initComponents + } + + // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + private JSlider translateXSlider; + private JSlider translateYSlider; + private JSlider scaleXSlider; + private JSlider scaleYSlider; + private JSlider rotateSlider; + private JLabel tScaleXLabel; + private JLabel tScaleYLabel; + private JLabel tShearXLabel; + private JLabel tShearYLabel; + private JLabel tTranslateXLabel; + private JLabel tTranslateYLabel; + private JLabel cScaleXLabel; + private JLabel cScaleYLabel; + private JLabel cRotationDegreesLabel; + private FlatPaintingHiDPITest.HiDPI1xPainter painter; + // JFormDesigner - End of variables declaration //GEN-END:variables + + //---- class HiDPI1xPainter ----------------------------------------------- + + public static class HiDPI1xPainter + extends JComponent + { + int translateX; + int translateY; + int scaleX; + int scaleY; + int rotate; + + public HiDPI1xPainter() { + } + + @Override + protected void paintComponent( Graphics g ) { + int width = getWidth(); + int height = getHeight(); + + Graphics2D g2 = (Graphics2D) g.create(); + try { + FlatUIUtils.setRenderingHints( g2 ); + + g2.setColor( Color.blue ); + g2.drawRect( 0, 0, width - 1, height - 1 ); + + g2.setColor( Color.cyan ); + g2.drawLine( 0, translateY, width, translateY ); + g2.drawLine( translateX, 0, translateX, height ); + + g2.translate( translateX, translateY ); + g2.scale( scaleX / 100., scaleY / 100. ); + g2.rotate( Math.toRadians( rotate ) ); + + g2.setColor( Color.red ); + g2.fillRect( 0, 0, 100, 50 ); + + g2.setColor( Color.green ); + HiDPIUtils.paintAtScale1x( g2, 0, 0, 100, 50, + (g2d, x2, y2, width2, height2, scaleFactor) -> { + g2d.fillRect( x2 + 10, y2 + 10, width2 - 20, height2 - 20 ); + } ); + } finally { + g2.dispose(); + } + } + } +} diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingHiDPITest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingHiDPITest.jfd new file mode 100644 index 00000000..3a8b048d --- /dev/null +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingHiDPITest.jfd @@ -0,0 +1,289 @@ +JFDML JFormDesigner: "8.0.0.0.122" Java: "17.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": "hidemode 3" + "$columnConstraints": "[fill][400,fill]para[grow,fill]" + "$rowConstraints": "[fill][][][][][grow]" + } ) { + name: "this" + "border": sfield com.jformdesigner.model.FormObject NULL_VALUE + add( new FormComponent( "javax.swing.JLabel" ) { + name: "translateXLabel" + "text": "TranslateX:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JSlider" ) { + name: "translateXSlider" + "maximum": 500 + "paintLabels": true + "paintTicks": true + "majorTickSpacing": 100 + "minorTickSpacing": 25 + "value": 100 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "sliderChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "translateYLabel" + "text": "TranslateY:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1" + } ) + add( new FormComponent( "javax.swing.JSlider" ) { + name: "translateYSlider" + "maximum": 500 + "paintLabels": true + "paintTicks": true + "majorTickSpacing": 100 + "minorTickSpacing": 25 + "value": 100 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "sliderChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 1" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "scaleXLabel" + "text": "ScaleX:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 2" + } ) + add( new FormComponent( "javax.swing.JSlider" ) { + name: "scaleXSlider" + "maximum": 300 + "value": 100 + "paintTicks": true + "paintLabels": true + "majorTickSpacing": 50 + "snapToTicks": true + "minorTickSpacing": 10 + "minimum": -100 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "sliderChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 2" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "scaleYLabel" + "text": "ScaleY:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 3" + } ) + add( new FormComponent( "javax.swing.JSlider" ) { + name: "scaleYSlider" + "maximum": 300 + "value": 100 + "paintTicks": true + "paintLabels": true + "majorTickSpacing": 50 + "snapToTicks": true + "minorTickSpacing": 10 + "minimum": -100 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "sliderChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 3" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "rotateLabel" + "text": "Rotate:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 4" + } ) + add( new FormComponent( "javax.swing.JSlider" ) { + name: "rotateSlider" + "maximum": 360 + "minimum": -360 + "value": 0 + "majorTickSpacing": 90 + "paintLabels": true + "paintTicks": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "sliderChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 4" + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "hidemode 3" + "$columnConstraints": "[fill][50,fill][50,fill]" + "$rowConstraints": "[][]0[]0[]para[][]0[]" + } ) { + name: "panel1" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tLabel" + "text": "AffineTransform:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "xLabel" + "text": "X" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0,alignx center,growx 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "yLabel" + "text": "Y" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0,alignx center,growx 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tScaleLabel" + "text": "Scale:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1,gapx indent" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tScaleXLabel" + "text": "text" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 1" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tScaleYLabel" + "text": "text" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 1" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tShearLabel" + "text": "Shear:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 2,gapx indent" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tShearXLabel" + "text": "text" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 2" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tShearYLabel" + "text": "text" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 2" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tTranslateLabel" + "text": "Translate:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 3,gapx indent" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tTranslateXLabel" + "text": "text" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 3" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tTranslateYLabel" + "text": "text" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 3" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "cLabel" + "text": "Computed:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 4" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "cScaleLabel" + "text": "Scale:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 5,gapx indent" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "cScaleXLabel" + "text": "text" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 5" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "cScaleYLabel" + "text": "text" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 5" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "cRotationLabel" + "text": "Rotation:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 6,gapx indent" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "cRotationDegreesLabel" + "text": "text" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 6" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0 1 4" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "resetButton" + "text": "Reset" + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "reset", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 4,align left bottom,grow 0 0" + } ) + add( new FormComponent( "com.formdev.flatlaf.testing.FlatPaintingHiDPITest$HiDPI1xPainter" ) { + name: "painter" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 5 3 1,grow,width 600,height 400" + } ) + }, new FormLayoutConstraints( null ) { + "location": new java.awt.Point( 0, 0 ) + "size": new java.awt.Dimension( 685, 680 ) + } ) + } +}