/*******************************************************************************
* Copyright (c) 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
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.ui.preferences.includepath;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.Window;
import org.eclipse.php.internal.ui.PHPUIMessages;
import org.eclipse.php.internal.ui.PHPUiPlugin;
import org.eclipse.php.internal.ui.wizards.fields.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
/**
* TODO adapt into DLTK's mechanism
*/
public class VariableBlock {
private ListDialogField fVariablesList;
private Control fControl;
private boolean fHasChanges;
private List fSelectedElements;
private boolean fAskToBuild;
private boolean fInPreferencePage;
/**
* Constructor for VariableBlock
*/
public VariableBlock(boolean inPreferencePage, String initSelection) {
fSelectedElements = new ArrayList(0);
fInPreferencePage = inPreferencePage;
fAskToBuild = true;
String[] buttonLabels = new String[] { PHPUIMessages.VariableBlock_vars_add_button,
PHPUIMessages.VariableBlock_vars_edit_button, PHPUIMessages.VariableBlock_vars_remove_button };
VariablesAdapter adapter = new VariablesAdapter();
IPVariableElementLabelProvider labelProvider = new IPVariableElementLabelProvider(!inPreferencePage);
fVariablesList = new ListDialogField(adapter, buttonLabels, labelProvider);
fVariablesList.setDialogFieldListener(adapter);
fVariablesList.setLabelText(PHPUIMessages.VariableBlock_vars_label);
fVariablesList.setRemoveButtonIndex(2);
fVariablesList.enableButton(1, false);
fVariablesList.setViewerSorter(new ViewerSorter() {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
if (e1 instanceof IPVariableElement && e2 instanceof IPVariableElement) {
return ((IPVariableElement) e1).getName().compareTo(((IPVariableElement) e2).getName());
}
return super.compare(viewer, e1, e2);
}
});
refresh(initSelection);
}
public boolean hasChanges() {
return fHasChanges;
}
public void setChanges(boolean hasChanges) {
fHasChanges = hasChanges;
}
public Control createContents(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setFont(parent.getFont());
LayoutUtil.doDefaultLayout(composite, new DialogField[] { fVariablesList }, true, 0, 0);
LayoutUtil.setHorizontalGrabbing(fVariablesList.getListControl(null));
fControl = composite;
return composite;
}
public void addDoubleClickListener(IDoubleClickListener listener) {
fVariablesList.getTableViewer().addDoubleClickListener(listener);
}
public void addSelectionChangedListener(ISelectionChangedListener listener) {
fVariablesList.getTableViewer().addSelectionChangedListener(listener);
}
private Shell getShell() {
if (fControl != null) {
return fControl.getShell();
}
return PHPUiPlugin.getActiveWorkbenchShell();
}
private class VariablesAdapter implements IDialogFieldListener, IListAdapter {
// -------- IListAdapter --------
@Override
public void customButtonPressed(ListDialogField field, int index) {
switch (index) {
case 0: /* add */
editEntries(null);
break;
case 1: /* edit */
List selected = field.getSelectedElements();
editEntries((IPVariableElement) selected.get(0));
break;
}
}
@Override
public void selectionChanged(ListDialogField field) {
doSelectionChanged(field);
}
@Override
public void doubleClicked(ListDialogField field) {
if (fInPreferencePage) {
List selected = field.getSelectedElements();
if (canEdit(selected, containsReserved(selected))) {
editEntries((IPVariableElement) selected.get(0));
}
}
}
// ---------- IDialogFieldListener --------
@Override
public void dialogFieldChanged(DialogField field) {
}
}
private boolean containsReserved(List selected) {
for (int i = selected.size() - 1; i >= 0; i--) {
if (((IPVariableElement) selected.get(i)).isReserved()) {
return true;
}
}
return false;
}
private static void addAll(Object[] objs, Collection dest) {
for (int i = 0; i < objs.length; i++) {
dest.add(objs[i]);
}
}
private boolean canEdit(List selected, boolean containsReserved) {
return selected.size() == 1 && !containsReserved;
}
private void doSelectionChanged(DialogField field) {
List selected = fVariablesList.getSelectedElements();
boolean containsReserved = containsReserved(selected);
// edit
fVariablesList.enableButton(1, canEdit(selected, containsReserved));
// remove button
fVariablesList.enableButton(2, !containsReserved);
fSelectedElements = selected;
}
private void editEntries(IPVariableElement entry) {
List existingEntries = fVariablesList.getElements();
VariableCreationDialog dialog = new VariableCreationDialog(getShell(), entry, existingEntries);
if (dialog.open() != Window.OK) {
return;
}
IPVariableElement newEntry = dialog.getIncludePathElement();
if (entry == null) {
fVariablesList.addElement(newEntry);
entry = newEntry;
fHasChanges = true;
} else {
boolean hasChanges = !(entry.getName().equals(newEntry.getName())
&& entry.getPath().equals(newEntry.getPath()));
if (hasChanges) {
fHasChanges = true;
entry.setName(newEntry.getName());
entry.setPath(newEntry.getPath());
fVariablesList.refresh();
}
}
fVariablesList.selectElements(new StructuredSelection(entry));
}
public List getSelectedElements() {
return fSelectedElements;
}
public void performDefaults() {
fVariablesList.removeAllElements();
String[] reservedName = {}; // IncludePathVariableManager.instance().getReservedVariables();
for (int i = 0; i < reservedName.length; i++) {
IPVariableElement elem = new IPVariableElement(reservedName[i], Path.EMPTY, true);
elem.setReserved(true);
fVariablesList.addElement(elem);
}
fHasChanges = true;
}
public boolean performOk() {
ArrayList removedVariables = new ArrayList();
ArrayList changedVariables = new ArrayList();
// removedVariables.addAll(Arrays.asList(PHPProjectOptions.getIncludePathVariableNames()));
// remove all unchanged
List changedElements = fVariablesList.getElements();
List unchangedElements = fVariablesList.getElements();
for (int i = changedElements.size() - 1; i >= 0; i--) {
IPVariableElement curr = (IPVariableElement) changedElements.get(i);
if (curr.isReserved()) {
changedElements.remove(curr);
} else {
IPath path = curr.getPath();
IPath prevPath = null; // PHPProjectOptions.getIncludePathVariable(curr.getName());
if (prevPath != null && prevPath.equals(path)) {
changedElements.remove(curr);
} else {
changedVariables.add(curr.getName());
unchangedElements.remove(curr);
}
}
removedVariables.remove(curr.getName());
}
int steps = changedElements.size() + removedVariables.size();
if (steps > 0) {
boolean needsBuild = false;
if (fAskToBuild && doesChangeRequireFullBuild(removedVariables, changedVariables)) {
String title = PHPUIMessages.VariableBlock_needsbuild_title;
String message = PHPUIMessages.VariableBlock_needsbuild_message;
MessageDialog buildDialog = new MessageDialog(
getShell(), title, null, message, MessageDialog.QUESTION, new String[] {
IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL },
2);
int res = buildDialog.open();
if (res != 0 && res != 1) {
return false;
}
needsBuild = (res == 0);
}
final VariableBlockRunnable runnable = new VariableBlockRunnable(removedVariables, changedElements,
unchangedElements, needsBuild);
Job buildJob = new Job(PHPUIMessages.VariableBlock_job_description) {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
runnable.setVariables(monitor);
} catch (CoreException e) {
return e.getStatus();
} catch (OperationCanceledException e) {
return Status.CANCEL_STATUS;
} finally {
monitor.done();
}
return Status.OK_STATUS;
}
};
buildJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
buildJob.setUser(true);
buildJob.schedule();
return true;
}
// ProgressMonitorDialog dialog= new ProgressMonitorDialog(getShell());
// try {
// dialog.run(true, true, runnable);
// } catch (InvocationTargetException e) {
// ExceptionHandler.handle(e, getShell(),
// PHPUIMessages.getString("VariableBlock.operation_errror.title"),
// PHPUIMessages.getString("VariableBlock.operation_errror.message"));
// return false;
// } catch (InterruptedException e) {
// return false;
// }
// }
return true;
}
private boolean doesChangeRequireFullBuild(List removed, List changed) {
/*
* IProject[] projects =
* PHPWorkspaceModelManager.getInstance().listProjects(); for (int i =
* 0; i < projects.length; i++) { PHPProjectOptions options =
* PHPProjectOptions.forProject(projects[i]); IIncludePathEntry[]
* entries = options.readRawIncludePath(); for (int k = 0; k <
* entries.length; k++) { IIncludePathEntry curr = entries[k]; if
* (curr.getEntryKind() == IIncludePathEntry.IPE_VARIABLE) { String var
* = curr.getPath().segment(0); if (removed.contains(var) ||
* changed.contains(var)) { return true; } } } }
*/return false;
}
private class VariableBlockRunnable implements IRunnableWithProgress {
private List fToRemove;
private List fToChange;
private List fUnchanged;
private boolean fDoBuild;
public VariableBlockRunnable(List toRemove, List toChange, List unchanged, boolean doBuild) {
fToRemove = toRemove;
fToChange = toChange;
fUnchanged = unchanged;
fDoBuild = doBuild;
}
/*
* @see IRunnableWithProgress#run(IProgressMonitor)
*/
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.beginTask(PHPUIMessages.VariableBlock_operation_desc, fDoBuild ? 2 : 1);
try {
setVariables(monitor);
} catch (CoreException e) {
throw new InvocationTargetException(e);
} catch (OperationCanceledException e) {
throw new InterruptedException();
} finally {
monitor.done();
}
}
public void setVariables(IProgressMonitor monitor) throws CoreException {
int nVariables = fToChange.size() + fToRemove.size() + fUnchanged.size();
String[] names = new String[nVariables];
IPath[] paths = new IPath[nVariables];
int k = 0;
for (int i = 0; i < fUnchanged.size(); i++) {
IPVariableElement curr = (IPVariableElement) fUnchanged.get(i);
names[k] = curr.getName();
paths[k] = curr.getPath();
k++;
}
for (int i = 0; i < fToChange.size(); i++) {
IPVariableElement curr = (IPVariableElement) fToChange.get(i);
names[k] = curr.getName();
paths[k] = curr.getPath();
k++;
}
for (int i = 0; i < fToRemove.size(); i++) {
names[k] = (String) fToRemove.get(i);
paths[k] = null;
k++;
}
// PHPProjectOptions.setIncludePathVariables(names, paths, new
// SubProgressMonitor(monitor, 1));
if (fDoBuild) {
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD,
new SubProgressMonitor(monitor, 1));
}
}
}
/**
* If set to true, a dialog will ask the user to build on variable changed
*
* @param askToBuild
* The askToBuild to set
*/
public void setAskToBuild(boolean askToBuild) {
fAskToBuild = askToBuild;
}
/**
*
*/
public void refresh(String initSelection) {
IPVariableElement initSelectedElement = null;
/*
* String[] reservedName =
* IncludePathVariableManager.instance().getReservedVariables();
* ArrayList reserved = new ArrayList(reservedName.length);
* addAll(reservedName, reserved);
*
* String[] entries = PHPProjectOptions.getIncludePathVariableNames();
* ArrayList elements = new ArrayList(entries.length); for (int i = 0; i
* < entries.length; i++) { String name = entries[i]; IPVariableElement
* elem; IPath entryPath =
* PHPProjectOptions.getIncludePathVariable(name); if (entryPath !=
* null) { elem = new IPVariableElement(name, entryPath,
* reserved.contains(name)); elements.add(elem); if
* (name.equals(initSelection)) { initSelectedElement = elem; } } else {
* PHPCorePlugin .logErrorMessage(
* "VariableBlock: IncludePath variable with null value: " + name); } }
* fVariablesList.setElements(elements);
*/
if (initSelectedElement != null) {
ISelection sel = new StructuredSelection(initSelectedElement);
fVariablesList.selectElements(sel);
} else {
fVariablesList.selectFirstElement();
}
fHasChanges = false;
}
}