blob: 205ce7b03c470530d6e2be0be710af1d42b58ff0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2010 Sonatype, Inc.
* 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:
* Sonatype, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.m2e.editor.pom;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.PROPERTIES;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.findChild;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.getChild;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.getTextValue;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.performOnDOMDocument;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.removeChild;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.removeIfNoChildElement;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.setText;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.eclipse.emf.ecore.xml.type.internal.DataValue.XMLChar;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.m2e.core.ui.internal.dialogs.MavenPropertyDialog;
import org.eclipse.m2e.core.ui.internal.editing.PomEdits.Operation;
import org.eclipse.m2e.core.ui.internal.editing.PomEdits.OperationTuple;
import org.eclipse.m2e.editor.MavenEditorImages;
import org.eclipse.m2e.editor.composites.ListEditorComposite;
import org.eclipse.m2e.editor.composites.ListEditorContentProvider;
import org.eclipse.m2e.editor.internal.Messages;
/**
* This is properties editor (double click edits the property)
*
* @author Anton Kraev, Milos Kleint
*/
public class PropertiesSection {
private static Logger LOG = LoggerFactory.getLogger(PropertiesSection.class);
private final MavenPomEditorPage page;
private FormToolkit toolkit;
private Composite composite;
private Section propertiesSection;
ListEditorComposite<PropertyElement> propertiesEditor;
private VerifyListener listener = new VerifyListener() {
public void verifyText(VerifyEvent e) {
e.doit = XMLChar.isValidName(e.text);
}
};
private GridData propertiesSectionData;
public PropertiesSection(FormToolkit toolkit, Composite composite, MavenPomEditorPage page) {
this.toolkit = toolkit;
this.composite = composite;
this.page = page;
createSection();
}
private List<PropertyElement> getProperties() {
final List<PropertyElement> toRet = new ArrayList<PropertyElement>();
try {
performOnDOMDocument(new OperationTuple(page.getPomEditor().getDocument(), new Operation() {
public void process(Document document) {
Element properties = findChild(document.getDocumentElement(), PROPERTIES);
if(properties != null) {
NodeList nl = properties.getChildNodes();
for(int i = 0; i < nl.getLength(); i++ ) {
Node child = nl.item(i);
if(child instanceof Element) {
toRet.add(new PropertyElement(child.getNodeName(), getTextValue(child)));
}
}
}
}
}, true));
} catch(Exception e) {
LOG.error("Cannot read properties", e); //$NON-NLS-1$
}
return toRet;
}
private Section createSection() {
propertiesSection = toolkit.createSection(composite, //
ExpandableComposite.TITLE_BAR | ExpandableComposite.EXPANDED | ExpandableComposite.TWISTIE);
propertiesSectionData = new GridData(SWT.FILL, SWT.FILL, true, false);
propertiesSection.setLayoutData(propertiesSectionData);
propertiesSection.setText(Messages.PropertiesSection_section_properties);
propertiesSection.setData("name", "propertiesSection"); //$NON-NLS-1$ //$NON-NLS-2$
propertiesSection.addExpansionListener(new ExpansionAdapter() {
public void expansionStateChanged(ExpansionEvent e) {
setExpanded(e.getState());
}
});
toolkit.paintBordersFor(propertiesSection);
propertiesEditor = new ListEditorComposite<PropertyElement>(propertiesSection, SWT.NONE);
propertiesSection.setClient(propertiesEditor);
propertiesEditor.getViewer().getTable().setData("name", "properties"); //$NON-NLS-1$ //$NON-NLS-2$
propertiesEditor.setContentProvider(new ListEditorContentProvider<PropertyElement>());
propertiesEditor.setLabelProvider(new PropertyPairLabelProvider());
propertiesEditor.setCreateButtonListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
createNewProperty();
}
});
propertiesEditor.setRemoveButtonListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
deleteProperties(propertiesEditor.getSelection());
}
});
propertiesEditor.setDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
editProperty(propertiesEditor.getSelection());
}
});
toolkit.paintBordersFor(propertiesEditor);
toolkit.adapt(propertiesEditor);
return propertiesSection;
}
public void refresh() {
propertiesEditor.setInput(getProperties());
propertiesEditor.refresh();
}
void editProperty(List<PropertyElement> list) {
if(list.size() != 1) {
return;
}
final PropertyElement pp = list.get(0);
MavenPropertyDialog dialog = new MavenPropertyDialog(propertiesSection.getShell(), //
Messages.PropertiesSection_title_editProperty, pp.getName(), pp.getValue(), listener);
if(dialog.open() == IDialogConstants.OK_ID) {
final String key = dialog.getName();
final String value = dialog.getValue();
try {
page.performEditOperation(new Operation() {
public void process(Document document) {
Element properties = getChild(document.getDocumentElement(), PROPERTIES);
Element old = findChild(properties, pp.getName());
if(old == null) {
//should never happen..
old = getChild(properties, pp.getName());
}
if(!pp.getName().equals(key)) {
Element newElement = document.createElement(key);
properties.replaceChild(newElement, old);
setText(newElement, pp.getValue());
old = newElement;
}
if(!pp.getValue().equals(value)) {
setText(old, value);
}
}
}, LOG, "error updating property");
} finally {
propertiesEditor.setInput(getProperties());
}
}
}
void createNewProperty() {
MavenPropertyDialog dialog = new MavenPropertyDialog(propertiesSection.getShell(), //
Messages.PropertiesSection_title_addProperty, "", "", listener); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
if(dialog.open() == IDialogConstants.OK_ID) {
final String key = dialog.getName();
final String value = dialog.getValue();
try {
page.performEditOperation(new Operation() {
public void process(Document document) {
Element prop = getChild(document.getDocumentElement(), PROPERTIES, key);
setText(prop, value);
}
}, LOG, "error creating property");
} finally {
propertiesEditor.setInput(getProperties());
}
}
}
void deleteProperties(final List<PropertyElement> selection) {
try {
page.performEditOperation(new Operation() {
public void process(Document document) {
Element props = findChild(document.getDocumentElement(), PROPERTIES);
if(props != null) {
//now what if we don't find the props? profile or parent? or out of sync?
for(PropertyElement el : selection) {
Element prop = findChild(props, el.getName());
removeChild(props, prop);
}
removeIfNoChildElement(props);
}
}
}, LOG, "error deleting property");
} finally {
propertiesEditor.setInput(getProperties());
}
}
public ExpandableComposite getSection() {
return propertiesSection;
}
static class PropertyPairLabelProvider extends LabelProvider {
public String getText(Object element) {
if(element instanceof PropertyElement) {
PropertyElement pair = (PropertyElement) element;
return NLS.bind(Messages.PropertyPairLabelProvider_0, pair.getName(), pair.getValue());
}
return super.getText(element);
}
public Image getImage(Object element) {
return MavenEditorImages.IMG_PROPERTY;
}
}
static class PropertyElement {
private final String name;
private final String value;
public PropertyElement(String name, String value) {
this.name = name;
this.value = value;
}
public String getValue() {
return value;
}
public String getName() {
return name;
}
}
public void setExpanded(boolean expanded) {
propertiesSection.setExpanded(expanded);
if(propertiesSectionData != null) {
propertiesSectionData.grabExcessVerticalSpace = expanded;
propertiesSection.getParent().layout();
}
}
}