ch.unifr.pai.twice.multipointer.client.WebsocketControl.java Source code

Java tutorial

Introduction

Here is the source code for ch.unifr.pai.twice.multipointer.client.WebsocketControl.java

Source

package ch.unifr.pai.twice.multipointer.client;

/*
 * Copyright 2013 Oliver Schmid
 * 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.
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import ch.unifr.pai.twice.multipointer.client.MouseCursorTimeoutEvent.Handler;
import ch.unifr.pai.twice.utils.device.client.UUID;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Use {@link ExtendedWebsocketControl} instead
 * 
 * @author Oliver Schmid
 * 
 */
@Deprecated
public class WebsocketControl extends MultiCursorController implements ResizeHandler {

    private boolean opened = false;

    private JavaScriptObject websocket;

    private final List<MouseCursor> cursors = new ArrayList<MouseCursor>();

    private final Map<String, MouseCursor> assignedMouseCursors = new HashMap<String, MouseCursor>();

    private final Map<String, MouseCursor> preferredMouseCursors = new HashMap<String, MouseCursor>();

    private final Set<MouseCursor> activeCursorsCounter = new HashSet<MouseCursor>();

    private final Storage storage = Storage.getLocalStorageIfSupported();

    private final int maxCursorsOnScreen = 5;

    private void initializeCursorList() {
        cursors.clear();
        assignedMouseCursors.clear();
        cursors.add(defineMouseCursor("black", "#1a1a1a"));
        cursors.add(defineMouseCursor("blue", "#336aa6"));
        cursors.add(defineMouseCursor("green", "#42a75b"));
        cursors.add(defineMouseCursor("grey", "#646663"));
        cursors.add(defineMouseCursor("red", "#d65555"));
        cursors.add(defineMouseCursor("yellow", "#f7d64c"));
        cursors.add(defineMouseCursor("purple", "#cb2c7a"));

    }

    private MouseCursor getCursorByColor(String color) {
        for (MouseCursor c : activeCursorsCounter) {
            if (c.getColor().equals(color))
                return c;
        }
        return null;

    }

    private MouseCursor defineMouseCursor(String cursor, String color) {
        final MouseCursor c = new MouseCursor(cursor, color);
        c.addMouseCursorEventHandler(new Handler() {

            @Override
            public void onMouseCursorTimeout(MouseCursorTimeoutEvent event) {
                if (event.isDetached()) {
                    GWT.log("Detaching cursor " + c.getFileName());
                    String uuid = null;
                    for (String assignedCursor : assignedMouseCursors.keySet()) {
                        if (assignedMouseCursors.get(assignedCursor) == c) {
                            uuid = assignedCursor;
                            break;
                        }
                    }
                    if (uuid != null) {
                        assignedMouseCursors.remove(uuid);
                        if (storage != null)
                            storage.removeItem("ch.unifr.pai.mice.multicursor.assignedCursor." + c.getFileName());
                    }
                    if (!cursors.contains(c))
                        cursors.add(c);
                }
                activeCursorsCounter.remove(c);
                if (storage != null)
                    storage.removeItem("ch.unifr.pai.mice.multicursor.activeCursor." + c.getFileName());

            }
        });
        if (storage != null) {
            String assigneduuid = storage.getItem("ch.unifr.pai.mice.multicursor.assignedCursor." + cursor);
            if (assigneduuid != null)
                assignedMouseCursors.put(assigneduuid, c);
            String preferreduuid = storage.getItem("ch.unifr.pai.mice.multicursor.preferredCursor." + cursor);
            if (preferreduuid != null)
                preferredMouseCursors.put(preferreduuid, c);
            String activeCursor = storage.getItem("ch.unifr.pai.mice.multicursor.activeCursor." + cursor);
            if (activeCursor != null)
                activeCursorsCounter.add(c);
        }
        if (!activeCursorsCounter.contains(c))
            c.getElement().getStyle().setDisplay(Display.NONE);
        else
            c.show();
        RootPanel.get().add(c);
        return c;
    }

    HandlerRegistration r;

    public native boolean isInIFrame() /*-{
                                       return $wnd.top.location != $wnd.location;
                                       }-*/;

    @Override
    public void start() {
        if (!isInIFrame()) {
            initializeCursorList();
            if (r != null)
                r.removeHandler();
            r = Window.addResizeHandler(this);
            UrlBuilder b = Window.Location.createUrlBuilder();
            b.setProtocol("ws");
            b.setPath("mouseControlXBrowser");
            b.setHash(null);
            String p = Window.Location.getPort();
            Integer port;
            try {
                port = p != null ? Integer.parseInt(p) : 8080;
            } catch (NumberFormatException e) {
                port = 8080;
            }
            b.setPort(port + 1);
            for (String param : Window.Location.getParameterMap().keySet()) {
                b.removeParameter(param);
            }
            websocket = createWebsocket(this, b.buildString());
            if (websocket != null)
                createOnBeforeUnloadHandler(websocket);
        }
    }

    @Override
    public void stop() {
        super.stop();
        stopWebsocket(websocket);
        for (MouseCursor c : activeCursorsCounter) {
            c.hide();
        }

    }

    private native void send(JavaScriptObject websocket, String message)/*-{
                                                                        if (websocket != null)
                                                                        websocket.send(message);
                                                                        }-*/;

    private native JavaScriptObject createOnBeforeUnloadHandler(JavaScriptObject websocket)/*-{
                                                                                           $wnd.onbeforeunload = function() {
                                                                                           //$wnd.alert("CLOSE WEBSOCKET: "+websocket);
                                                                                           websocket.close();
                                                                                           }
                                                                                           }-*/;

    private native JavaScriptObject stopWebsocket(JavaScriptObject websocket)/*-{
                                                                             websocket.close();
                                                                             }-*/;

    private native JavaScriptObject createWebsocket(WebsocketControl w, String url)/*-{
                                                                                   if ("WebSocket" in $wnd) {
                                                                                   // Let us open a web socket
                                                                                   var ws = new WebSocket(url);
                                                                                   ws.onmessage = function(evt) {
                                                                                   w.@ch.unifr.pai.twice.multipointer.client.WebsocketControl::onMessage(Ljava/lang/String;)(evt.data);
                                                                                   }
                                                                                   ws.onopen = function() {
                                                                                   w.@ch.unifr.pai.twice.multipointer.client.WebsocketControl::onOpen()();
                                                                                   }
                                                                                   ws.onclose = function() {
                                                                                   w.@ch.unifr.pai.twice.multipointer.client.WebsocketControl::onClose()();
                                                                                   }
                                                                                       
                                                                                   //Add onbeforeunload to handle closing correctly in chrome
                                                                                   $wnd.onbeforeunload = function() {
                                                                                   ws.onclose = function() {
                                                                                   };
                                                                                   ws.close();
                                                                                   }
                                                                                   return ws;
                                                                                   } else {
                                                                                   $wnd
                                                                                   .alert("This browser does not support multipointer functionalities (needs websockets)!");
                                                                                   }
                                                                                       
                                                                                   return null;
                                                                                   }-*/;

    private void onMessage(String data) {
        if (data != null) {
            String[] values = data.split("@");
            if (values.length > 0) {
                String uuid = values[0];
                MouseCursor m = getOrCreateCursor(uuid);
                if (m != null) {
                    boolean isActive = activeCursorsCounter.contains(m);
                    if (activeCursorsCounter.size() < maxCursorsOnScreen || isActive) {
                        if (!isActive) {
                            activeCursorsCounter.add(m);
                            if (storage != null) {
                                storage.setItem("ch.unifr.pai.mice.multicursor.activeCursor." + m.getFileName(),
                                        "true");
                            }
                        }
                        if (values.length > 1) {
                            String action = null;
                            Map<String, String> params = new HashMap<String, String>();
                            for (int i = 1; i < values.length; i++) {
                                String[] param = values[i].split("=");
                                if (param[0].equals("a"))
                                    action = param[1];
                                else
                                    params.put(param[0], param[1]);
                            }
                            m.interpretMessage(action, params);
                        }
                    }
                }
            }
        }
    }

    private MouseCursor getOrCreateCursor(String uuid) {
        MouseCursor m = assignedMouseCursors.get(uuid);
        // If a cursor is already assigned to the uuid, return this one
        if (m != null)
            return m;
        if (cursors.size() > 0) {
            // otherwise Get the preferred mouse cursor for this uuid and check
            // if it's still available
            m = preferredMouseCursors.get(uuid);
            // If there is no preferred cursor or if the preferred cursor is
            // already in use, take another one
            if (m == null || !cursors.contains(m)) {
                m = cursors.get(0);
                preferredMouseCursors.put(uuid, m);
                if (storage != null)
                    storage.setItem("ch.unifr.pai.mice.multicursor.preferredCursor." + m.getFileName(), uuid);
            }
            m.setUuid(uuid);
            cursors.remove(m);
            assignedMouseCursors.put(uuid, m);
            if (storage != null)
                storage.setItem("ch.unifr.pai.mice.multicursor.assignedCursor." + m.getFileName(), uuid);
            if (opened && websocket != null) {
                send(websocket, UUID.get() + "@c@" + uuid + "@" + m.getColor());
            }
            return m;
        }
        return null;
    }

    private void onOpen() {
        this.opened = true;
        send(websocket, UUID.get() + "@s@" + Window.getClientWidth() + "@" + Window.getClientHeight());
        // Window.alert("Multi cursor control started!");
    }

    private void onClose() {
        if (!opened) {
            Window.alert("The websocket server is not reachable!");
        } else {
            opened = false;
            // Window.alert("Stopping multi cursor control!");
        }
    }

    @Override
    public void onResize(ResizeEvent event) {
        if (opened && websocket != null) {
            send(websocket, UUID.get() + "@r@" + Window.getClientWidth() + "@" + Window.getClientHeight());
        }
    }

    @Override
    public void notifyCursor(String uuid, String action) {
        send(websocket, UUID.get() + "@" + action + "@" + uuid);
    }

}