annis.gui.controlpanel.QueryPanel.java Source code

Java tutorial

Introduction

Here is the source code for annis.gui.controlpanel.QueryPanel.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.controlpanel;

import annis.gui.AnnisUI;
import annis.gui.ExportPanel;
import annis.gui.HistoryPanel;
import annis.gui.components.VirtualKeyboardCodeEditor;
import annis.gui.components.codemirror.AqlCodeEditor;
import annis.gui.frequency.FrequencyQueryPanel;
import annis.gui.objects.Query;
import annis.gui.objects.QueryUIState;
import annis.gui.querybuilder.QueryBuilderChooser;
import annis.libgui.Helper;
import annis.libgui.IDGenerator;
import annis.model.AqlParseError;
import annis.model.QueryNode;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.event.ShortcutAction.ModifierKey;
import com.vaadin.event.ShortcutListener;
import com.vaadin.server.ClassResource;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.ThemeResource;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.ListSelect;
import com.vaadin.ui.ProgressBar;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TabSheet.Tab;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme;
import java.util.List;
import org.slf4j.LoggerFactory;
import org.vaadin.hene.popupbutton.PopupButton;

/**
 *
 * @author thomas
 */
public class QueryPanel extends GridLayout implements ValueChangeListener {

    private static final org.slf4j.Logger log = LoggerFactory.getLogger(QueryPanel.class);

    public static final int MAX_HISTORY_MENU_ITEMS = 5;

    // the view name
    public static final String NAME = "query";

    private AqlCodeEditor txtQuery;
    private TextArea txtStatus;
    private Button btShowResult;
    //private Button btShowResultNewTab;
    private PopupButton btHistory;
    private final ListSelect lstHistory;
    private final QueryUIState state;
    private ProgressBar piCount;
    private String lastPublicStatus;
    private Window historyWindow;
    private PopupButton btMoreActions;
    private FrequencyQueryPanel frequencyPanel;

    private final AnnisUI ui;

    private final BeanItemContainer<Query> historyContainer = new BeanItemContainer<>(Query.class);;

    public QueryPanel(final AnnisUI ui) {
        super(4, 5);
        this.ui = ui;

        this.lastPublicStatus = "Welcome to ANNIS! " + "A tutorial is available on the right side.";

        this.state = ui.getQueryState();

        setSpacing(true);
        setMargin(false);

        setRowExpandRatio(0, 1.0f);
        setColumnExpandRatio(0, 0.0f);
        setColumnExpandRatio(1, 0.1f);
        setColumnExpandRatio(2, 0.0f);
        setColumnExpandRatio(3, 0.0f);

        txtQuery = new AqlCodeEditor();
        txtQuery.setPropertyDataSource(state.getAql());
        txtQuery.setInputPrompt("Please enter AQL query");
        txtQuery.addStyleName("query");
        if (ui.getInstanceFont() == null) {
            txtQuery.addStyleName("default-query-font");
            txtQuery.setTextareaStyle("default-query-font");
        } else {
            txtQuery.addStyleName(Helper.CORPUS_FONT);
            txtQuery.setTextareaStyle(Helper.CORPUS_FONT);
        }

        txtQuery.addStyleName("keyboardInput");
        txtQuery.setWidth("100%");
        txtQuery.setHeight(15f, Unit.EM);
        txtQuery.setTextChangeTimeout(500);

        final VirtualKeyboardCodeEditor virtualKeyboard;
        if (ui.getInstanceConfig().getKeyboardLayout() == null) {
            virtualKeyboard = null;
        } else {
            virtualKeyboard = new VirtualKeyboardCodeEditor();
            virtualKeyboard.setKeyboardLayout(ui.getInstanceConfig().getKeyboardLayout());
            virtualKeyboard.extend(txtQuery);
        }

        txtStatus = new TextArea();
        txtStatus.setValue(this.lastPublicStatus);
        txtStatus.setWidth("100%");
        txtStatus.setHeight(4.0f, Unit.EM);
        txtStatus.addStyleName("border-layout");
        txtStatus.setReadOnly(true);

        piCount = new ProgressBar();
        piCount.setIndeterminate(true);
        piCount.setEnabled(false);
        piCount.setVisible(false);

        btShowResult = new Button("Search");
        btShowResult.setIcon(FontAwesome.SEARCH);
        btShowResult.setWidth("100%");
        btShowResult.addClickListener(new ShowResultClickListener());
        btShowResult.setDescription("<strong>Show Result</strong><br />Ctrl + Enter");
        btShowResult.setClickShortcut(KeyCode.ENTER, ModifierKey.CTRL);
        btShowResult.setDisableOnClick(true);

        VerticalLayout historyListLayout = new VerticalLayout();
        historyListLayout.setSizeUndefined();

        lstHistory = new ListSelect();
        lstHistory.setWidth("200px");
        lstHistory.setNullSelectionAllowed(false);
        lstHistory.setValue(null);
        lstHistory.addValueChangeListener((ValueChangeListener) this);
        lstHistory.setImmediate(true);
        lstHistory.setContainerDataSource(historyContainer);
        lstHistory.setItemCaptionPropertyId("query");
        lstHistory.addStyleName(Helper.CORPUS_FONT);

        Button btShowMoreHistory = new Button("Show more details", new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                if (historyWindow == null) {
                    historyWindow = new Window("History");
                    historyWindow.setModal(false);
                    historyWindow.setWidth("400px");
                    historyWindow.setHeight("250px");
                }
                historyWindow.setContent(new HistoryPanel(state.getHistory(), ui.getQueryController()));

                if (UI.getCurrent().getWindows().contains(historyWindow)) {
                    historyWindow.bringToFront();
                } else {
                    UI.getCurrent().addWindow(historyWindow);
                }
            }
        });
        btShowMoreHistory.setWidth("100%");

        historyListLayout.addComponent(lstHistory);
        historyListLayout.addComponent(btShowMoreHistory);

        historyListLayout.setExpandRatio(lstHistory, 1.0f);
        historyListLayout.setExpandRatio(btShowMoreHistory, 0.0f);

        btHistory = new PopupButton("History");
        btHistory.setContent(historyListLayout);
        btHistory.setDescription("<strong>Show History</strong><br />"
                + "Either use the short overview (arrow down) or click on the button " + "for the extended view.");

        Button btShowKeyboard = null;
        if (virtualKeyboard != null) {
            btShowKeyboard = new Button();
            btShowKeyboard.setWidth("100%");
            btShowKeyboard.setDescription("Click to show a virtual keyboard");
            btShowKeyboard.addStyleName(ValoTheme.BUTTON_ICON_ONLY);
            btShowKeyboard.addStyleName(ValoTheme.BUTTON_SMALL);
            btShowKeyboard.setIcon(new ClassResource(VirtualKeyboardCodeEditor.class, "keyboard.png"));
            btShowKeyboard.addClickListener(new ShowKeyboardClickListener(virtualKeyboard));
        }

        Button btShowQueryBuilder = new Button("Query<br />Builder");
        btShowQueryBuilder.setHtmlContentAllowed(true);
        btShowQueryBuilder.addStyleName(ValoTheme.BUTTON_SMALL);
        btShowQueryBuilder.addStyleName(ValoTheme.BUTTON_ICON_ALIGN_TOP);
        btShowQueryBuilder.setIcon(new ThemeResource("images/tango-icons/32x32/document-properties.png"));
        btShowQueryBuilder.addClickListener(new ShowQueryBuilderClickListener(ui));

        VerticalLayout moreActionsLayout = new VerticalLayout();
        moreActionsLayout.setWidth("250px");
        btMoreActions = new PopupButton("More");
        btMoreActions.setContent(moreActionsLayout);

        //    btShowResultNewTab = new Button("Search (open in new tab)");
        //    btShowResultNewTab.setWidth("100%");
        //    btShowResultNewTab.addClickListener(new ShowResultInNewTabClickListener());
        //    btShowResultNewTab.setDescription("<strong>Show Result and open result in new tab</strong><br />Ctrl + Shift + Enter");
        //    btShowResultNewTab.setDisableOnClick(true);
        //    btShowResultNewTab.setClickShortcut(KeyCode.ENTER, ModifierKey.CTRL, ModifierKey.SHIFT);
        //    moreActionsLayout.addComponent(btShowResultNewTab);

        Button btShowExport = new Button("Export", new ShowExportClickListener(ui));
        btShowExport.setIcon(FontAwesome.DOWNLOAD);
        btShowExport.setWidth("100%");
        moreActionsLayout.addComponent(btShowExport);

        Button btShowFrequency = new Button("Frequency Analysis", new ShowFrequencyClickListener(ui));
        btShowFrequency.setIcon(FontAwesome.BAR_CHART_O);
        btShowFrequency.setWidth("100%");
        moreActionsLayout.addComponent(btShowFrequency);

        /*
         * We use the grid layout for a better rendering efficiency, but this comes
         * with the cost of some complexity when defining the positions of the
         * elements in the layout.
         * 
         * This grid hopefully helps a little bit in understanding the "magic"
         * numbers better.
         * 
         * Q: Query text field
         * QB: Button to toggle query builder // TODO
         * KEY: Button to show virtual keyboard
         * SEA: "Search" button
         * MOR: "More actions" button 
         * HIST: "History" button
         * STAT: Text field with the real status
         * PROG: indefinite progress bar (spinning circle)
         * 
         *   \  0  |  1  |  2  |  3  
         * --+-----+---+---+---+-----
         * 0 |  Q  |  Q  |  Q  | QB 
         * --+-----+-----+-----+-----
         * 1 |  Q  |  Q  |  Q  | KEY 
         * --+-----+-----+-----+-----
         * 2 | SEA | MOR | HIST|     
         * --+-----+-----+-----+-----
         * 3 | STAT| STAT| STAT| PROG
         */
        addComponent(txtQuery, 0, 0, 2, 1);
        addComponent(txtStatus, 0, 3, 2, 3);
        addComponent(btShowResult, 0, 2);
        addComponent(btMoreActions, 1, 2);
        addComponent(btHistory, 2, 2);
        addComponent(piCount, 3, 3);
        addComponent(btShowQueryBuilder, 3, 0);
        if (btShowKeyboard != null) {
            addComponent(btShowKeyboard, 3, 1);
        }

        // alignment
        setRowExpandRatio(0, 0.0f);
        setRowExpandRatio(1, 1.0f);
        setColumnExpandRatio(0, 1.0f);
        setColumnExpandRatio(1, 0.0f);
        setColumnExpandRatio(2, 0.0f);
        setColumnExpandRatio(3, 0.0f);

        //setComponentAlignment(btShowQueryBuilder, Alignment.BOTTOM_CENTER);
    }

    @Override
    public void attach() {
        super.attach();
        IDGenerator.assignIDForFields(QueryPanel.this, btShowResult, btMoreActions);

    }

    public void updateShortHistory() {
        historyContainer.removeAllItems();

        int counter = 0;

        for (Query q : state.getHistory().getItemIds()) {
            if (counter >= MAX_HISTORY_MENU_ITEMS) {
                break;
            } else {
                historyContainer.addBean(q);
            }
            counter++;
        }
    }

    public void setQuery(String query) {
        if (txtQuery != null) {
            txtQuery.setValue(query);
        }
    }

    public String getQuery() {
        if (txtQuery != null) {
            return (String) txtQuery.getValue();
        }
        return "";
    }

    public void setNodes(List<QueryNode> nodes) {
        txtQuery.setNodes(nodes);
    }

    public void setErrors(List<AqlParseError> errors) {
        txtQuery.setErrors(errors);
    }

    public void notifyFrequencyTabClose() {
        txtQuery.removeTextChangeListener(frequencyPanel);
        frequencyPanel = null;
    }

    @Override
    public void valueChange(ValueChangeEvent event) {
        btHistory.setPopupVisible(false);
        Object q = event.getProperty().getValue();
        if (ui != null && ui.getQueryController() != null && q instanceof Query) {
            ui.getQueryController().setQuery((Query) q);
        }
    }

    public class ShowResultClickListener implements Button.ClickListener {

        @Override
        public void buttonClick(ClickEvent event) {
            if (ui != null && ui.getQueryController() != null) {
                ui.getQueryController().executeSearch(true, true);
            }
        }
    }

    //  public class ShowResultInNewTabClickListener implements Button.ClickListener
    //  {
    //
    //    @Override
    //    public void buttonClick(ClickEvent event)
    //    {
    //      if(controller != null)
    //      {
    //        controller.setQuery((txtQuery.getValue()));
    //        controller.executeQuery(false);
    //      }
    //    }
    //  }

    public void setCountIndicatorEnabled(boolean enabled) {
        if (piCount != null && btShowResult != null && txtStatus != null) {
            if (enabled) {
                if (!piCount.isVisible()) {
                    piCount.setVisible(true);
                    piCount.setEnabled(true);
                }
            }

            btShowResult.setEnabled(!enabled);
            //      btShowResultNewTab.setEnabled(!enabled);
        }
    }

    public void setStatus(String status) {
        if (txtStatus != null) {
            txtStatus.setReadOnly(false);
            txtStatus.setValue(status);
            lastPublicStatus = status;
            txtStatus.setReadOnly(true);
        }
    }

    public void setStatus(String status, String resultStatus) {
        if (txtStatus != null) {
            txtStatus.setReadOnly(false);
            txtStatus.setValue(status + resultStatus);
            lastPublicStatus = status;
            txtStatus.setReadOnly(true);
        }
    }

    private static class ShowKeyboardClickListener implements ClickListener {

        private final VirtualKeyboardCodeEditor virtualKeyboard;

        public ShowKeyboardClickListener(VirtualKeyboardCodeEditor virtualKeyboard) {
            this.virtualKeyboard = virtualKeyboard;
        }

        @Override
        public void buttonClick(ClickEvent event) {
            virtualKeyboard.show();
        }
    }

    private class ShowExportClickListener implements ClickListener {
        private AnnisUI ui;
        private ExportPanel panel;

        public ShowExportClickListener(AnnisUI ui) {
            this.ui = ui;
        }

        @Override
        public void buttonClick(ClickEvent event) {
            if (panel == null) {
                panel = new ExportPanel(QueryPanel.this, ui.getQueryController(), state);
            }

            final TabSheet tabSheet = ui.getSearchView().getMainTab();
            Tab tab = tabSheet.getTab(panel);

            if (tab == null) {
                tab = tabSheet.addTab(panel, "Export");
                tab.setIcon(FontAwesome.DOWNLOAD);
            }

            tab.setClosable(true);
            tabSheet.setSelectedTab(panel);

            btMoreActions.setPopupVisible(false);
        }

    }

    private class ShowFrequencyClickListener implements ClickListener {
        private AnnisUI ui;

        public ShowFrequencyClickListener(AnnisUI ui) {
            this.ui = ui;
        }

        @Override
        public void buttonClick(ClickEvent event) {
            if (frequencyPanel == null) {
                frequencyPanel = new FrequencyQueryPanel(ui.getQueryController(), state);
                txtQuery.addTextChangeListener(frequencyPanel);
            }

            final TabSheet tabSheet = ui.getSearchView().getMainTab();
            Tab tab = tabSheet.getTab(frequencyPanel);

            if (tab == null) {
                tab = tabSheet.addTab(frequencyPanel, "Frequency Analysis");
                tab.setIcon(FontAwesome.BAR_CHART_O);
            }

            tab.setClosable(true);
            tabSheet.setSelectedTab(frequencyPanel);

            btMoreActions.setPopupVisible(false);
        }

    }

    private static class ShowQueryBuilderClickListener implements ClickListener {

        private QueryBuilderChooser queryBuilder;
        private AnnisUI ui;

        public ShowQueryBuilderClickListener(AnnisUI ui) {
            this.ui = ui;
        }

        @Override
        public void buttonClick(ClickEvent event) {
            if (queryBuilder == null) {
                queryBuilder = new QueryBuilderChooser(ui.getQueryController(), ui, ui.getInstanceConfig());
            }
            final TabSheet tabSheet = ui.getSearchView().getMainTab();
            Tab tab = tabSheet.getTab(queryBuilder);

            if (tab == null) {
                tab = tabSheet.addTab(queryBuilder, "Query Builder",
                        new ThemeResource("images/tango-icons/16x16/document-properties.png"));

                ui.addAction(new ShortcutListener("^Query builder") {
                    @Override
                    public void handleAction(Object sender, Object target) {
                        if (queryBuilder != null && tabSheet.getTab(queryBuilder) != null) {
                            tabSheet.setSelectedTab(queryBuilder);
                        }
                    }
                });
            }

            tab.setClosable(true);
            tabSheet.setSelectedTab(queryBuilder);
        }

    }

    public String getLastPublicStatus() {
        return lastPublicStatus;
    }

    public ProgressBar getPiCount() {
        return piCount;
    }

}