| /***************************************************************************** |
| * 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.autosizeableclasses.statemachine; |
| |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.Request; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest; |
| import org.eclipse.papyrus.infra.gmfdiag.common.service.palette.AspectUnspecifiedTypeCreationTool.CreateAspectUnspecifiedTypeRequest; |
| |
| import org.eclipse.papyrus.uml.diagram.clazz.lf.autosizeableclasses.edit.policies.utils.ConcernedCompartment; |
| import org.eclipse.papyrus.uml.diagram.common.editparts.ClassEditPart; |
| |
| /** |
| * This class transforms low-level events or operations into high-level events |
| * for the state machine. In fact, there is few differences between these two |
| * types of events. A LowEventManager will receive a stream of events (through |
| * its methods). For example, the mouse moves of one pixel over a class, its |
| * method hovering a class will be invoked. If the mouse moves of one other |
| * pixel over the same class,its method hovering a class will be invoked once |
| * again. The role of LowEventManager will be to fire high-level event the first |
| * time the mouse over a class... and for the other following hovered pixels of |
| * the class. <BR> |
| * That's the reason why this manager needs to store current request, concerned |
| * compartment and classEditPart to detect new type of interaction or new |
| * element involved in the current interaction.<BR> |
| * An instance of LowEventManager is always attached to a state machine: it |
| * always fires events on this machine as a transmission mean. |
| * |
| */ |
| public class LowEventManager { |
| |
| private StateMachine stateMachine; |
| private ClassEditPart currentClassEditPart; |
| private Request currentRequest; |
| private int concernedCompartment; |
| |
| /** |
| * The constructor takes a state machine as a parameter (in order to fire |
| * high-level events on it) |
| * |
| * @param stateMachine the state machine |
| */ |
| public LowEventManager(StateMachine stateMachine) { |
| super(); |
| this.stateMachine = stateMachine; |
| } |
| |
| /** |
| * @return the state machine associated to this low event manager. |
| */ |
| public StateMachine getStateMachine() { |
| return stateMachine; |
| } |
| |
| /** |
| * This method is used by edit policies to indicate that the mouse is hovering a |
| * something except a class. If, previously, a class was hovered, then a |
| * high-level event is fired (HOVERING_SOMETHING_BUT_A_CLASS) and there is no |
| * more current hovered class. |
| * |
| * @param editPart the editPart concerned by the hovering. |
| */ |
| public void hoveringSomethingButAClass(EditPart editPart) { |
| if (getCurrentClassEditPart() != null) { |
| setCurrentClassEditPart(null); |
| getStateMachine().fireEvent(StateMachineElementsFactory.getInstance().createEvent(Events.HOVERING_SOMETHING_BUT_A_CLASS)); |
| } |
| |
| } |
| |
| /** |
| * This method is used by edit policies to indicate that the mouse is hovering a |
| * class or one of its components. If, previously, a class was hovered, then a |
| * high-level event is fired (HOVERING_ANOTHER_CLASS) and the current hovered |
| * class is now the one attached to the edit part parameter. If there wasn't |
| * hovered class, another type of high-level event is fired (HOVERING_A_CLASS) |
| * but with the same assignment for the current hovered class. |
| * |
| * @param editPart the editPart concerned by the hovering. |
| */ |
| public void hoveringAClass(EditPart editPart) { |
| ClassEditPart hoveredClassEditPart = getCorrespondingClassEditPart(editPart); |
| |
| if (getCurrentClassEditPart() == null) { |
| setCurrentClassEditPart(hoveredClassEditPart); |
| getStateMachine() |
| .fireEvent(StateMachineElementsFactory.getInstance().createEvent(Events.HOVERING_A_CLASS, hoveredClassEditPart)); |
| } |
| |
| if (getCurrentClassEditPart() != hoveredClassEditPart) { |
| setCurrentClassEditPart(hoveredClassEditPart); |
| getStateMachine() |
| .fireEvent(StateMachineElementsFactory.getInstance().createEvent(Events.HOVERING_ANOTHER_CLASS, hoveredClassEditPart)); |
| } |
| |
| } |
| |
| /** |
| * This method is used by edit policies to indicate that the current user-level |
| * operation has changed. There is no more current hovered class. The high-level |
| * event ACTIVE_TOOL_CHANGED will be fired. |
| */ |
| public void activeToolChanged() { |
| setCurrentClassEditPart(null); |
| getStateMachine().fireEvent(StateMachineElementsFactory.getInstance().createEvent(Events.ACTIVE_TOOL_CHANGED)); |
| } |
| |
| /** |
| * This method is called when we are sure to deal with a class or one of its |
| * components. The method return the class edit part that can be the edit part |
| * passed as parameter or the class edit part that contains this parameter (for |
| * compartments or other class components). |
| * |
| * @param editPart the hovering edit par. |
| * @return the corresponding class edit part |
| */ |
| private ClassEditPart getCorrespondingClassEditPart(EditPart editPart) { |
| while (!(editPart instanceof ClassEditPart)) { |
| editPart = editPart.getParent(); |
| } |
| return (ClassEditPart) editPart; |
| } |
| |
| /** |
| * @return the current class edit part (if any) |
| */ |
| public ClassEditPart getCurrentClassEditPart() { |
| return currentClassEditPart; |
| } |
| |
| /** |
| * @param currentClassEditPart the new hovered class edit part. |
| */ |
| public void setCurrentClassEditPart(ClassEditPart currentClassEditPart) { |
| this.currentClassEditPart = currentClassEditPart; |
| } |
| |
| /** |
| * Requests are used to detect a new type of user-level action is active tool |
| * listener didn't manage to detect it. |
| * |
| * @return the current processed request. |
| */ |
| public Request getCurrentRequest() { |
| return currentRequest; |
| } |
| |
| /** |
| * This method aims at detecting - through the stream of requests - whether |
| * there is a new user-level action. During a property creation d-n-d, hovering |
| * a class produces a particular request but hovering next the class diagram |
| * will produce another request (because the possible result is different). But it's still the same user-level action. |
| * So this method analyzes the request in order to detect such thing. |
| * |
| * @param request the new current request (possibly a request of the same type). |
| */ |
| public void setCurrentRequest(Request request) { |
| if (request == null) { |
| getStateMachine().fireEvent(StateMachineElementsFactory.getInstance().createEvent(Events.END_OF_REQUEST)); |
| this.currentRequest = null; |
| } else if (currentRequest != null && (isCreationRequest(request) == isCreationRequest(currentRequest) |
| && isDropObjectRequest(request) == isDropObjectRequest(currentRequest))) { |
| this.currentRequest = request; |
| } else { |
| |
| if (currentRequest != null) { |
| getStateMachine().fireEvent(StateMachineElementsFactory.getInstance().createEvent(Events.END_OF_REQUEST)); |
| } |
| |
| if (isCreationRequest(request)) { |
| this.currentRequest = request; |
| setConcernedCompartment(ConcernedCompartment.getChecker().getConcernedCompartment(request)); |
| getStateMachine().fireEvent(StateMachineElementsFactory.getInstance().createEvent(Events.NEW_CREATE_REQUEST)); |
| } |
| if (isDropObjectRequest(request)) { |
| this.currentRequest = request; |
| setConcernedCompartment(ConcernedCompartment.getChecker().getConcernedCompartment(request)); |
| getStateMachine().fireEvent(StateMachineElementsFactory.getInstance().createEvent(Events.NEW_DROP_REQUEST)); |
| } |
| } |
| } |
| |
| /** |
| * @param request request |
| * @return true if it is a creation request or a creation request is in a "bundle" request. |
| */ |
| protected boolean isCreationRequest(Request request) { |
| return request instanceof CreateAspectUnspecifiedTypeRequest || request instanceof CreateViewAndElementRequest; |
| } |
| |
| /** |
| * @param request request |
| * @return true if it is a drop object request. |
| */ |
| protected boolean isDropObjectRequest(Request request) { |
| return request instanceof DropObjectsRequest; |
| } |
| |
| /** |
| * Returns the concerned compartment, always deduced from different elements (mainly the request). For more details, see {@link org.eclipse.papyrus.uml.diagram.clazz.lf.autosizeableclasses.edit.policies.utils.ConcernedCompartment}. |
| * @return the concerned compartment |
| */ |
| protected int getConcernedCompartment() { |
| return concernedCompartment; |
| } |
| |
| /** |
| * Allows to set the current concerned compartment. For more details, see {@link org.eclipse.papyrus.uml.diagram.clazz.lf.autosizeableclasses.edit.policies.utils.ConcernedCompartment}. |
| * @param concernedCompartment the new concerned compartment. |
| */ |
| protected void setConcernedCompartment(int concernedCompartment) { |
| this.concernedCompartment = concernedCompartment; |
| } |
| |
| } |