blob: 0fd6f2d42c0038b076598abe9e9ba24f74dca0a3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 IBM 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:
* IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.ui.internal;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ControlAnimator;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.progress.UIJob;
/**
* Animates a control by sliding it up or down. The animation is
* achieved using the UI's job functionality and by incrementally
* decreasing or increasing the control's y coordinate.
*
* @since 3.2
*/
public class WorkbenchControlAnimator extends ControlAnimator {
/**
* A constant denoting the CLOSED animation state of
* a control (value is 0)
*/
private static final int CLOSED = 0;
/**
* A constant denoting the OPENING animation state of
* a control (value is 1)
*/
private static final int OPENING = 1;
/**
* A constant denoting the OPEN animation state of
* a control (value is 2)
*/
private static final int OPEN = 2;
/**
* A constant denoting the CLOSING animation state of
* a control (value is 3)
*/
private static final int CLOSING = 3;
private UIJob slideJob;
private int endY;
private boolean finished;
private boolean inTransition = false;
private boolean animated = false;
private int state = CLOSED;
private int LONG_DELAY = 300;
private int SHORT_DELAY = 25;
/**
* Constructs a new WorbenchControlAnimator instance and passes along the
* control that will be animated.
*
* @param control the control that will be animated.
*/
public WorkbenchControlAnimator(Control control) {
super(control);
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.ControlAnimator#setVisible(boolean)
*/
public void setVisible(boolean visible) {
// // return immediately if already OPENING/OPEN and
// // visible is true or if CLOSING/CLOSED and visible
// // is false.
// switch (getAnimationState()) {
// case OPENING:
// case OPEN:
// if (visible)
// return;
// break;
// case CLOSING:
// case CLOSED:
// if (!visible)
// return;
// break;
// }
if(animated) {
super.setVisible(visible);
return;
}
setAnimationState(visible ? OPENING: CLOSING);
finished = false;
control.setVisible(true);
Rectangle parentBounds = control.getParent().getBounds();
int bottom = parentBounds.height;
if (bottom <= 0) {
setAnimationState(OPEN);
return;
}
endY = visible ? bottom - control.getBounds().height
: bottom;
if(slideJob != null)
slideJob.cancel();
slideJob = getSlideJob();
control.addDisposeListener(new DisposeListener(){
public void widgetDisposed(org.eclipse.swt.events.DisposeEvent e) {
slideJob = null;
}
});
// Wait before displaying the control to allow for opening
// condition to change, but no waiting before closing the control.
if(getAnimationState() == OPENING && !inTransition){
slideJob.schedule(LONG_DELAY);
} else {
slideJob.schedule(SHORT_DELAY);
}
}
/**
* Creates a job in the UI thread to display or hide the control
* by increasing or decreasing the y coordinate and setting the new
* location. The job will continually re-schedule itself until the
* the control is no longer in transition and will also stop
* if the monitor is canceled or the control is disposed.
*
* @return the UIJob responsible for opening or closing the control
*/
private UIJob getSlideJob(){
UIJob newSlideJob = new UIJob("Sliding Message") { //$NON-NLS-1$
public IStatus runInUIThread(IProgressMonitor monitor) {
if(!monitor.isCanceled() && !control.isDisposed()){
Point loc = control.getLocation();
switch (getAnimationState()) {
case OPENING:
animated = true;
loc.y--;
if (loc.y >= endY) {
control.setLocation(loc);
} else {
finished = true;
setAnimationState(OPEN);
}
break;
case CLOSING:
loc.y++;
if (loc.y <= endY) {
control.setLocation(loc);
} else {
finished = true;
setAnimationState(CLOSED);
control.setVisible(false);
}
break;
default:
break;
}
if(!finished) {
inTransition = true;
slideJob.schedule(5);
} else
inTransition = false;
return Status.OK_STATUS;
}
return Status.CANCEL_STATUS;
}
};
newSlideJob.setSystem(true);
return newSlideJob;
}
/**
* Sets the state of the control and whether or not
* it should be visible. The value should be one of
* the following: {@link #OPENING}, {@link #OPEN},
* {@link #CLOSING}, or {@link #CLOSED}
*
* @param state the desired state of the control
*/
private void setAnimationState(int state) {
this.state = state;
}
/**
* Returns the current state of the control.
*
* @return the current state of the control: {@link #OPENING},
* {@link #OPEN}, {@link #CLOSING}, or {@link #CLOSED}
*/
private int getAnimationState() {
return state;
}
}