Fr Widget Basics

This chapter teaches you the basics of Fr_Widget toolkit

Writing your first Fr_Widget based program
Basically, you need always to have a Fr_CoinWindow. This widget is the container of the other widgets you create. It is a subclass of Fr_Group. The Fr_CoinWindow used to distribute events and hold a link to each widget you have in your window.

Fr_CoinWindow doesn't draw any thing and it is not restricted to any dimensions. But there must be a such windows for getting your Fr_Widgets work. If FreeCAD adapt this toolkit someday, the Fr_CoinWindow should be always available and you shouldn't required to create one. But at the moment, you have to create one Fr_CoinWindow whenever you need to use the toolkit. Notice that you shouldn't make several of Fr_CoinWindow.. Only once.

The widgets interact with the user using the callback system.

Explaining the code

 * First line imports the fr_arrow_widget. Later we use it to create the widget itself.
 * Second line imports the fr_coinwindow. As mentioned this is the container of the system. Without this widget, you will not be able to show anything
 * Third line is math library from Python. It is required for now but this will change. It is used to convert the rotation angle to radians. But in the future the interface angles will be in degree. Internally is still radians as COIN3D is in radians.

Creating Fr_Line_widget as an example
Lets start creating a new drawing widget. This widget will draw a line and has a label. We need to get two vertices to draw the line. The widget itself is a subclass of the abstract object called Fr_Widget.

Fr_Widget is the base class for all widgets. It contains basic variable, objects and functions definitions. Some of these are not implemented and you have to implemented. If you will use any function that aren't implemented, an exception will popup.

Part 1
The class declaration for our new object:

The line (super) must be written in the first line after the definition of the class since we want to initialize the abstract widget(Fr_Widget) before changing the internal objects and variables.

We have as arguments to the widget:(vertices, label and line width). You must give exactly 2 vertices to the class, but line width and label is optional. Default line width is be 1.

There are four callbacks that we should define if we want to take benefit of the events. These are external function user should define them to do other tasks as events occur. For example mouse click or keyboard events etc...

The last two lines are related to Coin3d. The first one is a coin.SoSwitch object in coin which can be used to hide or show the drawn object. The other line is the configuration of that switch. We allow by default showing all objects.

Part 2
Look at Fr_Widget. The functions that have no implementation must be implemented here. The most important functions are (draw, handle, redraw, label_draw,label_redraw). Drawing the object will be different from widget to widget. But they have many things in common. The uses the drawing functions implemented in fr_draw.py. Since the actual drawing is implemented in fr_draw, we will not describe here the COIN3D commands.

Each function in the fr_draw returns the same object which is a coin.SoSeparator. This object is a container (group) of several coin commands. Details of those commands could be found in the documentation of COIN3D. But we will be describing the most common used commands when we explain the fr_draw.py.

Part 3
We start to explain the code. This part is not difficult to understand .. It sets the width.

This is the most important function in this toolkit. It handles the events occur in the coin window and try to distinguish between different events. Coin3d doesn't implement by default double-click, but this function is implementing that also.

For Keyboard events, at the moment the toolkit doesn't mask the events. They are still the coin3d definition. This might change in the future. Whenever a widget uses the event, it must return 1 as an indication that the event(s) is/are processed. I think the code is self explanatory. Events, colors, and other constants could be found in the file constant.py.

Part 4
This part is about the function 'draw'. This function is responsible for drawing the whole widget. It takes care of drawing the widget when it is active, inactive, selected, has focus, lost focus etc...

It has a direct connection to the fr_draw library that provides the primitive drawings for ex. (Line, Square, Box, Arrow, 2D Arrow, Cube, Cylinder etc...). For our widget we uses the line drawing. Lets look at the code:

The function checks if we have got two vectors since the line needs two vectors. And after that it chooses the desired color based on the widgets status. Every widget needs to save the node to the widget and to the switch the widget has. The SoSwitch is to hide the widget when that is required. When the widget needs to redraw the whole drawing, first it removes the SoSeparator from the COIN3D scene graph and it should remove it from the widget also. And then it will recreate the whole thing again. that function is called redraw. The label is also drawn here. But we will talk about the labels later. But you need to call the draw_label here. COIN3D drawings will be discussed in a separate page. Something to remember, draw your coin3d objects in the same way you draw in FreeCAD. Always make the default position (0,0,1). .i.e. the object should be drawn towards +Z axis. This is useful since when you apply rotation of other FreeCAD object your COIN object will take that direction without any problem. This is why my arrows (2d or 3D) are all located on the Z axis by default if you don't change them.

Part 5
Widgets Label: Labels are necessary for the widget toolkit. For example the label for line widget can be used to show the length of the side the line is drawn for. It has also the call back mechanism so you can interact with the text shown on the screen.

For our widget (Fr_Line_Widget) the label is drawn near to the beginning of the line i.e. near to the first Vertex. At the moment there is no alignment mechanism but that is in the todo list. This part will be updated later when that is implemented.

Label drawings are collect in the file fr_label_draw.py.

The text drawn is only 2D. There might be the need of making 3D text, but this will/must come to the todo list.

PropertyValues is an object that is used to send the parameter to the drawing function. It simplifies the API interface for the label drawing. Many parameter must be defined for the label. For example (font name, font size, used color, position or the vector , alignment (which is not implemented yet) etc... All these are used to determine how the draw_label will draw the actual text. The returned value from the draw_label is an SoSeparator which should be added to the scene graph.

Part 6
This part is also relate to draw function. We need a mechanism to redraw the drawings. Normally you must remove the drawings and redraw the objects to get the coin3d objects changed. Fr_Wdiget do the same. Looking to the following code:

First function (redraw) will remove the drawings from the scene graph and remove the holder of the objects inside the widget. SoSepartor will be deleted since it will be recreated when draw function activates. But the SoSwitch object inside the widget doesn't need to be delete. It will not have any child/children. The same should happen to the label. That is why we have another function for redrawing the label (lblRedraw).

Part 7
We need also functions that will put the size of the object, resize it and move it. Bellow are the functions:

Label move is not implemented yet. But drawing move, size and resize indeed is the same function. There are many ways to do this job but to make it simple, Fr_Widget delete the original vectors and simply redraw the whole object. There is not so much to clarify. It is clear how the function works.

Part 8
to be continued...