Developing A Script Console¶
Introduction¶
The following example shows how QML was used to prototype a simple JavaScript console.
The resulting tool can be used to experiment with scripting in SEQUOIA.
It can also be extended further with more advanced features.
The Full Code¶
Here is the source code of the script:
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.3
import QtQuick.Layouts 1.0
import Thinkbox.Sequoia.Nodes 1.0
import Thinkbox.Sequoia.Documents 1.0
import Thinkbox.Sequoia.Conversion 1.0
Rectangle {
width: 600
height: 400
color: "#41485B"
property string consoleEchoString: "//Welcome to the Sequoia JavaScript Console!\n//Please type your code in the bottom pane, then press EVALUATE...\n"
GroupBox {
anchors.fill: parent
ColumnLayout {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
Button {
id: clearEchoButton
Layout.fillWidth: true
text: "CLEAR Console Echo..."
onClicked: {
consoleEchoString = consoleOutputArea.text = ""
}
enabled: true
}
TextArea {
id: consoleOutputArea
height:100
text: consoleEchoString
Layout.fillWidth: true
style: TextAreaStyle {
backgroundColor: "#2D374D"
selectionColor: "#578ED6"
textColor: "#FFFFFF"
}
readOnly : true
}
Button {
id: evaluateScriptButton
Layout.fillWidth: true
text: "EVALUATE Console Script:"
onClicked: {
var stringToEval = consoleTextArea.text
stringToEval = stringToEval.replace(/LOG/, "console.log")
stringToEval = stringToEval.replace(/GNP/, "NodeControl.getNodeProperty")
stringToEval = stringToEval.replace(/SNP/, "NodeControl.setNodeProperty")
stringToEval = stringToEval.replace(/NC/, "NodeCreation")
stringToEval = stringToEval.replace(/CPL/, "NodeCreation.createPointLoader")
stringToEval = stringToEval.replace(/CROI/, "NodeCreation.createPointROI")
stringToEval = stringToEval.replace(/CMK/, "NodeCreation.createMarker")
stringToEval = stringToEval.replace(/CML/, "NodeCreation.createMeshLoader")
stringToEval = stringToEval.replace(/CM/, "NodeCreation.createMesher")
stringToEval = stringToEval.replace(/CIP/, "NodeCreation.createImageProjection")
stringToEval = stringToEval.replace(/CSP/, "NodeCreation.createPointSurface")
stringToEval = stringToEval.replace(/DC/, "DocumentControl")
stringToEval = stringToEval.replace(/GCD/, "DocumentControl.getCurrentDocument")
eval (stringToEval)
consoleEchoString += stringToEval + "\n\n"
consoleTextArea.text = ""
consoleOutputArea.text = consoleEchoString
}
}
TextArea {
id: consoleTextArea
height:100
text: ""
Layout.fillWidth: true
Layout.fillHeight: true
style: TextAreaStyle {
backgroundColor: "#2D2D37"
selectionColor: "#578ED6"
textColor: "#FFFFFF"
}
}
}
}
}
Step By Step¶
Now let’s look at the various code blocks of this script.
Importing QML Modules¶
For the design and setup of the Qt User Interface, we will need to import the modules for
QML itself
QML Controls
QML Control Styles
QML Layouts
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.3
import QtQuick.Layouts 1.0
Importing Thinkbox Sequoia Module¶
To be able to access Sequoia-related methods, we need to also import all Sequoia modules:
import Thinkbox.Sequoia.Nodes 1.0
import Thinkbox.Sequoia.Documents 1.0
import Thinkbox.Sequoia.Conversion 1.0
Dialog Frame¶
We define the dialog as a rectangle of 600x400 pixels.
We set the color to the default SEQUOIA dark gray-blue color.
We define a string property called consoleEchoString - it will be used to store the content of the top pane:
Rectangle {
width: 600
height: 400
color: "#41485B"
property string consoleEchoString: "//Welcome to the Sequoia JavaScript Console!\n//Please type your code in the bottom pane, then press EVALUATE...\n"
Group Box¶
Inside the dialog, we will define a group box filling the Rectangle.
Then we create a column layout - it will be achored on all 4 sides to the Rectangle and thus resize with it.
A column layout creates a column with rows of controls stacked vertically:
GroupBox {
anchors.fill: parent
ColumnLayout {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
Clear Console Echo Button¶
We define a button with id clearEchoButton which will be used to clear the top pane when pressed.
The button wlll have the width of the group box.
Its caption will be “CLEAR Console Echo…”
When clicked, it will simply set the property consoleEchoString of the Rectangle, as well as the text area object representing the top pane, to an empty string.
Button {
id: clearEchoButton
Layout.fillWidth: true
text: "CLEAR Console Echo..."
onClicked: {
consoleEchoString = consoleOutputArea.text = ""
}
enabled: true
}
Echo Pane¶
Next we define a text area control with id consoleOutputArea.
This control will be read-only and will show the consoleEchoString property we defined in the beginning as the script.
The height of the control is 100 pixels, and the width will fit the width of the parent control.
The style sets the background, selection and text colors to match the typical SEQUOIA UI scheme.
TextArea {
id: consoleOutputArea
height:100
text: consoleEchoString
Layout.fillWidth: true
style: TextAreaStyle {
backgroundColor: "#2D374D"
selectionColor: "#578ED6"
textColor: "#FFFFFF"
}
readOnly : true
}
EVALUATE Console Script button¶
This is the button that will execute the script entered in the bottom pane.
It will have the id evaluateScriptButton and will fit the width of its parent.
Button {
id: evaluateScriptButton
Layout.fillWidth: true
text: "EVALUATE Console Script:"
The Evaluate Button Clicked Event¶
Now let’s look at the code that should be executed when the button is pressed.
The event contains JavaScript code that
Takes the text entered in the bottom pane,
Filters it to expand some “macros”,
Evaluates it,
Appends it to consoleEchoString property where all previous scripts are preserved
Resets the bottom pane
Updates the top pane with the new consoleEchoString content.
Most SEQUOIA methods are pretty long and require a lot of typing.
For example, DocumentControl.getCurrentDocument needs to be entered each time you want to know what Document is active.
To reduce the amount of code to be typed in the bottom pane, the console implements a few custom “macros” that expand to full functions.
For example, typing just GCD() results in DocumentControl.getCurrentDocument() executing and appearing in the Echo top pane!
The multiple replace calls below make sure often used methods have fast-to-enter and easy-to-remember two or three-letter macros.
onClicked: {
var stringToEval = consoleTextArea.text
stringToEval = stringToEval.replace(/LOG/, "console.log")
stringToEval = stringToEval.replace(/GNP/, "NodeControl.getNodeProperty")
stringToEval = stringToEval.replace(/SNP/, "NodeControl.setNodeProperty")
stringToEval = stringToEval.replace(/NC/, "NodeCreation")
stringToEval = stringToEval.replace(/CPL/, "NodeCreation.createPointLoader")
stringToEval = stringToEval.replace(/CROI/, "NodeCreation.createPointROI")
stringToEval = stringToEval.replace(/CMK/, "NodeCreation.createMarker")
stringToEval = stringToEval.replace(/CML/, "NodeCreation.createMeshLoader")
stringToEval = stringToEval.replace(/CM/, "NodeCreation.createMesher")
stringToEval = stringToEval.replace(/CIP/, "NodeCreation.createImageProjection")
stringToEval = stringToEval.replace(/CSP/, "NodeCreation.createPointSurface")
stringToEval = stringToEval.replace(/DC/, "DocumentControl")
stringToEval = stringToEval.replace(/GCD/, "DocumentControl.getCurrentDocument")
eval (stringToEval)
consoleEchoString += stringToEval + "\n\n"
consoleTextArea.text = ""
consoleOutputArea.text = consoleEchoString
}
}
Bottom Pane¶
The last
TextArea {
id: consoleTextArea
height:100
text: ""
Layout.fillWidth: true
Layout.fillHeight: true
style: TextAreaStyle {
backgroundColor: "#2D2D37"
selectionColor: "#578ED6"
textColor: "#FFFFFF"
}
}
The braces below just close the scopes of the column layout, group box, and Rectangle:
}
}
}