1
|
import io.FileWorker;
|
2
|
import javafx.concurrent.Worker;
|
3
|
import javafx.scene.effect.BlendMode;
|
4
|
import javafx.scene.input.Clipboard;
|
5
|
import javafx.scene.input.ClipboardContent;
|
6
|
import javafx.scene.input.DataFormat;
|
7
|
import javafx.scene.input.KeyCode;
|
8
|
import javafx.scene.web.WebEngine;
|
9
|
import javafx.scene.web.WebView;
|
10
|
import netscape.javascript.JSObject;
|
11
|
|
12
|
/**
|
13
|
* An instance of this class represents the editor element in the GUI.
|
14
|
*/
|
15
|
public class Editor {
|
16
|
|
17
|
/**
|
18
|
* Default editor mode. The best are Zeek and Javascript (when using this
|
19
|
* deserializer).
|
20
|
*/
|
21
|
public static final String DEFAULT_MODE = "javascript";
|
22
|
|
23
|
/**
|
24
|
* Default editor theme. The best is eclipse (when using this deserializer).
|
25
|
*/
|
26
|
public static final String DEFAULT_THEME = "eclipse";
|
27
|
|
28
|
/**
|
29
|
* A read-only text area that displays the resulting JSON.
|
30
|
*/
|
31
|
private WebView view;
|
32
|
|
33
|
/**
|
34
|
* WebView engine.
|
35
|
*/
|
36
|
private WebEngine engine;
|
37
|
|
38
|
/**
|
39
|
* ACE editor instance in the web page.
|
40
|
*/
|
41
|
private JSObject editor;
|
42
|
|
43
|
/**
|
44
|
* Session of the ACE editor. It is used for other settings that cannot be
|
45
|
* specified in the editor.
|
46
|
*/
|
47
|
private JSObject session;
|
48
|
|
49
|
/**
|
50
|
* Resulting JSON.
|
51
|
*/
|
52
|
private String json;
|
53
|
|
54
|
/**
|
55
|
* WebView and WebEngine initialization.
|
56
|
*/
|
57
|
public Editor() {
|
58
|
view = new WebView();
|
59
|
view.setPrefHeight(400);
|
60
|
view.setBlendMode(BlendMode.DARKEN); // for "transparent" background.
|
61
|
view.setContextMenuEnabled(false);
|
62
|
view.setOnKeyReleased(event -> { // copy does not work by default => text to clipboard.
|
63
|
if (event.isControlDown() && event.getCode() == KeyCode.C) {
|
64
|
String copy = (String) editor.call("getSelectedText");
|
65
|
if (copy != null) {
|
66
|
ClipboardContent content = new ClipboardContent();
|
67
|
content.put(DataFormat.PLAIN_TEXT, copy);
|
68
|
Clipboard.getSystemClipboard().setContent(content);
|
69
|
}
|
70
|
}
|
71
|
});
|
72
|
|
73
|
engine = view.getEngine();
|
74
|
engine.loadContent(getBasicHTML()); // load page.
|
75
|
engine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
|
76
|
if (newValue == Worker.State.SUCCEEDED) {
|
77
|
JSObject ace = (JSObject) engine.executeScript("ace");
|
78
|
editor = (JSObject) ace.call("edit", "editor");
|
79
|
session = (JSObject) editor.call("getSession");
|
80
|
|
81
|
editor.call("setScrollSpeed", ".1"); // slower scrolling.
|
82
|
session.call("setUseWorker", false); // disable content checking.
|
83
|
editor.call("setReadOnly", true);
|
84
|
|
85
|
setMode(DEFAULT_MODE);
|
86
|
setTheme(DEFAULT_THEME);
|
87
|
}
|
88
|
});
|
89
|
}
|
90
|
|
91
|
/**
|
92
|
* Sets a new mode in the editor.
|
93
|
*
|
94
|
* @param mode new editor mode.
|
95
|
*/
|
96
|
public void setMode(String mode) {
|
97
|
session.call("setMode", "ace/mode/" + mode);
|
98
|
}
|
99
|
|
100
|
/**
|
101
|
* Sets a new theme in the editor.
|
102
|
*
|
103
|
* @param theme new editor theme.
|
104
|
*/
|
105
|
public void setTheme(String theme) {
|
106
|
editor.call("setTheme", "ace/theme/" + theme);
|
107
|
}
|
108
|
|
109
|
/**
|
110
|
* @return the using instance of the WebView.
|
111
|
*/
|
112
|
public WebView getView() {
|
113
|
return view;
|
114
|
}
|
115
|
|
116
|
/**
|
117
|
* @return the text displayed in the editor.
|
118
|
*/
|
119
|
public String getJson() {
|
120
|
return json;
|
121
|
}
|
122
|
|
123
|
/**
|
124
|
* Replaces the editor content.
|
125
|
*
|
126
|
* @param json new content.
|
127
|
*/
|
128
|
public void setContent(String json) {
|
129
|
this.json = json;
|
130
|
editor.call("setValue", "");
|
131
|
editor.call("insert", json);
|
132
|
}
|
133
|
|
134
|
/**
|
135
|
* @return basic HTML page with ACE for WebView engine.
|
136
|
*/
|
137
|
private String getBasicHTML() {
|
138
|
return "<!DOCTYPE html>"
|
139
|
+ "<html>"
|
140
|
+ " <head>"
|
141
|
+ " <style type=\"text/css\">"
|
142
|
+ " #editor {"
|
143
|
+ " margin: 0;"
|
144
|
+ " position: absolute;"
|
145
|
+ " top: 0;"
|
146
|
+ " bottom: 0;"
|
147
|
+ " left: 0;"
|
148
|
+ " right: 0;"
|
149
|
+ " }"
|
150
|
+ " </style>"
|
151
|
+ " </head>"
|
152
|
+ " <body>"
|
153
|
+ " <div id=\"editor\"></div>"
|
154
|
+ " <script src=\"" + FileWorker.getResource("/ace/ace.js") + "\"></script>"
|
155
|
+ " </body>"
|
156
|
+ "</html>";
|
157
|
}
|
158
|
|
159
|
/**
|
160
|
* Converts classic text with HTML tags to the correct HTML (critical characters
|
161
|
* replaced by HTML entities). For insertion to JS. IT IS NO LONGER USED - only
|
162
|
* for "NICE TO HAVE".
|
163
|
*
|
164
|
* @param str text that is half plain text ('\n', '\t', etc.) and half html.
|
165
|
*
|
166
|
* @return correct HTML with HTML entities.
|
167
|
*/
|
168
|
@SuppressWarnings(value = { "unused" })
|
169
|
private String escape(String str) {
|
170
|
StringBuilder builder = new StringBuilder();
|
171
|
char strArray[] = str.toCharArray();
|
172
|
for (int i = 0; i < strArray.length; i++) {
|
173
|
char c = strArray[i];
|
174
|
switch (c) {
|
175
|
case '\'':
|
176
|
builder.append("'");
|
177
|
break;
|
178
|
case '<':
|
179
|
builder.append("<");
|
180
|
break;
|
181
|
case '>':
|
182
|
builder.append(">");
|
183
|
break;
|
184
|
case '&':
|
185
|
builder.append("&");
|
186
|
break;
|
187
|
case '"':
|
188
|
builder.append(""");
|
189
|
break;
|
190
|
case '\n':
|
191
|
builder.append("<br/>");
|
192
|
break;
|
193
|
case '\t':
|
194
|
builder.append(" ");
|
195
|
break;
|
196
|
case ' ':
|
197
|
builder.append(" ");
|
198
|
break;
|
199
|
case (char) 13:
|
200
|
break;
|
201
|
default:
|
202
|
if (c < 128) {
|
203
|
builder.append(c);
|
204
|
} else {
|
205
|
builder.append("&#").append((int) c).append(";");
|
206
|
}
|
207
|
}
|
208
|
}
|
209
|
return builder.toString();
|
210
|
}
|
211
|
|
212
|
}
|