blob: 02e00d8f648869665187638e5c80cfeb6b8f8412 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2019 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Xavier Le Pallec (for CEA LIST) xlepallec@lilo.org - Bug 558456
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.clazz.lf.classtextualedition.classcompartments;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.common.command.AbstractCommand;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.transaction.RollbackException;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.notation.BasicCompartment;
import org.eclipse.gmf.runtime.notation.LayoutConstraint;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.Shape;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.emf.gmf.util.GMFUnsafe;
import org.eclipse.papyrus.infra.gmfdiag.common.utils.ServiceUtilsForEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassAttributeCompartmentEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassAttributeCompartmentEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassOperationCompartmentEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassOperationCompartmentEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.lf.classtextualedition.Activator;
import org.eclipse.papyrus.uml.diagram.clazz.lf.classtextualedition.mapping.jsonstructures.JsonUmlClass;
import org.eclipse.papyrus.uml.diagram.common.editparts.ClassEditPart;
/**
* This class is dedicated to expand if necessary the properties and operations
* compartments: if the textual definition of the class includes properties and
* the properties compartment is not visible and the same for operations. <BR>
* This is why one of constructor includes an instance of UmlClass (textual
* definition of the class).
*/
public class ClassExpander {
private ClassEditPart classEditPart;
private JsonUmlClass theClass;
private final static Activator LOGGER = Activator.getDefault();
/**
* This constructor only uses one parameter (class edit part). That means that
* there is no textual definition of the class to consider.
*
* @param classEditPart
* the class to "expand".
*/
public ClassExpander(ClassEditPart classEditPart) {
this(classEditPart, null);
}
/**
* This constructor uses two parameters: a class edit part and the textual
* definition of the class. That means that there is a textual definition of the
* class to consider.
*
* @param classEditPart
* the class to "expand".
* @param theClass
* the textual definition of the class
*/
public ClassExpander(ClassEditPart classEditPart, JsonUmlClass theClass) {
super();
this.classEditPart = classEditPart;
this.theClass = theClass;
}
//
// different facilities functions
//
/**
* The main public method: called to display the properties and operations
* compartments if necessary (i.e. if the textual definition induces a change).
* It is just a redirection/proxy to
* {@link ClassExpander#setCompartmentsVisible()}.
*/
public void expandIfNecessary() {
setCompartmentsVisible();
}
/**
* This private method does the main work: get all the compartments and check
* whether they have to be visible/displayed or not.
*/
private void setCompartmentsVisible() {
List<BasicCompartment> compartmentList = getClassCompartments();
if (!compartmentList.isEmpty()) {
try {
TransactionalEditingDomain editingDomain = ServiceUtilsForEditPart.getInstance()
.getTransactionalEditingDomain(classEditPart);
executeWithoutCommandStack(editingDomain, new AbstractCommand() {
@Override
public void execute() {
for (BasicCompartment compartment : compartmentList) {
if (isNonEmptyPropertyOrOperationCompartment(compartment) && !compartment.isVisible()) {
compartment.setVisible(true);
addALittleHeightForACompartment();
}
}
}
@Override
public void redo() {
// #TODO expand to undo
}
});
} catch (ServiceException exception) {
Activator.getDefault().logError(exception.toString(), exception);
}
}
}
/**
* This method checks
* <UL>
* <LI>if the compartment is the properties or operation one</LI>
* <LI>if the corresponding textual definition has been given and if it is,
* there is elements for this compartment.</LI>
* </UL>
*
* @param compartment
* the compartment to consider
* @return true if properties/operations, with textual definition defining
* something for it.
*/
protected boolean isNonEmptyPropertyOrOperationCompartment(BasicCompartment compartment) {
return ((compartment.getType().equals(ClassAttributeCompartmentEditPart.VISUAL_ID)
&& (theClass == null || !theClass.getProperties().isEmpty()))
|| (compartment.getType().equals(ClassAttributeCompartmentEditPartCN.VISUAL_ID)
&& (theClass == null || !theClass.getProperties().isEmpty()))
|| (compartment.getType().equals(ClassOperationCompartmentEditPart.VISUAL_ID)
&& (theClass == null || !theClass.getOperations().isEmpty()))
|| (compartment.getType().equals(ClassOperationCompartmentEditPartCN.VISUAL_ID)
&& (theClass == null || !theClass.getOperations().isEmpty())));
}
/**
* This method returns the properties and operations compartments (notation
* level) that we can potentially expand.
*
* @return the properties and operations compartments
*/
private List<BasicCompartment> getClassCompartments() {
List<BasicCompartment> compartmentList = new ArrayList<>();
if (classEditPart.getModel() instanceof Shape) {
Shape classModel = Shape.class.cast(classEditPart.getModel());
for (Object child : classModel.getChildren()) {
if (isACompartmentToExpandCollapse(child)) {
compartmentList.add(BasicCompartment.class.cast(child));
}
}
} else {
LOGGER.logCastProblem("classEditPart.getModel()", Shape.class); //$NON-NLS-1$
}
return compartmentList;
}
/**
* This method adds a little height to the class when displaying a compartment
* (this one is normally empty).
*/
protected void addALittleHeightForACompartment() {
if (classEditPart.getModel() instanceof Shape) {
Shape classModel = Shape.class.cast(classEditPart.getModel());
LayoutConstraint layoutConstraint = classModel.getLayoutConstraint();
int currentHeight = java.lang.Integer.class.cast(layoutConstraint.eGet(NotationPackage.eINSTANCE.getSize_Height()));
UmlClassResizer.getInstance().realResizeHeight(classModel.getLayoutConstraint(), currentHeight + 20);
} else {
LOGGER.logCastProblem("classEditPart.getModel()", Shape.class); //$NON-NLS-1$
}
}
/**
* This methods checks if the compartment is properties or operations ones.
*
* @param child
* compartment to check.
* @return true if one of previously listed.
*/
private boolean isACompartmentToExpandCollapse(Object child) {
if (child instanceof BasicCompartment) {
BasicCompartment compartment = BasicCompartment.class.cast(child);
if (compartment.getType().equals(ClassAttributeCompartmentEditPart.VISUAL_ID)
|| compartment.getType().equals(ClassOperationCompartmentEditPart.VISUAL_ID)
|| compartment.getType().equals(ClassAttributeCompartmentEditPartCN.VISUAL_ID)
|| compartment.getType().equals(ClassOperationCompartmentEditPartCN.VISUAL_ID)) {
return true;
}
}
return false;
}
/**
* This method allows to execute a command without changing the command stack.
* This allows to avoid seeing the command in the Undo/Redo menu.
*
* @param editingDomain
* This parameter is always needed to perform a command
* @param command
* The command to perform
*/
private void executeWithoutCommandStack(TransactionalEditingDomain editingDomain, Command command) {
try {
GMFUnsafe.write(editingDomain, command);
} catch (InterruptedException exception) {
Activator.getDefault().logError(exception.toString(), exception);
} catch (RollbackException exception) {
Activator.getDefault().logError(exception.toString(), exception);
}
}
}