public boolean animate(ActionListener callback) {
		if (timer != null && timer.isRunning()) {
			return false;
		}

		this.callbackListener = callback;
		this.direction = isTargetAtBaseLocation() ? SimpleShutterAnimation.DIRECTION_UP : SimpleShutterAnimation.DIRECTION_DOWN;
		step = 0;
		timer = new Timer(10, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (step < 100) {
					double h = target.getHeight() - base;
					target.setLocation(new Point(target.getX(), new Double(h * Math.pow(2.98, -0.054 * step) * Math.cos(0.086 * step) - (direction == DIRECTION_UP ? h : 0 - base)).intValue() * (direction == DIRECTION_UP ? 1 : -1)));
					step++;
				} else {
					target.setLocation(new Point(target.getX(), direction == DIRECTION_UP ? target.getBounds().y : new Double(0 - base).intValue()));
					timer.stop();
					if (callbackListener != null) {
						callbackListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "finish"));
					}
				}
			}
		});
		timer.start();
		return true;
	}