View Javadoc

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, &quot;myCard&quot;);
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, &quot;MyChildName&quot;);
35   *  myChild.getName() &lt;i&gt;=&gt; &quot;MyChildName&quot;&lt;/i&gt;
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(&quot;MyChildName&quot;);
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 				}// if
194 			}// if
195 		}// for
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 			}// if
205 		}// for
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 		}// for
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 			}// if
229 		}// for
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 }