Java tutorial
/******************************************************************************* * 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(); } }