/******************************************************************************* * Copyright (c) 2013 Arapiki Solutions 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: * psmith - initial API and * implementation and/or initial documentation *******************************************************************************/ package com.buildml.eclipse.packages.handlers; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.ui.handlers.IHandlerService; import com.buildml.eclipse.bobj.UIConnection; import com.buildml.eclipse.bobj.UIFileActionConnection; import com.buildml.eclipse.bobj.UIMergeFileGroupConnection; import com.buildml.eclipse.packages.PackageDiagramEditor; import com.buildml.eclipse.packages.properties.ConnectionPropertyPage; import com.buildml.eclipse.utils.AlertDialog; import com.buildml.eclipse.utils.EclipsePartUtils; import com.buildml.eclipse.utils.GraphitiUtils; import com.buildml.eclipse.utils.errors.FatalError; import com.buildml.model.IActionMgr; import com.buildml.model.IBuildStore; import com.buildml.model.IFileGroupMgr; import com.buildml.model.undo.ActionUndoOp; import com.buildml.model.undo.FileGroupUndoOp; import com.buildml.model.undo.MultiUndoOp; /** * An Eclipse UI Handler for managing the "New Filter" UI command. * * @author Peter Smith <psmith@arapiki.com> */ public class HandlerNewFilter extends AbstractHandler { /*=====================================================================================* * PUBLIC METHODS *=====================================================================================*/ /* (non-Javadoc) * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent) */ @Override public Object execute(ExecutionEvent event) throws ExecutionException { IBuildStore buildStore = EclipsePartUtils.getActiveBuildStore(); IFileGroupMgr fileGroupMgr = buildStore.getFileGroupMgr(); IActionMgr actionMgr = buildStore.getActionMgr(); PackageDiagramEditor pde = EclipsePartUtils.getActivePackageDiagramEditor(); if ((buildStore == null) || (pde == null)) { return null; } int pkgId = pde.getPackageId(); List<Object> selectedObjects = GraphitiUtils.getSelection(); UIConnection bo = (UIConnection)selectedObjects.get(0); /* all our steps to create a filter must be recorded in the undo/redo stack */ MultiUndoOp multiOp = new MultiUndoOp(); /* * Handle addition of new filter between a file group and an INPUT slot for * an action (we can't have filters after action OUTPUTs). */ int filterGroupId = -1; if (bo instanceof UIFileActionConnection) { UIFileActionConnection connection = (UIFileActionConnection)bo; int actionId = connection.getActionId(); int slotId = connection.getSlotId(); int fileGroupId = connection.getFileGroupId(); filterGroupId = fileGroupMgr.newFilterGroup(pkgId, fileGroupId); if (filterGroupId < 0) { AlertDialog.displayErrorDialog("Can't create filter", "Unable to create new filter on this connection"); return null; } /* modify the action's slot so it now refers to our new filter group */ ActionUndoOp actionOp = new ActionUndoOp(buildStore, actionId); int oldSlotId = (Integer)actionMgr.getSlotValue(actionId, slotId); actionOp.recordSlotChange(slotId, oldSlotId, filterGroupId); multiOp.add(actionOp); } else if (bo instanceof UIMergeFileGroupConnection) { UIMergeFileGroupConnection connection = (UIMergeFileGroupConnection)bo; int sourceFileGroupId = connection.getSourceFileGroupId(); int targetFileGroupId = connection.getTargetFileGroupId(); int index = connection.getIndex(); /* create and populate the new filter */ filterGroupId = fileGroupMgr.newFilterGroup(pkgId, sourceFileGroupId); if (filterGroupId < 0) { return filterGroupId; } if (filterGroupId < 0) { AlertDialog.displayErrorDialog("Can't create filter", "Unable to create new filter on this connection"); return null; } /* modify the members of the merge group so that "index" entry now refers to the filter */ FileGroupUndoOp fileGroupOp = new FileGroupUndoOp(buildStore, targetFileGroupId); Integer currentMembers[] = fileGroupMgr.getSubGroups(targetFileGroupId); Integer newMembers[] = currentMembers.clone(); newMembers[index] = filterGroupId; fileGroupOp.recordMembershipChange(Arrays.asList(currentMembers), Arrays.asList(newMembers)); multiOp.add(fileGroupOp); } /* * Now that we've created an empty filter, pop up the properties page to allow the user * to edit the filter patterns. We do this by storing our multiOp in the UIConnection object, which * is then used by the properties dialog (see ConnectionPropertyPage). */ bo.setFilterGroupId(filterGroupId); bo.setUndoRedoOperation(multiOp); /* Open the standard "properties" dialog for UIConnection */ String commandId = "org.eclipse.ui.file.properties"; IHandlerService handlerService = (IHandlerService) EclipsePartUtils.getService(IHandlerService.class); try { handlerService.executeCommand(commandId, null); } catch (Exception e) { throw new FatalError("Unable to open Properties Dialog."); } /* * At this point, the operation has been invoked (by ConnectionPropertyPage.performOK), so detach * it from the UIConnection. Note that if "cancel" was pressed, we also need to remove the * filter. */ if (bo.getUndoRedoOperation() == null) { bo.removeFilter(); } bo.setUndoRedoOperation(null); return null; } /*-------------------------------------------------------------------------------------*/ /* * This handler is enabled when exactly one connection arrow is enabled (and no other * diagram elements are selected. */ @Override public boolean isEnabled() { /* only a single element may be selected */ List<Object> selectedObjects = GraphitiUtils.getSelection(); if (selectedObjects.size() != 1) { return false; } /* check whether this is a connection we know about */ Object bo = selectedObjects.get(0); if (!(bo instanceof UIConnection)) { return false; } UIConnection connection = (UIConnection)bo; /* for UIFileActionConnection object, we can only add a filter when going into an action */ if (bo instanceof UIFileActionConnection) { UIFileActionConnection fileActionConnection = (UIFileActionConnection)bo; if (fileActionConnection.getDirection() == UIFileActionConnection.OUTPUT_FROM_ACTION) { return false; } } /* finally check whether this connection already has a filter - we can only have one */ return !(connection.hasFilter()); } /*-------------------------------------------------------------------------------------*/ }