jasima_gui.dialogs.streamEditor.DetailsPageBase.java Source code

Java tutorial

Introduction

Here is the source code for jasima_gui.dialogs.streamEditor.DetailsPageBase.java

Source

/*******************************************************************************
 * Copyright (c) 2010-2015 Torsten Hildebrandt and jasima contributors
 *
 * This file is part of jasima, v1.2.
 *
 * jasima is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jasima 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with jasima.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package jasima_gui.dialogs.streamEditor;

import jasima_gui.dialogs.streamEditor.util.ConstraintValidator;
import jasima_gui.dialogs.streamEditor.util.DoubleListProperty;
import jasima_gui.dialogs.streamEditor.util.DoubleProperty;
import jasima_gui.dialogs.streamEditor.util.IntegerListProperty;
import jasima_gui.dialogs.streamEditor.util.IntegerProperty;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;

import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.IDetailsPage;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.IMessage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

public abstract class DetailsPageBase implements IDetailsPage {

    public static class FormParseError {
        public FormParseError(String errorMsg, String hoverText, Exception reason) {
            super();
            this.errorMsg = errorMsg;
            this.hoverText = hoverText;
            this.reason = reason;
        }

        public final String errorMsg;
        public final String hoverText;
        public final Exception reason;
    }

    private HashMap<String, FormProperty> props;

    private MasterBlock master;
    protected IManagedForm mForm;
    protected FormToolkit toolkit;
    private Composite client;

    protected Object input;
    private boolean isStale;

    private ConstraintValidator[] constraints = new ConstraintValidator[] {};

    boolean disableModifyEvent = false;

    protected Section section;

    public DetailsPageBase() {
        super();
        props = new LinkedHashMap<String, FormProperty>();
    }

    public FormProperty addDoubleProperty(String beanPropertyName, String labelText) {
        return addProperty(new DoubleProperty(this, beanPropertyName, labelText));
    }

    public FormProperty addDoubleListProperty(String beanPropertyName, String labelText) {
        return addProperty(new DoubleListProperty(this, beanPropertyName, labelText));
    }

    public FormProperty addIntegerListProperty(String beanPropertyName, String labelText) {
        return addProperty(new IntegerListProperty(this, beanPropertyName, labelText));
    }

    public FormProperty addIntegerProperty(String beanPropertyName, String labelText) {
        return addProperty(new IntegerProperty(this, beanPropertyName, labelText));
    }

    public FormProperty addProperty(FormProperty p) {
        props.put(p.propertyName, p);
        return p;
    }

    public FormProperty getProperty(String propName) {
        return props.get(propName);
    }

    @Override
    public void initialize(IManagedForm form) {
        this.mForm = form;
        this.toolkit = mForm.getToolkit();

        isStale = true;
    }

    @Override
    public void selectionChanged(IFormPart part, ISelection selection) {
        IStructuredSelection ssel = (IStructuredSelection) selection;
        if (ssel.size() == 1) {
            setFormInput(ssel.getFirstElement());
            assert getInputType().equals(input.getClass().getName());
        } else
            setFormInput(null);
    }

    @Override
    public void createContents(Composite parent) {
        parent.setLayout(new FillLayout());

        section = toolkit.createSection(parent, Section.DESCRIPTION | Section.TITLE_BAR);
        section.setText(getTitle());
        section.setDescription(getDescription());
        toolkit.createSeparator(section, SWT.NULL);

        client = toolkit.createComposite(section, SWT.WRAP);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginWidth = layout.marginHeight = 2;
        client.setLayout(layout);

        for (FormProperty p : props.values()) {
            p.createWidget();
        }

        section.setClient(client);
        toolkit.paintBordersFor(client);
    }

    protected abstract String getDescription();

    protected abstract String getTitle();

    public abstract String getInputType();

    private void checkPropDescriptor(PropertyDescriptor pd) {
        FormProperty p = props.get(pd.getName());
        if (p != null) {
            p.beanDescriptor = pd;
        }
    }

    @Override
    public boolean setFormInput(Object input) {
        if (this.input != input) {
            this.input = input;
            isStale = true;

            // find getter/setter methods for each property
            BeanInfo bi;
            try {
                bi = Introspector.getBeanInfo(input.getClass());
                PropertyDescriptor[] propDesc = bi.getPropertyDescriptors();
                for (PropertyDescriptor pd : propDesc) {
                    checkPropDescriptor(pd);
                }
            } catch (IntrospectionException e) {
                throw new RuntimeException(e);
            }
        }

        // refresh gui
        disableModifyEvent = true;
        try {
            refresh();
        } finally {
            disableModifyEvent = false;

            updateModel();
        }

        return false;
    }

    protected void updateModel() {
        // force validating constraints
        for (FormProperty p : props.values()) {
            p.updateModel();
        }
    }

    @Override
    public void dispose() {
    }

    @Override
    public boolean isDirty() {
        boolean isDirty = false;
        for (FormProperty p : props.values()) {
            if (p.isDirty) {
                isDirty = true;
                break;
            }
        }

        return isDirty;
    }

    @Override
    public void commit(boolean onSave) {
        for (FormProperty p : props.values()) {
            if (p.error == null && p.isDirty) {
                // call setter
                try {
                    p.beanDescriptor.getWriteMethod().invoke(input, p.getValue());
                    p.isDirty = false;
                } catch (Exception shouldNotOccur) {
                    throw new RuntimeException(shouldNotOccur);
                }
            }
        }
    }

    @Override
    public void setFocus() {
    }

    @Override
    public boolean isStale() {
        return isStale;
    }

    @Override
    public void refresh() {
        isStale = false;
        if (input == null)
            return;

        for (FormProperty p : props.values()) {
            try {
                // get current value
                Object v = p.beanDescriptor.getReadMethod().invoke(input);
                p.setValue(v);

                p.updateGui();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    public boolean checkGlobalConstraints() {
        hideError();

        // any local error?
        boolean anyError = false;
        for (FormProperty p : props.values()) {
            ControlDecoration deco = p.getDecoration();
            if (p.error != null) {
                anyError = true;
                deco.setDescriptionText(p.error.errorMsg);
                deco.show();
                deco.showHoverText(p.error.hoverText);
            } else {
                deco.setDescriptionText(null);
                deco.hide();
            }
        }

        if (!anyError) {
            // check global constraints
            ArrayList<ConstraintValidator> failed = new ArrayList<ConstraintValidator>();
            for (ConstraintValidator v : getConstraints()) {
                if (!v.isValid())
                    failed.add(v);
            }

            // report errors
            if (failed.size() > 0) {
                anyError = true;
                String mainMsg = failed.size() == 1 ? "1 error" : String.format("%d errors", failed.size());
                master.getManagedForm().getForm().setMessage(mainMsg, IMessageProvider.ERROR,
                        failed.toArray(new IMessage[failed.size()]));

                // show error decoration on causing properties
                for (ConstraintValidator cv : failed) {
                    for (FormProperty p : cv.dependsOn()) {
                        ControlDecoration deco = p.getDecoration();
                        String s = deco.getDescriptionText();
                        if (s != null)
                            s += "\n" + cv.getMessage();
                        else
                            s = cv.getMessage();
                        deco.setDescriptionText(s);
                        deco.show();
                    }
                }
            } else {
                anyError = false;
            }
        }

        master.okButton.setEnabled(!anyError);

        return !anyError;
    }

    private void hideError() {
        master.getManagedForm().getForm().setMessage(null, IMessageProvider.NONE);
    }

    public MasterBlock getMaster() {
        return master;
    }

    public void setMaster(MasterBlock master) {
        this.master = master;
    }

    public Composite getClient() {
        return client;
    }

    public ConstraintValidator[] getConstraints() {
        return constraints;
    }

    public void setConstraints(ConstraintValidator[] constraints) {
        this.constraints = constraints;
    }

    public void addConstraint(ConstraintValidator v) {
        ArrayList<ConstraintValidator> l = new ArrayList<ConstraintValidator>();
        if (constraints != null) {
            l.addAll(Arrays.asList(constraints));
        }
        l.add(v);
        constraints = l.toArray(new ConstraintValidator[l.size()]);
    }

}