Workspace 6.21.5
|
In this section, we're going to understand the code that was automatically generated by Workspace so that we know how to customise our datatype.
Using our new datatype (continue on with tutorial Writing a Workspace Datatype )
As should any C++ header, our file contains a header guard followed by any other header files this one requires. The datafactorytraits.h header defines the DECLARE_WORKSPACE_DATA_FACTORY macro which we will explain shortly.
Next comes our implementation class's definition, wrapped in our namespace.
Next comes our class's definition. As you would expect, it is exported using our plugin's API symbol.
The first thing to note is that the only data member we see here is a pointer to type RectangleImpl
. This is an "implementation" class defined in the .cpp file, which contains the real data members owned by our data type. This isn't essential when creating a new Workspace data type (or any class in C++ for that matter), but we do it here in order to to keep our data type's implementation separate from its interface.
The other interesting thing about this class is that it extends CSIRO::DataExecution::ObjectGroup
. An ObjectGroup
is a special type of class that Workspace is able to easily interact with. Workspace knows the names and data types of all an object group's members, which means it can automatically create operations for Composing (ComposeGroup) and Decomposing (DecomposeGroup) them. See More about object groups for extra information on ObjectGroups and how they work.
The last and most important thing we need to look at is the set of DECLARE macros at the bottom of the file:
The first line of of code (and one more bit of code in the .cpp file which is explained later in the tutorial) is what takes our class and turns it into a Workspace data type. The DECLARE_WORKSPACE_DATA_FACTORY macro takes two parameters. The first parameter must be the fully scoped class name and the second parameter should be the export symbol used between the class
keyword and the class name in the class definition.
The second line is another special macro, reserved for when the data type inherits another Workspace data type. It allows Workspace to handle derived-to-base class conversion and other special scenarios. It takes three parameters; the scoped derived class name, the scoped base class name and the export symbol.
ObjectGroups
; ObjectGroups just simplify the process by saving the user from creating custom "builder" operations. In fact, you can use any C++ class you define as a custom data type. The magic that turns a class into Workspace data type is the DECLARE_WORKSPACE_DATA_FACTORY and DEFINE_WORKSPACE_DATA_FACTORY macros.
Using our new datatype (continue on with tutorial Writing a Workspace Datatype )
Again, we include the headers needed. The Workspace/DataExecution/DataObjects/typeddatafactory.h header provides the DEFINE_WORKSPACE_DATA_FACTORY macro used at the end of this file to define your custom data type's factory. This macro is the matching pair to the DECLARE_WORKSPACE_DATA_FACTORY macro used in the header. We also need to include the plugin's header (because we need to know about its getInstance()
function) and the header for the class itself.
Now let's have a look at the implementation class, RectangleImpl
.
This class contains our member variables, as well as a back reference to our datatype itself (owner_). Note that the members are TypedObjects
, similar to the data types used previously in operation tutorial. For object groups, any members we wish to expose to Workspace must be TypedObjects. For non-object-group data types, this is not necessary.
Next, let's have a look at our implementation classes functions:
We see that it has a simple constructor which initialises our members, a copy constructor which does the same and a function called setObjects()
, which is invoked by both the constructor and copy constructor. This function is responsible for assigning our data members Visible Names, which Workspace uses when editing our datatype with the ComposeGroup and DecomposeGroup operations.
Let's keep looking at the functions in the file
Our constructor and destructor serve only to initialise our implementation class. Nothing tricky here.
The clone function is used by Workspace to duplicate our data type when necessary. We simply return a copied instance of our Rectangle.
Here we see the assignment and comparison operators, our get / set functions and the very important DEFINE_WORKSPACE_DATA_FACTORY macro. Depending upon what you want to do with your data type, you may want to remove some or all of the get / set functions.
The DEFINE_WORKSPACE_DATA_FACTORY macro should just about always be at the end of the file and it must sit outside any namespaces. Most importantly, it must never appear in a header file. The macro associates your custom class with your plugin and adds a data factory for it to Workspace. It even takes care of handling whether or not your class supports serialization. It should be used as follows:
getInstance()
function of your plugin.The wizard will also automatically add our data factory to the simpleplugin.cpp file, and add the headers and source files to the CMakeLists.txt files in exactly the same way as we did with our operation. You can have a look at those files below:
Using our new datatype (continue on with tutorial Writing a Workspace Datatype )