Package org.apache.harmony.awt

Source Code of org.apache.harmony.awt.ScrollStateController

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You 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.
*/
/**
* @author Dmitry A. Durnev
* @version $Revision$
*/
package org.apache.harmony.awt;

import java.awt.Adjustable;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

/**
* Implements scrolling behavior for any container which
* has up to 1 child and up to 2 scrollbars[and implements
* Scrollable interface], for example ScrollPane.
* Listens to adjustment events and mouse wheel events
* and updates the scrollable object in response.
* @see org.apache.harmony.awt.Scrollable
*/
public class ScrollStateController extends ComponentAdapter implements
        AdjustmentListener, MouseWheelListener {

    private static final int HSCROLLBAR_HEIGHT = 16;

    private static final int VSCROLLBAR_WIDTH = 16;

    private final Scrollable scrollable;

    private final Component component;

    private final Adjustable hAdj;

    private final Adjustable vAdj;

    public ScrollStateController(Scrollable scrollable) {
        this.scrollable = scrollable;
        component = scrollable.getComponent();
        hAdj = scrollable.getHAdjustable();
        vAdj = scrollable.getVAdjustable();
    }

    /**
     * Scrolls vertically or horizontally(if scrollable has only
     * horizontal scrollbar) on mouse wheel move
     */
    public void mouseWheelMoved(MouseWheelEvent e) {
        int type = e.getScrollType();
        int unitType = MouseWheelEvent.WHEEL_UNIT_SCROLL;
        Adjustable adj = vAdj;
        if (!isAdjNeeded(vAdj) && isAdjNeeded(hAdj)) {
            // scroll horizontally if only horiz scrollbar
            // is present
            adj = hAdj;
        }
        int incrSize = (type == unitType ? adj.getUnitIncrement() : adj
                .getBlockIncrement());
        int scrollAmount = e.getUnitsToScroll() * incrSize;

        adj.setValue(adj.getValue() + scrollAmount);
    }

    /**
     * Scrolls component on adjustment events from
     * scrollbars, repaints scrollable viewport
     */
    public void adjustmentValueChanged(AdjustmentEvent e) {
        // set scrolled component's position here:
        Adjustable srcAdj = e.getAdjustable();
        int val = e.getValue();

        Insets ins = scrollable.getInsets();
        Point loc = scrollable.getLocation();
        if (srcAdj == hAdj) {
            loc.x = ins.left - val;
        }
        if (srcAdj == vAdj) {
            loc.y = ins.top - val;
        }
        scrollable.setLocation(loc);
        int hSize = scrollable.getWidth() - getHrzInsets(ins);
        int vSize = scrollable.getHeight() - getVrtInsets(ins);
        Rectangle r = new Rectangle(ins.left, ins.top, hSize, vSize);
        scrollable.doRepaint(r); // repaint only client area
    }

    /**
     * Recalculates internal scrollable layout
     * on component resize
     */
    @Override
    public void componentResized(ComponentEvent e) {
        if (!component.isDisplayable()) {
            return;
        }
        scrollable.doRepaint();
    }

    /**
     * Adds vertical scrollbar width to the specified horizontal
     * insets
     * @param insets
     * @return sum of left & right insets & vertical scrollbar width
     */
    private int getHrzInsets(Insets insets) {
        return (insets != null) ?
            insets.left + insets.right + scrollable.getAdjustableWidth() : 0;
    }
   
    /**
     * Adds horizontal scrollbar height to the specified vertical
     * insets
     * @param insets
     * @return sum of top & bottom insets & horizontal scrollbar height
     */
    private int getVrtInsets(Insets insets) {
        return (insets != null) ?
            insets.top + insets.bottom + scrollable.getAdjustableHeight() : 0;
    }

    /**
     * Sets scrollbars bounds, values & increments
     */
    public void layoutScrollbars() {
        boolean hAdjNeeded = isAdjNeeded(hAdj);
        boolean vAdjNeeded = isAdjNeeded(vAdj);
        Insets insets = scrollable.getInsets();
        Dimension size = scrollable.getSize();

        setAdjBounds(hAdjNeeded, vAdjNeeded);

        if (hAdj != null) {
            int hSize = scrollable.getWidth() - getHrzInsets(insets);
            int hGap = insets.left + insets.right;
            int hVis = getVisFromSize(hSize, hGap);
            int newHMax = Math.max(size.width, hVis);
            scrollable.setAdjustableSizes(hAdj, hVis, 0, newHMax);
            hAdj.setBlockIncrement(getBlockIncrFromVis(hVis));
        }

        if (vAdj != null) {
            int vSize = scrollable.getHeight() - getVrtInsets(insets);
            int vGap = insets.bottom + insets.top;
            int vVis = getVisFromSize(vSize, vGap);
            int newVMax = Math.max(size.height, vVis);
            scrollable.setAdjustableSizes(vAdj, vVis, 0, newVMax);
            vAdj.setBlockIncrement(getBlockIncrFromVis(vVis));
        }
    }
   
    /**
     * Calculates & sets scrollbars bounds
     *
     * @param hAdjNeeded true if it's necessary to layout horizontal scrollbar
     * @param vAdjNeeded true if it's necessary to layout vertical scrollbar
     */
    private void setAdjBounds(boolean hAdjNeeded, boolean vAdjNeeded) {
        Rectangle hRect = new Rectangle();
        Rectangle vRect = new Rectangle();
        int spHeight = scrollable.getHeight();
        int spWidth = scrollable.getWidth();
        Insets ins = scrollable.getInsets();

        if (hAdjNeeded) {
            hRect.height = HSCROLLBAR_HEIGHT;
            int vWidth = vAdjNeeded ? VSCROLLBAR_WIDTH : 0;
            hRect.width = spWidth - vWidth - (ins.left + ins.right);
            hRect.y = spHeight - hRect.height - ins.bottom;
            hRect.x = ins.left;
        }
        scrollable.setAdjustableBounds(hAdj, hRect);
        if (vAdjNeeded) {
            int hHeight = hAdjNeeded ? HSCROLLBAR_HEIGHT : 0;
            vRect.height = spHeight - hHeight - (ins.top + ins.bottom);
            vRect.width = VSCROLLBAR_WIDTH;
            vRect.x = spWidth - vRect.width - ins.right;
            vRect.y = ins.top;
        }
        scrollable.setAdjustableBounds(vAdj, vRect);
    }

    /**
     * Calculates block increment given visible amount of scrollbar
     * @param vis visible amount
     * @return block increment size
     */
    private int getBlockIncrFromVis(int vis) {
        return Math.max(1, vis * 9 / 10);
    }

    /**
     * Calculates visible amount given size(length) of scrollbar's
     * viewport
     * @param size viewport size
     * @param gap insets(without scrollbar area) size
     * @return visible amount
     */
    private int getVisFromSize(int size, int gap) {
        return Math.max(1, size - gap);
    }

    /**
     * Determines whether a specified adjustable should
     * be displayed using scrollbar display policy
     * @param adj scrollbar
     * @return true if scrollbar should be displayed, false otherwise
     */
    private boolean isAdjNeeded(Adjustable adj) {
        if (adj == null) {
            return false;
        }
        switch (scrollable.getAdjustableMode(adj)) {
            case Scrollable.ALWAYS:
                return true;
            case Scrollable.NEVER:
                return false;
            case Scrollable.AS_NEEDED:
                return calculateNeeded(adj);
            case Scrollable.HORIZONTAL_ONLY:
                return adj.getOrientation() == Adjustable.HORIZONTAL;
            case Scrollable.VERTICAL_ONLY:
                return adj.getOrientation() == Adjustable.VERTICAL;
        }
        return true;
    }

    /**
     * Only for Scrollable.AS_NEEDED scrollbar display policy:
     *  determines if the specified scrollbar should be visible.
     *  Scrollbar is shown only if child component can be scrolled in
     *  corresponding direction, i. e. the size of the child exceeds
     *  container size, and there's enough space for
     *  scrollbar itself.
     * @param adj scrollbar
     * @return true if scrollbar is needed, false otherwise
     */
    private boolean calculateNeeded(Adjustable adj) {
        Insets ins = scrollable.getInsets();
        Component comp = scrollable.getComponent();
        final int GAP = ins.left + ins.right;
        boolean isVertical = (adj.getOrientation() == Adjustable.VERTICAL);
        Dimension viewSize = comp.getSize();
        viewSize.width -= getHrzInsets(ins);
        viewSize.height -= getVrtInsets(ins);
        int viewWidth = viewSize.width;
        int viewHeight = viewSize.height;
        int spOtherSize = isVertical ? viewWidth : viewHeight;
        int spSize = isVertical ? viewHeight : viewWidth;

        int compSize = 0;
        int adjSize = (isVertical ? scrollable.getAdjustableWidth()
                                 : scrollable.getAdjustableHeight());
        if (comp != null) {
            Dimension prefSize = scrollable.getSize();
            compSize = isVertical ? prefSize.height
                                 : prefSize.width;
        }
        return ((spSize < compSize) &&
                (spOtherSize > adjSize + GAP));
    }
}
TOP

Related Classes of org.apache.harmony.awt.ScrollStateController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.