| /* |
| * Copyright (c) 2015 The Eclipse Foundation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v2.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v20.html |
| * |
| * Contributors: |
| * Yatta Solutions - [466264] initial API and implementation |
| */ |
| package org.eclipse.oomph.setup.internal.installer; |
| |
| import org.eclipse.oomph.internal.ui.ImageHoverButton; |
| import org.eclipse.oomph.ui.SpriteAnimator; |
| import org.eclipse.oomph.ui.UIUtil; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ControlAdapter; |
| import org.eclipse.swt.events.ControlEvent; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Composite; |
| |
| /** |
| * @author Andreas Scharf |
| */ |
| public class SimpleInstallLaunchButton extends ImageHoverButton |
| { |
| static final Color COLOR_INSTALL = SetupInstallerPlugin.getColor(250, 148, 0); |
| |
| private static final Color COLOR_FOREGROUND_DEFAULT = AbstractSimpleDialog.COLOR_WHITE; |
| |
| private static final Color COLOR_INSTALLING = SetupInstallerPlugin.getColor(50, 196, 0); |
| |
| private static final Color COLOR_INSTALLING_FOREGROUND = AbstractSimpleDialog.COLOR_LABEL_FOREGROUND; |
| |
| private static final Color COLOR_LAUNCH = COLOR_INSTALLING; |
| |
| private static final long MINIMUM_PROGRESS_ANIMATION_DELAY = 20; |
| |
| private static final long MAXIMUM_PROGRESS_ANIMATION_DELAY = 200; |
| |
| private State currentState; |
| |
| private float progress; |
| |
| private ProgressSpinner progressSpinner; |
| |
| public SimpleInstallLaunchButton(Composite parent) |
| { |
| super(parent, SWT.PUSH); |
| |
| setForeground(UIUtil.getDisplay().getSystemColor(SWT.COLOR_WHITE)); |
| setFont(SimpleInstallerDialog.getFont(5, "bold")); //$NON-NLS-1$ |
| setCornerWidth(10); |
| setAlignment(SWT.CENTER); |
| setDisabledBackgroundColor(COLOR_DEFAULT_DISABLED_BACKGROUND); |
| setBackgroundMode(SWT.INHERIT_FORCE); |
| setLayout(null); |
| |
| if (SimpleVariablePage.PROGRESS_WATCHDOG_TIMEOUT != 0) |
| { |
| progressSpinner = new ProgressSpinner(SetupInstallerPlugin.INSTANCE.getSWTImage("simple/progress_sprite.png"), 8, 4, 20); //$NON-NLS-1$ |
| |
| addControlListener(new ControlAdapter() |
| { |
| @Override |
| public void controlResized(ControlEvent e) |
| { |
| relocateProgressAnimation(); |
| } |
| |
| @Override |
| public void controlMoved(ControlEvent e) |
| { |
| relocateProgressAnimation(); |
| } |
| }); |
| |
| // Skip first white image. |
| progressSpinner.setKeyframeRange(1, 31); |
| } |
| |
| setCurrentState(State.INSTALL); |
| } |
| |
| public float getProgress() |
| { |
| return progress; |
| } |
| |
| public void setProgress(float progress) |
| { |
| if (progress < 0 || progress > 1) |
| { |
| throw new IllegalArgumentException(Messages.SimpleInstallLaunchButton_BadProgress_exception); |
| } |
| |
| this.progress = progress; |
| redraw(); |
| } |
| |
| @Override |
| public boolean isHover() |
| { |
| // No hover during install. |
| return currentState == State.INSTALLING ? false : super.isHover(); |
| } |
| |
| public void setCurrentState(State newState) |
| { |
| if (newState == null) |
| { |
| throw new IllegalArgumentException(Messages.SimpleInstallLaunchButton_NullState_exception); |
| } |
| |
| if (currentState != newState) |
| { |
| State oldState = currentState; |
| currentState = newState; |
| stateChanged(oldState, currentState); |
| } |
| } |
| |
| private void stateChanged(State oldState, State newState) |
| { |
| setDefaultImage(newState.icon); |
| setHoverImage(newState.hoverIcon); |
| setDisabledImage(newState.disabledIcon); |
| setText(newState.label); |
| setToolTipText(newState.tooltip); |
| setBackground(newState.backgroundColor); |
| setForeground(newState.foregroundColor); |
| |
| switch (newState) |
| { |
| case INSTALLING: |
| setListenersPaused(true); |
| setCursor(null); |
| setShowButtonDownState(false); |
| if (progressSpinner != null) |
| { |
| progressSpinner.setVisible(true); |
| } |
| |
| break; |
| |
| default: |
| setListenersPaused(false); |
| setCursor(UIUtil.getDisplay().getSystemCursor(SWT.CURSOR_HAND)); |
| setShowButtonDownState(true); |
| stopProgressAnimation(); |
| if (progressSpinner != null) |
| { |
| progressSpinner.setVisible(false); |
| } |
| } |
| } |
| |
| public void setProgressAnimationSpeed(float speed) |
| { |
| if (progressSpinner != null) |
| { |
| if (speed < 0 || speed > 1) |
| { |
| throw new IllegalArgumentException(Messages.SimpleInstallLaunchButton_BadSpeed_exception); |
| } |
| |
| int delay = Math.round((1f - speed) * MAXIMUM_PROGRESS_ANIMATION_DELAY); |
| progressSpinner.setDelay(Math.max(delay, MINIMUM_PROGRESS_ANIMATION_DELAY)); |
| } |
| } |
| |
| public void stopProgressAnimation() |
| { |
| if (progressSpinner != null) |
| { |
| progressSpinner.setVisible(false); |
| } |
| } |
| |
| public void startProgressAnimation() |
| { |
| if (progressSpinner != null) |
| { |
| relocateProgressAnimation(); |
| progressSpinner.setVisible(true); |
| } |
| } |
| |
| private void relocateProgressAnimation() |
| { |
| if (progressSpinner != null) |
| { |
| GC gc = new GC(this); |
| |
| try |
| { |
| Point textExtent = gc.textExtent(getText()); |
| int spinnerTextGap = 10; |
| Rectangle clientArea = getClientArea(); |
| int startX = (clientArea.width - textExtent.x) / 2 - spinnerTextGap - progressSpinner.getWidth(); |
| int startY = (clientArea.height - progressSpinner.getHeight()) / 2; |
| progressSpinner.setLocation(startX, startY); |
| } |
| finally |
| { |
| gc.dispose(); |
| } |
| } |
| } |
| |
| public State getCurrentState() |
| { |
| return currentState; |
| } |
| |
| @Override |
| public void drawBackground(GC gc, int x, int y, int width, int height, int offsetX, int offsetY) |
| { |
| if (currentState == State.INSTALLING) |
| { |
| gc.setBackground(AbstractSimpleDialog.COLOR_LIGHTEST_GRAY); |
| gc.fillRoundRectangle(x, y, width, height, getCornerWidth(), getCornerWidth()); |
| |
| int progressWidth = (int)(width * progress); |
| gc.setBackground(currentState.backgroundColor); |
| gc.fillRoundRectangle(x, y, progressWidth, height, getCornerWidth(), getCornerWidth()); |
| |
| // Check if we should draw a hard edge. |
| if (progressWidth <= width - getCornerWidth() / 2) |
| { |
| gc.fillRectangle(progressWidth - getCornerWidth(), y, getCornerWidth(), height); |
| } |
| |
| if (progressSpinner != null) |
| { |
| progressSpinner.update(gc); |
| } |
| } |
| else |
| { |
| super.drawBackground(gc, x, y, width, height, offsetX, offsetY); |
| } |
| } |
| |
| /** |
| * @author Andreas Scharf |
| */ |
| public static enum State |
| { |
| INSTALL(Messages.SimpleInstallLaunchButton_Install_label, Messages.SimpleInstallLaunchButton_Install_message, COLOR_INSTALL, COLOR_FOREGROUND_DEFAULT, |
| SetupInstallerPlugin.INSTANCE.getSWTImage("simple/install_button_install.png"), //$NON-NLS-1$ |
| SetupInstallerPlugin.INSTANCE.getSWTImage("simple/install_button_install_hover.png"), //$NON-NLS-1$ |
| SetupInstallerPlugin.INSTANCE.getSWTImage("simple/install_button_install_disabled.png")), //$NON-NLS-1$ |
| |
| INSTALLING(Messages.SimpleInstallLaunchButton_Installing_label, Messages.SimpleInstallLaunchButton_Installing_message, COLOR_INSTALLING, |
| COLOR_INSTALLING_FOREGROUND, null, null, null), |
| |
| LAUNCH(Messages.SimpleInstallLaunchButton_Launch_label, Messages.SimpleInstallLaunchButton_Launch_message, COLOR_LAUNCH, COLOR_FOREGROUND_DEFAULT, |
| SetupInstallerPlugin.INSTANCE.getSWTImage("simple/install_button_launch.png"), //$NON-NLS-1$ |
| SetupInstallerPlugin.INSTANCE.getSWTImage("simple/install_button_launch_hover.png"), null); //$NON-NLS-1$ |
| |
| public final Image icon; |
| |
| public final Image hoverIcon; |
| |
| public final Image disabledIcon; |
| |
| public final String label; |
| |
| public final String tooltip; |
| |
| public final Color backgroundColor; |
| |
| public final Color foregroundColor; |
| |
| State(final String label, final String tooltip, final Color backgroundColor, final Color foregroundColor, final Image icon, final Image hoverIcon, |
| Image disabledIcon) |
| { |
| this.label = label; |
| this.tooltip = tooltip; |
| this.backgroundColor = backgroundColor; |
| this.foregroundColor = foregroundColor; |
| this.icon = icon; |
| this.hoverIcon = hoverIcon; |
| this.disabledIcon = disabledIcon; |
| } |
| } |
| |
| /** |
| * Simple animation of progress. In contrast to {@link SpriteAnimator}, this spinner is |
| * not a SWT component, which eases handling of transparency on different platforms. |
| * |
| * @author Andreas Scharf |
| */ |
| private class ProgressSpinner implements Runnable |
| { |
| private Image[] sprites; |
| |
| private int currentSpriteIndex = 0; |
| |
| private long nextKeyframeTime = -1; |
| |
| private boolean visible; |
| |
| private long delay; |
| |
| private int x = -1; |
| |
| private int y = -1; |
| |
| private int firstKeyframe = -1; |
| |
| private int lastKeyframe = -1; |
| |
| public ProgressSpinner(Image textureAtlas, int countX, int countY, long delay) |
| { |
| this.delay = delay; |
| sprites = UIUtil.extractSprites(textureAtlas, countX, countY); |
| |
| firstKeyframe = 0; |
| lastKeyframe = sprites.length - 1; |
| |
| visible = false; |
| } |
| |
| public void setLocation(int x, int y) |
| { |
| this.x = x; |
| this.y = y; |
| } |
| |
| public void setKeyframeRange(int firstKeyframe, int lastKeyframe) |
| { |
| this.firstKeyframe = firstKeyframe; |
| this.lastKeyframe = lastKeyframe; |
| } |
| |
| public int getWidth() |
| { |
| return sprites[0].getBounds().width; |
| } |
| |
| public int getHeight() |
| { |
| return sprites[0].getBounds().height; |
| } |
| |
| public void setDelay(long delay) |
| { |
| this.delay = delay; |
| } |
| |
| public void setVisible(boolean visible) |
| { |
| this.visible = visible; |
| if (this.visible) |
| { |
| schedule(); |
| } |
| } |
| |
| public void update(GC gc) |
| { |
| if (!visible || x < 0 || y < 0) |
| { |
| return; |
| } |
| |
| gc.drawImage(sprites[currentSpriteIndex], x, y); |
| |
| long now = System.currentTimeMillis(); |
| if (now >= nextKeyframeTime) |
| { |
| if (++currentSpriteIndex > lastKeyframe) |
| { |
| currentSpriteIndex = firstKeyframe; |
| } |
| |
| nextKeyframeTime = now + delay; |
| } |
| } |
| |
| @Override |
| public void run() |
| { |
| if (visible && !isDisposed()) |
| { |
| SimpleInstallLaunchButton.this.redraw(); |
| schedule(); |
| } |
| } |
| |
| private void schedule() |
| { |
| getDisplay().timerExec((int)delay, this); |
| } |
| } |
| } |