Graphical User Interface
This web pages describes how to add and manage the elements of the GUI by example. A more elaborate discussion on the philosophy and the structure of the interface to the user and the user interaction with the module can be found in VR++ 0.8.0 Programmer's Guide.
In this web page we assume that the project of interest is located in the new_module directory. The name of the project is NewModule.
Conceptually, the GUI of the module consists of two parts: the GUI of the other modules the NewModule is interacting with, and the part the NewModule creates itself. Figure 1 shows an example GUI of a module.
Figure 1: An Example GUI of a Module
In the Figure 1, the Data selection, Coordinate System Parameters, and most of Variable selection sections are created by the other modules of the 3DVDM/VR++ systems. The NewModule only adds two additional GUI elements into the GUI: Show Objects and Object Size.
The GUI elements and the mapping between the elements of the GUI and the variables of your module are programmed in three files:
| GUI Files: |
new_module/include/3dvdm/new_module/NewModuleMapper.h new_module/tasks/NewModuleMapper.cc new_module/masters/NewModuleMaster.cxx |
The GUI elements of the NewModule are programmed in the NewModuleMapper::updateMenuDefinition function, in the NewModuleMapper.cc file:
| updateMenuDefinition Function, NewModuleMapper.cc File: |
void NewModuleMapper::updateMenuDefinition()
{
string NewModuleMenu;
NewModuleMenu += "Show Objects\tBOOL\tTrue\n";
NewModuleMenu += "Object Size\tFLOAT\t0.01\t0.08\t1.0\t2\n";
menuDefinition += NewModuleMenu;
send( subMenu1Id );
}
|
The code adds two GUI elements: the Show Object element and the Object Size into the menu. The Show Object is a check box with the True initial value. The Object Size element is a slider of float type with the range from 0.01 to 1.0, initial value 0.8, and two decimal values for the fraction part.
The GUI elements are associated with the C++ variables in the all three files: NewModuleMapper.h NewModuleMapper.cc, and NewModuleMaster.cxx.
NewModuleMapper.h defines the C++ variables, which are associated with the GUI elements (green block of the code):
| Definition of C++ variables, NewModuleMapper.h File |
#ifndef NewModuleMapper_h
#define NewModuleMapper_h
#include <vr++/data/DBMapperTask.h>
#include <vr++/data/DataSet.h>
class NewModuleMapper : public DBMapperTask {
private:
int showObjectsId, objectSizeId;
int subMenu1Id;
DataSet *dataSubset;
public:
NewModuleMapper();
string getName() { return "NewModuleMapper"; };
void updateMenuDefinition();
/** The main function where all the calculations take place.
* @return returns true, if the properties were calculated, else false.
*/
TaskState calculateProperties();
protected:
|
string newModuleMenu; /** Visualize the objects (default is true) */ bool showObjects; /** The size of the objects (default is 0.8 ) */ float objectSize; |
}; #endif |
The C++ variables are connected to the menu in the constructor of the NewModuleMapper class, and in the main function of the NewModuleMaster class:
| Constructor, NewModuleMapper.cc File |
NewModuleMapper::NewModuleMapper()
{
subMenu1Id = addOutput("newModuleMenu", newModuleMenu);
|
// Input newInputGroup(); showObjects = true; showObjectsId = addInput( "showObjects", showObjects ); newInputGroup(); objectSize = 0.08; objectSizeId = addInput( "objectSize", objectSize ); |
} |
| Constructor, NewModuleMapper.cc File |
#include <vr++/kernel/Master.h>
int main(int argc, char *argv[])
{
Master master;
int sourceTask, mapperTask;
int queryTask1, queryTask2, queryTask3;
int keyboardTask, cameraTask, lightTask, coordinateSystemTask, drawTask;
int triangleTask;
int sideWinderTask;
bool ok;
ok = master.config(argc, argv);
ok = ok && master.setTask("DataSlave", "DBSourceTask", sourceTask);
ok = ok && master.setTask("NewModuleSlave", "NewModuleMapper", mapperTask);
ok = ok && master.setTask("gtkSlave", "QueryTask", queryTask1);
ok = ok && master.setTask("gtkSlave", "QueryTask", queryTask2);
ok = ok && master.setTask("gtkSlave", "QueryTask", queryTask3);
ok = ok && master.setTask("GraphicsSlave", "KeyboardTask", keyboardTask);
ok = ok && master.setTask("GraphicsSlave", "LightTask", lightTask);
ok = ok && master.setTask("GraphicsSlave", "CameraTask", cameraTask);
ok = ok && master.setTask("GraphicsSlave", "DrawGeometryTask", drawTask);
ok = ok && master.setTask("GraphicsSlave", "CoordinateSystemTask",
coordinateSystemTask);
ok = ok && master.setTask("GraphicsSlave", "TriangleTask", triangleTask);
ok = ok && master.setTask("InputSlave", "KeyboardNavTask", sideWinderTask);
// Loading data
ok = ok && master.connect(SYNCHRONOUS, sourceTask, "dataSet",
mapperTask, "dataSet");
// Navigation
ok = ok && master.connect(IMMEDIATE, keyboardTask, "characters",
sideWinderTask, "characters");
ok = ok && master.connect(IMMEDIATE, keyboardTask, "axes",
sideWinderTask, "axes");
ok = ok && master.connect(INCREMENTAL, sideWinderTask, "cameraSettings",
cameraTask, "cameraSettings");
// Coordinate system
ok = ok && master.connect(INCREMENTAL, mapperTask, "coordinateSystemData",
coordinateSystemTask, "coordinateSystemData");
// Graphics
ok = ok && master.connect(SYNCHRONOUS, mapperTask, "properties",
drawTask, "properties"); // object properties
ok = ok && master.connect(SYNCHRONOUS, mapperTask, "triangleProperties",
triangleTask, "triangleProperties"); // triangle properties
// Data source menu
ok = ok && master.connect(IMMEDIATE, sourceTask, "menuDefinition",
queryTask1, "menuDefinition");
ok = ok && master.connect(INCREMENTAL, queryTask1, "listParameters", 0, 0,
sourceTask, "dataFileNumber");
ok = ok && master.connect(INCREMENTAL, queryTask1, "intParameters", 0, 0,
sourceTask, "quantiles");
// Coordinate system menu
ok = ok && master.connect(IMMEDIATE, coordinateSystemTask, "menuDefinition",
queryTask2, "menuDefinition");
ok = ok && master.connect(INCREMENTAL, queryTask2, "boolParameters", 0, 0,
coordinateSystemTask, "visible");
ok = ok && master.connect(INCREMENTAL, queryTask2, "boolParameters", 1, 1,
coordinateSystemTask, "inverse");
ok = ok && master.connect(INCREMENTAL, queryTask2, "floatParameters", 0, 0,
coordinateSystemTask, "strokeWidth");
ok = ok && master.connect(INCREMENTAL, queryTask2, "floatParameters", 1, 1,
coordinateSystemTask, "lineWidth");
ok = ok && master.connect(INCREMENTAL, queryTask2, "floatParameters", 2, 2,
coordinateSystemTask, "fontSize");
// NewModule part
ok = ok && master.connect(IMMEDIATE, mapperTask, "menuDefinition",
queryTask3, "menuDefinition");
ok = ok && master.connect(INCREMENTAL, queryTask3, "listParameters",
mapperTask, "mappings");
|
ok = ok && master.connect(INCREMENTAL, queryTask3, "boolParameters", 0, 0,
mapperTask, "showObjects" );
ok = ok && master.connect(INCREMENTAL, queryTask3, "floatParameters",0, 0,
mapperTask, "objectSize" );
|
ok = ok && master.run(); return ok ? 0 : 1; } |
Please note, that the string names of the connecting variables are identical (cf. red colored strings in the codes).
