/*
* CustomStsToolDiagramEditPart.java
*
* This file is part of the STS-Tool project.
* Copyright (c) 2011-2012 "University of Trento - DISI" All rights reserved.
*
* Is strictly forbidden to remove this copyright notice from this source code.
*
* Disclaimer of Warranty:
* STS-Tool (this software) is provided "as-is" and without warranty of any kind,
* express, implied or otherwise, including without limitation, any warranty of
* merchantability or fitness for a particular purpose.
* In no event shall the copyright holder or contributors be liable for any direct,
* indirect, incidental, special, exemplary, or consequential damages
* including, but not limited to, procurement of substitute goods or services;
* loss of use, data, or profits; or business interruption) however caused and on
* any theory of liability, whether in contract, strict liability, or tort (including
* negligence or otherwise) arising in any way out of the use of this software, even
* if advised of the possibility of such damage.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* "University of Trento - DISI","University of Trento - DISI" DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA, 02110-1301 USA, or download the license from the following URL:
* http://www.sts-tool.eu/License.php
*
* For more information, please contact STS-Tool group at this
* address: ststool@disi.unitn.it
*
*/
package eu.aniketos.wp1.ststool.diagram.custom.editpart;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.common.ui.services.icon.IconService;
import org.eclipse.gmf.runtime.diagram.core.edithelpers.CreateElementRequestAdapter;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.SemanticCreateCommand;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DiagramDragDropEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DiagramPopupBarEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.XYLayoutEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.preferences.IPreferenceConstants;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper;
import org.eclipse.gmf.runtime.diagram.ui.requests.RefreshConnectionsRequest;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.gmf.runtime.notation.impl.ShapeImpl;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import eu.aniketos.wp1.ststool.StsElement;
import eu.aniketos.wp1.ststool.diagram.custom.view.ViewsManager;
import eu.aniketos.wp1.ststool.diagram.custom.view.constraint.NodeGraphicalConstraint;
import eu.aniketos.wp1.ststool.diagram.edit.parts.AgentEditPart;
import eu.aniketos.wp1.ststool.diagram.edit.parts.Goal2EditPart;
import eu.aniketos.wp1.ststool.diagram.edit.parts.RoleEditPart;
import eu.aniketos.wp1.ststool.diagram.edit.parts.TResource2EditPart;
import eu.aniketos.wp1.ststool.diagram.extensionpoint.ExecuteCommandRequest;
import eu.aniketos.wp1.ststool.diagram.part.StsToolDiagramEditorPlugin;
import eu.aniketos.wp1.ststool.diagram.providers.StsToolElementTypes;
import eu.aniketos.wp1.ststool.impl.StsToolDiagramImpl;
/**
* Extension class of the DiagramEditPart that override some method to achieve some stsTool functionality
*/
public abstract class CustomStsToolDiagramEditPart extends DiagramEditPart {
@Override
public void performRequest(Request request){
if (request instanceof ExecuteCommandRequest && request.getType().equals("ExecuteCommandRequest")) {
getEditDomain().getCommandStack().execute(((ExecuteCommandRequest) request).getCommand());
}
super.performRequest(request);
}
/**
* The viewsManager instance for the current Diagram
*/
private ViewsManager viewsManager = null;
private static final List<IElementType> popupElements = new ArrayList<IElementType>();
static {
popupElements.add(StsToolElementTypes.Agent_2001);
popupElements.add(StsToolElementTypes.Role_2002);
popupElements.add(StsToolElementTypes.IResource_2005);
popupElements.add(StsToolElementTypes.Event_2006);
}
/**
* Extension of the default constructor with the viewsManager initialization
*
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart#DiagramEditPart(View)
*/
public CustomStsToolDiagramEditPart(View diagramView) {
super(diagramView);
StsToolDiagramImpl diag = (StsToolDiagramImpl) diagramView.getElement();
try {
this.viewsManager = new ViewsManager(diag.getGraphicalConstraintMap());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Filtered list of children, based on the current view. Note and Text will be leaved.
*
* @return List of children that can be showed in the current view.
*
* @see org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart#getModelChildren()
*/
@Override
protected List getModelChildren(){
Object model = getModel();
if (model != null && model instanceof View) {
ArrayList list = new ArrayList(((View) model).getVisibleChildren());
ArrayList result = new ArrayList();
Iterator it = list.iterator();
while (it.hasNext()) {
Object o = it.next();
if (o instanceof ShapeImpl) {
String SvisualID = ((ShapeImpl) o).getType();
if (SvisualID.equals("Note") || SvisualID.equals("Text")) {
//result.add(o);
} else {
int visualID = Integer.parseInt(((ShapeImpl) o).getType());
if (getViewsManager().isElementVisible(StsToolElementTypes.getElementType(visualID))) {
result.add(o);
}
}
}
}
return result;
}
return Collections.EMPTY_LIST;
}
@Override
protected void createDefaultEditPolicies(){
super.createDefaultEditPolicies();
//removeEditPolicy(EditPolicyRoles.POPUPBAR_ROLE);
installEditPolicy(EditPolicyRoles.POPUPBAR_ROLE, new DiagramPopupBarEditPolicy() {
@Override
protected void populatePopupBars(){
for (IElementType e : popupElements) {
if (getViewsManager().isElementVisible(e)) addPopupBarDescriptor(e, IconService.getInstance().getIcon(e, 0));
}
}
});
installEditPolicy(EditPolicy.LAYOUT_ROLE, new XYLayoutEditPolicy() {
@Override
protected Command createChangeConstraintCommand(ChangeBoundsRequest request,EditPart child,Object constraint){
Map<String, Object> map = request.getExtendedData();
if (map != null && map.get("noSave") != null && map.get("noSave").equals("true")) {
Rectangle r = (Rectangle) constraint;
r.setSize((Dimension) map.get("size"));
return super.createChangeConstraintCommand(request, child, r);
}
StsElement element = (StsElement) (((ShapeImpl) ((GraphicalEditPart) child).getModel()).basicGetElement());
CompoundCommand cc = new CompoundCommand();
Rectangle oldConstraint = new Rectangle();
int view = getViewsManager().getCurrentIntView();
NodeGraphicalConstraint oldCons = new NodeGraphicalConstraint(getViewsManager().getObjectConstraint(view, element.getStsUniqueID()));
oldConstraint.setLocation(oldCons.location);
oldConstraint.setSize(oldCons.size);
cc.add(super.createChangeConstraintCommand(request, child, constraint));
Rectangle r = ((Rectangle) constraint).getCopy();
if (child instanceof AgentEditPart || child instanceof RoleEditPart) {
StsToolShapeCompartmentEditPart scep = (StsToolShapeCompartmentEditPart) ((IGraphicalEditPart) child).getChildBySemanticHint("7001");
if (scep == null) scep = (StsToolShapeCompartmentEditPart) ((IGraphicalEditPart) child).getChildBySemanticHint("7002");
if (scep.isCollapsed()) {
r.setSize(oldCons.size);
}
}
cc.add(new ChangePositionConstraintCommand(view, element, r, oldConstraint));
return cc;
}
});
installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CreationEditPolicy() {
@Override
protected Command getCreateElementAndViewCommand(CreateViewAndElementRequest request){
request.setSize(new Dimension(-1, -1));
/*
* if(request.getViewAndElementDescriptor().getSemanticHint().equals(
* "2001")){
* request.setSize(AgentNodeFigure.THIS_DIMENSION);
* }
* else
* if(request.getViewAndElementDescriptor().getSemanticHint().equals
* ("2002")){
* request.setSize(RoleNodeFigure.THIS_DIMENSION);
* }
*/
if (request.getViewAndElementDescriptor().getSemanticHint().equals("2003"))
return UnexecutableCommand.INSTANCE;
else if (request.getViewAndElementDescriptor().getSemanticHint().equals("2004")) return UnexecutableCommand.INSTANCE;
// get the element descriptor
CreateElementRequestAdapter requestAdapter = request.getViewAndElementDescriptor().getCreateElementRequestAdapter();
// get the semantic request
CreateElementRequest createElementRequest = (CreateElementRequest) requestAdapter.getAdapter(CreateElementRequest.class);
if (createElementRequest.getContainer() == null) {
// complete the semantic request by filling in the
// host's semantic
// element as the context
View view = (View) getHost().getModel();
EObject hostElement = ViewUtil.resolveSemanticElement(view);
if (hostElement == null && view.getElement() == null) {
hostElement = view;
}
// Returns null if host is unresolvable so that
// trying to create a
// new element in an unresolved shape will not be
// allowed.
if (hostElement == null) { return null; }
createElementRequest.setContainer(hostElement);
}
// get the create element command based on the
// elementdescriptor's
// request
Command createElementCommand = getHost().getCommand(new EditCommandRequestWrapper((CreateElementRequest) requestAdapter.getAdapter(CreateElementRequest.class), request.getExtendedData()));
if (createElementCommand == null) { return UnexecutableCommand.INSTANCE; }
if (!createElementCommand.canExecute()) { return createElementCommand; }
// create the semantic create wrapper command
SemanticCreateCommand semanticCommand = new SemanticCreateCommand(requestAdapter, createElementCommand);
Command viewCommand = getCreateCommand(request);
Command refreshConnectionCommand = getHost().getCommand(new RefreshConnectionsRequest(((List) request.getNewObject())));
Rectangle r = new Rectangle(request.getLocation(), new Dimension(-1, -1));
InitConstraint c = new InitConstraint(createElementRequest, r);
CompositeCommand cc = new CompositeCommand(semanticCommand.getLabel());
cc.compose(semanticCommand);
Command result = new ICommandProxy(cc).chain(c); // <--added here command to initialize position constrait
result.chain(viewCommand);
if (refreshConnectionCommand != null) {
result.chain(refreshConnectionCommand);
}
return result;
}
});
installEditPolicy(EditPolicyRoles.DRAG_DROP_ROLE, new DiagramDragDropEditPolicy() {
@Override
protected Command getDropCommand(ChangeBoundsRequest request){
Iterator i = request.getEditParts().iterator();
while (i.hasNext()) {
Object o = i.next();
if (o instanceof Goal2EditPart || o instanceof TResource2EditPart) {
request.setMoveDelta(new Point(0, 0));
return UnexecutableCommand.INSTANCE;
}
}
return super.getDropCommand(request);
}
});
}
/**
* Get the current viewManager, used to get the current view, or to change view.
*
* @return the currentViewManger
*/
public ViewsManager getViewsManager(){
return viewsManager;
}
IPropertyChangeListener ipcl = new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event){
if (event.getProperty().equals(IPreferenceConstants.PREF_DEFAULT_FONT)) {
try {
int view = getViewsManager().getCurrentIntView();
getViewsManager().setCurrentView(ViewsManager.EMPTY_VIEW);
getViewsManager().setCurrentView(view);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
};
@Override
public void activate(){
super.activate();
StsToolDiagramEditorPlugin.getInstance().getPreferenceStore().addPropertyChangeListener(ipcl);
}
@Override
public void deactivate(){
StsToolDiagramEditorPlugin.getInstance().getPreferenceStore().removePropertyChangeListener(ipcl);
super.deactivate();
}
@Override
public Command getCommand(Request request){
if (request.getType().equals("duplicate")) return null;
return super.getCommand(request);
}
/**
* Command used to change the position constraint of a object when moved in the current diagram
*/
class ChangePositionConstraintCommand extends Command {
StsElement element;
Rectangle oldConstraint;
Rectangle newConstraint;
int view;
boolean collapsed;
/**
*
* @param view
* the current view, for which the object position should be changed
* @param element
* the model element associated to the object
* @param newConstraint
* the new position Constraint
* @param oldConstraint
* the current position constraint (used to perform UNDO)
*/
public ChangePositionConstraintCommand(int view, StsElement element, Rectangle newConstraint, Rectangle oldConstraint) {
super("Change Position");
this.element = element;
this.oldConstraint = oldConstraint;
this.newConstraint = newConstraint;
this.view = view;
}
@Override
public boolean canExecute(){
return true;
}
@Override
public boolean canUndo(){
return true;
}
@Override
public void execute(){
if (element != null) {
try {
collapsed = new NodeGraphicalConstraint(getViewsManager().getObjectConstraint(view, element.getStsUniqueID())).collapsed;
NodeGraphicalConstraint c = new NodeGraphicalConstraint(newConstraint);
c.collapsed = collapsed;
getViewsManager().setObjectConstraint(view, element.getStsUniqueID(), c.getConstraintInString());
} catch (Exception e) {
System.err.println("Error " + e.getStackTrace()[0].getClassName() + " at line " + e.getStackTrace()[0].getLineNumber());
}
}
}
@Override
public void undo(){
if (element != null) {
try {
NodeGraphicalConstraint c = new NodeGraphicalConstraint(oldConstraint);
c.collapsed = collapsed;
getViewsManager().setObjectConstraint(view, element.getStsUniqueID(), c.getConstraintInString());
} catch (Exception e) {
System.err.println("Error " + e.getStackTrace()[0].getClassName() + " at line " + e.getStackTrace()[0].getLineNumber());
}
}
}
}
/**
* Command used to initialize the position constraint of a object when created in the current diagram
*/
class InitConstraint extends Command {
CreateElementRequest createElementRequest;
Rectangle bounds;
Command setConstraintCommand = null;
/**
* Create a Command used to initialize the position constraint for the current view
*
* @param createElementRequest
* the request used to create the element
* @param constraint
* the object Constriant
*/
public InitConstraint(CreateElementRequest createElementRequest, Rectangle constraint) {
this.createElementRequest = createElementRequest;
this.bounds = constraint;
}
@Override
public boolean canExecute(){
return true;
}
@Override
public boolean canUndo(){
return true;
}
@Override
public void execute(){
StsElement element = (StsElement) createElementRequest.getNewElement();
if (element != null) {
try {
NodeGraphicalConstraint constraint = new NodeGraphicalConstraint(bounds.getLocation(), bounds.getSize());
getViewsManager().setObjectConstraintForAllViews(element.getStsUniqueID(), constraint.getConstraintInString());
} catch (Exception e) {
System.err.println("Error " + e.getStackTrace()[0].getClassName() + " at line " + e.getStackTrace()[0].getLineNumber());
}
}
}
@Override
public void undo(){
StsElement element = (StsElement) createElementRequest.getNewElement();
if (element != null) {
try {
getViewsManager().removeObjectConstraintForAllViews(element.getStsUniqueID());
} catch (Exception e) {
System.err.println("Error " + e.getStackTrace()[0].getClassName() + " at line " + e.getStackTrace()[0].getLineNumber());
}
}
}
}
public void flushHistory(){
getEditDomain().getCommandStack().dispose();
}
/* @Override
protected void handleNotificationEvent(Notification event) {
super.handleNotificationEvent(event);
if (event.getEventType()==Notification.ADD){
Object o = event.getNewValue();
if(o instanceof StsElement){
final StsElement e = (StsElement)o;
System.out.println("ADDED :"+e.getClass().getSimpleName()+" "+e.getStsUniqueID
());
new Thread(new Runnable() {
@Override
public void run() {
long startTime= System.currentTimeMillis();
long maxTime=1000;
EditPart ep=null;
while(System.currentTimeMillis()-startTime<maxTime && ep==null){
ep=findEditPart(CustomStsToolDiagramEditPart.this, e);
try {Thread.currentThread().sleep(10);} catch (InterruptedException e)
{e.printStackTrace();}
}
System.out.println("EP found "+ep);
}
}).start();
}
}
if (event.getEventType()==Notification.REMOVE){
Object o = event.getOldValue();
if(o instanceof StsElement){
StsElement e = (StsElement)o;
System.out.println("REMOVED :"+e.getClass().getSimpleName()+" "+e.
getStsUniqueID());
}
}
}*/
}