edu.nps.moves.mmowgli.modules.actionplans.ActionPlanPageTabTalk.java Source code

Java tutorial

Introduction

Here is the source code for edu.nps.moves.mmowgli.modules.actionplans.ActionPlanPageTabTalk.java

Source

/*
  Copyright (C) 2010-2014 Modeling Virtual Environments and Simulation
  (MOVES) Institute at the Naval Postgraduate School (NPS)
  http://www.MovesInstitute.org and http://www.nps.edu
     
  This file is part of Mmowgli.
      
  Mmowgli is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  any later version.
    
  Mmowgli 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 General Public License for more details.
    
  You should have received a copy of the GNU General Public License
  along with Mmowgli in the form of a file named COPYING.  If not,
  see <http://www.gnu.org/licenses/>
*/

package edu.nps.moves.mmowgli.modules.actionplans;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.SortedSet;

import org.hibernate.Session;

import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.ui.*;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Window.CloseEvent;
import com.vaadin.ui.Window.CloseListener;
import com.vaadin.ui.themes.BaseTheme;

import edu.nps.moves.mmowgli.Mmowgli2UI;
import edu.nps.moves.mmowgli.cache.MCacheUserHelper.QuickUser;
import edu.nps.moves.mmowgli.components.HtmlLabel;
import edu.nps.moves.mmowgli.components.ToggleLinkButton;
import edu.nps.moves.mmowgli.db.*;
import edu.nps.moves.mmowgli.hibernate.HSess;
import edu.nps.moves.mmowgli.markers.*;
import edu.nps.moves.mmowgli.messaging.WantsChatLogUpdates;
import edu.nps.moves.mmowgli.modules.cards.EditCardTextWindow;
import edu.nps.moves.mmowgli.modules.gamemaster.GameEventLogger;
import edu.nps.moves.mmowgli.utility.MmowgliLinkInserter;

import static edu.nps.moves.mmowgli.MmowgliConstants.*;

/**
 * ActionPlanPageTabTalk.java
 * Created on Feb 8, 2011
 * Updated on Mar 14, 2014
 *
 * MOVES Institute
 * Naval Postgraduate School, Monterey, CA, USA
 * www.nps.edu
 *
 * @author Mike Bailey, jmbailey@nps.edu
 * @version $Id$
 */
public class ActionPlanPageTabTalk extends ActionPlanPageTabPanel
        implements/* ClickListener, */WantsChatLogUpdates {
    private static final long serialVersionUID = 3549944451620639594L;

    private NativeButton submitButt;
    private NativeButton discardButt;
    private ToggleLinkButton viewAllButt;
    private Panel chatScroller;
    private TextArea chatTextField;
    private SimpleDateFormat dateFormatter;
    private Component chatEntryComponent;
    private NativeButton chatSubmitButt;
    private Label nonAuthorLabel;
    private boolean showingHiddenMsgs = false;
    private boolean isGameMasterOrAdmin = false;

    @HibernateSessionThreadLocalConstructor
    public ActionPlanPageTabTalk(Object apId, boolean isMockup, boolean readonly) {
        super(apId, isMockup, readonly);

        submitButt = new NativeButton();
        discardButt = new NativeButton();
        dateFormatter = new SimpleDateFormat("MM/dd HH:mm z");
        chatEntryComponent = createChatEntryField();
        User me = Mmowgli2UI.getGlobals().getUserTL();

        isGameMasterOrAdmin = me.isAdministrator() || me.isGameMaster();
    }

    @Override
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (visible)
            chatSubmitButt.setClickShortcut(KeyCode.ENTER);
        else
            chatSubmitButt.removeClickShortcut();
    }

    @Override
    public void initGui() {
        setSizeUndefined();
        VerticalLayout leftVL = this.getLeftLayout();

        leftVL.setSpacing(true);

        Label missionLab = new Label("Authors, this is your team space.");
        leftVL.addComponent(missionLab);
        leftVL.setComponentAlignment(missionLab, Alignment.TOP_LEFT);
        missionLab.addStyleName("m-actionplan-mission-title-text");

        ActionPlan ap = ActionPlan.getTL(apId);

        Label missionContentLab;
        Game g = Game.getTL();
        if (!isMockup)
            missionContentLab = new HtmlLabel(ap.getTalkItOverInstructions());
        else {
            missionContentLab = new HtmlLabel(g.getDefaultActionPlanTalkText());
        }

        leftVL.addComponent(missionContentLab);
        leftVL.setComponentAlignment(missionContentLab, Alignment.TOP_LEFT);
        leftVL.addStyleName("m-actionplan-mission-content-text");

        Label sp;
        leftVL.addComponent(sp = new Label());
        sp.setHeight("1px");
        leftVL.setExpandRatio(sp, 1.0f);

        VerticalLayout rightVL = getRightLayout();
        rightVL.setSpacing(true);

        Label lab;
        rightVL.addComponent(lab = new Label());
        lab.setHeight("15px");

        rightVL.addComponent(nonAuthorLabel = new Label("This is a space for plan authors to communicate."));
        nonAuthorLabel.setVisible(false);

        rightVL.addComponent(chatEntryComponent);
        chatEntryComponent.setWidth("100%");

        if (isGameMasterOrAdmin) {
            HorizontalLayout hl = new HorizontalLayout();
            rightVL.addComponent(hl);
            hl.setWidth("100%");

            hl.addComponent(sp = new Label());
            sp.setWidth("1px");
            hl.setExpandRatio(sp, 1.0f);

            viewAllButt = new ToggleLinkButton("View all", "View unhidden only", "m-actionplan-comment-text");
            viewAllButt.setToolTips("Temporarily show all messages, including those marked \"hidden\" (gm)",
                    "Temporarily hide messages marked \"hidden\" (gm)");
            viewAllButt.addStyleName("m-actionplan-comments-button");
            viewAllButt.addOnListener(new ViewAllListener());
            viewAllButt.addOffListener(new ViewUnhiddenOnlyListener());
            hl.addComponent(viewAllButt);

            hl.addComponent(sp = new Label());
            sp.setWidth("8px");
        }
        Component comp = createChatScroller(rightVL);
        comp.setWidth("99%");
        rightVL.setExpandRatio(comp, 1.0f);
        comp.setHeight("99%");
        fillChatScrollerTL();
    }

    @SuppressWarnings("serial")
    class ViewAllListener implements ClickListener {
        @Override
        @MmowgliCodeEntry
        @HibernateOpened
        @HibernateClosed
        public void buttonClick(ClickEvent event) {
            HSess.init();
            showingHiddenMsgs = true;
            fillChatScrollerTL();
            HSess.close();
        }
    }

    @SuppressWarnings("serial")
    class ViewUnhiddenOnlyListener implements ClickListener {
        @Override
        @MmowgliCodeEntry
        @HibernateOpened
        @HibernateClosed
        public void buttonClick(ClickEvent event) {
            HSess.init();
            showingHiddenMsgs = false;
            fillChatScrollerTL();
            HSess.close();
        }
    }

    private void fillChatScrollerTL() {
        ((VerticalLayout) chatScroller.getContent()).removeAllComponents();

        ActionPlan ap = ActionPlan.getTL(apId);
        ChatLog log = ap.getChatLog();
        if (log != null) {// shouldn't have to do this, both log and messages should be set up to have the sets build by default
            SortedSet<Message> msgs = log.getMessages();
            if (msgs != null) // ditto
                for (Message m : msgs) {
                    addMessageToScroller(m);
                }
        }
    }

    private void addMessageToScroller(Message m) {
        ChatMsg cm = new ChatMsg(m);
        ((VerticalLayout) chatScroller.getContent()).addComponent(cm);
        cm.setWidth("98%");
        handleVisible(cm);
    }

    private void handleVisible(ChatMsg cm) {
        boolean vis = showingHiddenMsgs || !cm.getMessage().isHidden();
        cm.setVisible(vis);
    }

    private void addMessageToScrollerTop(Message m, Session sess) {
        addMessageToScrollerAtPosition(m, 0, sess);
    }

    private void addMessageToScrollerAtPosition(Message m, int pos, Session sess) {
        ChatMsg cm = new ChatMsg(m, sess);
        ((VerticalLayout) chatScroller.getContent()).addComponent(cm, pos);
        cm.setWidth("98%");
        handleVisible(cm);
    }

    @SuppressWarnings("serial")
    class ChatMsg extends VerticalLayout {
        private Message msg;
        private CheckBox superInterestingCB;
        private Label textLabel;

        ChatMsg(Message m) {
            this(m, null);
        }

        ChatMsg(Message m, Session sess) {
            if (sess == null)
                sess = HSess.get();
            msg = m;
            setSpacing(true);
            setMargin(false);

            Object myId = Mmowgli2UI.getGlobals().getUserID();
            if (myId.equals(m.getFromUser().getId()))
                addStyleName("m-chatmessage-mine");
            else
                addStyleName("m-chatmessage");

            HorizontalLayout hl = new HorizontalLayout();
            hl.setWidth("99%");
            addComponent(hl);
            Label lab;
            hl.setMargin(false);
            hl.setSpacing(true);

            hl.addComponent(lab = new HtmlLabel("<b>" + m.getFromUser().getUserName() + "</b>"));
            lab.setSizeUndefined();
            hl.addComponent(lab = new HtmlLabel("<b>" + dateFormatter.format(m.getDateTime()) + "</b>"));
            lab.setSizeUndefined();

            if (isGameMasterOrAdmin) {
                Label sp;
                hl.addComponent(sp = new Label());
                sp.setWidth("1px");
                hl.setExpandRatio(sp, 1.0f);

                hl.addComponent(superInterestingCB = new CheckBox("super-interesting"));
                superInterestingCB.setValue(msg.isSuperInteresting());
                superInterestingCB.addStyleName("m-actionplan-comment-superinteresting");
                superInterestingCB.setImmediate(true);
                superInterestingCB.addValueChangeListener(new SuperInterestingCheckBoxListener());
                superInterestingCB.setEnabled(!isReadOnly);
                hl.setComponentAlignment(superInterestingCB, Alignment.TOP_CENTER);

                final ToggleLinkButton tlb;
                hl.addComponent(tlb = new ToggleLinkButton("hide", "show", "m-actionplan-comment-text"));
                hl.setComponentAlignment(tlb, Alignment.MIDDLE_CENTER);
                tlb.setInitialState(!msg.isHidden());
                tlb.setEnabled(!isReadOnly);
                tlb.addOnListener(new Button.ClickListener() {
                    @Override
                    @MmowgliCodeEntry
                    @HibernateOpened
                    @HibernateClosed
                    public void buttonClick(ClickEvent event) {
                        HSess.init();
                        msg.setHidden(true);
                        Message.updateTL(msg);
                        if (!showingHiddenMsgs)
                            ChatMsg.this.setVisible(false); // hide
                        HSess.close();
                    }
                });
                tlb.addOffListener(new Button.ClickListener() {
                    @Override
                    @MmowgliCodeEntry
                    @HibernateOpened
                    @HibernateClosed
                    public void buttonClick(ClickEvent event) {
                        HSess.init();
                        msg.setHidden(false);
                        Message.updateTL(msg);
                        ChatMsg.this.setVisible(true); // show
                        HSess.close();
                    }
                });
                tlb.setToolTips("Hide this message in this list", "Show this message in this list");

                NativeButton editButt = new NativeButton();
                editButt.setCaption("edit");
                editButt.setStyleName(BaseTheme.BUTTON_LINK);
                editButt.addStyleName("borderless");
                editButt.addStyleName("m-actionplan-comment-text");
                editButt.setDescription("Edit this text (game masters only)");

                editButt.addClickListener(new EditListener());
                editButt.setEnabled(!isReadOnly);

                editButt.setSizeUndefined();
                hl.addComponent(editButt);
                hl.setComponentAlignment(editButt, Alignment.MIDDLE_CENTER);
            }

            Game g = (Game) sess.get(Game.class, 1L);
            String linkifiedString = MmowgliLinkInserter.insertLinksOob(m.getText(), g, sess);
            addComponent(textLabel = new HtmlLabel(linkifiedString));
        }

        class EditListener implements ClickListener {
            EditCardTextWindow w;

            @Override

            public void buttonClick(ClickEvent event) {
                EditCardTextWindow w = new EditCardTextWindow(msg.getText(), Integer.MAX_VALUE);
                w.setCaption("Edit Chat Message");
                w.addCloseListener(new SaveTextListener());
            }

            class SaveTextListener implements CloseListener {
                @Override
                @MmowgliCodeEntry
                @HibernateOpened
                @HibernateClosed
                public void windowClose(CloseEvent e) {
                    EditCardTextWindow w = (EditCardTextWindow) e.getWindow();
                    if (w.results != null) {
                        HSess.init();
                        textLabel.setValue(MmowgliLinkInserter.insertLinksTL(w.results, null));
                        msg.setText(w.results);
                        Message.updateTL(msg);
                        User me = Mmowgli2UI.getGlobals().getUserTL();
                        GameEventLogger.chatTextEdittedTL(me.getUserName(), apId, msg);
                        HSess.close();
                    }
                }
            }
        }

        public Message getMessage() {
            return msg;
        }

        class SuperInterestingCheckBoxListener implements ValueChangeListener {
            @Override
            @MmowgliCodeEntry
            @HibernateOpened
            @HibernateClosed
            public void valueChange(ValueChangeEvent event) {
                HSess.init();
                Boolean supInt = (Boolean) superInterestingCB.getValue();
                msg.setSuperInteresting(supInt);
                Message.updateTL(msg);
                User me = Mmowgli2UI.getGlobals().getUserTL();
                GameEventLogger.commentMarkedSuperInterestingTL(me.getUserName(), apId, msg, supInt);
                HSess.close();
            }
        }
    }

    private Component createChatScroller(VerticalLayout cont) {
        chatScroller = new Panel();
        cont.addComponent(chatScroller);
        VerticalLayout vl = new VerticalLayout();
        chatScroller.setContent(vl);
        vl.addStyleName("m-padding2");
        vl.setWidth("99%"); // the padding screws up the panel's width calc
        return chatScroller;
    }

    private Component createChatEntryField() {
        HorizontalLayout hl = new HorizontalLayout();
        chatTextField = new TextArea();
        chatTextField.setRows(3);
        chatTextField.setWordwrap(true);
        chatTextField.setInputPrompt("Type here to chat, RETURN submits");
        chatTextField.setId(ACTIONPLAN_TALK_IT_OVER_TEXT_BOX);
        hl.addComponent(chatTextField);
        chatTextField.setWidth("99%");
        hl.setExpandRatio(chatTextField, 1.0f);
        chatTextField.setReadOnly(isReadOnly);

        chatSubmitButt = new NativeButton();
        chatSubmitButt.setStyleName("m-submitButton");
        hl.addComponent(chatSubmitButt);
        chatSubmitButt.addClickListener(new ChatButtonListener());
        chatSubmitButt.setEnabled(!isReadOnly);
        chatSubmitButt.setId(ACTIONPLAN_TALK_IT_OVER_SUBMIT_BUTTON);
        return hl;
    }

    @SuppressWarnings("serial")
    class ChatButtonListener implements ClickListener {
        Message msg;

        @Override
        @MmowgliCodeEntry
        @HibernateOpened
        @HibernateClosed
        public void buttonClick(ClickEvent event) {
            String s = chatTextField.getValue().toString();
            if (s == null || s.length() <= 0)
                return;
            HSess.init();
            User me = Mmowgli2UI.getGlobals().getUserTL();
            msg = new Message(s);

            if (!me.isGameMaster())
                buttonClick2TL(me);
            else
                getProxyAuthorTL(me, this, event.getButton());
            HSess.close();
        }

        private void buttonClick2TL(User proxAuth) {
            msg.setFromUser(proxAuth);
            Message.saveTL(msg); // persist
            ActionPlan ap = ActionPlan.getTL(apId);
            ChatLog log = ap.getChatLog();
            log.getMessages().add(msg);
            ChatLog.updateTL(log); // persist

            addMessageToScrollerTop(msg, HSess.get());
            chatTextField.setValue("");
            chatTextField.focus();
        }
    }

    @SuppressWarnings("serial")
    private void getProxyAuthorTL(final User me, final ChatButtonListener cbLis, Button butt) {
        ArrayList<User> meLis = new ArrayList<User>(1);
        meLis.add(me);

        final AddAuthorDialog dial = new AddAuthorDialog(meLis, true);
        dial.infoLabel.setValue("As administrator, you may choose another player to be comment author.");
        dial.setCaption("Select Proxy Author");
        dial.setMultiSelect(false);
        dial.cancelButt.setCaption("Use myself");
        dial.addButt.setCaption("Use selected");
        dial.selectItemAt(0);
        dial.addListener(new CloseListener() {
            @Override
            @MmowgliCodeEntry
            @HibernateOpened
            @HibernateClosed
            public void windowClose(CloseEvent e) {
                HSess.init();
                User u = me;
                if (dial.addClicked) {
                    Object o = dial.getSelected();
                    if (o instanceof User) {
                        u = (User) o;
                    } else if (o instanceof QuickUser) {
                        QuickUser qu = (QuickUser) o;
                        u = User.getTL(qu.id);
                    }
                }
                cbLis.buttonClick2TL(u);
                HSess.close();
            }
        });

        UI.getCurrent().addWindow(dial);
        dial.center();
    }

    /* return true if need gui update */
    @Override
    public boolean logUpdated_oobTL(Serializable chatLogId) {
        // This comes in on MY updates too, should do nothing since my just-entered msg is already displayed
        ActionPlan ap = ActionPlan.getTL(apId);
        ChatLog log = ap.getChatLog();
        if (chatLogId.equals(log.getId())) {

            // somebody else updated this log.
            // try not to load everything.  All lists should be in order
            SortedSet<Message> msgs = log.getMessages();
            if (msgs.size() <= 0)
                return false;
            VerticalLayout lay = (VerticalLayout) chatScroller.getContent();

            Message topMsg = null;
            if (lay.getComponentCount() > 0)
                topMsg = ((ChatMsg) lay.getComponent(0)).getMessage();

            int pos = 0;
            for (Iterator<Message> itr = msgs.iterator(); itr.hasNext();) {
                Message m = itr.next();
                if (topMsg != null && m.getId() == topMsg.getId())
                    break;
                addMessageToScrollerAtPosition(m, pos++, HSess.get());
            }
            return true;
        }
        return false;
    }

    @Override
    public boolean actionPlanUpdatedOobTL(Serializable apId) {
        return false;
    }

    boolean author = false;
    boolean gm = false;

    public void setICanChat(boolean yn) {
        submitButt.setEnabled(yn & !isReadOnly);
        discardButt.setEnabled(yn & !isReadOnly);
        chatEntryComponent.setVisible(yn);
        chatScroller.setVisible(yn || isGameMasterOrAdmin);
        nonAuthorLabel.setVisible(!yn);
        if (viewAllButt != null)
            viewAllButt.setVisible(yn);
    }

    @Override
    public void setICanEdit(boolean yn) {
        author = yn;
    }

    public void setImGM(boolean yn) {
        gm = yn;
    }
}