535 lines
18 KiB
Plaintext
535 lines
18 KiB
Plaintext
|
|
/**
|
|||
|
|
|
|||
|
|
\page page_tutorial Tutorials
|
|||
|
|
|
|||
|
|
\tableofcontents
|
|||
|
|
|
|||
|
|
<!-- ---------------------------------------------------------------------- -->
|
|||
|
|
|
|||
|
|
\section fluid_hello_world_tutorial Hello, World!
|
|||
|
|
|
|||
|
|
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{inline} html flFunction.png "Function/Method"
|
|||
|
|
\image{inline} latex flFunction.png
|
|||
|
|
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.
|
|||
|
|
|
|||
|
|
\image html fluid4.png "Function/Method Properties Dialog"
|
|||
|
|
\image latex fluid4.png "Function/Method Properties Dialog" width=7cm
|
|||
|
|
|
|||
|
|
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{inline} html flWindow.png "Group/Window"
|
|||
|
|
\image{inline} latex flWindow.png
|
|||
|
|
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{inline} html flBox.png "Other/Box"
|
|||
|
|
\image{inline} latex flBox.png
|
|||
|
|
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.
|
|||
|
|
|
|||
|
|
<!-- ---------------------------------------------------------------------- -->
|
|||
|
|
|
|||
|
|
\section fluid_1of7guis_tutorial 7GUIs, Task 1
|
|||
|
|
|
|||
|
|
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.
|
|||
|
|
|
|||
|
|
\image html 1of7GUIs.png "Task 1 of 7GUIs"
|
|||
|
|
\image latex 1of7GUIs.png "Task 1 of 7GUIs" width=5cm
|
|||
|
|
|
|||
|
|
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:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
int i = counter_widget->ivalue();
|
|||
|
|
i++;
|
|||
|
|
counter_widget->value(i);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
That's it. This is a complete interactive desktop application. Compile, link,
|
|||
|
|
run, and test it to see how it works.
|
|||
|
|
|
|||
|
|
<!-- ---------------------------------------------------------------------- -->
|
|||
|
|
|
|||
|
|
\section fluid_cubeview_tutorial Cube View
|
|||
|
|
|
|||
|
|
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.
|
|||
|
|
|
|||
|
|
\image html cubeview.png "CubeView demo"
|
|||
|
|
\image latex cubeview.png "CubeView demo" width=7cm
|
|||
|
|
|
|||
|
|
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:
|
|||
|
|
|
|||
|
|
-# Use FLUID to create a complete user interface class, including
|
|||
|
|
constructor and any member functions necessary.
|
|||
|
|
-# Use FLUID to set callback member functions of custom widget classes.
|
|||
|
|
-# Subclass an Fl_Gl_Window to suit your purposes.
|
|||
|
|
|
|||
|
|
\subsection fluid_cubeview The CubeView Class
|
|||
|
|
|
|||
|
|
The CubeView class is a subclass of Fl_Gl_Window. It has methods for
|
|||
|
|
setting the zoom, the \e x and \e y pan, and the rotation angle
|
|||
|
|
about the \e x and \e 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.
|
|||
|
|
|
|||
|
|
\par The CubeView Class Definition
|
|||
|
|
|
|||
|
|
Here is the CubeView class definition, as given by its header file
|
|||
|
|
"test/CubeView.h":
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
<!-- Code copied from test/CubeView.h -->
|
|||
|
|
\code
|
|||
|
|
#include <FL/Fl.H>
|
|||
|
|
#include <FL/Fl_Gl_Window.H>
|
|||
|
|
#include <FL/gl.h>
|
|||
|
|
|
|||
|
|
class CubeView : public Fl_Gl_Window {
|
|||
|
|
|
|||
|
|
public:
|
|||
|
|
CubeView(int x, int y, int w, int h, const char *l = 0);
|
|||
|
|
|
|||
|
|
// This value determines the scaling factor used to draw the cube.
|
|||
|
|
double size;
|
|||
|
|
|
|||
|
|
/* Set the rotation about the vertical (y) axis.
|
|||
|
|
*
|
|||
|
|
* This function is called by the horizontal roller in
|
|||
|
|
* CubeViewUI and the initialize button in CubeViewUI.
|
|||
|
|
*/
|
|||
|
|
void v_angle(double angle) { vAng = angle; }
|
|||
|
|
|
|||
|
|
// Return the rotation about the vertical (y) axis.
|
|||
|
|
double v_angle() const { return vAng; }
|
|||
|
|
|
|||
|
|
/* Set the rotation about the horizontal (x) axis.
|
|||
|
|
*
|
|||
|
|
* This function is called by the vertical roller in
|
|||
|
|
* CubeViewUI and the initialize button in CubeViewUI.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
void h_angle(double angle) { hAng = angle; }
|
|||
|
|
|
|||
|
|
// The rotation about the horizontal (x) axis.
|
|||
|
|
double h_angle() const { return hAng; }
|
|||
|
|
|
|||
|
|
/* Sets the x shift of the cube view camera.
|
|||
|
|
*
|
|||
|
|
* This function is called by the slider in CubeViewUI
|
|||
|
|
* and the initialize button in CubeViewUI.
|
|||
|
|
*/
|
|||
|
|
void panx(double x) { xshift = x; }
|
|||
|
|
|
|||
|
|
/* Sets the y shift of the cube view camera.
|
|||
|
|
*
|
|||
|
|
* This function is called by the slider in CubeViewUI
|
|||
|
|
* and the initialize button in CubeViewUI.
|
|||
|
|
*/
|
|||
|
|
void pany(double y) { yshift = y; }
|
|||
|
|
|
|||
|
|
/* The widget class draw() override.
|
|||
|
|
*
|
|||
|
|
* The draw() function initializes Gl for another round of
|
|||
|
|
* drawing, then calls specialized functions for drawing each
|
|||
|
|
* of the entities displayed in the cube view.
|
|||
|
|
*/
|
|||
|
|
void draw();
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
/* Draw the cube boundaries.
|
|||
|
|
*
|
|||
|
|
* Draw the faces of the cube using the boxv[] vertices,
|
|||
|
|
* using GL_LINE_LOOP for the faces.
|
|||
|
|
*/
|
|||
|
|
void drawCube();
|
|||
|
|
|
|||
|
|
double vAng, hAng;
|
|||
|
|
double xshift, yshift;
|
|||
|
|
|
|||
|
|
float boxv0[3]; float boxv1[3];
|
|||
|
|
float boxv2[3]; float boxv3[3];
|
|||
|
|
float boxv4[3]; float boxv5[3];
|
|||
|
|
float boxv6[3]; float boxv7[3];
|
|||
|
|
};
|
|||
|
|
\endcode
|
|||
|
|
|
|||
|
|
\par The CubeView Class Implementation
|
|||
|
|
|
|||
|
|
Here is the CubeView implementation. It is very similar to the
|
|||
|
|
"CubeView" demo included with FLTK.
|
|||
|
|
<br>
|
|||
|
|
|
|||
|
|
<!-- Code copied from test/CubeView.cxx -->
|
|||
|
|
\code
|
|||
|
|
#include "CubeView.h"
|
|||
|
|
#include <math.h>
|
|||
|
|
|
|||
|
|
CubeView::CubeView(int x, int y, int w, int h, const char *l)
|
|||
|
|
: Fl_Gl_Window(x, y, w, h, l)
|
|||
|
|
{
|
|||
|
|
Fl::use_high_res_GL(1);
|
|||
|
|
vAng = 0.0;
|
|||
|
|
hAng = 0.0;
|
|||
|
|
size = 10.0;
|
|||
|
|
xshift = 0.0;
|
|||
|
|
yshift = 0.0;
|
|||
|
|
|
|||
|
|
/* The cube definition. These are the vertices of a unit cube
|
|||
|
|
* centered on the origin.*/
|
|||
|
|
|
|||
|
|
boxv0[0] = -0.5; boxv0[1] = -0.5; boxv0[2] = -0.5;
|
|||
|
|
boxv1[0] = 0.5; boxv1[1] = -0.5; boxv1[2] = -0.5;
|
|||
|
|
boxv2[0] = 0.5; boxv2[1] = 0.5; boxv2[2] = -0.5;
|
|||
|
|
boxv3[0] = -0.5; boxv3[1] = 0.5; boxv3[2] = -0.5;
|
|||
|
|
boxv4[0] = -0.5; boxv4[1] = -0.5; boxv4[2] = 0.5;
|
|||
|
|
boxv5[0] = 0.5; boxv5[1] = -0.5; boxv5[2] = 0.5;
|
|||
|
|
boxv6[0] = 0.5; boxv6[1] = 0.5; boxv6[2] = 0.5;
|
|||
|
|
boxv7[0] = -0.5; boxv7[1] = 0.5; boxv7[2] = 0.5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CubeView::drawCube() {
|
|||
|
|
/* Draw a colored cube */
|
|||
|
|
#define ALPHA 0.5
|
|||
|
|
glShadeModel(GL_FLAT);
|
|||
|
|
|
|||
|
|
glBegin(GL_QUADS);
|
|||
|
|
glColor4f(0.0, 0.0, 1.0, ALPHA);
|
|||
|
|
glVertex3fv(boxv0);
|
|||
|
|
glVertex3fv(boxv1);
|
|||
|
|
glVertex3fv(boxv2);
|
|||
|
|
glVertex3fv(boxv3);
|
|||
|
|
|
|||
|
|
glColor4f(1.0, 1.0, 0.0, ALPHA);
|
|||
|
|
glVertex3fv(boxv0);
|
|||
|
|
glVertex3fv(boxv4);
|
|||
|
|
glVertex3fv(boxv5);
|
|||
|
|
glVertex3fv(boxv1);
|
|||
|
|
|
|||
|
|
glColor4f(0.0, 1.0, 1.0, ALPHA);
|
|||
|
|
glVertex3fv(boxv2);
|
|||
|
|
glVertex3fv(boxv6);
|
|||
|
|
glVertex3fv(boxv7);
|
|||
|
|
glVertex3fv(boxv3);
|
|||
|
|
|
|||
|
|
glColor4f(1.0, 0.0, 0.0, ALPHA);
|
|||
|
|
glVertex3fv(boxv4);
|
|||
|
|
glVertex3fv(boxv5);
|
|||
|
|
glVertex3fv(boxv6);
|
|||
|
|
glVertex3fv(boxv7);
|
|||
|
|
|
|||
|
|
glColor4f(1.0, 0.0, 1.0, ALPHA);
|
|||
|
|
glVertex3fv(boxv0);
|
|||
|
|
glVertex3fv(boxv3);
|
|||
|
|
glVertex3fv(boxv7);
|
|||
|
|
glVertex3fv(boxv4);
|
|||
|
|
|
|||
|
|
glColor4f(0.0, 1.0, 0.0, ALPHA);
|
|||
|
|
glVertex3fv(boxv1);
|
|||
|
|
glVertex3fv(boxv5);
|
|||
|
|
glVertex3fv(boxv6);
|
|||
|
|
glVertex3fv(boxv2);
|
|||
|
|
glEnd();
|
|||
|
|
|
|||
|
|
glColor3f(1.0, 1.0, 1.0);
|
|||
|
|
glBegin(GL_LINES);
|
|||
|
|
glVertex3fv(boxv0);
|
|||
|
|
glVertex3fv(boxv1);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv1);
|
|||
|
|
glVertex3fv(boxv2);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv2);
|
|||
|
|
glVertex3fv(boxv3);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv3);
|
|||
|
|
glVertex3fv(boxv0);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv4);
|
|||
|
|
glVertex3fv(boxv5);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv5);
|
|||
|
|
glVertex3fv(boxv6);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv6);
|
|||
|
|
glVertex3fv(boxv7);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv7);
|
|||
|
|
glVertex3fv(boxv4);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv0);
|
|||
|
|
glVertex3fv(boxv4);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv1);
|
|||
|
|
glVertex3fv(boxv5);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv2);
|
|||
|
|
glVertex3fv(boxv6);
|
|||
|
|
|
|||
|
|
glVertex3fv(boxv3);
|
|||
|
|
glVertex3fv(boxv7);
|
|||
|
|
glEnd();
|
|||
|
|
} // drawCube
|
|||
|
|
|
|||
|
|
void CubeView::draw() {
|
|||
|
|
if (!valid()) {
|
|||
|
|
glLoadIdentity();
|
|||
|
|
glViewport(0, 0, pixel_w(), pixel_h());
|
|||
|
|
glOrtho(-10, 10, -10, 10, -20050, 10000);
|
|||
|
|
glEnable(GL_BLEND);
|
|||
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|||
|
|
|
|||
|
|
glPushMatrix();
|
|||
|
|
|
|||
|
|
glTranslatef((GLfloat)xshift, (GLfloat)yshift, 0);
|
|||
|
|
glRotatef((GLfloat)hAng, 0, 1, 0);
|
|||
|
|
glRotatef((GLfloat)vAng, 1, 0, 0);
|
|||
|
|
glScalef(float(size), float(size), float(size));
|
|||
|
|
|
|||
|
|
drawCube();
|
|||
|
|
|
|||
|
|
glPopMatrix();
|
|||
|
|
}
|
|||
|
|
\endcode
|
|||
|
|
|
|||
|
|
\subsection fluid_cubeview_ui The CubeViewUI Class
|
|||
|
|
|
|||
|
|
We will completely construct a window to display and control the
|
|||
|
|
CubeView defined in the previous section using FLUID.
|
|||
|
|
|
|||
|
|
\par Defining the CubeViewUI Class
|
|||
|
|
|
|||
|
|
Once you have started FLUID, the first step in defining a class is to
|
|||
|
|
create a new class within FLUID using the <b>New->Code->Class</b>
|
|||
|
|
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.
|
|||
|
|
|
|||
|
|
\image html fluid1.png "FLUID file for CubeView"
|
|||
|
|
\image latex fluid1.png "FLUID file for CubeView" width=7cm
|
|||
|
|
|
|||
|
|
\par Adding the Class Constructor
|
|||
|
|
|
|||
|
|
Click on the CubeViewUI class in the FLUID window and add a new method
|
|||
|
|
by selecting <b>New->Code->Function/Method.</b> 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
|
|||
|
|
<b>New->Group->Window</b>. In a similar manner add the
|
|||
|
|
following to the CubeViewUI constructor:
|
|||
|
|
|
|||
|
|
\li A horizontal roller named \p hrot
|
|||
|
|
\li A vertical roller named \p vrot
|
|||
|
|
\li A horizontal slider named \p xpan
|
|||
|
|
\li A vertical slider named \p ypan
|
|||
|
|
\li A horizontal value slider named \p 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:
|
|||
|
|
|
|||
|
|
\image html fluid2.png "FLUID window containing CubeView demo"
|
|||
|
|
\image latex fluid2.png "FLUID window containing CubeView demo" width=7cm
|
|||
|
|
|
|||
|
|
We will talk about the \p show() method that is highlighted
|
|||
|
|
shortly.
|
|||
|
|
|
|||
|
|
\par Adding the CubeView Widget
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
<b>New->Other->Box</b> 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 <b>Class:</b> text
|
|||
|
|
entry box. This tells FLUID that it is not an Fl_Box, but a
|
|||
|
|
similar widget with the same constructor.
|
|||
|
|
|
|||
|
|
In the <b>Extra Code:</b> field enter <tt>\#include "CubeView.h"</tt>
|
|||
|
|
|
|||
|
|
This \p \#include is important, as we have just included
|
|||
|
|
CubeView as a member of CubeViewUI, so any public CubeView methods are
|
|||
|
|
now available to CubeViewUI.
|
|||
|
|
|
|||
|
|
\image html fluid3-cxx.png "CubeView methods"
|
|||
|
|
\image latex fluid3-cxx.png "CubeView methods" width=7cm
|
|||
|
|
|
|||
|
|
\par Defining the Callbacks
|
|||
|
|
|
|||
|
|
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 <b>Callback</b>
|
|||
|
|
field of the widget panel. For example, the callback for the
|
|||
|
|
\p ypan slider is:
|
|||
|
|
|
|||
|
|
\code
|
|||
|
|
cube->pany(((Fl_Slider *)o)->value());
|
|||
|
|
cube->redraw();
|
|||
|
|
\endcode
|
|||
|
|
|
|||
|
|
We call <tt>cube->redraw()</tt> 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.
|
|||
|
|
|
|||
|
|
\par Adding a Class Method
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
<b>New->Code->Function/Method</b>. Just use the name
|
|||
|
|
\p 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 \p void.
|
|||
|
|
|
|||
|
|
\image html fluid4.png "CubeView constructor"
|
|||
|
|
\image latex fluid4.png "CubeView constructor" width=7cm
|
|||
|
|
|
|||
|
|
Once the new method has been added, highlight its name and select
|
|||
|
|
<b>New->Code->Code.</b> Enter the method's code in the code window.
|
|||
|
|
|
|||
|
|
\subsection fluid_addconst Adding Constructor Initialization Code
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
<b>New->Code->Code</b>. Add any required code.
|
|||
|
|
|
|||
|
|
\subsection fluid_gencode Generating the 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 <b>Edit->Preferences</b>.
|
|||
|
|
|
|||
|
|
At the bottom of the preferences dialog box is the key:
|
|||
|
|
<b>"Include Header from Code"</b>.
|
|||
|
|
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.
|
|||
|
|
|
|||
|
|
*/
|