blob: e11f8ebf8f7079a76b89bdd9af2a778eb6a29d09 [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.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;
}
}