de.spartusch.nasfvi.client.MainWidget.java Source code

Java tutorial

Introduction

Here is the source code for de.spartusch.nasfvi.client.MainWidget.java

Source

/*
 * Copyright 2011 Stefan Partusch
 *
 * 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 de.spartusch.nasfvi.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.Widget;

/**
 * The main widget of the client containing most of the UI. This class
 * implements the {@link HistoryStateSetter} interface and queries are only
 * sent to the server when a history token is set using this interface.
 * Suggestions on the other hand are processed automatically whenever the
 * user enters text in the widget's <code>SuggestBox</code>.
 * @author Stefan Partusch
 *
 */
public class MainWidget extends Composite
        implements RequestCallback, ValueChangeHandler<String>, HistoryStateSetter, KeyUpHandler {
    interface MyUiBinder extends UiBinder<Widget, MainWidget> {
    }

    private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

    /** Regular expression to detect placeholders in queries. */
    private static final String PLACEHOLDERS = ".*\\([A-Z][a-z]+\\).*";
    /** Examples of queries. */
    private final String[] examples;
    /** URL stubs to use. */
    private final String suggestionsUrl, parseUrl;

    @UiField
    SuggestBox suggestBox;
    @UiField
    SimplePanel responsePanel;
    @UiField
    DisclosurePanel hints;
    @UiField
    HTML exampleItems;

    /**
     * @param examples Examples of queries to display in the main widget
     * @param suggestionsUrl URL stub for retrieving suggestions
     * @param parseUrl URL stub for parsing
     */
    public MainWidget(final String[] examples, final String suggestionsUrl, final String parseUrl) {
        this.examples = examples;
        this.suggestionsUrl = suggestionsUrl;
        this.parseUrl = parseUrl;

        initWidget(uiBinder.createAndBindUi(this));

        setExamples();

        suggestBox.addKeyUpHandler(this);

        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                suggestBox.setFocus(true);
            }
        });
    }

    @UiFactory
    protected final SuggestBox createSuggestBox() {
        TextArea textArea = new TextArea();

        textArea.setCharacterWidth(50);
        textArea.setVisibleLines(4);

        return new SuggestBox(new Suggestions(suggestionsUrl), textArea);
    }

    /**
     * Selects some examples randomly and displays them.
     */
    private void setExamples() {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < 5; i++) {
            int index = Random.nextInt(examples.length);
            sb.append("<li>").append(examples[index]).append("</li>");
        }

        exampleItems.setHTML(sb.toString());
    }

    @UiHandler("moreExamples")
    protected final void moreExamplesClicked(final ClickEvent event) {
        setExamples();
    }

    @UiHandler("sendButton")
    protected final void sendButtonClicked(final ClickEvent event) {
        setHistoryState(null, 0);
    }

    /**
     * Displays a message within the main widget.
     * @param message Message to display
     * @param cssClass CSS class to use for styling
     * @see #clearMessage
     */
    private void setMessage(final String message, final String cssClass) {
        String msg = message;

        if (cssClass != null && !cssClass.isEmpty()) {
            msg = "<span class='" + cssClass + "'>" + message + "</span>";
        }

        responsePanel.setWidget(new HTML(msg));
    }

    /**
     * Clears a message displayed in the main widget.
     * @see #setMessage
     */
    private void clearMessage() {
        responsePanel.clear();
    }

    @Override
    public final void onError(final Request request, final Throwable exception) {
        Main.displayError(exception.getLocalizedMessage(), exception.toString());
    }

    @Override
    public final void onResponseReceived(final Request request, final Response response) {
        int sc = response.getStatusCode();
        String respText = response.getText();

        if (sc == Response.SC_OK) {
            NResponse nresp = NResponse.parse(respText);

            if (nresp.isSuccess()) {
                hints.setOpen(false);
                NResponseWidget widget = new NResponseWidget(nresp, this);
                responsePanel.setWidget(widget);
            } else {
                setMessage("Ihre Anfrage wurde verstanden und verarbeitet."
                        + " Doch das Vorlesungsverzeichnis enthlt keine Daten" + " zur Beantwortung der Anfrage.",
                        null);
            }
        } else if (sc == Response.SC_BAD_REQUEST) {
            setMessage("Die Anfrage konnte nicht verarbeitet werden." + " Bitte formulieren Sie um!", "error");
        } else {
            Main.displayError(response.getStatusText(), respText);
        }
    }

    @Override
    public final void setHistoryState(final String query, final int offset) {
        String q = query;

        if (q == null || q.isEmpty()) {
            q = suggestBox.getText();
        }

        History.newItem(URL.encodeQueryString(q) + "&" + String.valueOf(offset), true);
    }

    @Override
    public final void onValueChange(final ValueChangeEvent<String> event) {
        String[] state = event.getValue().split("&", -1);

        if (state.length != 2) {
            throw new AssertionError();
        }

        String q = URL.decodeQueryString(state[0]).replaceAll("\\s+", " ").trim();
        String offset = state[1];

        suggestBox.setText(q);

        if (q.isEmpty()) {
            setMessage("Bitte geben Sie eine Anfrage in das Textfeld ein.", "error");
        } else if (q.matches(PLACEHOLDERS)) {
            setMessage("Bitte ersetzen Sie smtliche Platzhalter durch" + " konkrete Werte!", "error");
        } else {
            clearMessage();
            try {
                String getUrl = parseUrl + URL.encodeQueryString(q) + "&offset=" + offset;
                RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, getUrl);
                builder.setCallback(this);
                builder.send();
            } catch (RequestException e) {
                Main.displayError(e.getLocalizedMessage(), e.toString());
            }
        }
    }

    @Override
    public final void onKeyUp(final KeyUpEvent event) {
        if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
            setHistoryState(null, 0);
        }
    }
}