FLUID for FLTK 1.4.0
|
The first FLUID tutorial explains the FLUID basics. It creates a single main()
function that opens an application window with a static text box inside.
After launching FLUID we want to make sure that two very useful tool windows are open. The "Widget Bin" gives quick access to all available widgets and functional types. It can be opened via the main menu: Edit > Show Widget Bin, or using the shortcut Alt-B.
The second very helpful tool box is the "Code View". The Code View gives a preview of the code as it will be generated by FLUID. All changes in the layout or in attributes are reflected immediately in the Code View. Choose Edit > Show Code View or press Alt-C to get this toolbox. Make sure that Auto-Refresh and Auto-Position are active in the Code View.
Let's start Hello World from scratch. If there is already a previous project loaded, select File > New or Ctrl-N.
Before we can create a window, we need a "C" function that can be called when we run the program. Select New > Code > Function/Method... or click on the image in the widget bin.
A function is added as a first line to the widget tree in the main window, and a "Function/Method Properties" dialog box will pop up. For our Hello World program, delete all text in the top "Name(args)" text field. If this field is left empty, FLUID will generate a main(argc, argv)
function for us.
Click OK to apply the changes you made in the Function Properties dialog. You can get this dialog back at any time by selecting the function in the main window and pressing F1, or by double-clicking it.
Note that the function will not show up in the Code View yet. FLUID will not generate code for functions that don't have any content, and only create a forward declaration in the header file, assuming that the function will be implemented inside another module.
Keep the main
function selected and add an Fl_Window
to the function by selecting New > Group > Window..., by clicking the image in the Widget Bin, or by dragging the Group/Window image from the Widget Bin onto the desktop.
A new application window will open up on the desktop. The thin red outline around the window indicates that it is selected. Dragging the red line will resize the window. Take a look at the Code View: the main function is now generated, including code to instantiate our Fl_Window
.
To edit all the attributes of our window, make sure it is selected and press F1, or double-click the entry in the main FLUID window, or double-click the window itself. The "Widget Properties" dialog box will pop up. Enter some text in the "Label:" text box and see how the label is updated immediately in the window itself, in the widget list, and in the Code View.
Adding a static text to our window is just as easy. Put an Fl_Box
into our window by selecting New > Other > Box, or by clicking on the image in the Widget Bin, or by dragging the Other/Box image from the Widget Bin into our newly created window.
Most importantly, enter the text "Hello, World!" in the "Label:" field of the Box Widget Properties panel to achieve the goal of this tutorial. Now is also a great time to experiment with label styles, label fonts, sizes, colors, etc. .
Finally, we should save our project as an .fl
project file somewhere. Once the project is saved, select File > Write Code or press Shift-Ctrl-C to write our source code and header file to the same directory.
Compile the program using a Makefile, CMake file, or fltk-config as described in the FLTK manual and the README.txt
files in the FLTK source tree.
In the first "Hello World" tutorial, we built an entire application in FLUID. It's a boring application though that does nothing except quitting when the close button in the window border is clicked.
The second tutorial will introduce callbacks by implementing task 1, "Counter", of 7GUIs. 7GUIs has been created as a spin-off of my master’s thesis Comparison of Object-Oriented and Functional Programming for GUI Development at the Human-Computer Interaction group of the Leibniz Universität Hannover in 2014. 7GUIs defines seven tasks that represent typical challenges in GUI programming. https://eugenkiss.github.io/7guis/ .
Task 1 requires "Understanding the basic ideas of a language/toolkit. The task is to build a frame containing a label or read-only textfield T and a button B. Initially, the value in T is “0” and each click of B increases the value in T by one."
Our knowledge from tutorial 1 is enough to generate the main()
function, and add an Fl_Window
, an Fl_Output
, and an Fl_Button
. To make life easy, FLUID comes with a built-in template for this tutorial. Just select File > New from Template... and double-click "1of7GUIs" in the Template Panel.
We will need to reference the output widget in our callback, so let's assign a pointer to the widget to a global variable and give that variable a name. Open the Widget Properties dialog by double-clicking the output widget. Change to the "C++" tab, and enter "`counter_widget`" in the "Name:" field.
The "Count" button is the active element in our application. To tell the app what to do when the user clicks the button, we create a callback function for that button. Open the widget properties dialog for the button. In the "C++" tab, we find the input field "Callback:".
The callback is called exactly once every time the user clicks the button. Our strategy here is to read the current value from the counter_widget
, increment it by 1, and write it back to counter_widget
. The FLTK documentation tells us that we can use Fl_Output::ivalue()
to get text in Fl_Output
as an integer, and we can write it back by calling Fl_Output::value(int)
. When the value is changed, FLTK will automatically redraw the output widget for us. So here is the callback code:
That's it. This is a complete interactive desktop application. Compile, link, run, and test it to see how it works.
This tutorial will show you how to generate a complete user interface class with FLUID that is used for the CubeView program provided with FLTK.
The window is of class CubeViewUI, and is completely generated by FLUID, including class member functions. The central display of the cube is a separate subclass of Fl_Gl_Window called CubeView. CubeViewUI manages CubeView using callbacks from the various sliders and rollers to manipulate the viewing angle and zoom of CubeView.
At the completion of this tutorial you will (hopefully) understand how to:
The CubeView class is a subclass of Fl_Gl_Window. It has methods for setting the zoom, the x and y pan, and the rotation angle about the x and y axes.
You can safely skip this section as long as you realize that CubeView is a sublass of Fl_Gl_Window and will respond to calls from CubeViewUI, generated by FLUID.
Here is the CubeView class definition, as given by its header file "test/CubeView.h":
Here is the CubeView implementation. It is very similar to the "CubeView" demo included with FLTK.
We will completely construct a window to display and control the CubeView defined in the previous section using FLUID.
Once you have started FLUID, the first step in defining a class is to create a new class within FLUID using the New->Code->Class menu item. Name the class "CubeViewUI" and leave the subclass blank. We do not need any inheritance for this window. You should see the new class declaration in the FLUID browser window.
Click on the CubeViewUI class in the FLUID window and add a new method by selecting New->Code->Function/Method. The name of the function will also be CubeViewUI. FLUID will understand that this will be the constructor for the class and will generate the appropriate code. Make sure you declare the constructor public.
Then add a window to the CubeViewUI class. Highlight the name of the constructor in the FLUID browser window and click on New->Group->Window. In a similar manner add the following to the CubeViewUI constructor:
hrot
vrot
xpan
ypan
zoom
None of these additions need be public. And they shouldn't be unless you plan to expose them as part of the interface for CubeViewUI.
When you are finished you should have something like this:
We will talk about the show()
method that is highlighted shortly.
What we have is nice, but does little to show our cube. We have already defined the CubeView class and we would like to show it within the CubeViewUI.
The CubeView class inherits the Fl_Gl_Window class, which is created in the same way as an Fl_Box widget. Use New->Other->Box to add a square box to the main window. This will be no ordinary box, however.
The Box properties window will appear. The key to letting CubeViewUI display CubeView is to enter CubeView in the Class: text entry box. This tells FLUID that it is not an Fl_Box, but a similar widget with the same constructor.
In the Extra Code: field enter #include "CubeView.h"
This #include
is important, as we have just included CubeView as a member of CubeViewUI, so any public CubeView methods are now available to CubeViewUI.
Each of the widgets we defined before adding CubeView can have callbacks that call CubeView methods. You can call an external function or put a short amount of code in the Callback field of the widget panel. For example, the callback for the ypan
slider is:
We call cube->redraw()
after changing the value to update the CubeView window. CubeView could easily be modified to do this, but it is nice to keep this exposed. In the case where you may want to do more than one view change only redrawing once saves a lot of time.
There is no reason to wait until after you have added CubeView to enter these callbacks. FLUID assumes you are smart enough not to refer to members or functions that don't exist.
You can add class methods within FLUID that have nothing to do with the GUI. As an example add a show function so that CubeViewUI can actually appear on the screen.
Make sure the top level CubeViewUI is selected and select New->Code->Function/Method. Just use the name show()
. We don't need a return value here, and since we will not be adding any widgets to this method FLUID will assign it a return type of void
.
Once the new method has been added, highlight its name and select New->Code->Code. Enter the method's code in the code window.
If you need to add code to initialize a class, for example setting initial values of the horizontal and vertical angles in the CubeView, you can simply highlight the constructor and select New->Code->Code. Add any required code.
Now that we have completely defined the CubeViewUI, we have to generate the code. There is one last trick to ensure this all works. Open the preferences dialog from Edit->Preferences.
At the bottom of the preferences dialog box is the key: "Include Header from Code". Select that option and set your desired file extensions and you are in business. You can include the CubeViewUI.h (or whatever extension you prefer) as you would any other C++ class.