Browse Source

Added MigLayout

New layout for channel mode pane
New layout for the error list dialog
layoutGrid uses outter padding not initial padding
Feedback dialog layout

git-svn-id: http://svn.dmdirc.com/trunk@2537 00569f92-eb28-0410-84fd-f71c24880f
tags/0.5.5
Gregory Holmes 16 years ago
parent
commit
249c998c1a
30 changed files with 12154 additions and 128 deletions
  1. 18
    6
      src/com/dmdirc/ui/swing/MainFrame.java
  2. 20
    9
      src/com/dmdirc/ui/swing/UIUtilities.java
  3. 19
    0
      src/com/dmdirc/ui/swing/components/ParamModePanel.java
  4. 156
    0
      src/com/dmdirc/ui/swing/dialogs/FeedbackDialog.java
  5. 31
    45
      src/com/dmdirc/ui/swing/dialogs/channelsetting/ChannelModesPane.java
  6. 9
    19
      src/com/dmdirc/ui/swing/dialogs/error/ErrorDetailPanel.java
  7. 20
    48
      src/com/dmdirc/ui/swing/dialogs/error/ErrorListDialog.java
  8. 1
    1
      src/com/dmdirc/ui/swing/dialogs/error/FatalErrorDialog.java
  9. 173
    0
      src/com/dmdirc/ui/swing/dialogs/serversetting/UserModesPane.java
  10. 489
    0
      src/net/miginfocom/layout/AC.java
  11. 247
    0
      src/net/miginfocom/layout/BoundSize.java
  12. 1432
    0
      src/net/miginfocom/layout/CC.java
  13. 255
    0
      src/net/miginfocom/layout/ComponentWrapper.java
  14. 1580
    0
      src/net/miginfocom/layout/ConstraintParser.java
  15. 69
    0
      src/net/miginfocom/layout/ContainerWrapper.java
  16. 437
    0
      src/net/miginfocom/layout/DimConstraint.java
  17. 2618
    0
      src/net/miginfocom/layout/Grid.java
  18. 753
    0
      src/net/miginfocom/layout/IDEUtil.java
  19. 65
    0
      src/net/miginfocom/layout/InCellGapProvider.java
  20. 645
    0
      src/net/miginfocom/layout/LC.java
  21. 75
    0
      src/net/miginfocom/layout/LayoutCallback.java
  22. 542
    0
      src/net/miginfocom/layout/LayoutUtil.java
  23. 203
    0
      src/net/miginfocom/layout/LinkHandler.java
  24. 513
    0
      src/net/miginfocom/layout/PlatformDefaults.java
  25. 94
    0
      src/net/miginfocom/layout/ResizeConstraint.java
  26. 62
    0
      src/net/miginfocom/layout/UnitConverter.java
  27. 605
    0
      src/net/miginfocom/layout/UnitValue.java
  28. 540
    0
      src/net/miginfocom/swing/MigLayout.java
  29. 379
    0
      src/net/miginfocom/swing/SwingComponentWrapper.java
  30. 104
    0
      src/net/miginfocom/swing/SwingContainerWrapper.java

+ 18
- 6
src/com/dmdirc/ui/swing/MainFrame.java View File

@@ -41,6 +41,7 @@ import com.dmdirc.ui.interfaces.MainWindow;
41 41
 import com.dmdirc.ui.interfaces.Window;
42 42
 import com.dmdirc.ui.swing.components.Frame;
43 43
 import com.dmdirc.ui.swing.components.SwingStatusBar;
44
+import com.dmdirc.ui.swing.dialogs.FeedbackDialog;
44 45
 import com.dmdirc.ui.swing.dialogs.NewServerDialog;
45 46
 import com.dmdirc.ui.swing.dialogs.PluginDialog;
46 47
 import com.dmdirc.ui.swing.dialogs.PreferencesDialog;
@@ -472,7 +473,8 @@ public final class MainFrame extends JFrame implements WindowListener,
472 473
      */
473 474
     private void initComponents(final SwingStatusBar statusBar) {
474 475
         final JSplitPane mainSplitPane = new JSplitPane();
475
-
476
+        final JPanel panel = new JPanel();
477
+        
476 478
         frameManagerPanel = new JPanel();
477 479
         desktopPane = new JDesktopPane();
478 480
         desktopPane.setBackground(new Color(238, 238, 238));
@@ -485,16 +487,17 @@ public final class MainFrame extends JFrame implements WindowListener,
485 487
 
486 488
         setPreferredSize(new Dimension(800, 600));
487 489
 
490
+        panel.setLayout(new BorderLayout());
491
+        panel.add(mainSplitPane, BorderLayout.CENTER);
492
+        panel.add(statusBar, BorderLayout.SOUTH);
493
+        
488 494
         getContentPane().setLayout(new BorderLayout(0, 0));
489
-
490
-        getContentPane().add(mainSplitPane, BorderLayout.CENTER);
491
-
492
-        getContentPane().add(statusBar, BorderLayout.SOUTH);
495
+        
496
+        getContentPane().add(panel, BorderLayout.CENTER);
493 497
 
494 498
         setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
495 499
 
496 500
         setTitle("DMDirc");
497
-        frameManagerPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
498 501
         desktopPane.setBorder(UIManager.getBorder("TextField.border"));
499 502
 
500 503
         pack();
@@ -724,6 +727,13 @@ public final class MainFrame extends JFrame implements WindowListener,
724 727
         menuItem.setActionCommand("JoinDevChat");
725 728
         menuItem.addActionListener(this);
726 729
         helpMenu.add(menuItem);
730
+        
731
+        menuItem = new JMenuItem();
732
+        menuItem.setMnemonic('f');
733
+        menuItem.setText("Send Feedback");
734
+        menuItem.setActionCommand("feedback");
735
+        menuItem.addActionListener(this);
736
+        helpMenu.add(menuItem);
727 737
 
728 738
         pluginsMenu = new JMenu("Plugins");
729 739
         pluginsMenu.setMnemonic('p');
@@ -931,6 +941,8 @@ public final class MainFrame extends JFrame implements WindowListener,
931 941
         } else if (e.getActionCommand().equals("configurePlugin")) {
932 942
             PluginManager.getPluginManager().
933 943
                     getPlugin(pluginList.get(e.getSource())).showConfig();
944
+        } else if (e.getActionCommand().equals("feedback")) {
945
+            FeedbackDialog.showFeedbackDialog();
934 946
         }
935 947
     }
936 948
 

+ 20
- 9
src/com/dmdirc/ui/swing/UIUtilities.java View File

@@ -66,18 +66,18 @@ public final class UIUtilities {
66 66
      * @param parent parent container
67 67
      * @param rows number of rows
68 68
      * @param columns number of columns
69
-     * @param initialXPadding initial x padding
70
-     * @param initialYPadding initial y padding
69
+     * @param outerXPadding outer x padding
70
+     * @param outerYPadding outer y padding
71 71
      * @param xPadding x padding
72 72
      * @param yPadding y padding
73 73
      */
74 74
     public static void layoutGrid(final Container parent, final int rows,
75
-            final int columns, final int initialXPadding,
76
-            final int initialYPadding, final int xPadding, final int yPadding) {
75
+            final int columns, final int outerXPadding,
76
+            final int outerYPadding, final int xPadding, final int yPadding) {
77 77
         final SpringLayout layout = (SpringLayout) parent.getLayout();
78 78
         
79
-        Spring x = Spring.constant(initialXPadding);
80
-        Spring y = Spring.constant(initialYPadding);
79
+        Spring x = Spring.constant(outerXPadding);
80
+        Spring y = Spring.constant(outerYPadding);
81 81
         SpringLayout.Constraints constraints;
82 82
         
83 83
         for (int c = 0; c < columns; c++) {
@@ -92,7 +92,11 @@ public final class UIUtilities {
92 92
                 constraints.setX(x);
93 93
                 constraints.setWidth(width);
94 94
             }
95
-            x = Spring.sum(x, Spring.sum(width, Spring.constant(xPadding)));
95
+            if (c == columns - 1) {
96
+                x = Spring.sum(x, width);
97
+            } else {
98
+                x = Spring.sum(x, Spring.sum(width, Spring.constant(xPadding)));
99
+            }
96 100
         }
97 101
         
98 102
         for (int r = 0; r < rows; r++) {
@@ -107,10 +111,17 @@ public final class UIUtilities {
107 111
                 constraints.setY(y);
108 112
                 constraints.setHeight(Spring.constant(height));
109 113
             }
110
-            y = Spring.sum(y, Spring.sum(Spring.constant(height),
111
-                    Spring.constant(yPadding)));
114
+            if (r == rows - 1) {
115
+                y = Spring.sum(y, Spring.constant(height));
116
+            } else {
117
+                y = Spring.sum(y, Spring.sum(Spring.constant(height),
118
+                        Spring.constant(yPadding)));
119
+            }
112 120
         }
113 121
         
122
+        x = Spring.sum(x, Spring.constant(outerXPadding));
123
+        y = Spring.sum(y, Spring.constant(outerYPadding));
124
+        
114 125
         final SpringLayout.Constraints pCons = layout.getConstraints(parent);
115 126
         pCons.setConstraint(SpringLayout.SOUTH, y);
116 127
         pCons.setConstraint(SpringLayout.EAST, x);

+ 19
- 0
src/com/dmdirc/ui/swing/components/ParamModePanel.java View File

@@ -23,6 +23,7 @@
23 23
 package com.dmdirc.ui.swing.components;
24 24
 
25 25
 import com.dmdirc.config.ConfigManager;
26
+import java.awt.Component;
26 27
 import static com.dmdirc.ui.swing.UIUtilities.LARGE_BORDER;
27 28
 import static com.dmdirc.ui.swing.UIUtilities.SMALL_BORDER;
28 29
 
@@ -167,6 +168,24 @@ public final class ParamModePanel extends JPanel implements ActionListener {
167 168
         return mode;
168 169
     }
169 170
     
171
+    /**
172
+     * Returns the checkbox component.
173
+     * 
174
+     * @return Checkbox component.
175
+     */
176
+    public Component getCheckboxComponent() {
177
+        return checkBox;
178
+    }
179
+    
180
+    /**
181
+     * Returns the value component.
182
+     * 
183
+     * @return Value component
184
+     */
185
+    public Component getValueComponent() {
186
+        return textField;
187
+    }
188
+    
170 189
 }
171 190
 
172 191
 /**

+ 156
- 0
src/com/dmdirc/ui/swing/dialogs/FeedbackDialog.java View File

@@ -0,0 +1,156 @@
1
+/*
2
+ * Copyright (c) 2006-2007 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.ui.swing.dialogs;
24
+
25
+import com.dmdirc.Main;
26
+import com.dmdirc.ui.swing.MainFrame;
27
+import com.dmdirc.ui.swing.components.StandardDialog;
28
+import com.dmdirc.ui.swing.components.TextLabel;
29
+import java.awt.Dimension;
30
+import java.awt.event.ActionEvent;
31
+import java.awt.event.ActionListener;
32
+import javax.swing.JButton;
33
+import javax.swing.JLabel;
34
+import javax.swing.JPanel;
35
+import javax.swing.JScrollPane;
36
+import javax.swing.JTextArea;
37
+import javax.swing.JTextField;
38
+import net.miginfocom.swing.MigLayout;
39
+
40
+/** Feedback form. */
41
+public class FeedbackDialog extends StandardDialog implements ActionListener {
42
+
43
+    /**
44
+     * A version number for this class. It should be changed whenever the class
45
+     * structure is changed (or anything else that would prevent serialized
46
+     * objects being unserialized with the new class).
47
+     */
48
+    private static final long serialVersionUID = 1;
49
+    /** A previously created instance of FeedbackDialog. */
50
+    private static FeedbackDialog me;
51
+    /** Information label. */
52
+    private TextLabel info;
53
+    /** Name field. */
54
+    private JTextField name;
55
+    /** Email field. */
56
+    private JTextField email;
57
+    /** Feedback area. */
58
+    private JTextArea feedback;
59
+    /** Buttons panel. */
60
+    private JPanel buttonsPanel;
61
+
62
+    /** Instantiates the feedback dialog. */
63
+    private FeedbackDialog() {
64
+        super((MainFrame) Main.getUI().getMainWindow(), false);
65
+
66
+        initComponents();
67
+        layoutComponents();
68
+        addListeners();
69
+        
70
+        setPreferredSize(new Dimension(600, 400));
71
+
72
+        pack();
73
+    }
74
+
75
+    /**
76
+     * Creates the new feedback dialog if one doesn't exist, and displays it.
77
+     */
78
+    public static synchronized void showFeedbackDialog() {
79
+        me = getFeedbackDialog();
80
+
81
+        me.setLocationRelativeTo((MainFrame) Main.getUI().getMainWindow());
82
+        me.setVisible(true);
83
+        me.requestFocus();
84
+    }
85
+
86
+    /**
87
+     * Returns the current instance of the FeedbackDialog.
88
+     *
89
+     * @return The current FeedbackDialog instance
90
+     */
91
+    public static synchronized FeedbackDialog getFeedbackDialog() {
92
+        if (me == null) {
93
+            me = new FeedbackDialog();
94
+        }
95
+
96
+        return me;
97
+    }
98
+
99
+    /** Initialises the components. */
100
+    private void initComponents() {
101
+        buttonsPanel = new JPanel();
102
+        orderButtons(new JButton(), new JButton());
103
+        info =  new TextLabel("This is a feedback dialog, if you fancy " +
104
+                "sending us some feedback fill in the form below, only the " +
105
+                "feedback field is required, but if you want us to get back " +
106
+                "to you the email address is pretty vital and the name " +
107
+                "fairly useful.", this);
108
+        name = new JTextField();
109
+        email = new JTextField();
110
+        feedback = new JTextArea();
111
+    }
112
+
113
+    /** Lays out the components. */
114
+    private void layoutComponents() {
115
+        setLayout(new MigLayout("fill"));
116
+
117
+        add(info, "span 3, growx, wrap");
118
+        
119
+        add(new JLabel("Name: "));
120
+        add(name, "span 2, growx, wrap");
121
+
122
+        add(new JLabel("Email: "));
123
+        add(email, "span 2, growx, wrap");
124
+
125
+        add(new JLabel("Feedback: "));
126
+        add(new JScrollPane(feedback), "span 2, grow, pushx, wrap");
127
+        
128
+        add(getCancelButton(), "skip, right, tag cancel, sg button");
129
+        add(getOkButton(), "tag ok, sg button");
130
+    }
131
+
132
+    /** Adds listeners to the components. */
133
+    private void addListeners() {
134
+        getOkButton().addActionListener(this);
135
+        getCancelButton().addActionListener(this);
136
+    }
137
+
138
+    /**
139
+     * {@inheritDoc}
140
+     *
141
+     * @param e action event
142
+     */
143
+    @Override
144
+    public void actionPerformed(final ActionEvent e) {
145
+        dispose();
146
+    }
147
+
148
+    /** {@inheritDoc} */
149
+    @Override
150
+    public void dispose() {
151
+        synchronized (me) {
152
+            super.dispose();
153
+            me = null;
154
+        }
155
+    }
156
+}

+ 31
- 45
src/com/dmdirc/ui/swing/dialogs/channelsetting/ChannelModesPane.java View File

@@ -25,21 +25,20 @@ package com.dmdirc.ui.swing.dialogs.channelsetting;
25 25
 import com.dmdirc.Channel;
26 26
 import com.dmdirc.parser.IRCParser;
27 27
 import com.dmdirc.ui.swing.components.ParamModePanel;
28
-import static com.dmdirc.ui.swing.UIUtilities.SMALL_BORDER;
29 28
 
30
-import java.awt.GridBagConstraints;
31
-import java.awt.GridBagLayout;
29
+import java.awt.Insets;
32 30
 import java.util.Hashtable;
33 31
 import java.util.Map;
34
-
35 32
 import javax.swing.BorderFactory;
36
-import javax.swing.Box;
33
+
37 34
 import javax.swing.JCheckBox;
35
+import javax.swing.JLabel;
38 36
 import javax.swing.JPanel;
37
+import javax.swing.JSeparator;
39 38
 
40
-/**
41
- * Non list mode panel.
42
- */
39
+import net.miginfocom.swing.MigLayout;
40
+
41
+/** Non list mode panel. */
43 42
 public final class ChannelModesPane extends JPanel {
44 43
 
45 44
     /**
@@ -66,6 +65,7 @@ public final class ChannelModesPane extends JPanel {
66 65
         this.channel = channel;
67 66
 
68 67
         initModesPanel();
68
+        layoutComponents();
69 69
 
70 70
         setVisible(true);
71 71
     }
@@ -80,8 +80,6 @@ public final class ChannelModesPane extends JPanel {
80 80
 
81 81
     /** Initialises the modes panel. */
82 82
     private void initModesPanel() {
83
-        final GridBagConstraints constraints = new GridBagConstraints();
84
-
85 83
         final IRCParser parser = channel.getServer().getParser();
86 84
 
87 85
         final String booleanModes = parser.getBoolChanModes();
@@ -89,20 +87,9 @@ public final class ChannelModesPane extends JPanel {
89 87
         final String paramModes =
90 88
                 parser.getSetOnlyChanModes() + parser.getSetUnsetChanModes();
91 89
 
92
-        setLayout(new GridBagLayout());
93
-        setBorder(BorderFactory.createEmptyBorder(SMALL_BORDER, SMALL_BORDER,
94
-                SMALL_BORDER, SMALL_BORDER));
95
-
96 90
         modeCheckBoxes =
97 91
                 new Hashtable<String, JCheckBox>();
98 92
 
99
-        constraints.gridx = 0;
100
-        constraints.gridy = 0;
101
-        constraints.fill = GridBagConstraints.HORIZONTAL;
102
-        constraints.anchor = GridBagConstraints.NORTHWEST;
103
-        constraints.weightx = 1.0;
104
-        constraints.weighty = 0.0;
105
-
106 93
         // Lay out all the boolean mode checkboxes
107 94
         for (int i = 0; i < booleanModes.length();
108 95
                 i++) {
@@ -132,16 +119,8 @@ public final class ChannelModesPane extends JPanel {
132 119
             }
133 120
 
134 121
             final JCheckBox checkBox = new JCheckBox(text, state);
122
+            checkBox.setMargin(new Insets(0, 0, 0, 0));
135 123
             checkBox.setToolTipText(tooltip);
136
-            checkBox.setBorder(BorderFactory.createEmptyBorder(SMALL_BORDER, 0,
137
-                    0, SMALL_BORDER));
138
-            add(checkBox, constraints);
139
-
140
-            constraints.gridx++;
141
-            if (constraints.gridx == 2) {
142
-                constraints.gridy++;
143
-                constraints.gridx = 0;
144
-            }
145 124
 
146 125
             modeCheckBoxes.put(mode, checkBox);
147 126
             if (channel.getConfigManager().
@@ -156,13 +135,6 @@ public final class ChannelModesPane extends JPanel {
156 135
         modeInputs =
157 136
                 new Hashtable<String, ParamModePanel>();
158 137
 
159
-        constraints.gridwidth = 2;
160
-
161
-        if (constraints.gridx != 0) {
162
-            constraints.gridy++;
163
-            constraints.gridx = 0;
164
-        }
165
-
166 138
         for (int i = 0; i < paramModes.length();
167 139
                 i++) {
168 140
             final String mode = paramModes.substring(i, i + 1);
@@ -174,18 +146,32 @@ public final class ChannelModesPane extends JPanel {
174 146
             final ParamModePanel panel =
175 147
                     new ParamModePanel(mode, state, value,
176 148
                     channel.getConfigManager());
177
-            panel.setBorder(BorderFactory.createEmptyBorder(SMALL_BORDER, 0, 0,
178
-                    0));
179
-            add(panel, constraints);
180 149
 
181 150
             modeInputs.put(mode, panel);
151
+        }
152
+    }
153
+
154
+    /** Lays out the components. */
155
+    private void layoutComponents() {
156
+        final JPanel booleanModes =
157
+                new JPanel(new MigLayout("wrap 2, fillx"));
158
+        for (JCheckBox checkBox : modeCheckBoxes.values()) {
159
+            booleanModes.add(checkBox);
160
+        }
182 161
 
183
-            constraints.gridy++;
162
+        final JPanel paramModes =
163
+                new JPanel(new MigLayout("wrap 2, fillx"));
164
+        for (ParamModePanel modePanel : modeInputs.values()) {
165
+            paramModes.add(modePanel.getCheckboxComponent());
166
+            paramModes.add(modePanel.getValueComponent(), "growx");
184 167
         }
168
+
169
+        booleanModes.setBorder(BorderFactory.createTitledBorder("Boolean modes"));
170
+        paramModes.setBorder(BorderFactory.createTitledBorder("Parameter modes"));
185 171
         
186
-        constraints.weighty = 1.0;
187
-        constraints.fill = GridBagConstraints.VERTICAL;
188
-        add(Box.createVerticalGlue(), constraints);
172
+        setLayout(new MigLayout("flowy, fillx", "fill", ""));
173
+        add(booleanModes);
174
+        add(paramModes);
189 175
     }
190 176
 
191 177
     /**
@@ -244,4 +230,4 @@ public final class ChannelModesPane extends JPanel {
244 230
             channel.getChannelInfo().sendModes();
245 231
         }
246 232
     }
247
-}
233
+}

+ 9
- 19
src/com/dmdirc/ui/swing/dialogs/error/ErrorDetailPanel.java View File

@@ -33,9 +33,9 @@ import javax.swing.JPanel;
33 33
 import javax.swing.JScrollPane;
34 34
 import javax.swing.JTextArea;
35 35
 import javax.swing.JTextField;
36
-import javax.swing.SpringLayout;
37 36
 import javax.swing.SwingUtilities;
38 37
 import javax.swing.text.BadLocationException;
38
+import net.miginfocom.swing.MigLayout;
39 39
 
40 40
 /**
41 41
  * Shows information about an error.
@@ -174,35 +174,25 @@ public final class ErrorDetailPanel extends JPanel implements ErrorListener {
174 174
     
175 175
     /** Lays out the components. */
176 176
     private void layoutComponents() {
177
-        setLayout(new SpringLayout());
177
+        setLayout(new MigLayout("fill, wrap 2", "[right]rel[grow,fill]", ""));
178 178
         
179
-        JLabel label;
180
-        
181
-        label = new JLabel("ID: ");
182
-        add(label);
179
+        add(new JLabel("ID: "));
183 180
         add(id);
184 181
         
185
-        label = new JLabel("Date: ");
186
-        add(label);
182
+        add(new JLabel("Date: "));
187 183
         add(date);
188 184
         
189
-        label = new JLabel("Severity: ");
190
-        add(label);
185
+        add(new JLabel("Severity: "));
191 186
         add(level);
192 187
         
193
-        label = new JLabel("Report status: ");
194
-        add(label);
188
+        add(new JLabel("Report status: "));
195 189
         add(reportStatus);
196 190
         
197
-        label = new JLabel("Error status: ");
198
-        add(label);
191
+        add(new JLabel("Error status: "));
199 192
         add(errorStatus);
200 193
         
201
-        label = new JLabel("Details: ");
202
-        add(label);
203
-        add(scrollPane);
204
-        
205
-        layoutGrid(this, 6, 2, 0, 0, SMALL_BORDER, SMALL_BORDER);
194
+        add(new JLabel("Details: "));
195
+        add(scrollPane, "grow");
206 196
     }
207 197
 
208 198
     public void errorAdded(final ProgramError error) {

+ 20
- 48
src/com/dmdirc/ui/swing/dialogs/error/ErrorListDialog.java View File

@@ -30,28 +30,25 @@ import com.dmdirc.logger.ProgramError;
30 30
 import com.dmdirc.ui.swing.MainFrame;
31 31
 import com.dmdirc.ui.swing.components.PackingTable;
32 32
 import com.dmdirc.ui.swing.components.StandardDialog;
33
-import static com.dmdirc.ui.swing.UIUtilities.LARGE_BORDER;
34
-import static com.dmdirc.ui.swing.UIUtilities.SMALL_BORDER;
35 33
 
36 34
 import java.awt.Dimension;
37 35
 import java.awt.event.ActionEvent;
38 36
 import java.awt.event.ActionListener;
39 37
 import java.util.ArrayList;
40 38
 import java.util.Collection;
41
-import java.util.List;
42 39
 
43
-import javax.swing.BorderFactory;
44
-import javax.swing.Box;
45
-import javax.swing.BoxLayout;
46 40
 import javax.swing.JButton;
47 41
 import javax.swing.JPanel;
48 42
 import javax.swing.JScrollPane;
43
+import javax.swing.JSplitPane;
49 44
 import javax.swing.JTable;
50 45
 import javax.swing.ListSelectionModel;
51 46
 import javax.swing.event.ListSelectionEvent;
52 47
 import javax.swing.event.ListSelectionListener;
53 48
 import javax.swing.table.TableCellRenderer;
54 49
 
50
+import net.miginfocom.swing.MigLayout;
51
+
55 52
 /**
56 53
  * Error list dialog.
57 54
  */
@@ -63,7 +60,7 @@ public final class ErrorListDialog extends StandardDialog implements
63 60
      * structure is changed (or anything else that would prevent serialized
64 61
      * objects being unserialized with the new class).
65 62
      */
66
-    private static final long serialVersionUID = 4;
63
+    private static final long serialVersionUID = 5;
67 64
     
68 65
     /** Previously instantiated instance of ErrorListDialog. */
69 66
     private static ErrorListDialog me;
@@ -83,9 +80,6 @@ public final class ErrorListDialog extends StandardDialog implements
83 80
     /** Error detail panel. */
84 81
     private ErrorDetailPanel errorDetails;
85 82
     
86
-    /** Buttons pane. */
87
-    private JPanel buttonsPanel;
88
-    
89 83
     /** Send button. */
90 84
     private JButton sendButton;
91 85
     
@@ -134,7 +128,7 @@ public final class ErrorListDialog extends StandardDialog implements
134 128
     
135 129
     /** Initialises the components. */
136 130
     private void initComponents() {
137
-        initButtonsPanel();
131
+        initButtons();
138 132
         
139 133
         scrollPane = new JScrollPane();
140 134
         
@@ -175,10 +169,8 @@ public final class ErrorListDialog extends StandardDialog implements
175 169
         errorDetails = new ErrorDetailPanel();
176 170
     }
177 171
     
178
-    /** Initialises the button panel. */
179
-    private void initButtonsPanel() {
180
-        buttonsPanel = new JPanel();
181
-        
172
+    /** Initialises the buttons. */
173
+    private void initButtons() {        
182 174
         orderButtons(new JButton(), new JButton());
183 175
         
184 176
         getCancelButton().setText("Close");
@@ -193,28 +185,6 @@ public final class ErrorListDialog extends StandardDialog implements
193 185
         } else {
194 186
             deleteAllButton.setEnabled(false);
195 187
         }
196
-        
197
-        sendButton.setPreferredSize(new Dimension(100, 25));
198
-        deleteButton.setPreferredSize(new Dimension(100, 25));
199
-        sendButton.setMinimumSize(new Dimension(100, 25));
200
-        deleteButton.setMinimumSize(new Dimension(100, 25));
201
-        deleteAllButton.setMinimumSize(new Dimension(100, 25));
202
-        
203
-        buttonsPanel.setBorder(BorderFactory.createEmptyBorder(0, SMALL_BORDER,
204
-                SMALL_BORDER, SMALL_BORDER));
205
-        
206
-        buttonsPanel.setPreferredSize(new Dimension(600, 35));
207
-        buttonsPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35));
208
-        
209
-        buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.LINE_AXIS));
210
-        buttonsPanel.add(Box.createHorizontalGlue());
211
-        buttonsPanel.add(deleteAllButton);
212
-        buttonsPanel.add(Box.createHorizontalGlue());
213
-        buttonsPanel.add(deleteButton);
214
-        buttonsPanel.add(Box.createHorizontalStrut(SMALL_BORDER));
215
-        buttonsPanel.add(sendButton);
216
-        buttonsPanel.add(Box.createHorizontalStrut(LARGE_BORDER));
217
-        buttonsPanel.add(getCancelButton());
218 188
     }
219 189
     
220 190
     /** Initialises the listeners. */
@@ -230,19 +200,21 @@ public final class ErrorListDialog extends StandardDialog implements
230 200
     
231 201
     /** Lays out the components. */
232 202
     private void layoutComponents() {
233
-        getContentPane().setLayout(new BoxLayout(getContentPane(),
234
-                BoxLayout.PAGE_AXIS));
203
+        final JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true);
204
+        final JPanel panel = new JPanel();
205
+        
206
+        panel.setLayout(new MigLayout("fill"));
207
+        
208
+        panel.add(errorDetails, "wrap, grow");
209
+        panel.add(deleteAllButton, "split 4, tag left, sgx button");
210
+        panel.add(deleteButton, "tag other, sgx button");
211
+        panel.add(sendButton, "tag other, sgx button");
212
+        panel.add(getCancelButton(), "tag ok, sgx button");
235 213
         
236
-        scrollPane.setBorder(BorderFactory.createCompoundBorder(
237
-                BorderFactory.createEmptyBorder(SMALL_BORDER, SMALL_BORDER,
238
-                0, SMALL_BORDER),
239
-                scrollPane.getBorder()));
240
-        errorDetails.setBorder(BorderFactory.createEmptyBorder(SMALL_BORDER,
241
-                SMALL_BORDER, 0, 0));
214
+        splitPane.setTopComponent(scrollPane);
215
+        splitPane.setBottomComponent(panel);
242 216
         
243
-        getContentPane().add(scrollPane);
244
-        getContentPane().add(errorDetails);
245
-        getContentPane().add(buttonsPanel);
217
+        getContentPane().add(splitPane);
246 218
     }
247 219
     
248 220
     /** {@inheritDoc}. */

+ 1
- 1
src/com/dmdirc/ui/swing/dialogs/error/FatalErrorDialog.java View File

@@ -74,7 +74,7 @@ public final class FatalErrorDialog extends JDialog implements ActionListener,
74 74
     private JLabel infoLabel;
75 75
     
76 76
     /** label. */
77
-    private JTextArea messageLabel;
77
+    private TextLabel messageLabel;
78 78
     
79 79
     /** label. */
80 80
     private JButton showMore;

+ 173
- 0
src/com/dmdirc/ui/swing/dialogs/serversetting/UserModesPane.java View File

@@ -0,0 +1,173 @@
1
+/*
2
+ * Copyright (c) 2006-2007 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.ui.swing.dialogs.serversetting;
24
+
25
+import com.dmdirc.Server;
26
+import com.dmdirc.parser.IRCParser;
27
+import static com.dmdirc.ui.swing.UIUtilities.SMALL_BORDER;
28
+
29
+import java.awt.GridBagConstraints;
30
+import java.awt.GridBagLayout;
31
+import java.util.Hashtable;
32
+import java.util.Map;
33
+
34
+import javax.swing.BorderFactory;
35
+import javax.swing.Box;
36
+import javax.swing.JCheckBox;
37
+import javax.swing.JPanel;
38
+
39
+/** User mode panel. */
40
+public final class UserModesPane extends JPanel {
41
+
42
+    /**
43
+     * A version number for this class. It should be changed whenever the class
44
+     * structure is changed (or anything else that would prevent serialized
45
+     * objects being unserialized with the new class).
46
+     */
47
+    private static final long serialVersionUID = 1;
48
+    /** Parent server. */
49
+    private final Server server;
50
+    /** The checkboxes used for boolean modes. */
51
+    private Map<String, JCheckBox> modeCheckBoxes;
52
+
53
+    /**
54
+     * Creates a new instance of UserModesPane.
55
+     *
56
+     * @param server Parent server
57
+     */
58
+    public UserModesPane(final Server server) {
59
+        super();
60
+
61
+        this.server = server;
62
+        
63
+        initModesPanel();
64
+
65
+        setVisible(true);
66
+    }
67
+
68
+    /** Updates the panel. */
69
+    public void update() {
70
+        setVisible(false);
71
+        removeAll();
72
+        initModesPanel();
73
+        setVisible(true);
74
+    }
75
+
76
+    /** Initialises the modes panel. */
77
+    private void initModesPanel() {
78
+        final GridBagConstraints constraints = new GridBagConstraints();
79
+
80
+        final IRCParser parser = server.getParser();
81
+
82
+        final String booleanModes = ""; //parser.getUserModes();
83
+        final String ourBooleanModes = parser.getMyself().getUserModeStr();
84
+
85
+        setLayout(new GridBagLayout());
86
+        setBorder(BorderFactory.createEmptyBorder(SMALL_BORDER, SMALL_BORDER,
87
+                SMALL_BORDER, SMALL_BORDER));
88
+
89
+        modeCheckBoxes =
90
+                new Hashtable<String, JCheckBox>();
91
+
92
+        constraints.gridx = 0;
93
+        constraints.gridy = 0;
94
+        constraints.fill = GridBagConstraints.HORIZONTAL;
95
+        constraints.anchor = GridBagConstraints.NORTHWEST;
96
+        constraints.weightx = 1.0;
97
+        constraints.weighty = 0.0;
98
+
99
+        // Lay out all the boolean mode checkboxes
100
+        for (int i = 0; i < booleanModes.length();
101
+                i++) {
102
+            final String mode = booleanModes.substring(i, i + 1);
103
+            final char modeChar = mode.toCharArray()[0];
104
+            final boolean state =
105
+                    ourBooleanModes.split(" ")[0].contains(mode.subSequence(0, 1));
106
+            String text;
107
+            String tooltip;
108
+
109
+            if (server.getConfigManager().
110
+                    getOptionBool("server", "friendlymodes", false) &&
111
+                    server.getConfigManager().hasOption("server", "mode" + mode)) {
112
+                text =  server.getConfigManager().
113
+                        getOption("server", "mode" + mode);
114
+            } else {
115
+                text = "Mode " + mode;
116
+            }
117
+
118
+            if (server.getConfigManager().hasOption("server", "mode" + mode)) {
119
+                tooltip =
120
+                        "Mode " + mode + ": " +
121
+                        server.getConfigManager().
122
+                        getOption("server", "mode" + mode);
123
+            } else {
124
+                tooltip = "Mode " + mode + ": Unknown";
125
+            }
126
+
127
+            final JCheckBox checkBox = new JCheckBox(text, state);
128
+            checkBox.setToolTipText(tooltip);
129
+            checkBox.setBorder(BorderFactory.createEmptyBorder(SMALL_BORDER, 0,
130
+                    0, SMALL_BORDER));
131
+            add(checkBox, constraints);
132
+
133
+            constraints.gridx++;
134
+            if (constraints.gridx == 2) {
135
+                constraints.gridy++;
136
+                constraints.gridx = 0;
137
+            }
138
+
139
+            modeCheckBoxes.put(mode, checkBox);
140
+        }
141
+        
142
+        constraints.weighty = 1.0;
143
+        constraints.fill = GridBagConstraints.VERTICAL;
144
+        add(Box.createVerticalGlue(), constraints);
145
+    }
146
+
147
+    /**
148
+     * Processes the channel settings dialog and constructs a mode string for
149
+     * changed modes, then sends this to the server.
150
+     */
151
+    public void setChangedBooleanModes() {
152
+        /*boolean changed = false;
153
+        final IRCParser parser = channel.getServer().getParser();
154
+        final String booleanModes = parser.getBoolChanModes();
155
+        final String ourBooleanModes = channel.getChannelInfo().getModeStr();
156
+
157
+        for (int i = 0; i < booleanModes.length();
158
+                i++) {
159
+            final String mode = booleanModes.substring(i, i + 1);
160
+            final boolean state =
161
+                    ourBooleanModes.split(" ")[0].contains(mode.subSequence(0, 1));
162
+
163
+            if (modeCheckBoxes.get(mode) != null &&
164
+                    state != modeCheckBoxes.get(mode).isSelected()) {
165
+                changed = true;
166
+                //change the mode
167
+            }
168
+        }
169
+        if (changed) {
170
+            //send modes
171
+        }*/
172
+    }
173
+}

+ 489
- 0
src/net/miginfocom/layout/AC.java View File

@@ -0,0 +1,489 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+import java.io.*;
38
+import java.util.ArrayList;
39
+
40
+/** A constraint that holds the column <b>or</b> row constraints for the grid. It also holds the gaps between the rows and columns.
41
+ * <p>
42
+ * This class is a holder and builder for a number of {@link net.miginfocom.layout.DimConstraint}s.
43
+ * <p>
44
+ * For a more thorough explanation of what these constraints do, and how to build the constriants, see the White Paper or Cheat Sheet at www.migcomponents.com.
45
+ * <p>
46
+ * Note that there are two way to build this constraint. Through String (e.g. <code>"[100]3[200,fill]"</code> or through API (E.g.
47
+ * <code>new AxisConstraint().size("100").gap("3").size("200").fill()</code>.
48
+ */
49
+public final class AC implements Externalizable {
50
+    
51
+    /**
52
+     * A version number for this class. It should be changed whenever the class
53
+     * structure is changed (or anything else that would prevent serialized
54
+     * objects being unserialized with the new class).
55
+     */
56
+    private static final long serialVersionUID = 1;
57
+
58
+    private final ArrayList<DimConstraint> cList =
59
+            new ArrayList<DimConstraint>(8);
60
+    private transient int curIx = 0;
61
+
62
+    /** Constructor. Creates an instance that can be configured manually. Will be initialized with a default
63
+     * {@link net.miginfocom.layout.DimConstraint}.
64
+     */
65
+    public AC() {
66
+        cList.add(new DimConstraint());
67
+    }
68
+
69
+    /** Property. The different {@link net.miginfocom.layout.DimConstraint}s that this object consists of.
70
+     * These <code><DimConstraints/code> contains all information in this class.
71
+     * @return The different {@link net.miginfocom.layout.DimConstraint}s that this object consists of. A new list and
72
+     * never <code>null</code>.
73
+     */
74
+    public final DimConstraint[] getConstaints() {
75
+        return cList.toArray(new DimConstraint[cList.size()]);
76
+    }
77
+
78
+    /** Sets the different {@link net.miginfocom.layout.DimConstraint}s that this object should consists of.
79
+     * @param constr The different {@link net.miginfocom.layout.DimConstraint}s that this object consists of. The list
80
+     * will be copied for storage. <code>null</code> or and emty array will reset the constaints to one <code>DimConstraint</code>
81
+     * with default values.
82
+     */
83
+    public final void setConstaints(DimConstraint[] constr) {
84
+        if (constr == null || constr.length < 1) {
85
+            constr =new DimConstraint[]{new DimConstraint()};
86
+        }
87
+        cList.clear();
88
+        cList.ensureCapacity(constr.length);
89
+        for (int i = 0; i < constr.length;
90
+                i++) {
91
+            cList.add(constr[i]);
92
+        }
93
+    }
94
+
95
+    /** Returns the number of rows/columns that this constraints currently have.
96
+     * @return The number of rows/columns that this constraints currently have. At least 1.
97
+     */
98
+    public int getCount() {
99
+        return cList.size();
100
+    }
101
+
102
+    /** Sets the total number of rows/columns to <code>size</code>. If the number of rows/columns is already more
103
+     * than <code>size</code> nothing will happen.
104
+     * @param size The total number of rows/columns
105
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
106
+     */
107
+    public final AC count(int size) {
108
+        makeSize(size);
109
+        return this;
110
+    }
111
+
112
+    /** Specifies that the current row/column should not be grid-like. The while row/colum will have its components layed out
113
+     * in one single cell. It is the same as to say that the cells in this column/row will all be merged (a.k.a spanned).
114
+     * <p>
115
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
116
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
117
+     */
118
+    public final AC noGrid() {
119
+        return noGrid(curIx);
120
+    }
121
+
122
+    /** Specifies that the indicated rows/columns should not be grid-like. The while row/colum will have its components layed out
123
+     * in one single cell. It is the same as to say that the cells in this column/row will all be merged (a.k.a spanned).
124
+     * <p>
125
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
126
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
127
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
128
+     */
129
+    public final AC noGrid(int... indexes) {
130
+        for (int i = indexes.length - 1; i >= 0;
131
+                i--) {
132
+            int ix = indexes[i];
133
+            makeSize(ix);
134
+            cList.get(ix).setNoGrid(true);
135
+        }
136
+        return this;
137
+    }
138
+
139
+    /** Sets the current row/column to <code>i</code>. If the current number of rows/columns is less than <code>i</code> a call
140
+     * to {@link #count(int)} will set the size accoringly.
141
+     * <p>
142
+     * The next call to any of the constriant methods (e.g. {@link net.miginfocom.layout.AC#noGrid}) will be carried
143
+     * out on this new row/column.
144
+     * <p>
145
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
146
+     * @param i The new current row/column.
147
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
148
+     */
149
+    public final AC index(int i) {
150
+        makeSize(i);
151
+        curIx = i;
152
+        return this;
153
+    }
154
+
155
+    /** Specifies that the current row/column's component should grow by default. It does not affect the size of the row/column.
156
+     * <p>
157
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
158
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
159
+     */
160
+    public final AC fill() {
161
+        return fill(curIx);
162
+    }
163
+
164
+    /** Specifies that the indicated rows'/columns' component should grow by default. It does not affect the size of the row/column.
165
+     * <p>
166
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
167
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
168
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
169
+     */
170
+    public final AC fill(int... indexes) {
171
+        for (int i = indexes.length - 1; i >= 0;
172
+                i--) {
173
+            int ix = indexes[i];
174
+            makeSize(ix);
175
+            cList.get(ix).setFill(true);
176
+        }
177
+        return this;
178
+    }
179
+//	/** Specifies that the current row/column should be put in the end group <code>s</code> and will thus share the same ending
180
+//	 * coordinate within the group.
181
+//	 * <p>
182
+//	 * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
183
+//	 * @param s A name to associate on the group that should be the same for other rows/columns in the same group.
184
+//	 * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
185
+//	 */
186
+//	public final AxisConstraint endGroup(String s)
187
+//	{
188
+//		return endGroup(s, curIx);
189
+//	}
190
+//
191
+//	/** Specifies that the indicated rows/columns should be put in the end group <code>s</code> and will thus share the same ending
192
+//	 * coordinate within the group.
193
+//	 * <p>
194
+//	 * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
195
+//	 * @param s A name to associate on the group that should be the same for other rows/columns in the same group.
196
+//	 * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
197
+//	 * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
198
+//	 */
199
+//	public final AxisConstraint endGroup(String s, int... indexes)
200
+//	{
201
+//		for (int i = indexes.length - 1; i >= 0; i--) {
202
+//			int ix = indexes[i];
203
+//			makeSize(ix);
204
+//			cList.get(ix).setEndGroup(s);
205
+//		}
206
+//		return this;
207
+//	}
208
+
209
+    /** Specifies that the current row/column should be put in the size group <code>s</code> and will thus share the same size
210
+     * constraints as the other components in the group.
211
+     * <p>
212
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
213
+     * @param s A name to associate on the group that should be the same for other rows/columns in the same group.
214
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
215
+     */
216
+    public final AC sizeGroup(String s) {
217
+        return sizeGroup(s, curIx);
218
+    }
219
+
220
+    /** Specifies that the indicated rows/columns should be put in the size group <code>s</code> and will thus share the same size
221
+     * constraints as the other components in the group.
222
+     * <p>
223
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
224
+     * @param s A name to associate on the group that should be the same for other rows/columns in the same group.
225
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
226
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
227
+     */
228
+    public final AC sizeGroup(String s, int... indexes) {
229
+        for (int i = indexes.length - 1; i >= 0;
230
+                i--) {
231
+            int ix = indexes[i];
232
+            makeSize(ix);
233
+            cList.get(ix).setSizeGroup(s);
234
+        }
235
+        return this;
236
+    }
237
+
238
+    /** Specifies the current row/column's min and/or preferred and/or max size. E.g. <code>"10px"</code> or <code>"50:100:200"</code>.
239
+     * <p>
240
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
241
+     * @param s The minimum and/or preferred and/or maximum size of this row. The string will be interpreted
242
+     * as a <b>BoundSize</b>. For more info on how <b>BoundSize</b> is formatted see the documentation.
243
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
244
+     */
245
+    public final AC size(String s) {
246
+        return size(s, curIx);
247
+    }
248
+
249
+    /** Specifies the indicated rows'/columns' min and/or preferred and/or max size. E.g. <code>"10px"</code> or <code>"50:100:200"</code>.
250
+     * <p>
251
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
252
+     * @param size The minimum and/or preferred and/or maximum size of this row. The string will be interpreted
253
+     * as a <b>BoundSize</b>. For more info on how <b>BoundSize</b> is formatted see the documentation.
254
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
255
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
256
+     */
257
+    public final AC size(String size, int... indexes) {
258
+        BoundSize bs =
259
+                ConstraintParser.parseBoundSize(size, false, true);
260
+        for (int i = indexes.length - 1; i >= 0;
261
+                i--) {
262
+            int ix = indexes[i];
263
+            makeSize(ix);
264
+            cList.get(ix).setSize(bs);
265
+        }
266
+        return this;
267
+    }
268
+
269
+    /** Specifies the gap size to be the default one <b>AND</b> moves to the next column/row. The method is called <code>.gap()</code>
270
+     * rather the more natural <code>.next()</code> to indicate that it is very much related to the other <code>.gap(..)</code> methods.
271
+     * <p>
272
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
273
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
274
+     */
275
+    public final AC gap() {
276
+        curIx++;
277
+        return this;
278
+    }
279
+
280
+    /** Specifies the gap size to <code>size</code> <b>AND</b> moves to the next column/row.
281
+     * <p>
282
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
283
+     * @param size minimum and/or preferred and/or maximum size of the gap between this and the next row/column.
284
+     * The string will be interpreted as a <b>BoundSize</b>. For more info on how <b>BoundSize</b> is formatted see the documentation.
285
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
286
+     */
287
+    public final AC gap(String size) {
288
+        return gap(size, curIx++);
289
+    }
290
+
291
+    /** Specifies the indicated rows'/columns' gap size to <code>size</code>.
292
+     * <p>
293
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
294
+     * @param size minimum and/or preferred and/or maximum size of the gap between this and the next row/column.
295
+     * The string will be interpreted as a <b>BoundSize</b>. For more info on how <b>BoundSize</b> is formatted see the documentation.
296
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
297
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
298
+     */
299
+    public final AC gap(String size, int... indexes) {
300
+        BoundSize bsa =
301
+                size != null
302
+                ? ConstraintParser.parseBoundSize(size, true, true) : null;
303
+
304
+        for (int i = indexes.length - 1; i >= 0;
305
+                i--) {
306
+            int ix = indexes[i];
307
+            makeSize(ix);
308
+            if (bsa != null) {
309
+                cList.get(ix).setGapAfter(bsa);
310
+            }
311
+        }
312
+        return this;
313
+    }
314
+
315
+    /** Specifies the current row/column's columns default alignment <b>for its components</b>. It does not affect the positioning
316
+     * or size of the columns/row itself. For columns it is the horizonal alignment (e.g. "left") and for rows it is the vertical
317
+     * alignment (e.g. "top").
318
+     * <p>
319
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
320
+     * @param side The default side to align the components. E.g. "top" or "left", or "leading" or "trailing" or "bottom" or "right".
321
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
322
+     */
323
+    public final AC align(String side) {
324
+        return align(side, curIx);
325
+    }
326
+
327
+    /** Specifies the indicated rows'/columns' columns default alignment <b>for its components</b>. It does not affect the positioning
328
+     * or size of the columns/row itself. For columns it is the horizonal alignment (e.g. "left") and for rows it is the vertical
329
+     * alignment (e.g. "top").
330
+     * <p>
331
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
332
+     * @param side The default side to align the components. E.g. "top" or "left", or "before" or "after" or "bottom" or "right".
333
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
334
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
335
+     */
336
+    public final AC align(String side, int... indexes) {
337
+        UnitValue al =
338
+                ConstraintParser.parseAlignKeywords(side, true);
339
+        if (al == null) {
340
+            al =    ConstraintParser.parseAlignKeywords(side, false);
341
+        }
342
+        for (int i = indexes.length - 1; i >= 0;
343
+                i--) {
344
+            int ix = indexes[i];
345
+            makeSize(ix);
346
+            cList.get(ix).setAlign(al);
347
+        }
348
+        return this;
349
+    }
350
+
351
+    /** Specifies the current row/column's grow priority.
352
+     * <p>
353
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
354
+     * @param p The new grow priority.
355
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
356
+     */
357
+    public final AC growPrio(int p) {
358
+        return growPrio(p, curIx);
359
+    }
360
+
361
+    /** Specifies the indicated rows'/columns' grow priority.
362
+     * <p>
363
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
364
+     * @param p The new grow priority.
365
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
366
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
367
+     */
368
+    public final AC growPrio(int p, int... indexes) {
369
+        for (int i = indexes.length - 1; i >= 0;
370
+                i--) {
371
+            int ix = indexes[i];
372
+            makeSize(ix);
373
+            cList.get(ix).setGrowPriority(p);
374
+        }
375
+        return this;
376
+    }
377
+
378
+    /** Specifies the current row/column's grow weight within columns/rows with the same <code>grow priority</code>.
379
+     * <p>
380
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
381
+     * @param w The new grow weight.
382
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
383
+     */
384
+    public final AC grow(float w) {
385
+        return grow(w, curIx);
386
+    }
387
+
388
+    /** Specifies the indicated rows'/columns' grow weight within columns/rows with the same <code>grow priority</code>.
389
+     * <p>
390
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
391
+     * @param w The new grow weight.
392
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
393
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
394
+     */
395
+    public final AC grow(float w, int... indexes) {
396
+        Float gw = new Float(w);
397
+        for (int i = indexes.length - 1; i >= 0;
398
+                i--) {
399
+            int ix = indexes[i];
400
+            makeSize(ix);
401
+            cList.get(ix).setGrow(gw);
402
+        }
403
+        return this;
404
+    }
405
+
406
+    /** Specifies the current row/column's shrink priority.
407
+     * <p>
408
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
409
+     * @param p The new shrink priority.
410
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
411
+     */
412
+    public final AC shrinkPrio(int p) {
413
+        return shrinkPrio(p, curIx);
414
+    }
415
+
416
+    /** Specifies the indicated rows'/columns' shrink priority.
417
+     * <p>
418
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
419
+     * @param p The new shrink priority.
420
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
421
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
422
+     */
423
+    public final AC shrinkPrio(int p, int... indexes) {
424
+        for (int i = indexes.length - 1; i >= 0;
425
+                i--) {
426
+            int ix = indexes[i];
427
+            makeSize(ix);
428
+            cList.get(ix).setShrinkPriority(p);
429
+        }
430
+        return this;
431
+    }
432
+
433
+    /** Specifies that the current row/column's shrink weight withing the columns/rows with the same <code>shrink priority</code>.
434
+     * <p>
435
+     * For a more thorough explanation of what this constraint does see the White Paper or Cheat Sheet at www.migcomponents.com.
436
+     * @param w The shrink weight.
437
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
438
+     */
439
+    public final AC shrinkWeight(float w) {
440
+        return shrinkWeight(w, curIx);
441
+    }
442
+
443
+    /** Specifies the indicated rows'/columns' shrink weight withing the columns/rows with the same <code>shrink priority</code>.
444
+     * <p>
445
+     * For a more thorough explanation of what this constraint does see the White Paper or Cheat Sheet at www.migcomponents.com.
446
+     * @param w The shrink weight.
447
+     * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint.
448
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>.
449
+     */
450
+    public final AC shrinkWeight(float w, int... indexes) {
451
+        Float sw = new Float(w);
452
+        for (int i = indexes.length - 1; i >= 0;
453
+                i--) {
454
+            int ix = indexes[i];
455
+            makeSize(ix);
456
+            cList.get(ix).setShrink(sw);
457
+        }
458
+        return this;
459
+    }
460
+
461
+    private void makeSize(int sz) {
462
+        if (cList.size() <= sz) {
463
+            cList.ensureCapacity(sz);
464
+            for (int i = cList.size(); i <= sz;
465
+                    i++) {
466
+                cList.add(new DimConstraint());
467
+            }
468
+        }
469
+    }
470
+    // ************************************************
471
+    // Persistence Delegate and Serializable combined.
472
+    // ************************************************
473
+
474
+    private Object readResolve() throws ObjectStreamException {
475
+        return LayoutUtil.getSerializedObject(this);
476
+    }
477
+
478
+    public void readExternal(ObjectInput in) throws IOException,
479
+            ClassNotFoundException {
480
+        LayoutUtil.setSerializedObject(this,
481
+                LayoutUtil.readAsXML(in));
482
+    }
483
+
484
+    public void writeExternal(ObjectOutput out) throws IOException {
485
+        if (getClass() == AC.class) {
486
+            LayoutUtil.writeAsXML(out, this);
487
+        }
488
+    }
489
+}

+ 247
- 0
src/net/miginfocom/layout/BoundSize.java View File

@@ -0,0 +1,247 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+import java.beans.Encoder;
38
+import java.beans.Expression;
39
+import java.beans.PersistenceDelegate;
40
+import java.io.*;
41
+
42
+/** A size that contains minimum, preferred and maximum size of type {@link UnitValue}.
43
+ * <p>
44
+ * This class is a simple value container and it is immutable.
45
+ * <p>
46
+ * If a size is missing (i.e., <code>null</code>) that boundary should be considered "not in use".
47
+ * <p>
48
+ * You can create a BoundSize from a String with the use of {@link ConstraintParser#parseBoundSize(String, boolean, boolean)}
49
+ */
50
+public class BoundSize implements Serializable
51
+{
52
+	public static final BoundSize ZERO_PIXEL = new BoundSize(UnitValue.ZERO, "0px");
53
+
54
+	private final transient UnitValue min;
55
+	private final transient UnitValue pref;
56
+	private final transient UnitValue max;
57
+	private final transient boolean gapPush;
58
+
59
+	/** Constructor that use the same value for min/preferred/max size.
60
+	 * @param minMaxPref The value to use for min/preferred/max size.
61
+	 * @param createString The string used to create the BoundsSize.
62
+	 */
63
+	public BoundSize(UnitValue minMaxPref, String createString)
64
+	{
65
+		this(minMaxPref, minMaxPref, minMaxPref, createString);
66
+	}
67
+
68
+	/** Constructor. <b>This method is here for serilization only and should normally not be used. Use
69
+	 * {@link ConstraintParser#parseBoundSize(String, boolean, boolean)} instead.
70
+	 * @param min The minimum size. May be <code>null</code>.
71
+	 * @param preferred  The preferred size. May be <code>null</code>.
72
+	 * @param max  The maximum size. May be <code>null</code>.
73
+	 * @param createString The string used to create the BoundsSize.
74
+	 */
75
+	public BoundSize(UnitValue min, UnitValue preferred, UnitValue max, String createString)    // Bound to old delegate!!!!!
76
+	{
77
+		this(min, preferred, max, false, createString);
78
+	}
79
+
80
+	/** Constructor. <b>This method is here for serilization only and should normally not be used. Use
81
+	 * {@link ConstraintParser#parseBoundSize(String, boolean, boolean)} instead.
82
+	 * @param min The minimum size. May be <code>null</code>.
83
+	 * @param preferred  The preferred size. May be <code>null</code>.
84
+	 * @param max  The maximum size. May be <code>null</code>.
85
+	 * @param gapPush If the size should be hinted as "pushing" and thus want to occupy free space if noone else is claiming it.
86
+	 * @param createString The string used to create the BoundsSize.
87
+	 */
88
+	public BoundSize(UnitValue min, UnitValue preferred, UnitValue max, boolean gapPush, String createString)
89
+	{
90
+		this.min = min;
91
+		this.pref = preferred;
92
+		this.max = max;
93
+		this.gapPush = gapPush;
94
+
95
+		LayoutUtil.putCCString(this, createString);    // this escapes!!
96
+	}
97
+
98
+	/** Returns the minimum size as sent into the constructor.
99
+	 * @return The minimum size as sent into the constructor. May be <code>null</code>.
100
+	 */
101
+	public final UnitValue getMin()
102
+	{
103
+		return min;
104
+	}
105
+
106
+	/** Returns the preferred size as sent into the constructor.
107
+	 * @return The preferred size as sent into the constructor. May be <code>null</code>.
108
+	 */
109
+	public final UnitValue getPreferred()
110
+	{
111
+		return pref;
112
+	}
113
+
114
+	/** Returns the maximum size as sent into the constructor.
115
+	 * @return The maximum size as sent into the constructor. May be <code>null</code>.
116
+	 */
117
+	public final UnitValue getMax()
118
+	{
119
+		return max;
120
+	}
121
+
122
+	/** If the size should be hinted as "pushing" and thus want to occupy free space if noone else is claiming it.
123
+	 * @return The value.
124
+	 */
125
+	public boolean getGapPush()
126
+	{
127
+		return gapPush;
128
+	}
129
+
130
+	/** Returns if this bound size has no min, preferred or maximum size set (they are all <code>null</code>)
131
+	 * @return If unset.
132
+	 */
133
+	public boolean isUnset()
134
+	{
135
+		return pref == null && min == null && max == null;
136
+	}
137
+
138
+	/** Returns the minimum, preferred or maximum size for this bounded size.
139
+	 * @param sizeType The type. <code>LayoutUtil.MIN</code>, <code>LayoutUtil.PREF</code> or <code>LayoutUtil.MAX</code>.
140
+	 * @return
141
+	 */
142
+	final UnitValue getSize(int sizeType)
143
+	{
144
+		switch(sizeType) {
145
+			case LayoutUtil.MIN:
146
+				return min;
147
+			case LayoutUtil.PREF:
148
+				return pref;
149
+			case LayoutUtil.MAX:
150
+				return max;
151
+			default:
152
+				throw new IllegalArgumentException("Unknown size: " + sizeType);
153
+		}
154
+	}
155
+
156
+	/** Convert the bound sizes to pixels.
157
+	 * <p>
158
+	 * <code>null</code> bound sizes will be 0 for min and preferred and {@link net.miginfocom.layout.LayoutUtil#INF} for max.
159
+	 * @param refSize The reference size.
160
+	 * @param parent The parent. Not <code>null</code>.
161
+	 * @param comp The component, if applicable, can be <code>null</code>.
162
+	 * @return An array of lenth three (min,pref,max).
163
+	 */
164
+	final int[] getPixelSizes(float refSize, ContainerWrapper parent, ComponentWrapper comp)
165
+	{
166
+		return new int[] {
167
+				min != null ? min.getPixels(refSize, parent, comp) : 0,
168
+				pref != null ? pref.getPixels(refSize, parent, comp) : 0,
169
+				max != null ? max.getPixels(refSize, parent, comp) : LayoutUtil.INF
170
+		};
171
+	}
172
+
173
+	/** Returns the a constraint string that can be re-parsed to be the exact same UnitValue.
174
+	 * @return A String. Never <code>null</code>.
175
+	 */
176
+	String getConstraintString()
177
+	{
178
+		String cs = LayoutUtil.getCCString(this);
179
+		if (cs != null)
180
+			return cs;
181
+
182
+		if (min == pref && pref == max)
183
+			return min != null ? (min.getConstraintString() + "!") : "null";
184
+
185
+		StringBuilder sb = new StringBuilder(16);
186
+
187
+		if (min != null)
188
+			sb.append(min.getConstraintString()).append(':');
189
+
190
+		if (pref != null) {
191
+			sb.append(pref.getConstraintString());
192
+		} else if (min != null) {
193
+			sb.append('n');
194
+		}
195
+
196
+		if (max != null)
197
+			sb.append(sb.length() == 0 ? "::" : ":").append(max.getConstraintString());
198
+
199
+		if (gapPush) {
200
+			if (sb.length() > 0)
201
+				sb.append(':');
202
+			sb.append("push");
203
+		}
204
+
205
+		return sb.toString();
206
+	}
207
+
208
+	static {
209
+		LayoutUtil.setDelegate(BoundSize.class, new PersistenceDelegate() {
210
+			protected Expression instantiate(Object oldInstance, Encoder out)
211
+			{
212
+				BoundSize bs = (BoundSize) oldInstance;
213
+				if (Grid.TEST_GAPS) {
214
+					return new Expression(oldInstance, BoundSize.class, "new", new Object[] {
215
+							bs.getMin(), bs.getPreferred(), bs.getMax(), bs.getGapPush(), bs.getConstraintString()
216
+					});
217
+				} else {
218
+					return new Expression(oldInstance, BoundSize.class, "new", new Object[] {
219
+							bs.getMin(), bs.getPreferred(), bs.getMax(), bs.getConstraintString()
220
+					});
221
+				}
222
+			}
223
+		});
224
+	}
225
+
226
+	// ************************************************
227
+	// Persistence Delegate and Serializable combined.
228
+	// ************************************************
229
+
230
+	private static final long serialVersionUID = 1L;
231
+
232
+	protected Object readResolve() throws ObjectStreamException
233
+	{
234
+		return LayoutUtil.getSerializedObject(this);
235
+	}
236
+
237
+	private void writeObject(ObjectOutputStream out) throws IOException
238
+	{
239
+		if (getClass() == BoundSize.class)
240
+			LayoutUtil.writeAsXML(out, this);
241
+	}
242
+
243
+	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
244
+	{
245
+		LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in));
246
+	}
247
+}

+ 1432
- 0
src/net/miginfocom/layout/CC.java
File diff suppressed because it is too large
View File


+ 255
- 0
src/net/miginfocom/layout/ComponentWrapper.java View File

@@ -0,0 +1,255 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+/** A class that wraps the important parts of a Component.
38
+ * <p>
39
+ * <b>NOTE!</b>.equals() and .hashcode() should be shunted to the wrapped component. E.g.
40
+ * <pre>
41
+ * 	public int hashCode()
42
+{
43
+return getComponent().hashCode();
44
+}
45
+public final boolean equals(Object o)
46
+{
47
+if (o == null || o instanceof ComponentWrapper == false)
48
+return false;
49
+return getComponent().equals(((ComponentWrapper) o).getComponent());
50
+}
51
+ * </pre>
52
+ */
53
+public interface ComponentWrapper {
54
+
55
+    static final int TYPE_UNSET = -1;
56
+    public static final int TYPE_UNKNOWN = 0;
57
+    public static final int TYPE_CONTAINER = 1;
58
+    public static final int TYPE_LABEL = 2;
59
+    public static final int TYPE_TEXT_FIELD = 3;
60
+    public static final int TYPE_TEXT_AREA = 4;
61
+    public static final int TYPE_BUTTON = 5;
62
+    public static final int TYPE_LIST = 6;
63
+    public static final int TYPE_TABLE = 7;
64
+    public static final int TYPE_SCROLL_PANE = 8;
65
+    public static final int TYPE_IMAGE = 9;
66
+    public static final int TYPE_PANEL = 10;
67
+    public static final int TYPE_COMBO_BOX = 11;
68
+    public static final int TYPE_SLIDER = 12;
69
+    public static final int TYPE_SPINNER = 13;
70
+    public static final int TYPE_PROGRESS_BAR = 14;
71
+    public static final int TYPE_TREE = 15;
72
+    public static final int TYPE_CHECK_BOX = 16;
73
+    public static final int TYPE_SCROLL_BAR = 17;
74
+    public static final int TYPE_SEPARATOR = 18;
75
+
76
+    /** Returns the actual object that this wrapper is aggregating. This might be needed for getting
77
+     * information about the object that the wrapper interface does not provide.
78
+     * <p>
79
+     * If this is a container the container should be returned instead.
80
+     * @return The actual object that this wrapper is aggregating. Not <code>null</code>.
81
+     */
82
+    public abstract Object getComponent();
83
+
84
+    /** Returns the current x coordinate for this component.
85
+     * @return The current x coordinate for this component.
86
+     */
87
+    public abstract int getX();
88
+
89
+    /** Returns the current y coordinate for this component.
90
+     * @return The current y coordinate for this component.
91
+     */
92
+    public abstract int getY();
93
+
94
+    /** Returns the current width for this component.
95
+     * @return The current width for this component.
96
+     */
97
+    public abstract int getWidth();
98
+
99
+    /** Returns the current height for this component.
100
+     * @return The current height for this component.
101
+     */
102
+    public abstract int getHeight();
103
+
104
+    /** Returns the screen x-coordinate for the upper left coordinate of the component layoutable bounds.
105
+     * @return The screen x-coordinate for the upper left coordinate of the component layoutable bounds.
106
+     */
107
+    public abstract int getScreenLocationX();
108
+
109
+    /** Returns the screen y-coordinate for the upper left coordinate of the component layoutable bounds.
110
+     * @return The screen y-coordinate for the upper left coordinate of the component layoutable bounds.
111
+     */
112
+    public abstract int getScreenLocationY();
113
+
114
+    /** Returns the minimum width of the component.
115
+     * @return The minimum width of the component.
116
+     */
117
+    public abstract int getMinimumWidth();
118
+
119
+    /** Returns the minimum height of the component.
120
+     * @return The minimum height of the component.
121
+     */
122
+    public abstract int getMinimumHeight();
123
+
124
+    /** Returns the preferred width of the component.
125
+     * @return The preferred width of the component.
126
+     */
127
+    public abstract int getPreferredWidth();
128
+
129
+    /** Returns the preferred height of the component.
130
+     * @return The preferred height of the component.
131
+     */
132
+    public abstract int getPreferredHeight();
133
+
134
+    /** Returns the maximum width of the component.
135
+     * @return The maximum width of the component.
136
+     */
137
+    public abstract int getMaximumWidth();
138
+
139
+    /** Returns the maximum height of the component.
140
+     * @return The maximum height of the component.
141
+     */
142
+    public abstract int getMaximumHeight();
143
+
144
+    /** Sets the component's bounds.
145
+     * @param x The x coordinate.
146
+     * @param y The y coordinate.
147
+     * @param width The width.
148
+     * @param height The height.
149
+     */
150
+    public abstract void setBounds(int x, int y, int width, int height);
151
+
152
+    /** Returns if the component's visibility is set to <code>true</code>. This should not return if the component is
153
+     * actually visibile, but if the visibility is set to true or not.
154
+     * @return <code>true</code> means visible.
155
+     */
156
+    public abstract boolean isVisible();
157
+
158
+    /** Returns the baseline for the component given the suggested height.
159
+     * @param width The width to calculate for if other than the current. If <code>-1</code> the current size should be used.
160
+     * @param height The height to calculate for if other than the current. If <code>-1</code> the current size should be used.
161
+     * @return The baseline from the top or -1 if not applicable.
162
+     */
163
+    public abstract int getBaseline(int width, int height);
164
+
165
+    /** Returns if the component has a baseline and if it can be retrieved. Should for instance return
166
+     * <code>false</code> for Swing before mustang.
167
+     * @return If the component has a baseline and if it can be retrieved.
168
+     */
169
+    public abstract boolean hasBaseline();
170
+
171
+    /** Returns the container for this component.
172
+     * @return The container for this component. Should never be <code>null</code>.
173
+     */
174
+    public abstract ContainerWrapper getParent();
175
+
176
+    /** Returns the pixel unit factor for the horizontal or vertical dimension.
177
+     * <p>
178
+     * The factor is 1 for both dimensions on the normal font in a JPanel on Windows. The factor should increase with a bigger "X".
179
+     * <p>
180
+     * This is the Swing version:
181
+     * <pre>
182
+     * Rectangle2D r = fm.getStringBounds("X", parent.getGraphics());
183
+     * wFactor = r.getWidth() / 6;
184
+     * hFactor = r.getHeight() / 13.27734375f;
185
+     * </pre>
186
+     * @param isHor If it is the horizontal factor that should be returned.
187
+     * @return The factor.
188
+     */
189
+    public abstract float getPixelUnitFactor(boolean isHor);
190
+
191
+    /** Returns the DPI (Dots Per Inch) of the screen the component is currently in or for the default
192
+     * screen if the component is not visible.
193
+     * @return The DPI.
194
+     */
195
+    public abstract int getHorizontalScreenDPI();
196
+
197
+    /** Returns the DPI (Dots Per Inch) of the screen the component is currently in or for the default
198
+     * screen if the component is not visible.
199
+     * @return The DPI.
200
+     */
201
+    public abstract int getVerticalScreenDPI();
202
+
203
+    /** Returns the pixel size of the screen that the component is currently in or for the default
204
+     * screen if the component is not visible or <code>null</code>.
205
+     * @return The screen size. E.g. <code>1280</code>.
206
+     */
207
+    public abstract int getScreenWidth();
208
+
209
+    /** Returns the pixel size of the screen that the component is currently in or for the default
210
+     * screen if the component is not visible or <code>null</code>.
211
+     * @return The screen size. E.g. <code>1024</code>.
212
+     */
213
+    public abstract int getScreenHeight();
214
+
215
+    /** Returns a String id that can be used to reference the component in link constraints. This value should
216
+     * return the default id for the component. The id can be set for a component in the constraints and if
217
+     * so the value returned by this method will never be used. If there are no sensible id for the component
218
+     * <code>null</code> should be returned.
219
+     * <p>
220
+     * For instance the Swing implementation returns the string returned from <code>Component.getName()</code>.
221
+     * @return The string link id or <code>null</code>.
222
+     */
223
+    public abstract String getLinkId();
224
+
225
+    /** Returns a hash code that should be resonably different for anything that might change the layout. This value is used to
226
+     *  know if the component layout needs to clear any caches.
227
+     * @return A hash code that should be resonably different for anything that might change the layout. Returns -1 if the widget is
228
+     * disposed.
229
+     */
230
+    public abstract int getLayoutHashCode();
231
+
232
+    /** Returns the padding on a component by component basis. This method can be overridden to return padding to compensate for example for
233
+     * borders that have shadows or where the outer most pixel is not the visual "edge" to align to.
234
+     * <p>
235
+     * Default implementation returnes <code>null</code> for all components except for Windows XP's JTabbedPane which will return new Insets(0, 0, 2, 2).
236
+     * <p>
237
+     * <b>NOTE!</B> To reduce cenerated garbage the returned padding should never be changed so that the same insets can be returned many times.
238
+     * @return <code>null</code> if no padding. <b>NOTE!</B> To reduce cenerated garbage the returned padding should never be changed so that
239
+     * the same insets can be returned many times. [top, left, bottom, right]
240
+     */
241
+    public int[] getVisualPadding();
242
+
243
+    /** Paints component outline to indicate where it is.
244
+     */
245
+    public abstract void paintDebugOutline();
246
+
247
+    /** Returns the type of component that this wrapper is wrapping.
248
+     * <p>
249
+     * This method can be invoked often so the result should be cached.
250
+     * @param disregardScrollPane Is <code>true</code> any wrapping scroll pane should be disregarded and the type
251
+     * of the scrolled component should be returned.
252
+     * @return The type of component that this wrapper is wrapping. E.g. {@link #TYPE_LABEL}.
253
+     */
254
+    public abstract int getComponetType(boolean disregardScrollPane);
255
+}

+ 1580
- 0
src/net/miginfocom/layout/ConstraintParser.java
File diff suppressed because it is too large
View File


+ 69
- 0
src/net/miginfocom/layout/ContainerWrapper.java View File

@@ -0,0 +1,69 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+/** A class that wraps a container that contains components. */
38
+public interface ContainerWrapper extends ComponentWrapper {
39
+
40
+    /** Returns the components of the container that wrapper is wrapping.
41
+     * @return The components of the container that wrapper is wrapping. Never <code>null</code>.
42
+     */
43
+    public abstract ComponentWrapper[] getComponents();
44
+
45
+    /** Returns the number of components that this parent has.
46
+     * @return The number of components that this parent has.
47
+     */
48
+    public abstract int getComponentCount();
49
+
50
+    /** Returns the <code>LayoutHandler</code> (in Swing terms) that is handling the layout of this container.
51
+     * If there exist no such class the method should return the same as {@link #getComponent()}, which is the
52
+     * container itself.
53
+     * @return The layout handler instance. Never <code>null</code>.
54
+     */
55
+    public abstract Object getLayout();
56
+
57
+    /** Returns if this container is using left-to-right component ordering.
58
+     * @return If this container is using left-to-right component ordering.
59
+     */
60
+    public abstract boolean isLeftToRight();
61
+
62
+    /** Paints a cell to indicate where it is.
63
+     * @param x The x coordinate to start the drwaing.
64
+     * @param y The x coordinate to start the drwaing.
65
+     * @param width The width to draw/fill
66
+     * @param height The height to draw/fill
67
+     */
68
+    public abstract void paintDebugCell(int x, int y, int width, int height);
69
+}

+ 437
- 0
src/net/miginfocom/layout/DimConstraint.java View File

@@ -0,0 +1,437 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+import java.io.*;
38
+
39
+/** A simple value holder for a constraint for one dimension. */
40
+public final class DimConstraint implements Externalizable {
41
+    
42
+    /**
43
+     * A version number for this class. It should be changed whenever the class
44
+     * structure is changed (or anything else that would prevent serialized
45
+     * objects being unserialized with the new class).
46
+     */
47
+    private static final long serialVersionUID = 1;
48
+
49
+    /** How this entity can be resized in the dimension that this constraint represents. */
50
+    final ResizeConstraint resize = new ResizeConstraint();
51
+    // Look at the properties' getter/setter methods for exmplanation
52
+    private String sizeGroup = null; // A "context" compared with equals.
53
+    private BoundSize size = null; // Min, pref, max. May be null.
54
+    private BoundSize gapBefore = null;
55
+    private BoundSize gapAfter = null;
56
+    private UnitValue align = null;
57
+    // **************  Only applicable on components! *******************
58
+    private String endGroup = null; // A "context" compared with equals.
59
+    // **************  Only applicable on rows/columns! *******************
60
+    private boolean fill = false;
61
+    private boolean noGrid = false;
62
+
63
+    /** Empty constructor.
64
+     */
65
+    public DimConstraint() {
66
+    }
67
+
68
+    /** Returns the grow priority. Relative priority is used for determining which entities gets the extra space first.
69
+     * <p>
70
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
71
+     * @return The grow priority.
72
+     */
73
+    public int getGrowPriority() {
74
+        return resize.growPrio;
75
+    }
76
+
77
+    /** Sets the grow priority. Relative priority is used for determining which entities gets the extra space first.
78
+     * <p>
79
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
80
+     * @param p The new grow priority.
81
+     */
82
+    public void setGrowPriority(int p) {
83
+        resize.growPrio = p;
84
+    }
85
+
86
+    /** Returns the grow weight.<p>
87
+     * Grow weight is how flexilble the entity should be, relative to other entities, when it comes to growing. <code>null</code> or
88
+     * zero mean it will never grow. An entity that has twise the grow weight compared to another entity will get twice
89
+     * as much of available space.
90
+     * <p>
91
+     * GrowWeight are only compared within the same GrowPrio.
92
+     * <p>
93
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
94
+     * @return The current grow weight.
95
+     */
96
+    public Float getGrow() {
97
+        return resize.grow;
98
+    }
99
+
100
+    /** Sets the grow weight.<p>
101
+     * Grow weight is how flexilble the entity should be, relative to other entities, when it comes to growing. <code>null</code> or
102
+     * zero mean it will never grow. An entity that has twise the grow weight compared to another entity will get twice
103
+     * as much of available space.
104
+     * <p>
105
+     * GrowWeight are only compared within the same GrowPrio.
106
+     * <p>
107
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
108
+     * @param weight The new grow weight.
109
+     */
110
+    public void setGrow(Float weight) {
111
+        resize.grow = weight;
112
+    }
113
+
114
+    /** Returns the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarse.
115
+     * <p>
116
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
117
+     * @return The shrink priority.
118
+     */
119
+    public int getShrinkPriority() {
120
+        return resize.shrinkPrio;
121
+    }
122
+
123
+    /** Sets the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarse.
124
+     * <p>
125
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
126
+     * @param p The new shrink priority.
127
+     */
128
+    public void setShrinkPriority(int p) {
129
+        resize.shrinkPrio = p;
130
+    }
131
+
132
+    /** Returns the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarse.
133
+     * Shrink weight is how flexilble the entity should be, relative to other entities, when it comes to shrinking. <code>null</code> or
134
+     * zero mean it will never shrink (default). An entity that has twise the shrink weight compared to another entity will get twice
135
+     * as much of available space.
136
+     * <p>
137
+     * Shrink(Weight) are only compared within the same ShrinkPrio.
138
+     * <p>
139
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
140
+     * @return The current shrink weight.
141
+     */
142
+    public Float getShrink() {
143
+        return resize.shrink;
144
+    }
145
+
146
+    /** Sets the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarse.
147
+     * Shrink weight is how flexilble the entity should be, relative to other entities, when it comes to shrinking. <code>null</code> or
148
+     * zero mean it will never shrink (default). An entity that has twise the shrink weight compared to another entity will get twice
149
+     * as much of available space.
150
+     * <p>
151
+     * Shrink(Weight) are only compared within the same ShrinkPrio.
152
+     * <p>
153
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
154
+     * @param weight The new shrink weight.
155
+     */
156
+    public void setShrink(Float weight) {
157
+        resize.shrink = weight;
158
+    }
159
+
160
+    public UnitValue getAlignOrDefault(boolean isCols) {
161
+        if (align != null) {
162
+            return align;
163
+        }
164
+        return isCols ? UnitValue.LEADING : UnitValue.CENTER;
165
+    }
166
+
167
+    /** Returns the alignment used either as a default value for sub-entities or for this entity.
168
+     * <p>
169
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
170
+     * @return The alignment.
171
+     */
172
+    public UnitValue getAlign() {
173
+        return align;
174
+    }
175
+
176
+    /** Sets the alignment used wither as a default value for sub-entities or for this entity.
177
+     * <p>
178
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
179
+     * @param uv The new shrink priority. E.g. {@link UnitValue#CENTER} or {@link net.miginfocom.layout.UnitValue#LEADING}.
180
+     */
181
+    public void setAlign(UnitValue uv) {
182
+        this.align = uv;
183
+    }
184
+
185
+    /** Returns the gap after this entitiy. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and
186
+     * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps.
187
+     * <p>
188
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
189
+     * @return The gap after this entitiy
190
+     */
191
+    public BoundSize getGapAfter() {
192
+        return gapAfter;
193
+    }
194
+
195
+    /** Sets the gap after this entitiy. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and
196
+     * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps.
197
+     * <p>
198
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
199
+     * @param size The new gap.
200
+     * @see net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean).
201
+     */
202
+    public void setGapAfter(BoundSize size) {
203
+        this.gapAfter = size;
204
+    }
205
+
206
+    boolean hasGapAfter() {
207
+        return gapAfter != null && gapAfter.isUnset() == false;
208
+    }
209
+
210
+    boolean isGapAfterPush() {
211
+        return gapAfter != null && gapAfter.getGapPush();
212
+    }
213
+
214
+    /** Returns the gap before this entitiy. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and
215
+     * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps.
216
+     * <p>
217
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
218
+     * @return The gap before this entitiy
219
+     */
220
+    public BoundSize getGapBefore() {
221
+        return gapBefore;
222
+    }
223
+
224
+    /** Sets the gap before this entitiy. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and
225
+     * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps.
226
+     * <p>
227
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
228
+     * @param size The new gap.
229
+     * @see net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean).
230
+     */
231
+    public void setGapBefore(BoundSize size) {
232
+        this.gapBefore = size;
233
+    }
234
+
235
+    boolean hasGapBefore() {
236
+        return gapBefore != null && gapBefore.isUnset() == false;
237
+    }
238
+
239
+    boolean isGapBeforePush() {
240
+        return gapBefore != null && gapBefore.getGapPush();
241
+    }
242
+
243
+    /** Returns the min/prerefferd/max size for the entity in the dimension that this object describes.
244
+     * <p>
245
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
246
+     * @return The current size. May be <code>null</code>.
247
+     * @see net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean).
248
+     */
249
+    public BoundSize getSize() {
250
+        return size;
251
+    }
252
+
253
+    /** Sets the min/prerefferd/max size for the eintity in the dimension that this object describes.
254
+     * <p>
255
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
256
+     * @param size The new size. May be <code>null</code>.
257
+     */
258
+    public void setSize(BoundSize size) {
259
+        this.size = size;
260
+    }
261
+
262
+    /** Returns the size group that this entitiy should be in for the demension that this object is describing.
263
+     * If this constraint is in a size group that is specified here. <code>null</code> means no size group
264
+     * and all other values are legal. Comparison with .equals(). Components/columnss/rows in the same size group
265
+     * will have the same min/preferred/max size; that of the largest in the group for the first two and the
266
+     * smallest for max.
267
+     * <p>
268
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
269
+     * @return The current size group. May be <code>null</code>.
270
+     */
271
+    public String getSizeGroup() {
272
+        return sizeGroup;
273
+    }
274
+
275
+    /** Sets the size group that this entitiy should be in for the demension that this object is describing.
276
+     * If this constraint is in a size group that is specified here. <code>null</code> means no size group
277
+     * and all other values are legal. Comparison with .equals(). Components/columnss/rows in the same size group
278
+     * will have the same min/preferred/max size; that of the largest in the group for the first two and the
279
+     * smallest for max.
280
+     * <p>
281
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
282
+     * @param s The new size group. <code>null</code> disables size grouping.
283
+     */
284
+    public void setSizeGroup(String s) {
285
+        sizeGroup = s;
286
+    }
287
+    // **************  Only applicable on components ! *******************
288
+
289
+    /** Returns the end group that this entitiy should be in for the demension that this object is describing.
290
+     * If this constraint is in an end group that is specified here. <code>null</code> means no end group
291
+     * and all other values are legal. Comparison with .equals(). Components in the same end group
292
+     * will have the same end coordinate.
293
+     * <p>
294
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
295
+     * @return The current end group. <code>null</code> may be returned.
296
+     */
297
+    public String getEndGroup() {
298
+        return endGroup;
299
+    }
300
+
301
+    /** Sets the end group that this entitiy should be in for the demension that this object is describing.
302
+     * If this constraint is in an end group that is specified here. <code>null</code> means no end group
303
+     * and all other values are legal. Comparison with .equals(). Components in the same end group
304
+     * will have the same end coordinate.
305
+     * <p>
306
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
307
+     * @param s The new end group. <code>null</code> disables end grouping.
308
+     */
309
+    public void setEndGroup(String s) {
310
+        endGroup = s;
311
+    }
312
+    // **************  Not applicable on components below ! *******************
313
+
314
+    /** Returns if the component in the row/column that this constraint should default be grown in the same dimension that
315
+     * this constraint represents (width for column and height for a row).
316
+     * <p>
317
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
318
+     * @return code>true</code> means that components should grow.
319
+     */
320
+    public boolean isFill() {
321
+        return fill;
322
+    }
323
+
324
+    /** Sets if the component in the row/column that this constraint should default be grown in the same dimension that
325
+     * this constraint represents (width for column and height for a row).
326
+     * <p>
327
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
328
+     * @param b <code>true</code> means that components should grow.
329
+     */
330
+    public void setFill(boolean b) {
331
+        fill = b;
332
+    }
333
+
334
+    /** Returns if the row/column should default to flow and not to grid behaviour. This means that the whole row/column
335
+     * will be one cell and all components will end up in that cell.
336
+     * <p>
337
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
338
+     * @return <code>true</code> means that the whole row/column should be one cell.
339
+     */
340
+    public boolean isNoGrid() {
341
+        return noGrid;
342
+    }
343
+
344
+    /** Sets if the row/column should default to flow and not to grid behaviour. This means that the whole row/column
345
+     * will be one cell and all components will end up in that cell.
346
+     * <p>
347
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
348
+     * @param b <code>true</code> means that the whole row/column should be one cell.
349
+     */
350
+    public void setNoGrid(boolean b) {
351
+        this.noGrid = b;
352
+    }
353
+
354
+    /** Returns the gaps as pixel values.
355
+     * @param parent The parent. Used to get the pixel values.
356
+     * @param defGap The default gap to use if there is no gap set on this object (i.e. it is null).
357
+     * @param refSize The reference size used to get the pixel sizes.
358
+     * @param before IF it is the gap before rather than the gap after to return.
359
+     * @return The [min,preferred,max] sizes for the specified gap. Uses {@link net.miginfocom.layout.LayoutUtil#NOT_SET}
360
+     * for gap sizes that are <code>null</code>. Returns <code>null</code> if there was no gap specified. A new and free to use array.
361
+     */
362
+    int[] getRowGaps(ContainerWrapper parent,
363
+            BoundSize defGap, int refSize, boolean before) {
364
+        BoundSize gap = before ? gapBefore : gapAfter;
365
+        if (gap == null || gap.isUnset()) {
366
+            gap = defGap;
367
+        }
368
+        if (gap == null || gap.isUnset()) {
369
+            return null;
370
+        }
371
+        int[] ret = new int[3];
372
+        for (int i = LayoutUtil.MIN; i <= LayoutUtil.MAX;
373
+                i++) {
374
+            UnitValue uv = gap.getSize(i);
375
+            ret[i] =uv != null ? uv.getPixels(refSize, parent, null)
376
+                    : LayoutUtil.NOT_SET;
377
+        }
378
+        return ret;
379
+    }
380
+
381
+    /** Returns the gaps as pixel values.
382
+     * @param parent The parent. Used to get the pixel values.
383
+     * @param comp The component that the gap is for. If not for a component it is <code>null</code>.
384
+     * @param adjGap The gap that the adjacent component, if any, has towards <code>comp</code>.
385
+     * @param adjacentComp The adjacent component if any. May be <code>null</code>.
386
+     * @param refSize The reference size used to get the pixel sizes.
387
+     * @param adjacentSide Whan side the <code>adjacentComp</code> is on. 0 = top, 1 = left, 2 = bottom, 3 = right.
388
+     * @param tag The tag string that the component might be tagged with in the component constraints. May be <code>null</code>.
389
+     * @param isLTR If it is left-to-right.
390
+     * @return The [min,preferred,max] sizes for the specified gap. Uses {@link net.miginfocom.layout.LayoutUtil#NOT_SET}
391
+     * for gap sizes that are <code>null</code>. Returns <code>null</code> if there was no gap specified. A new and free to use array.
392
+     */
393
+    int[] getComponentGaps(ContainerWrapper parent,
394
+            ComponentWrapper comp, BoundSize adjGap,
395
+            ComponentWrapper adjacentComp, String tag, int refSize,
396
+            int adjacentSide, boolean isLTR) {
397
+        BoundSize gap = adjacentSide < 2 ? gapBefore : gapAfter;
398
+
399
+        boolean hasGap = gap != null && gap.getGapPush();
400
+        if ((gap == null || gap.isUnset()) &&
401
+                (adjGap == null || adjGap.isUnset()) && comp != null) {
402
+            gap = PlatformDefaults.getDefaultComponentGap(comp, adjacentComp,
403
+                    adjacentSide + 1, tag, isLTR);
404
+        }
405
+        if (gap == null) {
406
+            return hasGap
407
+                    ? new int[]{0, 0, LayoutUtil.NOT_SET} : null;
408
+        }
409
+        int[] ret = new int[3];
410
+        for (int i = LayoutUtil.MIN; i <= LayoutUtil.MAX;
411
+                i++) {
412
+            UnitValue uv = gap.getSize(i);
413
+            ret[i] =uv != null ? uv.getPixels(refSize, parent, null)
414
+                    : LayoutUtil.NOT_SET;
415
+        }
416
+        return ret;
417
+    }
418
+    // ************************************************
419
+    // Persistence Delegate and Serializable combined.
420
+    // ************************************************
421
+
422
+    private Object readResolve() throws ObjectStreamException {
423
+        return LayoutUtil.getSerializedObject(this);
424
+    }
425
+
426
+    public void readExternal(ObjectInput in) throws IOException,
427
+            ClassNotFoundException {
428
+        LayoutUtil.setSerializedObject(this,
429
+                LayoutUtil.readAsXML(in));
430
+    }
431
+
432
+    public void writeExternal(ObjectOutput out) throws IOException {
433
+        if (getClass() == DimConstraint.class) {
434
+            LayoutUtil.writeAsXML(out, this);
435
+        }
436
+    }
437
+}

+ 2618
- 0
src/net/miginfocom/layout/Grid.java
File diff suppressed because it is too large
View File


+ 753
- 0
src/net/miginfocom/layout/IDEUtil.java View File

@@ -0,0 +1,753 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+/** This class contains static methods to be used by IDE vendors to convert to and from String/API constraints.
38
+ * <p>
39
+ * <b>Note that {@link LayoutUtil#setDesignTime(boolean)} should be set to <code>true</code> for this class'
40
+ * methods to work.</b>
41
+ */
42
+public class IDEUtil {
43
+
44
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
45
+    public static final UnitValue ZERO = UnitValue.ZERO;
46
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
47
+    public static final UnitValue TOP = UnitValue.TOP;
48
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
49
+    public static final UnitValue LEADING =
50
+            UnitValue.LEADING;
51
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
52
+    public static final UnitValue LEFT = UnitValue.LEFT;
53
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
54
+    public static final UnitValue CENTER = UnitValue.CENTER;
55
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
56
+    public static final UnitValue TRAILING =
57
+            UnitValue.TRAILING;
58
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
59
+    public static final UnitValue RIGHT = UnitValue.RIGHT;
60
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
61
+    public static final UnitValue BOTTOM = UnitValue.BOTTOM;
62
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
63
+    public static final UnitValue LABEL = UnitValue.LABEL;
64
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
65
+    public static final UnitValue INF = UnitValue.INF;
66
+    /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */
67
+    public static final UnitValue BASELINE_IDENTITY =
68
+            UnitValue.BASELINE_IDENTITY;
69
+    private static final String[] X_Y_STRINGS =
70
+            new String[]{"x", "y", "x2", "y2"};
71
+
72
+    /** Returns the sizes of the rows and gaps for a container.	 * There will be two arrays returned [0] and [1].
73
+     * <p>
74
+     * The first array will be the indexes of the rows where indexes that
75
+     * are less than 30000 or larger than 30000 is docking rows. There might be extra docking rows that aren't
76
+     * visible but they always have size 0. Non docking indexes will probably always be 0, 1, 2, 3, etc..
77
+     * <p>
78
+     * The second array is the sizes of the form:<br>
79
+     * <code>[left inset][row size 1][gap 1][row size 2][gap 2][row size n][right inset]</code>.
80
+     * <p>
81
+     * The returned sizes will be the ones calculated in the last layout cycle.
82
+     * @param parentContainer The container to retuern the row sizes and gaps for. In Swing it will be a {@link java.awt.Container} and
83
+     * in SWT it will be a {@link org.eclipse.swt.widgets.Composite}.
84
+     * @return The sizes or <code>null</code> if {@link LayoutUtil#isDesignTime()} is <code>false</code> or
85
+     * <code>parentContainer</code> does not have a MigLayout layout manager.
86
+     * The returned sizes will be the ones calculated in the last layout cycle.
87
+     * @see LayoutUtil#isDesignTime()
88
+     */
89
+    public static int[][] getRowSizes(Object parentContainer) {
90
+        return Grid.getSizesAndIndexes(parentContainer, true);
91
+    }
92
+
93
+    /** Returns the sizes of the columns and gaps for a container.
94
+     * There will be two arrays returned [0] and [1].
95
+     * <p>
96
+     * The first array will be the indexes of the columns where indexes that
97
+     * are less than 30000 or larger than 30000 is docking columns. There might be extra docking columns that aren't
98
+     * visible but they always have size 0. Non docking indexes will probably always be 0, 1, 2, 3, etc..
99
+     * <p>
100
+     * The second array is the sizes of the form:<br>
101
+     * <code>[top inset][column size 1][gap 1][column size 2][gap 2][column size n][bottom inset]</code>.
102
+     * <p>
103
+     * The returned sizes will be the ones calculated in the last layout cycle.
104
+     * @param parentContainer The container to retuern the column sizes and gaps for. In Swing it will be a {@link java.awt.Container} and
105
+     * in SWT it will be a {@link org.eclipse.swt.widgets.Composite}.
106
+     * @return The sizes and indexes or <code>null</code> if {@link LayoutUtil#isDesignTime()} is <code>false</code> or
107
+     * <code>parentContainer</code> does not have a MigLayout layout manager.
108
+     * The returned sizes will be the ones calculated in the last layout cycle.
109
+     * @see LayoutUtil#isDesignTime()
110
+     */
111
+    public static int[][] getColumnSizes(Object parentContainer) {
112
+        return Grid.getSizesAndIndexes(parentContainer, false);
113
+    }
114
+
115
+    /** Returns the a constraint string that can be re-parsed to be the exact same AxisConstraint.
116
+     * @param ac The axis constraint to return as a constraint string.
117
+     * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
118
+     * as a String type (e.g. "flowx, gap rel, right").
119
+     * @param isCols The the constraint should be returned for columns rather than rows.
120
+     * @return A String. Never <code>null</code>.
121
+     */
122
+    public static final String getConstraintString(AC ac, boolean asAPI,
123
+            boolean isCols) {
124
+        StringBuffer sb = new StringBuffer(32);
125
+
126
+        DimConstraint[] dims = ac.getConstaints();
127
+        BoundSize defGap =
128
+                isCols ? PlatformDefaults.getGridGapX()
129
+                : PlatformDefaults.getGridGapY();
130
+
131
+        for (int i = 0; i < dims.length;
132
+                i++) {
133
+            DimConstraint dc = dims[i];
134
+
135
+            addRowDimConstraintString(dc, sb, asAPI);
136
+
137
+            if (i < dims.length - 1) {
138
+                BoundSize gapAft = dc.getGapAfter();
139
+                BoundSize gapBefNext = dims[i + 1].getGapBefore();
140
+
141
+                if (gapAft != null && gapAft == gapBefNext && gapAft != defGap) {
142
+                    if (asAPI) {
143
+                        sb.append(".gap(\"").append(getBS(gapAft)).append("\")");
144
+                    } else {
145
+                        sb.append(getBS(gapAft));
146
+                    }
147
+                } else {
148
+                    if (asAPI) {
149
+                        sb.append(".gap()");
150
+                    }
151
+                }
152
+            }
153
+        }
154
+
155
+        return sb.toString();
156
+    }
157
+
158
+    /** Adds the a constraint string that can be re-parsed to be the exact same DimConstraint.
159
+     * @param dc The layout constraint to return as a constraint string.
160
+     * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
161
+     * as a String type (e.g. "flowx, gap rel, right").
162
+     */
163
+    private static final void addRowDimConstraintString(DimConstraint dc,
164
+            StringBuffer sb, boolean asAPI) {
165
+        int gp = dc.getGrowPriority();
166
+
167
+        int firstComma = sb.length();
168
+
169
+        BoundSize size = dc.getSize();
170
+        if (size != null) {
171
+            if (asAPI) {
172
+                sb.append(".size(\"").append(getBS(size)).append("\")");
173
+            } else {
174
+                sb.append(',').append(getBS(size));
175
+            }
176
+        }
177
+
178
+        if (gp != 100) {
179
+            if (asAPI) {
180
+                sb.append(".growPrio(").append(gp).append("\")");
181
+            } else {
182
+                sb.append(",growprio ").append(gp);
183
+            }
184
+        }
185
+
186
+        Float gw = dc.getGrow();
187
+        if (gw != null) {
188
+            String g =
189
+                    gw.floatValue() != 100f
190
+                    ? LayoutUtil.floatToString(gw.floatValue()) : "";
191
+            if (asAPI) {
192
+                if (g.length() == 0) {
193
+                    sb.append(".grow()");
194
+                } else {
195
+                    sb.append(".grow(\"").append(g).append("\")");
196
+                }
197
+            } else {
198
+                sb.append(",grow").append(g.length() > 0 ? (" " + g) : "");
199
+            }
200
+        }
201
+
202
+        int sp = dc.getShrinkPriority();
203
+        if (sp != 100) {
204
+            if (asAPI) {
205
+                sb.append(".shrinkPrio(").append(sp).append("\")");
206
+            } else {
207
+                sb.append(",shrinkprio ").append(sp);
208
+            }
209
+        }
210
+
211
+        Float sw = dc.getShrink();
212
+        if (sw != null && sw.intValue() != 100) {
213
+            String s =
214
+                    LayoutUtil.floatToString(sw.floatValue());
215
+            if (asAPI) {
216
+                sb.append(".shrink(\"").append(s).append("\")");
217
+            } else {
218
+                sb.append(",shrink ").append(s);
219
+            }
220
+        }
221
+
222
+        String eg = dc.getEndGroup();
223
+        if (eg != null) {
224
+            if (asAPI) {
225
+                sb.append(".endGroup(\"").append(eg).append("\")");
226
+            } else {
227
+                sb.append(",endgroup ").append(eg);
228
+            }
229
+        }
230
+
231
+        String sg = dc.getSizeGroup();
232
+        if (sg != null) {
233
+            if (asAPI) {
234
+                sb.append(".sizeGroup(\"").append(sg).append("\")");
235
+            } else {
236
+                sb.append(",sizegroup ").append(sg);
237
+            }
238
+        }
239
+
240
+        UnitValue al = dc.getAlign();
241
+        if (al != null) {
242
+            if (asAPI) {
243
+                sb.append(".align(\"").append(getUV(al)).append("\")");
244
+            } else {
245
+                String s = getUV(al);
246
+                String alKw =
247
+                        (s.equals("top") || s.equals("bottom") ||
248
+                        s.equals("left") || s.equals("label") ||
249
+                        s.equals("leading") || s.equals("center") ||
250
+                        s.equals("trailing") || s.equals("right") ||
251
+                        s.equals("baseline")) ? "" : "align ";
252
+                sb.append(',').append(alKw).append(s);
253
+            }
254
+        }
255
+
256
+        if (dc.isNoGrid()) {
257
+            if (asAPI) {
258
+                sb.append(".noGrid()");
259
+            } else {
260
+                sb.append(",nogrid");
261
+            }
262
+        }
263
+
264
+        if (dc.isFill()) {
265
+            if (asAPI) {
266
+                sb.append(".fill()");
267
+            } else {
268
+                sb.append(",fill");
269
+            }
270
+        }
271
+
272
+        if (asAPI == false) {
273
+            if (sb.length() > firstComma) {
274
+                sb.setCharAt(firstComma, '[');
275
+                sb.append(']');
276
+            } else {
277
+                sb.append("[]");
278
+            }
279
+        }
280
+    }
281
+
282
+    /** Returns the a constraint string that can be re-parsed to be the exact same DimConstraint.
283
+     * @param dc The layout constraint to return as a constraint string.
284
+     * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
285
+     * as a String type (e.g. "flowx, gap rel, right").
286
+     * @param isHor The the DimConstraint is decoration something horizontal (column or x).
287
+     * @param noGrowAdd If <code>true</code> no grow constraints will be added.
288
+     * @return A constraint string. Never <code>null</code>.
289
+     */
290
+    private static final void addComponentDimConstraintString(DimConstraint dc,
291
+            StringBuffer sb, boolean asAPI, boolean isHor, boolean noGrowAdd) {
292
+        int gp = dc.getGrowPriority();
293
+        if (gp != 100) {
294
+            if (asAPI) {
295
+                sb.append(isHor ? ".growPrioX(" : ".growPrioY(").append(gp).
296
+                        append(')');
297
+            } else {
298
+                sb.append(isHor ? ",growpriox " : ",growprioy ").append(gp);
299
+            }
300
+        }
301
+
302
+        if (noGrowAdd == false) {
303
+            Float gw = dc.getGrow();
304
+            if (gw != null) {
305
+                String g =
306
+                        gw.floatValue() != 100f
307
+                        ? LayoutUtil.floatToString(gw.floatValue()) : "";
308
+                if (asAPI) {
309
+                    sb.append(isHor ? ".growX(" : ".growY(").append(g).
310
+                            append(')');
311
+                } else {
312
+                    sb.append(isHor ? ",growx" : ",growy").
313
+                            append(g.length() > 0 ? (" " + g) : "");
314
+                }
315
+            }
316
+        }
317
+
318
+        int sp = dc.getShrinkPriority();
319
+        if (sp != 100) {
320
+            if (asAPI) {
321
+                sb.append(isHor ? ".shrinkPrioX(" : ".shrinkPrioY(").append(sp).
322
+                        append(')');
323
+            } else {
324
+                sb.append(isHor ? ",shrinkpriox " : ",shrinkprioy ").append(sp);
325
+            }
326
+        }
327
+
328
+        Float sw = dc.getShrink();
329
+        if (sw != null && sw.intValue() != 100) {
330
+            String s =
331
+                    LayoutUtil.floatToString(sw.floatValue());
332
+            if (asAPI) {
333
+                sb.append(isHor ? ".shrinkX(" : ".shrinkY(").append(s).
334
+                        append(')');
335
+            } else {
336
+                sb.append(isHor ? ",shrinkx " : ",shrinky ").append(s);
337
+            }
338
+        }
339
+
340
+        String eg = dc.getEndGroup();
341
+        if (eg != null) {
342
+            if (asAPI) {
343
+                sb.append(isHor ? ".endGroupX(\"" : ".endGroupY(\"").append(eg).
344
+                        append("\")");
345
+            } else {
346
+                sb.append(isHor ? ",endgroupx " : ",endgroupy ").append(eg);
347
+            }
348
+        }
349
+
350
+        String sg = dc.getSizeGroup();
351
+        if (sg != null) {
352
+            if (asAPI) {
353
+                sb.append(isHor ? ".sizeGroupX(\"" : ".sizeGroupY(\"").
354
+                        append(sg).append("\")");
355
+            } else {
356
+                sb.append(isHor ? ",sizegroupx " : ",sizegroupy ").append(sg);
357
+            }
358
+        }
359
+
360
+        BoundSize size = dc.getSize();
361
+        if (size != null) {
362
+            if (size.getPreferred() == null) {
363
+                if (size.getMin() == null) {
364
+                    if (asAPI) {
365
+                        sb.append(isHor ? ".maxWidth(\"" : ".maxHeight(\"").
366
+                                append(getBS(size)).append("\")");
367
+                    } else {
368
+                        sb.append(isHor ? ",wmax " : ",hmax ").
369
+                                append(getBS(size));
370
+                    }
371
+                } else if (size.getMax() == null) {
372
+                    if (asAPI) {
373
+                        sb.append(isHor ? ".minWidth(\"" : ".minHeight(\"").
374
+                                append(getBS(size)).append("\")");
375
+                    } else {
376
+                        sb.append(isHor ? ",wmin " : ",hmin ").
377
+                                append(getBS(size));
378
+                    }
379
+                }
380
+            } else {
381
+                if (asAPI) {
382
+                    sb.append(isHor ? ".width(\"" : ".height(\"").
383
+                            append(getBS(size)).append("\")");
384
+                } else {
385
+                    sb.append(isHor ? ",width " : ",height ").
386
+                            append(getBS(size));
387
+                }
388
+            }
389
+        }
390
+
391
+        UnitValue al = dc.getAlign();
392
+        if (al != null) {
393
+            if (asAPI) {
394
+                sb.append(isHor ? ".alignX(\"" : ".alignY(\"").append(getUV(al)).
395
+                        append("\")");
396
+            } else {
397
+                sb.append(isHor ? ",alignx " : ",aligny ").append(getUV(al));
398
+            }
399
+        }
400
+
401
+        BoundSize gapBef = dc.getGapBefore();
402
+        BoundSize gapAft = dc.getGapAfter();
403
+        if (gapBef != null || gapAft != null) {
404
+            if (asAPI) {
405
+                sb.append(isHor ? ".gapX(\"" : ".gapY(\"").append(getBS(gapBef)).
406
+                        append("\", \"").append(getBS(gapAft)).append("\")");
407
+            } else {
408
+                sb.append(isHor ? ",gapx " : ",gapy ").append(getBS(gapBef)).
409
+                        append(' ').append(getBS(gapAft));
410
+            }
411
+        }
412
+    }
413
+
414
+    /** Returns the a constraint string that can be re-parsed to be the exact same LayoutConstraint.
415
+     * @param cc The component constraint to return as a constraint string.
416
+     * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
417
+     * as a String type (e.g. "flowx, gap rel, right").
418
+     * @return A String. Never <code>null</code>.
419
+     */
420
+    public static final String getConstraintString(CC cc, boolean asAPI) {
421
+        StringBuffer sb = new StringBuffer(16);
422
+
423
+        if (cc.isNewline()) {
424
+            sb.append(asAPI ? ".newline()" : ",newline");
425
+        }
426
+        if (cc.isExternal()) {
427
+            sb.append(asAPI ? ".external()" : ",external");
428
+        }
429
+        Boolean flowX = cc.getFlowX();
430
+        if (flowX != null) {
431
+            if (asAPI) {
432
+                sb.append(flowX.booleanValue() ? ".flowX()" : ".flowY()");
433
+            } else {
434
+                sb.append(flowX.booleanValue() ? ",flowx" : ",flowy");
435
+            }
436
+        }
437
+
438
+        UnitValue[] pad = cc.getPadding();
439
+        if (pad != null) {
440
+            sb.append(asAPI ? ".pad(\"" : ",pad ");
441
+            for (int i = 0; i < pad.length;
442
+                    i++) {
443
+                sb.append(getUV(pad[i])).append(i < pad.length - 1 ? " " : "");
444
+            }
445
+            if (asAPI) {
446
+                sb.append("\")");
447
+            }
448
+        }
449
+
450
+        UnitValue[] pos = cc.getPos();
451
+        if (pos != null) {
452
+            if (cc.isBoundsInGrid()) {
453
+                for (int i = 0; i < 4;
454
+                        i++) {
455
+                    if (pos[i] != null) {
456
+                        if (asAPI) {
457
+                            sb.append('.').append(X_Y_STRINGS[i]).append("(\"").
458
+                                    append(getUV(pos[i])).append("\")");
459
+                        } else {
460
+                            sb.append(',').append(X_Y_STRINGS[i]).
461
+                                    append(getUV(pos[i]));
462
+                        }
463
+                    }
464
+                }
465
+            } else {
466
+                sb.append(asAPI ? ".pos(\"" : ",pos ");
467
+                int iSz = (pos[2] != null || pos[3] != null) ? 4 : 2; // "pos x y" vs "pos x1 y1 x2 y2".
468
+                for (int i = 0; i < iSz;
469
+                        i++) {
470
+                    sb.append(getUV(pos[i])).append(i < iSz - 1 ? " " : "");
471
+                }
472
+                if (asAPI) {
473
+                    sb.append("\")");
474
+                }
475
+            }
476
+        }
477
+
478
+        String id = cc.getId();
479
+        if (id != null) {
480
+            if (asAPI) {
481
+                sb.append(".id(\"").append(id).append("\")");
482
+            } else {
483
+                sb.append(",id ").append(id);
484
+            }
485
+        }
486
+
487
+        String tag = cc.getTag();
488
+        if (tag != null) {
489
+            if (asAPI) {
490
+                sb.append(".tag(\"").append(tag).append("\")");
491
+            } else {
492
+                sb.append(",tag ").append(tag);
493
+            }
494
+        }
495
+
496
+        int hideMode = cc.getHideMode();
497
+        if (hideMode >= 0) {
498
+            if (asAPI) {
499
+                sb.append(".hideMode(").append(hideMode).append(')');
500
+            } else {
501
+                sb.append(",hideMode ").append(hideMode);
502
+            }
503
+        }
504
+
505
+        int skip = cc.getSkip();
506
+        if (skip > 0) {
507
+            if (asAPI) {
508
+                sb.append(".skip(").append(skip).append(')');
509
+            } else {
510
+                sb.append(",skip ").append(skip);
511
+            }
512
+        }
513
+
514
+        int split = cc.getSplit();
515
+        if (split > 1) {
516
+            String s =
517
+                    split == LayoutUtil.INF ? "" : String.valueOf(split);
518
+            if (asAPI) {
519
+                sb.append(".split(").append(s).append(')');
520
+            } else {
521
+                sb.append(",split ").append(s);
522
+            }
523
+        }
524
+
525
+        int cx = cc.getCellX();
526
+        int cy = cc.getCellY();
527
+        int spanX = cc.getSpanX();
528
+        int spanY = cc.getSpanY();
529
+        if (cx >= 0 && cy >= 0) {
530
+            if (asAPI) {
531
+                sb.append(".cell(").append(cx).append(", ").append(cy);
532
+                if (spanX > 1 || spanY > 1) {
533
+                    sb.append(", ").append(spanX).append(", ").append(spanY);
534
+                }
535
+                sb.append(')');
536
+            } else {
537
+                sb.append(",cell ").append(cx).append(' ').append(cy);
538
+                if (spanX > 1 || spanY > 1) {
539
+                    sb.append(' ').append(spanX).append(' ').append(spanY);
540
+                }
541
+            }
542
+        } else if (spanX > 1 || spanY > 1) {
543
+            if (spanX > 1 && spanY > 1) {
544
+                sb.append(asAPI ? ".span(" : ",span ").append(spanX).
545
+                        append(asAPI ? ", " : " ").append(spanY);
546
+            } else if (spanX > 1) {
547
+                sb.append(asAPI ? ".spanX(" : ",spanx ").
548
+                        append(spanX == LayoutUtil.INF ? ""
549
+                        : (String.valueOf(spanX)));
550
+            } else if (spanY > 1) {
551
+                sb.append(asAPI ? ".spanY(" : ",spany ").
552
+                        append(spanY == LayoutUtil.INF ? ""
553
+                        : (String.valueOf(spanY)));
554
+            }
555
+            if (asAPI) {
556
+                sb.append(')');
557
+            }
558
+        }
559
+
560
+        Float pushX = cc.getPushX();
561
+        Float pushY = cc.getPushY();
562
+        if (pushX != null || pushY != null) {
563
+            if (pushX != null && pushY != null) {
564
+                sb.append(asAPI ? ".push(" : ",push ");
565
+                if (pushX != 100.0 || pushY != 100.0) {
566
+                    sb.append(pushX).append(asAPI ? ", " : " ").append(pushY);
567
+                }
568
+            } else if (pushX != null) {
569
+                sb.append(asAPI ? ".pushX(" : ",pushx ").
570
+                        append(pushX == 100 ? ""
571
+                        : (String.valueOf(pushX)));
572
+            } else if (pushY != null) {
573
+                sb.append(asAPI ? ".pushY(" : ",pushy ").
574
+                        append(pushY == 100 ? ""
575
+                        : (String.valueOf(pushY)));
576
+            }
577
+            if (asAPI) {
578
+                sb.append(')');
579
+            }
580
+        }
581
+
582
+        int dock = cc.getDockSide();
583
+        if (dock >= 0) {
584
+            String ds = CC.DOCK_SIDES[dock];
585
+            if (asAPI) {
586
+                sb.append(".dock").
587
+                        append(Character.toUpperCase(ds.charAt(0))).
588
+                        append(ds.substring(1)).append("()");
589
+            } else {
590
+                sb.append(",").append(ds);
591
+            }
592
+        }
593
+
594
+        boolean noGrowAdd =
595
+                cc.getHorizontal().getGrow() != null &&
596
+                cc.getHorizontal().getGrow().intValue() == 100 &&
597
+                cc.getVertical().getGrow() != null &&
598
+                cc.getVertical().getGrow().intValue() == 100;
599
+
600
+        addComponentDimConstraintString(cc.getHorizontal(), sb, asAPI, true,
601
+                noGrowAdd);
602
+        addComponentDimConstraintString(cc.getVertical(), sb, asAPI, false,
603
+                noGrowAdd);
604
+        if (noGrowAdd) {
605
+            sb.append(asAPI ? ".grow()" : ",grow"); // Combine ".growX().growY()" into ".grow()".
606
+        }
607
+        if (cc.isWrap()) {
608
+            sb.append(asAPI ? ".wrap()" : ",wrap");
609
+        }
610
+        String s = sb.toString();
611
+        return s.length() == 0 || s.charAt(0) != ',' ? s : s.substring(1);
612
+    }
613
+
614
+    /** Returns the a constraint string that can be re-parsed to be the exact same LayoutConstraint.
615
+     * @param lc The layout constraint to return as a constraint string.
616
+     * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or
617
+     * as a String type (e.g. "flowx, gap rel, right").
618
+     * @return A String. Never <code>null</code>.
619
+     */
620
+    public static final String getConstraintString(LC lc, boolean asAPI) {
621
+        StringBuffer sb = new StringBuffer(16);
622
+
623
+        if (lc.isFlowX() == false) {
624
+            sb.append(asAPI ? ".flowY()" : ",flowy");
625
+        }
626
+        boolean fillX = lc.isFillX();
627
+        boolean fillY = lc.isFillY();
628
+        if (fillX || fillY) {
629
+            if (fillX == fillY) {
630
+                sb.append(asAPI ? ".fill()" : ",fill");
631
+            } else {
632
+                sb.append(asAPI ? (fillX ? ".fillX()" : ".fillY()")
633
+                        : (fillX ? ",fillx" : ",filly"));
634
+            }
635
+        }
636
+
637
+        Boolean leftToRight = lc.getLeftToRight();
638
+        if (leftToRight != null) {
639
+            if (asAPI) {
640
+                sb.append(".leftToRight(").append(leftToRight).append(')');
641
+            } else {
642
+                sb.append(leftToRight.booleanValue() ? ",ltr" : ",rtl");
643
+            }
644
+        }
645
+
646
+        if (lc.isTopToBottom() == false) {
647
+            sb.append(asAPI ? ".bottomToTop()" : ",btt");
648
+        }
649
+        UnitValue[] insets = lc.getInsets();
650
+        if (insets != null) {
651
+            String cs = LayoutUtil.getCCString(insets);
652
+            if (cs != null) {
653
+                if (asAPI) {
654
+                    sb.append(".insets(\"").append(cs).append("\")");
655
+                } else {
656
+                    sb.append(",insets ").append(cs);
657
+                }
658
+            } else {
659
+                sb.append(asAPI ? ".insets(\"" : ",insets ");
660
+                for (int i = 0; i < insets.length;
661
+                        i++) {
662
+                    sb.append(getUV(insets[i])).
663
+                            append(i < insets.length - 1 ? " " : "");
664
+                }
665
+                if (asAPI) {
666
+                    sb.append("\")");
667
+                }
668
+            }
669
+        }
670
+
671
+        if (lc.isNoGrid()) {
672
+            sb.append(asAPI ? ".noGrid()" : ",nogrid");
673
+        }
674
+        if (lc.isVisualPadding() == false) {
675
+            sb.append(asAPI ? ".noVisualPadding()" : ",novisualpadding");
676
+        }
677
+        int hideMode = lc.getHideMode();
678
+        if (hideMode > 0) {
679
+            if (asAPI) {
680
+                sb.append(".hideMode(").append(hideMode).append(')');
681
+            } else {
682
+                sb.append(",hideMode ").append(hideMode);
683
+            }
684
+        }
685
+
686
+        UnitValue alignX = lc.getAlignX();
687
+        UnitValue alignY = lc.getAlignY();
688
+        if (alignX != null || alignY != null) {
689
+            if (alignX != null && alignY != null) {
690
+                sb.append(asAPI ? ".align(\"" : ",align ").append(getUV(alignX)).
691
+                        append(' ').append(getUV(alignY));
692
+            } else if (alignX != null) {
693
+                sb.append(asAPI ? ".alignX(\"" : ",alignx ").
694
+                        append(getUV(alignX));
695
+            } else if (alignY != null) {
696
+                sb.append(asAPI ? ".alignY(\"" : ",aligny ").
697
+                        append(getUV(alignY));
698
+            }
699
+            if (asAPI) {
700
+                sb.append("\")");
701
+            }
702
+        }
703
+
704
+        BoundSize gridGapX = lc.getGridGapX();
705
+        BoundSize gridGapY = lc.getGridGapY();
706
+        if (gridGapX != null || gridGapY != null) {
707
+            if (gridGapX != null && gridGapY != null) {
708
+                sb.append(asAPI ? ".gridGap(\"" : ",gap ").
709
+                        append(getBS(gridGapX)).append(' ').
710
+                        append(getBS(gridGapY));
711
+            } else if (gridGapX != null) {
712
+                sb.append(asAPI ? ".gridGapX(\"" : ",gapx ").
713
+                        append(getBS(gridGapX));
714
+            } else if (gridGapY != null) {
715
+                sb.append(asAPI ? ".gridGapY(\"" : ",gapy ").
716
+                        append(getBS(gridGapY));
717
+            }
718
+            if (asAPI) {
719
+                sb.append("\")");
720
+            }
721
+        }
722
+
723
+        int wrapAfter = lc.getWrapAfter();
724
+        if (wrapAfter != LayoutUtil.INF) {
725
+            String ws = wrapAfter > 0 ? String.valueOf(wrapAfter) : "";
726
+            if (asAPI) {
727
+                sb.append(".wrap(").append(ws).append(')');
728
+            } else {
729
+                sb.append(",wrap ").append(ws);
730
+            }
731
+        }
732
+
733
+        int debugMillis = lc.getDebugMillis();
734
+        if (debugMillis > 0) {
735
+            if (asAPI) {
736
+                sb.append(".debug(").append(debugMillis).append(')');
737
+            } else {
738
+                sb.append(",debug ").append(debugMillis);
739
+            }
740
+        }
741
+
742
+        String s = sb.toString();
743
+        return s.length() == 0 || s.charAt(0) != ',' ? s : s.substring(1);
744
+    }
745
+
746
+    private static String getUV(UnitValue uv) {
747
+        return uv != null ? uv.getConstraintString() : "null";
748
+    }
749
+
750
+    private static String getBS(BoundSize bs) {
751
+        return bs != null ? bs.getConstraintString() : "null";
752
+    }
753
+}

+ 65
- 0
src/net/miginfocom/layout/InCellGapProvider.java View File

@@ -0,0 +1,65 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+/** An interfance to implement if you want to decide the gaps between two types of components within the same cell.
38
+ * <p>
39
+ * E.g.:
40
+ *
41
+ * <pre>
42
+ * if (adjacentComp == null || adjacentSide == SwingConstants.LEFT || adjacentSide == SwingConstants.TOP)
43
+ *	  return null;
44
+ *
45
+ * boolean isHor = (adjacentSide == SwingConstants.LEFT || adjacentSide == SwingConstants.RIGHT);
46
+ *
47
+ * if (adjacentComp.getComponetType(false) == ComponentWrapper.TYPE_LABEL && comp.getComponetType(false) == ComponentWrapper.TYPE_TEXT_FIELD)
48
+ *    return isHor ? UNRELATED_Y : UNRELATED_Y;
49
+ *
50
+ * return (adjacentSide == SwingConstants.LEFT || adjacentSide == SwingConstants.RIGHT) ? RELATED_X : RELATED_Y;
51
+ * </pre
52
+ */
53
+public interface InCellGapProvider
54
+{
55
+	/** Returns the default gap between two components that <b>are in the same cell</b>.
56
+	 * @param comp The component that the gap is for. Never <code>null</code>.
57
+	 * @param adjacentComp The adjacent component if any. May be <code>null</code>.
58
+	 * @param adjacentSide What side the <code>adjacentComp</code> is on. {@link javax.swing.SwingUtilities#TOP} or
59
+	 * {@link javax.swing.SwingUtilities#LEFT} or {@link javax.swing.SwingUtilities#BOTTOM} or {@link javax.swing.SwingUtilities#RIGHT}.
60
+	 * @param tag The tag string that the component might be tagged with in the component constraints. May be <code>null</code>.
61
+	 * @param isLTR If it is left-to-right.
62
+	 * @return The default gap between two components or <code>null</code> if there should be no gap.
63
+	 */
64
+	public abstract BoundSize getDefaultGap(ComponentWrapper comp, ComponentWrapper adjacentComp, int adjacentSide, String tag, boolean isLTR);
65
+}

+ 645
- 0
src/net/miginfocom/layout/LC.java View File

@@ -0,0 +1,645 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+import java.io.*;
38
+
39
+/** Contains the constraints for an instance of the {@link LC} layout manager. */
40
+public final class LC implements Externalizable {
41
+
42
+    /**
43
+     * A version number for this class. It should be changed whenever the class
44
+     * structure is changed (or anything else that would prevent serialized
45
+     * objects being unserialized with the new class).
46
+     */
47
+    private static final long serialVersionUID = 1;
48
+    // See the corresponding set/get method for documentation of the property!
49
+    private int wrapAfter = LayoutUtil.INF;
50
+    private Boolean leftToRight = null;
51
+    private UnitValue[] insets = null; // Never null elememts but if unset array is null
52
+    private UnitValue alignX = null;
53
+    private UnitValue alignY = null;
54
+    private BoundSize gridGapX = null;
55
+    private BoundSize gridGapY = null;
56
+    private int debugMillis = 0;
57
+    private int hideMode = 0;
58
+    private boolean noCache = false;
59
+    private boolean flowX = true;
60
+    private boolean fillX = false;
61
+    private boolean fillY = false;
62
+    private boolean topToBottom = true;
63
+    private boolean noGrid = false;
64
+    private boolean visualPadding = true;
65
+
66
+    /** Empty constructor.
67
+     */
68
+    public LC() {
69
+    }
70
+    // ************************************************************************
71
+    // * JavaBean get/set methods.
72
+    // ************************************************************************
73
+
74
+    /** If components have sizes or positions linked to the bounds of the parent in some way (as for instance the <code>"%"</code> unit has) the cache
75
+     * must be turned off for the panel. If components does not get the correct or expected size or position try to set this property to <code>true</code>.
76
+     * @return <code>true</code> means no cache and slightly slower layout.
77
+     */
78
+    public boolean isNoCache() {
79
+        return noCache;
80
+    }
81
+
82
+    /** If components have sizes or positions linked to the bounds of the parent in some way (as for instance the <code>"%"</code> unit has) the cache
83
+     * must be turned off for the panel. If components does not get the correct or expected size or position try to set this property to <code>true</code>.
84
+     * @param b <code>true</code> means no cache and slightly slower layout.
85
+     */
86
+    public void setNoCache(boolean b) {
87
+        this.noCache = b;
88
+    }
89
+
90
+    /** If the laid out components' bounds in total is less than the final size of the container these align values will be used to align the components
91
+     * in the parent. <code>null</code> is default and that means top/left alignment. The relative distances between the components will not be affected
92
+     * by this property.
93
+     * @return The current alignment.
94
+     */
95
+    public final UnitValue getAlignX() {
96
+        return alignX;
97
+    }
98
+
99
+    /** If the laid out components' bounds in total is less than the final size of the container these align values will be used to align the components
100
+     * in the parent. <code>null</code> is default and that means top/left alignment. The relative distances between the components will not be affected
101
+     * by this property.
102
+     * @param uv The new alignment. Use {@link ConstraintParser#parseAlignKeywords(String, boolean)} to create the {@link UnitValue}. May be <code>null</code>.
103
+     */
104
+    public final void setAlignX(UnitValue uv) {
105
+        this.alignX = uv;
106
+    }
107
+
108
+    /** If the laid out components' bounds in total is less than the final size of the container these align values will be used to align the components
109
+     * in the parent. <code>null</code> is default and that means top/left alignment. The relative distances between the components will not be affected
110
+     * by this property.
111
+     * @return The current alignment.
112
+     */
113
+    public final UnitValue getAlignY() {
114
+        return alignY;
115
+    }
116
+
117
+    /** If the laid out components' bounds in total is less than the final size of the container these align values will be used to align the components
118
+     * in the parent. <code>null</code> is default and that means top/left alignment. The relative distances between the components will not be affected
119
+     * by this property.
120
+     * @param uv The new alignment. Use {@link ConstraintParser#parseAlignKeywords(String, boolean)} to create the {@link UnitValue}. May be <code>null</code>.
121
+     */
122
+    public final void setAlignY(UnitValue uv) {
123
+        this.alignY = uv;
124
+    }
125
+
126
+    /** If <code>&gt; 0</code> the debug decorations will be repainted every <code>millis</code>. No debug information if <code>&lt;= 0</code> (default).
127
+     * @return The current debug repaint interval.
128
+     */
129
+    public final int getDebugMillis() {
130
+        return debugMillis;
131
+    }
132
+
133
+    /** If <code>&gt; 0</code> the debug decorations will be repainted every <code>millis</code>. No debug information if <code>&lt;= 0</code> (default).
134
+     * @param millis The new debug repaint interval.
135
+     */
136
+    public final void setDebugMillis(int millis) {
137
+        this.debugMillis = millis;
138
+    }
139
+
140
+    /** If the layout should always claim the whole bounds of the laid out container even if the preferred size is smaller.
141
+     * @return <code>true</code> means fill. <code>false</code> is default.
142
+     */
143
+    public final boolean isFillX() {
144
+        return fillX;
145
+    }
146
+
147
+    /** If the layout should always claim the whole bounds of the laid out container even if the preferred size is smaller.
148
+     * @param b <code>true</code> means fill. <code>false</code> is default.
149
+     */
150
+    public final void setFillX(boolean b) {
151
+        this.fillX = b;
152
+    }
153
+
154
+    /** If the layout should always claim the whole bounds of the laid out container even if the preferred size is smaller.
155
+     * @return <code>true</code> means fill. <code>false</code> is default.
156
+     */
157
+    public final boolean isFillY() {
158
+        return fillY;
159
+    }
160
+
161
+    /** If the layout should always claim the whole bounds of the laid out container even if the preferred size is smaller.
162
+     * @param b <code>true</code> means fill. <code>false</code> is default.
163
+     */
164
+    public final void setFillY(boolean b) {
165
+        this.fillY = b;
166
+    }
167
+
168
+    /** The default flow direction. Normally (which is <code>true</code>) this is horizontal and that means that the "next" component
169
+     * will be put in the cell to the right (or to the left if left-to-right is false).
170
+     * @return <code>true</code> is the default flow horizontally.
171
+     * @see #setLeftToRight(Boolean)
172
+     */
173
+    public final boolean isFlowX() {
174
+        return flowX;
175
+    }
176
+
177
+    /** The default flow direction. Normally (which is <code>true</code>) this is horizontal and that means that the "next" component
178
+     * will be put in the cell to the right (or to the left if left-to-right is false).
179
+     * @param b <code>true</code> is the default flow horizontally.
180
+     * @see #setLeftToRight(Boolean)
181
+     */
182
+    public final void setFlowX(boolean b) {
183
+        this.flowX = b;
184
+    }
185
+
186
+    /** If non-<code>null</code> (<code>null</code> is default) these value will be used as the default gaps between the columns in the grid.
187
+     * @return The default grid gap between columns in the grid. <code>null</code> if the platform default is used.
188
+     */
189
+    public final BoundSize getGridGapX() {
190
+        return gridGapX;
191
+    }
192
+
193
+    /** If non-<code>null</code> (<code>null</code> is default) these value will be used as the default gaps between the columns in the grid.
194
+     * @param x The default grid gap between columns in the grid. If <code>null</code> the platform default is used.
195
+     */
196
+    public final void setGridGapX(BoundSize x) {
197
+        this.gridGapX = x;
198
+    }
199
+
200
+    /** If non-<code>null</code> (<code>null</code> is default) these value will be used as the default gaps between the rows in the grid.
201
+     * @return The default grid gap between rows in the grid. <code>null</code> if the platform default is used.
202
+     */
203
+    public final BoundSize getGridGapY() {
204
+        return gridGapY;
205
+    }
206
+
207
+    /** If non-<code>null</code> (<code>null</code> is default) these value will be used as the default gaps between the rows in the grid.
208
+     * @param y The default grid gap between rows in the grid. If <code>null</code> the platform default is used.
209
+     */
210
+    public final void setGridGapY(BoundSize y) {
211
+        this.gridGapY = y;
212
+    }
213
+
214
+    /** How a component that is hidden (not visible) should be treated by default.
215
+     * @return The mode:<br>
216
+     * 0 == Normal. Bounds will be caclulated as if the component was visible.<br>
217
+     * 1 == If hidden the size will be 0, 0 but the gaps remain.<br>
218
+     * 2 == If hidden the size will be 0, 0 and gaps set to zero.<br>
219
+     * 3 == If hidden the component will be disregarded completely and not take up a cell in the grid..
220
+     */
221
+    public final int getHideMode() {
222
+        return hideMode;
223
+    }
224
+
225
+    /** How a component that is hidden (not visible) should be treated.
226
+     * @param mode The mode:<br>
227
+     * 0 == Normal. Bounds will be caclulated as if the component was visible.<br>
228
+     * 1 == If hidden the size will be 0, 0 but the gaps remain.<br>
229
+     * 2 == If hidden the size will be 0, 0 and gaps set to zero.<br>
230
+     * 3 == If hidden the component will be disregarded completely and not take up a cell in the grid..
231
+     */
232
+    public final void setHideMode(int mode) {
233
+        if (mode < 0 || mode > 3) {
234
+            throw new IllegalArgumentException("Wrong hideMode: " + mode);
235
+        }
236
+        this.hideMode = mode;
237
+    }
238
+
239
+    /** The insets for the layed out panel. The insets will be an empty space around the components in the panel. <code>null</code> values
240
+     * means that the default panel insets for the platform is used. See {@link PlatformDefaults#setDialogInsets(net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue)}.
241
+     * @return The insets. Of length 4 (top, left, bottom, right) or <code>null</code>. The elements (1 to 4) may be <code>null</code>. The array is a copy and can be used freely.
242
+     * @see net.miginfocom.layout.ConstraintParser#parseInsets(String, boolean)
243
+     */
244
+    public final UnitValue[] getInsets() {
245
+        return insets != null
246
+                ? new UnitValue[]{insets[0], insets[1], insets[2], insets[3]}
247
+                : null;
248
+    }
249
+
250
+    /** The insets for the layed out panel. The insets will be an empty space around the components in the panel. <code>null</code> values
251
+     * means that the default panel insets for the platform is used. See {@link PlatformDefaults#setDialogInsets(net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue)}.
252
+     * @param ins The new insets. Must be of length 4 (top, left, bottom, right) or <code>null</code>. The elements (1 to 4) may be <code>null</code> to use
253
+     * the platform default for that side. The array is copied for storage.
254
+     * @see net.miginfocom.layout.ConstraintParser#parseInsets(String, boolean)
255
+     */
256
+    public final void setInsets(UnitValue[] ins) {
257
+        this.insets =
258
+                ins != null ? new UnitValue[]{ins[0], ins[1], ins[2], ins[3]}
259
+                : null;
260
+    }
261
+
262
+    /** If the layout should be forced to be left-to-right or right-to-left. A value of <code>null</code> is default and
263
+     * means that this will be picked up from the {@link java.util.Locale} that the container being layed out is reporting.
264
+     * @return <code>Boolean.TRUE</code> if force left-to-right. <code>Boolean.FALSE</code> if force tight-to-left. <code>null</code>
265
+     * for the default "let the current Locale decide".
266
+     */
267
+    public final Boolean getLeftToRight() {
268
+        return leftToRight;
269
+    }
270
+
271
+    /** If the layout should be forced to be left-to-right or right-to-left. A value of <code>null</code> is default and
272
+     * means that this will be picked up from the {@link java.util.Locale} that the container being layed out is reporting.
273
+     * @param b <code>Boolean.TRUE</code> to force left-to-right. <code>Boolean.FALSE</code> to force tight-to-left. <code>null</code>
274
+     * for the default "let the current Locale decide".
275
+     */
276
+    public final void setLeftToRight(Boolean b) {
277
+        this.leftToRight = b;
278
+    }
279
+
280
+    /** If the whole layout should be non grid based. It is the same as setting the "nogrid" property on every row/column in the grid.
281
+     * @return <code>true</code> means not grid based. <code>false</code> is default.
282
+     */
283
+    public final boolean isNoGrid() {
284
+        return noGrid;
285
+    }
286
+
287
+    /** If the whole layout should be non grid based. It is the same as setting the "nogrid" property on every row/column in the grid.
288
+     * @param b <code>true</code> means no grid. <code>false</code> is default.
289
+     */
290
+    public final void setNoGrid(boolean b) {
291
+        this.noGrid = b;
292
+    }
293
+
294
+    /** If the layout should go from the default top-to-bottom in the grid instead of the optinal bottom-to-top.
295
+     * @return <code>true</code> for the default top-to-bottom.
296
+     */
297
+    public final boolean isTopToBottom() {
298
+        return topToBottom;
299
+    }
300
+
301
+    /** If the layout should go from the default top-to-bottom in the grid instead of the optinal bottom-to-top.
302
+     * @param b <code>true</code> for the default top-to-bottom.
303
+     */
304
+    public final void setTopToBottom(boolean b) {
305
+        this.topToBottom = b;
306
+    }
307
+
308
+    /** If visual padding should be automatically used and compensated for by this layout instance.
309
+     * @return <code>true</code> if visual padding.
310
+     */
311
+    public final boolean isVisualPadding() {
312
+        return visualPadding;
313
+    }
314
+
315
+    /** If visual padding should be automatically used and compensated for by this layout instance.
316
+     * @param b <code>true</code> turns on visual padding.
317
+     */
318
+    public final void setVisualPadding(boolean b) {
319
+        this.visualPadding = b;
320
+    }
321
+
322
+    /** Returns after what cell the grid should always auto wrap.
323
+     * @return After what cell the grid should always auto wrap. If <code>0</code> the number of columns/rows in the
324
+     * {@link net.miginfocom.layout.AC} is used. <code>LayoutUtil.INF</code> is used for no auto wrap.
325
+     */
326
+    public final int getWrapAfter() {
327
+        return wrapAfter;
328
+    }
329
+
330
+    /** Sets after what cell the grid should always auto wrap.
331
+     * @param count After what cell the grid should always auto wrap. If <code>0</code> the number of columns/rows in the
332
+     * {@link net.miginfocom.layout.AC} is used. <code>LayoutUtil.INF</code> is used for no auto wrap.
333
+     */
334
+    public final void setWrapAfter(int count) {
335
+        this.wrapAfter = count;
336
+    }
337
+    // ************************************************************************
338
+    // * Builder methods.
339
+    // ************************************************************************
340
+
341
+    /** Sets a wrap after the number of columns/rows that is defined in the {@link net.miginfocom.layout.AC}.
342
+     * <p>
343
+     * Same functionality as {@link #setWrapAfter(int 0)} only this method returns <code>this</code> for chaining multiple calls.
344
+     * <p>
345
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
346
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
347
+     */
348
+    public final LC wrap() {
349
+        setWrapAfter(0);
350
+        return this;
351
+    }
352
+
353
+    /** Same functionality as {@link #setWrapAfter(int)} only this method returns <code>this</code> for chaining multiple calls.
354
+     * <p>
355
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
356
+     * @param count After what cell the grid should always auto wrap. If <code>0</code> the number of columns/rows in the
357
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
358
+     */
359
+    public final LC wrapAfter(int count) {
360
+        setWrapAfter(count);
361
+        return this;
362
+    }
363
+
364
+    /** Same functionality as {@link #setNoCache(boolean true)} only this method returns <code>this</code> for chaining multiple calls.
365
+     * <p>
366
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
367
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
368
+     */
369
+    public final LC noCache() {
370
+        setNoCache(true);
371
+        return this;
372
+    }
373
+
374
+    /** Same functionality as {@link #setFlowX(boolean true)} only this method returns <code>this</code> for chaining multiple calls.
375
+     * <p>
376
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
377
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
378
+     */
379
+    public final LC flowY() {
380
+        setFlowX(false);
381
+        return this;
382
+    }
383
+
384
+    /** Same functionality as {@link #setFillX(boolean true)} and {@link #setFillY(boolean true)} conmbined.T his method returns
385
+     * <code>this</code> for chaining multiple calls.
386
+     * <p>
387
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
388
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
389
+     */
390
+    public final LC fill() {
391
+        setFillX(true);
392
+        setFillY(true);
393
+        return this;
394
+    }
395
+
396
+    /** Same functionality as {@link #setFillX(boolean true)} only this method returns <code>this</code> for chaining multiple calls.
397
+     * <p>
398
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
399
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
400
+     */
401
+    public final LC fillX() {
402
+        setFillX(true);
403
+        return this;
404
+    }
405
+
406
+    /** Same functionality as {@link #setFillY(boolean true)} only this method returns <code>this</code> for chaining multiple calls.
407
+     * <p>
408
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
409
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
410
+     */
411
+    public final LC fillY() {
412
+        setFillY(true);
413
+        return this;
414
+    }
415
+
416
+    /** Same functionality as {@link #setLeftToRight(Boolean)} only this method returns <code>this</code> for chaining multiple calls.
417
+     * <p>
418
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
419
+     * @param b <code>true</code> for forcing left-to-right. <code>false</code> for forcing right-to-left.
420
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
421
+     */
422
+    public final LC leftToRight(boolean b) {
423
+        setLeftToRight(b ? Boolean.TRUE : Boolean.FALSE); // Not .valueOf du to retroweaver...
424
+        return this;
425
+    }
426
+
427
+    /** Same functionality as {@link #setTopToBottom(boolean false)} only this method returns <code>this</code> for chaining multiple calls.
428
+     * <p>
429
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
430
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
431
+     */
432
+    public final LC bottomToTop() {
433
+        setTopToBottom(false);
434
+        return this;
435
+    }
436
+
437
+    /** Same functionality as {@link #setNoGrid(boolean true)} only this method returns <code>this</code> for chaining multiple calls.
438
+     * <p>
439
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
440
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
441
+     */
442
+    public final LC noGrid() {
443
+        setNoGrid(true);
444
+        return this;
445
+    }
446
+
447
+    /** Same functionality as {@link #setVisualPadding(boolean false)} only this method returns <code>this</code> for chaining multiple calls.
448
+     * <p>
449
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
450
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
451
+     */
452
+    public final LC noVisualPadding() {
453
+        setVisualPadding(false);
454
+        return this;
455
+    }
456
+
457
+    /** Sets the same inset (expressed as a <code>UnitValue</code>, e.g. "10px" or "20mm") all around.
458
+     * <p>
459
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
460
+     * @param allSides The unit value to set for all sides. May be <code>null</code> which means that the default panel insets
461
+     * for the platform is used.
462
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
463
+     * @see #setInsets(UnitValue[])
464
+     */
465
+    public final LC insetsAll(String allSides) {
466
+        UnitValue insH = ConstraintParser.parseUnitValue(allSides, true);
467
+        UnitValue insV = ConstraintParser.parseUnitValue(allSides, false);
468
+        insets = new UnitValue[]{insV, insH, insV, insH}; // No setter to avoid copy again
469
+        return this;
470
+    }
471
+
472
+    /** Same functionality as <code>setInsets(ConstraintParser.parseInsets(s, true))</code>. This method returns <code>this</code>
473
+     * for chaining multiple calls.
474
+     * <p>
475
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
476
+     * @param s The string to parse. E.g. "10 10 10 10" or "20". If less than 4 groups the last will be used for the missing.
477
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
478
+     * @see #setInsets(UnitValue[])
479
+     */
480
+    public final LC insets(String s) {
481
+        insets = ConstraintParser.parseInsets(s, true);
482
+        return this;
483
+    }
484
+
485
+    /** Sets the different insets (expressed as a <code>UnitValue</code>s, e.g. "10px" or "20mm") for the corresponding sides.
486
+     * <p>
487
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
488
+     * @param top The top inset. E.g. "10px" or "10mm" or "related". May be <code>null</code> in which case the default inset for this
489
+     * side for the platform will be used.
490
+     * @param left The left inset. E.g. "10px" or "10mm" or "related". May be <code>null</code> in which case the default inset for this
491
+     * side for the platform will be used.
492
+     * @param bottom The bottom inset. E.g. "10px" or "10mm" or "related". May be <code>null</code> in which case the default inset for this
493
+     * side for the platform will be used.
494
+     * @param right The right inset. E.g. "10px" or "10mm" or "related". May be <code>null</code> in which case the default inset for this
495
+     * side for the platform will be used.
496
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
497
+     * @see #setInsets(UnitValue[])
498
+     */
499
+    public final LC insets(String top, String left, String bottom, String right) {
500
+        insets =new UnitValue[]{ConstraintParser.parseUnitValue(top, false),
501
+                ConstraintParser.parseUnitValue(left, true),
502
+                ConstraintParser.parseUnitValue(bottom, false),
503
+                ConstraintParser.parseUnitValue(right, true)};
504
+        return this;
505
+    }
506
+
507
+    /** Same functionality as <code>setAlignX(ConstraintParser.parseUnitValueOrAlign(unitValue, true))</code> only this method returns <code>this</code>
508
+     * for chaining multiple calls.
509
+     * <p>
510
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
511
+     * @param align The align keyword or for instance "100px". E.g "left", "right", "leading" or "trailing".
512
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
513
+     * @see #setAlignX(UnitValue)
514
+     */
515
+    public final LC alignX(String align) {
516
+        setAlignX(ConstraintParser.parseUnitValueOrAlign(align, true, null));
517
+        return this;
518
+    }
519
+
520
+    /** Same functionality as <code>setAlignY(ConstraintParser.parseUnitValueOrAlign(align, false))</code> only this method returns <code>this</code> for chaining multiple calls.
521
+     * <p>
522
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
523
+     * @param align The align keyword or for instance "100px". E.g "top" or "bottom".
524
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
525
+     * @see #setAlignY(UnitValue)
526
+     */
527
+    public final LC alignY(String align) {
528
+        setAlignY(ConstraintParser.parseUnitValueOrAlign(align, false, null));
529
+        return this;
530
+    }
531
+
532
+    /** Sets both the alignX and alignY as the same time.
533
+     * <p>
534
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
535
+     * @param ax The align keyword or for instance "100px". E.g "left", "right", "leading" or "trailing".
536
+     * @param ay The align keyword or for instance "100px". E.g "top" or "bottom".
537
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
538
+     * @see #alignX(String)
539
+     * @see #alignY(String)
540
+     */
541
+    public final LC align(String ax, String ay) {
542
+        if (ax != null) {
543
+            alignX(ax);
544
+        }
545
+        if (ay != null) {
546
+            alignY(ay);
547
+        }
548
+        return this;
549
+    }
550
+
551
+    /** Same functionality as <code>setGridGapX(ConstraintParser.parseBoundSize(boundsSize, true, true))</code> only this method
552
+     * returns <code>this</code> for chaining multiple calls.
553
+     * <p>
554
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
555
+     * @param boundsSize The <code>BoundSize</code> of the gap. This is a minimum and/or preferred and/or maximum size. E.g.
556
+     * <code>"50:100:200"</code> or <code>"100px"</code>.
557
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
558
+     * @see #setGridGapX(BoundSize)
559
+     */
560
+    public final LC gridGapX(String boundsSize) {
561
+        setGridGapX(ConstraintParser.parseBoundSize(boundsSize, true, true));
562
+        return this;
563
+    }
564
+
565
+    /** Same functionality as <code>setGridGapY(ConstraintParser.parseBoundSize(boundsSize, true, false))</code> only this method
566
+     * returns <code>this</code> for chaining multiple calls.
567
+     * <p>
568
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
569
+     * @param boundsSize The <code>BoundSize</code> of the gap. This is a minimum and/or preferred and/or maximum size. E.g.
570
+     * <code>"50:100:200"</code> or <code>"100px"</code>.
571
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
572
+     * @see #setGridGapY(BoundSize)
573
+     */
574
+    public final LC gridGapY(String boundsSize) {
575
+        setGridGapX(ConstraintParser.parseBoundSize(boundsSize, true, false));
576
+        return this;
577
+    }
578
+
579
+    /** Sets both grid gaps at the same time. see {@link #gridGapX(String)} and {@link #gridGapY(String)}.
580
+     * <p>
581
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
582
+     * @param gapx The <code>BoundSize</code> of the gap. This is a minimum and/or preferred and/or maximum size. E.g.
583
+     * <code>"50:100:200"</code> or <code>"100px"</code>.
584
+     * @param gapy The <code>BoundSize</code> of the gap. This is a minimum and/or preferred and/or maximum size. E.g.
585
+     * <code>"50:100:200"</code> or <code>"100px"</code>.
586
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
587
+     * @see #gridGapX(String)
588
+     * @see #gridGapY(String)
589
+     */
590
+    public final LC gridGap(String gapx, String gapy) {
591
+        if (gapx != null) {
592
+            gridGapX(gapx);
593
+        }
594
+        if (gapy != null) {
595
+            gridGapY(gapy);
596
+        }
597
+        return this;
598
+    }
599
+
600
+    /** Same functionality as {@link #setDebugMillis(int repaintMillis)} only this method returns <code>this</code> for chaining multiple calls.
601
+     * <p>
602
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
603
+     * @param repaintMillis The new debug repaint interval.
604
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
605
+     * @see #setDebugMillis(int)
606
+     */
607
+    public final LC debug(int repaintMillis) {
608
+        setDebugMillis(repaintMillis);
609
+        return this;
610
+    }
611
+
612
+    /** Same functionality as {@link #setHideMode(int mode)} only this method returns <code>this</code> for chaining multiple calls.
613
+     * <p>
614
+     * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com.
615
+     * @param mode The mode:<br>
616
+     * 0 == Normal. Bounds will be caclulated as if the component was visible.<br>
617
+     * 1 == If hidden the size will be 0, 0 but the gaps remain.<br>
618
+     * 2 == If hidden the size will be 0, 0 and gaps set to zero.<br>
619
+     * 3 == If hidden the component will be disregarded completely and not take up a cell in the grid..
620
+     * @return <code>this</code> so it is possible to chain calls. E.g. <code>new LayoutConstraint().noGrid().gap().fill()</code>.
621
+     * @see #setHideMode(int)
622
+     */
623
+    public final LC hideMode(int mode) {
624
+        setHideMode(mode);
625
+        return this;
626
+    }
627
+    // ************************************************
628
+    // Persistence Delegate and Serializable combined.
629
+    // ************************************************
630
+
631
+    private Object readResolve() throws ObjectStreamException {
632
+        return LayoutUtil.getSerializedObject(this);
633
+    }
634
+
635
+    public void readExternal(ObjectInput in) throws IOException,
636
+            ClassNotFoundException {
637
+        LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in));
638
+    }
639
+
640
+    public void writeExternal(ObjectOutput out) throws IOException {
641
+        if (getClass() == LC.class) {
642
+            LayoutUtil.writeAsXML(out, this);
643
+        }
644
+    }
645
+}

+ 75
- 0
src/net/miginfocom/layout/LayoutCallback.java View File

@@ -0,0 +1,75 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+/** A class to extend if you want to provide more control over where a component is placed or the size of it.
38
+ * <p>
39
+ * Note! Returned arrays from this class will never be altered. This means that caching of arrays in these methods
40
+ * is OK.
41
+ */
42
+public abstract class LayoutCallback {
43
+
44
+    /** Returns a position similar to the "pos" the component constraint.
45
+     * @param comp The component wrapper that holds the actual component (JComponent is Swing and Control in SWT).
46
+     * <b>Should not be altered.</b>
47
+     * @return The [x, y, x2, y2] as explained in the documentation for "pos". If <code>null</code>
48
+     * is returned nothing is done and this is the default.
49
+     * @see UnitValue
50
+     * @see net.miginfocom.layout.ConstraintParser#parseUnitValue(String, boolean)
51
+     */
52
+    public UnitValue[] getPosition(ComponentWrapper comp) {
53
+        return null;
54
+    }
55
+
56
+    /** Returns a size similar to the "width" and "height" in the component constraint.
57
+     * @param comp The component wrapper that holds the actual component (JComponent is Swing and Control in SWT).
58
+     * <b>Should not be altered.</b>
59
+     * @return The [width, height] as explained in the documentation for "width" and "height". If <code>null</code>
60
+     * is returned nothing is done and this is the default.
61
+     * @see net.miginfocom.layout.BoundSize
62
+     * @see net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean)
63
+     */
64
+    public BoundSize[] getSize(ComponentWrapper comp) {
65
+        return null;
66
+    }
67
+
68
+    /** A last minute change of the bounds. The bound for the layout cycle has been set and you can correct there
69
+     * after any set of rules you like.
70
+     * @param comp The component wrapper that holds the actual component (JComponent is Swing and Control in SWT).
71
+     * <b>Should not be altered.</b>
72
+     */
73
+    public void correctBounds(ComponentWrapper comp) {
74
+    }
75
+}

+ 542
- 0
src/net/miginfocom/layout/LayoutUtil.java View File

@@ -0,0 +1,542 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+import java.beans.*;
38
+import java.io.*;
39
+import java.util.IdentityHashMap;
40
+import java.util.TreeSet;
41
+import java.util.WeakHashMap;
42
+
43
+/** A utility class that has only static helper methods. */
44
+public final class LayoutUtil {
45
+
46
+    /** A substitute value for aa really large value. Integer.MAX_VALUE is not used since that means a lot of defensive code
47
+     * for potential overflow must exist in many places. This value is large enough for being unresonable yet it is hard to
48
+     * overflow.
49
+     */
50
+    static final int INF = (Integer.MAX_VALUE >> 10) - 100; // To reduce likelyhood of overflow errors when calculating.
51
+    /** Tag int for a value that in considered "not set". Used as "null" element in int arays.
52
+     */
53
+    static final int NOT_SET = Integer.MIN_VALUE + 12346; // Magic value...
54
+    // Index for the different sizes
55
+    public static final int MIN = 0;
56
+    public static final int PREF = 1;
57
+    public static final int MAX = 2;
58
+    private static WeakHashMap<Object, String> CR_MAP = null;
59
+    private static WeakHashMap<Object, Boolean> DT_MAP = null; // The Containers that have design time. Value not used.
60
+    private static int eSz = 15;
61
+
62
+    private LayoutUtil() {
63
+    }
64
+
65
+    /** Returns the current version of MiG Layout.
66
+     * @return The current version of MiG Layout.
67
+     */
68
+    public static String getVersion() {
69
+        return "2.5.5";
70
+    }
71
+
72
+    /** Sets if design time is turned on for a Container in {@link ContainerWrapper}.
73
+     * @param cw The container to set design time for. <code>null</code> is legal and can be used as
74
+     * a key to turn on/off design time "in general". Note though that design time "in general" is
75
+     * always on as long as there is at least one ContainerWrapper with design time.
76
+     * <p>
77
+     * <strong>If this method has not ever been called it will default to what
78
+     * <code>Beans.isDesignTime()</code> returns.</strong> This means that if you call
79
+     * this method you indicate that you will take responsibility for the design time value.
80
+     * @param b <code>true</code> means design time on.
81
+     */
82
+    public static void setDesignTime(ContainerWrapper cw, boolean b) {
83
+        if (DT_MAP == null) {
84
+            DT_MAP =new WeakHashMap<Object, Boolean>();
85
+        }
86
+        DT_MAP.put(cw != null ? cw.getComponent() : null, new Boolean(b));
87
+    }
88
+
89
+    /** Returns if design time is turned on for a Container in {@link ContainerWrapper}.
90
+     * @param cw The container to set design time for. <code>null</code> is legal will return <code>true</code>
91
+     * if there is at least one <code>ContainerWrapper</code> (or <code>null</code>) that have design time
92
+     * turned on.
93
+     * @return If design time is set for <code>cw</code>.
94
+     */
95
+    public static boolean isDesignTime(ContainerWrapper cw) {
96
+        if (DT_MAP == null) {
97
+            return Beans.isDesignTime();
98
+        }
99
+        Boolean b = DT_MAP.get(cw != null ? cw.getComponent() : null);
100
+        return b != null ? b.booleanValue() : false;
101
+    }
102
+
103
+    /** The size of an empty row or columns in a grid during design time.
104
+     * @return The number of pixels. Default is 15.
105
+     */
106
+    public static int getDesignTimeEmptySize() {
107
+        return eSz;
108
+    }
109
+
110
+    /** The size of an empty row or columns in a grid during design time.
111
+     * @param pixels The number of pixels. Default is 15.
112
+     */
113
+    public static void setDesignTimeEmptySize(int pixels) {
114
+        eSz = pixels;
115
+    }
116
+
117
+    /** Associates <code>con</code> with the creation string <code>s</code>. The <code>con</code> object should
118
+     * probably have an equals method that compares identities or <code>con</code> objects that .equals() will only
119
+     * be able to have <b>one</b> creation string.
120
+     * <p>
121
+     * If {@link LayoutUtil#isDesignTime(ContainerWrapper)} returns <code>false</code> the method does nothing.
122
+     * @param con The object. if <code>null</code> the method does nothing.
123
+     * @param s The creation string. if <code>null</code> the method does nothing.
124
+     */
125
+    static void putCCString(Object con, String s) {
126
+        if (s != null && con != null && isDesignTime(null)) {
127
+            if (CR_MAP == null) {
128
+                CR_MAP =new WeakHashMap<Object, String>(64);
129
+            }
130
+            CR_MAP.put(con, s);
131
+        }
132
+    }
133
+
134
+    /** Sets/add the persistence delagates to be used for a class.
135
+     * @param c The class to set the registered deligate for.
136
+     * @param del The new deligate or <code>null</code> to erase to old one.
137
+     */
138
+    static synchronized void setDelegate(Class c, PersistenceDelegate del) {
139
+        try {
140
+            Introspector.getBeanInfo(c).getBeanDescriptor().
141
+                    setValue("persistenceDelegate", del);
142
+        } catch (Exception e1) {
143
+        }
144
+    }
145
+
146
+    /** Returns strings set with {@link #putCCString(Object, String)} or <code>null</code> if nothing is associated or
147
+     * {@link LayoutUtil#isDesignTime(ContainerWrapper)} returns <code>false</code>.
148
+     * @param con The constraitn object.
149
+     * @return The creation string or <code>null</code> if nothing is registered with the <code>con</code> object.
150
+     */
151
+    static String getCCString(Object con) {
152
+        return CR_MAP != null ? CR_MAP.get(con) : null;
153
+    }
154
+
155
+    static void throwCC() {
156
+        throw new IllegalStateException("setStoreConstraintData(true) must be set for strings to be saved.");
157
+    }
158
+
159
+    /** Takes a number on min/preferred/max sizes and resize constraints and returns the calculated sizes which sum should add up to <code>bounds</code>. Whether the sum
160
+     * will actually equal <code>bounds</code> is dependent om the pref/max sizes and resise constraints.
161
+     * @param sizes [ix],[MIN][PREF][MAX]. Grid.CompWrap.NOT_SET will be treated as N/A or 0. A "[MIN][PREF][MAX]" array with null elements will be interpreted as very flexible (no bounds)
162
+     * but if the array itself is null it will not get any size.
163
+     * @param resConstr Elements can be <code>null</code> and the whole array can be <code>null</code>. <code>null</code> means that the size will not be flexible at all.
164
+     * Can have length less than <code>sizes</code> in which case the last element should be used for the elements missing.
165
+     * @param defGrowWeights If there is no grow weight for a resConstr the correspinding value of this array is used.
166
+     * These forced resConstr will be grown last though and only if needed to fill to the bounds.
167
+     * @param startSizeType The initial size to use. E.g. {@link net.miginfocom.layout.LayoutUtil#MIN}.
168
+     * @param bounds To use for relative sizes.
169
+     * @return The sizes. Array length will match <code>sizes</code>.
170
+     */
171
+    static int[] calculateSerial(int[][] sizes, ResizeConstraint[] resConstr,
172
+            Float[] defGrowWeights, int startSizeType, int bounds) {
173
+        float[] lengths = new float[sizes.length]; // heights/widths that are set
174
+        float usedLength = 0.0f;
175
+
176
+        // Give all preferred size to start with
177
+        for (int i = 0; i < sizes.length;
178
+                i++) {
179
+            if (sizes[i] != null) {
180
+                float len =
181
+                        sizes[i][startSizeType] != NOT_SET
182
+                        ? sizes[i][startSizeType] : 0;
183
+                int newSizeBounded =
184
+                        getBrokenBoundary(len, sizes[i][MIN], sizes[i][MAX]);
185
+                if (newSizeBounded != NOT_SET) {
186
+                    len = newSizeBounded;
187
+                }
188
+                usedLength += len;
189
+                lengths[i] = len;
190
+            }
191
+        }
192
+
193
+        int useLengthI = Math.round(usedLength);
194
+        if (useLengthI != bounds && resConstr != null) {
195
+            boolean isGrow = useLengthI < bounds;
196
+
197
+            // Create a Set with the available priorities
198
+            TreeSet<Integer> prioList =
199
+                    new TreeSet<Integer>();
200
+            for (int i = 0; i < sizes.length;
201
+                    i++) {
202
+                ResizeConstraint resC = (ResizeConstraint) getIndexSafe(resConstr, i);
203
+                if (resC != null) {
204
+                    prioList.add(new Integer(isGrow ? resC.growPrio
205
+                            : resC.shrinkPrio));
206
+                }
207
+            }
208
+            Integer[] prioIntegers =
209
+                    prioList.toArray(new Integer[prioList.size()]);
210
+
211
+            for (int force = 0;
212
+                    force <= ((isGrow && defGrowWeights != null) ? 1 : 0);
213
+                    force++) {
214
+                // Run twice if defGrow and the need for growing.
215
+                for (int pr = prioIntegers.length - 1; pr >= 0;
216
+                        pr--) {
217
+                    int curPrio = prioIntegers[pr].intValue();
218
+
219
+                    float totWeight = 0f;
220
+                    Float[] resizeWeight = new Float[sizes.length];
221
+                    for (int i = 0; i < sizes.length;
222
+                            i++) {
223
+                        if (sizes[i] == null) {
224
+                            // if no min/pref/max size at all do not grow or shrink.
225
+                            continue;
226
+                        }
227
+                        ResizeConstraint resC =
228
+                                (ResizeConstraint) getIndexSafe(resConstr, i);
229
+                        if (resC != null) {
230
+                            int prio = isGrow ? resC.growPrio : resC.shrinkPrio;
231
+
232
+                            if (curPrio == prio) {
233
+                                if (isGrow) {
234
+                                    resizeWeight[i] =
235
+                                            (force == 0 || resC.grow != null)
236
+                                            ? resC.grow
237
+                                            : (defGrowWeights[i <
238
+                                            defGrowWeights.length ? i
239
+                                            : defGrowWeights.length - 1]);
240
+                                } else {
241
+                                    resizeWeight[i] = resC.shrink;
242
+                                }
243
+                                if (resizeWeight[i] != null) {
244
+                                    totWeight += resizeWeight[i].floatValue();
245
+                                }
246
+                            }
247
+                        }
248
+                    }
249
+
250
+                    if (totWeight > 0f) {
251
+                        boolean hit;
252
+                        do {
253
+                            float toChange = bounds - usedLength;
254
+                            hit = false;
255
+                            float changedWeight = 0f;
256
+                            for (int i = 0;
257
+                                    i < sizes.length && totWeight > 0.0001f;
258
+                                    i++) {
259
+
260
+                                Float weight = resizeWeight[i];
261
+                                if (weight != null) {
262
+                                    float sizeDelta =
263
+                                            toChange * weight.floatValue() /
264
+                                            totWeight;
265
+                                    float newSize = lengths[i] + sizeDelta;
266
+
267
+                                    if (sizes[i] != null) {
268
+                                        int newSizeBounded =
269
+                                                getBrokenBoundary(newSize,
270
+                                                sizes[i][MIN], sizes[i][MAX]);
271
+                                        if (newSizeBounded != NOT_SET) {
272
+                                            resizeWeight[i] = null;
273
+                                            hit = true;
274
+                                            changedWeight += weight.floatValue();
275
+                                            newSize = newSizeBounded;
276
+                                            sizeDelta = newSize - lengths[i];
277
+                                        }
278
+                                    }
279
+
280
+                                    lengths[i] = newSize;
281
+                                    usedLength += sizeDelta;
282
+                                }
283
+                            }
284
+                            totWeight -= changedWeight;
285
+                        } while (hit);
286
+                    }
287
+                }
288
+            }
289
+        }
290
+        return roundSizes(lengths);
291
+    }
292
+
293
+    static Object getIndexSafe(Object[] arr, int ix) {
294
+        return arr != null ? arr[ix < arr.length ? ix : arr.length - 1] : null;
295
+    }
296
+
297
+    /** Returns the broken boundary if <code>sz</code> is outside the boundaries <code>lower</code> or <code>upper</code>. If both boundaries
298
+     * are broken, the lower one is returned. If <code>sz</code> is &lt; 0 then <code>new Float(0f)</code> is returned so that no sizes can be
299
+     * negative.
300
+     * @param sz The size to check
301
+     * @param lower The lower boundary (or <code>null</code> fo no boundary).
302
+     * @param upper The upper boundary (or <code>null</code> fo no boundary).
303
+     * @return The broken boundary or <code>null</code> if no boundary was broken.
304
+     */
305
+    private static int getBrokenBoundary(float sz, int lower, int upper) {
306
+        if (lower != NOT_SET) {
307
+            if (sz < lower) {
308
+                return new Integer(lower);
309
+            }
310
+        } else if (sz < 0f) {
311
+            return new Integer(0);
312
+        }
313
+
314
+        if (upper != NOT_SET && sz > upper) {
315
+            return new Integer(upper);
316
+        }
317
+        return NOT_SET;
318
+    }
319
+
320
+    static int sum(int[] terms, int start, int len) {
321
+        int s = 0;
322
+        for (int i = start, iSz = start + len; i < iSz;
323
+                i++) {
324
+            s += terms[i];
325
+        }
326
+        return s;
327
+    }
328
+
329
+    static int sum(int[] terms) {
330
+        return sum(terms, 0, terms.length);
331
+    }
332
+
333
+    public static int getSizeSafe(int[] sizes, int sizeType) {
334
+        if (sizes == null || sizes[sizeType] == NOT_SET) {
335
+            return sizeType == MAX ? LayoutUtil.INF : 0;
336
+        }
337
+        return sizes[sizeType];
338
+    }
339
+
340
+    static BoundSize derive(BoundSize bs, UnitValue min, UnitValue pref,
341
+            UnitValue max) {
342
+        if (bs == null) {
343
+            return new BoundSize(min, pref, max, null);
344
+        }
345
+        return new BoundSize(min != null ? min : bs.getMin(),
346
+                pref != null ? pref : bs.getPreferred(),
347
+                max != null ? max : bs.getMax(), null);
348
+    }
349
+
350
+    /** Returns if left-to-right orientation is used. If not set explicitly in the layout constraints the Locale
351
+     * of the <code>parent</code> is used.
352
+     * @param lc The constraint if there is one. Can be <code>null</code>.
353
+     * @param container The parent that may be used to get the left-to-right if ffc does not specify this.
354
+     * @return If left-to-right orientation is currently used.
355
+     */
356
+    public static final boolean isLeftToRight(LC lc, ContainerWrapper container) {
357
+        if (lc != null && lc.getLeftToRight() != null) {
358
+            return lc.getLeftToRight().booleanValue();
359
+        }
360
+        return container == null || container.isLeftToRight();
361
+    }
362
+
363
+    /** Round a number of float sizes into int sizes so that the total length match up
364
+     * @param sizes The sizes to round
365
+     * @return An array of equal length as <code>sizes</code>.
366
+     */
367
+    static int[] roundSizes(float[] sizes) {
368
+        int[] retInts = new int[sizes.length];
369
+        float posD = 0;
370
+
371
+        for (int i = 0; i < retInts.length;
372
+                i++) {
373
+            int posI = (int) (posD + 0.5f);
374
+
375
+            posD += sizes[i];
376
+
377
+            retInts[i] = (int) (posD + 0.5f) - posI;
378
+        }
379
+
380
+        return retInts;
381
+    }
382
+
383
+    /** Safe equals. null == null, but null never equals anything else.
384
+     * @param o1 The first object. May be <code>null</code>.
385
+     * @param o2 The second object. May be <code>null</code>.
386
+     * @return Returns <code>true</code> if <code>o1</code> and <code>o2</code> are equal (using .equals()) or both are <code>null</code>.
387
+     */
388
+    static final boolean equals(Object o1, Object o2) {
389
+        return o1 == o2 || (o1 != null && o2 != null && o1.equals(o2));
390
+    }
391
+//	static int getBaselineCorrect(Component comp)
392
+//	{
393
+//		Dimension pSize = comp.getPreferredSize();
394
+//		int baseline = comp.getBaseline(pSize.width, pSize.height);
395
+//		int nextBaseline = comp.getBaseline(pSize.width, pSize.height + 1);
396
+//
397
+//		// Amount to add to height when calculating where baseline
398
+//		// lands for a particular height:
399
+//		int padding = 0;
400
+//
401
+//		// Where the baseline is relative to the mid point
402
+//		int baselineOffset = baseline - pSize.height / 2;
403
+//		if (pSize.height % 2 == 0 && baseline != nextBaseline) {
404
+//			padding = 1;
405
+//		} else if (pSize.height % 2 == 1 && baseline == nextBaseline) {
406
+//			baselineOffset--;
407
+//			padding = 1;
408
+//		}
409
+//
410
+//		// The following calculates where the baseline lands for
411
+//		// the height z:
412
+//		return (pSize.height + padding) / 2 + baselineOffset;
413
+//	}
414
+
415
+    /** Converts a <code>float</code> to a string and is removing the ".0" if the float is an integer.
416
+     * @param f the float.
417
+     * @return <code>f</code> as a string. Never <code>null</code>.
418
+     */
419
+    static final String floatToString(float f) {
420
+        String valS = String.valueOf(f);
421
+        return valS.endsWith(".0") ? valS.substring(0, valS.length() - 2) : valS;
422
+    }
423
+
424
+    /** Returns the inset for the side.
425
+     * @param side top == 0, left == 1, bottom = 2, right = 3.
426
+     * @param getDefault If <code>true</code> the default insets will get retrieved if <code>lc</code> has none set.
427
+     * @return The inset for the side. Never <code>null</code>.
428
+     */
429
+    static final UnitValue getInsets(LC lc, int side, boolean getDefault) {
430
+        UnitValue[] i = lc.getInsets();
431
+        return (i != null && i[side] != null) ? i[side]
432
+                : (getDefault ? PlatformDefaults.getPanelInsets(side)
433
+                : UnitValue.ZERO);
434
+    }
435
+
436
+    /** Writes the objet and CLOSES the stream. Uses the persistence delegate registered in this class.
437
+     * @param os The stream to write to. Will be closed.
438
+     * @param o The object to be serialized.
439
+     * @param listener The listener to recieve the exeptions if there are any. If <code>null</code> not used.
440
+     */
441
+    static void writeXMLObject(OutputStream os, Object o,
442
+            ExceptionListener listener) {
443
+        ClassLoader oldClassLoader =
444
+                Thread.currentThread().getContextClassLoader();
445
+        Thread.currentThread().
446
+                setContextClassLoader(LayoutUtil.class.getClassLoader());
447
+
448
+        XMLEncoder encoder = new XMLEncoder(os);
449
+
450
+        if (listener != null) {
451
+            encoder.setExceptionListener(listener);
452
+        }
453
+        encoder.writeObject(o);
454
+        encoder.close(); // Must be closed to write.
455
+        Thread.currentThread().setContextClassLoader(oldClassLoader);
456
+    }
457
+    private static ByteArrayOutputStream writeOutputStream = null;
458
+
459
+    /** Writes an object to XML.
460
+     * @param out The boject out to write to. Will not be closed.
461
+     * @param o The object to write.
462
+     */
463
+    public static synchronized void writeAsXML(ObjectOutput out, Object o)
464
+            throws IOException {
465
+        if (writeOutputStream == null) {
466
+            writeOutputStream = new ByteArrayOutputStream(16384);
467
+        }
468
+        writeOutputStream.reset();
469
+
470
+        writeXMLObject(writeOutputStream, o,
471
+                new ExceptionListener() {
472
+
473
+            public void exceptionThrown(Exception e) {
474
+                e.printStackTrace();
475
+            }
476
+        });
477
+
478
+        byte[] buf = writeOutputStream.toByteArray();
479
+
480
+        out.writeInt(buf.length);
481
+        out.write(buf);
482
+    }
483
+    private static byte[] readBuf = null;
484
+
485
+    /** Reads an object from <code>in</code> using the
486
+     * @param in The object input to read from.
487
+     * @return The object. Never <code>null</code>.
488
+     * @throws IOException If there was a problem saving as XML
489
+     */
490
+    public static synchronized Object readAsXML(ObjectInput in) throws IOException {
491
+        if (readBuf == null) {
492
+            readBuf = new byte[16384];
493
+        }
494
+        Thread cThread = Thread.currentThread();
495
+        ClassLoader oldCL = null;
496
+
497
+        try {
498
+            oldCL = cThread.getContextClassLoader();
499
+            cThread.setContextClassLoader(LayoutUtil.class.getClassLoader());
500
+        } catch (SecurityException e) {
501
+        }
502
+
503
+        Object o = null;
504
+        try {
505
+            int length = in.readInt();
506
+            if (length > readBuf.length) {
507
+                readBuf = new byte[length];
508
+            }
509
+            in.readFully(readBuf, 0, length);
510
+
511
+            o =     new XMLDecoder(new ByteArrayInputStream(readBuf, 0, length)).readObject();
512
+        } catch (EOFException e) {
513
+        }
514
+
515
+        if (oldCL != null) {
516
+            cThread.setContextClassLoader(oldCL);
517
+        }
518
+        return o;
519
+    }
520
+    private static final IdentityHashMap<Object, Object> SER_MAP =
521
+            new IdentityHashMap<Object, Object>(2);
522
+
523
+    /** Sets the serialized object and associates it with <code>caller</code>.
524
+     * @param caller The objec created <code>o</code>
525
+     * @param o The just serialized object.
526
+     */
527
+    public static void setSerializedObject(Object caller, Object o) {
528
+        synchronized (SER_MAP) {
529
+            SER_MAP.put(caller, o);
530
+        }
531
+    }
532
+
533
+    /** Returns the serialized object that are associated with <code>caller</code>. It also removes it from the list.
534
+     * @param caller The original creator of the object.
535
+     * @return The object.
536
+     */
537
+    public static Object getSerializedObject(Object caller) {
538
+        synchronized (SER_MAP) {
539
+            return SER_MAP.remove(caller);
540
+        }
541
+    }
542
+}

+ 203
- 0
src/net/miginfocom/layout/LinkHandler.java View File

@@ -0,0 +1,203 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+import java.lang.ref.WeakReference;
38
+import java.util.ArrayList;
39
+import java.util.HashMap;
40
+
41
+/** Link handler. */
42
+public final class LinkHandler {
43
+
44
+    public static final int X = 0;
45
+    public static final int Y = 1;
46
+    public static final int WIDTH = 2;
47
+    public static final int HEIGHT = 3;
48
+    public static final int X2 = 4;
49
+    public static final int Y2 = 5;
50
+    private static final ArrayList<WeakReference<Object>> LAYOUTS =
51
+            new ArrayList<WeakReference<Object>>(4);
52
+    private static final ArrayList<HashMap<String, int[]>> VALUES =
53
+            new ArrayList<HashMap<String, int[]>>(4);
54
+    private static final ArrayList<HashMap<String, int[]>> VALUES_TEMP =
55
+            new ArrayList<HashMap<String, int[]>>(4);
56
+
57
+    private LinkHandler() {
58
+    }
59
+
60
+    public static synchronized Integer getValue(Object layout,
61
+            String key, int type) {
62
+        Integer ret = null;
63
+        boolean cont = true;
64
+
65
+        for (int i = LAYOUTS.size() - 1; i >= 0;
66
+                i--) {
67
+            Object l = LAYOUTS.get(i).get();
68
+            if (ret == null && l == layout) {
69
+                int[] rect = VALUES_TEMP.get(i).get(key);
70
+                if (cont && rect != null &&
71
+                        rect[type] != LayoutUtil.NOT_SET) {
72
+                    ret = new Integer(rect[type]);
73
+                } else {
74
+                    rect = VALUES.get(i).get(key);
75
+                    ret =   (rect != null &&
76
+                            rect[type] !=
77
+                            LayoutUtil.NOT_SET)
78
+                            ? new Integer(rect[type]) : null;
79
+                }
80
+                cont = false;
81
+            }
82
+
83
+            if (l == null) {
84
+                LAYOUTS.remove(i);
85
+                VALUES.remove(i);
86
+                VALUES_TEMP.remove(i);
87
+            }
88
+        }
89
+        return ret;
90
+    }
91
+
92
+    public static synchronized boolean setBounds(Object layout,
93
+            String key, int x, int y, int width, int height) {
94
+        return setBounds(layout, key, x, y, width, height, false, false);
95
+    }
96
+
97
+    static synchronized boolean setBounds(Object layout, String key, int x,
98
+            int y, int width, int height, boolean temporary, boolean incCur) {
99
+        for (int i = LAYOUTS.size() - 1; i >= 0;
100
+                i--) {
101
+            Object l = LAYOUTS.get(i).get();
102
+            if (l == layout) {
103
+                HashMap<String, int[]> map =
104
+                        (temporary ? VALUES_TEMP : VALUES).get(i);
105
+                int[] old = map.get(key);
106
+
107
+                if (old == null || old[X] != x || old[Y] != y ||
108
+                        old[WIDTH] != width || old[HEIGHT] != height) {
109
+                    if (old == null || incCur == false) {
110
+                        map.put(key,
111
+                                new int[]{x, y, width, height, x + width,
112
+                                y + height});
113
+                        return true;
114
+                    } else {
115
+                        boolean changed = false;
116
+
117
+                        if (x != LayoutUtil.NOT_SET) {
118
+                            if (old[X] ==
119
+                                    LayoutUtil.NOT_SET || x < old[X]) {
120
+                                old[X] = x;
121
+                                old[WIDTH] = old[X2] - x;
122
+                                changed = true;
123
+                            }
124
+
125
+                            if (width != LayoutUtil.NOT_SET) {
126
+                                int x2 = x + width;
127
+                                if (old[X2] ==
128
+                                        LayoutUtil.NOT_SET || x2 > old[X2]) {
129
+                                    old[X2] = x2;
130
+                                    old[WIDTH] = x2 - old[X];
131
+                                    changed = true;
132
+                                }
133
+                            }
134
+                        }
135
+
136
+                        if (y != LayoutUtil.NOT_SET) {
137
+                            if (old[Y] ==
138
+                                    LayoutUtil.NOT_SET || y < old[Y]) {
139
+                                old[Y] = y;
140
+                                old[HEIGHT] = old[Y2] - y;
141
+                                changed = true;
142
+                            }
143
+
144
+                            if (height !=
145
+                                    LayoutUtil.NOT_SET) {
146
+                                int y2 = y + height;
147
+                                if (old[Y2] ==
148
+                                        LayoutUtil.NOT_SET || y2 > old[Y2]) {
149
+                                    old[Y2] = y2;
150
+                                    old[HEIGHT] = y2 - old[Y];
151
+                                    changed = true;
152
+                                }
153
+                            }
154
+                        }
155
+                        return changed;
156
+                    }
157
+                }
158
+                return false;
159
+            }
160
+        }
161
+
162
+        LAYOUTS.add(new WeakReference<Object>(layout));
163
+        int[] bounds = new int[]{x, y, width, height, x + width, y + height};
164
+
165
+        HashMap<String, int[]> values =
166
+                new HashMap<String, int[]>(4);
167
+        if (temporary) {
168
+            values.put(key, bounds);
169
+        }
170
+        VALUES_TEMP.add(values);
171
+
172
+        values = new HashMap<String, int[]>(4);
173
+        if (temporary == false) {
174
+            values.put(key, bounds);
175
+        }
176
+        VALUES.add(values);
177
+
178
+        return true;
179
+    }
180
+
181
+    public static synchronized boolean clearBounds(Object layout,
182
+            String key) {
183
+        for (int i = LAYOUTS.size() - 1; i >= 0;
184
+                i--) {
185
+            Object l = LAYOUTS.get(i).get();
186
+            if (l == layout) {
187
+                return VALUES.get(i).remove(key) != null;
188
+            }
189
+        }
190
+        return false;
191
+    }
192
+
193
+    static synchronized void clearTemporaryBounds(Object layout) {
194
+        for (int i = LAYOUTS.size() - 1; i >= 0;
195
+                i--) {
196
+            Object l = LAYOUTS.get(i).get();
197
+            if (l == layout) {
198
+                VALUES_TEMP.get(i).clear();
199
+                return;
200
+            }
201
+        }
202
+    }
203
+}

+ 513
- 0
src/net/miginfocom/layout/PlatformDefaults.java View File

@@ -0,0 +1,513 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+import javax.swing.*;
38
+import java.util.HashMap;
39
+
40
+/** Currently handles Windows and Mac OS X spacing. */
41
+public final class PlatformDefaults {
42
+
43
+    private static InCellGapProvider gapProvider = null;
44
+    private static volatile int MOD_COUNT = 0;
45
+    private static final UnitValue LPX4 =
46
+            new UnitValue(4, UnitValue.LPX, null);
47
+    private static final UnitValue LPX7 =
48
+            new UnitValue(7, UnitValue.LPX, null);
49
+    private static final UnitValue LPX8 =
50
+            new UnitValue(8, UnitValue.LPX, null);
51
+    private static final UnitValue LPX9 =
52
+            new UnitValue(9, UnitValue.LPX, null);
53
+    private static final UnitValue LPX10 =
54
+            new UnitValue(10, UnitValue.LPX, null);
55
+    private static final UnitValue LPX11 =
56
+            new UnitValue(11, UnitValue.LPX, null);
57
+    private static final UnitValue LPX12 =
58
+            new UnitValue(12, UnitValue.LPX, null);
59
+    private static final UnitValue LPX14 =
60
+            new UnitValue(14, UnitValue.LPX, null);
61
+    private static final UnitValue LPX16 =
62
+            new UnitValue(16, UnitValue.LPX, null);
63
+    private static final UnitValue LPX20 =
64
+            new UnitValue(20, UnitValue.LPX, null);
65
+    private static final UnitValue LPY4 =
66
+            new UnitValue(4, UnitValue.LPY, null);
67
+    private static final UnitValue LPY7 =
68
+            new UnitValue(7, UnitValue.LPY, null);
69
+    private static final UnitValue LPY8 =
70
+            new UnitValue(8, UnitValue.LPY, null);
71
+    private static final UnitValue LPY9 =
72
+            new UnitValue(9, UnitValue.LPY, null);
73
+    private static final UnitValue LPY10 =
74
+            new UnitValue(10, UnitValue.LPY, null);
75
+    private static final UnitValue LPY11 =
76
+            new UnitValue(11, UnitValue.LPY, null);
77
+    private static final UnitValue LPY12 =
78
+            new UnitValue(12, UnitValue.LPY, null);
79
+    private static final UnitValue LPY14 =
80
+            new UnitValue(14, UnitValue.LPY, null);
81
+    private static final UnitValue LPY16 =
82
+            new UnitValue(16, UnitValue.LPY, null);
83
+    private static final UnitValue LPY20 =
84
+            new UnitValue(20, UnitValue.LPY, null);
85
+    public static final int WINDOWS_XP = 0;
86
+    public static final int MAC_OSX = 1;
87
+//	private static final int GNOME = 2;
88
+//	private static final int KDE = 3;
89
+    private static int CUR_PLAF = WINDOWS_XP;
90
+    // Used for holding values.
91
+    private static final UnitValue[] PANEL_INS =
92
+            new UnitValue[4];
93
+    private static final UnitValue[] DIALOG_INS =
94
+            new UnitValue[4];
95
+    private static String BUTTON_FORMAT = null;
96
+    private static final HashMap<String, UnitValue> HOR_DEFS =
97
+            new HashMap<String, UnitValue>(32);
98
+    private static final HashMap<String, UnitValue> VER_DEFS =
99
+            new HashMap<String, UnitValue>(32);
100
+    private static BoundSize DEF_VGAP = null;
101
+    private static BoundSize DEF_HGAP = null;
102
+    static BoundSize RELATED_X = null;
103
+    static BoundSize RELATED_Y = null;
104
+    static BoundSize UNRELATED_X = null;
105
+    static BoundSize UNRELATED_Y = null;
106
+    private static UnitValue BUTT_WIDTH = null;
107
+    static {
108
+        setPlatform(getCurrentPlatform());
109
+        MOD_COUNT = 0;
110
+    }
111
+
112
+    /** Returns the platform that the JRE is running on currently.
113
+     * @return The platform that the JRE is running on currently. E.g. {@link #MAC_OSX} or {@link #WINDOWS_XP}.
114
+     */
115
+    public static int getCurrentPlatform() {
116
+        return System.getProperty("os.name").startsWith("Mac OS") ? MAC_OSX
117
+                : WINDOWS_XP;
118
+    }
119
+
120
+    private PlatformDefaults() {
121
+    }
122
+
123
+    /** Set the defaults to the default for the platform
124
+     * @param plaf The platform. <code>PlatformDefaults.WINDOWS</code> or <code>PlatformDefaults.MAC_OSX</code>
125
+     */
126
+    public static void setPlatform(int plaf) {
127
+        if (plaf < WINDOWS_XP || plaf > MAC_OSX) {
128
+            throw new IllegalArgumentException("Unknown platform: " + plaf);
129
+        }
130
+        CUR_PLAF = plaf;
131
+        if (plaf == WINDOWS_XP) {
132
+            setRelatedGap(LPX4, LPY4);
133
+            setUnrelatedGap(LPX7, LPY9);
134
+            setParagraphGap(LPX14, LPY14);
135
+            setIndentGap(LPX9, LPY9);
136
+            setGridCellGap(LPX4, LPY4);
137
+
138
+            setMinimumButtonWidth(new UnitValue(75,
139
+                    UnitValue.PIXEL, null));
140
+            setButtonOrder("L_E+U+YNBXOCAH_R");
141
+            setDialogInsets(LPY11, LPX11, LPY11, LPX11);
142
+            setPanelInsets(LPY7, LPX7, LPY7, LPX7);
143
+        } else {
144
+            setRelatedGap(LPX8, LPY8);
145
+            setUnrelatedGap(LPX12, LPY12);
146
+            setParagraphGap(LPX16, LPY16);
147
+            setIndentGap(LPX10, LPY10);
148
+            setGridCellGap(LPX8, LPY8);
149
+
150
+            setMinimumButtonWidth(new UnitValue(68,
151
+                    UnitValue.PIXEL, null));
152
+            setButtonOrder("L_HE+U+NYBXCOA_R");
153
+            setDialogInsets(LPY14, LPX20, LPY20, LPX20);
154
+            setPanelInsets(LPY16, LPX16, LPY16, LPX16);
155
+        }
156
+    }
157
+
158
+    /** Returns the current platform
159
+     * @return <code>PlatformDefaults.WINDOWS</code> or <code>PlatformDefaults.MAC_OSX</code>
160
+     */
161
+    public static int getPlatform() {
162
+        return CUR_PLAF;
163
+    }
164
+
165
+    /** Sets gap value for components that are "related".
166
+     * @param x The value that will be transformed to pixels. If <code>null</code> the current value will not change.
167
+     * @param y The value that will be transformed to pixels. If <code>null</code> the current value will not change.
168
+     */
169
+    public static void setRelatedGap(UnitValue x,
170
+            UnitValue y) {
171
+        setUnitValue(new String[]{"r", "rel", "related"}, x, y);
172
+
173
+        RELATED_X = new BoundSize(x, x, null, "rel:rel");
174
+        RELATED_Y = new BoundSize(y, y, null, "rel:rel");
175
+    }
176
+
177
+    /** Sets gap value for components that are "unrelated".
178
+     * @param x The value that will be transformed to pixels. If <code>null</code> the current value will not change.
179
+     * @param y The value that will be transformed to pixels. If <code>null</code> the current value will not change.
180
+     */
181
+    public static void setUnrelatedGap(UnitValue x,
182
+            UnitValue y) {
183
+        setUnitValue(new String[]{"u", "unrel", "unrelated"}, x, y);
184
+
185
+        UNRELATED_X =
186
+                new BoundSize(x, x, null, "unrel:unrel");
187
+        UNRELATED_Y =
188
+                new BoundSize(y, y, null, "unrel:unrel");
189
+    }
190
+
191
+    /** Sets paragraph gap value for components.
192
+     * @param x The value that will be transformed to pixels. If <code>null</code> the current value will not change.
193
+     * @param y The value that will be transformed to pixels. If <code>null</code> the current value will not change.
194
+     */
195
+    public static void setParagraphGap(UnitValue x,
196
+            UnitValue y) {
197
+        setUnitValue(new String[]{"p", "para", "paragraph"}, x, y);
198
+    }
199
+
200
+    /** Sets gap value for components that are "intended".
201
+     * @param x The value that will be transformed to pixels. If <code>null</code> the current value will not change.
202
+     * @param y The value that will be transformed to pixels. If <code>null</code> the current value will not change.
203
+     */
204
+    public static void setIndentGap(UnitValue x,
205
+            UnitValue y) {
206
+        setUnitValue(new String[]{"i", "ind", "indent"}, x, y);
207
+    }
208
+
209
+    /** Sets gap between two cells in the grid. Note that this is not a gap between component IN a cell, that has to be set
210
+     * on the component constraints. The value will be the min and preferred size of the gap.
211
+     * @param x The value that will be transformed to pixels. If <code>null</code> the current value will not change.
212
+     * @param y The value that will be transformed to pixels. If <code>null</code> the current value will not change.
213
+     */
214
+    public static void setGridCellGap(UnitValue x,
215
+            UnitValue y) {
216
+        if (x != null) {
217
+            DEF_HGAP = new BoundSize(x, x, null, null);
218
+        }
219
+        if (y != null) {
220
+            DEF_VGAP = new BoundSize(y, y, null, null);
221
+        }
222
+        MOD_COUNT++;
223
+    }
224
+
225
+    /** Sets the recommended minimum button width.
226
+     * @param width The recommended minimum button width.
227
+     */
228
+    public static void setMinimumButtonWidth(UnitValue width) {
229
+        BUTT_WIDTH = width;
230
+        MOD_COUNT++;
231
+    }
232
+
233
+    /** Returns the recommended minimum button width depending on the current set platform.
234
+     * @return The recommended minimum button width depending on the current set platform.
235
+     */
236
+    public static UnitValue getMinimumButtonWidth() {
237
+        return BUTT_WIDTH;
238
+    }
239
+
240
+    /** Returns the unit value associated with the unit. (E.i. "related" or "indent"). Must be lower case.
241
+     * @param unit The unit string.
242
+     * @return Tthe unit value associated with the unit. <code>null</code> for unrecognized units.
243
+     */
244
+    public static UnitValue getUnitValueX(String unit) {
245
+        return HOR_DEFS.get(unit);
246
+    }
247
+
248
+    /** Returns the unit value associated with the unit. (E.i. "related" or "indent"). Must be lower case.
249
+     * @param unit The unit string.
250
+     * @return Tthe unit value associated with the unit. <code>null</code> for unrecognized units.
251
+     */
252
+    public static UnitValue getUnitValueY(String unit) {
253
+        return VER_DEFS.get(unit);
254
+    }
255
+
256
+    /** Sets the unit value assiciated with a unit string. This may be used to store values for new unit strings
257
+     * or modify old. Note that if a built in unit (such as "related") is modified all versions of it must be
258
+     * set (I.e. "r", "rel" and "related"). The build in values will be reset to the default ones if the platform
259
+     * is re-set.
260
+     * @param unitStrings The unit strings. E.g. "mu", "myunit". Will be converted to lower case and trimmed. Not <code>null</code>.
261
+     * @param x The value for the horizontal dimension. If <code>null</code> the value is not changed.
262
+     * @param y The value for the vertical dimension. Might be same object as for <code>x</code>. If <code>null</code> the value is not changed.
263
+     */
264
+    public static final void setUnitValue(String[] unitStrings,
265
+            UnitValue x, UnitValue y) {
266
+        for (int i = 0; i < unitStrings.length;
267
+                i++) {
268
+            String s = unitStrings[i].toLowerCase().trim();
269
+            if (x != null) {
270
+                HOR_DEFS.put(s, x);
271
+            }
272
+            if (y != null) {
273
+                VER_DEFS.put(s, y);
274
+            }
275
+        }
276
+        MOD_COUNT++;
277
+    }
278
+
279
+    /** Understands ("r", "rel", "related") OR ("u", "unrel", "unrelated") OR ("i", "ind", "indent") OR ("p", "para", "paragraph").
280
+     */
281
+    static final int convertToPixels(float value, String unit, boolean isHor,
282
+            float ref, ContainerWrapper parent,
283
+            ComponentWrapper comp) {
284
+        UnitValue uv = (isHor ? HOR_DEFS : VER_DEFS).get(unit);
285
+        return uv != null
286
+                ? Math.round(value * uv.getPixels(ref, parent, comp))
287
+                : UnitConverter.UNABLE;
288
+    }
289
+
290
+    /** Returns the order for the typical buttons in a standard button bar. It is one letter per button type.
291
+     * @return The button order.
292
+     * @see #setButtonOrder(String)
293
+     */
294
+    public static final String getButtonOrder() {
295
+        return BUTTON_FORMAT;
296
+    }
297
+
298
+    /** Sets the order for the typical buttons in a standard button bar. It is one letter per button type.
299
+     * <p>
300
+     * Letter in upper case will get the minimum button width that the {@link #getMinimumButtonWidth()} specifies
301
+     * and letters in lower case will get the width the corrent look&feel specifies.
302
+     * <p>
303
+     * Gaps will never be added to before the first component or after the last component. However, '+' (push) will be
304
+     * applied before and after as well, but with a minimum size of 0 if first/last so there will not be a gap
305
+     * before or after.
306
+     * <p>
307
+     * If gaps are explicitly set on buttons they will never be reduced, but they may be increased.
308
+     * <p>
309
+     * These are the characters that can be used:
310
+     * <ul>
311
+     * <li><code>'L'</code> - Buttons with this style tag will staticall end up on the left end of the bar.
312
+     * <li><code>'R'</code> - Buttons with this style tag will staticall end up on the right end of the bar.
313
+     * <li><code>'H'</code> - A tag for the "help" button that normally is supposed to be on the right.
314
+     * <li><code>'E'</code> - A tag for the "help2" button that normally is supposed to be on the left.
315
+     * <li><code>'Y'</code> - A tag for the "yes" button.
316
+     * <li><code>'N'</code> - A tag for the "no" button.
317
+     * <li><code>'X'</code> - A tag for the "next >" or "forward >" button.
318
+     * <li><code>'B'</code> - A tag for the "< back>" or "< previous" button.
319
+     * <li><code>'I'</code> - A tag for the "finish".
320
+     * <li><code>'A'</code> - A tag for the "apply" button.
321
+     * <li><code>'C'</code> - A tag for the "cancel" or "close" button.
322
+     * <li><code>'O'</code> - A tag for the "ok" or "done" button.
323
+     * <li><code>'U'</code> - All Uncategorized, Other, or "Unknown" buttons. Tag will be "other".
324
+     * <li><code>'+'</code> - A glue push gap that will take as much space as it can and at least an "unrelated" gap. (Platform dependant)
325
+     * <li><code>'_'</code> - (underscore) An "unrelated" gap. (Platform dependant)
326
+     * </ul>
327
+     * <p>
328
+     * Even though the style tags are normally applied to buttons this works with all components.
329
+     * <p>
330
+     * The normal style for MAC OS X is <code>"L_HE+U+FBI_NYCOA_R"</code> and for Windows is <code>"L_E+U+FBI_YNOCAH_R"</code>
331
+     * @param order The new button order for the current platform.
332
+     */
333
+    public static final void setButtonOrder(String order) {
334
+        BUTTON_FORMAT = order;
335
+        MOD_COUNT++;
336
+    }
337
+
338
+    /** Returns the tag (used in the {@link CC}) for a char. The char is same as used in {@link #getButtonOrder()}.
339
+     * @param c The char. Must be lower case!
340
+     * @return The tag that corresponds to the char or <code>null</code> if the char is unrecognized.
341
+     */
342
+    static final String getTagForChar(char c) {
343
+        switch (c) {
344
+            case 'o':
345
+                return "ok";
346
+            case 'c':
347
+                return "cancel";
348
+            case 'h':
349
+                return "help";
350
+            case 'e':
351
+                return "help2";
352
+            case 'y':
353
+                return "yes";
354
+            case 'n':
355
+                return "no";
356
+            case 'a':
357
+                return "apply";
358
+            case 'x':
359
+                return "next"; // a.k.a forward
360
+            case 'b':
361
+                return "back"; // a.k.a. previous
362
+            case 'i':
363
+                return "finish";
364
+            case 'l':
365
+                return "left";
366
+            case 'r':
367
+                return "right";
368
+            case 'u':
369
+                return "other";
370
+            default:
371
+                return null;
372
+        }
373
+    }
374
+
375
+    /** Returns the platform recommended inter-cell gap in the horizontal (x) dimension..
376
+     * @return The platform recommended inter-cell gap in the horizontal (x) dimension..
377
+     */
378
+    public static BoundSize getGridGapX() {
379
+        return DEF_HGAP;
380
+    }
381
+
382
+    /** Returns the platform recommended inter-cell gap in the vertical (x) dimension..
383
+     * @return The platform recommended inter-cell gap in the vertical (x) dimension..
384
+     */
385
+    public static BoundSize getGridGapY() {
386
+        return DEF_VGAP;
387
+    }
388
+
389
+    /** Returns the default dialog inset depending of the current platform.
390
+     * @param side top == 0, left == 1, bottom = 2, right = 3.
391
+     * @return The inset. Never <code>null</code>.
392
+     */
393
+    public static UnitValue getDialogInsets(int side) {
394
+        return DIALOG_INS[side];
395
+    }
396
+
397
+    /** Sets the default insets for a dialog. Values that are null will not be changed.
398
+     * @param top The top inset. May be <code>null</code>.
399
+     * @param left The left inset. May be <code>null</code>.
400
+     * @param bottom The bottom inset. May be <code>null</code>.
401
+     * @param right The right inset. May be <code>null</code>.
402
+     */
403
+    public static void setDialogInsets(UnitValue top,
404
+            UnitValue left, UnitValue bottom,
405
+            UnitValue right) {
406
+        if (top != null) {
407
+            DIALOG_INS[0] = top;
408
+        }
409
+        if (left != null) {
410
+            DIALOG_INS[1] = left;
411
+        }
412
+        if (bottom != null) {
413
+            DIALOG_INS[2] = bottom;
414
+        }
415
+        if (right != null) {
416
+            DIALOG_INS[3] = right;
417
+        }
418
+        MOD_COUNT++;
419
+    }
420
+
421
+    /** Returns the default panel inset depending of the current platform.
422
+     * @param side top == 0, left == 1, bottom = 2, right = 3.
423
+     * @return The inset. Never <code>null</code>.
424
+     */
425
+    public static UnitValue getPanelInsets(int side) {
426
+        return PANEL_INS[side];
427
+    }
428
+
429
+    /** Sets the default insets for a dialog. Values that are null will not be changed.
430
+     * @param top The top inset. May be <code>null</code>.
431
+     * @param left The left inset. May be <code>null</code>.
432
+     * @param bottom The bottom inset. May be <code>null</code>.
433
+     * @param right The right inset. May be <code>null</code>.
434
+     */
435
+    public static void setPanelInsets(UnitValue top,
436
+            UnitValue left, UnitValue bottom,
437
+            UnitValue right) {
438
+        if (top != null) {
439
+            PANEL_INS[0] = top;
440
+        }
441
+        if (left != null) {
442
+            PANEL_INS[1] = left;
443
+        }
444
+        if (bottom != null) {
445
+            PANEL_INS[2] = bottom;
446
+        }
447
+        if (right != null) {
448
+            PANEL_INS[3] = right;
449
+        }
450
+        MOD_COUNT++;
451
+    }
452
+
453
+    /** Returns the percentage used for alignment for labels (0 is left, 50 is center and 100 is right).
454
+     * @return The percentage used for alignment for labels
455
+     */
456
+    public static float getLabelAlignPercentage() {
457
+        return CUR_PLAF == MAC_OSX ? 1f : 0f;
458
+    }
459
+
460
+    /** Returns the default gap between two components that <b>are in the same cell</b>.
461
+     * @param comp The component that the gap is for. Never <code>null</code>.
462
+     * @param adjacentComp The adjacent component if any. May be <code>null</code>.
463
+     * @param adjacentSide What side the <code>adjacentComp</code> is on. {@link javax.swing.SwingUtilities#TOP} or
464
+     * {@link javax.swing.SwingUtilities#LEFT} or {@link javax.swing.SwingUtilities#BOTTOM} or {@link javax.swing.SwingUtilities#RIGHT}.
465
+     * @param tag The tag string that the component might be tagged with in the component constraints. May be <code>null</code>.
466
+     * @param isLTR If it is left-to-right.
467
+     * @return The default gap between two components or <code>null</code> if there should be no gap.
468
+     */
469
+    static BoundSize getDefaultComponentGap(ComponentWrapper comp,
470
+            ComponentWrapper adjacentComp, int adjacentSide,
471
+            String tag, boolean isLTR) {
472
+        if (gapProvider != null) {
473
+            return gapProvider.getDefaultGap(comp, adjacentComp, adjacentSide,
474
+                    tag, isLTR);
475
+        }
476
+        if (adjacentComp == null) {
477
+            return null;
478
+
479
+//		if (adjacentComp == null || adjacentSide == SwingConstants.LEFT || adjacentSide == SwingConstants.TOP)
480
+//			return null;
481
+        }
482
+        return (adjacentSide == SwingConstants.LEFT ||
483
+                adjacentSide == SwingConstants.RIGHT) ? RELATED_X : RELATED_Y;
484
+    }
485
+
486
+    /** Returns the current gap privider or <code>null</code> if none is set and "related" should always be used.
487
+     * @return The current gap privider or <code>null</code> if none is set and "related" should always be used.
488
+     */
489
+    public static InCellGapProvider getGapProvider() {
490
+        return gapProvider;
491
+    }
492
+
493
+    /** Sets the current gap privider or <code>null</code> if none is set and "related" should always be used.
494
+     * @param provider The current gap privider or <code>null</code> if none is set and "related" should always be used.
495
+     */
496
+    public static void setGapProvider(InCellGapProvider provider) {
497
+        gapProvider = provider;
498
+    }
499
+
500
+    /** Returns how many times the defaults has been changed. This can be used as a light weight check to
501
+     * see if layout caches needs to be refreshed.
502
+     * @return How many times the defaults has been changed.
503
+     */
504
+    public static int getModCount() {
505
+        return MOD_COUNT;
506
+    }
507
+
508
+    /** Tells all layout manager instances to revalidate and recalculated everything.
509
+     */
510
+    public void invalidate() {
511
+        MOD_COUNT++;
512
+    }
513
+}

+ 94
- 0
src/net/miginfocom/layout/ResizeConstraint.java View File

@@ -0,0 +1,94 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+import java.io.*;
38
+
39
+/**
40
+ * A parsed constraint that specifies how an entity (normally column/row or component) can shrink or
41
+ * grow compared to other entities.
42
+ */
43
+final class ResizeConstraint implements Externalizable {
44
+
45
+    /**
46
+     * A version number for this class. It should be changed whenever the class
47
+     * structure is changed (or anything else that would prevent serialized
48
+     * objects being unserialized with the new class).
49
+     */
50
+    private static final long serialVersionUID = 1;
51
+    static final Float WEIGHT_100 = new Float(100);
52
+    /** How flexilble the entity should be, relative to other entities, when it comes to growing. <code>null</code> or
53
+     * zero mean it will never grow. An entity that has twise the growWeight compared to another entity will get twice
54
+     * as much of available space.
55
+     * <p>
56
+     * "grow" are only compared within the same "growPrio".
57
+     */
58
+    Float grow = null;
59
+    /** The relative priority used for determining which entities gets the extra space first.
60
+     */
61
+    int growPrio = 100;
62
+    Float shrink = WEIGHT_100;
63
+    int shrinkPrio = 100;
64
+
65
+    public ResizeConstraint() {
66
+    }
67
+
68
+    ResizeConstraint(int shrinkPrio, Float shrinkWeight, int growPrio,
69
+            Float growWeight) {
70
+        this.shrinkPrio = shrinkPrio;
71
+        this.shrink = shrinkWeight;
72
+        this.growPrio = growPrio;
73
+        this.grow = growWeight;
74
+    }
75
+    // ************************************************
76
+    // Persistence Delegate and Serializable combined.
77
+    // ************************************************
78
+
79
+    private Object readResolve() throws ObjectStreamException {
80
+        return LayoutUtil.getSerializedObject(this);
81
+    }
82
+
83
+    public void readExternal(ObjectInput in) throws IOException,
84
+            ClassNotFoundException {
85
+        LayoutUtil.setSerializedObject(this,
86
+                LayoutUtil.readAsXML(in));
87
+    }
88
+
89
+    public void writeExternal(ObjectOutput out) throws IOException {
90
+        if (getClass() == ResizeConstraint.class) {
91
+            LayoutUtil.writeAsXML(out, this);
92
+        }
93
+    }
94
+}

+ 62
- 0
src/net/miginfocom/layout/UnitConverter.java View File

@@ -0,0 +1,62 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+/** Unit converter. */
38
+public abstract class UnitConverter {
39
+
40
+    /**
41
+     * Value to return if this converter can not handle the <code>unit</code> sent in as an argument
42
+     * to the convert method.
43
+     */
44
+    public static final int UNABLE = -87654312;
45
+
46
+    /**
47
+     * Converts <code>value</code> to pixels.
48
+     * @param value The value to be converted.
49
+     * @param unit The unit of <code>value</code>. Never <code>null</code> and at least one character.
50
+     * @param refValue Some reference value that may of may not be used. If the unit is percent for instance this value
51
+     * is the value to take the percent from. Usually the size of the parent component in the appropriate dimension.
52
+     * @param isHor If the value is horizontal (<code>true</code>) or vertical (<code>false</code>).
53
+     * @param parent The parent of the target component that <code>value</code> is to be applied to.
54
+     * Might for instance be needed to get the screen that the component is on in a multi screen environment.
55
+     * <p>
56
+     * May be <code>null</code> in which case a "best guess" value should be returned.
57
+     * @param comp The component, if applicable, or <code>null</code> if none.
58
+     * @return The number of pixels if <code>unit</code> is handled by this converter, <code>UnitConverter.UNABLE</code> if not.
59
+     */
60
+    public abstract int convertToPixels(float value, String unit, boolean isHor,
61
+            float refValue, ContainerWrapper parent, ComponentWrapper comp);
62
+}

+ 605
- 0
src/net/miginfocom/layout/UnitValue.java View File

@@ -0,0 +1,605 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.layout;
36
+
37
+import java.beans.Encoder;
38
+import java.beans.Expression;
39
+import java.beans.PersistenceDelegate;
40
+import java.io.*;
41
+import java.util.ArrayList;
42
+import java.util.HashMap;
43
+
44
+public final class UnitValue implements Serializable {
45
+
46
+    private static float dpiAdjFact = 1.0F;
47
+    private static final HashMap<String, Integer> UNIT_MAP =
48
+            new HashMap<String, Integer>(32);
49
+    private static final ArrayList<UnitConverter> CONVERTERS =
50
+            new ArrayList<UnitConverter>();
51
+    /** An operation indicating a static value. */
52
+    public static final int STATIC = 100;
53
+    /** An operation indicating a addition of two sub units. */
54
+    public static final int ADD = 101; // Must have "sub-unit values"
55
+    /** An operation indicating a subtraction of two sub units */
56
+    public static final int SUB = 102; // Must have "sub-unit values"
57
+    /** An operation indicating a multiplication of two sub units.*/
58
+    public static final int MUL = 103; // Must have "sub-unit values"
59
+    /** An operation indicating a division of two sub units.*/
60
+    public static final int DIV = 104; // Must have "sub-unit values"
61
+    /** An operation indicating the minimum of two sub units. */
62
+    public static final int MIN = 105; // Must have "sub-unit values"
63
+    /** An operation indicating the maximum of two sub units. */
64
+    public static final int MAX = 106; // Must have "sub-unit values"
65
+    /** An operation indicating the middle value of two sub units. */
66
+    public static final int MID = 107; // Must have "sub-unit values"
67
+    /** A unit indicating pixels. */
68
+    public static final int PIXEL = 0;
69
+    /** A unit indicating logical horizontal pixels. */
70
+    public static final int LPX = 1;
71
+    /** A unit indicating logical vertical pixels. */
72
+    public static final int LPY = 2;
73
+    /** A unit indicating millimeters. */
74
+    public static final int MM = 3;
75
+    /** A unit indicating centimeters. */
76
+    public static final int CM = 4;
77
+    /** A unit indicating inches. */
78
+    public static final int INCH = 5;
79
+    /** A unit indicating percent. */
80
+    public static final int PERCENT = 6;
81
+    /** A unit indicating points. */
82
+    public static final int PT = 7;
83
+    /** A unit indicating screen width in pixels. */
84
+    public static final int SPX = 8;
85
+    /** A unit indicating screen height in pixels. */
86
+    public static final int SPY = 9;
87
+    /** A unit indicating alignment. */
88
+    public static final int ALIGN = 12;
89
+    /** A unit indicating minimum size. */
90
+    public static final int MIN_SIZE = 13;
91
+    /** A unit indicating preferred size. */
92
+    public static final int PREF_SIZE = 14;
93
+    /** A unit indicating maximum size. */
94
+    public static final int MAX_SIZE = 15;
95
+    /** A unit indicating botton size. */
96
+    public static final int BUTTON = 16;
97
+    /** A unit indicating linking to x. */
98
+    public static final int LINK_X = 18; // First link
99
+    /** A unit indicating linking to y. */
100
+    public static final int LINK_Y = 19;
101
+    /** A unit indicating linking to width. */
102
+    public static final int LINK_W = 20;
103
+    /** A unit indicating linking to height. */
104
+    public static final int LINK_H = 21;
105
+    /** A unit indicating linking to x2. */
106
+    public static final int LINK_X2 = 22;
107
+    /** A unit indicating linking to y2. */
108
+    public static final int LINK_Y2 = 23;
109
+    /** A unit indicating linking to x position on screen. */
110
+    public static final int LINK_XPOS = 24;
111
+    /** A unit indicating linking to y position on screen. */
112
+    public static final int LINK_YPOS = 25; // Last link
113
+    /** A unit indicating a lookup. */
114
+    public static final int LOOKUP = 26;
115
+    /** A unit indicating label alignment. */
116
+    public static final int LABEL_ALIGN = 27;
117
+    private static final int IDENTITY = -1;
118
+    static {
119
+        UNIT_MAP.put("px", new Integer(PIXEL));
120
+        UNIT_MAP.put("lpx", new Integer(LPX));
121
+        UNIT_MAP.put("lpy", new Integer(LPY));
122
+        UNIT_MAP.put("%", new Integer(PERCENT));
123
+        UNIT_MAP.put("cm", new Integer(CM));
124
+        UNIT_MAP.put("in", new Integer(INCH));
125
+        UNIT_MAP.put("spx", new Integer(SPX));
126
+        UNIT_MAP.put("spy", new Integer(SPY));
127
+        UNIT_MAP.put("al", new Integer(ALIGN));
128
+        UNIT_MAP.put("mm", new Integer(MM));
129
+        UNIT_MAP.put("pt", new Integer(PT));
130
+        UNIT_MAP.put("min", new Integer(MIN_SIZE));
131
+        UNIT_MAP.put("minimum", new Integer(MIN_SIZE));
132
+        UNIT_MAP.put("p", new Integer(PREF_SIZE));
133
+        UNIT_MAP.put("pref", new Integer(PREF_SIZE));
134
+        UNIT_MAP.put("max", new Integer(MAX_SIZE));
135
+        UNIT_MAP.put("maximum", new Integer(MAX_SIZE));
136
+        UNIT_MAP.put("button", new Integer(BUTTON));
137
+        UNIT_MAP.put("label", new Integer(LABEL_ALIGN));
138
+    }
139
+    static final UnitValue ZERO =
140
+            new UnitValue(0, null, PIXEL, true, STATIC, null, null, "0px");
141
+    static final UnitValue TOP =
142
+            new UnitValue(0, null, PERCENT, false, STATIC, null, null, "top");
143
+    static final UnitValue LEADING =
144
+            new UnitValue(0, null, PERCENT, true, STATIC, null, null, "leading");
145
+    static final UnitValue LEFT =
146
+            new UnitValue(0, null, PERCENT, true, STATIC, null, null, "left");
147
+    static final UnitValue CENTER =
148
+            new UnitValue(50, null, PERCENT, true, STATIC, null, null, "center");
149
+    static final UnitValue TRAILING =
150
+            new UnitValue(100, null, PERCENT, true, STATIC, null, null,
151
+            "trailing");
152
+    static final UnitValue RIGHT =
153
+            new UnitValue(100, null, PERCENT, true, STATIC, null, null, "right");
154
+    static final UnitValue BOTTOM =
155
+            new UnitValue(100, null, PERCENT, false, STATIC, null, null,
156
+            "bottom");
157
+    static final UnitValue LABEL =
158
+            new UnitValue(0, null, LABEL_ALIGN, false, STATIC, null, null,
159
+            "label");
160
+    static final UnitValue INF =
161
+            new UnitValue(LayoutUtil.INF, null, PIXEL, true, STATIC, null, null,
162
+            "inf");
163
+    static final UnitValue BASELINE_IDENTITY =
164
+            new UnitValue(0, null, IDENTITY, false, STATIC, null, null,
165
+            "baseline");
166
+    private static int DEFAULT_UNIT = PIXEL;
167
+    private final transient float value;
168
+    private final transient int unit;
169
+    private final transient int oper;
170
+    private final transient String unitStr;
171
+    private final transient boolean isHor;
172
+    private final transient UnitValue[] subUnits;
173
+
174
+    // Pixel
175
+    public UnitValue(float value) {
176
+        this(value, null, PIXEL, true, STATIC, null, null, value + "px");
177
+    }
178
+
179
+    public UnitValue(float value, int unit, String createString) {
180
+        this(value, null, unit, true, STATIC, null, null, createString);
181
+    }
182
+
183
+    UnitValue(float value, String unitStr, boolean isHor, int oper,
184
+            String createString) {
185
+        this(value, unitStr, -1, isHor, oper, null, null, createString);
186
+    }
187
+
188
+    UnitValue(boolean isHor, int oper, UnitValue sub1,
189
+            UnitValue sub2, String createString) {
190
+        this(0, "", -1, isHor, oper, sub1, sub2, createString);
191
+        if (sub1 == null || sub2 == null) {
192
+            throw new IllegalArgumentException("Sub units is null!");
193
+        }
194
+    }
195
+
196
+    private UnitValue(float value, String unitStr, int unit, boolean isHor,
197
+            int oper, UnitValue sub1, UnitValue sub2,
198
+            String createString) {
199
+        if (oper < STATIC || oper > MID) {
200
+            throw new IllegalArgumentException("Unknown Operation: " + oper);
201
+        }
202
+        if (oper >= ADD && oper <= MID && (sub1 == null || sub2 == null)) {
203
+            throw new IllegalArgumentException(oper +
204
+                    " Operation may not have null sub-UnitValues.");
205
+        }
206
+        this.value = value;
207
+        this.oper = oper;
208
+        this.isHor = isHor;
209
+        this.unitStr = unitStr;
210
+        this.unit = unitStr != null ? parseUnitString() : unit;
211
+        this.subUnits =
212
+                sub1 != null && sub2 != null
213
+                ? new UnitValue[]{sub1, sub2} : null;
214
+
215
+        LayoutUtil.putCCString(this, createString); // "this" escapes!! Safe though.
216
+    }
217
+
218
+    /** Returns the size in pixels rounded.
219
+     * @param refValue The reference value. Normally the size of the parent. For unit {@link #ALIGN} the current size of the component should be sent in.
220
+     * @param parent The parent. May be <code>null</code> for testing the validity of the value, but should normally not and are not
221
+     * required to return any usable value if <code>null</code>.
222
+     * @param comp The component, if any, that the value is for. Might be <code>null</code> if the value is not
223
+     * connected to any component.
224
+     * @return The size in pixels.
225
+     */
226
+    public final int getPixels(float refValue,
227
+            ContainerWrapper parent, ComponentWrapper comp) {
228
+        return Math.round(getPixelsExact(refValue, parent, comp));
229
+    }
230
+
231
+    /** Returns the size in pixels.
232
+     * @param refValue The reference value. Normally the size of the parent. For unit {@link #ALIGN} the current size of the component should be sent in.
233
+     * @param parent The parent. May be <code>null</code> for testing the validity of the value, but should normally not and are not
234
+     * required to return any usable value if <code>null</code>.
235
+     * @param comp The component, if any, that the value is for. Might be <code>null</code> if the value is not
236
+     * connected to any component.
237
+     * @return The size in pixels.
238
+     */
239
+    public final float getPixelsExact(float refValue,
240
+            ContainerWrapper parent, ComponentWrapper comp) {
241
+        if (parent == null) {
242
+            return 1;
243
+        }
244
+        if (oper == STATIC) {
245
+            switch (unit) {
246
+                case PIXEL:
247
+                    return value;
248
+                case LPX:
249
+                case LPY:
250
+                    return parent.getPixelUnitFactor(unit == LPX) * value;
251
+                case MM:
252
+                    return dpiAdjFact *
253
+                            (isHor ? parent.getHorizontalScreenDPI()
254
+                            : parent.getVerticalScreenDPI()) * value / 25.4f;
255
+                case CM:
256
+                    return dpiAdjFact *
257
+                            (isHor ? parent.getHorizontalScreenDPI()
258
+                            : parent.getVerticalScreenDPI()) * value / 2.54f;
259
+                case INCH:
260
+                    return dpiAdjFact *
261
+                            (isHor ? parent.getHorizontalScreenDPI()
262
+                            : parent.getVerticalScreenDPI()) * value;
263
+                case PERCENT:
264
+                    return value * refValue * 0.01f;
265
+                case PT:
266
+                    return dpiAdjFact *
267
+                            (isHor ? parent.getHorizontalScreenDPI()
268
+                            : parent.getVerticalScreenDPI()) * value / 72f;
269
+                case SPX:
270
+                case SPY:
271
+                    return (unit == SPX ? parent.getScreenWidth()
272
+                            : parent.getScreenHeight()) * value * 0.01f;
273
+                case ALIGN:
274
+                    Integer st =
275
+                            LinkHandler.getValue(parent.getLayout(), "visual",
276
+                            isHor ? LinkHandler.X
277
+                            : LinkHandler.Y);
278
+                    Integer sz =
279
+                            LinkHandler.getValue(parent.getLayout(), "visual",
280
+                            isHor ? LinkHandler.WIDTH
281
+                            : LinkHandler.HEIGHT);
282
+                    if (st == null || sz == null) {
283
+                        return 0;
284
+                    }
285
+                    return value *
286
+                            (Math.max(0, sz.intValue()) - refValue) +
287
+                            st.intValue();
288
+                case MIN_SIZE:
289
+                    if (comp == null) {
290
+                        return 0;
291
+                    }
292
+                    return isHor ? comp.getMinimumWidth()
293
+                            : comp.getMinimumHeight();
294
+                case PREF_SIZE:
295
+                    if (comp == null) {
296
+                        return 0;
297
+                    }
298
+                    return isHor ? comp.getPreferredWidth()
299
+                            : comp.getPreferredHeight();
300
+                case MAX_SIZE:
301
+                    if (comp == null) {
302
+                        return 0;
303
+                    }
304
+                    return isHor ? comp.getMaximumWidth()
305
+                            : comp.getMaximumHeight();
306
+                case BUTTON:
307
+                    return PlatformDefaults.getMinimumButtonWidth().
308
+                            getPixels(refValue, parent, comp);
309
+                case LINK_X:
310
+                case LINK_Y:
311
+                case LINK_W:
312
+                case LINK_H:
313
+                case LINK_X2:
314
+                case LINK_Y2:
315
+                case LINK_XPOS:
316
+                case LINK_YPOS:
317
+                    Integer v =
318
+                            LinkHandler.getValue(parent.getLayout(),
319
+                            getLinkTargetId(),
320
+                            unit - (unit >= LINK_XPOS ? LINK_XPOS : LINK_X));
321
+                    if (v == null) {
322
+                        return 0;
323
+                    }
324
+                    if (unit == LINK_XPOS) {
325
+                        return parent.getScreenLocationX() + v.intValue();
326
+                    }
327
+                    if (unit == LINK_YPOS) {
328
+                        return parent.getScreenLocationY() + v.intValue();
329
+                    }
330
+                    return v.intValue();
331
+                case LOOKUP:
332
+                    float res = lookup(refValue, parent, comp);
333
+                    if (res != UnitConverter.UNABLE) {
334
+                        return res;
335
+                    }
336
+                    break;
337
+                case LABEL_ALIGN:
338
+                    return PlatformDefaults.getLabelAlignPercentage() * refValue;
339
+                case IDENTITY:
340
+            }
341
+            throw new IllegalArgumentException("Unknown/illegal unit: " + unit +
342
+                    ", unitStr: " + unitStr);
343
+        }
344
+
345
+        if (subUnits != null && subUnits.length == 2) {
346
+            float r1 = subUnits[0].getPixelsExact(refValue, parent, comp);
347
+            float r2 = subUnits[1].getPixelsExact(refValue, parent, comp);
348
+            switch (oper) {
349
+                case ADD:
350
+                    return r1 + r2;
351
+                case SUB:
352
+                    return r1 - r2;
353
+                case MUL:
354
+                    return r1 * r2;
355
+                case DIV:
356
+                    return r1 / r2;
357
+                case MIN:
358
+                    return r1 < r2 ? r1 : r2;
359
+                case MAX:
360
+                    return r1 > r2 ? r1 : r2;
361
+                case MID:
362
+                    return (r1 + r2) * 0.5f;
363
+            }
364
+        }
365
+
366
+        throw new IllegalArgumentException("Internal: Unknown Oper: " + oper);
367
+    }
368
+
369
+    private final float lookup(float refValue,
370
+            ContainerWrapper parent, ComponentWrapper comp) {
371
+        float res = UnitConverter.UNABLE;
372
+        for (int i = CONVERTERS.size() - 1; i >= 0;
373
+                i--) {
374
+            res =   CONVERTERS.get(i).
375
+                    convertToPixels(value, unitStr, isHor, refValue, parent,
376
+                    comp);
377
+            if (res != UnitConverter.UNABLE) {
378
+                return res;
379
+            }
380
+        }
381
+        return PlatformDefaults.convertToPixels(value, unitStr, isHor, refValue,
382
+                parent, comp);
383
+    }
384
+
385
+    private final int parseUnitString() {
386
+        int len = unitStr.length();
387
+        if (len == 0) {
388
+            return DEFAULT_UNIT;
389
+        }
390
+        Integer u = UNIT_MAP.get(unitStr);
391
+        if (u != null) {
392
+            return u.intValue();
393
+        }
394
+        if (unitStr.equals("lp")) {
395
+            return isHor ? LPX : LPY;
396
+        }
397
+        if (unitStr.equals("sp")) {
398
+            return isHor ? SPX : SPY;
399
+        }
400
+        if (lookup(0, null, null) != UnitConverter.UNABLE) {
401
+            // To test so we can fail fast
402
+            return LOOKUP;
403
+        }
404
+        if (unitStr.endsWith(".x")) {
405
+            return LINK_X;
406
+        }
407
+        if (unitStr.endsWith(".y")) {
408
+            return LINK_Y;
409
+        }
410
+        if (unitStr.endsWith(".w")) {
411
+            return LINK_W;
412
+        }
413
+        if (unitStr.endsWith(".h")) {
414
+            return LINK_H;
415
+        }
416
+        if (unitStr.endsWith(".x2")) {
417
+            return LINK_X2;
418
+        }
419
+        if (unitStr.endsWith(".y2")) {
420
+            return LINK_Y2;
421
+        }
422
+        if (unitStr.endsWith(".xpos")) {
423
+            return LINK_XPOS;
424
+        }
425
+        if (unitStr.endsWith(".ypos")) {
426
+            return LINK_YPOS;
427
+        }
428
+        throw new IllegalArgumentException("Unknown keyword: " + unitStr);
429
+    }
430
+
431
+    final boolean isLinked() {
432
+        return unit >= LINK_X && unit <= LINK_YPOS;
433
+    }
434
+
435
+    final boolean isLinkedDeep() {
436
+        if (subUnits == null) {
437
+            return isLinked();
438
+        }
439
+        for (int i = 0; i < subUnits.length;
440
+                i++) {
441
+            if (subUnits[i].isLinkedDeep()) {
442
+                return true;
443
+            }
444
+        }
445
+
446
+        return false;
447
+    }
448
+
449
+    final String getLinkTargetId() {
450
+        return unitStr.substring(0,
451
+                unitStr.length() -
452
+                (unit < LINK_X2 ? 2 : (unit > LINK_Y2 ? 5 : 3)));
453
+    }
454
+
455
+    final UnitValue getSubUnitValue(int i) {
456
+        return subUnits[i];
457
+    }
458
+
459
+    final int getSubUnitCount() {
460
+        return subUnits != null ? subUnits.length : 0;
461
+    }
462
+
463
+    public final UnitValue[] getSubUnits() {
464
+        return subUnits;
465
+    }
466
+
467
+    public final int getUnit() {
468
+        return unit;
469
+    }
470
+
471
+    public final String getUnitString() {
472
+        return unitStr;
473
+    }
474
+
475
+    public final int getOperation() {
476
+        return oper;
477
+    }
478
+
479
+    public final float getValue() {
480
+        return value;
481
+    }
482
+
483
+    public final boolean isHorizontal() {
484
+        return isHor;
485
+    }
486
+
487
+    public final String toString() {
488
+        return getClass().getName() + ". Value=" + value + ", unit=" + unit +
489
+                ", unitString: " + unitStr + ", oper=" + oper + ", isHor: " +
490
+                isHor;
491
+    }
492
+
493
+    /** Returns the creation string for this object. Note that {@link LayoutUtil#setDesignTime(ContainerWrapper, boolean)} must be
494
+     * set to <code>true</code> for the creation strings to be stored.
495
+     * @return The constraint string or <code>null</code> if none is registered.
496
+     */
497
+    public final String getConstraintString() {
498
+        return LayoutUtil.getCCString(this);
499
+    }
500
+
501
+    public final int hashCode() {
502
+        return (int) (value * 12345) + (oper >>> 5) + unit >>> 17;
503
+    }
504
+
505
+    /** Adds a global unit converter that can convert from some <code>unit</code> to pixels.
506
+     * <p>
507
+     * This converter will be asked before the platform converter so the values for it (e.g. "related" and "unrelated")
508
+     * can be overridden. It is however not possible to override the built in ones (e.g. "mm", "pixel" or "lp").
509
+     * @param conv The converter. Not <code>null</code>.
510
+     */
511
+    public static final synchronized void addGlobalUnitConverter(UnitConverter conv) {
512
+        if (conv == null) {
513
+            throw new NullPointerException();
514
+        }
515
+        CONVERTERS.add(conv);
516
+    }
517
+
518
+    /** Removed the converter.
519
+     * @param unit The converter.
520
+     * @return If there was a converter found and thus removed.
521
+     */
522
+    public static final synchronized boolean removeGlobalUnitConverter(String unit) {
523
+        return CONVERTERS.remove(unit);
524
+    }
525
+
526
+    /** Returns the global converters currently registered. The platform converter will not be in this list.
527
+     * @return The converters. Never <code>null</code>.
528
+     */
529
+    public static final synchronized UnitConverter[] getGlobalUnitConverters() {
530
+        return CONVERTERS.toArray(new UnitConverter[CONVERTERS.size()]);
531
+    }
532
+
533
+    /** Returns the DPI (dots per inch) factor.
534
+     * @return The DPI (dots per inch) factor. Default is 1.0f.
535
+     * @see #setScreenDPIAdjustmentFactor(float).
536
+     */
537
+    public static final float getScreenDPIAdjustmentFactor() {
538
+        return dpiAdjFact;
539
+    }
540
+
541
+    /** Sets a number that will be multiplied to all units of types "cm" (Centimeter), "mm" (millimeter), "dot" and "inch". This
542
+     * is for compensating for screens that have the wrong actualy dpi (dots-per-inch) set in the operating system, as for instance the
543
+     * laptop screens with a resolution on 1920x1200. They normally get 96 dpi in Windows, even though they are closer
544
+     * to 120dpi.
545
+     * @param f Will be multipled to the DPI, so somewhere around 1.0f.
546
+     */
547
+    public static final void setScreenDPIAdjustmentFactor(float f) {
548
+        dpiAdjFact = f;
549
+    }
550
+
551
+    /** Returns the current default unit. The default unit is the unit used if no unit is set. E.g. "width 10".
552
+     * @return The current default unit.
553
+     */
554
+    public static final int getDefaultUnit() {
555
+        return DEFAULT_UNIT;
556
+    }
557
+
558
+    /** Sets the default unit. The default unit is the unit used if no unit is set. E.g. "width 10".
559
+     * @param unit The new default unit.
560
+     */
561
+    public static final void setDefaultUnit(int unit) {
562
+        if (unit < PIXEL || unit > LABEL_ALIGN) {
563
+            throw new IllegalArgumentException("Illegal Unit: " + unit);
564
+        }
565
+        DEFAULT_UNIT = unit;
566
+    }
567
+    static {
568
+        LayoutUtil.setDelegate(UnitValue.class,
569
+                new PersistenceDelegate() {
570
+
571
+            protected Expression instantiate(Object oldInstance,
572
+                    Encoder out) {
573
+                UnitValue uv = (UnitValue) oldInstance;
574
+                String cs = uv.getConstraintString();
575
+                if (cs == null) {
576
+                    throw new IllegalStateException("Design time must be on to use XML persistence. See LayoutUtil.");
577
+                }
578
+                return new Expression(oldInstance,
579
+                        ConstraintParser.class, "parseUnitValueOrAlign",
580
+                        new Object[]{uv.getConstraintString(),
581
+                        uv.isHorizontal() ? Boolean.TRUE : Boolean.FALSE, null});
582
+            }
583
+        });
584
+    }
585
+    // ************************************************
586
+    // Persistence Delegate and Serializable combined.
587
+    // ************************************************
588
+    private static final long serialVersionUID = 1L;
589
+
590
+    private Object readResolve() throws ObjectStreamException {
591
+        return LayoutUtil.getSerializedObject(this);
592
+    }
593
+
594
+    private void writeObject(ObjectOutputStream out) throws IOException {
595
+        if (getClass() == UnitValue.class) {
596
+            LayoutUtil.writeAsXML(out, this);
597
+        }
598
+    }
599
+
600
+    private void readObject(ObjectInputStream in) throws IOException,
601
+            ClassNotFoundException {
602
+        LayoutUtil.setSerializedObject(this,
603
+                LayoutUtil.readAsXML(in));
604
+    }
605
+}

+ 540
- 0
src/net/miginfocom/swing/MigLayout.java View File

@@ -0,0 +1,540 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.swing;
36
+
37
+import net.miginfocom.layout.*;
38
+import javax.swing.*;
39
+import java.awt.*;
40
+import java.awt.event.ActionEvent;
41
+import java.awt.event.ActionListener;
42
+import java.io.*;
43
+import java.util.*;
44
+
45
+/** A very flexbile layout manager.
46
+ * <p>
47
+ * Read the documentation that came with this layout manager for information on usage.
48
+ */
49
+public final class MigLayout implements LayoutManager2, Externalizable {
50
+
51
+    /**
52
+     * A version number for this class. It should be changed whenever the class
53
+     * structure is changed (or anything else that would prevent serialized
54
+     * objects being unserialized with the new class).
55
+     */
56
+    private static final long serialVersionUID = 1;
57
+    // ******** Instance part ********
58
+    /** The component to string constraints mappings.
59
+     */
60
+    private final Map<Component, Object> scrConstrMap =
61
+            new IdentityHashMap<Component, Object>(8);
62
+    /** Hold the serializable text representation of the constraints.
63
+     */
64
+    private Object layoutConstraints = "";
65
+    private Object colConstraints = "";
66
+    private Object rowConstraints = ""; // Should never be null!
67
+    // ******** Transient part ********
68
+    private transient ContainerWrapper cacheParentW = null;
69
+    private final transient Map<ComponentWrapper, CC> ccMap =
70
+            new HashMap<ComponentWrapper, CC>(8);
71
+    private transient javax.swing.Timer debugTimer = null;
72
+    private transient LC lc = null;
73
+    private transient AC colSpecs = null;
74
+    private transient AC rowSpecs = null;
75
+    private transient Grid grid = null;
76
+    private transient int lastModCount =
77
+            PlatformDefaults.getModCount();
78
+    private transient int lastHash = -1;
79
+    private transient Dimension lastInvalidSize = null;
80
+    private transient ArrayList<LayoutCallback> callbackList = null;
81
+
82
+    /** Constructor with no constraints.
83
+     */
84
+    public MigLayout() {
85
+        this("", "", "");
86
+    }
87
+
88
+    /** Constructor.
89
+     * @param layoutConstraints The constraints that concern the whole layout. <code>null</code> will be treated as "".
90
+     */
91
+    public MigLayout(String layoutConstraints) {
92
+        this(layoutConstraints, "", "");
93
+    }
94
+
95
+    /** Constructor.
96
+     * @param layoutConstraints The constraints that concern the whole layout. <code>null</code> will be treated as "".
97
+     * @param colConstraints The constraints for the columns in the grid. <code>null</code> will be treated as "".
98
+     */
99
+    public MigLayout(String layoutConstraints, String colConstraints) {
100
+        this(layoutConstraints, colConstraints, "");
101
+    }
102
+
103
+    /** Constructor.
104
+     * @param layoutConstraints The constraints that concern the whole layout. <code>null</code> will be treated as "".
105
+     * @param colConstraints The constraints for the columns in the grid. <code>null</code> will be treated as "".
106
+     * @param rowConstraints The constraints for the rows in the grid. <code>null</code> will be treated as "".
107
+     */
108
+    public MigLayout(String layoutConstraints, String colConstraints,
109
+            String rowConstraints) {
110
+        setLayoutConstraints(layoutConstraints);
111
+        setColumnConstraints(colConstraints);
112
+        setRowConstraints(rowConstraints);
113
+    }
114
+
115
+    /** Constructor.
116
+     * @param layoutConstraints The constraints that concern the whole layout. <code>null</code> will be treated as an empty cosntraint.
117
+     */
118
+    public MigLayout(LC layoutConstraints) {
119
+        this(layoutConstraints, null, null);
120
+    }
121
+
122
+    /** Constructor.
123
+     * @param layoutConstraints The constraints that concern the whole layout. <code>null</code> will be treated as an empty cosntraint.
124
+     * @param colConstraints The constraints for the columns in the grid. <code>null</code> will be treated as an empty constraint.
125
+     */
126
+    public MigLayout(LC layoutConstraints,
127
+            AC colConstraints) {
128
+        this(layoutConstraints, colConstraints, null);
129
+    }
130
+
131
+    /** Constructor.
132
+     * @param layoutConstraints The constraints that concern the whole layout. <code>null</code> will be treated as an empty cosntraint.
133
+     * @param colConstraints The constraints for the columns in the grid. <code>null</code> will be treated as an empty constraint.
134
+     * @param rowConstraints The constraints for the rows in the grid. <code>null</code> will be treated as an empty constraint.
135
+     */
136
+    public MigLayout(LC layoutConstraints,
137
+            AC colConstraints, AC rowConstraints) {
138
+        setLayoutConstraints(layoutConstraints);
139
+        setColumnConstraints(colConstraints);
140
+        setRowConstraints(rowConstraints);
141
+    }
142
+
143
+    /** Returns layout constraints eighter as a <code>String</code> or {@link net.miginfocom.layout.LC} depending what was sent in
144
+     * to the constructor or set with {@link #setLayoutConstraints(Object)}.
145
+     * @return The layout constraints eighter as a <code>String</code> or {@link net.miginfocom.layout.LC} depending what was sent in
146
+     * to the constructor or set with {@link #setLayoutConstraints(Object)}. Never <code>null</code>.
147
+     */
148
+    public Object getLayoutConstraints() {
149
+        return layoutConstraints;
150
+    }
151
+
152
+    /** Sets the layout constraints for the layout manager instance as a String.
153
+     * <p>
154
+     * See the class JavaDocs for information on how this string is formatted.
155
+     * @param constr The layout constraints as a String representation. <code>null</code> is converted to <code>""</code> for storage.
156
+     * @throws RuntimeException if the constaint was not valid.
157
+     */
158
+    public void setLayoutConstraints(Object constr) {
159
+        if (constr == null || constr instanceof String) {
160
+            constr =ConstraintParser.prepare((String) constr);
161
+            lc =    ConstraintParser.parseLayoutConstraint((String) constr);
162
+        } else if (constr instanceof LC) {
163
+            lc = (LC) constr;
164
+        } else {
165
+            throw new IllegalArgumentException("Illegal constraint type: " +
166
+                    constr.getClass().toString());
167
+        }
168
+        layoutConstraints = constr;
169
+        grid = null;
170
+    }
171
+
172
+    /** Returns the column layout constraints either as a <code>String</code> or {@link net.miginfocom.layout.AC}.
173
+     * @return The column constraints eighter as a <code>String</code> or {@link net.miginfocom.layout.LC} depending what was sent in
174
+     * to the constructor or set with {@link #setLayoutConstraints(Object)}. Never <code>null</code>.
175
+     */
176
+    public Object getColumnConstraints() {
177
+        return colConstraints;
178
+    }
179
+
180
+    /** Sets the column layout constraints for the layout manager instance as a String.
181
+     * <p>
182
+     * See the class JavaDocs for information on how this string is formatted.
183
+     * @param constr The column layout constraints as a String representation. <code>null</code> is converted to <code>""</code> for storage.
184
+     * @throws RuntimeException if the constaint was not valid.
185
+     */
186
+    public void setColumnConstraints(Object constr) {
187
+        if (constr == null || constr instanceof String) {
188
+            constr =ConstraintParser.prepare((String) constr);
189
+            colSpecs =
190
+                    ConstraintParser.parseColumnConstraints((String) constr);
191
+        } else if (constr instanceof AC) {
192
+            colSpecs = (AC) constr;
193
+        } else {
194
+            throw new IllegalArgumentException("Illegal constraint type: " +
195
+                    constr.getClass().toString());
196
+        }
197
+        colConstraints = constr;
198
+        grid = null;
199
+    }
200
+
201
+    /** Returns the row layout constraints as a String representation. This string is the exact string as set with {@link #setRowConstraints(Object)}
202
+     * or sent into the constructor.
203
+     * <p>
204
+     * See the class JavaDocs for information on how this string is formatted.
205
+     * @return The row layout constraints as a String representation. Never <code>null</code>.
206
+     */
207
+    public Object getRowConstraints() {
208
+        return rowConstraints;
209
+    }
210
+
211
+    /** Sets the row layout constraints for the layout manager instance as a String.
212
+     * <p>
213
+     * See the class JavaDocs for information on how this string is formatted.
214
+     * @param constr The row layout constraints as a String representation. <code>null</code> is converted to <code>""</code> for storage.
215
+     * @throws RuntimeException if the constaint was not valid.
216
+     */
217
+    public void setRowConstraints(Object constr) {
218
+        if (constr == null || constr instanceof String) {
219
+            constr =ConstraintParser.prepare((String) constr);
220
+            rowSpecs =
221
+                    ConstraintParser.parseRowConstraints((String) constr);
222
+        } else if (constr instanceof AC) {
223
+            rowSpecs = (AC) constr;
224
+        } else {
225
+            throw new IllegalArgumentException("Illegal constraint type: " +
226
+                    constr.getClass().toString());
227
+        }
228
+        rowConstraints = constr;
229
+        grid = null;
230
+    }
231
+
232
+    /** Returns the component constraints as a String representation. This string is the exact string as set with {@link #setComponentConstraints(java.awt.Component, Object)}
233
+     * or set when adding the component to the parent component.
234
+     * <p>
235
+     * See the class JavaDocs for information on how this string is formatted.
236
+     * @param comp The component to return the constraints for.
237
+     * @return The component constraints as a String representation ir <code>null</code> if the component is not registered
238
+     * with this layout manager. The returned values is either a String or a {@link net.miginfocom.layout.CC}
239
+     * depending on what constraint was sent in when the component was added. May be <code>null</code>.
240
+     */
241
+    public Object getComponentConstraints(Component comp) {
242
+        synchronized (comp.getParent().getTreeLock()) {
243
+            return scrConstrMap.get(comp);
244
+        }
245
+    }
246
+
247
+    /** Sets the component constraint for the component that already must be handleded by this layout manager.
248
+     * <p>
249
+     * See the class JavaDocs for information on how this string is formatted.
250
+     * @param constr The component constraints as a String or {@link net.miginfocom.layout.CC}. <code>null</code> is ok.
251
+     * @param comp The component to set the constraints for.
252
+     * @throws RuntimeException if the constaint was not valid.
253
+     * @throws IllegalArgumentException If the component is not handlering the component.
254
+     */
255
+    public void setComponentConstraints(Component comp, Object constr) {
256
+        setComponentConstraintsImpl(comp, constr, false);
257
+    }
258
+
259
+    /** Sets the component constraint for the component that already must be handleded by this layout manager.
260
+     * <p>
261
+     * See the class JavaDocs for information on how this string is formatted.
262
+     * @param constr The component constraints as a String or {@link net.miginfocom.layout.CC}. <code>null</code> is ok.
263
+     * @param comp The component to set the constraints for.
264
+     * @throws RuntimeException if the constaint was not valid.
265
+     * @throws IllegalArgumentException If the component is not handling the component.
266
+     */
267
+    private void setComponentConstraintsImpl(Component comp,
268
+            Object constr, boolean noCheck) {
269
+        Container parent = comp.getParent();
270
+        synchronized (parent.getTreeLock()) {
271
+            if (noCheck == false && scrConstrMap.containsKey(comp) == false) {
272
+                throw new IllegalArgumentException("Component must already be added to parent!");
273
+            }
274
+            ComponentWrapper cw =
275
+                    new SwingComponentWrapper(comp);
276
+
277
+            if (constr == null || constr instanceof String) {
278
+                String cStr =
279
+                        ConstraintParser.prepare((String) constr);
280
+
281
+                scrConstrMap.put(comp, constr);
282
+                ccMap.put(cw,
283
+                        ConstraintParser.parseComponentConstraint(cStr));
284
+            } else if (constr instanceof CC) {
285
+
286
+                scrConstrMap.put(comp, constr);
287
+                ccMap.put(cw, (CC) constr);
288
+            } else {
289
+                throw new IllegalArgumentException("Constraint must be String or ComponentConstraint: " +
290
+                        constr.getClass().toString());
291
+            }
292
+
293
+            grid = null;
294
+        }
295
+    }
296
+
297
+    /** Returns if this layout manager is currently managing this component.
298
+     * @param c The component to check. If <code>null</code> then <code>false</code> will be returned.
299
+     * @return If this layout manager is currently managing this component.
300
+     */
301
+    public boolean isManagingComponent(Component c) {
302
+        return scrConstrMap.containsKey(c);
303
+    }
304
+
305
+    /** Adds the callback function that will be called at different stages of the layout cylce.
306
+     * @param callback The callback. Not <code>null</code>.
307
+     */
308
+    public void addLayoutCallback(LayoutCallback callback) {
309
+        if (callback == null) {
310
+            throw new NullPointerException();
311
+        }
312
+        if (callbackList == null) {
313
+            callbackList =
314
+                    new ArrayList<LayoutCallback>(1);
315
+        }
316
+        callbackList.add(callback);
317
+    }
318
+
319
+    /** Removes the callback if it exists.
320
+     * @param callback The callback. May be <code>null</code>.
321
+     */
322
+    public void removeLayoutCallback(LayoutCallback callback) {
323
+        if (callbackList != null) {
324
+            callbackList.remove(callback);
325
+        }
326
+    }
327
+
328
+    /** Sets the debugging state for this layout manager instance. If debug is turned on a timer will repaint the last laid out parent
329
+     * with debug information on top.
330
+     * <p>
331
+     * Red fill and dashed darked red outline is used to indicate occupied cells in the grid. Blue dashed outline indicate indicate
332
+     * component bounds set.
333
+     * <p>
334
+     * Note that debug can also be set on the layout constraints. There it will be persisted. The calue set here will not. See the class
335
+     * JavaDocs for information.
336
+     * @param b <code>true</code> means debug is turned on.
337
+     */
338
+    private synchronized void setDebug(final ComponentWrapper parentW, boolean b) {
339
+        if (b &&(debugTimer == null ||
340
+                debugTimer.getDelay() != lc.getDebugMillis())) {
341
+            if (debugTimer != null) {
342
+                debugTimer.stop();
343
+            }
344
+            final Component parent =
345
+                    (Component) parentW.getParent().getComponent();
346
+
347
+            debugTimer =
348
+                    new javax.swing.Timer(lc.getDebugMillis(),
349
+                    new ActionListener() {
350
+
351
+                public void actionPerformed(ActionEvent e) {
352
+                    if (grid != null) {
353
+                        grid.paintDebug();
354
+                    }
355
+                }
356
+            });
357
+
358
+            if (parent != null) {
359
+                SwingUtilities.invokeLater(new Runnable() {
360
+
361
+                    public void run() {
362
+                        Container p = parent.getParent();
363
+                        if (p != null) {
364
+                            if (p instanceof JComponent) {
365
+                                ((JComponent) p).revalidate();
366
+                            } else {
367
+                                parent.invalidate();
368
+                                p.validate();
369
+                            }
370
+                        }
371
+                    }
372
+                });
373
+            }
374
+
375
+            debugTimer.setInitialDelay(100);
376
+            debugTimer.start();
377
+        } else if (!b && debugTimer != null) {
378
+            debugTimer.stop();
379
+            debugTimer = null;
380
+        }
381
+    }
382
+
383
+    /** Returns the current debugging state.
384
+     * @return The current debugging state.
385
+     */
386
+    private boolean getDebug() {
387
+        return debugTimer != null;
388
+    }
389
+
390
+    /** Check if something has changed and if so recrete it to the cached objects.
391
+     * @param parent The parent that is the target for this layout manager.
392
+     */
393
+    private final void checkCache(Container parent) {
394
+        if (parent == null) {
395
+            return;
396
+        }
397
+        ContainerWrapper par = checkParent(parent);
398
+
399
+        // Check if the grid is valid
400
+        int mc = PlatformDefaults.getModCount();
401
+        if (lastModCount != mc) {
402
+            grid = null;
403
+            lastModCount = mc;
404
+        }
405
+
406
+        int hash = 0;
407
+        for (Iterator<ComponentWrapper> it = ccMap.keySet().iterator();
408
+                it.hasNext();) {
409
+            hash += it.next().getLayoutHashCode();
410
+        }
411
+        if (hash != lastHash) {
412
+            grid = null;
413
+            lastHash = hash;
414
+        }
415
+
416
+        if (parent.isValid() == false) {
417
+            Dimension ps = parent.getSize();
418
+            if (lastInvalidSize == null || !lastInvalidSize.equals(ps)) {
419
+                grid = null;
420
+                lastInvalidSize = ps;
421
+            }
422
+        }
423
+
424
+        setDebug(par, lc.getDebugMillis() > 0);
425
+
426
+        if (grid == null) {
427
+            grid =  new Grid(par, lc, rowSpecs, colSpecs, ccMap, callbackList);
428
+        }
429
+    }
430
+
431
+    private final ContainerWrapper checkParent(Container parent) {
432
+        if (parent == null) {
433
+            return null;
434
+        }
435
+        if (cacheParentW == null || cacheParentW.getComponent() != parent) {
436
+            cacheParentW = new SwingContainerWrapper(parent);
437
+        }
438
+        return cacheParentW;
439
+    }
440
+
441
+    public void layoutContainer(Container parent) {
442
+        synchronized (parent.getTreeLock()) {
443
+            checkCache(parent);
444
+
445
+            Insets i = parent.getInsets();
446
+            int[] b =
447
+                    new int[]{i.left, i.top,
448
+                    parent.getWidth() - i.left - i.right,
449
+                    parent.getHeight() - i.top - i.bottom};
450
+
451
+            grid.layout(b, lc.getAlignX(), lc.getAlignY(), getDebug(), false);
452
+
453
+            lastInvalidSize = null;
454
+        }
455
+    }
456
+
457
+    public Dimension minimumLayoutSize(Container parent) {
458
+        synchronized (parent.getTreeLock()) {
459
+            return getSizeImpl(parent, LayoutUtil.MIN);
460
+        }
461
+    }
462
+
463
+    public Dimension preferredLayoutSize(Container parent) {
464
+        synchronized (parent.getTreeLock()) {
465
+            return getSizeImpl(parent, LayoutUtil.PREF);
466
+        }
467
+    }
468
+
469
+    public Dimension maximumLayoutSize(Container parent) {
470
+        return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
471
+    }
472
+
473
+    // Implementation method that does the job.
474
+    private Dimension getSizeImpl(Container parent, int sizeType) {
475
+        checkCache(parent);
476
+
477
+        Insets i = parent.getInsets();
478
+
479
+        int w = LayoutUtil.getSizeSafe(grid != null ? grid.getWidth() : null,
480
+                sizeType) + i.left + i.right;
481
+        int h = LayoutUtil.getSizeSafe(grid != null ? grid.getHeight() : null,
482
+                sizeType) + i.top + i.bottom;
483
+
484
+        return new Dimension(w, h);
485
+    }
486
+
487
+    public float getLayoutAlignmentX(Container parent) {
488
+        return lc != null && lc.getAlignX() != null
489
+                ? lc.getAlignX().getPixels(1, checkParent(parent), null) : 0;
490
+    }
491
+
492
+    public float getLayoutAlignmentY(Container parent) {
493
+        return lc != null && lc.getAlignY() != null
494
+                ? lc.getAlignY().getPixels(1, checkParent(parent), null) : 0;
495
+    }
496
+
497
+    public void addLayoutComponent(String s, Component comp) {
498
+        addLayoutComponent(comp, s);
499
+    }
500
+
501
+    public void addLayoutComponent(Component comp, Object constraints) {
502
+        synchronized (comp.getParent().getTreeLock()) {
503
+            setComponentConstraintsImpl(comp, constraints, true);
504
+        }
505
+    }
506
+
507
+    public void removeLayoutComponent(Component comp) {
508
+        synchronized (comp.getParent().getTreeLock()) {
509
+            scrConstrMap.remove(comp);
510
+            ccMap.remove(new SwingComponentWrapper(comp));
511
+        }
512
+    }
513
+
514
+    public void invalidateLayout(Container target) {
515
+        if (lc.isNoCache()) {
516
+            grid = null;
517
+
518
+            // the validity of components is maintained automatically.
519
+        }
520
+    }
521
+    // ************************************************
522
+    // Persistence Delegate and Serializable combined.
523
+    // ************************************************
524
+
525
+    private Object readResolve() throws ObjectStreamException {
526
+        return LayoutUtil.getSerializedObject(this);
527
+    }
528
+
529
+    public void readExternal(ObjectInput in) throws IOException,
530
+            ClassNotFoundException {
531
+        LayoutUtil.setSerializedObject(this,
532
+                LayoutUtil.readAsXML(in));
533
+    }
534
+
535
+    public void writeExternal(ObjectOutput out) throws IOException {
536
+        if (getClass() == MigLayout.class) {
537
+            LayoutUtil.writeAsXML(out, this);
538
+        }
539
+    }
540
+}

+ 379
- 0
src/net/miginfocom/swing/SwingComponentWrapper.java View File

@@ -0,0 +1,379 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.swing;
36
+
37
+import net.miginfocom.layout.ComponentWrapper;
38
+import net.miginfocom.layout.ContainerWrapper;
39
+import javax.swing.*;
40
+import javax.swing.text.JTextComponent;
41
+import java.awt.*;
42
+import java.awt.geom.Rectangle2D;
43
+import java.lang.reflect.Method;
44
+import java.util.IdentityHashMap;
45
+
46
+/** Swing component wrapper. */
47
+public class SwingComponentWrapper implements ComponentWrapper {
48
+
49
+    private static boolean maxSet = false;
50
+    private static boolean vp = true;
51
+    /** Debug color for component bounds outline. */
52
+    private static final Color DB_COMP_OUTLINE = new Color(0, 0, 200);
53
+    private final Component c;
54
+    private int compType = TYPE_UNSET;
55
+
56
+    public SwingComponentWrapper(Component c) {
57
+        this.c = c;
58
+    }
59
+
60
+    public final int getBaseline(int width, int height) {
61
+        if (BL_METHOD == null) {
62
+            return -1;
63
+        }
64
+        try {
65
+            Object[] args =
66
+                    new Object[]{new Integer(c.getWidth()), new Integer(height)};
67
+            return ((Integer) BL_METHOD.invoke(c, args)).intValue();
68
+        } catch (Exception e) {
69
+            return -1;
70
+        }
71
+    }
72
+
73
+    public final Object getComponent() {
74
+        return c;
75
+    }
76
+    /** Cache.
77
+     */
78
+    private static final IdentityHashMap<FontMetrics, Point.Float> FM_MAP =
79
+            new IdentityHashMap<FontMetrics, Point.Float>(4);
80
+    private static final Font SUBST_FONT =
81
+            new Font("sansserif", Font.PLAIN, 11);
82
+
83
+    public final float getPixelUnitFactor(boolean isHor) {
84
+        Font font = c.getFont();
85
+        FontMetrics fm = c.getFontMetrics(font != null ? font : SUBST_FONT);
86
+        Point.Float p = FM_MAP.get(fm);
87
+        if (p == null) {
88
+            Rectangle2D r = fm.getStringBounds("X", c.getGraphics());
89
+            p =     new Point.Float(((float) r.getWidth()) / 6f,
90
+                    ((float) r.getHeight()) / 13.27734375f);
91
+            FM_MAP.put(fm, p);
92
+        }
93
+        return isHor ? p.x : p.y;
94
+    }
95
+//	/** Cache.
96
+//	 */
97
+//	private final static IdentityHashMap<FontMetrics, Point.Float> FM_MAP2 = new IdentityHashMap<FontMetrics, Point.Float>(4);
98
+//	private final static Font SUBST_FONT2 = new Font("sansserif", Font.PLAIN, 11);
99
+//
100
+//	public float getDialogUnit(boolean isHor)
101
+//	{
102
+//		Font font = c.getFont();
103
+//		FontMetrics fm = c.getFontMetrics(font != null ? font : SUBST_FONT2);
104
+//		Point.Float dluP = FM_MAP2.get(fm);
105
+//		if (dluP == null) {
106
+//			float w = fm.charWidth('X') / 4f;
107
+//			int ascent = fm.getAscent();
108
+//			float h = (ascent > 14 ? ascent : ascent + (15 - ascent) / 3) / 8f;
109
+//
110
+//			dluP = new Point.Float(w, h);
111
+//			FM_MAP2.put(fm, dluP);
112
+//		}
113
+//		return isHor ? dluP.x : dluP.y;
114
+//	}
115
+
116
+    public final int getX() {
117
+        return c.getX();
118
+    }
119
+
120
+    public final int getY() {
121
+        return c.getY();
122
+    }
123
+
124
+    public final int getHeight() {
125
+        return c.getHeight();
126
+    }
127
+
128
+    public final int getWidth() {
129
+        return c.getWidth();
130
+    }
131
+
132
+    public final int getScreenLocationX() {
133
+        Point p = new Point();
134
+        SwingUtilities.convertPointToScreen(p, c);
135
+        return p.x;
136
+    }
137
+
138
+    public final int getScreenLocationY() {
139
+        Point p = new Point();
140
+        SwingUtilities.convertPointToScreen(p, c);
141
+        return p.y;
142
+    }
143
+
144
+    public final int getMinimumHeight() {
145
+        c.getPreferredSize();
146
+//		if (min == null) {
147
+//			getPreferredHeight();   // To defeat a bug where the minimum size is difference before and after the first call to getPreferredSize();
148
+//			min = ;
149
+//		}
150
+        return c.getMinimumSize().height;
151
+    }
152
+
153
+    public final int getMinimumWidth() {
154
+        c.getPreferredSize();
155
+//		if (min == null) {
156
+//			getPreferredWidth();   // To defeat a bug where the minimum size is difference before and after the first call to getPreferredSize();
157
+//			min = ;
158
+//		}
159
+        return c.getMinimumSize().width;
160
+    }
161
+
162
+    public final int getPreferredHeight() {
163
+        return c.getPreferredSize().height;
164
+    }
165
+
166
+    public final int getPreferredWidth() {
167
+        return c.getPreferredSize().width;
168
+    }
169
+
170
+    public final int getMaximumHeight() {
171
+        if (!isMaxSet(c)) {
172
+            return Short.MAX_VALUE;
173
+        }
174
+        return c.getMaximumSize().height;
175
+    }
176
+
177
+    public final int getMaximumWidth() {
178
+        if (!isMaxSet(c)) {
179
+            return Short.MAX_VALUE;
180
+        }
181
+        return c.getMaximumSize().width;
182
+    }
183
+
184
+    private boolean isMaxSet(Component c) {
185
+        if (IMS_METHOD != null) {
186
+            try {
187
+                return (Boolean) IMS_METHOD.invoke(c, (Object) null);
188
+            } catch (Exception e) {
189
+                IMS_METHOD = null; // So we do not try every time.
190
+            }
191
+        }
192
+        return isMaxSizeSetOn1_4();
193
+    }
194
+
195
+    public final ContainerWrapper getParent() {
196
+        return new SwingContainerWrapper(c.getParent());
197
+    }
198
+
199
+    public final int getHorizontalScreenDPI() {
200
+        return c.getToolkit().getScreenResolution();
201
+    }
202
+
203
+    public final int getVerticalScreenDPI() {
204
+        return c.getToolkit().getScreenResolution();
205
+    }
206
+
207
+    public final int getScreenWidth() {
208
+        return c.getToolkit().getScreenSize().width;
209
+    }
210
+
211
+    public final int getScreenHeight() {
212
+        return c.getToolkit().getScreenSize().height;
213
+    }
214
+
215
+    public final boolean hasBaseline() {
216
+        return getBaseline(10, 10) != -1;
217
+    }
218
+
219
+    public final String getLinkId() {
220
+        return c.getName();
221
+    }
222
+
223
+    public final void setBounds(int x, int y, int width, int height) {
224
+        c.setBounds(x, y, width, height);
225
+    }
226
+
227
+    public boolean isVisible() {
228
+        return c.isVisible();
229
+    }
230
+
231
+    public final int[] getVisualPadding() {
232
+        if (vp && c instanceof JTabbedPane) {
233
+//			if (((JTabbedPane) c).getUI().getClass().getName().equals("com.sun.java.swing.plaf.windows.WindowsTabbedPaneUI"))
234
+            if (UIManager.getLookAndFeel().getClass().getName().
235
+                    endsWith("WindowsLookAndFeel")) {
236
+                return new int[]{-1, 0, 2, 2};
237
+            }
238
+        }
239
+        return null;
240
+    }
241
+
242
+    public static boolean isMaxSizeSetOn1_4() {
243
+        return maxSet;
244
+    }
245
+
246
+    public static void setMaxSizeSetOn1_4(boolean b) {
247
+        maxSet = b;
248
+    }
249
+
250
+    public static final boolean isVisualPaddingEnabled() {
251
+        return vp;
252
+    }
253
+
254
+    public static final void setVisualPaddingEnabled(boolean b) {
255
+        vp = b;
256
+    }
257
+
258
+    public final void paintDebugOutline() {
259
+        if (c.isShowing() == false) {
260
+            return;
261
+        }
262
+        Graphics2D g = (Graphics2D) c.getGraphics();
263
+        if (g == null) {
264
+            return;
265
+        }
266
+        g.setPaint(DB_COMP_OUTLINE);
267
+        g.setStroke(new BasicStroke(1f, BasicStroke.CAP_SQUARE,
268
+                BasicStroke.JOIN_MITER, 10f, new float[]{2f, 4f}, 0));
269
+        g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
270
+    }
271
+
272
+    public int getComponetType(boolean disregardScrollPane) {
273
+        if (compType == TYPE_UNSET) {
274
+            compType = checkType(disregardScrollPane);
275
+        }
276
+        return compType;
277
+    }
278
+
279
+    public int getLayoutHashCode() {
280
+//		Dimension d = c.getMaximumSize();
281
+//		int h = d.width + (d.height << 5);
282
+//
283
+//		d = c.getPreferredSize();
284
+//		h += (d.width << 10) + (d.height << 15);
285
+//
286
+//		d = c.getMinimumSize();
287
+//		h += (d.width << 20) + (d.height << 25);
288
+//
289
+//		if (c.isVisible())
290
+//			h += 1324511;
291
+//
292
+//		String id = getLinkId();
293
+//		if (id != null)
294
+//			h += id.hashCode();
295
+//		return h;
296
+        // Since 2.3 will check the parent.isValid instead everything that affects that can be removed from the layout hashcode.
297
+        String id = getLinkId();
298
+        return id != null ? id.hashCode() : 1;
299
+    }
300
+
301
+    private final int checkType(boolean disregardScrollPane) {
302
+        Component c = this.c;
303
+
304
+        if (disregardScrollPane) {
305
+            if (c instanceof JScrollPane) {
306
+                c = ((JScrollPane) c).getViewport().getView();
307
+            } else if (c instanceof ScrollPane) {
308
+                c = ((ScrollPane) c).getComponent(0);
309
+            }
310
+        }
311
+
312
+        if (c instanceof JTextField || c instanceof TextField) {
313
+            return TYPE_TEXT_FIELD;
314
+        } else if (c instanceof JLabel || c instanceof Label) {
315
+            return TYPE_LABEL;
316
+        } else if (c instanceof JToggleButton || c instanceof Checkbox) {
317
+            return TYPE_CHECK_BOX;
318
+        } else if (c instanceof AbstractButton || c instanceof Button) {
319
+            return TYPE_BUTTON;
320
+        } else if (c instanceof JComboBox || c instanceof Choice) {
321
+            return TYPE_LABEL;
322
+        } else if (c instanceof JTextComponent || c instanceof TextComponent) {
323
+            return TYPE_TEXT_AREA;
324
+        } else if (c instanceof JPanel || c instanceof Canvas) {
325
+            return TYPE_PANEL;
326
+        } else if (c instanceof JList || c instanceof List) {
327
+            return TYPE_LIST;
328
+        } else if (c instanceof JTable) {
329
+            return TYPE_TABLE;
330
+        } else if (c instanceof JSeparator) {
331
+            return TYPE_SEPARATOR;
332
+        } else if (c instanceof JSpinner) {
333
+            return TYPE_SPINNER;
334
+        } else if (c instanceof JProgressBar) {
335
+            return TYPE_PROGRESS_BAR;
336
+        } else if (c instanceof JSlider) {
337
+            return TYPE_SLIDER;
338
+        } else if (c instanceof JScrollPane) {
339
+            return TYPE_SCROLL_PANE;
340
+        } else if (c instanceof JScrollBar || c instanceof Scrollbar) {
341
+            return TYPE_SCROLL_BAR;
342
+        } else if (c instanceof Container) {
343
+            // only AWT components is not containers.
344
+            return TYPE_CONTAINER;
345
+        }
346
+        return TYPE_UNKNOWN;
347
+    }
348
+
349
+    public final int hashCode() {
350
+        return getComponent().hashCode();
351
+    }
352
+
353
+    public final boolean equals(Object o) {
354
+        if (o instanceof ComponentWrapper == false) {
355
+            return false;
356
+        }
357
+        return getComponent().equals(((ComponentWrapper) o).getComponent());
358
+    }
359
+    /** Cached method used for getting base line with reflection.
360
+     */
361
+    private static Method BL_METHOD = null;
362
+    static {
363
+        try {
364
+            BL_METHOD =
365
+                    Component.class.getDeclaredMethod("getBaseline",
366
+                    new Class[]{int.class, int.class});
367
+        } catch (Throwable e) { // No such method or security exception
368
+        }
369
+    }
370
+    private static Method IMS_METHOD = null;
371
+    static {
372
+        try {
373
+            IMS_METHOD =
374
+                    Component.class.getDeclaredMethod("isMaximumSizeSet",
375
+                    (Class<?>) null);
376
+        } catch (Throwable e) { // No such method or security exception
377
+        }
378
+    }
379
+}

+ 104
- 0
src/net/miginfocom/swing/SwingContainerWrapper.java View File

@@ -0,0 +1,104 @@
1
+/*
2
+ * License (BSD):
3
+ * ==============
4
+ *
5
+ * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification,
9
+ * are permitted provided that the following conditions are met:
10
+ * Redistributions of source code must retain the above copyright notice, this list
11
+ * of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice, this
13
+ * list of conditions and the following disclaimer in the documentation and/or other
14
+ * materials provided with the distribution.
15
+ * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without specific
17
+ * prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28
+ * OF SUCH DAMAGE.
29
+ *
30
+ * @version 1.0
31
+ * @author Mikael Grev, MiG InfoCom AB
32
+ *         Date: 2006-sep-08
33
+ */
34
+
35
+package net.miginfocom.swing;
36
+
37
+import net.miginfocom.layout.ComponentWrapper;
38
+import net.miginfocom.layout.ContainerWrapper;
39
+import java.awt.*;
40
+
41
+/** Swing container wrapper. */
42
+public final class SwingContainerWrapper extends SwingComponentWrapper
43
+        implements ContainerWrapper {
44
+
45
+    /** Debug color for cell outline. */
46
+    private static final Color DB_CELL_OUTLINE = new Color(255, 0, 0);
47
+
48
+    public SwingContainerWrapper(Container c) {
49
+        super(c);
50
+    }
51
+
52
+    public ComponentWrapper[] getComponents() {
53
+        Container c = (Container) getComponent();
54
+        ComponentWrapper[] cws =
55
+                new ComponentWrapper[c.getComponentCount()];
56
+        for (int i = 0; i < cws.length;
57
+                i++) {
58
+            cws[i] =new SwingComponentWrapper(c.getComponent(i));
59
+        }
60
+        return cws;
61
+    }
62
+
63
+    public int getComponentCount() {
64
+        return ((Container) getComponent()).getComponentCount();
65
+    }
66
+
67
+    public Object getLayout() {
68
+        return ((Container) getComponent()).getLayout();
69
+    }
70
+
71
+    public final boolean isLeftToRight() {
72
+        return ((Container) getComponent()).getComponentOrientation().
73
+                isLeftToRight();
74
+    }
75
+
76
+    public final void paintDebugCell(int x, int y, int width, int height) {
77
+        Component c = (Component) getComponent();
78
+        if (c.isShowing() == false) {
79
+            return;
80
+        }
81
+        Graphics2D g = (Graphics2D) c.getGraphics();
82
+        if (g == null) {
83
+            return;
84
+        }
85
+        g.setStroke(new BasicStroke(1f, BasicStroke.CAP_SQUARE,
86
+                BasicStroke.JOIN_MITER, 10f, new float[]{2f, 3f}, 0));
87
+        g.setPaint(DB_CELL_OUTLINE);
88
+        g.drawRect(x, y, width - 1, height - 1);
89
+    }
90
+
91
+    public int getComponetType(boolean disregardScrollPane) {
92
+        return TYPE_CONTAINER;
93
+    }
94
+    // Removed for 2.3 because the parent.isValid() in MigLayout will catch this instead.
95
+//	public int getLayoutHashCode()
96
+//	{
97
+//		int h = super.getLayoutHashCode();
98
+//
99
+//		if (isLeftToRight())
100
+//			h += 416343;
101
+//
102
+//		return h;
103
+//	}
104
+}

Loading…
Cancel
Save