/*******************************************************************************
* Copyright (c) 2006-2009 Nicolas Richeton.
* 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 :
* Nicolas Richeton (nicolas.richeton@gmail.com) - initial API and implementation
*******************************************************************************/
package org.eclipse.nebula.cwt.animation;
import org.eclipse.nebula.cwt.animation.effects.IEffect;
import org.eclipse.nebula.cwt.animation.effects.MoveScrollBar;
import org.eclipse.nebula.cwt.animation.movement.IMovement;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Scrollable;
/**
* <p>
* This class replace the default scrolling behavior by an animation effect.
* </p>
*
* <p>
* Compatible with :
* </p>
* <ul>
* <li>Shell</li>
* <li>StyledText</li>
* <li>Canvas</li>
* <li>Gallery</li>
* </ul>
*
* @author Nicolas Richeton
*
*/
public class ScrollingSmoother {
Scrollable component;
ScrollBar verticalScrollBar;
ScrollBar horizontalScrollBar;
MoveScrollBar me = null;
IMovement movement = null;
/**
* @param c2
* @param movement
*/
public ScrollingSmoother(final Scrollable c2, IMovement movement) {
this.component = c2;
verticalScrollBar = c2.getVerticalBar();
horizontalScrollBar = c2.getHorizontalBar();
this.movement = movement;
}
protected ScrollBar getScrollbar(Event event) {
ScrollBar result = verticalScrollBar;
if (result == null) {
result = horizontalScrollBar;
}
return result;
}
Listener mouseWheelListener = new Listener() {
public void handleEvent(Event event) {
// Remove standard behavior
event.doit = false;
// Get scrollbar on which the event occurred.
ScrollBar currentScrollBar = getScrollbar(event);
int start = currentScrollBar.getSelection();
int end = start;
// If an effect is currently running, get the current and target
// values.
if (me != null) {
start = me.getCurrent();
end = me.getEnd();
}
end -= event.count * currentScrollBar.getIncrement();
if (end > currentScrollBar.getMaximum()
- currentScrollBar.getThumb()) {
end = currentScrollBar.getMaximum()
- currentScrollBar.getThumb();
}
if (end < currentScrollBar.getMinimum()) {
end = currentScrollBar.getMinimum();
}
startEffect(new MoveScrollBar(currentScrollBar, start, end,
2000, movement, null, null));
}
};
/**
* Enable or disable scrolling efeect.
*
* @param enable
* true or false.
*/
public void smoothControl(boolean enable) {
if (enable) {
component.addListener(SWT.MouseWheel, mouseWheelListener);
if (verticalScrollBar != null)
verticalScrollBar
.addSelectionListener(cancelEffectIfUserSelection);
if (horizontalScrollBar != null)
horizontalScrollBar
.addSelectionListener(cancelEffectIfUserSelection);
} else {
component.removeListener(SWT.MouseWheel, mouseWheelListener);
if (verticalScrollBar != null)
verticalScrollBar
.removeSelectionListener(cancelEffectIfUserSelection);
if (horizontalScrollBar != null)
horizontalScrollBar
.removeSelectionListener(cancelEffectIfUserSelection);
}
}
SelectionListener cancelEffectIfUserSelection = new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
public void widgetSelected(SelectionEvent e) {
if (!(e.data instanceof MoveScrollBar))
me = null;
}
};
protected void startEffect(MoveScrollBar moveScrollBarEffect) {
IEffect oldEffect = me;
me = moveScrollBarEffect;
if (oldEffect == null) {
Display.getCurrent().syncExec(new Runnable() {
public void run() {
if (me != null && !me.isDone()) {
me.doEffect();
Display.getCurrent().timerExec(10, this);
} else {
me = null;
}
}
});
}
}
}