Package net.sourceforge.marathon.util

Source Code of net.sourceforge.marathon.util.PropertyEditor$ColorEditor

/*******************************************************************************
*  Copyright (C) 2010 Jalian Systems Private Ltd.
*  Copyright (C) 2010 Contributors to Marathon OSS Project
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Library General Public
*  License as published by the Free Software Foundation; either
*  version 2 of the License, or (at your option) any later version.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Library General Public License for more details.
*
*  You should have received a copy of the GNU Library General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*  Project website: http://www.marathontesting.com
*  Help: Marathon help forum @ http://groups.google.com/group/marathon-testing
*
*******************************************************************************/
package net.sourceforge.marathon.util;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.net.URL;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.prefs.Preferences;

import javax.swing.AbstractAction;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.NumberFormatter;

import net.sourceforge.marathon.util.PropertyList.Property;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.factories.ButtonBarFactory;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

public class PropertyEditor extends EscapeDialog {

    private static final class PropertyTable extends JTable {
        private static final long serialVersionUID = 1L;

        private PropertyTable(TableModel dm) {
            super(dm);
            setRowHeight(20);
        }

        @Override
        public TableCellRenderer getCellRenderer(int row, int column) {
            if (column == 0)
                return super.getCellRenderer(row, column);
            PropertyTableModel model = (PropertyTableModel) getModel();
            Property property = model.getProperty(row);
            if (property.getKlass().equals(Color.class))
                return new ColorRenderer(false);
            if (property.getKlass().equals(Font.class))
                return new FontRenderer();
            return super.getCellRenderer(row, column);
        }

        @Override
        public TableCellEditor getCellEditor(int row, int column) {
            if (column == 0)
                return super.getCellEditor(row, column);
            PropertyTableModel model = (PropertyTableModel) getModel();
            Property property = model.getProperty(row);
            if (property.getKlass().equals(Color.class))
                return new ColorEditor();
            if (property.getKlass().equals(Font.class)) {
                JComboBox box = new JComboBox(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
                return new DefaultCellEditor(box);
            }
            if (property.getKlass().equals(Boolean.class)) {
                JComboBox box = new JComboBox(new String[] { "true", "false" });
                return new DefaultCellEditor(box);
            }
            if (property.getKlass().equals(String[].class)) {
                JComboBox box = new JComboBox(property.getItems());
                return new DefaultCellEditor(box);
            }
            if (property.getKlass().equals(Integer.class))
                return new IntegerEditor(0, Integer.MAX_VALUE);
            return super.getCellEditor(row, column);
        }
    }

    public static class IntegerEditor extends DefaultCellEditor {
        private static final long serialVersionUID = 1L;

        JFormattedTextField ftf;
        NumberFormat integerFormat;
        private Integer minimum, maximum;

        public IntegerEditor(int min, int max) {
            super(new JFormattedTextField());
            ftf = (JFormattedTextField) getComponent();
            minimum = Integer.valueOf(min);
            maximum = Integer.valueOf(max);

            // Set up the editor for the integer cells.
            integerFormat = NumberFormat.getIntegerInstance();
            NumberFormatter intFormatter = new NumberFormatter(integerFormat);
            intFormatter.setFormat(integerFormat);
            intFormatter.setMinimum(minimum);
            intFormatter.setMaximum(maximum);

            ftf.setFormatterFactory(new DefaultFormatterFactory(intFormatter));
            ftf.setValue(minimum);
            ftf.setHorizontalAlignment(JTextField.TRAILING);
            ftf.setFocusLostBehavior(JFormattedTextField.PERSIST);

            // React when the user presses Enter while the editor is
            // active. (Tab is handled as specified by
            // JFormattedTextField's focusLostBehavior property.)
            ftf.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "check");
            ftf.getActionMap().put("check", new AbstractAction() {
                private static final long serialVersionUID = 1L;

                public void actionPerformed(ActionEvent e) {
                    if (!ftf.isEditValid()) { // The text is invalid.
                        if (userSaysRevert()) { // reverted
                            ftf.postActionEvent(); // inform the editor
                        }
                    } else
                        try { // The text is valid,
                            ftf.commitEdit(); // so use it.
                            ftf.postActionEvent(); // stop editing
                        } catch (java.text.ParseException exc) {
                        }
                }
            });
        }

        // Override to invoke setValue on the formatted text field.
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            JFormattedTextField ftf = (JFormattedTextField) super
                    .getTableCellEditorComponent(table, value, isSelected, row, column);
            ftf.setValue(Integer.parseInt(value.toString()));
            return ftf;
        }

        // Override to ensure that the value remains an Integer.
        public Object getCellEditorValue() {
            JFormattedTextField ftf = (JFormattedTextField) getComponent();
            Object o = ftf.getValue();
            if (o instanceof Integer) {
                return o;
            } else if (o instanceof Number) {
                return Integer.valueOf(((Number) o).intValue());
            } else {
                try {
                    return integerFormat.parseObject(o.toString());
                } catch (ParseException exc) {
                    return null;
                }
            }
        }

        // Override to check whether the edit is valid,
        // setting the value if it is and complaining if
        // it isn't. If it's OK for the editor to go
        // away, we need to invoke the superclass's version
        // of this method so that everything gets cleaned up.
        public boolean stopCellEditing() {
            JFormattedTextField ftf = (JFormattedTextField) getComponent();
            if (ftf.isEditValid()) {
                try {
                    ftf.commitEdit();
                } catch (java.text.ParseException exc) {
                }

            } else { // text is invalid
                if (!userSaysRevert()) { // user wants to edit
                    return false; // don't let the editor go away
                }
            }
            return super.stopCellEditing();
        }

        /**
         * Lets the user know that the text they entered is bad. Returns true if
         * the user elects to revert to the last good value. Otherwise, returns
         * false, indicating that the user wants to continue editing.
         */
        protected boolean userSaysRevert() {
            Toolkit.getDefaultToolkit().beep();
            ftf.selectAll();
            Object[] options = { "Edit", "Revert" };
            int answer = JOptionPane.showOptionDialog(SwingUtilities.getWindowAncestor(ftf),
                    "The value must be an integer between " + minimum + " and " + maximum + ".\n"
                            + "You can either continue editing " + "or revert to the last valid value.", "Invalid Text Entered",
                    JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[1]);

            if (answer == 1) { // Revert!
                ftf.setValue(ftf.getValue());
                return true;
            }
            return false;
        }
    }

    public static class FontRenderer extends DefaultTableCellRenderer {
        private static final long serialVersionUID = 1L;

        private String fontName;

        @Override
        protected void setValue(Object value) {
            fontName = (String) value;
            super.setValue(value);
        }

        @Override
        public Font getFont() {
            return Font.decode(fontName);
        }
    }

    public static class ColorEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
        private static final long serialVersionUID = 1L;

        Color currentColor;
        JButton button;
        JColorChooser colorChooser;
        JDialog dialog;
        protected static final String EDIT = "edit";

        public ColorEditor() {
            // Set up the editor (from the table's point of view),
            // which is a button.
            // This button brings up the color chooser dialog,
            // which is the editor from the user's point of view.
            button = UIUtils.createEmptyButton();
            button.setActionCommand(EDIT);
            button.addActionListener(this);
            button.setBorderPainted(false);

            // Set up the dialog that the button brings up.
            colorChooser = new JColorChooser();
            dialog = JColorChooser.createDialog(button, "Pick a Color", true, // modal
                    colorChooser, this, // OK button handler
                    null); // no CANCEL button handler
        }

        /**
         * Handles events from the editor button and from the dialog's OK
         * button.
         */
        public void actionPerformed(ActionEvent e) {
            if (EDIT.equals(e.getActionCommand())) {
                // The user has clicked the cell, so
                // bring up the dialog.
                button.setBackground(currentColor);
                colorChooser.setColor(currentColor);
                dialog.setVisible(true);

                // Make the renderer reappear.
                fireEditingStopped();

            } else { // User pressed dialog's "OK" button.
                currentColor = colorChooser.getColor();
            }
        }

        // Implement the one CellEditor method that AbstractCellEditor doesn't.
        public Object getCellEditorValue() {
            return "#" + Integer.toHexString((currentColor.getRGB() & 0x00FFFFFF) | 0x1000000).substring(1);
        }

        // Implement the one method defined by TableCellEditor.
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            currentColor = Color.decode(value.toString());
            return button;
        }
    }

    public static class ColorRenderer extends JLabel implements TableCellRenderer {
        private static final long serialVersionUID = 1L;

        Border unselectedBorder = null;
        Border selectedBorder = null;
        boolean isBordered = true;

        public ColorRenderer(boolean isBordered) {
            this.isBordered = isBordered;
            setOpaque(true); // MUST do this for background to show up.
        }

        public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row,
                int column) {
            Color newColor = Color.decode(color.toString());
            setBackground(newColor);
            if (isBordered) {
                if (isSelected) {
                    if (selectedBorder == null) {
                        selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getSelectionBackground());
                    }
                    setBorder(selectedBorder);
                } else {
                    if (unselectedBorder == null) {
                        unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getBackground());
                    }
                    setBorder(unselectedBorder);
                }
            }

            setToolTipText("RGB value: " + newColor.getRed() + ", " + newColor.getGreen() + ", " + newColor.getBlue());
            return this;
        }
    }

    class PropertyTableModel extends AbstractTableModel {
        private static final long serialVersionUID = 1L;

        public int getColumnCount() {
            return 2;
        }

        public int getRowCount() {
            return propList.getSize();
        }

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

        public Object getValueAt(int rowIndex, int columnIndex) {
            Property property = propList.getProperty(rowIndex);
            if (columnIndex == 0)
                return property.getDescription();
            else
                return property.getValue();
        }

        public Property getProperty(int row) {
            return propList.getProperty(row);
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return columnIndex != 0;
        }

        @Override
        public void setValueAt(Object value, int rowIndex, int columnIndex) {
            Property property = propList.getProperty(rowIndex);
            if (columnIndex == 0)
                return;
            else
                property.setValue(value.toString());
        }
    }

    private static final long serialVersionUID = 1L;
    private PropertyList propList;
    protected Class<?> preferencesPackage;
    private URL defaultProperties;
    private JButton cancelButton;
    private JButton okButton;

    public PropertyEditor(JFrame parent, Class<?> preferencesPackage, URL propertiesURL, String title) {
        super(parent, title, true);
        this.preferencesPackage = preferencesPackage;
        this.defaultProperties = propertiesURL;
        setResizable(false);
        loadDefaultProperties();
        updateWithPrefs();
        final JTable table = createTable();
        FormLayout layout = new FormLayout("3dlu, pref, 3dlu", "3dlu, fill:pref, 3dlu, pref, 3dlu");
        PanelBuilder builder = new PanelBuilder(layout);
        CellConstraints constraints = new CellConstraints();
        builder.add(new JScrollPane(table), constraints.xy(2, 2));
        okButton = UIUtils.createOKButton();
        cancelButton = UIUtils.createCancelButton();
        JButton resetButton = UIUtils.createLoadDefaultsButton();
        okButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                savePreferences();
                dispose();
            }

            private void savePreferences() {
                Preferences prefs = Preferences.userNodeForPackage(PropertyEditor.this.preferencesPackage);
                List<Property> list = propList.getProperties();
                for (Property property : list) {
                    prefs.put(property.getKey(), property.getValue());
                }
            }
        });
        cancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
        resetButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                loadDefaultProperties();
                ((PropertyTableModel) table.getModel()).fireTableDataChanged();
            }
        });
        JPanel bbuilder = ButtonBarFactory.buildRightAlignedBar(okButton, cancelButton, resetButton);
        bbuilder.setBackground(new Color(255, 255, 255));
        builder.getPanel().setBackground(new Color(255, 255, 255));
        builder.add(bbuilder, constraints.xy(2, 4));
        getContentPane().add(builder.getPanel());
        pack();
        Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
        setLocation((size.width - getSize().width) / 2, (size.height - getSize().height) / 2);
    }

    private void updateWithPrefs() {
        Preferences prefs = Preferences.userNodeForPackage(preferencesPackage);
        List<Property> list = propList.getProperties();
        for (Property property : list) {
            String val = prefs.get(property.getKey(), null);
            if (val != null)
                property.setValue(val);
        }
    }

    private JTable createTable() {
        JTable table = new PropertyTable(new PropertyTableModel());
        return table;
    }

    private void loadDefaultProperties() {
        propList = new PropertyList();
        Properties props = new Properties();
        try {
            props.load(defaultProperties.openStream());
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        SortedSet<Entry<Object, Object>> sortedSet = new TreeSet<Entry<Object, Object>>(new Comparator<Entry<Object, Object>>() {
            public int compare(Entry<Object, Object> o1, Entry<Object, Object> o2) {
                String key1 = (String) o1.getKey();
                String key2 = (String) o2.getKey();
                return key1.compareTo(key2);
            }
        });
        sortedSet.addAll(props.entrySet());
        for (Entry<Object, Object> prop : sortedSet) {
            String key = (String) prop.getKey();
            String value = (String) prop.getValue();
            if (key.startsWith("view.style"))
                continue;
            if (value.equals("true") || value.equals("false")) {
                propList.addBooleanProperty(key, key, Boolean.parseBoolean(value));
                continue;
            } else if (value.startsWith("#")) {
                try {
                    Color color = Color.decode(value);
                    propList.addColorProperty(key, key, color);
                    continue;
                } catch (NumberFormatException e) {
                }
            }
            try {
                int i = Integer.parseInt(value);
                propList.addIntegerProperty(key, key, i);
                continue;
            } catch (NumberFormatException e) {
            }
            if (key.endsWith(".font")) {
                Font font2 = Font.decode(value);
                if (font2 == null)
                    font2 = Font.decode(null);
                propList.addFontProperty(key, key, font2);
            } else if (key.equals("buffer.wrap")) {
                propList.addSelectionProperty(key, key, value, new String[] { "none", "soft", "hard" });
            } else if (key.equals("view.gutter.numberAlignment")) {
                propList.addSelectionProperty(key, key, value, new String[] { "left", "center", "right" });
            } else if (key.equals("buffer.folding")) {
                propList.addSelectionProperty(key, key, value, new String[] { "explicit", "indent", "none" });
            } else if (key.equals("view.antiAlias")) {
                propList.addSelectionProperty(key, key, value, new String[] { "none", "standard", "subpixel" });
            } else if (key.endsWith(".fontstyle")) {
                propList.addSelectionProperty(key, key, value, new String[] { "normal", "bold", "italic", "bold-italic" });
            } else {
                propList.addStringProperty(key, key, value);
            }
        }
    }

    @Override public JButton getOKButton() {
        return okButton;
    }

    @Override public JButton getCloseButton() {
        return cancelButton;
    }
}
TOP

Related Classes of net.sourceforge.marathon.util.PropertyEditor$ColorEditor

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.