|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. *//* * SheetCellEditor.java * * Created on December 17, 2002, 5:48 PM */ package org.openide.explorer.propertysheet; import java.awt.*; import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import java.util.EventObject; import org.openide.*; import org.openide.nodes.Node.Property; /** Table cell editor which wraps inplace editors in its * table cell editor interface. * @author Tim Boudreau */ final class SheetCellEditor implements TableCellEditor, ActionListener { /** A lazy, reusable change event. */ ChangeEvent ce=null; ReusablePropertyEnv reusableEnv; /** Private constructor; only the default instance may be used. */ SheetCellEditor(ReusablePropertyEnv env) { reusableEnv = env; } /** Utility field used by event firing mechanism. */ private javax.swing.event.EventListenerList listenerList = null; void setInplaceEditor (InplaceEditor ie) { if (ie == inplaceEditor) { return; } if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, " SheetCellEditor.setInplaceEditor " + ie); //NOI18N } if (ie == null) { if (inplaceEditor != null) inplaceEditor.clear(); } else { ie.addActionListener(this); } if (inplaceEditor != null) { inplaceEditor.removeActionListener(this); } inplaceEditor = ie; } PropertyEditor getPropertyEditor() { PropertyEditor result; if (inplaceEditor == null) { result = null; } else { result = inplaceEditor.getPropertyEditor(); } return result; } public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { Component result = null; //since you can't change the model, no worries SheetTable stb = (SheetTable) table; lastUpdateSuccess=true; //fetch the property from the set model Property p = (Property) stb.getSheetModel() .getPropertySetModel().getFeatureDescriptor(row); result = getEditorComponent (p, this, table.getForeground(), table.getBackground(), table.getSelectionBackground(), table.getSelectionForeground()); if (result instanceof ButtonPanel) { ((ButtonPanel) result).setButtonAction (stb.getCustomEditorAction()); } if (result != null) { result.setFont(stb.getFont()); } return result; } private InplaceEditorFactory factory =null; private InplaceEditorFactory factory() { if (factory == null) { factory = new InplaceEditorFactory(true, reusableEnv); } return factory; } private ButtonPanel buttonPanel=null; private ButtonPanel buttonPanel() { if (buttonPanel == null) { buttonPanel = new ButtonPanel(); } return buttonPanel; } public boolean isLastUpdateSuccessful() { return lastUpdateSuccess; } public Component getEditorComponent(Property p, ActionListener al, Color foreground, Color background, Color selBg, Color selFg) { JComponent result = null; InplaceEditor inplace; //get an appropriate inplace editor connected to this property //store the value, attaching action listener the editor setInplaceEditor (inplace = factory().getInplaceEditor(p, false)); //if it should have a custom editor button, embed it in the shared //instance of ButtonPanel PropertyEditor ped = inplaceEditor.getPropertyEditor(); // Issue 35521 forget trying to edit things that don't have property // editor if (ped instanceof PropUtils.NoPropertyEditorEditor) { setInplaceEditor(null); return null; } boolean propRequestsSuppressButton = Boolean.TRUE.equals( p.getValue("suppressCustomEditor")); //NOI18N JComponent realEditor = null; if (ped.supportsCustomEditor() && !propRequestsSuppressButton) { realEditor = inplaceEditor.getComponent(); ButtonPanel bp = buttonPanel(); //use our static instance of ButtonPanel bp.setInplaceEditor(inplace); //attach the table's custom editor action to the button result = bp; } else { result = inplaceEditor.getComponent(); } return result; } /** Handler for action events thrown by the current inplaceEditor. * An action event will cause stopCellEditing() to be called, and * this instance of SheetCellEditor to stop listening for * further action events on the inplace editor. */ public void actionPerformed (ActionEvent ae) { if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, "Editor received an action event - " + ae.getActionCommand()); //NOI18N } if (!(ae.getSource() instanceof InplaceEditor)) { if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, " Event came from an unknown object type - assuming a legacy EnhancedPropertyEditor is the cause and updating property"); //NOI18N } //Then we have a legacy inplace editor handled by wrapper editor. //Assume any action means we should update the property. if (inplaceEditor != null) { if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, "WRITING PROPERTY VALUE FROM EDITOR TO PROPERTY"); //NOI18N } PropUtils.updateProp (inplaceEditor.getPropertyModel(), inplaceEditor.getPropertyEditor(), ""); //NOI18N } cancelCellEditing(); } if (ae.getActionCommand() == InplaceEditor.COMMAND_SUCCESS) { stopCellEditing(); } else if (ae.getActionCommand() == InplaceEditor.COMMAND_FAILURE) { if (PropUtils.psCommitOnFocusLoss) { stopCellEditing(); } else { cancelCellEditing(); } } else { return; } } protected void fireEditingStopped() { if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, " SheetCellEditor firing editing stopped to table "); //NOI18N } if (listenerList == null) return; Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==CellEditorListener.class) { if (ce == null) { ce = new ChangeEvent(this); } ((CellEditorListener)listeners[i+1]).editingStopped(ce); } } } protected void fireEditingCancelled() { if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, " SheetCellEditor firing editing cancelled to table "); //NOI18N } if (listenerList == null) return; Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==CellEditorListener.class) { if (ce == null) { ce = new ChangeEvent(this); } ((CellEditorListener)listeners[i+1]).editingCanceled(ce); } } } InplaceEditor inplaceEditor=null; /** Returns the last-provided inplace editor. */ public InplaceEditor getInplaceEditor () { return inplaceEditor; } public void cancelCellEditing() { if (inplaceEditor != null) { try { if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, " SheetCellEditor.cancelCellEditing ", true); //NOI18N } fireEditingCancelled(); } finally { setInplaceEditor (null); } } } public Object getCellEditorValue() { if (inplaceEditor != null) return inplaceEditor.getValue(); return null; } public boolean isCellEditable(EventObject anEvent) { return true; } public boolean shouldSelectCell(EventObject anEvent) { if (anEvent instanceof MouseEvent) { MouseEvent e = (MouseEvent)anEvent; return e.getID() != MouseEvent.MOUSE_DRAGGED; } return true; } boolean lastUpdateSuccess = true; public boolean stopCellEditing() { if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, "SheetCellEditor.StopCellEditing", true); //NOI18N } if (inplaceEditor != null) { try { Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner(); //JTable with client property terminateEditOnFocusLost will try to //update the value. That's not what we want, as it means you can //have a partial value, open a custom editor and get an error because //the table tried to write the partial value, when it lost focus //to a custom editor. if (!PropUtils.psCommitOnFocusLoss) { if ((!(c instanceof JTable)) && (!inplaceEditor.isKnownComponent(c)) && (c != inplaceEditor.getComponent()) ) { if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, "Focused component is unknown - discarding"); //NOI18N } return false; } } //get the model, updateProp will clear it PropertyModel mdl = inplaceEditor.getPropertyModel(); try { lastUpdateSuccess = PropUtils.updateProp (inplaceEditor); } catch (NullPointerException npe) { if (inplaceEditor == null || inplaceEditor.getPropertyEditor() == null) { String propID; if (mdl instanceof NodePropertyModel) { propID = ((NodePropertyModel) mdl).getProperty().toString() + " editor class " + (mdl.getPropertyEditorClass() != null ? mdl.getPropertyEditorClass().getName() : " unknown editor class") + " "; } else { propID = ""; } //c.f. issue 39249 - Really this sort of behavior is unacceptable //and should throw an exception, but there is the faint chance //that the user can be editing a property when some remote process //causes it to change, in which case the exception would be wrong. //May be possible to add a thread-check for the culprit change, //and throw an exception only if it happened on the EQ, not if otherwise, //but even that wouldn't be foolproof, and if all node changes are //moved to EQ it won't work at all. ErrorManager.getDefault().log(ErrorManager.WARNING, "Property " + propID + "value changed *while* the property sheet was setting its value " + "but before it had been set. This almost always means that the " + "property editor has modified the property's value itself. " + "Property editors should NEVER directly modify properties, it is " + "up to the displayer to decide if/when the property should be " + "updated. This behavior may cause an exception in the " + "future."); ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, npe); return false; } else { throw npe; } } //Fire the action first - appears more repsonsive if the editor is //immediately removed, before running the post-set action (which, //for the form editor, will, for example, change the caret position //in the editor) if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, " SheetCellEditor Firing editing stopped"); //NOI18N } fireEditingStopped(); // if (lastUpdateSuccess) { tryPostSetAction(mdl); // } } finally { setInplaceEditor (null); reusableEnv.clear(); } return true; // } else { // return false; // } } else { return false; } } /** Allow a post-set hook */ void tryPostSetAction(PropertyModel mdl) { if (mdl instanceof ExPropertyModel) { FeatureDescriptor fd=((ExPropertyModel) mdl).getFeatureDescriptor(); if (fd != null) { Action a = (Action) fd.getValue("postSetAction"); //NOI18N if (a != null) { if (PropUtils.isLoggable(SheetCellEditor.class)) { PropUtils.log (SheetCellEditor.class, " Running post-set action " + a); //NOI18N } ActionEvent ae=new ActionEvent (this, ActionEvent.ACTION_PERFORMED, InplaceEditor.COMMAND_SUCCESS); a.actionPerformed(ae); } } } } public synchronized void addCellEditorListener(javax.swing.event.CellEditorListener listener) { if (listenerList == null ) { listenerList = new javax.swing.event.EventListenerList(); } listenerList.add(javax.swing.event.CellEditorListener.class, listener); } public synchronized void removeCellEditorListener(javax.swing.event.CellEditorListener listener) { listenerList.remove(CellEditorListener.class, listener); //XXX this needs to be here to make editor tag caching //work (this is due to performance problems with //getTags() on ObjectEditor). Once caching can be //removed, this call should be removed too. if (listenerList.getListenerCount(CellEditorListener.class) == 0) { if (inplaceEditor != null) { inplaceEditor.clear(); } } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.