blob: 599cb69c364822f7ae41fba898b690f42923f311 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2017 Code 9 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:
* Code 9 Corporation - initial API and implementation
* EclipseSource Corporation - ongoing enhancements
* Rafael Oliveira Nobrega <rafael.oliveira@gmail.com> - bug 244997, 248216
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 487988
* Martin Karpisek <martin.karpisek@gmail.com> - Bug 351356
*******************************************************************************/
package org.eclipse.pde.internal.ds.ui.editor.sections;
import java.util.Iterator;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.IModelChangedEvent;
import org.eclipse.pde.internal.core.text.IDocumentElementNode;
import org.eclipse.pde.internal.ds.core.IDSComponent;
import org.eclipse.pde.internal.ds.core.IDSDocumentFactory;
import org.eclipse.pde.internal.ds.core.IDSModel;
import org.eclipse.pde.internal.ds.core.IDSProperties;
import org.eclipse.pde.internal.ds.core.IDSProperty;
import org.eclipse.pde.internal.ds.ui.Activator;
import org.eclipse.pde.internal.ds.ui.Messages;
import org.eclipse.pde.internal.ds.ui.editor.DSInputContext;
import org.eclipse.pde.internal.ds.ui.editor.DSLabelProvider;
import org.eclipse.pde.internal.ds.ui.editor.FormLayoutFactory;
import org.eclipse.pde.internal.ds.ui.editor.dialogs.DSEditPropertiesDialog;
import org.eclipse.pde.internal.ds.ui.editor.dialogs.DSEditPropertyDialog;
import org.eclipse.pde.internal.ui.editor.PDEFormPage;
import org.eclipse.pde.internal.ui.editor.TableSection;
import org.eclipse.pde.internal.ui.editor.context.InputContextManager;
import org.eclipse.pde.internal.ui.parts.EditableTablePart;
import org.eclipse.pde.internal.ui.parts.TablePart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
public class DSPropertiesSection extends TableSection {
private TableViewer fPropertiesTable;
private Action fRemoveAction;
private Action fAddPropertiesAction;
private Action fAddPropertyAction;
private Action fEditAction;
private static final int F_UP_FLAG = -1;
private static final int F_DOWN_FLAG = 1;
class ContentProvider implements IStructuredContentProvider {
@Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof IDSModel) {
IDSModel model = (IDSModel) inputElement;
IDSComponent component = model.getDSComponent();
if (component != null) {
// gets all children from DS component to get properties and
// property elements in order of appearance
IDocumentElementNode[] childNodes = component
.getChildNodes();
// count the number of property and properties elements
int propertyLength = 0;
int propertiesLength = 0;
if (component.getPropertyElements() != null) {
propertyLength = component.getPropertyElements().length;
}
if (component.getPropertiesElements() != null) {
propertiesLength = component.getPropertiesElements().length;
}
// creates and returns an array with all property and
// properties elements
Object[] props = new Object[propertyLength
+ propertiesLength];
int index = 0;
for (IDocumentElementNode child : childNodes) {
if (child instanceof IDSProperties
|| child instanceof IDSProperty) {
props[index] = child;
index++;
}
}
return props;
}
}
return new Object[0];
}
}
public DSPropertiesSection(PDEFormPage page, Composite parent) {
super(page, parent, Section.DESCRIPTION,
new String[] { Messages.DSPropertiesSection_addProperties,
Messages.DSPropertiesSection_addProperty,
Messages.DSPropertiesSection_edit,
Messages.DSPropertiesSection_remove,
Messages.DSPropertiesSection_up,
Messages.DSPropertiesSection_down, });
createClient(getSection(), page.getEditor().getToolkit());
}
@Override
protected void createClient(Section section, FormToolkit toolkit) {
section.setText(Messages.DSPropertiesSection_title);
section.setDescription(Messages.DSPropertiesSection_description);
section.setLayout(FormLayoutFactory.createClearGridLayout(false, 1));
GridData data = new GridData(GridData.FILL_BOTH);
data.horizontalSpan = 2;
section.setLayoutData(data);
Composite container = createClientContainer(section, 2, toolkit);
EditableTablePart tablePart = getTablePart();
tablePart.setEditable(isEditable());
createViewerPartControl(container, SWT.FULL_SELECTION | SWT.MULTI, 2,
toolkit);
fPropertiesTable = tablePart.getTableViewer();
fPropertiesTable.setContentProvider(new ContentProvider());
fPropertiesTable.setLabelProvider(new DSLabelProvider());
makeActions();
IDSModel model = getDSModel();
if (model != null) {
fPropertiesTable.setInput(model);
model.addModelChangedListener(this);
}
toolkit.paintBordersFor(container);
section.setClient(container);
}
@Override
public void dispose() {
IDSModel model = getDSModel();
if (model != null)
model.removeModelChangedListener(this);
}
@Override
public void refresh() {
fPropertiesTable.refresh();
updateButtons();
updateTitle();
}
private void updateTitle() {
int itemCount = fPropertiesTable.getTable().getItemCount();
getSection().setText(
NLS.bind(Messages.DSPropertiesSection_title, Integer.valueOf(
itemCount)));
}
@Override
protected void buttonSelected(int index) {
switch (index) {
case 0:
handleAddProperties();
break;
case 1:
handleAddProperty();
break;
case 2:
handleEdit();
break;
case 3:
handleRemove();
break;
case 4:
handleUpDown(F_UP_FLAG);
break;
case 5:
handleUpDown(F_DOWN_FLAG);
break;
}
}
private void handleUpDown(int newRelativeIndex) {
Object[] array = fPropertiesTable.getStructuredSelection().toArray();
if (newRelativeIndex == F_UP_FLAG) {
moveUp(newRelativeIndex, array);
} else {
moveDown(newRelativeIndex, array);
}
return;
}
private void moveDown(int newRelativeIndex, Object[] array) {
for (int i = array.length - 1; i >= 0; i--) {
Object object = array[i];
if (object == null) {
continue;
} else if (object instanceof IDocumentElementNode) {
// Move the task object up or down one position
getDSModel().getDSComponent().moveChildNode(
(IDocumentElementNode) object, newRelativeIndex, true);
}
}
}
private void moveUp(int newRelativeIndex, Object[] array) {
for (Object object : array) {
if (object == null) {
continue;
} else if (object instanceof IDocumentElementNode) {
// Move the task object up or down one position
getDSModel().getDSComponent().moveChildNode(
(IDocumentElementNode) object, newRelativeIndex, true);
}
}
}
private void handleAddProperty() {
DSEditPropertyDialog dialog = new DSEditPropertyDialog(Activator
.getActiveWorkbenchShell(), createPropertyElement(), this, true);
dialog.open();
}
private void handleEdit() {
if (fPropertiesTable.getStructuredSelection() != null) {
int selectionIndex = fPropertiesTable.getTable()
.getSelectionIndex();
if (selectionIndex != -1) {
Object selectionElement = fPropertiesTable
.getElementAt(selectionIndex);
if (selectionElement instanceof IDSProperties) {
DSEditPropertiesDialog dialog = new DSEditPropertiesDialog(
Activator.getActiveWorkbenchShell(),
(IDSProperties) selectionElement, this);
dialog.create();
dialog.getShell().setSize(500, 200);
dialog.open();
} else if (selectionElement instanceof IDSProperty) {
DSEditPropertyDialog dialog = new DSEditPropertyDialog(
Activator.getActiveWorkbenchShell(),
(IDSProperty) selectionElement, this, false);
dialog.create();
dialog.getShell().setSize(500, 300);
dialog.open();
}
}
}
}
private void makeActions() {
fAddPropertiesAction = new Action(
Messages.DSPropertiesSection_addProperties) {
@Override
public void run() {
handleAddProperties();
}
};
fAddPropertiesAction.setEnabled(isEditable());
fAddPropertyAction = new Action(
Messages.DSPropertiesSection_addProperty) {
@Override
public void run() {
handleAddProperty();
}
};
fAddPropertyAction.setEnabled(isEditable());
fEditAction = new Action(Messages.DSPropertiesSection_edit) {
@Override
public void run() {
handleEdit();
}
};
fEditAction.setEnabled(isEditable());
fRemoveAction = new Action(Messages.DSPropertiesSection_remove) {
@Override
public void run() {
handleRemove();
}
};
fRemoveAction.setEnabled(isEditable());
}
private void updateButtons() {
Table table = fPropertiesTable.getTable();
TablePart tablePart = getTablePart();
tablePart.setButtonEnabled(0, isEditable());
tablePart.setButtonEnabled(1, isEditable());
tablePart.setButtonEnabled(2, isEditable()
&& table.getSelection().length > 0);
tablePart.setButtonEnabled(3, isEditable()
&& table.getSelection().length > 0);
tablePart.setButtonEnabled(4, isEditable()
&& table.getSelection().length > 0 && !table.isSelected(0));
tablePart.setButtonEnabled(5, isEditable()
&& table.getSelection().length > 0
&& !table.isSelected(table.getItems().length - 1));
}
private void handleRemove() {
IStructuredSelection ssel = fPropertiesTable.getStructuredSelection();
if (ssel.size() > 0) {
Iterator<?> iter = ssel.iterator();
while (iter.hasNext()) {
Object object = iter.next();
if (object instanceof IDSProperties) {
getDSModel().getDSComponent().removePropertiesElement(
(IDSProperties) object);
}
if (object instanceof IDSProperty) {
getDSModel().getDSComponent().removePropertyElement(
(IDSProperty) object);
}
}
}
}
private void handleAddProperties() {
doOpenSelectionDialogProperties();
}
private void doOpenSelectionDialogProperties() {
final IProject project = getProject();
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(
Activator.getActiveWorkbenchShell(),
new WorkbenchLabelProvider(), new WorkbenchContentProvider());
dialog.setInput(project.getWorkspace());
dialog.addFilter(new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement,
Object element) {
if (element instanceof IProject)
return ((IProject) element).equals(project);
return true;
}
});
dialog.setAllowMultiple(false);
dialog.setTitle(Messages.DSPropertiesDetails_dialogTitle);
dialog.setMessage(Messages.DSPropertiesDetails_dialogMessage);
dialog.setValidator(selection -> {
if (selection != null && selection.length > 0
&& selection[0] instanceof IFile)
return new Status(IStatus.OK, Activator.PLUGIN_ID,
IStatus.OK, "", null); //$NON-NLS-1$
return new Status(IStatus.ERROR, Activator.PLUGIN_ID,
IStatus.ERROR, "", null); //$NON-NLS-1$
});
if (dialog.open() == Window.OK) {
IResource res = (IResource) dialog.getFirstResult();
IPath path = res.getProjectRelativePath();
if (res instanceof IContainer)
path = path.addTrailingSeparator();
String value = path.toString();
addProperties(value);
}
}
private void addProperties(String entry) {
IDSDocumentFactory factory = getDSModel().getFactory();
IDSComponent component = getDSModel().getDSComponent();
IDSProperties properties = factory.createProperties();
// set interface attribute
properties.setEntry(entry);
// add properties
component.addPropertiesElement(properties);
}
private IDSProperty createPropertyElement() {
IDSDocumentFactory factory = getDSModel().getFactory();
IDSProperty property = factory.createProperty();
return property;
}
@Override
public void modelChanged(IModelChangedEvent e) {
if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
markStale();
} else if (e.getChangeType() == IModelChangedEvent.REMOVE) {
Object[] objects = e.getChangedObjects();
for (Object object : objects) {
Table table = fPropertiesTable.getTable();
if (object instanceof IDSProperties) {
int index = table.getSelectionIndex();
fPropertiesTable.remove(object);
if (canSelect()) {
table.setSelection(index < table.getItemCount() ? index
: table.getItemCount() - 1);
}
}
if (object instanceof IDSProperty) {
int index = table.getSelectionIndex();
fPropertiesTable.remove(object);
if (canSelect()) {
table.setSelection(index < table.getItemCount() ? index
: table.getItemCount() - 1);
}
}
}
updateButtons();
} else if (e.getChangeType() == IModelChangedEvent.INSERT) {
Object[] objects = e.getChangedObjects();
if (objects.length > 0) {
fPropertiesTable.refresh();
fPropertiesTable.setSelection(new StructuredSelection(
objects[objects.length - 1]));
}
updateButtons();
} else {
fPropertiesTable.refresh();
updateButtons();
}
fPropertiesTable.getTable().getDisplay().asyncExec(() -> {
if (!fPropertiesTable.getTable().isDisposed())
updateTitle();
});
}
private DSInputContext getDSContext() {
InputContextManager manager = getPage().getPDEEditor()
.getContextManager();
return (DSInputContext) manager.findContext(DSInputContext.CONTEXT_ID);
}
private IDSModel getDSModel() {
DSInputContext context = getDSContext();
return context == null ? null : (IDSModel) context.getModel();
}
@Override
public boolean doGlobalAction(String actionId) {
if (!isEditable()) {
return false;
}
if (actionId.equals(ActionFactory.DELETE.getId())) {
handleRemove();
return true;
}
return super.doGlobalAction(actionId);
}
@Override
protected void selectionChanged(IStructuredSelection selection) {
getPage().getPDEEditor().setSelection(selection);
updateButtons();
}
}