com.hp.alm.ali.idea.ui.editor.BaseEditor.java Source code

Java tutorial

Introduction

Here is the source code for com.hp.alm.ali.idea.ui.editor.BaseEditor.java

Source

/*
 * Copyright 2013 Hewlett-Packard Development Company, L.P
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hp.alm.ali.idea.ui.editor;

import com.hp.alm.ali.idea.services.EntityService;
import com.hp.alm.ali.idea.ui.GridBagSplitter;
import com.hp.alm.ali.idea.ui.ScrollablePanel;
import com.hp.alm.ali.idea.ui.dialog.MyDialog;
import com.hp.alm.ali.idea.entity.EntityEditManager;
import com.hp.alm.ali.idea.ui.editor.field.EditableField;
import com.hp.alm.ali.idea.ui.editor.field.EditableFieldListener;
import com.hp.alm.ali.idea.model.Entity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.ui.UIUtil;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;

public abstract class BaseEditor extends MyDialog {

    private GridBagConstraints gbc;
    protected JPanel gridPanel;
    protected JPanel gridFooter;

    protected Map<String, EditableField> fields;
    private int verticalExpandCount = 0;

    private JButton save;

    protected Project project;
    protected Entity entity;
    protected SaveHandler saveHandler;

    public BaseEditor(Project project, String title, Entity entity, SaveHandler saveHandler) {
        super(project, title, false, true, Arrays.asList(Button.Save, Button.Cancel));
        this.project = project;
        this.entity = entity;
        this.saveHandler = saveHandler;

        fields = new LinkedHashMap<String, EditableField>();

        gridPanel = new ScrollablePanel(new GridBagLayout()) {
            public Dimension getPreferredSize() {
                // allocate room for expandable content
                Dimension dim = super.getPreferredSize();
                dim.height += verticalExpandCount * 100;
                return dim;
            }
        };
        gridFooter = new JPanel();

        JPanel panel = new ScrollablePanel(new BorderLayout());
        panel.setBorder(new EmptyBorder(10, 10, 10, 10));
        panel.add(gridPanel, BorderLayout.CENTER);
        panel.add(gridFooter, BorderLayout.SOUTH);
        getContentPane().add(new JBScrollPane(panel, JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER));

        save = getButton(Button.Save);
        save.setEnabled(false);
        getRootPane().setDefaultButton(save);

        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    }

    public void execute() {
        final EntityEditManager entityEditManager = project.getComponent(EntityEditManager.class);
        ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
            @Override
            public void run() {
                final Entity locked = entityEditManager.startEditing(entity);
                if (locked != null) {
                    BaseEditor.this.entity = locked;

                    beforeUpdate();
                    UIUtil.invokeLaterIfNeeded(new Runnable() {
                        @Override
                        public void run() {
                            // reset and update UI
                            fields.clear();
                            gridPanel.removeAll();
                            gbc = new GridBagConstraints();
                            gbc.gridx = 0;
                            gbc.gridy = 0;
                            gbc.insets = new Insets(5, 5, 5, 5);
                            gbc.anchor = GridBagConstraints.NORTH;
                            gbc.fill = GridBagConstraints.BOTH;
                            update();

                            save.addPropertyChangeListener("enabled", new PropertyChangeListener() {
                                @Override
                                public void propertyChange(PropertyChangeEvent evt) {
                                    entityEditManager.setEntityDirty(locked,
                                            Boolean.TRUE.equals(evt.getNewValue()));
                                }
                            });
                            addWindowListener(new WindowAdapter() {
                                @Override
                                public void windowClosed(WindowEvent e) {
                                    if (!project.isDisposed()) {
                                        entityEditManager.stopEditing(locked);
                                    }
                                }

                                @Override
                                public void windowClosing(WindowEvent e) {
                                    close(false);
                                }
                            });
                            setVisible(true);
                        }
                    });
                }
            }
        });
    }

    public Entity getModified() {
        Entity ret = new Entity(entity.getType(), entity.getId());
        for (String column : fields.keySet()) {
            EditableField ef = fields.get(column);
            if (entity.getId() <= 0 || ef.hasChanged()) {
                ret.setProperty(column, ef.getValue());
            }
        }
        return ret;
    }

    protected void buttonPerformed(Button button) {
        super.buttonPerformed(button);

        switch (button) {
        case Save:
            StringBuffer message = new StringBuffer();
            String error = validate(message);
            if (error != null) {
                Messages.showErrorDialog(message.toString(), error);
                return;
            }
            if (saveHandler.save(getModified(), entity)) {
                close(true);
            }
        }
    }

    protected void packAndPosition() {
        pack();
        centerOnOwner();
    }

    private void updateSave() {
        for (EditableField field : fields.values()) {
            if (field.isRequired() && field.getValue().isEmpty()) {
                save.setEnabled(false);
                return;
            }
        }
        for (EditableField field : fields.values()) {
            if (field.hasChanged()) {
                save.setEnabled(true);
                return;
            }
        }
        save.setEnabled(false);
    }

    public String validate(StringBuffer message) {
        return null;
    }

    /**
     * Called before actual {@link #update()} outside dispatch thread.
     */
    public void beforeUpdate() {
    }

    public abstract void update();

    public Dimension getPreferredSize() {
        Dimension dim = super.getPreferredSize();
        dim.width = Math.min(dim.width, 800);
        dim.height = Math.min(dim.height, 600);
        return dim;
    }

    public void addField(String name, EditableField field) {
        addField(name, field, false);
    }

    public void addField(String name, EditableField field, boolean verticalExpand) {
        fields.put(name, field);

        final JLabel label = makeLabel(field.getLabel());
        gbc.weightx = 0;
        gbc.weighty = 0;

        if (verticalExpand) {
            if (verticalExpandCount++ > 0) {
                // at least two expandable fields: allow to reallocate space
                GridBagSplitter gridBagSplitter = new GridBagSplitter(this, gridPanel, gbc.gridy) {
                    protected Component getComponentForRow(int n) {
                        return gridPanel.getComponent(n * 2 + 1);
                    }
                };

                gbc.insets = new Insets(0, 0, 0, 0);
                // simplify mapping in gridBagSplitter by inserting dummy component
                gridPanel.add(new JPanel(), gbc);
                gbc.gridx++;
                gridPanel.add(gridBagSplitter.getComponent(), gbc);
                gbc.gridy++;
                gbc.gridx = 0;
                gbc.insets = new Insets(5, 5, 5, 5);
            }
        }

        gridPanel.add(label, gbc);
        gbc.gridx++;

        Component comp = field.getComponent();
        gbc.weightx = 1;
        gbc.weighty = verticalExpand ? 1 : 0;
        gridPanel.add(comp, gbc);
        gbc.gridx = 0;
        gbc.gridy++;

        if (field.isDisableDefaultAction()) {
            comp.addFocusListener(new FocusListener() {
                JButton defaultButton;

                public void focusGained(FocusEvent focusEvent) {
                    defaultButton = getRootPane().getDefaultButton();
                    getRootPane().setDefaultButton(null);
                }

                public void focusLost(FocusEvent focusEvent) {
                    getRootPane().setDefaultButton(defaultButton);
                }
            });
        }

        field.addUpdateListener(new EditableFieldListener() {
            public void updated(EditableField field) {
                makeBold(label, field.hasChanged());
                if (field.isRequired() && field.getValue().isEmpty()) {
                    label.setForeground(Color.RED);
                } else {
                    label.setForeground(UIManager.getDefaults().getColor("Label.foreground"));
                }
                updateSave();
            }
        });

        if (field.isRequired() && field.getValue().isEmpty()) {
            label.setForeground(Color.RED);
        }
    }

    public EditableField getField(String name) {
        return fields.get(name);
    }

    private JLabel makeLabel(String text) {
        JLabel label = new JLabel(text);
        // make room for bold text (avoid re-layout)
        Dimension dim = label.getPreferredSize();
        dim.width = (int) (dim.width * 1.2f);
        label.setPreferredSize(dim);
        label.setMinimumSize(dim);
        label.setVerticalAlignment(JLabel.TOP);
        return label;
    }

    public static boolean makeBold(JLabel label, boolean bold) {
        Font f = label.getFont();
        if (bold) {
            label.setFont(f.deriveFont(f.getStyle() | Font.BOLD));
        } else {
            label.setFont(f.deriveFont(f.getStyle() & ~Font.BOLD));
        }
        return bold;
    }

    public static interface SaveHandler {

        boolean save(Entity modified, Entity base);

    }

    public static abstract class BaseHandler implements SaveHandler {

        protected EntityService entityService;

        public BaseHandler(Project project) {
            entityService = project.getComponent(EntityService.class);
        }
    }
}