net.anthavio.vinbudin.vui.ChatUI.java Source code

Java tutorial

Introduction

Here is the source code for net.anthavio.vinbudin.vui.ChatUI.java

Source

/**
 * This file is part of vinbudin.
 *
 * vinbudin is free software: you can redistribute it and/or modify
 * it 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.
 *
 * vinbudin 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with vinbudin.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.anthavio.vinbudin.vui;

import java.text.SimpleDateFormat;
import java.util.Iterator;

import net.anthavio.aspect.Logged;
import net.anthavio.vaadin.CallbackRegistry;
import net.anthavio.vinbudin.ChatMan;
import net.anthavio.vinbudin.ChatMessage;
import net.anthavio.vinbudin.ChatMessageListener;
import net.anthavio.vinbudin.ChatService;
import net.anthavio.vinbudin.OAuthController.OAuthProvider;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.dialogs.ConfirmDialog;
import org.vaadin.spring.VaadinUI;

import com.vaadin.annotations.PreserveOnRefresh;
import com.vaadin.annotations.Push;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.Title;
import com.vaadin.event.ShortcutAction;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.server.VaadinRequest;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.shared.ui.ui.Transport;
import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.MenuBar.Command;
import com.vaadin.ui.MenuBar.MenuItem;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Notification.Type;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;

/**
 * 
 * @author martin.vanek
 *
 */
@VaadinUI
@Theme("valo")
@Title("Vaadin Chat")
@PreserveOnRefresh
@Push(transport = Transport.WEBSOCKET)
public class ChatUI extends UI {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private static final long serialVersionUID = 1L;

    public static final String ME_KEY = "ME";

    @Autowired
    ChatService service;

    @Autowired
    CallbackRegistry registry;

    MenuBar menubar = new MenuBar();
    MenuItem miLogin;
    LoginCommand loginCommand = new LoginCommand();
    MenuItem miLogout;

    TextField fieldMessage = new TextField();
    Button buttonSend = new Button("Send");
    Button buttonCancel = new Button("Cancel");
    Button buttonClear = new Button("Clear");

    Label labelBoard = new Label("", ContentMode.PREFORMATTED);

    @Logged
    @Override
    protected void init(VaadinRequest request) {

        fieldMessage.setMaxLength(100);
        fieldMessage.setEnabled(false);
        fieldMessage.setWidth("100%");
        fieldMessage.addTextChangeListener(event -> {
            String text = event.getText();
            buttonSend.setEnabled(text != null && text.length() > 2);
        });

        buttonSend.setEnabled(false);
        buttonSend.setClickShortcut(KeyCode.ENTER);
        buttonSend.addStyleName(ValoTheme.BUTTON_PRIMARY);

        buttonSend.addClickListener(event -> {
            ChatMessage message = new ChatMessage(getMe(), fieldMessage.getValue());
            service.addMessage(message);
            fieldMessage.setValue("");
            buttonSend.setEnabled(false);
        });

        buttonCancel.setClickShortcut(ShortcutAction.KeyCode.ESCAPE);
        buttonCancel.addClickListener(event -> {
            fieldMessage.setValue("");
            buttonSend.setEnabled(false);
        });

        buttonClear.setEnabled(false);
        buttonClear.addClickListener(event -> {
            ConfirmDialog.show(this, "Please Confirm:", "Delete all messages?", "Yes", "Nope",
                    new ConfirmDialog.Listener() {
                        public void onClose(ConfirmDialog dialog) {
                            if (dialog.isConfirmed()) {
                                service.clearMessages();
                                ChatMessage message = new ChatMessage(getMe(), "Cleared discussion...");
                                service.addMessage(message);
                            }
                        }
                    });
        });

        menubar.setWidth("100%");
        miLogin = menubar.addItem("Login", null);
        for (OAuthProvider p : OAuthProvider.values()) {
            miLogin.addItem(p.name(), loginCommand);
        }
        miLogout = menubar.addItem("Replace Me", null);
        miLogout.addItem("Logout", (selectedItem) -> {
            //Say good bye...
            ChatMessage message = new ChatMessage(getMe(), "Logged out...");
            service.addMessage(message);

            setMe(null);
            setUiStateByLogin();
        });

        HorizontalLayout lSending = new HorizontalLayout(fieldMessage, buttonSend, buttonCancel, buttonClear);
        lSending.setWidth("100%");
        lSending.setSpacing(true);
        lSending.setExpandRatio(fieldMessage, 1);

        labelBoard.setSizeFull();

        VerticalLayout layout = new VerticalLayout(menubar, lSending, labelBoard);
        layout.setSpacing(true);
        layout.setMargin(true);
        setContent(layout);
        setSizeFull();

        setUiStateByLogin();
        refreshMessageBoard();
        fieldMessage.focus();
        registry.attach(this, new ChatMessageListener() {

            @Override
            public void onEvent(ChatMessage message) {
                onChatMessage(message);
            }
        });
    }

    @Logged
    @Override
    protected void refresh(VaadinRequest request) {
        setUiStateByLogin();
        refreshMessageBoard();
        fieldMessage.focus();
    }

    @Logged
    @Override
    public void detach() {
        registry.detach(this);
        super.detach();
    }

    private ChatMan getMe() {
        return (ChatMan) UI.getCurrent().getSession().getSession().getAttribute(ME_KEY);
    }

    private void setMe(ChatMan me) {
        UI.getCurrent().getSession().getSession().setAttribute(ME_KEY, me);
    }

    private void setUiStateByLogin() {
        boolean loggedin = getMe() != null;
        fieldMessage.setEnabled(loggedin);
        buttonClear.setEnabled(loggedin);

        miLogin.setVisible(!loggedin);
        miLogout.setVisible(loggedin);
        if (loggedin) {
            miLogout.setText(getMe().getName());
        }
    }

    @Logged
    //@EventBusListenerMethod
    public void onChatMessage(ChatMessage message) {
        //Push magic happens here
        access(new Runnable() {
            @Override
            public void run() {
                try {
                    if (message.getAuthor() != getMe()) {
                        Notification n = new Notification("Message from " + message.getAuthor().getName(),
                                message.getText(), Type.TRAY_NOTIFICATION);
                        n.show(getPage());
                    }
                    refreshMessageBoard();
                } catch (Exception x) {
                    logger.warn("onChatMessage push failed", x);
                }
            }
        });

    }

    private void refreshMessageBoard() {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy 'at' HH:mm z");
        Iterator<ChatMessage> messages = service.messagesIterator();
        StringBuilder sb = new StringBuilder();
        messages.forEachRemaining(message -> {
            sb.append(sdf.format(message.getDate())).append(", ").append(message.getAuthor().getName()).append(" [")
                    .append(message.getAuthor().getFrom().name()).append("]: ").append(message.getText())
                    .append("\n");
        });
        labelBoard.setValue(sb.toString());
    }

    private class LoginCommand implements Command {

        private static final long serialVersionUID = 1L;

        @Override
        public void menuSelected(MenuItem selectedItem) {
            OAuthProvider provider = OAuthProvider.getByName(selectedItem.getText());
            String url = provider.getOAuth().getAuthorizationUrl(provider.getScopes(),
                    String.valueOf(System.currentTimeMillis()));
            getUI().getPage().setLocation(url); //redirect to OAuth...
        }
    }

}