| /***************************************************************************** |
| * 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); |
| } |
| } |
| } |