History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/ScrollPaneLayout.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/ScrollPaneLayout.java+1121−0
@@ -0,0 +1,1121 @@
1+/*
2+ * Copyright (c) 1997, 2008, 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 javax.swing;
27+
28+
29+import javax.swing.border.*;
30+
31+import java.awt.LayoutManager;
32+import java.awt.Component;
33+import java.awt.Container;
34+import java.awt.Rectangle;
35+import java.awt.Dimension;
36+import java.awt.Insets;
37+import java.io.Serializable;
38+
39+
40+/**
41+ * The layout manager used by <code>JScrollPane</code>.
42+ * <code>JScrollPaneLayout</code> is
43+ * responsible for nine components: a viewport, two scrollbars,
44+ * a row header, a column header, and four "corner" components.
45+ * <p>
46+ * <strong>Warning:</strong>
47+ * Serialized objects of this class will not be compatible with
48+ * future Swing releases. The current serialization support is
49+ * appropriate for short term storage or RMI between applications running
50+ * the same version of Swing. As of 1.4, support for long term storage
51+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
52+ * has been added to the <code>java.beans</code> package.
53+ * Please see {@link java.beans.XMLEncoder}.
54+ *
55+ * @see JScrollPane
56+ * @see JViewport
57+ *
58+ * @author Hans Muller
59+ */
60+public class ScrollPaneLayout
61+ implements LayoutManager, ScrollPaneConstants, Serializable
62+{
63+
64+ /**
65+ * The scrollpane's viewport child.
66+ * Default is an empty <code>JViewport</code>.
67+ * @see JScrollPane#setViewport
68+ */
69+ protected JViewport viewport;
70+
71+
72+ /**
73+ * The scrollpane's vertical scrollbar child.
74+ * Default is a <code>JScrollBar</code>.
75+ * @see JScrollPane#setVerticalScrollBar
76+ */
77+ protected JScrollBar vsb;
78+
79+
80+ /**
81+ * The scrollpane's horizontal scrollbar child.
82+ * Default is a <code>JScrollBar</code>.
83+ * @see JScrollPane#setHorizontalScrollBar
84+ */
85+ protected JScrollBar hsb;
86+
87+
88+ /**
89+ * The row header child. Default is <code>null</code>.
90+ * @see JScrollPane#setRowHeader
91+ */
92+ protected JViewport rowHead;
93+
94+
95+ /**
96+ * The column header child. Default is <code>null</code>.
97+ * @see JScrollPane#setColumnHeader
98+ */
99+ protected JViewport colHead;
100+
101+
102+ /**
103+ * The component to display in the lower left corner.
104+ * Default is <code>null</code>.
105+ * @see JScrollPane#setCorner
106+ */
107+ protected Component lowerLeft;
108+
109+
110+ /**
111+ * The component to display in the lower right corner.
112+ * Default is <code>null</code>.
113+ * @see JScrollPane#setCorner
114+ */
115+ protected Component lowerRight;
116+
117+
118+ /**
119+ * The component to display in the upper left corner.
120+ * Default is <code>null</code>.
121+ * @see JScrollPane#setCorner
122+ */
123+ protected Component upperLeft;
124+
125+
126+ /**
127+ * The component to display in the upper right corner.
128+ * Default is <code>null</code>.
129+ * @see JScrollPane#setCorner
130+ */
131+ protected Component upperRight;
132+
133+
134+ /**
135+ * The display policy for the vertical scrollbar.
136+ * The default is <code>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED</code>.
137+ * <p>
138+ * This field is obsolete, please use the <code>JScrollPane</code> field instead.
139+ *
140+ * @see JScrollPane#setVerticalScrollBarPolicy
141+ */
142+ protected int vsbPolicy = VERTICAL_SCROLLBAR_AS_NEEDED;
143+
144+
145+ /**
146+ * The display policy for the horizontal scrollbar.
147+ * The default is <code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED</code>.
148+ * <p>
149+ * This field is obsolete, please use the <code>JScrollPane</code> field instead.
150+ *
151+ * @see JScrollPane#setHorizontalScrollBarPolicy
152+ */
153+ protected int hsbPolicy = HORIZONTAL_SCROLLBAR_AS_NEEDED;
154+
155+
156+ /**
157+ * This method is invoked after the ScrollPaneLayout is set as the
158+ * LayoutManager of a <code>JScrollPane</code>.
159+ * It initializes all of the internal fields that
160+ * are ordinarily set by <code>addLayoutComponent</code>. For example:
161+ * <pre>
162+ * ScrollPaneLayout mySPLayout = new ScrollPanelLayout() {
163+ * public void layoutContainer(Container p) {
164+ * super.layoutContainer(p);
165+ * // do some extra work here ...
166+ * }
167+ * };
168+ * scrollpane.setLayout(mySPLayout):
169+ * </pre>
170+ */
171+ public void syncWithScrollPane(JScrollPane sp) {
172+ viewport = sp.getViewport();
173+ vsb = sp.getVerticalScrollBar();
174+ hsb = sp.getHorizontalScrollBar();
175+ rowHead = sp.getRowHeader();
176+ colHead = sp.getColumnHeader();
177+ lowerLeft = sp.getCorner(LOWER_LEFT_CORNER);
178+ lowerRight = sp.getCorner(LOWER_RIGHT_CORNER);
179+ upperLeft = sp.getCorner(UPPER_LEFT_CORNER);
180+ upperRight = sp.getCorner(UPPER_RIGHT_CORNER);
181+ vsbPolicy = sp.getVerticalScrollBarPolicy();
182+ hsbPolicy = sp.getHorizontalScrollBarPolicy();
183+ }
184+
185+
186+ /**
187+ * Removes an existing component. When a new component, such as
188+ * the left corner, or vertical scrollbar, is added, the old one,
189+ * if it exists, must be removed.
190+ * <p>
191+ * This method returns <code>newC</code>. If <code>oldC</code> is
192+ * not equal to <code>newC</code> and is non-<code>null</code>,
193+ * it will be removed from its parent.
194+ *
195+ * @param oldC the <code>Component</code> to replace
196+ * @param newC the <code>Component</code> to add
197+ * @return the <code>newC</code>
198+ */
199+ protected Component addSingletonComponent(Component oldC, Component newC)
200+ {
201+ if ((oldC != null) && (oldC != newC)) {
202+ oldC.getParent().remove(oldC);
203+ }
204+ return newC;
205+ }
206+
207+
208+ /**
209+ * Adds the specified component to the layout. The layout is
210+ * identified using one of:
211+ * <ul>
212+ * <li>ScrollPaneConstants.VIEWPORT
213+ * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR
214+ * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR
215+ * <li>ScrollPaneConstants.ROW_HEADER
216+ * <li>ScrollPaneConstants.COLUMN_HEADER
217+ * <li>ScrollPaneConstants.LOWER_LEFT_CORNER
218+ * <li>ScrollPaneConstants.LOWER_RIGHT_CORNER
219+ * <li>ScrollPaneConstants.UPPER_LEFT_CORNER
220+ * <li>ScrollPaneConstants.UPPER_RIGHT_CORNER
221+ * </ul>
222+ *
223+ * @param s the component identifier
224+ * @param c the the component to be added
225+ * @exception IllegalArgumentException if <code>s</code> is an invalid key
226+ */
227+ public void addLayoutComponent(String s, Component c)
228+ {
229+ if (s.equals(VIEWPORT)) {
230+ viewport = (JViewport)addSingletonComponent(viewport, c);
231+ }
232+ else if (s.equals(VERTICAL_SCROLLBAR)) {
233+ vsb = (JScrollBar)addSingletonComponent(vsb, c);
234+ }
235+ else if (s.equals(HORIZONTAL_SCROLLBAR)) {
236+ hsb = (JScrollBar)addSingletonComponent(hsb, c);
237+ }
238+ else if (s.equals(ROW_HEADER)) {
239+ rowHead = (JViewport)addSingletonComponent(rowHead, c);
240+ }
241+ else if (s.equals(COLUMN_HEADER)) {
242+ colHead = (JViewport)addSingletonComponent(colHead, c);
243+ }
244+ else if (s.equals(LOWER_LEFT_CORNER)) {
245+ lowerLeft = addSingletonComponent(lowerLeft, c);
246+ }
247+ else if (s.equals(LOWER_RIGHT_CORNER)) {
248+ lowerRight = addSingletonComponent(lowerRight, c);
249+ }
250+ else if (s.equals(UPPER_LEFT_CORNER)) {
251+ upperLeft = addSingletonComponent(upperLeft, c);
252+ }
253+ else if (s.equals(UPPER_RIGHT_CORNER)) {
254+ upperRight = addSingletonComponent(upperRight, c);
255+ }
256+ else {
257+ throw new IllegalArgumentException("invalid layout key " + s);
258+ }
259+ }
260+
261+
262+ /**
263+ * Removes the specified component from the layout.
264+ *
265+ * @param c the component to remove
266+ */
267+ public void removeLayoutComponent(Component c)
268+ {
269+ if (c == viewport) {
270+ viewport = null;
271+ }
272+ else if (c == vsb) {
273+ vsb = null;
274+ }
275+ else if (c == hsb) {
276+ hsb = null;
277+ }
278+ else if (c == rowHead) {
279+ rowHead = null;
280+ }
281+ else if (c == colHead) {
282+ colHead = null;
283+ }
284+ else if (c == lowerLeft) {
285+ lowerLeft = null;
286+ }
287+ else if (c == lowerRight) {
288+ lowerRight = null;
289+ }
290+ else if (c == upperLeft) {
291+ upperLeft = null;
292+ }
293+ else if (c == upperRight) {
294+ upperRight = null;
295+ }
296+ }
297+
298+
299+ /**
300+ * Returns the vertical scrollbar-display policy.
301+ *
302+ * @return an integer giving the display policy
303+ * @see #setVerticalScrollBarPolicy
304+ */
305+ public int getVerticalScrollBarPolicy() {
306+ return vsbPolicy;
307+ }
308+
309+
310+ /**
311+ * Sets the vertical scrollbar-display policy. The options
312+ * are:
313+ * <ul>
314+ * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED
315+ * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER
316+ * <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
317+ * </ul>
318+ * Note: Applications should use the <code>JScrollPane</code> version
319+ * of this method. It only exists for backwards compatibility
320+ * with the Swing 1.0.2 (and earlier) versions of this class.
321+ *
322+ * @param x an integer giving the display policy
323+ * @exception IllegalArgumentException if <code>x</code> is an invalid
324+ * vertical scroll bar policy, as listed above
325+ */
326+ public void setVerticalScrollBarPolicy(int x) {
327+ switch (x) {
328+ case VERTICAL_SCROLLBAR_AS_NEEDED:
329+ case VERTICAL_SCROLLBAR_NEVER:
330+ case VERTICAL_SCROLLBAR_ALWAYS:
331+ vsbPolicy = x;
332+ break;
333+ default:
334+ throw new IllegalArgumentException("invalid verticalScrollBarPolicy");
335+ }
336+ }
337+
338+
339+ /**
340+ * Returns the horizontal scrollbar-display policy.
341+ *
342+ * @return an integer giving the display policy
343+ * @see #setHorizontalScrollBarPolicy
344+ */
345+ public int getHorizontalScrollBarPolicy() {
346+ return hsbPolicy;
347+ }
348+
349+ /**
350+ * Sets the horizontal scrollbar-display policy.
351+ * The options are:<ul>
352+ * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED
353+ * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
354+ * <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
355+ * </ul>
356+ * Note: Applications should use the <code>JScrollPane</code> version
357+ * of this method. It only exists for backwards compatibility
358+ * with the Swing 1.0.2 (and earlier) versions of this class.
359+ *
360+ * @param x an int giving the display policy
361+ * @exception IllegalArgumentException if <code>x</code> is not a valid
362+ * horizontal scrollbar policy, as listed above
363+ */
364+ public void setHorizontalScrollBarPolicy(int x) {
365+ switch (x) {
366+ case HORIZONTAL_SCROLLBAR_AS_NEEDED:
367+ case HORIZONTAL_SCROLLBAR_NEVER:
368+ case HORIZONTAL_SCROLLBAR_ALWAYS:
369+ hsbPolicy = x;
370+ break;
371+ default:
372+ throw new IllegalArgumentException("invalid horizontalScrollBarPolicy");
373+ }
374+ }
375+
376+
377+ /**
378+ * Returns the <code>JViewport</code> object that displays the
379+ * scrollable contents.
380+ * @return the <code>JViewport</code> object that displays the scrollable contents
381+ * @see JScrollPane#getViewport
382+ */
383+ public JViewport getViewport() {
384+ return viewport;
385+ }
386+
387+
388+ /**
389+ * Returns the <code>JScrollBar</code> object that handles horizontal scrolling.
390+ * @return the <code>JScrollBar</code> object that handles horizontal scrolling
391+ * @see JScrollPane#getHorizontalScrollBar
392+ */
393+ public JScrollBar getHorizontalScrollBar() {
394+ return hsb;
395+ }
396+
397+ /**
398+ * Returns the <code>JScrollBar</code> object that handles vertical scrolling.
399+ * @return the <code>JScrollBar</code> object that handles vertical scrolling
400+ * @see JScrollPane#getVerticalScrollBar
401+ */
402+ public JScrollBar getVerticalScrollBar() {
403+ return vsb;
404+ }
405+
406+
407+ /**
408+ * Returns the <code>JViewport</code> object that is the row header.
409+ * @return the <code>JViewport</code> object that is the row header
410+ * @see JScrollPane#getRowHeader
411+ */
412+ public JViewport getRowHeader() {
413+ return rowHead;
414+ }
415+
416+
417+ /**
418+ * Returns the <code>JViewport</code> object that is the column header.
419+ * @return the <code>JViewport</code> object that is the column header
420+ * @see JScrollPane#getColumnHeader
421+ */
422+ public JViewport getColumnHeader() {
423+ return colHead;
424+ }
425+
426+
427+ /**
428+ * Returns the <code>Component</code> at the specified corner.
429+ * @param key the <code>String</code> specifying the corner
430+ * @return the <code>Component</code> at the specified corner, as defined in
431+ * {@link ScrollPaneConstants}; if <code>key</code> is not one of the
432+ * four corners, <code>null</code> is returned
433+ * @see JScrollPane#getCorner
434+ */
435+ public Component getCorner(String key) {
436+ if (key.equals(LOWER_LEFT_CORNER)) {
437+ return lowerLeft;
438+ }
439+ else if (key.equals(LOWER_RIGHT_CORNER)) {
440+ return lowerRight;
441+ }
442+ else if (key.equals(UPPER_LEFT_CORNER)) {
443+ return upperLeft;
444+ }
445+ else if (key.equals(UPPER_RIGHT_CORNER)) {
446+ return upperRight;
447+ }
448+ else {
449+ return null;
450+ }
451+ }
452+
453+
454+ /**
455+ * The preferred size of a <code>ScrollPane</code> is the size of the insets,
456+ * plus the preferred size of the viewport, plus the preferred size of
457+ * the visible headers, plus the preferred size of the scrollbars
458+ * that will appear given the current view and the current
459+ * scrollbar displayPolicies.
460+ * <p>Note that the rowHeader is calculated as part of the preferred width
461+ * and the colHeader is calculated as part of the preferred size.
462+ *
463+ * @param parent the <code>Container</code> that will be laid out
464+ * @return a <code>Dimension</code> object specifying the preferred size of the
465+ * viewport and any scrollbars
466+ * @see ViewportLayout
467+ * @see LayoutManager
468+ */
469+ public Dimension preferredLayoutSize(Container parent)
470+ {
471+ /* Sync the (now obsolete) policy fields with the
472+ * JScrollPane.
473+ */
474+ JScrollPane scrollPane = (JScrollPane)parent;
475+ vsbPolicy = scrollPane.getVerticalScrollBarPolicy();
476+ hsbPolicy = scrollPane.getHorizontalScrollBarPolicy();
477+
478+ Insets insets = parent.getInsets();
479+ int prefWidth = insets.left + insets.right;
480+ int prefHeight = insets.top + insets.bottom;
481+
482+ /* Note that viewport.getViewSize() is equivalent to
483+ * viewport.getView().getPreferredSize() modulo a null
484+ * view or a view whose size was explicitly set.
485+ */
486+
487+ Dimension extentSize = null;
488+ Dimension viewSize = null;
489+ Component view = null;
490+
491+ if (viewport != null) {
492+ extentSize = viewport.getPreferredSize();
493+ view = viewport.getView();
494+ if (view != null) {
495+ viewSize = view.getPreferredSize();
496+ } else {
497+ viewSize = new Dimension(0, 0);
498+ }
499+ }
500+
501+ /* If there's a viewport add its preferredSize.
502+ */
503+
504+ if (extentSize != null) {
505+ prefWidth += extentSize.width;
506+ prefHeight += extentSize.height;
507+ }
508+
509+ /* If there's a JScrollPane.viewportBorder, add its insets.
510+ */
511+
512+ Border viewportBorder = scrollPane.getViewportBorder();
513+ if (viewportBorder != null) {
514+ Insets vpbInsets = viewportBorder.getBorderInsets(parent);
515+ prefWidth += vpbInsets.left + vpbInsets.right;
516+ prefHeight += vpbInsets.top + vpbInsets.bottom;
517+ }
518+
519+ /* If a header exists and it's visible, factor its
520+ * preferred size in.
521+ */
522+
523+ if ((rowHead != null) && rowHead.isVisible()) {
524+ prefWidth += rowHead.getPreferredSize().width;
525+ }
526+
527+ if ((colHead != null) && colHead.isVisible()) {
528+ prefHeight += colHead.getPreferredSize().height;
529+ }
530+
531+ /* If a scrollbar is going to appear, factor its preferred size in.
532+ * If the scrollbars policy is AS_NEEDED, this can be a little
533+ * tricky:
534+ *
535+ * - If the view is a Scrollable then scrollableTracksViewportWidth
536+ * and scrollableTracksViewportHeight can be used to effectively
537+ * disable scrolling (if they're true) in their respective dimensions.
538+ *
539+ * - Assuming that a scrollbar hasn't been disabled by the
540+ * previous constraint, we need to decide if the scrollbar is going
541+ * to appear to correctly compute the JScrollPanes preferred size.
542+ * To do this we compare the preferredSize of the viewport (the
543+ * extentSize) to the preferredSize of the view. Although we're
544+ * not responsible for laying out the view we'll assume that the
545+ * JViewport will always give it its preferredSize.
546+ */
547+
548+ if ((vsb != null) && (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {
549+ if (vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS) {
550+ prefWidth += vsb.getPreferredSize().width;
551+ }
552+ else if ((viewSize != null) && (extentSize != null)) {
553+ boolean canScroll = true;
554+ if (view instanceof Scrollable) {
555+ canScroll = !((Scrollable)view).getScrollableTracksViewportHeight();
556+ }
557+ if (canScroll && (viewSize.height > extentSize.height)) {
558+ prefWidth += vsb.getPreferredSize().width;
559+ }
560+ }
561+ }
562+
563+ if ((hsb != null) && (hsbPolicy != HORIZONTAL_SCROLLBAR_NEVER)) {
564+ if (hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) {
565+ prefHeight += hsb.getPreferredSize().height;
566+ }
567+ else if ((viewSize != null) && (extentSize != null)) {
568+ boolean canScroll = true;
569+ if (view instanceof Scrollable) {
570+ canScroll = !((Scrollable)view).getScrollableTracksViewportWidth();
571+ }
572+ if (canScroll && (viewSize.width > extentSize.width)) {
573+ prefHeight += hsb.getPreferredSize().height;
574+ }
575+ }
576+ }
577+
578+ return new Dimension(prefWidth, prefHeight);
579+ }
580+
581+
582+ /**
583+ * The minimum size of a <code>ScrollPane</code> is the size of the insets
584+ * plus minimum size of the viewport, plus the scrollpane's
585+ * viewportBorder insets, plus the minimum size
586+ * of the visible headers, plus the minimum size of the
587+ * scrollbars whose displayPolicy isn't NEVER.
588+ *
589+ * @param parent the <code>Container</code> that will be laid out
590+ * @return a <code>Dimension</code> object specifying the minimum size
591+ */
592+ public Dimension minimumLayoutSize(Container parent)
593+ {
594+ /* Sync the (now obsolete) policy fields with the
595+ * JScrollPane.
596+ */
597+ JScrollPane scrollPane = (JScrollPane)parent;
598+ vsbPolicy = scrollPane.getVerticalScrollBarPolicy();
599+ hsbPolicy = scrollPane.getHorizontalScrollBarPolicy();
600+
601+ Insets insets = parent.getInsets();
602+ int minWidth = insets.left + insets.right;
603+ int minHeight = insets.top + insets.bottom;
604+
605+ /* If there's a viewport add its minimumSize.
606+ */
607+
608+ if (viewport != null) {
609+ Dimension size = viewport.getMinimumSize();
610+ minWidth += size.width;
611+ minHeight += size.height;
612+ }
613+
614+ /* If there's a JScrollPane.viewportBorder, add its insets.
615+ */
616+
617+ Border viewportBorder = scrollPane.getViewportBorder();
618+ if (viewportBorder != null) {
619+ Insets vpbInsets = viewportBorder.getBorderInsets(parent);
620+ minWidth += vpbInsets.left + vpbInsets.right;
621+ minHeight += vpbInsets.top + vpbInsets.bottom;
622+ }
623+
624+ /* If a header exists and it's visible, factor its
625+ * minimum size in.
626+ */
627+
628+ if ((rowHead != null) && rowHead.isVisible()) {
629+ Dimension size = rowHead.getMinimumSize();
630+ minWidth += size.width;
631+ minHeight = Math.max(minHeight, size.height);
632+ }
633+
634+ if ((colHead != null) && colHead.isVisible()) {
635+ Dimension size = colHead.getMinimumSize();
636+ minWidth = Math.max(minWidth, size.width);
637+ minHeight += size.height;
638+ }
639+
640+ /* If a scrollbar might appear, factor its minimum
641+ * size in.
642+ */
643+
644+ if ((vsb != null) && (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {
645+ Dimension size = vsb.getMinimumSize();
646+ minWidth += size.width;
647+ minHeight = Math.max(minHeight, size.height);
648+ }
649+
650+ if ((hsb != null) && (hsbPolicy != HORIZONTAL_SCROLLBAR_NEVER)) {
651+ Dimension size = hsb.getMinimumSize();
652+ minWidth = Math.max(minWidth, size.width);
653+ minHeight += size.height;
654+ }
655+
656+ return new Dimension(minWidth, minHeight);
657+ }
658+
659+
660+ /**
661+ * Lays out the scrollpane. The positioning of components depends on
662+ * the following constraints:
663+ * <ul>
664+ * <li> The row header, if present and visible, gets its preferred
665+ * width and the viewport's height.
666+ *
667+ * <li> The column header, if present and visible, gets its preferred
668+ * height and the viewport's width.
669+ *
670+ * <li> If a vertical scrollbar is needed, i.e. if the viewport's extent
671+ * height is smaller than its view height or if the <code>displayPolicy</code>
672+ * is ALWAYS, it's treated like the row header with respect to its
673+ * dimensions and is made visible.
674+ *
675+ * <li> If a horizontal scrollbar is needed, it is treated like the
676+ * column header (see the paragraph above regarding the vertical scrollbar).
677+ *
678+ * <li> If the scrollpane has a non-<code>null</code>
679+ * <code>viewportBorder</code>, then space is allocated for that.
680+ *
681+ * <li> The viewport gets the space available after accounting for
682+ * the previous constraints.
683+ *
684+ * <li> The corner components, if provided, are aligned with the
685+ * ends of the scrollbars and headers. If there is a vertical
686+ * scrollbar, the right corners appear; if there is a horizontal
687+ * scrollbar, the lower corners appear; a row header gets left
688+ * corners, and a column header gets upper corners.
689+ * </ul>
690+ *
691+ * @param parent the <code>Container</code> to lay out
692+ */
693+ public void layoutContainer(Container parent)
694+ {
695+ /* Sync the (now obsolete) policy fields with the
696+ * JScrollPane.
697+ */
698+ JScrollPane scrollPane = (JScrollPane)parent;
699+ vsbPolicy = scrollPane.getVerticalScrollBarPolicy();
700+ hsbPolicy = scrollPane.getHorizontalScrollBarPolicy();
701+
702+ Rectangle availR = scrollPane.getBounds();
703+ availR.x = availR.y = 0;
704+
705+ Insets insets = parent.getInsets();
706+ availR.x = insets.left;
707+ availR.y = insets.top;
708+ availR.width -= insets.left + insets.right;
709+ availR.height -= insets.top + insets.bottom;
710+
711+ /* Get the scrollPane's orientation.
712+ */
713+ boolean leftToRight = SwingUtilities.isLeftToRight(scrollPane);
714+
715+ /* If there's a visible column header remove the space it
716+ * needs from the top of availR. The column header is treated
717+ * as if it were fixed height, arbitrary width.
718+ */
719+
720+ Rectangle colHeadR = new Rectangle(0, availR.y, 0, 0);
721+
722+ if ((colHead != null) && (colHead.isVisible())) {
723+ int colHeadHeight = Math.min(availR.height,
724+ colHead.getPreferredSize().height);
725+ colHeadR.height = colHeadHeight;
726+ availR.y += colHeadHeight;
727+ availR.height -= colHeadHeight;
728+ }
729+
730+ /* If there's a visible row header remove the space it needs
731+ * from the left or right of availR. The row header is treated
732+ * as if it were fixed width, arbitrary height.
733+ */
734+
735+ Rectangle rowHeadR = new Rectangle(0, 0, 0, 0);
736+
737+ if ((rowHead != null) && (rowHead.isVisible())) {
738+ int rowHeadWidth = Math.min(availR.width,
739+ rowHead.getPreferredSize().width);
740+ rowHeadR.width = rowHeadWidth;
741+ availR.width -= rowHeadWidth;
742+ if ( leftToRight ) {
743+ rowHeadR.x = availR.x;
744+ availR.x += rowHeadWidth;
745+ } else {
746+ rowHeadR.x = availR.x + availR.width;
747+ }
748+ }
749+
750+ /* If there's a JScrollPane.viewportBorder, remove the
751+ * space it occupies for availR.
752+ */
753+
754+ Border viewportBorder = scrollPane.getViewportBorder();
755+ Insets vpbInsets;
756+ if (viewportBorder != null) {
757+ vpbInsets = viewportBorder.getBorderInsets(parent);
758+ availR.x += vpbInsets.left;
759+ availR.y += vpbInsets.top;
760+ availR.width -= vpbInsets.left + vpbInsets.right;
761+ availR.height -= vpbInsets.top + vpbInsets.bottom;
762+ }
763+ else {
764+ vpbInsets = new Insets(0,0,0,0);
765+ }
766+
767+
768+ /* At this point availR is the space available for the viewport
769+ * and scrollbars. rowHeadR is correct except for its height and y
770+ * and colHeadR is correct except for its width and x. Once we're
771+ * through computing the dimensions of these three parts we can
772+ * go back and set the dimensions of rowHeadR.height, rowHeadR.y,
773+ * colHeadR.width, colHeadR.x and the bounds for the corners.
774+ *
775+ * We'll decide about putting up scrollbars by comparing the
776+ * viewport views preferred size with the viewports extent
777+ * size (generally just its size). Using the preferredSize is
778+ * reasonable because layout proceeds top down - so we expect
779+ * the viewport to be laid out next. And we assume that the
780+ * viewports layout manager will give the view it's preferred
781+ * size. One exception to this is when the view implements
782+ * Scrollable and Scrollable.getViewTracksViewport{Width,Height}
783+ * methods return true. If the view is tracking the viewports
784+ * width we don't bother with a horizontal scrollbar, similarly
785+ * if view.getViewTracksViewport(Height) is true we don't bother
786+ * with a vertical scrollbar.
787+ */
788+
789+ Component view = (viewport != null) ? viewport.getView() : null;
790+ Dimension viewPrefSize =
791+ (view != null) ? view.getPreferredSize()
792+ : new Dimension(0,0);
793+
794+ Dimension extentSize =
795+ (viewport != null) ? viewport.toViewCoordinates(availR.getSize())
796+ : new Dimension(0,0);
797+
798+ boolean viewTracksViewportWidth = false;
799+ boolean viewTracksViewportHeight = false;
800+ boolean isEmpty = (availR.width < 0 || availR.height < 0);
801+ Scrollable sv;
802+ // Don't bother checking the Scrollable methods if there is no room
803+ // for the viewport, we aren't going to show any scrollbars in this
804+ // case anyway.
805+ if (!isEmpty && view instanceof Scrollable) {
806+ sv = (Scrollable)view;
807+ viewTracksViewportWidth = sv.getScrollableTracksViewportWidth();
808+ viewTracksViewportHeight = sv.getScrollableTracksViewportHeight();
809+ }
810+ else {
811+ sv = null;
812+ }
813+
814+ /* If there's a vertical scrollbar and we need one, allocate
815+ * space for it (we'll make it visible later). A vertical
816+ * scrollbar is considered to be fixed width, arbitrary height.
817+ */
818+
819+ Rectangle vsbR = new Rectangle(0, availR.y - vpbInsets.top, 0, 0);
820+
821+ boolean vsbNeeded;
822+ if (isEmpty) {
823+ vsbNeeded = false;
824+ }
825+ else if (vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS) {
826+ vsbNeeded = true;
827+ }
828+ else if (vsbPolicy == VERTICAL_SCROLLBAR_NEVER) {
829+ vsbNeeded = false;
830+ }
831+ else { // vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED
832+ vsbNeeded = !viewTracksViewportHeight && (viewPrefSize.height > extentSize.height);
833+ }
834+
835+
836+ if ((vsb != null) && vsbNeeded) {
837+ adjustForVSB(true, availR, vsbR, vpbInsets, leftToRight);
838+ extentSize = viewport.toViewCoordinates(availR.getSize());
839+ }
840+
841+ /* If there's a horizontal scrollbar and we need one, allocate
842+ * space for it (we'll make it visible later). A horizontal
843+ * scrollbar is considered to be fixed height, arbitrary width.
844+ */
845+
846+ Rectangle hsbR = new Rectangle(availR.x - vpbInsets.left, 0, 0, 0);
847+ boolean hsbNeeded;
848+ if (isEmpty) {
849+ hsbNeeded = false;
850+ }
851+ else if (hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) {
852+ hsbNeeded = true;
853+ }
854+ else if (hsbPolicy == HORIZONTAL_SCROLLBAR_NEVER) {
855+ hsbNeeded = false;
856+ }
857+ else { // hsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED
858+ hsbNeeded = !viewTracksViewportWidth && (viewPrefSize.width > extentSize.width);
859+ }
860+
861+ if ((hsb != null) && hsbNeeded) {
862+ adjustForHSB(true, availR, hsbR, vpbInsets);
863+
864+ /* If we added the horizontal scrollbar then we've implicitly
865+ * reduced the vertical space available to the viewport.
866+ * As a consequence we may have to add the vertical scrollbar,
867+ * if that hasn't been done so already. Of course we
868+ * don't bother with any of this if the vsbPolicy is NEVER.
869+ */
870+ if ((vsb != null) && !vsbNeeded &&
871+ (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {
872+
873+ extentSize = viewport.toViewCoordinates(availR.getSize());
874+ vsbNeeded = viewPrefSize.height > extentSize.height;
875+
876+ if (vsbNeeded) {
877+ adjustForVSB(true, availR, vsbR, vpbInsets, leftToRight);
878+ }
879+ }
880+ }
881+
882+ /* Set the size of the viewport first, and then recheck the Scrollable
883+ * methods. Some components base their return values for the Scrollable
884+ * methods on the size of the Viewport, so that if we don't
885+ * ask after resetting the bounds we may have gotten the wrong
886+ * answer.
887+ */
888+
889+ if (viewport != null) {
890+ viewport.setBounds(availR);
891+
892+ if (sv != null) {
893+ extentSize = viewport.toViewCoordinates(availR.getSize());
894+
895+ boolean oldHSBNeeded = hsbNeeded;
896+ boolean oldVSBNeeded = vsbNeeded;
897+ viewTracksViewportWidth = sv.
898+ getScrollableTracksViewportWidth();
899+ viewTracksViewportHeight = sv.
900+ getScrollableTracksViewportHeight();
901+ if (vsb != null && vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED) {
902+ boolean newVSBNeeded = !viewTracksViewportHeight &&
903+ (viewPrefSize.height > extentSize.height);
904+ if (newVSBNeeded != vsbNeeded) {
905+ vsbNeeded = newVSBNeeded;
906+ adjustForVSB(vsbNeeded, availR, vsbR, vpbInsets,
907+ leftToRight);
908+ extentSize = viewport.toViewCoordinates
909+ (availR.getSize());
910+ }
911+ }
912+ if (hsb != null && hsbPolicy ==HORIZONTAL_SCROLLBAR_AS_NEEDED){
913+ boolean newHSBbNeeded = !viewTracksViewportWidth &&
914+ (viewPrefSize.width > extentSize.width);
915+ if (newHSBbNeeded != hsbNeeded) {
916+ hsbNeeded = newHSBbNeeded;
917+ adjustForHSB(hsbNeeded, availR, hsbR, vpbInsets);
918+ if ((vsb != null) && !vsbNeeded &&
919+ (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {
920+
921+ extentSize = viewport.toViewCoordinates
922+ (availR.getSize());
923+ vsbNeeded = viewPrefSize.height >
924+ extentSize.height;
925+
926+ if (vsbNeeded) {
927+ adjustForVSB(true, availR, vsbR, vpbInsets,
928+ leftToRight);
929+ }
930+ }
931+ }
932+ }
933+ if (oldHSBNeeded != hsbNeeded ||
934+ oldVSBNeeded != vsbNeeded) {
935+ viewport.setBounds(availR);
936+ // You could argue that we should recheck the
937+ // Scrollable methods again until they stop changing,
938+ // but they might never stop changing, so we stop here
939+ // and don't do any additional checks.
940+ }
941+ }
942+ }
943+
944+ /* We now have the final size of the viewport: availR.
945+ * Now fixup the header and scrollbar widths/heights.
946+ */
947+ vsbR.height = availR.height + vpbInsets.top + vpbInsets.bottom;
948+ hsbR.width = availR.width + vpbInsets.left + vpbInsets.right;
949+ rowHeadR.height = availR.height + vpbInsets.top + vpbInsets.bottom;
950+ rowHeadR.y = availR.y - vpbInsets.top;
951+ colHeadR.width = availR.width + vpbInsets.left + vpbInsets.right;
952+ colHeadR.x = availR.x - vpbInsets.left;
953+
954+ /* Set the bounds of the remaining components. The scrollbars
955+ * are made invisible if they're not needed.
956+ */
957+
958+ if (rowHead != null) {
959+ rowHead.setBounds(rowHeadR);
960+ }
961+
962+ if (colHead != null) {
963+ colHead.setBounds(colHeadR);
964+ }
965+
966+ if (vsb != null) {
967+ if (vsbNeeded) {
968+ if (colHead != null &&
969+ UIManager.getBoolean("ScrollPane.fillUpperCorner"))
970+ {
971+ if ((leftToRight && upperRight == null) ||
972+ (!leftToRight && upperLeft == null))
973+ {
974+ // This is used primarily for GTK L&F, which needs to
975+ // extend the vertical scrollbar to fill the upper
976+ // corner near the column header. Note that we skip
977+ // this step (and use the default behavior) if the
978+ // user has set a custom corner component.
979+ vsbR.y = colHeadR.y;
980+ vsbR.height += colHeadR.height;
981+ }
982+ }
983+ vsb.setVisible(true);
984+ vsb.setBounds(vsbR);
985+ }
986+ else {
987+ vsb.setVisible(false);
988+ }
989+ }
990+
991+ if (hsb != null) {
992+ if (hsbNeeded) {
993+ if (rowHead != null &&
994+ UIManager.getBoolean("ScrollPane.fillLowerCorner"))
995+ {
996+ if ((leftToRight && lowerLeft == null) ||
997+ (!leftToRight && lowerRight == null))
998+ {
999+ // This is used primarily for GTK L&F, which needs to
1000+ // extend the horizontal scrollbar to fill the lower
1001+ // corner near the row header. Note that we skip
1002+ // this step (and use the default behavior) if the
1003+ // user has set a custom corner component.
1004+ if (leftToRight) {
1005+ hsbR.x = rowHeadR.x;
1006+ }
1007+ hsbR.width += rowHeadR.width;
1008+ }
1009+ }
1010+ hsb.setVisible(true);
1011+ hsb.setBounds(hsbR);
1012+ }
1013+ else {
1014+ hsb.setVisible(false);
1015+ }
1016+ }
1017+
1018+ if (lowerLeft != null) {
1019+ lowerLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x,
1020+ hsbR.y,
1021+ leftToRight ? rowHeadR.width : vsbR.width,
1022+ hsbR.height);
1023+ }
1024+
1025+ if (lowerRight != null) {
1026+ lowerRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x,
1027+ hsbR.y,
1028+ leftToRight ? vsbR.width : rowHeadR.width,
1029+ hsbR.height);
1030+ }
1031+
1032+ if (upperLeft != null) {
1033+ upperLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x,
1034+ colHeadR.y,
1035+ leftToRight ? rowHeadR.width : vsbR.width,
1036+ colHeadR.height);
1037+ }
1038+
1039+ if (upperRight != null) {
1040+ upperRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x,
1041+ colHeadR.y,
1042+ leftToRight ? vsbR.width : rowHeadR.width,
1043+ colHeadR.height);
1044+ }
1045+ }
1046+
1047+ /**
1048+ * Adjusts the <code>Rectangle</code> <code>available</code> based on if
1049+ * the vertical scrollbar is needed (<code>wantsVSB</code>).
1050+ * The location of the vsb is updated in <code>vsbR</code>, and
1051+ * the viewport border insets (<code>vpbInsets</code>) are used to offset
1052+ * the vsb. This is only called when <code>wantsVSB</code> has
1053+ * changed, eg you shouldn't invoke adjustForVSB(true) twice.
1054+ */
1055+ private void adjustForVSB(boolean wantsVSB, Rectangle available,
1056+ Rectangle vsbR, Insets vpbInsets,
1057+ boolean leftToRight) {
1058+ int oldWidth = vsbR.width;
1059+ if (wantsVSB) {
1060+ int vsbWidth = Math.max(0, Math.min(vsb.getPreferredSize().width,
1061+ available.width));
1062+
1063+ available.width -= vsbWidth;
1064+ vsbR.width = vsbWidth;
1065+
1066+ if( leftToRight ) {
1067+ vsbR.x = available.x + available.width + vpbInsets.right;
1068+ } else {
1069+ vsbR.x = available.x - vpbInsets.left;
1070+ available.x += vsbWidth;
1071+ }
1072+ }
1073+ else {
1074+ available.width += oldWidth;
1075+ }
1076+ }
1077+
1078+ /**
1079+ * Adjusts the <code>Rectangle</code> <code>available</code> based on if
1080+ * the horizontal scrollbar is needed (<code>wantsHSB</code>).
1081+ * The location of the hsb is updated in <code>hsbR</code>, and
1082+ * the viewport border insets (<code>vpbInsets</code>) are used to offset
1083+ * the hsb. This is only called when <code>wantsHSB</code> has
1084+ * changed, eg you shouldn't invoked adjustForHSB(true) twice.
1085+ */
1086+ private void adjustForHSB(boolean wantsHSB, Rectangle available,
1087+ Rectangle hsbR, Insets vpbInsets) {
1088+ int oldHeight = hsbR.height;
1089+ if (wantsHSB) {
1090+ int hsbHeight = Math.max(0, Math.min(available.height,
1091+ hsb.getPreferredSize().height));
1092+
1093+ available.height -= hsbHeight;
1094+ hsbR.y = available.y + available.height + vpbInsets.bottom;
1095+ hsbR.height = hsbHeight;
1096+ }
1097+ else {
1098+ available.height += oldHeight;
1099+ }
1100+ }
1101+
1102+
1103+
1104+ /**
1105+ * Returns the bounds of the border around the specified scroll pane's
1106+ * viewport.
1107+ *
1108+ * @return the size and position of the viewport border
1109+ * @deprecated As of JDK version Swing1.1
1110+ * replaced by <code>JScrollPane.getViewportBorderBounds()</code>.
1111+ */
1112+ @Deprecated
1113+ public Rectangle getViewportBorderBounds(JScrollPane scrollpane) {
1114+ return scrollpane.getViewportBorderBounds();
1115+ }
1116+
1117+ /**
1118+ * The UI resource version of <code>ScrollPaneLayout</code>.
1119+ */
1120+ public static class UIResource extends ScrollPaneLayout implements javax.swing.plaf.UIResource {}
1121+}