001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.gui.component; 020 021import icy.gui.component.button.IcyButton; 022import icy.resource.ResourceUtil; 023import icy.resource.icon.IcyIcon; 024 025import java.awt.Color; 026import java.awt.Component; 027import java.awt.event.ActionEvent; 028import java.awt.event.ActionListener; 029import java.util.EventListener; 030 031import javax.swing.BorderFactory; 032import javax.swing.Box; 033import javax.swing.BoxLayout; 034import javax.swing.Icon; 035import javax.swing.JLabel; 036import javax.swing.JPanel; 037import javax.swing.JTabbedPane; 038import javax.swing.SwingConstants; 039 040/** 041 * JTabbedPane with close button (configurable) in tab. 042 * 043 * @author Stephane 044 */ 045public class CloseableTabbedPane extends JTabbedPane 046{ 047 /** 048 * 049 */ 050 private static final long serialVersionUID = 2105647353561738725L; 051 052 public static interface CloseableTabbedPaneListener extends EventListener 053 { 054 /** 055 * Called when the tab close button has been clicked.<br> 056 * This callback is used to do special actions before tab close.<br> 057 * You can prevent the close operation by returning false. 058 * 059 * @return true if the tab can be closed, false otherwise. 060 */ 061 public boolean tabClosing(int index, String title); 062 063 /** 064 * Called when the tab has been closed. 065 */ 066 public void tabClosed(int index, String title); 067 } 068 069 private class CloseableTabComponent extends JPanel 070 { 071 /** 072 * 073 */ 074 private static final long serialVersionUID = 6828288788693627610L; 075 076 final private IcyButton closeButton; 077 final private JLabel label; 078 final private Component sep; 079 080 public CloseableTabComponent(String title, Icon icon) 081 { 082 super(); 083 084 setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); 085 setBorder(BorderFactory.createEmptyBorder()); 086 setOpaque(false); 087 088 label = new JLabel(title, icon, SwingConstants.CENTER); 089 label.setOpaque(false); 090 091 sep = Box.createHorizontalStrut(6); 092 093 closeButton = new IcyButton(new IcyIcon(ResourceUtil.ICON_DELETE, 12)); 094 closeButton.setFlat(true); 095 closeButton.setContentAreaFilled(false); 096 closeButton.setToolTipText("close"); 097 098 closeButton.addActionListener(new ActionListener() 099 { 100 @Override 101 public void actionPerformed(ActionEvent actionevent) 102 { 103 final int index = indexOfTabComponent(CloseableTabComponent.this); 104 105 if (index != -1) 106 { 107 if (CloseableTabbedPane.this.fireTabClosing(index, getTitle())) 108 { 109 CloseableTabbedPane.this.removeTabAt(index); 110 CloseableTabbedPane.this.fireTabClosed(index, getTitle()); 111 } 112 } 113 } 114 }); 115 116 add(label); 117 add(sep); 118 add(closeButton); 119 120 validate(); 121 } 122 123 public boolean isClosable() 124 { 125 return closeButton.isVisible(); 126 } 127 128 public void setClosable(boolean value) 129 { 130 sep.setVisible(value); 131 closeButton.setVisible(value); 132 } 133 134 public String getTitle() 135 { 136 return label.getText(); 137 } 138 139 public void setTitle(String title) 140 { 141 label.setText(title); 142 } 143 144 public void setIcon(Icon icon) 145 { 146 label.setIcon(icon); 147 } 148 149 public void setDisabledIcon(Icon disabledIcon) 150 { 151 label.setDisabledIcon(disabledIcon); 152 } 153 154 public void setBackgroundAll(Color background) 155 { 156 label.setBackground(background); 157 closeButton.setBackground(background); 158 } 159 160 public void setForegroundAll(Color foreground) 161 { 162 label.setForeground(foreground); 163 closeButton.setForeground(foreground); 164 } 165 } 166 167 /** 168 * {@link JTabbedPane} 169 */ 170 public CloseableTabbedPane() 171 { 172 super(); 173 } 174 175 /** 176 * {@link JTabbedPane} 177 */ 178 public CloseableTabbedPane(int tabPlacement) 179 { 180 super(tabPlacement); 181 } 182 183 /** 184 * {@link JTabbedPane} 185 */ 186 public CloseableTabbedPane(int tabPlacement, int tabLayoutPolicy) 187 { 188 super(tabPlacement, tabLayoutPolicy); 189 } 190 191 /** 192 * Returns the 'closable' state of tab component at <code>index</code>. 193 * 194 * @param index 195 * the tab index where the check state is queried 196 * @return true if tab component at <code>index</code> can be closed (close button visible).<br> 197 * Returns false otherwise 198 * @exception IndexOutOfBoundsException 199 * if index is out of range (index < 0 || index >= tab count) 200 * @see #setTabClosable(int, boolean) 201 */ 202 public boolean isTabClosable(int index) 203 { 204 return ((CloseableTabComponent) getTabComponentAt(index)).isClosable(); 205 } 206 207 /** 208 * Set the 'closable' state of tab component at <code>index</code>. 209 * 210 * @param index 211 * the tab index we want to set the 'closable' state 212 * @param value 213 * true if the tab should be 'closable' (close button visible), false otherwise. 214 * @exception IndexOutOfBoundsException 215 * if index is out of range (index < 0 || index >= tab count) 216 * @see #isTabClosable(int) 217 */ 218 public void setTabClosable(int index, boolean value) 219 { 220 ((CloseableTabComponent) getTabComponentAt(index)).setClosable(value); 221 } 222 223 @Override 224 public void setIconAt(int index, Icon icon) 225 { 226 super.setIconAt(index, icon); 227 228 final CloseableTabComponent comp = (CloseableTabComponent) getTabComponentAt(index); 229 230 if (comp != null) 231 comp.setIcon(icon); 232 } 233 234 @Override 235 public void setDisabledIconAt(int index, Icon disabledIcon) 236 { 237 super.setDisabledIconAt(index, disabledIcon); 238 239 final CloseableTabComponent comp = (CloseableTabComponent) getTabComponentAt(index); 240 241 if (comp != null) 242 comp.setDisabledIcon(disabledIcon); 243 } 244 245 @Override 246 public void setBackgroundAt(int index, Color background) 247 { 248 super.setBackgroundAt(index, background); 249 250 final CloseableTabComponent comp = (CloseableTabComponent) getTabComponentAt(index); 251 252 if (comp != null) 253 comp.setBackgroundAll(background); 254 } 255 256 @Override 257 public void setForegroundAt(int index, Color foreground) 258 { 259 super.setForegroundAt(index, foreground); 260 261 final CloseableTabComponent comp = (CloseableTabComponent) getTabComponentAt(index); 262 263 if (comp != null) 264 comp.setForegroundAll(foreground); 265 } 266 267 @Override 268 public void setTitleAt(int index, String title) 269 { 270 super.setTitleAt(index, title); 271 272 final CloseableTabComponent comp = (CloseableTabComponent) getTabComponentAt(index); 273 274 if (comp != null) 275 comp.setTitle(title); 276 } 277 278 @Override 279 public void insertTab(String title, Icon icon, Component component, String tip, int index) 280 { 281 super.insertTab(title, icon, component, tip, index); 282 283 setTabComponentAt(index, new CloseableTabComponent(title, icon)); 284 } 285 286 protected void fireTabClosed(int index, String text) 287 { 288 for (CloseableTabbedPaneListener l : listenerList.getListeners(CloseableTabbedPaneListener.class)) 289 l.tabClosed(index, text); 290 291 } 292 293 protected boolean fireTabClosing(int index, String text) 294 { 295 for (CloseableTabbedPaneListener l : listenerList.getListeners(CloseableTabbedPaneListener.class)) 296 if (!l.tabClosing(index, text)) 297 return false; 298 299 return true; 300 } 301 302 public void addCloseableTabbedPaneListener(CloseableTabbedPaneListener l) 303 { 304 listenerList.add(CloseableTabbedPaneListener.class, l); 305 } 306 307 public void removeCloseableTabbedPaneListener(CloseableTabbedPaneListener l) 308 { 309 listenerList.remove(CloseableTabbedPaneListener.class, l); 310 } 311}