package ch.unifr.pai.twice.widgets.mpproxy.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.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import ch.unifr.pai.twice.multipointer.client.MultiCursorController; import ch.unifr.pai.twice.multipointer.client.WebsocketControl; import ch.unifr.pai.twice.multipointer.client.widgets.MultiFocusTextBox; import com.google.gwt.dom.client.InputElement; import com.google.gwt.dom.client.NodeList; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.TextBoxBase; /** * Multipointer extension of the {@link ProxyBody} * * @author Oliver Schmid * */ public class MPProxyBody extends ProxyBody { private static TextBox hiddenTextBoxForFocusControl = new TextBox(); private final String[] colors = { "red", "green", "blue", "yellow" }; private final Map<String, String> deviceToColor = new HashMap<String, String>(); private final int currentColorIndex = -1; private static Map<String, TextBoxBase> focusedElement = new HashMap<String, TextBoxBase>(); private static Set<String> owningDevices = new HashSet<String>(); private final MultiCursorController multiCursor = new WebsocketControl(); /** * Replace all textboxes with multi focus text boxes * * @param mainElement */ private void replaceAllTextBoxes(Element mainElement) { NodeList<com.google.gwt.dom.client.Element> inputFields = mainElement.getElementsByTagName("input"); for (int i = 0; i < inputFields.getLength(); i++) { final com.google.gwt.dom.client.Element el = inputFields.getItem(i); String type = el.getAttribute("type"); if (type == null || type.isEmpty() || type.equalsIgnoreCase("text")) { MultiFocusTextBox box = new MultiFocusTextBox(); box.replaceTextInput(InputElement.as(el)); replacements.add(box); // Scheduler.get().scheduleDeferred(new ScheduledCommand() { // // @Override // public void execute() { // el.getStyle().setDisplay(Display.NONE); // } // }); } } } @Override public void initialize() { // multiCursor.start(); super.initialize(); replaceAllTextBoxes(RootPanel.getBodyElement()); // // hiddenTextBoxForFocusControl.setHeight("0px"); // // hiddenTextBoxForFocusControl.setWidth("0px"); // // hiddenTextBoxForFocusControl.getElement().getStyle() // // .setPosition(Position.ABSOLUTE); // // hiddenTextBoxForFocusControl.getElement().getStyle().setZIndex(-1); // // hiddenTextBoxForFocusControl.getElement().getStyle().setTop(0, Unit.PX); // // hiddenTextBoxForFocusControl.getElement().getStyle() // // .setLeft(0, Unit.PX); // // RootPanel.get().add(hiddenTextBoxForFocusControl); // Event.addNativePreviewHandler(new NativePreviewHandler() { // public void onPreviewNativeEvent(NativePreviewEvent event) { // // // boolean doProcess = true; // // // // // Block all mouse events which are not originated from a // // // owningDevice (if defined) // // switch (event.getTypeInt()) { // // case Event.ONCLICK: // // case Event.ONMOUSEOVER: // // case Event.ONMOUSEUP: // // case Event.ONMOUSEDOWN: // // case Event.ONMOUSEMOVE: // // case Event.ONMOUSEOUT: // // case Event.ONDBLCLICK: // // case Event.ONMOUSEWHEEL: // // String device = MultiCursorController.getUUIDNative(event // // .getNativeEvent()); // // if (owningDevices != null && owningDevices.size() > 0 // // && !owningDevices.contains(device)) { // // doProcess = false; // // event.cancel(); // // event.getNativeEvent().preventDefault(); // // } // // break; // // } // // // if (doProcess) { // // Record the currently focused element per device // switch (event.getTypeInt()) { // case Event.ONMOUSEUP: // case Event.ONMOUSEDOWN: // case Event.ONCLICK: // Element e = event.getNativeEvent().getEventTarget() // .<Element> cast(); // TextBoxBase base = getTextBoxBase(e); // TextBoxBase old = focusedElement // .remove(MultiCursorController.getUUIDNative(event // .getNativeEvent())); // if (old != null) { // old.getElement().getStyle().clearBorderColor(); // RootPanel.detachNow(old); // } // if (base != null) { // String device = MultiCursorController.getUUIDNative(event // .getNativeEvent()); // focusedElement.put(device, base); // String color = deviceToColor.get(device); // if (color == null) { // if (currentColorIndex > -1 // && currentColorIndex < colors.length - 2) { // color = colors[currentColorIndex]; // currentColorIndex++; // } else { // color = colors[0]; // currentColorIndex = 0; // } // deviceToColor.put(device, color); // } // // base.getElement().getStyle() // .setBorderStyle(BorderStyle.SOLID); // base.getElement().getStyle() // .setBorderWidth(1, Unit.PX); // base.getElement().getStyle().setBorderColor(color); // // event.cancel(); // // event.getNativeEvent().preventDefault(); // // DomEvent.fireNativeEvent(Document.get().createMouseDownEvent(0, // // 0, 0, 0, 0, false, false, false, false, 0), // // hiddenTextBoxForFocusControl); // } // break; // } // } // } // // }); // // // Scheduler.get().scheduleDeferred(new ScheduledCommand() { // // // // @Override // // public void execute() { // // hiddenTextBoxForFocusControl.setFocus(true); // // } // // }); } /** * Expose the deviceOwnership to JavaScript * * @param devices */ private static void setOwningDevices(String devices) { owningDevices.clear(); if (devices != null && !devices.isEmpty()) { for (String s : devices.split(",")) { owningDevices.add(s); } } // If a device no longer owns the frame, it does not have any focused // element anymore. if (!owningDevices.isEmpty()) { for (String current : focusedElement.keySet()) { if (!owningDevices.contains(current)) { focusedElement.remove(current); } } } } /** * @param e * @return a textbox or textarea widget if the element is one of those, otherwise null */ private TextBoxBase getTextBoxBase(Element e) { if (e.getTagName().equalsIgnoreCase("input") && (e.getAttribute("type") == null || e.getAttribute("type").isEmpty() || e.getAttribute("type").equalsIgnoreCase("text"))) return TextBox.wrap(e); else if (e.getTagName().equalsIgnoreCase("textarea")) return TextArea.wrap(e); return null; } /** * Set up the JS-callable signature as a global JS function. * */ private native void publishInterfaces() /*-{ $wnd.miceSetOwningDevices = @ch.unifr.pai.twice.widgets.mpproxy.client.MPProxyBody::setOwningDevices(Ljava/lang/String;); $wnd.backInHistory = @com.google.gwt.user.client.History::back(); $wnd.forwardInHistory = @com.google.gwt.user.client.History::forward(); $wnd.reloadFrame = @com.google.gwt.user.client.Window.Location::reload(); }-*/; }