From 7bb144d1607a73e58d168f79e2de48bc69a9f839 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Thu, 05 Feb 2009 13:05:53 +0000
Subject: [PATCH] Update the code so that the scroll positions are maintained after the contents of the panels are updated.  This way, even if configuration or monitoring information are changed, there are no sudden changes of the scroll position which was quite annoying.

---
 opends/src/guitools/org/opends/guitools/controlpanel/ui/RebuildIndexPanel.java |   18 +++
 opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusPanel.java       |   17 +++
 opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseIndexPanel.java  |   26 ++++
 opends/src/guitools/org/opends/guitools/controlpanel/util/ViewPositions.java   |   93 ++++++++++++++++++
 opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java |   40 ++++++-
 opends/src/guitools/org/opends/guitools/controlpanel/ui/VerifyIndexPanel.java  |   16 +++
 opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java       |   86 +++++++++++++++++
 7 files changed, 284 insertions(+), 12 deletions(-)

diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseIndexPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseIndexPanel.java
index b542cbe..3bc4754 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseIndexPanel.java
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseIndexPanel.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2008-2009 Sun Microsystems, Inc.
  */
 
 package org.opends.guitools.controlpanel.ui;
@@ -33,6 +33,7 @@
 import java.awt.Dimension;
 import java.awt.GridBagConstraints;
 import java.awt.Insets;
+import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
@@ -79,6 +80,7 @@
 import org.opends.guitools.controlpanel.ui.nodes.VLVIndexTreeNode;
 import org.opends.guitools.controlpanel.ui.renderer.TreeCellRenderer;
 import org.opends.guitools.controlpanel.util.Utilities;
+import org.opends.guitools.controlpanel.util.ViewPositions;
 import org.opends.messages.Message;
 
 /**
@@ -96,6 +98,8 @@
   private IndexBrowserRightPanel entryPane;
   private TreePanel treePane;
 
+  private JScrollPane treeScroll;
+
   private JButton newIndex;
   private JButton newVLVIndex;
 
@@ -309,7 +313,7 @@
     Utilities.setBorder(treePane, new EmptyBorder(10, 0, 10, 0));
 
     entryPane = new IndexBrowserRightPanel();
-    JScrollPane treeScroll = Utilities.createScrollPane(treePane);
+    treeScroll = Utilities.createScrollPane(treePane);
 
     entryPane.addIndexSelectionListener(new IndexSelectionListener()
     {
@@ -580,6 +584,8 @@
   private void repopulateTree(JTree tree)
   {
     ignoreSelectionEvents = true;
+
+    final Point currentPosition = treeScroll.getViewport().getViewPosition();
     DefaultMutableTreeNode root = getRoot(tree);
 
     TreePath path = tree.getSelectionPath();
@@ -710,6 +716,20 @@
 
     updateEntryPane();
 
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        if (firstTreeRepopulate)
+        {
+          treeScroll.getViewport().setViewPosition(new Point(0, 0));
+        }
+        else
+        {
+          treeScroll.getViewport().setViewPosition(currentPosition);
+        }
+      }
+    });
     firstTreeRepopulate = false;
     ignoreSelectionEvents = false;
   }
@@ -720,6 +740,7 @@
    */
   private void updateEntryPane()
   {
+    ViewPositions pos = Utilities.getViewPositions(entryPane);
     TreePath[] paths = treePane.getTree().getSelectionPaths();
     TreePath path = null;
     if ((paths != null) && (paths.length == 1))
@@ -765,6 +786,7 @@
         entryPane.displayVoid();
       }
     }
+    Utilities.updateViewPositions(pos);
   }
 
   private DefaultMutableTreeNode getRoot(JTree tree)
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java
index 6c99cf2..5a54ecc 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2008-2009 Sun Microsystems, Inc.
  */
 
 package org.opends.guitools.controlpanel.ui;
@@ -34,6 +34,7 @@
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Insets;
+import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyAdapter;
@@ -82,6 +83,7 @@
 import org.opends.guitools.controlpanel.ui.renderer.TreeCellRenderer;
 import org.opends.guitools.controlpanel.util.LowerCaseComparator;
 import org.opends.guitools.controlpanel.util.Utilities;
+import org.opends.guitools.controlpanel.util.ViewPositions;
 import org.opends.messages.Message;
 import org.opends.server.api.AttributeSyntax;
 import org.opends.server.api.MatchingRule;
@@ -110,6 +112,8 @@
   private SchemaBrowserRightPanel entryPane;
   private TreePanel treePane;
 
+  private JScrollPane treeScroll;
+
   private TreePath lastEntryTreePath;
 
   private Schema lastSchema;
@@ -317,7 +321,7 @@
         if ((e.getKeyCode() == KeyEvent.VK_ENTER) && applyButton.isEnabled())
         {
           filter.displayRefreshIcon(FilterTextField.DEFAULT_REFRESH_ICON_TIME);
-          repopulateTree(treePane.getTree());
+          repopulateTree(treePane.getTree(), false);
         }
       }
     });
@@ -329,7 +333,7 @@
       public void actionPerformed(ActionEvent ev)
       {
         filter.displayRefreshIcon(FilterTextField.DEFAULT_REFRESH_ICON_TIME);
-        repopulateTree(treePane.getTree());
+        repopulateTree(treePane.getTree(), false);
       }
     });
     gbc.gridx ++;
@@ -351,7 +355,7 @@
       public void actionPerformed(ActionEvent ev)
       {
         filter.displayRefreshIcon(FilterTextField.DEFAULT_REFRESH_ICON_TIME);
-        repopulateTree(treePane.getTree());
+        repopulateTree(treePane.getTree(), false);
       }
     });
 
@@ -479,7 +483,7 @@
     Utilities.setBorder(lNoMatchFound, new EmptyBorder(15, 15, 15, 15));
     gbc.fill = GridBagConstraints.HORIZONTAL;
     p.add(lNoMatchFound, gbc);
-    JScrollPane treeScroll = Utilities.createScrollPane(p);
+    treeScroll = Utilities.createScrollPane(p);
 
     entryPane.addSchemaElementSelectionListener(
         new SchemaElementSelectionListener()
@@ -608,6 +612,7 @@
   public void configurationChanged(ConfigurationChangeEvent ev)
   {
     final ServerDescriptor desc = ev.getNewDescriptor();
+    final boolean forceScroll = lastSchema == null;
     if ((lastSchema == null) ||
         !ServerDescriptor.areSchemasEqual(lastSchema, desc.getSchema())||
         true)
@@ -619,7 +624,7 @@
         {
           public void run()
           {
-            repopulateTree(treePane.getTree());
+            repopulateTree(treePane.getTree(), forceScroll);
           }
         });
       }
@@ -676,14 +681,18 @@
   /**
    * Repopulates the tree.
    * @param tree the tree to be repopulated.
+   * @param forceScroll whether the scroll must be reset or not.
    */
-  private void repopulateTree(JTree tree)
+  private void repopulateTree(JTree tree, final boolean forceScroll)
   {
     if (lastSchema == null)
     {
       return;
     }
     ignoreSelectionEvents = true;
+
+    final Point currentPosition = treeScroll.getViewport().getViewPosition();
+
     DefaultMutableTreeNode root = getRoot(tree);
 
     TreePath path = tree.getSelectionPath();
@@ -1023,6 +1032,21 @@
       }
     }
     repaint();
+
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        if (forceScroll)
+        {
+          treeScroll.getViewport().setViewPosition(new Point(0, 0));
+        }
+        else
+        {
+          treeScroll.getViewport().setViewPosition(currentPosition);
+        }
+      }
+    });
   }
 
   /**
@@ -1031,6 +1055,7 @@
    */
   private void updateEntryPane()
   {
+    ViewPositions pos = Utilities.getViewPositions(entryPane);
     TreePath[] paths = treePane.getTree().getSelectionPaths();
     TreePath path = null;
     if ((paths != null) && (paths.length == 1))
@@ -1123,6 +1148,7 @@
         entryPane.displayMessage(NO_SCHEMA_ITEM_SELECTED);
       }
     }
+    Utilities.updateViewPositions(pos);
   }
 
   /**
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/RebuildIndexPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/RebuildIndexPanel.java
index 6ee5966..5771488 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/RebuildIndexPanel.java
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/RebuildIndexPanel.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2008-2009 Sun Microsystems, Inc.
  */
 
 package org.opends.guitools.controlpanel.ui;
@@ -41,6 +41,7 @@
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
+import javax.swing.JScrollPane;
 import javax.swing.ListCellRenderer;
 import javax.swing.SwingUtilities;
 
@@ -59,6 +60,7 @@
 import org.opends.guitools.controlpanel.ui.renderer.CustomListCellRenderer;
 import org.opends.guitools.controlpanel.ui.renderer.IndexCellRenderer;
 import org.opends.guitools.controlpanel.util.Utilities;
+import org.opends.guitools.controlpanel.util.ViewPositions;
 import org.opends.messages.Message;
 
 /**
@@ -256,11 +258,25 @@
        */
       public void run()
       {
+        ViewPositions pos;
+        JScrollPane scroll =
+          Utilities.getContainingScroll(RebuildIndexPanel.this);
+        if (scroll != null)
+        {
+          pos = Utilities.getViewPositions(scroll);
+        }
+        else
+        {
+          pos = Utilities.getViewPositions(RebuildIndexPanel.this);
+        }
+
         boolean comboVisible = baseDNs.getModel().getSize() > 0;
         baseDNs.setVisible(comboVisible);
         lNoBaseDNsFound.setVisible(!comboVisible);
         addRemove.getAvailableList().repaint();
         addRemove.getSelectedList().repaint();
+
+        Utilities.updateViewPositions(pos);
       }
     });
   }
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusPanel.java
index 2b8aab8..43cfbb8 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusPanel.java
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusPanel.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2008-2009 Sun Microsystems, Inc.
  */
 
 package org.opends.guitools.controlpanel.ui;
@@ -49,6 +49,7 @@
 import javax.swing.JComponent;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
+import javax.swing.JScrollPane;
 import javax.swing.JTable;
 import javax.swing.SwingConstants;
 import javax.swing.SwingUtilities;
@@ -64,6 +65,7 @@
 import org.opends.guitools.controlpanel.ui.renderer.BaseDNCellRenderer;
 import org.opends.guitools.controlpanel.ui.renderer.CustomCellRenderer;
 import org.opends.guitools.controlpanel.util.Utilities;
+import org.opends.guitools.controlpanel.util.ViewPositions;
 import org.opends.messages.Message;
 import org.opends.messages.MessageBuilder;
 import org.opends.server.types.DN;
@@ -232,6 +234,17 @@
    */
   public void updateContents(ServerDescriptor desc)
   {
+    JScrollPane scroll = Utilities.getContainingScroll(this);
+    ViewPositions pos;
+    if (scroll != null)
+    {
+      pos = Utilities.getViewPositions(scroll);
+    }
+    else
+    {
+      pos = Utilities.getViewPositions(this);
+    }
+
     Collection<OpenDsException> exceptions = desc.getExceptions();
     if (exceptions.size() == 0)
     {
@@ -412,6 +425,8 @@
     authenticate.setVisible(!isAuthenticated && isRunning);
 
     recalculateSizes();
+
+    Utilities.updateViewPositions(pos);
   }
 
   /**
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/VerifyIndexPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/VerifyIndexPanel.java
index a9e9535..8b4fcb1 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/VerifyIndexPanel.java
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/VerifyIndexPanel.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2008-2009 Sun Microsystems, Inc.
  */
 
 package org.opends.guitools.controlpanel.ui;
@@ -46,6 +46,7 @@
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
 import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
 import javax.swing.ListCellRenderer;
 import javax.swing.SwingUtilities;
 
@@ -67,6 +68,7 @@
 import org.opends.guitools.controlpanel.ui.renderer.IndexCellRenderer;
 import org.opends.guitools.controlpanel.ui.renderer.IndexComboBoxCellRenderer;
 import org.opends.guitools.controlpanel.util.Utilities;
+import org.opends.guitools.controlpanel.util.ViewPositions;
 import org.opends.messages.Message;
 
 /**
@@ -304,6 +306,17 @@
        */
       public void run()
       {
+        ViewPositions pos;
+        JScrollPane scroll =
+          Utilities.getContainingScroll(VerifyIndexPanel.this);
+        if (scroll != null)
+        {
+          pos = Utilities.getViewPositions(scroll);
+        }
+        else
+        {
+          pos = Utilities.getViewPositions(VerifyIndexPanel.this);
+        }
         comboBoxSelected(hmIndexes,
             (CategorizedComboBoxElement)baseDNs.getSelectedItem(),
             addRemove);
@@ -313,6 +326,7 @@
         boolean comboVisible = baseDNs.getModel().getSize() > 0;
         baseDNs.setVisible(comboVisible);
         lNoBaseDNsFound.setVisible(!comboVisible);
+        Utilities.updateViewPositions(pos);
       }
     });
   }
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java b/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java
index 7f80f0c..84854a2 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java
@@ -31,9 +31,11 @@
 
 import java.awt.Color;
 import java.awt.Component;
+import java.awt.Container;
 import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.Image;
+import java.awt.Point;
 import java.awt.Toolkit;
 import java.awt.Window;
 import java.awt.event.MouseAdapter;
@@ -73,6 +75,7 @@
 import javax.swing.JTextArea;
 import javax.swing.JTextField;
 import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
 import javax.swing.border.Border;
 import javax.swing.border.EmptyBorder;
 import javax.swing.border.EtchedBorder;
@@ -2101,4 +2104,87 @@
     label.setIcon(requiredIcon);
     label.setHorizontalTextPosition(SwingConstants.LEADING);
   }
+
+
+  /**
+   * Updates the scrolls with the provided points.
+   * This method uses SwingUtilities.invokeLater so it can be also called
+   * outside the event thread.
+   * @param pos the scroll and points.
+   */
+  public static void updateViewPositions(final ViewPositions pos)
+  {
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        for (int i=0; i<pos.size(); i++)
+        {
+          pos.getScrollPane(i).getViewport().setViewPosition(pos.getPoint(i));
+        }
+      }
+    });
+  }
+
+  /**
+   * Gets the view positions object for the provided component.  This includes
+   * all the scroll panes inside the provided component.
+   * @param comp the component.
+   * @return the view positions for the provided component.
+   */
+  public static ViewPositions getViewPositions(Component comp)
+  {
+    ViewPositions pos = new ViewPositions();
+    if (comp instanceof Container)
+    {
+      updateContainedViewPositions((Container)comp, pos);
+    }
+    return pos;
+  }
+
+  /**
+   * Returns the scrolpane where the provided component is contained.
+   * <CODE>null</CODE> if the component is not contained in any scrolpane.
+   * @param comp the component.
+   * @return the scrolpane where the provided component is contained.
+   */
+  public static JScrollPane getContainingScroll(Component comp)
+  {
+    JScrollPane scroll = null;
+    Container parent = comp.getParent();
+    while ((scroll == null) && (parent != null))
+    {
+      if (parent instanceof JScrollPane)
+      {
+        scroll = (JScrollPane)parent;
+      }
+      else
+      {
+        parent = parent.getParent();
+      }
+    }
+    return scroll;
+  }
+
+  private static void updateContainedViewPositions(Container comp,
+      ViewPositions pos)
+  {
+    if (comp instanceof JScrollPane)
+    {
+      JScrollPane scroll = (JScrollPane)comp;
+      Point p = scroll.getViewport().getViewPosition();
+      pos.add(scroll, p);
+    }
+    else
+    {
+      for (int i=0; i<comp.getComponentCount(); i++)
+      {
+        Component child = comp.getComponent(i);
+        if (child instanceof Container)
+        {
+          updateContainedViewPositions((Container)child, pos);
+        }
+      }
+    }
+  }
 }
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/util/ViewPositions.java b/opends/src/guitools/org/opends/guitools/controlpanel/util/ViewPositions.java
new file mode 100644
index 0000000..f6b4ba6
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/util/ViewPositions.java
@@ -0,0 +1,93 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+package org.opends.guitools.controlpanel.util;
+
+import java.awt.Point;
+import java.util.ArrayList;
+
+import javax.swing.JScrollPane;
+
+/**
+ * A class used to be able to update the scroll position in different panels.
+ * It basically contains two lists of scrollbars and points.
+ *
+ */
+public class ViewPositions
+{
+  private ArrayList<JScrollPane> scrolls = new ArrayList<JScrollPane>();
+  private ArrayList<Point> points = new ArrayList<Point>();
+
+  /**
+   * Returns the size of the lists.
+   * @return the size of the lists.
+   */
+  public int size()
+  {
+    return scrolls.size();
+  }
+
+  /**
+   * Adds a pair of scrollbar and point to the list.
+   * @param scroll the scroll bar.
+   * @param p the point.
+   */
+  public void add(JScrollPane scroll, Point p)
+  {
+    scrolls.add(scroll);
+    points.add(p);
+  }
+
+  /**
+   * Clears the contents of both lists.
+   *
+   */
+  public void clear()
+  {
+    scrolls.clear();
+    points.clear();
+  }
+
+  /**
+   * Returns the point at the provided index.
+   * @param index the index.
+   * @return the point at the provided index.
+   */
+  public Point getPoint(int index)
+  {
+    return points.get(index);
+  }
+
+  /**
+   * Returns the scroll at the provided index.
+   * @param index the index.
+   * @return the scroll at the provided index.
+   */
+  public JScrollPane getScrollPane(int index)
+  {
+    return scrolls.get(index);
+  }
+}

--
Gitblit v1.10.0