1 /* |
|
2 * CDDL HEADER START |
|
3 * |
|
4 * The contents of this file are subject to the terms of the |
|
5 * Common Development and Distribution License (the "License"). |
|
6 * You may not use this file except in compliance with the License. |
|
7 * |
|
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 * or http://www.opensolaris.org/os/licensing. |
|
10 * See the License for the specific language governing permissions |
|
11 * and limitations under the License. |
|
12 * |
|
13 * When distributing Covered Code, include this CDDL HEADER in each |
|
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 * If applicable, add the following below this CDDL HEADER, with the |
|
16 * fields enclosed by brackets "[]" replaced with your own identifying |
|
17 * information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 * |
|
19 * CDDL HEADER END |
|
20 */ |
|
21 |
|
22 /* |
|
23 * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. |
|
24 */ |
|
25 |
|
26 package com.oracle.solaris.vp.util.swing.layout; |
|
27 |
|
28 import java.awt.*; |
|
29 import javax.swing.JTabbedPane; |
|
30 |
|
31 public class TabbedPaneOverlayLayout extends |
|
32 UniqueConstrainedLayout<TabbedPaneOverlayLayout.Constraint> { |
|
33 |
|
34 // |
|
35 // Enums |
|
36 // |
|
37 |
|
38 public enum Constraint { |
|
39 TABS, OVERLAY |
|
40 } |
|
41 |
|
42 // |
|
43 // Constructors |
|
44 // |
|
45 |
|
46 public TabbedPaneOverlayLayout() { |
|
47 super(Constraint.TABS); |
|
48 } |
|
49 |
|
50 // |
|
51 // LayoutManager methods |
|
52 // |
|
53 |
|
54 /** |
|
55 * Lay out Components in the given Container. Assume a column-stacked |
|
56 * anchor, which can be overridden in this class's abstract methods. |
|
57 */ |
|
58 @Override |
|
59 public void layoutContainer(Container container) { |
|
60 Insets insets = container.getInsets(); |
|
61 Dimension cSize = container.getSize(); |
|
62 |
|
63 // The amount of space we have to work with |
|
64 int aWidth = cSize.width - insets.left - insets.right; |
|
65 int aHeight = cSize.height - insets.top - insets.bottom; |
|
66 |
|
67 // The amount the tabs must be shifted down to accomodate the component |
|
68 int tOffsetY = 0; |
|
69 |
|
70 Dimension tabsPreferred = null; |
|
71 |
|
72 JTabbedPane tabs = (JTabbedPane)constToComp.get(Constraint.TABS); |
|
73 if (tabs != null && tabs.isVisible()) { |
|
74 tabsPreferred = tabs.getPreferredSize(); |
|
75 } |
|
76 |
|
77 Component comp = constToComp.get(Constraint.OVERLAY); |
|
78 if (comp != null && comp.isVisible()) { |
|
79 Dimension compPreferred = comp.getPreferredSize(); |
|
80 |
|
81 int cWidth = compPreferred.width; |
|
82 int cHeight = compPreferred.height; |
|
83 |
|
84 if (tabsPreferred != null) { |
|
85 // Both tabs and comp are visible |
|
86 int tHeight = getTabsHeight(tabs); |
|
87 |
|
88 if (tHeight > cHeight) { |
|
89 cHeight = tHeight; |
|
90 } else { |
|
91 tOffsetY = cHeight - tHeight; |
|
92 } |
|
93 |
|
94 container.setComponentZOrder(comp, 0); |
|
95 container.setComponentZOrder(tabs, 1); |
|
96 } |
|
97 |
|
98 comp.setBounds( |
|
99 insets.left + aWidth - cWidth, insets.top, cWidth, cHeight); |
|
100 } |
|
101 |
|
102 if (tabsPreferred != null) { |
|
103 tabs.setBounds( |
|
104 insets.left, insets.top + tOffsetY, aWidth, aHeight - tOffsetY); |
|
105 } |
|
106 } |
|
107 |
|
108 // |
|
109 // AbstractLayout methods |
|
110 // |
|
111 |
|
112 @Override |
|
113 protected Dimension getLayoutSize(Container container, boolean preferred) { |
|
114 boolean tabsVisible = false; |
|
115 boolean compVisible = false; |
|
116 |
|
117 int width = 0; |
|
118 int height = 0; |
|
119 |
|
120 JTabbedPane tabs = (JTabbedPane)constToComp.get(Constraint.TABS); |
|
121 if (tabs != null && tabs.isVisible()) { |
|
122 tabsVisible = true; |
|
123 |
|
124 Dimension d = preferred ? |
|
125 tabs.getPreferredSize() : tabs.getMinimumSize(); |
|
126 |
|
127 width = d.width; |
|
128 height = d.height; |
|
129 } |
|
130 |
|
131 Component comp = constToComp.get(Constraint.OVERLAY); |
|
132 if (comp != null && comp.isVisible()) { |
|
133 compVisible = true; |
|
134 |
|
135 Dimension d = preferred ? |
|
136 comp.getPreferredSize() : comp.getMinimumSize(); |
|
137 |
|
138 if (tabsVisible) { |
|
139 int tHeight = getTabsHeight(tabs); |
|
140 int tWidth = getTabsWidth(tabs); |
|
141 |
|
142 d.width += tWidth; |
|
143 width = Math.max(width, d.width); |
|
144 |
|
145 if (tHeight < d.height) { |
|
146 height += d.height - tHeight; |
|
147 } |
|
148 } |
|
149 } |
|
150 |
|
151 Insets insets = container.getInsets(); |
|
152 width += insets.left + insets.right; |
|
153 height += insets.top + insets.bottom; |
|
154 |
|
155 return new Dimension(width, height); |
|
156 } |
|
157 |
|
158 // |
|
159 // Private methods |
|
160 // |
|
161 |
|
162 private int getTabsHeight(JTabbedPane tabs) { |
|
163 int highestBottom = -1; |
|
164 |
|
165 // Find the tab whose bottom edge is closest to the top |
|
166 for (int i = 0, n = tabs.getTabCount(); i < n; i++) { |
|
167 Rectangle bounds = tabs.getBoundsAt(i); |
|
168 if (bounds != null) { |
|
169 int bottom = bounds.y + bounds.height; |
|
170 |
|
171 if (highestBottom < 0 || bottom < highestBottom) { |
|
172 highestBottom = bottom; |
|
173 } |
|
174 } |
|
175 } |
|
176 |
|
177 return highestBottom < 0 ? 0 : highestBottom; |
|
178 } |
|
179 |
|
180 private int getTabsWidth(JTabbedPane tabs) { |
|
181 int width = 0; |
|
182 |
|
183 for (int i = 0, n = tabs.getTabCount(); i < n; i++) { |
|
184 Rectangle bounds = tabs.getBoundsAt(i); |
|
185 if (bounds != null) { |
|
186 width = Math.max(width, bounds.x + bounds.width); |
|
187 } |
|
188 } |
|
189 |
|
190 return width; |
|
191 } |
|
192 } |
|