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 }