/******************************************************************************* * Copyright (c) 2014 Mentor Graphics and others. * 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: * Mentor Graphics - initial API and implementation *******************************************************************************/ package com.codesourcery.internal.installer.ui; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import com.codesourcery.installer.Installer; /** * Composite that shows a list of steps to be performed, * steps that have been performed, and the * current step. */ public class SideBarComposite extends Composite { /** Step states */ public enum StepState {NONE, ERROR, SUCCESS}; /** Bullet empty image */ private Image bulletEmpty; /** Bullet error image */ private Image bulletError; /** Bullet checked image */ private Image bulletChecked; /** Bullet arrow image */ private Image bulletArrow; /** Bullet solid image */ private Image bulletSolid; /** * Step labels */ ArrayList<CLabel> stepLabels = new ArrayList<CLabel>(); /** * Steps area */ Composite stepsArea; /** * Font for current step */ Font currentFont; /** * Current step */ String currentStep; /** * Constructor * * @param parent Parent * @param style Style flags * @param bulletEmpty Empty bullet image * @param bulletSolid Solit bullet image * @param bulletChecked Checked bullet image * @param bulletArrow Arrow bullet image * @param bulletError Error bullet image * @param boldCurrent <code>true</code> to bold current step text, <code>false</code> to enlarge current step text. */ public SideBarComposite(Composite parent, int style, Image bulletEmpty, Image bulletSolid, Image bulletChecked, Image bulletArrow, Image bulletError, boolean boldCurrent) { super(parent, style); this.bulletEmpty = bulletEmpty; this.bulletSolid = bulletSolid; this.bulletChecked = bulletChecked; this.bulletArrow = bulletArrow; this.bulletError = bulletError; GridLayout layout = new GridLayout(1, false); setLayout(layout); // Steps area stepsArea = new Composite(this, SWT.NONE); GridLayout stepsLayout = new GridLayout(1, true); stepsLayout.marginHeight = 0; stepsLayout.marginWidth = 0; stepsArea.setLayout(stepsLayout); stepsArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); stepsArea.setBackground(getBackground()); setFont(parent.getFont()); // Create bold font FontData[] fontData = getFont().getFontData(); if (boldCurrent) { fontData[0].setStyle(SWT.BOLD); } else { fontData[0].setHeight(fontData[0].getHeight() + 3); } currentFont = new Font(getFont().getDevice(), fontData); } /** * Adds a step * * @param stepName Step name */ public void addStep(String stepName) { CLabel stepLabel = new CLabel(stepsArea, SWT.NONE); stepLabel.setText(stepName); stepLabel.setImage(bulletEmpty); stepLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 1, 1)); stepLabel.setData(new Step()); stepLabels.add(stepLabel); } /** * Sets the current step * * @param stepName Name of step to set current */ public void setCurrentStep(String stepName) { boolean mark = true; for (CLabel stepLabel : stepLabels) { Step step = (Step)stepLabel.getData(); step.setCompleted(mark); if (stepLabel.getText().equals(stepName)) { step.setCurrent(true); mark = false; } } updateLabels(); } public Point computeSize (int wHint, int hHint, boolean changed) { try { if (wHint == SWT.DEFAULT) { // Compute widest image int maxImageWidth = 0; Image widestImage = null; if ((bulletError != null) && (bulletError.getImageData().width > maxImageWidth)) { maxImageWidth = bulletError.getImageData().width; widestImage = bulletError; } if ((bulletChecked != null) && (bulletChecked.getImageData().width > maxImageWidth)) { maxImageWidth = bulletChecked.getImageData().width; widestImage = bulletChecked; } if ((bulletArrow != null) && (bulletArrow.getImageData().width > maxImageWidth)) { maxImageWidth = bulletArrow.getImageData().width; widestImage = bulletArrow; } if ((bulletSolid != null) && (bulletSolid.getImageData().width > maxImageWidth)) { maxImageWidth = bulletSolid.getImageData().width; widestImage = bulletSolid; } if ((bulletEmpty != null) && (bulletEmpty.getImageData().width > maxImageWidth)) { maxImageWidth = bulletEmpty.getImageData().width; widestImage = bulletEmpty; } // Set attributes to produce widest step for (CLabel stepLabel : stepLabels) { stepLabel.setFont(currentFont); stepLabel.setImage(widestImage); } } } catch (Exception e) { Installer.log(e); } // Compute size Point preferredSize = super.computeSize(wHint, hHint, changed); // Restore step attributes if (wHint == SWT.DEFAULT) { try { updateLabels(); } catch (Exception e) { Installer.log(e); } } return preferredSize; } /** * Updates all step labels. */ private void updateLabels() { Color activeColor = getDisplay().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND); Color inactiveColor = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW); for (CLabel stepLabel : stepLabels) { Step step = (Step)stepLabel.getData(); stepLabel.setFont(getFont()); stepLabel.setForeground(step.isCompleted ? activeColor : inactiveColor); // Step has error if (step.getState() == StepState.ERROR) { stepLabel.setImage(bulletError); } // Step is successful else if (step.getState() == StepState.SUCCESS) { stepLabel.setImage(bulletChecked); } // Step is current else if (step.isCurrent()) { stepLabel.setImage(bulletArrow); stepLabel.setFont(currentFont); } // Step is completed else if (step.isCompleted()) { stepLabel.setImage(bulletSolid); } // Step is not completed else { stepLabel.setImage(bulletEmpty); } } stepsArea.layout(true); } /** * Sets the state of a step. * * @param stepName Step name * @param state State */ public void setState(String stepName, StepState state) { for (CLabel stepLabel : stepLabels) { if (stepLabel.getText().equals(stepName)) { Step step = (Step)stepLabel.getData(); step.setState(state); break; } } updateLabels(); } /** * Returns the state of a step. * * @param stepName Step name * @return State */ public StepState getState(String stepName) { StepState state = StepState.NONE; for (CLabel stepLabel : stepLabels) { if (stepLabel.getText().equals(stepName)) { Step step = (Step)stepLabel.getData(); state = step.getState(); break; } } return state; } @Override public void dispose() { if (currentFont != null) { currentFont.dispose(); currentFont = null; } super.dispose(); } /** * Step in bar */ private class Step { /** <code>true</code> if current step */ private boolean isCurrent = false; /** <code>true</code> if state is completed */ private boolean isCompleted = false; /** Step state */ private StepState state = StepState.NONE; /** * Sets the step current. * * @param current <code>true</code> if current */ public void setCurrent(boolean current) { this.isCurrent = current; } /** * Returns if the step is current. * * @return <code>true</code> if current */ public boolean isCurrent() { return isCurrent; } /** * Sets the step completed. * * @param completed <code>true</code> if completed. */ public void setCompleted(boolean completed) { this.isCompleted = completed; } /** * Returns if the step is completed. * * @return <code>true</code> if completed. */ public boolean isCompleted() { return isCompleted; } /** * Sets the step state. * * @param state Step state */ public void setState(StepState state) { this.state = state; } /** * Returns the step state. * * @return Step state */ public StepState getState() { return state; } } }