Revision: 1149
Author:   anodos
Date:     2006-05-12 11:55:59 -0700 (Fri, 12 May 2006)
ViewCVS:  http://svn.sourceforge.net/spring-rich-c/?rev=1149&view=rev

Log Message:
-----------
Fixes RCP-344, "OverlayHelper does not proxy Scrollable interface when 
inserting overlay (JLayeredPane)"
- OverlayHelper will now check a JScrollPane's viewport view to see if it 
implements Scrollable.  If so, then, when replacing the view with its layered 
pane, it will use a layered pane that implements Scrollable and proxies the 
methods to the underlying (original) view.
- Modified OverlayHelper's custom layout manager to better handle Scrollable's 
flags: instead of trying to determine the layout size of the underlying view, 
it simply trusts that the viewport resized it (the layered pane) correctly, and 
passes that on to the underlying view.
- Created a regression test for this bug (see OverlayHelperTests).

Modified Paths:
--------------
    
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/util/OverlayHelper.java

Added Paths:
-----------
    
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/util/OverlayHelperTests.java
Modified: 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/util/OverlayHelper.java
===================================================================
--- 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/util/OverlayHelper.java
        2006-05-12 01:41:49 UTC (rev 1148)
+++ 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/util/OverlayHelper.java
        2006-05-12 18:55:59 UTC (rev 1149)
@@ -34,6 +34,7 @@
 import javax.swing.JRootPane;
 import javax.swing.JViewport;
 import javax.swing.SwingConstants;
+import javax.swing.Scrollable;
 
 /**
  * A helper class that attaches one component (the overlay) on top of another
@@ -42,8 +43,8 @@
  * @author oliverh
  */
 public class OverlayHelper implements SwingConstants {
-    private static final String LAYERED_PANE_PROPERTY = "overlayLayeredPane";
-
+    private static final String LAYERED_PANE_PROPERTY = "overlayLayeredPane";
+
     private final OverlayTargetChangeHandler overlayTargetChangeHandler = new 
OverlayTargetChangeHandler();
 
     private final OverlayChangeHandler overlayChangeHandler = new 
OverlayChangeHandler();
@@ -236,7 +237,7 @@
         }
         Dimension size = overlay.getPreferredSize();
         Rectangle newBound = new Rectangle(centerX - (size.width / 2), centerY 
- (size.height / 2), size.width,
-                size.height);
+                                           size.height);
         setOverlayBounds(newBound);
     }
 
@@ -253,7 +254,7 @@
     protected Container getOverlayCapableParent(JComponent component) {
         Container overlayCapableParent = component.getParent();
         while (overlayCapableParent != null && !(overlayCapableParent 
instanceof JRootPane)
-                && !(overlayCapableParent instanceof JViewport)) {
+               && !(overlayCapableParent instanceof JViewport)) {
             overlayCapableParent = overlayCapableParent.getParent();
         }
         return overlayCapableParent;
@@ -265,17 +266,21 @@
         }
         else if (overlayCapableParent instanceof JViewport) {
             JViewport viewPort = (JViewport)overlayCapableParent;
-            JLayeredPane layeredPane = 
(JLayeredPane)viewPort.getClientProperty(LAYERED_PANE_PROPERTY);
+            JLayeredPane layeredPane = 
(JLayeredPane)viewPort.getClientProperty(LAYERED_PANE_PROPERTY);
             Component view = viewPort.getView();
             // check if we already have a layeredPane installed and if it's 
still available
-            if ((layeredPane != null) && (view == layeredPane)) 
-                return layeredPane;
+            if ((layeredPane != null) && (view == layeredPane))
+                return layeredPane;
 
             // no layeredPane or it was removed at some point, so construct a 
new one
-            layeredPane = new JLayeredPane();
-            viewPort.putClientProperty(LAYERED_PANE_PROPERTY, layeredPane);
+            if(view instanceof Scrollable) {
+                layeredPane = new 
ScrollableProxyingLayeredPane((Scrollable)view);
+            } else {
+                layeredPane = new JLayeredPane();
+            }
+            viewPort.putClientProperty(LAYERED_PANE_PROPERTY, layeredPane);
             viewPort.remove(view);
-            layeredPane.setLayout(new SingleComponentLayoutManager(view, 
viewPort));
+            layeredPane.setLayout(new SingleComponentLayoutManager(view));
             layeredPane.add(view);
             layeredPane.setLayer(view, JLayeredPane.DEFAULT_LAYER.intValue());
             viewPort.setView(layeredPane);
@@ -283,18 +288,15 @@
         }
         else {
             throw new IllegalArgumentException("Don't know how to handle 
parent of type ["
-                    + overlayCapableParent.getClass().getName() + "].");
+                                               + 
overlayCapableParent.getClass().getName() + "].");
         }
     }
 
     public static class SingleComponentLayoutManager implements LayoutManager {
         private Component singleComponent;
 
-        private JViewport viewport;
-
-        public SingleComponentLayoutManager(Component singleComponent, 
JViewport viewport) {
+        public SingleComponentLayoutManager(Component singleComponent) {
             this.singleComponent = singleComponent;
-            this.viewport = viewport;
         }
 
         public void removeLayoutComponent(Component comp) {
@@ -304,12 +306,13 @@
         }
 
         public void layoutContainer(Container parent) {
-            final Dimension prefSize = singleComponent.getPreferredSize();
-            final Dimension viewSize = viewport.getExtentSize();
-            final int maxWidth = Math.max(prefSize.width, viewSize.width);
-            final int maxHeight = Math.max(prefSize.height, viewSize.height);
-
-            singleComponent.setBounds(0, 0, maxWidth, maxHeight);
+            // Fix 5/12/06 AlD: we don't need to base this on the
+            // preferred size of the singleComponent or the extentSize
+            // of the viewport because the viewport will have already resized
+            // the JLayeredPane and taken everything else into consideration.
+            // It will have also honored the Scrollable flags, which is
+            // something the original code here did not do.
+            singleComponent.setBounds(0, 0, parent.getWidth(), 
parent.getHeight());
         }
 
         public Dimension minimumLayoutSize(Container parent) {
@@ -320,4 +323,42 @@
             return singleComponent.getPreferredSize();
         }
     }
+
+
+
+
+    public static class ScrollableProxyingLayeredPane extends JLayeredPane
+        implements Scrollable {
+        private final Scrollable scrollableDelegate;
+
+        public ScrollableProxyingLayeredPane(final Scrollable delegate) {
+            super();
+            this.scrollableDelegate = delegate;
+        }
+        
+        
+        //
+        // METHODS FROM INTERFACE Scrollable
+        //
+
+        public Dimension getPreferredScrollableViewportSize() {
+            return 
this.scrollableDelegate.getPreferredScrollableViewportSize();
+        }
+
+        public int getScrollableUnitIncrement(Rectangle visibleRect, int 
orientation, int direction) {
+            return 
this.scrollableDelegate.getScrollableUnitIncrement(visibleRect, orientation, 
direction);
+        }
+
+        public int getScrollableBlockIncrement(Rectangle visibleRect, int 
orientation, int direction) {
+            return 
this.scrollableDelegate.getScrollableBlockIncrement(visibleRect, orientation, 
direction);
+        }
+
+        public boolean getScrollableTracksViewportWidth() {
+            return this.scrollableDelegate.getScrollableTracksViewportWidth();
+        }
+
+        public boolean getScrollableTracksViewportHeight() {
+            return this.scrollableDelegate.getScrollableTracksViewportHeight();
+        }
+    }
 }
\ No newline at end of file

Added: 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/util/OverlayHelperTests.java
===================================================================
--- 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/util/OverlayHelperTests.java
                           (rev 0)
+++ 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/util/OverlayHelperTests.java
   2006-05-12 18:55:59 UTC (rev 1149)
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2002-2004 the original author or authors.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy 
of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations 
under
+ * the License.
+ */
+package org.springframework.richclient.util;
+
+import java.awt.LayoutManager;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.BorderLayout;
+import java.awt.Component;
+
+import javax.swing.JPanel;
+import javax.swing.Scrollable;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.JLabel;
+import javax.swing.JComponent;
+
+import org.springframework.richclient.test.SpringRichTestCase;
+
+/**
+ * @author andy
+ * @since May 12, 2006 8:32:27 AM
+ */
+public class OverlayHelperTests extends SpringRichTestCase {
+    /**
+    * OverlayHelper installs the overlay as the View of a JScrollPane viewport,
+    * if the component is in a JScrollPane, so that the overlay is shown in
+    * the proper location when scrolled.  However, to accomplish this, it will
+    * remove the component that was in the viewport, add it to a JLayeredPane,
+    * and then add that JLayeredPane to the viewport instead. This introduced
+    * a bug if the viewport's view happened to implement the Scrollable
+    * interface, since JScrollPane does <i>not</i> implement the Scrollable
+    * interface.  See issue RCP-344.
+    */
+    public void testRegressionScrollableProxy() {
+        performScrollableTest();
+        performNonScrollableTest();
+    }
+
+    /**
+     * Ensures that OverlayHelper supports the Scrollable interface and
+     * properly proxies Scrollable methods.
+     */
+    private void performScrollableTest() {
+        final ScrollablePanel view = new ScrollablePanel(new BorderLayout());
+        view.setScrollableUnitIncrement(5);
+        view.setScrollableBlockIncrement(30);
+        view.setScrollableTracksViewportWidth(true);
+        
+        final JComponent overlay = createTestOverlay();
+        final JComponent someField = createTestComponent();
+
+        OverlayHelper.attachOverlay(overlay, someField, 0, 0, 0);
+        
+        view.add(someField);
+        
+        final JScrollPane scrollPane = new JScrollPane(view);
+        
+        final Component viewportView = scrollPane.getViewport().getView();
+
+        // If OverlayHelper changes the way it handles scrollable overlays,
+        // then the test will need to be revisited - this makes sure it
+        // won't get ignored. :)
+        assertFalse(viewportView == view);
+
+        assertTrue(viewportView instanceof Scrollable);
+        
assertTrue(((Scrollable)viewportView).getScrollableTracksViewportWidth());
+        
assertFalse(((Scrollable)viewportView).getScrollableTracksViewportHeight());
+        assertEquals(5, 
((Scrollable)viewportView).getScrollableUnitIncrement(null, 0, 0));
+        assertEquals(30, 
((Scrollable)viewportView).getScrollableBlockIncrement(null, 0, 0));
+        assertEquals(view.getPreferredScrollableViewportSize(), 
((Scrollable)viewportView).getPreferredScrollableViewportSize());
+    }
+
+    /**
+     * Ensures that OverlayHelper will NOT implement the Scrollable
+     * interface if the view component does not implement the Scrollable
+     * interface.
+     */
+    private void performNonScrollableTest() {
+        final JPanel view = new JPanel(new BorderLayout());
+        final JComponent overlay = createTestOverlay();
+        final JComponent someField = createTestComponent();
+        
+        OverlayHelper.attachOverlay(overlay, someField, 0, 0, 0);
+        
+        view.add(someField);
+        final JScrollPane scrollPane = new JScrollPane(view);
+        
+        final Component viewportView = scrollPane.getViewport().getView();
+        assertFalse(viewportView == view);
+        assertFalse(viewportView instanceof Scrollable);
+    }
+    
+    
+    
+    
+    
+    public void testSwapScrollableForNonScrollable() {
+        JComponent view = new ScrollablePanel(new BorderLayout());
+        
+        final JComponent overlay = createTestOverlay();
+        final JComponent someField = createTestComponent();
+
+        OverlayHelper.attachOverlay(overlay, someField, 0, 0, 0);
+        
+        view.add(someField);
+        
+        final JScrollPane scrollPane = new JScrollPane(view);
+        
+        Component viewportView = scrollPane.getViewport().getView();
+        assertFalse(viewportView == view);
+        assertTrue(viewportView instanceof Scrollable);
+        
+        view.remove(someField);
+        view = new JPanel(new BorderLayout());
+        view.add(someField);
+        scrollPane.setViewportView(view);
+        
+        viewportView = scrollPane.getViewport().getView();
+        assertFalse(viewportView == view);
+        assertFalse(viewportView instanceof Scrollable);
+        
+        view.remove(someField);
+        view = new ScrollablePanel(new BorderLayout());
+        view.add(someField);
+        scrollPane.setViewportView(view);
+        
+        viewportView = scrollPane.getViewport().getView();
+        assertFalse(viewportView == view);
+        assertTrue(viewportView instanceof Scrollable);
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    private JComponent createTestComponent() {
+        return new JTextField("Hello, world!") {
+            // This is to force the OverlayHelper to install the overlay,
+            // even though we don't have a UI visible.
+            public boolean isVisible() {
+                return true;
+            }
+            public boolean isShowing() {
+                return true;
+            }
+        };
+    }
+
+    private JComponent createTestOverlay() {
+        final JComponent overlay = new JLabel("x") {
+            // This is to force the OverlayHelper to install the overlay,
+            // even though we don't have a UI visible.
+            public boolean isVisible() {
+                return true;
+            }
+            public boolean isShowing() {
+                return true;
+            }
+        };
+        overlay.setOpaque(false);
+        return overlay;
+    }
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    public static class ScrollablePanel extends JPanel implements Scrollable {
+        private int scrollableUnitIncrement = 10;
+        private int scrollableBlockIncrement = 40;
+        private boolean scrollableTracksViewportWidth = false;
+        private boolean scrollableTracksViewportHeight = false;
+
+        public ScrollablePanel(LayoutManager layout, boolean isDoubleBuffered) 
{
+            super(layout, isDoubleBuffered);
+        }
+
+        public ScrollablePanel(LayoutManager layout) {
+            super(layout);
+        }
+
+        public ScrollablePanel(boolean isDoubleBuffered) {
+            super(isDoubleBuffered);
+        }
+
+        public ScrollablePanel() {
+        }
+
+
+        public void setScrollableUnitIncrement(final int 
scrollableUnitIncrement) {
+            this.scrollableUnitIncrement = scrollableUnitIncrement;
+        }
+
+        public void setScrollableBlockIncrement(final int 
scrollableBlockIncrement) {
+            this.scrollableBlockIncrement = scrollableBlockIncrement;
+        }
+
+        public void setScrollableTracksViewportWidth(final boolean 
scrollableTracksViewportWidth) {
+            this.scrollableTracksViewportWidth = scrollableTracksViewportWidth;
+        }
+
+        public void setScrollableTracksViewportHeight(final boolean 
scrollableTracksViewportHeight) {
+            this.scrollableTracksViewportHeight = 
scrollableTracksViewportHeight;
+        }
+
+
+
+        public Dimension getPreferredScrollableViewportSize() {
+            return getPreferredSize();
+        }
+
+        public int getScrollableUnitIncrement(Rectangle visibleRect, int 
orientation, int direction) {
+            return this.scrollableUnitIncrement;
+        }
+
+        public int getScrollableBlockIncrement(Rectangle visibleRect, int 
orientation, int direction) {
+            return this.scrollableBlockIncrement;
+        }
+
+        public boolean getScrollableTracksViewportWidth() {
+            return this.scrollableTracksViewportWidth;
+        }
+
+        public boolean getScrollableTracksViewportHeight() {
+            return this.scrollableTracksViewportHeight;
+        }
+    }
+}


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



-------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
spring-rich-c-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spring-rich-c-cvs

Reply via email to