Java tutorial
/** * Aptana Studio * Copyright (c) 2005-2012 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions). * Please see the license.html included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package com.aptana.projects.wizards; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.layout.RowDataFactory; import org.eclipse.jface.layout.RowLayoutFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; 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.ImageData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import com.aptana.core.projects.templates.IProjectTemplate; import com.aptana.core.util.ArrayUtil; import com.aptana.core.util.CollectionsUtil; import com.aptana.core.util.StringUtil; import com.aptana.projects.ProjectsPlugin; import com.aptana.projects.internal.wizards.Messages; import com.aptana.projects.templates.IDefaultProjectTemplate; import com.aptana.projects.templates.ProjectTemplatesManager; import com.aptana.ui.util.SWTUtils; import com.aptana.ui.widgets.StepIndicatorComposite; /** * Wizard page used to select a project template for new projects * * @author Nam Le <nle@appcelerator.com> */ public class ProjectTemplateSelectionPage extends WizardPage implements IStepIndicatorWizardPage { public static final String COMMAND_PROJECT_FROM_TEMPLATE_PROJECT_TEMPLATE_NAME = "projectTemplateId"; //$NON-NLS-1$ public static final String COMMAND_PROJECT_FROM_TEMPLATE_NEW_WIZARD_ID = "newWizardId"; //$NON-NLS-1$ private static final int IMAGE_SIZE = 48; private static final String TAG_ALL = "All"; //$NON-NLS-1$ private TableViewer tagsListViewer; private Composite templatesListComposite; private Label previewImage; private Label previewLabel; private Label previewDescription; private IProjectTemplate[] fTemplates; private IProjectTemplate fSelectedTemplate; private static ImageDescriptor wizardDesc = ProjectsPlugin .getImageDescriptor("/icons/project_template_blank.png"); //$NON-NLS-1$ private Image defaultTemplateImage = null; private Map<IProjectTemplate, Image> templateImages; private Map<Composite, IProjectTemplate> templateControlMap; private Map<String, List<IProjectTemplate>> templateTagsMap; protected StepIndicatorComposite stepIndicatorComposite; protected String[] stepNames; private ISelectionChangedListener tagSelectionChangedListener = new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { ISelection selection = tagsListViewer.getSelection(); if (!selection.isEmpty() && selection instanceof IStructuredSelection) { String tag = (String) ((IStructuredSelection) selection).getFirstElement(); setSelectedTemplate(tag, templateTagsMap.get(tag).get(0)); } } }; public ProjectTemplateSelectionPage(String pageName, List<IProjectTemplate> templates) { super(pageName); if (templates == null) { fTemplates = new IProjectTemplate[0]; } else { List<IProjectTemplate> modifiableTemplates = new ArrayList<IProjectTemplate>(templates); // sorts the list by priority first and then alphabetically Collections.sort(modifiableTemplates, new Comparator<IProjectTemplate>() { public int compare(IProjectTemplate o1, IProjectTemplate o2) { int result = o1.getPriority() - o2.getPriority(); return (result == 0) ? o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName()) : result; } }); fTemplates = templates.toArray(new IProjectTemplate[templates.size()]); } setTitle(Messages.ProjectTemplateSelectionPage_Title); setDescription(Messages.ProjectTemplateSelectionPage_Description); templateImages = new HashMap<IProjectTemplate, Image>(); templateControlMap = new LinkedHashMap<Composite, IProjectTemplate>(); templateTagsMap = new HashMap<String, List<IProjectTemplate>>(); populateTagsMap(); } public IProjectTemplate getSelectedTemplate() { return fSelectedTemplate; } public void createControl(Composite parent) { defaultTemplateImage = wizardDesc.createImage(); parent.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (defaultTemplateImage != null) { defaultTemplateImage.dispose(); defaultTemplateImage = null; } for (Image image : templateImages.values()) { if (!image.isDisposed()) { image.dispose(); } } templateImages = null; } }); Composite main = new Composite(parent, SWT.NONE); main.setLayout(GridLayoutFactory.fillDefaults().spacing(0, 10).create()); main.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); stepIndicatorComposite = new StepIndicatorComposite(main, stepNames); stepIndicatorComposite.setSelection(getStepName()); Label label = new Label(main, SWT.NONE); label.setText(Messages.ProjectTemplateSelectionPage_AvailableTemplates_TXT); label.setLayoutData(GridDataFactory.swtDefaults().create()); Composite templateList = createTemplatesList(main); templateList.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); // go through each tag and auto-select the first default template found; otherwise selects the first template in // the first tag if (!ArrayUtil.isEmpty(fTemplates)) { boolean foundDefault = false; TableItem[] items = tagsListViewer.getTable().getItems(); for (TableItem item : items) { String tag = item.getText(); List<IProjectTemplate> templates = templateTagsMap.get(tag); for (IProjectTemplate template : templates) { if (template instanceof IDefaultProjectTemplate) { foundDefault = true; setSelectedTemplate(tag, template); break; } } if (foundDefault) { break; } } if (!foundDefault) { String tag = items[0].getText(); setSelectedTemplate(tag, templateTagsMap.get(tag).get(0)); } } // Let left/right arrow keys traverse "list" of templates KeyListener keyListener = new KeyListener() { public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.ARROW_RIGHT) { setSelectedTemplate(getNextTemplate(fSelectedTemplate)); } else if (e.keyCode == SWT.ARROW_LEFT) { setSelectedTemplate(getPreviousTemplate(fSelectedTemplate)); } } }; // When template list has focus this takes effect templatesListComposite.addKeyListener(keyListener); // When tag list has focus, still let left/right key listener work tagsListViewer.getTable().addKeyListener(keyListener); tagsListViewer.getTable().setFocus(); Dialog.applyDialogFont(main); setControl(main); } private int getTemplateIndex(IProjectTemplate template) { Control[] children = templatesListComposite.getChildren(); for (Entry<Composite, IProjectTemplate> entry : templateControlMap.entrySet()) { if (entry.getValue().equals(template)) { Composite comp = entry.getKey(); for (int i = 0; i < children.length; i++) { if (comp == children[i]) { return i; } } } } return -1; } protected IProjectTemplate getPreviousTemplate(IProjectTemplate selectedTemplate) { int index = getTemplateIndex(selectedTemplate); if (index == -1) { return selectedTemplate; } Control[] children = templatesListComposite.getChildren(); int prevIndex = index - 1; if (prevIndex < 0) { prevIndex = children.length - 1; } return templateControlMap.get(children[prevIndex]); } protected IProjectTemplate getNextTemplate(IProjectTemplate selectedTemplate) { int index = getTemplateIndex(selectedTemplate); if (index == -1) { return selectedTemplate; } Control[] children = templatesListComposite.getChildren(); int nextIndex = index + 1; if (nextIndex >= children.length) { nextIndex = 0; } return templateControlMap.get(children[nextIndex]); } private Composite createTemplatesList(Composite parent) { Composite main = new Composite(parent, SWT.NONE); main.setLayout(GridLayoutFactory.fillDefaults().spacing(0, 0).numColumns(2).create()); Color background = main.getDisplay().getSystemColor(SWT.COLOR_WHITE); main.setBackground(background); // the left side is the list of template tags Composite templateTags = new Composite(main, SWT.BORDER); templateTags.setLayout(GridLayoutFactory.swtDefaults().create()); // If there are only the "All" tag and one other tag, don't both showing the left column. boolean exclude = templateTagsMap.size() <= 2; templateTags.setLayoutData( GridDataFactory.fillDefaults().grab(false, true).hint(150, SWT.DEFAULT).exclude(exclude).create()); templateTags.setBackground(background); List<String> tags = new ArrayList<String>(templateTagsMap.keySet()); Collections.sort(tags); tagsListViewer = new TableViewer(templateTags, SWT.SINGLE | SWT.FULL_SELECTION); tagsListViewer.setContentProvider(ArrayContentProvider.getInstance()); tagsListViewer.setLabelProvider(new LabelProvider() { @Override public Image getImage(Object element) { if (element instanceof String) { return getProjectTemplatesManager().getImageForTag((String) element); } return super.getImage(element); } }); tagsListViewer.setInput(tags); tagsListViewer.setComparator(new ViewerComparator() { @Override public int category(Object element) { // make sure the "All" tag appears at the bottom return TAG_ALL.equals(element) ? 1 : 0; } }); Table tagsList = tagsListViewer.getTable(); tagsList.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); tagsList.setBackground(background); FontData[] fontData = SWTUtils.resizeFont(tagsList.getFont(), 2); final Font tagFont = new Font(tagsList.getDisplay(), fontData); tagsList.setFont(tagFont); tagsList.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { tagFont.dispose(); } }); tagsListViewer.addSelectionChangedListener(tagSelectionChangedListener); // the right side has the list of templates for the selected tag and the details on the selected template Composite rightComp = new Composite(main, SWT.BORDER); rightComp.setLayout(GridLayoutFactory.fillDefaults().create()); rightComp.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); rightComp.setBackground(background); templatesListComposite = new Composite(rightComp, SWT.NONE); templatesListComposite.setLayout( RowLayoutFactory.swtDefaults().extendedMargins(5, 5, 5, 5).spacing(10).fill(true).create()); templatesListComposite .setLayoutData(GridDataFactory.fillDefaults().grab(true, true).hint(450, 250).create()); templatesListComposite.setBackground(background); Label separator = new Label(rightComp, SWT.SEPARATOR | SWT.HORIZONTAL); separator.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); Composite descriptionComp = createTemplateDescription(rightComp); descriptionComp .setLayoutData(GridDataFactory.fillDefaults().grab(true, false).hint(SWT.DEFAULT, 110).create()); return main; } protected Composite createTemplateDescription(Composite parent) { Composite main = new Composite(parent, SWT.NONE); main.setLayout(GridLayoutFactory.swtDefaults().extendedMargins(7, 0, 0, 0).numColumns(2).create()); Color background = main.getDisplay().getSystemColor(SWT.COLOR_WHITE); main.setBackground(background); previewImage = new Label(main, SWT.CENTER); previewImage.setBackground(background); previewImage.setLayoutData(GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).create()); previewLabel = new Label(main, SWT.LEFT); previewLabel.setBackground(background); previewLabel.setLayoutData( GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).create()); FontData[] fontData = SWTUtils.resizeFont(previewLabel.getFont(), 2); for (FontData data : fontData) { data.setStyle(data.getStyle() | SWT.BOLD); } final Font previewFont = new Font(previewLabel.getDisplay(), fontData); previewLabel.setFont(previewFont); previewLabel.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { previewFont.dispose(); } }); previewDescription = new Label(main, SWT.WRAP); previewDescription.setBackground(background); previewDescription.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(2, 1).create()); return main; } private void setSelectedTag(String tag) { tagsListViewer.removeSelectionChangedListener(tagSelectionChangedListener); tagsListViewer.setSelection(new StructuredSelection(tag)); tagsListViewer.addSelectionChangedListener(tagSelectionChangedListener); // re-construct the list of templates shown on the right Control[] children = templatesListComposite.getChildren(); for (Control templateControl : children) { templateControl.dispose(); } templateControlMap.clear(); List<IProjectTemplate> templates = templateTagsMap.get(tag); Color background = templatesListComposite.getBackground(); for (IProjectTemplate template : templates) { final Composite templateControl = new Composite(templatesListComposite, SWT.NONE); templateControl.setLayout(GridLayoutFactory.fillDefaults().extendedMargins(0, 0, 5, 5).create()); templateControl.setLayoutData(RowDataFactory.swtDefaults().hint(95, SWT.DEFAULT).create()); templateControl.setBackground(background); Label image = new Label(templateControl, SWT.CENTER); image.setImage(getImage(template)); image.setBackground(background); image.setLayoutData( GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).create()); Label text = new Label(templateControl, SWT.CENTER | SWT.WRAP); text.setText(template.getDisplayName()); text.setBackground(background); text.setLayoutData( GridDataFactory.fillDefaults().grab(true, true).align(SWT.CENTER, SWT.BEGINNING).create()); MouseAdapter mouseAdapter = new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { setSelectedTemplate(templateControlMap.get(templateControl)); } @Override public void mouseDoubleClick(MouseEvent e) { // Treat double-click like selecting the template and clicking "Next" if (canFlipToNextPage()) { getContainer().showPage(getNextPage()); } } }; templateControl.addMouseListener(mouseAdapter); image.addMouseListener(mouseAdapter); text.addMouseListener(mouseAdapter); templateControlMap.put(templateControl, template); } templatesListComposite.layout(true, true); } private void setSelectedTemplate(IProjectTemplate template) { // make the corresponding template control appear selected Set<Composite> templateControls = templateControlMap.keySet(); for (Composite composite : templateControls) { Color background; if (templateControlMap.get(composite) == template) { background = composite.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); } else { background = composite.getDisplay().getSystemColor(SWT.COLOR_WHITE); } composite.setBackground(background); Control[] children = composite.getChildren(); for (Control childComp : children) { childComp.setBackground(background); } } // update the preview area according to the template selection previewImage.setImage(getImage(template)); previewLabel.setText(template.getDisplayName()); String text = (template == null) ? null : template.getDescription(); previewDescription.setText(text == null ? StringUtil.EMPTY : text); fSelectedTemplate = template; } private void setSelectedTemplate(String tag, IProjectTemplate template) { setSelectedTag(tag); setSelectedTemplate(template); } private Image getImage(IProjectTemplate template) { Image image = templateImages.get(template); if (image == null) { // Resolve and load the image URL iconPath = template.getIconURL(); if (iconPath != null) { ImageDescriptor descriptor = ImageDescriptor.createFromURL(iconPath); if (descriptor != null) { image = descriptor.createImage(false); if (image != null) { // Scale the image to 48x48 in case it's not. ImageData imageData = image.getImageData(); if (imageData.x != IMAGE_SIZE || imageData.y != IMAGE_SIZE) { // dispose the previous one image.dispose(); // Scale the image data and create a new image imageData = imageData.scaledTo(IMAGE_SIZE, IMAGE_SIZE); image = ImageDescriptor.createFromImageData(imageData).createImage(); } } } } if (image == null) { image = defaultTemplateImage; } templateImages.put(template, image); } return image; } private void populateTagsMap() { templateTagsMap.clear(); for (IProjectTemplate template : fTemplates) { List<String> tags = template.getTags(); if (!CollectionsUtil.isEmpty(tags)) { for (String tag : tags) { List<IProjectTemplate> tagTemplates = templateTagsMap.get(tag); if (tagTemplates == null) { tagTemplates = new ArrayList<IProjectTemplate>(); templateTagsMap.put(tag, tagTemplates); } tagTemplates.add(template); } } } // add an "All" tag to hold the full list of templates templateTagsMap.put(TAG_ALL, Arrays.asList(fTemplates)); } public void initStepIndicator(String[] stepNames) { this.stepNames = stepNames; } public String getStepName() { return getTitle(); } protected ProjectTemplatesManager getProjectTemplatesManager() { return ProjectsPlugin.getDefault().getTemplatesManager(); } }