1 19 20 package org.netbeans.modules.db.util; 21 22 import java.awt.Color ; 23 import java.awt.Component ; 24 import java.awt.Dimension ; 25 import java.awt.event.ActionEvent ; 26 import java.awt.event.ActionListener ; 27 import java.awt.event.InputEvent ; 28 import java.awt.event.KeyAdapter ; 29 import java.awt.event.KeyEvent ; 30 import javax.swing.AbstractListModel ; 31 import javax.swing.ComboBoxModel ; 32 import javax.swing.DefaultListCellRenderer ; 33 import javax.swing.JComboBox ; 34 import javax.swing.JLabel ; 35 import javax.swing.JList ; 36 import javax.swing.JSeparator ; 37 import javax.swing.SwingUtilities ; 38 import javax.swing.event.ListDataEvent ; 39 import javax.swing.event.ListDataListener ; 40 import javax.swing.event.PopupMenuEvent ; 41 import javax.swing.event.PopupMenuListener ; 42 43 52 public final class DataComboBoxSupport { 53 54 private final DataComboBoxModel dataModel; 55 private final boolean allowAdding; 56 57 private Object previousItem = null; 58 private Object previousNonSpecialItem = null; 59 private int previousIndex = -1; 60 61 private boolean performingNewItemAction = false; 62 63 66 private static final class Separator extends JSeparator { 67 68 Separator() { 69 setForeground(Color.BLACK); 70 } 71 72 public Dimension getPreferredSize() { 73 Dimension size = super.getPreferredSize(); 74 return new Dimension (size.width, 1); 75 } 76 } 77 78 79 static final Separator SEPARATOR_ITEM = new Separator (); 80 81 84 final Object NEW_ITEM = new Object () { 85 public String toString() { 86 return dataModel.getNewItemDisplayName(); 87 } 88 }; 89 90 91 DataComboBoxSupport(JComboBox comboBox, DataComboBoxModel dataModel, boolean allowAdding) { 92 this.dataModel = dataModel; 93 this.allowAdding = allowAdding; 94 95 comboBox.setEditable(false); 96 97 comboBox.setModel(new ItemComboBoxModel()); 98 99 comboBox.setRenderer(new ItemListCellRenderer()); 100 comboBox.addKeyListener(new ItemKeyListener()); 101 comboBox.addActionListener(new ItemActionListener()); 102 comboBox.addPopupMenuListener(new ItemPopupMenuListener()); 103 } 104 105 108 public static void connect(JComboBox comboBox, DataComboBoxModel dataModel) { 109 connect(comboBox, dataModel, true); 110 } 111 112 115 public static void connect(JComboBox comboBox, DataComboBoxModel dataModel, boolean allowAdding) { 116 new DataComboBoxSupport(comboBox, dataModel, allowAdding); 117 } 118 119 private boolean isSpecialItem(Object item) { 120 return item == SEPARATOR_ITEM || item == NEW_ITEM; 121 } 122 123 private void setPreviousNonSpecialItem(JComboBox comboBox) { 124 if (comboBox.getSelectedItem() == NEW_ITEM) { 125 comboBox.setSelectedItem(previousNonSpecialItem); 127 } 128 } 129 130 private class ItemComboBoxModel extends AbstractListModel implements ComboBoxModel , ListDataListener { 131 132 135 public ItemComboBoxModel() { 136 getDelegate().addListDataListener(this); 137 } 138 139 public Object getElementAt(int index) { 140 if (allowAdding) { 141 if (getSize() == 1) { 142 if (index == 0) { 144 return NEW_ITEM; 145 } else { 146 throw new IllegalStateException ("Index out of bounds: " + index); } 148 } 149 150 if (index >= 0 && index < getDelegate().getSize()) { 152 return getDelegate().getElementAt(index); 153 } else if (index == getSize() - 2) { 154 return SEPARATOR_ITEM; 155 } else if (index == getSize() - 1) { 156 return NEW_ITEM; 157 } else { 158 throw new IllegalStateException ("Index out of bounds: " + index); } 160 } else { 161 return getDelegate().getElementAt(index); 163 } 164 } 165 166 public int getSize() { 167 if (allowAdding) { 170 return getDelegate().getSize() == 0 ? 1 : getDelegate().getSize() + 2; 171 } else { 172 return getDelegate().getSize(); 173 } 174 } 175 176 public void setSelectedItem(Object anItem) { 177 previousItem = getDelegate().getSelectedItem(); 178 previousIndex = getItemIndex(previousItem); 179 180 if (!isSpecialItem(previousItem)) { 181 previousNonSpecialItem = previousItem; 182 } 183 184 getDelegate().setSelectedItem(anItem); 185 } 186 187 public Object getSelectedItem() { 188 return getDelegate().getSelectedItem(); 189 } 190 191 public Object getPreviousItem() { 192 return previousItem; 193 } 194 195 private ComboBoxModel getDelegate() { 196 return dataModel.getListModel(); 197 } 198 199 private int getItemIndex(Object item) { 200 if (item == null) { 201 return -1; 202 } 203 for (int i = 0; i < getSize(); i++ ) { 204 if (getElementAt(i).equals(item)) { 205 return i; 206 } 207 } 208 return -1; 209 } 210 211 public void intervalRemoved(ListDataEvent e) { 212 throw new UnsupportedOperationException ("This is currently not supported."); 213 } 214 215 public void intervalAdded(ListDataEvent e) { 216 throw new UnsupportedOperationException ("This is currently not supported."); 217 } 218 219 public void contentsChanged(ListDataEvent e) { 220 fireContentsChanged(this, 0, getSize()); 221 } 222 } 223 224 private class ItemListCellRenderer extends DefaultListCellRenderer { 225 226 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 227 228 Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 229 JLabel label = (JLabel )component; 230 231 if (value != null && !isSpecialItem(value)) { 232 String displayName = dataModel.getItemDisplayName(value); 233 label.setText(dataModel.getItemDisplayName(value)); 234 label.setToolTipText(dataModel.getItemTooltipText(value)); 235 } else if (value == SEPARATOR_ITEM) { 236 return SEPARATOR_ITEM; 237 } else if (value != null) { 238 label.setText(value.toString()); 239 label.setToolTipText(null); 240 } 241 242 return label; 243 } 244 } 245 246 private final class ItemKeyListener extends KeyAdapter { 247 248 public void keyPressed(KeyEvent e) { 249 JComboBox comboBox = (JComboBox )e.getSource(); 250 251 int keyCode = e.getKeyCode(); 252 if (KeyEvent.VK_ENTER == keyCode) { 253 Object selectedItem = comboBox.getSelectedItem(); 254 if (selectedItem == NEW_ITEM) { 255 performingNewItemAction = true; 256 try { 257 comboBox.setPopupVisible(false); 258 e.consume(); 259 dataModel.newItemActionPerformed(); 260 } finally { 261 performingNewItemAction = false; 262 } 263 264 setPreviousNonSpecialItem(comboBox); 265 } 266 } 267 } 268 } 269 270 private final class ItemActionListener implements ActionListener { 271 272 public void actionPerformed(ActionEvent e) { 273 final JComboBox comboBox = (JComboBox )e.getSource(); 274 275 Object selectedItem = comboBox.getSelectedItem(); 276 if (selectedItem == SEPARATOR_ITEM) { 277 int newIndex = -1; 278 if (previousIndex != -1) { 279 int selectedIndex = comboBox.getSelectedIndex(); 281 if (selectedIndex > previousIndex) { 282 newIndex = selectedIndex + 1; 284 } else { 285 newIndex= selectedIndex - 1; 287 } 288 } 289 comboBox.setSelectedIndex(newIndex); 290 } else if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) { 291 if (selectedItem == NEW_ITEM) { 293 performingNewItemAction = true; 294 try { 295 comboBox.setPopupVisible(false); 296 dataModel.newItemActionPerformed(); 297 } finally { 298 performingNewItemAction = false; 299 } 300 301 setPreviousNonSpecialItem(comboBox); 302 final Object newSelectedItem = comboBox.getSelectedItem(); 307 SwingUtilities.invokeLater(new Runnable () { 308 public void run() { 309 comboBox.setSelectedItem(newSelectedItem); 310 } 311 }); 312 } 313 } 314 } 315 } 316 317 private final class ItemPopupMenuListener implements PopupMenuListener { 318 319 public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 320 } 321 322 public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 323 if (!performingNewItemAction) { 324 setPreviousNonSpecialItem((JComboBox )e.getSource()); 325 } 326 } 327 328 public void popupMenuCanceled(PopupMenuEvent e) { 329 if (!performingNewItemAction) { 334 setPreviousNonSpecialItem((JComboBox )e.getSource()); 335 } 336 } 337 } 338 } 339 | Popular Tags |