001 /*
002 * Copyright 2002-2007 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.richclient.dialog.control;
017
018 import java.beans.PropertyChangeEvent;
019 import java.beans.PropertyChangeListener;
020 import java.util.ArrayList;
021 import java.util.List;
022
023 import javax.swing.JComponent;
024 import javax.swing.JTabbedPane;
025 import javax.swing.event.ChangeEvent;
026 import javax.swing.event.ChangeListener;
027
028 import org.springframework.richclient.factory.ControlFactory;
029 import org.springframework.richclient.util.EventListenerListHelper;
030
031 /**
032 * Wrapper around <code>JTabbedPane</code>. When a <code>Tab</code> is made invisible, the tab is hidden from the
033 * ui, and vice versa.
034 * <p>
035 * TODO: move this to another package?
036 *
037 * @author Peter De Bruycker
038 */
039 public class ExtTabbedPane implements ControlFactory {
040
041 private List tabs = new ArrayList();
042
043 private JTabbedPane tabbedPane;
044
045 private PropertyChangeListener propertyChangeHandler = new PropertyChangeListener() {
046 public void propertyChange(PropertyChangeEvent evt) {
047 Tab tab = (Tab) evt.getSource();
048 if (tab.isVisible()) {
049 int index = getUIIndex(tab);
050 if (index >= 0) {
051 if (evt.getPropertyName().equals(Tab.TITLE_PROPERTY)) {
052 tabbedPane.setTitleAt(index, tab.getTitle());
053 }
054 if (evt.getPropertyName().equals(Tab.TOOLTIP_PROPERTY)) {
055 tabbedPane.setToolTipTextAt(index, tab.getTooltip());
056 }
057 if (evt.getPropertyName().equals(Tab.ICON_PROPERTY)) {
058 tabbedPane.setIconAt(index, tab.getIcon());
059 }
060 if (evt.getPropertyName().equals(Tab.COMPONENT_PROPERTY)) {
061 tabbedPane.setComponentAt(index, tab.getComponent());
062 }
063 if (evt.getPropertyName().equals(Tab.MNEMONIC_PROPERTY)) {
064 tabbedPane.setMnemonicAt(index, tab.getMnemonic());
065 }
066 if (evt.getPropertyName().equals(Tab.ENABLED_PROPERTY)) {
067 tabbedPane.setMnemonicAt(index, tab.getMnemonic());
068 }
069 }
070 }
071 if (evt.getPropertyName().equals("visible")) {
072 updateTabVisibility(tab);
073 }
074 }
075 };
076
077 private EventListenerListHelper changeListeners = new EventListenerListHelper(ChangeListener.class);
078
079 public ExtTabbedPane(JTabbedPane tabbedPane) {
080 this.tabbedPane = tabbedPane;
081 tabbedPane.addChangeListener(new ChangeListener() {
082 public void stateChanged(ChangeEvent e) {
083 // delegate change events to registered listeners
084 changeListeners.fire("stateChanged", e);
085 }
086 });
087 }
088
089 public ExtTabbedPane() {
090 this(new JTabbedPane());
091 }
092
093 public void addChangeListener(ChangeListener listener) {
094 changeListeners.add(listener);
095 }
096
097 public void removeChangeListener(ChangeListener listener) {
098 changeListeners.remove(listener);
099 }
100
101 public JComponent getControl() {
102 return tabbedPane;
103 }
104
105 public void addTab(Tab tab) {
106 tabs.add(tab);
107 if (tab.isVisible()) {
108 tabbedPane.addTab(tab.getTitle(), tab.getIcon(), tab.getComponent(), tab.getTooltip());
109 }
110 tab.addPropertyChangeListener(propertyChangeHandler);
111 }
112
113 public Tab getTab(int index) {
114 return (Tab) tabs.get(index);
115 }
116
117 public void removeTab(Tab tab) {
118 removeTab(tabs.indexOf(tab));
119 }
120
121 public void addTab(int index, Tab tab) {
122 tabs.add(index, tab);
123 if (tab.isVisible()) {
124 tabbedPane.insertTab(tab.getTitle(), tab.getIcon(), tab.getComponent(), tab.getTooltip(), index);
125 }
126 tab.addPropertyChangeListener(propertyChangeHandler);
127 }
128
129 public void removeTab(int index) {
130 tabbedPane.removeTabAt(index);
131 Tab tab = (Tab) tabs.remove(index);
132 tab.removePropertyChangeListener(propertyChangeHandler);
133 }
134
135 public void selectTab(Tab tab) {
136 if (tab.isVisible()) {
137 int targetIndex = getUIIndex(tab);
138 if (targetIndex >= 0) {
139 tabbedPane.setSelectedIndex(targetIndex);
140 }
141 }
142 }
143
144 public int convertUIIndexToModelIndex(int index) {
145 int modelIndex = index;
146 for (int i = 0; i <= modelIndex; i++) {
147 if (!getTab(i).isVisible()) {
148 modelIndex++;
149 }
150 }
151
152 return modelIndex;
153 }
154
155 public int getUIIndex(Tab tab) {
156 return convertModelIndexToUIIndex(tabs.indexOf(tab));
157 }
158
159 public int convertModelIndexToUIIndex(int index) {
160 int uiIndex = 0;
161
162 for (int i = 0; i < index; i++) {
163 if (getTab(i).isVisible()) {
164 uiIndex++;
165 }
166 }
167
168 return uiIndex;
169 }
170
171 private void updateTabVisibility(Tab tab) {
172 if (tab.isVisible()) {
173 tabbedPane.insertTab(tab.getTitle(), tab.getIcon(), tab.getComponent(), tab.getTooltip(), getUIIndex(tab));
174 }
175 else {
176 tabbedPane.removeTabAt(getUIIndex(tab));
177
178 }
179
180 // because insert and remove don't change the selected tab index, we
181 // trigger one manually
182 ChangeEvent event = new ChangeEvent(tabbedPane);
183 changeListeners.fire("stateChanged", event);
184 }
185 }