package com.cedarsoft.spring.rcp.tree.layered.aspects;
import com.cedarsoft.ObjectAccess;
import com.cedarsoft.ObjectRemove;
import com.cedarsoft.spring.rcp.aspects.AbstractAddRemoveAspect;
import com.cedarsoft.spring.rcp.commands.CommandBuilder;
import com.cedarsoft.spring.rcp.commands.CommandProvider;
import com.cedarsoft.spring.rcp.commands.DeleteCommand;
import com.cedarsoft.spring.rcp.tree.layered.DefaultTreeLayer;
import com.cedarsoft.spring.rcp.tree.layered.config.PopupConfigurer;
import com.cedarsoft.spring.rcp.id.IdStrategy;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.springframework.richclient.command.ActionCommand;
import javax.swing.JTree;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Add/remove aspect for a default tree layer
*
* @param <P> the parent type
* @param <C> the child type
*/
public class AddRemoveAspect<P, C> extends AbstractAddRemoveAspect<DefaultTreeLayer<P, C>> implements TreeLayerAspect<P, C> {
@NotNull
@NonNls
public static final String NEW_SIBLING_COMMAND_ID = "newSiblingCommand";
@NotNull
@NonNls
public static final String NEW_CHILD_COMMAND_ID = "newChildCommand";
@NotNull
private final Callback<P, C> callback;
@NotNull
private final CommandBuilder<DefaultTreeLayer<P, C>> newSiblingCommandBuilder = new CommandBuilder<DefaultTreeLayer<P, C>>();
public AddRemoveAspect( @NotNull IdStrategy idStrategy, @NotNull Callback<P, C> callback ) {
super( idStrategy );
this.callback = callback;
}
@Override
public void apply( @NotNull final DefaultTreeLayer<P, C> layer ) {
layer.addPopupConfigurer( new PopupConfigurer<P, C>() {
@Override
protected List<? extends ActionCommand> getCommands( @NotNull final P parent, @NotNull final C selectedChild, @NotNull final JTree source ) {
List<ActionCommand> commands = new ArrayList<ActionCommand>();
CommandBuilder<DefaultTreeLayer<P, C>> newCommandBuilder = getNewCommandBuilder();
newCommandBuilder.setProvider( new CommandProvider<DefaultTreeLayer<P, C>>() {
@Override
@NotNull
public ActionCommand getCommand( @NotNull DefaultTreeLayer<P, C> object ) {
return new ActionCommand( NEW_CHILD_COMMAND_ID ) {
@Override
protected void doExecuteCommand() {
callback.createNewChild( parent, selectedChild, source );
}
};
}
} );
newSiblingCommandBuilder.setProvider( new CommandProvider<DefaultTreeLayer<P, C>>() {
@Override
@NotNull
public ActionCommand getCommand( @NotNull DefaultTreeLayer<P, C> object ) {
return new ActionCommand( NEW_SIBLING_COMMAND_ID ) {
@Override
protected void doExecuteCommand() {
callback.createNewSibling( parent, selectedChild, source );
}
};
}
} );
CommandBuilder<DefaultTreeLayer<P, C>> deleteCommandBuilder = getDeleteCommandBuilder();
deleteCommandBuilder.setProvider( new CommandProvider<DefaultTreeLayer<P, C>>() {
@Override
@NotNull
public ActionCommand getCommand( @NotNull DefaultTreeLayer<P, C> object ) {
return new DeleteCommand<C>( new ObjectAccess<C>() {
@Override
@NotNull
public List<? extends C> getElements() {
return Collections.singletonList( selectedChild );
}
}, new ObjectRemove<C>() {
@Override
public void remove( @NotNull C element ) {
callback.remove( parent, selectedChild, source );
}
}, getIdStrategy() );
}
} );
final ActionCommand newCommand = newCommandBuilder.getCommand( layer );
final ActionCommand newSiblingCommand = newSiblingCommandBuilder.getCommand( layer );
final ActionCommand deleteCommand = deleteCommandBuilder.getCommand( layer );
if ( newCommand != null ) {
commands.add( newCommand );
}
if ( deleteCommand != null ) {
commands.add( deleteCommand );
}
if ( newSiblingCommand != null ) {
commands.add( newSiblingCommand );
}
return commands;
}
} );
}
@NotNull
public CommandBuilder<DefaultTreeLayer<P, C>> getNewSiblingCommandBuilder() {
return newSiblingCommandBuilder;
}
/**
* A callback interface
*
* @param <P> the parent type
* @param <C> the child type
*/
public interface Callback<P, C> {
/**
* Removes the child
*
* @param parent the parent
* @param child the child
* @param source the source tree
*/
void remove( @NotNull P parent, @NotNull C child, @NotNull JTree source );
/**
* Creates a new sibling for the given selected child
*
* @param parent the parent
* @param selectedChild the child the sibling will be created for
* @param source the source tree
*/
void createNewSibling( @NotNull P parent, @NotNull C selectedChild, @NotNull JTree source );
/**
* Creates a new child
*
* @param grandParent the grand parent
* @param parent the parent
* @param source the source
*/
void createNewChild( @NotNull P grandParent, @NotNull C parent, @NotNull JTree source );
}
}