/******************************************************************************* * Copyright (c) 2012 The PDT Extension Group (https://github.com/pdt-eg) * 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.pdtextensions.server.ui.internal.web; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableEditor; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IWorkbenchPropertyPage; import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; import org.eclipse.ui.dialogs.PropertyPage; import org.eclipse.ui.model.WorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.views.navigator.ResourceComparator; import org.pdtextensions.server.PEXServerPlugin; import org.pdtextensions.server.ui.internal.lhttpd.SWTUtil; import org.pdtextensions.server.web.IPhpWebFolder; import org.pdtextensions.server.web.IPhpWebProject; /** * @author mepeisen * */ public class ProjectPropertyPage extends PropertyPage implements IWorkbenchPropertyPage { protected IPhpWebProject project; private Text htdocs; private Button browse; private WebRootsList webRoots; private List<IPhpWebFolder> removedFolders = new ArrayList<IPhpWebFolder>(); /** * */ public ProjectPropertyPage() { // TODO Auto-generated constructor stub } /** * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite) */ @Override protected Control createContents(Composite parent) { IAdaptable element = getElement(); final IProject p = (IProject) element.getAdapter(IProject.class); try { this.project = PEXServerPlugin.create(p); } catch (CoreException e) { PEXServerPlugin.logError(e); } final Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 1; layout.verticalSpacing = 5; composite.setLayout(layout); composite.setLayoutData(new GridData(GridData.FILL_BOTH)); final Composite composite2 = new Composite(composite, SWT.NONE); layout = new GridLayout(); layout.numColumns = 3; layout.verticalSpacing = 5; composite2.setLayout(layout); composite2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); final Label label = new Label(composite2, SWT.WRAP); label.setText(Messages.ProjectPropertyPage_LabelHtdocsFolder); GridData data = new GridData(SWT.NONE); data.widthHint = 200; label.setLayoutData(data); this.htdocs = new Text(composite2, SWT.NONE); data = new GridData(GridData.FILL_HORIZONTAL); this.htdocs.setLayoutData(data); this.htdocs.setEditable(false); this.htdocs.setText(this.project.getDefaultWebFolder().getProjectRelativePath().toString()); this.browse = SWTUtil.createButton(composite2, Messages.ProjectPropertyPage_Browse); this.browse.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent se) { ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), new WorkbenchLabelProvider(), new ProjectContentProvider()); dialog.setTitle(Messages.ProjectPropertyPage_SelectHtdocsFolderTitle); dialog.setMessage(Messages.ProjectPropertyPage_SelectHtdocsFolderDescription); dialog.setInput(project.getEclipseProject().getWorkspace()); dialog.setComparator(new ResourceComparator(ResourceComparator.NAME)); dialog.setInitialSelection(project.getDefaultWebFolder()); dialog.setAllowMultiple(false); if (dialog.open() == IDialogConstants.OK_ID) { IResource resource = (IResource) dialog.getFirstResult(); if (resource != null) { htdocs.setText(resource.getProjectRelativePath().toString()); validate(); } } } }); this.webRoots = new WebRootsList(composite, SWT.NONE); data = new GridData(GridData.FILL_BOTH); this.webRoots.setLayoutData(data); validate(); return composite; } private void validate() { this.setErrorMessage(null); // validate htdocs if (this.htdocs.getText().length() > 0) { final IFolder htdocs = project.getEclipseProject().getFolder(this.htdocs.getText()); if (!htdocs.isAccessible() || !htdocs.exists()) { this.setErrorMessage(NLS.bind(Messages.ProjectPropertyPage_ErrorHtdocsDoesNotExist, this.htdocs.getText())); return; } } final Set<String> paths = new HashSet<String>(); for (final TableItem tableItem : webRoots.table.getItems()) { final WebRootItem item = (WebRootItem) tableItem.getData(); if (!item.getPathName().startsWith("/")) { //$NON-NLS-1$ this.setErrorMessage(NLS.bind(Messages.ProjectPropertyPage_ErrorPathMustStartWithSlash, item.getPathName())); return; } if (paths.contains(item.getPathName())) { this.setErrorMessage(NLS.bind(Messages.ProjectPropertyPage_ErrorDuplicatePath, item.getPathName())); return; } paths.add(item.getPathName()); if (!item.getFolder().exists()) { this.setErrorMessage(NLS.bind(Messages.ProjectPropertyPage_ErrorHtdocsDoesNotExist, item.getFolder().getProjectRelativePath().toString())); return; } } } /** * @author mepeisen * */ private final class ProjectContentProvider extends WorkbenchContentProvider { @Override public Object[] getChildren(Object element) { if (element instanceof IWorkspace) { return new Object[]{project.getEclipseProject()}; } final List<Object> result = new ArrayList<Object>(); for (final Object elm : super.getChildren(element)) { if (elm instanceof IFolder) { result.add(elm); } } return result.toArray(); } } private final class WebRootsList extends Composite { private Table table; private Button browseButton; private Button addButton; private Button removeButton; private TableEditor tableEditor; /** * @param parent * @param style */ public WebRootsList(Composite parent, int style) { super(parent, style); GridLayout layout = new GridLayout(); layout.numColumns = 2; this.setLayout(layout); this.table = new Table(this, SWT.H_SCROLL | SWT.V_SCROLL | SWT.VIRTUAL | SWT.SINGLE); this.table.setHeaderVisible(true); for (final IPhpWebFolder folder : project.getWebFolders()) { final TableItem item = new TableItem(table, SWT.NONE); final WebRootItem rootItem = new WebRootItem(folder); item.setText(0, rootItem.getPathName()); item.setText(1, rootItem.getFolder().getProjectRelativePath().toString()); item.setData(rootItem); } TableLayout tableLayout = new TableLayout(); GridData data = new GridData(GridData.FILL_BOTH); this.table.setLayoutData(data); TableColumn col = new TableColumn(table, SWT.NONE); col.setText(Messages.ProjectPropertyPage_TablePathName); ColumnWeightData colData = new ColumnWeightData(10, 100, true); tableLayout.addColumnData(colData); col = new TableColumn(table, SWT.NONE); col.setText(Messages.ProjectPropertyPage_TableHtdocsFolder); colData = new ColumnWeightData(10, 100, true); tableLayout.addColumnData(colData); table.setLayout(tableLayout); this.tableEditor = new TableEditor(table); this.tableEditor.horizontalAlignment = SWT.LEFT; this.tableEditor.grabHorizontal = true; this.tableEditor.minimumWidth = 50; this.table.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { final boolean enabled = table.getSelectionCount() == 1; browseButton.setEnabled(enabled); removeButton.setEnabled(enabled); final Control oldEditor = tableEditor.getEditor(); if (oldEditor != null) oldEditor.dispose(); if (enabled) { final TableItem item = WebRootsList.this.table.getSelection()[0]; Text newEditor = new Text(table, SWT.NONE); newEditor.setText(item.getText(0)); newEditor.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { Text text = (Text)tableEditor.getEditor(); String value = text.getText(); if (!value.startsWith("/")) value = "/" + value; //$NON-NLS-1$//$NON-NLS-2$ tableEditor.getItem().setText(0, value); ((WebRootItem)tableEditor.getItem().getData()).setPathName(value); validate(); } }); newEditor.selectAll(); newEditor.setFocus(); tableEditor.setEditor(newEditor, item, 0); } } }); final Composite composite = new Composite(this, SWT.NONE); data = new GridData(GridData.FILL_VERTICAL); composite.setLayoutData(data); composite.setLayout(new GridLayout(1, false)); this.browseButton = SWTUtil.createButton(composite, Messages.ProjectPropertyPage_Browse); this.browseButton.setEnabled(false); this.browseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (WebRootsList.this.table.getSelection() == null || WebRootsList.this.table.getSelection().length == 0) return; ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), new WorkbenchLabelProvider(), new ProjectContentProvider()); final TableItem item = WebRootsList.this.table.getSelection()[0]; dialog.setTitle(Messages.ProjectPropertyPage_SelectHtdocsFolderTitle); dialog.setMessage(Messages.ProjectPropertyPage_SelectHtdocsFolderDescription); dialog.setInput(project.getEclipseProject().getWorkspace()); dialog.setComparator(new ResourceComparator(ResourceComparator.NAME)); dialog.setInitialSelection(((WebRootItem)item.getData()).getFolder()); dialog.setAllowMultiple(false); if (dialog.open() == IDialogConstants.OK_ID) { IResource resource = (IResource) dialog.getFirstResult(); if (resource != null) { ((WebRootItem)item.getData()).setFolder((IContainer) resource); item.setText(1, resource.getProjectRelativePath().toString()); validate(); } } } }); this.addButton = SWTUtil.createButton(composite, Messages.ProjectPropertyPage_Add); this.addButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), new WorkbenchLabelProvider(), new ProjectContentProvider()); dialog.setTitle(Messages.ProjectPropertyPage_SelectHtdocsFolderTitle); dialog.setMessage(Messages.ProjectPropertyPage_SelectHtdocsFolderDescription); dialog.setInput(project.getEclipseProject().getWorkspace()); dialog.setComparator(new ResourceComparator(ResourceComparator.NAME)); dialog.setAllowMultiple(false); if (dialog.open() == IDialogConstants.OK_ID) { IResource resource = (IResource) dialog.getFirstResult(); if (resource != null) { final TableItem item = new TableItem(table, SWT.NONE); final WebRootItem rootItem = new WebRootItem("/" + resource.getProjectRelativePath().toString(), (IContainer) resource); //$NON-NLS-1$ item.setText(0, rootItem.getPathName()); item.setText(1, rootItem.getFolder().getProjectRelativePath().toString()); item.setData(rootItem); validate(); } } } }); this.removeButton = SWTUtil.createButton(composite, Messages.ProjectPropertyPage_Remove); this.removeButton.setEnabled(false); this.removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (WebRootsList.this.table.getSelection() == null || WebRootsList.this.table.getSelection().length == 0) return; final TableItem item = WebRootsList.this.table.getSelection()[0]; if (!((WebRootItem)item.getData()).isNew()) { removedFolders.add(((WebRootItem)item.getData()).getWebFolder()); } for (int i = 0; i < table.getItemCount(); i++) { if (table.getItem(i) == item) { table.remove(i); break; } } validate(); } }); } } private final class WebRootItem { private IPhpWebFolder webFolder; private boolean changed; private String pathName; private IContainer folder; public WebRootItem(String pathName, IContainer folder) { this.pathName = pathName; this.folder = folder; } public WebRootItem(IPhpWebFolder folder) { this.webFolder = folder; this.pathName = folder.getPathName(); this.folder = folder.getFolder(); } public void setPathName(String pathName) { this.pathName = pathName; this.changed = true; } public void setFolder(IContainer folder) { this.folder = folder; this.changed = true; } public boolean isChanged() { return this.changed; } public boolean isNew() { return this.webFolder == null; } public String getPathName() { return this.pathName; } public IContainer getFolder() { return this.folder; } public IPhpWebFolder getWebFolder() { return this.webFolder; } } @Override protected void performDefaults() { this.htdocs.setText(""); //$NON-NLS-1$ this.removedFolders.clear(); for (final IPhpWebFolder folder : this.project.getWebFolders()) { this.removedFolders.add(folder); } this.webRoots.table.removeAll(); this.validate(); super.performDefaults(); } @Override public boolean performOk() { try { this.project.setDefaultWebFolder(this.htdocs.getText().length() > 0 ? this.project.getEclipseProject().getFolder(this.htdocs.getText()) : this.project.getEclipseProject()); for (final IPhpWebFolder folder : this.removedFolders) { this.project.removeWebFolder(folder); } for (final TableItem tableItem : this.webRoots.table.getItems()) { final WebRootItem item = (WebRootItem) tableItem.getData(); if (item.isNew()) { this.project.createWebFolder(item.getFolder(), item.getPathName()); } else if (item.isChanged()) { item.getWebFolder().set(item.getFolder(), item.getPathName()); } } } catch (CoreException ex) { PEXServerPlugin.logError(ex); } return super.performOk(); } }