annis.gui.querybuilder.NodeWindow.java Source code

Java tutorial

Introduction

Here is the source code for annis.gui.querybuilder.NodeWindow.java

Source

/*
 * Copyright 2011 Corpuslinguistic working group Humboldt University Berlin.
 *
 * 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 annis.gui.querybuilder;

import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.LayoutEvents.LayoutClickEvent;
import com.vaadin.event.LayoutEvents.LayoutClickListener;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.ThemeResource;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.AbstractSelect.NewItemHandler;
import com.vaadin.ui.AbstractTextField;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 *
 * @author thomas
 */
public class NodeWindow extends Panel implements Button.ClickListener {

    public static final int HEIGHT = 100;
    public static final int WIDTH = 275;

    private static final String[] NODE_OPERATORS = new String[] { "=", "~", "!=", "!~" };

    private final Set<String> annoNames;

    private final TigerQueryBuilderCanvas parent;
    private final Button btEdge;
    private final Button btAdd;
    private final Button btClear;
    private final Button btClose;
    private final Button btMove;
    private final HorizontalLayout toolbar;
    private final List<ConstraintLayout> constraints;
    private boolean prepareEdgeDock;
    private final int id;
    private final VerticalLayout vLayout;

    public NodeWindow(int id, TigerQueryBuilderCanvas parent) {
        this.parent = parent;
        this.id = id;
        this.annoNames = new TreeSet<>();

        for (String a : parent.getAvailableAnnotationNames()) {
            annoNames.add(a.replaceFirst("^[^:]*:", ""));
        }
        constraints = new ArrayList<>();

        setSizeFull();

        // HACK: use our own border since the one from chameleon does not really work
        addStyleName(ValoTheme.PANEL_WELL);
        //addStyleName("border-layout");

        prepareEdgeDock = false;

        vLayout = new VerticalLayout();
        setContent(vLayout);
        vLayout.setWidth("100%");
        vLayout.setHeight("-1px");
        vLayout.setMargin(false);
        vLayout.setSpacing(true);

        toolbar = new HorizontalLayout();
        toolbar.addStyleName("toolbar");
        toolbar.setWidth("100%");
        toolbar.setHeight("-1px");
        toolbar.setMargin(false);
        toolbar.setSpacing(false);
        vLayout.addComponent(toolbar);

        btMove = new Button();
        btMove.setWidth("100%");
        btMove.setIcon(FontAwesome.ARROWS);
        btMove.setDescription("<strong>Move node</strong><br />Click, hold and move mouse to move the node.");
        btMove.addStyleName(ValoTheme.BUTTON_SMALL);
        btMove.addStyleName("drag-source-enabled");
        toolbar.addComponent(btMove);

        btEdge = new Button("Edge");
        btEdge.setIcon(FontAwesome.EXTERNAL_LINK);
        btEdge.addClickListener((Button.ClickListener) this);
        btEdge.addStyleName(ValoTheme.BUTTON_SMALL);
        //btEdge.addStyleName(ChameleonTheme.BUTTON_LINK);
        btEdge.setDescription("<strong>Add Edge</strong><br />" + "To create a new edge between "
                + "two nodes click this button first. " + "Then define a destination node by clicking its \"Dock\" "
                + "button.<br>You can cancel the action by clicking this button " + "(\"Cancel\") again.");
        btEdge.setImmediate(true);
        toolbar.addComponent(btEdge);

        btAdd = new Button("Add");
        btAdd.setIcon(FontAwesome.PLUS);
        btAdd.addStyleName(ValoTheme.BUTTON_SMALL);
        //btAdd.addStyleName(ChameleonTheme.BUTTON_LINK);
        btAdd.addClickListener((Button.ClickListener) this);
        btAdd.setDescription("<strong>Add Node Condition</strong><br />"
                + "Every condition will constraint the node described by this window. "
                + "Most conditions limit the node by defining which annotations and which "
                + "values of the annotation a node needs to have.");
        toolbar.addComponent(btAdd);

        btClear = new Button("Clear");
        btClear.setIcon(FontAwesome.TRASH_O);
        btClear.addStyleName(ValoTheme.BUTTON_SMALL);
        //btClear.addStyleName(ChameleonTheme.BUTTON_LINK);
        btClear.addClickListener((Button.ClickListener) this);
        btClear.setDescription("<strong>Clear All Node Conditions</strong>");
        toolbar.addComponent(btClear);

        btClose = new Button();
        btClose.setIcon(FontAwesome.TIMES_CIRCLE);
        btClose.setDescription("<strong>Close</strong><br />Close this node description window");
        btClose.addStyleName(ValoTheme.BUTTON_SMALL);
        btClose.addClickListener((Button.ClickListener) this);
        toolbar.addComponent(btClose);

        toolbar.setComponentAlignment(btMove, Alignment.TOP_LEFT);
        toolbar.setExpandRatio(btMove, 1.0f);

        toolbar.setComponentAlignment(btEdge, Alignment.TOP_CENTER);
        toolbar.setComponentAlignment(btAdd, Alignment.TOP_CENTER);
        toolbar.setComponentAlignment(btClear, Alignment.TOP_CENTER);
        toolbar.setComponentAlignment(btClose, Alignment.TOP_RIGHT);

    }

    public void setPrepareEdgeDock(boolean prepare) {
        this.prepareEdgeDock = prepare;

        btClear.setVisible(!prepare);
        btClose.setVisible(!prepare);
        btAdd.setVisible(!prepare);
        btMove.setVisible(!prepare);

        if (prepare) {
            btEdge.setCaption("Dock");
            btEdge.setIcon(new ThemeResource("images/pixel.png"));
        } else {
            btEdge.setIcon(FontAwesome.EXTERNAL_LINK);
            btEdge.setCaption("Edge");
        }
    }

    @Override
    public void buttonClick(ClickEvent event) {
        if (event.getButton() == btEdge) {
            if (prepareEdgeDock) {
                setPrepareEdgeDock(false);
                parent.addEdge(this);
            } else {
                parent.prepareAddingEdge(this);
                setPrepareEdgeDock(true);
                btEdge.setIcon(new ThemeResource("images/pixel.png"));
                btEdge.setCaption("Cancel");
            }
        } else if (event.getButton() == btClose) {
            parent.deleteNode(this);
        } else if (event.getButton() == btAdd) {
            ConstraintLayout c = new ConstraintLayout(parent, annoNames);
            c.setWidth("100%");
            c.setHeight("-1px");
            constraints.add(c);
            vLayout.addComponent(c);
            if (parent != null) {
                parent.updateQuery();
            }
        } else if (event.getButton() == btClear) {
            for (ConstraintLayout c : constraints) {
                vLayout.removeComponent(c);
            }
            constraints.clear();
            if (parent != null) {
                parent.updateQuery();
            }
        }
    }

    public Button getBtMove() {
        return btMove;
    }

    public int getID() {
        return id;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final NodeWindow other = (NodeWindow) obj;
        return other.getID() == getID();
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 41 * hash + this.id;
        return hash;
    }

    public List<ConstraintLayout> getConstraints() {
        return constraints;
    }

    public class ConstraintLayout extends HorizontalLayout implements LayoutClickListener, ValueChangeListener {

        private final TigerQueryBuilderCanvas parent;
        private final ComboBox cbName;
        private final ComboBox cbOperator;
        private final TextField txtValue;
        private final Button btDelete;

        public ConstraintLayout(TigerQueryBuilderCanvas parent, Set<String> annoNames) {
            this.parent = parent;

            setWidth("100%");

            cbName = new ComboBox();
            cbName.setNewItemsAllowed(true);
            cbName.setNewItemHandler(new SimpleNewItemHandler(cbName));
            cbName.setImmediate(true);
            cbName.setNullSelectionAllowed(true);
            cbName.setNullSelectionItemId("tok");
            cbName.addItem("tok");
            for (String n : annoNames) {
                cbName.addItem(n);
            }
            cbName.setValue("tok");
            cbName.addListener((ValueChangeListener) this);

            cbOperator = new ComboBox();
            cbOperator.setNewItemsAllowed(false);
            cbOperator.setNullSelectionAllowed(false);
            cbOperator.setImmediate(true);
            for (String o : NODE_OPERATORS) {
                cbOperator.addItem(o);
            }
            cbOperator.setValue(NODE_OPERATORS[0]);
            cbOperator.addListener((ValueChangeListener) this);

            txtValue = new TextField();
            txtValue.setImmediate(true);
            txtValue.addListener((ValueChangeListener) this);

            cbOperator.setWidth("4em");
            cbName.setWidth("100%");
            txtValue.setWidth("100%");

            btDelete = new Button("X");
            btDelete.addStyleName(ValoTheme.BUTTON_LINK);
            btDelete.setDescription("Remove node condition");
            btDelete.addClickListener(new Button.ClickListener() {

                @Override
                public void buttonClick(ClickEvent event) {
                    vLayout.removeComponent(ConstraintLayout.this);
                    constraints.remove(ConstraintLayout.this);
                }
            });

            addComponent(cbName);
            addComponent(cbOperator);
            addComponent(txtValue);
            addComponent(btDelete);

            setExpandRatio(cbName, 0.8f);
            setExpandRatio(txtValue, 1.0f);
            setExpandRatio(btDelete, 0.0f);

            setComponentAlignment(btDelete, Alignment.MIDDLE_RIGHT);

            addLayoutClickListener((LayoutClickListener) this);

        }

        @Override
        public void layoutClick(LayoutClickEvent event) {
            Component c = event.getClickedComponent();
            if (c != null && c instanceof AbstractField) {
                AbstractField f = (AbstractField) c;
                f.focus();
                if (event.isDoubleClick()) {
                    if (f instanceof AbstractTextField) {
                        ((AbstractTextField) f).selectAll();
                    }
                }
            }
        }

        public String getOperator() {
            if (cbOperator.getValue() == null) {
                return "";
            } else {
                return (String) cbOperator.getValue();
            }
        }

        public String getName() {
            if (cbName.getValue() == null) {
                return "tok";
            } else {
                return (String) cbName.getValue();
            }
        }

        public String getValue() {
            if (txtValue.getValue() == null) {
                return "";
            } else {
                return (String) txtValue.getValue();
            }
        }

        @Override
        public void valueChange(ValueChangeEvent event) {
            if (parent != null) {
                parent.updateQuery();
            }
        }

    }

    public static class SimpleNewItemHandler implements NewItemHandler {

        private ComboBox comboBox;

        public SimpleNewItemHandler(ComboBox comboBox) {
            this.comboBox = comboBox;
        }

        @Override
        public void addNewItem(String newItemCaption) {
            if (comboBox != null) {
                comboBox.addItem(newItemCaption);
                comboBox.setValue(newItemCaption);

            }
        }
    }

}