blob: 04728d0dd9bbb5fbf6a701fcf7373c8cc2b5c1d8 [file] [log] [blame]
/**
*
* 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»;
'''
}