1 /*
   2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.lwawt;
  27 
  28 import javax.swing.*;
  29 import javax.swing.event.ChangeListener;
  30 import javax.swing.event.ChangeEvent;
  31 import java.awt.*;
  32 import java.awt.event.MouseWheelEvent;
  33 import java.awt.peer.ScrollPanePeer;
  34 import java.util.List;
  35 
  36 final class LWScrollPanePeer extends LWContainerPeer<ScrollPane, JScrollPane>
  37         implements ScrollPanePeer, ChangeListener {
  38 
  39     LWScrollPanePeer(final ScrollPane target,
  40                      final PlatformComponent platformComponent) {
  41         super(target, platformComponent);
  42     }
  43 
  44     protected JScrollPane createDelegate() {
  45         final JScrollPane sp = new JScrollPane();
  46         final JPanel panel = new JPanel();
  47         panel.setOpaque(false);
  48         panel.setVisible(false);
  49         sp.getViewport().setView(panel);
  50         sp.setBorder(BorderFactory.createEmptyBorder());
  51         sp.getViewport().addChangeListener(this);
  52         return sp;
  53     }
  54 
  55     @Override
  56     public void stateChanged(final ChangeEvent e) {
  57         SwingUtilities.invokeLater(new Runnable() {
  58             @Override
  59             public void run() {
  60                 final LWComponentPeer viewPeer = getViewPeer();
  61                 if (viewPeer != null) {
  62                     final Rectangle r;
  63                     synchronized (getDelegateLock()) {
  64                         r = getDelegate().getViewport().getView().getBounds();
  65                     }
  66                     viewPeer.setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS,
  67                                        true, true);
  68                 }
  69             }
  70         });
  71     }
  72 
  73     @Override
  74     public void initialize() {
  75         super.initialize();
  76         final int policy = getTarget().getScrollbarDisplayPolicy();
  77         synchronized (getDelegateLock()) {
  78             getDelegate().getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
  79             getDelegate().setVerticalScrollBarPolicy(convertVPolicy(policy));
  80             getDelegate().setHorizontalScrollBarPolicy(convertHPolicy(policy));
  81         }
  82     }
  83 
  84     LWComponentPeer getViewPeer() {
  85         List<LWComponentPeer> peerList = getChildren();
  86         return peerList.isEmpty() ? null : peerList.get(0);
  87     }
  88 
  89 
  90     @Override
  91     protected Rectangle getContentSize() {
  92         Rectangle viewRect = getDelegate().getViewport().getViewRect();
  93         return new Rectangle(viewRect.width, viewRect.height);
  94     }
  95 
  96     @Override
  97     public void layout() {
  98         super.layout();
  99         synchronized (getDelegateLock()) {
 100             LWComponentPeer viewPeer = getViewPeer();
 101             if (viewPeer != null) {
 102                 Component view = getDelegate().getViewport().getView();
 103                 view.setBounds(viewPeer.getBounds());
 104                 view.setPreferredSize(viewPeer.getPreferredSize());
 105                 view.setMinimumSize(viewPeer.getMinimumSize());
 106                 getDelegate().invalidate();
 107                 getDelegate().validate();
 108                 viewPeer.setBounds(view.getBounds());
 109             }
 110         }
 111     }
 112 
 113     @Override
 114     public void handleEvent(AWTEvent e) {
 115         if (e instanceof MouseWheelEvent
 116                 && !getTarget().isWheelScrollingEnabled()) {
 117             return;
 118         }
 119         super.handleEvent(e);
 120     }
 121 
 122     @Override
 123     public boolean handlesWheelScrolling() {
 124         return isVerticalBarVisible() || isHorizontalBarVisible();
 125     }
 126 
 127     
 128     private boolean isVerticalBarVisible() {
 129         synchronized (getDelegateLock()) {
 130             JScrollBar verticalScrollBar = getDelegate().getVerticalScrollBar();
 131             return verticalScrollBar != null && verticalScrollBar.isVisible();
 132         }
 133     }
 134 
 135     private boolean isHorizontalBarVisible() {
 136         synchronized (getDelegateLock()) {
 137             JScrollBar horizontalScrollBar = getDelegate().getHorizontalScrollBar();
 138             return horizontalScrollBar != null && horizontalScrollBar.isVisible();
 139         }
 140     }
 141     
 142     @Override
 143     public Insets getInsets() {
 144         if (getViewPeer() != null) {
 145             synchronized (getDelegateLock()) {
 146                 int right = isVerticalBarVisible() ? getVScrollbarWidth() : 0;
 147                 int bottom = isHorizontalBarVisible() ? getHScrollbarHeight() : 0;
 148                 return new Insets(0, 0, bottom, right);
 149             }
 150         }
 151         return new Insets(0, 0, 0, 0);
 152     }
 153 
 154 
 155     @Override
 156     public void setScrollPosition(int x, int y) {
 157         synchronized (getDelegateLock()) {
 158             getDelegate().getViewport().setViewPosition(new Point(x, y));
 159         }
 160     }
 161 
 162     @Override
 163     public int getHScrollbarHeight() {
 164         synchronized (getDelegateLock()) {
 165             JScrollBar horizontalScrollBar = getDelegate().getHorizontalScrollBar();
 166             return horizontalScrollBar != null ? horizontalScrollBar.getHeight() : 0;
 167         }
 168     }
 169 
 170     @Override
 171     public int getVScrollbarWidth() {
 172         synchronized (getDelegateLock()) {
 173             JScrollBar verticalScrollBar = getDelegate().getVerticalScrollBar();
 174             return verticalScrollBar != null ? verticalScrollBar.getWidth() : 0;
 175         }
 176     }
 177 
 178     @Override
 179     public void childResized(int w, int h) {
 180         synchronized (getDelegateLock()) {
 181             getDelegate().invalidate();
 182             getDelegate().validate();
 183         }
 184     }
 185 
 186     @Override
 187     public void setUnitIncrement(Adjustable adj, int u) {
 188     }
 189 
 190     @Override
 191     public void setValue(Adjustable adj, int v) {
 192         LWComponentPeer c = getViewPeer();
 193         if (c == null) {
 194             return;
 195         }
 196         Point p = c.getTarget().getLocation();
 197         switch (adj.getOrientation()) {
 198             case Adjustable.VERTICAL:
 199                 setScrollPosition(-(p.x), v);
 200                 break;
 201             case Adjustable.HORIZONTAL:
 202                 setScrollPosition(v, (-p.y));
 203                 break;
 204         }
 205     }
 206 
 207     private static int convertHPolicy(final int policy) {
 208         switch (policy) {
 209             case ScrollPane.SCROLLBARS_NEVER:
 210                 return ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER;
 211             case ScrollPane.SCROLLBARS_ALWAYS:
 212                 return ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
 213             default:
 214                 return ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
 215         }
 216     }
 217 
 218     private static int convertVPolicy(final int policy) {
 219         switch (policy) {
 220             case ScrollPane.SCROLLBARS_NEVER:
 221                 return ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER;
 222             case ScrollPane.SCROLLBARS_ALWAYS:
 223                 return ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
 224             default:
 225                 return ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
 226         }
 227     }
 228 }