1 19 package org.openide.explorer.propertysheet; 20 21 import org.openide.explorer.propertysheet.editors.EnhancedPropertyEditor; 22 23 import java.awt.*; 24 import java.awt.event.*; 25 26 import java.beans.PropertyEditor ; 27 28 import javax.swing.*; 29 import javax.swing.event.AncestorListener ; 30 import javax.swing.plaf.ComboBoxUI ; 31 import javax.swing.plaf.metal.MetalLookAndFeel ; 32 import javax.swing.text.JTextComponent ; 33 34 35 46 class ComboInplaceEditor extends JComboBox implements InplaceEditor, FocusListener, AncestorListener { 47 48 static final KeyStroke[] cbKeyStrokes = new KeyStroke[] { 49 KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), 50 KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), 51 KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0, false), 52 KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0, false), 53 KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0, true), KeyStroke.getKeyStroke( 54 KeyEvent.VK_PAGE_UP, 0, true 55 ) 56 }; 57 private static PopupChecker checker = null; 58 protected PropertyEditor editor; 59 protected PropertyEnv env; 60 protected PropertyModel mdl; 61 boolean inSetUI = false; 62 private boolean tableUI; 63 private boolean connecting = false; 64 private boolean hasBeenEditable = false; 65 private boolean needLayout = false; 66 67 69 public ComboInplaceEditor(boolean tableUI) { 70 if (tableUI) { 71 putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); } 73 74 if (Boolean.getBoolean("netbeans.ps.combohack")) { setLightWeightPopupEnabled(false); 76 } 77 78 if (getClass() == ComboInplaceEditor.class) { 79 enableEvents(AWTEvent.FOCUS_EVENT_MASK); 80 } 81 82 this.tableUI = tableUI; 83 84 if (tableUI) { 85 updateUI(); 86 } 87 } 88 89 91 public void addNotify() { 92 super.addNotify(); 93 94 if (isEditable() && (getClass() == ComboInplaceEditor.class)) { 95 getEditor().getEditorComponent().addFocusListener(this); 96 } 97 98 getLayout().layoutContainer(this); 99 } 100 101 public void setEditable(boolean val) { 102 boolean hadBeenEditable = hasBeenEditable; 103 hasBeenEditable |= val; 104 super.setEditable(val); 105 106 if (hadBeenEditable != hasBeenEditable) { 107 log("Combo editor for " + editor + " setEditable (" + val + ")"); 108 needLayout = true; 109 } 110 } 111 112 114 public void removeNotify() { 115 log("Combo editor for " + editor + " removeNotify forcing popup close"); 116 setPopupVisible(false); 117 super.removeNotify(); 118 getEditor().getEditorComponent().removeFocusListener(this); 119 } 120 121 public Insets getInsets() { 122 if ("Aqua".equals(UIManager.getLookAndFeel().getID())) { 123 return new Insets(0, 0, 0, 0); 124 } else { 125 return super.getInsets(); 126 } 127 } 128 129 public void clear() { 130 editor = null; 131 env = null; 132 } 133 134 public void connect(PropertyEditor pe, PropertyEnv env) { 135 connecting = true; 136 137 try { 138 log("Combo editor connect to " + pe + " env=" + env); 139 140 this.env = env; 141 this.editor = pe; 142 setModel(new DefaultComboBoxModel(pe.getTags())); 143 144 boolean editable = (editor instanceof EnhancedPropertyEditor) 145 ? ((EnhancedPropertyEditor) editor).supportsEditingTaggedValues() 146 : ((env != null) && Boolean.TRUE.equals(env.getFeatureDescriptor().getValue("canEditAsText"))); 148 setEditable(editable); 149 setActionCommand(COMMAND_SUCCESS); 150 reset(); 151 } finally { 152 connecting = false; 153 } 154 } 155 156 private void log(String s) { 157 if (PropUtils.isLoggable(ComboInplaceEditor.class) && (getClass() == ComboInplaceEditor.class)) { 158 PropUtils.log(ComboInplaceEditor.class, s); } 160 } 161 162 public void setSelectedItem(Object o) { 163 if ((o == null) && (editor != null) && (editor.getTags() != null) && (editor.getTags().length > 0)) { 167 o = editor.getTags()[0]; 168 } 169 170 if (o != null) { 171 super.setSelectedItem(o); 172 } 173 } 174 175 177 public void fireActionEvent() { 178 if (connecting || (editor == null)) { 179 return; 180 } else { 181 if (editor == null) { 182 return; 183 } 184 185 if ("comboBoxEdited".equals(getActionCommand())) { 186 log("Translating comboBoxEdited action command to COMMAND_SUCCESS"); 187 setActionCommand(COMMAND_SUCCESS); 188 } 189 190 log("Combo editor firing ActionPerformed command=" + getActionCommand()); 191 super.fireActionEvent(); 192 } 193 } 194 195 public void reset() { 196 String targetValue = null; 197 198 if (editor != null) { 199 log("Combo editor reset setting selected item to " + editor.getAsText()); 200 targetValue = editor.getAsText(); 201 202 } 206 207 if ((getClass() == ComboInplaceEditor.class) && (env != null) && (env.getFeatureDescriptor() != null)) { 208 String initialEditValue = (String ) env.getFeatureDescriptor().getValue("initialEditValue"); 210 if (initialEditValue != null) { 211 targetValue = initialEditValue; 212 } 213 } 214 215 setSelectedItem(targetValue); 216 } 217 218 public Object getValue() { 219 if (isEditable()) { 220 return getEditor().getItem(); 221 } else { 222 return getSelectedItem(); 223 } 224 } 225 226 public PropertyEditor getPropertyEditor() { 227 return editor; 228 } 229 230 public PropertyModel getPropertyModel() { 231 return mdl; 232 } 233 234 public void setPropertyModel(PropertyModel pm) { 235 log("Combo editor set property model to " + pm); 236 this.mdl = pm; 237 } 238 239 public JComponent getComponent() { 240 return this; 241 } 242 243 public KeyStroke[] getKeyStrokes() { 244 return cbKeyStrokes; 245 } 246 247 public void handleInitialInputEvent(InputEvent e) { 248 } 250 251 252 public void updateUI() { 253 LookAndFeel lf = UIManager.getLookAndFeel(); 254 String id = lf.getID(); 255 boolean useClean = tableUI && (lf instanceof MetalLookAndFeel || "GTK".equals(id) || "Kunststoff".equals(id)); 257 if (useClean) { 258 super.setUI(PropUtils.createComboUI(this, tableUI)); 259 } else { 260 super.updateUI(); 261 } 262 263 if (tableUI & getEditor().getEditorComponent() instanceof JComponent) { 264 ((JComponent) getEditor().getEditorComponent()).setBorder(null); 265 } 266 } 267 268 271 public void setUI(ComboBoxUI ui) { 272 inSetUI = true; 273 274 try { 275 super.setUI(ui); 276 } finally { 277 inSetUI = false; 278 } 279 } 280 281 284 public void showPopup() { 285 try { 286 log(" Combo editor show popup"); 287 super.showPopup(); 288 } catch (NullPointerException e) { 289 log(" Combo editor show popup later due to npe"); 293 294 SwingUtilities.invokeLater( 295 new Runnable () { 296 public void run() { 297 ComboInplaceEditor.super.showPopup(); 298 } 299 } 300 ); 301 } 302 } 303 304 private void prepareEditor() { 305 Component c = getEditor().getEditorComponent(); 306 307 if (c instanceof JTextComponent ) { 308 JTextComponent jtc = (JTextComponent ) c; 309 String s = jtc.getText(); 310 311 if ((s != null) && (s.length() > 0)) { 312 jtc.setSelectionStart(0); 313 jtc.setSelectionEnd(s.length()); 314 } 315 316 if (tableUI) { 317 jtc.setBackground(getBackground()); 318 } else { 319 jtc.setBackground(PropUtils.getTextFieldBackground()); 320 } 321 if( tableUI ) 322 jtc.requestFocus(); 323 } 324 325 if (getLayout() != null) { 326 getLayout().layoutContainer(this); 327 } 328 329 repaint(); 330 } 331 332 334 public void processFocusEvent(FocusEvent fe) { 335 super.processFocusEvent(fe); 336 337 if (PropUtils.isLoggable(ComboInplaceEditor.class)) { 338 PropUtils.log(ComboInplaceEditor.class, "Focus event on combo " + "editor"); PropUtils.log(ComboInplaceEditor.class, fe); 340 } 341 342 Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 343 344 if (isDisplayable() && (fe.getID() == fe.FOCUS_GAINED) && (focusOwner == this) && !isPopupVisible()) { 345 if (isEditable()) { 346 prepareEditor(); 347 348 if( tableUI ) 349 SwingUtilities.invokeLater(new PopupChecker()); 350 } else { 351 if (tableUI) { 352 showPopup(); 353 354 SwingUtilities.invokeLater(new PopupChecker()); 356 } 357 } 358 359 repaint(); 360 } else if ((fe.getID() == fe.FOCUS_LOST) && isPopupVisible() && !isDisplayable()) { 361 if (!PropUtils.psCommitOnFocusLoss) { 362 setActionCommand(COMMAND_FAILURE); 363 fireActionEvent(); 364 } 365 366 SwingUtilities.invokeLater( 369 new Runnable () { 370 public void run() { 371 if (!isDisplayable()) { 372 hidePopup(); 373 } 374 } 375 } 376 ); 377 } 378 379 repaint(); 380 } 381 382 public boolean isKnownComponent(Component c) { 383 return (c == getEditor().getEditorComponent()); 384 } 385 386 public void setValue(Object o) { 387 setSelectedItem(o); 388 } 389 390 391 public boolean supportsTextEntry() { 392 return isEditable(); 393 } 394 395 397 protected void installAncestorListener() { 398 if (tableUI) { 401 addAncestorListener(this); 402 } else { 403 super.installAncestorListener(); 404 } 405 } 406 407 410 public void addFocusListener(FocusListener fl) { 411 if (!inSetUI || !tableUI) { 412 super.addFocusListener(fl); 413 } 414 } 415 416 public void focusGained(FocusEvent e) { 417 prepareEditor(); 419 } 420 421 422 public void focusLost(FocusEvent e) { 423 Component c = e.getOppositeComponent(); 424 425 if (!isAncestorOf(c) && (c != getEditor().getEditorComponent())) { 426 if ((c == this) || (c instanceof SheetTable && ((SheetTable) c).isAncestorOf(this))) { 427 return; 429 } 430 431 setActionCommand(COMMAND_FAILURE); 432 log(" Combo editor lost focus - setting action command to " + COMMAND_FAILURE); 433 getEditor().getEditorComponent().removeFocusListener(this); 434 435 if (checker == null) { 436 log("No active popup checker, firing action event"); 437 fireActionEvent(); 438 } 439 } 440 } 441 442 443 public void firePopupMenuCanceled() { 444 super.firePopupMenuCanceled(); 445 446 if (isEditable()) { 447 Component focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 448 449 if (isDisplayable() && (focus == this)) { 450 log("combo editor popup menu canceled. Requesting focus on editor component"); 451 getEditor().getEditorComponent().requestFocus(); 452 } 453 } 454 } 455 456 457 public void processKeyEvent(KeyEvent ke) { 458 super.processKeyEvent(ke); 459 460 if ((ke.getID() == ke.KEY_PRESSED) && (ke.getKeyCode() == ke.VK_ESCAPE)) { 461 setActionCommand(COMMAND_FAILURE); 462 fireActionEvent(); 463 } 464 } 465 466 public void ancestorAdded(javax.swing.event.AncestorEvent event) { 467 checker = new PopupChecker(); 472 SwingUtilities.invokeLater(checker); 473 } 474 475 public void ancestorMoved(javax.swing.event.AncestorEvent event) { 476 if (needLayout && (getLayout() != null)) { 478 getLayout().layoutContainer(this); 479 } 480 } 481 482 public void ancestorRemoved(javax.swing.event.AncestorEvent event) { 483 } 485 486 public void paintChildren(Graphics g) { 487 if ((editor != null) && !hasFocus() && editor.isPaintable()) { 488 return; 489 } else { 490 super.paintChildren(g); 491 } 492 } 493 494 public void paintComponent(Graphics g) { 495 if ((editor != null) && !hasFocus() && editor.isPaintable()) { 497 Insets ins = getInsets(); 498 Color c = g.getColor(); 499 500 try { 501 g.setColor(getBackground()); 502 g.fillRect(0, 0, getWidth(), getHeight()); 503 } finally { 504 g.setColor(c); 505 } 506 507 ins.left += PropUtils.getTextMargin(); 508 editor.paintValue( 509 g, 510 new Rectangle( 511 ins.left, ins.top, getWidth() - (ins.right + ins.left), getHeight() - (ins.top + ins.bottom) 512 ) 513 ); 514 } else { 515 super.paintComponent(g); 516 } 517 } 518 519 520 private class PopupChecker implements Runnable { 521 public void run() { 522 Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); 523 524 if (null != w && w.isAncestorOf(ComboInplaceEditor.this)) { 526 if (isShowing() && !isPopupVisible()) { 527 log("Popup checker ensuring editor prepared or popup visible"); 528 529 if (isEditable()) { 530 prepareEditor(); 531 } 532 showPopup(); 533 } 534 535 checker = null; 536 } 537 } 538 } 539 540 543 private class Renderer extends DefaultListCellRenderer { 544 private boolean sel = false; 545 546 549 public Color getBackground() { 550 if (ComboInplaceEditor.this == null) { 554 return null; 555 } 556 557 if (!sel && ((getText() != null) && (getSelectedItem() != null) && getText().equals(getSelectedItem()))) { 558 return ComboInplaceEditor.this.getBackground(); 559 } else { 560 return super.getBackground(); 561 } 562 } 563 564 public Component getListCellRendererComponent( 565 JList list, Object value, int index, boolean isSelected, boolean cellHasFocus 566 ) { 567 sel = isSelected; 568 569 return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 570 } 571 } 572 } 573 | Popular Tags |