Package nodebox.client

Source Code of nodebox.client.PortAttributesEditor

package nodebox.client;

import com.google.common.collect.ImmutableList;
import nodebox.Icons;
import nodebox.node.Port;
import nodebox.node.MenuItem;
import nodebox.ui.Theme;
import nodebox.util.HumanizedObject;

import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;

public class PortAttributesEditor extends JPanel implements ActionListener, FocusListener {

    // TODO: Don't update immediately, use save/cancel buttons.

    private JTextField nameField;
    private JTextField labelField;
    private JTextField typeField;
    private JTextField descriptionField;
    private JComboBox widgetBox;
    private JComboBox rangeBox;
    private JTextField valueField;
    private JTextField minimumValueField;
    private JCheckBox minimumValueCheck;
    private JTextField maximumValueField;
    private JCheckBox maximumValueCheck;
    private JTable menuItemsTable;
    private JButton addButton;
    private JButton removeButton;
    private JButton upButton;
    private JButton downButton;

    private static Map<String, HumanizedObject[]> humanizedWidgetsMap;
    private static HumanizedObject[] humanizedRanges;

    static {
        humanizedWidgetsMap = new HashMap<String, HumanizedObject[]>();
        for (String key : Port.WIDGET_MAPPING.keySet()) {
            ImmutableList<Port.Widget> widgets = Port.WIDGET_MAPPING.get(key);
            HumanizedObject[] humanizedWidgets = new HumanizedObject[widgets.size()];
            for (int i = 0; i < widgets.size(); i++) {
                humanizedWidgets[i] = new HumanizedObject(widgets.get(i));
            }
            humanizedWidgetsMap.put(key, humanizedWidgets);
        }
        humanizedRanges = new HumanizedObject[Port.Range.values().length];
        for (int i = 0; i < Port.Range.values().length; i++) {
            humanizedRanges[i] = new HumanizedObject(Port.Range.values()[i]);
        }
    }

    private int y = 0;

    private boolean focusLostEvents = true;

    private NodeAttributesDialog nodeAttributesDialog;
    private String portName;

    public PortAttributesEditor(NodeAttributesDialog dialog, String portName) {
        this.nodeAttributesDialog = dialog;
        this.portName = portName;
        initPanel();
        updateValues();
    }

    private void addRow(String label, JComponent component) {
        JLabel l = new JLabel(label);
        l.setFont(Theme.SMALL_BOLD_FONT);
        l.setBounds(18, y, 400, 18);
        add(l);
        y += 18;
        int componentHeight = (int) component.getPreferredSize().getHeight();
        component.setBounds(16, y, 400, componentHeight);
        y += componentHeight;
        y += 2; // vertical gap
        add(component);
    }

    public void initPanel() {
        // The panel uses an absolute layout.
        setLayout(null);

        // Name
        nameField = new JFormattedTextField(20);
        nameField.setEnabled(false);
        addRow("Name", nameField);

        // Label
        labelField = new JTextField(20);
        labelField.addActionListener(this);
        addRow("Label", labelField);

        // Type
        typeField = new JTextField(20);
        typeField.setEnabled(false);
        addRow("Type", typeField);

        // Description
        descriptionField = new JTextField(20);
        descriptionField.addActionListener(this);
        addRow("Description", descriptionField);

        // Widget
        if (getPort().isStandardType()) {
            widgetBox = new JComboBox(humanizedWidgetsMap.get(getPort().getType()));
            widgetBox.addActionListener(this);
            addRow("Widget", widgetBox);
        }

        rangeBox = new JComboBox(humanizedRanges);
        rangeBox.addActionListener(this);
        addRow("Range", rangeBox);

        // Value
        valueField = new JTextField(20);
        valueField.addActionListener(this);
        valueField.addFocusListener(this);
        addRow("Value", valueField);

        // Minimum Value
        minimumValueCheck = new JCheckBox();
        minimumValueCheck.addActionListener(this);
        minimumValueField = new JTextField(10);
        minimumValueField.addActionListener(this);
        minimumValueField.addFocusListener(this);
        JPanel minimumValuePanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 0));
        minimumValuePanel.add(minimumValueCheck);
        minimumValuePanel.add(minimumValueField);
        addRow("Minimum", minimumValuePanel);

        // Maximum Value
        maximumValueCheck = new JCheckBox();
        maximumValueCheck.addActionListener(this);
        maximumValueField = new JTextField(10);
        maximumValueField.addActionListener(this);
        maximumValueField.addFocusListener(this);
        JPanel maximumValuePanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 0));
        maximumValuePanel.add(maximumValueCheck);
        maximumValuePanel.add(maximumValueField);
        addRow("Maximum", maximumValuePanel);

        // Menu Items
        menuItemsTable = new JTable(new MenuItemsModel());
        menuItemsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        menuItemsTable.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2)
                    updateMenuItem();
            }
        });
        JPanel tablePanel = new JPanel(new BorderLayout(5, 5));
        JScrollPane tableScroll = new JScrollPane(menuItemsTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        tableScroll.setSize(200, 170);
        tableScroll.setPreferredSize(new Dimension(200, 170));
        tableScroll.setMaximumSize(new Dimension(200, 170));
        tableScroll.setMinimumSize(new Dimension(200, 170));
        tablePanel.add(tableScroll, BorderLayout.CENTER);
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 5));
        addButton = new JButton(new Icons.PlusIcon());
        addButton.addActionListener(this);
        removeButton = new JButton(new Icons.MinusIcon());
        removeButton.addActionListener(this);
        upButton = new JButton(new Icons.ArrowIcon(Icons.ArrowIcon.NORTH));
        upButton.addActionListener(this);
        downButton = new JButton(new Icons.ArrowIcon(Icons.ArrowIcon.SOUTH));
        downButton.addActionListener(this);
        buttonPanel.add(addButton);
        buttonPanel.add(removeButton);
        buttonPanel.add(upButton);
        buttonPanel.add(downButton);
        tablePanel.add(buttonPanel, BorderLayout.SOUTH);
        addRow("Menu Items", tablePanel);
    }

    private Port getPort() {
        return nodeAttributesDialog.getNode().getInput(portName);
    }

    public void updateValues() {
        Port port = getPort();
        nameField.setText(port.getName());
        labelField.setText(port.getDisplayLabel());
        typeField.setText(port.getType());
        descriptionField.setText(port.getDescription());
        rangeBox.setSelectedItem(getHumanizedRange(port.getRange()));
        if (port.isStandardType()) {
            widgetBox.setSelectedItem(getHumanizedWidget(port.getWidget()));
            valueField.setText(port.getValue().toString());
        } else
            valueField.setEnabled(false);
        Object minimumValue = port.getMinimumValue();
        String minimumValueString = minimumValue == null ? "" : minimumValue.toString();
        minimumValueCheck.setSelected(minimumValue != null);
        minimumValueField.setText(minimumValueString);
        minimumValueField.setEnabled(minimumValue != null);
        Object maximumValue = port.getMaximumValue();
        String maximumValueString = maximumValue == null ? "" : maximumValue.toString();
        maximumValueCheck.setSelected(maximumValue != null);
        maximumValueField.setText(maximumValueString);
        maximumValueField.setEnabled(maximumValue != null);
        menuItemsTable.tableChanged(new TableModelEvent(menuItemsTable.getModel()));
        revalidate();
    }

    public void actionPerformed(ActionEvent e) {
        Port port = getPort();
        if (e.getSource() == labelField) {
            if (labelField.getText().equals(port.getDisplayLabel())) return;
            nodeAttributesDialog.setPortLabel(portName, labelField.getText());
        } else if (e.getSource() == descriptionField) {
            nodeAttributesDialog.setPortDescription(portName, descriptionField.getText());
        } else if (e.getSource() == widgetBox) {
            HumanizedObject newWidget = (HumanizedObject) widgetBox.getSelectedItem();
            if (port.getWidget() == newWidget.getObject()) return;
            nodeAttributesDialog.setPortWidget(portName, (Port.Widget) newWidget.getObject());
        } else if (e.getSource() == rangeBox) {
            HumanizedObject newRange = (HumanizedObject) rangeBox.getSelectedItem();
            if (port.getRange() == newRange.getObject()) return;
            nodeAttributesDialog.setPortRange(portName, (Port.Range) newRange.getObject());
        } else if (e.getSource() == valueField) {
            String newValue = valueField.getText();
            if (port.getValue() != null && port.getValue().toString().equals(newValue)) return;
            try {
                nodeAttributesDialog.setPortValue(portName, Port.parseValue(port.getType(), valueField.getText()));
            } catch (IllegalArgumentException e1) {
                showError("Value " + valueField.getText() + " is invalid: " + e1.getMessage());
            }
        } else if (e.getSource() == minimumValueCheck) {
            if (minimumValueCheck.isSelected() && port.getMinimumValue() != null) return;
            nodeAttributesDialog.setPortMinimumValue(portName, minimumValueCheck.isSelected() ? (double) 0f : null);
        } else if (e.getSource() == minimumValueField) {
            try {
                float v = Float.parseFloat(minimumValueField.getText());
                if (v == port.getMinimumValue()) return;
                nodeAttributesDialog.setPortMinimumValue(portName, (double) v);
            } catch (Exception e1) {
                showError("Value " + minimumValueField.getText() + " is invalid: " + e1.getMessage());
            }
        } else if (e.getSource() == maximumValueCheck) {
            if (maximumValueCheck.isSelected() && port.getMaximumValue() != null) return;
            nodeAttributesDialog.setPortMaximumValue(portName, maximumValueCheck.isSelected() ? (double) 0f : null);
        } else if (e.getSource() == maximumValueField) {
            try {
                float v = Float.parseFloat(maximumValueField.getText());
                if (v == port.getMaximumValue()) return;
                nodeAttributesDialog.setPortMaximumValue(portName, (double) v);
            } catch (Exception e1) {
                showError("Value " + maximumValueField.getText() + " is invalid: " + e1.getMessage());
            }
        } else if (e.getSource() == addButton) {
            MenuItemDialog dialog = new MenuItemDialog((Dialog) SwingUtilities.getRoot(this));
            dialog.setVisible(true);
            if (dialog.isSuccessful()) {
                nodeAttributesDialog.addPortMenuItem(portName, dialog.getKey(), dialog.getLabel());
                menuItemsTable.tableChanged(new TableModelEvent(menuItemsTable.getModel()));
            }
        } else if (e.getSource() == removeButton) {
            MenuItem item = port.getMenuItems().get(menuItemsTable.getSelectedRow());
            nodeAttributesDialog.removePortMenuItem(portName, item);
        } else if (e.getSource() == upButton) {
            moveMenuItemUp();
        } else if (e.getSource() == downButton) {
            moveMenuItemDown();
        } else {
            throw new AssertionError("Unknown source " + e.getSource());
        }
        updateValues();
    }

    private HumanizedObject getHumanizedWidget(Port.Widget widget) {
        for (HumanizedObject humanizedWidget : humanizedWidgetsMap.get(getPort().getType())) {
            if (humanizedWidget.getObject() == widget) return humanizedWidget;
        }
        throw new AssertionError("Widget is not in humanized widget list.");
    }

    private HumanizedObject getHumanizedRange(Port.Range range) {
        for (HumanizedObject humanizedRange : humanizedRanges) {
            if (humanizedRange.getObject() == range) return humanizedRange;
        }
        throw new AssertionError("Range is not in humanized range list.");
    }

    private void showError(String msg) {
        // The message dialog popup will cause a focus lost event to be thrown,
        // which will cause another action event, throwing up a second dialog popup.
        // We temporarily disable focus lost events.
        focusLostEvents = false;
        JOptionPane.showMessageDialog(this, msg, "NodeBox", JOptionPane.ERROR_MESSAGE);
        focusLostEvents = true;
    }

    public void focusGained(FocusEvent e) {
        // Do nothing.
    }

    public void focusLost(FocusEvent e) {
        if (!focusLostEvents) return;
        actionPerformed(new ActionEvent(e.getSource(), 0, "focusLost"));
    }

    private void moveMenuItemDown() {
        int index = menuItemsTable.getSelectedRow();
        // Return if nothing was selected.
        if (index == -1) return;
        java.util.List<MenuItem> items = getPort().getMenuItems();
        // Return if the last item is selected.
        if (index >= items.size() - 1) return;
        nodeAttributesDialog.movePortMenuItemDown(portName, index);
        // TODO: Changing the selection doesn't have any effect on Mac.
        menuItemsTable.changeSelection(index + 1, 1, false, false);
    }

    private void moveMenuItemUp() {
        int index = menuItemsTable.getSelectedRow();
        // Return if nothing was selected.
        if (index == -1) return;
        // Return if the first item is selected.
        if (index == 0) return;
        nodeAttributesDialog.movePortMenuItemUp(portName, index);
        // TODO: Changing the selection doesn't have any effect on Mac.
        menuItemsTable.changeSelection(index - 1, 1, false, false);
    }
   
    private void updateMenuItem() {
        int index = menuItemsTable.getSelectedRow();
        if (index == -1) return;
        MenuItem item = getPort().getMenuItems().get(index);
        MenuItemDialog dialog = new MenuItemDialog((Dialog) SwingUtilities.getRoot(this), item);
        dialog.setVisible(true);
        if (dialog.isSuccessful()) {
            nodeAttributesDialog.updatePortMenuItem(portName, index, dialog.getKey(), dialog.getLabel());
            updateValues();
        }
    }

    private class MenuItemsModel extends AbstractTableModel {
        public int getRowCount() {
            return getPort().getMenuItems().size();
        }

        public int getColumnCount() {
            return 2;
        }

        public Object getValueAt(int row, int column) {
            MenuItem item = getPort().getMenuItems().get(row);
            if (column == 0) {
                return item.getKey();
            } else {
                return item.getLabel();
            }
        }

        @Override
        public String getColumnName(int column) {
            if (column == 0) {
                return "Key";
            } else {
                return "Label";
            }
        }
    }

    private class FormPanel extends JPanel {
        GridBagLayout layout = new GridBagLayout();
        private int rowCount = 0;

        private FormPanel() {
            setLayout(layout);
        }

        public void addRow(String label, JComponent component) {
            GridBagConstraints labelConstraints = new GridBagConstraints();
            labelConstraints.gridx = 0;
            labelConstraints.gridy = rowCount;
            labelConstraints.insets = new Insets(0, 0, 5, 5);
            labelConstraints.anchor = GridBagConstraints.LINE_END;

            GridBagConstraints componentConstraints = new GridBagConstraints();
            componentConstraints.gridx = 1;
            componentConstraints.gridy = rowCount;
            componentConstraints.gridwidth = GridBagConstraints.REMAINDER;
            componentConstraints.fill = GridBagConstraints.HORIZONTAL;
            componentConstraints.insets = new Insets(0, 0, 5, 0);
            componentConstraints.anchor = GridBagConstraints.LINE_START;

            JLabel l = new JLabel(label + ":");
            add(l, labelConstraints);
            add(component, componentConstraints);
            rowCount++;

            // Add another column/row that takes up all available space.
            // This moves the layout to the top-left corner.
            layout.columnWidths = new int[]{0, 0, 0};
            layout.columnWeights = new double[]{0.0, 0.0, 1.0E-4};
            layout.rowHeights = new int[rowCount + 1];
            layout.rowWeights = new double[rowCount + 1];
            layout.rowWeights[rowCount] = 1.0E-4;
        }
    }

    private class MenuItemDialog extends JDialog {
        private boolean successful = false;
        private JTextField keyField;
        private JTextField labelField;
        private JButton okButton, cancelButton;

        private MenuItemDialog(Dialog dialog) {
            this(dialog, new MenuItem("", ""));
        }

        private MenuItemDialog(Dialog dialog, MenuItem item) {
            super(dialog, "Menu Item", true);
            setResizable(false);
            setLocationByPlatform(true);
            JPanel content = new JPanel(new BorderLayout());
            FormPanel form = new FormPanel();
            keyField = new JTextField(item.getKey());
            labelField = new JTextField(item.getLabel());
            form.addRow("Key", keyField);
            form.addRow("Label", labelField);
            content.add(form, BorderLayout.CENTER);
            JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 5, 0));
            okButton = new JButton("OK");
            okButton.addActionListener(new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    // Commit key and label.
                    successful = true;
                    MenuItemDialog.this.setVisible(false);
                }
            });
            cancelButton = new JButton("Cancel");
            cancelButton.addActionListener(new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    MenuItemDialog.this.setVisible(false);
                }
            });
            buttonPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
            buttonPanel.add(cancelButton);
            buttonPanel.add(okButton);
            content.add(buttonPanel, BorderLayout.SOUTH);
            setContentPane(content);
            content.setBorder(BorderFactory.createEmptyBorder(20, 40, 20, 20));
            getRootPane().setDefaultButton(okButton);
            // Close window when escape key is pressed.
            getRootPane().registerKeyboardAction(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    setVisible(false);
                }
            }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
            pack();
        }

        public String getKey() {
            return keyField.getText();
        }

        public String getLabel() {
            return labelField.getText();
        }

        public boolean isSuccessful() {
            return successful;
        }
    }

}
TOP

Related Classes of nodebox.client.PortAttributesEditor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.