org.n52.client.sos.ctrl.DragImageControl.java Source code

Java tutorial

Introduction

Here is the source code for org.n52.client.sos.ctrl.DragImageControl.java

Source

/**
 * Copyright (C) 2012-2014 52North Initiative for Geospatial Open Source
 * Software GmbH
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2 as publishedby the Free
 * Software Foundation.
 *
 * If the program is linked with libraries which are licensed under one of the
 * following licenses, the combination of the program with the linked library is
 * not considered a "derivative work" of the program:
 *
 *     - Apache License, version 2.0
 *     - Apache Software License, version 1.0
 *     - GNU Lesser General Public License, version 3
 *     - Mozilla Public License, versions 1.0, 1.1 and 2.0
 *     - Common Development and Distribution License (CDDL), version 1.0
 *
 * Therefore the distribution of the program linked with libraries licensed under
 * the aforementioned licenses, is permitted by the copyright holders if the
 * distribution is compliant with both the GNU General Public License version 2
 * and the aforementioned licenses.
 *
 * This program 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.
 */
package org.n52.client.sos.ctrl;

/*
 * Copyright 2010 EES 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.
 */

import org.eesgmbh.gimv.client.event.ChangeImagePixelBoundsEvent;
import org.eesgmbh.gimv.client.event.LoadImageDataEvent;
import org.eesgmbh.gimv.client.event.SetDomainBoundsEvent;
import org.eesgmbh.gimv.client.event.SetDomainBoundsEventHandler;
import org.eesgmbh.gimv.client.event.SetMaxDomainBoundsEvent;
import org.eesgmbh.gimv.client.event.SetMaxDomainBoundsEventHandler;
import org.eesgmbh.gimv.client.event.StateChangeEvent;
import org.eesgmbh.gimv.client.event.StateChangeEventHandler;
import org.eesgmbh.gimv.client.event.ViewportDragFinishedEvent;
import org.eesgmbh.gimv.client.event.ViewportDragFinishedEventHandler;
import org.eesgmbh.gimv.client.event.ViewportDragInProgressEvent;
import org.eesgmbh.gimv.client.event.ViewportDragInProgressEventHandler;
import org.eesgmbh.gimv.client.presenter.ZoomBoxPresenter;
import org.eesgmbh.gimv.shared.util.Bounds;
import org.n52.client.sos.event.data.SwitchAutoscaleEvent;

import com.google.gwt.event.shared.HandlerManager;

/**
 * This control will change the image position within the viewport when the user
 * moves the mouse over the viewport with the left mouse button down (dragging).
 * 
 * <p>
 * After the user stopped dragging, new image data with the new domain bounds is
 * requested.
 * 
 * <p>
 * This control must be activated or deactivated with a {@link StateChangeEvent}
 * . The reason behind the mandatory activation is, that dragging can both mean
 * zooming or moving the image. Only this control or the
 * {@link ZoomBoxPresenter} can be active at the same time.
 * 
 * <p>
 * Registers with the {@link HandlerManager} to receive the following events
 * <ul>
 * <li> {@link ViewportDragInProgressEvent} (the control changes the image
 * position accordingly)
 * <li> {@link ViewportDragFinishedEvent} (will trigger a
 * {@link SetDomainBoundsEvent} and a {@link LoadImageDataEvent} )
 * <li> {@link SetDomainBoundsEvent} (mandatory, won't work otherwise)
 * <li> {@link StateChangeEvent} (must be set to move for the control to do
 * something)
 * <li> {@link SetMaxDomainBoundsEvent} (optional, if not received, there will be
 * no restriction)
 * </ul>
 * 
 * <p>
 * Fires the following events
 * <ul>
 * <li> {@link ChangeImagePixelBoundsEvent} fired on each
 * {@link ViewportDragInProgressEvent}
 * <li> {@link SetDomainBoundsEvent} fired after recieving
 * {@link ViewportDragFinishedEvent} with the new domain bounds
 * <li> {@link LoadImageDataEvent} fired after recieving
 * {@link ViewportDragFinishedEvent}
 * </ul>
 * 
 * @author Christian Seewald - EES GmbH - c.seewald@ees-gmbh.de
 */
public class DragImageControl {

    private final HandlerManager handlerManager;

    private boolean fireLoadImageDataEvent;

    private boolean active;

    private Bounds currentDomainBounds;

    private SetMaxDomainBoundsEvent currentMaxDomainBounds;

    /**
     * Registers with the handlerManager to receive all required events.
     * 
     * @param handlerManager
     *            A {@link HandlerManager}
     */
    public DragImageControl(HandlerManager handlerManager) {
        this.handlerManager = handlerManager;

        DragImageControlEventHandler eventHandler = new DragImageControlEventHandler();
        handlerManager.addHandler(ViewportDragInProgressEvent.TYPE, eventHandler);
        handlerManager.addHandler(ViewportDragFinishedEvent.TYPE, eventHandler);
        handlerManager.addHandler(SetDomainBoundsEvent.TYPE, eventHandler);
        handlerManager.addHandler(SetMaxDomainBoundsEvent.TYPE, eventHandler);
        handlerManager.addHandler(StateChangeEvent.TYPE, eventHandler);

        setFireLoadImageDataEvent(true);
    }

    /**
     * <p>
     * Specify whether a {@link LoadImageDataEvent} will be fired after a drag
     * is completed.
     * 
     * <p>
     * Default is true.
     * 
     * @param fireLoadImageDataEvent
     *            fire it, or not
     */
    public void setFireLoadImageDataEvent(boolean fireLoadImageDataEvent) {
        this.fireLoadImageDataEvent = fireLoadImageDataEvent;
    }

    private void onStateChange(StateChangeEvent event) {
        this.active = event.isMove();
    }

    private void onDragInProgress(ViewportDragInProgressEvent event) {
        if (this.active) {
            this.handlerManager.fireEvent(new ChangeImagePixelBoundsEvent(event.getHorizontalDragOffset(),
                    event.getVerticalDragOffset()));
        }
    }

    private void onDragFinished(ViewportDragFinishedEvent event) {
        if (this.active) {
            if (this.currentDomainBounds != null) {
                double xOffsetProp = -event.getProportionalBounds().getWidth();
                double yOffsetProp = -event.getProportionalBounds().getHeight();

                // constraining to max bounds
                Bounds newBounds = this.currentDomainBounds;

                if (this.currentMaxDomainBounds == null || this.currentMaxDomainBounds.containsHorizontally(
                        this.currentDomainBounds.shiftProportional(xOffsetProp, 0).getLeft(),
                        this.currentDomainBounds.shiftProportional(xOffsetProp, 0).getRight())) {
                    newBounds = newBounds.shiftProportional(xOffsetProp, 0);
                }

                if (this.currentMaxDomainBounds == null || this.currentMaxDomainBounds.containsVertically(
                        this.currentDomainBounds.shiftProportional(0, yOffsetProp).getTop(),
                        this.currentDomainBounds.shiftProportional(0, yOffsetProp).getBottom())) {
                    newBounds = newBounds.shiftProportional(0, yOffsetProp);
                }

                this.handlerManager.fireEvent(new SwitchAutoscaleEvent(false));

                this.handlerManager.fireEvent(new SetDomainBoundsEvent(newBounds));

                if (this.fireLoadImageDataEvent) {
                    this.handlerManager.fireEvent(new LoadImageDataEvent());
                }
            }
        }
    }

    private void onSetDomainBounds(SetDomainBoundsEvent event) {
        this.currentDomainBounds = event.getBounds();
    }

    private void onSetMaxDomainBounds(SetMaxDomainBoundsEvent event) {
        this.currentMaxDomainBounds = event;
    }

    private class DragImageControlEventHandler
            implements ViewportDragInProgressEventHandler, ViewportDragFinishedEventHandler,
            SetDomainBoundsEventHandler, SetMaxDomainBoundsEventHandler, StateChangeEventHandler {
        public void onDragInProgress(ViewportDragInProgressEvent event) {
            DragImageControl.this.onDragInProgress(event);
        }

        public void onDragFinished(ViewportDragFinishedEvent event) {
            DragImageControl.this.onDragFinished(event);
        }

        public void onSetDomainBounds(SetDomainBoundsEvent event) {
            DragImageControl.this.onSetDomainBounds(event);
        }

        public void onSetMaxDomainBounds(SetMaxDomainBoundsEvent event) {
            DragImageControl.this.onSetMaxDomainBounds(event);
        }

        public void onStateChange(StateChangeEvent event) {
            DragImageControl.this.onStateChange(event);
        }
    }
}