Package DisplayProject.controls

Source Code of DisplayProject.controls.NonCorneredScrollLayout

/*
Copyright (c) 2003-2009 ITerative Consulting Pty Ltd. All Rights Reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:

o Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
 
o Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
   
o This jcTOOL Helper Class software, whether in binary or source form may not be used within,
or to derive, any other product without the specific prior written permission of the copyright holder

 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


*/
package DisplayProject.controls;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Rectangle;

import javax.swing.JScrollPane;
import javax.swing.ScrollPaneLayout;
import javax.swing.Scrollable;
import javax.swing.border.Border;

/**
* In forte controls centred in a scroll pane such as a list view, Forte would
* not allow anything in the corners of the viewport where the scrollbars met.
* The lower corner, at the junction of the horizontal and vertical scrollbars
* was left blank and could be filled with the colour of the listview. The top
* right corner didn't exist -- the vertical scrollbar rose up to meet the top
* of the listview.
* <p>
* This layout manager can be used to mirror this functionality. It performs the
* same computations as the normal ScrollPaneLayout (which it extends) but when
* laying out the components, if there is no top left corner widget it allocates
* the extra room to the vertical scrollbar.
* <p>
* @author Tim
*/
@SuppressWarnings("serial")
public class NonCorneredScrollLayout extends ScrollPaneLayout {
    /**
     * Lay out the scroll pane. This method is largely copied from the superclass
     * so see the comments there. The only difference is
     */
    public void layoutContainer(Container parent) {
        /* Sync the (now obsolete) policy fields with the
         * JScrollPane.
         */
        JScrollPane scrollPane = (JScrollPane)parent;
        vsbPolicy = scrollPane.getVerticalScrollBarPolicy();
        hsbPolicy = scrollPane.getHorizontalScrollBarPolicy();

        Rectangle availR = scrollPane.getBounds();
        availR.x = availR.y = 0;

        Insets insets = parent.getInsets();
        availR.x = insets.left;
        availR.y = insets.top;
        availR.width -= insets.left + insets.right;
        availR.height -= insets.top + insets.bottom;

        /* Get the scrollPane's orientation.
         */
        boolean leftToRight = scrollPane.getComponentOrientation().isLeftToRight();

        /* If there's a visible column header remove the space it
         * needs from the top of availR.  The column header is treated
         * as if it were fixed height, arbitrary width.
         */
        Rectangle colHeadR = new Rectangle(0, availR.y, 0, 0);

        if ((colHead != null) && (colHead.isVisible())) {
            int colHeadHeight = Math.min(availR.height,
                                            colHead.getPreferredSize().height);
            colHeadR.height = colHeadHeight;
            availR.y += colHeadHeight;
            availR.height -= colHeadHeight;
        }

        /* If there's a visible row header remove the space it needs
         * from the left or right of availR.  The row header is treated
         * as if it were fixed width, arbitrary height.
         */

        Rectangle rowHeadR = new Rectangle(0, 0, 0, 0);

        if ((rowHead != null) && (rowHead.isVisible())) {
            int rowHeadWidth = Math.min(availR.width,
                                            rowHead.getPreferredSize().width);
            rowHeadR.width = rowHeadWidth;
            availR.width -= rowHeadWidth;
                if ( leftToRight ) {
                    rowHeadR.x = availR.x;
                    availR.x += rowHeadWidth;
                } else {
                    rowHeadR.x = availR.x + availR.width;
                }
        }

        /* If there's a JScrollPane.viewportBorder, remove the
         * space it occupies for availR.
         */

        Border viewportBorder = scrollPane.getViewportBorder();
        Insets vpbInsets;
        if (viewportBorder != null) {
            vpbInsets = viewportBorder.getBorderInsets(parent);
            availR.x += vpbInsets.left;
            availR.y += vpbInsets.top;
            availR.width -= vpbInsets.left + vpbInsets.right;
            availR.height -= vpbInsets.top + vpbInsets.bottom;
        }
        else {
            vpbInsets = new Insets(0,0,0,0);
        }


        /* At this point availR is the space available for the viewport
         * and scrollbars. rowHeadR is correct except for its height and y
         * and colHeadR is correct except for its width and x.  Once we're
         * through computing the dimensions  of these three parts we can
         * go back and set the dimensions of rowHeadR.height, rowHeadR.y,
         * colHeadR.width, colHeadR.x and the bounds for the corners.
         *
         * We'll decide about putting up scrollbars by comparing the
         * viewport views preferred size with the viewports extent
         * size (generally just its size).  Using the preferredSize is
         * reasonable because layout proceeds top down - so we expect
         * the viewport to be laid out next.  And we assume that the
         * viewports layout manager will give the view it's preferred
         * size.  One exception to this is when the view implements
         * Scrollable and Scrollable.getViewTracksViewport{Width,Height}
         * methods return true.  If the view is tracking the viewports
         * width we don't bother with a horizontal scrollbar, similarly
         * if view.getViewTracksViewport(Height) is true we don't bother
         * with a vertical scrollbar.
         */

        Component view = (viewport != null) ? viewport.getView() : null;
        Dimension viewPrefSize = 
            (view != null) ? view.getPreferredSize()
                                : new Dimension(0,0);

        Dimension extentSize =
            (viewport != null) ? viewport.toViewCoordinates(availR.getSize())
                                : new Dimension(0,0);

        boolean viewTracksViewportWidth = false;
        boolean viewTracksViewportHeight = false;
        boolean isEmpty = (availR.width < 0 || availR.height < 0);
        Scrollable sv;
            // Don't bother checking the Scrollable methods if there is no room
            // for the viewport, we aren't going to show any scrollbars in this
            // case anyway.
        if (!isEmpty && view instanceof Scrollable) {
            sv = (Scrollable)view;
            viewTracksViewportWidth = sv.getScrollableTracksViewportWidth();
            viewTracksViewportHeight = sv.getScrollableTracksViewportHeight();
        }
        else {
            sv = null;
        }

        /* If there's a vertical scrollbar and we need one, allocate
         * space for it (we'll make it visible later). A vertical
         * scrollbar is considered to be fixed width, arbitrary height.
         */

        Rectangle vsbR = new Rectangle(0, availR.y - vpbInsets.top, 0, 0);

        boolean vsbNeeded;
            if (isEmpty) {
                vsbNeeded = false;
            }
        else if (vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS) {
            vsbNeeded = true;
        }
        else if (vsbPolicy == VERTICAL_SCROLLBAR_NEVER) {
            vsbNeeded = false;
        }
        else // vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED
            vsbNeeded = !viewTracksViewportHeight && (viewPrefSize.height > extentSize.height);
        }


        if ((vsb != null) && vsbNeeded) {
            adjustForVSB(true, availR, vsbR, vpbInsets, leftToRight);
            extentSize = viewport.toViewCoordinates(availR.getSize());
        }

        /* If there's a horizontal scrollbar and we need one, allocate
         * space for it (we'll make it visible later). A horizontal
         * scrollbar is considered to be fixed height, arbitrary width.
         */

        Rectangle hsbR = new Rectangle(availR.x - vpbInsets.left, 0, 0, 0);
        boolean hsbNeeded;
            if (isEmpty) {
                hsbNeeded = false;
            }
        else if (hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) {
            hsbNeeded = true;
        }
        else if (hsbPolicy == HORIZONTAL_SCROLLBAR_NEVER) {
            hsbNeeded = false;
        }
        else // hsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED
            hsbNeeded = !viewTracksViewportWidth && (viewPrefSize.width > extentSize.width);
        }

        if ((hsb != null) && hsbNeeded) {
            adjustForHSB(true, availR, hsbR, vpbInsets);

            /* If we added the horizontal scrollbar then we've implicitly
             * reduced  the vertical space available to the viewport.
             * As a consequence we may have to add the vertical scrollbar,
             * if that hasn't been done so already.  Of course we
             * don't bother with any of this if the vsbPolicy is NEVER.
             */
            if ((vsb != null) && !vsbNeeded &&
            (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {

                extentSize = viewport.toViewCoordinates(availR.getSize());
                vsbNeeded = viewPrefSize.height > extentSize.height;

                if (vsbNeeded) {
                    adjustForVSB(true, availR, vsbR, vpbInsets, leftToRight);
                }
            }
        }

        /* Set the size of the viewport first, and then recheck the Scrollable
         * methods. Some components base their return values for the Scrollable
         * methods on the size of the Viewport, so that if we don't
         * ask after resetting the bounds we may have gotten the wrong
         * answer.
         */

        if (viewport != null) {
            viewport.setBounds(availR);

            if (sv != null) {
            extentSize = viewport.toViewCoordinates(availR.getSize());

            boolean oldHSBNeeded = hsbNeeded;
            boolean oldVSBNeeded = vsbNeeded;
            viewTracksViewportWidth = sv.
                                        getScrollableTracksViewportWidth();
            viewTracksViewportHeight = sv.
                                        getScrollableTracksViewportHeight();
            if (vsb != null && vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED) {
                boolean newVSBNeeded = !viewTracksViewportHeight &&
                                    (viewPrefSize.height > extentSize.height);
                if (newVSBNeeded != vsbNeeded) {
                vsbNeeded = newVSBNeeded;
                adjustForVSB(vsbNeeded, availR, vsbR, vpbInsets,
                            leftToRight);
                extentSize = viewport.toViewCoordinates
                                        (availR.getSize());
                }
            }
            if (hsb != null && hsbPolicy ==HORIZONTAL_SCROLLBAR_AS_NEEDED){
                boolean newHSBbNeeded = !viewTracksViewportWidth &&
                                (viewPrefSize.width > extentSize.width);
                if (newHSBbNeeded != hsbNeeded) {
                hsbNeeded = newHSBbNeeded;
                adjustForHSB(hsbNeeded, availR, hsbR, vpbInsets);
                if ((vsb != null) && !vsbNeeded &&
                    (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {

                    extentSize = viewport.toViewCoordinates
                                (availR.getSize());
                    vsbNeeded = viewPrefSize.height >
                            extentSize.height;

                    if (vsbNeeded) {
                    adjustForVSB(true, availR, vsbR, vpbInsets,
                                leftToRight);
                    }
                }
                }
            }
            if (oldHSBNeeded != hsbNeeded ||
                oldVSBNeeded != vsbNeeded) {
                viewport.setBounds(availR);
                // You could argue that we should recheck the
                // Scrollable methods again until they stop changing,
                // but they might never stop changing, so we stop here
                // and don't do any additional checks.
            }
            }
        }

        /* We now have the final size of the viewport: availR.
         * Now fixup the header and scrollbar widths/heights.
         */
        vsbR.height = availR.height + vpbInsets.top + vpbInsets.bottom;

        // ----------------------------
        // Changed code from superclass
        // ----------------------------
        if (upperRight == null && (colHead != null) && (colHead.isVisible())) {
            int colHeadHeight = Math.min(availR.height,
                                            colHead.getPreferredSize().height);
            vsbR.height += colHeadHeight;
            vsbR.y -= colHeadHeight;
        }
        // --------------------------------
        // End changed code from superclass
        // --------------------------------
        hsbR.width = availR.width + vpbInsets.left + vpbInsets.right;
        rowHeadR.height = availR.height + vpbInsets.top + vpbInsets.bottom;
        rowHeadR.y = availR.y - vpbInsets.top;
        colHeadR.width = availR.width + vpbInsets.left + vpbInsets.right;
        colHeadR.x = availR.x - vpbInsets.left;

        /* Set the bounds of the remaining components.  The scrollbars
         * are made invisible if they're not needed.
         */

        if (rowHead != null) {
            rowHead.setBounds(rowHeadR);
        }

        if (colHead != null) {
            colHead.setBounds(colHeadR);
        }

        if (vsb != null) {
            if (vsbNeeded) {
            vsb.setVisible(true);
            vsb.setBounds(vsbR);
            }
            else {
            vsb.setVisible(false);
            }
        }

        if (hsb != null) {
            if (hsbNeeded) {
            hsb.setVisible(true);
            hsb.setBounds(hsbR);
            }
            else {
            hsb.setVisible(false);
            }
        }

        if (lowerLeft != null) {
            lowerLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x,
                                    hsbR.y,
                                    leftToRight ? rowHeadR.width : vsbR.width,
                                    hsbR.height);
        }

        if (lowerRight != null) {
            lowerRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x,
                                    hsbR.y,
                                    leftToRight ? vsbR.width : rowHeadR.width,
                                    hsbR.height);
        }

        if (upperLeft != null) {
            upperLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x,
                                    colHeadR.y,
                                    leftToRight ? rowHeadR.width : vsbR.width,
                                    colHeadR.height);
        }

        if (upperRight != null) {
            upperRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x,
                                    colHeadR.y,
                                    leftToRight ? vsbR.width : rowHeadR.width,
                                    colHeadR.height);
        }
    }

    /**
* Adjusts the <code>Rectangle</code> <code>available</code> based on if
* the horizontal scrollbar is needed (<code>wantsHSB</code>).
* The location of the hsb is updated in <code>hsbR</code>, and
* the viewport border insets (<code>vpbInsets</code>) are used to offset
* the hsb.  This is only called when <code>wantsHSB</code> has
* changed, eg you shouldn't invoked adjustForHSB(true) twice.
* <p>
* This code is copied verbatum from the superclass since it is private
*/
    private void adjustForHSB(boolean wantsHSB, Rectangle available,
                    Rectangle hsbR, Insets vpbInsets) {
        int oldHeight = hsbR.height;
        if (wantsHSB) {
                int hsbHeight = Math.max(0, Math.min(available.height,
                                                hsb.getPreferredSize().height));

            available.height -= hsbHeight;
            hsbR.y = available.y + available.height + vpbInsets.bottom;
            hsbR.height = hsbHeight;
        }
        else {
            available.height += oldHeight;
        }
    }

    /**
* Adjusts the <code>Rectangle</code> <code>available</code> based on if
* the vertical scrollbar is needed (<code>wantsVSB</code>).
* The location of the vsb is updated in <code>vsbR</code>, and
* the viewport border insets (<code>vpbInsets</code>) are used to offset
* the vsb. This is only called when <code>wantsVSB</code> has
* changed, eg you shouldn't invoke adjustForVSB(true) twice.
* <p>
* This code is copied verbatum from the superclass since it is private
*/
    private void adjustForVSB(boolean wantsVSB, Rectangle available,
                    Rectangle vsbR, Insets vpbInsets,
                            boolean leftToRight) {
        int oldWidth = vsbR.width;
        if (wantsVSB) {
                int vsbWidth = Math.max(0, Math.min(vsb.getPreferredSize().width,
                                                    available.width));

            available.width -= vsbWidth;
            vsbR.width = vsbWidth;

                if( leftToRight ) {
                    vsbR.x = available.x + available.width + vpbInsets.right;
                } else {
                    vsbR.x = available.x - vpbInsets.left;
                    available.x += vsbWidth;
                }
        }
        else {
            available.width += oldWidth;
        }
    }
}

TOP

Related Classes of DisplayProject.controls.NonCorneredScrollLayout

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.