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