altosui: Rewrite info table to mix with scroll pane well. Fix startup size
authorKeith Packard <keithp@keithp.com>
Sun, 21 Nov 2010 00:19:42 +0000 (16:19 -0800)
committerKeith Packard <keithp@keithp.com>
Sun, 21 Nov 2010 00:19:42 +0000 (16:19 -0800)
Using a single table for the info table means that the scroll pane
automatically picks up the table headers and shows them above the
scrollable view.

This patch also fixes the application size at startup so that no
scrollbar is required in the info table, and the window is < 800x600.

Signed-off-by: Keith Packard <keithp@keithp.com>
ao-tools/altosui/Altos.java
ao-tools/altosui/AltosAscent.java
ao-tools/altosui/AltosDescent.java
ao-tools/altosui/AltosFlightInfoTableModel.java
ao-tools/altosui/AltosFlightUI.java
ao-tools/altosui/AltosInfoTable.java
ao-tools/altosui/AltosLanded.java
ao-tools/altosui/AltosPad.java

index 197e98db7956bc4645fbcadb1ec9e8fe5f596320..8ee94e04b0b7bcd6d83815c5c3541ec231e378a9 100644 (file)
@@ -73,6 +73,8 @@ public class Altos {
        static final Font value_font = new Font("Monospaced", Font.PLAIN, 22);
        static final Font status_font = new Font("SansSerif", Font.BOLD, 24);
 
+       static final int text_width = 16;
+
        static void initialize_map()
        {
                string_to_state.put("startup", ao_flight_startup);
index 2ceaa183b1ca1fa49c0f3173d87376041aa8385f..64bdcf3097cc5eae63ad395e96eded6ef6ad4a9f 100644 (file)
@@ -65,7 +65,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(label, c);
                        add(label);
 
-                       value = new JTextField(17);
+                       value = new JTextField(Altos.text_width);
                        value.setFont(Altos.value_font);
                        value.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = 2; c.gridy = y;
@@ -102,7 +102,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(label, c);
                        add(label);
 
-                       value = new JTextField(17);
+                       value = new JTextField(Altos.text_width);
                        value.setFont(Altos.value_font);
                        value.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = 2; c.gridy = y;
@@ -151,7 +151,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(label, c);
                        add(label);
 
-                       value = new JTextField(17);
+                       value = new JTextField(Altos.text_width);
                        value.setFont(Altos.value_font);
                        value.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = 2; c.gridy = y;
@@ -161,7 +161,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(value, c);
                        add(value);
 
-                       max_value = new JTextField(17);
+                       max_value = new JTextField(Altos.text_width);
                        max_value.setFont(Altos.value_font);
                        max_value.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = 3; c.gridy = y;
index abe64fdcc6772bc6e579555b5f86b3c403ef9b9c..16ccd458d2524b8d82ce22a4ed0e6f20a116b81d 100644 (file)
@@ -66,7 +66,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(label, c);
                        add(label);
 
-                       value = new JTextField(17);
+                       value = new JTextField(Altos.text_width);
                        value.setFont(Altos.value_font);
                        value.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = 4; c.gridy = y;
@@ -112,7 +112,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay {
                        c.weightx = 0;
                        add(label, c);
 
-                       value = new JTextField(17);
+                       value = new JTextField(Altos.text_width);
                        value.setFont(Altos.value_font);
                        value.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = x + 2; c.gridy = y;
@@ -159,7 +159,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(label, c);
                        add(label);
 
-                       value1 = new JTextField(17);
+                       value1 = new JTextField(Altos.text_width);
                        value1.setFont(Altos.value_font);
                        value1.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = x + 2; c.gridy = y;
@@ -169,7 +169,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(value1, c);
                        add(value1);
 
-                       value2 = new JTextField(17);
+                       value2 = new JTextField(Altos.text_width);
                        value2.setFont(Altos.value_font);
                        value2.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = x + 4; c.gridy = y;
index 3355ff527beba857378aa2cd5b6e62ec211f1d03..e23eff68f45beb0d4dca1649e95da3a078ae6d55 100644 (file)
@@ -29,53 +29,56 @@ import java.util.prefs.*;
 import java.util.concurrent.LinkedBlockingQueue;
 
 public class AltosFlightInfoTableModel extends AbstractTableModel {
-       private String[] columnNames = {"Field", "Value"};
+       final static private String[] columnNames = {"Field", "Value"};
 
-       class InfoLine {
-               String  name;
-               String  value;
+       int     rows;
+       int     cols;
+       private String[][] data;
 
-               public InfoLine(String n, String v) {
-                       name = n;
-                       value = v;
-               }
-       }
-
-       private ArrayList<InfoLine> rows = new ArrayList<InfoLine>();
-
-       public int getColumnCount() { return columnNames.length; }
-       public String getColumnName(int col) { return columnNames[col]; }
-
-       public int getRowCount() { return 17; }
-
-       int     current_row = 0;
-       int     prev_num_rows = 0;
+       public int getColumnCount() { return cols; }
+       public int getRowCount() { return rows; }
+       public String getColumnName(int col) { return columnNames[col & 1]; }
 
        public Object getValueAt(int row, int col) {
-               if (row >= rows.size())
+               if (row >= rows || col >= cols)
                        return "";
-               if (col == 0)
-                       return rows.get(row).name;
-               else
-                       return rows.get(row).value;
+               return data[row][col];
        }
 
-       public void resetRow() {
-               current_row = 0;
+       int[]   current_row;
+
+       public void reset() {
+               for (int i = 0; i < cols / 2; i++)
+                       current_row[i] = 0;
        }
-       public void addRow(String name, String value) {
-               if (current_row >= rows.size())
-                       rows.add(current_row, new InfoLine(name, value));
-               else
-                       rows.set(current_row, new InfoLine(name, value));
-               current_row++;
+
+       public void clear() {
+               reset();
+               for (int c = 0; c < cols; c++)
+                       for (int r = 0; r < rows; r++)
+                               data[r][c] = "";
+               fireTableDataChanged();
+       }
+
+       public void addRow(int col, String name, String value) {
+               if (current_row[col] < rows) {
+                       data[current_row[col]][col * 2] = name;
+                       data[current_row[col]][col * 2 + 1] = value;
+               }
+               current_row[col]++;
        }
+
        public void finish() {
-               if (current_row > prev_num_rows)
-                       fireTableRowsInserted(prev_num_rows, current_row - 1);
-               while (rows.size() > current_row)
-                       rows.remove(rows.size() - 1);
-               prev_num_rows = current_row;
+               for (int c = 0; c < cols / 2; c++)
+                       while (current_row[c] < rows)
+                               addRow(c, "", "");
                fireTableDataChanged();
        }
+
+       public AltosFlightInfoTableModel (int in_rows, int in_cols) {
+               rows = in_rows;
+               cols = in_cols * 2;
+               data = new String[rows][cols];
+               current_row = new int[in_cols];
+       }
 }
index ac88aa152ba661467e4dac8447e71953d0ce259f..d5bcdb104d8f63a00224259155fe6fc67cf8a046 100644 (file)
@@ -44,7 +44,6 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
        AltosLanded     landed;
 
        private AltosFlightStatus flightStatus;
-       private JScrollPane flightInfoPane;
        private AltosInfoTable flightInfo;
 
        static final int tab_pad = 1;
@@ -66,14 +65,6 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
                return tab_landed;
        }
 
-       public int width() {
-               return flightInfo.width();
-       }
-
-       public int height() {
-               return flightStatus.height() + flightInfo.height();
-       }
-
        void stop_display() {
                if (thread != null && thread.isAlive()) {
                        thread.interrupt();
@@ -146,6 +137,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
 
                setTitle(String.format("AltOS %s", reader.name));
 
+               /* Stick channel selector at top of table for telemetry monitoring */
                if (serial >= 0) {
                        // Channel menu
                        channels = new AltosChannelMenu(AltosPreferences.channel(serial));
@@ -162,6 +154,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
                        bag.add (channels, c);
                }
 
+               /* Flight status is always visible */
                flightStatus = new AltosFlightStatus();
                c.gridx = 0;
                c.gridy = 1;
@@ -169,6 +162,9 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
                c.weightx = 1;
                bag.add(flightStatus, c);
 
+               /* The rest of the window uses a tabbed pane to
+                * show one of the alternate data views
+                */
                pane = new JTabbedPane();
 
                pad = new AltosPad();
@@ -184,9 +180,9 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
                pane.add("Landed", landed);
 
                flightInfo = new AltosInfoTable();
-               flightInfoPane = new JScrollPane(flightInfo.box());
-               pane.add("Table", flightInfoPane);
+               pane.add("Table", new JScrollPane(flightInfo));
 
+               /* Make the tabbed pane use the rest of the window space */
                c.gridx = 0;
                c.gridy = 2;
                c.fill = GridBagConstraints.BOTH;
@@ -194,9 +190,6 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
                c.weighty = 1;
                bag.add(pane, c);
 
-               this.setSize(this.getPreferredSize());
-               this.validate();
-
                setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                addWindowListener(new WindowAdapter() {
                        @Override
@@ -209,7 +202,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
                        }
                });
 
-               this.setVisible(true);
+               pack();
+               setVisible(true);
 
                thread = new AltosDisplayThread(this, voice, this, reader);
 
index 289244106951f50478e2c8af693f88a4c3aab114..c571d5c901be7a2d32ad99d01847f25aa3d99ce2 100644 (file)
@@ -28,11 +28,8 @@ import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.LinkedBlockingQueue;
 
-public class AltosInfoTable {
-       private Box                       box;
-       private JTable                    table[];
-       private AltosFlightInfoTableModel model[];
-       private Box                       ibox[];
+public class AltosInfoTable extends JTable {
+       private AltosFlightInfoTableModel model;
 
        private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 12);
        private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 12);
@@ -40,58 +37,35 @@ public class AltosInfoTable {
        static final int info_columns = 3;
        static final int info_rows = 17;
 
-       public AltosInfoTable() {
-               box = Box.createHorizontalBox();
-               model = new AltosFlightInfoTableModel[info_columns];
-               table = new JTable[info_columns];
-               ibox = new Box[info_columns];
-               for (int i = 0; i < info_columns; i++) {
-                       model[i] = new AltosFlightInfoTableModel();
-                       table[i] = new JTable(model[i]);
-                       ibox[i] = box.createVerticalBox();
-
-                       table[i].setFont(infoValueFont);
-                       table[i].setRowHeight(rowHeight());
-                       table[i].setShowGrid(true);
-                       ibox[i].add(table[i].getTableHeader());
-                       ibox[i].add(table[i]);
-                       box.add(ibox[i]);
-               }
-       }
-
-       public int rowHeight() {
-               FontMetrics     infoValueMetrics = table[0].getFontMetrics(infoValueFont);
-               return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 20 / 10;
-       }
-
-       public int columnWidth() {
-               FontMetrics     infoValueMetrics = table[0].getFontMetrics(infoValueFont);
-               return infoValueMetrics.charWidth('0') * 20 * 2;
+       int desired_row_height() {
+               FontMetrics     infoValueMetrics = getFontMetrics(infoValueFont);
+               return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10;
        }
 
-       public int height() {
-               return rowHeight() * info_rows;
-       }
-
-       public int width() {
-               return columnWidth() * info_columns;
+       public AltosInfoTable() {
+               super(new AltosFlightInfoTableModel(info_rows, info_columns));
+               model = (AltosFlightInfoTableModel) getModel();
+               setFont(infoValueFont);
+               setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
+               setShowGrid(true);
+               setRowHeight(desired_row_height());
+               doLayout();
        }
 
-       public Box box() {
-               return box;
+       public Dimension getPreferredScrollableViewportSize() {
+               return getPreferredSize();
        }
 
        void info_reset() {
-               for (int i = 0; i < info_columns; i++)
-                       model[i].resetRow();
+               model.reset();
        }
 
        void info_add_row(int col, String name, String value) {
-               model[col].addRow(name, value);
+               model.addRow(col, name, value);
        }
 
        void info_add_row(int col, String name, String format, Object... parameters) {
-               model[col].addRow(name, String.format(format, parameters));
+               info_add_row (col, name, String.format(format, parameters));
        }
 
        void info_add_deg(int col, String name, double v, int pos, int neg) {
@@ -103,17 +77,15 @@ public class AltosInfoTable {
                double  deg = Math.floor(v);
                double  min = (v - deg) * 60;
 
-               model[col].addRow(name, String.format("%3.0f°%08.5f'", deg, min));
+               info_add_row(col, name, String.format("%3.0f°%08.5f'", deg, min));
        }
 
        void info_finish() {
-               for (int i = 0; i < info_columns; i++)
-                       model[i].finish();
+               model.finish();
        }
 
        public void clear() {
-               info_reset();
-               info_finish();
+               model.clear();
        }
 
        public void show(AltosState state, int crc_errors) {
index 059dbb6dcf91ab2d50bbf5b8a027e8476e308a87..d34efe6dbcfb8f2a7540754809bcfb4df77e790c 100644 (file)
@@ -61,7 +61,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(label, c);
                        add(label);
 
-                       value = new JTextField(17);
+                       value = new JTextField(Altos.text_width);
                        value.setFont(value_font);
                        value.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = 1; c.gridy = y;
index 480e4d79f81aa73778ec665b75dd6d4e5eca7632..669543472a71ff3074ad823f0e24c562dcc4220e 100644 (file)
@@ -65,7 +65,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(label, c);
                        add(label);
 
-                       value = new JTextField(17);
+                       value = new JTextField(Altos.text_width);
                        value.setFont(Altos.value_font);
                        value.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = 2; c.gridy = y;
@@ -101,7 +101,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay {
                        layout.setConstraints(label, c);
                        add(label);
 
-                       value = new JTextField(17);
+                       value = new JTextField(Altos.text_width);
                        value.setFont(Altos.value_font);
                        value.setHorizontalAlignment(SwingConstants.RIGHT);
                        c.gridx = 2; c.gridy = y;