Skip to content

Instantly share code, notes, and snippets.

@ThomasRohde
Last active July 23, 2023 10:41
Show Gist options
  • Save ThomasRohde/2287bb69346283f89e963d429d1d9195 to your computer and use it in GitHub Desktop.
Save ThomasRohde/2287bb69346283f89e963d429d1d9195 to your computer and use it in GitHub Desktop.
Form library for #Archi, #JArchi, #Archimatetool
/*
Author: Thomas Klok Rohde, Danske Bank A/S
Description: Example usage of show_form.js - Insert chart JSON into property field.
Dependencies: https://github.com/jsonform/jsonform
History:
October 11, 2022 : Created with base set of scripts
*/
console.show();
console.clear();
load(__DIR__ + "lib/show_form.js");
let note = $(selection).filter("diagram-model-note").first();
if (note == undefined)
throw new Error("No note selected");
// Get a list of all defined properties in the model
let props = new Set();
$("*").not("folder").each(o => {
o.prop().forEach(p => {
if (p.length) props.add(p);
})
})
let guide = "-- Choose a property --";
let properties = Array.from(props);
properties.unshift(guide);
let formSchema = {
"title": {
"type": "string",
"title": "Chart title",
"description": "Enter a title for the chart",
"required": true
},
"chart": {
"type": "string",
"title": "Chart",
"enum": ["chartArchiDistribution", "chartPropertyTable", "chartTIME", "chartTreemap", "chartGauges"],
"description": "Select a chart",
"required": true
},
"distribution": {
"type": "object",
"title": "Element distribution",
"properties": {
"type": {
"type": "string",
"title": "Type",
"enum": ["bar", "lines"]
}
}
},
"treemap": {
"type": "object",
"title": "Treemap",
"properties": {
"property": {
"type": "string",
"title": "Property",
"enum": properties
},
"type": {
"type": "string",
"title": "Type",
"enum": ["treemap", "sunburst"]
},
"level": {
"type": "integer",
"title": "Level",
"minimum": 1,
"maximum": 6
}
}
},
"gauge": {
"type": "object",
"title": "Gauge",
"properties": {
"property": {
"type": "string",
"title": "Property",
"enum": properties
},
"type": {
"type": "string",
"title": "Type",
"enum": ["bullet", "gauge"]
},
"min": {
"type": "integer",
"title": "Minimum",
},
"max": {
"type": "integer",
"title": "Maximum",
}
}
},
"filter": {
"type": "string",
"title": "Javascript filter",
"description": "Enter javascript expression - name, type and obj are available for evaluation"
},
"na": {
"type": "string",
"title": "Not available"
}
};
let formLayout = [
{
"key": "title",
"type": "text"
},
{
"key": "filter",
"type": "text"
},
{
"key": "chart",
"type": "selectfieldset",
"titleMap": {
"chartArchiDistribution": "Element distribution",
"chartPropertyTable": "Properties",
"chartTIME": "TIME",
"chartTreemap": "Treemap",
"chartGauges": "Gauges"
},
"items": [
{
"key": "distribution.type",
"type": "select",
"titleMap": {
"bar": "Bar",
"lines": "Lines"
}
},
{
"type": "hidden",
"key": "na"
},
{
"type": "hidden",
"key": "na"
},
{
"type": "section",
"title": "Treemap chart type",
"items": [
{
"key": "treemap.property",
"type": "select"
},
{
"key": "treemap.type",
"type": "select",
"titleMap": {
"treemap": "Treemap",
"sunburst": "Sunburst"
}
},
{
"key": "treemap.level",
"type": "range",
"step": 1,
"indicator": true
}
]
},
{
"type": "section",
"title": "Gauge chart type",
"items": [
{
"key": "gauge.property",
"type": "select"
},
{
"key": "gauge.type",
"type": "select",
"titleMap": {
"bullet": "Bullet",
"gauge": "Gauge"
}
},
{
"key": "gauge.min",
"type": "text",
},
{
"key": "gauge.max",
"type": "text",
}
]
}]
}
];
let value = showForm(formSchema, formLayout, JSON.parse(note.prop("Chart")), 800, 1200);
if (value) {
if (value.treemap && value.treemap.property == guide) value.treemap.property = null;
note.prop("Chart", JSON.stringify(value));
load(__DIR__ + "Refresh chart.ajs");
}
/*
Author: Thomas Klok Rohde, Danske Bank A/S
Description: Display form and return data
Dependencies: https://github.com/jsonform/jsonform
Usage: Download dependencies for JSONform from Github, and place this script and the dependencies in your __DIR__/lib directory.
History:
October 11, 2022 : Created with base set of scripts
*/
function showForm(formSchema, formLayout = [ "*" ], defaultValue = null, width = 1200, height = 900) {
const SWT = Java.type('org.eclipse.swt.SWT');
const FillLayout = Java.type('org.eclipse.swt.layout.FillLayout');
const Shell = Java.type('org.eclipse.swt.widgets.Shell');
const Browser = Java.type('org.eclipse.swt.browser.Browser');
const ProgressAdapter = Java.extend(Java.type('org.eclipse.swt.browser.ProgressAdapter'));
const LocationAdapter = Java.extend(Java.type('org.eclipse.swt.browser.LocationAdapter'));
const CustomFunction = Java.extend(Java.type('org.eclipse.swt.browser.BrowserFunction'));
const IArchiImages = Java.type('com.archimatetool.editor.ui.IArchiImages');
const ImageFactory = Java.type('com.archimatetool.editor.ui.ImageFactory');
const Rectangle = Java.type('org.eclipse.swt.graphics.Rectangle');
const Monitor = Java.type('org.eclipse.swt.widgets.Monitor');
let display = shell.getDisplay();
let newShell = new Shell(display, SWT.MODAL | SWT.TITLE | SWT.ON_TOP);
newShell.setText("Insert chart");
newShell.setLayout(new FillLayout());
let insertValue = (defaultValue) ? `"value": ${JSON.stringify(defaultValue, null, 1)},` : "";
let html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Getting started with JSON Form</title>
<link rel="stylesheet" style="text/css" href="${__DIR__ + "bootstrap.css"}" />
<style>
body {
margin: 8px
}
.jsonform-required > label:after {
content: ' *';
color: red;
}
</style>
</head>
<body>
<form></form>
<script type="text/javascript" src="${__DIR__ + "jquery.min.js"}"></script>
<script type="text/javascript" src="${__DIR__ + "underscore.js"}"></script>
<script type="text/javascript" src="${__DIR__ + "jsv.js"}"></script>
<script type="text/javascript" src="${__DIR__ + "jsonform.js"}"></script>
<script type="text/javascript">
let formLayout = ${JSON.stringify(formLayout, null, 1)};
formLayout.unshift({
"type": "help",
"helpvalue": "Select a chart type, and then click on <em>Insert</em> to insert the chart into the selected view."
});
formLayout.unshift({
"type": "button",
"title": "Cancel",
"onClick": function (evt) { evt.preventDefault(); cancelPressedEvent(); }
});
formLayout.unshift({
"type": "submit",
"title": "Insert",
});
$('form').jsonForm({
"schema": ${JSON.stringify(formSchema, null, 1)},
"form": formLayout,
${insertValue}
"onSubmitValid": function (value) {
insertPressedEvent(JSON.stringify(value));
}
});
</script>
</body>
</html>`;
var insertPressed = false;
var cancelPressed = false;
let browser = new Browser(newShell, SWT.NONE);
var value;
browser.addProgressListener(new ProgressAdapter({
completed: function (event) {
let fncOk = new CustomFunction(browser, "insertPressedEvent", {
function: function (args) {
value = args[0];
insertPressed = true;
}
});
let fncCancel = new CustomFunction(browser, "cancelPressedEvent", {
function: function (args) {
cancelPressed = true;
}
});
browser.addLocationListener(new LocationAdapter({
changed: function (e) {
browser.removeLocationListener(this);
fncOk.dispose();
fncCancel.dispose();
}
}));
}
}));
// Write the HTML to a temporary file, so we are allowed to execute a local script
let System = Java.type('java.lang.System');
let tmpfile = System.getProperty("java.io.tmpdir") + "form.html";
$.fs.writeFile(tmpfile, html);
browser.setUrl("file:///" + tmpfile);
// Set icon to Archi icon, in case shell has a style which displays icons
newShell.setImage(IArchiImages.ImageFactory.getImage(IArchiImages.ICON_APP));
newShell.setSize(width, height);
// Center dialog on screen
const primary = display.getPrimaryMonitor();
const bounds = primary.getBounds();
const rect = newShell.getBounds();
const x = bounds.x + (bounds.width - rect.width) / 2;
const y = bounds.y + (bounds.height - rect.height) / 2;
newShell.setLocation(x, y);
newShell.open();
while (!newShell.isDisposed() && !insertPressed && !cancelPressed) {
if (!display.readAndDispatch()) display.sleep();
}
if (insertPressed && value != undefined && value != null) {
newShell.dispose();
}
else if (cancelPressed) {
console.log('Dialog cancelled.');
newShell.dispose();
}
if (value) return JSON.parse(value);
else return null;
}
@trischbeck
Copy link

Thomas, this looks very interesting - thanks for sharing!

Could you help me a little in how to use your script? The dialog box to insert the chart appears - however, the "Insert" button itself is greyed out. What values would I need to enter so as to show the distributino of ArchiMate types for the overall model?

Kind regards, Thomas (yes, also :-))

@ThomasRohde
Copy link
Author

Write a title for the chart (more than 5 characters long) and press TAB. The Insert button should become enabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment