addActionHandler.dispose();
}
for( ElementType memberType : possibleTypesService.types() )
{
final SapphireActionHandler addActionHandler = new AddActionHandler( memberType );
addActionHandler.init( addAction, null );
addActionHandler.attach( addActionHandlerListener );
addActionHandlers.add( addActionHandler );
addAction.addHandler( addActionHandler );
}
}
};
refreshAddActionHandlersOp.run();
final org.eclipse.sapphire.Listener possibleTypesServiceListener = new org.eclipse.sapphire.Listener()
{
@Override
public void handle( final org.eclipse.sapphire.Event event )
{
refreshAddActionHandlersOp.run();
}
};
possibleTypesService.attach( possibleTypesServiceListener );
addOnDisposeOperation
(
new Runnable()
{
public void run()
{
addAction.removeHandlers( addActionHandlers );
for( SapphireActionHandler addActionHandler : addActionHandlers )
{
addActionHandler.dispose();
}
possibleTypesService.detach( possibleTypesServiceListener );
}
}
);
}
if( this.exposeDeleteAction )
{
final SapphireAction deleteAction = actions.getAction( ACTION_DELETE );
final SapphireActionHandler deleteActionHandler = new DeleteActionHandler();
deleteActionHandler.init( deleteAction, null );
deleteAction.addHandler( deleteActionHandler );
addOnDisposeOperation
(
new Runnable()
{
public void run()
{
deleteAction.removeHandler( deleteActionHandler );
}
}
);
}
if( ! property.definition().hasAnnotation( FixedOrderList.class ) )
{
final SapphireAction moveUpAction = actions.getAction( ACTION_MOVE_UP );
final SapphireActionHandler moveUpActionHandler = new MoveUpActionHandler();
moveUpActionHandler.init( moveUpAction, null );
moveUpAction.addHandler( moveUpActionHandler );
addOnDisposeOperation
(
new Runnable()
{
public void run()
{
moveUpAction.removeHandler( moveUpActionHandler );
}
}
);
final SapphireAction moveDownAction = actions.getAction( ACTION_MOVE_DOWN );
final SapphireActionHandler moveDownActionHandler = new MoveDownActionHandler();
moveDownActionHandler.init( moveDownAction, null );
moveDownAction.addHandler( moveDownActionHandler );
addOnDisposeOperation
(
new Runnable()
{
public void run()
{
moveDownAction.removeHandler( moveDownActionHandler );
}
}
);
final org.eclipse.sapphire.Listener moveActionHandlerListener = new org.eclipse.sapphire.Listener()
{
@Override
public void handle( final org.eclipse.sapphire.Event event )
{
if( event instanceof PostExecuteEvent )
{
TablePropertyEditorPresentation.this.refreshOperation.run();
// This is a workaround for a weird problem on SWT on Windows. If modifier keys are pressed
// when the list is re-ordered (as in when issuing move up or move down command from the
// keyboard), the focused row can detached from selected row.
final Element element = getSelectedElement();
final TableItem[] items = TablePropertyEditorPresentation.this.table.getItems();
for( int i = 0; i < items.length; i++ )
{
if( items[ i ].getData() == element )
{
TablePropertyEditorPresentation.this.table.setSelection( i );
break;
}
}
}
}
};
moveUpAction.attach( moveActionHandlerListener );
moveDownAction.attach( moveActionHandlerListener );
final ElementsTransfer transfer = new ElementsTransfer( element().type().getModelElementClass().getClassLoader() );
final Transfer[] transfers = new Transfer[] { transfer };
final DragSource dragSource = new DragSource( this.table, DND.DROP_COPY | DND.DROP_MOVE );
dragSource.setTransfer( transfers );
final List<Element> dragElements = new ArrayList<Element>();
dragSource.addDragListener
(
new DragSourceListener()
{
public void dragStart( final DragSourceEvent event )
{
if( TablePropertyEditorPresentation.this.tableViewer.getComparator() == null )
{
dragElements.addAll( getSelectedElements() );
event.doit = true;
}
else
{
event.doit = false;
}
}
public void dragSetData( final DragSourceEvent event )
{
event.data = dragElements;
}
public void dragFinished( final DragSourceEvent event )
{
if( event.detail == DND.DROP_MOVE )
{
// When drop target is the same editor as drag source, the drop handler takes care of removing
// elements from their original location. The following block of code accounts for the case when
// dropping into another editor.
boolean droppedIntoAnotherEditor = false;
for( Element dragElement : dragElements )
{
if( ! dragElement.disposed() )
{
droppedIntoAnotherEditor = true;
break;
}
}
if( droppedIntoAnotherEditor )
{
try
{
final Element selectionPostDelete = findSelectionPostDelete( property(), dragElements );
for( Element dragElement : dragElements )
{
final ElementList<?> dragElementContainer = (ElementList<?>) dragElement.parent();
dragElementContainer.remove( dragElement );
}
setSelectedElement( selectionPostDelete );
}
catch( Exception e )
{
// Log this exception unless the cause is EditFailedException. These exception
// are the result of the user declining a particular action that is necessary
// before the edit can happen (such as making a file writable).
final EditFailedException editFailedException = EditFailedException.findAsCause( e );
if( editFailedException == null )
{
Sapphire.service( LoggingService.class ).log( e );
}
}
}
}
dragElements.clear();
}
}
);
final DropTarget target = new DropTarget( this.table, DND.DROP_COPY | DND.DROP_MOVE );
target.setTransfer( transfers );
target.addDropListener
(
new DropTargetAdapter()
{
public void dragOver( final DropTargetEvent event )
{
if( event.item != null )
{
final TableItem dragOverItem = (TableItem) event.item;
final Point pt = dragOverItem.getDisplay().map( null, TablePropertyEditorPresentation.this.table, event.x, event.y );
final Rectangle bounds = dragOverItem.getBounds();
if( pt.y < bounds.y + bounds.height / 2 )
{
event.feedback = DND.FEEDBACK_INSERT_BEFORE;
}
else
{
event.feedback = DND.FEEDBACK_INSERT_AFTER;
}
}
event.feedback |= DND.FEEDBACK_SCROLL;
}
public void drop( final DropTargetEvent event )
{
if( event.data == null )
{
event.detail = DND.DROP_NONE;
return;
}
final List<ElementData> droppedElements = (List<ElementData>) event.data;
final Set<ElementType> possibleTypesService = property.service( PossibleTypesService.class ).types();
for( final ElementData droppedElement : droppedElements )
{
if( ! possibleTypesService.contains( droppedElement.type() ) )
{
event.detail = DND.DROP_NONE;
return;
}
}
final ElementList<?> list = property();
int position;
if( event.item == null )
{
position = list.size();
}
else
{
final TableItem dropTargetItem = (TableItem) event.item;
final TableRow dropTargetRow = (TableRow) dropTargetItem.getData();
final Element dropTargetElement = dropTargetRow.element();
final Point pt = TablePropertyEditorPresentation.this.table.getDisplay().map( null, TablePropertyEditorPresentation.this.table, event.x, event.y );
final Rectangle bounds = dropTargetItem.getBounds();
position = list.indexOf( dropTargetElement );
if( pt.y >= bounds.y + bounds.height / 2 )
{
position++;
}
}
try
{
if( event.detail == DND.DROP_MOVE )
{
for( Element dragElement : dragElements )
{
final ElementList<?> dragElementContainer = (ElementList<?>) dragElement.parent();
if( dragElementContainer == list && dragElementContainer.indexOf( dragElement ) < position )
{
position--;
}
dragElementContainer.remove( dragElement );
}
}
final List<Element> newSelection = new ArrayList<Element>();
for( final ElementData droppedElement : droppedElements )
{
final Element insertedElement = list.insert( droppedElement.type(), position );
insertedElement.copy( droppedElement );
newSelection.add( insertedElement );
position++;
}
if( TablePropertyEditorPresentation.this.table.isDisposed() )
{
return;
}
TablePropertyEditorPresentation.this.tableViewer.refresh();
setSelectedElements( newSelection );
}
catch( Exception e )
{
// Log this exception unless the cause is EditFailedException. These exception
// are the result of the user declining a particular action that is necessary
// before the edit can happen (such as making a file writable).
final EditFailedException editFailedException = EditFailedException.findAsCause( e );
if( editFailedException == null )
{
Sapphire.service( LoggingService.class ).log( e );
}
event.detail = DND.DROP_NONE;
}
}
}
);
}
}
final boolean toolBarNeeded = toolBarActionsPresentation.hasActions();
mainComposite.setLayout( glayout( ( toolBarNeeded ? 2 : 1 ), 0, 0, 0, 0 ) );
if( toolBarNeeded )
{
final ToolBar toolbar = new ToolBar( mainComposite, SWT.FLAT | SWT.VERTICAL );
toolbar.setLayoutData( gdvfill() );
toolBarActionsPresentation.setToolBar( toolbar );
toolBarActionsPresentation.render();
addControl( toolbar );
this.decorator.addEditorControl( toolbar );
}
if( menuActionsPresentation.hasActions() )
{
final Menu menu = new Menu( this.table );
this.table.setMenu( menu );
menuActionsPresentation.setMenu( menu );
menuActionsPresentation.render();
}
final HyperlinkTable hyperlinkTable = new HyperlinkTable( this.table, actions );
hyperlinkTable.setController
(
new HyperlinkTable.Controller()
{
@Override
public boolean isHyperlinkEnabled( final TableItem item,
final int column )
{
final SapphireActionHandler jumpHandler = getJumpHandler( item, column );
if( jumpHandler != null )
{
return jumpHandler.isEnabled();
}
return false;
}
@Override
public void handleHyperlinkEvent( final TableItem item,
final int column )
{
final SapphireActionHandler jumpHandler = getJumpHandler( item, column );
if( jumpHandler != null )
{
jumpHandler.execute( TablePropertyEditorPresentation.this );
}
}
private SapphireActionHandler getJumpHandler( final TableItem item,
final int column )