IDE Customization Guide
User Manual:
Open the PDF directly: View PDF
.
Page Count: 38
| Download | |
| Open PDF In Browser | View PDF |
OMNeT++
IDE Customization Guide
Version 5.0
Copyright © 2016 András Varga and OpenSim Ltd.
1. Writing Wizards .................................................................................................. 1
Motivation ....................................................................................................... 1
Overview ......................................................................................................... 2
Template Processing ............................................................................... 3
Defining the GUI ..................................................................................... 3
Using the IDE ................................................................................................. 3
Editing XSWT Files ................................................................................. 3
Editing Template Files ............................................................................ 4
Writing an Example Wizard ............................................................................ 4
Configuring the Wizard ........................................................................... 4
Creating a New Wizard Page ................................................................... 5
Creating Templated Files ........................................................................ 6
Wizard Types .................................................................................................. 7
New Project Wizards ............................................................................... 7
New Simulation Wizards ......................................................................... 8
New INI, MSG or NED File Wizards ........................................................ 9
New Simple Module Wizard .................................................................. 10
Import Wizards ..................................................................................... 10
Export Wizards ..................................................................................... 10
New Wizard Wizard ............................................................................... 11
Configuration Keys ........................................................................................ 11
Templates ..................................................................................................... 12
Generating multiple files ....................................................................... 13
Conditional file creation ........................................................................ 13
Custom Wizard Pages ................................................................................... 13
XSWT Forms ........................................................................................ 14
Binding of Template Variables to Widgets .............................................. 15
Conditional Pages .................................................................................. 16
Conditional Widgets .............................................................................. 16
Extending the Wizards in Java ..................................................................... 17
Creating Wizard Pages .......................................................................... 17
Creating Custom Widgets ...................................................................... 17
Extending your Template with Custom Classes and Widgets ................. 17
Extending the Template Processing ....................................................... 18
Common Pitfalls ........................................................................................... 18
XSWT Tips and Tricks ................................................................................. 18
Appendix A - Widgets in XSWT .................................................................... 20
Standard SWT widgets ......................................................................... 20
Custom widgets .................................................................................... 21
Appendix B - Predefined Template Variables ................................................. 24
General ................................................................................................. 25
Template information ............................................................................ 25
File name related variables ................................................................... 26
Project name related variables .............................................................. 26
C++ project control ............................................................................. 26
NED files and message files .................................................................. 27
Variables specific to New Simulation wizards ........................................ 27
Variables for New Wizard generation ..................................................... 27
Miscellaneous ........................................................................................ 27
Appendix C - Functions, Classes and Macros available from Templates ......... 28
Custom Macros and Functions ............................................................. 28
Math ...................................................................................................... 29
StringUtils ............................................................................................. 29
WordUtils .............................................................................................. 29
CollectionUtils ....................................................................................... 30
FileUtils ................................................................................................. 30
NedUtils ................................................................................................ 32
IDEUtils ................................................................................................ 33
iii
IDE Customization Guide
LangUtils ............................................................................................... 33
ProcessUtils .......................................................................................... 34
iv
Chapter 1. Writing Wizards
Motivation
The IDE offers several wizards via the File|New menu: New OMNeT++ Project, New
Simple Module, New Compound Module, New Network, New Simulation, New Msg
File, and New Ini File. This chapter describes how a user can add content to these
dialogs to create wizards that are specific to simulation models. These wizards include
a New INET Ad-Hoc Network wizard, a New MiXiM Simulation wizard, an Import INET
Network From CSV File wizard, a New MiXiM Radio Model wizard, and others.
For someone who is writing a model framework which will be available for the general
public, wizards are a great way to educate future users about the simulation model.
While documentation and example simulations are somewhat passive ways of showing
off model features to users, wizards encourage users to experiment with the model and
explore its capabilities. The right set of capable wizards can give users a jump start
by emphasizing learning by doing.
Users can prepare these wizards with little effort and without any Java or C++
programming, and can be distributed with the corresponding model framework (i.e.
INET or MiXiM). When end users import the model framework project into the IDE,
the wizards are automatically added to the corresponding wizard dialogs; the end user
does not need to install them or do anything to deploy the wizards.
To facilitate the creation of wizards, we have also added a New Wizard wizard to the
File|New menu.
Figure 1.1. The New Wizard wizard
1
Writing Wizards
Overview
Custom wizards are read from the templates/ folder of OMNeT++ projects. Wizards
are implemented by mixing a templating engine (for generating the output files) and
a GUI description language (for custom wizard pages to gather user input for the file
generation). Because of the use of a templating engine, we will also refer to custom
wizards as "content templates."
The IDE offers several OMNeT++ related wizard dialogs: New OMNeT++ Project,
New NED File, New Simple Module, and so on. Every content template can contribute
to one or more of those wizard dialogs.
Figure 1.2. The File | New menu
In the templates/ folder, every subfolder that contains a template.properties file
is treated as a content template (other folders are ignored). Every content template
folder may contain several types of files:
• The template.properties file contains general information about the wizard. It
defines the initial value for the template variables and specifies the custom wizard
pages to be shown when the wizard is run.
• *.ftl files are template files that will be copied (without the .ftl extension) into
the target folder after template variable substitution.
• *.xswt files describe custom wizard pages that gather user input.
• *.fti (template include) files are included by *.ftl files. This can be used to factor
out common parts from the template files. The wizard ignores .fti files (i.e. does
not copy them into the new project or folder).
• *.jar files can be used to extend the wizard’s functionality with dynamically loaded
Java code.
• All other files are regarded as files that have to be copied into the target folder
verbatim when the wizard runs. The wizard folder may contain subdirectories which
may also contain files of the above type (except template.properties, of course).
2
Writing Wizards
Template Processing
Template processing uses the FreeMarker library (http://freemarker.org) and all
template syntax supported by FreeMarker can be used. In particular, variable
references of the syntax ${varName} will be replaced with the variable value.
The FreeMarker language also offers constructs that make it a full programming
language: variable assignments, conditionals, loops, switch statement, functions,
macros, expression evaluation, built-in operators, etc., as well as access to fields and
methods of classes defined in Java. This means that any algorithm can be expressed
in the FreeMarker language, and if that is not enough, one can directly access Java
classes using FreeMarker’s Bean Wrapper.
Documentation for the FreeMarker template language can be found at: http://
freemarker.org/docs/index.html
Templates can use several sources for input. They can:
• gather information from the user, using custom wizard pages,
• call any Java code to execute any arbitrarily complex algorithm,
• call external programs, and
• read and write from/to any file on the filesystem
Defining the GUI
Custom wizard pages are defined in XSWT (http://xswt.sourceforge.net). XSWT is
an XML based language that allows the definition of SWT (the widget set used by
Eclipse) widget hierarchies, without the need to write any code in Java. XSWT also
maps widget properties to XML attributes so the visual appearance of the wizard pages
can be easily tweaked. It is also possible to invoke methods on the generated widgets
and use the SWT layout containers, allowing further customizations. Each .xswt file
in the template directory defines a separate wizard page which can be shown either
conditionally or unconditionally.
XSWT documentation and a tutorial can be found at: http://www.coconut-palmsoftware.com/the_new_visual_editor/doku.php?id=xswt:home.
Currently we use XSWT 1.1.2. Newer XSWT versions from http://www.coconut-palmsoftware.com/~xswt/integration/plugins/ did not work well.
Using the IDE
The IDE offers support for editing both .ftl and .xswt files to help create wizard
pages and templates.
Editing XSWT Files
Double-clicking on an XSWT file will open it in the XSWT editor. The editor provides
basic syntax highlighting. An extremely useful feature of the IDE is the XSWT Preview,
where you can preview the form being edited (it updates when you save the file). The
Preview should open automatically when you open the XSWT file; if it does not (or you
close it), you can access it via the Window|Show View… menu item.
3
Writing Wizards
Some (custom) widgets may not appear in the Preview; this is because the Preview does
not load jar files from the projects.
Figure 1.3. Editing an XSWT file
Editing Template Files
The FreeMarker Editor opens when you double-click files with the *.ftl or *.fti
extension. The FreeMarker Editor offers basic syntax highlighting, validation (error
markers appear during editing if the template is not syntactically correct), and basic
content assist. Content assist can help you with directives (<#...> syntax) and built-in
operations (like ?number, ?size, ?default, etc). The content assist popup appears
automatically when you type <# (actually a closing > is also needed for the editor to
recognize the tag), and when you hit ? within a directive or an interpolation (${...}).
Writing an Example Wizard
In the following sections, we will create a simple wizard as an example, which will
support either creating a simulation (complete with NED and INI files), or just a single
NED file with a network defined in it. The user will be able to specify the type and the
number of the submodules the network contains.
Configuring the Wizard
The first step when creating a wizard is to create a new folder under the templates
directory of the project. A file named template.properties must be present in
the newly created directory. This file is used to configure the wizard. Create a
folder a folder named templates/examplewizard under the project, then create
template.properties and add the following lines to it:
templateName = New Test Wizard
templateDescription = Generate an example
templateCategory = Test Wizards
supportedWizardTypes = simulation, network
These lines specify the name, type and category for the wizard. Category is used to
specify how the wizards will be grouped in the tree control section of the template
4
Writing Wizards
selection page. Wizard type specifies in which New … Wizard your wizard will appear.
You can specify one or more of project, simulation, network, etc.; the list of all
possible wizard types will be covered later in this document. In this case, the wizard
will appear in the New Simulation and New Network wizard dialogs.
You can now decide what data you would like to ask the user to provide. Template
variables and their values can be defined as key-value pairs:
nodeType = Dummy
networkSize = 6
The nodeType variable will be used as the submodule type in your network, while the
networkSize defines how many submodules you want in the network.
We define a custom wizard page where the user can specify the values of the above
variables (i.e. override their default value, specified above).
page.1.file = parameters.xswt
page.1.title = Network parameters
We will use the file parameters.xswt to define the layout and the content of the new
wizard page.
There are numerous other configuration keys that can be used in
template.properties. See the "Configuration Keys" section for an exhaustive list of
options.
Creating a New Wizard Page
Files with .xswt extension (Wizard Page definitions) are used to define the UI and add
new wizard pages to gather user input for template generation. In the previous section,
we specified that the file called parameters.xswt will contain the new wizard page
definition. We will add a spinner control to specify the size of our network and a text
control to specify the node type. Create a new file called parameters.xswt with the
following content:
5
Writing Wizards
The above defined wizard page will have two columns. The first column contains
labels and the second contains editable widgets. The x:id="varName" attributes in
the spinner and text control definitions are used to bind a template variable to the
control. When a page is displayed, the content of the bound variables are copied into
the controls. When the user navigates away from the page or presses the Finish button,
the content of the controls are copied back to the bound variables. These variables can
be used in the template files we are about to define in the following section.
To see the list of all available widgets, check the Appendix.
Creating Templated Files
When the template is used, the contents of the template folder (and its subfolders)
will be copied over into the new project, thus preserving the directory structure with
the exception of template.properties (it is also possible to specify other files and
folders to be ignored by specifying a file list for the ignoreResources configuration
key).
When the wizard is being used, a pool of variables is kept by the wizard dialog. These
variables are initialized from the key = value lines in the template.properties
files; they can get displayed and/or edited on custom wizard pages. Eventually, they get
substituted into *.ftl files (using the ${varname} syntax).
Some variables have special meaning and are interpreted by the wizard dialog (e.g. the
nedSrcFolders variable determines which folders get denoted as NED Source Folders
by the New OMNeT++ Project wizard). Variables can be used to generate output file
names, can be used as input file names, and can serve as input and working variables
for arbitrarily complex algorithms programmed in the template (*.ftl) files.
Let us have a quick look at the FreeMarker template language. Variables can be inserted
into the output using the ${varname} syntax. One can also write expressions inside
${..}. For example, ${numServers?number + 1} uses the number built-in operator
to convert the numServers variable to a number, adds one to it, and inserts the result
into the template output. FreeMarker has many other functions (conversion to string,
upper-case version of a string, size of an array, etc.) that work as built-in operators.
Programming facilities can be accessed via directives that have the <#...> syntax.
Use <#if> (<#if> cond>..<#elseif cond>..<#else>..#if>) for conditionals;
<#list> for iterations and loops (e.g. <#list words as w>..#list>; <#list
0..9 as i>..#list>; <#list 9..0 as i>..#list>); and <#assign> for
assigning variables (<#assign x=5>; <#assign x>the number ${i}#assign>).
One can define functions (<#function>) and macros (<#macros>). You can also
include other templates (<#include>). Here, we only covered a small fraction of
FreeMarker’s possibilities; we recommend that you read the FreeMarker manual for
more information.
Let us create a file with a filename that has an .ftl extension (e.g.
untitled.ned.ftl). Because of the extension, this file will be processed by the
templating engine. The actual name of the file does not matter, because the
<@setoutput .../> directive instructs the templating engine to output everything
from the current file into the file that is specified by the targetFileName variable.
The targetFileName, targetTypeName, bannerComment and nedPackageName
variables are automatically filled out by the wizard, based on the filename and folder
the user selected on the first wizard page.
6
Writing Wizards
<@setoutput path=targetFileName />
${bannerComment}
<#if nedPackageName!="">package ${nedPackageName};#if>
network ${targetTypeName}
{
node[${networkSize}] : ${nodeType}
}
The template variables will be substituted into the template automatically.
Specific wizard dialog types will also define extra variables for use in the templates. For
example, the wizard type that creates a complete simulation (with all required files)
will put the simulationName variable into the context. To see all defined variables,
check the Appendix.
The New Wizard wizard in the IDE provides you with some working examples, useful
utilities for writing wizards, and sample code for accessing various features along with
other helpful information. The aim of these wizards is to help you become productive
in the shortest time possible.
As a last step in our example, we will also create an INI file template:
Create a file called omnetpp.ini.ftl, and fill with:
<#if wizardType=="simulation">
network = ${targetTypeName}
#if>
We need the INI file only if we are creating a simulation. If the current type is not
simulation, the content will be empty, and the file will not be written to the disk.
Wizard Types
The wizard will set the wizardType template variable when it executes, so template
code can check under which wizard type it is running (using <#if>..#if>), and
execute accordingly. This feature allows the user to create templates that can be used
for multiple wizard types.
There are several types of wizards you can create. Each one has a different goal.
New Project Wizards
wizardType = project
Project wizards create new projects and let the user create files in them. It is possible
to adjust project properties to customize the new project. You can add C++ support
to the project, set source and NED folders, etc.
The first two pages of the wizard are standard: they prompt the user for the name of
the new project and let the user choose a content template. These pages are followed
by pages provided by the selected content template. If the user selected C++ support
on the first page, custom pages are followed by the standard CDT New Project pages.
When the user clicks Finish, the wizard creates the project and configures it
according to the selected options (C++ support, source folders, etc.). Then, template
files are copied into the new project, performing template processing as necessary.
Templated pages are responsible for creating the package.ned file according to the
7
Writing Wizards
nedPackageName and namespaceName options, as well as creating source files in the
NED and C++ source folders.
NED and C++ files are not automatically placed into the NED and C++ source
folders. Templated pages have to be written (for example using setoutput) so that
they explicitly create the files in the proper places.
There are a few useful variables that template files use. The rawProjectName variable
contains the project name. This variable cannot be directly used as C++ or NED
package names, type names, etc, because it may contain spaces or other characters not
allowed in identifiers. For convenience, the wizard provides sanitized versions of the
project name that can be used as identifiers; they are in the variables projectName,
PROJECTNAME and projectname, and differ in capitalization. The targetFolder
variable is set to /. These variables cannot be edited in custom wizard
pages.
The variables addProjectReference, makemakeOptions, sourceFolders and
nedSourceFolders affect the creation of the project before template files get
processed. It is allowable to provide an initialization value for these variables in
template.properties and to let the user change them in custom pages.
For conformance with other wizards, the project wizard initializes the following
variables with different case versions of the project name: targetTypeName,
nedPackageName, and namespaceName. The targetMainFile variable is initialized
to projectName+.ned, but there is no requirement for the template to actually
create this file. It can provide a different initialization value for these variables in
template.properties and can let the user change them in custom pages.
If the new project contains a simulation, it is recommended that targetTypeName
and targetMainFile are used as the network name and NED file name respectively.
The targetFileName variable is not set because the project wizard is not required
to create a file.
See the appendix for the variable names that are supported in project wizard templates.
New Simulation Wizards
wizardType = simulation
A new simulation is basically a new folder containing all files required to run a
simulation. The simulation folder usually contains NED files, an INI file, and possibly
also CC, H and MSG files.
The first two pages of the wizard are standard; they prompt the user for the parent
and name of the new folder, and let the user choose a content template. These pages
are followed by pages provided by the selected content template. Simulations can only
be created in new folders under existing projects or folders.
When the user clicks Finish, the wizard creates the folder. The template files are then
copied into the new folder, performing template processing as necessary.
There are a few useful variables that template files can use. The
simulationFolderName contains the name of the new folder (without path). This
variable cannot be directly used as a C++ or NED identifier, because it may contain
spaces or other characters not allowed in identifiers. For convenience, the wizard
provides the simulationName variable which is a sanitized version of the folder name.
8
Writing Wizards
The targetFolder variable is set to the workspace path of the new folder. These
variables cannot be edited in custom wizard pages.
For conformance with other wizards, the simulation wizard initializes the
targetTypeName variable with the simulation name. The targetMainFile variable
is initialized to simulationName+.ned, but there is no requirement that the template
actually creates this file. It can provide a different initialization value for these variables
in template.properties and can let the user change them in custom pages.
The intended purpose of targetTypeName and targetMainFile is to be used as the
network name and NED file name respectively in the new simulation.
The targetFileName variable is not set because the simulation wizard is not required
to create a file.
The nedPackageName and namespaceName variables are set by the wizard to the
NED package name and C++ namespace expected for the given folder. These values
are derived from the folder path, the toplevel package.ned file and the @namespace
property in it, and cannot be overridden.
See the appendix for the variable names that are supported in simulation wizard
templates.
New INI, MSG or NED File Wizards
wizardType = compoundmodule, network, nedfile, inifile, msgfile
These wizard types generate a single file. The first two pages of the wizard are standard;
they prompt the user for the parent folder and name of the new file, and let the user
choose a content template. These pages are followed by pages provided by the selected
content template.
Currently the wizard does not ensure that the created file will be under a NED/C++
source folder. This may change in the future.
When the user clicks Finish, template files are copied into the selected parent folder,
performing template processing as necessary. The template files are expected to create
a file with the name chosen by the user.
The wizard passes the file name to the template files in the targetFileName variable.
The wizard does not prevent the templates from creating other files than
targetFileName. It is the responsibility of the template author to ensure that only
a single file is created.
There are a few useful variables that template files can use. The targetFolder variable
is set to the workspace path of the parent folder. This variable cannot be edited in
custom wizard pages.
For conformance with other wizards, the new wizard initializes the targetTypeName
variable to a sanitized version of the file name (minus extension). This variable can
be used as a NED or message type name in the generated file. The targetMainFile
variable is the same as targetFileName.
One can provide a different initialization value for the targetTypeName variable in
template.properties and let the user change it in custom pages.
9
Writing Wizards
The nedPackageName and namespaceName variables are set by the wizard to the NED
package name and C++ namespace expected for the given folder. These values are
derived from the file path, the toplevel package.ned file and the @namespace property
in it, and cannot be overridden.
See the appendix for the variable names that are supported in new file wizard
templates.
New Simple Module Wizard
wizardType = simplemodule
The simple module wizard creates a simple module, usually consisting of a NED file
and C++ implementation files. This wizard works in a similar way as the New NED
File or New Compound Module wizard, but it is allowed to create other files (C++
sources) in addition to the NED file.
Import Wizards
wizardType = import
An import wizard is not a standalone type, but rather a flag on other wizard types.
It makes the wizard appear in the File|Import… dialog in addition to the File|New
… dialogs.
To access the import wizards, choose OMNeT++, Networks, simulations and other
items as import source on the first page of the Import dialog. The next page will be
the content template selection page. After choosing a template, the next page will be
the file, folder or project name selection page of the New… wizard, followed by the
custom wizard pages.
If an import wizard supports more than one wizard types (e.g. project, simulation,
nedfile, etc.), the File|Import… dialog will use only one of those types. The type is
chosen in the following order of preference: network, nedfile, compoundmodule,
simplemodule, msgfile, inifile, simulation, and project. This may be changed
in the future to explicit wizard type selection.
Export Wizards
wizardType = export
Export wizards can be accessed via the File|Export… dialog and export data into one
or more files in the workspace or in the file system.
To access the export wizards, choose OMNeT++, Networks, simulations and other
items as export destination on the first page of the Export dialog. The next page will
be the content template selection page, followed by the custom wizard pages.
Export wizards do not have a standard file/folder selection page, the target file name(s)
must be obtained from the user on custom wizard pages.
You can use the SaveAsChooser and ExternalSaveAsChooser custom controls to
prompt for a file name in the workspace and in the file system respectively.
The export wizard does not set targetFileName, targetMainFile, or any similar
variables. It is entirely up to the template author to define a variable for storing the
output file name, letting the user edit it, and saving the content in that file.
10
Writing Wizards
Template files are not allowed to produce any output; they are supposed to create the
target files programmatically.
Templates
can
use
static
methods
of
the
FileUtils
class,
such
as
createFile(workspacepath,
content)
and
createExternalFile(filesystempath, content), to create the files. Here,
content is a string that holds the text to be written out into the file in the platform’s
default encoding.
The content text may be assembled using plain string concatenation (<#assign
content = content + "\nsome text">), or templated content (<#assign
content>some text, ${foo} and ${bar}...#assign>).
New Wizard Wizard
wizardType = wizard
A New Wizard wizard creates a wizard under the templates/ folder of a workspace
project.
The first two pages of the wizard are standard. They prompt the user to select the
project that will hold the wizard, choose the wizard name (name of the new folder
under templates/), and pick a content template. These pages are followed by pages
provided by the selected content template.
When the user clicks Finish, the wizard creates the folder under the templates/
folder of the chosen project. After that, template files are copied into the new folder,
performing template processing as necessary.
There are a few useful variables that template files can use. The newWizardName
variable contains the name of the new folder (without path), and newWizardProject
contains the name of the project. The project name variables (rawProjectName,
projectName, PROJECTNAME, etc.) and targetFolder variables are also set. These
variables cannot be edited in custom wizard pages.
The wizard does not set the targetFileName and targetMainFile variables.
See the appendix for the variable names that are supported in New Wizard wizard
templates.
To create a template.properties file for the new wizard, use a
template.properties.ftl file in the wizard wizard. Similarly, you will likely have
files with the .xswt.ftl and .ftl.ftl extensions in the wizard wizard. Inside
.ftl.ftl files, use the <#noparse>..#noparse> directive to protect parts that
you want to be copied verbatim into the created wizards.
Configuration Keys
The template.properties file is a standard Java property file (key = value
syntax) that can be used to supply a template name, a template description, and other
information.
Recognized property file keys:
templateName
The template’s display name. This is the name that
appears in the tree in the template selection page. This
11
Writing Wizards
property defaults to the name of the folder that holds
the wizard files.
templateDescription
Description of the template. This may appear as a
tooltip or in a description page in the wizard.
templateCategory
Template category is used for organizing the templates
into a tree in the wizard’s template selection page.
Defaults to the name of the project that provides the
template.
templateImage
Name of the icon that appears with the name in the
wizard’s template selection page.
supportedWizardTypes
Comma-separated or JSON-syntax list of wizard types
(e.g. nedfile, simplemodule, project, inifile)
that this template supports. If not specified, the wizard
will support all known wizard types.
ignoreResources
Comma-separated or JSON-syntax list of non-template
files or folders designating those files that will
not get copied over to the new project. The
template.properties file and custom wizard page
files automatically count as non-templates, so they do
not have to be listed. Wildcards (*, **, ?) are accepted.
Note that *.foo is interpreted as ./*.foo; write **/
*.foo to mean foo files anywhere.
verbatimFiles
Comma-separated or JSON-syntax list of files that
need to be copied over into the target project verbatim,
even if they have the .ftl extension. Wildcards (*, **,
?) are accepted. Note that *.foo is interpreted as ./
*.foo; write **/*.foo to mean foo files anywhere.
The New OMNeT++ Project wizard also recognizes the following options (these options
can be overridden from custom wizard pages):
addProjectReference
True or false; defaults to true. If true, the template’s
project will be added to the referenced project’s list of
the new project.
sourceFolders
Comma-separated or JSON-syntax list of C++ source
folders to be created and configured. By default, none.
nedSourceFolders
Comma-separated or JSON-syntax list of NED source
folders to be created and configured. By default, none.
makemakeOptions
Comma-separated list of items in the syntax
"folder:options", or a JSON-syntax map of strings; it sets
opp_makemake options for the given folders. There is
no default.
There are additional options for adding custom pages into the wizard, as described
in the next section.
Templates
For wizards, several variables are predefined, such as templateName,
targetFolder,
date, and author; others, like targetFileName,
12
Writing Wizards
targetTypeName, simulationFolderName, nedPackageName, etc., are defined
only for certain wizard dialogs. A full list of variables is provided in the Appendix.
Generating multiple files
By default, templates are processed and copied with the same name (chopping the
.ftl extension), but it is possible to redirect the output of the template to a different
file using the <@setoutput path=.../> macro. The filename can contain slashes,
too, which means that one can write files in a different folder. If the folder does not
exist, it will be created. For example:
<@setoutput path=targetFileName/>
If filename is empty, the directive restores output to the original file name (the
template’s name). This also works if a folder name is given and only the file name is
missing (<@setoutput path="src/">). Then, it will write the file with the original
name but into the specified folder.
If there are multiple setoutput macros with the same file name within a template,
the content will be concatenated. Concatenation only works within one template; if
you have multiple templates writing into the same file, they will overwrite each other’s
content. It is undefined which one will win.
Conditional file creation
Empty and blank files (i.e. those containing only white space) will not be created (i.e.
processing will skip writing it without any question, warning or error). This allows
you to easily create files conditionally; you just have to surround the file body with
<#if>..#if>.
The above rule also means that one cannot even deliberately create empty files
with templates. However, this "limitation" is easy to overcome. Most file formats
(NED, C++, INI, XML, etc.) have a comment syntax, so you can write a file
that contains only a comment ( // file intentionally left blank ).
Alternatively, you can create an empty file using the FileUtils Java utility class (<@do
FileUtils.createFile("empty.txt", "")!/>).
Although blank files are not created, the template engine will not delete an existing file
that happens to be already there with the same name.
Custom Wizard Pages
The following properties can be used to define custom pages in the wizard. is an
integer page ID (starting with 1); its ordering defines the order of wizard pages.
page..file
The name of the XSWT file that describes the wizard
page layout.
page..class
In addition to XSWT files, custom Java pages may also
be defined in Java code. This can be useful when the
wizard page would be too complex to describe with
XSWT, when it would need to have significant active
behavior, or when the wizard page code already exists
in Java form. See below for further discussion about
custom pages.
page..title
Title of the wizard page, displayed in the page’s title
area. Defaults to the template name.
13
Writing Wizards
page..description
Description of the wizard page, shown in the dialog’s
title area below the title. Defaults to text in the format
"Page 1 of 3".
page..condition
A condition for showing the page. If it evaluates to
false, the page will be skipped when it would normally
come in the page sequence of the wizard. This makes
it possible not only to skip pages, but also to show
different pages based on some choice or choices the
user made earlier in the wizard (decision tree). The
condition will be evaluated by the template engine,
so any valid FreeMarker expression that can produce
true or "true" as a result will do. The expression
must be supplied without the ${ and } marks.
The string you enter will be substituted into the
"${( )?string}" string (will replace
""), and evaluate as such. An example will
be provided later.
All property file entries are available as template variables, too. In addition, most
property values may refer to other property values or template variables, using the
${name} syntax.
XSWT Forms
An XSWT form is defined in an XML file with the root element . Some XSWT
specific elements and attributes (import and package declarations, id and class
attributes to name a few) are defined in the http://sweet_swt.sf.net/xswt XML
namespace (we use the x namespace prefix here).
Controls that can be used in XSWT are instantiated by an element with same name as
the control (but starting with lowercase).
Controls and classes used in an XSWT file must be imported before they can be used.
Entities and attributes in an XSWT file are directly mapped to the corresponding
SWT controls and their properties. For example, a tag creates an
org.eclipse.swt.custom.StyledText control. Similarly, a text attribute causes
the setText() method of the control to be called.
Alternatively, it is possible to call a public method on the control by embedding a "call"
as a child tag and supplying the parameters as p0, p1, etc.:
14
Writing Wizards
Because of a limitation in XSWT, only methods accepting String parameters can be
accessed this way.
Integer constants in controls (public static final int fields) can be used in an
XSWT file by appending the Java class name before them:
Constants in the SWT class do not need the SWT. prefix. You can write:
Children can be added to a compound control inside the
x:children> tags.
Layout and layout data can also be added as a new tag inside a control element:
Layout is always needed; otherwise, the control will not appear on the page.
SWT is documented on the Eclipse website. See: http://www.eclipse.org/swt/docs.php
for documentation, examples and tutorials.
Binding of Template Variables to Widgets
XSWT allows one to tag widgets with ID attributes. Widget IDs will become the names
of template variables with the values being the content of widgets. For example, text
widgets (org.eclipse.swt.widgets.Text) provide a string value (Java type "String"), while
checkboxes and radio buttons provide a boolean (Java type "Boolean").
XSWT also allows filling up the widgets with default values (e.g. ), but this feature should be used with care because the defaults
set in XSWT may not make it to the file templates. This occurs because if the user
clicks Finish early, the rest of the wizard pages (and their widgets) may not be created
at all, so values set in the XSWT will take no effect.
For this reason, defaults should always be set in the property file. To do so, simply use
a key with the ID of the widget; those values will be written into the wizard page when
the page is created. For example, if you have a text widget with x:id="numNodes" and
a checkbox with x:id="generateTraffic", then the following lines
15
Writing Wizards
numNodes = 100
generateTraffic = true
will fill in the text widget with "100" and select the checkbox. Widgets that do not have
such lines in the property file will be left alone. The property file takes precedence over
values specified in the XSWT file.
Compound data structures (arrays, maps, and any combination of them) can be
specified in the JSON syntax (http://json.org). They can be iterated over in the
templates and can be used as input/output for custom compound widgets. Examples:
apps = ["ftp", "smtp", "news"]
layers = {"datalink":"ieee80211", "network":"ip", "transport":["tcp","udp"]}
If you get an error about syntax errors in a JSON entry, the http://jsonlint.com website
can help you locate the problem.
Conditional Pages
Now that we have covered basic XSWT, we can revisit how one can use page conditions.
Consider the following practical example of creating a wizard for wireless networks.
On the first page of the wizard you could have a [] Configure routing checkbox with the
ID wantRouting. If this checkbox is selected, you want to display a second page where
the user can select a routing protocol, followed by configuration pages determined by
the chosen routing protocol.
To achieve this, you would add the following lines to template.properties:
# page with the "wantRouting" checkbox
page.1.title = General
# page with the "protocol" combobox
page.2.title = Choose Routing Protocol
page.3.title = AODV Options
page.4.title = DSDV Options
page.2.condition = wantRouting
page.3.condition = wantRouting && protocol=="AODV"
page.4.condition = wantRouting && protocol=="DSDV"
The .condition keys will make the wizard include only the pages where the condition
evaluates to true. Conditions can be arbitrary FreeMarker expressions that evaluate to
true (as boolean) or "true" (as string). Conditions are re-evaluated after every page,
so you can depend on variables edited on earlier pages.
Conditional Widgets
It is also possible to create controls conditionally. To overcome the limitation that
XSWT page descriptions are completely static, XSWT files undergo FreeMarker
template processing before giving them to the XSWT engine for instantiation. This
template processing occurs right before the page gets displayed, so data entered on
previous pages can also be used as input for generating XSWT source. This feature
can be useful in making conditional widgets (i.e. using <#if> to make part of the
page appear only when a certain option has been activated on earlier pages), to create
a previously unknown number of widgets (using a <#list>..#list> loop), to
populate combo boxes, listboxes or other widgets with options, and more.
16
Writing Wizards
<#if wizardType=="simulation">
#if>
If the user navigates in the wizard back and forth several times (using the Next and Back
buttons), the contents of wizard pages are always re-created with the current values of
template variables just before getting displayed, so they will always be up to date.
Extending the Wizards in Java
It is possible to create new Wizard pages, custom widgets or add new template variables
by extending the wizards in Java.
Creating Wizard Pages
Defining a wizard page in Java requires that you install the Eclipse Plug-in Development
Environment (PDE) and that you have some Eclipse development skills.
The template.properties key for denoting a Java-based wizard page is
page..class, and the value should be the fully qualified name of the Java class
that implements the wizard page. The requirements for the class are:
• the class must be accessible to the class loader,
• the class must extend org.omnetpp.common.wizard.ICustomWizardPage, and
• the class must have a public constructor with the following argument list: (String
name, IContentTemplate creatorTemplate, String condition)
Creating Custom Widgets
Since XSWT works via Java reflection, your own custom widgets can be used in forms,
similar to normal SWT widgets. No glue or registration code is needed; simply add
their package to the tags at the top of the XSWT file.
However, some Java code is needed so that the wizard knows how to write template
variables into your widgets and how to extract them after editing. This functionality can
be added via the org.omnetpp.common.wizard.IWidgetAdapter interface. This
interface must be implemented either by the widget class itself, or by a class named
Adapter in the same package. The interface has methods to tell
whether the adapter supports a given widget, to read the value out of the widget, and
to write a value into the widget.
In addition to basic data types (Boolean, Integer, Double, String, etc.), it
is possible to use compound data types as well (i.e. those composed of the List and
Map interfaces of the Java Collections API). The default values can be given in the
template.properties file in the JSON notation and the result can be used in the
templates (iteration via <#list>, etc.).
Extending your Template with Custom Classes and Widgets
Jar files placed into the plugins/ subdirectory of an OMNeT++ project will be loaded
automatically and will be available to all templates. Jar files in that directory may be
plain Java jars and Eclipse plug-in jars (the latter makes it also possible to contribute
new functionality into the IDE via various extension points, but this is outside the scope
of this discussion about wizards).
Jar files placed in the folder of the template will be loaded automatically when
the template is used and the classes in it will be available for that template.
17
Writing Wizards
Custom SWT widget classes can be imported and used in XSWT forms, and
other code can be used in the template files via the FreeMarker Bean Wrapper
(e.g. ${classes["org.example.SomeClass"].someStaticMethod(...)}, see the
example wizards.) Like .xswt files and template.properties, jar files are not copied
over into the destination folder when the wizard executes.
Extending the Template Processing
If
you
are
skilled
in
writing
Eclipse
plug-ins,
there
are
ways
you can extend content templates. One is to contribute to the
org.omnetpp.common.wizard.templatecontributor extension point, which lets
you supply IContentTemplateContributor objects that can extend the content
template implementation in various ways. You can contribute new variables, functions
or macros to the template context.
Common Pitfalls
• Variables need to be defined. Referring to an undefined variable is an error in
FreeMarker (i.e. it does not return an empty string as in bash or in makefiles).
• Default values should be specified in template.properties, not in the XSWT
forms. You should not define them in the XSWT page by pre-filling the corresponding
widget (e.g. ). If you specify the value in a page, the
assignment will not take effect if the user skips that page (i.e. clicks Finish earlier).
That causes the variable to remain undefined, resulting in a runtime error during
template processing.
• Type mismatch. Variables have types in FreeMarker and one can get type conversion
errors if the templates are not programmed carefully. For example, comparing
a number and a string is a runtime error. A more serious problem is that
widgets in wizard pages may implicitly perform type conversion. For example, a
numHosts=100 line in template.properties defines a number, but if you have a
widget in the form, the variable will come back from
it as a string. Even worse, whether the number->string conversion takes place will
depend on whether the page gets displayed in the wizard session. Therefore, it is
recommended that you explicitly convert numeric variables to numbers at the top of
templates (e.g. <#assign numHosts = numHosts?number>).
• For some reason, FreeMarker refuses to print boolean variables (e.g. ${isFoo}
results in a runtime error). The common workaround is to write <#if
isFoo>true<#else>false#if>; this can be shortened with our iif() function:
${iff(isFoo, "true", "false")}.
• Many string operations are available both as built-in FreeMarker operators
(varname?trim) and as Java methods via FreeMarker’s BeanWrapper
(varname.trim()). If you are mixing the two, it is possible that you will start getting
spurious errors for the Java method calls. In that case, simply change Java method
calls to FreeMarker built-ins.
• Some Java functionality (the instance of operator, Class.newInstance(), etc.)
cannot be accessed via BeanWrapper. If you hit such a limitation, check our
LangUtils class that provides FreeMarker-callable static methods to plug these
holes.
XSWT Tips and Tricks
How can I make a checkbox or radio button? and are not
recognized in my XSWT files!
18
Writing Wizards
They are called Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.4 Linearized : No Modify Date : 2016:04:14 13:43:51+02:00 Create Date : 2016:04:14 13:43:44+02:00 Title : IDE Customization Guide Creator : DocBook XSL Stylesheets with Apache FOP Producer : Apache FOP Version 0.95 Profile CMM Type : Linotronic Profile Version : 2.1.0 Profile Class : Display Device Profile Color Space Data : RGB Profile Connection Space : XYZ Profile Date Time : 1998:02:09 06:49:00 Profile File Signature : acsp Primary Platform : Microsoft Corporation CMM Flags : Not Embedded, Independent Device Manufacturer : Hewlett-Packard Device Model : sRGB Device Attributes : Reflective, Glossy, Positive, Color Rendering Intent : Perceptual Connection Space Illuminant : 0.9642 1 0.82491 Profile Creator : Hewlett-Packard Profile ID : 0 Profile Copyright : Copyright (c) 1998 Hewlett-Packard Company Profile Description : sRGB IEC61966-2.1 Media White Point : 0.95045 1 1.08905 Media Black Point : 0 0 0 Red Matrix Column : 0.43607 0.22249 0.01392 Green Matrix Column : 0.38515 0.71687 0.09708 Blue Matrix Column : 0.14307 0.06061 0.7141 Device Mfg Desc : IEC http://www.iec.ch Device Model Desc : IEC 61966-2.1 Default RGB colour space - sRGB Viewing Cond Desc : Reference Viewing Condition in IEC61966-2.1 Viewing Cond Illuminant : 19.6445 20.3718 16.8089 Viewing Cond Surround : 3.92889 4.07439 3.36179 Viewing Cond Illuminant Type : D50 Luminance : 76.03647 80 87.12462 Measurement Observer : CIE 1931 Measurement Backing : 0 0 0 Measurement Geometry : Unknown Measurement Flare : 0.999% Measurement Illuminant : D65 Technology : Cathode Ray Tube Display Red Tone Reproduction Curve : (Binary data 2060 bytes, use -b option to extract) Green Tone Reproduction Curve : (Binary data 2060 bytes, use -b option to extract) Blue Tone Reproduction Curve : (Binary data 2060 bytes, use -b option to extract) Page Count : 38EXIF Metadata provided by EXIF.tools