de.swm.commons.mobile.client.widgets.FlipSwitch.java Source code

Java tutorial

Introduction

Here is the source code for de.swm.commons.mobile.client.widgets.FlipSwitch.java

Source

/*
 * Copyright 2011 SWM Services GmbH.
 * 
 * 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.
 */
package de.swm.commons.mobile.client.widgets;

import com.google.gwt.dom.client.Element;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.editor.client.adapters.TakesValueEditor;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasValue;
import de.swm.commons.mobile.client.SWMMobile;
import de.swm.commons.mobile.client.event.DragController;
import de.swm.commons.mobile.client.event.DragEvent;
import de.swm.commons.mobile.client.event.DragEventsHandler;
import de.swm.commons.mobile.client.utils.Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
 * Flip-Switch (boolean widget) with data binding.
 * 
 */
public class FlipSwitch extends SWMMobileWidgetBase
        implements DragEventsHandler, ClickHandler, HasValueChangeHandlers<Boolean>,
        IsEditor<LeafValueEditor<Boolean>>, HasValue<Boolean>, HasClickHandlers, HasFocusHandlers, HasBlurHandlers {

    private static final Logger LOGGER = Logger.getLogger(FlipSwitch.class.getName());

    private static final int DURATION = 200;
    private static final double MIDDLE = 0.5;
    protected boolean myEnabled = true;
    protected boolean myValue = true;
    protected final HTML myHtml = new HTML();
    private LeafValueEditor<Boolean> editor;
    private final List<DragEventsHandler> dragHandlers = new ArrayList<DragEventsHandler>();
    private String option1 = "On";
    private String option2 = "Off";

    /**
     * Default constructor.
     */
    public FlipSwitch() {
        initWidget(myHtml);
        setStyleName(SWMMobile.getTheme().getMGWTCssBundle().getFlipSwitchCss().flipSwitch());
        myHtml.addClickHandler(this);
        updateUI();
    }

    private void updateUI() {
        myHtml.setHTML("<div></div><div></div><div><div><div>" + this.option1 + "</div><div></div><div>"
                + this.option2 + "</div></div></div>");
    }

    @Override
    public void onInitialLoad() {
        super.onInitialLoad();
        if (!myValue) {
            updateFlipPosition(0);
        }
    }

    @Override
    public void onLoad() {
        super.onLoad();
        DragController.get().addDragEventsHandler(this);
    }

    @Override
    public void onUnload() {
        DragController.get().removeDragEventsHandler(this);
    }

    @Override
    public void onDragStart(DragEvent e) {
        if (!myEnabled) {
            return;
        }
        DragController.get().captureDragEvents(this);
        Utils.setTransitionDuration(getFilpElement(), 0);
        for (DragEventsHandler toNotify : this.dragHandlers) {
            toNotify.onDragStart(e);
        }
    }

    @Override
    public void onDragMove(DragEvent e) {
        if (!myEnabled) {
            return;
        }
        e.stopPropagation();
        Element flip = getFilpElement();
        int x = Utils.getTranslateX(flip);
        int newX = (int) (x + e.getOffsetX());
        int onPosition = getOnPosition();
        int offPosition = getOffPosition();
        if (newX > onPosition) {
            newX = onPosition;
        } else if (newX < offPosition) {
            newX = offPosition;
        }
        if (newX != x) {
            Utils.setTranslateX(flip, newX);
        }

        for (DragEventsHandler toNotify : this.dragHandlers) {
            toNotify.onDragMove(e);
        }
    }

    @Override
    public void onDragEnd(DragEvent e) {
        if (!myEnabled) {
            return;
        }
        DragController.get().releaseDragCapture(this);
        Element flip = getFilpElement();
        int x = Utils.getTranslateX(flip);
        int onPosition = getOnPosition();
        int offPosition = getOffPosition();
        if (x == onPosition) {
            setValue(true, false, 0, true);
        } else if (x == offPosition) {
            setValue(false, false, 0, true);
        } else {
            float ratio = (float) x / (float) (offPosition - onPosition);
            boolean newValue = ratio < MIDDLE;
            int duration = (int) ((MIDDLE - Math.abs(ratio - MIDDLE)) * DURATION);
            LOGGER.info("ratio " + ratio + " duration " + duration);
            setValue(newValue, true, duration, true);
        }

        for (DragEventsHandler toNotify : this.dragHandlers) {
            toNotify.onDragEnd(e);
        }
    }

    /**
     * Manually sets the value.
     * 
     * @param value
     *            the new value
     * @param forceUpdateFlipPosition
     *            tue updated the position
     * @param duration
     *            the duration af the animation in ms
     */
    private void setValue(boolean value, boolean forceUpdateFlipPosition, int duration, boolean fireEvents) {
        if (myValue != value) {
            myValue = value;
            updateFlipPosition(duration);
            if (fireEvents) {
                ValueChangeEvent.fire(this, myValue);
            }
        } else if (forceUpdateFlipPosition) {
            updateFlipPosition(duration);
        }
    }

    public boolean isEnabled() {
        return myEnabled;
    }

    /**
     * Enables/disables the widget.
     * 
     * @param enabled
     *            true if enabled.
     */
    public void setEnabled(boolean enabled) {
        if (enabled == myEnabled) {
            return;
        }
        if (enabled) {
            removeStyleName(SWMMobile.getTheme().getMGWTCssBundle().getFlipSwitchCss().disabled());
        } else {
            addStyleName(SWMMobile.getTheme().getMGWTCssBundle().getFlipSwitchCss().disabled());
        }
        myEnabled = enabled;
    }

    @Override
    public void onClick(ClickEvent event) {
        if (myEnabled) {
            setValue(!myValue);
        }
    }

    /**
     * Updates the flip position.
     * 
     * @param duration
     *            the duration of the animation
     */
    private void updateFlipPosition(int duration) {
        Utils.setTransitionDuration(getFilpElement(), duration);
        Element flip = getFilpElement();
        if (myValue) {
            Utils.setTranslateX(flip, getOnPosition());
        } else {
            Utils.setTranslateX(flip, getOffPosition());
        }
    }

    private Element getFilpElement() {
        return (Element) getElement().getChild(2).getChild(0);
    }

    private int getOnPosition() {
        return 0;
    }

    /**
     * Returns the absolute off potion
     * 
     * @return the sreen postion
     */
    private int getOffPosition() {
        Element flip = getFilpElement();
        Element parent = flip.getParentElement();
        int flipWidth = flip.getScrollWidth();
        int parentWidth = parent.getClientWidth();
        return parentWidth - flipWidth;
    }

    @Override
    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Boolean> handler) {
        return this.addHandler(handler, ValueChangeEvent.getType());
    }

    @Override
    public LeafValueEditor<Boolean> asEditor() {
        if (editor == null) {
            editor = TakesValueEditor.of(this);
        }
        return editor;
    }

    @Override
    public void setValue(Boolean value) {
        if (value != null) {
            setValue(value, false, DURATION, true);
        }

    }

    @Override
    public void setValue(Boolean value, boolean fireEvents) {
        this.setValue(value, true, DURATION, fireEvents);
    }

    public Boolean getValue() {
        return myValue;
    }

    @Override
    public HandlerRegistration addClickHandler(ClickHandler handler) {
        return myHtml.addClickHandler(handler);
    }

    /**
     * Add a drag handler to the widget.
     * 
     * @param hanlder
     *            a drag handler.
     * @return the drag handler.
     */
    public HandlerRegistration addDragHandler(final DragEventsHandler hanlder) {
        HandlerRegistration registration = new HandlerRegistration() {

            @Override
            public void removeHandler() {
                dragHandlers.remove(hanlder);
            }
        };

        dragHandlers.add(hanlder);
        return registration;
    }

    @Override
    public HandlerRegistration addBlurHandler(BlurHandler handler) {
        return myHtml.addDomHandler(handler, BlurEvent.getType());
    }

    @Override
    public HandlerRegistration addFocusHandler(FocusHandler handler) {
        return myHtml.addDomHandler(handler, FocusEvent.getType());
    }

    /**
     * Gets the Name of the second option.
     * @return the String of the second option.
     */
    public String getOption2() {
        return option2;
    }

    /**
     * Sets the Name of the second option.
     * @param option2 the String of the second option.
     */
    public void setOption2(String option2) {
        this.option2 = option2;
        this.updateUI();
    }

    /**
     * Gets the Name of the first option.
     * @return the String of the first option.
     */
    public String getOption1() {
        return option1;
    }

    /**
     * Gets the Name of the first option.
     * @param option1 the String of the first option.
     */
    public void setOption1(String option1) {
        this.option1 = option1;
        this.updateUI();
    }
}