package org.zend.php.zendserver.deployment.ui.editors;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
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.editor.FormEditor;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.zend.php.zendserver.deployment.core.descriptor.IDescriptorContainer;
import org.zend.sdklib.mapping.IMapping;
import org.zend.sdklib.mapping.IMappingChangeEvent;
import org.zend.sdklib.mapping.IMappingChangeEvent.Kind;
import org.zend.sdklib.mapping.IMappingChangeListener;
import org.zend.sdklib.mapping.IMappingEntry;
import org.zend.sdklib.mapping.IMappingEntry.Type;
public abstract class PropertiesTreeSection implements IResourceChangeListener,
IResourceDeltaVisitor, IMappingChangeListener {
private Section section;
private FormToolkit toolkit;
protected CheckboxTreeViewer fTreeViewer;
protected IResource fOriginalResource;
protected IResource fParentResource;
protected boolean isChecked;
private boolean fDoRefresh = false;
protected IDescriptorContainer model;
protected FormEditor editor;
public PropertiesTreeSection(FormEditor editor, Composite parent,
FormToolkit toolkit, IDescriptorContainer model) {
super();
this.section = toolkit.createSection(parent, Section.DESCRIPTION
| Section.TITLE_BAR | Section.EXPANDED);
this.model = model;
this.toolkit = toolkit;
this.editor = editor;
initializeSection();
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
}
public class TreeContentProvider implements ITreeContentProvider {
private final List<String> excluded = Arrays.asList(new String[] {
".buildpath", ".project", ".settings", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
});
public Object[] getElements(Object parent) {
try {
if (parent instanceof IContainer) {
return getFilteredMembers(parent);
}
} catch (CoreException e) {
}
return new Object[0];
}
private Object[] getFilteredMembers(Object parent) throws CoreException {
List<IResource> filteredMembers = new ArrayList<IResource>();
IResource[] members = ((IContainer) parent).members();
for (IResource res : members) {
if (!excluded.contains(res.getName()) && !res.isLinked()) {
filteredMembers.add(res);
}
}
return filteredMembers.toArray(new IResource[0]);
}
/**
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
*/
public Object[] getChildren(Object parent) {
try {
if (parent instanceof IFolder) {
return getFilteredMembers(parent);
}
} catch (CoreException e) {
}
return new Object[0];
}
public Object[] getFolderChildren(Object parent) {
IResource[] members = null;
try {
if (!(parent instanceof IFolder))
return new Object[0];
members = ((IFolder) parent).members();
ArrayList<IResource> results = new ArrayList<IResource>();
for (int i = 0; i < members.length; i++) {
if ((members[i].getType() == IResource.FOLDER)) {
results.add(members[i]);
}
}
return results.toArray();
} catch (CoreException e) {
// TODO log
}
return new Object[0];
}
/**
* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
*/
public Object getParent(Object element) {
if (element != null && element instanceof IResource) {
return ((IResource) element).getParent();
}
return null;
}
/**
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
*/
public boolean hasChildren(Object element) {
if (element instanceof IFolder)
return getChildren(element).length > 0;
return false;
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
private void initializeSection() {
Composite sectionClient = toolkit.createComposite(section);
section.setClient(createClient());
sectionClient.setLayout(new GridLayout(3, false));
section.setLayoutData(new GridData(GridData.FILL_BOTH));
}
private Control createClient() {
Composite container = toolkit.createComposite(section);
container.setLayout(new GridLayout(1, true));
fTreeViewer = new CheckboxTreeViewer(toolkit.createTree(container,
SWT.CHECK));
fTreeViewer.setContentProvider(new TreeContentProvider());
fTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
fTreeViewer.setAutoExpandLevel(0);
fTreeViewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(final CheckStateChangedEvent event) {
final Object element = event.getElement();
BusyIndicator.showWhile(section.getDisplay(), new Runnable() {
public void run() {
try {
if (event.getChecked()) {
if (element instanceof IFile) {
IFile file = (IFile) element;
if (file.getParent() == getContainer()) {
handleRootFileChecked(file);
} else {
handleFolderFileChecked(file);
}
} else if (element instanceof IFolder) {
IContainer folder = (IContainer) element;
if (folder.getParent() == getContainer()) {
handleRootFolderChecked(folder);
} else {
handleFolderFolderChecked(folder);
}
}
} else {
if (element instanceof IFile) {
IFile file = (IFile) element;
if (file.getParent() == getContainer()) {
handleRootFileUnchecked(file);
} else {
handleFolderFileUnchecked(file);
}
} else if (element instanceof IFolder) {
IContainer folder = (IContainer) element;
if (folder.getParent() == getContainer()) {
handleRootFolderUnchecked(folder);
} else {
handleFolderFolderUnchecked(folder);
}
}
}
refresh();
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
});
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
fTreeViewer.getTree().setLayoutData(gd);
initialize();
toolkit.paintBordersFor(container);
return container;
}
private void handleRootFileUnchecked(IResource file) {
removeIncludeMapping(getName(file));
}
private void handleRootFolderUnchecked(IContainer folder) throws CoreException {
IResource[] members = folder.members();
for (IResource member : members) {
String name = getName(member);
removeIncludeMapping(name);
removeExcludeMapping(name);
}
removeIncludeMapping(getName(folder));
}
private void handleFolderFileUnchecked(IResource file) throws CoreException {
handleRootFileUnchecked(file);
handleFileInFolderUnchecked(file);
}
private void handleFolderFolderUnchecked(IContainer folder) throws CoreException {
handleRootFolderUnchecked(folder);
handleFileInFolderUnchecked(folder);
}
private void handleFileInFolderUnchecked(IResource file) throws CoreException {
IContainer parent = file.getParent();
try {
String[] parentsIncluded = model.getMappingModel().getFolders(parent.getLocation().toString());
if (parentsIncluded != null) {
for (String parentName : parentsIncluded) {
if (parentName.equals(getFolder())) {
addExcludeMapping(getName(file), false);
}
}
}
} catch (IOException e) {
// should not occur if we are there
}
}
private void handleRootFileChecked(IResource file) {
removeExcludeMapping(getName(file));
addIncludeMapping(getName(file), false);
}
private void handleRootFolderChecked(IContainer folder)
throws CoreException {
IResource[] members = folder.members();
for (IResource member : members) {
String name = getName(member);
if (member instanceof IFolder) {
handleRootFolderChecked((IFolder) member);
}
removeIncludeMapping(name);
removeExcludeMapping(name);
}
removeExcludeMapping(getName(folder));
addIncludeMapping(getName(folder), false);
}
private void handleFolderFileChecked(IResource file) throws CoreException {
handleRootFileChecked(file);
removeIfParentIncluded(file);
}
private void handleFolderFolderChecked(IContainer folder)
throws CoreException {
handleRootFolderChecked(folder);
removeIfParentIncluded(folder);
}
private void removeIfParentIncluded(IResource resource) {
IContainer parent = resource.getParent();
if (parent == null || parent.equals(getContainer())) {
return;
}
try {
String[] parentsIncluded = model.getMappingModel().getFolders(parent.getLocation().toString());
if (parentsIncluded != null) {
for (String parentName : parentsIncluded) {
if (parentName.equals(getFolder())) {
if (!isExcludedAnyParents(resource)) {
removeIncludeMapping(getName(resource));
return;
}
}
}
}
removeIfParentIncluded(parent);
} catch (IOException e) {
//
}
}
private boolean isExcludedAnyParents(IResource resource) {
IContainer parent = resource.getParent();
if (parent != null) {
try {
if (model.getMappingModel().isExcluded(getFolder(), parent.getLocation().toString())) {
return true;
} else {
return isExcludedAnyParents(parent);
}
} catch (IOException e) {
return false;
}
}
return false;
}
private boolean addIncludeMapping(String name, boolean isGlobal) {
return model.getMappingModel().addMapping(getFolder(), Type.INCLUDE, name, isGlobal);
}
private boolean addExcludeMapping(String name, boolean isGlobal) {
return model.getMappingModel().addMapping(getFolder(), Type.EXCLUDE, name, isGlobal);
}
private boolean removeIncludeMapping(String name) {
return model.getMappingModel().removeMapping(getFolder(), Type.INCLUDE, name);
}
private boolean removeExcludeMapping(String name) {
return model.getMappingModel().removeMapping(getFolder(), Type.EXCLUDE, name);
}
private String getName(IResource resource) {
return resource.getProjectRelativePath()
.makeRelativeTo(getContainer().getProjectRelativePath()).toPortableString();
}
private void initialize() {
if (fTreeViewer.getInput() == null) {
fTreeViewer.setUseHashlookup(true);
fTreeViewer.setInput(getContainer());
}
initializeCheckState();
model.getMappingModel().addMappingChangeListener(this);
}
private void asyncRefresh() {
Control control = fTreeViewer.getControl();
if (!control.isDisposed()) {
control.getDisplay().asyncExec(new Runnable() {
public void run() {
if (!fTreeViewer.getControl().isDisposed()) {
fTreeViewer.refresh(true);
initializeCheckState();
}
}
});
}
}
protected IResource handleAllUnselected(IResource resource, String name) {
IResource parent = resource.getParent();
if (parent.equals(getContainer())) {
return resource;
}
try {
boolean uncheck = true;
IResource[] members = ((IFolder) parent).members();
for (int i = 0; i < members.length; i++) {
if (fTreeViewer.getChecked(members[i])
&& !members[i].getName().equals(name))
uncheck = false;
}
if (uncheck) {
return handleAllUnselected(parent, parent.getName());
}
return resource;
} catch (CoreException e) {
// TODO log
return null;
}
}
protected void initializeCheckState() {
uncheckAll();
List<IMapping> includes = new ArrayList<IMapping>();
IMappingEntry entry = model.getMappingModel().getEntry(getFolder(), Type.INCLUDE);
if (entry != null) {
includes.addAll(entry.getMappings());
}
List<IMapping> excludes = new ArrayList<IMapping>();
entry = model.getMappingModel().getEntry(getFolder(), Type.EXCLUDE);
if (entry != null) {
excludes.addAll(entry.getMappings());
}
excludes.addAll(model.getMappingModel().getDefaultExclusion());
initializeCheckState(includes, excludes);
}
protected IContainer getContainer() {
return model.getFile().getParent();
}
protected abstract String getFolder();
public void setText(String label) {
section.setText(label);
}
public void setDescription(String label) {
section.setDescription(label);
}
public void uncheckAll() {
fTreeViewer.setCheckedElements(new Object[0]);
fTreeViewer.setGrayedElements(new Object[0]);
}
public void resourceChanged(IResourceChangeEvent event) {
if (fTreeViewer.getControl().isDisposed())
return;
fDoRefresh = false;
IResourceDelta delta = event.getDelta();
try {
if (delta != null)
delta.accept(this);
if (fDoRefresh) {
asyncRefresh();
fDoRefresh = false;
}
} catch (CoreException e) {
}
}
public boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
IProject project = model.getFile().getProject();
if ((resource instanceof IFile || resource instanceof IFolder)
&& resource.getProject().equals(project)) {
if (delta.getKind() == IResourceDelta.ADDED
|| delta.getKind() == IResourceDelta.REMOVED) {
fDoRefresh = true;
return false;
}
} else if (resource instanceof IProject
&& ((IProject) resource).equals(project)) {
return delta.getKind() != IResourceDelta.REMOVED;
}
return true;
}
public void initializeCheckState(final List<IMapping> includes,
final List<IMapping> excludes) {
fTreeViewer.getTree().getDisplay().asyncExec(new Runnable() {
public void run() {
BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
public void run() {
if (fTreeViewer.getTree().isDisposed()) {
return;
}
List<IMappingEntry> entries = model.getMappingModel().getEnties();
for (IMappingEntry entry : entries) {
if (entry.getType() == Type.INCLUDE
&& entry.getFolder().equals(getFolder())) {
List<IMapping> mappings = entry.getMappings();
for (IMapping mapping : mappings) {
IResource res = getContainer().findMember(mapping.getPath());
if (res != null) {
try {
checkTreeElements(res, mapping);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
private void checkTreeElements(IResource resource, IMapping mapping)
throws IOException, CoreException {
if (!model.getMappingModel().isExcluded(getFolder(),
resource.getLocation().toOSString())) {
if (mapping != null) {
if (resource instanceof IFolder) {
fTreeViewer.setChecked(resource, true);
checkAllChildren(resource);
} else {
fTreeViewer.setChecked(resource, true);
}
} else {
fTreeViewer.setChecked(resource, true);
if (resource instanceof IFolder) {
checkAllChildren(resource);
}
}
}
}
private void checkAllChildren(IResource resource) throws CoreException,
IOException {
IResource[] members = ((IContainer) resource).members();
for (IResource member : members) {
checkTreeElements(member, null);
}
}
});
}
});
}
public void refresh() {
initializeCheckState();
}
public void mappingChanged(IMappingChangeEvent event) {
if (event.getChangeKind() != Kind.STORE) {
try {
model.getMappingModel().store();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}