edu.csun.ecs.cs.multitouchj.ui.control.Control.java Source code

Java tutorial

Introduction

Here is the source code for edu.csun.ecs.cs.multitouchj.ui.control.Control.java

Source

/**
 * Copyright 2009 Atsuya Takagi
 *
 * 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 edu.csun.ecs.cs.multitouchj.ui.control;

import java.awt.Color;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.lwjgl.opengl.DisplayMode;

import edu.csun.ecs.cs.multitouchj.objectobserver.event.Event;
import edu.csun.ecs.cs.multitouchj.objectobserver.event.EventListenerManager;
import edu.csun.ecs.cs.multitouchj.objectobserver.event.ObjectObserverEvent;
import edu.csun.ecs.cs.multitouchj.ui.event.ControlEvent;
import edu.csun.ecs.cs.multitouchj.ui.event.ControlListener;
import edu.csun.ecs.cs.multitouchj.ui.event.FloatEvent;
import edu.csun.ecs.cs.multitouchj.ui.event.FloatListener;
import edu.csun.ecs.cs.multitouchj.ui.event.ObjectEvent;
import edu.csun.ecs.cs.multitouchj.ui.event.TouchEvent;
import edu.csun.ecs.cs.multitouchj.ui.event.TouchListener;
import edu.csun.ecs.cs.multitouchj.ui.geometry.Point;
import edu.csun.ecs.cs.multitouchj.ui.geometry.Size;
import edu.csun.ecs.cs.multitouchj.ui.gesture.GestureHandler;
import edu.csun.ecs.cs.multitouchj.ui.gesture.GestureManager;
import edu.csun.ecs.cs.multitouchj.ui.graphic.Renderable;
import edu.csun.ecs.cs.multitouchj.ui.graphic.WindowManager;
import edu.csun.ecs.cs.multitouchj.ui.utility.OpenGlUtility;

/**
 * @author Atsuya Takagi
 *
 * $Id: Control.java 82 2009-03-15 23:07:07Z Atsuya Takagi $
 */
public abstract class Control implements Renderable {
    private static final Class[] EVENTS_INTERESTED = { TouchEvent.class, FloatEvent.class };
    private static Log log = LogFactory.getLog(Control.class);
    private Point center;
    private Size size;
    private Color color;
    private float opacity;
    private boolean visibility;
    private float rotation;
    private WindowManager windowManager;
    private EventListenerManager eventListenerManager;
    private GestureManager gestureManager;

    public Control() {
        center = new Point();
        size = new Size();
        color = Color.WHITE;
        opacity = 1.0f;
        visibility = true;
        rotation = 0.0f;
        eventListenerManager = new EventListenerManager();
        gestureManager = new GestureManager(this);
        windowManager = WindowManager.getInstance();

        initialize();
    }

    public void addTouchListener(TouchListener touchListener) {
        eventListenerManager.addEventListener(TouchListener.class, touchListener);
    }

    public void removeTouchListener(TouchListener touchListener) {
        eventListenerManager.removeEventListener(TouchListener.class, touchListener);
    }

    public void addFloatListener(FloatListener floatListener) {
        eventListenerManager.addEventListener(FloatListener.class, floatListener);
    }

    public void removeFloatListener(FloatListener floatListener) {
        eventListenerManager.removeEventListener(FloatListener.class, floatListener);
    }

    public void addControlListener(ControlListener controlListener) {
        eventListenerManager.addEventListener(ControlListener.class, controlListener);
    }

    public void removeControlListener(ControlListener controlListener) {
        eventListenerManager.removeEventListener(ControlListener.class, controlListener);
    }

    public void dispose() {
        removeTouchListener(gestureManager);
        removeFloatListener(gestureManager);

        windowManager.unregisterControl(this);
    }

    public Point getPosition() {
        return new Point(center);
    }

    public Point getOpenGlPosition() {
        DisplayMode displayMode = windowManager.getDisplayManager().getCurrentDisplayMode();
        return OpenGlUtility.getOpenGlPosition(new Size(displayMode.getWidth(), displayMode.getHeight()), center);
    }

    public void setPosition(Point position) {
        center.set(position);

        ControlEvent controlEvent = new ControlEvent(this);
        onControlMoved(controlEvent);
    }

    public Point getTopLeftPosition() {
        return new Point((center.getX() - (size.getWidth() / 2.0f)), (center.getY() - (size.getHeight() / 2.0f)));
    }

    public void setTopLeftPosition(Point position) {
        Size size = getSize();
        Point center = new Point((position.getX() + (size.getWidth() / 2.0f)),
                (position.getY() + (size.getHeight() / 2.0f)));

        setPosition(center);
    }

    public Size getSize() {
        return new Size(size);
    }

    public void setSize(Size size) {
        this.size.set(size);

        ControlEvent controlEvent = new ControlEvent(this);
        onControlResized(controlEvent);
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = new Color(color.getRGB());
    }

    public float getOpacity() {
        return opacity;
    }

    public void setOpacity(float opacity) {
        float value = opacity;
        if (value > 1.0f) {
            value = 1.0f;
        } else if (value < 0.0f) {
            value = 0.0f;
        }

        this.opacity = value;
    }

    public boolean isVisible() {
        return visibility;
    }

    public void setVisible(boolean value) {
        this.visibility = value;
    }

    public float getRotation() {
        return rotation;
    }

    public void setRotation(float rotation) {
        float value = rotation;
        while (value < 0.0f) {
            value += 360.0f;
        }
        value = (Math.abs(value) % 360.0f);

        //log.info("Rotation: "+value);

        this.rotation = value;
    }

    public boolean isWithin(Point position) {
        //log.debug("isWithin: "+getTopLeftPosition().toString()+", "+getSize().toString());

        boolean result = false;
        if (getRotation() == 0.0f) {
            result = isWithinWithoutRotation(position);
        } else {
            result = isWithinWithRotation(position);
        }

        return result;
    }

    /*
    public boolean wantsEvent(Event event) {
    boolean wants = false;
        
    if(isEventInterested(event)) {
        if(event instanceof ObjectEvent) {
            ObjectEvent objectEvent = (ObjectEvent)event;
            wants = isWithin(objectEvent.getPosition());
        }
    }
        
    return wants;
    }
    */

    public void dispatchEvent(Event event) {
        processEvent(event);
    }

    public Point getClientPosition(Point point) {
        Point topLeft = getTopLeftPosition();
        return new Point((point.getX() - topLeft.getX()), (point.getY() - topLeft.getY()));
    }

    protected WindowManager getWindowManager() {
        return windowManager;
    }

    protected void processEvent(Event event) {
        //log.debug("processEvent");

        if (isEventInterested(event)) {
            if (event instanceof ObjectEvent) {
                processObjectEvent((ObjectEvent) event);
            }
        }
    }

    protected void processObjectEvent(ObjectEvent objectEvent) {
        //log.debug("processObjectEvent");

        ObjectEvent.Status status = objectEvent.getStatus();

        if (objectEvent instanceof TouchEvent) {
            TouchEvent touchEvent = (TouchEvent) objectEvent;
            if (ObjectEvent.Status.Started.equals(status)) {
                onTouchStarted(touchEvent);
            } else if (ObjectEvent.Status.Moved.equals(status)) {
                onTouchMoved(touchEvent);
            } else if (ObjectEvent.Status.Ended.equals(status)) {
                onTouchEnded(touchEvent);
            }
        } else {
            FloatEvent floatEvent = (FloatEvent) objectEvent;
            if (ObjectEvent.Status.Started.equals(status)) {
                onFloatStarted(floatEvent);
            } else if (ObjectEvent.Status.Moved.equals(status)) {
                onFloatMoved(floatEvent);
            } else if (ObjectEvent.Status.Ended.equals(status)) {
                onFloatEnded(floatEvent);
            }
        }
    }

    protected boolean isEventInterested(Event event) {
        boolean result = false;
        for (Class klass : EVENTS_INTERESTED) {
            if (event.getClass().equals(klass)) {
                result = true;
                break;
            }
        }

        return result;
    }

    protected void onTouchStarted(TouchEvent touchEvent) {
        //log.info("Control.onTouchStarted");
        notifyEventListeners(TouchListener.class, "touchStarted", new Class[] { TouchEvent.class },
                new Object[] { touchEvent });
    }

    protected void onTouchMoved(TouchEvent touchEvent) {
        //log.info("Control.onTouchMoved");
        notifyEventListeners(TouchListener.class, "touchMoved", new Class[] { TouchEvent.class },
                new Object[] { touchEvent });
    }

    protected void onTouchEnded(TouchEvent touchEvent) {
        //log.info("Control.onTouchEnded");
        notifyEventListeners(TouchListener.class, "touchEnded", new Class[] { TouchEvent.class },
                new Object[] { touchEvent });
    }

    protected void onFloatStarted(FloatEvent floatEvent) {
        //log.info("Control.onFloatStarted");
        notifyEventListeners(FloatListener.class, "floatStarted", new Class[] { FloatEvent.class },
                new Object[] { floatEvent });
    }

    protected void onFloatMoved(FloatEvent floatEvent) {
        //log.info("Control.onFloatMoved");
        notifyEventListeners(FloatListener.class, "floatMoved", new Class[] { FloatEvent.class },
                new Object[] { floatEvent });
    }

    protected void onFloatEnded(FloatEvent floatEvent) {
        //log.info("Control.onFloatEnded");
        notifyEventListeners(FloatListener.class, "floatEnded", new Class[] { FloatEvent.class },
                new Object[] { floatEvent });
    }

    protected void onControlResized(ControlEvent controlEvent) {
        notifyEventListeners(ControlListener.class, "controlResized", new Class[] { ControlEvent.class },
                new Object[] { controlEvent });
    }

    protected void onControlMoved(ControlEvent controlEvent) {
        notifyEventListeners(ControlListener.class, "controlMoved", new Class[] { ControlEvent.class },
                new Object[] { controlEvent });
    }

    protected void notifyEventListeners(Class klass, String methodName, Class[] classes, Object[] objects) {
        synchronized (eventListenerManager) {
            try {
                eventListenerManager.notifyEventListeners(klass, methodName, classes, objects);
            } catch (Exception exception) {
                log.info("Failed to notify event listeners.", exception);
            }
        }
    }

    protected boolean isWithinWithoutRotation(Point position) {
        Size size = getSize();
        Point center = getPosition();
        Point topLeftPosition = new Point((center.getX() - (size.getWidth() / 2.0f)),
                (center.getY() - (size.getHeight() / 2.0f)));

        boolean result = false;
        if (((position.getX() >= topLeftPosition.getX())
                && (position.getX() <= (topLeftPosition.getX() + size.getWidth())))
                && ((position.getY() >= topLeftPosition.getY())
                        && (position.getY() <= (topLeftPosition.getY() + size.getHeight())))) {
            result = true;
        }

        return result;
    }

    protected boolean isWithinWithRotation(Point position) {
        // topleft, topright, bottomright, bottomleft
        // get points centered at (0, 0)
        Size size = getSize();
        Point[] points = new Point[4];
        points[0] = new Point(-1 * (size.getWidth() / 2.0f), (size.getHeight() / 2.0f));
        points[1] = new Point((size.getWidth() / 2.0f), (size.getHeight() / 2.0f));
        points[2] = new Point((size.getWidth() / 2.0f), -1 * (size.getHeight() / 2.0f));
        points[3] = new Point(-1 * (size.getWidth() / 2.0f), -1 * (size.getHeight() / 2.0f));
        /*
        log.info("Vertices:");
        for(int i = 0; i < points.length; i++) {
        log.info("\t"+points[i].toString());
        }
        */

        // rotate at (0, 0)
        double rotationInDegree = getRotation();
        double rotationInRadian = Math.toRadians(rotationInDegree);
        for (Point point : points) {
            double rotatedX = (point.getX() * Math.cos(rotationInRadian))
                    - (point.getY() * Math.sin(rotationInRadian));
            double rotatedY = (point.getX() * Math.sin(rotationInRadian))
                    + (point.getY() * Math.cos(rotationInRadian));
            point.set((float) rotatedX, (float) rotatedY);
        }
        /*
        log.info("Rotated Vertices:");
        for(int i = 0; i < points.length; i++) {
        log.info("\t"+points[i].toString());
        }
        */

        // check to see if position is above or below the slope of sides of
        // this rectangle
        DisplayMode displayMode = windowManager.getDisplayManager().getCurrentDisplayMode();
        Point center = getOpenGlPosition();
        Point centeredPosition = OpenGlUtility
                .getOpenGlPosition(new Size(displayMode.getWidth(), displayMode.getHeight()), position);
        //log.info("Position GL: "+centeredPosition.toString());
        centeredPosition.minus(center);
        //log.info("Center: "+center.toString());
        //log.info("Position: "+position.toString());
        //log.info("Centered: "+centeredPosition.toString());

        boolean[] results = new boolean[points.length];
        for (int i = 0; i < points.length; i++) {
            Point target1 = points[i];
            Point target2 = points[((i + 1) % points.length)];
            Point target3 = points[((i + 2) % points.length)];

            double targetValue = (centeredPosition.getY() - target1.getY());
            if (target2.getX() != target1.getX()) {
                targetValue = (centeredPosition.getY() - target1.getY())
                        - ((target2.getY() - target1.getY()) / (target2.getX() - target1.getX()))
                                * (centeredPosition.getX() - target1.getX());
            }
            double testValue = (target3.getY() - target1.getY());
            if (target2.getX() != target1.getX()) {
                testValue = (target3.getY() - target1.getY())
                        - ((target2.getY() - target1.getY()) / (target2.getX() - target1.getX()))
                                * (target3.getX() - target1.getX());
            }
            //log.info("target: "+targetValue+", test: "+testValue);

            results[i] = (targetValue == 0.0);
            if (((targetValue > 0.0) && (testValue > 0.0)) || ((targetValue < 0.0) && (testValue < 0.0))) {
                results[i] = true;
            }
        }
        /*
        log.info("Results:");
        for(int i = 0; i < results.length; i++) {
        log.info("\t"+results[i]);
        }
        */

        boolean isWithin = true;
        for (boolean result : results) {
            if (!result) {
                isWithin = false;
                break;
            }
        }
        /*
        float[] results = new float[points.length];
        for(int i = 0; i < points.length; i++) {
        Point target1 = points[i];
        Point target2 = points[((i + 1) % points.length)];
            
        float targetValue = (centeredPosition.getY() - target1.getY());
        if(target2.getX() != target1.getX()) {
            targetValue = (centeredPosition.getY() - target1.getY()) -
                ((target2.getY() - target1.getY()) / (target2.getX() - target1.getX())) *
                (centeredPosition.getX() - target1.getX());
        }
        results[i] = targetValue;
        }
        log.info("Results:");
        for(int i = 0; i < results.length; i++) {
        log.info("\t"+results[i]);
        }
            
        boolean isWithin = false;
        for(float result : results) {
        if(result == 0.0f) {
            isWithin = true;
            break;
        }
        }
        if(!isWithin) {
        int numberOfAboves = 0;
        for(float result : results) {
            if(result > 0.0f) {
                numberOfAboves += 1;
            }
        }
        if(numberOfAboves == 2) {
            isWithin = true;
        }
        }
        */

        //log.info("isWithin: "+isWithin);

        return isWithin;
    }

    protected void initialize() {
        windowManager.registerControl(this);

        for (GestureHandler gestureHandler : getGestureHandlers()) {
            gestureManager.addGestureHandler(gestureHandler);
        }
        addFloatListener(gestureManager);
        addTouchListener(gestureManager);
    }

    protected List<GestureHandler> getGestureHandlers() {
        LinkedList<GestureHandler> gestureHandlers = new LinkedList<GestureHandler>();
        return gestureHandlers;
    }
}