| /** |
| * |
| * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| * |
| * This copyright notice shows up in the generated Java code |
| * |
| */ |
| |
| package org.eclipse.osbp.xtext.topologydsl.jvmmodel |
| |
| import com.vaadin.ui.Component |
| import com.vaadin.ui.VerticalLayout |
| import java.util.Locale |
| import javax.annotation.PostConstruct |
| import javax.annotation.PreDestroy |
| import javax.inject.Inject |
| import org.eclipse.e4.core.contexts.IEclipseContext |
| import org.eclipse.e4.core.services.events.IEventBroker |
| import org.eclipse.e4.ui.model.application.MApplication |
| import org.eclipse.osbp.osgi.hybrid.api.AbstractHybridVaaclipseView |
| import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService |
| import org.eclipse.osbp.ui.api.user.IUser |
| import org.eclipse.osbp.utils.constants.GeneratorConstants |
| import org.eclipse.osbp.utils.theme.EnumCssClass |
| import org.eclipse.osbp.utils.vaadin.ViewLayoutManager |
| import org.eclipse.osbp.xtext.topologydsl.Topology |
| import org.eclipse.osbp.xtext.topologydsl.TopologyPackage |
| import org.eclipse.xtext.common.types.JvmDeclaredType |
| import org.eclipse.xtext.common.types.JvmField |
| import org.eclipse.xtext.common.types.JvmVisibility |
| import org.eclipse.xtext.naming.IQualifiedNameProvider |
| import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer |
| import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor |
| import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder |
| import org.osgi.service.event.EventHandler |
| import org.slf4j.Logger |
| |
| /** |
| * <p> |
| * This inferrer infers models of extension .topology and generates code to be used by a e4 application as view. Underlying components |
| * are from the vaadin component repository and especially JavaScript components based on D3. |
| * </p> |
| * |
| * @author Jose Dominguez |
| */ |
| /** |
| * <p>Infers a JVM model from the source model.</p> |
| * |
| * <p>The JVM model should contain all elements that would appear in the Java code |
| * which is generated from the source model. Other models link against the JVM model rather than the source model.</p> |
| */ |
| class TopologyDSLJvmModelInferrer extends AbstractModelInferrer { |
| |
| /** |
| * convenience API to build and initialize JVM types and their members. |
| */ |
| @Inject extension IQualifiedNameProvider |
| @Inject extension JvmTypesBuilder |
| @Inject extension TopologyDSLD3JavaComponentsCreator |
| |
| def dispatch void infer(TopologyPackage pckg, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) { |
| for (Topology topology : pckg.topologies) { |
| var cls = topology.toClass(pckg.name.concat(".").concat(topology.name).concat("Topology")) |
| cls.superTypes.add(_typeReferenceBuilder.typeRef(AbstractHybridVaaclipseView)) |
| cls.superTypes.add(_typeReferenceBuilder.typeRef(IUser.UserLocaleListener)) |
| acceptor.accept(cls, |
| [ |
| documentation = GeneratorConstants.GENERATED_CLASSES_DOCUMENTATION |
| it.toFields(topology) |
| it.toConstructor(topology) |
| it.toOperations(topology) |
| ]) |
| topology.createJsJavaComponent(acceptor) |
| } |
| } |
| |
| /** |
| * <p>build the constructors to be used by an e4 application.</p> |
| * |
| */ |
| def void toConstructor(JvmDeclaredType type, Topology topology) { |
| type.members += topology.toConstructor( |
| [ |
| annotations += _annotationTypesBuilder.annotationRef(Inject) |
| parameters += topology.toParameter("parent", _typeReferenceBuilder.typeRef(VerticalLayout)) |
| parameters += topology.toParameter("context", _typeReferenceBuilder.typeRef(IEclipseContext)) |
| parameters += topology.toParameter("app", _typeReferenceBuilder.typeRef(MApplication)) |
| body = [append('''super(parent,context,app);''')] |
| ]) |
| } |
| |
| /** |
| * <p>build the class variables.</p> |
| * |
| */ |
| def void toFields(JvmDeclaredType type, Topology topology) { |
| var JvmField field = null |
| // create logger |
| field = topology.toField("log", _typeReferenceBuilder.typeRef(Logger))[setInitializer([append('''org.slf4j.LoggerFactory.getLogger("topology")''')])] |
| field.static = true |
| field.visibility = JvmVisibility::PRIVATE |
| type.members += field |
| field = topology.toField("layoutManager", _typeReferenceBuilder.typeRef(ViewLayoutManager)) |
| type.members += field |
| field = topology.toField("dataComponent", _typeReferenceBuilder.typeRef(Component)) |
| type.members += field |
| field = topology.toField("eventBroker", _typeReferenceBuilder.typeRef(IEventBroker))[ |
| annotations += _annotationTypesBuilder.annotationRef(Inject)] |
| type.members += field |
| field = topology.toField("refreshView", _typeReferenceBuilder.typeRef(EventHandler)) |
| type.members += field |
| field = topology.toField("panelWidth", _typeReferenceBuilder.typeRef(int)) |
| type.members += field |
| field = topology.toField("panelHeight", _typeReferenceBuilder.typeRef(int)) |
| type.members += field |
| field = topology.toField("dslMetadataService", _typeReferenceBuilder.typeRef(IDSLMetadataService)) [annotations += _annotationTypesBuilder.annotationRef(Inject)] |
| type.members += field |
| field = topology.toField("locale", _typeReferenceBuilder.typeRef(Locale)) |
| type.members += field |
| field = topology.toField("user", _typeReferenceBuilder.typeRef(IUser))[annotations += _annotationTypesBuilder.annotationRef(Inject)] |
| type.members += field |
| } |
| |
| /** |
| * <p>build the methods.</p> |
| * |
| */ |
| def void toOperations(JvmDeclaredType type, Topology topology) { |
| |
| // create view |
| type.members += topology.toMethod("createView", _typeReferenceBuilder.typeRef(Void::TYPE), |
| [ |
| parameters += topology.toParameter("parent", _typeReferenceBuilder.typeRef(VerticalLayout)) |
| body = [append('''«topology.createView»''')] |
| ]) |
| |
| // create components |
| type.members += topology.toMethod("createComponents", _typeReferenceBuilder.typeRef(Void::TYPE), |
| [ |
| body = [append('''«topology.createComponents»''')] |
| ]) |
| |
| // create D3 Topology |
| type.members += topology.toMethod("createD3Topology", _typeReferenceBuilder.typeRef(Component), |
| [ |
| body = [append('''«topology.createD3Topology»''')] |
| ]) |
| |
| // subscribe to eventBroker |
| type.members += topology.toMethod("subscribe", _typeReferenceBuilder.typeRef(Void::TYPE), |
| [ |
| visibility = JvmVisibility.PROTECTED |
| annotations += _annotationTypesBuilder.annotationRef(PostConstruct) |
| body = [append('''«topology.subscribe»''')] |
| ]) |
| |
| // unsubscribe from eventBroker |
| type.members += topology.toMethod("unsubscribe", _typeReferenceBuilder.typeRef(Void::TYPE), |
| [ |
| visibility = JvmVisibility.PROTECTED |
| annotations += _annotationTypesBuilder.annotationRef(PreDestroy) |
| body = [append('''«topology.unsubscribe»''')] |
| ]) |
| // locale notification |
| type.members += topology.toMethod("localeChanged", _typeReferenceBuilder.typeRef(Void::TYPE), |
| [ |
| visibility = JvmVisibility.PUBLIC |
| annotations += _annotationTypesBuilder.annotationRef(Override) |
| parameters += topology.toParameter("locale", _typeReferenceBuilder.typeRef(Locale)) |
| body = [append('''«topology.localeChanged»''')] |
| ]) |
| } |
| |
| // subscribe to view refresh |
| def subscribe(Topology topology) ''' |
| eventBroker.subscribe(EventBrokerMsg.REFRESH_VIEW+"«topology.name»Topology", refreshView);''' |
| |
| def unsubscribe(Topology topology) ''' |
| eventBroker.unsubscribe(refreshView);''' |
| |
| /** |
| * <p>build the main method to be called from e4.</p> |
| * |
| */ |
| def String createView(Topology topology) { |
| var body = ''' |
| layoutManager = new ViewLayoutManager(); |
| layoutManager.init(parent); |
| refreshView = «topology.refreshView» |
| user.addUserLocaleListener(this); |
| // to resize the chart according to split positions of partsashcontainer - setContainerData is tracked |
| ((EObject)getPart()).eAdapters().add(new AdapterImpl() { |
| public void notifyChanged(Notification notification) { |
| if (notification.getEventType()==Notification.SET && |
| notification.getFeatureID(UIElementImpl.class) == UiPackageImpl.UI_ELEMENT__CONTAINER_DATA) |
| { |
| log.debug("render due to split position changed"); |
| renderData(); |
| } |
| } |
| }); |
| SizeReporter sizeReporter = new SizeReporter(layoutManager.getDataArea()); |
| sizeReporter.addResizeListener(new ComponentResizeListener() { |
| @Override |
| public void sizeChanged(ComponentResizeEvent event) { |
| boolean changed = false; |
| if (panelWidth != event.getWidth()) { |
| changed = true; |
| panelWidth = event.getWidth(); |
| } |
| if (panelHeight != event.getHeight()) { |
| changed = true; |
| panelHeight = event.getHeight(); |
| } |
| if (changed) { |
| log.debug("Panel size changed : " + event.getWidth() + " x " + event.getHeight()); |
| renderData(); |
| } |
| } |
| }); |
| ''' |
| return body |
| } |
| |
| /** |
| * <p>create a handler for external triggered refresh requests.</p> |
| * |
| */ |
| def String refreshView(Topology topology) { |
| var body = "" |
| body = ''' |
| «body» |
| new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| renderData(); |
| } |
| }; |
| ''' |
| return body |
| } |
| |
| /** |
| * <p>build the data components.</p> |
| * |
| */ |
| def String createComponents(Topology topology) { |
| var body = ''' |
| if (panelWidth == 0 && panelHeight == 0) { |
| return; |
| } |
| log.debug("topology creates components"); |
| try { |
| // remove any previous component |
| if (dataComponent != null) { |
| layoutManager.getDataArea().removeComponent(dataComponent); |
| dataComponent = null; |
| } |
| // generate a new result component |
| dataComponent = createD3Topology(); |
| dataComponent.setSizeFull(); |
| dataComponent.addStyleName("«EnumCssClass.DATA_COMPONENT.styleName»"); // <== is THIS necessary any more??? |
| layoutManager.getDataArea().addComponent(dataComponent); |
| layoutManager.getDataArea().setExpandRatio(dataComponent, 1); |
| } catch (Exception e) { |
| log.error(e.getLocalizedMessage()); |
| } |
| log.debug("topology creating components finished"); |
| ''' |
| return body |
| } |
| |
| def localeChanged(Topology topology) |
| ''' |
| if(layoutManager != null) { |
| layoutManager.setLabelValue(dslMetadataService.translate(locale.toLanguageTag(), "«topology.titleValue»")); |
| } |
| ''' |
| } |