Scilab GUI: improve the dialog rendering 59/12959/3
Clément DAVID [Fri, 18 Oct 2013 14:24:48 +0000 (16:24 +0200)]
 * fix bug 11571 : x_mdialog did not let the L&F select the window size.
 * With huge x_mdialog the user should resize the Java dialog but the previous layout allocate more space to the title and the JScrollPaned content did not resize.
 * Scilab boolean are also parsed to display a checkbox instead of a string.

To check the modification, run the x_mdialog example and resize the window.

Change-Id: Icb736f3ecaef50e300c8b39146cf05cce9c1742e

scilab/CHANGES_5.5.X
scilab/modules/gui/help/en_US/x_mdialog.xml
scilab/modules/gui/src/java/org/scilab/modules/gui/bridge/messagebox/SwingScilabMessageBox.java

index 8552935..a87e8e6 100644 (file)
@@ -9,6 +9,8 @@ Scilab Bug Fixes
 * Bug #7705 fixed - In the Genetic algorithms help pages, documented the
                     "dimension", "minbounds" and "maxbounds" fields.
 
+* Bug #11571 fixed - x_mdialog did not let the Look&Feel select the window size.
+
 * Bug #11680 fixed - GUI functions in Scilab 5.4.X were much slower than in Scilab 5.3.3.
 
 * Bug #12769 fixed - xset("window", 1) did not set the current axes.
index 9e583ac..a9590e2 100644 (file)
@@ -86,10 +86,26 @@ sig = x_mdialog('enter sine signal',txt,['1';'10';'0'])
 mag = evstr(sig(1))
 frq = evstr(sig(2))
 ph  = evstr(sig(3))
-
+ ]]></programlisting>
+        <programlisting role="example"><![CDATA[ 
 rep = x_mdialog(['System Simulation';'with PI regulator'],...
                  ['P gain';'I gain '],[' ';' '])
  ]]></programlisting>
+        <programlisting role="example"><![CDATA[
+sz = [4,3];
+default_input_matrix = string(int32(rand(sz(1), sz(2)) * 200 - 100));
+labelsv = 'row '+string(1:sz(1));
+labelsh = 'col '+string(1:sz(2));
+rep = x_mdialog('Enter a matrix',...
+                 labelsv, labelsh, default_input_matrix)
+ ]]></programlisting>
+        <programlisting role="example"><![CDATA[
+sz = [10,10];
+default_input_matrix = string(rand(sz(1), sz(2)) > 0.5);
+labelsv = string(1:sz(1));
+labelsh = string(1:sz(2));
+rep = x_mdialog('Enter a boolean matrix', labelsv, labelsh, default_input_matrix)
+ ]]></programlisting>
     </refsection>
     <refsection role="see also">
         <title>See Also</title>
index 45b4783..c4db172 100644 (file)
@@ -2,6 +2,7 @@
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2008 - INRIA - Vincent Couvert
  * Copyright (C) 2010 - DIGITEO - Vincent Couvert
+ * Copyright (C) 2013 - Scilab Enterprises - Clement DAVID
  *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
 
 package org.scilab.modules.gui.bridge.messagebox;
 
+import java.awt.BorderLayout;
 import java.awt.Component;
-import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Image;
-import java.awt.Insets;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.MouseEvent;
@@ -33,6 +33,10 @@ import javax.swing.Action;
 import javax.swing.BorderFactory;
 import javax.swing.ButtonGroup;
 import javax.swing.DefaultListModel;
+import javax.swing.GroupLayout;
+import javax.swing.GroupLayout.Alignment;
+import javax.swing.GroupLayout.ParallelGroup;
+import javax.swing.GroupLayout.SequentialGroup;
 import javax.swing.Icon;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
@@ -69,26 +73,12 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
 
     private static final long serialVersionUID = 7939976395338222763L;
 
-    private static final int WINDOW_WIDTH = 650;
-    private static final int MESSAGE_HEIGHT = 200;
-    private static final int LISTBOX_HEIGHT = 200;
-
-    private static final int X_MDIALOG_MARGIN = 5;
-    private static final int X_MDIALOG_TEXTFIELD_SIZE = 10;
-
     private static final int X_MESSAGE_TYPE = 0;
     private static final int X_DIALOG_TYPE = 1;
     private static final int X_CHOOSE_TYPE = 2;
     private static final int X_MDIALOG_TYPE = 3;
     private static final int X_CHOICES_TYPE = 4;
 
-    private static final String SCIDIR = System.getenv("SCI");
-
-    /**
-     * Offset around object and its ScrollPane
-     */
-    private static final int OFFSET = 5;
-
     /**
      * New line character for mutli-line text components
      */
@@ -108,8 +98,7 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
 
     private int elementId;
 
-    private Icon messageIcon; // = new
-    // ImageIcon(ScilabSwingUtilities.findIcon("scilab"));
+    private Icon messageIcon;
 
     private int scilabDialogType = X_MESSAGE_TYPE;
 
@@ -139,7 +128,7 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
     private String[] lineLabels;
     private String[] columnLabels;
     private String[] defaultInput;
-    private JTextField[] textFields;
+    private Component[] textFields;
     private String[] userValues;
 
     /**
@@ -162,7 +151,7 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
     private String title;
     private final Image imageForIcon = ((ImageIcon) scilabIcon).getImage();
     private int messageType = -1;
-    private Object[] objs;
+    private Component[] objs;
     private Object[] buttons;
     private boolean modal = true;
     private JCheckBox checkbox;
@@ -278,9 +267,6 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
         });
 
         JScrollPane messageScrollPane = new JScrollPane(messageLabel);
-        int scrollWidth = (int) Math.min(WINDOW_WIDTH, messageLabel.getPreferredSize().getWidth() + OFFSET);
-        int scrollHeight = (int) Math.min(MESSAGE_HEIGHT, messageLabel.getPreferredSize().getHeight() + OFFSET);
-        messageScrollPane.setPreferredSize(new Dimension(scrollWidth, scrollHeight));
         // Make the scroll Pane transparent
         messageScrollPane.setOpaque(false);
         messageScrollPane.getViewport().setOpaque(false);
@@ -294,7 +280,7 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
             // All objects in the MessageBox:
             //  - Message
             //  - Editable zone
-            objs = new Object[2];
+            objs = new Component[2];
 
             objs[0] = messageScrollPane;
 
@@ -393,10 +379,6 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
             // Editable text zone
             JScrollPane scrollPane = new JScrollPane(panel);
 
-            scrollWidth = (int) Math.min(WINDOW_WIDTH, panel.getPreferredSize().getWidth() + OFFSET);
-            scrollHeight = (int) Math.min(LISTBOX_HEIGHT, panel.getPreferredSize().getHeight() + OFFSET);
-            scrollPane.setPreferredSize(new Dimension(scrollWidth, scrollHeight));
-
             objs[1] = scrollPane;
 
             // And now the buttons
@@ -419,7 +401,7 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
             // All objects in the MessageBox:
             //  - Message
             //  - Editable zone
-            objs = new Object[2];
+            objs = new Component[2];
 
             objs[0] = messageScrollPane;
 
@@ -429,59 +411,124 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
             } else {
                 numberOfColumns = columnLabels.length + 1;
             }
-            GridBagLayout layout = new GridBagLayout();
-            JPanel panel = new JPanel(layout);
-            GridBagConstraints constraints = new GridBagConstraints();
-            constraints.gridx = 0;
-            constraints.gridy = 0;
-            constraints.fill = GridBagConstraints.HORIZONTAL;
-            constraints.insets = new Insets(X_MDIALOG_MARGIN, X_MDIALOG_MARGIN, X_MDIALOG_MARGIN, X_MDIALOG_MARGIN);
-
-            int line = 0;
-            int col = 0;
-            // Optional first line
+
+            // Allocate the Java Components
+            final JLabel[] colLabels;
+            final JLabel[] rowLabels;
             if (columnLabels != null) {
-                // Column label for "Row labels" column
-                panel.add(new JLabel(""), constraints);
-                constraints.gridx++;
-                for (col = 0; col < columnLabels.length; col++) {
-                    panel.add(new JLabel(columnLabels[col]), constraints);
-                    constraints.gridx++;
+                // Optional first line
+                colLabels = new JLabel[columnLabels.length + 1];
+
+                // the first column label is on top of the row label
+                colLabels[0] = new JLabel("");
+
+                // create the components on each column
+                for (int col = 0; col < columnLabels.length; col++) {
+                    colLabels[col + 1] = new JLabel(columnLabels[col]);
                 }
-                constraints.gridy++;
+            } else {
+                // there is no first line
+                colLabels = null;
+            }
+            rowLabels = new JLabel[lineLabels.length];
+            for (int row = 0; row < lineLabels.length; row++) {
+                // add a gap (a space) between the column's labels and data
+                rowLabels[row] = new JLabel(lineLabels[row] + " ");
             }
-
 
             // Prepare return value
             if (columnLabels == null) {
                 userValues = new String[lineLabels.length];
-                textFields = new JTextField[lineLabels.length];
+                textFields = new Component[lineLabels.length];
             } else {
                 userValues = new String[lineLabels.length * columnLabels.length];
-                textFields = new JTextField[lineLabels.length * columnLabels.length];
+                textFields = new Component[lineLabels.length * columnLabels.length];
             }
-            for (line = 0; line < lineLabels.length; line++) {
-                constraints.gridx = 0;
-                panel.add(new JLabel(lineLabels[line]), constraints);
-                constraints.gridx++;
-                for (col = 0; col < numberOfColumns - 1; col++) {
-                    textFields[col * lineLabels.length + line] = new JTextField(defaultInput[col * lineLabels.length + line]);
-                    panel.add(textFields[col * lineLabels.length + line], constraints);
-                    textFields[col * lineLabels.length + line].setColumns(X_MDIALOG_TEXTFIELD_SIZE);
-                    constraints.gridx++;
+
+            // set the initial values
+            for (int line = 0; line < lineLabels.length; line++) {
+                for (int col = 0; col < numberOfColumns - 1; col++) {
+                    final String initial = defaultInput[col * lineLabels.length + line];
+
+                    final Component c;
+                    if ("T".equalsIgnoreCase(initial)) {
+                        c = new JCheckBox();
+                        ((JCheckBox) c).setSelected(true);
+                    } else if ("F".equalsIgnoreCase(initial)) {
+                        c = new JCheckBox();
+                        ((JCheckBox) c).setSelected(false);
+                    } else {
+                        c = new JTextField(initial);
+                    }
+
+                    textFields[col * lineLabels.length + line] = c;
+                    rowLabels[line].setLabelFor(c);
                 }
-                constraints.gridy++;
             }
 
-            panel.doLayout();
+            // Prepare the layout
+            JPanel panel = new JPanel();
+            GroupLayout layout = new GroupLayout(panel);
+            panel.setLayout(layout);
+
+            final SequentialGroup horizontalGroup = layout.createSequentialGroup().addContainerGap();
+            final SequentialGroup verticalGroup = layout.createSequentialGroup().addContainerGap();
+
+            // Horizontal layout
+            {
+                final ParallelGroup localGroup = layout.createParallelGroup(Alignment.LEADING);
+
+                if (colLabels != null) {
+                    localGroup.addComponent(colLabels[0]);
+                }
+                // special case for the row label
+                for (int row = 0; row < lineLabels.length; row++) {
+                    localGroup.addComponent(rowLabels[row]);
+                }
+                horizontalGroup.addGroup(localGroup);
+            }
+            for (int col = 0 ; col < numberOfColumns - 1; col++) {
+                final ParallelGroup localGroup = layout.createParallelGroup(Alignment.LEADING);
+
+                if (colLabels != null) {
+                    // center the labels to be rendered like a spreadsheet
+                    localGroup.addComponent(colLabels[col + 1], Alignment.CENTER);
+                }
+
+                // common case for the initial values
+                for (int row = 0; row < lineLabels.length; row++) {
+                    localGroup.addComponent(textFields[col * lineLabels.length + row]);
+                }
+
+                horizontalGroup.addGroup(localGroup);
+            }
+            layout.setHorizontalGroup(
+                layout.createParallelGroup(Alignment.LEADING)
+                .addGroup(horizontalGroup.addContainerGap()));
+
+            // Vertical layout
+            if (colLabels != null) {
+                final ParallelGroup localGroup = layout.createParallelGroup(Alignment.BASELINE);
+                for (int col = 0 ; col < numberOfColumns; col++) {
+                    localGroup.addComponent(colLabels[col]);
+                }
+                verticalGroup.addGroup(localGroup);
+            }
+            for (int row = 0; row < lineLabels.length; row++) {
+                final ParallelGroup localGroup = layout.createParallelGroup(Alignment.BASELINE);
+                localGroup.addComponent(rowLabels[row]);
+                for (int col = 0 ; col < numberOfColumns - 1; col++) {
+                    localGroup.addComponent(textFields[col * lineLabels.length + row]);
+                }
+                verticalGroup.addGroup(localGroup);
+            }
+            layout.setVerticalGroup(
+                layout.createParallelGroup(Alignment.LEADING)
+                .addGroup(verticalGroup.addContainerGap()));
 
             // Editable text zone
             JScrollPane scrollPane = new JScrollPane(panel);
 
-            scrollWidth = (int) Math.min(WINDOW_WIDTH, panel.getPreferredSize().getWidth() + OFFSET);
-            scrollHeight = (int) Math.min(LISTBOX_HEIGHT, panel.getPreferredSize().getHeight() + OFFSET);
-            scrollPane.setPreferredSize(new Dimension(scrollWidth, scrollHeight));
-
             objs[1] = scrollPane;
 
             // And now the buttons
@@ -504,7 +551,7 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
             // All objects in the MessageBox:
             //  - Message
             //  - Listbox
-            objs = new Object[2];
+            objs = new Component[2];
 
             // Add the message
             objs[0] = messageScrollPane;
@@ -525,7 +572,7 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
             // All objects in the MessageBox:
             //  - Message
             //  - Editable zone
-            objs = new Object[2];
+            objs = new Component[2];
 
             objs[0] = messageScrollPane;
 
@@ -533,9 +580,6 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
             textArea = new JTextArea(initialValue);
             textArea.setRows(initialValueSize);
             JScrollPane scrollPane = new JScrollPane(textArea);
-            scrollWidth = (int) Math.min(WINDOW_WIDTH, textArea.getPreferredSize().getWidth() + OFFSET);
-            scrollHeight = (int) Math.min(LISTBOX_HEIGHT, textArea.getPreferredSize().getHeight() + OFFSET);
-            scrollPane.setPreferredSize(new Dimension(scrollWidth, scrollHeight));
 
             objs[1] = scrollPane;
 
@@ -559,7 +603,7 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
             // All objects in the MessageBox:
             //  - Message
             int nb = checkbox == null ? 1 : 2;
-            objs = new Object[nb];
+            objs = new Component[nb];
 
             // Add the message
             objs[0] = messageScrollPane;
@@ -593,13 +637,26 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
         }
         // Display
         ((JScrollPane) objs[0]).setBorder(BorderFactory.createEmptyBorder());
+        final JPanel message = new JPanel(new BorderLayout());
+        message.add(objs[0], BorderLayout.NORTH);
+
+        if (objs.length == 2) {
+            message.add(objs[1], BorderLayout.CENTER);
+        } else {
+            // seems that this case is never called as x_message is no more available into Scilab.
+            final JPanel content = new JPanel();
+            for (int i = 1; i < objs.length; i++) {
+                content.add(objs[i]);
+            }
+            message.add(content, BorderLayout.CENTER);
+        }
         if (messageType != -1) {
-            setContentPane(new JOptionPane(objs, messageType, JOptionPane.CANCEL_OPTION, null, buttons));
+            setContentPane(new JOptionPane(message, messageType, JOptionPane.CANCEL_OPTION, null, buttons));
         } else {
             if (messageIcon == null) {
                 messageIcon = scilabIcon;
             }
-            setContentPane(new JOptionPane(objs, messageType, JOptionPane.CANCEL_OPTION, messageIcon, buttons));
+            setContentPane(new JOptionPane(message, messageType, JOptionPane.CANCEL_OPTION, messageIcon, buttons));
         }
         pack();
         super.setModal(modal); /* Must call the JDialog class setModal */
@@ -648,7 +705,16 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
                 userValue = textArea.getText();
             } else if (scilabDialogType == X_MDIALOG_TYPE) {
                 for (int textFieldIndex = 0; textFieldIndex < textFields.length; textFieldIndex++) {
-                    userValues[textFieldIndex] = textFields[textFieldIndex].getText();
+                    final Component c = textFields[textFieldIndex];
+                    if (c instanceof JTextField) {
+                        userValues[textFieldIndex] = ((JTextField) c).getText();
+                    } else if (c instanceof JCheckBox) {
+                        if (((JCheckBox) c).isSelected()) {
+                            userValues[textFieldIndex] = "%t";
+                        } else {
+                            userValues[textFieldIndex] = "%f";
+                        }
+                    }
                 }
                 userValue = ""; /* To make getValueSize return a non zero value */
             } else if (scilabDialogType == X_CHOICES_TYPE) {
@@ -829,9 +895,6 @@ public class SwingScilabMessageBox extends JDialog implements SimpleMessageBox,
         }
         listBox.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
         JScrollPane scrollPane = new JScrollPane(listBox);
-        int scrollWidth = (int) Math.min(WINDOW_WIDTH, listBox.getPreferredSize().getWidth() + OFFSET);
-        int scrollHeight = LISTBOX_HEIGHT;
-        scrollPane.setPreferredSize(new Dimension(scrollWidth, scrollHeight));
         return  scrollPane;
     }