/******************************************************************************* * Copyright (c) 2010, 2013 Wind River Systems 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: * Doug Schaefer (WRS) - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.ui.wizards; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.eclipse.cdt.managedbuilder.core.IToolChain; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.internal.ui.Messages; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.progress.WorkbenchJob; /** * Page to select existing code location and toolchain. * * @since 7.0 */ public class NewMakeProjFromExistingPage extends WizardPage { Text projectName; Text location; Button langc; Button langcpp; IWorkspaceRoot root; List tcList; Map<String, IToolChain> tcMap = new HashMap<String, IToolChain>(); /** * True if the user entered a non-empty string in the project name field. In that state, we avoid * automatically filling the project name field with the directory name (last segment of the location) he * has entered. */ boolean projectNameSetByUser; protected NewMakeProjFromExistingPage() { super(Messages.NewMakeProjFromExistingPage_0); setTitle(Messages.NewMakeProjFromExistingPage_1); setDescription(Messages.NewMakeProjFromExistingPage_2); root = ResourcesPlugin.getWorkspace().getRoot(); } @Override public void createControl(Composite parent) { Composite comp = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); comp.setLayout(layout); comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); addProjectNameSelector(comp); addSourceSelector(comp); addLanguageSelector(comp); addToolchainSelector(comp); setControl(comp); } public void addProjectNameSelector(Composite parent) { Group group = new Group(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; group.setLayout(layout); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); group.setText(Messages.NewMakeProjFromExistingPage_3); projectName = new Text(group, SWT.BORDER); projectName.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); projectName.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { validatePage(); if (getProjectName().isEmpty()) { projectNameSetByUser = false; } } }); // Note that the modify listener gets called not only when the user enters text but also when we // programatically set the field. This listener only gets called when the user modifies the field projectName.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { projectNameSetByUser = true; } }); } /** * Validates the contents of the page, setting the page error message and Finish button state accordingly * * @since 8.1 */ protected void validatePage() { // Don't generate an error if project name or location is empty, but do disable Finish button. String msg = null; boolean complete = true; // ultimately treated as false if msg != null String name = getProjectName(); if (name.isEmpty()) { complete = false; } else { IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.PROJECT); if (!status.isOK()) { msg = status.getMessage(); } else { IProject project = root.getProject(name); if (project.exists()) { msg = Messages.NewMakeProjFromExistingPage_4; } } } if (msg == null) { String loc = getLocation(); if (loc.isEmpty()) { complete = false; } else { final File file= new File(loc); if (file.isDirectory()) { // Ensure we can create files in the directory. if (!file.canWrite()) msg = Messages.NewMakeProjFromExistingPage_DirReadOnlyError; // Set the project name to the directory name but not if the user has supplied a name // (bugzilla 368987). Use a job to ensure proper sequence of activity, as setting the Text // will invoke the listener, which will invoke this method. else if (!projectNameSetByUser && !name.equals(file.getName())) { WorkbenchJob wjob = new WorkbenchJob("update project name") { //$NON-NLS-1$ @Override public IStatus runInUIThread(IProgressMonitor monitor) { if (!projectName.isDisposed()) { projectName.setText(file.getName()); } return Status.OK_STATUS; } }; wjob.setSystem(true); wjob.schedule(); } } else { msg = Messages.NewMakeProjFromExistingPage_8; } } } setErrorMessage(msg); setPageComplete((msg == null) && complete); } /** @deprecated Replaced by {@link #validatePage()} */ @Deprecated public void validateProjectName() { validatePage(); } public void addSourceSelector(Composite parent) { Group group = new Group(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; group.setLayout(layout); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); group.setText(Messages.NewMakeProjFromExistingPage_5); location = new Text(group, SWT.BORDER); location.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); location.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { validatePage(); } }); validatePage(); Button browse = new Button(group, SWT.NONE); browse.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true)); browse.setText(Messages.NewMakeProjFromExistingPage_6); browse.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { DirectoryDialog dialog = new DirectoryDialog(location.getShell()); dialog.setMessage(Messages.NewMakeProjFromExistingPage_7); String dir = dialog.open(); if (dir != null) location.setText(dir); } @Override public void widgetDefaultSelected(SelectionEvent e) { } }); } /** @deprecated Replaced by {@link #validatePage()} */ @Deprecated void validateSource() { validatePage(); } public void addLanguageSelector(Composite parent) { Group group = new Group(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; group.setLayout(layout); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); group.setText(Messages.NewMakeProjFromExistingPage_9); // TODO, should be a way to dynamically list these langc = new Button(group, SWT.CHECK); langc.setText("C"); //$NON-NLS-1$ langc.setSelection(true); langcpp = new Button(group, SWT.CHECK); langcpp.setText("C++"); //$NON-NLS-1$ langcpp.setSelection(true); } public void addToolchainSelector(Composite parent) { Group group = new Group(parent, SWT.NONE); GridLayout layout = new GridLayout(); group.setLayout(layout); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); group.setText(Messages.NewMakeProjFromExistingPage_10); tcList = new List(group, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); // Base the List control size on the number of total toolchains, up to 15 entries, but allocate for no // less than five (small list boxes look strange). A vertical scrollbar will appear as needed updateTcMap(false); gd.heightHint = tcList.getItemHeight() * (1 + Math.max(Math.min(tcMap.size(), 15), 5)); // +1 for <none> tcList.setLayoutData(gd); tcList.add(Messages.NewMakeProjFromExistingPage_11); final Button supportedOnly = new Button(group, SWT.CHECK); supportedOnly.setSelection(false); supportedOnly.setText(Messages.NewMakeProjFromExistingPage_show_only_supported); gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; supportedOnly.setLayoutData(gd); supportedOnly.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateTcWidget(supportedOnly.getSelection()); }}); supportedOnly.setSelection(true); updateTcWidget(true); } /** * Load our map and with the suitable toolchains and then populate the List control * * @param supportedOnly * if true, consider only supported toolchains */ private void updateTcWidget(boolean supportedOnly) { updateTcMap(supportedOnly); ArrayList<String> names = new ArrayList<String>(tcMap.keySet()); Collections.sort(names); tcList.removeAll(); tcList.add(Messages.NewMakeProjFromExistingPage_11); // <none> for (String name : names) tcList.add(name); tcList.setSelection(0); // select <none> } /** * Load our map with the suitable toolchains. * * @param supportedOnly * if true, add only toolchains that are available and which support the host platform */ private void updateTcMap(boolean supportedOnly) { tcMap.clear(); IToolChain[] toolChains = ManagedBuildManager.getRealToolChains(); for (IToolChain toolChain : toolChains) { if (toolChain.isAbstract() || toolChain.isSystemObject()) continue; if (supportedOnly) { if (!toolChain.isSupported() || !ManagedBuildManager.isPlatformOk(toolChain)) { continue; } } tcMap.put(toolChain.getUniqueRealName(), toolChain); } } public String getProjectName() { return projectName.getText().trim(); } public String getLocation() { return location.getText().trim(); } public boolean isC() { return langc.getSelection(); } public boolean isCPP() { return langcpp.getSelection(); } public IToolChain getToolChain() { String[] selection = tcList.getSelection(); return selection.length != 0 ? tcMap.get(selection[0]) : null; } }