1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.gui.component;
21
22 import java.awt.CardLayout;
23 import java.awt.Component;
24 import java.awt.Container;
25
26 import javax.swing.DefaultListModel;
27 import javax.swing.Icon;
28 import javax.swing.ImageIcon;
29 import javax.swing.JLabel;
30 import javax.swing.JList;
31 import javax.swing.JScrollPane;
32 import javax.swing.JSplitPane;
33 import javax.swing.ListCellRenderer;
34 import javax.swing.ListSelectionModel;
35 import javax.swing.SwingConstants;
36 import javax.swing.border.EmptyBorder;
37 import javax.swing.event.ChangeEvent;
38 import javax.swing.event.ChangeListener;
39 import javax.swing.event.ListSelectionEvent;
40 import javax.swing.event.ListSelectionListener;
41
42 /***
43 * This class provides a tabbed pane like behaving widget. The
44 * <code>IconSplitPane</code> is split up in two parts. The left part is a
45 * {@link javax.swing.JList JList} that contains icons and their descriptions.
46 * The right part can be any component. If the user selects on of the icons
47 * from the list the respective panel is show at the right.
48 *
49 * <p>The names of the methods are modelled after the
50 * {@link javax.swing.JTabbedPane JTabbedPane}.
51 */
52 public class IconSplitPane extends JSplitPane
53 {
54
55
56
57
58
59 private JList jlIcons;
60 private DefaultListModel dlmIcons;
61 private CardLayout clCenter;
62 private Container jpCenter;
63 private transient ChangeEvent changeEvent = null;
64
65
66
67 public IconSplitPane()
68 {
69 super(JSplitPane.HORIZONTAL_SPLIT);
70
71 initialize();
72 }
73
74
75
76 private void initialize()
77 {
78 setOneTouchExpandable(true);
79
80 jlIcons = new JList();
81 dlmIcons = new DefaultListModel();
82 jlIcons.setModel(dlmIcons);
83 jlIcons.addListSelectionListener(new IconListener());
84 jlIcons.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
85 jlIcons.setCellRenderer(new IconRenderer());
86
87 JScrollPane jspIcons = new JScrollPane(jlIcons);
88 jspIcons.setHorizontalScrollBarPolicy
89 (JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
90 add(jspIcons, JSplitPane.LEFT);
91
92 clCenter = new CardLayout();
93 jpCenter = new Container();
94 jpCenter.setLayout(clCenter);
95 add(jpCenter, JSplitPane.RIGHT);
96 }
97
98 /***
99 * Adds a new tab.
100 */
101 public void addTab(String description, Icon icon, Component c)
102 {
103 insertTab(description, icon, c, dlmIcons.size());
104 }
105
106 /***
107 * Inserts a new tab at <code>index</code>.
108 */
109 public void insertTab(String description, Icon icon, Component c,
110 int index)
111 {
112 if (icon != null) {
113 if (icon instanceof ImageIcon) {
114 ((ImageIcon)icon).setDescription(description);
115 }
116 dlmIcons.insertElementAt(icon, index);
117 }
118 else {
119 dlmIcons.insertElementAt(description, index);
120 }
121
122 jpCenter.add(c, description, index);
123 setDividerLocation(jlIcons.getPreferredSize().width + 30);
124
125 if (dlmIcons.size() == 1) {
126 jlIcons.setSelectedIndex(0);
127
128 }
129 else if (jlIcons.getSelectedIndex() >= index) {
130 jlIcons.setSelectedIndex(jlIcons.getSelectedIndex() + 1);
131 }
132 }
133
134 /***
135 * Returns all tabs as an array.
136 */
137 public Component[] getTabs()
138 {
139 return jpCenter.getComponents();
140 }
141
142 /***
143 * Returns the tab at index <code>i</code>.
144 */
145 public Component getTabAt(int i)
146 {
147 return jpCenter.getComponents()[i];
148 }
149
150 /***
151 * Returns the number of tabs.
152 */
153 public int getTabCount()
154 {
155 return jpCenter.getComponentCount();
156 }
157
158 /***
159 * Returns the description at index <code>i</code>.
160 */
161 public String getDescriptionAt(int i)
162 {
163 Object o = dlmIcons.get(i);
164 if (o != null) {
165 if (o instanceof ImageIcon) {
166 return ((ImageIcon)o).getDescription();
167 }
168 return o.toString();
169 }
170
171 return null;
172 }
173
174 /***
175 * Returns the icon at index <code>i</code>.
176 */
177 public Icon getIconAt(int i)
178 {
179 Object o = dlmIcons.get(i);
180 if (o instanceof Icon) {
181 return (Icon)o;
182 }
183 else {
184 return null;
185 }
186 }
187
188 /***
189 * Returns the title at index <code>i</code>.
190 */
191 public String getTitleAt(int i)
192 {
193 return dlmIcons.get(i).toString();
194 }
195
196 /***
197 * Sets the icon at index <code>i</code> to <code>icon</code>.
198 */
199 public void setIconAt(int i, Icon icon)
200 {
201 if (icon != null) {
202 if (icon instanceof ImageIcon) {
203 ((ImageIcon)icon).setDescription(getDescriptionAt(i));
204 }
205
206 dlmIcons.set(i, icon);
207 }
208 }
209
210 /***
211 * Returns the <code>index</code> of the currently selected tab.
212 */
213 public int getSelectedIndex()
214 {
215 return jlIcons.getSelectedIndex();
216 }
217
218 /***
219 * Selects <code>c</code>. The corresponding icon will also be selected.
220 */
221 public void setSelectedComponent(Component c)
222 {
223 int i = indexOfComponent(c);
224 if (i != -1) {
225 jlIcons.setSelectedIndex(i);
226 }
227 }
228
229 /***
230 * Returns the index of <code>c</code>.
231 */
232 public int indexOfComponent(Component c)
233 {
234 int count = jpCenter.getComponentCount();
235 for (int i = 0; i < count; i++) {
236 if (jpCenter.getComponent(i) == c) {
237 return i;
238 }
239 }
240
241 return -1;
242 }
243
244 /***
245 * Removes tab <code>c</code>.
246 */
247 public void remove(Component c)
248 {
249 if (jpCenter == null)
250 return;
251
252 int i = indexOfComponent(c);
253 if (i != -1) {
254 removeTabAt(i);
255 }
256 }
257
258 /***
259 * Removes tab at index <code>i</code>.
260 */
261 public void removeTabAt(int i)
262 {
263 if (i == jlIcons.getSelectedIndex()) {
264 jlIcons.setSelectedIndex(0);
265 }
266 jpCenter.remove(i);
267 dlmIcons.remove(i);
268 }
269
270 /***
271 * Adds a listener that gets notified when a tab is selected.
272 */
273 public void addChangeListener(ChangeListener l)
274 {
275 listenerList.add(ChangeListener.class, l);
276 }
277
278 /***
279 * Removes a <code>ChangeListener</code>.
280 *
281 * @param l the ChangeListener to remove
282 * @see #fireStateChanged
283 * @see #addChangeListener
284 */
285 public void removeChangeListener(ChangeListener l) {
286 listenerList.remove(ChangeListener.class, l);
287 }
288
289 /***
290 * Send a <code>ChangeEvent</code>, whose source is this tabbedpane, to
291 * each listener. This method method is called each time
292 * a <code>ChangeEvent</code> is received from the model.
293 *
294 * @see #addChangeListener
295 */
296 protected void fireStateChanged() {
297
298 Object[] listeners = listenerList.getListenerList();
299
300
301 for (int i = listeners.length-2; i>=0; i-=2) {
302 if (listeners[i]==ChangeListener.class) {
303
304 if (changeEvent == null)
305 changeEvent = new ChangeEvent(this);
306 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
307 }
308 }
309 }
310
311 /***
312 * Returns the currently selected tab.
313 */
314 public Component getSelectedComponent()
315 {
316 return jpCenter.getComponent(jlIcons.getSelectedIndex());
317 }
318
319
320
321 /***
322 * Listens for icon selection events.
323 */
324 private class IconListener implements ListSelectionListener
325 {
326
327 public void valueChanged(ListSelectionEvent e)
328 {
329 int index = jlIcons.getSelectedIndex();
330 if (index != -1) {
331 String description = null;
332 Object o = dlmIcons.elementAt(index);
333 if (o instanceof ImageIcon)
334 description = ((ImageIcon)o).getDescription();
335 else if (o instanceof String)
336 description = (String)o;
337 clCenter.show(jpCenter, description);
338 fireStateChanged();
339 }
340 }
341
342 }
343
344 /***
345 * Renders the icons in the <code>JList</code>.
346 */
347 private class IconRenderer extends JLabel implements ListCellRenderer
348 {
349
350 public IconRenderer()
351 {
352 this.setOpaque(true);
353 this.setHorizontalAlignment(CENTER);
354 this.setVerticalAlignment(CENTER);
355 this.setHorizontalTextPosition(CENTER);
356 this.setVerticalTextPosition(SwingConstants.BOTTOM);
357 this.setBorder(new EmptyBorder(5, 5, 5, 5));
358 }
359
360 public Component getListCellRendererComponent(JList list, Object value,
361 int index,
362 boolean isSelected,
363 boolean cellHasFocus)
364 {
365 if (isSelected) {
366 this.setBackground(list.getSelectionBackground());
367 this.setForeground(list.getSelectionForeground());
368 }
369 else {
370 this.setBackground(list.getBackground());
371 this.setForeground(list.getForeground());
372 }
373
374 this.setText(null);
375 this.setIcon(null);
376
377 if (value instanceof ImageIcon) {
378 ImageIcon icon = (ImageIcon)value;
379 this.setText(icon.getDescription());
380 this.setIcon(icon);
381 }
382 else if (value instanceof String) {
383 this.setText((String)value);
384 }
385
386 return this;
387 }
388
389 }
390
391 }