/*******************************************************************************
* Copyright (c) 2000, 2009 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.wst.jsdt.internal.ui.wizards.buildpaths.newsourcepage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.StructuredSelection;
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.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.wst.jsdt.core.IIncludePathEntry;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.internal.corext.buildpath.BuildpathDelta;
import org.eclipse.wst.jsdt.internal.corext.buildpath.ClasspathModifier;
import org.eclipse.wst.jsdt.internal.corext.buildpath.IBuildpathModifierListener;
import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
import org.eclipse.wst.jsdt.internal.ui.preferences.ScrolledPageContent;
import org.eclipse.wst.jsdt.internal.ui.util.PixelConverter;
import org.eclipse.wst.jsdt.internal.ui.util.ViewerPane;
import org.eclipse.wst.jsdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.wst.jsdt.internal.ui.wizards.buildpaths.BuildPathBasePage;
import org.eclipse.wst.jsdt.internal.ui.wizards.buildpaths.BuildPathsBlock;
import org.eclipse.wst.jsdt.internal.ui.wizards.buildpaths.CPListElement;
import org.eclipse.wst.jsdt.internal.ui.wizards.buildpaths.CPListElementAttribute;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.ListDialogField;
public class NewSourceContainerWorkbookPage extends BuildPathBasePage implements IBuildpathModifierListener {
public static final String OPEN_SETTING= "org.eclipse.wst.jsdt.internal.ui.wizards.buildpaths.NewSourceContainerPage.openSetting"; //$NON-NLS-1$
private ListDialogField fClassPathList;
private HintTextGroup fHintTextGroup;
private DialogPackageExplorer fPackageExplorer;
private DialogPackageExplorerActionGroup fActionGroup;
private IJavaScriptProject fJavaScriptProject;
private final IRunnableContext fContext;
/**
* 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 context a runnable context, can be <code>null</code>
* @param buildPathsBlock
*/
public NewSourceContainerWorkbookPage(ListDialogField classPathList, IRunnableContext context, BuildPathsBlock buildPathsBlock) {
fClassPathList= classPathList;
fContext= context;
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
*/
public void init(IJavaScriptProject javaProject) {
fJavaScriptProject= 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(fJavaScriptProject);
}
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(IJavaScriptProject)</code>.
*
* @param parent the parent composite
* @return composite containing controls
*
* @see #init(IJavaScriptProject)
*/
public Control getControl(Composite parent) {
final int[] sashWeight= {60};
final IPreferenceStore preferenceStore= JavaScriptPlugin.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() {
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));
fActionGroup= new DialogPackageExplorerActionGroup(fHintTextGroup, fContext, fPackageExplorer, this);
fActionGroup.addBuildpathModifierListener(this);
// 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.wst.jsdt.internal.ui.wizards.buildpaths.BuildPathBasePage#getSelection()
*/
public List getSelection() {
List selectedList= new ArrayList();
IJavaScriptProject project= fJavaScriptProject;
try {
List list= ((StructuredSelection)fPackageExplorer.getSelection()).toList();
List 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 IJavaScriptProject) {
IIncludePathEntry entry= ClasspathModifier.getClasspathEntryFor(project.getPath(), project, IIncludePathEntry.CPE_SOURCE);
if (entry == null)
continue;
CPListElement cpElement= CPListElement.createFromExisting(entry, project);
selectedList.add(cpElement);
}
}
} catch (JavaScriptModelException e) {
return new ArrayList();
}
return selectedList;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.internal.ui.wizards.buildpaths.BuildPathBasePage#setSelection(java.util.List)
*/
public void setSelection(List selection, boolean expand) {
// page switch
if (selection.size() == 0)
return;
List cpEntries= new ArrayList();
for (int i= 0; i < selection.size(); i++) {
Object obj= selection.get(i);
if (obj instanceof CPListElement) {
CPListElement element= (CPListElement) obj;
if (element.getEntryKind() == IIncludePathEntry.CPE_SOURCE) {
cpEntries.add(element);
}
} else if (obj instanceof CPListElementAttribute) {
CPListElementAttribute attribute= (CPListElementAttribute)obj;
CPListElement element= attribute.getParent();
if (element.getEntryKind() == IIncludePathEntry.CPE_SOURCE) {
cpEntries.add(element);
}
}
}
// refresh classpath
List list= fClassPathList.getElements();
IIncludePathEntry[] entries= new IIncludePathEntry[list.size()];
for(int i= 0; i < list.size(); i++) {
CPListElement entry= (CPListElement) list.get(i);
entries[i]= entry.getClasspathEntry();
}
try {
fJavaScriptProject.setRawIncludepath(entries, null);
} catch (JavaScriptModelException e) {
JavaScriptPlugin.log(e);
}
fPackageExplorer.setSelection(cpEntries);
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.internal.ui.wizards.buildpaths.BuildPathBasePage#isEntryKind(int)
*/
public boolean isEntryKind(int kind) {
return kind == IIncludePathEntry.CPE_SOURCE;
}
/**
* Update <code>fClassPathList</code>.
*/
public void buildpathChanged(BuildpathDelta delta) {
fClassPathList.setElements(Arrays.asList(delta.getNewEntries()));
}
/**
* {@inheritDoc}
*/
public void setFocus() {
fPackageExplorer.getViewerControl().setFocus();
}
public IJavaScriptProject getJavaScriptProject() {
return fJavaScriptProject;
}
}