Index: src/org/openide/explorer/propertysheet/ComboInplaceEditor.java =================================================================== RCS file: /cvs/openide/src/org/openide/explorer/propertysheet/ComboInplaceEditor.java,v retrieving revision 1.21 diff -u -r1.21 ComboInplaceEditor.java --- src/org/openide/explorer/propertysheet/ComboInplaceEditor.java 1 Mar 2004 05:14:00 -0000 1.21 +++ src/org/openide/explorer/propertysheet/ComboInplaceEditor.java 25 Aug 2004 16:35:21 -0000 @@ -176,23 +176,26 @@ } public void reset() { - log ("Combo editor reset setting selected item to " + editor.getAsText()); - String targetValue = editor.getAsText(); - - //issue 26367, form editor needs ability to set a custom value - //when editing is initiated (event handler combos, part of them - //cleaning up their EnhancedPropertyEditors). - - if (getClass() == ComboInplaceEditor.class && env != null && - env.getFeatureDescriptor() != null) { - - String initialEditValue = (String) env.getFeatureDescriptor(). - getValue("initialEditValue"); //NOI18N - - if (initialEditValue != null) { - targetValue = initialEditValue; + String targetValue = null; + if (editor != null) { + log ("Combo editor reset setting selected item to " + editor.getAsText()); + targetValue = editor.getAsText(); + + //issue 26367, form editor needs ability to set a custom value + //when editing is initiated (event handler combos, part of them + //cleaning up their EnhancedPropertyEditors). + + if (getClass() == ComboInplaceEditor.class && env != null && + env.getFeatureDescriptor() != null) { + + String initialEditValue = (String) env.getFeatureDescriptor(). + getValue("initialEditValue"); //NOI18N + + if (initialEditValue != null) { + targetValue = initialEditValue; + } + } - } setSelectedItem(targetValue); } @@ -453,7 +456,7 @@ /** A handy runnable which will ensure the popup is really displayed */ private class PopupChecker implements Runnable { public void run() { - if (isShowing() && !isPopupVisible()) { + if (isShowing() && !isPopupVisible() && hasFocus()) { log ("Popup checker ensuring editor prepared or popup visible"); if (isEditable()) { prepareEditor(); Index: src/org/openide/explorer/propertysheet/CustomEditorAction.java =================================================================== RCS file: /cvs/openide/src/org/openide/explorer/propertysheet/CustomEditorAction.java,v retrieving revision 1.6 diff -u -r1.6 CustomEditorAction.java --- src/org/openide/explorer/propertysheet/CustomEditorAction.java 3 Feb 2004 02:30:18 -0000 1.6 +++ src/org/openide/explorer/propertysheet/CustomEditorAction.java 25 Aug 2004 16:35:21 -0000 @@ -88,23 +88,6 @@ final java.beans.PropertyEditor editor = PropUtils.getPropertyEditor (p); - //if there is no custom property editor... - if (!editor.supportsCustomEditor()) { - if (PropUtils.isLoggable(CustomEditorAction.class)) { - PropUtils.log (CustomEditorAction.class, "Cant invoke custom " + - "editor for editor " + editor + " - it returns false " + - "from supportsCustomEditor()."); //NOI18N - } - //Somebody invoked it from the keyboard on an editor w/o custom editor - Toolkit.getDefaultToolkit().beep(); - return; - } - - final Component curComp = invoker.getCursorChangeComponent(); - - Cursor cur = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); - curComp.setCursor (cur); - //Create a new PropertyEnv to carry the values of the Property to the editor PropertyEnv env = null; if (editor instanceof ExPropertyEditor) { @@ -124,7 +107,23 @@ //Set up the editor with any hints from the property ((ExPropertyEditor) editor).attachEnv (env); } + + //if there is no custom property editor... + if (!editor.supportsCustomEditor()) { + if (PropUtils.isLoggable(CustomEditorAction.class)) { + PropUtils.log (CustomEditorAction.class, "Cant invoke custom " + + "editor for editor " + editor + " - it returns false " + + "from supportsCustomEditor()."); //NOI18N + } + //Somebody invoked it from the keyboard on an editor w/o custom editor + Toolkit.getDefaultToolkit().beep(); + return; + } + final Component curComp = invoker.getCursorChangeComponent(); + Cursor cur = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + curComp.setCursor (cur); + // customEditing = true; Object partialValue=invoker.getPartialValue(); @@ -211,7 +210,7 @@ WindowListener wl = new WindowAdapter() { public void windowClosed(WindowEvent e) { if (pdm.getComponent() instanceof EnhancedCustomPropertyEditor) { - if (!pdm.wasCancelled()) { + if (!pdm.wasCancelled() && !closedOption && !pdm.wasOK() && !pdm.wasReset()) { try { //Enhanced custom property editors don't trigger property changes, so try to force it pdm.getEditor().setValue(((EnhancedCustomPropertyEditor) pdm.getComponent()).getPropertyValue()); @@ -234,6 +233,17 @@ Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR)); } + // MCF ISSUE 44366 + public void windowClosing(WindowEvent ev) { + if (PropUtils.isLoggable(CustomEditorAction.class)) { + PropUtils.log (CustomEditorAction.class, + "CustomerEditorAction windowClosing event"); + } + closedOption = true; + } + + // MCF ISSUE 44366 + boolean closedOption = false; }; Index: src/org/openide/explorer/propertysheet/EditablePropertyDisplayer.java =================================================================== RCS file: /cvs/openide/src/org/openide/explorer/propertysheet/EditablePropertyDisplayer.java,v retrieving revision 1.6 diff -u -r1.6 EditablePropertyDisplayer.java --- src/org/openide/explorer/propertysheet/EditablePropertyDisplayer.java 28 Jan 2004 15:00:01 -0000 1.6 +++ src/org/openide/explorer/propertysheet/EditablePropertyDisplayer.java 25 Aug 2004 16:35:21 -0000 @@ -715,7 +715,7 @@ bp.setButtonAction(getCustomEditorAction()); } - private Action getCustomEditorAction() { + Action getCustomEditorAction() { if (customEditorAction == null) { PropertyModel mdl=null;; if (modelRef != null) { Index: src/org/openide/explorer/propertysheet/IndexedPropertyEditor.java =================================================================== RCS file: /cvs/openide/src/org/openide/explorer/propertysheet/IndexedPropertyEditor.java,v retrieving revision 1.26 diff -u -r1.26 IndexedPropertyEditor.java --- src/org/openide/explorer/propertysheet/IndexedPropertyEditor.java 9 Dec 2003 09:30:01 -0000 1.26 +++ src/org/openide/explorer/propertysheet/IndexedPropertyEditor.java 25 Aug 2004 16:35:21 -0000 @@ -67,6 +67,7 @@ } else { throw new IllegalStateException("This is not an array: " + details); // NOI18N } + env.setChangeImmediate(false); } Index: src/org/openide/explorer/propertysheet/PropertyDialogManager.java =================================================================== RCS file: /cvs/openide/src/org/openide/explorer/propertysheet/PropertyDialogManager.java,v retrieving revision 1.67 diff -u -r1.67 PropertyDialogManager.java --- src/org/openide/explorer/propertysheet/PropertyDialogManager.java 26 Feb 2004 22:41:36 -0000 1.67 +++ src/org/openide/explorer/propertysheet/PropertyDialogManager.java 25 Aug 2004 16:35:21 -0000 @@ -20,6 +20,7 @@ import javax.swing.JButton; import javax.swing.JOptionPane; import javax.swing.JComponent; +import javax.swing.UIManager; import org.openide.DialogDescriptor; import org.openide.nodes.Node; @@ -212,16 +213,33 @@ defaultButton.getAccessibleContext().setAccessibleDescription(getString("ACSD_CTL_Default")); defaultButton.setDefaultCapable(false); defaultButton.setVerifyInputWhenFocusTarget(false); - options = new Object[] { + + if ("Aqua".equals(UIManager.getLookAndFeel().getID())) { + //Support Aqua button ordering + options = new Object[] { defaultButton, + cancelButton, + okButton + }; + } else { + options = new Object[] { + okButton, + defaultButton, + cancelButton + }; + } + } else { + if ("Aqua".equals(UIManager.getLookAndFeel().getID())) { + options = new Object[] { + cancelButton, + okButton + }; + } else { + options = new Object[] { okButton, cancelButton - }; - } else { - options = new Object[] { - okButton, - cancelButton - }; + }; + } } defaultOption = okButton; } @@ -408,7 +426,16 @@ public boolean wasCancelled() { return cancelled; } - + + private boolean ok = false; + public boolean wasOK() { + return ok; + } + private boolean reset = false; + public boolean wasReset() { + return reset; + } + /** Called when user presses a button on some option (button) in the * dialog. * @param evt The button press event. @@ -416,10 +443,13 @@ private void doButtonPressed(ActionEvent evt) { String label = evt.getActionCommand(); if (label.equals(getString("CTL_Cancel"))) { - cancelled = true; + cancelled = true; // XXX shouldn't this be reset otherwise? cancelValue(); } + ok = false; + reset = false; if (label.equals(getString("CTL_Default"))) { + reset = true; if (prop != null) { try { prop.restoreDefaultValue(); @@ -431,6 +461,7 @@ } } if ( label.equals(getString("CTL_OK"))) { + ok = true; if ((env!=null)&&(env.getState() == PropertyEnv.STATE_NEEDS_VALIDATION)) { env.setState(PropertyEnv.STATE_VALID); if (env.getState() != PropertyEnv.STATE_VALID) { Index: src/org/openide/explorer/propertysheet/PropertyPanel.java =================================================================== RCS file: /cvs/openide/src/org/openide/explorer/propertysheet/PropertyPanel.java,v retrieving revision 1.141 diff -u -r1.141 PropertyPanel.java --- src/org/openide/explorer/propertysheet/PropertyPanel.java 10 Feb 2004 23:01:35 -0000 1.141 +++ src/org/openide/explorer/propertysheet/PropertyPanel.java 25 Aug 2004 16:35:21 -0000 @@ -30,6 +30,7 @@ import java.beans.PropertyEditor; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; +import javax.swing.Action; import javax.swing.JComponent; import org.openide.nodes.Node; @@ -248,6 +249,37 @@ System.err.println(""); //NOI18N } }); + getActionMap().put("invokeCustomEditor", new CustomEditorProxyAction()); //NOI18N + } + + /** + * Held in action map to allow TreeTableView to invoke the custom editor over read-only cells + */ + private class CustomEditorProxyAction extends AbstractAction { + Action wrapped = null; + public void actionPerformed(ActionEvent e) { + Action wrapped = getWrapped(); + if (wrapped != null) { + wrapped.actionPerformed (e); + } + } + + public Action getWrapped() { + Node.Property p = getProperty(); + EditablePropertyDisplayer pd = getPropertyDisplayer() instanceof EditablePropertyDisplayer ? + (EditablePropertyDisplayer) getPropertyDisplayer() : new EditablePropertyDisplayer(p); + + return pd.getCustomEditorAction(); + } + + public boolean isEnabled() { + Action wrapped = getWrapped(); + if (wrapped != null) { + return wrapped.isEnabled(); + } else { + return getProperty() != null; + } + } } private boolean initializing = false; Index: src/org/openide/explorer/view/TreeTable.java =================================================================== RCS file: /cvs/openide/src/org/openide/explorer/view/TreeTable.java,v retrieving revision 1.44.2.2 diff -u -r1.44.2.2 TreeTable.java --- src/org/openide/explorer/view/TreeTable.java 6 Mar 2004 16:29:17 -0000 1.44.2.2 +++ src/org/openide/explorer/view/TreeTable.java 25 Aug 2004 16:35:22 -0000 @@ -28,6 +28,7 @@ import javax.swing.table.TableColumn; import javax.swing.plaf.basic.BasicTableUI; import java.util.EventObject; +import java.beans.PropertyEditor; import javax.swing.plaf.TableUI; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellEditor; @@ -35,6 +36,7 @@ import org.openide.nodes.Node.Property; import org.openide.nodes.Node; import org.openide.ErrorManager; +import org.openide.explorer.propertysheet.PropertyPanel; import org.openide.util.NbBundle; import org.openide.awt.MouseUtils; @@ -43,7 +45,7 @@ * * @author Jan Rojcek */ -class TreeTable extends JTable { +class TreeTable extends JTable implements Runnable { /** A subclass of JTree. */ private TreeTableCellRenderer tree; private NodeTableModel tableModel; @@ -73,8 +75,7 @@ this.tree = new TreeTableCellRenderer(treeModel); this.tableModel = new TreeTableModelAdapter(tree, tableModel); - NodeRenderer rend = NodeRenderer.sharedInstance (); - tree.setCellRenderer(rend); + tree.setCellRenderer(new NodeRenderer()); // Install a tableModel representing the visible rows in the tree. setModel(this.tableModel); @@ -158,12 +159,12 @@ false), "beginEdit"); getActionMap().put("beginEdit", new EditAction()); - imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, + imp2.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "cancelEdit"); getActionMap().put("cancelEdit", new CancelEditAction()); imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, - false), "enter"); + false), "enter"); getActionMap().put("enter", new EnterAction()); imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "next"); @@ -273,30 +274,21 @@ private void calcRowHeight(Graphics g) { Font f = getFont(); FontMetrics fm = g.getFontMetrics(f); - int rowHeight = fm.getHeight() + 4; + int rowHeight = fm.getHeight() + fm.getMaxDescent(); needCalcRowHeight = false; - rowHeight = Math.min(20, rowHeight); - setRowHeight (rowHeight); + rowHeight = Math.max(20, rowHeight); + tree.setRowHeight (rowHeight); + setRowHeight(rowHeight); } - /* - * Overridden to pass the new rowHeight to the tree. - */ - public void setRowHeight(int rowHeight) { - super.setRowHeight(rowHeight); - if (tree != null && tree.getRowHeight() != rowHeight) { - tree.setRowHeight(getRowHeight()); - } - } - /** * Returns the tree that is being shared between the model. */ JTree getTree() { return tree; } - - /** + + /** * Returns table column index of the column displaying the tree. */ int getTreeColumnIndex() { @@ -351,7 +343,7 @@ //Bypass standard tab and escape handling, and use our registered //actions instead - if ((e.getKeyCode() != e.VK_TAB && e.getKeyCode() != e.VK_ESCAPE) || (e.getModifiers() & e.CTRL_MASK) != 0) { + if (!isEditing() || ((e.getKeyCode() != e.VK_TAB && e.getKeyCode() != e.VK_ESCAPE) || (e.getModifiers() & e.CTRL_MASK) != 0)) { super.processKeyEvent(e); } else { processKeyBinding(KeyStroke.getKeyStroke( @@ -386,7 +378,7 @@ inEditRequest =false; return false; } - + if (isEditing()) { inEditorChangeRequest = true; try { @@ -396,7 +388,7 @@ inEditorChangeRequest = false; } } - + //Treat a keyEvent request to edit on a non-editable //column as a request to edit the nearest column that is //editable @@ -407,28 +399,31 @@ editable = false; column = 1; } - + + boolean columnShifted = false; if (!editable && (e instanceof KeyEvent || e == null)) { for (int i=column; i < getColumnCount(); i++) { if (getModel().isCellEditable(row, i)) { + columnShifted = i != column; column = i; changeSelection(row, column, false, false); break; } } } - - + + final Rectangle r = getCellRect (row, column, true); + //#44226 - Provide a way to invoke the custom editor on disabled cells + boolean canTryCustomEditor = !columnShifted && e instanceof MouseEvent ? + ((MouseEvent) e).getX() > r.x + r.width - 24 && ((MouseEvent) e).getX() < r.x + r.width : + true; try { canEdit = (lastRow == row); Object o = getValueAt(row, column); if (o instanceof Property) { // && (e == null || e instanceof KeyEvent)) { //Toggle booleans without instantiating an editor Property p = (Property) o; - if (p.getValueType() == Boolean.class || p.getValueType() == Boolean.TYPE) { - if (!p.canWrite()) { - return false; - } + if (p.canWrite() && (p.getValueType() == Boolean.class || p.getValueType() == Boolean.TYPE)) { try { Boolean val = (Boolean) p.getValue(); if (Boolean.FALSE.equals(val)) { @@ -437,34 +432,65 @@ //This covers null multi-selections too p.setValue(Boolean.FALSE); } - Rectangle r = getCellRect (row, column, true); + repaint (r.x, r.y, r.width, r.height); return false; } catch (Exception e1) { ErrorManager.getDefault().notify(ErrorManager.WARNING, e1); return false; } + } else if (canTryCustomEditor && !Boolean.TRUE.equals(p.getValue("suppressCustomEditor"))) { //NOI18N + PropertyPanel panel = new PropertyPanel (p); + PropertyEditor ed = panel.getPropertyEditor(); + if (ed != null && ed.supportsCustomEditor()) { + Action act = panel.getActionMap().get("invokeCustomEditor"); //NOI18N + if (act != null) { + SwingUtilities.invokeLater (new Runnable(){ + public void run() { + r.x = 0; + r.width = getWidth(); + TreeTable.this.repaint (r); + } + }); + act.actionPerformed(null); + return false; + } + } + } + if (!p.canWrite()) { + return false; } } - + boolean ret = super.editCellAt(row, column, e); if (ret) { - editorComp.requestFocus(); - } - - if (ret && column == getTreeColumnIndex()) { + //InvokeLater to get out of the way of anything the winsys is going to do + if (column == getTreeColumnIndex()) { ignoreScrolling = true; tree.scrollRectToVisible(tree.getRowBounds(row)); ignoreScrolling = false; + } else { + SwingUtilities.invokeLater (this); } + } + return ret; } finally { inEditRequest = false; } } - - /* + + /** + * + */ + public void run() { + if (editorComp != null && editorComp.isShowing()) { + editorComp.requestFocus(); + } + } + + /* */ public void valueChanged(ListSelectionEvent e) { if (getSelectedRowCount() == 1) @@ -578,7 +604,6 @@ public TreeTableCellRenderer(TreeModel model) { super(model); - setRowHeight(getRowHeight()); setToggleClickCount(0); putClientProperty("JTree.lineStyle", "None"); // NOI18N } @@ -599,20 +624,26 @@ //do nothing } + /** + * Accessor so NodeRenderer can check if the tree table or its child has + * focus and paint with the appropriate color. + * + * @see NodeRenderer#configureFrom + * @return The tree table + */ + TreeTable getTreeTable() { + return TreeTable.this; + } + /** * Sets the row height of the tree, and forwards the row height to * the table. */ - public void setRowHeight(int rowHeight) { - if (rowHeight > 0) { - synchronized (getTreeLock()) { - super.setRowHeight(rowHeight); - if (TreeTable.this != null && - TreeTable.this.getRowHeight() != rowHeight) { - TreeTable.this.setRowHeight(getRowHeight()); - } - } - } + public void setRowHeight(int rowHeight) { + if (rowHeight > 0) { + super.setRowHeight(rowHeight); + TreeTable.this.setRowHeight(rowHeight); + } } /** @@ -701,14 +732,19 @@ boolean tableHasFocus = focusOwner == this || focusOwner == TreeTable.this - || TreeTable.this.isAncestorOf(focusOwner); + || TreeTable.this.isAncestorOf(focusOwner) || + focusOwner instanceof JRootPane; //RootPane == popup menu + //TODO - it should be possible to simply set the correct + //color in prepareRenderer for the tree's cell renderer, + //rather than set it for the whole tree. Might fix a + //couple problems. -Tim setBackground(tableHasFocus ? table.getSelectionBackground() : - NodeRenderer.getNoFocusSelectionBackground()); + getUnfocusedSelectedBackground()); setForeground(tableHasFocus ? table.getSelectionForeground() : - NodeRenderer.getNoFocusSelectionForeground()); + getUnfocusedSelectedForeground()); } else { setBackground(table.getBackground()); setForeground(table.getForeground()); @@ -818,10 +854,10 @@ if (isEditing() && editorComp != null) { editorComp.setBackground(focused ? getSelectionBackground() : - NodeRenderer.getNoFocusSelectionBackground()); + getUnfocusedSelectedBackground()); editorComp.setForeground(focused ? getSelectionForeground() : - NodeRenderer.getNoFocusSelectionForeground()); + getUnfocusedSelectedForeground()); } } @@ -1181,7 +1217,7 @@ int min = listSelectionModel.getMinSelectionIndex(); int max = listSelectionModel.getMaxSelectionIndex(); - this.clearSelection (); + boolean unset = true; if(min != -1 && max != -1) { for(int counter = min; counter <= max; counter++) { if(listSelectionModel.isSelectedIndex(counter)) { @@ -1189,11 +1225,19 @@ (counter); if(selPath != null) { - addSelectionPath(selPath); + if (unset) { + setSelectionPath(selPath); + unset = false; + } else { + addSelectionPath(selPath); + } } } } } + if (unset) { + clearSelection(); + } } finally { updatingListSelectionModel = false; @@ -1323,7 +1367,8 @@ setDispatchComponent(e); repostEvent(e); } - else { + + if (e.getID() == MouseEvent.MOUSE_PRESSED) { table.requestFocus(); } @@ -1547,8 +1592,7 @@ } public boolean isEnabled() { - // return isEditing(); - return true; + return isEditing(); } } @@ -1611,4 +1655,46 @@ } } } + + private static Color unfocusedSelBg = null; + private static Color unfocusedSelFg = null; + + /** Get the system-wide unfocused selection background color */ + static Color getUnfocusedSelectedBackground() { + if (unfocusedSelBg == null) { + //allow theme/ui custom definition + unfocusedSelBg = + UIManager.getColor("nb.explorer.unfocusedSelBg"); //NOI18N + if (unfocusedSelBg == null) { + //try to get standard shadow color + unfocusedSelBg = UIManager.getColor("controlShadow"); //NOI18N + if (unfocusedSelBg == null) { + //Okay, the look and feel doesn't suport it, punt + unfocusedSelBg = Color.lightGray; + } + //Lighten it a bit because disabled text will use controlShadow/ + //gray + unfocusedSelBg = unfocusedSelBg.brighter(); + } + } + return unfocusedSelBg; + } + + /** Get the system-wide unfocused selection foreground color */ + static Color getUnfocusedSelectedForeground() { + if (unfocusedSelFg == null) { + //allow theme/ui custom definition + unfocusedSelFg = + UIManager.getColor("nb.explorer.unfocusedSelFg"); //NOI18N + if (unfocusedSelFg == null) { + //try to get standard shadow color + unfocusedSelFg = UIManager.getColor("textText"); //NOI18N + if (unfocusedSelFg == null) { + //Okay, the look and feel doesn't suport it, punt + unfocusedSelFg = Color.BLACK; + } + } + } + return unfocusedSelFg; + } } Index: src/org/openide/nodes/Index.java =================================================================== RCS file: /cvs/openide/src/org/openide/nodes/Index.java,v retrieving revision 1.23 diff -u -r1.23 Index.java --- src/org/openide/nodes/Index.java 14 May 2002 15:49:01 -0000 1.23 +++ src/org/openide/nodes/Index.java 25 Aug 2004 16:35:22 -0000 @@ -7,7 +7,7 @@ * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original - * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun * Microsystems, Inc. All Rights Reserved. */ @@ -380,10 +380,10 @@ */ public int indexOf (final Node node) { try { - PR.enterWriteAccess (); + PR.enterReadAccess (); return ((List)nodes).indexOf(node); } finally { - PR.exitWriteAccess (); + PR.exitReadAccess (); } }