1 package org.telscenter.pas.common.ui.panel;
2
3 import java.awt.Component;
4 import java.awt.Container;
5 import java.awt.Dimension;
6 import java.awt.Insets;
7 import java.awt.LayoutManager;
8 import java.awt.Rectangle;
9
10 import javax.swing.JComponent;
11 import javax.swing.JPanel;
12
13 /***
14 * A simpler alternative to a JPanel with a CardLayout. The AWT CardLayout
15 * layout manager can be inconvenient to use because the special "stack of
16 * cards" operations it supports require a cast to use. For example to show the
17 * card named "myCard" given a JPanel with a CardLayout one would write:
18 *
19 * <pre>
20 * ((CardLayout) (myJPanel.getLayout())).show(myJPanel, "myCard");
21 * </pre>
22 *
23 * This doesn't work well with Swing - all of the CardLayout display operations,
24 * like <code>show</code> call validate directly. Swing supports automatic
25 * validation (see JComponent.revalidate()); this direct call to validate is
26 * inefficient.
27 * <p>
28 * The CardPane JPanel subclass is intended to support a layout with a modest
29 * number of cards, on the order of 100 or less. A cards name is it's component
30 * name, as in java.awt.Component.getName(), which is set when the component is
31 * added to the CardPanel:
32 *
33 * <pre>
34 * myCardPanel.add(myChild, "MyChildName");
35 * myChild.getName() <i>=> "MyChildName"</i>
36 * </pre>
37 *
38 * As with CardLayout, the first child added to a CardPanel is made visible and
39 * there's only one child visible at a time. The <code>showCard</code> method
40 * accepts either a childs name or the child itself:
41 *
42 * <pre>
43 * myCardPanel.show("MyChildName");
44 * myCardPanel.show(myChild);
45 * </pre>
46 *
47 * <p>
48 * The CardPanel class doesn't support the vgap/hgap CardLayout properties since
49 * one can add a Border, see JComponent.setBorder().
50 */
51
52 public class CardPanel extends JPanel {
53 private static class Layout implements LayoutManager {
54 /***
55 * Set the childs name (if non-null) and and make it visible iff it's
56 * the only CardPanel child.
57 *
58 * @see java.awt.Component#setName
59 */
60 public void addLayoutComponent(String name, Component child) {
61 if (name != null) {
62 child.setName(name);
63 }
64 child.setVisible(child.getParent().getComponentCount() == 1);
65 }
66
67 /***
68 * If this child was visible, then make the first remaining child
69 * visible.
70 */
71 public void removeLayoutComponent(Component child) {
72 if (child.isVisible()) {
73 Container parent = child.getParent();
74 if (parent.getComponentCount() > 0) {
75 parent.getComponent(0).setVisible(true);
76 }
77 }
78 }
79
80 /***
81 * @return the maximum preferred width/height + the parents insets
82 */
83 public Dimension preferredLayoutSize(Container parent) {
84 int nChildren = parent.getComponentCount();
85 Insets insets = parent.getInsets();
86 int width = insets.left + insets.right;
87 int height = insets.top + insets.bottom;
88
89 for (int i = 0; i < nChildren; i++) {
90 Dimension d = parent.getComponent(i).getPreferredSize();
91 if (d.width > width) {
92 width = d.width;
93 }
94 if (d.height > height) {
95 height = d.height;
96 }
97 }
98 return new Dimension(width, height);
99 }
100
101 /***
102 * @return the maximum minimum width/height + the parents insets
103 */
104 public Dimension minimumLayoutSize(Container parent) {
105 int nChildren = parent.getComponentCount();
106 Insets insets = parent.getInsets();
107 int width = insets.left + insets.right;
108 int height = insets.top + insets.bottom;
109
110 for (int i = 0; i < nChildren; i++) {
111 Dimension d = parent.getComponent(i).getMinimumSize();
112 if (d.width > width) {
113 width = d.width;
114 }
115 if (d.height > height) {
116 height = d.height;
117 }
118 }
119 return new Dimension(width, height);
120 }
121
122 public void layoutContainer(Container parent) {
123 int nChildren = parent.getComponentCount();
124 Insets insets = parent.getInsets();
125 for (int i = 0; i < nChildren; i++) {
126 Component child = parent.getComponent(i);
127 if (child.isVisible()) {
128 Rectangle r = parent.getBounds();
129 int width = r.width - insets.left + insets.right;
130 int height = r.height - insets.top + insets.bottom;
131 child.setBounds(insets.left, insets.top, width, height);
132 break;
133 }
134 }
135 }
136 }
137
138 /***
139 * Creates a CardPanel. Children, called "cards" in this API, should be
140 * added with add(). The first child we be made visible, subsequent children
141 * will be hidden. To show a card, use one of the show*Card methods.
142 */
143 public CardPanel() {
144 super(new Layout());
145 }
146
147 /***
148 * Return the index of the first (and one would hope - only) visible child.
149 * If a visible child can't be found, perhaps the caller has inexlicably
150 * hidden all of the children, then return -1.
151 */
152 private int getVisibleChildIndex() {
153 int nChildren = getComponentCount();
154 for (int i = 0; i < nChildren; i++) {
155 Component child = getComponent(i);
156 if (child.isVisible()) {
157 return i;
158 }
159 }
160 return -1;
161 }
162
163 /***
164 * Hide the currently visible child "card" and show the specified card. If
165 * the specified card isn't a child of the CardPanel then we add it here.
166 */
167 public void showCard(Component card) {
168 if (card.getParent() != this) {
169 add(card);
170 }
171 int index = getVisibleChildIndex();
172 if (index != -1) {
173 getComponent(index).setVisible(false);
174 }
175 card.setVisible(true);
176 revalidate();
177 repaint();
178 }
179
180 /***
181 * Show the card with the specified name.
182 *
183 * @see java.awt.Component#getName
184 */
185 public void showCard(String name) {
186 int nChildren = getComponentCount();
187 for (int i = 0; i < nChildren; i++) {
188 Component child = getComponent(i);
189 if (child.getName() != null) {
190 if (child.getName().equals(name)) {
191 showCard(child);
192 break;
193 }
194 }
195 }
196 }
197
198 public Component getCard(String name) {
199 int nChildren = getComponentCount();
200 for (int i = 0; i < nChildren; i++) {
201 Component child = getComponent(i);
202 if (child.getName().equals(name)) {
203 return child;
204 }
205 }
206 return null;
207 }
208
209 public void printCardName() {
210 int nChildren = getComponentCount();
211 for (int i = 0; i < nChildren; i++) {
212 Component child = getComponent(i);
213 System.out.println("CARD NAME: " + child.getName());
214 }
215 }
216
217 /***
218 * Removes the results card from the card panel stack
219 */
220 protected void removeCard(String name) {
221 int nChildren = getComponentCount();
222 for (int i = 0; i < nChildren; i++) {
223 Component child = getComponent(i);
224 if (child.getName().equals(name)) {
225 remove(child);
226 revalidate();
227 break;
228 }
229 }
230 }
231
232 /***
233 * Show the card that was added to this CardPanel after the currently
234 * visible card. If the currently visible card was added last, then show the
235 * first card.
236 */
237 public void showNextCard() {
238 if (getComponentCount() <= 0) {
239 return;
240 }
241 int index = getVisibleChildIndex();
242 if (index == -1) {
243 showCard(getComponent(0));
244 } else if (index == (getComponentCount() - 1)) {
245 showCard(getComponent(0));
246 } else {
247 showCard(getComponent(index + 1));
248 }
249 }
250
251 /***
252 * Show the card that was added to this CardPanel before the currently
253 * visible card. If the currently visible card was added first, then show
254 * the last card.
255 */
256 public void showPreviousCard() {
257 if (getComponentCount() <= 0) {
258 return;
259 }
260 int index = getVisibleChildIndex();
261 if (index == -1) {
262 showCard(getComponent(0));
263 } else if (index == 0) {
264 showCard(getComponent(getComponentCount() - 1));
265 } else {
266 showCard(getComponent(index - 1));
267 }
268 }
269
270 /***
271 * Show the first card that was added to this CardPanel.
272 */
273 public void showFirstCard() {
274 if (getComponentCount() <= 0) {
275 return;
276 }
277 showCard(getComponent(0));
278 }
279
280 /***
281 * Show the last card that was added to this CardPanel.
282 */
283 public void showLastCard() {
284 if (getComponentCount() <= 0) {
285 return;
286 }
287 showCard(getComponent(getComponentCount() - 1));
288 }
289 }