Package org.eclipse.jst.pagedesigner.editpolicies

Source Code of org.eclipse.jst.pagedesigner.editpolicies.MouseSelectableChildDecorator$AnimatedHideLocator

/*******************************************************************************
* Copyright (c) 2001, 2007 Oracle Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Oracle Corporation - initial API and implementation
*******************************************************************************/
/**
*
*/
package org.eclipse.jst.pagedesigner.editpolicies;

import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Locator;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.parts.ElementEditPart;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;

/**
* A child decorator that supports mouse selection
*
* @author cbateman
*
*/
class MouseSelectableChildDecorator extends NonVisualChildDecorator
{
    private static final String PIN_UP_IMAGE_FILE = "pin_up.gif"; //$NON-NLS-1$
   
  private static final String PIN_DOWN_IMAGE_FILE = "pin_down.gif"; //$NON-NLS-1$

  // no visual or affordance showing
    private static final int           STATE_START = 0;
   
    // the host is showing hover feedback, but is not selected
    private static final int           STATE_HOST_HOVER = 1;
   
    // the host has primary selection
    private static final int           STATE_HOST_SELECTED = 2;
   
    // the selection handle for the decorator has mouse hover
    private static final int           STATE_HANDLE_HOVER = 3;
   
    // the selection handle has been selected (is showing)
    private static final int           STATE_HANDLE_MENU_BAR_SHOWING = 4;
   
    // the menu bar has hover
    private static final int           STATE_HANDLE_MENU_BAR_HOVER = 5;
   
    // the menu bar has primary selection
    private static final int           STATE_HANDLE_MENU_BAR_SELECTED = 6;
   
    /**
     * An event indicating the host received hover
     */
    public static final int           EVENT_HOST_HOVER_RECEIVED = 31;
    /**
     * An event indicating the host lost hover
     */
    public static final int           EVENT_HOST_HOVER_LOST = 32;
    /**
     * An event indicating the host received selection
     */
    public static final int           EVENT_HOST_SELECTION_RECEIVED = 33;
    /**
     * An event indicating the host lost selection
     */
    public static final int           EVENT_HOST_SELECTION_LOST = 34;
    private static final int          EVENT_HANDLE_HOVER_RECEIVED = 35;
    private static final int          EVENT_HANDLE_HOVER_LOST = 36;
    private static final int          EVENT_HANDLE_SELECTED = 37;
    private static final int          EVENT_ALL_SELECTION_LOST = 38;
    private static final int          EVENT_MENU_BAR_SELECTION_RECEIVED = 39;
   
    private MouseMotionListener      _motionListener;
    private MouseListener            _mouseListener;
    private boolean                  _isMouseOver = false;
    private ElementMenuBar           _elementMenuBar;

    private DisplayStateMachine      _stateMachine;
    private VerticalMenuLocator      _menuLocator;
    private AnimatedHideLocator      _hideLocator;
    private IFigure                  _hoverParent;
    private IFigure                  _selectionParent;

    private ISelectionChangedListener _menuSelectionListener;
   
    MouseSelectableChildDecorator(final GraphicalEditPart hostPart, int location,
            IFigure hoverParent, IFigure selectionParent) {
        super(hostPart, location);
        _menuLocator = new VerticalMenuLocator(hostPart, this);
        _hideLocator = new AnimatedHideLocator();
        _elementMenuBar = ((ElementEditPart)hostPart).getElementMenuBar();
        _stateMachine = new DisplayStateMachine();
        _hoverParent = hoverParent;
        _selectionParent = selectionParent;
       
        _motionListener = new MouseMotionListener.Stub()
        {
            public void mouseEntered(MouseEvent me) {
                _isMouseOver = true;
                updateState(EVENT_HANDLE_HOVER_RECEIVED);
            }
   
            public void mouseExited(MouseEvent me) {
                _isMouseOver = false;
                updateState(EVENT_HANDLE_HOVER_LOST);
            }
        };
        addMouseMotionListener(_motionListener);
           
        _mouseListener = new MouseListener.Stub()
        {
            public void mousePressed(MouseEvent me) {
                updateState(EVENT_HANDLE_SELECTED);
            }
        };
        addMouseListener(_mouseListener);
       
        _menuSelectionListener = new ISelectionChangedListener()
        {
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                if (selection.size() == 0)
                {
                    // if the host part has been given back selection, then
                    // we have a host selection event
                    if (getOwner().getSelected() == EditPart.SELECTED_PRIMARY)
                    {
                        updateState(EVENT_HOST_SELECTION_RECEIVED);
                    }
                    // otherwise, both the host and the non-visual children are lost,
                    // so fire all selection lost
                    else
                    {
                        updateState(EVENT_ALL_SELECTION_LOST);
                    }
                }
                // otherwise, one or more non-visual children have selection
                else
                {
                    updateState(EVENT_MENU_BAR_SELECTION_RECEIVED);
                }
            }
        };
        _elementMenuBar.addSelectionChangedListener(_menuSelectionListener);
    }
   
    public void paintFigure(Graphics g) {
        // TODO: could we use an image label toggle button here instead?   
        Image  arrowImage = null;
       
        if (_stateMachine.isMenuShowing())
        {
            arrowImage = PDPlugin.getDefault().getImage(PIN_DOWN_IMAGE_FILE);
        }
        else
        {
            arrowImage = PDPlugin.getDefault().getImage(PIN_UP_IMAGE_FILE);
        }
       
        Rectangle r = getBounds();
        g.setAlpha(75);
        g.setBackgroundColor(getFillColor());
        g.fillRectangle(r.x, r.y, r.width, r.height);
        g.setAlpha(getAlpha());
        g.drawImage(arrowImage, r.x+1, r.y+1);
        g.setForegroundColor(getBorderColor());
        g.drawRectangle(r.x, r.y, r.width-1, r.height-1);
    }

    /**
     * @param event
     */
    public void updateState(int event)
    {
        int oldState = _stateMachine.doTransition(event);
        updateVisual(oldState);
    }
   
    /**
     * @param oldState
     */
    protected void updateVisual(int oldState)
    {
        // overriding all other considerations is whether the menu bar even has
        // any items to show.  If not don't show anything
        if (!_elementMenuBar.hasChildParts())
        {
            if (getParent() != null)
            {
                getParent().remove(this);
            }
           
            return;
        }
       
        switch (_stateMachine._curState)
        {
            case STATE_START:
                hide(_elementMenuBar, false);
                IFigure parent = getParent();
                if (parent != null)
                {
                    parent.remove(this);
                }
            break;
           
            case STATE_HOST_HOVER:
                if (_hoverParent != null)
                {
                    _hoverParent.add(this);
                    validate();
                }
                show(_elementMenuBar, false);
                setVisible(false);
            break;
           
            case STATE_HOST_SELECTED:
                if (_selectionParent != null)
                {
                    _selectionParent.add(this);
                    validate();
                }

                setVisible(true);

                if (oldState != STATE_HOST_SELECTED
                        && oldState != STATE_HANDLE_HOVER)
                {
                    show(_elementMenuBar, true);
                    hide(_elementMenuBar, true);
                }
                else
                {
                    if (!_hideLocator._isAnimating)
                    {
                        hide(_elementMenuBar, false);
                    }
                }
                repaint();
            break;
           
            case STATE_HANDLE_HOVER:
                if (_stateMachine.isMenuShowing(oldState))
                {
                    hide(_elementMenuBar, false);
                }
                else
                {
                    show(_elementMenuBar, false);
                }
                repaint();
            break;
           
            case STATE_HANDLE_MENU_BAR_SHOWING:
                show(_elementMenuBar, true);
                repaint();
            break;
           
            case STATE_HANDLE_MENU_BAR_HOVER:
            case STATE_HANDLE_MENU_BAR_SELECTED:
                //revalidate();
            break;
           
           
            default:
               
        }
    }

    protected void init() {
        setPreferredSize(new Dimension(12, 12));
    }
   
    /**
     *
     */
    public void dispose()
    {
        hide(_elementMenuBar, false);
       
        if (_motionListener != null)
        {
            removeMouseMotionListener(_motionListener);
            _motionListener = null;
        }
       
        if (_mouseListener != null)
        {
            removeMouseListener(_mouseListener);
            _mouseListener = null;
        }
       
        if (_menuSelectionListener != null)
        {
            _elementMenuBar.removeSelectionChangedListener(_menuSelectionListener);
            _menuSelectionListener = null;
        }
    }
   
    private void hide(ElementMenuBar menuBar, boolean animate)
    {
        if (animate)
        {
            final Point endPoint = this.getLocation().getCopy();
            //TODO: don't understand when translation is necessary...
            //this.translateToAbsolute(endPoint);
           
            endPoint.x += this.getBounds().width / 2;
            endPoint.y += this.getBounds().height / 2;
            _hideLocator.setHideEndPoint(endPoint);
            _hideLocator.relocate(menuBar);
        }
        else
        {
            if (menuBar.getParent() != null)
            {
                getParent().remove(menuBar);
            }
        }
    }
   
    private void show(ElementMenuBar menuBar, boolean enabled)
    {
        menuBar.setEnabled(enabled);
        getParent().add(menuBar);
        _menuLocator.relocate(menuBar);
    }
   
    protected int getAlpha()
    {
        return (_isMouseOver || _stateMachine.isMenuShowing()) ? 255 : 75;
    }
   
    private class DisplayStateMachine
    {
        private int _curState = STATE_START;
       
        /**
         * @param event
         * @return execute a state machine transition on event
         */
        public int doTransition(int event)
        {
            final int     oldState = _curState;
           
            switch(_curState)
            {
                case STATE_START:
                    // can only transition from start state
                    // on a host event
                    if (event == EVENT_HOST_HOVER_RECEIVED)
                    {
                        _curState = STATE_HOST_HOVER;
                    }
                    else if (event == EVENT_HOST_SELECTION_RECEIVED)
                    {
                        _curState = STATE_HOST_SELECTED;
                    }
                break;
               
                case STATE_HOST_HOVER:
                    if (event == EVENT_HOST_SELECTION_RECEIVED)
                    {
                        _curState = STATE_HOST_SELECTED;
                    }
                    else if (event == EVENT_HOST_SELECTION_LOST
                            || event == EVENT_HOST_HOVER_LOST)
                    {
                        _curState = STATE_START;
                    }
                    else if (event == EVENT_HOST_HOVER_RECEIVED)
                    {
                        // preserve state in this case
                    }
                break;

                case STATE_HOST_SELECTED:
                    // once the host is selected,the only host event that
                    // that can change state is selection lost
                    if (event == EVENT_HOST_SELECTION_LOST)
                    {
                        _curState = STATE_START;
                    }
                    else if (event == EVENT_HANDLE_HOVER_RECEIVED)
                    {
                        _curState = STATE_HANDLE_HOVER;
                    }
                    else if (event == EVENT_HANDLE_SELECTED)
                    {
                        _curState = STATE_HANDLE_MENU_BAR_SHOWING;
                    }
                    else if (event == EVENT_ALL_SELECTION_LOST)
                    {
                        _curState = STATE_START;
                    }
                break;
                   
                case STATE_HANDLE_HOVER:
                    if (event == EVENT_HANDLE_HOVER_LOST)
                    {
                        _curState = STATE_HOST_SELECTED;
                    }
                    else if (event == EVENT_HANDLE_SELECTED)
                    {
                        _curState = STATE_HANDLE_MENU_BAR_SHOWING;
                    }
                    else if (event == EVENT_HOST_SELECTION_LOST)
                    {
                        _curState = STATE_START;
                    }
                break;
                case STATE_HANDLE_MENU_BAR_SHOWING:
                    if (event == EVENT_HANDLE_SELECTED)
                    {
                        _curState = STATE_HANDLE_HOVER;
                    }
                    else if (event == EVENT_MENU_BAR_SELECTION_RECEIVED)
                    {
                        _curState = STATE_HANDLE_MENU_BAR_SELECTED;
                    }
                    else if (event == EVENT_ALL_SELECTION_LOST)
                    {
                        _curState = STATE_START;
                    }
                break;

                case STATE_HANDLE_MENU_BAR_HOVER:
                break;                   

                case STATE_HANDLE_MENU_BAR_SELECTED:
                    if (event == EVENT_ALL_SELECTION_LOST)
                    {
                        _curState = STATE_START;
                    }
                    else if (event == EVENT_HANDLE_SELECTED)
                    {
                        _curState = STATE_HANDLE_HOVER;
                    }
                break;
               
            }
           
           
            return oldState;
        }

        /**
         * @return true if the  menu should be showing in the  current state
         */
        public boolean isMenuShowing()
        {
            return isMenuShowing(_curState);
        }

        /**
         * @param state
         * @return true if state is one in which the menu should be showing
         */
        public boolean isMenuShowing(int state)
        {
            return _curState == STATE_HANDLE_MENU_BAR_SHOWING
                    || _curState == STATE_HANDLE_MENU_BAR_HOVER
                    || _curState == STATE_HANDLE_MENU_BAR_SELECTED;
        }
    }
   
    private static class VerticalMenuLocator implements Locator
    {
        private IFigure  _referenceFigure;
       
        VerticalMenuLocator(GraphicalEditPart owner, IFigure reference)
        {
            _referenceFigure = reference;
        }
       
        public void relocate(IFigure target)
        {
            final Rectangle finalBounds = getFinalMenuBounds(target);
            target.setBounds(finalBounds);
        }
       
       
        private Rectangle getInitialMenuBounds(final IFigure target)
        {
            Rectangle targetBounds =
                new PrecisionRectangle(_referenceFigure.getBounds().getResized(-1, -1));
            _referenceFigure.translateToAbsolute(targetBounds);
            target.translateToRelative(targetBounds);
            return targetBounds;
        }

        private Rectangle getFinalMenuBounds(final IFigure target)
        {
            final IFigure referenceFigure =  _referenceFigure;
           
            Rectangle targetBounds = getInitialMenuBounds(target);
            Dimension targetSize = target.getPreferredSize();

            // copied from super.relocate because relativeX/Y are private in super
            // changed from super to remove div by 2 that centers target; we want
            // it to be corner-to-corner
            targetBounds.x
                += targetBounds.width+4;
            targetBounds.y
                  -= (targetSize.height / 2) - referenceFigure.getBounds().height/2;
            targetBounds.setSize(targetSize);
            //target.setBounds(targetBounds);

//            final Rectangle viewPortRect =
//                ((IHTMLGraphicalViewer)_owner.getViewer()).getViewport().getBounds();
//            final Rectangle targetRect = targetBounds.getCopy();
//           
//            targetRect.intersect(viewPortRect);

//            int width = targetBounds.width - targetRect.width;
//            int height = targetBounds.height - targetRect.height;
           
//            if (width != 0)
//            {
//                targetBounds.x -= width;
//            }
//           
//            if (height != 0)
//            {
//                targetBounds.y += height;
//            }
           
            return targetBounds;
        }
    }
   
    private static class AnimatedHideLocator implements Locator
    {
        private Point _endPoint;
        private boolean _isAnimating;
       
        /**
         * @param endPoint -- must be absolute coordinate
         */
        public void setHideEndPoint(Point endPoint)
        {
            _endPoint = endPoint;
        }
       
        public void relocate(IFigure target)
        {
            final Point newEndPoint = _endPoint.getCopy();
            target.translateToRelative(_endPoint);
            Rectangle startBounds = target.getBounds().getCopy();
            animateBoundsChange(target, startBounds, newEndPoint);
        }

        private void animateBoundsChange(final IFigure target,
                final Rectangle startBounds,
                final Point endPoint)
        {
            final int numSteps = 5;
            final int numMs = 500;
            final int timeSteps = numMs/numSteps;
           
            int xDelta = endPoint.x - startBounds.x;
            int yDelta = endPoint.y - startBounds.y;
           
            final int widthIncrement = -1 * startBounds.width / numSteps;
            final int heightIncrement = -1 * startBounds.height / numSteps;
            int xIncrement = xDelta / numSteps;
            int yIncrement = yDelta  / numSteps;
           
            target.setBounds(startBounds);
            if (widthIncrement != 0 || heightIncrement != 0)
            {
                _isAnimating = true;
                doAnimation(numMs, timeSteps, widthIncrement, heightIncrement, xIncrement, yIncrement, endPoint, target);
            }
        }
       
        private void doAnimation(final int remainingTime,
                final int timeIncrement,
                final int widthIncrement, final int heightIncrement
                , final int xIncrement, final int yIncrement
                , final Point endPoint
                , final IFigure target)
        {
            Display.getCurrent().timerExec(timeIncrement,
            new Runnable()
            {
            public void run()
            {
               if (remainingTime <= 0)
               {
                   if (target.getParent() != null)
                   {
                       target.getParent().remove(target);
                   }
                   _isAnimating = false;
               }
               else
               {
                   final Rectangle curBounds = target.getBounds().getCopy();
                   curBounds.width += widthIncrement;
                   curBounds.height += heightIncrement;
                   curBounds.x += xIncrement;
                   curBounds.y += yIncrement;
                   target.setBounds(curBounds);
                   target.revalidate();
                   doAnimation(remainingTime-timeIncrement, timeIncrement, widthIncrement, heightIncrement, xIncrement, yIncrement, endPoint, target);
               }
            }
            });
         }
    }
}
TOP

Related Classes of org.eclipse.jst.pagedesigner.editpolicies.MouseSelectableChildDecorator$AnimatedHideLocator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.