Author: thomasobrien95
Date: Thu Jan  8 08:55:37 2009
New Revision: 2908

Modified:
   trunk/src/ca/sqlpower/architect/swingui/ProfileManagerView.java
   trunk/src/ca/sqlpower/architect/swingui/ProfileRowComponent.java

Log:
Profile row components can now be focused. This allows adding actions
to move up and down the list with the arrow keys as well as deleting
with the delete button and enter will display profiles.

Modified: trunk/src/ca/sqlpower/architect/swingui/ProfileManagerView.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/ProfileManagerView.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/ProfileManagerView.java Thu Jan 8 08:55:37 2009
@@ -27,6 +27,8 @@
 import java.awt.Window;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
 import java.util.ArrayList;
@@ -45,6 +47,7 @@
 import javax.swing.JScrollBar;
 import javax.swing.JScrollPane;
 import javax.swing.JTextField;
+import javax.swing.KeyStroke;
 import javax.swing.ScrollPaneConstants;
 import javax.swing.Scrollable;
 import javax.swing.SwingUtilities;
@@ -110,12 +113,117 @@
     /**
      * The list of row components we will be showing in the results panel.
      */
- List<ProfileRowComponent> showingRows = new ArrayList<ProfileRowComponent>(); + final List<ProfileRowComponent> showingRows = new ArrayList<ProfileRowComponent>();

private class ResultListPanel extends JPanel implements Scrollable, SelectionListener {
+
+        /**
+ * This string maps an action for pressing up on the keyboard to select
+         * the profile above the selected profile.
+         */
+ private static final String SELECT_ABOVE_ACTION = "selectAboveAction";
+
+        /**
+ * This string maps an action for pressing down on the keyboard to select
+         * the profile below the selected profile.
+         */
+ private static final String SELECT_BELOW_ACTION = "selectBelowAction";
+
+        /**
+ * This string maps an action for pressing delete on the keyboard remove
+         * the profile from the profile manager.
+         */
+        private static final String DELETE_ACTION = "deleteAction";
+
+        /**
+         * This string maps an action for pressing enter on the keyboard to
+         * display the selected profiles.
+         */
+ private static final String SHOW_PROFILE_ACTION = "showProfileAction";
+
         private ProfileRowComponent lastSelectedRow;
         private boolean ignoreSelectionEvents = false;

+        /**
+ * This scroll pane contains the ResultListPanel to be displayed. This
+         * can be null if the ResultListPanel is not in a JScrollPane.
+         */
+        private final JScrollPane parentPanel;
+
+        public ResultListPanel(JScrollPane parent) {
+            this.parentPanel = parent;
+ getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), SELECT_ABOVE_ACTION);
+            getActionMap().put(SELECT_ABOVE_ACTION, new AbstractAction() {
+                public void actionPerformed(ActionEvent e) {
+                    ProfileRowComponent focusedRow = null;
+                    for (ProfileRowComponent prc : showingRows) {
+                        if (prc.hasFocus()) {
+                            focusedRow = prc;
+                            break;
+                        }
+                    }
+                    if (focusedRow == null) {
+                        return;
+                    }
+                    if (showingRows.indexOf(focusedRow) != 0) {
+ ProfileRowComponent abovePRC = showingRows.get(showingRows.indexOf(focusedRow) - 1); + abovePRC.setSelected(true, SelectionEvent.SINGLE_SELECT);
+                        if (parentPanel != null) {
+ Rectangle viewRect = parentPanel.getViewport().getViewRect(); + parentPanel.getViewport().scrollRectToVisible(new Rectangle((int) (abovePRC.getX() - viewRect.getX()), + (int) (abovePRC.getY() - viewRect.getY()), + (int) (abovePRC.getWidth()), + (int) (abovePRC.getHeight())));
+                        }
+                    }
+                }
+            });
+ getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), SELECT_BELOW_ACTION);
+            getActionMap().put(SELECT_BELOW_ACTION, new AbstractAction() {
+                public void actionPerformed(ActionEvent e) {
+                    ProfileRowComponent focusedRow = null;
+                    for (ProfileRowComponent prc : showingRows) {
+                        if (prc.hasFocus()) {
+                            focusedRow = prc;
+                            break;
+                        }
+                    }
+                    if (focusedRow == null) {
+                        return;
+                    }
+ if (showingRows.indexOf(focusedRow) != showingRows.size() - 1) { + ProfileRowComponent belowPRC = showingRows.get(showingRows.indexOf(focusedRow) + 1); + belowPRC.setSelected(true, SelectionEvent.SINGLE_SELECT);
+                        if (parentPanel != null) {
+ Rectangle viewRect = parentPanel.getViewport().getViewRect(); + parentPanel.getViewport().scrollRectToVisible(new Rectangle((int) (belowPRC.getX() - viewRect.getX()), + (int) (belowPRC.getY() - viewRect.getY()), + (int) (belowPRC.getWidth()), + (int) (belowPRC.getHeight())));
+                        }
+                    }
+                }
+
+            });
+
+ getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), DELETE_ACTION); + getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), DELETE_ACTION);
+            getActionMap().put(DELETE_ACTION, new AbstractAction() {
+                public void actionPerformed(ActionEvent e) {
+                    for (int i = showingRows.size() - 1; i >= 0; i--) {
+                        ProfileRowComponent rowComp = showingRows.get(i);
+                        if (rowComp.isSelected()) {
+                            pm.removeProfile(rowComp.getResult());
+                        }
+                    }
+                    updateResultListPanel();
+                }
+            });
+
+ getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), SHOW_PROFILE_ACTION);
+            getActionMap().put(SHOW_PROFILE_ACTION, viewSelectedAction);
+        }
+
         @Override
         public Dimension getPreferredSize() {
             Dimension d = super.getPreferredSize();
@@ -238,6 +346,26 @@
         public void keyTyped(KeyEvent e) {}
         public void keyReleased(KeyEvent e) {}
     }
+
+    /**
+ * This action will open a viewer for all of the currently selected profiles.
+     */
+ private final Action viewSelectedAction = new AbstractAction(Messages.getString("ProfileManagerView.viewSelectedActionName")) { //$NON-NLS-1$
+
+        public void actionPerformed(ActionEvent e) {
+            ProfileResultsViewer profileResultsViewer =
+                new ProfileResultsViewer(pm);
+            profileResultsViewer.clearScanList();
+            for (ProfileRowComponent rowComp : showingRows) {
+                if (rowComp.isSelected()) {
+                    TableProfileResult result = rowComp.getResult();
+ profileResultsViewer.addTableProfileResultToScan(result);
+                    profileResultsViewer.addTableProfileResult(result);
+                }
+            }
+            profileResultsViewer.getDialog().setVisible(true);
+        }
+    };

     public ProfileManagerView(final ProfileManager pm) {
         super();
@@ -299,7 +427,18 @@
         group.add(nameRadioButton);
         group.add(dateRadioButton);
         nameRadioButton.setSelected(true);
-        resultListPanel = new ResultListPanel();
+        scrollPane = new JScrollPane();
+        resultListPanel = new ResultListPanel(scrollPane);
+        scrollPane.setViewportView(resultListPanel);
+        resultListPanel.setFocusable(true);
+        resultListPanel.addFocusListener(new FocusListener() {
+            public void focusLost(FocusEvent e) {
+                logger.debug("Result list lost focus");
+            }
+            public void focusGained(FocusEvent e) {
+                logger.debug("Result list gained focus");
+            }
+        });
         resultListPanel.addKeyListener(pageListener);
resultListPanel.setBackground(UIManager.getColor("List.background")); //$NON-NLS-1$
         resultListPanel.setLayout(new GridLayout(0, 1));
@@ -315,8 +454,8 @@
             showingRows.add(myRowComponent);
         }

-        scrollPane = new JScrollPane(resultListPanel);
         scrollPane.getViewport().setBackground(Color.WHITE);
+        scrollPane.getViewport().setFocusable(true);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
         add(scrollPane, BorderLayout.CENTER);

@@ -339,22 +478,6 @@
         };
         bottomPanel.add(new JButton(viewAllAction));

- Action viewSelectedAction = new AbstractAction(Messages.getString("ProfileManagerView.viewSelectedActionName")) { //$NON-NLS-1$
-
-            public void actionPerformed(ActionEvent e) {
-                ProfileResultsViewer profileResultsViewer =
-                    new ProfileResultsViewer(pm);
-                profileResultsViewer.clearScanList();
-                for (ProfileRowComponent rowComp : showingRows) {
-                    if (rowComp.isSelected()) {
-                        TableProfileResult result = rowComp.getResult();
- profileResultsViewer.addTableProfileResultToScan(result);
-                        profileResultsViewer.addTableProfileResult(result);
-                    }
-                }
-                profileResultsViewer.getDialog().setVisible(true);
-            }
-        };
         bottomPanel.add(new JButton(viewSelectedAction));

         statusText = new JLabel();
@@ -409,6 +532,7 @@
         }
         pm.setProcessingOrder(tableProfileResults);
         resultListPanel.revalidate();
+        logger.debug("Showing rows has contents " + showingRows);
     }

     /**

Modified: trunk/src/ca/sqlpower/architect/swingui/ProfileRowComponent.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/ProfileRowComponent.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/ProfileRowComponent.java Thu Jan 8 08:55:37 2009
@@ -26,13 +26,16 @@
 import java.awt.LayoutManager2;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
 import java.awt.event.InputEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.ArrayList;
 import java.util.List;

-import javax.swing.BorderFactory;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
 import javax.swing.JComponent;
@@ -40,6 +43,8 @@
 import javax.swing.JPanel;
 import javax.swing.JProgressBar;
 import javax.swing.UIManager;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;

 import org.apache.log4j.Logger;

@@ -299,21 +304,7 @@
             Object obj = evt.getSource();
             if (evt.getButton() == MouseEvent.BUTTON1) {
                 if (evt.getClickCount() == 2) {
-                    if (getResult().getException() != null) {
-                        ASUtils.showExceptionDialogNoReport(
-                                ProfileRowComponent.this,
- "Profiling failed for table " + getResult().getProfiledObject(),
-                                getResult().getException());
- } else if (getResult().getProgressMonitor().isFinished() && - !getResult().getProgressMonitor().isCancelled() &&
-                                    !(obj instanceof JButton)) {
-                        ProfileResultsViewer profileResultsViewer =
- new ProfileResultsViewer((ProfileManagerImpl) pm);
-                        profileResultsViewer.clearScanList();
- profileResultsViewer.addTableProfileResultToScan(result);
-                        profileResultsViewer.addTableProfileResult(result);
-                        profileResultsViewer.getDialog().setVisible(true);
-                    }
+                    showProfile(obj);
} else if ((evt.getModifiers() & InputEvent.CTRL_MASK) != 0){ setSelected(!selected, SelectionEvent.CTRL_MULTISELECT); } else if ((evt.getModifiers() & InputEvent.SHIFT_MASK) != 0){
@@ -326,6 +317,28 @@
     }

     /**
+     * This will show the profile for a specific table (the source) or
+     * an exception if the profile failed.
+     */
+    private void showProfile(Object source) {
+        if (getResult().getException() != null) {
+            ASUtils.showExceptionDialogNoReport(
+                    ProfileRowComponent.this,
+ "Profiling failed for table " + getResult().getProfiledObject(),
+                    getResult().getException());
+        } else if (getResult().getProgressMonitor().isFinished() &&
+                        !getResult().getProgressMonitor().isCancelled() &&
+                        !(source instanceof JButton)) {
+            ProfileResultsViewer profileResultsViewer =
+                new ProfileResultsViewer((ProfileManagerImpl) pm);
+            profileResultsViewer.clearScanList();
+            profileResultsViewer.addTableProfileResultToScan(result);
+            profileResultsViewer.addTableProfileResult(result);
+            profileResultsViewer.getDialog().setVisible(true);
+        }
+    }
+
+    /**
* Listens for changes in the profile's state (started, cancelled, finished)
      * and makes the appropriate UI updates on this component.
      */
@@ -387,11 +400,24 @@
         super(new RowComponentLayout(5, 5));
         this.result = result;
         this.pm = pm;
-        setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
+        setBorder(new EmptyBorder(4, 4, 4, 4));
         setBackground(Color.WHITE);

         add(new JLabel(tableIcon), ComponentType.ICON);

+        addFocusListener(new FocusListener() {
+
+            public void focusLost(FocusEvent e) {
+                setBorder(new EmptyBorder(4, 4, 4, 4));
+ logger.debug("Focus lost on " + result.getProfiledObject().getName() + " bounds are " + getBounds());
+            }
+
+            public void focusGained(FocusEvent e) {
+                setBorder(new LineBorder(Color.BLACK));
+ logger.debug("Focus gained on " + result.getProfiledObject().getName() + " bounds are " + getBounds());
+            }
+        });
+
         this.reProfileButton = new JButton(refreshIcon);
         reProfileButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
@@ -411,15 +437,16 @@
             }
         });

-        this.deleteButton = new JButton(deleteIcon);
-        deleteButton.addActionListener(new ActionListener() {
+        Action deleteAction = new AbstractAction() {
             public void actionPerformed(ActionEvent e) {
logger.debug("ProfileRowComponent: DELETE object: " + result);
                 pm.removeProfile(result);
             }
-        });
+        };
+        deleteButton = new JButton(deleteAction);
+        deleteButton.setIcon(deleteIcon);
         add(deleteButton, ComponentType.DELETE);
-
+
         SQLTable table = result.getProfiledObject();

         StringBuilder tableName = new StringBuilder();
@@ -462,6 +489,11 @@
     private final JProgressBar progressBar = new JProgressBar();

     public void setSelected(boolean v,int selectionType) {
+ logger.debug("Is this profile row component focusable? " + isFocusable());
+        logger.debug("Does this panel have focus? " + isFocusOwner());
+        if (v) {
+            requestFocusInWindow();
+        }
         selected = v;
setBackground(selected ? UIManager.getColor("List.selectionBackground"): UIManager.getColor("List.background")); fireSelectionEvent(new SelectionEvent(ProfileRowComponent.this, selected ? SelectionEvent.SELECTION_EVENT : SelectionEvent.DESELECTION_EVENT,selectionType));
@@ -504,5 +536,10 @@
         for (int i = profileListeners.size() - 1; i >= 0; i--) {
             profileListeners.get(i).profileListChanged(e);
         }
+    }
+
+    @Override
+    public String toString() {
+ return result.getProfiledObject().getName() + " with status " + statusLabel.getText();
     }
 }

Reply via email to