/*
 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package sun.awt.windows;

import java.awt.*;
import java.awt.event.AdjustmentEvent;
import java.awt.peer.ScrollPanePeer;

import sun.awt.AWTAccessor;
import sun.awt.PeerEvent;

import sun.util.logging.PlatformLogger;

final class WScrollPanePeer extends WPanelPeer implements ScrollPanePeer {

    private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WScrollPanePeer");

    int scrollbarWidth;
    int scrollbarHeight;
    int prevx;
    int prevy;

    static {
        initIDs();
    }

    static native void initIDs();
    @Override
    native void create(WComponentPeer parent);
    native int getOffset(int orient);

    WScrollPanePeer(Component target) {
        super(target);
        scrollbarWidth = _getVScrollbarWidth();
        scrollbarHeight = _getHScrollbarHeight();
    }

    @Override
    void initialize() {
        super.initialize();
        setInsets();
        Insets i = getInsets();
        setScrollPosition(-i.left,-i.top);
    }

    @Override
    public void setUnitIncrement(Adjustable adj, int p) {
        // The unitIncrement is grabbed from the target as needed.
    }

    @Override
    public Insets insets() {
        return getInsets();
    }
    private native void setInsets();

    @Override
    public native synchronized void setScrollPosition(int x, int y);

    @Override
    public int getHScrollbarHeight() {
        return scrollbarHeight;
    }
    private native int _getHScrollbarHeight();

    @Override
    public int getVScrollbarWidth() {
        return scrollbarWidth;
    }
    private native int _getVScrollbarWidth();

    public Point getScrollOffset() {
        int x = getOffset(Adjustable.HORIZONTAL);
        int y = getOffset(Adjustable.VERTICAL);
        return new Point(x, y);
    }

    
The child component has been resized. The scrollbars must be updated with the new sizes. At the native level the sizes of the actual windows may not have changed yet, so the size information from the java-level is passed down and used.
/** * The child component has been resized. The scrollbars must be * updated with the new sizes. At the native level the sizes of * the actual windows may not have changed yet, so the size * information from the java-level is passed down and used. */
@Override public void childResized(int width, int height) { ScrollPane sp = (ScrollPane)target; Dimension vs = sp.getSize(); setSpans(vs.width, vs.height, width, height); setInsets(); } native synchronized void setSpans(int viewWidth, int viewHeight, int childWidth, int childHeight);
Called by ScrollPane's internal observer of the scrollpane's adjustables. This is called whenever a scroll position is changed in one of adjustables, whether it was modified externally or from the native scrollbars themselves.
/** * Called by ScrollPane's internal observer of the scrollpane's adjustables. * This is called whenever a scroll position is changed in one * of adjustables, whether it was modified externally or from the * native scrollbars themselves. */
@Override public void setValue(Adjustable adj, int v) { Component c = getScrollChild(); if (c == null) { return; } Point p = c.getLocation(); switch(adj.getOrientation()) { case Adjustable.VERTICAL: setScrollPosition(-(p.x), v); break; case Adjustable.HORIZONTAL: setScrollPosition(v, -(p.y)); break; } } private Component getScrollChild() { ScrollPane sp = (ScrollPane)target; Component child = null; try { child = sp.getComponent(0); } catch (ArrayIndexOutOfBoundsException e) { // do nothing. in this case we return null } return child; } /* * Called from Windows in response to WM_VSCROLL/WM_HSCROLL message */ private void postScrollEvent(int orient, int type, int pos, boolean isAdjusting) { Runnable adjustor = new Adjustor(orient, type, pos, isAdjusting); WToolkit.executeOnEventHandlerThread(new ScrollEvent(target, adjustor)); } /* * Event that executes on the Java dispatch thread to move the * scroll bar thumbs and paint the exposed area in one synchronous * operation. */ class ScrollEvent extends PeerEvent { ScrollEvent(Object source, Runnable runnable) { super(source, runnable, 0L); } @Override public PeerEvent coalesceEvents(PeerEvent newEvent) { if (log.isLoggable(PlatformLogger.Level.FINEST)) { log.finest("ScrollEvent coalesced: " + newEvent); } if (newEvent instanceof ScrollEvent) { return newEvent; } return null; } } /* * Runnable for the ScrollEvent that performs the adjustment. */ class Adjustor implements Runnable { int orient; // selects scrollbar int type; // adjustment type int pos; // new position (only used for absolute) boolean isAdjusting; // isAdjusting status Adjustor(int orient, int type, int pos, boolean isAdjusting) { this.orient = orient; this.type = type; this.pos = pos; this.isAdjusting = isAdjusting; } @Override public void run() { if (getScrollChild() == null) { return; } ScrollPane sp = (ScrollPane)WScrollPanePeer.this.target; ScrollPaneAdjustable adj = null; // ScrollPaneAdjustable made public in 1.4, but // get[HV]Adjustable can't be declared to return // ScrollPaneAdjustable because it would break backward // compatibility -- hence the cast if (orient == Adjustable.VERTICAL) { adj = (ScrollPaneAdjustable)sp.getVAdjustable(); } else if (orient == Adjustable.HORIZONTAL) { adj = (ScrollPaneAdjustable)sp.getHAdjustable(); } else { if (log.isLoggable(PlatformLogger.Level.FINE)) { log.fine("Assertion failed: unknown orient"); } } if (adj == null) { return; } int newpos = adj.getValue(); switch (type) { case AdjustmentEvent.UNIT_DECREMENT: newpos -= adj.getUnitIncrement(); break; case AdjustmentEvent.UNIT_INCREMENT: newpos += adj.getUnitIncrement(); break; case AdjustmentEvent.BLOCK_DECREMENT: newpos -= adj.getBlockIncrement(); break; case AdjustmentEvent.BLOCK_INCREMENT: newpos += adj.getBlockIncrement(); break; case AdjustmentEvent.TRACK: newpos = this.pos; break; default: if (log.isLoggable(PlatformLogger.Level.FINE)) { log.fine("Assertion failed: unknown type"); } return; } // keep scroll position in acceptable range newpos = Math.max(adj.getMinimum(), newpos); newpos = Math.min(adj.getMaximum(), newpos); // set value, this will synchronously fire an AdjustmentEvent adj.setValueIsAdjusting(isAdjusting); // Fix for 4075484 - consider type information when creating AdjustmentEvent // We can't just call adj.setValue() because it creates AdjustmentEvent with type=TRACK // Instead, we call private method setTypedValue of ScrollPaneAdjustable. AWTAccessor.getScrollPaneAdjustableAccessor().setTypedValue(adj, newpos, type); // Paint the exposed area right away. To do this - find // the heavyweight ancestor of the scroll child. Component hwAncestor = getScrollChild(); while (hwAncestor != null && !(hwAncestor.getPeer() instanceof WComponentPeer)) { hwAncestor = hwAncestor.getParent(); } if (log.isLoggable(PlatformLogger.Level.FINE)) { if (hwAncestor == null) { log.fine("Assertion (hwAncestor != null) failed, " + "couldn't find heavyweight ancestor of scroll pane child"); } } WComponentPeer hwPeer = (WComponentPeer)hwAncestor.getPeer(); hwPeer.paintDamagedAreaImmediately(); } } }