f9039b2ae2
git-svn-id: file:///fltk/svn/fltk/trunk@2 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
215 lines
7.9 KiB
Plaintext
215 lines
7.9 KiB
Plaintext
Fluid (the FL User Interface Designer) is a graphical editor that
|
|
is used to produce FL source code.
|
|
|
|
Fluid edits and saves it's state in ".fl" files. These files are
|
|
text, and you could (with care) edit them in a text editor, perhaps to
|
|
get some special effects.
|
|
|
|
When asked to "compile", fluid outputs a .C source file and a .H
|
|
header file: The .C file contains one or more public functions, each
|
|
of which will create one or more FL windows and all the objects in
|
|
those windows. The .H file declares (as externs) all the functions
|
|
and named objects created by the .C file, and includes all the
|
|
necessary FL header files for those objects.
|
|
|
|
The C file must be compiled and linked with a "main" source file(s)
|
|
that you write. This source code must include the .H output, and
|
|
should call the functions in the .C file to create windows. The main
|
|
code must do show() on the windows and run the Fl::wait() loop.
|
|
|
|
_________
|
|
/ /
|
|
__________ +->/.C file /--------+
|
|
/ / / /________/ |
|
|
/.fl file /<==>[fluid]< #include |
|
|
/_________/ \ ___v_____ |
|
|
\ / / |
|
|
+>/.H file / |
|
|
/________/ |
|
|
^ |
|
|
#include |
|
|
___|_____ | __________
|
|
/ / V / /
|
|
/ main.C /--->[c++,link]-->/ program /
|
|
/________/ /_________/
|
|
|
|
|
|
Objects created by fluid are either "named" or "unnamed". If they
|
|
are named, the .C file will declare a global variable with that name
|
|
of type "<type>*". This pointer has a value of zero until the fluid
|
|
function is called, the fluid function will set it to the instance of
|
|
the . Unnamed objects are only accessible through
|
|
pointers from other objects.
|
|
|
|
Windows may be named or unnamed. Named windows are only created
|
|
once even if you call the function several times (fluid outputs "if
|
|
(!name) {...}" around the code that creates the window). Unnamed
|
|
windows lets you create many instances of the same window structure, a
|
|
pointer to the unnamed window is returned from the fluid function (you
|
|
can only put one unnamed window in a function).
|
|
|
|
Objects may either call a named callback function that you write in
|
|
another source file, or you can supply a small piece of C++ source and
|
|
fluid will write a private callback function into the .C file.
|
|
|
|
================================================================
|
|
Worlds shortest tutorial:
|
|
================================================================
|
|
|
|
Type "fluid&"
|
|
|
|
Pick "New/Function" off the menu.
|
|
|
|
Delete the function name in the popup window and hit OK. The text
|
|
"main()" with a triangle next to it should appear highlighted in the
|
|
main window.
|
|
|
|
Pick "New/Window" off the menu.
|
|
|
|
Move the window and resize it to the size you want.
|
|
|
|
Pick "New/buttons/Button" off the menu.
|
|
|
|
Hit the "OK" button to dismiss the panel that appears.
|
|
|
|
In the window you created, try moving the button by dragging it
|
|
around. Notice that it "snaps" to fixed locations. If you want to
|
|
drag it smoothly, hold down Alt. You can also change the size of the
|
|
steps with Edit/Preferences.
|
|
|
|
Try resizing the object by dragging the edges and corners.
|
|
|
|
Type Alt+c to copy the object.
|
|
|
|
Type Alt+v to paste a copy into the window.
|
|
|
|
Type Alt+v several times.
|
|
|
|
Drag the objects and resize them so they don't overlap. Notice
|
|
that you have to click an object to pick it first, then drag it.
|
|
|
|
Try selecting several objects by dragging a box around them. Check
|
|
what happens when you move them, or when you drag an edge to resize
|
|
them.
|
|
|
|
You can also use Shift+click to toggle objects on and off.
|
|
|
|
You can also select objects by clicking on them in the list in the
|
|
main window, try that.
|
|
|
|
Double-click one of the buttons. You will get a control panel.
|
|
|
|
Try changing the "label". Try changing other items near the top of
|
|
the panel. To see any changes to the box type clearer, type "Alt+o"
|
|
to make the red overlay disappear.
|
|
|
|
Type "#include <stdlib.h>" into the first line of "extra code:".
|
|
|
|
Type "exit(0);" into the "callback:".
|
|
|
|
Hit OK.
|
|
|
|
Pick "File/Save As" off the menu.
|
|
|
|
Type "test.fl" into the file chooser and hit return.
|
|
|
|
Pick "File/Write Code" off the menu.
|
|
|
|
Go back to your terminal window. Type "more test.C" and "more
|
|
test.H" and you can see the code it made.
|
|
|
|
Type "make test" (you may have to add libaries to your Makefile).
|
|
|
|
Type "./test" to run your program.
|
|
|
|
Try the buttons. The one you put the code into will exit the
|
|
program.
|
|
|
|
Type "Alt+Q" to exit fluid.
|
|
|
|
Ok, now try to make a real program.
|
|
|
|
================================================================
|
|
|
|
This code is quite a kludge and probably impossible to figure out. I
|
|
hope it will be fixed someday, but my intention was to make FL itself
|
|
clean and simple, even if the user interface designer is forced to be
|
|
more complex as a result.
|
|
|
|
An object in fluid is represented by a subclass of "Fl_Type".
|
|
|
|
Creating a new instance of an object is done by calling the virtual
|
|
method "make()" on Fl_Type. To allow an initial version of each type
|
|
to be created, there is a static "factory" instance of every subclass
|
|
of Fl_Type. For now, make() is only called on these. The intention
|
|
was to use make() to copy objects, but that did not happen. Instead I
|
|
write the descriptions and read them back from a file in /usr/tmp,
|
|
which is much more reliable because the read/write code is tested
|
|
every time a file is saved!
|
|
|
|
The (non-factory) instances are linked into a list by the previous and
|
|
next pointers. The "hierarchy" is stored by a "level" number on each
|
|
object, and an "isparent" flag on the parent. To find the "brother"
|
|
of an object, code must search forward for the next object whose level
|
|
is equal to this one. A null pointer or an object with a lower level
|
|
number indicates no brother.
|
|
|
|
If the type is a subclass of Fl_Object, the "o" pointer points at an
|
|
Fl_Object. This allows the code in FL to be used to draw the object.
|
|
The user_data() field on the Fl_Object is used as a back pointer to
|
|
the Fl_Type. The "factory" has an "o" pointer that points at the
|
|
"template object". This is an Fl_Object created the first time make()
|
|
is called and is used to figure out what the default values for the
|
|
fields are for the object.
|
|
|
|
This "o" pointer exists in all Fl_Type objects, even the base class.
|
|
If this is not an Fl_Object item, then the "o" pointer is zero. This
|
|
avoided a lot of virtual functions, but is mostly for historical
|
|
reasons. Rather than RTTI, I use some tests to determine subclasses:
|
|
|
|
if (o && level == 1)
|
|
this is an Fl_Window_Type
|
|
else if (o && isparent)
|
|
this is a Fl_Group_Type
|
|
else if (o)
|
|
this is a Fl_Object_Type
|
|
else if (!level)
|
|
this is a function
|
|
else
|
|
this is a menu item or something
|
|
(none of these implemented yet)
|
|
|
|
|
|
Fl_Type::first
|
|
|
|
|
| NULL
|
|
| ^
|
|
V |
|
|
+---------+ +-----------+
|
|
| Fl_Type |------ o ---> | Fl_Window |
|
|
| level=0 |<-user_data()-| |
|
|
|isparent |<-+ +-----------+
|
|
+---------+ | | ^
|
|
| ^ parent first |
|
|
next prev / | parent
|
|
V | / V |
|
|
+---------+ +-----------+
|
|
| Fl_Type |------ o ---> | Fl_Object |
|
|
| level=1 | | |
|
|
| |<-user_data()-| |
|
|
| | +-----------+
|
|
| | +---------+
|
|
| |-factory->| Fl_Type |---- o ---->[Fl_Object]
|
|
+---------+ | | template object
|
|
| ^ +---------+
|
|
next prev (next,prev=NULL)
|
|
V |
|
|
+---------+
|
|
| Fl_Type |
|
|
+---------+
|
|
| ^
|
|
V |
|
|
NULL |
|
|
|
|
|
Fl_Type::last
|