blob: eefa64ddb786c33fecbaa36ca11b04c0fd1bdf70 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="https://cdn.metroui.org.ua/v4/css/metro-all.min.css">
<link rel="stylesheet" href="custom.css">
<script>
function buttonHtml(icon, hint) {
return "<span class='mif-" + icon + "' data-role='hint' data-hint-text='" + hint + "' data-hint-position='bottom'></span>";
}
var programPanelButtons = [{
html: buttonHtml("help", "EOL language reference"),
cls: "sys-button",
onclick: "window.open('https://www.eclipse.org/epsilon/doc/eol');"
},{
html: buttonHtml("play", "Run the EOL program"),
cls: "success",
onclick: "runEol()"
}];
var modelPanelButtons = [{
html: buttonHtml("help", "Flexmi language reference"),
cls: "sys-button",
onclick: "window.open('https://www.eclipse.org/epsilon/doc/flexmi');"
},{
html: buttonHtml("refresh", "Render the model diagram"),
cls: "sys-button",
onclick: "refreshModelDiagram()"
},{
html: buttonHtml("tree", "Show/hide the model diagram"),
cls: "sys-button",
onclick: "toggle('modelDiagram', function(){refreshModelDiagram();})"
}];
var metamodelPanelButtons = [{
html: buttonHtml("help", "Emfatic language reference"),
cls: "sys-button",
onclick: "window.open('https://www.eclipse.org/emfatic');"
},{
html: buttonHtml("refresh", "Render the metamodel diagram"),
cls: "sys-button",
onclick: "refreshMetamodelDiagram()"
},{
html: buttonHtml("tree", "Show/hide the metamodel diagram"),
cls: "sys-button",
onclick: "toggle('metamodelDiagram', function(){refreshMetamodelDiagram();})"
}];
var secondModelPanelButtons = [{
html: buttonHtml("help", "Flexmi language reference"),
cls: "sys-button",
onclick: "window.open('https://www.eclipse.org/epsilon/doc/flexmi');"
},{
html: buttonHtml("refresh", "Render the model diagram"),
cls: "sys-button",
onclick: "refreshSecondModelDiagram()"
},{
html: buttonHtml("tree", "Show/hide the model diagram"),
cls: "sys-button",
onclick: "toggle('secondModelDiagram', function(){refreshSecondModelDiagram();})"
}];
var secondMetamodelPanelButtons = [{
html: buttonHtml("help", "Emfatic language reference"),
cls: "sys-button",
onclick: "window.open('https://www.eclipse.org/emfatic');"
},{
html: buttonHtml("refresh", "Render the metamodel diagram"),
cls: "sys-button",
onclick: "refreshSecondMetamodelDiagram()"
},{
html: buttonHtml("tree", "Show/hide the metamodel diagram"),
cls: "sys-button",
onclick: "toggle('secondMetamodelDiagram', function(){refreshSecondMetamodelDiagram();})"
}];
var thirdModelPanelButtons = [];
var consolePanelButtons = [{
html: buttonHtml("cross", "Clear the console"),
cls: "sys-button",
onclick: "consoleEditor.setValue('')"
}];
</script>
</head>
<body class="h-100" onresize="fit()">
<div data-role="navview">
<div class="navview-pane">
<button class="pull-button">
<span class="default-icon-menu"></span>
</button>
<ul class="navview-menu">
<li class="item-header">Epsilon Playground</li>
<li>
<a href="#" id="exampleLink">
<span class="icon"><span class="mif-link"></span></span>
<span class="caption">Link to this example</span>
</a>
</li>
</ul>
</div>
<div class="navview-content">
<div id="splitter" data-role="splitter" class="h-100" style="min-height:800px">
<div data-role="splitter" data-split-mode="vertical">
<div id="EOL" data-role="panel" data-title-caption="Program (EOL)" data-title-icon="<span class='mif-apps'></span>" data-custom-buttons="programPanelButtons">
<div class="editor" id="programEditor"></div>
</div>
<div data-role="panel" data-title-caption="Console" data-title-icon="<span class='mif-display'></span>" data-custom-buttons="consolePanelButtons">
<div class="editor" id="console"></div>
</div>
</div>
<div data-role="splitter" data-split-mode="vertical">
<div data-role="panel" data-title-caption="Model (Flexmi)" data-title-icon="<span class='mif-cloud'></span>" data-custom-buttons="modelPanelButtons">
<div data-role="splitter" class="h-100">
<div class="editor" id="flexmiEditor"></div>
<div id="modelDiagram" style="display:none;"></div>
</div>
</div>
<div data-role="panel" data-title-caption="Metamodel (Emfatic)" data-title-icon="<span class='mif-cloud3'></span>" data-custom-buttons="metamodelPanelButtons">
<div data-role="splitter" class="h-100">
<div class="editor" id="emfaticEditor"></div>
<div id="metamodelDiagram" style="display:none;"></div>
</div>
</div>
</div>
<div data-role="splitter" data-split-mode="vertical" id="secondModelSplitter">
<div id="secondModelPanel" data-role="panel" data-title-caption="Second Model (Flexmi)" data-title-icon="<span class='mif-cloud'></span>" data-custom-buttons="secondModelPanelButtons">
<div data-role="splitter" class="h-100">
<div class="editor" id="secondFlexmiEditor"></div>
<div id="secondModelDiagram" style="display:none;"></div>
</div>
</div>
<div id="secondMetamodelPanel" data-role="panel" data-title-caption="Second Metamodel (Emfatic)" data-title-icon="<span class='mif-cloud3'></span>" data-custom-buttons="secondMetamodelPanelButtons">
<div data-role="splitter" class="h-100">
<div class="editor" id="secondEmfaticEditor"></div>
<div id="secondMetamodelDiagram" style="display:none;"></div>
</div>
</div>
</div>
<div data-role="splitter" data-split-mode="vertical" id="thirdModelSplitter">
<div data-role="panel" data-title-caption="Model (Flexmi)" data-title-icon="<span class='mif-cloud'></span>" data-custom-buttons="thirdModelPanelButtons">
<div id="thirdModelDiagram" style="display:none;"></div>
</div>
</div>
</div>
</div>
</div>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
<script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>
<script src="https://cdn.metroui.org.ua/v4/js/metro.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="eol.js" type="text/javascript"></script>
<script src="emfatic.js" type="text/javascript"></script>
<script>
var language = "eol";
Array.from(document.querySelectorAll('.editor')).forEach(function(e) {
var editor = ace.edit(e);
editor.setTheme("ace/theme/eclipse");
editor.renderer.setShowGutter(false);
editor.setFontSize("1rem");
});
var programEditor = ace.edit(document.getElementById('programEditor'));
var flexmiEditor = ace.edit(document.getElementById('flexmiEditor'));
var emfaticEditor = ace.edit(document.getElementById('emfaticEditor'));
var secondFlexmiEditor = ace.edit(document.getElementById('secondFlexmiEditor'));
var secondEmfaticEditor = ace.edit(document.getElementById('secondEmfaticEditor'));
var consoleEditor = ace.edit(document.getElementById('console'));
var editors = [programEditor, flexmiEditor, emfaticEditor, secondFlexmiEditor, secondEmfaticEditor, consoleEditor];
editors.forEach(e => e.setShowPrintMargin(false));
emfaticEditor.getSession().setMode("ace/mode/emfatic");
flexmiEditor.getSession().setMode("ace/mode/xml");
secondEmfaticEditor.getSession().setMode("ace/mode/emfatic");
secondFlexmiEditor.getSession().setMode("ace/mode/xml");
consoleEditor.setReadOnly(true);
editors.forEach(e => e.getSession().on('change', function() { updateExampleLink(); }));
var url = window.location + "";
var questionMark = url.indexOf("?");
var content = "eyJlb2wiOiIvLyBGb3IgZXZlcnkgdGFzayBpbiB0aGUgbW9kZWxcbmZvciAodCBpbiBUYXNrLmFsbCkge1xuICAgIC8vIFByaW50IHRoZSB0aXRsZSBhbmQgdGhlIHRvdGFsIHBlcnNvbi1tb250aHMgb2YgdGhlIHRhc2tcbiAgICAodC50aXRsZSArIFwiOiBcIiArIHQuZ2V0VG90YWxFZmZvcnQoKSkucHJpbnRsbigpO1xufVxuXG4vLyBDb3VudCB0aGUgdGFza3MgdGhhdCBhcmUgdW5kZXJ0YWtlbiBieSBhIHNpbmdsZSBwZXJzb25cblRhc2suYWxsLnNlbGVjdCh0fHQuZWZmb3J0LnNpemUoKSA9IDEpLnNpemUoKS5cbiAgICBwcmludGxuKFwiT25lLXBlcnNvbiB0YXNrczogXCIpO1xuXG4vLyBSZXR1cm5zIHRoZSB0b3RhbCBwZXJzb24tbW9udGhzIGZvciBhIHRhc2tcbm9wZXJhdGlvbiBUYXNrIGdldFRvdGFsRWZmb3J0KCkge1xuICAgIHJldHVybiBzZWxmLmVmZm9ydC5jb2xsZWN0KGV8c2VsZi5kdXJhdGlvbiplLnBlcmNlbnRhZ2UvMTAwLjApLnN1bSgpO1xufSIsImVtZmF0aWMiOiJAbmFtZXNwYWNlKHVyaT1cInBzbFwiLCBwcmVmaXg9XCJcIilcbnBhY2thZ2UgcHNsO1xuXG5jbGFzcyBQcm9qZWN0IHtcbiAgYXR0ciBTdHJpbmcgbmFtZTtcbiAgYXR0ciBTdHJpbmcgZGVzY3JpcHRpb247XG4gIHZhbCBUYXNrWypdIHRhc2tzO1xuICB2YWwgUGVyc29uWypdIHBlb3BsZTtcbn1cblxuY2xhc3MgVGFzayB7XG4gIGF0dHIgU3RyaW5nIHRpdGxlO1xuICBhdHRyIGludCBzdGFydDtcbiAgYXR0ciBpbnQgZHVyYXRpb247XG4gIHZhbCBFZmZvcnRbKl0gZWZmb3J0O1xufVxuXG5jbGFzcyBQZXJzb24ge1xuICBhdHRyIFN0cmluZyBuYW1lO1xufVxuXG5jbGFzcyBFZmZvcnQge1xuICByZWYgUGVyc29uIHBlcnNvbjtcbiAgYXR0ciBpbnQgcGVyY2VudGFnZSA9IDEwMDtcbn0iLCJmbGV4bWkiOiI8P25zdXJpIHBzbD8+XG48cHJvamVjdCB0aXRsZT1cIkFDTUVcIj5cbiAgPHBlcnNvbiBuYW1lPVwiQWxpY2VcIi8+XG4gIDxwZXJzb24gbmFtZT1cIkJvYlwiLz5cbiAgPHRhc2sgdGl0bGU9XCJBbmFseXNpc1wiIHN0YXJ0PVwiMVwiIGR1cj1cIjNcIj5cbiAgICA8ZWZmb3J0IHBlcnNvbj1cIkFsaWNlXCIvPlxuICA8L3Rhc2s+XG4gIDx0YXNrIHRpdGxlPVwiRGVzaWduXCIgc3RhcnQ9XCI0XCIgZHVyPVwiNlwiPlxuICAgIDxlZmZvcnQgcGVyc29uPVwiQm9iXCIvPlxuICA8L3Rhc2s+XG4gIDx0YXNrIHRpdGxlPVwiSW1wbGVtZW50YXRpb25cIiBzdGFydD1cIjdcIiBkdXI9XCIzXCI+XG4gICAgPGVmZm9ydCBwZXJzb249XCJCb2JcIiBwZXJjPVwiNTBcIi8+XG4gICAgPGVmZm9ydCBwZXJzb249XCJBbGljZVwiIHBlcmM9XCI1MFwiLz5cbiAgPC90YXNrPlxuPC9wcm9qZWN0PlxuIn0=";
if (questionMark > -1) {
content = url.substring(questionMark+1, url.length);
}
var json = JSON.parse(atob(content));
programEditor.getSession().setMode("ace/mode/eol");
programEditor.setValue(json.eol, 1);
flexmiEditor.setValue(json.flexmi, 1);
emfaticEditor.setValue(json.emfatic, 1);
secondFlexmiEditor.setValue(json.secondFlexmi, 1);
secondEmfaticEditor.setValue(json.secondEmfatic, 1);
consoleEditor.setValue("",1);
//document.getElementById("secondModelSplitter").style.display = "none";
//document.getElementById("secondMetamodelDiagram").style.display = "none";
//toggle("secondModelPanel", function(){window.alert();});
setInterval(fit, 100);
function updateExampleLink() {
document.getElementById('exampleLink').href = "?" + btoa(editorsToJson());
}
function editorsToJson() {
return JSON.stringify(
{
"eol": programEditor.getValue(),
"emfatic": emfaticEditor.getValue(),
"flexmi": flexmiEditor.getValue(),
"secondEmfatic": secondEmfaticEditor.getValue(),
"secondFlexmi": secondFlexmiEditor.getValue()
}
);
}
function fit() {
document.getElementById("splitter").style.minHeight = window.innerHeight + "px";
var editorParentStyle = "flex-basis: calc(100% - 4px);";
document.getElementById("programEditor").parentNode.style = editorParentStyle;
document.getElementById("console").parentNode.style = editorParentStyle;
document.getElementById("flexmiEditor").parentNode.parentNode.style = editorParentStyle + ";padding:0px";
document.getElementById("emfaticEditor").parentNode.parentNode.style = editorParentStyle + ";padding:0px";
document.getElementById("secondFlexmiEditor").parentNode.parentNode.style = editorParentStyle + ";padding:0px";
document.getElementById("secondEmfaticEditor").parentNode.parentNode.style = editorParentStyle + ";padding:0px";
editors.forEach(e => e.resize());
}
function runEol() {
var xhr = new XMLHttpRequest();
var url = "https://europe-west2-epsilon-live-gcp.cloudfunctions.net/run-eol";
//var url = "http://localhost:8080";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
consoleEditor.setValue(json.output, 1);
}
Metro.notify.killAll();
}
};
var data = editorsToJson();
xhr.send(data);
Metro.notify.create("Executing program...", null, {keepOpen: true, cls: "yellow"});
}
function refreshModelDiagram() {
refreshDiagram("https://europe-west2-epsilon-live-gcp.cloudfunctions.net/flexmi-to-graphviz",
"modelDiagram", "model", "dot");
}
function refreshMetamodelDiagram() {
refreshDiagram("https://europe-west2-epsilon-live-gcp.cloudfunctions.net/emfatic-to-graphviz",
"metamodelDiagram", "metamodel", "fdp");
}
function refreshSecondModelDiagram() {
refreshDiagram("https://europe-west2-epsilon-live-gcp.cloudfunctions.net/flexmi-to-graphviz",
"secondModelDiagram", "model", "dot");
}
function refreshSecondMetamodelDiagram() {
refreshDiagram("https://europe-west2-epsilon-live-gcp.cloudfunctions.net/emfatic-to-graphviz",
"secondMetamodelDiagram", "metamodel", "fdp");
}
function toggle(elementId, onEmpty) {
var element = document.getElementById(elementId);
if (element.style.display == "none") {
element.style.display = "block";
if (element.innerHTML.length == 0) {
onEmpty();
}
}
else element.style.display = "none";
}
function refreshDiagram(url, diagramId, diagramName, engine) {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
var t = d3.transition()
.ease(d3.easeLinear);
d3.select("#" + diagramId).graphviz({fit: true, height: "100%", width:"100%", engine: engine})
.transition(t)
.renderDot(json[diagramId]);
Metro.notify.killAll();
}
}
};
var data = editorsToJson();
xhr.send(data);
Metro.notify.create("Rendering " + diagramName + " diagram...", null, {keepOpen: true, cls: "yellow"});
}
</script>
</body>
</html>