blob: 44bbb7683a96d0a9066ed90456fa9ca75f10d944 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.uima.caseditor.editor.outline;
import java.util.Collection;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;
import org.apache.uima.caseditor.CasEditorPlugin;
import org.apache.uima.caseditor.Images;
import org.apache.uima.caseditor.editor.AnnotationEditor;
import org.apache.uima.caseditor.editor.CasEditorError;
import org.apache.uima.caseditor.editor.IAnnotationEditorModifyListener;
import org.apache.uima.caseditor.editor.action.DeleteFeatureStructureAction;
import org.apache.uima.caseditor.editor.action.LowerLeftAnnotationSideAction;
import org.apache.uima.caseditor.editor.action.LowerRightAnnotationSideAction;
import org.apache.uima.caseditor.editor.action.MergeAnnotationAction;
import org.apache.uima.caseditor.editor.action.WideLeftAnnotationSideAction;
import org.apache.uima.caseditor.editor.action.WideRightAnnotationSideAction;
import org.apache.uima.caseditor.editor.util.AnnotationSelection;
import org.apache.uima.caseditor.editor.util.FeatureStructureTransfer;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.views.contentoutline.ContentOutline;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
/**
* This outline view displays all <code>AnnotationFS</code>s of the current
* mode/type from the binded editor.
*/
public final class AnnotationOutline extends ContentOutlinePage
implements ISelectionListener {
/**
* This listener receive events from the bound editor.
*/
protected class EditorListener implements IAnnotationEditorModifyListener {
/**
* Called if the editor annotation mode was changed.
*
* @param newMode
*/
public void annotationModeChanged(Type newMode) {
changeAnnotationMode();
mTableViewer.refresh();
}
public void showAnnotationsChanged(Collection<Type> shownAnnotationTypes) {
mTableViewer.refresh();
}
}
/**
* Selects all elements in the tree viewer.
*/
private class SelectAllAction extends Action {
/**
* Selects all elements in the tree viewer.
*/
@Override
public void run() {
mTableViewer.getTree().selectAll();
mTableViewer.setSelection(mTableViewer.getSelection());
}
}
private OutlineStyles style = OutlineStyles.TYPE;
private Composite mOutlineComposite;
private TreeViewer mTableViewer;
/**
* The <code>AnnotationEditor</code> which is bound to this outline view.
*/
private AnnotationEditor editor;
/**
* Creates a new <code>AnnotationOutline</code> object.
*
* @param editor -
* the editor to bind
*/
public AnnotationOutline(AnnotationEditor editor) {
this.editor = editor;
}
/**
* Creates the outline table control.
*
* @param parent
*/
@Override
public void createControl(Composite parent) {
mOutlineComposite = new Composite(parent, SWT.NONE);
mOutlineComposite.setLayout(new FillLayout());
createTableViewer(mOutlineComposite);
mOutlineComposite.layout(true);
getSite().getPage().addSelectionListener(this);
getSite().setSelectionProvider(mTableViewer);
changeAnnotationMode();
// TODO: create a listener interface ... for editor listener
editor.addAnnotationListener(new EditorListener());
DragSource source = new DragSource(mTableViewer.getTree(), DND.DROP_COPY);
source.setTransfer(new Transfer[] { FeatureStructureTransfer.getInstance() });
source.addDragListener(new DragSourceListener() {
TreeItem dragSourceItem = null;
public void dragStart(DragSourceEvent event) {
TreeItem[] selection = mTableViewer.getTree().getSelection();
if (selection.length > 0) {
event.doit = true;
dragSourceItem = selection[0];
} else {
event.doit = false;
}
}
public void dragSetData(DragSourceEvent event) {
IAdaptable adaptable = (IAdaptable) dragSourceItem.getData();
event.data = adaptable.getAdapter(FeatureStructure.class);
}
public void dragFinished(DragSourceEvent event) {
// not needed
}
});
}
/**
* Adds the actions to the tool bar.
*
* @param menuManager
* @param toolBarManager
* @param statusLineManager
*/
@Override
public void makeContributions(IMenuManager menuManager, IToolBarManager toolBarManager,
IStatusLineManager statusLineManager) {
// wide left annotation side action
WideLeftAnnotationSideAction wideLeftAnnotationSideAction = new WideLeftAnnotationSideAction(
editor.getDocument());
wideLeftAnnotationSideAction.setText("Wides the left annotation side");
wideLeftAnnotationSideAction.setImageDescriptor(CasEditorPlugin
.getTaeImageDescriptor(Images.WIDE_LEFT_SIDE));
getSite().getSelectionProvider().addSelectionChangedListener(wideLeftAnnotationSideAction);
toolBarManager.add(wideLeftAnnotationSideAction);
// lower left annotation side action
LowerLeftAnnotationSideAction lowerLeftAnnotationSideAction = new LowerLeftAnnotationSideAction(
editor.getDocument());
lowerLeftAnnotationSideAction.setText("Lowers the left annotation side");
lowerLeftAnnotationSideAction.setImageDescriptor(CasEditorPlugin
.getTaeImageDescriptor(Images.LOWER_LEFT_SIDE));
getSite().getSelectionProvider().addSelectionChangedListener(lowerLeftAnnotationSideAction);
toolBarManager.add(lowerLeftAnnotationSideAction);
// lower right annotation side action
LowerRightAnnotationSideAction lowerRightAnnotionSideAction =
new LowerRightAnnotationSideAction(editor.getDocument());
lowerRightAnnotionSideAction.setText("Lowers the right annotation side");
lowerRightAnnotionSideAction.setImageDescriptor(CasEditorPlugin
.getTaeImageDescriptor(Images.LOWER_RIGHT_SIDE));
getSite().getSelectionProvider().addSelectionChangedListener(lowerRightAnnotionSideAction);
toolBarManager.add(lowerRightAnnotionSideAction);
// wide right annotation side action
WideRightAnnotationSideAction wideRightAnnotationSideAction = new WideRightAnnotationSideAction(
editor.getDocument());
wideRightAnnotationSideAction.setText("Wides the right annotation side");
wideRightAnnotationSideAction.setImageDescriptor(CasEditorPlugin
.getTaeImageDescriptor(Images.WIDE_RIGHT_SIDE));
getSite().getSelectionProvider().addSelectionChangedListener(wideRightAnnotationSideAction);
toolBarManager.add(wideRightAnnotationSideAction);
// merge action
MergeAnnotationAction mergeAction = new MergeAnnotationAction(editor.getDocument());
getSite().getSelectionProvider().addSelectionChangedListener(mergeAction);
mergeAction.setImageDescriptor(CasEditorPlugin.getTaeImageDescriptor(Images.MERGE));
toolBarManager.add(mergeAction);
// delete action
toolBarManager.add(ActionFactory.DELETE.create(getSite().getWorkbenchWindow()));
}
/**
* Retrieves the control.
*
* @return the control
*/
@Override
public Control getControl() {
return mOutlineComposite;
}
/**
* Adds the these actions to the global action handler: {@link DeleteFeatureStructureAction}
* SelectAllAction
*
* @param actionBars
*/
@Override
public void setActionBars(IActionBars actionBars) {
DeleteFeatureStructureAction deleteAction = new DeleteFeatureStructureAction(editor
.getDocument());
actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), deleteAction);
getSite().getSelectionProvider().addSelectionChangedListener(deleteAction);
actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), new SelectAllAction());
Action action = new SwitchStyleAction(this);
IMenuManager dropDownMenu = actionBars.getMenuManager();
dropDownMenu.add(action);
super.setActionBars(actionBars);
}
OutlineStyles currentStyle() {
return style;
}
void switchStyle(OutlineStyles style) {
this.style = style;
if (OutlineStyles.MODE.equals(style)) {
mTableViewer.setContentProvider(new ModeSensitiveContentProvider(
editor, mTableViewer));
} else if (OutlineStyles.TYPE.equals(style)) {
mTableViewer.setContentProvider(new TypeGroupedContentProvider(
editor, mTableViewer));
} else {
throw new CasEditorError("Unkown style!");
}
mTableViewer.refresh();
}
/**
* Sets the focus.
*/
@Override
public void setFocus() {
mOutlineComposite.setFocus();
}
private void changeAnnotationMode() {
mTableViewer.setInput(editor.getDocument());
mTableViewer.refresh();
}
private void createTableViewer(Composite parent) {
int style = SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION;
if (mTableViewer != null) {
mTableViewer.getTree().dispose();
}
mTableViewer = new TreeViewer(parent, style);
GridData gridData = new GridData(GridData.FILL_BOTH);
gridData.grabExcessVerticalSpace = true;
gridData.horizontalSpan = 3;
mTableViewer.getTree().setLayoutData(gridData);
mTableViewer.getTree().setLinesVisible(true);
mTableViewer.getTree().setHeaderVisible(true);
TreeColumn textColumn = new TreeColumn(mTableViewer.getTree(), SWT.LEFT);
textColumn.setText("Text");
textColumn.setWidth(130);
// performance optimization, the table can contain many items
mTableViewer.setUseHashlookup(false);
// Note: The type style is considered as the default
mTableViewer.setContentProvider(new TypeGroupedContentProvider(editor, mTableViewer));
mTableViewer.setFilters(new ViewerFilter[]{new ViewerFilter() {
// TODO: Improve this filter ... it is to sloooooooooow
@Override
public boolean select(Viewer viewer, Object parentElement,
Object element) {
Collection<Type> shownTypes = editor.getShownAnnotationTypes();
if (element instanceof AnnotationTypeTreeNode) {
AnnotationTypeTreeNode typeNode = (AnnotationTypeTreeNode) element;
if (shownTypes.contains(typeNode.getType()))
return true;
else
return false;
}
else if (element instanceof AnnotationTreeNode) {
AnnotationTreeNode annotationNode = (AnnotationTreeNode) element;
return shownTypes.contains(annotationNode.getAnnotation().getType());
}
else {
throw new CasEditorError("Unxexpected element type!");
}
}}});
mTableViewer.setLabelProvider(new OutlineLabelProvider());
mTableViewer.setSorter(new OutlineTableSorter());
mTableViewer.setAutoExpandLevel(3);
// set input element here ... this is the document
}
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
boolean isForeignSelection = !(part instanceof ContentOutline && ((ContentOutline) part)
.getCurrentPage() == this);
if (isForeignSelection) {
if (selection instanceof StructuredSelection) {
AnnotationSelection annotations = new AnnotationSelection((StructuredSelection) selection);
if (!annotations.isEmpty()) {
ISelection tableSelection = new StructuredSelection(new AnnotationTreeNode(editor
.getDocument(), annotations.getFirst()));
mTableViewer.setSelection(tableSelection, true);
}
}
}
}
@Override
public void dispose() {
super.dispose();
getSite().getPage().removeSelectionListener(this);
// remove selection listener
getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this);
}
}