| /** |
| * |
| * 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 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: |
| * 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.ejt.vaadin.sizereporter.ComponentResizeEvent |
| import com.ejt.vaadin.sizereporter.ComponentResizeListener |
| import com.ejt.vaadin.sizereporter.SizeReporter |
| import com.vaadin.ui.HorizontalLayout |
| import com.vaadin.ui.JavaScriptFunction |
| import com.vaadin.ui.Label |
| import com.vaadin.ui.Panel |
| import elemental.json.JsonArray |
| import elemental.json.JsonException |
| import elemental.json.impl.JreJsonString |
| import java.io.IOException |
| import java.io.InputStream |
| import java.util.ArrayList |
| import java.util.List |
| import javax.inject.Inject |
| import org.apache.commons.io.IOUtils |
| import org.eclipse.e4.core.services.events.IEventBroker |
| import org.eclipse.e4.ui.model.application.ui.impl.UIElementImpl |
| import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl |
| import org.eclipse.emf.common.notify.Adapter |
| import org.eclipse.emf.common.notify.Notification |
| import org.eclipse.emf.common.notify.impl.AdapterImpl |
| import org.eclipse.emf.ecore.EObject |
| import org.eclipse.emf.ecore.resource.Resource |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent |
| import org.eclipse.osbp.ui.api.e4.IE4Focusable |
| import org.eclipse.osbp.xtext.basic.generator.BasicDslGeneratorUtils |
| import org.eclipse.osbp.xtext.i18n.I18NModelGenerator |
| import org.eclipse.osbp.xtext.topologydsl.Topology |
| import org.eclipse.osbp.xtext.topologydsl.TopologyModel |
| import org.eclipse.osbp.xtext.topologydsl.TopologyProjection |
| import org.eclipse.xtext.generator.IFileSystemAccess |
| import org.eclipse.xtext.naming.IQualifiedNameProvider |
| import org.eclipse.xtext.xbase.compiler.GeneratorConfig |
| import org.eclipse.xtext.xbase.compiler.ImportManager |
| |
| class TopologyModelGenerator extends I18NModelGenerator { |
| @Inject extension IQualifiedNameProvider |
| @Inject extension D3JsJavaUtil |
| @Inject extension BasicDslGeneratorUtils |
| |
| override createAppendable(EObject context, ImportManager importManager, GeneratorConfig config) { |
| // required to initialize the needed builder to avoid deprecated methods |
| builder = context.eResource |
| // --------- |
| addImportFor(importManager, _typeReferenceBuilder |
| , Label |
| , List |
| , ArrayList |
| , HorizontalLayout |
| , Notification |
| , IEventBroker |
| , JavaScriptFunction |
| , JsonArray |
| , JsonException |
| , JreJsonString |
| , InputStream |
| , IOUtils |
| , IOException |
| , Notification |
| , Adapter |
| , AdapterImpl |
| , EObject |
| , UIElementImpl |
| , UiPackageImpl |
| , SizeReporter |
| , ComponentResizeListener |
| , ComponentResizeEvent |
| , EventDispatcherEvent |
| , EventDispatcherEvent.EventDispatcherDataTag |
| , EventDispatcherEvent.EventDispatcherCommand |
| , IE4Focusable |
| , Panel |
| |
| ) |
| super.createAppendable(context, importManager, config) |
| } |
| |
| override void doGenerate(Resource input, IFileSystemAccess fsa) { |
| super.doGenerate(input, fsa) |
| for (obj : input.contents) { |
| if(obj instanceof TopologyModel) { |
| (obj as TopologyModel).jsGenerate(fsa) |
| } |
| } |
| } |
| |
| def jsGenerate(TopologyModel topologyModel, IFileSystemAccess fsa) { |
| for (pkg : topologyModel.packages) { |
| for (topology : pkg.topologies) { |
| var pckgName = pkg.fullyQualifiedName.toString |
| var strBuilder = new StringBuilder |
| var pckgNamePath = pckgName.replaceAll("\\.", "/") |
| |
| var propOutputFile = '''«pckgNamePath»/js/«topology.createTopologyJsFilename»''' |
| |
| // println("********************* Property-Output *********************") |
| topology.generateJsFile(strBuilder) |
| if (strBuilder.length > 0) { |
| fsa.generateFile(propOutputFile, strBuilder) |
| } |
| } |
| } |
| } |
| |
| def void generateJsFile(Topology topology, StringBuilder strBuilder) { |
| var topologyFilePath = topology.createfullyQualifiedTopologyFilename.replaceAll("\\.", "_") |
| strBuilder.generateTopoJsFile(topologyFilePath, topology) |
| } |
| |
| def generateTopoJsFile(StringBuilder strBuilder, String topologyJavaFileName, Topology topology) { |
| strBuilder.append( |
| ''' |
| «topologyJavaFileName» = function() { |
| var connector = this; |
| var width = this.getState().panelWidth; |
| var height = this.getState().panelHeight; |
| var scale = 2*(width < height)?width:height; |
| scale = scale>1000?1000:scale; |
| «var countryNameUpper = topology.fileName» |
| «var countryName = topology.fileName» |
| «topology.generateProjection» |
| |
| var path = d3.geoPath().projection(projection); |
| |
| var cxD3«countryNameUpper»TopoJsHTMLRootComponent = this.getElement(); |
| cxD3«countryNameUpper»TopoJsHTMLRootComponent.innerHTML = |
| "<div id=\""+this.getState().htmlTagId+"_div\">" + "</div>"; |
| |
| var cxD3«countryNameUpper»TopoJsHTMLRootComponentSelection = d3.select(cxD3«countryNameUpper»TopoJsHTMLRootComponent).select("#"+this.getState().htmlTagId+"_div"); |
| |
| var cxD3«countryNameUpper»TopoJsHTMLRootComponentSvg = cxD3«countryNameUpper»TopoJsHTMLRootComponentSelection.append("svg") |
| .attr("width", width) |
| .attr("height", height); |
| |
| var cxD3«countryNameUpper»TopoJsHTMLRootComponentG = cxD3«countryNameUpper»TopoJsHTMLRootComponentSvg.append("g"); |
| |
| «IF topology.zoomable» |
| var zoom = d3.zoom() |
| .scaleExtent([1, 8]) |
| .on("zoom",function() { |
| cxD3«countryNameUpper»TopoJsHTMLRootComponentG.attr("transform","translate("+ |
| d3.event.translate +")scale(" + d3.event.scale + ")"); |
| }); |
| «ENDIF» |
| |
| jsonTreeFunction = function(topology) { |
| «var topologyObject = "unit"» |
| «IF !(topology.projection == TopologyProjection.WORLD)» |
| // To create the 'unit' |
| cxD3«countryNameUpper»TopoJsHTMLRootComponentG.selectAll(".unit") |
| .data(topojson.feature(topology, topology.objects.«topologyObject»).features) |
| .enter().append("path") |
| .attr("class", function(d) { return "«countryName» unit " + d.id; }) |
| .attr("d", path); |
| // To create the '«topologyObject = "states"» of a country' |
| «ELSE» |
| // To create the countries of the '«topologyObject = "world"»' |
| «topology.partition = true» |
| «ENDIF» |
| «IF topology.partition» |
| cxD3«countryNameUpper»TopoJsHTMLRootComponentG.selectAll("path") |
| .data(topojson.feature(topology, topology.objects.«topologyObject»).features) |
| .enter().append("path") |
| .attr("class", "«countryName»") |
| .attr("d", path); |
| cxD3«countryNameUpper»TopoJsHTMLRootComponentG.selectAll("path").on("click", function click(d) { |
| var data = this.__data__; |
| var id = data.id; |
| if (data.properties.iso_3166_2 != null) { |
| id = data.properties.iso_3166_2; |
| } |
| var name = data.properties.«topology.property.literal»; |
| connector.on«topology.fileName»Click(id, name); |
| }); |
| «ENDIF» |
| |
| «IF topology.places» |
| // To create the cities |
| cxD3«countryNameUpper»TopoJsHTMLRootComponentG.selectAll(".place-label") |
| .data(topojson.feature(topology, topology.objects.places).features) |
| .enter().append("text") |
| .attr("class", "place-label") |
| .attr("transform", function(d) { |
| return "translate(" + projection(d.geometry.coordinates)+")";}) |
| .attr("dy", ".35em") |
| .text(function(d) { return d.properties.name; |
| }); |
| // To create the city dots |
| cxD3«countryNameUpper»TopoJsHTMLRootComponentG.append("path") |
| .datum(topojson.feature(topology, topology.objects.places)) |
| .attr("d", path) |
| .attr("class", "place"); |
| // sends the city labels to Server |
| cxD3«countryNameUpper»TopoJsHTMLRootComponentG.selectAll("text.place-label").on("click", function click(d) { |
| var data = this.__data__; |
| var id = data.id; |
| var name = data.properties.«topology.property.literal»; |
| connector.on«topology.fileName»Click(id, name); |
| }); |
| «ENDIF» |
| |
| «IF topology.zoomable» |
| cxD3«countryNameUpper»TopoJsHTMLRootComponentSvg.call(zoom).call(zoom.event); |
| «ENDIF» |
| }; |
| jsonTreeFunction(JSON.parse(this.getState().jsonData)); |
| } |
| ''') |
| } |
| |
| def generateProjection(Topology topology) ''' |
| var projection = d3.geo«topology.projection.literal.toFirstUpper»() |
| «IF topology.hasRotation».rotate([«topology.rotate_x», «topology.rotate_y»])«ENDIF» |
| «IF topology.hasCentering».center([«topology.center_x», «topology.center_y»])«ENDIF» |
| «IF topology.hasScaling».scale(scale*«topology.scale»)«ELSE».scale(scale)«ENDIF» |
| «IF topology.hasTranslation».translate([«topology.translate_x», «topology.translate_y»])«ELSE».translate([width / 2, height / 2])«ENDIF»; |
| ''' |
| } |