| <!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> |