? core/windows/src/org/netbeans/core/windows/MetaWindowManager.java ? core/windows/src/org/netbeans/core/windows/view/MergedView.java Index: core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/ToolbarTabDisplayerUI.java =================================================================== RCS file: /cvs/core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/ToolbarTabDisplayerUI.java,v retrieving revision 1.3 diff -u -u -r1.3 ToolbarTabDisplayerUI.java --- core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/ToolbarTabDisplayerUI.java 18 Nov 2004 13:31:00 -0000 1.3 +++ core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/ToolbarTabDisplayerUI.java 7 Jul 2005 07:06:57 -0000 @@ -498,5 +498,13 @@ g.setColor(color); } + + public Dimension getPreferredSize() { + Dimension result = new Dimension(super.getPreferredSize()); + if ("Aqua".equals(UIManager.getLookAndFeel().getID())) { + result.height += 5; + } + return result; + } } } Index: core/windows/src/org/netbeans/core/windows/view/ui/tabcontrol/TabbedContainerBridgeImpl.java =================================================================== RCS file: /cvs/core/windows/src/org/netbeans/core/windows/view/ui/tabcontrol/TabbedContainerBridgeImpl.java,v retrieving revision 1.1 diff -u -u -r1.1 TabbedContainerBridgeImpl.java --- core/windows/src/org/netbeans/core/windows/view/ui/tabcontrol/TabbedContainerBridgeImpl.java 15 Jun 2004 00:37:47 -0000 1.1 +++ core/windows/src/org/netbeans/core/windows/view/ui/tabcontrol/TabbedContainerBridgeImpl.java 7 Jul 2005 07:06:59 -0000 @@ -18,6 +18,7 @@ package org.netbeans.core.windows.view.ui.tabcontrol; +import java.awt.Component; import java.util.List; import java.util.Arrays; import javax.swing.JComponent; @@ -115,8 +116,7 @@ public void setInnerComponent(JComponent jc, JComponent inner) { TabbedContainer cont = (TabbedContainer) jc; - ComponentConverter cc = new ComponentConverter.Fixed (inner); - cont.setComponentConverter(cc); + cont.setComponentConverter(new CC (inner)); } public JComponent getInnerComponent(JComponent jc) { @@ -132,6 +132,26 @@ td[i] = new TabData (objects[i], null, titles[i], null); } cont.getModel().setTabs(td); + } + + private static final class CC implements ComponentConverter { + private final JComponent inner; + public CC (JComponent inner) { + this.inner = inner; + } + public Component getComponent(TabData data) { + Component result = null; + if (data == null) { + result = inner; + } else if (data.getUserObject() instanceof Component) { + result = (Component) data.getUserObject(); + } else { + result = inner; + } + if (!(result instanceof javax.swing.JSplitPane)) { + } + return result; + } } } Index: form/src/org/netbeans/modules/form/Bundle.properties =================================================================== RCS file: /cvs/form/src/org/netbeans/modules/form/Bundle.properties,v retrieving revision 1.163 diff -u -u -r1.163 Bundle.properties --- form/src/org/netbeans/modules/form/Bundle.properties 3 Jun 2005 14:25:49 -0000 1.163 +++ form/src/org/netbeans/modules/form/Bundle.properties 7 Jul 2005 07:07:15 -0000 @@ -685,3 +685,8 @@ CTL_AlignmentButton_d=Set bottom alignment CTL_ResizeButton_h=Change horizontal resizability CTL_ResizeButton_v=Change vertical resizability + +#CustPanel +FMT_ClassName=({0}) +LBL_Enabled=Enabled + Index: form/src/org/netbeans/modules/form/CustPanel.java =================================================================== RCS file: form/src/org/netbeans/modules/form/CustPanel.java diff -N form/src/org/netbeans/modules/form/CustPanel.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ form/src/org/netbeans/modules/form/CustPanel.java 7 Jul 2005 07:07:16 -0000 @@ -0,0 +1,420 @@ +/* + * CustPanel.java + * + * Created on July 6, 2005, 7:19 AM + * + * To change this template, choose Tools | Options and locate the template under + * the Source Creation and Management node. Right-click the template and choose + * Open. You can then make changes to the template in the Source Editor. + */ + +package org.netbeans.modules.form; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.lang.reflect.InvocationTargetException; +import javax.swing.BoxLayout; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JTextField; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import javax.swing.border.Border; +import org.openide.ErrorManager; +import org.openide.explorer.propertysheet.PropertyPanel; +import org.openide.nodes.Node; +import org.openide.util.NbBundle; + +/** + * + * @author tim + */ +class CustPanel extends JPanel implements MouseListener, FocusListener, Border, KeyListener, ActionListener { + private JLabel nameLbl = new JLabel(); + private JLabel typeLbl = new JLabel(); + private JTextField nameField = new JTextField(); + private JSeparator js = new JSeparator(); + private PropertyPanel custom = new PropertyPanel(); + private JCheckBox enabled = new JCheckBox(); + private JLabel propLbl = new JLabel(); + + /** Creates a new instance of CustPanel */ + CustPanel() { + setLayout (new BoxLayout (this, BoxLayout.Y_AXIS)); + init(); + } + + void init() { + nameLbl.setBorder (this); + nameLbl.addMouseListener (this); + nameField.addFocusListener (this); + nameField.addKeyListener(this); + nameField.addActionListener(this); + enabled.addActionListener(this); + enabled.setText (NbBundle.getMessage(CustPanel.class, "LBL_Enabled")); //NOI18N + add (nameLbl); + add (typeLbl); + nameLbl.setHorizontalAlignment(SwingConstants.CENTER); + typeLbl.setHorizontalAlignment(SwingConstants.CENTER); + nameField.setHorizontalAlignment(SwingConstants.CENTER); + add (custom); + Font f = UIManager.getFont("Label.font"); //NOI18N + if (f == null) { + f = new Font ("Dialog", Font.PLAIN, 12); //NOI18N + } + propLbl.setFont (f.deriveFont(Font.BOLD)); + f = f.deriveFont (Font.BOLD, 16f); + nameLbl.setFont (f); + nameField.setFont (f); + //Turn this on if we want to use custom editors +// custom.setChangeImmediate(true); + custom.putClientProperty ("radioButtonMax", new Integer (3)); //NOI18N + custom.putClientProperty ("useLabels", Boolean.FALSE); + enabled.setVisible(false); + propLbl.setVisible(false); + enabled.setVisible(false); + js.setVisible(false); + add (js); + add (propLbl); + add (enabled); + } + + public Dimension getPreferredSize() { + return new Dimension (300, 300); + } + + public void paint (java.awt.Graphics g) { + super.paint (g); + } + + private RADComponentNode node = null; + void setNode (RADComponentNode node) { + this.node = node; + updateContents(); + } + + private void updateContents() { + if (nameField.isShowing()) { + stopEditing(false); + } + if (node != null) { + nameLbl.setText (node.getRADComponent().getName()); + String s = node.getRADComponent().getBeanClass().getName(); + int idx = s.lastIndexOf ("."); + if (idx != -1) { + s = s.substring (idx + 1); + } + s = NbBundle.getMessage(CustPanel.class, "FMT_ClassName", s); //NOI18N + typeLbl.setText (s); + } + updateProperty(); + validate(); + repaint(); + } + + public void doLayout() { + Dimension d = nameLbl.getPreferredSize(); + int gap = 6; + int wf = getWidth() / 4; + int y = gap; + nameLbl.setBounds(y, y, getWidth() - 8, d.height); + y += d.height + gap; + typeLbl.setBounds(4, y, getWidth() -8, typeLbl.getPreferredSize().height); + nameField.setBounds (nameLbl.getBounds()); + y += d.height + gap; + + d = propLbl.getPreferredSize(); + propLbl.setBounds (gap, y, d.width, d.height); + js.setBounds (gap + d.width + gap, y + (d.height / 2), getWidth() - (gap + gap + gap + d.width), d.height / 2); + + y += propLbl.getHeight() + gap; + y += gap; + d = custom.getPreferredSize(); + custom.setBounds (4, y, getWidth() - 8, Math.max (20, d.height)); + y += gap + custom.getHeight(); + d = enabled.getPreferredSize(); + enabled.setBounds (getWidth() - (d.width + gap), getHeight() - (gap + d.height), d.width, d.height); + } + + private void stopEditing (boolean take) { + if (take && node != null && nameField.isShowing()) { + try { + String s = nameField.getText().trim(); + node.setName(s); + } catch (Exception e) { + ErrorManager.getDefault().notify(e); + } + } + nameLbl.setVisible (true); + nameField.setVisible(false); + remove (nameField); + updateContents(); + revalidate(); + repaint(); + } + + private void startEditing () { + if (!nameField.isShowing()) { + nameField.setText (nameLbl.getText()); + nameField.setVisible(true); + nameLbl.setVisible(false); + add (nameField); + validate(); + repaint(); + nameField.requestFocus(); + } + } + + public void mouseClicked(MouseEvent e) { + } + + boolean armed = false; + public void mousePressed(MouseEvent e) { + armed = node != null; + } + + public void mouseReleased(MouseEvent e) { + if (armed && node != null) { + startEditing(); + } + armed = false; + } + + boolean containsMouse = false; + public void mouseEntered(MouseEvent e) { + containsMouse = true; + nameLbl.repaint(); + } + + public void mouseExited(MouseEvent e) { + containsMouse = false; + nameLbl.repaint(); + } + + public void focusGained(FocusEvent e) { + nameField.setSelectionStart (0); + nameField.setSelectionEnd (nameField.getText().length()); + } + + public void focusLost(FocusEvent e) { + stopEditing (true); + } + + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + if (containsMouse) { + g.setColor (new Color (180, 180, 255)); + g.drawRect (x, y, width - 1, height - 1); + } + } + + public Insets getBorderInsets(Component c) { + return new Insets (1, 1, 1, 1); + } + + public boolean isBorderOpaque() { + return false; + } + + private void updateProperty() { + Node.Property p = null; + if (node != null) { +// Code below should work is form editor sets preferred properties +// correctly; it doesn't. Could hack w/ check for html display +// name +// +// Node.PropertySet[] ps = node.getPropertySets(); +// for (int i=0; i < ps.length; i++) { +// Node.Property[] props = ps[i].getProperties(); +// for (int j=0; j < props.length; j++) { +// if (props[j].isPreferred()) { +// p = props[j]; +// break; +// } +// } +// } + if (p == null) { + Class clazz = node.getRADComponent().getBeanClass(); + String propName = getPropForClass (clazz); + if (propName != null) { + p = node.getProperty(propName); + } + } + } + if (p != null) { + //Optional - use custom editor - looks weird w/ form connection + //editor, though +// custom.setPreferences(PropertyPanel.PREF_CUSTOM_EDITOR); + custom.setProperty (p); + } + custom.setVisible (p != null); + js.setVisible (p != null); + propLbl.setVisible (p != null); + propLbl.setText (p == null ? "" : capitalize (p.getDisplayName())); + Node.Property en = node.getProperty("enabled"); + if (en == null) { + //??? sometimes it's capitalized + en = node.getProperty("Enabled"); + } + enabled.setVisible (en != null); + if (en != null) { + try { + enabled.setSelected (Boolean.TRUE.equals(en.getValue())); + } catch (Exception e) { + ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); + } + } + } + + private String getPropForClass (Class clazz) { + String result = null; + String s = clazz.getName(); + int ix = s.lastIndexOf ("."); + if (ix != -1) { + s = s.substring (ix + 1); + } + if ("JTable".equals(s) || "JList".equals(s) || "JTree".equals(s) || + "JComboBox".equals(s)) { + return "model"; + } else if ("JLabel".equals(s) || "JTextField".equals (s) || + "JButton".equals(s) || + "JToggleButton".equals(s) || "JMenu".equals(s) || + "JMenuItem".equals(s) || + "JTextArea".equals(s) || + "JRadioButton".equals(s) || + "JCheckBox".equals(s)) { + + return "text"; + } else if ("JSpinner".equals(s) || "JSlider".equals(s) || + "JProgressBar".equals(s) || "JScrollBar".equals(s)) { + return "value"; + } else if ("JSplitPane".equals(s)) { + return "dividerLocation"; + } else if ("JScrollPane".equals(s)) { + return "horizontalScrollBarPolicy"; + } else if ("JFrame".equals(s) || "JDialog".equals(s)) { + return "title"; + } + + //XXX to be continued...AWT components & such + return null; + } + + private static String capitalize (String s) { + if (s.length() > 0) { + StringBuffer sb = new StringBuffer (s); + sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); + return sb.toString(); + } else { + return s; + } + } + + public void keyTyped(KeyEvent e) { + if (Character.isDigit(e.getKeyChar()) + && (nameField.getText().trim().length() == 0 || + (nameField.getSelectionStart() == 0 && + nameField.getSelectionEnd() == nameField.getText().length()))) { + System.err.println("block typed a"); + e.consume(); + } else { + char[] c = new char[] { + ',', + '.', + ';', + '+', + '-', + '%', + '*', + '(', + ')', + '{', + '}', + '[', + ']', + ' ', + '&', + '!', + '^', + '@', + '\\', + '/'}; + boolean block = false; + for (int i=0; i < c.length; i++) { + if (c[i] == e.getKeyCode()) { + block = true; + break; + } + } + if (block) { + System.err.println("block typed b"); + e.consume(); + } + } + } + + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() >= KeyEvent.VK_0 && e.getKeyCode() <= KeyEvent.VK_9) { + if (nameField.getText().trim().length() == 0 || + (nameField.getSelectionStart() == 0 && + nameField.getSelectionEnd() == nameField.getText().length())) { + System.err.println(" block pressed a"); + e.consume(); + } else if (e.getKeyCode() == KeyEvent.VK_COMMA || + e.getKeyCode() == KeyEvent.VK_DIVIDE || + e.getKeyCode() == KeyEvent.VK_PERIOD || + e.getKeyCode() == KeyEvent.VK_SEMICOLON || + e.getKeyCode() == KeyEvent.VK_PLUS || + e.getKeyCode() == KeyEvent.VK_ASTERISK || + e.getKeyCode() == KeyEvent.VK_LEFT_PARENTHESIS || + e.getKeyCode() == KeyEvent.VK_RIGHT_PARENTHESIS || + e.getKeyCode() == KeyEvent.VK_OPEN_BRACKET || + e.getKeyCode() == KeyEvent.VK_SPACE || + e.getKeyCode() == KeyEvent.VK_CLOSE_BRACKET || + e.getKeyCode() == KeyEvent.VK_BRACELEFT || + e.getKeyCode() == KeyEvent.VK_BRACERIGHT || + e.getKeyCode() == KeyEvent.VK_AMPERSAND || + e.getKeyCode() == KeyEvent.VK_COLON || + e.getKeyCode() == KeyEvent.VK_CIRCUMFLEX || + e.getKeyCode() == KeyEvent.VK_EXCLAMATION_MARK || + e.getKeyCode() == KeyEvent.VK_SLASH) { + System.err.println(" block pressed b"); + e.consume(); + } + } + } + + public void keyReleased(KeyEvent e) { +// keyPressed (e); + } + + public void actionPerformed(ActionEvent e) { + if (e.getSource() == enabled) { + Node.Property p = node.getProperty("enabled"); + if (p != null) { + try { + p.setValue (enabled.isSelected() ? Boolean.TRUE : Boolean.FALSE); + } catch (IllegalAccessException ex) { + ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); + } catch (InvocationTargetException ex1) { + ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex1); + } + } + } else { + stopEditing(true); + } + } + +} Index: form/src/org/netbeans/modules/form/RADComponentNode.java =================================================================== RCS file: /cvs/form/src/org/netbeans/modules/form/RADComponentNode.java,v retrieving revision 1.98 diff -u -u -r1.98 RADComponentNode.java --- form/src/org/netbeans/modules/form/RADComponentNode.java 3 Jun 2005 14:25:55 -0000 1.98 +++ form/src/org/netbeans/modules/form/RADComponentNode.java 7 Jul 2005 07:07:16 -0000 @@ -18,13 +18,14 @@ import java.text.MessageFormat; import java.util.*; import java.beans.*; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; import java.security.*; import javax.swing.Action; +import org.netbeans.modules.form.CustPanel; import org.openide.ErrorManager; import org.openide.actions.*; -import org.openide.cookies.*; -import org.openide.loaders.*; import org.openide.nodes.*; import org.openide.util.*; import org.openide.util.actions.SystemAction; @@ -520,6 +521,36 @@ // Node.Property prop = component.getPropertyByName(name, true); // return (FormProperty) (prop instanceof FormProperty ? prop : null); } + + private static Reference custPanel = null; + + /** + * Overridden to return a class-wide shared panel from + * getValue("customizer"). getCustomizer() could be used instead, + * but is far more likely to be inefficiently written, creating a + * new component for each call. + */ + public Object getValue (String s) { + if ("customizer".equals(s)) { + return getCustPanel(); + } else { + return super.getValue(s); + } + } + + private CustPanel getCustPanel() { + CustPanel result = null; + if (custPanel != null) { + result = (CustPanel) custPanel.get(); + } + if (result == null) { + result = new CustPanel(); + custPanel = new WeakReference (result); + } + result.setNode(this); + return result; + } + // ----------------------------------------------------------------------------- // Innerclasses Index: openide/explorer/src/org/openide/explorer/propertysheet/Bundle.properties =================================================================== RCS file: /cvs/openide/explorer/src/org/openide/explorer/propertysheet/Bundle.properties,v retrieving revision 1.1 diff -u -u -r1.1 Bundle.properties --- openide/explorer/src/org/openide/explorer/propertysheet/Bundle.properties 21 Apr 2005 20:12:41 -0000 1.1 +++ openide/explorer/src/org/openide/explorer/propertysheet/Bundle.properties 7 Jul 2005 07:07:56 -0000 @@ -211,3 +211,6 @@ object to display in the property sheet LBL_QUICKSEARCH=Quick Search: + +LBL_Customizer=Customizer + Index: openide/explorer/src/org/openide/explorer/propertysheet/PSheet.java =================================================================== RCS file: /cvs/openide/explorer/src/org/openide/explorer/propertysheet/PSheet.java,v retrieving revision 1.1 diff -u -u -r1.1 PSheet.java --- openide/explorer/src/org/openide/explorer/propertysheet/PSheet.java 21 Apr 2005 20:12:45 -0000 1.1 +++ openide/explorer/src/org/openide/explorer/propertysheet/PSheet.java 7 Jul 2005 07:07:57 -0000 @@ -116,10 +116,19 @@ tabname = PropUtils.basicPropsTabName(); // use basic tab } - boolean success = TabbedContainerBridge.getDefault().setSelectionByName(comp, tabname); + TabbedContainerBridge tcb = TabbedContainerBridge.getDefault(); + + //First try to use the Customizer button, which may be present + boolean success = tcb.setSelectionByName( + comp, NbBundle.getMessage (PSheet.class, "LBL_Customizer")); + + if (!success) { + success = tcb.setSelectionByName(comp, tabname); + } if (!success) { - TabbedContainerBridge.getDefault().setSelectionByName(comp, PropUtils.basicPropsTabName()); + TabbedContainerBridge.getDefault().setSelectionByName(comp, + PropUtils.basicPropsTabName()); } else { if (selectionListener != null) { ChangeEvent ce = new ChangeEvent(this); @@ -730,8 +739,7 @@ if (tabbed != null) { Object o = TabbedContainerBridge.getDefault().getSelectedItem(tabbed); - if (o instanceof Node.PropertySet[]) { //won't be first time - + if (o instanceof Node.PropertySet[] || o instanceof JComponent) { //won't be first time return o; } } Index: openide/explorer/src/org/openide/explorer/propertysheet/PropertySheet.java =================================================================== RCS file: /cvs/openide/explorer/src/org/openide/explorer/propertysheet/PropertySheet.java,v retrieving revision 1.1 diff -u -u -r1.1 PropertySheet.java --- openide/explorer/src/org/openide/explorer/propertysheet/PropertySheet.java 21 Apr 2005 20:12:47 -0000 1.1 +++ openide/explorer/src/org/openide/explorer/propertysheet/PropertySheet.java 7 Jul 2005 07:07:59 -0000 @@ -560,8 +560,22 @@ psheet.setState(psheet.getState() | PSheet.STATE_HAS_TABS); TabInfo info = getTabItems(node); + + Object[] sets; + String[] titles; + if (node.getValue("customizer") instanceof JComponent) { + sets = new Object[info.sets.length + 1]; + titles = new String[info.titles.length+1]; + System.arraycopy (info.sets, 0, sets, 1, info.sets.length); + System.arraycopy (info.titles, 0, titles, 1, info.titles.length); + sets[0] = node.getValue("customizer"); + titles[0] = NbBundle.getMessage(PropertySheet.class, "LBL_Customizer"); + } else { + sets = info.sets; + titles = info.titles; + } - psheet.setTabbedContainerItems(info.sets, info.titles); + psheet.setTabbedContainerItems(sets, titles); psheet.manager().setCurrentNodeName(node.getName()); psm.setPropertySets(info.getSets(0)); } else { @@ -799,6 +813,9 @@ } } } + if (n.getValue("customizer") instanceof JComponent) { + needTabs = true; + } return needTabs; } @@ -885,16 +902,19 @@ psheet.storeScrollAndTabInfo(); } - PropertySet[] sets = (PropertySet[]) psheet.getTabbedContainerSelection(); - - if (sets != null) { - table.getPropertySetModel().setPropertySets(sets); - - if ((sets.length > 0) && !psheet.isAdjusting()) { - String tab = (String) sets[0].getValue("tabName"); //NOI18N - tab = (tab == null) ? PropUtils.basicPropsTabName() : tab; - psheet.manager().storeLastSelectedGroup(tab); - psheet.adjustForName(tab); + Object o = psheet.getTabbedContainerSelection(); + if (o instanceof PropertySet[]) { + PropertySet[] sets = (PropertySet[]) o; + + if (sets != null) { + table.getPropertySetModel().setPropertySets(sets); + + if ((sets.length > 0) && !psheet.isAdjusting()) { + String tab = (String) sets[0].getValue("tabName"); //NOI18N + tab = (tab == null) ? PropUtils.basicPropsTabName() : tab; + psheet.manager().storeLastSelectedGroup(tab); + psheet.adjustForName(tab); + } } } } @@ -991,10 +1011,13 @@ if ((psheet.getState() & PSheet.STATE_HAS_TABS) != 0) { //If we're in a tabbed pane, we want the first visible //property set's help id - Node.PropertySet[] ps = (Node.PropertySet[]) psheet.getTabbedContainerSelection(); + Object o = psheet.getTabbedContainerSelection(); + if (o instanceof Node.PropertySet[]) { + Node.PropertySet[] ps = (Node.PropertySet[]) psheet.getTabbedContainerSelection(); - if ((ps != null) && (ps.length > 0)) { - id = (String) ps[0].getValue("helpID"); //NOI18N + if ((ps != null) && (ps.length > 0)) { + id = (String) ps[0].getValue("helpID"); //NOI18N + } } } else if ((id == null) && (pclistener != null)) { //Otherwise, look for the first property set on the node