📄 configurator.java
字号:
protected class NodeAnchor implements ActionListener { /** * The node meta-name. * * One of: * * <ul> * * <li> House * <li> Unit * <li> HVAC Controller * <li> HVAC Driver * <li> Zone * <li> Thermostat * <li> Damper * <li> Class * <li> Controller Class * * </ul> * * and so on and so forth. */ private String meta; /** * The node name. * * May be missing for the nodes that can't be named (example: HVAC * Controller, HVAC Driver, Zone Controller). */ protected String name; /** * The help pane relative URL. * * The prefix of the URL is defined in the configurator * configuration file (<code>configurator.docroot</code> element), * and this variable contains the rest of the URL. */ protected String helpURL; /** * The node display component. */ protected JComponent display; /** * The display layout. * * <p> * * VT: NOTE: This shouldn't be really made an instance variable, but * since the subclasses need to add buttons, "worse is better" wins * in this case. */ protected GridBagLayout layout = new GridBagLayout(); /** * The display layout constraints. * * @see #layout */ protected GridBagConstraints cs = new GridBagConstraints(); /** * The component available to the subclasses to add the * subcomponents to. * * This component will have a titled border displaying the * meta-name. */ protected JPanel content; /** * Commit button. */ protected JButton commitButton; /** * Reset button. */ protected JButton resetButton; /** * Create the instance. * * @param meta Meta name. * * @param name Node name. * * @param helpURL Relative help URL. */ public NodeAnchor(String meta, String name, String helpURL) { if ( meta == null ) { throw new IllegalArgumentException("Meta can't be null"); } this.meta = meta.trim(); this.name = name; this.helpURL = helpURL; display = new JPanel(); display.setLayout(layout); content = new JPanel(); if ( isConfigurable() ) { content.setBorder(BorderFactory.createTitledBorder(meta)); int extra = getExtraButtonCount(); cs.fill = GridBagConstraints.BOTH; cs.gridx = 0; cs.gridy = 0; // We want the grid width to be equal to the number of // buttons we are displaying cs.gridwidth = 2 + extra; // We want approximately 4:1 vertical ratio between the node // control area and error/button area cs.gridheight = 4; cs.weightx = 1; cs.weighty = 1; layout.setConstraints(content, cs); display.add(content); cs.gridy += 4; cs.gridwidth = 1; cs.gridheight = 1; cs.weighty = 0; cs.fill = GridBagConstraints.HORIZONTAL; commitButton = new JButton("Commit"); commitButton.setEnabled(false); commitButton.addActionListener(this); layout.setConstraints(commitButton, cs); display.add(commitButton); cs.gridx++; resetButton = new JButton("Reset"); resetButton.addActionListener(this); resetButton.setEnabled(false); layout.setConstraints(resetButton, cs); display.add(resetButton); cs.gridx++; // The rest of the buttons will have to be added by the // subclass constructors } else { JLabel label = new JLabel("This node is not configurable"); content.add(label); display.add(content); } } public void actionPerformed(ActionEvent e) { // Do nothing here } /** * Get the node display. * * @return The panel reflecting the node properties. */ public JComponent getPanel() { // Just in case, set the minimum size display.setMinimumSize(new Dimension(400, 200)); return display; } /** * Get the meta. */ public String getMeta() { return meta; } /** * Get the name. */ public String getName() { return name; } /** * Get the full help URL. * * @return The URL for the page to be displayed in the right bottom * pane, as string. */ public String getHelpURL() { return getConfiguration().getString("configurator.docroot") + "/" + helpURL; } public String toString() { String result = meta; if ( name != null ) { result += ": " + name; } return result; } /** * @return true if the node is configurable. */ protected boolean isConfigurable() { return true; } protected void renameNode(String newName) { name = newName.trim(); // VT: FIXME: This sequence produces bad results when the new // name is longer than the old one, so some more tweaking is // required. Most probably, the node changed has to be // invalidated along with the tree itself, or the cell renderer // has to be tinkered with. // // This effect is especially bad with the leaf nodes - nothing // seems to make them revalidate their preferred size. cfTree.invalidate(); cfTree.repaint(); } /** * How many buttons except <code>Commit</code> and * <code>Reset</code> does the node need. * * This will change the button layout - all the buttons will be * lined up vertically to the right of the error message area. * * @return Non-negative number corresponding the number of extra * buttons the node need. */ public int getExtraButtonCount() { return 0; } } /** * An anchor class that supports editing the node name. */ protected class StringAnchor extends NodeAnchor implements DocumentListener { /** * Text field that allows editing the name. */ protected JTextField textField; /** * The variable tracking the current context of the {@link * #textField text field}, to allow the validation. */ protected String currentText; /** * Create the instance. * * @param meta Meta name. * * @param name Node name. * * @param helpURL Relative help URL. */ public StringAnchor(String meta, String name, String helpURL) { super(meta, name, helpURL); textField = new JTextField(name, 20); textField.getDocument().addDocumentListener(this); content.add(textField); currentText = textField.getText(); } public void changedUpdate(DocumentEvent e) { // VT: NOTE: The plain document (that we have here) doesn't // cause this call, but let it be there just in case track(e.getDocument()); } public void insertUpdate(DocumentEvent e) { track(e.getDocument()); } public void removeUpdate(DocumentEvent e) { track(e.getDocument()); } private void track(Document d) { currentText = textField.getText(); validate(d); } /** * Validate the content of the document and take appropriate * actions. * * In this class, no actions are taken, however, they will be in * other classes - for example, {@link UnitAnchor UnitAnchor} and * {@link ZoneAnchor ZoneAnchor}, where the content of different * instances can't be the same upon commit. * * @see UniqueStringAnchor */ protected void validate(Document d) { // Let's take a shortcut and validate the text instead if ( currentText.trim().equals("") ) { // This is an unconditional screwup commitButton.setEnabled(false); return; } if ( name.equals(currentText.trim()) ) { commitButton.setEnabled(false); resetButton.setEnabled(false); } else { commitButton.setEnabled(true); resetButton.setEnabled(true); } } /** * React to the buttons pressed. * * @param e Event. */ public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if ( source == commitButton ) { renameNode(currentText); commitButton.setEnabled(false);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -