eu.esdihumboldt.hale.ui.style.dialog.RuleStylePage.java Source code

Java tutorial

Introduction

Here is the source code for eu.esdihumboldt.hale.ui.style.dialog.RuleStylePage.java

Source

/*
 * Copyright (c) 2012 Data Harmonisation Panel
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     HUMBOLDT EU Integrated Project #030962
 *     Data Harmonisation Panel <http://www.dhpanel.eu>
 */
package eu.esdihumboldt.hale.ui.style.dialog;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.LineSymbolizer;
import org.geotools.styling.PointSymbolizer;
import org.geotools.styling.PolygonSymbolizer;
import org.geotools.styling.Rule;
import org.geotools.styling.Style;
import org.geotools.styling.StyleBuilder;
import org.geotools.styling.Symbolizer;
import org.opengis.filter.Filter;

import de.fhg.igd.slf4jplus.ALogger;
import de.fhg.igd.slf4jplus.ALoggerFactory;
import eu.esdihumboldt.hale.common.schema.model.TypeDefinition;
import eu.esdihumboldt.hale.ui.style.StyleHelper;
import eu.esdihumboldt.hale.ui.style.editors.Editor;
import eu.esdihumboldt.hale.ui.style.editors.EditorFactory;
import eu.esdihumboldt.hale.ui.style.editors.LineSymbolizerEditor;
import eu.esdihumboldt.hale.ui.style.editors.PointSymbolizerEditor;
import eu.esdihumboldt.hale.ui.style.editors.PolygonSymbolizerEditor;
import eu.esdihumboldt.hale.ui.style.editors.RuleEditor;
import eu.esdihumboldt.hale.ui.style.internal.InstanceStylePlugin;
import eu.esdihumboldt.hale.ui.style.internal.Messages;

/**
 * Rule based style editor page
 * 
 * @author Simon Templer
 * @partner 01 / Fraunhofer Institute for Computer Graphics Research
 */
public class RuleStylePage extends FeatureStylePage {

    /**
     * {@link Rule} list item
     */
    private class RuleItem {

        private Rule rule;

        /**
         * Creates a new rule item
         * 
         * @param rule the rule
         */
        public RuleItem(Rule rule) {
            this.rule = rule;
        }

        /**
         * Get the item's rule
         * 
         * @return the rule
         */
        public Rule getRule() {
            return rule;
        }

        /**
         * Set the item's rule
         * 
         * @param rule the rule to set
         */
        public void setRule(Rule rule) {
            this.rule = rule;
        }

        /**
         * @see Object#toString()
         */
        @Override
        public String toString() {
            String name = getRule().getName();
            if (name == null || name.isEmpty()) {
                return Messages.RuleStylePage_Rule + rules.indexOf(this);
            } else {
                return name;
            }
        }

    }

    private static final StyleBuilder styleBuilder = new StyleBuilder();

    private static Image addImage = null;

    private static Image removeImage = null;

    private static Image renameImage = null;

    private static Image upImage = null;

    private static Image downImage = null;

    private Button addButton;

    private Button removeButton;

    private Button renameButton;

    private Button upButton;

    private Button downButton;

    private Composite editorArea;

    private ListViewer listViewer;

    private int currentIndex = -1;

    private Editor<Rule> currentEditor = null;

    private List<RuleItem> rules;

    private boolean changed = false;

    private static final ALogger log = ALoggerFactory.getLogger(RuleStylePage.class);

    /**
     * Creates a new editor page
     * 
     * @param parent the parent dialog
     */
    public RuleStylePage(FeatureStyleDialog parent) {
        super(parent, Messages.RuleStylePage_SuperTitle);

        if (addImage == null) {
            addImage = InstanceStylePlugin.getImageDescriptor("/icons/add.gif").createImage(); //$NON-NLS-1$
        }

        if (removeImage == null) {
            removeImage = InstanceStylePlugin.getImageDescriptor("/icons/remove.gif").createImage(); //$NON-NLS-1$
        }

        if (renameImage == null) {
            renameImage = InstanceStylePlugin.getImageDescriptor("/icons/rename.gif").createImage(); //$NON-NLS-1$
        }

        if (upImage == null) {
            upImage = InstanceStylePlugin.getImageDescriptor("/icons/arrow_up.gif").createImage(); //$NON-NLS-1$
        }

        if (downImage == null) {
            downImage = InstanceStylePlugin.getImageDescriptor("/icons/arrow_down.gif").createImage(); //$NON-NLS-1$
        }
    }

    /**
     * @see FeatureStylePage#getStyle(boolean)
     */
    @Override
    public Style getStyle(boolean force) throws Exception {
        updateCurrentRule();

        if (force || changed) {
            Rule[] ruleArray = new Rule[rules.size()];
            for (int i = 0; i < rules.size(); i++) {
                Rule rule = rules.get(i).getRule();

                // set else filter
                rule.setIsElseFilter(rule.getFilter() == null);

                // TODO other rule manipulation?

                ruleArray[i] = rule;
            }

            // create style
            FeatureTypeStyle fts = styleBuilder.createFeatureTypeStyle("Feature", ruleArray); //$NON-NLS-1$
            Style style = styleBuilder.createStyle();
            style.featureTypeStyles().add(fts);
            return style;
        } else {
            return null;
        }
    }

    /**
     * Update the {@link Rule} whose editor is currently open
     * 
     * @throws Exception if an error occurs during the update
     */
    private void updateCurrentRule() throws Exception {
        if (currentEditor != null && currentEditor.isChanged()) {
            Rule rule = currentEditor.getValue();

            if (rule != null) {
                rules.get(currentIndex).setRule(rule);

                changed = true;
            }
        }
    }

    /**
     * @see IDialogPage#createControl(Composite)
     */
    @Override
    public void createControl(Composite parent) {
        changed = false;

        Composite page = new Composite(parent, SWT.NONE);
        page.setLayout(new GridLayout(2, false));

        // DISABLED - this method seems to change the rule order - Rule[]
        // ruleArray = SLD.rules(getParent().getStyle());
        // use list instead:
        List<Rule> ruleList;
        try {
            ruleList = getParent().getStyle().featureTypeStyles().get(0).rules();
        } catch (Exception e) {
            ruleList = new ArrayList<Rule>();
        }

        // init index
        if (ruleList.size() > 0) {
            currentIndex = 0;
        } else {
            currentIndex = -1;
        }

        currentEditor = null;

        // populate rule map
        rules = new ArrayList<RuleItem>(ruleList.size() + 5);
        for (int i = 0; i < ruleList.size(); i++) {
            Rule rule = ruleList.get(i);
            if (rule != null) {
                rules.add(new RuleItem(rule));
            }
        }

        // rule list
        Composite ruleArea = new Composite(page, SWT.NONE);
        ruleArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
        GridLayout leftLayout = new GridLayout(5, true);
        leftLayout.horizontalSpacing = 1;
        leftLayout.verticalSpacing = 1;
        ruleArea.setLayout(leftLayout);

        // label
        Label rulesLabel = new Label(ruleArea, SWT.NONE);
        rulesLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 5, 1));
        rulesLabel.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT));
        rulesLabel.setText(Messages.RuleStylePage_RuleLabelText);

        // viewer
        listViewer = new ListViewer(ruleArea);
        listViewer.getList().setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true, 5, 1));
        listViewer.setContentProvider(new IStructuredContentProvider() {

            @Override
            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
                // ignore
            }

            @Override
            public void dispose() {
                // ignore
            }

            @SuppressWarnings("unchecked")
            @Override
            public Object[] getElements(Object inputElement) {
                try {
                    List<RuleItem> rules = (List<RuleItem>) inputElement;
                    return rules.toArray();
                } catch (Exception e) {
                    return null;
                }
            }
        });
        listViewer.setInput(rules);

        if (currentIndex >= 0 && currentIndex < rules.size()) {
            listViewer.setSelection(new StructuredSelection(rules.get(currentIndex)));
        }

        listViewer.addSelectionChangedListener(new ISelectionChangedListener() {

            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                RuleItem item = (RuleItem) ((IStructuredSelection) event.getSelection()).getFirstElement();

                int newIndex = rules.indexOf(item);

                if (currentIndex != newIndex) {
                    try {
                        updateCurrentRule();
                    } catch (Exception e) {
                        log.userError("Invalid editor state, could not update rule.", e);
                        return;
                    }
                    currentIndex = newIndex;
                    updateEditor();
                }
            }
        });

        // buttons
        addButton = new Button(ruleArea, SWT.PUSH);
        addButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
        addButton.setImage(addImage);
        addButton.addSelectionListener(new SelectionListener() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                addRule();
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                // ignore
            }
        });
        addButton.setToolTipText(Messages.RuleStylePage_AddRuleButtonToolTippText);

        removeButton = new Button(ruleArea, SWT.PUSH);
        removeButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
        removeButton.setImage(removeImage);
        removeButton.addSelectionListener(new SelectionListener() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                removeCurrentRule();
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                // ignore
            }
        });
        removeButton.setToolTipText(Messages.RuleStylePage_RemoveRuleButtonToolTippText);

        upButton = new Button(ruleArea, SWT.PUSH);
        upButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
        upButton.setImage(upImage);
        upButton.addSelectionListener(new SelectionListener() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                moveCurrentRuleUp();
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                // ignore
            }
        });
        upButton.setToolTipText(Messages.RuleStylePage_UpRuleButtonToolTippText);

        downButton = new Button(ruleArea, SWT.PUSH);
        downButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
        downButton.setImage(downImage);
        downButton.addSelectionListener(new SelectionListener() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                moveCurrentRuleDown();
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                // ignore
            }
        });
        downButton.setToolTipText(Messages.RuleStylePage_DownRuleButtonToolTippText);

        renameButton = new Button(ruleArea, SWT.PUSH);
        renameButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
        renameButton.setImage(renameImage);
        renameButton.addSelectionListener(new SelectionListener() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                renameCurrentRule();
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                // ignore
            }
        });
        renameButton.setToolTipText(Messages.RuleStylePage_RenameRuleButtonToolTippText);

        // editor area
        editorArea = new Composite(page, SWT.NONE);
        editorArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        editorArea.setLayout(new FillLayout());

        setControl(page);

        updateEditor();
    }

    /**
     * Move the current rule up
     */
    protected void moveCurrentRuleUp() {
        if (currentIndex >= 1 && currentIndex < rules.size()) {
            try {
                updateCurrentRule();
            } catch (Exception e) {
                log.userError("Invalid editor state, could not update rule.", e);
                return;
            }

            RuleItem item1 = rules.get(currentIndex);
            Rule temp = item1.getRule();

            RuleItem item2 = rules.get(--currentIndex);
            item1.setRule(item2.getRule());
            item2.setRule(temp);

            listViewer.refresh(true);
            listViewer.setSelection(new StructuredSelection(item2));
            updateEditor();

            changed = true;
        }
    }

    /**
     * Move the current rule down
     */
    protected void moveCurrentRuleDown() {
        if (currentIndex >= 0 && currentIndex < rules.size() - 1) {
            try {
                updateCurrentRule();
            } catch (Exception e) {
                log.userError("Invalid editor state, could not update rule.", e);
                return;
            }

            RuleItem item1 = rules.get(currentIndex);
            Rule temp = item1.getRule();

            RuleItem item2 = rules.get(++currentIndex);
            item1.setRule(item2.getRule());
            item2.setRule(temp);

            listViewer.refresh(true);
            listViewer.setSelection(new StructuredSelection(item2));
            updateEditor();

            changed = true;
        }
    }

    /**
     * Rename the current rule
     */
    protected void renameCurrentRule() {
        if (currentIndex >= 0 && currentIndex < rules.size()) {
            RuleItem item = rules.get(currentIndex);
            Rule rule = item.getRule();

            InputDialog dlg = new InputDialog(getShell(), Messages.RuleStylePage_InputDialogTitle,
                    Messages.RuleStylePage_InputDialogDescription, rule.getName(), null);

            if (dlg.open() == InputDialog.OK) {
                rule.setName(dlg.getValue());
                listViewer.update(item, null);

                changed = true;
            }
        }
    }

    /**
     * Remove the current rule
     */
    protected void removeCurrentRule() {
        if (currentIndex >= 0 && currentIndex < rules.size()) {
            RuleItem item = rules.remove(currentIndex);
            currentIndex--;
            listViewer.remove(item);
            listViewer.refresh(true);
            updateEditor();

            changed = true;
        }
    }

    /**
     * Add a new {@link Rule}
     */
    protected void addRule() {
        SymbolizerDialog symDlg = new SymbolizerDialog(getShell());
        symDlg.open();
        Symbolizer symbolizer = symDlg.getSymbolizer();

        if (symbolizer != null) {
            Rule rule = styleBuilder.createRule(symbolizer);
            RuleItem item = new RuleItem(rule);
            rules.add(item);
            listViewer.add(item);

            updateButtonState();

            changed = true;
        }
    }

    /**
     * Display the editor for the current rule in the editor area
     */
    private void updateEditor() {
        if (currentEditor != null) {
            currentEditor.getControl().dispose();
        }

        if (currentIndex >= 0 && currentIndex < rules.size()) {
            Rule rule = rules.get(currentIndex).getRule();

            currentEditor = createEditor(rule, editorArea);
            editorArea.layout(true);
        }

        updateButtonState();
    }

    /**
     * Update the button states
     */
    private void updateButtonState() {
        boolean valid = currentIndex >= 0 && currentIndex < rules.size();

        removeButton.setEnabled(valid);
        renameButton.setEnabled(valid);

        upButton.setEnabled(valid && currentIndex >= 1);
        downButton.setEnabled(valid && currentIndex < rules.size() - 1);
    }

    /**
     * Create a rule editor
     * 
     * @param rule the rule
     * @param parent the parent composite
     * 
     * @return the {@link Rule} editor
     */
    private Editor<Rule> createEditor(Rule rule, Composite parent) {
        TypeDefinition type = getParent().getType();
        Filter filter = rule.getFilter();

        Symbolizer symbolizer = null;
        Symbolizer[] symbolizers = rule.getSymbolizers();

        if (symbolizers != null && symbolizers.length > 0) {
            symbolizer = symbolizers[0];
        }

        if (symbolizer == null) {
            // fallback if there is no symbolizer defined
            FeatureTypeStyle fts = StyleHelper.getDefaultStyle(type, getParent().getDataSet());
            symbolizer = fts.rules().get(0).getSymbolizers()[0];
        }

        Editor<Rule> editor;

        if (symbolizer instanceof PointSymbolizer) {
            editor = createEditor(parent, type, filter, PointSymbolizer.class, (PointSymbolizer) symbolizer);
        } else if (symbolizer instanceof PolygonSymbolizer) {
            editor = createEditor(parent, type, filter, PolygonSymbolizer.class, (PolygonSymbolizer) symbolizer);
        } else { // TODO support other symbolizers
                 // default: LineSymbolizer
            editor = createEditor(parent, type, filter, LineSymbolizer.class, (LineSymbolizer) symbolizer);
        }

        return editor;
    }

    private static <T extends Symbolizer> RuleEditor<?> createEditor(Composite parent, TypeDefinition ft,
            Filter filter, Class<T> type, T symbolizer) {

        if (PointSymbolizer.class.isAssignableFrom(type)) {
            return new RuleEditor<PointSymbolizer>(parent, ft, filter, PointSymbolizer.class,
                    (PointSymbolizer) symbolizer, new EditorFactory<PointSymbolizer>() {

                        @Override
                        public Editor<PointSymbolizer> createEditor(Composite parent, PointSymbolizer value) {
                            return new PointSymbolizerEditor(parent, value);
                        }
                    });
        } else if (PolygonSymbolizer.class.isAssignableFrom(type)) {
            return new RuleEditor<PolygonSymbolizer>(parent, ft, filter, PolygonSymbolizer.class,
                    (PolygonSymbolizer) symbolizer, new EditorFactory<PolygonSymbolizer>() {

                        @Override
                        public Editor<PolygonSymbolizer> createEditor(Composite parent, PolygonSymbolizer value) {
                            return new PolygonSymbolizerEditor(parent, value);
                        }
                    });
        } else {
            return new RuleEditor<LineSymbolizer>(parent, ft, filter, LineSymbolizer.class,
                    (LineSymbolizer) symbolizer, new EditorFactory<LineSymbolizer>() {

                        @Override
                        public Editor<LineSymbolizer> createEditor(Composite parent, LineSymbolizer value) {
                            return new LineSymbolizerEditor(parent, value);
                        }
                    });
        }
        // FIXME Does not work properly
    }

}