blob: 67ba20db0530c4fb360b9dc42f89d3fcf5670804 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 Rushan R. Gilmullin and others.
* 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:
* Rushan R. Gilmullin - initial API and implementation
*******************************************************************************/
package org.eclipse.osbp.vaaclipse.emf;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.Active;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.osbp.vaaclipse.emf.api.view.IConstants;
import org.eclipse.osbp.vaadin.emf.api.EmfModelElementClickEvent;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.eclipse.osbp.vaaclipse.publicapi.events.IWidgetModelAssociations;
import org.eclipse.osbp.vaaclipse.publicapi.events.VaaclipseUiEvents;
import com.vaadin.event.LayoutEvents;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Component;
@SuppressWarnings("serial")
public class ModeledUiClickController implements
LayoutEvents.LayoutClickListener, EventHandler {
@Inject
private IEclipseContext context;
@Inject
private IEventBroker eventBroker;
private boolean enabled;
private AbstractOrderedLayout content;
@PostConstruct
protected void setup() {
}
@Inject
protected void activate(@Active @Optional MTrimmedWindow window) {
if (content != null) {
return;
}
if (window != null) {
content = (AbstractOrderedLayout) window.getContext().get(
"rootLayoutClickNotifier");
}
if (content != null) {
setEnabled(true);
}
}
public void setEnabled(boolean value) {
if (content == null) {
return;
}
this.enabled = value;
if (enabled) {
content.addLayoutClickListener(this);
// e4 ui model
eventBroker.subscribe(
UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT, this);
eventBroker.subscribe(UIEvents.Item.TOPIC_SELECTED, this);
eventBroker.subscribe(VaaclipseUiEvents.Item.TOPIC_EXECUTED, this);
} else {
if (content != null) {
content.removeLayoutClickListener(this);
content = null;
}
eventBroker.unsubscribe(this);
}
}
public boolean isEnabled() {
return enabled;
}
@Override
public void layoutClick(LayoutEvents.LayoutClickEvent event) {
Component clickedUI = event.getClickedComponent();
EObject clickedModel = context.get(IWidgetModelAssociations.class)
.getElement(clickedUI);
if (clickedModel == null) {
return;
}
// if designer parts where clicked, then do not send event
if (!isDesignerPart(clickedModel)) {
eventBroker.send(IConstants.TOPIC__ELEMENT_CLICKED,
new EmfModelElementClickEvent(clickedUI,
(EObject) clickedModel));
}
}
@PreDestroy
protected void destroy() {
if (isEnabled()) {
setEnabled(false);
}
context = null;
eventBroker = null;
content = null;
}
@Override
public void handleEvent(Event event) {
// if a perspective was selected, we need to send a layoutclick event
//
if (event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MPerspectiveStack) {
// events from e4 application model
//
String type = (String) event.getProperty(UIEvents.EventTags.TYPE);
if (UIEvents.EventTypes.SET.equals(type)
&& event.getProperty(UIEvents.EventTags.ATTNAME).equals(
"selectedElement")) {
MUIElement newValue = (MUIElement) event
.getProperty(UIEvents.EventTags.NEW_VALUE);
// if designer parts where clicked, then do not send event
if (!isDesignerPart((EObject) newValue)) {
Object widget = context.get(IWidgetModelAssociations.class)
.getWidget((EObject) newValue);
eventBroker.send(IConstants.TOPIC__ELEMENT_CLICKED,
new EmfModelElementClickEvent(widget,
(EObject) newValue));
}
}
} else if (event.getTopic().endsWith(
VaaclipseUiEvents.Item.TOPIC_EXECUTED)) {
// events from e4 application model -> executed items
//
MUIElement item = (MUIElement) event.getProperty(IEventBroker.DATA);
// if designer parts where clicked, then do not send event
if (!isDesignerPart((EObject) item)) {
Object widget = context.get(IWidgetModelAssociations.class)
.getWidget((EObject) item);
eventBroker.send(IConstants.TOPIC__ELEMENT_CLICKED,
new EmfModelElementClickEvent(widget, (EObject) item));
}
}
}
/**
* Check if the model or its parent up to part or sashContainer have the tag
* "designerPart".
*
* @param element
* @return
*/
private boolean isDesignerPart(EObject element) {
if (element == null) {
return false;
}
if (!(element instanceof MUIElement)) {
return false;
}
MUIElement uiElement = (MUIElement) element;
if (element instanceof MPart || element instanceof MPartSashContainer) {
// do not check parents
return uiElement.getTags().contains(IConstants.TAG__DESIGNER_PARTS);
}
if (uiElement.getTags().contains(IConstants.TAG__DESIGNER_PARTS)) {
// it is designer part
return false;
} else {
// check up the parent until part or sashcontainer reached
EObject parent = ((EObject) element).eContainer();
return isDesignerPart(parent);
}
}
}