com.liferay.ide.project.ui.upgrade.animated.GearControl.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.ide.project.ui.upgrade.animated.GearControl.java

Source

/*******************************************************************************
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 *******************************************************************************/

package com.liferay.ide.project.ui.upgrade.animated;

import com.liferay.ide.project.ui.upgrade.animated.UpgradeView.PageActionListener;
import com.liferay.ide.project.ui.upgrade.animated.UpgradeView.PageNavigatorListener;
import com.liferay.ide.project.ui.upgrade.animated.UpgradeView.PageValidationListener;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;

/**
 * @author Andy Wu
 * @author Simon Jiang
 */
public class GearControl extends AbstractCanvas
        implements PageNavigatorListener, PageActionListener, PageValidationListener {

    private float angle;

    private final int BORDER = 20;

    private Display display;

    private Image errorImage;
    private Image warningImage;
    private Map<String, PageValidateEvent> validationMessageMap = new HashMap<String, PageValidateEvent>();

    private final Color[] gearBackground = new Color[2];
    private final Color[] gearForeground = new Color[2];

    private int gearMaxNumber = 10;

    private final Path[] gearPaths = new Path[gearMaxNumber];
    private final Point[] tooltipPoints = new Point[gearMaxNumber];

    private Color DARK_GRAY;
    private Color GRAY;
    private Color WHITE;
    private Color tooltipColor;

    private int hover = NONE;

    private boolean needRedraw = false;

    private Font numberFont;

    private int oldHover = NONE;

    private int oldSelection = NONE;

    private boolean overflow;

    private final double RADIAN = 2 * Math.PI / 360;

    private float radius;

    private int selection;

    private final List<SelectionChangedListener> selectionChangedListeners = Collections
            .synchronizedList(new ArrayList<SelectionChangedListener>());

    private float speed;

    private long startAnimation;

    private final int TEETH = 8;

    private final float ANGLE = 360 / TEETH;

    private Font tooltipFont;

    public GearControl(Composite parent, int style) {
        super(parent, style | SWT.DOUBLE_BUFFERED);

        init();

        scheduleRun();
    }

    public void addSelectionChangedListener(SelectionChangedListener listener) {
        selectionChangedListeners.add(listener);
    }

    private Path drawGear(GC gc, Display display, double cx, double cy, double outerR, double innerR,
            float angleOffset) {
        double radian2 = ANGLE / 2 * RADIAN;
        double radian3 = .06;

        Path path = new Path(display);

        for (int i = 0; i < TEETH; i++) {
            double radian = (i * ANGLE + angleOffset) * RADIAN;
            double x = cx + outerR * Math.cos(radian);
            double y = cy - outerR * Math.sin(radian);

            if (i == 0) {
                path.moveTo((int) x, (int) y);
            }

            double r1 = radian + radian3;
            double r3 = radian + radian2;
            double r2 = r3 - radian3;
            double r4 = r3 + radian2;

            x = cx + innerR * Math.cos(r1);
            y = cy - innerR * Math.sin(r1);
            path.lineTo((int) x, (int) y);

            x = cx + innerR * Math.cos(r2);
            y = cy - innerR * Math.sin(r2);
            path.lineTo((int) x, (int) y);

            x = cx + outerR * Math.cos(r3);
            y = cy - outerR * Math.sin(r3);
            path.lineTo((int) x, (int) y);

            x = cx + outerR * Math.cos(r4);
            y = cy - outerR * Math.sin(r4);
            path.lineTo((int) x, (int) y);
        }

        path.close();
        gc.fillPath(path);
        gc.drawPath(path);

        return path;
    }

    public final int getSelection() {
        return selection;
    }

    protected void init() {
        super.init();

        display = getDisplay();

        errorImage = JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_ERROR);
        warningImage = JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_WARNING);

        WHITE = display.getSystemColor(SWT.COLOR_WHITE);
        GRAY = display.getSystemColor(SWT.COLOR_GRAY);
        DARK_GRAY = display.getSystemColor(SWT.COLOR_DARK_GRAY);

        Font initialFont = getFont();
        FontData[] fontData = initialFont.getFontData();

        for (int i = 0; i < fontData.length; i++) {
            fontData[i].setHeight(16);
            fontData[i].setStyle(SWT.BOLD);
        }

        baseFont = new Font(display, fontData);

        numberFont = createFont(24);
        tooltipFont = createFont(24);

        radius = 32;
        setSize((int) (gearMaxNumber * 2 * radius), (int) (2 * radius));

        // Not selected.
        gearBackground[0] = createColor(169, 171, 202);
        gearForeground[0] = createColor(140, 132, 171);

        // Selected.
        gearBackground[1] = createColor(247, 148, 30);
        gearForeground[1] = createColor(207, 108, 0);

        tooltipColor = createColor(253, 232, 206);
    }

    @Override
    protected boolean needRedraw() {
        boolean retVal = false;

        if (needRedraw) {
            needRedraw = false;
            retVal = true;
        }

        if (overflow) {
            overflow = false;
            retVal = true;
        }

        if (hover != oldHover) {
            retVal = true;
        }

        if (speed >= ANGLE) {
            startAnimation = 0;

            return retVal;
        }

        long now = currentTime;

        if (startAnimation == 0) {
            startAnimation = now;
        }

        long timeSinceStart = now - startAnimation;

        speed = timeSinceStart * ANGLE / 400;
        angle += speed;

        return true;
    }

    @Override
    protected void onMouseDown(int x, int y) {
        if (x != Integer.MIN_VALUE && y != Integer.MIN_VALUE) {
            GC gc = new GC(this);

            for (int i = 0; i < gearPaths.length; i++) {
                Path path = gearPaths[i];

                if (path != null && path.contains(x, y, gc, false)) {
                    if (i != getSelection()) {
                        setSelection(i);
                    }
                }
            }
        }
    }

    @Override
    protected void onMouseMove(int x, int y) {
        if (x != Integer.MIN_VALUE && y != Integer.MIN_VALUE) {
            GC gc = new GC(this);

            int number = UpgradeView.getPageNumber();

            for (int i = 0; i < number; i++) {
                Path path = gearPaths[i];

                if (path != null && path.contains(x, y, gc, false)) {
                    if (i != hover) {
                        hover = i;
                    }

                    return;
                }
            }
        }

        hover = NONE;
    }

    @Override
    public void onPageAction(PageActionEvent event) {
        int targetPageIndex = event.getTargetPageIndex();

        needRedraw = true;

        if (targetPageIndex != NONE) {
            setSelection(targetPageIndex);
        }

    }

    @Override
    public void onPageNavigate(PageNavigateEvent event) {
        setSelection(event.getTargetPage());
    }

    @Override
    public void onValidation(PageValidateEvent event) {
        String pageId = event.getPageId();

        validationMessageMap.put(pageId, event);

        Page page = UpgradeView.getPage(selection);

        if (page.getPageId().equals(pageId)) {
            needRedraw = true;
        }
    }

    @Override
    protected void paint(GC gc) {
        gc.setFont(getBaseFont());
        gc.setLineWidth(3);
        gc.setAntialias(SWT.ON);

        int alpha = Math.min((int) (255 * speed / ANGLE), 255);

        int number = UpgradeView.getPageNumber();

        for (int i = 0; i < number; i++) {
            tooltipPoints[i] = paintGear(gc, i, alpha);
        }

        if (hover >= 0 && hover < tooltipPoints.length) {
            Point point = tooltipPoints[hover];

            String title = UpgradeView.getPage(hover).getTitle();

            gc.setFont(tooltipFont);
            gc.setForeground(DARK_GRAY);
            gc.setBackground(tooltipColor);

            Rectangle rectangle = drawText(gc, point.x, point.y + 14, title, 2);

            gc.setForeground(GRAY);
            gc.setLineWidth(1);
            gc.drawRectangle(rectangle);
        }

        paintValidationMessage(gc);

        oldHover = hover;

    }

    private void paintValidationMessage(GC gc) {
        Page page = UpgradeView.getPage(selection);

        String pageId = page.getPageId();

        PageValidateEvent event = validationMessageMap.get(pageId);

        if (event != null) {
            String message = event.getMessage();

            if (message != null && !message.equals("ok")) {
                if (event.getType().equals(PageValidateEvent.ERROR)) {
                    drawImage(gc, errorImage, 30, 130);
                } else {
                    drawImage(gc, warningImage, 30, 130);
                }

                gc.setBackground(tooltipColor);
                gc.setForeground(DARK_GRAY);
                gc.setLineWidth(1);

                Rectangle rectangle = drawTextNotCenter(gc, 40, 120, message, 2);

                gc.drawRectangle(rectangle);
            }
        }
    }

    private Point paintBadge(GC gc, double x, double y, double outerR, int i, int alpha) {
        if (selection >= gearMaxNumber) {
            gc.setAlpha(255 - alpha);
        } else if (oldSelection >= gearMaxNumber) {
            gc.setAlpha(alpha);
        }

        Image badgeImage = null;

        Page page = UpgradeView.getPage(i);

        PageAction pageAction = page.getSelectedAction();

        if (pageAction != null) {
            badgeImage = pageAction.getBageImage();
        }

        if (badgeImage != null) {
            gc.drawImage(badgeImage, (int) (x - badgeImage.getBounds().width / 2), (int) (y - outerR - 12));
            gc.setAlpha(255);
        }

        return new Point((int) x, (int) (y + outerR));
    }

    private Point paintGear(GC gc, int i, int alpha) {
        double offset = 2 * i * radius;
        double x = BORDER + radius + offset;
        double y = BORDER + radius;
        double r2 = (double) radius * .8f;
        double r3 = (double) radius * .5f;

        int selected = 0;
        double factor = 1;

        if (i == oldSelection) {
            if (speed < ANGLE / 2) {
                selected = 1;
            }
        } else if (i == selection) {
            if (speed >= ANGLE / 2) {
                selected = 1;
                factor += (ANGLE - speed) * .02;
            } else {
                factor += speed * .02;
            }
        }

        boolean hovered = false;

        if (i == hover) {
            factor += .1;
            oldHover = hover;
            if (selected == 0) {
                hovered = true;
            }
        }

        double outerR = factor * radius;
        double innerR = factor * r2;
        float angleOffset = (angle + i * ANGLE) * (i % 2 == 1 ? -1 : 1) / 7;

        gc.setForeground(hovered ? DARK_GRAY : gearForeground[selected]);
        gc.setBackground(hovered ? GRAY : gearBackground[selected]);

        if (outerR < 32.0) {
            outerR = 32.0D;
        }

        if (innerR < 25.0) {
            innerR = 25.600000381469727D;
        }

        Path path = drawGear(gc, display, x, y, outerR, innerR, angleOffset);

        if (gearPaths[i] != null) {
            gearPaths[i].dispose();
        }

        gearPaths[i] = path;

        int ovalX = (int) (x - factor * r3);
        int ovalY = (int) (y - factor * r3);
        int ovalR = (int) (2 * factor * r3);
        gc.setBackground(WHITE);
        gc.fillOval(ovalX, ovalY, ovalR, ovalR);
        gc.drawOval(ovalX, ovalY, ovalR, ovalR);

        if (i < gearMaxNumber) {
            String number = Integer.toString(i + 1);

            gc.setForeground(selected == 1 ? gearForeground[1] : GRAY);
            gc.setFont(numberFont);

            drawText(gc, x, y - 1, number);
        }

        return paintBadge(gc, x, y, outerR, i, alpha);
    }

    public void restart() {
        angle = 0;
        speed = 0;
    }

    public final void setSelection(int selection) {
        hover = NONE;
        oldHover = NONE;

        if (selection < 0) {
            selection = 0;
            overflow = true;
        } else if (selection > gearMaxNumber - 1) {
            selection = gearMaxNumber - 1;
            overflow = true;
        }

        if (overflow) {
            overflow = false;

            while (needRedraw()) {
            }

            overflow = true;

            return;
        }

        oldSelection = this.selection;

        this.selection = selection;

        for (SelectionChangedListener listener : selectionChangedListeners) {
            listener.onSelectionChanged(selection);
        }

        restart();
    }
}