io.apiman.manager.ui.client.local.services.MouseOverService.java Source code

Java tutorial

Introduction

Here is the source code for io.apiman.manager.ui.client.local.services.MouseOverService.java

Source

/*
 * Copyright 2015 JBoss Inc
 *
 * 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 io.apiman.manager.ui.client.local.services;

import io.apiman.manager.ui.client.local.events.MouseInEvent;
import io.apiman.manager.ui.client.local.events.MouseOutEvent;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.ScrollEvent;
import com.google.gwt.user.client.Window.ScrollHandler;
import com.google.gwt.user.client.ui.Widget;

/**
 * A service that allows widgets to register for mouse-in and
 * mouse-out events.  This is here because the built-in support
 * for mouse-in and mouse-out in GWT is not bullet-proof.  Sometimes
 * you can get the mouse-in event but not the mouse-out event.
 * 
 * This service watches the mouse move around the screen (captures
 * all mouse movement) and then does its own calculations and
 * tracking.
 *
 * @author eric.wittmann@redhat.com
 */
@ApplicationScoped
public class MouseOverService {

    @Inject
    LoggerService logger;

    private Map<Widget, WidgetMouseTrackingInfo> enabledWidgets = new HashMap<Widget, WidgetMouseTrackingInfo>();

    /**
     * Constructor.
     */
    public MouseOverService() {
    }

    @PostConstruct
    protected void postConstruct() {
        Event.addNativePreviewHandler(new NativePreviewHandler() {
            @Override
            public void onPreviewNativeEvent(NativePreviewEvent event) {
                if (event.getTypeInt() == Event.ONMOUSEMOVE) {
                    int x = event.getNativeEvent().getClientX();
                    int y = event.getNativeEvent().getClientY();
                    handleMouseMove(x, y);
                }
            }
        });
        Window.addWindowScrollHandler(new ScrollHandler() {
            @Override
            public void onWindowScroll(ScrollEvent event) {
                clearAll();
            }
        });
        Window.addResizeHandler(new ResizeHandler() {
            @Override
            public void onResize(ResizeEvent event) {
                clearAll();
            }
        });
    }

    /**
     * Called to enable mouse-in and mouse-out events for a 
     * given widget.
     * @param widget
     */
    public void enableMouseEvents(final Widget widget) {
        enableMouseEvents(widget, null);
    }

    /**
     * Called to enable mouse-in and mouse-out events for a 
     * given widget.
     * @param widget
     * @param tracking
     */
    public void enableMouseEvents(final Widget widget, final WidgetMouseTrackingInfo tracking) {
        widget.addAttachHandler(new AttachEvent.Handler() {
            @Override
            public void onAttachOrDetach(AttachEvent event) {
                if (event.isAttached()) {
                    enabledWidgets.put(widget, tracking == null ? new WidgetMouseTrackingInfo() : tracking);
                } else {
                    enabledWidgets.remove(widget);
                }
            }
        });
    }

    /**
     * Called when the service spies on a native mouse movement event.
     * @param clientX
     * @param clientY
     */
    private void handleMouseMove(int clientX, int clientY) {
        for (Entry<Widget, WidgetMouseTrackingInfo> entry : enabledWidgets.entrySet()) {
            Widget w = entry.getKey();
            WidgetMouseTrackingInfo info = entry.getValue();
            if (isMouseInWidget(w, info, clientX, clientY)) {
                if (!info.mouseIn) {
                    info.mouseIn = true;
                    MouseInEvent.fire(w);
                }
            } else {
                if (info.mouseIn) {
                    info.mouseIn = false;
                    MouseOutEvent.fire(w);
                }
            }
        }
    }

    /**
     * Returns true if the mouse coordinates fall within the bounding box
     * of the given widget.
     * @param w
     * @param info 
     * @param clientX
     * @param clientY
     */
    private boolean isMouseInWidget(Widget w, WidgetMouseTrackingInfo info, int clientX, int clientY) {
        try {
            int top = w.getElement().getAbsoluteTop() - Window.getScrollTop() - info.extraTop;
            int bottom = top + w.getElement().getClientHeight() + info.extraBottom;
            int left = w.getElement().getAbsoluteLeft() - Window.getScrollLeft() - info.extraLeft;
            int right = left + w.getElement().getClientWidth() + info.extraRight;

            //            logger.info("Client: {0},{1}  Widget: {2},{3} -> {4},{5}", clientX, clientY, left, top, right, bottom);

            return clientX >= left && clientX <= right && clientY >= top && clientY <= bottom;
        } catch (Throwable t) {
            return false;
        }
    }

    /**
     * Clear the mouse-in info for all tracked widgets.
     */
    protected void clearAll() {
        for (Entry<Widget, WidgetMouseTrackingInfo> entry : enabledWidgets.entrySet()) {
            Widget w = entry.getKey();
            WidgetMouseTrackingInfo info = entry.getValue();
            if (info.mouseIn) {
                info.mouseIn = false;
                MouseOutEvent.fire(w);
            }
        }
    }

    public static final class WidgetMouseTrackingInfo {
        public boolean mouseIn = false;
        public int extraLeft = 0;
        public int extraRight = 0;
        public int extraTop = 0;
        public int extraBottom = 0;
    }

}