ch.unifr.pai.twice.layout.client.mobile.MobileInterface.java Source code

Java tutorial

Introduction

Here is the source code for ch.unifr.pai.twice.layout.client.mobile.MobileInterface.java

Source

package ch.unifr.pai.twice.layout.client.mobile;

/*
 * 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.LinkedHashMap;
import java.util.Map;

import ch.unifr.pai.twice.layout.client.DynamicLayout;
import ch.unifr.pai.twice.module.client.TWICEModule;
import ch.unifr.pai.twice.module.client.TWICEModuleController;
import ch.unifr.pai.twice.mousecontrol.client.MobileKeyboard;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Float;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimpleLayoutPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * The mobile layout mechanism logic. The mobile layout contains a menu bar on the top, displaying a button on the top left to open a menu. The menu appears
 * from the left and presents the different components which are available. There is always only one
 * 
 * @author Oliver Schmid
 * 
 */
public class MobileInterface {
    static MobileResourceBundle RESOURCES = GWT.create(MobileResourceBundle.class);

    SimpleLayoutPanel main = new SimpleLayoutPanel();
    private final static Map<String, Widget> components = new LinkedHashMap<String, Widget>();
    private final static Map<String, AsyncCallback<Widget>> callbacks = new LinkedHashMap<String, AsyncCallback<Widget>>();
    private static String currentcomponentname;
    private final FlowPanel controlbar = new FlowPanel();
    Menu menu = new Menu();
    Button others = new Button();

    private final MobileKeyboard keyboardButton = new MobileKeyboard();
    private final Button hideKeyboard = new Button();
    private final AbsolutePanel keyboardPanel = new AbsolutePanel();

    /**
     * Initializes the main components
     */
    public MobileInterface() {
        RESOURCES.mobileLayoutStyle().ensureInjected();
        controlbar.setStyleName("controlbar");
        others.setStyleName(RESOURCES.mobileLayoutStyle().menuButton());
        others.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                menu.show();
            }
        });
        others.getElement().getStyle().setDisplay(Display.INLINE);
        others.setWidth("auto");
        others.getElement().getStyle().setFloat(Float.LEFT);
        keyboardPanel.getElement().getStyle().setFloat(Float.RIGHT);
        keyboardButton.addStyleName("mobileKeyboard");
        hideKeyboard.addStyleName("mobileKeyboard");
        keyboardPanel.add(hideKeyboard);
        keyboardPanel.add(keyboardButton);
        // hideKeyboard.setWidth("50px");
        // hideKeyboard.setHeight("100%");
        // keyboardButton.setWidth("50px");
        // keyboardButton.setHeight("50px");
        // keyboardPanel.setWidgetPosition(hideKeyboard, 0, 0);
        // keyboardPanel.setWidgetPosition(keyboardButton, 0, 0);
        hideKeyboard.getElement().getStyle().setDisplay(Display.NONE);
        keyboardButton.addFocusHandler(new FocusHandler() {

            @Override
            public void onFocus(FocusEvent event) {
                hideKeyboard.getElement().getStyle().setDisplay(Display.BLOCK);
                keyboardButton.getElement().getStyle().setDisplay(Display.NONE);
            }
        });
        keyboardButton.addBlurHandler(new BlurHandler() {

            @Override
            public void onBlur(BlurEvent event) {
                hideKeyboard.getElement().getStyle().setDisplay(Display.NONE);
                keyboardButton.setValue(null);
                keyboardButton.getElement().getStyle().setDisplay(Display.BLOCK);

            }
        });
        hideKeyboard.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                hideKeyboard.getElement().getStyle().setDisplay(Display.NONE);
                keyboardButton.setValue(null);
                keyboardButton.getElement().getStyle().setDisplay(Display.BLOCK);

            }
        });
        controlbar.add(others);
        controlbar.add(keyboardPanel);
    }

    /**
     * Adds the top bar to the layout
     */
    private void addControlBar() {
        DynamicLayout.getPanel().add(controlbar);
        controlbar.getElement().getStyle().setTop(0, Unit.PX);
        controlbar.getElement().getStyle().setHeight(40, Unit.PX);
        controlbar.getElement().getStyle().setLeft(0, Unit.PX);
        controlbar.getElement().getStyle().setRight(0, Unit.PX);
        controlbar.getElement().getStyle().setPosition(Position.ABSOLUTE);
        controlbar.getElement().getStyle().setDisplay(Display.BLOCK);
        currentWidget.getElement().getStyle().setMarginTop(40, Unit.PX);
    }

    private Widget currentWidget;

    /**
     * Switch to a specific component ({@link TWICEModule}). If the module has not been accessed yet, it is instantiated and the callback is invoked.
     * 
     * @param componentName
     */
    void switchComponent(String componentName) {
        RootLayoutPanel.get().clear();
        if (componentName == null && components.keySet().size() > 0) {
            componentName = (String) components.keySet().toArray()[0];
        }
        // Is it a not yet instantiated module?
        final TWICEModule module = modules.get(componentName);
        if (module != null) {
            // Then instantiate it and add it to the components
            final String moduleComponentName = componentName;
            TWICEModuleController.instantiateModule(module, new AsyncCallback<Widget>() {

                @Override
                public void onSuccess(Widget result) {
                    if (currentWidget != null)
                        TWICEModuleController.stop(currentWidget);
                    components.put(moduleComponentName, result);
                    modules.remove(moduleComponentName);
                    AsyncCallback<Widget> callback = callbacks.get(moduleComponentName);
                    if (callback != null) {
                        callback.onSuccess(result);
                    }
                    switchToWidget(moduleComponentName, result);
                }

                @Override
                public void onFailure(Throwable caught) {
                    Window.alert("Was not able to initialize module " + moduleComponentName);
                }
            });
        } else {
            Widget w = components.get(componentName);
            if (w == null && components.size() > 0) {
                componentName = (String) components.keySet().toArray()[0];
                w = components.get(componentName);
            }
            switchToWidget(componentName, w);

        }
    }

    /**
     * Hide the current widget if there is one and show the given component on the single screen
     * 
     * @param componentName
     * @param w
     */
    private void switchToWidget(String componentName, Widget w) {
        if (w != null) {
            boolean issamewidget = currentWidget == w;
            if (currentWidget != null) {
                if (!issamewidget)
                    TWICEModuleController.stop(currentWidget);
                currentWidget.removeFromParent();
            }
            currentWidget = w;
            currentcomponentname = componentName;
            TWICEModule m = TWICEModuleController.getTWICEModule(currentWidget);
            if (m != null && m.attachToRootPanel(currentWidget)) {
                RootPanel.get().add(w);
            } else {
                RootLayoutPanel.get().add(w);
            }
            if (!issamewidget)
                TWICEModuleController.start(currentWidget);
        }
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {

            @Override
            public void execute() {
                addControlBar();
            }
        });
    }

    boolean initialized;

    /**
     * Adds a component - if it is the first one, it will be directly shown on the main screen (initialized)
     * 
     * @param componentName
     * @param component
     */
    public void addComponent(String componentName, Widget component) {
        components.put(componentName, component);
        if (!initialized) {
            switchComponent(componentName);
            initialized = true;
        }
        // menu.addEntry(componentName);
    }

    /**
     * A map of registered modules (used to lookup for lazy instantiation)
     */
    private static Map<String, TWICEModule<? extends Widget>> modules = new LinkedHashMap<String, TWICEModule<? extends Widget>>();

    /**
     * Adds the module with the given name to the layout
     * 
     * @param moduleName
     * @param module
     * @param callback
     */
    public void addModule(String moduleName, TWICEModule<? extends Widget> module,
            AsyncCallback<? extends Widget> callback) {
        modules.put(moduleName, module);
        components.put(moduleName, null);
        callbacks.put(moduleName, (AsyncCallback<Widget>) callback);
    }

    /**
     * The menu that appears from the left if the menu button is pressed
     * 
     * @author Oliver Schmid
     * 
     */
    public class Menu extends FlowPanel {
        Map<String, Label> menuButtons = new HashMap<String, Label>();

        public Menu() {
            // setWidth("240px");
            addStyleName(RESOURCES.mobileLayoutStyle().menu());
            // getElement().getStyle().setHeight(100, Unit.PCT);
            // getElement().getStyle().setBackgroundColor("#2E2E2E");
            // getElement().getStyle().setZIndex(10001);
            // getElement().getStyle().setBorderWidth(0, Unit.PX);

        }

        /**
         * Hide the menu
         */
        public void hide() {
            removeFromParent();
        }

        /**
         * Show the menu
         */
        public void show() {

            clear();
            for (String s : components.keySet()) {
                final String name = s;
                final Label b = new Label(name);
                menuButtons.put(name, b);
                b.getElement().getStyle().setColor("#ffffff");
                b.getElement().getStyle().setFontSize(16, Unit.PX);
                b.getElement().getStyle().setMargin(5, Unit.PX);
                b.getElement().getStyle().setPadding(10, Unit.PX);
                b.addClickHandler(new ClickHandler() {

                    @Override
                    public void onClick(ClickEvent event) {
                        if (currentcomponentname != null) {
                            Label old = menuButtons.get(currentcomponentname);
                            if (old != null)
                                old.removeStyleName(RESOURCES.mobileLayoutStyle().selectedMenuEntry());
                        }
                        switchComponent(name);
                        b.setStyleName(RESOURCES.mobileLayoutStyle().selectedMenuEntry());
                        Menu.this.hide();
                    }
                });
                if (s.equals(currentcomponentname)) {
                    b.setStyleName(RESOURCES.mobileLayoutStyle().selectedMenuEntry());
                }
                add(b);
            }
            if (currentWidget != null) {
                currentWidget.getElement().getStyle().setLeft(240, Unit.PX);
            }
            controlbar.getElement().getStyle().setLeft(240, Unit.PX);
            DynamicLayout.getPanel().add(this);
        }
    }

}