blob: f054c2f8e8693ea8709ca793e2716149692839d8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 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
*
*******************************************************************************/
package org.eclipse.dltk.internal.ui.wizards.buildpath;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IAccessRule;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IScriptModel;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.internal.ui.wizards.NewWizardMessages;
import org.eclipse.dltk.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.dltk.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.dltk.internal.ui.wizards.dialogfields.ITreeListAdapter;
import org.eclipse.dltk.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.dltk.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.dltk.internal.ui.wizards.dialogfields.TreeListDialogField;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.ModelElementSorter;
import org.eclipse.dltk.ui.util.PixelConverter;
import org.eclipse.dltk.ui.viewsupport.ScriptUILabelProvider;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ListSelectionDialog;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
public class ProjectsWorkbookPage extends BuildPathBasePage {
private final int IDX_ADDPROJECT = 0;
private final int IDX_EDIT = 2;
private final int IDX_REMOVE = 3;
private ListDialogField fBuildpathList;
private IScriptProject fCurrJProject;
private TreeListDialogField fProjectsList;
private Control fSWTControl;
private final IWorkbenchPreferenceContainer fPageContainer;
public ProjectsWorkbookPage(ListDialogField buildpathList,
IWorkbenchPreferenceContainer pageContainer) {
fBuildpathList = buildpathList;
fPageContainer = pageContainer;
fSWTControl = null;
String[] buttonLabels = new String[] {
NewWizardMessages.ProjectsWorkbookPage_projects_add_button,
null,
NewWizardMessages.ProjectsWorkbookPage_projects_edit_button,
NewWizardMessages.ProjectsWorkbookPage_projects_remove_button };
ProjectsAdapter adapter = new ProjectsAdapter();
fProjectsList = new TreeListDialogField(adapter, buttonLabels,
new BPListLabelProvider());
fProjectsList.setDialogFieldListener(adapter);
fProjectsList.setLabelText(
NewWizardMessages.ProjectsWorkbookPage_projects_label);
fProjectsList.enableButton(IDX_REMOVE, false);
fProjectsList.enableButton(IDX_EDIT, false);
fProjectsList.setViewerComparator(new BPListElementSorter());
}
@Override
public void init(IScriptProject jproject) {
fCurrJProject = jproject;
if (Display.getCurrent() != null) {
updateProjectsList();
} else {
Display.getDefault().asyncExec(() -> updateProjectsList());
}
}
@Override
public void setTitle(String title) {
fProjectsList.setLabelText(title);
}
private void updateProjectsList() {
// add the projects-cpentries that are already on the class path
List cpelements = fBuildpathList.getElements();
final List checkedProjects = new ArrayList(cpelements.size());
for (int i = cpelements.size() - 1; i >= 0; i--) {
BPListElement cpelem = (BPListElement) cpelements.get(i);
if (isEntryKind(cpelem.getEntryKind())) {
checkedProjects.add(cpelem);
}
}
fProjectsList.setElements(checkedProjects);
}
// -------- UI creation ---------
@Override
public Control getControl(Composite parent) {
PixelConverter converter = new PixelConverter(parent);
Composite composite = new Composite(parent, SWT.NONE);
LayoutUtil.doDefaultLayout(composite,
new DialogField[] { fProjectsList }, true, SWT.DEFAULT,
SWT.DEFAULT);
LayoutUtil.setHorizontalGrabbing(fProjectsList.getTreeControl(null));
int buttonBarWidth = converter.convertWidthInCharsToPixels(24);
fProjectsList.setButtonsMinWidth(buttonBarWidth);
fSWTControl = composite;
return composite;
}
private void updateBuildpathList() {
List projelements = fProjectsList.getElements();
boolean remove = false;
List cpelements = fBuildpathList.getElements();
// backwards, as entries will be deleted
for (int i = cpelements.size() - 1; i >= 0; i--) {
BPListElement cpe = (BPListElement) cpelements.get(i);
if (isEntryKind(cpe.getEntryKind())) {
if (!projelements.remove(cpe)) {
cpelements.remove(i);
remove = true;
}
}
}
for (int i = 0; i < projelements.size(); i++) {
cpelements.add(projelements.get(i));
}
if (remove || (projelements.size() > 0)) {
fBuildpathList.setElements(cpelements);
}
}
@Override
public List getSelection() {
return fProjectsList.getSelectedElements();
}
@Override
public void setSelection(List selElements, boolean expand) {
fProjectsList.selectElements(new StructuredSelection(selElements));
if (expand) {
for (int i = 0; i < selElements.size(); i++) {
fProjectsList.expandElement(selElements.get(i), 1);
}
}
}
@Override
public boolean isEntryKind(int kind) {
return kind == IBuildpathEntry.BPE_PROJECT;
}
private class ProjectsAdapter
implements IDialogFieldListener, ITreeListAdapter {
private final Object[] EMPTY_ARR = new Object[0];
// -------- IListAdapter --------
@Override
public void customButtonPressed(TreeListDialogField field, int index) {
projectPageCustomButtonPressed(field, index);
}
@Override
public void selectionChanged(TreeListDialogField field) {
projectPageSelectionChanged(field);
}
@Override
public void doubleClicked(TreeListDialogField field) {
projectPageDoubleClicked(field);
}
@Override
public void keyPressed(TreeListDialogField field, KeyEvent event) {
projectPageKeyPressed(field, event);
}
@Override
public Object[] getChildren(TreeListDialogField field, Object element) {
if (element instanceof BPListElement) {
return ((BPListElement) element).getChildren();
}
return EMPTY_ARR;
}
@Override
public Object getParent(TreeListDialogField field, Object element) {
if (element instanceof BPListElementAttribute) {
return ((BPListElementAttribute) element).getParent();
}
return null;
}
@Override
public boolean hasChildren(TreeListDialogField field, Object element) {
return getChildren(field, element).length > 0;
}
// ---------- IDialogFieldListener --------
@Override
public void dialogFieldChanged(DialogField field) {
projectPageDialogFieldChanged(field);
}
}
private void projectPageCustomButtonPressed(DialogField field, int index) {
BPListElement[] entries = null;
switch (index) {
case IDX_ADDPROJECT: /* add project */
entries = openProjectDialog(null);
break;
case IDX_EDIT: /* edit */
editEntry();
return;
case IDX_REMOVE: /* remove */
removeEntry();
return;
}
if (entries != null) {
int nElementsChosen = entries.length;
// remove duplicates
List cplist = fProjectsList.getElements();
List elementsToAdd = new ArrayList(nElementsChosen);
for (int i = 0; i < nElementsChosen; i++) {
BPListElement curr = entries[i];
if (!cplist.contains(curr) && !elementsToAdd.contains(curr)) {
elementsToAdd.add(curr);
}
}
fProjectsList.addElements(elementsToAdd);
if (index == IDX_ADDPROJECT) {
fProjectsList.refresh();
}
fProjectsList.postSetSelection(new StructuredSelection(entries));
}
}
private void removeEntry() {
List selElements = fProjectsList.getSelectedElements();
for (int i = selElements.size() - 1; i >= 0; i--) {
Object elem = selElements.get(i);
if (elem instanceof BPListElementAttribute) {
BPListElementAttribute attrib = (BPListElementAttribute) elem;
String key = attrib.getKey();
Object value = null;
if (key.equals(BPListElement.ACCESSRULES)) {
value = new IAccessRule[0];
}
attrib.getParent().setAttribute(key, value);
selElements.remove(i);
}
}
if (selElements.isEmpty()) {
fProjectsList.refresh();
fBuildpathList.dialogFieldChanged(); // validate
} else {
fProjectsList.removeElements(selElements);
}
}
private boolean canRemove(List selElements) {
if (selElements.size() == 0) {
return false;
}
int elements = 0;
int attributes = 0;
for (int i = 0; i < selElements.size(); i++) {
Object elem = selElements.get(i);
if (elem instanceof BPListElementAttribute) {
BPListElementAttribute attrib = (BPListElementAttribute) elem;
if (attrib.getKey().equals(BPListElement.ACCESSRULES)) {
return ((IAccessRule[]) attrib.getValue()).length > 0;
}
if (attrib.getValue() == null) {
return false;
}
attributes++;
} else if (elem instanceof BPListElement) {
elements++;
}
}
return attributes == selElements.size()
|| elements == selElements.size();
}
private boolean canEdit(List selElements) {
if (selElements.size() != 1) {
return false;
}
Object elem = selElements.get(0);
if (elem instanceof BPListElement) {
return false;
}
if (elem instanceof BPListElementAttribute) {
return true;
}
return false;
}
/**
* Method editEntry.
*/
private void editEntry() {
List selElements = fProjectsList.getSelectedElements();
if (selElements.size() != 1) {
return;
}
Object elem = selElements.get(0);
if (fProjectsList.getIndexOfElement(elem) != -1) {
editElementEntry((BPListElement) elem);
} else if (elem instanceof BPListElementAttribute) {
editAttributeEntry((BPListElementAttribute) elem);
}
}
private void editAttributeEntry(BPListElementAttribute elem) {
String key = elem.getKey();
if (key.equals(BPListElement.ACCESSRULES)) {
showAccessRestrictionDialog(elem.getParent());
}
// else if (key.equals(BPListElement.NATIVE_LIB_PATH)) {
// BPListElement selElement= elem.getParent();
// NativeLibrariesDialog dialog= new NativeLibrariesDialog(getShell(),
// selElement);
// if (dialog.open() == Window.OK) {
// selElement.setAttribute(BPListElement.NATIVE_LIB_PATH,
// dialog.getNativeLibraryPath());
// fProjectsList.refresh();
// fClassPathList.dialogFieldChanged(); // validate
// }
// }
}
private void showAccessRestrictionDialog(BPListElement selElement) {
AccessRulesDialog dialog = new AccessRulesDialog(getShell(), selElement,
fCurrJProject, fPageContainer != null);
int res = dialog.open();
if (res == Window.OK || res == AccessRulesDialog.SWITCH_PAGE) {
selElement.setAttribute(BPListElement.ACCESSRULES,
dialog.getAccessRules());
selElement.setAttribute(BPListElement.COMBINE_ACCESSRULES,
dialog.doCombineAccessRules());
fProjectsList.refresh();
fBuildpathList.dialogFieldChanged(); // validate
if (res == AccessRulesDialog.SWITCH_PAGE) {
dialog.performPageSwitch(fPageContainer);
}
}
}
private void editElementEntry(BPListElement elem) {
BPListElement[] res = openProjectDialog(elem);
if (res != null && res.length > 0) {
BPListElement curr = res[0];
curr.setExported(elem.isExported());
fProjectsList.replaceElement(elem, curr);
}
}
private Shell getShell() {
if (fSWTControl != null) {
return fSWTControl.getShell();
}
return DLTKUIPlugin.getActiveWorkbenchShell();
}
private BPListElement[] openProjectDialog(BPListElement elem) {
try {
ArrayList selectable = new ArrayList();
final IScriptModel model = fCurrJProject.getModel();
final IDLTKLanguageToolkit toolkit = fCurrJProject
.getLanguageToolkit();
selectable.addAll(Arrays.asList(toolkit != null
? model.getScriptProjects(toolkit.getNatureId())
: model.getScriptProjects()));
selectable.remove(fCurrJProject);
List elements = fProjectsList.getElements();
for (int i = 0; i < elements.size(); i++) {
BPListElement curr = (BPListElement) elements.get(0);
IScriptProject proj = (IScriptProject) DLTKCore
.create(curr.getResource());
selectable.remove(proj);
}
Object[] selectArr = selectable.toArray();
new ModelElementSorter().sort(null, selectArr);
// IScriptProject project = elem.getScriptProject();
ScriptUILabelProvider labelProvider = new ScriptUILabelProvider();
ListSelectionDialog dialog = new ListSelectionDialog(getShell(),
Arrays.asList(selectArr), new ArrayContentProvider(),
labelProvider,
NewWizardMessages.ProjectsWorkbookPage_chooseProjects_message);
dialog.setTitle(
NewWizardMessages.ProjectsWorkbookPage_chooseProjects_title);
dialog.setHelpAvailable(false);
if (dialog.open() == Window.OK) {
Object[] result = dialog.getResult();
BPListElement[] cpElements = new BPListElement[result.length];
for (int i = 0; i < result.length; i++) {
IScriptProject curr = (IScriptProject) result[i];
cpElements[i] = new BPListElement(fCurrJProject,
IBuildpathEntry.BPE_PROJECT, curr.getPath(),
curr.getResource(), false);
}
return cpElements;
}
} catch (ModelException e) {
return null;
}
return null;
}
protected void projectPageDoubleClicked(TreeListDialogField field) {
List selection = fProjectsList.getSelectedElements();
if (canEdit(selection)) {
editEntry();
}
}
protected void projectPageKeyPressed(TreeListDialogField field,
KeyEvent event) {
if (field == fProjectsList) {
if (event.character == SWT.DEL && event.stateMask == 0) {
List selection = field.getSelectedElements();
if (canRemove(selection)) {
removeEntry();
}
}
}
}
private void projectPageDialogFieldChanged(DialogField field) {
if (fCurrJProject != null) {
// already initialized
updateBuildpathList();
}
}
private void projectPageSelectionChanged(DialogField field) {
List selElements = fProjectsList.getSelectedElements();
fProjectsList.enableButton(IDX_EDIT, canEdit(selElements));
fProjectsList.enableButton(IDX_REMOVE, canRemove(selElements));
boolean noAttributes = containsOnlyTopLevelEntries(selElements);
fProjectsList.enableButton(IDX_ADDPROJECT, noAttributes);
}
}