/*******************************************************************************
* Copyright (c) 2009 Fraunhofer IWU 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:
* Fraunhofer IWU - initial API and implementation
*******************************************************************************/
package net.enilink.komma.owl.editor.ontology;
import java.util.Collection;
import java.util.Iterator;
import net.enilink.komma.common.command.AbstractCommand.INoChangeRecording;
import net.enilink.komma.common.command.CommandResult;
import net.enilink.komma.common.command.SimpleCommand;
import net.enilink.komma.common.notify.INotification;
import net.enilink.komma.common.notify.INotificationListener;
import net.enilink.komma.common.notify.NotificationFilter;
import net.enilink.komma.core.IEntityManager;
import net.enilink.komma.core.INamespace;
import net.enilink.komma.core.KommaException;
import net.enilink.komma.core.Namespace;
import net.enilink.komma.core.URI;
import net.enilink.komma.core.URIs;
import net.enilink.komma.edit.provider.IItemColorProvider;
import net.enilink.komma.edit.ui.properties.IEditUIPropertiesImages;
import net.enilink.komma.edit.ui.properties.KommaEditUIPropertiesPlugin;
import net.enilink.komma.edit.ui.provider.ExtendedColorRegistry;
import net.enilink.komma.edit.ui.provider.ExtendedImageRegistry;
import net.enilink.komma.edit.ui.views.AbstractEditingDomainPart;
import net.enilink.komma.model.IModel;
import net.enilink.komma.model.event.INamespaceNotification;
import net.enilink.komma.owl.editor.OWLEditorPlugin;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableColorProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.ToolBar;
public class NamespacesPart extends AbstractEditingDomainPart {
private IModel model;
private TableViewer namespaceViewer;
private Action deleteItemAction, addItemAction;
private NamespaceListener listener = new NamespaceListener();
enum ColumnType {
Prefix, Namespace
}
static class NewNamespace implements INamespace {
String prefix;
URI uri;
NewNamespace(String prefix, URI uri) {
this.prefix = prefix;
this.uri = uri;
}
@Override
public String getPrefix() {
return prefix;
}
@Override
public URI getURI() {
return uri;
}
@Override
public boolean isDerived() {
return false;
}
}
static class ModifyNamespaceCommand extends SimpleCommand implements
INoChangeRecording {
final IModel model;
final INamespace oldNs;
final INamespace newNs;
ModifyNamespaceCommand(IModel model, INamespace oldNs, INamespace newNs) {
super("Modify namespace");
this.model = model;
this.oldNs = oldNs;
this.newNs = newNs;
}
@Override
protected CommandResult doExecuteWithResult(
IProgressMonitor progressMonitor, IAdaptable info)
throws ExecutionException {
IEntityManager em = model.getManager();
try {
if (oldNs != null) {
em.removeNamespace(oldNs.getPrefix());
}
if (newNs != null) {
em.setNamespace(newNs.getPrefix(), newNs.getURI());
}
// force model to be modified
model.setModified(true);
} catch (KommaException e) {
return CommandResult.newErrorCommandResult(e);
}
return CommandResult.newOKCommandResult();
}
@Override
protected CommandResult doUndoWithResult(
IProgressMonitor progressMonitor, IAdaptable info)
throws ExecutionException {
IEntityManager em = model.getManager();
try {
if (newNs != null) {
em.removeNamespace(newNs.getPrefix());
}
if (oldNs != null) {
em.setNamespace(oldNs.getPrefix(), oldNs.getURI());
}
} catch (KommaException e) {
return CommandResult.newErrorCommandResult(e);
}
return CommandResult.newOKCommandResult();
}
@Override
protected CommandResult doRedoWithResult(
IProgressMonitor progressMonitor, IAdaptable info)
throws ExecutionException {
return doExecuteWithResult(progressMonitor, info);
}
}
private class NamespaceEditingSupport extends EditingSupport {
ColumnType columnType;
TextCellEditor cellEditor;
public NamespaceEditingSupport(TableViewer viewer, ColumnType columnType) {
super(viewer);
this.columnType = columnType;
this.cellEditor = new TextCellEditor(viewer.getTable(), SWT.SINGLE);
}
@Override
protected CellEditor getCellEditor(Object element) {
return cellEditor;
}
@Override
protected boolean canEdit(Object element) {
return true;
}
@Override
protected Object getValue(Object element) {
final INamespace namespace = (INamespace) element;
switch (columnType) {
case Prefix:
return namespace.getPrefix();
case Namespace:
return namespace.getURI().toString();
}
return "";
}
@Override
protected void setValue(Object element, final Object value) {
final INamespace namespace = (INamespace) element;
final IEntityManager em = model.getManager();
switch (columnType) {
case Prefix:
if (value.equals(((INamespace) element).getPrefix())) {
return;
}
for (INamespace existing : em.getNamespaces()) {
if (value.equals(existing.getPrefix())) {
return;
}
}
if (namespace.getURI().isRelative()) {
if (namespace instanceof NewNamespace) {
((NewNamespace) namespace).prefix = (String) value;
namespaceViewer.refresh(namespace);
}
return;
}
execute(new ModifyNamespaceCommand(model, namespace,
new Namespace((String) value, namespace.getURI())));
break;
case Namespace:
URI uri;
try {
uri = URIs.createURI(value.toString());
} catch (Exception e) {
return;
}
if (uri.equals(((INamespace) element).getURI())) {
return;
}
for (INamespace existing : em.getNamespaces()) {
if (uri.equals(existing.getURI())) {
return;
}
}
if (!uri.isRelative()) {
execute(new ModifyNamespaceCommand(model, namespace,
new Namespace(namespace.getPrefix(), uri)));
} else if (namespace instanceof NewNamespace) {
((NewNamespace) namespace).uri = uri;
namespaceViewer.refresh(namespace);
}
}
}
}
private boolean execute(ModifyNamespaceCommand command) {
try {
getEditingDomain().getCommandStack().execute(command, null, null);
return true;
} catch (ExecutionException e) {
OWLEditorPlugin.INSTANCE.log(e);
}
return false;
}
public void removeNamespace(final INamespace element) {
execute(new ModifyNamespaceCommand(model, element, null));
}
private class NamespaceListener implements
INotificationListener<INotification> {
@Override
public NotificationFilter<INotification> getFilter() {
return NotificationFilter.instanceOf(INamespaceNotification.class);
}
@Override
public void notifyChanged(
Collection<? extends INotification> notifications) {
namespaceViewer.refresh();
}
};
private class NamespaceLabelProvider extends LabelProvider implements
ITableLabelProvider, ITableColorProvider {
Color foreground = namespaceViewer.getControl().getForeground();
Color background = namespaceViewer.getControl().getBackground();
@Override
public Image getColumnImage(Object element, int columnIndex) {
return getImage(element);
}
@Override
public String getColumnText(Object element, int columnIndex) {
if (element instanceof INamespace) {
switch (columnIndex) {
case 0:
return ((INamespace) element).getPrefix();
case 1:
return ((INamespace) element).getURI().toString();
}
}
return "";
}
@Override
public Color getForeground(Object element, int columnIndex) {
if (element instanceof INamespace
&& ((INamespace) element).isDerived()) {
return ExtendedColorRegistry.INSTANCE.getColor(foreground,
background, IItemColorProvider.GRAYED_OUT_COLOR);
}
return null;
}
@Override
public Color getBackground(Object element, int columnIndex) {
return null;
}
}
public void createContents(Composite parent) {
parent.setLayout(new GridLayout(1, false));
createActions(parent);
Table table = getWidgetFactory().createTable(parent,
SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
table.setLinesVisible(true);
table.setHeaderVisible(true);
namespaceViewer = new TableViewer(table);
// setup table columns [prefix, namespace]
TableViewerColumn column = new TableViewerColumn(namespaceViewer,
SWT.LEFT);
column.getColumn().setText("Prefix");
column.setEditingSupport(new NamespaceEditingSupport(namespaceViewer,
ColumnType.Prefix));
column = new TableViewerColumn(namespaceViewer, SWT.LEFT);
column.getColumn().setAlignment(SWT.LEFT);
column.getColumn().setText("Namespace");
column.setEditingSupport(new NamespaceEditingSupport(namespaceViewer,
ColumnType.Namespace));
namespaceViewer.setContentProvider(new IStructuredContentProvider() {
@Override
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
}
@Override
public void dispose() {
}
@Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof IModel) {
return ((IModel) inputElement).getManager().getNamespaces()
.toList().toArray();
}
return new Object[0];
}
});
namespaceViewer.setLabelProvider(new NamespaceLabelProvider());
namespaceViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
if (deleteItemAction != null)
deleteItemAction.setEnabled(!event.getSelection()
.isEmpty());
}
});
namespaceViewer.setComparator(new ViewerComparator() {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
INamespace ns1 = (INamespace) e1;
INamespace ns2 = (INamespace) e2;
return ns1.getPrefix().compareToIgnoreCase(ns2.getPrefix());
}
});
namespaceViewer.getControl().setLayoutData(
new GridData(SWT.FILL, SWT.FILL, true, true));
}
public void createActions(Composite parent) {
IToolBarManager toolBarManager = (IToolBarManager) getForm()
.getAdapter(IToolBarManager.class);
ToolBarManager ownManager = null;
if (toolBarManager == null) {
toolBarManager = ownManager = new ToolBarManager(SWT.HORIZONTAL);
ToolBar toolBar = ownManager.createControl(parent);
getWidgetFactory().adapt(toolBar);
toolBar.setLayoutData(new GridData(SWT.RIGHT, SWT.DEFAULT, true,
false));
}
addItemAction = new Action("Add") {
public void run() {
addItem();
}
};
addItemAction.setImageDescriptor(ExtendedImageRegistry.getInstance()
.getImageDescriptor(
KommaEditUIPropertiesPlugin.INSTANCE
.getImage(IEditUIPropertiesImages.ADD)));
toolBarManager.add(addItemAction);
deleteItemAction = new Action("Remove") {
public void run() {
deleteItem();
}
};
deleteItemAction.setImageDescriptor(ExtendedImageRegistry.getInstance()
.getImageDescriptor(
KommaEditUIPropertiesPlugin.INSTANCE
.getImage(IEditUIPropertiesImages.REMOVE)));
deleteItemAction.setEnabled(false);
toolBarManager.add(deleteItemAction);
if (ownManager != null) {
ownManager.update(true);
}
}
void addItem() {
INamespace newNs = new NewNamespace("", URIs.createURI(""));
namespaceViewer.add(newNs);
namespaceViewer.setSelection(new StructuredSelection(newNs), true);
}
void deleteItem() {
IStructuredSelection selection = (IStructuredSelection) namespaceViewer
.getSelection();
for (Iterator<?> it = selection.iterator(); it.hasNext();) {
INamespace namespace = (INamespace) it.next();
removeNamespace(namespace);
}
}
@Override
public boolean setFocus() {
if (namespaceViewer != null && namespaceViewer.getTable().setFocus()) {
return true;
}
return super.setFocus();
}
public void setInput(Object input) {
if (this.model != null) {
this.model.getModelSet().removeListener(listener);
}
this.model = (IModel) input;
if (this.model != null) {
this.model.getModelSet().addListener(listener);
}
setStale(true);
}
@Override
public void refresh() {
namespaceViewer.setInput(model);
for (TableColumn column : namespaceViewer.getTable().getColumns()) {
column.pack();
}
super.refresh();
}
@Override
public void dispose() {
if (this.model != null) {
this.model.getModelSet().removeListener(listener);
this.model = null;
}
super.dispose();
}
}