From e603bd81a18f67ada8b33523a26718f7e864d8a3 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Mon, 10 Aug 2020 13:53:32 +0200 Subject: [PATCH] FlatSmoothScrollingTest: added simple line chart that shows changes to scrollbar values --- .../testing/FlatSmoothScrollingTest.java | 413 ++++++++++++++++-- .../testing/FlatSmoothScrollingTest.jfd | 51 ++- 2 files changed, 419 insertions(+), 45 deletions(-) diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSmoothScrollingTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSmoothScrollingTest.java index cca6d768..3c8dabb4 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSmoothScrollingTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSmoothScrollingTest.java @@ -16,15 +16,27 @@ package com.formdev.flatlaf.testing; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.Point; +import java.awt.Rectangle; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import javax.swing.*; import javax.swing.table.AbstractTableModel; import javax.swing.tree.*; +import com.formdev.flatlaf.ui.FlatUIUtils; +import com.formdev.flatlaf.util.HiDPIUtils; +import com.formdev.flatlaf.util.UIScale; import net.miginfocom.swing.*; /** @@ -44,6 +56,8 @@ public class FlatSmoothScrollingTest FlatSmoothScrollingTest() { initComponents(); + updateChartDelayedChanged(); + // allow enabling/disabling smooth scrolling with Alt+S without moving focus to checkbox registerKeyboardAction( e -> { @@ -53,23 +67,30 @@ public class FlatSmoothScrollingTest KeyStroke.getKeyStroke( "alt " + (char) smoothScrollingCheckBox.getMnemonic() ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); - listScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "list vert" ) ); - listScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "list horz" ) ); + listLabel.setIcon( new ColorIcon( Color.red.darker() ) ); + treeLabel.setIcon( new ColorIcon( Color.blue.darker() ) ); + tableLabel.setIcon( new ColorIcon( Color.green.darker() ) ); + textAreaLabel.setIcon( new ColorIcon( Color.magenta.darker() ) ); + textPaneLabel.setIcon( new ColorIcon( Color.cyan.darker() ) ); + editorPaneLabel.setIcon( new ColorIcon( Color.orange.darker() ) ); - treeScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "tree vert" ) ); - treeScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "tree horz" ) ); + listScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "list vert", Color.red.darker() ) ); + listScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "list horz", Color.red ) ); - tableScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "table vert" ) ); - tableScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "table horz" ) ); + treeScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "tree vert", Color.blue.darker() ) ); + treeScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "tree horz", Color.blue ) ); - textAreaScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "textArea vert" ) ); - textAreaScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "textArea horz" ) ); + tableScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "table vert", Color.green.darker() ) ); + tableScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "table horz", Color.green ) ); - textPaneScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "textPane vert" ) ); - textPaneScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "textPane horz" ) ); + textAreaScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "textArea vert", Color.magenta.darker() ) ); + textAreaScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "textArea horz", Color.magenta ) ); - editorPaneScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "editorPane vert" ) ); - editorPaneScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "editorPane horz" ) ); + textPaneScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "textPane vert", Color.cyan.darker() ) ); + textPaneScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "textPane horz", Color.cyan ) ); + + editorPaneScrollPane.getVerticalScrollBar().addAdjustmentListener( new AdjustmentHandler( "editorPane vert", Color.orange.darker() ) ); + editorPaneScrollPane.getHorizontalScrollBar().addAdjustmentListener( new AdjustmentHandler( "editorPane horz", Color.orange ) ); ArrayList items = new ArrayList<>(); for( char ch = '0'; ch < 'z'; ch++ ) { @@ -138,27 +159,40 @@ public class FlatSmoothScrollingTest UIManager.put( "ScrollPane.smoothScrolling", smoothScrollingCheckBox.isSelected() ); } + private void clearChart() { + lineChartPanel.clear(); + } + + private void updateChartDelayedChanged() { + lineChartPanel.setUpdateDelayed( updateChartDelayedCheckBox.isSelected() ); + } + private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents smoothScrollingCheckBox = new JCheckBox(); listLabel = new JLabel(); - label1 = new JLabel(); - label5 = new JLabel(); + treeLabel = new JLabel(); + tableLabel = new JLabel(); listScrollPane = new FlatSmoothScrollingTest.DebugScrollPane(); list = new JList<>(); treeScrollPane = new FlatSmoothScrollingTest.DebugScrollPane(); tree = new JTree(); tableScrollPane = new JScrollPane(); table = new JTable(); - label2 = new JLabel(); - label3 = new JLabel(); - label4 = new JLabel(); + textAreaLabel = new JLabel(); + textPaneLabel = new JLabel(); + editorPaneLabel = new JLabel(); textAreaScrollPane = new FlatSmoothScrollingTest.DebugScrollPane(); textArea = new JTextArea(); textPaneScrollPane = new FlatSmoothScrollingTest.DebugScrollPane(); textPane = new JTextPane(); editorPaneScrollPane = new FlatSmoothScrollingTest.DebugScrollPane(); editorPane = new JEditorPane(); + panel1 = new JPanel(); + updateChartDelayedCheckBox = new JCheckBox(); + clearChartButton = new JButton(); + scrollPane1 = new JScrollPane(); + lineChartPanel = new FlatSmoothScrollingTest.LineChartPanel(); //======== this ======== setLayout(new MigLayout( @@ -173,7 +207,8 @@ public class FlatSmoothScrollingTest "[]" + "[200,grow,fill]" + "[]" + - "[200,grow,fill]")); + "[200,grow,fill]" + + "[300,grow,fill]")); //---- smoothScrollingCheckBox ---- smoothScrollingCheckBox.setText("Smooth scrolling"); @@ -184,15 +219,18 @@ public class FlatSmoothScrollingTest //---- listLabel ---- listLabel.setText("JList:"); + listLabel.setHorizontalTextPosition(SwingConstants.LEADING); add(listLabel, "cell 0 1,aligny top,growy 0"); - //---- label1 ---- - label1.setText("JTree:"); - add(label1, "cell 1 1"); + //---- treeLabel ---- + treeLabel.setText("JTree:"); + treeLabel.setHorizontalTextPosition(SwingConstants.LEADING); + add(treeLabel, "cell 1 1"); - //---- label5 ---- - label5.setText("JTable:"); - add(label5, "cell 2 1"); + //---- tableLabel ---- + tableLabel.setText("JTable:"); + tableLabel.setHorizontalTextPosition(SwingConstants.LEADING); + add(tableLabel, "cell 2 1"); //======== listScrollPane ======== { @@ -212,17 +250,20 @@ public class FlatSmoothScrollingTest } add(tableScrollPane, "cell 2 2 2 1,width 100,height 100"); - //---- label2 ---- - label2.setText("JTextArea:"); - add(label2, "cell 0 3"); + //---- textAreaLabel ---- + textAreaLabel.setText("JTextArea:"); + textAreaLabel.setHorizontalTextPosition(SwingConstants.LEADING); + add(textAreaLabel, "cell 0 3"); - //---- label3 ---- - label3.setText("JTextPane:"); - add(label3, "cell 1 3"); + //---- textPaneLabel ---- + textPaneLabel.setText("JTextPane:"); + textPaneLabel.setHorizontalTextPosition(SwingConstants.LEADING); + add(textPaneLabel, "cell 1 3"); - //---- label4 ---- - label4.setText("JEditorPane:"); - add(label4, "cell 2 3"); + //---- editorPaneLabel ---- + editorPaneLabel.setText("JEditorPane:"); + editorPaneLabel.setHorizontalTextPosition(SwingConstants.LEADING); + add(editorPaneLabel, "cell 2 3"); //======== textAreaScrollPane ======== { @@ -241,45 +282,92 @@ public class FlatSmoothScrollingTest editorPaneScrollPane.setViewportView(editorPane); } add(editorPaneScrollPane, "cell 2 4"); + + //======== panel1 ======== + { + panel1.setLayout(new MigLayout( + "ltr,insets 0,hidemode 3,aligny bottom", + // columns + "[200,right]", + // rows + "[]" + + "[]")); + + //---- updateChartDelayedCheckBox ---- + updateChartDelayedCheckBox.setText("Update chart delayed"); + updateChartDelayedCheckBox.setMnemonic('U'); + updateChartDelayedCheckBox.setSelected(true); + updateChartDelayedCheckBox.addActionListener(e -> updateChartDelayedChanged()); + panel1.add(updateChartDelayedCheckBox, "cell 0 0"); + + //---- clearChartButton ---- + clearChartButton.setText("Clear Chart"); + clearChartButton.addActionListener(e -> clearChart()); + panel1.add(clearChartButton, "cell 0 1"); + } + add(panel1, "cell 3 4"); + + //======== scrollPane1 ======== + { + scrollPane1.setViewportView(lineChartPanel); + } + add(scrollPane1, "cell 0 5 4 1,width 100"); // JFormDesigner - End of component initialization //GEN-END:initComponents } // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables private JCheckBox smoothScrollingCheckBox; private JLabel listLabel; - private JLabel label1; - private JLabel label5; + private JLabel treeLabel; + private JLabel tableLabel; private FlatSmoothScrollingTest.DebugScrollPane listScrollPane; private JList list; private FlatSmoothScrollingTest.DebugScrollPane treeScrollPane; private JTree tree; private JScrollPane tableScrollPane; private JTable table; - private JLabel label2; - private JLabel label3; - private JLabel label4; + private JLabel textAreaLabel; + private JLabel textPaneLabel; + private JLabel editorPaneLabel; private FlatSmoothScrollingTest.DebugScrollPane textAreaScrollPane; private JTextArea textArea; private FlatSmoothScrollingTest.DebugScrollPane textPaneScrollPane; private JTextPane textPane; private FlatSmoothScrollingTest.DebugScrollPane editorPaneScrollPane; private JEditorPane editorPane; + private JPanel panel1; + private JCheckBox updateChartDelayedCheckBox; + private JButton clearChartButton; + private JScrollPane scrollPane1; + private FlatSmoothScrollingTest.LineChartPanel lineChartPanel; // JFormDesigner - End of variables declaration //GEN-END:variables //---- class AdjustmentHandler -------------------------------------------- - private static class AdjustmentHandler + private class AdjustmentHandler implements AdjustmentListener { private final String name; + private final Color chartColor; private int count; AdjustmentHandler( String name ) { + this( name, null ); + } + + AdjustmentHandler( String name, Color chartColor ) { this.name = name; + this.chartColor = chartColor; } @Override public void adjustmentValueChanged( AdjustmentEvent e ) { + if( chartColor != null ) { + JScrollBar sb = (JScrollBar) e.getSource(); + double value = (double) (e.getValue() - sb.getMinimum()) / (double) (sb.getMaximum() - sb.getVisibleAmount()); + lineChartPanel.addValue( value, chartColor ); + } + System.out.printf( "%s (%d): %s %3d %b%n", name, ++count, adjustmentType2Str( e.getAdjustmentType() ), @@ -316,4 +404,251 @@ public class FlatSmoothScrollingTest }; } } + + //---- class LineChartPanel ----------------------------------------------- + + private static class LineChartPanel + extends JComponent + implements Scrollable + { + private static final int SECOND_WIDTH = 200; + private static final int NEW_SEQUENCE_TIME_LAG = 500; + private static final int NEW_SEQUENCE_GAP = 20; + + private static class Data { + final double value; + final long time; // in milliseconds + + Data( double value, long time ) { + this.value = value; + this.time = time; + } + } + + private final Map> color2dataMap = new HashMap<>(); + private final Timer repaintTime; + private Color lastUsedChartColor; + private boolean updateDelayed; + + LineChartPanel() { + int resolution = FlatUIUtils.getUIInt( "ScrollPane.smoothScrolling.resolution", 10 ); + + repaintTime = new Timer( resolution * 2, e -> repaintAndRevalidate() ); + repaintTime.setRepeats( false ); + } + + void addValue( double value, Color chartColor ) { + List chartData = color2dataMap.computeIfAbsent( chartColor, k -> new ArrayList<>() ); + chartData.add( new Data( value, System.currentTimeMillis()) ); + + lastUsedChartColor = chartColor; + + if( updateDelayed ) { + repaintTime.stop(); + repaintTime.start(); + } else + repaintAndRevalidate(); + } + + void clear() { + color2dataMap.clear(); + lastUsedChartColor = null; + + repaint(); + revalidate(); + } + + void setUpdateDelayed( boolean updateDelayed ) { + this.updateDelayed = updateDelayed; + } + + private void repaintAndRevalidate() { + repaint(); + revalidate(); + + // scroll horizontally + if( lastUsedChartColor != null ) { + int[] lastSeqX = new int[1]; + int cw = chartWidth( color2dataMap.get( lastUsedChartColor ), lastSeqX ); + scrollRectToVisible( new Rectangle( lastSeqX[0], 0, cw - lastSeqX[0], getHeight() ) ); + } + } + + @Override + protected void paintComponent( Graphics g ) { + Graphics g2 = g.create(); + try { + HiDPIUtils.paintAtScale1x( (Graphics2D) g2, this, this::paintImpl ); + } finally { + g2.dispose(); + } + } + + private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { + FlatUIUtils.setRenderingHints( g ); + + int secondWidth = (int) (SECOND_WIDTH * scaleFactor); + int seqGapWidth = (int) (NEW_SEQUENCE_GAP * scaleFactor); + + g.translate( x, y ); + + // fill background + g.setColor( Color.white ); + g.fillRect( x, y, width, height ); + + // paint horizontal lines + g.setColor( Color.LIGHT_GRAY ); + for( int i = 1; i < 10; i++ ) { + int hy = (height * i) / 10; + g.drawLine( 0, hy, width, hy ); + } + + // paint vertical lines + g.setColor( Color.LIGHT_GRAY ); + for( int i = secondWidth; i < width; i += secondWidth ) + g.drawLine( i, 0, i, height ); + + // paint lines + for( Map.Entry> e : color2dataMap.entrySet() ) { + Color chartColor = e.getKey(); + List chartData = e.getValue(); + + long seqTime = 0; + int seqX = 0; + long ptime = 0; + int px = 0; + int py = 0; + int pcount = 0; + + g.setColor( chartColor ); + + int size = chartData.size(); + for( int i = 0; i < size; i++ ) { + Data data = chartData.get( i ); + int dy = (int) ((height - 1) * data.value); + + if( data.time > ptime + NEW_SEQUENCE_TIME_LAG ) { + if( i > 0 && pcount == 0 ) + g.drawLine( px, py, px + (int) (4 * scaleFactor), py ); + + // start new sequence + seqTime = data.time; + seqX = (i > 0) ? px + seqGapWidth : 0; + px = seqX; + pcount = 0; + } else { + // line in sequence + int dx = (int) (seqX + (((data.time - seqTime) / 1000.) * secondWidth)); + g.drawLine( px, py, dx, dy ); + px = dx; + pcount++; + } + + py = dy; + ptime = data.time; + } + } + } + + private int chartWidth() { + int width = 0; + for( List chartData : color2dataMap.values() ) + width = Math.max( width, chartWidth( chartData, null ) ); + return width; + } + + private int chartWidth( List chartData, int[] lastSeqX ) { + long seqTime = 0; + int seqX = 0; + long ptime = 0; + int px = 0; + + int size = chartData.size(); + for( int i = 0; i < size; i++ ) { + Data data = chartData.get( i ); + + if( data.time > ptime + NEW_SEQUENCE_TIME_LAG ) { + // start new sequence + seqTime = data.time; + seqX = (i > 0) ? px + NEW_SEQUENCE_GAP : 0; + px = seqX; + } else { + // line in sequence + int dx = (int) (seqX + (((data.time - seqTime) / 1000.) * SECOND_WIDTH)); + px = dx; + } + + ptime = data.time; + } + + if( lastSeqX != null ) + lastSeqX[0] = seqX; + + return px; + } + + @Override + public Dimension getPreferredSize() { + return new Dimension( chartWidth(), 200 ); + } + + @Override + public Dimension getPreferredScrollableViewportSize() { + return new Dimension( chartWidth(), 200 ); + } + + @Override + public int getScrollableUnitIncrement( Rectangle visibleRect, int orientation, int direction ) { + return SECOND_WIDTH; + } + + @Override + public int getScrollableBlockIncrement( Rectangle visibleRect, int orientation, int direction ) { + JViewport viewport = (JViewport) SwingUtilities.getAncestorOfClass( JViewport.class, this ); + return (viewport != null) ? viewport.getWidth() : 200; + } + + @Override + public boolean getScrollableTracksViewportWidth() { + JViewport viewport = (JViewport) SwingUtilities.getAncestorOfClass( JViewport.class, this ); + return (viewport != null) ? viewport.getWidth() > chartWidth() : true; + } + + @Override + public boolean getScrollableTracksViewportHeight() { + return true; + } + } + + //---- class ColorIcon ---------------------------------------------------- + + private static class ColorIcon + implements Icon + { + private final Color color; + + ColorIcon( Color color ) { + this.color = color; + } + + @Override + public void paintIcon( Component c, Graphics g, int x, int y ) { + int width = getIconWidth(); + int height = getIconHeight(); + + g.setColor( color ); + g.fillRect( x, y, width, height ); + } + + @Override + public int getIconWidth() { + return UIScale.scale( 24 ); + } + + @Override + public int getIconHeight() { + return UIScale.scale( 12 ); + } + + } } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSmoothScrollingTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSmoothScrollingTest.jfd index cdeac49e..f6eb30b1 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSmoothScrollingTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatSmoothScrollingTest.jfd @@ -6,7 +6,7 @@ new FormModel { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "ltr,insets dialog,hidemode 3" "$columnConstraints": "[200,fill][200,fill][200,fill][200,fill]" - "$rowConstraints": "[][][200,grow,fill][][200,grow,fill]" + "$rowConstraints": "[][][200,grow,fill][][200,grow,fill][300,grow,fill]" } ) { name: "this" add( new FormComponent( "javax.swing.JCheckBox" ) { @@ -21,18 +21,21 @@ new FormModel { add( new FormComponent( "javax.swing.JLabel" ) { name: "listLabel" "text": "JList:" + "horizontalTextPosition": 10 }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 1,aligny top,growy 0" } ) add( new FormComponent( "javax.swing.JLabel" ) { - name: "label1" + name: "treeLabel" "text": "JTree:" + "horizontalTextPosition": 10 }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { - name: "label5" + name: "tableLabel" "text": "JTable:" + "horizontalTextPosition": 10 }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 1" } ) @@ -65,20 +68,23 @@ new FormModel { "value": "cell 2 2 2 1,width 100,height 100" } ) add( new FormComponent( "javax.swing.JLabel" ) { - name: "label2" + name: "textAreaLabel" "text": "JTextArea:" + "horizontalTextPosition": 10 }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 3" } ) add( new FormComponent( "javax.swing.JLabel" ) { - name: "label3" + name: "textPaneLabel" "text": "JTextPane:" + "horizontalTextPosition": 10 }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 3" } ) add( new FormComponent( "javax.swing.JLabel" ) { - name: "label4" + name: "editorPaneLabel" "text": "JEditorPane:" + "horizontalTextPosition": 10 }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 3" } ) @@ -106,6 +112,39 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 4" } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$columnConstraints": "[200,right]" + "$rowConstraints": "[][]" + "$layoutConstraints": "ltr,insets 0,hidemode 3,aligny bottom" + } ) { + name: "panel1" + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "updateChartDelayedCheckBox" + "text": "Update chart delayed" + "mnemonic": 85 + "selected": true + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "updateChartDelayedChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "clearChartButton" + "text": "Clear Chart" + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "clearChart", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 3 4" + } ) + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "scrollPane1" + add( new FormComponent( "com.formdev.flatlaf.testing.FlatSmoothScrollingTest$LineChartPanel" ) { + name: "lineChartPanel" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 5 4 1,width 100" + } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) "size": new java.awt.Dimension( 790, 715 )