--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+import org.eclipse.core.resources.IFolder;
+
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.layout.PixelConverter;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.StructuredSelection;
+
+import org.eclipse.ui.forms.events.ExpansionAdapter;
+import org.eclipse.ui.forms.events.ExpansionEvent;
+import org.eclipse.ui.forms.widgets.ExpandableComposite;
+
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+import org.eclipse.jdt.internal.corext.buildpath.BuildpathDelta;
+import org.eclipse.jdt.internal.corext.buildpath.ClasspathModifier;
+import org.eclipse.jdt.internal.corext.buildpath.IBuildpathModifierListener;
+
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.preferences.ScrolledPageContent;
+import org.eclipse.jdt.internal.ui.util.ViewerPane;
+import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathsBlock;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementAttribute;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
+
+
+public class NewSourceContainerWorkbookPage extends BuildPathBasePage implements IBuildpathModifierListener {
+
+ public static final String OPEN_SETTING= "org.eclipse.jdt.internal.ui.wizards.buildpaths.NewSourceContainerPage.openSetting"; //$NON-NLS-1$
+
+ private ListDialogField<CPListElement> fClassPathList;
+ private HintTextGroup fHintTextGroup;
+ private DialogPackageExplorer fPackageExplorer;
+ private SelectionButtonDialogField fUseFolderOutputs;
+ private final StringDialogField fOutputLocationField;
+ private DialogPackageExplorerActionGroup fActionGroup;
+
+ private IJavaProject fJavaProject;
+
+ private final IRunnableContext fContext;
+
+ private final BuildPathsBlock fBuildPathsBlock;
+
+
+ /**
+ * Constructor of the <code>NewSourceContainerWorkbookPage</code> which consists of
+ * a tree representing the project, a toolbar with the available actions, an area
+ * containing hyperlinks that perform the same actions as those in the toolbar but
+ * additionally with some short description.
+ *
+ * @param classPathList
+ * @param outputLocationField
+ * @param context a runnable context, can be <code>null</code>
+ * @param buildPathsBlock
+ */
+ public NewSourceContainerWorkbookPage(ListDialogField<CPListElement> classPathList, StringDialogField outputLocationField, IRunnableContext context, BuildPathsBlock buildPathsBlock) {
+ fClassPathList= classPathList;
+ fOutputLocationField= outputLocationField;
+ fContext= context;
+ fBuildPathsBlock= buildPathsBlock;
+
+ fUseFolderOutputs= new SelectionButtonDialogField(SWT.CHECK);
+ fUseFolderOutputs.setSelection(false);
+ fUseFolderOutputs.setLabelText(NewWizardMessages.SourceContainerWorkbookPage_folders_check);
+
+ fPackageExplorer= new DialogPackageExplorer();
+ fHintTextGroup= new HintTextGroup();
+ }
+
+ /**
+ * Initialize the controls displaying
+ * the content of the java project and saving
+ * the '.classpath' and '.project' file.
+ *
+ * Must be called before initializing the
+ * controls using <code>getControl(Composite)</code>.
+ *
+ * @param javaProject the current java project
+ */
+ @Override
+ public void init(IJavaProject javaProject) {
+ fJavaProject= javaProject;
+ fPackageExplorer.addPostSelectionChangedListener(fHintTextGroup);
+ fActionGroup.getResetAllAction().setBreakPoint(javaProject);
+
+ if (Display.getCurrent() != null) {
+ doUpdateUI();
+ } else {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ doUpdateUI();
+ }
+ });
+ }
+ }
+
+ private void doUpdateUI() {
+ fPackageExplorer.setInput(fJavaProject);
+
+ boolean useFolderOutputs= false;
+ List<CPListElement> cpelements= fClassPathList.getElements();
+ for (int i= 0; i < cpelements.size() && !useFolderOutputs; i++) {
+ CPListElement cpe= cpelements.get(i);
+ if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ if (cpe.getAttribute(CPListElement.OUTPUT) != null) {
+ useFolderOutputs= true;
+ }
+ }
+ }
+ fUseFolderOutputs.setSelection(useFolderOutputs);
+ }
+
+ public void dispose() {
+ if (fActionGroup != null) {
+ fActionGroup.removeBuildpathModifierListener(this);
+ fActionGroup= null;
+ }
+ fPackageExplorer.removePostSelectionChangedListener(fHintTextGroup);
+ fPackageExplorer.dispose();
+ }
+
+ /**
+ * Initializes controls and return composite containing
+ * these controls.
+ *
+ * Before calling this method, make sure to have
+ * initialized this instance with a java project
+ * using <code>init(IJavaProject)</code>.
+ *
+ * @param parent the parent composite
+ * @return composite containing controls
+ *
+ * @see #init(IJavaProject)
+ */
+ @Override
+ public Control getControl(Composite parent) {
+ final int[] sashWeight= {60};
+ final IPreferenceStore preferenceStore= JavaPlugin.getDefault().getPreferenceStore();
+ preferenceStore.setDefault(OPEN_SETTING, true);
+
+ // ScrolledPageContent is needed for resizing on expand the expandable composite
+ ScrolledPageContent scrolledContent = new ScrolledPageContent(parent);
+ Composite body= scrolledContent.getBody();
+ body.setLayout(new GridLayout());
+
+ final SashForm sashForm= new SashForm(body, SWT.VERTICAL | SWT.NONE);
+ sashForm.setFont(sashForm.getFont());
+
+ ViewerPane pane= new ViewerPane(sashForm, SWT.BORDER | SWT.FLAT);
+ pane.setContent(fPackageExplorer.createControl(pane));
+ fPackageExplorer.setContentProvider();
+
+ final ExpandableComposite excomposite= new ExpandableComposite(sashForm, SWT.NONE, ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT);
+ excomposite.setFont(sashForm.getFont());
+ excomposite.setText(NewWizardMessages.NewSourceContainerWorkbookPage_HintTextGroup_title);
+ final boolean isExpanded= preferenceStore.getBoolean(OPEN_SETTING);
+ excomposite.setExpanded(isExpanded);
+ excomposite.addExpansionListener(new ExpansionAdapter() {
+ @Override
+ public void expansionStateChanged(ExpansionEvent e) {
+ ScrolledPageContent parentScrolledComposite= getParentScrolledComposite(excomposite);
+ if (parentScrolledComposite != null) {
+ boolean expanded= excomposite.isExpanded();
+ parentScrolledComposite.reflow(true);
+ adjustSashForm(sashWeight, sashForm, expanded);
+ preferenceStore.setValue(OPEN_SETTING, expanded);
+ }
+ }
+ });
+
+ excomposite.setClient(fHintTextGroup.createControl(excomposite));
+ fUseFolderOutputs.doFillIntoGrid(body, 1);
+
+ fActionGroup= new DialogPackageExplorerActionGroup(fHintTextGroup, fContext, fPackageExplorer, this);
+ fActionGroup.addBuildpathModifierListener(this);
+
+
+ fUseFolderOutputs.setDialogFieldListener(new IDialogFieldListener() {
+ public void dialogFieldChanged(DialogField field) {
+ boolean isUseFolders= fUseFolderOutputs.isSelected();
+ if (!isUseFolders) {
+ ResetAllOutputFoldersAction action= new ResetAllOutputFoldersAction(fContext, fJavaProject, fPackageExplorer) {
+ @Override
+ public void run() {
+ commitDefaultOutputFolder();
+ super.run();
+ }
+ };
+ action.addBuildpathModifierListener(NewSourceContainerWorkbookPage.this);
+ action.run();
+ }
+ fPackageExplorer.showOutputFolders(isUseFolders);
+ }
+ });
+
+ Composite outputLocation= new Composite(body, SWT.NONE);
+ outputLocation.setLayout(new GridLayout(2, false));
+ outputLocation.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+
+ LayoutUtil.doDefaultLayout(outputLocation, new DialogField[] {fOutputLocationField }, true, SWT.DEFAULT, SWT.DEFAULT);
+ LayoutUtil.setHorizontalGrabbing(fOutputLocationField.getTextControl(null));
+
+ // Create toolbar with actions on the left
+ ToolBarManager tbm= fActionGroup.createLeftToolBarManager(pane);
+ pane.setTopCenter(null);
+ pane.setTopLeft(tbm.getControl());
+
+ // Create toolbar with help on the right
+ tbm= fActionGroup.createLeftToolBar(pane);
+ pane.setTopRight(tbm.getControl());
+
+ fHintTextGroup.setActionGroup(fActionGroup);
+ fPackageExplorer.setActionGroup(fActionGroup);
+
+ sashForm.setWeights(new int[] {60, 40});
+ adjustSashForm(sashWeight, sashForm, excomposite.isExpanded());
+ GridData gd= new GridData(GridData.FILL_BOTH);
+ PixelConverter converter= new PixelConverter(parent);
+ gd.heightHint= converter.convertHeightInCharsToPixels(20);
+ sashForm.setLayoutData(gd);
+
+ parent.layout(true);
+
+ return scrolledContent;
+ }
+
+ /**
+ * Adjust the size of the sash form.
+ *
+ * @param sashWeight the weight to be read or written
+ * @param sashForm the sash form to apply the new weights to
+ * @param isExpanded <code>true</code> if the expandable composite is
+ * expanded, <code>false</code> otherwise
+ */
+ private void adjustSashForm(int[] sashWeight, SashForm sashForm, boolean isExpanded) {
+ if (isExpanded) {
+ int upperWeight= sashWeight[0];
+ sashForm.setWeights(new int[]{upperWeight, 100 - upperWeight});
+ }
+ else {
+ // TODO Dividing by 10 because of https://bugs.eclipse.org/bugs/show_bug.cgi?id=81939
+ sashWeight[0]= sashForm.getWeights()[0] / 10;
+ sashForm.setWeights(new int[]{95, 5});
+ }
+ sashForm.layout(true);
+ }
+
+ /**
+ * Get the scrolled page content of the given control by
+ * traversing the parents.
+ *
+ * @param control the control to get the scrolled page content for
+ * @return the scrolled page content or <code>null</code> if none found
+ */
+ private ScrolledPageContent getParentScrolledComposite(Control control) {
+ Control parent= control.getParent();
+ while (!(parent instanceof ScrolledPageContent)) {
+ parent= parent.getParent();
+ }
+ if (parent instanceof ScrolledPageContent) {
+ return (ScrolledPageContent) parent;
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage#getSelection()
+ */
+ @Override
+ public List<CPListElement> getSelection() {
+ List<CPListElement> selectedList= new ArrayList<CPListElement>();
+
+ IJavaProject project= fJavaProject;
+ try {
+ List<?> list= ((StructuredSelection)fPackageExplorer.getSelection()).toList();
+ List<CPListElement> existingEntries= ClasspathModifier.getExistingEntries(project);
+
+ for(int i= 0; i < list.size(); i++) {
+ Object obj= list.get(i);
+ if (obj instanceof IPackageFragmentRoot) {
+ IPackageFragmentRoot element= (IPackageFragmentRoot)obj;
+ CPListElement cpElement= ClasspathModifier.getClasspathEntry(existingEntries, element);
+ selectedList.add(cpElement);
+ }
+ else if (obj instanceof IJavaProject) {
+ IClasspathEntry entry= ClasspathModifier.getClasspathEntryFor(project.getPath(), project, IClasspathEntry.CPE_SOURCE);
+ if (entry == null)
+ continue;
+ CPListElement cpElement= CPListElement.createFromExisting(entry, project);
+ selectedList.add(cpElement);
+ }
+ }
+ } catch (JavaModelException e) {
+ return new ArrayList<CPListElement>();
+ }
+ return selectedList;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage#setSelection(java.util.List)
+ */
+ @Override
+ public void setSelection(List<?> selection, boolean expand) {
+ // page switch
+
+ if (selection.size() == 0)
+ return;
+
+ List<CPListElement> cpEntries= new ArrayList<CPListElement>();
+
+ for (int i= 0; i < selection.size(); i++) {
+ Object obj= selection.get(i);
+ if (obj instanceof CPListElement) {
+ CPListElement element= (CPListElement) obj;
+ if (element.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ cpEntries.add(element);
+ }
+ } else if (obj instanceof CPListElementAttribute) {
+ CPListElementAttribute attribute= (CPListElementAttribute)obj;
+ CPListElement element= attribute.getParent();
+ if (element.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ cpEntries.add(element);
+ }
+ }
+ }
+
+ // refresh classpath
+ List<CPListElement> list= fClassPathList.getElements();
+ IClasspathEntry[] entries= new IClasspathEntry[list.size()];
+ for(int i= 0; i < list.size(); i++) {
+ CPListElement entry= list.get(i);
+ entries[i]= entry.getClasspathEntry();
+ }
+ try {
+ fJavaProject.setRawClasspath(entries, null);
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ }
+
+ fPackageExplorer.setSelection(cpEntries);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage#isEntryKind(int)
+ */
+ @Override
+ public boolean isEntryKind(int kind) {
+ return kind == IClasspathEntry.CPE_SOURCE;
+ }
+
+ /**
+ * Update <code>fClassPathList</code>.
+ * @param delta describing the changes to the buildpath
+ */
+ public void buildpathChanged(BuildpathDelta delta) {
+ fClassPathList.setElements(Arrays.asList(delta.getNewEntries()));
+
+ try {
+ fOutputLocationField.setText(fJavaProject.getOutputLocation().makeRelative().toString());
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ }
+ }
+
+ public void commitDefaultOutputFolder() {
+ if (!fBuildPathsBlock.isOKStatus())
+ return;
+ try {
+ IPath path= new Path(fOutputLocationField.getText()).makeAbsolute();
+ IPath outputLocation= fJavaProject.getOutputLocation();
+ if (path.equals(outputLocation))
+ return;
+
+ if (!outputLocation.equals(fJavaProject.getPath())) {
+ IFolder folder= fJavaProject.getProject().getWorkspace().getRoot().getFolder(outputLocation);
+ if (folder.exists() && JavaCore.create(folder) == null) {
+ folder.delete(true, null);
+ }
+ }
+ fJavaProject.setOutputLocation(path, null);
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ } catch (CoreException e) {
+ JavaPlugin.log(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setFocus() {
+ fPackageExplorer.getViewerControl().setFocus();
+ }
+
+ public IJavaProject getJavaProject() {
+ return fJavaProject;
+ }
+}