diff options
| -rw-r--r-- | documentation/basics.dox | 362 | ||||
| -rw-r--r-- | documentation/common.dox | 667 | ||||
| -rw-r--r-- | documentation/drawing.dox | 967 | ||||
| -rw-r--r-- | documentation/editor.dox | 905 | ||||
| -rw-r--r-- | documentation/enumerations.dox | 304 | ||||
| -rw-r--r-- | documentation/events.dox | 389 | ||||
| -rw-r--r-- | documentation/examples.dox | 448 | ||||
| -rw-r--r-- | documentation/fluid.dox | 1359 | ||||
| -rw-r--r-- | documentation/forms.dox | 201 | ||||
| -rw-r--r-- | documentation/glut.dox | 193 | ||||
| -rw-r--r-- | documentation/index.dox | 104 | ||||
| -rw-r--r-- | documentation/intro.dox | 367 | ||||
| -rw-r--r-- | documentation/license.dox | 437 | ||||
| -rw-r--r-- | documentation/migration_1_1.dox | 158 | ||||
| -rw-r--r-- | documentation/migration_1_3.dox | 11 | ||||
| -rw-r--r-- | documentation/opengl.dox | 463 | ||||
| -rw-r--r-- | documentation/osissues.dox | 740 | ||||
| -rw-r--r-- | documentation/preface.dox | 2 | ||||
| -rw-r--r-- | documentation/subclassing.dox | 431 |
19 files changed, 8454 insertions, 54 deletions
diff --git a/documentation/basics.dox b/documentation/basics.dox new file mode 100644 index 000000000..3c330f907 --- /dev/null +++ b/documentation/basics.dox @@ -0,0 +1,362 @@ +/** + + \page basics 2 - FLTK Basics + + <P>This chapter teaches you the basics of compiling programs +that use FLTK.</P> + +<H2>Writing Your First FLTK Program</H2> + +<P>All programs must include the file <TT><FL/Fl.H></TT>. +In addition the program must include a header file for each +FLTK class it uses. Listing 1 shows a simple "Hello, +World!" program that uses FLTK to display the window.</P> + +<UL> +<P><I>Listing 1 - "hello.cxx"</I> +<PRE> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/Fl_Box.H> + +int main(int argc, char **argv) { + <A href="Fl_Window.html">Fl_Window</A> *window = new <A href="Fl_Window.html#Fl_Window.Fl_Window">Fl_Window</A>(300,180); + <A href="Fl_Box.html">Fl_Box</A> *box = new <A href="Fl_Box.html#Fl_Box.Fl_Box">Fl_Box</A>(20,40,260,100,"Hello, World!"); + box-><A href="Fl_Widget.html#Fl_Widget.box">box</A>(<A href="common.html#boxtypes">FL_UP_BOX</A>); + box-><A href="Fl_Widget.html#Fl_Widget.labelsize">labelsize</A>(36); + box-><A href="Fl_Widget.html#Fl_Widget.labelfont">labelfont</A>(<A href="drawing.html#fonts">FL_BOLD</A>+<A href="drawing.html#fonts">FL_ITALIC</A>); + box-><A href="Fl_Widget.html#Fl_Widget.labeltype">labeltype</A>(<A href="common.html#labels">FL_SHADOW_LABEL</A>); + window-><A href="Fl_Group.html#Fl_Group.end">end</A>(); + window-><A href="Fl_Window.html#Fl_Window.show">show</A>(argc, argv); + return <A href="Fl.html#Fl.run">Fl::run</A>(); +} +</PRE></UL> + +<!-- NEED 2in --> + +<P>After including the required header files, the program then creates a +window. All following widgets will automatically be children of this window.</P> + +<UL><PRE> +Fl_Window *window = new <A href="Fl_Window.html#Fl_Window">Fl_Window</A>(300,180); +</PRE></UL> + +<P>Then we create a box with the "Hello, World!" string in it. FLTK automatically adds +the new box to <tt>window</tt>, the current grouping widget.</P> + +<UL><PRE> +Fl_Box *box = new <A href="Fl_Box.html#Fl_Box">Fl_Box</A>(20,40,260,100,"Hello, World!"); +</PRE></UL> + +<P>Next, we set the type of box and the size, font, and style of the label:</P> + +<UL><PRE> +box-><A href="Fl_Widget.html#Fl_Widget.box">box</A>(FL_UP_BOX); +box-><A href=Fl_Widget.html#Fl_Widget.labelsize>labelsize</A>(36); +box-><A href=Fl_Widget.html#Fl_Widget.labelfont>labelfont</A>(FL_BOLD+FL_ITALIC); +box-><A href=Fl_Widget.html#Fl_Widget.labeltype>labeltype</A>(FL_SHADOW_LABEL); +</PRE></UL> + +<P>We tell FLTK that we will not add any more widgets to <tt>window</tt>.</P> + +<UL><PRE> +window-><A href=Fl_Group.html#Fl_Group.end>end</A>(); +</PRE></UL> + +<P>Finally, we show the window and enter the FLTK event loop:</P> + +<UL><PRE> +window-><A href=Fl_Window.html#Fl_Window.show>show</A>(argc, argv); +return <A href="Fl.html#Fl.run">Fl::run</A>(); +</PRE></UL> + +<P>The resulting program will display the window in Figure 2-1. +You can quit the program by closing the window or pressing the +<KBD>ESC</KBD>ape key.</P> + +<P ALIGN="CENTER"><IMG src="hello.C.gif" alt="Hello, World! Window"><BR> +<I>Figure 2-1: The Hello, World! Window</I></P> + +<H3>Creating the Widgets</H3> + +<P>The widgets are created using the C++ <TT>new</TT> operator. For +most widgets the arguments to the constructor are:</P> + +<UL><PRE> +Fl_Widget(x, y, width, height, label) +</PRE></UL> + +<P>The <TT>x</TT> and <TT>y</TT> parameters determine where the +widget or window is placed on the screen. In FLTK the top left +corner of the window or screen is the origin (i.e. x = 0, y = +0) and the units are in pixels.</P> + +<P>The <TT>width</TT> and <TT>height</TT> parameters determine +the size of the widget or window in pixels. The maximum widget +size is typically governed by the underlying window system or +hardware.</P> + +<P><tt>label</tt> is a pointer to a character string to label +the widget with or <tt>NULL</tt>. If not specified the label +defaults to <tt>NULL</tt>. The label string must be in static +storage such as a string constant because FLTK does not make a +copy of it - it just uses the pointer.</P> + +<H3>Creating Widget hierarchies</H3> + +<P>Widgets are commonly ordered into functional groups, which +in turn may be grouped again, creating a hierarchy of widgets. +FLTK makes it easy to fill groups by automatically adding all widgets +that are created between a <tt>myGroup->begin()</tt> and +<tt>myGroup->end()</tt>. In this example, <tt>myGroup</tt> +would be the <i>current</i> group.</P> + +<P>Newly created groups and their derived widgets implicitly call +<tt>begin()</tt> in the constructor, effectively adding all +subsequently created widgets to itself until <tt>end()</tt> +is called.</P> + +<P>Setting the current group to <tt>NULL</tt> will stop automatic +hierarchies. New widgets can now be added manually using +<tt>Fl_Group::add(...)</tt> and <tt>Fl_Group::insert(...)</tt>.</P> + +<H3>Get/Set Methods</H3> + +<P><tt>box->box(FL_UP_BOX)</tt> sets the type of box the +Fl_Box draws, changing it from the default of +<tt>FL_NO_BOX</tt>, which means that no box is drawn. In our +"Hello, World!" example we use <TT>FL_UP_BOX</TT>, +which means that a raised button border will be drawn around +the widget. You can learn more about boxtypes in +<A href="common.html#boxtypes">Chapter 3</A>.</P> + +<P>You could examine the boxtype in by doing +<tt>box->box()</tt>. FLTK uses method name overloading to make +short names for get/set methods. A "set" method is always of +the form "void name(type)", and a "get" method is always +of the form "type name() const".</P> + +<H3>Redrawing After Changing Attributes</H3> + +<P>Almost all of the set/get pairs are very fast, short inline +functions and thus very efficient. However, <i>the "set" methods +do not call <TT>redraw()</TT></i> - you have to call it +yourself. This greatly reduces code size and execution time. The +only common exceptions are <tt>value()</tt> which calls +<TT>redraw()</TT> and <tt>label()</tt> which calls +<TT>redraw_label()</TT> if necessary.</P> + +<H3>Labels</H3> + +<P>All widgets support labels. In the case of window widgets, +the label is used for the label in the title bar. Our example +program calls the <A href=Fl_Widget.html#Fl_Widget.labelfont> +<TT>labelfont</TT></A>, +<A href=Fl_Widget.html#Fl_Widget.labelsize><TT> labelsize</TT></A>, +and <A href=Fl_Widget.html#Fl_Widget.labeltype><TT>labeltype</TT></A> +methods.</P> + +<P>The <TT>labelfont</TT> method sets the typeface and style +that is used for the label, which for this example we are using +<TT>FL_BOLD</TT> and <TT>FL_ITALIC</TT>. You can also specify +typefaces directly. </P> <P>The <TT>labelsize</TT> method sets +the height of the font in pixels. </P> <P>The <TT>labeltype</TT> +method sets the type of label. FLTK supports normal, embossed, +and shadowed labels internally, and more types can be added as +desired.</P> + +<P>A complete list of all label options can be found in +<A href="common.html#labels">Chapter 3</A>.</P> + +<H3>Showing the Window</H3> + +<P>The <TT>show()</TT> method shows the widget or window. For windows +you can also provide the command-line arguments to allow users to +customize the appearance, size, and position of your windows.</P> + +<H3>The Main Event Loop</H3> + +<P>All FLTK applications (and most GUI applications in general) +are based on a simple event processing model. User actions such +as mouse movement, button clicks, and keyboard activity generate +events that are sent to an application. The application may then +ignore the events or respond to the user, typically by redrawing +a button in the "down" position, adding the text to an input +field, and so forth.</P> + +<P>FLTK also supports idle, timer, and file pseudo-events that +cause a function to be called when they occur. Idle functions +are called when no user input is present and no timers or files +need to be handled - in short, when the application is not doing +anything. Idle callbacks are often used to update a 3D display +or do other background processing.</P> + +<P>Timer functions are called after a specific amount of time +has expired. They can be used to pop up a progress dialog after +a certain amount of time or do other things that need to happen +at more-or-less regular intervals. FLTK timers are not 100% +accurate, so they should not be used to measure time intervals, +for example.</P> + +<P>File functions are called when data is ready to read or +write, or when an error condition occurs on a file. They are +most often used to monitor network connections (sockets) for +data-driven displays.</P> + +<P>FLTK applications must periodically check +(<TT>Fl::check()</TT>) or wait (<TT>Fl::wait()</TT>) for events +or use the <A href="Fl.html#Fl.run"><TT>Fl::run()</TT></A> +method to enter a standard event processing loop. Calling +<TT>Fl::run()</TT> is equivalent to the following code:</P> + +<UL><PRE> +while (Fl::wait()); +</PRE></UL> + +<P><TT>Fl::run()</TT> does not return until all of the windows +under FLTK control are closed by the user or your program.</P> + +<H2>Compiling Programs with Standard Compilers</H2> + +<P>Under UNIX (and under Microsoft Windows when using the GNU development +tools) you will probably need to tell the compiler where to find the +header files. This is usually done using the <TT>-I</TT> option:</P> + +<UL><PRE> +CC -I/usr/local/include ... +gcc -I/usr/local/include ... +</PRE></UL> + +<P>The <TT>fltk-config</TT> script included with FLTK can be +used to get the options that are required by your compiler:</P> + +<UL><PRE> +CC `fltk-config --cxxflags` ... +</PRE></UL> + +<P>Similarly, when linking your application you will need to tell the +compiler to use the FLTK library:</P> + +<UL><PRE> +CC ... -L/usr/local/lib -lfltk -lXext -lX11 -lm +gcc ... -L/usr/local/lib -lfltk -lXext -lX11 -lm +</PRE></UL> + +<P>Aside from the "fltk" library, there is also a "fltk_forms" +library for the XForms compatibility classes, "fltk_gl" for the +OpenGL and GLUT classes, and "fltk_images" for the image file +classes, <A +HREF="Fl_Help_Dialog.html#Fl_Help_Dialog"><CODE>Fl_Help_Dialog</CODE></A> +widget, and system icon support. + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="10" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + <P>The libraries are named "fltk.lib", "fltkgl.lib", "fltkforms.lib", + and "fltkimages.lib", respectively under Windows. + </TD> +</TR> +</TABLE></CENTER> + +<P>As before, the <TT>fltk-config</TT> script included with FLTK can be +used to get the options that are required by your linker:</P> + +<UL><PRE> +CC ... `fltk-config --ldflags` +</PRE></UL> + +<!-- NEED 2in --> + +<P>The forms, GL, and images libraries are included with the "--use-foo" +options, as follows: + +<UL><PRE> +CC ... `fltk-config --use-forms --ldflags` +CC ... `fltk-config --use-gl --ldflags` +CC ... `fltk-config --use-images --ldflags` +CC ... `fltk-config --use-forms --use-gl --use-images --ldflags` +</PRE></UL> + +<P>Finally, you can use the <TT>fltk-config</TT> script to +compile a single source file as a FLTK program: + +<UL><PRE> +fltk-config --compile filename.cpp +fltk-config --use-forms --compile filename.cpp +fltk-config --use-gl --compile filename.cpp +fltk-config --use-images --compile filename.cpp +fltk-config --use-forms --use-gl --use-images --compile filename.cpp +</PRE></UL> + +<P>Any of these will create an executable named <TT>filename</TT>. + +<H2>Compiling Programs with Microsoft Visual C++</H2> + +<P>In Visual C++ you will need to tell the compiler where to +find the FLTK header files. This can be done by selecting +"Settings" from the "Project" menu and then +changing the "Preprocessor" settings under the +"C/C++" tab. You will also need to add the FLTK and +WinSock (WSOCK32.LIB) libraries to the "Link" +settings.</P> + +<P>You can build your Microsoft Windows applications as Console or +WIN32 applications. If you want to use the standard C <TT>main()</TT> +function as the entry point, FLTK includes a <TT>WinMain()</TT> +function that will call your <TT>main()</TT> function for you.</P> + +<P><I>Note: The Visual C++ 5.0 optimizer is known to cause problems with +many programs. We only recommend using the "Favor Small Code" +optimization setting.</I> The Visual C++ 6.0 optimizer seems to be much +better and can be used with the "optimized for speed" setting.</P> + +<H2>Naming</H2> + +<P>All public symbols in FLTK start with the characters 'F' and 'L':</P> + +<UL> + + <LI>Functions are either <TT>Fl::foo()</TT> or + <TT>fl_foo()</TT>.</LI> + + <LI>Class and type names are capitalized: + <TT>Fl_Foo</TT>.</LI> + + <LI><A href="enumerations.html">Constants and + enumerations</A> are uppercase: <TT>FL_FOO</TT>.</LI> + + <LI>All header files start with <TT><FL/...></TT>. + </LI> + +</UL> + +<!-- NEED 5in --> + +<H2>Header Files</H2> + +<P>The proper way to include FLTK header files is:</P> + +<UL><PRE> +#include <FL/Fl_xyz.H> +</PRE></UL> + +<CENTER><TABLE BORDER="1" CELLPADDING="10" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>Case <I>is</I> significant on many operating systems, + and the C standard uses the forward slash (/) to + separate directories. <i>Do not use any of the following + include lines:</i></P> + + <UL><PRE> + #include <FL\Fl_xyz.H> + #include <fl/fl_xyz.h> + #include <Fl/fl_xyz.h> + </PRE></UL> + + </TD> +</TR> +</TABLE></CENTER> + +*/ diff --git a/documentation/common.dox b/documentation/common.dox new file mode 100644 index 000000000..20553873e --- /dev/null +++ b/documentation/common.dox @@ -0,0 +1,667 @@ +/** + + \page common 3 - Common Widgets and Attributes + +<P>This chapter describes many of the widgets that are provided +with FLTK and covers how to query and set the standard +attributes.</P> + +<H2>Buttons</H2> + +<P>FLTK provides many types of buttons:</P> + +<UL> + + <LI><A HREF="Fl_Button.html"><TT>Fl_Button</TT></A> - A + standard push button.</LI> + + <LI><A HREF="Fl_Check_Button.html"><TT>Fl_Check_Button</TT></A> - + A button with a check box.</LI> + + <LI><A HREF="Fl_Light_Button.html"><TT>Fl_Light_Button</TT></A> - + A push button with a light.</LI> + + <LI><A HREF="Fl_Repeat_Button.html"><TT>Fl_Repeat_Button</TT></A> - + A push button that repeats when held.</LI> + + <LI><A HREF="Fl_Return_Button.html"><TT>Fl_Return_Button</TT></A> - + A push button that is activated by the <KBD>Enter</KBD> key.</LI> + + <LI><A HREF="Fl_Round_Button.html"><TT>Fl_Round_Button</TT></A> - + A button with a radio circle.</LI> + +</UL> + +<P ALIGN="CENTER"><IMG SRC="buttons.gif" ALT="FLTK Buttons"><BR> +Figure 3-1: FLTK Button Widgets</P> + +<P>All of these buttons just need the corresponding +<TT><FL/Fl_xyz_Button.H></TT> header file. The constructor +takes the bounding box of the button and optionally a label +string:</P> + +<UL><PRE> +Fl_Button *button = new Fl_Button(x, y, width, height, "label"); +Fl_Light_Button *lbutton = new Fl_Light_Button(x, y, width, height); +Fl_Round_Button *rbutton = new Fl_Round_Button(x, y, width, height, "label"); +</PRE></UL> + +<P>Each button has an associated +<A href="Fl_Button.html#Fl_Button.type"><TT>type()</TT></A> +which allows it to behave as a push button, toggle button, or +radio button:</P> + +<UL><PRE> +button->type(FL_NORMAL_BUTTON); +lbutton->type(FL_TOGGLE_BUTTON); +rbutton->type(FL_RADIO_BUTTON); +</PRE></UL> + +<P>For toggle and radio buttons, the +<A href="Fl_Button.html#Fl_Button.value"><TT>value()</TT></A> +method returns the current button state (0 = off, 1 = on). The +<A href="Fl_Button.html#Fl_Button.set"><TT>set()</TT></A> and +<A href="Fl_Button.html#Fl_Button.clear"><TT>clear()</TT></A> +methods can be used on toggle buttons to turn a toggle button +on or off, respectively. Radio buttons can be turned on with +the +<A href="Fl_Button.html#Fl_Button.setonly"><TT>setonly()</TT></A> +method; this will also turn off other radio buttons in the same +group.</P> + +<H2>Text</H2> + +<P>FLTK provides several text widgets for displaying and receiving text:</P> + +<UL> + + <LI><A HREF="Fl_Input.html"><TT>Fl_Input</TT></A> - A + one-line text input field.</LI> + + <LI><A HREF="Fl_Output.html"><TT>Fl_Output</TT></A> - A + one-line text output field.</LI> + + <LI><A HREF="Fl_Multiline_Input.html"><TT>Fl_Multiline_Input</TT></A> + - A multi-line text input field. </LI> + + <LI><A HREF="Fl_Multiline_Output.html"><TT>Fl_Multiline_Output</TT></A> + - A multi-line text output field.</LI> + + <LI><A HREF="Fl_Text_Display.html"><TT>Fl_Text_Display</TT></A> + - A multi-line text display widget.</LI> + + <LI><A HREF="Fl_Text_Editor.html"><TT>Fl_Text_Editor</TT></A> - + A multi-line text editing widget. </LI> + + <LI><A HREF="Fl_Help_View.html"><TT>Fl_Help_View</TT></A> - A + HTML text display widget.</LI> + +</UL> + +<P>The <TT>Fl_Output</TT> and <TT>Fl_Multiline_Output</TT> +widgets allow the user to copy text from the output field but +not change it.</P> + +<P>The <A href="Fl_Input.html#Fl_Input.value"><TT>value()</TT></A> +method is used to get or set the string that is displayed:</P> + +<UL><PRE> +Fl_Input *input = new Fl_Input(x, y, width, height, "label"); +input->value("Now is the time for all good men..."); +</PRE></UL> + +<P>The string is copied to the widget's own storage when you set +the <tt>value()</tt> of the widget.</P> + +<P>The <TT>Fl_Text_Display</TT> and <TT>Fl_Text_Editor</TT> +widgets use an associated <TT>Fl_Text_Buffer</TT> class for the +value, instead of a simple string.</P> + +<!-- NEED 4in --> + +<H2>Valuators</H2> + +<P>Unlike text widgets, valuators keep track of numbers instead of +strings. FLTK provides the following valuators:</P> + +<UL> + + <LI><A HREF="Fl_Counter.html"><TT>Fl_Counter</TT></A> - A widget with arrow buttons that shows the + current value. </LI> + + <LI><A HREF="Fl_Dial.html"><TT>Fl_Dial</TT></A> - A round knob. </LI> + + <LI><A HREF="Fl_Roller.html"><TT>Fl_Roller</TT></A> - An SGI-like dolly widget. </LI> + + <LI><A HREF="Fl_Scrollbar.html"><TT>Fl_Scrollbar</TT></A> - A standard scrollbar widget. </LI> + + <LI><A HREF="Fl_Slider.html"><TT>Fl_Slider</TT></A> - A scrollbar with a knob. </LI> + + <LI><A HREF="Fl_Value_Slider.html"><TT>Fl_Value_Slider</TT></A> - A slider that shows the current value. </LI> + +</UL> + +<P ALIGN="CENTER"><IMG SRC="valuators.gif" ALT="FLTK Valuators"><BR> +<I>Figure 3-2: FLTK valuator widgets</I></P> + +<P>The <A href="Fl_Valuator.html#Fl_Valuator.value"><TT>value()</TT></A> +method gets and sets the current value of the widget. The +<A href="Fl_Valuator.html#Fl_Valuator.minimum"><TT>minimum()</TT></A> +and <A href="Fl_Valuator.html#Fl_Valuator.maximum"><TT>maximum()</TT></A> +methods set the range of values that are reported by the +widget.</P> + +<!-- NEED 5in --> + +<H2>Groups</H2> + +<P>The <TT>Fl_Group</TT> widget class is used as a general +purpose "container" widget. Besides grouping radio +buttons, the groups are used to encapsulate windows, tabs, and +scrolled windows. The following group classes are available +with FLTK:</P> + +<UL> + + <LI><A HREF="Fl_Double_Window.html"><TT>Fl_Double_Window</TT></A> - A double-buffered window on the screen. </LI> + + <LI><A HREF="Fl_Gl_Window.html"><TT>Fl_Gl_Window</TT></A> - An OpenGL window on the screen. </LI> + + <LI><A HREF="Fl_Group.html"><TT>Fl_Group</TT></A> - The base container class; can be used to group + any widgets together. </LI> + + <LI><A HREF="Fl_Pack.html"><TT>Fl_Pack</TT></A> - A collection of widgets that are packed into the group area.</LI> + + <LI><A HREF="Fl_Scroll.html"><TT>Fl_Scroll</TT></A> - A scrolled window area. </LI> + + <LI><A HREF="Fl_Tabs.html"><TT>Fl_Tabs</TT></A> - Displays child widgets as tabs. </LI> + + <LI><A HREF="Fl_Tile.html"><TT>Fl_Tile</TT></A> - A tiled window area.</LI> + + <LI><A HREF="Fl_Window.html"><TT>Fl_Window</TT></A> - A window on the screen. </LI> + +</UL> + +<H2>Setting the Size and Position of Widgets</H2> + +<P>The size and position of widgets is usually set when you +create them. You can access them with the <tt>x()</tt>, +<tt>y()</tt>, <tt>w()</tt>, and <tt>h()</tt> methods.</P> + +<P>You can change the size and position by using the +<TT>position()</TT>, <TT> resize()</TT>, and <TT>size()</TT> +methods:</P> + +<UL><PRE> +button->position(x, y); +group->resize(x, y, width, height); +window->size(width, height); +</PRE></UL> + +<P>If you change a widget's size or position after it is +displayed you will have to call <tt>redraw()</tt> on the +widget's parent.</P> + +<H2><A NAME="colors">Colors</A></H2> + +<P>FLTK stores the colors of widgets as an 32-bit unsigned +number that is either an index into a color palette of 256 +colors or a 24-bit RGB color. The color palette is <i>not</i> +the X or WIN32 colormap, but instead is an internal table with +fixed contents.</P> + +<P>There are symbols for naming some of the more common colors:</P> + +<UL> + <LI><TT>FL_BLACK</TT></LI> + + <LI><TT>FL_RED</TT></LI> + + <LI><TT>FL_GREEN</TT></LI> + + <LI><TT>FL_YELLOW</TT></LI> + + <LI><TT>FL_BLUE</TT></LI> + + <LI><TT>FL_MAGENTA</TT></LI> + + <LI><TT>FL_CYAN</TT></LI> + + <LI><TT>FL_WHITE</TT></LI> +</UL> + +<P>These symbols are the default colors for all FLTK widgets. They are +explained in more detail in the chapter +<A HREF="enumerations.html#colors">Enumerations</A></P> + +<UL> + <LI><TT>FL_FOREGROUND_COLOR</TT> </LI> + + <LI><TT>FL_BACKGROUND_COLOR</TT> </LI> + + <LI><TT>FL_INACTIVE_COLOR</TT> </LI> + + <LI><TT>FL_SELECTION_COLOR</TT> </LI> +</UL> + +<P>RGB colors can be set using the <A HREF="functions.html#fl_rgb_color"><TT>fl_rgb_color()</TT></A> +function:</P> + +<UL><PRE> +Fl_Color c = fl_rgb_color(85, 170, 255); +</PRE></UL> + +<P>The widget color is set using the <TT>color()</TT> method:</P> + +<UL><PRE> +button->color(FL_RED); +</PRE></UL> + +<P>Similarly, the label color is set using the <TT>labelcolor()</TT> +method:</P> + +<UL><PRE> +button->labelcolor(FL_WHITE); +</PRE></UL> + +<H2><A NAME="boxtypes">Box Types</A></H2> + +<P>The type <TT>Fl_Boxtype</TT> stored and returned in +<A href="Fl_Widget.html#Fl_Widget.box"><TT>Fl_Widget::box()</TT></A> +is an enumeration defined in <A href="enumerations.html#Enumerations"><TT><Enumerations.H></TT></A>. +Figure 3-3 shows the standard box types included with FLTK.</P> + +<P ALIGN="CENTER"><IMG src="boxtypes.gif" ALT="FLTK Box Types"><BR> +<I>Figure 3-3: FLTK box types</I></P> + +<P><TT>FL_NO_BOX</TT> means nothing is drawn at all, so whatever is +already on the screen remains. The <TT>FL_..._FRAME</TT> types only +draw their edges, leaving the interior unchanged. The blue color in +Figure 3-3 is the area that is not drawn by the frame types.</P> + +<H3>Making Your Own Boxtypes</H3> + +<P>You can define your own boxtypes by making a small function that draws +the box and adding it to the table of boxtypes.</P> + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + <P>This interface has changed in FLTK 2.0!</P> + </TD> +</TR> +</TABLE></CENTER> + +<H4>The Drawing Function</H4> + +<P>The drawing function is passed the bounding box and background color +for the widget:</P> + +<UL><PRE> +void xyz_draw(int x, int y, int w, int h, Fl_Color c) { +... +} +</PRE></UL> + +<!-- NEED 3in --> + +<P>A simple drawing function might fill a rectangle with the +given color and then draw a black outline:</P> + +<UL><PRE> +void xyz_draw(int x, int y, int w, int h, Fl_Color c) { + fl_color(c); + fl_rectf(x, y, w, h); + fl_color(FL_BLACK); + fl_rect(x, y, w, h); +} +</PRE></UL> + +<H4><A name="fl_down">Fl_Boxtype fl_down(Fl_Boxtype)</A></H4> + +<P><tt>fl_down</tt> returns the "pressed" or "down" version of a box. +If no "down" version of a given box exists, the behavior of this function +is undefined and some random box or frame is returned. +See also: <A HREF="drawing.html#fl_frame">fl_frame drawing</A>. + +<H4><A name="fl_frame">Fl_Boxtype fl_frame(Fl_Boxtype)</A></H4> + +<P><tt>fl_frame</tt> returns the unfilled, frame-only version of a box. +If no frame version of a given box exists, the behavior of this function +is undefined and some random box or frame is returned. +See also: <A HREF="drawing.html#fl_frame">fl_frame drawing</A>. + +<H4><A name="fl_box">Fl_Boxtype fl_box(Fl_Boxtype)</A></H4> + +<P><tt>fl_box</tt> returns the filled version of a frame. +If no filled version of a given frame exists, the behavior of this function +is undefined and some random box or frame is returned. +See also: <TT><A HREF="#fl_frame">fl_frame</A></TT>. + +<H4>Adding Your Box Type</H4> + +<P>The <TT>Fl::set_boxtype()</TT> method adds or replaces the +specified box type:</P> + +<UL><PRE> +#define XYZ_BOX FL_FREE_BOXTYPE + +Fl::set_boxtype(XYZ_BOX, xyz_draw, 1, 1, 2, 2); +</PRE></UL> + +<P>The last 4 arguments to <TT>Fl::set_boxtype()</TT> are the +offsets for the x, y, width, and height values that should be +subtracted when drawing the label inside the box.</P> + +<P>A complete box design contains four box types in this order: +a filled, neutral box (<TT>UP_BOX</TT>), a filled, depressed box +(<TT>DOWN_BOX</TT>), and the same as outlines only (<TT>UP_FRAME</TT> +and <TT>DOWN_FRAME</TT>). The function +<TT><A HREF="#fl_down">fl_down(Fl_Boxtype)</A></TT> +expects the neutral design on a boxtype with a numerical +value evenly divideable by two. +<TT><A HREF="#fl_frame">fl_frame(Fl_Boxtype)</A></TT> +expects the <TT>UP_BOX</TT> design at a value divideable by four.</P> + +<H2><A NAME="labels">Labels and Label Types</A></H2> + +<P>The <TT>label()</TT>, <TT>align()</TT>, <TT>labelfont()</TT>, +<TT>labelsize()</TT>, <TT>labeltype()</TT>, <TT>image()</TT>, and +<TT>deimage()</TT> methods control the labeling of widgets.</P> + +<H3>label()</H3> + +<P>The <TT>label()</TT> method sets the string that is displayed +for the label. Symbols can be included with the label string by +escaping them using the "@" symbol - "@@" displays a single at +sign. Figure 3-4 shows the available symbols.</P> + +<P ALIGN="CENTER"><A name="symbols"><IMG src="symbols.gif" ALT="FLTK Symbols"><BR> +<I>Figure 3-4: FLTK label symbols</I></A></P> + +<!-- NEED 2in --> + +<P>The @ sign may also be followed by the following optional +"formatting" characters, in this order:</P> + +<UL> + + <LI>'#' forces square scaling, rather than distortion to + the widget's shape.</LI> + + <LI>+[1-9] or -[1-9] tweaks the scaling a little bigger + or smaller.</LI> + + <LI>'$' flips the symbol horizontaly, '%' flips it verticaly.</LI> + + <LI>[0-9] - rotates by a multiple of 45 degrees. '5' and + '6' do no rotation while the others point in the + direction of that key on a numeric keypad. '0', followed by four + more digits rotates the symbol by that amount in degrees.</LI> + +</UL> + +<P>Thus, to show a very large arrow pointing downward you would use the +label string "@+92->". + +<H3>align()</H3> + +<P>The <TT>align()</TT> method positions the label. The following +constants are defined and may be OR'd together as needed:</P> + +<UL> + + <LI><TT>FL_ALIGN_CENTER</TT> - center the label in the widget.</LI> + + <LI><TT>FL_ALIGN_TOP</TT> - align the label at the top of the widget.</LI> + + <LI><TT>FL_ALIGN_BOTTOM</TT> - align the label at the bottom of the + widget.</LI> + + <LI><TT>FL_ALIGN_LEFT</TT> - align the label to the left of the widget.</LI> + + <LI><TT>FL_ALIGN_RIGHT</TT> - align the label to the right of the + widget.</LI> + + <LI><TT>FL_ALIGN_INSIDE</TT> - align the label inside the widget.</LI> + + <LI><TT>FL_ALIGN_CLIP</TT> - clip the label to the widget's bounding + box.</LI> + + <LI><TT>FL_ALIGN_WRAP</TT> - wrap the label text as needed.</LI> + + <LI><TT>FL_TEXT_OVER_IMAGE</TT> - show the label text over the image.</LI> + + <LI><TT>FL_IMAGE_OVER_TEXT</TT> - show the label image over the text (default).</LI> + +</UL> + +<H3><A NAME="labeltypes">labeltype()</A></H3> + +<P>The <TT>labeltype()</TT> method sets the type of the label. The +following standard label types are included:</P> + +<UL> + + <LI><TT>FL_NORMAL_LABEL</TT> - draws the text.</LI> + + <LI><TT>FL_NO_LABEL</TT> - does nothing.</LI> + + <LI><TT>FL_SHADOW_LABEL</TT> - draws a drop shadow under + the text.</LI> + + <LI><TT>FL_ENGRAVED_LABEL</TT> - draws edges as though + the text is engraved.</LI> + + <LI><TT>FL_EMBOSSED_LABEL</TT> - draws edges as thought + the text is raised.</LI> + + <LI><TT>FL_ICON_LABEL</TT> - draws the icon associated + with the text.</LI> + +</UL> + +<H3>image() and deimage()</H3> + +<P>The <TT>image()</TT> and <TT>deimage()</TT> methods set an image that +will be displayed with the widget. The <TT>deimage()</TT> method sets the +image that is shown when the widget is inactive, while the <TT>image()</TT> +method sets the image that is shown when the widget is active.</P> + +<P>To make an image you use a subclass of +<A HREF="drawing.html#Fl_Image"><TT>Fl_Image</TT></A>.</P> + +<H4>Making Your Own Label Types</H4> + +<P>Label types are actually indexes into a table of functions +that draw them. The primary purpose of this is to use this to +draw the labels in ways inaccessible through the +<TT>fl_font</TT> mechanisim (e.g. <TT>FL_ENGRAVED_LABEL</TT>) or +with program-generated letters or symbology.</P> + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + <P>This interface has changed in FLTK 2.0!</P> + </TD> +</TR> +</TABLE></CENTER> + +<H5>Label Type Functions</H5> + +<P>To setup your own label type you will need to write two +functions: one to draw and one to measure the label. The draw +function is called with a pointer to a <TT>Fl_Label</TT> +structure containing the label information, the bounding box for +the label, and the label alignment:</P> + +<UL><PRE> +void xyz_draw(const Fl_Label *label, int x, int y, int w, int h, Fl_Align align) { +... +} +</PRE></UL> + +<P>The label should be drawn <I>inside</I> this bounding box, +even if <TT>FL_ALIGN_INSIDE</TT> is not enabled. The function +is not called if the label value is <TT>NULL</TT>.</P> + +<P>The measure function is called with a pointer to a +<TT>Fl_Label</TT> structure and references to the width and +height:</P> + +<UL><PRE> +void xyz_measure(const Fl_Label *label, int &w, int &h) { +... +} +</PRE></UL> + +<P>The function should measure the size of the label and set +<TT>w</TT> and <TT>h</TT> to the size it will occupy.</P> + +<H5>Adding Your Label Type</H5> + +<P>The <TT>Fl::set_labeltype</TT> method creates a label type +using your draw and measure functions:</P> + +<UL><PRE> +#define XYZ_LABEL FL_FREE_LABELTYPE + +Fl::set_labeltype(XYZ_LABEL, xyz_draw, xyz_measure); +</PRE></UL> + +<P>The label type number <TT>n</TT> can be any integer value +starting at the constant <TT>FL_FREE_LABELTYPE</TT>. Once you +have added the label type you can use the <TT>labeltype()</TT> +method to select your label type.</P> + +<P>The <TT>Fl::set_labeltype</TT> method can also be used to overload +an existing label type such as <TT>FL_NORMAL_LABEL</TT>.</P> + +<H4><A NAME="add_symbol">Making your own symbols</A></H4> + +<P>It is also possible to define your own drawings and add +them to the symbol list, so they can be rendered as part of +any label.</P> + +<P>To create a new symbol, you implement a drawing function +<tt>void drawit(Fl_Color c)</tt> which typically uses the +<a href="drawing.html#complex">complex drawing functions</a> +to generate a vector shape inside a two-by-two units sized box +around the origin. This function is then linked into the symbols +table using <tt>fl_add_symbol</tt>:</P> + +<UL><PRE> +<A NAME="fl_add_symbol">int fl_add_symbol(const char *name, void (*drawit)(Fl_Color), int scalable)</A> +</PRE></UL> + +<P><i>name</i> is the name of the symbol without the "@"; <i>scalable</I> +must be set to 1 if the symbol is generated using scalable vector drawing +functions.</P> + +<UL><PRE> +<A NAME="fl_draw_symbol">int fl_draw_symbol(const char *name,int x,int y,int w,int h,Fl_Color col)</A> +</PRE></UL> + +<P>This function draw a named symbol fitting the given rectangle. + +<H2>Callbacks</H2> + +<P>Callbacks are functions that are called when the value of a +widget changes. A callback function is sent a <TT>Fl_Widget</TT> +pointer of the widget that changed and a pointer to data that +you provide:</P> + +<UL><PRE> +void xyz_callback(Fl_Widget *w, void *data) { +... +} +</PRE></UL> + +<P>The <TT>callback()</TT> method sets the callback function for a +widget. You can optionally pass a pointer to some data needed for the +callback:</P> + +<UL><PRE> +int xyz_data; + +button->callback(xyz_callback, &xyz_data); +</PRE></UL> + +<P>Normally callbacks are performed only when the value of the +widget changes. You can change this using the +<A href="Fl_Widget.html#Fl_Widget.when"><TT>when()</TT></A> +method:</P> + +<UL><PRE> +button->when(FL_WHEN_NEVER); +button->when(FL_WHEN_CHANGED); +button->when(FL_WHEN_RELEASE); +button->when(FL_WHEN_RELEASE_ALWAYS); +button->when(FL_WHEN_ENTER_KEY); +button->when(FL_WHEN_ENTER_KEY_ALWAYS); +button->when(FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED); +</PRE></UL> + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>You cannot delete a widget inside a callback, as the + widget may still be accessed by FLTK after your callback + is completed. Instead, use the <a + href='Fl.html#Fl.delete_widget'><tt>Fl::delete_widget()</tt></a> + method to mark your widget for deletion when it is safe + to do so.</p> + + <p><B>Hint:</B> + + <P>Many programmers new to FLTK or C++ try to use a + non-static class method instead of a static class method + or function for their callback. Since callbacks are done + outside a C++ class, the <TT>this</TT> pointer is not + initialized for class methods.</P> + + <P>To work around this problem, define a static method + in your class that accepts a pointer to the class, and + then have the static method call the class method(s) as + needed. The data pointer you provide to the + <TT>callback()</TT> method of the widget can be a + pointer to the instance of your class.</P> + +<PRE> +class Foo { + void my_callback(Fl_Widget *w); + static void my_static_callback(Fl_Widget *w, void *f) { ((Foo *)f)->my_callback(w); } + ... +} + +... + +w->callback(my_static_callback, (void *)this); +</PRE> + </TD> +</TR> +</TABLE></CENTER> + +<H2>Shortcuts</H2> + +<P>Shortcuts are key sequences that activate widgets such as +buttons or menu items. The <TT>shortcut()</TT> method sets the +shortcut for a widget:</P> + +<UL><PRE> +button->shortcut(FL_Enter); +button->shortcut(FL_SHIFT + 'b'); +button->shortcut(FL_CTRL + 'b'); +button->shortcut(FL_ALT + 'b'); +button->shortcut(FL_CTRL + FL_ALT + 'b'); +button->shortcut(0); // no shortcut +</PRE></UL> + +<P>The shortcut value is the key event value - the ASCII value +or one of the special keys like +<a href="enumerations.html#key_values"><TT>FL_Enter</TT></a> - +combined with any modifiers like <KBD>Shift</KBD>, +<KBD>Alt</KBD>, and <KBD>Control</KBD>.</P> + +*/ diff --git a/documentation/drawing.dox b/documentation/drawing.dox new file mode 100644 index 000000000..29694cc00 --- /dev/null +++ b/documentation/drawing.dox @@ -0,0 +1,967 @@ +/** + + \page drawing 5 - Drawing Things in FLTK + +<P>This chapter covers the drawing functions that are provided with FLTK. + +<H2>When Can You Draw Things in FLTK?</H2> + +<P>There are only certain places you can execute drawing code in FLTK. +Calling these functions at other places will result in undefined +behavior! + +<UL> + + <LI>The most common place is inside the virtual method + <A + href="subclassing.html#draw"><TT>Fl_Widget::draw()</TT></A>. + To write code here, you must subclass one of the + existing <TT>Fl_Widget</TT> classes and implement your + own version of <TT>draw()</TT>.</LI> + + <LI>You can also write <A + href="common.html#boxtypes">boxtypes</A> and <A + href="common.html#labeltypes">labeltypes</A>. These are + small procedures that can be called by existing <A + HREF="subclassing.html#draw"><TT>Fl_Widget::draw()</TT></A> + methods. These "types" are identified by an + 8-bit index that is stored in the widget's + <TT>box()</TT>, <TT>labeltype()</TT>, and possibly other + properties.</LI> + + <LI>You can call <A + href="Fl_Window.html#Fl_Window.make_current"><TT>Fl_Window::make_current()</TT></A> + to do incremental update of a widget. Use <A + href=Fl_Widget.html#Fl_Widget.window><TT>Fl_Widget::window()</TT></A> + to find the window.</LI> + +</UL> + +<H2>FLTK Drawing Functions</H2> + +<P>To use the drawing functions you must first include the +<TT><FL/fl_draw.H></TT> header file. FLTK provides the +following types of drawing functions: + +<UL> + + <LI><A href="#boxdraw">Boxes</A></LI> + + <LI><A href="#clipping">Clipping</A></LI> + + <LI><A href="#colors">Colors</A></LI> + + <LI><A href="#lines">Line dashes and thickness</A></LI> + + <LI><A href="#fast">Fast Shapes</A></LI> + + <LI><A href="#complex">Complex Shapes</A></LI> + + <LI><A href="#text">Text</A></LI> + + <LI><A href="#images">Images</A></LI> + + <LI><A href="#overlay">Overlay</A></LI> + + <LI><A href="#offscreen">Offscreen Drawing</A></LI> + +</UL> + +<H3><A name="boxdraw">Boxes</A></H3> + +<P>FLTK provides three functions that can be used to draw boxes +for buttons and other UI controls. Each function uses the +supplied upper-lefthand corner and width and height to determine +where to draw the box. + +<H4><A NAME="fl_draw_box">void fl_draw_box(Fl_Boxtype b, int x, int y, int w, int h, Fl_Color c);</A></H4> + +<P>The first box drawing function is <CODE>fl_draw_box()</CODE> +which draws a standard boxtype <CODE>c</CODE> in the specified +color <CODE>c</CODE>. + +<H4><A NAME="fl_frame">void fl_frame(const char *s, int x, int y, int w, int h);</A></H4> + +<P>The <CODE>fl_frame()</CODE> function draws a series of line +segments around the given box. The string <CODE>s</CODE> must +contain groups of 4 letters which specify one of 24 standard +grayscale values, where 'A' is black and 'X' is white. The order +of each set of 4 characters is: top, left, bottom, right. The +results of calling <CODE>fl_frame()</CODE> with a string that is +not a multiple of 4 characters in length are undefined. + +<P>The only difference between this function and +<CODE>fl_frame2()</CODE> is the order of the line segments. + +<P>See also: <A HREF="common.html#fl_frame">fl_frame boxtype</A>. + +<H4><A NAME="fl_frame2">void fl_frame2(const char *s, int x, int y, int w, int h);</A></H4> + +<P>The <CODE>fl_frame2()</CODE> function draws a series of line +segments around the given box. The string <CODE>s</CODE> must +contain groups of 4 letters which specify one of 24 standard +grayscale values, where 'A' is black and 'X' is white. The order +of each set of 4 characters is: bottom, right, top, left. The +results of calling <CODE>fl_frame2()</CODE> with a string that is +not a multiple of 4 characters in length are undefined. + +<P>The only difference between this function and +<CODE>fl_frame()</CODE> is the order of the line segments. + +<H3><A name="clipping">Clipping</A></H3> + +<P>You can limit all your drawing to a rectangular region by calling +<TT>fl_push_clip</TT>, and put the drawings back by using <TT>fl_pop_clip</TT>. +This rectangle is measured in pixels and is unaffected by the current +transformation matrix. + +<P>In addition, the system may provide clipping when updating windows +which may be more complex than a simple rectangle.</P> + +<H4><A name="fl_push_clip">void fl_clip(int x, int y, int w, int h)</A><BR> +void fl_push_clip(int x, int y, int w, int h)</H4> + +<P>Intersect the current clip region with a rectangle and push this new +region onto the stack. The <CODE>fl_clip()</CODE> name is deprecated and +will be removed from future releases. + +<H4><A NAME=fl_push_no_clip>void fl_push_no_clip()</A></H4> + +<P>Pushes an empty clip region on the stack so nothing will be clipped. + +<H4><A NAME=fl_pop_clip>void fl_pop_clip()</A></H4> + +<P>Restore the previous clip region. + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>You must call <TT>fl_pop_clip()</TT> once for every + time you call <TT>fl_push_clip()</TT>. If you return to FLTK + with the clip stack not empty unpredictable results + occur. + + </TD> +</TR> +</TABLE></CENTER> + +<H4><A NAME=fl_not_clipped>int fl_not_clipped(int x, int y, int w, int h)</A></H4> + +<P>Returns non-zero if any of the rectangle intersects the current clip +region. If this returns 0 you don't have to draw the object. + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>Under X this returns 2 if the rectangle is partially + clipped, and 1 if it is entirely inside the clip region. + + </TD> +</TR> +</TABLE></CENTER> + +<H4><A NAME=fl_clip_box>int fl_clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, +int &H)</A></H4> + +<P>Intersect the rectangle <TT>x,y,w,h</TT> with the current +clip region and returns the bounding box of the result in +<TT>X,Y,W,H</TT>. Returns non-zero if the resulting rectangle is +different than the original. This can be used to limit the +necessary drawing to a rectangle. <TT>W</TT> and <TT>H</TT> are +set to zero if the rectangle is completely outside the region. + +<H4><A NAME=fl_clip_region>void fl_clip_region(Fl_Region r) +<BR>Fl_Region fl_clip_region()</A></H4> + +<P>Replace the top of the clip stack with a clipping region of any shape. +Fl_Region is an operating system specific type. The second form returns +the current clipping region. + +<H3><A name="colors">Colors</A></H3> + +<P>FLTK manages colors as 32-bit unsigned integers. Values from +0 to 255 represent colors from the FLTK 1.0.x standard colormap +and are allocated as needed on screens without TrueColor +support. The <TT>Fl_Color</TT> enumeration type defines the +standard colors and color cube for the first 256 colors. All of +these are named with symbols in <A +href="enumerations.html#colors"><TT><FL/Enumerations.H></TT></A>. + +<P>Color values greater than 255 are treated as 24-bit RGB +values. These are mapped to the closest color supported by the +screen, either from one of the 256 colors in the FLTK 1.0.x +colormap or a direct RGB value on TrueColor screens. You can +generate 24-bit RGB color values using the <A +HREF="functions.html#fl_rgb_color"><TT>fl_rgb_color()</TT></A> +function. + +<H4><A name="fl_color">void fl_color(Fl_Color)</A></H4> + +<P>Sets the color for all subsequent drawing operations. + +<P>For colormapped displays, a color cell will be allocated out +of <TT>fl_colormap</TT> the first time you use a color. If the +colormap fills up then a least-squares algorithm is used to find +the closest color.</P> + +<H4>Fl_Color fl_color()</H4> + +<P>Returns the last <TT>fl_color()</TT> that was set. This can +be used for state save/restore. + +<H4>void fl_color(uchar r, uchar g, uchar b)</H4> + +<P>Set the color for all subsequent drawing operations. The +closest possible match to the RGB color is used. The RGB color +is used directly on TrueColor displays. For colormap visuals the +nearest index in the gray ramp or color cube is used. + +<h3><A name="lines">Line Dashes and Thickness</a></h3> + +<P>FLTK supports drawing of lines with different styles and +widths. Full functionality is not available under Windows 95, 98, +and Me due to the reduced drawing functionality these operating +systems provide. + +<h4><A NAME="fl_line_style">void fl_line_style(int style, int width=0, char* dashes=0)</A></h4> + +<P>Set how to draw lines (the "pen"). If you change this it is your +responsibility to set it back to the default with +<tt>fl_line_style(0)</tt>. + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>Because of how line styles are implemented on WIN32 + systems, you <I>must</I> set the line style <I>after</I> + setting the drawing color. If you set the color after + the line style you will lose the line style settings! + + </TD> +</TR> +</TABLE></CENTER> + +<P><i>style</i> is a bitmask which is a bitwise-OR of the following +values. If you don't specify a dash type you will get a solid +line. If you don't specify a cap or join type you will get a +system-defined default of whatever value is fastest. + +<ul> + + <li><tt>FL_SOLID -------</tt> + + <li><tt>FL_DASH - - - -</tt> + + <li><tt>FL_DOT .......</tt> + + <li><tt>FL_DASHDOT - . - .</tt> + + <li><tt>FL_DASHDOTDOT - .. -</tt> + + <li><tt>FL_CAP_FLAT</tt> + + <li><tt>FL_CAP_ROUND</tt> + + <li><tt>FL_CAP_SQUARE</tt> (extends past end point 1/2 line width) + + <li><tt>FL_JOIN_MITER</tt> (pointed) + + <li><tt>FL_JOIN_ROUND</tt> + + <li><tt>FL_JOIN_BEVEL</tt> (flat) + +</ul> + +<P><i>width</i> is the number of pixels thick to draw the lines. +Zero results in the system-defined default, which on both X and +Windows is somewhat different and nicer than 1. + +<!-- NEED 4in --> + +<P><i>dashes</i> is a pointer to an array of dash lengths, measured in +pixels. The first location is how long to draw a solid portion, the +next is how long to draw the gap, then the solid, etc. It is +terminated with a zero-length entry. A <TT>NULL</TT> pointer or a zero-length +array results in a solid line. Odd array sizes are not supported and +result in undefined behavior. + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>The dashes array does not work under Windows 95, 98, + or Me, since those operating systems do not support + complex line styles. + + </TD> +</TR> +</TABLE></CENTER> + +<H3><A name="fast">Drawing Fast Shapes</A></H3> + +<P>These functions are used to draw almost all the FLTK widgets. +They draw on exact pixel boundaries and are as fast as possible. +Their behavior is duplicated exactly on all platforms FLTK is +ported. It is undefined whether these are affected by the <A +href="#complex">transformation matrix</A>, so you should only +call these while the matrix is set to the identity matrix (the +default). + +<H4><A NAME=fl_point>void fl_point(int x, int y)</A></H4> + +<P>Draw a single pixel at the given coordinates. + +<H4><A NAME=fl_rectf>void fl_rectf(int x, int y, int w, int h) +<BR>void fl_rectf(int x, int y, int w, int h)</A></H4> + +<P>Color a rectangle that exactly fills the given bounding box. + +<H4>void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b)</H4> + +<P>Color a rectangle with "exactly" the passed +<TT>r,g,b</TT> color. On screens with less than 24 bits of +color this is done by drawing a solid-colored block using <A +href="#fl_draw_image"><TT>fl_draw_image()</TT></A> so that +the correct color shade is produced. + +<H4><A NAME=fl_rect>void fl_rect(int x, int y, int w, int h) +<BR>void fl_rect(int x, int y, int w, int h, Fl_Color c)</A></H4> + +<P>Draw a 1-pixel border <I>inside</I> this bounding box. + +<H4><A NAME=fl_line>void fl_line(int x, int y, int x1, int y1) +<BR>void fl_line(int x, int y, int x1, int y1, int x2, int y2)</A></H4> + +<P>Draw one or two lines between the given points. + +<H4><A NAME=fl_loop>void fl_loop(int x, int y, int x1, int y1, int x2, int y2) +<BR>void fl_loop(int x, int y, int x1, int y1, int x2, int y2, int x3, +int y3)</A></H4> + +<P>Outline a 3 or 4-sided polygon with lines. + +<H4><A NAME=fl_polygon>void fl_polygon(int x, int y, int x1, int y1, int x2, int y2) +<BR>void fl_polygon(int x, int y, int x1, int y1, int x2, int y2, int +x3, int y3)</A></H4> + +<P>Fill a 3 or 4-sided polygon. The polygon must be convex. + +<H4><A NAME=fl_xyline>void fl_xyline(int x, int y, int x1) +<BR>void fl_xyline(int x, int y, int x1, int y2) +<BR>void fl_xyline(int x, int y, int x1, int y2, int x3)</A></H4> + +<P>Draw horizontal and vertical lines. A horizontal line is +drawn first, then a vertical, then a horizontal. + +<H4><A NAME=fl_yxline>void fl_yxline(int x, int y, int y1) +<BR>void fl_yxline(int x, int y, int y1, int x2) +<BR>void fl_yxline(int x, int y, int y1, int x2, int y3)</A></H4> + +<P>Draw vertical and horizontal lines. A vertical line is drawn +first, then a horizontal, then a vertical. + +<H4><A NAME=fl_pie>void fl_arc(int x, int y, int w, int h, double a1, double a2) +<BR>void fl_pie(int x, int y, int w, int h, double a1, double a2)</A></H4> + +<P>Draw ellipse sections using integer coordinates. These +functions match the rather limited circle drawing code provided +by X and WIN32. The advantage over using <A +href="#fl_arc"><TT>fl_arc</TT></A> with floating point +coordinates is that they are faster because they often use the +hardware, and they draw much nicer small circles, since the +small sizes are often hard-coded bitmaps. + +<P>If a complete circle is drawn it will fit inside the passed bounding +box. The two angles are measured in degrees counterclockwise from +3'oclock and are the starting and ending angle of the arc, <TT>a2</TT> +must be greater or equal to <TT>a1</TT>.</P> + +<P><TT>fl_arc()</TT> draws a series of lines to approximate the arc. +Notice that the integer version of <TT>fl_arc()</TT> has a different +number of arguments than the <A href="#fl_arc"><TT>fl_arc()</TT></A> +function described later in this chapter.</P> + +<P><TT>fl_pie()</TT> draws a filled-in pie slice. This slice may +extend outside the line drawn by <TT>fl_arc</TT>; to avoid this +use <TT>w - 1</TT> and <TT>h - 1</TT>.</P> + +<h4><a name=fl_scroll>void fl_scroll(int X, int Y, int W, int H, int dx, int dy, +void (*draw_area)(void*, int,int,int,int), void* data)</a></h4> + +<P>Scroll a rectangle and draw the newly exposed portions. The contents +of the rectangular area is first shifted by <tt>dx</tt> and +<tt>dy</tt> pixels. The callback is then called for every newly +exposed rectangular area, + +<H3><A name="complex">Drawing Complex Shapes</A></H3> + +<P>The complex drawing functions let you draw arbitrary shapes +with 2-D linear transformations. The functionality matches that +found in the Adobe® PostScript<SUP>TM</SUP> language. The +exact pixels that are filled are less defined than for the fast +drawing functions so that FLTK can take advantage of drawing +hardware. On both X and WIN32 the transformed vertices are +rounded to integers before drawing the line segments: this +severely limits the accuracy of these functions for complex +graphics, so use OpenGL when greater accuracy and/or performance +is required. + +<H4><A NAME=fl_push_matrix>void fl_push_matrix() +<BR>void fl_pop_matrix()</A></H4> + +<P>Save and restore the current transformation. The maximum +depth of the stack is 4. + +<H4><A NAME=fl_scale>void fl_scale(float x, float y) +<BR>void fl_scale(float x) +<BR>void fl_translate(float x, float y) +<BR>void fl_rotate(float d) +<BR>void fl_mult_matrix(float a, float b, float c, float d, float +x, float y)</A></H4> + +<P>Concatenate another transformation onto the current one. The rotation +angle is in degrees (not radians) and is counter-clockwise. + +<H4><A NAME=fl_transform>double fl_transform_x(double x, double y) +<BR>double fl_transform_y(double x, double y) +<BR>double fl_transform_dx(double x, double y) +<BR>double fl_transform_dy(double x, double y) +<BR>void fl_transformed_vertex(double xf, double yf)</A></H4> + +<P>Transform a coordinate or a distance trough the current transformation matrix. +After transforming a coordinate pair, it can be added to the vertex +list without any forther translations using <tt>fl_transformed_vertex</tt>. + +<H4><A NAME=fl_begin_points>void fl_begin_points() +<BR>void fl_end_points()</A></H4> + +<P>Start and end drawing a list of points. Points are added to +the list with <tt>fl_vertex</tt>. + +<H4><A NAME=fl_begin_line>void fl_begin_line() +<BR>void fl_end_line()</A></H4> + +<P>Start and end drawing lines. + +<H4><A NAME=fl_begin_loop>void fl_begin_loop() +<BR> void fl_end_loop()</A></H4> + +<P>Start and end drawing a closed sequence of lines. + +<H4><A NAME=fl_begin_polygon>void fl_begin_polygon() +<BR>void fl_end_polygon()</A></H4> + +<P>Start and end drawing a convex filled polygon. + +<H4><A NAME=fl_begin_complex_polygon>void fl_begin_complex_polygon() +<BR>void fl_gap() +<BR>void fl_end_complex_polygon()</A></H4> + +<P>Start and end drawing a complex filled polygon. This polygon +may be concave, may have holes in it, or may be several +disconnected pieces. Call <TT>fl_gap()</TT> to seperate loops of +the path. It is unnecessary but harmless to call +<TT>fl_gap()</TT> before the first vertex, after the last one, +or several times in a row. + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>For portability, you should only draw polygons that + appear the same whether "even/odd" or + "non-zero" winding rules are used to fill + them. Holes should be drawn in the opposite direction of + the outside loop. + + </TD> +</TR> +</TABLE></CENTER> + +<P><TT>fl_gap()</TT> should only be called between <TT> +fl_begin_complex_polygon()</TT> and +<TT>fl_end_complex_polygon()</TT>. To outline the polygon, use +<TT>fl_begin_loop()</TT> and replace each <TT>fl_gap()</TT> with +<TT>fl_end_loop();fl_begin_loop()</TT>.</P> + +<H4><A NAME=fl_vertex>void fl_vertex(float x, float y)</A></H4> +Add a single vertex to the current path. + +<H4><A NAME=fl_curve>void fl_curve(float x, float y, float x1, float y1, float x2, float +y2, float x3, float y3)</A></H4> + +<P>Add a series of points on a Bezier curve to the path. The curve ends +(and two of the points) are at <TT>x,y</TT> and <TT>x3,y3</TT>. + +<H4><A NAME="fl_arc">void fl_arc(float x, float y, float r, float start, float end)</A></H4> + +<P>Add a series of points to the current path on the arc of a +circle; you can get elliptical paths by using scale and rotate +before calling <TT>fl_arc()</TT>. <TT>x,y</TT> are the center of +the circle, and <TT>r</TT> is its radius. <TT>fl_arc()</TT> +takes <TT>start</TT> and <TT>end</TT> angles that are measured +in degrees counter-clockwise from 3 o'clock. If <TT>end</TT> is +less than <TT>start</TT> then it draws the arc in a clockwise +direction. + +<H4><A NAME=fl_circle>void fl_circle(float x, float y, float r)</A></H4> + +<P><TT>fl_circle()</TT> is equivalent to <TT>fl_arc(...,0,360)</TT> but +may be faster. It must be the <I>only</I> thing in the path: if you +want a circle as part of a complex polygon you must use <TT>fl_arc()</TT>. + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P><TT>fl_circle()</TT> draws incorrectly if the + transformation is both rotated and non-square scaled. + + </TD> +</TR> +</TABLE></CENTER> + +<H3><A name="text">Drawing Text</A></H3> + +<P>All text is drawn in the <A href="#fl_font">current font</A>. +It is undefined whether this location or the characters are +modified by the current transformation. + +<H4><A NAME=fl_draw>void fl_draw(const char *, int x, int y) +<BR>void fl_draw(const char *, int n, int x, int y)</A></H4> + +<P>Draw a nul-terminated string or an array of <TT>n</TT> characters +starting at the given location. Text is aligned to the left and to +the baseline of the font. To align to the bottom, subtract fl_descent() from +<i>y</i>. To align to the top, subtract fl_descent() and add fl_height(). +This version of fl_draw provides direct access to +the text drawing function of the underlying OS. It does not apply any +special handling to control characters. + +<H4>void fl_draw(const char *, int x, int y, int w, int h, +Fl_Align align, Fl_Image *img = 0, int draw_symbols = 1)</H4> + +<P>Fancy string drawing function which is used to draw all the +labels. The string is formatted and aligned inside the passed +box. Handles '\t' and '\n', expands all other control +characters to ^X, and aligns inside or against the edges of the +box described by <i>x</i>, <i>y</i>, <i>w</i> and <i>h</i>. See <A +href="Fl_Widget.html#Fl_Widget.align"><TT>Fl_Widget::align()</TT></A> +for values for <TT>align</TT>. The value +<TT>FL_ALIGN_INSIDE</TT> is ignored, as this function always +prints inside the box. + +<P>If <TT>img</TT> is provided and is not <TT>NULL</TT>, the +image is drawn above or below the text as specified by the +<TT>align</TT> value. + +<P>The <TT>draw_symbols</TT> argument specifies whether or not +to look for symbol names starting with the "@" character. + +<P>The text length is limited to 1024 caracters per line. + +<H4><A NAME=fl_measure>void fl_measure(const char *, int &w, +int &h, int draw_symbols = 1)</A></H4> + +<P>Measure how wide and tall the string will be when printed by +the <TT>fl_draw(...align)</TT> function. If the incoming +<TT>w</TT> is non-zero it will wrap to that width. + +<H4><A NAME=fl_height>int fl_height()</A></H4> + +<P>Recommended minimum line spacing for the current font. You +can also just use the value of <TT>size</TT> passed to <A +href=#fl_font><TT>fl_font()</TT></A>. + +<H4><A NAME=fl_descent>int fl_descent()</A></H4> + +<P>Recommended distance above the bottom of a +<TT>fl_height()</TT> tall box to draw the text at so it looks +centered vertically in that box. + +<H4><A NAME=fl_width>float fl_width(const char*) +<BR>float fl_width(const char*, int n) +<BR>float fl_width(uchar)</A></H4> + +<P>Return the pixel width of a nul-terminated string, a sequence of <TT>n</TT> +characters, or a single character in the current font. + +<H4><A NAME=fl_shortcut_label>const char *fl_shortcut_label(ulong)</A></H4> + +<P>Unparse a shortcut value as used by <A +href="Fl_Button.html#Fl_Button.shortcut"><TT>Fl_Button</TT></A> +or <A +href="Fl_Menu_Item.html#Fl_Menu_Item"><TT>Fl_Menu_Item</TT></A> +into a human-readable string like "Alt+N". This only +works if the shortcut is a character key or a numbered function +key. If the shortcut is zero an empty string is returned. The +return value points at a static buffer that is overwritten with +each call. + +<H3><A name="fonts">Fonts</A></H3> + +<P>FLTK supports a set of standard fonts based on the Times, +Helvetica/Arial, Courier, and Symbol typefaces, as well as +custom fonts that your application may load. Each font is +accessed by an index into a font table. + +<P>Initially only the first 16 faces are filled in. There are +symbolic names for them: <TT>FL_HELVETICA</TT>, +<TT>FL_TIMES</TT>, <TT>FL_COURIER</TT>, and modifier values +<TT>FL_BOLD</TT> and <TT>FL_ITALIC</TT> which can be added to +these, and <TT>FL_SYMBOL</TT> and <TT>FL_ZAPF_DINGBATS</TT>. +Faces greater than 255 cannot be used in <TT>Fl_Widget</TT> +labels, since <TT>Fl_Widget</TT> stores the index as a byte.</P> + +<H4><A name="fl_font">void fl_font(int face, int size)</A></H4> + +<P>Set the current font, which is then used by the routines +described above. You may call this outside a draw context if +necessary to call <TT>fl_width()</TT>, but on X this will open +the display. + +<P>The font is identified by a <TT>face</TT> and a +<TT>size</TT>. The size of the font is measured in +<TT>pixels</TT> and not "points". Lines should be spaced +<TT>size</TT> pixels apart or more.</P> + +<H4><A NAME=fl_size>int fl_font() +<BR>int fl_size()</A></H4> + +<P>Returns the face and size set by the most recent call to +<TT>fl_font(a,b)</TT>. This can be used to save/restore the +font. + +<H3><A NAME=character_encoding>Character Encoding</A></H3> + +<P>FLTK 1 supports western character sets using the eight bit encoding +of the user-selected global code page. For MS Windows and X11, the code +page is assumed to be Windows-1252/Latin1, a superset to ISO 8859-1. +On Mac OS X, we assume MacRoman. + +<P>FLTK provides the functions <tt>fl_latin1_to_local</tt>, +<tt>fl_local_to_latin1</tt>, <tt>fl_mac_roman_to_local</tt>, and +<tt>fl_local_to_mac_roman</tt> to convert strings between both +encodings. These functions are only required if your source +code contains "C"-strings with international characters and +if this source will be compiled on multiple platforms. + +<P>Assuming that the following source code was written on MS Windows, +this example will output the correct label on OS X and X11 as well. +Without the conversion call, the label on OS X would read +<tt>Fahrvergn¸gen</tt> with a deformed umlaut u. +<PRE> + btn = new Fl_Button(10, 10, 300, 25); + btn->copy_label(fl_latin1_to_local("Fahrvergnügen")); +</PRE> + +<P>If your application uses characters that are not part of both +encodings, or it will be used in areas that commonly use different +code pages, yoou might consider upgrading to FLTK 2 which supports +UTF-8 encoding. + +<H3><A name="overlay">Drawing Overlays</A></H3> + +<P>These functions allow you to draw interactive selection rectangles +without using the overlay hardware. FLTK will XOR a single rectangle +outline over a window. + +<H4>void fl_overlay_rect(int x, int y, int w, int h); +<BR>void fl_overlay_clear();</H4> + +<P><TT>fl_overlay_rect()</TT> draws a selection rectangle, erasing any +previous rectangle by XOR'ing it first. <TT>fl_overlay_clear()</TT> +will erase the rectangle without drawing a new one. + +<P>Using these functions is tricky. You should make a widget +with both a <TT>handle()</TT> and <TT>draw()</TT> method. +<TT>draw()</TT> should call <TT>fl_overlay_clear()</TT> before +doing anything else. Your <TT>handle()</TT> method should call +<TT>window()->make_current()</TT> and then +<TT>fl_overlay_rect()</TT> after <TT>FL_DRAG</TT> events, and +should call <TT>fl_overlay_clear()</TT> after a +<TT>FL_RELEASE</TT> event.</P> + +<H2><A name="images">Drawing Images</A></H2> + +<P>To draw images, you can either do it directly from data in +your memory, or you can create a <A +href="#Fl_Image"><TT>Fl_Image</TT></A> object. The advantage of +drawing directly is that it is more intuitive, and it is faster +if the image data changes more often than it is redrawn. The +advantage of using the object is that FLTK will cache translated +forms of the image (on X it uses a server pixmap) and thus +redrawing is <I>much</I> faster. + +<H3>Direct Image Drawing</H3> + +<P>The behavior when drawing images when the current +transformation matrix is not the identity is not defined, so you +should only draw images when the matrix is set to the identity. + +<H4><A NAME="fl_draw_image">void fl_draw_image(const uchar *, int X, int Y, int W, int H, int D += 3, int LD = 0) +<BR>void fl_draw_image_mono(const uchar *, int X, int Y, int W, int H, +int D = 1, int LD = 0)</A></H4> + +<P>Draw an 8-bit per color RGB or luminance image. The pointer +points at the "r" data of the top-left pixel. Color +data must be in <TT>r,g,b</TT> order. <TT>X,Y</TT> are where to +put the top-left corner. <TT>W</TT> and <TT>H</TT> define the +size of the image. <TT>D</TT> is the delta to add to the pointer +between pixels, it may be any value greater or equal to +<TT>3</TT>, or it can be negative to flip the image +horizontally. <TT>LD</TT> is the delta to add to the pointer +between lines (if 0 is passed it uses <TT>W * D</TT>), and may +be larger than <TT>W * D</TT> to crop data, or negative to flip +the image vertically. + +<P>It is highly recommended that you put the following code before the +first <TT>show()</TT> of <I>any</I> window in your program to get rid +of the dithering if possible: </P> + +<UL><PRE> +Fl::visual(FL_RGB); +</PRE></UL> + +<P>Gray scale (1-channel) images may be drawn. This is done if +<TT>abs(D)</TT> is less than 3, or by calling +<TT>fl_draw_image_mono()</TT>. Only one 8-bit sample is used for +each pixel, and on screens with different numbers of bits for +red, green, and blue only gray colors are used. Setting +<TT>D</TT> greater than 1 will let you display one channel of a +color image. + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>The X version does not support all possible visuals. + If FLTK cannot draw the image in the current visual it + will abort. FLTK supports any visual of 8 bits or less, + and all common TrueColor visuals up to 32 bits.</P> + + </TD> +</TR> +</TABLE></CENTER> + +<H4>typedef void (*fl_draw_image_cb)(void *, int x, int y, int w, uchar +*) +<BR>void fl_draw_image(fl_draw_image_cb, void *, int X, int Y, int W, +int H, int D = 3) +<BR>void fl_draw_image_mono(fl_draw_image_cb, void *, int X, int Y, +int W, int H, int D = 1)</H4> + +<P>Call the passed function to provide each scan line of the +image. This lets you generate the image as it is being drawn, +or do arbitrary decompression of stored data, provided it can be +decompressed to individual scan lines easily. + +<P>The callback is called with the <TT>void *</TT> user data +pointer which can be used to point at a structure of information +about the image, and the <TT>x</TT>, <TT>y</TT>, and <TT>w</TT> +of the scan line desired from the image. 0,0 is the upper-left +corner of the image, <I>not <TT>X,Y</TT></I>. A pointer to a +buffer to put the data into is passed. You must copy <TT>w</TT> +pixels from scanline <TT>y</TT>, starting at pixel <TT>x</TT>, +to this buffer.</P> + +<P>Due to cropping, less than the whole image may be requested. +So <TT>x</TT> may be greater than zero, the first <TT>y</TT> may +be greater than zero, and <TT>w</TT> may be less than +<TT>W</TT>. The buffer is long enough to store the entire <TT>W +* D</TT> pixels, this is for convenience with some decompression +schemes where you must decompress the entire line at once: +decompress it into the buffer, and then if <TT>x</TT> is not +zero, copy the data over so the <TT>x</TT>'th pixel is at the +start of the buffer.</P> + +<P>You can assume the <TT>y</TT>'s will be consecutive, except +the first one may be greater than zero.</P> + +<P>If <TT>D</TT> is 4 or more, you must fill in the unused bytes +with zero.</P> + +<H4><A NAME=fl_draw_pixmap>int fl_draw_pixmap(char **data, int X, int Y, Fl_Color = FL_GRAY)</A></H4> + +<P>Draws XPM image data, with the top-left corner at the given position. +The image is dithered on 8-bit displays so you won't lose color space +for programs displaying both images and pixmaps. This function returns +zero if there was any error decoding the XPM data. + +<P>To use an XPM, do:</P> + +<UL><PRE> +#include "foo.xpm" +... +fl_draw_pixmap(foo, X, Y); +</PRE></UL> + +<P>Transparent colors are replaced by the optional +<TT>Fl_Color</TT> argument. To draw with true transparency you must +use the <A HREF="Fl_Pixmap.html"><TT>Fl_Pixmap</TT></A> class. + +<H4><A NAME=fl_measure_pixmap>int fl_measure_pixmap(char **data, int &w, int &h)</A></H4> + +<P>An XPM image contains the dimensions in its data. This +function finds and returns the width and height. The return +value is non-zero if the dimensions were parsed ok and zero if +there was any problem. + +<H3>Direct Image Reading</H3> + +<p>FLTK provides a single function for reading from the current +window or off-screen buffer into a RGB(A) image buffer.</p> + +<H4><A NAME="fl_read_image">uchar *fl_read_image(uchar *p, int +X, int Y, int W, int H, int alpha = 0);</A></H4> + +<p>Read a RGB(A) image from the current window or off-screen +buffer. The <tt>p</tt> argument points to a buffer that can hold +the image and must be at least <tt>W*H*3</tt> bytes when reading +RGB images and <tt>W*H*4</tt> bytes when reading RGBA images. If +<tt>NULL</tt>, <tt>fl_read_image()</tt> will create an array of +the proper size which can be freed using <tt>delete[]</tt>.</p> + +<p>The <tt>alpha</tt> parameter controls whether an alpha +channel is created and the value that is placed in the alpha +channel. If 0, no alpha channel is generated.</p> + +<H3><A name="Fl_Image">Image Classes</A></H3> + +<P>FLTK provides a base image class called <A +HREF="Fl_Image.html"><TT>Fl_Image</TT></A> which supports +creating, copying, and drawing images of various kinds, along +with some basic color operations. Images can be used as labels +for widgets using the <A +HREF="Fl_Widget.html#Fl_Widget.image"><TT>image()</TT></A> and +<A +HREF="Fl_Widget.html#Fl_Widget.deimage"><TT>deimage()</TT></A> +methods or drawn directly. + +<P>The <TT>Fl_Image</TT> class +does almost nothing by itself, but is instead supported by three +basic image types: + +<UL> + + <LI><A HREF="Fl_Bitmap.html"><TT>Fl_Bitmap</TT></A></LI> + + <LI><A HREF="Fl_Pixmap.html"><TT>Fl_Pixmap</TT></A></LI> + + <LI><A HREF="Fl_RGB_Image.html"><TT>Fl_RGB_Image</TT></A></LI> + +</UL> + +<P>The <TT>Fl_Bitmap</TT> class encapsulates a mono-color bitmap image. +The <TT>draw()</TT> method draws the image using the current drawing +color. + +<P>The <TT>Fl_Pixmap</TT> class encapsulates a colormapped image. +The <TT>draw()</TT> method draws the image using the colors in the +file, and masks off any transparent colors automatically. + +<P>The <TT>Fl_RGB_Image</TT> class encapsulates a full-color +(or grayscale) image with 1 to 4 color components. Images with +an even number of components are assumed to contain an +alpha channel that is used for transparency. The transparency +provided by the <TT>draw()</TT> method is either a 24-bit +blend against the existing window contents or a "screen door" +transparency mask, depending on the platform and screen color depth. + +<H4><A NAME=fl_can_do_alpha_blending>char fl_can_do_alpha_blending()</A></H4> + +<P><TT>fl_can_do_alpha_blending()</TT> will return 1, if your +platform supports true alpha blending for RGBA images, or 0, +if FLTK will use screen door transparency. + +<P>FLTK also provides several image classes based on the three +standard image types for common file formats: + +<UL> + + <LI><A HREF="Fl_GIF_Image.html"><TT>Fl_GIF_Image</TT></A></LI> + + <LI><A HREF="Fl_JPEG_Image.html"><TT>Fl_JPEG_Image</TT></A></LI> + + <LI><A HREF="Fl_PNG_Image.html"><TT>Fl_PNG_Image</TT></A></LI> + + <LI><A HREF="Fl_PNM_Image.html"><TT>Fl_PNM_Image</TT></A></LI> + + <LI><A HREF="Fl_XBM_Image.html"><TT>Fl_XBM_Image</TT></A></LI> + + <LI><A HREF="Fl_XPM_Image.html"><TT>Fl_XPM_Image</TT></A></LI> + +</UL> + +<P>Each of these image classes load a named file of the +corresponding format. The <A +HREF="Fl_Shared_Image.html"><TT>Fl_Shared_Image</TT></A> class +can be used to load any type of image file - the class examines +the file and constructs an image of the appropriate type. + +<P>Finally, FLTK provides a special image class called <A +HREF="Fl_Tiled_Image.html"><TT>Fl_Tiled_Image</TT></A> to tile +another image object in the specified area. This class can be +used to tile a background image in a <TT>Fl_Group</TT> widget, +for example. + +<H4>virtual void copy();<BR> +virtual void copy(int w, int h);</H4> + +<P>The <TT>copy()</TT> method creates a copy of the image. The second form +specifies the new size of the image - the image is resized using the +nearest-neighbor algorithm. + +<H4>void draw(int x, int y, int w, int h, int ox = 0, int oy = 0);</H4> + +<P>The <TT>draw()</TT> method draws the image object. +<TT>x,y,w,h</TT> indicates a destination rectangle. +<TT>ox,oy,w,h</TT> is a source rectangle. This source rectangle +is copied to the destination. The source rectangle may extend +outside the image, i.e. <TT>ox</TT> and <TT>oy</TT> may be +negative and <TT>w</TT> and <TT>h</TT> may be bigger than the +image, and this area is left unchanged. + +<H4>void draw(int x, int y)</H4> + +<P>Draws the image with the upper-left corner at <TT>x,y</TT>. +This is the same as doing <TT>draw(x,y,img->w(),img->h(),0,0)</TT>. + +<h3><A NAME=offscreen>Offscreen Drawing</A></h3> + +Sometimes it can be very useful to generate a complex drawing +in memory first and copy it to the screen at a later point in +time. This technique can significantly reduce the amount of +repeated drawing. <tt>Fl_Double_Window</tt> uses offscreen rendering +to avoid flickering on systems that don't support +double-buffering natively. + +<H4><A NAME=fl_create_offscreen>Fl_Offscreen fl_create_offscreen(int w, int h)</A></H4> + +<P>Create an RGB offscreen buffer with <tt>w*h</tt> pixels. + +<H4><A NAME=fl_delete_offscreen>void fl_delete_offscreen(Fl_Offscreen)</A></H4> + +<P>Delete a previously created offscreen buffer. All drawings are lost. + +<H4><A NAME=fl_begin_offscreen>void fl_begin_offscreen(Fl_Offscreen)</A></H4> + +<P>Send all subsequent drawing commands to this offscreen buffer. +FLTK can draw into a buffer at any time. There is no need to wait for +an Fl_Widget::draw() to occur. + +<H4><A NAME=fl_end_offscreen>void fl_end_offscreen()</A></H4> + +<P>Quit sending drawing commands to this offscreen buffer. + +<H4><A NAME=fl_copy_offscreen>void fl_copy_offscreen(int x, int y, +int w, int h, Fl_Offscreen osrc, int srcx, int srcy)</A></H4> + +<P>Copy a rectangular area of the size <tt>w*h</tt> from <tt>srcx, srcy</tt> in the offscreen +buffer into the current buffer at <tt>x, y</tt>. + +*/ diff --git a/documentation/editor.dox b/documentation/editor.dox new file mode 100644 index 000000000..260c7a887 --- /dev/null +++ b/documentation/editor.dox @@ -0,0 +1,905 @@ +/** + + \page editor 4 - Designing a Simple Text Editor + +<P>This chapter takes you through the design of a simple +FLTK-based text editor. + +<H2>Determining the Goals of the Text Editor</H2> + +<P>Since this will be the first big project you'll be doing with FLTK, +lets define what we want our text editor to do: + +<OL> + + <LI>Provide a menubar/menus for all functions.</LI> + <LI>Edit a single text file, possibly with multiple views.</LI> + <LI>Load from a file.</LI> + <LI>Save to a file.</LI> + <LI>Cut/copy/delete/paste functions.</LI> + <LI>Search and replace functions.</LI> + <LI>Keep track of when the file has been changed.</LI> + +</OL> + +<!-- NEED 4in --> + +<H2>Designing the Main Window</H2> + +<P>Now that we've outlined the goals for our editor, we can begin with +the design of our GUI. Obviously the first thing that we need is a +window, which we'll place inside a class called <TT>EditorWindow</TT>: + +<UL><PRE> +class EditorWindow : public Fl_Double_Window { + public: + EditorWindow(int w, int h, const char* t); + ~EditorWindow(); + + Fl_Window *replace_dlg; + Fl_Input *replace_find; + Fl_Input *replace_with; + Fl_Button *replace_all; + Fl_Return_Button *replace_next; + Fl_Button *replace_cancel; + + Fl_Text_Editor *editor; + char search[256]; +}; +</PRE></UL> + +<H2>Variables</H2> + +<P>Our text editor will need some global variables to keep track of +things: + +<UL><PRE> +int changed = 0; +char filename[256] = ""; +Fl_Text_Buffer *textbuf; +</PRE></UL> + +<P>The <TT>textbuf</TT> variable is the text editor buffer for +our window class described previously. We'll cover the other +variables as we build the application.</P> + +<H2>Menubars and Menus</H2> + +<P>The first goal requires us to use a menubar and menus that +define each function the editor needs to perform. The <A +href="Fl_Menu_Item.html"><TT>Fl_Menu_Item</TT></A> structure is +used to define the menus and items in a menubar:</P> + +<UL><PRE> +Fl_Menu_Item menuitems[] = { + { "&File", 0, 0, 0, FL_SUBMENU }, + { "&New File", 0, (Fl_Callback *)new_cb }, + { "&Open File...", FL_CTRL + 'o', (Fl_Callback *)open_cb }, + { "&Insert File...", FL_CTRL + 'i', (Fl_Callback *)insert_cb, 0, FL_MENU_DIVIDER }, + { "&Save File", FL_CTRL + 's', (Fl_Callback *)save_cb }, + { "Save File &As...", FL_CTRL + FL_SHIFT + 's', (Fl_Callback *)saveas_cb, 0, FL_MENU_DIVIDER }, + { "New &View", FL_ALT + 'v', (Fl_Callback *)view_cb, 0 }, + { "&Close View", FL_CTRL + 'w', (Fl_Callback *)close_cb, 0, FL_MENU_DIVIDER }, + { "E&xit", FL_CTRL + 'q', (Fl_Callback *)quit_cb, 0 }, + { 0 }, + + { "&Edit", 0, 0, 0, FL_SUBMENU }, + { "&Undo", FL_CTRL + 'z', (Fl_Callback *)undo_cb, 0, FL_MENU_DIVIDER }, + { "Cu&t", FL_CTRL + 'x', (Fl_Callback *)cut_cb }, + { "&Copy", FL_CTRL + 'c', (Fl_Callback *)copy_cb }, + { "&Paste", FL_CTRL + 'v', (Fl_Callback *)paste_cb }, + { "&Delete", 0, (Fl_Callback *)delete_cb }, + { 0 }, + + { "&Search", 0, 0, 0, FL_SUBMENU }, + { "&Find...", FL_CTRL + 'f', (Fl_Callback *)find_cb }, + { "F&ind Again", FL_CTRL + 'g', find2_cb }, + { "&Replace...", FL_CTRL + 'r', replace_cb }, + { "Re&place Again", FL_CTRL + 't', replace2_cb }, + { 0 }, + + { 0 } +}; +</PRE></UL> + +<P>Once we have the menus defined we can create the +<TT>Fl_Menu_Bar</TT> widget and assign the menus to it with:</P> + +<UL><PRE> +Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, 640, 30); +m->copy(menuitems); +</PRE></UL> + +<P>We'll define the callback functions later. + +<H2>Editing the Text</H2> + +<P>To keep things simple our text editor will use the +<A HREF="Fl_Text_Editor.html"><TT>Fl_Text_Editor</TT></A> +widget to edit the text: + +<UL><PRE> +w->editor = new Fl_Text_Editor(0, 30, 640, 370); +w->editor->buffer(textbuf); +</PRE></UL> + +<P>So that we can keep track of changes to the file, we also want to add +a "modify" callback:</P> + +<UL><PRE> +textbuf->add_modify_callback(changed_cb, w); +textbuf->call_modify_callbacks(); +</PRE></UL> + +<P>Finally, we want to use a mono-spaced font like <TT>FL_COURIER</TT>: + +<UL><PRE> +w->editor->textfont(FL_COURIER); +</PRE></UL> + +<H2>The Replace Dialog</H2> + +<P>We can use the FLTK convenience functions for many of the +editor's dialogs, however the replace dialog needs its own +custom window. To keep things simple we will have a +"find" string, a "replace" string, and +"replace all", "replace next", and +"cancel" buttons. The strings are just +<TT>Fl_Input</TT> widgets, the "replace all" and +"cancel" buttons are <TT>Fl_Button</TT> widgets, and +the "replace next " button is a +<TT>Fl_Return_Button</TT> widget:</P> + +<P ALIGN="CENTER"><IMG src="editor-replace.gif" ALT="The search and replace dialog."><BR> +<I>Figure 4-1: The search and replace dialog.</I></P> + +<UL><PRE> +Fl_Window *replace_dlg = new Fl_Window(300, 105, "Replace"); +Fl_Input *replace_find = new Fl_Input(70, 10, 200, 25, "Find:"); +Fl_Input *replace_with = new Fl_Input(70, 40, 200, 25, "Replace:"); +Fl_Button *replace_all = new Fl_Button(10, 70, 90, 25, "Replace All"); +Fl_Button *replace_next = new Fl_Button(105, 70, 120, 25, "Replace Next"); +Fl_Button *replace_cancel = new Fl_Button(230, 70, 60, 25, "Cancel"); +</PRE></UL> + +<H2>Callbacks</H2> + +<P>Now that we've defined the GUI components of our editor, we +need to define our callback functions.</P> + +<H3>changed_cb()</H3> + +<P>This function will be called whenever the user changes any text in the +<TT>editor</TT> widget: + +<UL><PRE> +void changed_cb(int, int nInserted, int nDeleted,int, const char*, void* v) { + if ((nInserted || nDeleted) && !loading) changed = 1; + EditorWindow *w = (EditorWindow *)v; + set_title(w); + if (loading) w->editor->show_insert_position(); +} +</PRE></UL> + +<P>The <TT>set_title()</TT> function is one that we will write to set +the changed status on the current file. We're doing it this way +because we want to show the changed status in the window's +title bar. + +<H3>copy_cb()</H3> + +<P>This callback function will call <A +href="Fl_Text_Editor.html#Fl_Text_Editor.kf_copy"><TT>kf_copy()</TT></A> +to copy the currently selected text to the clipboard:</P> + +<UL><PRE> +void copy_cb(Fl_Widget*, void* v) { + EditorWindow* e = (EditorWindow*)v; + Fl_Text_Editor::kf_copy(0, e->editor); +} +</PRE></UL> + +<H3>cut_cb()</H3> + +<P>This callback function will call <A +href="Fl_Text_Editor.html#Fl_Text_Editor.kf_cut"><TT>kf_cut()</TT></A> +to cut the currently selected text to the clipboard:</P> + +<UL><PRE> +void cut_cb(Fl_Widget*, void* v) { + EditorWindow* e = (EditorWindow*)v; + Fl_Text_Editor::kf_cut(0, e->editor); +} +</PRE></UL> + +<H3>delete_cb()</H3> + +<P>This callback function will call <A +href="Fl_Text_Buffer.html#Fl_Text_Buffer.remove_selection"><TT>remove_selection()</TT></A> +to delete the currently selected text to the clipboard:</P> + +<UL><PRE> +void delete_cb(Fl_Widget*, void* v) { + textbuf->remove_selection(); +} +</PRE></UL> + +<H3>find_cb()</H3> + +<P>This callback function asks for a search string using the <A +href="functions.html#fl_input2"><TT>fl_input()</TT></A> +convenience function and then calls the <TT>find2_cb()</TT> +function to find the string: + +<UL><PRE> +void find_cb(Fl_Widget* w, void* v) { + EditorWindow* e = (EditorWindow*)v; + const char *val; + + val = fl_input("Search String:", e->search); + if (val != NULL) { + // User entered a string - go find it! + strcpy(e->search, val); + find2_cb(w, v); + } +</PRE></UL> + +<H3>find2_cb()</H3> + +<P>This function will find the next occurrence of the search +string. If the search string is blank then we want to pop up the +search dialog: + +<UL><PRE> +void find2_cb(Fl_Widget* w, void* v) { + EditorWindow* e = (EditorWindow*)v; + if (e->search[0] == '\0') { + // Search string is blank; get a new one... + find_cb(w, v); + return; + } + + int pos = e->editor->insert_position(); + int found = textbuf->search_forward(pos, e->search, &pos); + if (found) { + // Found a match; select and update the position... + textbuf->select(pos, pos+strlen(e->search)); + e->editor->insert_position(pos+strlen(e->search)); + e->editor->show_insert_position(); + } + else fl_alert("No occurrences of \'%s\' found!", e->search); +} +</PRE></UL> + +<P>If the search string cannot be found we use the <A +href="functions.html#fl_alert"><TT>fl_alert()</TT></A> +convenience function to display a message to that effect. + +<H3>new_cb()</H3> +<P>This callback function will clear the editor widget and current +filename. It also calls the <TT>check_save()</TT> function to give the +user the opportunity to save the current file first as needed: + +<UL><PRE> +void new_cb(Fl_Widget*, void*) { + if (!check_save()) return; + + filename[0] = '\0'; + textbuf->select(0, textbuf->length()); + textbuf->remove_selection(); + changed = 0; + textbuf->call_modify_callbacks(); +} +</PRE></UL> + +<H3>open_cb()</H3> + +<P>This callback function will ask the user for a filename and then load +the specified file into the input widget and current filename. It also +calls the <TT>check_save()</TT> function to give the user the +opportunity to save the current file first as needed: + +<UL><PRE> +void open_cb(Fl_Widget*, void*) { + if (!check_save()) return; + + char *newfile = fl_file_chooser("Open File?", "*", filename); + if (newfile != NULL) load_file(newfile, -1); +} +</PRE></UL> + +<P>We call the <TT>load_file()</TT> function to actually load the file. + +<H3>paste_cb()</H3> + +<P>This callback function will call <A +href="Fl_Text_Editor.html#Fl_Text_Editor.kf_paste"><TT>kf_paste()</TT></A> +to paste the clipboard at the current position:</P> + +<UL><PRE> +void paste_cb(Fl_Widget*, void* v) { + EditorWindow* e = (EditorWindow*)v; + Fl_Text_Editor::kf_paste(0, e->editor); +} +</PRE></UL> + +<H3>quit_cb()</H3> + +<P>The quit callback will first see if the current file has been +modified, and if so give the user a chance to save it. It then exits +from the program: + +<UL><PRE> +void quit_cb(Fl_Widget*, void*) { + if (changed && !check_save()) + return; + + exit(0); +} +</PRE></UL> + +<H3>replace_cb()</H3> + +<P>The replace callback just shows the replace dialog: + +<UL><PRE> +void replace_cb(Fl_Widget*, void* v) { + EditorWindow* e = (EditorWindow*)v; + e->replace_dlg->show(); +} +</PRE></UL> + +<H3>replace2_cb()</H3> + +<P>This callback will replace the next occurence of the replacement +string. If nothing has been entered for the replacement string, then +the replace dialog is displayed instead: + +<UL><PRE> +void replace2_cb(Fl_Widget*, void* v) { + EditorWindow* e = (EditorWindow*)v; + const char *find = e->replace_find->value(); + const char *replace = e->replace_with->value(); + + if (find[0] == '\0') { + // Search string is blank; get a new one... + e->replace_dlg->show(); + return; + } + + e->replace_dlg->hide(); + + int pos = e->editor->insert_position(); + int found = textbuf->search_forward(pos, find, &pos); + + if (found) { + // Found a match; update the position and replace text... + textbuf->select(pos, pos+strlen(find)); + textbuf->remove_selection(); + textbuf->insert(pos, replace); + textbuf->select(pos, pos+strlen(replace)); + e->editor->insert_position(pos+strlen(replace)); + e->editor->show_insert_position(); + } + else fl_alert("No occurrences of \'%s\' found!", find); +} +</PRE></UL> + +<H3>replall_cb()</H3> + +<P>This callback will replace all occurences of the search +string in the file: + +<UL><PRE> +void replall_cb(Fl_Widget*, void* v) { + EditorWindow* e = (EditorWindow*)v; + const char *find = e->replace_find->value(); + const char *replace = e->replace_with->value(); + + find = e->replace_find->value(); + if (find[0] == '\0') { + // Search string is blank; get a new one... + e->replace_dlg->show(); + return; + } + + e->replace_dlg->hide(); + + e->editor->insert_position(0); + int times = 0; + + // Loop through the whole string + for (int found = 1; found;) { + int pos = e->editor->insert_position(); + found = textbuf->search_forward(pos, find, &pos); + + if (found) { + // Found a match; update the position and replace text... + textbuf->select(pos, pos+strlen(find)); + textbuf->remove_selection(); + textbuf->insert(pos, replace); + e->editor->insert_position(pos+strlen(replace)); + e->editor->show_insert_position(); + times++; + } + } + + if (times) fl_message("Replaced %d occurrences.", times); + else fl_alert("No occurrences of \'%s\' found!", find); +} +</PRE></UL> + +<H3>replcan_cb()</H3> + +<P>This callback just hides the replace dialog: + +<UL><PRE> +void replcan_cb(Fl_Widget*, void* v) { + EditorWindow* e = (EditorWindow*)v; + e->replace_dlg->hide(); +} +</PRE></UL> + +<H3>save_cb()</H3> + +<P>This callback saves the current file. If the current filename is +blank it calls the "save as" callback: + +<UL><PRE> +void save_cb(void) { + if (filename[0] == '\0') { + // No filename - get one! + saveas_cb(); + return; + } + else save_file(filename); +} +</PRE></UL> + +<P>The <TT>save_file()</TT> function saves the current file to the +specified filename. + +<H3>saveas_cb()</H3> + +<P>This callback asks the user for a filename and saves the current file: + +<UL><PRE> +void saveas_cb(void) { + char *newfile; + + newfile = fl_file_chooser("Save File As?", "*", filename); + if (newfile != NULL) save_file(newfile); +} +</PRE></UL> + +<P>The <TT>save_file()</TT> function saves the current file to the +specified filename. + +<H2>Other Functions</H2> + +<P>Now that we've defined the callback functions, we need our support +functions to make it all work: + +<H3>check_save()</H3> + +<P>This function checks to see if the current file needs to be saved. If +so, it asks the user if they want to save it: + +<UL><PRE> +int check_save(void) { + if (!changed) return 1; + + int r = fl_choice("The current file has not been saved.\n" + "Would you like to save it now?", + "Cancel", "Save", "Discard"); + + if (r == 1) { + save_cb(); // Save the file... + return !changed; + } + + return (r == 2) ? 1 : 0; +} +</PRE></UL> + +<H3>load_file()</H3> + +<P>This function loads the specified file into the <TT>textbuf</TT> class: + +<UL><PRE> +int loading = 0; +void load_file(char *newfile, int ipos) { + loading = 1; + int insert = (ipos != -1); + changed = insert; + if (!insert) strcpy(filename, ""); + int r; + if (!insert) r = textbuf->loadfile(newfile); + else r = textbuf->insertfile(newfile, ipos); + if (r) + fl_alert("Error reading from file \'%s\':\n%s.", newfile, strerror(errno)); + else + if (!insert) strcpy(filename, newfile); + loading = 0; + textbuf->call_modify_callbacks(); +} +</PRE></UL> + +<P>When loading the file we use the <A +href="Fl_Text_Buffer.html#Fl_Text_Buffer.loadfile"><TT>loadfile()</TT></A> +method to "replace" the text in the buffer, or the <A +href="Fl_Text_Buffer.html#Fl_Text_Buffer.insertfile"><TT>insertfile()</TT></A> +method to insert text in the buffer from the named file. + +<H3>save_file()</H3> + +<P>This function saves the current buffer to the specified file: + +<UL><PRE> +void save_file(char *newfile) { + if (textbuf->savefile(newfile)) + fl_alert("Error writing to file \'%s\':\n%s.", newfile, strerror(errno)); + else + strcpy(filename, newfile); + changed = 0; + textbuf->call_modify_callbacks(); +} +</PRE></UL> + +<H3>set_title()</H3> + +<P>This function checks the <TT>changed</TT> variable and updates the +window label accordingly: +<UL><PRE> +void set_title(Fl_Window* w) { + if (filename[0] == '\0') strcpy(title, "Untitled"); + else { + char *slash; + slash = strrchr(filename, '/'); +#ifdef WIN32 + if (slash == NULL) slash = strrchr(filename, '\\'); +#endif + if (slash != NULL) strcpy(title, slash + 1); + else strcpy(title, filename); + } + + if (changed) strcat(title, " (modified)"); + + w->label(title); +} +</PRE></UL> + +<H2>The main() Function</H2> + +<P>Once we've created all of the support functions, the only thing left +is to tie them all together with the <TT>main()</TT> function. +The <TT>main()</TT> function creates a new text buffer, creates a +new view (window) for the text, shows the window, loads the file on +the command-line (if any), and then enters the FLTK event loop: + +<UL><PRE> +int main(int argc, char **argv) { + textbuf = new Fl_Text_Buffer; + + Fl_Window* window = new_view(); + + window->show(1, argv); + + if (argc > 1) load_file(argv[1], -1); + + return Fl::run(); +} +</PRE></UL> + +<H2>Compiling the Editor</H2> + +<P>The complete source for our text editor can be found in the <TT>test/editor.cxx</TT> source file. Both the Makefile and Visual C++ +workspace include the necessary rules to build the editor. You can +also compile it using a standard compiler with: + +<UL><PRE> +CC -o editor editor.cxx -lfltk -lXext -lX11 -lm +</PRE></UL> + +<P>or by using the <TT>fltk-config</TT> script with: + +<UL><PRE> +fltk-config --compile editor.cxx +</PRE></UL> + +<P>As noted in <A href="basics.html">Chapter 1</A>, you may need to +include compiler and linker options to tell them where to find the FLTK +library. Also, the <TT>CC</TT> command may also be called <TT>gcc</TT> +or <TT>c++</TT> on your system. + +<P>Congratulations, you've just built your own text editor!</P> + +<H2>The Final Product</H2> + +The final editor window should look like the image in Figure 4-2. + +<P ALIGN="CENTER"><IMG src="editor.gif" ALT="The completed editor window."><BR> +<I>Figure 4-2: The completed editor window</I></P> + +<H2>Advanced Features</H2> + +<P>Now that we've implemented the basic functionality, it is +time to show off some of the advanced features of the +<CODE>Fl_Text_Editor</CODE> widget. + +<H3>Syntax Highlighting</H3> + +<P>The <CODE>Fl_Text_Editor</CODE> widget supports highlighting +of text with different fonts, colors, and sizes. The +implementation is based on the excellent <A +HREF="http://www.nedit.org/">NEdit</A> text editor core, which +uses a parallel "style" buffer which tracks the font, color, and +size of the text that is drawn. + +<P>Styles are defined using the +<CODE>Fl_Text_Display::Style_Table_Entry</CODE> structure +defined in <CODE><FL/Fl_Text_Display.H></CODE>: + +<UL><PRE> +struct Style_Table_Entry { + Fl_Color color; + Fl_Font font; + int size; + unsigned attr; +}; +</PRE></UL> + +<P>The <CODE>color</CODE> member sets the color for the text, +the <CODE>font</CODE> member sets the FLTK font index to use, +and the <CODE>size</CODE> member sets the pixel size of the +text. The <CODE>attr</CODE> member is currently not used. + +<P>For our text editor we'll define 7 styles for plain code, +comments, keywords, and preprocessor directives: + +<UL><PRE> +Fl_Text_Display::Style_Table_Entry styletable[] = { // Style table + { FL_BLACK, FL_COURIER, FL_NORMAL_SIZE }, // A - Plain + { FL_DARK_GREEN, FL_COURIER_ITALIC, FL_NORMAL_SIZE }, // B - Line comments + { FL_DARK_GREEN, FL_COURIER_ITALIC, FL_NORMAL_SIZE }, // C - Block comments + { FL_BLUE, FL_COURIER, FL_NORMAL_SIZE }, // D - Strings + { FL_DARK_RED, FL_COURIER, FL_NORMAL_SIZE }, // E - Directives + { FL_DARK_RED, FL_COURIER_BOLD, FL_NORMAL_SIZE }, // F - Types + { FL_BLUE, FL_COURIER_BOLD, FL_NORMAL_SIZE } // G - Keywords +}; +</PRE></UL> + +<P>You'll notice that the comments show a letter next to each +style - each style in the style buffer is referenced using a +character starting with the letter 'A'. + +<P>You call the <CODE>highlight_data()</CODE> method to associate the +style data and buffer with the text editor widget: + +<UL><PRE> +Fl_Text_Buffer *stylebuf; + +w->editor->highlight_data(stylebuf, styletable, + sizeof(styletable) / sizeof(styletable[0]), + 'A', style_unfinished_cb, 0); +</PRE></UL> + +<P>Finally, you need to add a callback to the main text buffer so +that changes to the text buffer are mirrored in the style buffer: + +<UL><PRE> +textbuf->add_modify_callback(style_update, w->editor); +</PRE></UL> + +<P>The <CODE>style_update()</CODE> function, like the <CODE>change_cb()</CODE> +function described earlier, is called whenever text is added or removed from +the text buffer. It mirrors the changes in the style buffer and then updates +the style data as necessary: + +<UL><PRE> +// +// 'style_update()' - Update the style buffer... +// + +void +style_update(int pos, // I - Position of update + int nInserted, // I - Number of inserted chars + int nDeleted, // I - Number of deleted chars + int nRestyled, // I - Number of restyled chars + const char *deletedText, // I - Text that was deleted + void *cbArg) { // I - Callback data + int start, // Start of text + end; // End of text + char last, // Last style on line + *style, // Style data + *text; // Text data + + + // If this is just a selection change, just unselect the style buffer... + if (nInserted == 0 && nDeleted == 0) { + stylebuf->unselect(); + return; + } + + // Track changes in the text buffer... + if (nInserted > 0) { + // Insert characters into the style buffer... + style = new char[nInserted + 1]; + memset(style, 'A', nInserted); + style[nInserted] = '\0'; + + stylebuf->replace(pos, pos + nDeleted, style); + delete[] style; + } else { + // Just delete characters in the style buffer... + stylebuf->remove(pos, pos + nDeleted); + } + + // Select the area that was just updated to avoid unnecessary + // callbacks... + stylebuf->select(pos, pos + nInserted - nDeleted); + + // Re-parse the changed region; we do this by parsing from the + // beginning of the line of the changed region to the end of + // the line of the changed region... Then we check the last + // style character and keep updating if we have a multi-line + // comment character... + start = textbuf->line_start(pos); + end = textbuf->line_end(pos + nInserted - nDeleted); + text = textbuf->text_range(start, end); + style = stylebuf->text_range(start, end); + last = style[end - start - 1]; + + style_parse(text, style, end - start); + + stylebuf->replace(start, end, style); + ((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); + + if (last != style[end - start - 1]) { + // The last character on the line changed styles, so reparse the + // remainder of the buffer... + free(text); + free(style); + + end = textbuf->length(); + text = textbuf->text_range(start, end); + style = stylebuf->text_range(start, end); + + style_parse(text, style, end - start); + + stylebuf->replace(start, end, style); + ((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); + } + + free(text); + free(style); +} +</PRE></UL> + +<P>The <CODE>style_parse()</CODE> function scans a copy of the +text in the buffer and generates the necessary style characters +for display. It assumes that parsing begins at the start of a line: + +<UL><PRE> +// +// 'style_parse()' - Parse text and produce style data. +// + +void +style_parse(const char *text, + char *style, + int length) { + char current; + int col; + int last; + char buf[255], + *bufptr; + const char *temp; + + for (current = *style, col = 0, last = 0; length > 0; length --, text ++) { + if (current == 'A') { + // Check for directives, comments, strings, and keywords... + if (col == 0 && *text == '#') { + // Set style to directive + current = 'E'; + } else if (strncmp(text, "//", 2) == 0) { + current = 'B'; + } else if (strncmp(text, "/*", 2) == 0) { + current = 'C'; + } else if (strncmp(text, "\\\"", 2) == 0) { + // Quoted quote... + *style++ = current; + *style++ = current; + text ++; + length --; + col += 2; + continue; + } else if (*text == '\"') { + current = 'D'; + } else if (!last && islower(*text)) { + // Might be a keyword... + for (temp = text, bufptr = buf; + islower(*temp) && bufptr < (buf + sizeof(buf) - 1); + *bufptr++ = *temp++); + + if (!islower(*temp)) { + *bufptr = '\0'; + + bufptr = buf; + + if (bsearch(&bufptr, code_types, + sizeof(code_types) / sizeof(code_types[0]), + sizeof(code_types[0]), compare_keywords)) { + while (text < temp) { + *style++ = 'F'; + text ++; + length --; + col ++; + } + + text --; + length ++; + last = 1; + continue; + } else if (bsearch(&bufptr, code_keywords, + sizeof(code_keywords) / sizeof(code_keywords[0]), + sizeof(code_keywords[0]), compare_keywords)) { + while (text < temp) { + *style++ = 'G'; + text ++; + length --; + col ++; + } + + text --; + length ++; + last = 1; + continue; + } + } + } + } else if (current == 'C' && strncmp(text, "*/", 2) == 0) { + // Close a C comment... + *style++ = current; + *style++ = current; + text ++; + length --; + current = 'A'; + col += 2; + continue; + } else if (current == 'D') { + // Continuing in string... + if (strncmp(text, "\\\"", 2) == 0) { + // Quoted end quote... + *style++ = current; + *style++ = current; + text ++; + length --; + col += 2; + continue; + } else if (*text == '\"') { + // End quote... + *style++ = current; + col ++; + current = 'A'; + continue; + } + } + + // Copy style info... + if (current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G'; + else *style++ = current; + col ++; + + last = isalnum(*text) || *text == '.'; + + if (*text == '\n') { + // Reset column and possibly reset the style + col = 0; + if (current == 'B' || current == 'E') current = 'A'; + } + } +} +</PRE></UL> + +*/ diff --git a/documentation/enumerations.dox b/documentation/enumerations.dox new file mode 100644 index 000000000..10ed628f5 --- /dev/null +++ b/documentation/enumerations.dox @@ -0,0 +1,304 @@ +/** + + \page enumerations C - FLTK Enumerations + +<P>This appendix lists the enumerations provided in the +<TT><FL/Enumerations.H></TT> header file, organized by +section. Constants whose value is zero are marked with "(0)", +this is often useful to know when programming. + +<H2>Version Numbers</H2> + The FLTK version number is stored in a number of compile-time +constants: +<UL> +<LI><TT>FL_MAJOR_VERSION</TT> - The major release number, currently 1. </LI> +<LI><TT>FL_MINOR_VERSION</TT> - The minor release number, currently 1. </LI> +<LI><TT>FL_PATCH_VERSION</TT> - The patch release number, currently 0. </LI> +<LI><TT>FL_VERSION</TT> - A combined floating-point version number for +the major, minor, and patch release numbers, currently 1.0100. </LI> +</UL> +<H2><A NAME="events">Events</A></H2> + Events are identified by an <TT>Fl_Event</TT> enumeration value. The +following events are currently defined: +<UL> +<LI><TT>FL_NO_EVENT</TT> - No event (or an event fltk does not +understand) occurred (0).</LI> +<LI><TT>FL_PUSH</TT> - A mouse button was pushed. </LI> +<LI><TT>FL_RELEASE</TT> - A mouse button was released. </LI> +<LI><TT>FL_ENTER</TT> - The mouse pointer entered a widget. </LI> +<LI><TT>FL_LEAVE</TT> - The mouse pointer left a widget. </LI> +<LI><TT>FL_DRAG</TT> - The mouse pointer was moved with a button + pressed. </LI> +<LI><TT>FL_FOCUS</TT> - A widget should receive keyboard focus. </LI> +<LI><TT>FL_UNFOCUS</TT> - A widget loses keyboard focus. </LI> +<LI><TT>FL_KEYBOARD</TT> - A key was pressed. </LI> +<LI><TT>FL_CLOSE</TT> - A window was closed. </LI> +<LI><TT>FL_MOVE</TT> - The mouse pointer was moved with no buttons + pressed. </LI> +<LI><TT>FL_SHORTCUT</TT> - The user pressed a shortcut key. </LI> +<LI><TT>FL_DEACTIVATE</TT> - The widget has been deactivated. </LI> +<LI><TT>FL_ACTIVATE</TT> - The widget has been activated. </LI> +<LI><TT>FL_HIDE</TT> - The widget has been hidden. </LI> +<LI><TT>FL_SHOW</TT> - The widget has been shown. </LI> +<LI><TT>FL_PASTE</TT> - The widget should paste the contents of the + clipboard. </LI> +<LI><TT>FL_SELECTIONCLEAR</TT> - The widget should clear any selections + made for the clipboard. </LI> +<LI><TT>FL_MOUSEWHEEL</TT> - The horizontal or vertical mousewheel was turned. </LI> +<LI><TT>FL_DND_ENTER</TT> - The mouse pointer entered a widget dragging data. </LI> +<LI><TT>FL_DND_DRAG</TT> - The mouse pointer was moved dragging data. </LI> +<LI><TT>FL_DND_LEAVE</TT> - The mouse pointer left a widget still dragging data. </LI> +<LI><TT>FL_DND_RELEASE</TT> - Dragged data is about to be dropped. </LI> +</UL> +<H2><a name=when>Callback "When" Conditions</A></H2> + The following constants determine when a callback is performed: +<UL> +<LI><TT>FL_WHEN_NEVER</TT> - Never call the callback (0). </LI> +<LI><TT>FL_WHEN_CHANGED</TT> - Do the callback only when the widget +value changes. </LI> +<LI><TT>FL_WHEN_NOT_CHANGED</TT> - Do the callback whenever the user +interacts with the widget. </LI> +<LI><TT>FL_WHEN_RELEASE</TT> - Do the callback when the button or key +is released and the value changes. </LI> +<LI><TT>FL_WHEN_ENTER_KEY</TT> - Do the callback when the user presses + the ENTER key and the value changes. </LI> +<LI><TT>FL_WHEN_RELEASE_ALWAYS</TT> - Do the callback when the button + or key is released, even if the value doesn't change. </LI> +<LI><TT>FL_WHEN_ENTER_KEY_ALWAYS</TT> - Do the callback when the user + presses the ENTER key, even if the value doesn't change. </LI> +</UL> +<H2><A NAME="button_values">Fl::event_button() Values</A></H2> + +<P>The following constants define the button numbers for <TT>FL_PUSH</TT> and +<TT>FL_RELEASE</TT> events: + +<UL> + <LI><TT>FL_LEFT_MOUSE</TT> - the left mouse button + <LI><TT>FL_MIDDLE_MOUSE</TT> - the middle mouse button + <LI><TT>FL_RIGHT_MOUSE</TT> - the right mouse button +</UL> + +<H2><A NAME="key_values">Fl::event_key() Values</A></H2> + The following constants define the non-ASCII keys on the keyboard for <TT> +FL_KEYBOARD</TT> and <TT>FL_SHORTCUT</TT> events: +<UL> +<LI><TT>FL_Button</TT> - A mouse button; use <TT>Fl_Button + n</TT> + for mouse button <TT>n</TT>. </LI> +<LI><TT>FL_BackSpace</TT> - The backspace key. </LI> +<LI><TT>FL_Tab</TT> - The tab key. </LI> +<LI><TT>FL_Enter</TT> - The enter key. </LI> +<LI><TT>FL_Pause</TT> - The pause key. </LI> +<LI><TT>FL_Scroll_Lock</TT> - The scroll lock key. </LI> +<LI><TT>FL_Escape</TT> - The escape key. </LI> +<LI><TT>FL_Home</TT> - The home key. </LI> +<LI><TT>FL_Left</TT> - The left arrow key. </LI> +<LI><TT>FL_Up</TT> - The up arrow key. </LI> +<LI><TT>FL_Right</TT> - The right arrow key. </LI> +<LI><TT>FL_Down</TT> - The down arrow key. </LI> +<LI><TT>FL_Page_Up</TT> - The page-up key. </LI> +<LI><TT>FL_Page_Down</TT> - The page-down key. </LI> +<LI><TT>FL_End</TT> - The end key. </LI> +<LI><TT>FL_Print</TT> - The print (or print-screen) key. </LI> +<LI><TT>FL_Insert</TT> - The insert key. </LI> +<LI><TT>FL_Menu</TT> - The menu key. </LI> +<LI><TT>FL_Num_Lock</TT> - The num lock key. </LI> +<LI><TT>FL_KP</TT> - One of the keypad numbers; use <TT>FL_KP + n</TT> + for number <TT>n</TT>. </LI> +<LI><TT>FL_KP_Enter</TT> - The enter key on the keypad. </LI> +<LI><TT>FL_F</TT> - One of the function keys; use <TT>FL_F + n</TT> + for function key <TT>n</TT>. </LI> +<LI><TT>FL_Shift_L</TT> - The lefthand shift key. </LI> +<LI><TT>FL_Shift_R</TT> - The righthand shift key. </LI> +<LI><TT>FL_Control_L</TT> - The lefthand control key. </LI> +<LI><TT>FL_Control_R</TT> - The righthand control key. </LI> +<LI><TT>FL_Caps_Lock</TT> - The caps lock key. </LI> +<LI><TT>FL_Meta_L</TT> - The left meta/Windows key. </LI> +<LI><TT>FL_Meta_R</TT> - The right meta/Windows key. </LI> +<LI><TT>FL_Alt_L</TT> - The left alt key. </LI> +<LI><TT>FL_Alt_R</TT> - The right alt key. </LI> +<LI><TT>FL_Delete</TT> - The delete key. </LI> +</UL> +<H2>Fl::event_state() Values</H2> + The following constants define bits in the <TT>Fl::event_state()</TT> + value: +<UL> +<LI><TT>FL_SHIFT</TT> - One of the shift keys is down. </LI> +<LI><TT>FL_CAPS_LOCK</TT> - The caps lock is on. </LI> +<LI><TT>FL_CTRL</TT> - One of the ctrl keys is down. </LI> +<LI><TT>FL_ALT</TT> - One of the alt keys is down. </LI> +<LI><TT>FL_NUM_LOCK</TT> - The num lock is on. </LI> +<LI><TT>FL_META</TT> - One of the meta/Windows keys is down. </LI> +<LI><TT>FL_COMMAND</TT> - An alias for <TT>FL_CTRL</TT> on WIN32 and X11, or +<TT>FL_META</TT> on MacOS X. </LI> +<LI><TT>FL_SCROLL_LOCK</TT> - The scroll lock is on. </LI> +<LI><TT>FL_BUTTON1</TT> - Mouse button 1 is pushed. </LI> +<LI><TT>FL_BUTTON2</TT> - Mouse button 2 is pushed. </LI> +<LI><TT>FL_BUTTON3</TT> - Mouse button 3 is pushed. </LI> +<LI><TT>FL_BUTTONS</TT> - Any mouse button is pushed. </LI> +<LI><TT>FL_BUTTON(n)</TT> - Mouse button N (N > 0) is pushed. </LI> + +</UL> +<!-- NEED 4in --> +<H2><a name=align>Alignment Values</A></H2> + The following constants define bits that can be used with <A href=Fl_Widget.html#Fl_Widget.align> +<TT>Fl_Widget::align()</TT></A> to control the positioning of the +label: +<UL> +<LI><TT>FL_ALIGN_CENTER</TT> - The label is centered (0). </LI> +<LI><TT>FL_ALIGN_TOP</TT> - The label is top-aligned. </LI> +<LI><TT>FL_ALIGN_BOTTOM</TT> - The label is bottom-aligned. </LI> +<LI><TT>FL_ALIGN_LEFT</TT> - The label is left-aligned. </LI> +<LI><TT>FL_ALIGN_RIGHT</TT> - The label is right-aligned. </LI> +<LI><TT>FL_ALIGN_CLIP</TT> - The label is clipped to the widget. </LI> +<LI><TT>FL_ALIGN_WRAP</TT> - The label text is wrapped as needed. </LI> +<LI><TT>FL_ALIGN_TOP_LEFT</TT></LI> +<LI><TT>FL_ALIGN_TOP_RIGHT</TT></LI> +<LI><TT>FL_ALIGN_BOTTOM_LEFT</TT></LI> +<LI><TT>FL_ALIGN_BOTTOM_RIGHT</TT></LI> +<LI><TT>FL_ALIGN_LEFT_TOP</TT></LI> +<LI><TT>FL_ALIGN_RIGHT_TOP</TT></LI> +<LI><TT>FL_ALIGN_LEFT_BOTTOM</TT></LI> +<LI><TT>FL_ALIGN_RIGHT_BOTTOM</TT></LI> +<LI><TT>FL_ALIGN_INSIDE</TT> - 'or' this with other values to put +label inside the widget. </LI> + +</UL> +<H2><a name=fonts>Fonts</A></H2> + The following constants define the standard FLTK fonts: +<ul> +<LI><TT>FL_HELVETICA</TT> - Helvetica (or Arial) normal (0). </LI> +<LI><TT>FL_HELVETICA_BOLD</TT> - Helvetica (or Arial) bold. </LI> +<LI><TT>FL_HELVETICA_ITALIC</TT> - Helvetica (or Arial) oblique. </LI> +<LI><TT>FL_HELVETICA_BOLD_ITALIC</TT> - Helvetica (or Arial) +bold-oblique. </LI> +<LI><TT>FL_COURIER</TT> - Courier normal. </LI> +<LI><TT>FL_COURIER_BOLD</TT> - Courier bold. </LI> +<LI><TT>FL_COURIER_ITALIC</TT> - Courier italic. </LI> +<LI><TT>FL_COURIER_BOLD_ITALIC</TT> - Courier bold-italic. </LI> +<LI><TT>FL_TIMES</TT> - Times roman. </LI> +<LI><TT>FL_TIMES_BOLD</TT> - Times bold. </LI> +<LI><TT>FL_TIMES_ITALIC</TT> - Times italic. </LI> +<LI><TT>FL_TIMES_BOLD_ITALIC</TT> - Times bold-italic. </LI> +<LI><TT>FL_SYMBOL</TT> - Standard symbol font. </LI> +<LI><TT>FL_SCREEN</TT> - Default monospaced screen font. </LI> +<LI><TT>FL_SCREEN_BOLD</TT> - Default monospaced bold screen font. </LI> +<LI><TT>FL_ZAPF_DINGBATS</TT> - Zapf-dingbats font. +</ul> + +<H2><a name=colors>Colors</A></H2> + +<P>The <TT>Fl_Color</TT> enumeration type holds a FLTK color value. +Colors are either 8-bit indexes into a virtual colormap or 24-bit RGB +color values. Color indices occupy the lower 8 bits of the value, while +RGB colors occupy the upper 24 bits, for a byte organization of RGBI. + +<H3>Color Constants</H3> + +<P>Constants are defined for the user-defined foreground and background +colors, as well as specific colors and the start of the grayscale ramp +and color cube in the virtual colormap. Inline functions are provided to +retrieve specific grayscale, color cube, or RGB color values. + +<P>The following color constants can be used to access the user-defined +colors: + +<UL> + + <LI><TT>FL_BACKGROUND_COLOR</TT> - the default + background color</LI> + + <LI><TT>FL_BACKGROUND2_COLOR</TT> - the default + background color for text, list, and valuator widgets</LI> + + <LI><TT>FL_FOREGROUND_COLOR</TT> - the default + foreground color (0) used for labels and text</LI> + + <LI><TT>FL_INACTIVE_COLOR</TT> - the inactive foreground + color</LI> + + <LI><TT>FL_SELECTION_COLOR</TT> - the default selection/highlight + color</LI> + +</UL> + +<P>The following color constants can be used to access the colors from the +FLTK standard color cube: + +<UL> + + <LI><TT>FL_BLACK</TT></LI> + <LI><TT>FL_BLUE</TT></LI> + <LI><TT>FL_CYAN</TT></LI> + <LI><TT>FL_DARK_BLUE</TT></LI> + <LI><TT>FL_DARK_CYAN</TT></LI> + <LI><TT>FL_DARK_GREEN</TT></LI> + <LI><TT>FL_DARK_MAGENTA</TT></LI> + <LI><TT>FL_DARK_RED</TT></LI> + <LI><TT>FL_DARK_YELLOW</TT></LI> + <LI><TT>FL_GREEN</TT></LI> + <LI><TT>FL_MAGENTA</TT></LI> + <LI><TT>FL_RED</TT></LI> + <LI><TT>FL_WHITE</TT></LI> + <LI><TT>FL_YELLOW</TT></LI> + +</UL> + +<P>The inline methods for getting a grayscale, color cube, or +RGB color value are described in <A +HREF="functions.html#functions">Appendix B - Function +Reference</A>. + +<H2><a name=cursor>Cursors</A></H2> + +<P>The following constants define the mouse cursors that are available in +FLTK. The double-headed arrows are bitmaps +provided by FLTK on X, the others are provided by system-defined +cursors.</P> + +<UL> + + <LI><TT>FL_CURSOR_DEFAULT</TT> - the default cursor, usually an arrow (0)</LI> + <LI><TT>FL_CURSOR_ARROW</TT> - an arrow pointer </LI> + <LI><TT>FL_CURSOR_CROSS</TT> - crosshair </LI> + <LI><TT>FL_CURSOR_WAIT</TT> - watch or hourglass </LI> + <LI><TT>FL_CURSOR_INSERT</TT> - I-beam </LI> + <LI><TT>FL_CURSOR_HAND</TT> - hand (uparrow on MSWindows) </LI> + <LI><TT>FL_CURSOR_HELP</TT> - question mark </LI> + <LI><TT>FL_CURSOR_MOVE</TT> - 4-pointed arrow </LI> + <LI><TT>FL_CURSOR_NS</TT> - up/down arrow </LI> + <LI><TT>FL_CURSOR_WE</TT> - left/right arrow </LI> + <LI><TT>FL_CURSOR_NWSE</TT> - diagonal arrow </LI> + <LI><TT>FL_CURSOR_NESW</TT> - diagonal arrow </LI> + <LI><TT>FL_CURSOR_NONE</TT> - invisible </LI> + +</UL> + +<H2>FD "When" Conditions</H2> + +<UL> + + <LI><TT>FL_READ</TT> - Call the callback when there is data to be + read.</LI> + + <LI><TT>FL_WRITE</TT> - Call the callback when data can be written + without blocking.</LI> + + <LI><TT>FL_EXCEPT</TT> - Call the callback if an exception occurs on + the file.</LI> + +</UL> + +<H2><a name=damage>Damage Masks</A></H2> + The following damage mask bits are used by the standard FLTK widgets: +<UL> +<LI><TT>FL_DAMAGE_CHILD</TT> - A child needs to be redrawn. </LI> +<LI><TT>FL_DAMAGE_EXPOSE</TT> - The window was exposed. </LI> +<LI><TT>FL_DAMAGE_SCROLL</TT> - The <TT>Fl_Scroll</TT> widget was + scrolled. </LI> +<LI><TT>FL_DAMAGE_OVERLAY</TT> - The overlay planes need to be redrawn. </LI> +<LI><TT>FL_DAMAGE_USER1</TT> - First user-defined damage bit. </LI> +<LI><TT>FL_DAMAGE_USER2</TT> - Second user-defined damage bit. </LI> +<LI><TT>FL_DAMAGE_ALL</TT> - Everything needs to be redrawn. </LI> +</UL> + +*/ diff --git a/documentation/events.dox b/documentation/events.dox new file mode 100644 index 000000000..d2610064e --- /dev/null +++ b/documentation/events.dox @@ -0,0 +1,389 @@ +/** + + \page events 6 - Handling Events + +<P>This chapter discusses the FLTK event model and how to handle +events in your program or widget. + +<H2>The FLTK Event Model</H2> + +<P>Every time a user moves the mouse pointer, clicks a button, +or presses a key, an event is generated and sent to your +application. Events can also come from other programs like the +window manager. + +<P>Events are identified by the integer argument passed to the +<A href="subclassing.html#handle"><TT>Fl_Widget::handle()</TT></A> virtual +method. Other information about the most recent event is stored in +static locations and acquired by calling the <A +href="#event_xxx"><TT>Fl::event_*()</TT></A> methods. This static +information remains valid until the next event is read from the window +system, so it is ok to look at it outside of the <TT>handle()</TT> +method. + +<H2>Mouse Events</H2> + +<H3>FL_PUSH</H3> + +<P>A mouse button has gone down with the mouse pointing at this +widget. You can find out what button by calling <A +href="Fl.html#Fl.event_button"><TT> +Fl::event_button()</TT></A>. You find out the mouse position by +calling <A +href="Fl.html#Fl.event_x"><TT>Fl::event_x()</TT></A> and <A +href="Fl.html#Fl.event_y"> <TT>Fl::event_y()</TT></A>. + +<P>A widget indicates that it "wants" the mouse click +by returning non-zero from its <A +href="subclassing.html#handle"><TT>handle()</TT></A> method. It +will then become the <A href="Fl.html#Fl.pushed"><TT> +Fl::pushed()</TT></A> widget and will get <TT>FL_DRAG</TT> and +the matching <TT>FL_RELEASE</TT> events. If <TT>handle()</TT> +returns zero then FLTK will try sending the <TT>FL_PUSH</TT> to +another widget. </P> + +<H3>FL_DRAG</H3> + +<P>The mouse has moved with a button held down. The current +button state is in <a +href="Fl.html#Fl.event_state"><tt>Fl::event_state()</tt></a>. +The mouse position is in <a +href="Fl.html#Fl.event_x"><tt>Fl::event_x()</tt></a> and <a +href="Fl.html#Fl.event_y"><tt>Fl::event_y()</tt></a>. + +<P>In order to receive <TT>FL_DRAG</TT> events, the widget must +return non-zero when handling <TT>FL_PUSH</TT>.</P> + +<H3>FL_RELEASE</H3> + +<P>A mouse button has been released. You can find out what +button by calling <A +href="Fl.html#Fl.event_button"><TT>Fl::event_button()</TT></A>. + +<P>In order to receive the <TT>FL_RELEASE</TT> event, the widget must +return non-zero when handling <TT>FL_PUSH</TT>.</P> + +<H3>FL_MOVE</H3> + +<P>The mouse has moved without any mouse buttons held down. +This event is sent to the <A +href="Fl.html#Fl.belowmouse"><TT>Fl::belowmouse()</TT></A> +widget.</P> + +<P>In order to receive <TT>FL_MOVE</TT> events, the widget must +return non-zero when handling <TT>FL_ENTER</TT>.</P> + +<H3>FL_MOUSEWHEEL</H3> + +<P>The user has moved the mouse wheel. The <A +HREF="Fl.html#Fl.event_dx"><TT>Fl::event_dx()</TT></A> and <A +HREF="Fl.html#Fl.event_dy"><TT>Fl::event_dy()</TT></A> methods +can be used to find the amount to scroll horizontally and +vertically. + +<H2>Focus Events</H2> + +<H3>FL_ENTER</H3> + +<P>The mouse has been moved to point at this widget. This can +be used for highlighting feedback. If a widget wants to +highlight or otherwise track the mouse, it indicates this by +returning non-zero from its <A +href="Fl.html#Fl.handle"><TT>handle()</TT></A> method. It then +becomes the <A +href="Fl.html#Fl.belowmouse"><TT>Fl::belowmouse()</TT></A> +widget and will receive <TT>FL_MOVE</TT> and <TT>FL_LEAVE</TT> +events. + +<H3>FL_LEAVE</H3> + +<P>The mouse has moved out of the widget. + +<P>In order to receive the <TT>FL_LEAVE</TT> event, the widget must +return non-zero when handling <TT>FL_ENTER</TT>.</P> + +<H3>FL_FOCUS</H3> + +<P>This indicates an <I>attempt</I> to give a widget the +keyboard focus. + +<P>If a widget wants the focus, it should change itself to +display the fact that it has the focus, and return non-zero from +its <A +href="Fl_Widget.html#Fl_Widget.handle"><TT>handle()</TT></A> +method. It then becomes the <A +href="Fl.html#Fl.focus"><TT>Fl::focus()</TT></A> widget and gets +<TT>FL_KEYDOWN</TT>, <TT>FL_KEYUP</TT>, and <TT>FL_UNFOCUS</TT> +events. + +<P>The focus will change either because the window manager +changed which window gets the focus, or because the user tried +to navigate using tab, arrows, or other keys. You can check <A +href="Fl.html#Fl.event_key"><TT>Fl::event_key()</TT></A> to +figure out why it moved. For navigation it will be the key +pressed and interaction with the window manager it will be +zero. + +<H3>FL_UNFOCUS</H3> + +<P>This event is sent to the previous <A +href="Fl.html#Fl.focus"><TT>Fl::focus()</TT></A> widget when +another widget gets the focus or the window loses focus. + +<H2>Keyboard Events</H2> + +<H3>FL_KEYDOWN, FL_KEYUP</H3> + +<P>A key was pressed or released. The key can be found in <A +href="Fl.html#Fl.event_key"><TT>Fl::event_key()</TT></A>. The +text that the key should insert can be found with <A +href="Fl.html#Fl.event_text"><TT>Fl::event_text()</TT></A> and +its length is in <A +href="Fl.html#Fl.event_length"><TT>Fl::event_length()</TT></A>. +If you use the key <TT>handle()</TT> should return 1. If you +return zero then FLTK assumes you ignored the key and will +then attempt to send it to a parent widget. If none of them want +it, it will change the event into a <TT>FL_SHORTCUT</TT> event. + +<P>To receive <CODE>FL_KEYBOARD</CODE> events you must also +respond to the <CODE>FL_FOCUS</CODE> and <CODE>FL_UNFOCUS</CODE> +events. + +<P>If you are writing a text-editing widget you may also want to +call the <a href="Fl.html#Fl.compose"><TT>Fl::compose()</TT></a> +function to translate individual keystrokes into foreign +characters. + +<P><code>FL_KEYUP</code> events are sent to the widget that +currently has focus. This is not necessarily the same widget +that received the corresponding <code>FL_KEYDOWN</code> event +because focus may have changed between events. + +<H3>FL_SHORTCUT</H3> + +<P>If the <A href="Fl.html#Fl.focus"><TT>Fl::focus()</TT></A> +widget is zero or ignores an <TT>FL_KEYBOARD</TT> event then +FLTK tries sending this event to every widget it can, until one +of them returns non-zero. <TT>FL_SHORTCUT</TT> is first sent to +the <TT>Fl::belowmouse()</TT> widget, then its parents and +siblings, and eventually to every widget in the window, trying +to find an object that returns non-zero. FLTK tries really hard +to not to ignore any keystrokes! + +<P>You can also make "global" shortcuts by using <A +href="Fl.html#Fl.add_handler"><TT>Fl::add_handler()</TT></A>. A +global shortcut will work no matter what windows are displayed +or which one has the focus.</P> + +<H2>Widget Events</H2> + +<H3>FL_DEACTIVATE</H3> + +<P>This widget is no longer active, due to <A +href="Fl_Widget.html#Fl_Widget.deactivate"><TT>deactivate()</TT></A> +being called on it or one of its parents. <TT> active()</TT> may +still be true after this, the widget is only active if +<TT>active()</TT> is true on it and all its parents (use <TT>active_r()</TT> to check this). + +<H3>FL_ACTIVATE</H3> + +<P>This widget is now active, due to <A +href="Fl_Widget.html#Fl_Widget.activate"><TT>activate()</TT></A> +being called on it or one of its parents. + +<H3>FL_HIDE</H3> + +<P>This widget is no longer visible, due to <A +href="Fl_Widget.html#Fl_Widget.hide"><tt>hide()</tt></a> being +called on it or one of its parents, or due to a parent window +being minimized. <tt>visible()</tt> may still be true after +this, but the widget is visible only if <tt>visible()</tt> is +true for it and all its parents (use <tt>visible_r()</tt> to +check this). + +<h3>FL_SHOW</h3> + +<P>This widget is visible again, due to <a +href="Fl_Widget.html#Fl_Widget.show"><TT>show()</TT></A> being +called on it or one of its parents, or due to a parent window +being restored. <I>Child <TT>Fl_Window</TT>s respond to this by +actually creating the window if not done already, so if you +subclass a window, be sure to pass <TT>FL_SHOW</TT> to the base +class <TT>handle()</TT> method!</I> + +<H2>Clipboard Events</H2> + +<H3>FL_PASTE</H3> + +<P>You should get this event some time after you call <A +href="Fl.html#Fl.paste"><TT>Fl::paste()</TT></A>. The contents +of <A href="Fl.html#Fl.event_text"><TT>Fl::event_text()</TT></A> +is the text to insert and the number of characters is in <A +href="Fl.html#Fl.event_length"><TT>Fl::event_length()</TT></A>. + +<H3>FL_SELECTIONCLEAR</H3> + +<P>The <A +href="Fl.html#Fl.selection_owner"><TT>Fl::selection_owner()</TT></A> +will get this event before the selection is moved to another +widget. This indicates that some other widget or program has +claimed the selection. Motif programs used this to clear the +selection indication. Most modern programs ignore this. + +<H2><A NAME="dnd">Drag And Drop Events</A></H2> + +<P>FLTK supports drag and drop of text and files from any +application on the desktop. Text is transfered using +the current code page. Files are received as a list of full path +and file names, seperated by newline. On some platforms, path +names are prepended with <tt>file://</tt>. + +<P>The drag and drop data is available in <tt>Fl::event_text()</tt> +at the concluding <tt>FL_PASTE</tt>. On some platforms, the +event text is also available for the <tt>FL_DND_*</tt> events, +however application must not depend on that behavior because it +depends on the protocol used on each platform. + +<P><tt>FL_DND_*</tt> events cannot be used in widgets derived +from <tt>Fl_Group</tt> or <tt>Fl_Window</tt>. + +<H3>FL_DND_ENTER</H3> + +<P>The mouse has been moved to point at this widget. A widget +that is interested in receiving drag'n'drop data must return 1 +to receive FL_DND_DRAG, FL_DND_LEAVE and FL_DND_RELEASE events. + +<H3>FL_DND_DRAG</H3> + +<P>The mouse has been moved inside a widget while dragging data. +A widget that is interested in receiving drag'n'drop data should +indicate the possible drop position. + +<H3>FL_DND_LEAVE</H3> + +<P>The mouse has moved out of the widget. + +<H3>FL_DND_RELEASE</H3> + +<P>The user has released the mouse button dropping data into +the widget. If the widget returns 1, it will receive the data in +the immediatly following FL_PASTE event. + +<!-- NEED 6in --> + +<H2><A name="event_xxx">Fl::event_*() methods</A></H2> + +<P>FLTK keeps the information about the most recent event in +static storage. This information is good until the next event is +processed. Thus it is valid inside <TT>handle()</TT> and +<TT>callback()</TT> methods. + +<P>These are all trivial inline functions and thus very fast and small: </P> + +<UL> + + <LI><A HREF="Fl.html#Fl.event_button"><TT>Fl::event_button</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_clicks"><TT>Fl::event_clicks</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_dx"><TT>Fl::event_dx</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_dy"><TT>Fl::event_dy</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_inside"><TT>Fl::event_inside</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_is_click"><TT>Fl::event_is_click</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_key"><TT>Fl::event_key</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_length"><TT>Fl::event_length</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_state"><TT>Fl::event_state</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_text"><TT>Fl::event_text</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_x"><TT>Fl::event_x</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_x_root"><TT>Fl::event_x_root</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_y"><TT>Fl::event_y</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.event_y_root"><TT>Fl::event_y_root</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.get_key"><TT>Fl::get_key</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.get_mouse"><TT>Fl::get_mouse</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.test_shortcut"><TT>Fl::test_shortcut</TT></A></LI> + +</UL> + +<H2><A name=propagation>Event Propagation</A></H2> + +<P>FLTK follows very simple and unchangeable rules for sending +events. The major innovation is that widgets can indicate (by +returning 0 from the <TT>handle()</TT> method) that they are not +interested in an event, and FLTK can then send that event +elsewhere. This eliminates the need for "interests" +(event masks or tables), and this is probably the main reason +FLTK is much smaller than other toolkits. + +<P>Most events are sent directly to the <TT>handle()</TT> method +of the <TT>Fl_Window</TT> that the window system says they +belong to. The window (actually the <TT>Fl_Group</TT> that +<TT>Fl_Window</TT> is a subclass of) is responsible for sending +the events on to any child widgets. To make the +<TT>Fl_Group</TT> code somewhat easier, FLTK sends some events +(<TT>FL_DRAG</TT>, <TT>FL_RELEASE</TT>, <TT>FL_KEYBOARD</TT>, +<TT>FL_SHORTCUT</TT>, <TT>FL_UNFOCUS</TT>, and +<TT>FL_LEAVE</TT>) directly to leaf widgets. These procedures +control those leaf widgets: + +<UL> + + <LI><A HREF="Fl.html#Fl.add_handler"><TT>Fl::add_handler</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.belowmouse"><TT>Fl::belowmouse</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.focus"><TT>Fl::focus</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.grab"><TT>Fl::grab</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.modal"><TT>Fl::modal</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.pushed"><TT>Fl::pushed</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.release"><TT>Fl::release</TT></A></LI> + + <LI><A HREF="Fl_Widget.html#Fl_Widget.take_focus"><TT>Fl_Widget::take_focus</TT></A></LI> + +</UL> + +<H2><A name="compose">FLTK Compose-Character Sequences</A></H2> + +<P>The foreign-letter compose processing done by the <A +href="Fl_Input.html#compose"><tt>Fl_Input</tt></a> widget is provided in +a function that you can call if you are writing your own text editor +widget. + +<p>FLTK uses its own compose processing to allow "preview" of +the partially composed sequence, which is impossible with the +usual "dead key" processing. + +<p>Although currently only characters in the ISO-8859-1 +character set are handled, you should call this in case any +enhancements to the processing are done in the future. The +interface has been designed to handle arbitrary UTF-8 encoded +text. + +<P>The following methods are provided for character composition: + +<UL> + + <LI><A HREF="Fl.html#Fl.compose"><TT>Fl::compose()</TT></A></LI> + + <LI><A HREF="Fl.html#Fl.compose_reset"><TT>Fl::compose_reset()</TT></A></LI> + +</UL> + +*/ diff --git a/documentation/examples.dox b/documentation/examples.dox new file mode 100644 index 000000000..7ae2482d9 --- /dev/null +++ b/documentation/examples.dox @@ -0,0 +1,448 @@ +/** + + \page examples J - Example Source Code + +<P ALIGN="RIGHT">March 19, 2005</P> + +<P>The FLTK distribution contains over 60 sample applications written +in, or ported to, FLTK. If the FLTK archive you received does not +contain a 'test' directory, you can download the complete FLTK +distribution from +<a href="http://fltk.org/software.php">http://fltk.org/software.php</a>.</P> + +<P>Most of the example programs were created while testing a group of widgets. +They are not meant to be great achievements in clean C++ programming, but merely +a test platform to verify the functionality of the FLTK library.</P> + +<table width=100% border=0> +<tr><td colspan=4><font size=+1><b>Example Applications</b></font></td> +<tr> +<td><a href="#adjuster"><tt>adjuster</tt></a></td> +<td><a href="#arc"><tt>arc</tt></a></td> +<td><a href="#ask"><tt>ask</tt></a></td> +<td><a href="#bitmap"><tt>bitmap</tt></a></td> +<td><a href="#blocks"><tt>blocks</tt></a></td> +<td><a href="#boxtype"><tt>boxtype</tt></a></td> +</tr> +<tr> +<td><a href="#browser"><tt>browser</tt></a></td> +<td><a href="#button"><tt>button</tt></a></td> +<td><a href="#buttons"><tt>buttons</tt></a></td> +<td><a href="#checkers"><tt>checkers</tt></a></td> +<td><a href="#clock"><tt>clock</tt></a></td> +<td><a href="#colbrowser"><tt>colbrowser</tt></a></td> +</tr> +<tr> +<td><a href="#color_chooser"><tt>color_chooser</tt></a></td> +<td><a href="#cube"><tt>cube</tt></a></td> +<td><a href="#CubeView"><tt>CubeView</tt></a></td> +<td><a href="#cursor"><tt>cursor</tt></a></td> +<td><a href="#curve"><tt>curve</tt></a></td> +<td><a href="#demo"><tt>demo</tt></a></td> +</tr> +<tr> +<td><a href="#doublebuffer"><tt>doublebuffer</tt></a></td> +<td><a href="#editor"><tt>editor</tt></a></td> +<td><a href="#fast_slow"><tt>fast_slow</tt></a></td> +<td><a href="#file_chooser"><tt>file_chooser</tt></a></td> +<td><a href="#fluid"><tt>fluid</tt></a></td> +<td><a href="#fonts"><tt>fonts</tt></a></td> +</tr> +<tr> +<td><a href="#forms"><tt>forms</tt></a></td> +<td><a href="#fractals"><tt>fractals</tt></a></td> +<td><a href="#fullscreen"><tt>fullscreen</tt></a></td> +<td><a href="#gl_overlay"><tt>gl_overlay</tt></a></td> +<td><a href="#glpuzzle"><tt>glpuzzle</tt></a></td> +<td><a href="#hello"><tt>hello</tt></a></td> +</tr> +<tr> +<td><a href="#help"><tt>help</tt></a></td> +<td><a href="#iconize"><tt>iconize</tt></a></td> +<td><a href="#image"><tt>image</tt></a></td> +<td><a href="#inactive"><tt>inactive</tt></a></td> +<td><a href="#input"><tt>input</tt></a></td> +<td><a href="#input_choice"><tt>input_choice</tt></a></td> +</tr> +<tr> +<td><a href="#keyboard"><tt>keyboard</tt></a></td> +<td><a href="#label"><tt>label</tt></a></td> +<td><a href="#line_style"><tt>line_style</tt></a></td> +<td><a href="#list_visuals"><tt>list_visuals</tt></a></td> +<td><a href="#mandelbrot"><tt>mandelbrot</tt></a></td> +<td><a href="#menubar"><tt>menubar</tt></a></td> +</tr> +<tr> +<td><a href="#message"><tt>message</tt></a></td> +<td><a href="#minimum"><tt>minimum</tt></a></td> +<td><a href="#navigation"><tt>navigation</tt></a></td> +<td><a href="#output"><tt>output</tt></a></td> +<td><a href="#overlay"><tt>overlay</tt></a></td> +<td><a href="#pack"><tt>pack</tt></a></td> +</tr> +<tr> +<td><a href="#pixmap_browser"><tt>pixmap_browser</tt></a></td> +<td><a href="#pixmap"><tt>pixmap</tt></a></td> +<td><a href="#preferences"><tt>preferences</tt></a></td> +<td><a href="#radio"><tt>radio</tt></a></td> +<td><a href="#resizebox"><tt>resizebox</tt></a></td> +<td><a href="#resize"><tt>resize</tt></a></td> +</tr> +<tr> +<td><a href="#scroll"><tt>scroll</tt></a></td> +<td><a href="#shape"><tt>shape</tt></a></td> +<td><a href="#subwindow"><tt>subwindow</tt></a></td> +<td><a href="#sudoku"><tt>sudoku</tt></a></td> +<td><a href="#symbols"><tt>symbols</tt></a></td> +<td><a href="#tabs"><tt>tabs</tt></a></td> +</tr> +<tr> +<td><a href="#threads"><tt>threads</tt></a></td> +<td><a href="#tile"><tt>tile</tt></a></td> +<td><a href="#tiled_image"><tt>tiled_image</tt></a></td> +<td><a href="#valuators"><tt>valuators</tt></a></td> +</tr> +</table> + +<h3><a name="adjuster">adjuster</h3> +<tt>adjuster</tt> shows a nifty little widget for quickly +setting values in a great range. + +<h3><a name="arc">arc</h3> +The <tt>arc</tt> demo explains how to derive your own widget to +generate some custom drawings. The sample drawings use the matrix +based arc drawing for some fun effects. + +<h3><a name="ask">ask</h3> +<tt>ask</tt> shows some of FLTK's standard dialog boxes. Click +the correct answers or you may end up in a loop, or you may end +up in a loop, or you... . + +<h3><a name="bitmap">bitmap</h3> +This simple test shows the use of a single color bitmap as a +label for a box widget. Bitmaps are stored in the X11 '.bmp' +file format and can be part of the source code. + +<h3><a name="blocks">blocks</h3> +A wonderful and addictive game that shows the usage of FLTK +timers, graphics, and how to implement sound on all platforms. +<tt>blocks</tt> is also a good example for the Mac OS X specific +bundle format. + +<h3><a name="boxtype">boxtype</h3> +<tt>boxtype</tt> gives an overview of readily available boxes and +frames in FLTK. More types can be added by the application programmer. +When using themes, FLTK shuffles boxtypes around to give your program +a new look. + +<h3><a name="browser">browser</h3> +<tt>browser</tt> shows the capabilities of the <tt>Fl_Browser</tt> widget. +Important features tested are loading of files, line formatting, and +correct positioning of the browser data window. + +<h3><a name="button">button</h3> +The <tt>button</tt> test is a simple demo of push-buttons and callbacks. + +<h3><a name="buttons">buttons</h3> +<tt>buttons</tt> shows a sample of FLTK button types. + +<h3><a name="checkers">checkers</h3> +Written by Steve Poulsen in early 1979, <tt>checkers</tt> shows +how to convert a VT100 text-terminal based program into a neat +application with a graphical UI. Check out the code that drags the +pieces, and how the pieces are drawn by layering. Then tell me +how to beat the computer at Checkers. + +<h3><a name="clock">clock</h3> +The <tt>clock</tt> demo shows two analog clocks. The innards of +the <tt>Fl_Clock</tt> widget are pretty interesting, explaining +the use of timeouts and matrix based drawing. + +<h3><a name="colbrowser">colbrowser</h3> +<tt>colbrowser</tt> runs only on X11 systems. It reads +<i>/usr/lib/X11/rgb.txt</i> to show the color representation +of every text entry in the file. This is beautiful, but +only moderatly useful unless your UI is written in <i>Motif</i>. + +<h3><a name="color_chooser">color_chooser</h3> +The <tt>color_chooser</tt> gives a short demo of FLTK's palette based +color chooser and of the RGB based color wheel. + +<h3><a name="cube">cube</h3> +The <tt>cube</tt> demo shows the speed of OpenGL. It also tests +the ability to render two OpenGL buffers into a single window, +and shows OpenGL text. + +<h3><a name="CubeView">CubeView</h3> +<tt>CubeView</tt> shows how to create a UI containing OpenGL with Fluid. + +<h3><a name="cursor">cursor</h3> +The <tt>cursor</tt> demo show all mouse cursor shapes that come standard +with FLTK. The <i>fgcolor</i> and <i>bgcolor</i> sliders work only +on few systems (some version of Irix for example). + +<h3><a name="curve">curve</h3> +<tt>curve</tt> draws a nice Bezier curve into a custom widget. The +<i>points</i> option for splines is not supported on all platforms. + +<h3><a name="demo">demo</h3> +This tool allows quick access to all programs in the <tt>test</tt> directory. +<tt>demo</tt> is based on the visuals of the IrixGL demo program. The menu +tree can be changed by editing <tt>test/demo.menu</tt>. + +<h3><a name="doublebuffer">doublebuffer</h3> +The <tt>doublebuffer</tt> demo show the difference between a single +buffered window, which may flicker during a slow redraw, and a +double buffered window, which never flickers, but uses twice the +amount of RAM. Some modern OS's double buffer all windows automatically +to allow transparency and shadows on the desktop. FLTK is smart enough +to not tripple buffer a window in that case. + +<h3><a name="editor">editor</h3> +FLTK has two very different text input widgets. <tt>Fl_Input</tt> +and derived classes are rather leight weight, however +<tt>Fl_Text_Editor</tt> is a complete port of <i>nedit</i> (with permission). +The <tt>editor</tt> test is almost a full application, showing custom +syntax highlighting and dialog creation. + +<h3><a name="fast_slow">fast_slow</h3> +<tt>fast_slow</tt> shows how an application can use then <tt>when()</tt> +setting to receive different kinds of callbacks. + +<h3><a name="file_chooser">file_chooser</h3> +The standard FLTK <tt>file_chooser</tt> is the result of many +iterations, trying to find a middle ground between a complex +browser and a fast light implementation. + +<h3><a name="fonts">fonts</h3> +<tt>fonts</tt> show all available text fonts on the host system. +If your machine still has some pixmap based fonts, the supported +sizes will be shown in bold face. Only the first 256 fonts will +be listed. + +<h3><a name="forms">forms</h3> +<tt>forms</tt> is an XForms program with very few changes. +Search for "fltk" to find all changes necessary to port to fltk. +This demo show the different boxtypes. Note that some +boxtypes are not appropriate for some objects. + +<h3><a name="fractals">fractals</h3> +<tt>fractals</tt> shows how to mix OpenGL, Glut and FLTK code. +FLTK supports a rather large subset of Glut, so that many Glut +application compile just fine. + +<h3><a name="fullscreen">fullscreen</h3> +This demo shows how to do many of the window manipulations that +are popular for games. +You can toggle the border on/off, switch between single- +and double-buffered rendering, and take over the entire +screen. More information in the source code. + +<h3><a name="gl_overlay">gl_overlay</h3> +<tt>gl_overlay</tt> shows OpenGL overlay plane rendering. If no +hardware overlay plane is available, FLTK will simulate it +for you. + +<h3><a name="glpuzzle">glpuzzle</h3> +The <tt>glpuzzle</tt> test shows how most Glut source code compiles +easily under FLTK. + +<h3><a name="hello">hello</h3> +<tt>hello</tt>: Hello, World. Need I say maore? Well, maybe. This +tiny demo shows how little is needed to get a functioning application +running with FLTK. Quite impressive, I'd say. + +<h3><a name="help">help</h3> +<tt>help</tt> displays the built-in FLTK help browser. The +<tt>Fl_Help_Dialog</tt> understands a subset of html and renders +various image formats. This widget makes it easy to provide help +pages to the user without depending on the operating system's +html browser. + +<h3><a name="iconize">iconize</h3> +<tt>iconize</tt> demonstrates the effect of the window functions +<tt>hide()</tt>, <tt>iconize()</tt>, and <tt>show()</tt>. + +<h3><a name="image">image</h3> +The <tt>image</tt> demo shows how an image can be created on the fly. +This generated image contains an alpha (transparency) channel which +lets previous renderings 'shine through', either via true +transparency or by using screen door transparency (pixelation). + +<h3><a name="inactive">inactive</h3> +<tt>inactive</tt> tests the correct rendering of inactive widgets. +To see the inactive version of images, you can check out the pixmap +or image test. + +<h3><a name="input">input</h3> +This tool shows and tests different types of text input fields based on +<tt>Fl_Input_</tt>. The <tt>input</tt> program also tests various +settings of <tt>Fl_Input::when()</tt>. + +<h3><a name="input_choice">input_choice</h3> +<tt>input_choice</tt> tests the latest addition to FLTK1, a text input +field with an attached pulldown menu. Windows users will recognize +similarities to the 'ComboBox'. <tt>input_choice</tt> starts up in +'plastic' scheme, but the traditional scheme is also supported. + +<h3><a name="keyboard">keyboard</h3> +FLTK unifies keyboard events for all platforms. The <tt>keyboard</tt> +test can be used to check the return values of <tt>Fl::event_key()</tt> +and <tt>Fl::event_text()</tt>. It is also great to see the modifier +buttons and the scroll wheel at work. Quit this application by closing +the window. The ESC key will not work. + +<h3><a name="label">label</h3> +Every FLTK widget can have a label attached to it. The <tt>label</tt> +demo shows alignment, clipping and wrapping of text labels. Labels +can contain symbols at the start and end of the text, like <i>@FLTK</i> +or <i>@circle uh-huh @square</i>. + +<h3><a name="line_style">line_style</h3> +Advanced line drawing can be tested with <tt>line_style</tt>. +Not all platforms support all line styles. + +<h3><a name="list_visuals">list_visuals</h3> +This little app finds all available pixel formats for the current X11 +screen. But since you are now an FLTK user, you don't have to worry +about any of this. + +<h3><a name="mandelbrot">mandelbrot</h3> +<tt>mandelbrot</tt> shows two advanced topics in one test. It creates +grayscale images on the fly, updating them via the <i>idle</i> callback +system. This is one of the few occasions where the <i>idle</i> callback +is very useful by giving all available processor time to the application +without blocking the UI or other apps. + +<h3><a name="menubar">menubar</h3> +The <tt>menubar</tt> tests many aspects of FLTK's popup menu system. +Among the features are radio buttons, menus taller than the screen, +arbitrary sub menu depth, and global shortcuts. + +<h3><a name="message">message</h3> +<tt>message</tt> pops up a few of FLTK's standars message boxes. + +<h3><a name="minimum">minimum</h3> +The <tt>minimum</tt> test program verifies that the update regions +are set correctly. In a real life application, the trail would +be avoided by choosing a smaller label or by setting label clipping +differently. + +<h3><a name="navigation">navigation</h3> +<tt>navigation</tt> demonstrates how the text cursor moves from +text field to text field when using the arrow keys, tab, and shift-tab. + +<h3><a name="output">output</h3> +<tt>output</tt> shows the difference between the single line and +multi line mode of the <tt>Fl_Output</tt> widget. Fonts can be +selected from the FLTK standard list of fonts. + +<h3><a name="overlay">overlay</h3> +The <tt>overlay</tt> test app show how easy an FLTK window can +be layered to display cursor and manipulator style elemnts. This +example derives a new class from <tt>Fl_Overly_WIndow</tt> and +provides a new function to draw custom overlays. + +<h3><a name="pack">pack</h3> +The <tt>pack</tt> test program demonstrates the resizing +and repositioning of children of the <tt>Fl_Pack</tt> group. +Putting an <tt>Fl_Pack</tt> into an <tt>Fl_Scroll</tt> is +a useful way to create a browser for large sets of data. + +<h3><a name="pixmap_browser">pixmap_browser</h3> +<tt>pixmap_browser</tt> tests the shared-image interface. When using +the same image multiple times, <tt>Fl_Shared_Image</tt> will keep it +only once in memory. + +<h3><a name="pixmap">pixmap</h3> +This simple test shows the use of a LUT based pixmap as a +label for a box widget. Pixmaps are stored in the X11 '.xpm' +file format and can be part of the source code. Pixmaps support +one transparent color. + +<h3><a name="preferences">preferences</h3> +I do have my <tt>preferences</tt> in the morning, but sometimes I +just can't remember a thing. This is where the <tt>Fl_Preferences</tt> +come in handy. They remember any kind of data between program launches. + +<h3><a name="radio">radio</h3> +The <tt>radio</tt> tool was created entirely with <i>fluid</i>. It +shows some of the available button types and tests radio +button behavior. + +<h3><a name="resizebox">resizebox</h3> +<tt>resizebox</tt> shows some possible ways of FLTK's automatic +resize bahavior.. + +<h3><a name="resize">resize</h3> +The <tt>resize</tt> demo tests size and position functions with +the given window manager. + +<h3><a name="scroll">scroll</h3> +<tt>scroll</tt> shows how to scroll an area of widgets, one of +them beeing a slow custom drawing. <tt>Fl_Scroll</tt> uses +clipping and smart window area copying to improve redraw speed. +The buttons at the bottom of the window control decoration rendering +and updates. + +<h3><a name="shape">shape</h3> +<tt>shape</tt> is a very minimal demo that shows how to create +your own OpenGL rendering widget. Now that you know that, go ahead +and write that flight simulator you always dreamt of. + +<h3><a name="subwindow">subwindow</h3> +The <tt>subwindow</tt> demo tests messaging and drawing between +the main window and 'true' sub windows. A sub window is different +to a group by resetting the FLTK coordinate stystem to 0, 0 in the +top left corner. On Win32 and X11, subwindows have their own +operating system specific handle. + +<h3><a name="sudoku">sudoku</h3> +Another highly addictive game - don't play it, I warned you. +The implementation shows how to create application icons, +how to deal with OS specifics, and how to generate sound. + +<h3><a name="symbols">symbols</h3> +<tt>symbols</tt> are a speciality of FLTK. These little vector +drawings can be integrated into labels. They scale and rotate, +and with a little patience, you can define your own. The rotation +number refers to 45 degree rotations if you were looking at a +numeric keypad (2 is down, 6 is right, etc.). + +<h3><a name="tabs">tabs</h3> +The <tt>tabs</tt> tool was created with <i>fluid</i>. It tests +correct hiding and redisplaying of tabs, navigation across tabs, +resize behavior, and no unneeded redrawing of invisible widgets. + +<P>The <tt>tabs</tt> application shows the <tt>Fl_Tabs</tt> widget +on the left and the <tt>Fl_Wizard</tt> widget on the right side +for direct comparison of these two panel management widgets. + +<h3><a name="threads">threads</h3> +FLTK can be used in a multithreading environment. There are some +limitations, mostly due to the underlying operating system. +<tt>threads</tt> show how to use <tt>Fl::lock()</tt>, +<tt>Fl::unlock()</tt>, and <tt>Fl::awake()</tt> in secondary threads +to keep FLTK happy. Although locking works on all platforms, +this demo is not available on every machine. + +<h3><a name="tile">tile</h3> +The <tt>tile</tt> tool shows a nice way of using <tt>Fl_Tile</tt>. +To test correct resizing of subwindows, the widget for region +1 is created from an <tt>Fl_Window</tt> class. + +<h3><a name="tiled_image">tiled_image</h3> +The <tt>tiled_image</tt> demo uses an image as the background +for a window by repeating it over the full size of the widget. +Thw window is resizable and shows how the image gets repeated. + +<h3><a name="valuators">valuators</h3> +<tt>valuators</tt> shows all of FLTK's nifty widgets to change +numeric values. + +<h3><a name="fluid">fluid</h3> +<tt>fuid</tt> is not only a big test program, but also a very +useful visual UI designer. Many parts of <tt>fluid</tt> were +created using <tt>fluid</tt>. + +*/ diff --git a/documentation/fluid.dox b/documentation/fluid.dox new file mode 100644 index 000000000..38a82c7c6 --- /dev/null +++ b/documentation/fluid.dox @@ -0,0 +1,1359 @@ +/** + + \page fluid 9 - Programming with FLUID + +<P>This chapter shows how to use the Fast Light User-Interface Designer +("FLUID") to create your GUIs.</P> + +<P>Subchapters: +<UL> +<LI><A HREF="#what_is_fluid">What is FLUID</A></LI> +<LI><A HREF="#fluid_under_linux">Running FLUID Under UNIX</A></LI> +<LI><A HREF="#fluid_under_windows">Running FLUID Under Microsoft Windows</A></LI> +<LI><A HREF="#compiling_fl_files">Compiling <TT>.fl</TT> files</A></LI> +<LI><A HREF="#tutorial">A Short Tutorial</A></LI> +<LI><A HREF="#references">FLUID Reference</A></LI> +<LI><A HREF="#I18N">Internationalization with FLUID</A></LI> +<LI><A HREF="#limitations">Know limitations</A></LI> +</UL></P> + +<H2><A NAME="what_is_fluid">What is FLUID?</A></H2> + +<P>The Fast Light User Interface Designer, or FLUID, is a +graphical editor that is used to produce FLTK source code. FLUID +edits and saves its state in <TT>.fl</TT> files. These files +are text, and you can (with care) edit them in a text editor, +perhaps to get some special effects.</P> + +<P>FLUID can "compile" the <TT>.fl</TT> file into a +<TT>.cxx</TT> and a <TT>.h</TT> file. The <TT>.cxx</TT> file +defines all the objects from the <TT>.fl</TT> file and the +<TT>.h</TT> file declares all the global ones. FLUID also +supports localization (<A HREF="#I18N">Internationalization</A>) +of label strings using message files and the GNU gettext or +POSIX catgets interfaces. + +<P>A simple program can be made by putting all your code (including a <TT> +main()</TT> function) into the <TT>.fl</TT> file and thus making the <TT>.cxx</TT> file a +single source file to compile. Most programs are more complex than +this, so you write other <TT>.cxx</TT> files that call the FLUID functions. +These <TT>.cxx</TT> files must <TT>#include</TT> the <TT>.h</TT> file or they can <TT> +#include</TT> the <TT>.cxx</TT> file so it still appears to be a single source +file. + +<P ALIGN="CENTER"><IMG src="fluid-org.gif" ALT="FLUID organization."><BR> +<I>Figure 9-1: FLUID organization.</I></P> + +<P>Normally the FLUID file defines one or more functions or classes which +output C++ code. Each function defines a one or more FLTK +windows, and all the widgets that go inside those windows.</P> +<P>Widgets created by FLUID are either "named", "complex named" or +"unnamed". A named widget has a legal C++ variable identifier as its +name (i.e. only alphanumeric and underscore). In this case FLUID +defines a global variable or class member that will point at the widget +after the function defining it is called. A complex named object has +punctuation such as '.' or '->' or any other symbols in its name. In +this case FLUID assigns a pointer to the widget to the name, but does +not attempt to declare it. This can be used to get the widgets into +structures. An unnamed widget has a blank name and no pointer is stored.</P> +<P>Widgets 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 <TT>.cxx</TT> file.</P> +<H2><A NAME="fluid_under_linux">Running FLUID Under UNIX</A></H2> + To run FLUID under UNIX, type: +<UL> +<PRE> +fluid <I>filename.fl</I> &</PRE> +</UL> +to edit the <TT>.fl</TT> file <TT>filename.fl</TT>. If the file does not exist +you will get an error pop-up, but if you dismiss it you will be editing +a blank file of that name. You can run FLUID without any name, in +which case you will be editing an unnamed blank setup (but you can use +save-as to write it to a file). +<P>You can provide any of the standard FLTK switches before the filename: </P> +<UL> +<PRE> +-display host:n.n +-geometry WxH+X+Y +-title windowtitle +-name classname +-iconic +-fg color +-bg color +-bg2 color +-scheme schemename +</PRE> +</UL> + +<P>Changing the colors may be useful to see what your interface +will look at if the user calls it with the same switches. +Similarly, using "-scheme plastic" will show how the interface +will look using the "plastic" scheme. + +<P>In the current version, if you don't put FLUID into the +background with '&' then you will be able to abort FLUID by +typing <KBD>CTRL-C</KBD> on the terminal. It will exit +immediately, losing any changes.</P> + +<H2><A NAME="fluid_under_windows">Running FLUID Under Microsoft Windows</A></H2> + +<P>To run FLUID under WIN32, double-click on the <I>FLUID.exe</I> +file. You can also run FLUID from the Command Prompt window. +FLUID always runs in the background under WIN32. + +<H2><A NAME="compiling_fl_files">Compiling <TT>.fl</TT> files</A></H2> + +<P>FLUID can also be called as a command-line +"compiler" to create the <TT>.cxx</TT> and <TT>.h</TT> +file from a <TT>.fl</TT> file. To do this type: + +<UL><PRE> +fluid -c <I>filename.fl</I> +</PRE></UL> + +<P>This will read the <TT>filename.fl</TT> file and write +<I>filename.cxx</I> and <I> filename.h</I>. Any leading +directory on <TT>filename.fl</TT> will be stripped, so they are +always written to the current directory. If there are any errors +reading or writing the files, FLUID will print the error and +exit with a non-zero code. You can use the following lines in a +makefile to automate the creation of the source and header +files: + +<UL><PRE> +my_panels.h my_panels.cxx: my_panels.fl + fluid -c my_panels.fl +</PRE></UL> + +<P>Most versions of make support rules that cause <TT>.fl</TT> +files to be compiled: + +<UL><PRE> +.SUFFIXES: .fl .cxx .h +.fl.h .fl.cxx: + fluid -c $< +</PRE></UL> + +<H2><A NAME="tutorial">A Short Tutorial</A></H2> + +<P>FLUID is an amazingly powerful little program. However, this +power comes at a price as it is not always obvious how to +accomplish seemingly simple tasks with it. 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. + +<P ALIGN=CENTER><IMG SRC="cubeview.gif" ALT="CubeView demo."><BR> +<I>Figure 9-2: CubeView demo.</I></P> + +<P>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. +<p>At the completion of this tutorial you will (hopefully) understand +how to: +<ol> +<li>Use FLUID to create a complete user interface class, including +constructor and any member functions necessary. +<li>Use FLUID to set callbacks member functions of a custom widget +classes. +<li>Subclass an <a +href="Fl_Gl_Window.html#Fl_Gl_Window"><TT>Fl_Gl_Window</TT></A> to suit +your purposes. +</ol> + +<h3>The CubeView Class</h3> +The CubeView class is a subclass of Fl_Gl_Window. It has methods for +setting the zoom, the <i>x</i> and <i>y</i> pan, and the rotation angle +about the <i>x</i> and <i>y</i>axes. +<p>You can safely skip this section as long as you realize the CubeView +is a sublass of <tt>Fl_Gl_Window</tt> and will respond to calls from +CubeViewUI, generated by FLUID. +<h4><a name="def">The CubeView Class Definition</a></h4> +Here is the CubeView class definition, as given by its header file +"test/CubeView.h": +<ul><pre> +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(float angle){vAng=angle;}; + // Return the rotation about the vertical (y ) axis. + float v_angle(){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(float angle){hAng=angle;}; + // the rotation about the horizontal (x ) axis. + float h_angle(){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(float 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(float y){yshift=y;}; + /* The widget class draw() override. + * The draw() function initialize 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. The color is #defined by + * CUBECOLOR. + */ + void drawCube(); + + float vAng,hAng; float 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]; +}; +</pre></ul> + +<h4><a name="imp">The CubeView Class Implementation</a></h4> + +<P>Here is the CubeView implementation. It is very similar to the +"cube" demo included with FLTK. + +<ul><pre> +#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) +{ + vAng = 0.0; hAng=0.0; size=10.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; +}; + +// The color used for the edges of the bounding cube. +#define CUBECOLOR 255,255,255,255 + +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,w(),h()); + glOrtho(-10,10,-10,10,-20000,10000); glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPushMatrix(); glTranslatef(xshift, yshift, 0); + glRotatef(hAng,0,1,0); glRotatef(vAng,1,0,0); + glScalef(float(size),float(size),float(size)); drawCube(); + glPopMatrix(); +}; +</pre></ul> + +<h3>The CubeViewUI Class</h3> + +<P>We will completely construct a window to display and control the +CubeView defined in the previous section using FLUID. + +<h4><a name="defui">Defining the CubeViewUI Class</a></h4> + +<P>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. + +<p align="center"><img src="fluid1.gif" ALT="FLUID file for CubeView."><BR> +<I>Figure 9-3: FLUID file for CubeView.</I></p> + +<h4><a name="addcon">Adding the Class Constructor</a></h4> + +<P>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 understands that this will +be the constructor for the class and will generate the appropriate +code. Make sure you declare the constructor public. + +<p>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: + +<ul> +<li>A horizontal roller named <tt>hrot</tt> +<li>A vertical roller named <tt>vrot</tt> +<li>A horizontal slider named <tt>xpan</tt> +<li>A vertical slider named <tt>ypan</tt> +<li>A horizontal value slider named <tt>zoom</tt> +</ul> + +<P>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. + +<p>When you are finished you should have something like this: + +<p align="center"><img src="fluid2.gif" ALT="FLUID window containing CubeView demo."><BR> +<I>Figure 9-4: FLUID window containing CubeView demo.</I></P> + +<p>We will talk about the <tt>show()</tt> method that is highlighted +shortly. + +<h4><a name="addcube">Adding the CubeView Widget</a></h4> + +<P>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. + +<p>The CubeView class inherits the <tt>Fl_Gl_Window</tt> class, which +is created in the same way as a <tt>Fl_Box</tt> widget. Use +<b>New->Other->Box</b> to add a square box to the main window. +This will be no ordinary box, however. + +<p>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 <tt>Fl_Box</tt>, but a +similar widget with the same constructor. In the "Extra +Code:" field enter <tt>#include "CubeView.h"</tt> + +<p>This <tt>#include</tt> is important, as we have just included +CubeView as a member of CubeViewUI, so any public CubeView methods are +now available to CubeViewUI. + +<p align="center"><img src="fluid3-cxx.gif" ALT="CubeView methods."><BR> +<I>Figure 9-5: CubeView methods.</I></p> + +<h4><a name="defcall">Defining the Callbacks</a></h4> + +<P>Each of the widgets we defined before adding CubeView can have +callbacks that call CubeView methods. You can call an external +function or put in a short amount of code in the "Callback" +field of the widget panel. For example, the callback for the +<tt>ypan</tt> slider is: + +<ul><pre> +cube->pany(((Fl_Slider *)o)->value()); +cube->redraw(); +</pre></ul> + +<P>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. + +<p>There is no reason no 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. + +<h4><a name="addmeth">Adding a Class Method</a></h4> + +<P>You can add class methods within FLUID that have nothing to do with the +GUI. An an example add a show function so that CubeViewUI can actually +appear on the screen. + +<p>Make sure the top level CubeViewUI is selected and select +<b>New->Code->Function/Method</b>. Just use the name +<tt>show()</tt>. 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 <tt>void</tt>. + +<p align="center"><img src="fluid4.gif" ALT="CubeView constructor."><BR> +<I>Figure 9-6: CubeView constructor.</I></p> + +<p>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. + +<h3><a name="addconst">Adding Constructor Initialization Code</a></h3> + +<P>If you need to add code to initialize 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. + +<h3><a name="gencode">Generating the Code</a></h3> + +<P>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>. + +<p>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. + +<!-- NEW PAGE --> + +<H2><A NAME="references">FLUID Reference</A></H2> + +<P>The following sections describe each of the windows in FLUID. + +<H3>The Widget Browser</H3> + +<P>The main window shows a menu bar and a scrolling browser of +all the defined widgets. The name of the <TT>.fl</TT> file being +edited is shown in the window title. + +<P>The widgets are stored in a hierarchy. You can open and close a +level by clicking the "triangle" at the left of a widget. +The leftmost widgets are the <I>parents</I>, and all the widgets +listed below them are their <I>children</I>. Parents don't have to have +any children.</P> + +<P>The top level of the hierarchy is composed of <I>functions</I> and +<I>classes</I>. Each of these will produce a single C++ public +function or class in the output <TT>.cxx</TT> file. Calling the function or +instantiating the class will create all of the child widgets.</P> + +<P>The second level of the hierarchy contains the <I>windows</I>. Each of these +produces an instance of class <tt>Fl_Window</tt>.</P> + +<P>Below that are either <I>widgets</I> (subclasses of <tt>Fl_Widget</tt>) or <I> +groups</I> of widgets (including other groups). Plain groups are for +layout, navigation, and resize purposes. <I>Tab groups</I> provide the +well-known file-card tab interface.</P> + +<P>Widgets are shown in the browser by either their <I>name</I> (such +as "main_panel" in the example), or by their <I>type</I> +and <I>label</I> (such as "Button "the green"").</P> + +<P>You <I>select</I> widgets by clicking on their names, which highlights +them (you can also select widgets from any displayed window). You can +select many widgets by dragging the mouse across them, or by using +Shift+Click to toggle them on and off. To select no widgets, click in +the blank area under the last widget. Note that hidden children may +be selected even when there is no visual indication of this. + +<P>You <I>open</I> widgets by double-clicking on them, or (to open several +widgets you have picked) by typing the F1 key. A control panel will appear +so you can change the widget(s).</P> + +<H3>Menu Items</H3> + +<P>The menu bar at the top is duplicated as a pop-up menu on any +displayed window. The shortcuts for all the menu items work in any +window. The menu items are: </P> + +<H4>File/Open... (Ctrl+o)</H4> + +<P>Discards the current editing session and reads in a different +<TT>.fl</TT> file. You are asked for confirmation if you have +changed the current file. + +<P>FLUID can also read <tt>.fd</tt> files produced by the Forms +and XForms "fdesign" programs. It is best to +File/Merge them instead of opening them. FLUID does not +understand everything in a <tt>.fd</tt> file, and will print a +warning message on the controlling terminal for all data it does +not understand. You will probably need to edit the resulting +setup to fix these errors. Be careful not to save the file +without changing the name, as FLUID will write over the +<tt>.fd</tt> file with its own format, which fdesign cannot +read! </P> + +<H4>File/Insert... (Ctrl+i)</H4> + +<P>Inserts the contents of another <TT>.fl</TT> file, without +changing the name of the current <TT>.fl</TT> file. All the +functions (even if they have the same names as the current ones) +are added, and you will have to use cut/paste to put the widgets +where you want. + +<H4>File/Save (Ctrl+s)</H4> + +<P>Writes the current data to the <TT>.fl</TT> file. If the +file is unnamed then FLUID will ask for a filename. + +<H4>File/Save As...(Ctrl+Shift+S)</H4> + +<P>Asks for a new filename and saves the file. + +<H4>File/Write Code (Ctrl+Shift+C)</H4> + +<P>"Compiles" the data into a <TT>.cxx</TT> and <TT>.h</TT> +file. These are exactly the same as the files you get when you run +FLUID with the <tt>-c</tt> switch. + +<P>The output file names are the same as the <TT>.fl</TT> file, with +the leading directory and trailing ".fl" stripped, and +".h" or ".cxx" appended.</P> + +<H4>File/Write Strings (Ctrl+Shift+W)</H4> + +<P>Writes a message file for all of the text labels defined in +the current file. + +<P>The output file name is the same as the <TT>.fl</TT> file, +with the leading directory and trailing ".fl" +stripped, and ".txt", ".po", or +".msg" appended depending on the <A +HREF="#I18N">Internationalization Mode</A>.</P> + +<H4>File/Quit (Ctrl+q)</H4> + +<P>Exits FLUID. You are asked for confirmation if you have +changed the current file. + +<H4>Edit/Undo (Ctrl+z)</H4> + +<P>This isn't implemented yet. You should do save often so you can +recover from any mistakes you make. + +<H4>Edit/Cut (Ctrl+x)</H4> + +<P>Deletes the selected widgets and all of their children. +These are saved to a "clipboard" file and can be +pasted back into any FLUID window. + +<H4>Edit/Copy (Ctrl+c)</H4> + +<P>Copies the selected widgets and all of their children to the +"clipboard" file. + +<H4>Edit/Paste (Ctrl+c)</H4> + +<P>Pastes the widgets from the clipboard file. + +<P>If the widget is a window, it is added to whatever function +is selected, or contained in the current selection.</P> + +<P>If the widget is a normal widget, it is added to whatever +window or group is selected. If none is, it is added to the +window or group that is the parent of the current selection.</P> + +<P>To avoid confusion, it is best to select exactly one widget +before doing a paste.</P> + +<P>Cut/paste is the only way to change the parent of a +widget.</P> + +<H4>Edit/Select All (Ctrl+a)</H4> + +<P>Selects all widgets in the same group as the current +selection. + +<P>If they are all selected already then this selects all +widgets in that group's parent. Repeatedly typing Ctrl+a will +select larger and larger groups of widgets until everything is +selected.</P> + +<H4>Edit/Open... (F1 or double click)</H4> + +<P>Displays the current widget in the attributes panel. If the +widget is a window and it is not visible then the window is +shown instead. + +<H4>Edit/Sort</H4> + +<P>Sorts the selected widgets into left to right, top to bottom +order. You need to do this to make navigation keys in FLTK work +correctly. You may then fine-tune the sorting with +"Earlier" and "Later". This does not affect +the positions of windows or functions. + +<H4>Edit/Earlier (F2)</H4> + +<P>Moves all of the selected widgets one earlier in order among +the children of their parent (if possible). This will affect +navigation order, and if the widgets overlap it will affect how +they draw, as the later widget is drawn on top of the earlier +one. You can also use this to reorder functions, classes, and +windows within functions. + +<H4>Edit/Later (F3)</H4> + +<P>Moves all of the selected widgets one later in order among +the children of their parent (if possible). + +<H4>Edit/Group (F7)</H4> + +<P>Creates a new <tt>Fl_Group</tt> and make all the currently +selected widgets children of it. + +<H4>Edit/Ungroup (F8)</H4> + +<P>Deletes the parent group if all the children of a group are +selected. + +<H4>Edit/Overlays on/off (Ctrl+Shift+O)</H4> + +<P>Toggles the display of the red overlays off, without changing +the selection. This makes it easier to see box borders and how +the layout looks. The overlays will be forced back on if you +change the selection. + +<H4>Edit/Project Settings... (Ctrl+p)</H4> + +<P>Displays the project settings panel. +The output filenames control the extensions or names of the +files the are generated by FLUID. If you check the "Include .h +from .cxx" button the code file will include the header file +automatically. + +<P>The internationalization options are described <A +HREF="#I18N">later in this chapter</A>. + +<P ALIGN="CENTER"><IMG SRC="fluid_prefs.gif" ALT="FLUID Preferences Window."><BR> +<I>Figure 9-7: FLUID Preferences Window.</I></P> + +<H4>Edit/GUI Settings... (Shift+Ctrl+p)</H4> + +<P>Displays the GUI settings panel. This panel is used +to control the user interface settings. + +<H4>New/Code/Function</H4> + +<P>Creates a new C function. You will be asked for a name for +the function. This name should be a legal C++ function +template, without the return type. You can pass arguments which +can be referred to by code you type into the individual widgets. + +<P>If the function contains any unnamed windows, it will be +declared as returning a Fl_Window pointer. The unnamed window +will be returned from it (more than one unnamed window is +useless). If the function contains only named windows, it will +be declared as returning nothing (<tt>void</tt>).</P> + +<P>It is possible to make the <TT>.cxx</TT> output be a +self-contained program that can be compiled and executed. This +is done by deleting the function name so +<tt>main(argc,argv)</tt> is used. The function will call +<tt>show()</tt> on all the windows it creates and then call +<tt>Fl::run()</tt>. This can also be used to test resize +behavior or other parts of the user interface.</P> + +<P>You can change the function name by double-clicking on the +function.</P> + +<H4>New/Window</H4> + +<P>Creates a new <tt>Fl_Window</tt> widget. The window is added +to the currently selected function, or to the function +containing the currently selected item. The window will appear, +sized to 100x100. You can resize it to whatever size you +require. + +<P>The widget panel will also appear and is described later in +this chapter.</P> + +<H4>New/...</H4> + +<P>All other items on the New menu are subclasses of +<tt>Fl_Widget</tt>. Creating them will add them to the +currently selected group or window, or the group or window +containing the currently selected widget. The initial +dimensions and position are chosen by copying the current +widget, if possible. + +<P>When you create the widget you will get the widget's control +panel, which is described later in this chapter.</P> + + +<H4>Layout/Align/... </H4> + +<P>Align all selected widgets to the first widget in the selection. + +<H4>Layout/Space Evenly/... </H4> + +<P>Space all selected widgets evenly inside the selected space. +Widgets will be sorted from first to last. + +<H4>Layout/Make Same Size/... </H4> + +<P>Make all slected widgets the same size as the first selected widget. + +<H4>Layout/Center in Group/... </H4> + +<P>Center all selected widgets relative to their parent widget + +<H4>Layout/Grid... (Ctrl+g)</H4> + +<P>Displays the grid settings panel. +This panel +controls the grid that all widgets snap to when you move and +resize them, and for the "snap" which is how far a widget has to +be dragged from its original position to actually change. + + +<H4>Shell/Execute Command... (Alt+x)</H4> + +<P>Displays the shell command panel. The shell command +is commonly used to run a 'make' script to compile the FLTK output. + +<H4>Shell/Execute Again (Alt+g)</H4> + +<P>Run the shell command again. + +<H4>Help/About FLUID</H4> + +<P>Pops up a panel showing the version of FLUID. + +<H4>Help/On FLUID</H4> + +<P>Shows this chapter of the manual. + +<H4>Help/Manual</H4> + +<P>Shows the contents page of the manual + +<H3>The Widget Panel</H3> + +<P>When you double-click on a widget or a set of widgets you +will get the "widget attribute panel". + +<P>When you change attributes using this panel, the changes are +reflected immediately in the window. It is useful to hit the +"no overlay" button (or type Ctrl+Shift+O) to hide the +red overlay so you can see the widgets more accurately, +especially when setting the box type. + +<P>If you have several widgets selected, they may have different +values for the fields. In this case the value for <I>one</I> of +the widgets is shown. But if you change this value, <I>all</I> +of the selected widgets are changed to the new value. + +<P>Hitting "OK" makes the changes permanent. +Selecting a different widget also makes the changes permanent. +FLUID checks for simple syntax errors such as mismatched +parenthesis in any code before saving any text. + +<P>"Revert" or "Cancel" put everything back +to when you last brought up the panel or hit OK. However in the +current version of FLUID, changes to "visible" +attributes (such as the color, label, box) are not undone by +revert or cancel. Changes to code like the callbacks are +undone, however. + +<!-- NEW PAGE --> +<P ALIGN="CENTER"><IMG src="fluid_widget_gui.gif" ALT="The FLUID widget GUI attributes."><BR> +<I>Figure 9-8: The FLUID widget GUI attributes.</I></P> + +<H3><A name="widget_attributes">GUI Attributes</A></H3> + +<H4>Label (text field)</H4> + +<P>String to print next to or inside the button. You can put +newlines into the string to make multiple lines. The easiest way +is by typing Ctrl+j.</P> + +<P><A href="common.html#symbols">Symbols</A> can be added to the +label using the at sign ("@"). + +<H4>Label (pull down menu)</H4> + +<P>How to draw the label. Normal, shadowed, engraved, and +embossed change the appearance of the text. + +<H4>Image</H4> + +<P>The active image for the widget. Click on the +<B>Browse...</B> button to pick an image file using the file +chooser. + +<H4>Inactive</H4> + +<P>The inactive image for the widget. Click on the +<B>Browse...</B> button to pick an image file using the file +chooser. + +<H4>Alignment (buttons)</H4> + +<P>Where to draw the label. The arrows put it on that side of +the widget, you can combine the to put it in the corner. The +"box" button puts the label inside the widget, rather +than outside. + +<P>The <B>clip</B> button clips the label to the widget box, the +<B>wrap</B> button wraps any text in the label, and the <B>text +image</B> button puts the text over the image instead of under +the image. + +<H4>Position (text fields)</H4> + +<P>The position fields show the current position and size of the +widget box. Enter new values to move and/or resize a widget. + +<H4>Values (text fields)</H4> + +<P>The values and limits of the current widget. Depending on the +type of widget, some or all of these fields may be inactive. + +<H4>Shortcut</H4> + +<P>The shortcut key to activate the widget. Click on the +shortcut button and press any key sequence to set the shortcut. + +<H4>Attributes (buttons)</H4> + +<P>The <B>Visible</B> button controls whether the widget is +visible (on) or hidden (off) initially. Don't change this for +windows or for the immediate children of a Tabs group. + +<P>The <B>Active</B> button controls whether the widget is +activated (on) or deactivated (off) initially. Most widgets +appear greyed out when deactivated. + +<P>The <B>Resizable</B> button controls whether the window is +resizeable. In addition all the size changes of a window or +group will go "into" the resizable child. If you have +a large data display surrounded by buttons, you probably want +that data area to be resizable. You can get more complex +behavior by making invisible boxes the resizable widget, or by +using hierarchies of groups. Unfortunately the only way to test +it is to compile the program. Resizing the FLUID window is +<I>not</I> the same as what will happen in the user program.</P> + +<P>The <B>Hotspot</B> button causes the parent window to be +positioned with that widget centered on the mouse. This +position is determined <I>when the FLUID function is called</I>, +so you should call it immediately before showing the window. If +you want the window to hide and then reappear at a new position, +you should have your program set the hotspot itself just before +<tt>show()</tt>. + +<P>The <B>Border</B> button turns the window manager border on +or off. On most window managers you will have to close the +window and reopen it to see the effect. + +<H4>X Class (text field)</H4> + +<P>The string typed into here is passed to the X window manager +as the class. This can change the icon or window decorations. +On most (all?) window managers you will have to close the window +and reopen it to see the effect. + + +<P ALIGN="CENTER"><IMG src="fluid_widget_style.gif" ALT="The FLUID widget Style attributes."><BR> +<I>Figure 9-9: The FLUID widget Style attributes.</I></P> + +<H3>Style Attributes</H3> + +<H4>Label Font (pulldown menu)</H4> + +<P>Font to draw the label in. Ignored by symbols, bitmaps, and +pixmaps. Your program can change the actual font used by these +"slots" in case you want some font other than the 16 +provided. + +<H4>Label Size (pulldown menu)</H4> + +<P>Pixel size (height) for the font to draw the label in. +Ignored by symbols, bitmaps, and pixmaps. To see the result +without dismissing the panel, type the new number and then Tab. + +<H4>Label Color (button)</H4> + +<P>Color to draw the label. Ignored by pixmaps (bitmaps, +however, do use this color as the foreground color). + +<H4>Box (pulldown menu)</H4> + +<P>The boxtype to draw as a background for the widget. + +<P>Many widgets will work, and draw faster, with a +"frame" instead of a "box". A frame does +not draw the colored interior, leaving whatever was already +there visible. Be careful, as FLUID may draw this ok but the +real program may leave unwanted stuff inside the widget.</P> + +<P>If a window is filled with child widgets, you can speed up +redrawing by changing the window's box type to +"NO_BOX". FLUID will display a checkerboard for any +areas that are not colored in by boxes. Note that this +checkerboard is not drawn by the resulting program. Instead +random garbage will be displayed.</P> + +<H4>Down Box (pulldown menu)</H4> + +<P>The boxtype to draw when a button is pressed or for some +parts of other widgets like scrollbars and valuators. + +<H4>Color (button)</H4> + +<P>The color to draw the box with.</P> + +<H4>Select Color (button)</H4> + +<P>Some widgets will use this color for certain parts. FLUID +does not always show the result of this: this is the color +buttons draw in when pushed down, and the color of input fields +when they have the focus.</P> + +<H4>Text Font, Size, and Color</H4> + +<P>Some widgets display text, such as input fields, pull-down +menus, and browsers. + + +<P ALIGN="CENTER"><IMG src="fluid_widget_cxx.gif" ALT="The FLUID widget C++ attributes."><BR> +<I>Figure 9-10: The FLUID widget C++ attributes.</I></P> + +<H3>C++ Attributes</H3> + +<H4>Class</H4> + +<P>This is how you use your own subclasses of +<tt>Fl_Widget</tt>. Whatever identifier you type in here will +be the class that is instantiated. + +<P>In addition, no <tt>#include</tt> header file is put in the +<TT>.h</TT> file. You must provide a <tt>#include</tt> line as +the first line of the "Extra Code" which declares your +subclass.</P> + +<P>The class must be similar to the class you are spoofing. It +does not have to be a subclass. It is sometimes useful to +change this to another FLTK class. Currently the only way to get +a double-buffered window is to change this field for the window +to "Fl_Double_Window" and to add "#include +<FL/Fl_Double_Window.h>" to the extra code.</P> + +<H4>Type (upper-right pulldown menu)</H4> + +<P>Some classes have subtypes that modify their appearance or behavior. +You pick the subtype off of this menu. + +<H4>Name (text field)</H4> + +<P>Name of a variable to declare, and to store a pointer to this +widget into. This variable will be of type "<class>*". If the name is +blank then no variable is created. + +<P>You can name several widgets with "name[0]", "name[1]", "name[2]", +etc. This will cause FLUID to declare an array of pointers. The array +is big enough that the highest number found can be stored. All widgets +that in the array must be the same type.</P> + +<H4>Public (button)</H4> + +<P>Controls whether the widget is publicly accessible. When +embedding widgets in a C++ class, this controls whether the +widget is <TT>public</TT> or <TT>private</TT> in the class. +Otherwise is controls whether the widget is declared +<TT>static</TT> or global (<TT>extern</TT>). + +<H4>Extra Code (text fields)</H4> + +<P>These four fields let you type in literal lines of code to +dump into the <TT>.h</TT> or <TT>.cxx</TT> files. + +<P>If the text starts with a <tt>#</tt> or the word +<tt>extern</tt> then FLUID thinks this is an "include" +line, and it is written to the <TT>.h</TT> file. If the same +include line occurs several times then only one copy is +written.</P> + +<P>All other lines are "code" lines. The current +widget is pointed to by the local variable <tt>o</tt>. The +window being constructed is pointed to by the local variable +<tt>w</tt>. You can also access any arguments passed to the +function here, and any named widgets that are before this +one.</P> + +<P>FLUID will check for matching parenthesis, braces, and +quotes, but does not do much other error checking. Be careful +here, as it may be hard to figure out what widget is producing +an error in the compiler. If you need more than four lines you +probably should call a function in your own <TT>.cxx</TT> +code.</P> + +<H4>Callback (text field)</H4> + +<P>This can either be the name of a function, or a small snippet +of code. If you enter anything but letters, numbers, and the +underscore then FLUID treats it as code. + +<P>A name names a function in your own code. It must be +declared as <tt>void name(<class>*,void*)</tt>.</P> + +<P>A code snippet is inserted into a static function in the +<TT>.cxx</TT> output file. The function prototype is <tt>void +name(class *o, void *v)</tt> so that you can refer to the +widget as <tt>o</tt> and the <tt>user_data()</tt> as +<tt>v</tt>. FLUID will check for matching parenthesis, braces, +and quotes, but does not do much other error checking. Be +careful here, as it may be hard to figure out what widget is +producing an error in the compiler.</P> + +<P>If the callback is blank then no callback is set.</P> + +<H4>User Data (text field)</H4> + +<P>This is a value for the <tt>user_data()</tt> of the widget. +If blank the default value of zero is used. This can be any +piece of C code that can be cast to a <tt>void</tt> pointer. + +<H4>Type (text field)</H4> + +<P>The <tt>void *</tt> in the callback function prototypes is +replaced with this. You may want to use <tt>long</tt> for old +XForms code. Be warned that anything other than <tt>void *</tt> +is not guaranteed to work! However on most architectures other +pointer types are ok, and <tt>long</tt> is usually ok, too. + +<H4>When (pulldown menu)</H4> + +<P>When to do the callback. This can be <B>Never</B>, +<B>Changed</B>, <B>Release</B>, or <B>Enter Key</B>. The value of +<B>Enter Key</B> is only useful for text input fields. + +<P>There are other rare but useful values for the +<tt>when()</tt> field that are not in the menu. You should use +the extra code fields to put these values in.</P> + +<H4>No Change (button)</H4> + +<P>The <B>No Change</B> button means the callback is done on the +matching event even if the data is not changed. + +<H3>Selecting and Moving Widgets</H3> + +<P>Double-clicking a window name in the browser will display it, +if not displayed yet. From this display you can select widgets, +sets of widgets, and move or resize them. To close a window +either double-click it or type <KBD>ESC</KBD>. + +<P>To select a widget, click it. To select several widgets drag +a rectangle around them. Holding down shift will toggle the +selection of the widgets instead.</P> + +<P>You cannot pick hidden widgets. You also cannot choose some +widgets if they are completely overlapped by later widgets. Use +the browser to select these widgets.</P> + +<P>The selected widgets are shown with a red "overlay" +line around them. You can move the widgets by dragging this +box. Or you can resize them by dragging the outer edges and +corners. Hold down the Alt key while dragging the mouse to +defeat the snap-to-grid effect for fine positioning.</P> + +<P>If there is a tab box displayed you can change which child is +visible by clicking on the file tabs. The child you pick is +selected.</P> + +<P>The arrow, tab, and shift+tab keys "navigate" the +selection. Left, right, tab, or shift+tab move to the next or +previous widgets in the hierarchy. Hit the right arrow enough +and you will select every widget in the window. Up/down widgets +move to the previous/next widgets that overlap horizontally. If +the navigation does not seem to work you probably need to +"Sort" the widgets. This is important if you have +input fields, as FLTK uses the same rules when using arrow keys +to move between input fields.</P> + +<P>To "open" a widget, double click it. To open +several widgets select them and then type F1 or pick +"Edit/Open" off the pop-up menu.</P> + +<P>Type Ctrl+o to temporarily toggle the overlay off without +changing the selection, so you can see the widget borders.</P> + +<P>You can resize the window by using the window manager border +controls. FLTK will attempt to round the window size to the +nearest multiple of the grid size and makes it big enough to +contain all the widgets (it does this using illegal X methods, +so it is possible it will barf with some window managers!). +Notice that the actual window in your program may not be +resizable, and if it is, the effect on child widgets may be +different.</P> + +<P>The panel for the window (which you get by double-clicking +it) is almost identical to the panel for any other Fl_Widget. +There are three extra items:</P> + +<H3><A name="images">Images</A></H3> + +<P>The <I>contents</I> of the image files in the <B>Image</B> +and <B>Inactive</B> text fields are written to the <TT>.cxx</TT> +file. If many widgets share the same image then only one copy is +written. Since the image data is embedded in the generated +source code, you need only distribute the C++ code and not the +image files themselves.</P> + +<P>However, the <I>filenames</I> are stored in the <TT>.fl</TT> +file so you will need the image files as well to read the +<TT>.fl</TT> file. Filenames are relative to the location of the +<TT>.fl</TT> file and not necessarily the current directory. We +recommend you either put the images in the same directory as the +<TT>.fl</TT> file, or use absolute path names.</P> + +<H4>Notes for All Image Types</H4> + +<P>FLUID runs using the default visual of your X server. This +may be 8 bits, which will give you dithered images. You may get +better results in your actual program by adding the code +"Fl::visual(FL_RGB)" to your code right before the +first window is displayed. + +<P>All widgets with the same image on them share the same code +and source X pixmap. Thus once you have put an image on a +widget, it is nearly free to put the same image on many other +widgets.</P> + +<P>If you edit an image at the same time you are using it in FLUID, +the only way to convince FLUID to read the image file again is to +remove the image from all widgets that are using it or re-load the +<TT>.fl</TT> file.</P> + +<P>Don't rely on how FLTK crops images that are outside the +widget, as this may change in future versions! The cropping of +inside labels will probably be unchanged.</P> + +<P>To more accurately place images, make a new "box" +widget and put the image in that as the label.</P> + +<H4>XBM (X Bitmap) Files</H4> + +<P>FLUID reads X bitmap files which use C source code to define +a bitmap. Sometimes they are stored with the ".h" or +".bm" extension rather than the standard +".xbm" extension. + +<P>FLUID writes code to construct an Fl_Bitmap image and use it +to label the widget. The '1' bits in the bitmap are drawn using +the label color of the widget. You can change this color in the +FLUID widget attributes panel. The '0' bits are transparent.</P> + +<P>The program "bitmap" on the X distribution does an +adequate job of editing bitmaps.</P> + +<H4>XPM (X Pixmap) Files</H4> + +<P>FLUID reads X pixmap files as used by the <TT>libxpm</TT> +library. These files use C source code to define a pixmap. The +filenames usually have the ".xpm" extension. + +<P>FLUID writes code to construct an Fl_Pixmap image and use it +to label the widget. The label color of the widget is ignored, +even for 2-color images that could be a bitmap. XPM files can +mark a single color as being transparent, and FLTK uses this +information to generate a transparency mask for the image.</P> + +<P>We have not found any good editors for small iconic pictures. +For pixmaps we have used <A +href="http://home.worldonline.dk/~torsten/xpaint/index.html">XPaint</A> +and the KDE icon editor.</P> + +<H4>BMP Files</H4> + +<P>FLUID reads Windows BMP image files which are often used in +WIN32 applications for icons. FLUID converts BMP files into +(modified) XPM format and uses a Fl_BMP_Image image to label the +widget. Transparency is handled the same as for XPM files. All +image data is uncompressed when written to the source file, so +the code may be much bigger than the <TT>.bmp</TT> file.</P> + +<H4>GIF Files</H4> + +<P>FLUID reads GIF image files which are often used in HTML +documents to make icons. FLUID converts GIF files into +(modified) XPM format and uses a Fl_GIF_Image image to label the +widget. Transparency is handled the same as for XPM files. All +image data is uncompressed when written to the source file, so +the code may be much bigger than the <TT>.gif</TT> file. Only +the first image of an animated GIF file is used.</P> + +<H4>JPEG Files</H4> + +<P>If FLTK is compiled with JPEG support, FLUID can read JPEG +image files which are often used for digital photos. FLUID uses +a Fl_JPEG_Image image to label the widget, and writes +uncompressed RGB or grayscale data to the source file. + +<H4>PNG (Portable Network Graphics) Files</H4> + +<P>If FLTK is compiled with PNG support, FLUID can read PNG +image files which are often used in HTML documents. FLUID uses a +Fl_PNG_Image image to label the widget, and writes uncompressed +RGB or grayscale data to the source file. PNG images can provide +a full alpha channel for partial transparency, and FLTK supports +this as best as possible on each platform. + +<H2><A NAME="I18N">Internationalization with FLUID</A></H2> + +<P>FLUID supports internationalization (I18N for short) of label +strings used by widgets. The preferences window +(<TT>Ctrl+p</TT>) provides access to the I18N options. + +<H3>I18N Methods</H3> + +<P>FLUID supports three methods of I18N: use none, use GNU +gettext, and use POSIX catgets. The "use none" method is the +default and just passes the label strings as-is to the widget +constructors. + +<P>The "GNU gettext" method uses GNU gettext (or a similar +text-based I18N library) to retrieve a localized string before +calling the widget constructor. + +<P>The "POSIX catgets" method uses the POSIX catgets function to +retrieve a numbered message from a message catalog before +calling the widget constructor. + +<H3>Using GNU gettext for I18N</H3> + +<P>FLUID's code support for GNU gettext is limited to calling a +function or macro to retrieve the localized label; you still +need to call <TT>setlocale()</TT> and <TT>textdomain()</TT> or +<TT>bindtextdomain()</TT> to select the appropriate language and +message file. + +<P>To use GNU gettext for I18N, open the preferences window and +choose "GNU gettext" from the "Use" chooser. Two new input +fields will then appear to control the include file and +function/macro name to use when retrieving the localized label +strings. + +<P ALIGN="CENTER"><IMG SRC="fluid-gettext.gif" ALT="I18N using GNU gettext."><BR> +<I>Figure 9-11: Internationalization using GNU gettext.</I></P> + +<P>The "#include" field controls the header file to include for +I18N; by default this is <TT><libintl.h></TT>, the +standard I18N file for GNU gettext. + +<P>The "Function" field controls the function (or macro) that +will retrieve the localized message; by default the +<TT>gettext</TT> function will be called. + +<H3>Using POSIX catgets for I18N</H3> + +<P>FLUID's code support for POSIX catgets allows you to use a +global message file for all interfaces or a file specific to +each <TT>.fl</TT> file; you still need to call +<TT>setlocale()</TT> to select the appropriate language. + +<P>To use POSIX catgets for I18N, open the preferences window +and choose "POSIX catgets" from the "Use" chooser. Three new +input fields will then appear to control the include file, +catalog file, and set number for retrieving the localized label +strings. + +<P ALIGN="CENTER"><IMG SRC="fluid-catgets.gif" ALT="I18N using POSIX catgets."><BR> +<I>Figure 9-12: Internationalization using POSIX catgets.</I></P> + +<P>The "#include" field controls the header file to include for +I18N; by default this is <TT><nl_types.h></TT>, the +standard I18N file for POSIX catgets. + +<P>The "File" field controls the name of the catalog file +variable to use when retrieving localized messages; by default +the file field is empty which forces a local (static) catalog +file to be used for all of the windows defined in your +<TT>.fl</TT> file. + +<P>The "Set" field controls the set number in the catalog file. +The default set is 1 and rarely needs to be changed. + +<H2><A NAME="limitations">Know limitations</A></H2> + +Declaration Blocks can be used to temporarily block out already +designed code using <code>#if 0</code> and <code>#endif</code> +type construction. This will effectively avoid compilation of +blocks of code. However, static code and data generated by this +segment (menu items, images, include statements, etc.) will still +be generated and likely cause compile-time warnings. + +*/ diff --git a/documentation/forms.dox b/documentation/forms.dox new file mode 100644 index 000000000..b2cb92ade --- /dev/null +++ b/documentation/forms.dox @@ -0,0 +1,201 @@ +/** + + \page forms E - Forms Compatibility + +<P>This appendix describes the Forms compatibility included with FLTK. +<H2>Importing Forms Layout Files</H2> +<A href=fluid.html#FLUID>FLUID</A> can read the .fd files put out by +all versions of Forms and XForms fdesign. However, it will mangle them +a bit, but it prints a warning message about anything it does not +understand. FLUID cannot write fdesign files, so you should save to a +new name so you don't write over the old one. +<P>You will need to edit your main code considerably to get it to link +with the output from FLUID. If you are not interested in this you may +have more immediate luck with the forms compatibility header, <TT> +<FL/forms.H></TT>. </P> +<H2>Using the Compatibility Header File</H2> + You should be able to compile existing Forms or XForms source code by +changing the include directory switch to your compiler so that the <TT> +forms.h</TT> file supplied with FLTK is included. Take a look at <TT> +forms.h</TT> to see how it works, but the basic trick is lots of inline +functions. Most of the XForms demo programs work without changes. +<P>You will also have to compile your Forms or XForms program using a +C++ compiler. The FLTK library does not provide C bindings or header +files. </P> +<P>Although FLTK was designed to be compatible with the GL Forms +library (version 0.3 or so), XForms has bloated severely and it's +interface is X-specific. Therefore, XForms compatibility is no longer +a goal of FLTK. Compatibility was limited to things that were free, or +that would add code that would not be linked in if the feature is +unused, or that was not X-specific. </P> +<P>To use any new features of FLTK, you should rewrite your code to not +use the inline functions and instead use "pure" FLTK. This will make +it a lot cleaner and make it easier to figure out how to call the FLTK +functions. Unfortunately this conversion is harder than expected and +even Digital Domain's inhouse code still uses <TT>forms.H</TT> a lot. </P> +<H2>Problems You Will Encounter</H2> +<P>Many parts of XForms use X-specific structures like <TT>XEvent</TT> + in their interface. I did not emulate these! Unfortunately these +features (such as the "canvas" widget) are needed by most large +programs. You will need to rewrite these to use FLTK subclasses. </P> +<P><A href=Fl_Free.html#Fl_Free><TT>Fl_Free</TT></A> widgets emulate +the <I>old</I> Forms "free" widget. It may be useful for porting +programs that change the <TT>handle()</TT> function on widgets, but you +will still need to rewrite things. </P> +<P><A href=Fl_Timer.html#Fl_Timer><TT>Fl_Timer</TT></A> widgets are +provided to emulate the XForms timer. These work, but are quite +inefficient and inaccurate compared to using <A href="Fl.html#Fl.add_timeout"> +<TT>Fl::add_timeout()</TT></A>. </P> +<P><I>All instance variables are hidden.</I> If you directly refer to +the x, y, w, h, label, or other fields of your Forms widgets you will +have to add empty parenthesis after each reference. The easiest way to +do this is to globally replace "->x" with "->x()", etc. Replace +"boxtype" with "box()". </P> +<P><TT>const char *</TT> arguments to most FLTK methods are simply +stored, while Forms would <TT>strdup()</TT> the passed string. This is +most noticable with the label of widgets. Your program must always +pass static data such as a string constant or malloc'd buffer to <TT> +label()</TT>. If you are using labels to display program output you +may want to try the <A href=Fl_Output.html#Fl_Output><TT>Fl_Output</TT></A> + widget. </P> +<P>The default fonts and sizes are matched to the older GL version of +Forms, so all labels will draw somewhat larger than an XForms program +does. </P> +<P>fdesign outputs a setting of a "fdui" instance variable to the main +window. I did not emulate this because I wanted all instance variables +to be hidden. You can store the same information in the <TT>user_data()</TT> + field of a window. To do this, search through the fdesign output for +all occurances of "->fdui" and edit to use "->user_data()" instead. + This will require casts and is not trivial. </P> +<P>The prototype for the functions passed to <TT>fl_add_timeout()</TT> + and <TT>fl_set_idle_callback()</TT> callback are different. </P> +<P><B>All the following XForms calls are missing:</B></P> +<UL> +<LI><TT>FL_REVISION</TT>, <TT>fl_library_version()</TT></LI> +<LI><TT>FL_RETURN_DBLCLICK</TT> (use <TT>Fl::event_clicks()</TT>) </LI> +<LI><TT>fl_add_signal_callback()</TT></LI> +<LI><TT>fl_set_form_atactivate()</TT> <TT>fl_set_form_atdeactivate()</TT> +</LI> +<LI><TT>fl_set_form_property()</TT></LI> +<LI><TT>fl_set_app_mainform()</TT>, <TT>fl_get_app_mainform()</TT></LI> +<LI><TT>fl_set_form_minsize()</TT>, <TT>fl_set_form_maxsize()</TT></LI> +<LI><TT>fl_set_form_event_cmask()</TT>, <TT>fl_get_form_event_cmask()</TT> +</LI> +<LI><TT>fl_set_form_dblbuffer()</TT>, <TT>fl_set_object_dblbuffer()</TT> + (use an <TT>Fl_Double_Window</TT> instead) </LI> +<LI><TT>fl_adjust_form_size()</TT></LI> +<LI><TT>fl_register_raw_callback()</TT></LI> +<LI><TT>fl_set_object_bw()</TT>, <TT>fl_set_border_width()</TT></LI> +<LI><TT>fl_set_object_resize()</TT>, <TT>fl_set_object_gravity()</TT></LI> +<LI><TT>fl_set_object_shortcutkey()</TT></LI> +<LI><TT>fl_set_object_automatic()</TT></LI> +<LI><TT>fl_get_object_bbox()</TT> (maybe FLTK should do this) </LI> +<LI><TT>fl_set_object_prehandler()</TT>, <TT>fl_set_object_posthandler()</TT> +</LI> +<LI><TT>fl_enumerate_fonts()</TT></LI> +<LI>Most drawing functions </LI> +<LI><TT>fl_set_coordunit()</TT> (FLTK uses pixels all the time) </LI> +<LI><TT>fl_ringbell()</TT></LI> +<LI><TT>fl_gettime()</TT></LI> +<LI><TT>fl_win*()</TT> (all these functions) </LI> +<LI><TT>fl_initialize(argc,argv,x,y,z)</TT> ignores last 3 arguments </LI> +<LI><TT>fl_read_bitmapfile()</TT>, <TT>fl_read_pixmapfile()</TT></LI> +<LI><TT>fl_addto_browser_chars()</TT></LI> +<LI><TT>FL_MENU_BUTTON</TT> just draws normally </LI> +<LI><TT>fl_set_bitmapbutton_file()</TT>, <TT>fl_set_pixmapbutton_file()</TT> +</LI> +<LI><TT>FL_CANVAS</TT> objects </LI> +<LI><TT>FL_DIGITAL_CLOCK</TT> (comes out analog) </LI> +<LI><TT>fl_create_bitmap_cursor()</TT>, <TT>fl_set_cursor_color()</TT></LI> +<LI><TT>fl_set_dial_angles()</TT></LI> +<LI><TT>fl_show_oneliner()</TT></LI> +<LI><TT>fl_set_choice_shortcut(a,b,c) </TT></LI> +<LI>command log </LI> +<LI>Only some of file selector is emulated </LI> +<LI><TT>FL_DATE_INPUT</TT></LI> +<LI><TT>fl_pup*()</TT> (all these functions) </LI> +<LI>textbox object (should be easy but I had no sample programs) </LI> +<LI>xyplot object </LI> +</UL> +<H2>Additional Notes</H2> + These notes were written for porting programs written with the older +IRISGL version of Forms. Most of these problems are the same ones +encountered when going from old Forms to XForms: +<H3>Does Not Run In Background</H3> + The IRISGL library always forked when you created the first window, +unless "foreground()" was called. FLTK acts like "foreground()" is +called all the time. If you really want the fork behavior do "if +(fork()) exit(0)" right at the start of your program. +<H3>You Cannot Use IRISGL Windows or fl_queue</H3> + If a Forms (not XForms) program if you wanted your own window for +displaying things you would create a IRISGL window and draw in it, +periodically calling Forms to check if the user hit buttons on the +panels. If the user did things to the IRISGL window, you would find +this out by having the value FL_EVENT returned from the call to Forms. +<P>None of this works with FLTK. Nor will it compile, the necessary +calls are not in the interface. </P> +<P>You have to make a subclass of <A href=Fl_Gl_Window.html#Fl_Gl_Window> +<TT>Fl_Gl_Window</TT></A> and write a <TT>draw()</TT> method and <TT> +handle()</TT> method. This may require anywhere from a trivial to a +major rewrite. </P> +<P>If you draw into the overlay planes you will have to also write a <TT> +draw_overlay()</TT> method and call <TT>redraw_overlay()</TT> on the +OpenGL window. </P> +<P>One easy way to hack your program so it works is to make the <TT> +draw()</TT> and <TT>handle()</TT> methods on your window set some +static variables, storing what event happened. Then in the main loop +of your program, call <TT>Fl::wait()</TT> and then check these +variables, acting on them as though they are events read from <TT> +fl_queue</TT>. </P> +<H3>You Must Use OpenGL to Draw Everything</H3> +<P>The file <TT><FL/gl.h></TT> defines replacements for a lot of IRISGL +calls, translating them to OpenGL. There are much better translators +available that you might want to investigate. </P> +<H3>You Cannot Make Forms Subclasses</H3> + Programs that call <TT>fl_make_object</TT> or directly setting the +handle routine will not compile. You have to rewrite them to use a +subclass of <TT>Fl_Widget</TT>. It is important to note that the <TT> +handle()</TT> method is not exactly the same as the <TT>handle()</TT> + function of Forms. Where a Forms <TT>handle()</TT> returned non-zero, +your <TT>handle()</TT> must call <TT>do_callback()</TT>. And your <TT> +handle()</TT> must return non-zero if it "understood" the event. +<P>An attempt has been made to emulate the "free" widget. This appears +to work quite well. It may be quicker to modify your subclass into a +"free" widget, since the "handle" functions match. </P> +<P>If your subclass draws into the overlay you are in trouble and will +have to rewrite things a lot. </P> +<H3>You Cannot Use <device.h></H3> + If you have written your own "free" widgets you will probably get a +lot of errors about "getvaluator". You should substitute: +<CENTER><TABLE border=1 WIDTH=90% summary="Mapping of Forms valuators to FLTK."> +<TR><TH align=center>Forms</TH><TH align=center>FLTK</TH></TR> +<TR><TD>MOUSE_X</TD><TD>Fl::event_x_root()</TD></TR> +<TR><TD>MOUSE_Y</TD><TD>Fl::event_y_root()</TD></TR> +<TR><TD>LEFTSHIFTKEY,RIGHTSHIFTKEY</TD><TD>Fl::event_shift()</TD></TR> +<TR><TD>CAPSLOCKKEY</TD><TD>Fl::event_capslock()</TD></TR> +<TR><TD>LEFTCTRLKEY,RIGHTCTRLKEY</TD><TD>Fl::event_ctrl()</TD></TR> +<TR><TD>LEFTALTKEY,RIGHTALTKEY</TD><TD>Fl::event_alt()</TD></TR> +<TR><TD>MOUSE1,RIGHTMOUSE</TD><TD>Fl::event_state()</TD></TR> +<TR><TD>MOUSE2,MIDDLEMOUSE</TD><TD>Fl::event_state()</TD></TR> +<TR><TD>MOUSE3,LEFTMOUSE</TD><TD>Fl::event_state()</TD></TR> +</TABLE></CENTER> + Anything else in <TT>getvaluator</TT> and you are on your own... +<H3>Font Numbers Are Different</H3> + The "style" numbers have been changed because I wanted to insert +bold-italic versions of the normal fonts. If you use Times, Courier, +or Bookman to display any text you will get a different font out of +FLTK. If you are really desperate to fix this use the following code: +<UL> +<PRE> +fl_font_name(3,"*courier-medium-r-no*"); +fl_font_name(4,"*courier-bold-r-no*"); +fl_font_name(5,"*courier-medium-o-no*"); +fl_font_name(6,"*times-medium-r-no*"); +fl_font_name(7,"*times-bold-r-no*"); +fl_font_name(8,"*times-medium-i-no*"); +fl_font_name(9,"*bookman-light-r-no*"); +fl_font_name(10,"*bookman-demi-r-no*"); +fl_font_name(11,"*bookman-light-i-no*"); +</PRE> + +*/ diff --git a/documentation/glut.dox b/documentation/glut.dox new file mode 100644 index 000000000..9cc4bd2c6 --- /dev/null +++ b/documentation/glut.dox @@ -0,0 +1,193 @@ +/** + + \page glut D - GLUT Compatibility + +<P>This appendix describes the GLUT compatibility header file supplied with FLTK. FLTK's GLUT compatibility is based on the original GLUT 3.7 and the follow-on FreeGLUT 2.4.0 libraries.</P> +<H2>Using the GLUT Compatibility Header File</H2> +<P>You should be able to compile existing GLUT source code by including <TT><FL/glut.H></TT> instead of <TT><GL/glut.h></TT>. This can be done by editing the source, by changing the <TT>-I</TT> switches to the compiler, or by providing a symbolic link from <TT>GL/glut.h</TT> to <TT>FL/glut.H</TT>.</P> +<P><I>All files calling GLUT procedures must be compiled with C++</I>. You may have to alter them slightly to get them to compile without warnings, and you may have to rename them to get make to use the C++ compiler.</P> +<P>You must link with the FLTK library. Most of <TT>FL/glut.H</TT> is inline functions. You should take a look at it (and maybe at <TT>test/glpuzzle.cxx</TT> in the FLTK source) if you are having trouble porting your GLUT program. </P> +<P>This has been tested with most of the demo programs that come with the GLUT and FreeGLUT distributions.</P> +<H2>Known Problems</H2> +<P>The following functions and/or arguments to functions are missing, and +you will have to replace them or comment them out for your code to +compile: +<UL> +<LI><TT>glutGet(GLUT_ELAPSED_TIME)</TT></LI> +<LI><TT>glutGet(GLUT_SCREEN_HEIGHT_MM)</TT></LI> +<LI><TT>glutGet(GLUT_SCREEN_WIDTH_MM)</TT></LI> +<LI><TT>glutGet(GLUT_WINDOW_NUM_CHILDREN)</TT></LI> +<LI><TT>glutInitDisplayMode(GLUT_LUMINANCE)</TT></LI> +<LI><TT>glutLayerGet(GLUT_HAS_OVERLAY)</TT></LI> +<LI><TT>glutLayerGet(GLUT_LAYER_IN_USE)</TT></LI> +<LI><TT>glutPushWindow()</TT></LI> +<LI><TT>glutSetColor(), glutGetColor(), glutCopyColormap()</TT></LI> +<LI><TT>glutVideoResize()</TT> missing. </LI> +<LI><TT>glutWarpPointer()</TT></LI> +<LI><TT>glutWindowStatusFunc()</TT></LI> +<LI>Spaceball, buttonbox, dials, and tablet functions</LI> +</UL> + Most of the symbols/enumerations have different values than GLUT uses. + This will break code that relies on the actual values. The only +symbols guaranteed to have the same values are true/false pairs like <TT> +GLUT_DOWN</TT> and <TT>GLUT_UP</TT>, mouse buttons <TT> +GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON</TT>, and <TT> +GLUT_KEY_F1</TT> thru <TT>F12</TT>. +<P>The strings passed as menu labels are not copied. </P> +<P><TT>glutPostRedisplay()</TT> does not work if called from inside a +display function. You must use <TT>glutIdleFunc()</TT> if you want +your display to update continuously. </P> +<P><TT>glutSwapBuffers()</TT> does not work from inside a display +function. This is on purpose, because FLTK swaps the buffers for you. </P> +<P><TT>glutUseLayer()</TT> does not work well, and should only be used +to initialize transformations inside a resize callback. You should +redraw overlays by using <TT>glutOverlayDisplayFunc()</TT>. </P> +<P>Overlays are cleared before the overlay display function is called. <TT> +glutLayerGet(GLUT_OVERLAY_DAMAGED)</TT> always returns true for +compatibility with some GLUT overlay programs. You must rewrite your +code so that <TT>gl_color()</TT> is used to choose colors in an +overlay, or you will get random overlay colors. </P> +<P><TT>glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR)</TT> just results in a +small crosshair. </P> +<P>The fonts used by <TT>glutBitmapCharacter() and glutBitmapWidth()</TT> + may be different. </P> +<P><TT>glutInit(argc,argv)</TT> will consume different switches than +GLUT does. It accepts the switches recognized by <A href="Fl.html#Fl.args"> +<TT>Fl::args()</TT></A>, and will accept any abbreviation of these +switches (such as "-di" for "-display"). </P> +<H2>Mixing GLUT and FLTK Code</H2> + You can make your GLUT window a child of a <TT>Fl_Window</TT> with the +following scheme. The biggest trick is that GLUT insists on <TT>show()</TT> +'ing the window at the point it is created, which means the <TT> +Fl_Window</TT> parent window must already be shown. +<UL> +<LI>Don't call <TT>glutInit()</TT>. </LI> +<LI>Create your <TT>Fl_Window</TT>, and any FLTK widgets. Leave a +blank area in the window for your GLUT window. </LI> +<LI><TT>show()</TT> the <TT>Fl_Window</TT>. Perhaps call <TT> +show(argc,argv)</TT>. </LI> +<LI>Call <TT>window->begin()</TT> so that the GLUT window will be +automatically added to it. </LI> +<LI>Use <TT>glutInitWindowSize()</TT> and <TT>glutInitWindowPosition()</TT> + to set the location in the parent window to put the GLUT window. </LI> +<LI>Put your GLUT code next. It probably does not need many changes. + Call <TT>window->end()</TT> immediately after the <TT> +glutCreateWindow()</TT>! </LI> +<LI>You can call either <TT>glutMainLoop()</TT>, <TT>Fl::run()</TT>, or +loop calling <TT>Fl::wait()</TT> to run the program. </LI> +</UL> +<HR break> +<H2><A name=Fl_Glut_Window>class Fl_Glut_Window</A></H2> +<HR> +<H3>Class Hierarchy</H3> +<UL> +<PRE> +<A href=Fl_Gl_Window.html#Fl_Gl_Window>Fl_Gl_Window</A> + | + +----<B>Fl_Glut_Window</B> +</PRE> +</UL> +<H3>Include Files</H3> +<UL> +<PRE> +#include <FL/glut.H> +</PRE> +</UL> +<H3>Description</H3> + Each GLUT window is an instance of this class. You may find it useful +to manipulate instances directly rather than use GLUT window id's. + These may be created without opening the display, and thus can fit +better into FLTK's method of creating windows. +<P>The current GLUT window is available in the global variable <TT> +glut_window</TT>. </P> +<P><TT>new Fl_Glut_Window(...)</TT> is the same as <TT> +glutCreateWindow()</TT> except it does not <TT>show()</TT> the window +or make the window current. </P> +<P><TT>window->make_current()</TT> is the same as <TT> +glutSetWindow(number)</TT>. If the window has not had <TT>show()</TT> + called on it yet, some functions that assumme an OpenGL context will +not work. If you do <TT>show()</TT> the window, call <TT>make_current()</TT> + again to set the context. </P> +<P><TT>~Fl_Glut_Window()</TT> is the same as <TT>glutDestroyWindow()</TT> +. </P> +<H3>Members</H3> +The <TT>Fl_Glut_Window</TT> class contains several public members that can +be altered directly: +<CENTER><TABLE WIDTH="80%" BORDER="1" ALT="Fl_Glut_Window public members."> +<TR> + <TH>member</TH> + <TH>description</TH> +</TR> +<TR> + <TD>display</TD> + <TD>A pointer to the function to call to draw the normal planes.</TD> +</TR> +<TR> + <TD>entry</TD> + <TD>A pointer to the function to call when the mouse moves into + or out of the window.</TD> +</TR> +<TR> + <TD>keyboard</TD> + <TD>A pointer to the function to call when a regular key is pressed.</TD> +</TR> +<TR> + <TD>menu[3]</TD> + <TD>The menu to post when one of the mouse buttons is pressed.</TD> +</TR> +<TR> + <TD>mouse</TD> + <TD>A pointer to the function to call when a button is pressed or + released.</TD> +</TR> +<TR> + <TD>motion</TD> + <TD>A pointer to the function to call when the mouse is moved with + a button down.</TD> +</TR> +<TR> + <TD>overlaydisplay</TD> + <TD>A pointer to the function to call to draw the overlay planes.</TD> +</TR> +<TR> + <TD>passivemotion</TD> + <TD>A pointer to the function to call when the mouse is moved with + no buttons down.</TD> +</TR> +<TR> + <TD>reshape</TD> + <TD>A pointer to the function to call when the window is resized.</TD> +</TR> +<TR> + <TD>special</TD> + <TD>A pointer to the function to call when a special key is pressed.</TD> +</TR> +<TR> + <TD>visibility</TD> + <TD>A pointer to the function to call when the window is iconified + or restored (made visible.)</TD> +</TR> +</TABLE></CENTER> + +<H3>Methods</H3> +<UL> +<LI><A href=#Fl_Glut_Window.Fl_Glut_Window>Fl_Glut_Window</A></LI> +<LI><A href=#Fl_Glut_Window.~Fl_Glut_Window>~Fl_Glut_Window</A></LI> +<LI><A href=#Fl_Glut_Window.make_current>make_current</A></LI> +</UL> +<H4><A name=Fl_Glut_Window.Fl_Glut_Window> +Fl_Glut_Window::Fl_Glut_Window(int x, int y, int w, int h, const char +*title = 0) +<BR> Fl_Glut_Window::Fl_Glut_Window(int w, int h, const char *title = 0)</A> +</H4> + The first constructor takes 4 int arguments to create the window with +a preset position and size. The second constructor with 2 arguments +will create the window with a preset size, but the window manager will +choose the position according to it's own whims. +<H4><A name=Fl_Glut_Window.~Fl_Glut_Window>virtual +Fl_Glut_Window::~Fl_Glut_Window()</A></H4> + Destroys the GLUT window. +<H4><A name="Fl_Glut_Window.make_current">void Fl_Glut_Window::make_current()</A></H4> +Switches all drawing functions to the GLUT window. + +*/ diff --git a/documentation/index.dox b/documentation/index.dox index 8253ce735..b4273c556 100644 --- a/documentation/index.dox +++ b/documentation/index.dox @@ -19,18 +19,16 @@ <TABLE BGCOLOR="#9f9fef" CELLPADDING="8" CELLSPACING="0" SUMMARY="Table of Contents" WIDTH="700"> <TR> - <TD ALIGN="LEFT" VALIGN="TOP"><B> + <TD ALIGN="LEFT" VALIGN="TOP"> + \subpage preface - </B> - <BR> - <BR> - <B><A HREF="intro.html#intro">1 - Introduction to FLTK</A></B> - <BR> - <BR> - <B><A HREF="basics.html#basics">2 - FLTK Basics</A></B> - <BR> - <BR> - <B><A HREF="common.html#common">3 - Common Widgets and Attributes</A></B> + + \subpage intro + + \subpage basics + + \subpage common + <B> <UL> <LI><A HREF="drawing.html#colors">Colors</A></LI> <LI><A HREF="common.html#boxtypes">Box Types</A></LI> @@ -38,66 +36,66 @@ <LI><A HREF="drawing.html#images">Images</A></LI> <LI><A HREF="Fl_Pixmap.html#Fl_Pixmap">class Fl_Pixmap</A></LI> </UL> - <B><A HREF="editor.html#editor">4 - Designing a Simple Text Editor</A></B> - <BR> - <BR> - <B><A HREF="drawing.html#drawing">5 - Drawing Things in FLTK</A></B> - <BR> - <BR> - <B><A HREF="events.html#events">6 - Handling Events</A></B> + </B> + + \subpage editor + + \subpage drawing + + \subpage events + <B> <UL> <LI><A HREF="events.html#event_xxx">Fl::event_*() methods</A></LI> <LI><A HREF="events.html#propagation">Event Propagation</A></LI> </UL> - <B><A HREF="subclassing.html#subclassing">7 - Adding and Extending - Widgets</A></B> - <BR> - <BR> - <B><A HREF="opengl.html#opengl">8 - Using OpenGL</A></B> + </B> + + \subpage subclassing + + \subpage opengl + </TD> + <TD ALIGN=LEFT VALIGN=TOP> - <B><A HREF="fluid.html#FLUID">9 - Programming with FLUID</A></B> + + \subpage fluid + <B> <UL> <LI><A HREF="fluid.html#widget_attributes">Widget Attributes</A></LI> <LI><A HREF="fluid.html#widget_attributes">Selecting Moving Widgets</A></LI> <LI><A HREF="fluid.html#images">Image Labels</A></LI> </UL> - <B> + </B> + \subpage advanced - </B> - <BR> - <BR> + <B><A HREF="classes.html">A - Class Reference</A></B> - <BR> - <BR> + <B><A HREF="globals_func.html">B - Function Reference</A></B> - <BR> - <BR> - <B><A HREF="enumerations.html#Enumerations">C - FLTK Enumerations.H</A> - </B> - <BR> - <BR> - <B><A HREF="glut.html#glut">D - GLUT Compatibility</A></B> + + \subpage enumerations + + \subpage glut + <B> <UL> <LI><A HREF="glut.html#Fl_Glut_Window">class Fl_Glut_Window</A></LI> </UL> - <B><A HREF="forms.html#forms">E - Forms Compatibility</A></B> - <BR> - <BR> - <B><A HREF="osissues.html#osissues">F - Operating System Issues</A></B> - <BR> - <BR> - <B><A HREF="migration.html">G - Migrating Code from FLTK 1.0.x</A></B> - <BR> - <BR> - <B><A HREF="license.html#license">H - Software License</A></B> - <BR> - <BR> - <B><A HREF="examples.html#examples">I - Example Source Code</A></B> - </TD> + </B> + + \subpage forms + + \subpage osissues + + \subpage migration_1_1 + + \subpage migration_1_3 + + \subpage license + + \subpage examples + +</TD> </TR> </TABLE> */ - - diff --git a/documentation/intro.dox b/documentation/intro.dox new file mode 100644 index 000000000..cdfb9b9f3 --- /dev/null +++ b/documentation/intro.dox @@ -0,0 +1,367 @@ +/** + + \page intro 1 - Introduction to FLTK + +<P>The Fast Light Tool Kit ("FLTK", pronounced +"fulltick") is a cross-platform C++ GUI toolkit for +UNIX®/Linux® (X11), Microsoft® Windows®, and +MacOS® X. FLTK provides modern GUI functionality without the +bloat and supports 3D graphics via OpenGL® and its built-in +GLUT emulation. It was originally developed by Mr. Bill Spitzak +and is currently maintained by a small group of developers +across the world with a central repository in the US.</P> + +<H2>History of FLTK</H2> + +<P>It has always been Bill's belief that the GUI API of all +modern systems is much too high level. Toolkits (even FLTK) are +<I>not</I> what should be provided and documented as part of an +operating system. The system only has to provide arbitrary +shaped but featureless windows, a powerful set of graphics +drawing calls, and a simple <I>unalterable</I> method of +delivering events to the owners of the windows. NeXT (if you +ignored NextStep) provided this, but they chose to hide it and +tried to push their own baroque toolkit instead.</P> + +<P>Many of the ideas in FLTK were developed on a NeXT (but +<I>not</I> using NextStep) in 1987 in a C toolkit Bill called +"views". Here he came up with passing events downward +in the tree and having the handle routine return a value +indicating whether it used the event, and the table-driven menus. In +general he was trying to prove that complex UI ideas could be +entirely implemented in a user space toolkit, with no knowledge +or support by the system.</P> + +<P>After going to film school for a few years, Bill worked at +Sun Microsystems on the (doomed) NeWS project. Here he found an +even better and cleaner windowing system, and he reimplemented +"views" atop that. NeWS did have an unnecessarily +complex method of delivering events which hurt it. But the +designers did admit that perhaps the user could write just as +good of a button as they could, and officially exposed the lower +level interface.</P> + +<P>With the death of NeWS Bill realized that he would have to +live with X. The biggest problem with X is the "window +manager", which means that the toolkit can no longer +control the window borders or drag the window around.</P> + +<P>At Digital Domain Bill discovered another toolkit, +"Forms". Forms was similar to his work, but provided +many more widgets, since it was used in many real applications, +rather then as theoretical work. He decided to use Forms, except +he integrated his table-driven menus into it. Several very large +programs were created using this version of Forms.</P> + +<P>The need to switch to OpenGL and GLX, portability, and a +desire to use C++ subclassing required a rewrite of Forms. +This produced the first version of FLTK. The conversion to C++ +required so many changes it made it impossible to recompile any +Forms objects. Since it was incompatible anyway, Bill decided +to incorporate his older ideas as much as possible by +simplifying the lower level interface and the event passing +mechanisim.</P> + +<P>Bill received permission to release it for free on the +Internet, with the GNU general public license. Response from +Internet users indicated that the Linux market dwarfed the SGI +and high-speed GL market, so he rewrote it to use X for all +drawing, greatly speeding it up on these machines. That is the +version you have now.</P> + +<P>Digital Domain has since withdrawn support for FLTK. While +Bill is no longer able to actively develop it, he still +contributes to FLTK in his free time and is a part of the FLTK +development team.</P> + +<H2>Features</H2> + +<P>FLTK was designed to be statically linked. This was done by +splitting it into many small objects and designing it so that +functions that are not used do not have pointers to them in the +parts that are used, and thus do not get linked in. This allows +you to make an easy-to-install program or to modify FLTK to +the exact requirements of your application without worrying +about bloat. FLTK works fine as a shared library, though, and +is now included with several Linux distributions.</P> + +<P>Here are some of the core features unique to FLTK:</P> + +<UL> + + <LI>sizeof(Fl_Widget) == 64 to 92.</LI> + + <LI>The "core" (the "hello" program + compiled & linked with a static FLTK library using + gcc on a 486 and then stripped) is 114K.</LI> + + <LI>The FLUID program (which includes every widget) is + 538k.</LI> + + <LI>Written directly atop core libraries (Xlib, WIN32 or + Carbon) for maximum speed, and carefully optimized for + code size and performance.</LI> + + <LI>Precise low-level compatability between the X11, + WIN32 and MacOS versions - only about 10% of the code is + different.</LI> + + <LI>Interactive user interface builder program. Output is + human-readable and editable C++ source code.</LI> + + <LI>Support for overlay hardware, with emulation if none + is available.</LI> + + <LI>Very small & fast portable 2-D drawing library + to hide Xlib, WIN32, or QuickDraw.</LI> + + <LI>OpenGL/Mesa drawing area widget.</LI> + + <LI>Support for OpenGL overlay hardware on both X11 and + WIN32, with emulation if none is available.</LI> + + <LI>Text widgets with Emacs key bindings, X cut & + paste, and foreign letter compose!</LI> + + <LI>Compatibility header file for the GLUT library.</LI> + + <LI>Compatibility header file for the XForms library.</LI> + +</UL> + +<H2>Licensing</H2> + +<P>FLTK comes with complete free source code. FLTK is available +under the terms of the <A href="license.html">GNU Library +General Public License</A> with exceptions that allow for static +linking. Contrary to popular belief, it can be used in +commercial software - even Bill Gates could use it!</P> + +<H2>What Does "FLTK" Mean?</H2> + +<P>FLTK was originally designed to be compatible with the Forms +Library written for SGI machines. In that library all the +functions and structures started with "fl_". This +naming was extended to all new methods and widgets in the C++ +library, and this prefix was taken as the name of the library. +It is almost impossible to search for "FL" on the +Internet, due to the fact that it is also the abbreviation for +Florida. After much debating and searching for a new name for +the toolkit, which was already in use by several people, Bill +came up with "FLTK", including a bogus excuse that it +stands for "The Fast Light Toolkit".</P> + +<H2>Building and Installing FLTK Under UNIX and MacOS X</H2> + +<P>In most cases you can just type "make". This will +run configure with the default of no options and then compile +everything.</P> + +<P>FLTK uses GNU autoconf to configure itself for your UNIX +platform. The main things that the configure script will look +for are the X11 and OpenGL (or Mesa) header and library files. +If these cannot be found in the standard include/library +locations you'll need to define the <tt>CFLAGS</tt>, +<tt>CXXFLAGS</tt>, and <tt>LDFLAGS</tt> environment variables. +For the Bourne and Korn shells you'd use:</P> + +<UL><PRE> +CFLAGS=-I<I>includedir</I>; export CFLAGS +CXXFLAGS=-I<I>includedir</I>; export CXXFLAGS +LDFLAGS=-L<I>libdir</I>; export LDFLAGS +</PRE></UL> + +<P>For C shell and tcsh, use:</P> + +<UL><PRE> +setenv CFLAGS "-I<I>includedir</I>" +setenv CXXFLAGS "-I<I>includedir</I>" +setenv LDFLAGS "-L<I>libdir</I>" +</PRE></UL> + +<P>By default configure will look for a C++ compiler named +<tt>CC</tt>, <tt>c++</tt>, <tt>g++</tt>, or <tt>gcc</tt> in that +order. To use another compiler you need to set the <tt>CXX</tt> +environment variable:</P> + +<UL><PRE> +CXX=xlC; export CXX +setenv CXX "xlC" +</PRE></UL> + +<P>The <tt>CC</tt> environment variable can also be used to +override the default C compiler (<tt>cc</tt> or <tt>gcc</tt>), +which is used for a few FLTK source files.</P> + +<P>You can run configure yourself to get the exact setup you +need. Type "./configure <options>", where +options are:</P> + +<DL> + + <DT>--enable-cygwin</DT> + <DD>Enable the Cygwin libraries under WIN32</DD> + + <DT>--enable-debug</DT> + <DD>Enable debugging code & symbols</DD> + + <DT>--disable-gl</DT> + <DD>Disable OpenGL support</DD> + + <DT>--enable-shared</DT> + <DD>Enable generation of shared libraries</DD> + + <DT>--enable-threads</DT> + <DD>Enable multithreading support</DD> + + <DT>--enable-xdbe</DT> + <DD>Enable the X double-buffer extension</DD> + + <DT>--enable-xft</DT> + <DD>Enable the Xft library for anti-aliased fonts under X11</DD> + + <DT>--bindir=/path</DT> + <DD>Set the location for executables [default = $prefix/bin]</DD> + + <DT>--datadir=/path</DT> + <DD>Set the location for data files. [default = $prefix/share]</DD> + + <DT>--libdir=/path</DT> + <DD>Set the location for libraries [default = $prefix/lib]</DD> + + <DT>--includedir=/path</DT> + <DD>Set the location for include files. [default = $prefix/include]</DD> + + <DT>--mandir=/path</DT> + <DD>Set the location for man pages. [default = $prefix/man]</DD> + + <DT>--prefix=/dir</DT> + <DD>Set the directory prefix for files [default = /usr/local]</DD> + +</DL> + +<P>When the configure script is done you can just run the +"make" command. This will build the library, FLUID +tool, and all of the test programs.</P> + +<P>To install the library, become root and type "make +install". This will copy the "fluid" executable +to "bindir", the header files to +"includedir", and the library files to +"libdir".</P> + +<H2>Building FLTK Under Microsoft Windows</H2> + +<P>There are three ways to build FLTK under Microsoft Windows. +The first is to use the Visual C++ 5.0 project files under the +"visualc" directory. Just open (or double-click on) +the "fltk.dsw" file to get the whole shebang.</P> + +<P>The second method is to use the <TT>configure</TT> script +included with the FLTK software; this has only been tested with +the CygWin tools:</P> + +<UL><PRE> +sh configure --prefix=C:/FLTK +make +</PRE></UL> + +<P>The final method is to use a GNU-based development tool with +the files in the "makefiles" directory. To build +using one of these tools simply copy the appropriate +makeinclude and config files to the main directory and do a +make:</P> + +<UL><PRE> +copy makefiles\Makefile.<env> Makefile +make +</PRE></UL> + +<H3>Using the Visual C++ DLL Library</H3> + +<P>The "fltkdll.dsp" project file builds a DLL-version +of the FLTK library. Because of name mangling differences +between PC compilers (even between different versions of Visual +C++!) you can only use the DLL that is generated with the same +version compiler that you built it with.</P> + +<P>When compiling an application or DLL that uses the FLTK DLL, +you will need to define the <tt>FL_DLL</tt> preprocessor symbol +to get the correct linkage commands embedded within the FLTK +header files.</P> + +<H2>Building FLTK Under OS/2</H2> + +<P>The current OS/2 build requires XFree86 for OS/2 to work. A +native Presentation Manager version has not been implemented +yet (volunteers are welcome!).</P> + +<p>The current set of Makefiles/configuration failes assumes that +EMX 0.9d and libExt +(from <A HREF="http://posix2.sourceforge.net">posix2.sourceforge.net</A>) +is installed. + +<P>To build the XFree86 version of FLTK for OS/2, copy the appropriate +makeinclude and config files to the main directory and do a make: </P> + +<UL><PRE> +copy makefiles\Makefile.os2x Makefile +make +</PRE></UL> + +<H2>Internet Resources</H2> + +<P>FLTK is available on the 'net in a bunch of locations:</P> + +<DL> + + <DT>WWW + <DD><A href="http://www.fltk.org/">http://www.fltk.org/</A> + <DD><A href="http://www.fltk.org/str.php">http://www.fltk.org/str.php</A> + [for reporting bugs] + <DD><A href="http://www.fltk.org/software.php">http://www.fltk.org/software.php</A> + [source code] + + <DT>FTP + <DD><A HREF="ftp://ftp.fltk.org/pub/fltk">California, USA (ftp.fltk.org)</A> + <DD><A HREF="ftp://ftp2.fltk.org/pub/fltk">Maryland, USA (ftp2.fltk.org)</A> + <DD><A HREF="ftp://ftp.funet.fi/pub/mirrors/ftp.fltk.org/pub/fltk">Espoo, Finland (ftp.funet.fi)</A> + <DD><A HREF="ftp://linux.mathematik.tu-darmstadt.de/pub/linux/mirrors/misc/fltk">Germany (linux.mathematik.tu-darmstadt.de)</A> + <DD><A HREF="ftp://gd.tuwien.ac.at/hci/fltk">Austria (gd.tuwien.ac.at)</A> + + <DT>EMail</DT> + <DD><A href="mailto:fltk@fltk.org">fltk@fltk.org</A> [see + instructions below] + <DD><A href="mailto:fltk-bugs@fltk.org">fltk-bugs@fltk.org</A> [for + reporting bugs] + + <DT>NNTP Newsgroups</DT> + <DD>news.easysw.com</DD> + +</DL> + +<P>To send a message to the FLTK mailing list +("fltk@fltk.org") you must first join the list. +Non-member submissions are blocked to avoid problems with +unsolicited email.</P> + +<P>To join the FLTK mailing list, send a message to +"majordomo@fltk.org" with "subscribe fltk" +in the message body. A digest of this list is available by +subscribing to the "fltk-digest" mailing list.</P> + +<H2>Reporting Bugs</H2> + +<P>To report a bug in FLTK, send an email to +"fltk-bugs@fltk.org". Please include the FLTK version, +operating system & version, and compiler that you are using +when describing the bug or problem. We will be unable to provide +any kind of help without that basic information.</P> + +<P>Bugs can also be reported to the "fltk.bugs" newsgroup or on the +SourceForge bug tracker pages.</P> + +<P>For general support and questions, please use the FLTK mailing list +at "fltk@fltk.org" or one of the newsgroups.</P> + +*/ diff --git a/documentation/license.dox b/documentation/license.dox new file mode 100644 index 000000000..fc2e766dd --- /dev/null +++ b/documentation/license.dox @@ -0,0 +1,437 @@ +/** + + \page license I - Software License + +<P ALIGN="RIGHT">December 11, 2001</P> + +<P>The FLTK library and included programs are provided under the terms +of the GNU Library General Public License (LGPL) with the following +exceptions:</P> + +<OL> + + <LI>Modifications to the FLTK configure script, config + header file, and makefiles by themselves to support + a specific platform do not constitute a modified or + derivative work.<BR> + <BR> + The authors do request that such modifications be + contributed to the FLTK project - send all + contributions to "fltk-bugs@fltk.org".<BR> + <BR> + </LI> + + <LI>Widgets that are subclassed from FLTK widgets do not + constitute a derivative work.<BR> + <BR> + </LI> + + <LI>Static linking of applications and widgets to the + FLTK library does not constitute a derivative work + and does not require the author to provide source + code for the application or widget, use the shared + FLTK libraries, or link their applications or + widgets against a user-supplied version of FLTK.<BR> + <BR> + If you link the application or widget to a modified + version of FLTK, then the changes to FLTK must be + provided under the terms of the LGPL in sections + 1, 2, and 4.<BR> + <BR> + </LI> + + <LI>You do not have to provide a copy of the FLTK license + with programs that are linked to the FLTK library, nor + do you have to identify the FLTK license in your + program or documentation as required by section 6 + of the LGPL.<BR> + <BR> + However, programs must still identify their use of FLTK. + The following example statement can be included in user + documentation to satisfy this requirement:<BR> + <BR> + <I>[program/widget] is based in part on the work of + the FLTK project (http://www.fltk.org).</I></LI> + +</OL> + +<HR> + +<P ALIGN=CENTER><BIG>GNU LIBRARY GENERAL PUBLIC LICENSE</BIG></P> +<P ALIGN=CENTER>Version 2, June 1991 +<BR> Copyright (C) 1991 Free Software Foundation, Inc. +<BR> 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +<BR> Everyone is permitted to copy and distribute verbatim copies of +this license document, but changing it is not allowed. +<BR> [This is the first released version of the library GPL. It is +numbered 2 because it goes with version 2 of the ordinary GPL.] </P> +<P><BIG>Preamble</BIG></P> + The licenses for most software are designed to take away your freedom +to share and change it. By contrast, the GNU General Public Licenses +are intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. +<P>This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. </P> +<P>When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it in +new free programs; and that you know you can do these things. </P> +<P>To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the library, or if you modify it. </P> +<P>For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. </P> +<P>Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. </P> +<P>Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. </P> +<P>Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. </P> +<P>Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License, which was designed for utility +programs. This license, the GNU Library General Public License, +applies to certain designated libraries. This license is quite +different from the ordinary one; be sure to read it in full, and don't +assume that anything in it is the same as in the ordinary license. </P> +<P>The reason we have a separate public license for some libraries is +that they blur the distinction we usually make between modifying or +adding to a program and simply using it. Linking a program with a +library, without changing the library, is in some sense simply using +the library, and is analogous to running a utility program or +application program. However, in a textual and legal sense, the linked +executable is a combined work, a derivative of the original library, +and the ordinary General Public License treats it as such. </P> +<P>Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. </P> +<P>However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended +to permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to +achieve this as regards changes in header files, but we have achieved +it as regards changes in the actual functions of the Library.) The +hope is that this will lead to faster development of free libraries. </P> +<P>The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the libary" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. </P> +<P>Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. </P> +<P ALIGN="CENTER"><BIG>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND +MODIFICATION</BIG></P> +<STRONG>0.</STRONG> This License Agreement applies to any software +library which contains a notice placed by the copyright holder or other +authorized party saying it may be distributed under the terms of this +Library General Public License (also called "this License"). Each +licensee is addressed as "you". +<P>A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. </P> +<P>The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) </P> +<P>"Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. </P> +<P>Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does and +what the program that uses the Library does. </P> +<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of +the Library's complete source code as you receive it, in any medium, +provided that you conspicuously and appropriately publish on each copy +an appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the Library. </P> +<P>You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. </P> +<P><STRONG>2.</STRONG> You may modify your copy or copies of the +Library or any portion of it, thus forming a work based on the Library, +and copy and distribute such modifications or work under the terms of +Section 1 above, provided that you also meet all of these conditions: <BLOCKQUOTE> +<STRONG>a)</STRONG> The modified work must itself be a software +library. +<P><STRONG>b)</STRONG> You must cause the files modified to carry +prominent notices stating that you changed the files and the date of +any change. </P> +<P><STRONG>c)</STRONG> You must cause the whole of the work to be +licensed at no charge to all third parties under the terms of this +License. </P> +<P><STRONG>d)</STRONG> If a facility in the modified Library refers to +a function or a table of data to be supplied by an application program +that uses the facility, other than as an argument passed when the +facility is invoked, then you must make a good faith effort to ensure +that, in the event an application does not supply such function or +table, the facility still operates, and performs whatever part of its +purpose remains meaningful. </P> +<P>(For example, a function in a library to compute square roots has a +purpose that is entirely well-defined independent of the application. + Therefore, Subsection 2d requires that any application-supplied +function or table used by this function must be optional: if the +application does not supply it, the square root function must still +compute square roots.) </P> +</BLOCKQUOTE> +<P>These requirements apply to the modified work as a whole. +If identifiable sections of that work are not derived from the +Library, and can be reasonably considered independent and separate +works in themselves, then this License, and its terms, do not apply to +those sections when you distribute them as separate works. But when +you distribute the same sections as part of a whole which is a work +based on the Library, the distribution of the whole must be on the +terms of this License, whose permissions for other licensees extend to +the entire whole, and thus to each and every part regardless of who +wrote it. </P> +<P>Thus, it is not the intent of this section to claim rights or +contest your rights to work written entirely by you; rather, the intent +is to exercise the right to control the distribution of derivative or +collective works based on the Library. </P> +<P>In addition, mere aggregation of another work not based on the +Library with the Library (or with a work based on the Library) on a +volume of a storage or distribution medium does not bring the other +work under the scope of this License. </P> +<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary +GNU General Public License instead of this License to a given copy of +the Library. To do this, you must alter all the notices that refer to +this License, so that they refer to the ordinary GNU General Public +License, version 2, instead of to this License. (If a newer version +than version 2 of the ordinary GNU General Public License has appeared, +then you can specify that version instead if you wish.) Do not make +any other change in these notices. </P> +<P>Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. </P> +<P>This option is useful when you wish to copy part of the code of the +Library into a program that is not a library. </P> +<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a +portion or derivative of it, under Section 2) in object code or +executable form under the terms of Sections 1 and 2 above provided that +you accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections 1 +and 2 above on a medium customarily used for software interchange. </P> +<P>If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to distribute +the source code, even though third parties are not compelled to copy +the source along with the object code. </P> +<P><STRONG>5.</STRONG> A program that contains no derivative of any +portion of the Library, but is designed to work with the Library by +being compiled or linked with it, is called a "work that uses the +Library". Such a work, in isolation, is not a derivative work of the +Library, and therefore falls outside the scope of this License. </P> +<P>However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. Section +6 states terms for distribution of such executables. </P> +<P>When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. </P> +<P>If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) </P> +<P>Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, whether +or not they are linked directly with the Library itself. </P> +<P><STRONG>6.</STRONG> As an exception to the Sections above, you may +also compile or link a "work that uses the Library" with the Library to +produce a work containing portions of the Library, and distribute that +work under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. </P> +<P>You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: <BLOCKQUOTE><STRONG>a)</STRONG> Accompany the work +with the complete corresponding machine-readable source code for the +Library including whatever changes were used in the work (which must +be distributed under Sections 1 and 2 above); and, if the work is an +executable linked with the Library, with the complete machine-readable +"work that uses the Library", as object code and/or source code, so +that the user can modify the Library and then relink to produce a +modified executable containing the modified Library. (It is +understood that the user who changes the contents of definitions files +in the Library will not necessarily be able to recompile the +application to use the modified definitions.) +<P><STRONG>b)</STRONG> Accompany the work with a written offer, valid +for at least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more than the cost +of performing this distribution. </P> +<P><STRONG>c)</STRONG> If distribution of the work is made by offering +access to copy from a designated place, offer equivalent access to +copy the above specified materials from the same place. </P> +<P><STRONG>d)</STRONG> Verify that the user has already received a copy +of these materials or that you have already sent this user a copy. </P> +</BLOCKQUOTE> +<P>For an executable, the required form of the "work that +uses the Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major components +(compiler, kernel, and so on) of the operating system on which the +executable runs, unless that component itself accompanies the +executable.</P> +<P>It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. </P> +<P><STRONG>7.</STRONG> You may place library facilities that are a work +based on the Library side-by-side in a single library together with +other library facilities not covered by this License, and distribute +such a combined library, provided that the separate distribution of the +work based on the Library and of the other library facilities is +otherwise permitted, and provided that you do these two things: <BLOCKQUOTE> +<STRONG>a)</STRONG> Accompany the combined library with a copy of the +same work based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the Sections +above. +<P><STRONG>b)</STRONG> Give prominent notice with the combined library +of the fact that part of it is a work based on the Library, and +explaining where to find the accompanying uncombined form of the same +work. </P> +</BLOCKQUOTE> +<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, +link with, or distribute the Library except as expressly provided under +this License. Any attempt otherwise to copy, modify, sublicense, link +with, or distribute the Library is void, and will automatically +terminate your rights under this License. However, parties who have +received copies, or rights, from you under this License will not have +their licenses terminated so long as such parties remain in full +compliance. </P> +<P><STRONG>9.</STRONG> You are not required to accept this License, +since you have not signed it. However, nothing else grants you +permission to modify or distribute the Library or its derivative works. + These actions are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Library (or any work based +on the Library), you indicate your acceptance of this License to do so, +and all its terms and conditions for copying, distributing or modifying +the Library or works based on it. </P> +<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any +work based on the Library), the recipient automatically receives a +license from the original licensor to copy, distribute, link with or +modify the Library subject to these terms and conditions. You may not +impose any further restrictions on the recipients' exercise of the +rights granted herein. You are not responsible for enforcing compliance +by third parties to this License. </P> +<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or +allegation of patent infringement or for any other reason (not limited +to patent issues), conditions are imposed on you (whether by court +order, agreement or otherwise) that contradict the conditions of this +License, they do not excuse you from the conditions of this License. + If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, +then as a consequence you may not distribute the Library at all. For +example, if a patent license would not permit royalty-free +redistribution of the Library by all those who receive copies directly +or indirectly through you, then the only way you could satisfy both it +and this License would be to refrain entirely from distribution of the +Library. </P> +<P>If any portion of this section is held invalid or unenforceable +under any particular circumstance, the balance of the section is +intended to apply, and the section as a whole is intended to apply in +other circumstances. </P> +<P>It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is implemented +by public license practices. Many people have made generous +contributions to the wide range of software distributed through that +system in reliance on consistent application of that system; it is up +to the author/donor to decide if he or she is willing to distribute +software through any other system and a licensee cannot impose that +choice. </P> +<P>This section is intended to make thoroughly clear what is believed +to be a consequence of the rest of this License. </P> +<P><STRONG>12.</STRONG> If the distribution and/or use of the Library +is restricted in certain countries either by patents or by copyrighted +interfaces, the original copyright holder who places the Library under +this License may add an explicit geographical distribution limitation +excluding those countries, so that distribution is permitted only in or +among countries not thus excluded. In such case, this License +incorporates the limitation as if written in the body of this License. </P> +<P><STRONG>13.</STRONG> The Free Software Foundation may publish +revised and/or new versions of the Library General Public License from +time to time. Such new versions will be similar in spirit to the +present version, but may differ in detail to address new problems or +concerns. </P> +<P>Each version is given a distinguishing version number. If the +Library specifies a version number of this License which applies to it +and "any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. </P> +<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library +into other free programs whose distribution conditions are incompatible +with these, write to the author to ask for permission. For software +which is copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. </P> +<P ALIGN="CENTER"><BIG>NO WARRANTY</BIG></P> +<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, +THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE +OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU +ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. </P> +<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW +OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY +WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE +LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL +OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. </P> +<P ALIGN="CENTER"><BIG>END OF TERMS AND CONDITIONS</BIG></P> + +*/ diff --git a/documentation/migration_1_1.dox b/documentation/migration_1_1.dox new file mode 100644 index 000000000..5ca8cef30 --- /dev/null +++ b/documentation/migration_1_1.dox @@ -0,0 +1,158 @@ +/** + + \page migration_1_1 G - Migrating Code from FLTK 1.0 to 1.1 + +<P>This appendix describes the differences between the FLTK +1.0.x and FLTK 1.1.x functions and classes.</P> + +<H2>Color Values</H2> + +<P>Color values are now stored in a 32-bit unsigned integer +instead of the unsigned character in 1.0.x. This allows for the +specification of 24-bit RGB values or 8-bit FLTK color indices. + +<P><TT>FL_BLACK</TT> and <TT>FL_WHITE</TT> now remain black and +white, even if the base color of the gray ramp is changed using +<A HREF="Fl.html#Fl.background"><TT>Fl::background()</TT></A>. +<TT>FL_DARK3</TT> and <TT>FL_LIGHT3</TT> can be used instead to +draw a very dark or a very bright background hue.</P> + +<P>Widgets use the new color symbols <TT>FL_FORGROUND_COLOR</TT>, +<TT>FL_BACKGROUND_COLOR</TT>, <TT>FL_BACKGROUND2_COLOR</TT>, +<TT>FL_INACTIVE_COLOR</TT>, and <TT>FL_SELECTION_COLOR</TT>. +More details can be found in the chapter +<A HREF="enumerations.html#colors">Enumerations</A>.</P> + +<H2>Cut and Paste Support</H2> + +<P>The FLTK clipboard is now broken into two parts - a local +selection value and a cut-and-paste value. This allows FLTK to +support things like highlighting and replacing text that was +previously cut or copied, which makes FLTK applications behave +like traditional GUI applications. + +<H2>File Chooser</H2> + +<P>The file chooser in FLTK 1.1.x is significantly different +than the one supplied with FLTK 1.0.x. Any code that directly +references the old <TT>FCB</TT> class or members will need +to be ported to the new <A +HREF="Fl_File_Chooser.html"><TT>Fl_File_Chooser</TT></A> +class.</P> + +<H2>Function Names</H2> + +<P>Some function names have changed from FLTK 1.0.x to 1.1.x in +order to avoid name space collisions. You can still use the old +function names by defining the <CODE>FLTK_1_0_COMPAT</CODE> +symbol on the command-line when you compile +(<CODE>-DFLTK_1_0_COMPAT</CODE>) or in your source, e.g.: + +<UL><PRE> +#define FLTK_1_0_COMPAT +#include <FL/Fl.H> +#include <FL/Enumerations.H> +#include <FL/filename.H> +</PRE></UL> + +<P>The following table shows the old and new function names:</P> + +<CENTER><TABLE WIDTH="80%" BORDER="1"> +<TR> + <TH>Old 1.0.x Name</TH> + <TH>New 1.1.x Name</TH> +</TR> +<TR> + <TD>contrast()</TD> + <TD>fl_contrast()</TD> +</TR> +<TR> + <TD>down()</TD> + <TD>fl_down()</TD> +</TR> +<TR> + <TD>filename_absolute()</TD> + <TD>fl_filename_absolute()</TD> +</TR> +<TR> + <TD>filename_expand()</TD> + <TD>fl_filename_expand()</TD> +</TR> +<TR> + <TD>filename_ext()</TD> + <TD>fl_filename_ext()</TD> +</TR> +<TR> + <TD>filename_isdir()</TD> + <TD>fl_filename_isdir()</TD> +</TR> +<TR> + <TD>filename_list()</TD> + <TD>fl_filename_list()</TD> +</TR> +<TR> + <TD>filename_match()</TD> + <TD>fl_filename_match()</TD> +</TR> +<TR> + <TD>filename_name()</TD> + <TD>fl_filename_name()</TD> +</TR> +<TR> + <TD>filename_relative()</TD> + <TD>fl_filename_relative()</TD> +</TR> +<TR> + <TD>filename_setext()</TD> + <TD>fl_filename_setext()</TD> +</TR> +<TR> + <TD>frame()</TD> + <TD>fl_frame()</TD> +</TR> +<TR> + <TD>inactive()</TD> + <TD>fl_inactive()</TD> +</TR> +<TR> + <TD>numericsort()</TD> + <TD>fl_numericsort()</TD> +</TR> +</TABLE></CENTER> + +<H2>Image Support</H2> + +<P>Image support in FLTK has been significantly revamped in +1.1.x. The <A HREF="Fl_Image.html"><TT>Fl_Image</TT></A> class +is now a proper base class, with the core image drawing +functionality in the <A +HREF="Fl_Bitmap.html"><TT>Fl_Bitmap</TT></A>, <A +HREF="Fl_Pixmap.html"><TT>Fl_Pixmap</TT></A>, and <A +HREF="Fl_RGB_Image.html"><TT>Fl_RGB_Image</TT></A> classes. + +<P>BMP, GIF, JPEG, PNG, XBM, and XPM image files can now be +loaded using the appropriate image classes, and the <A +HREF="Fl_Shared_Image.html"><TT>Fl_Shared_Image</TT></A> class +can be used to cache images in memory. + +<P>Image labels are no longer provided as an add-on label type. +If you use the old <TT>label()</TT> methods on an image, the +widget's <TT>image()</TT> method is called to set the image +as the label. + +<P>Image labels in menu items must still use the old labeltype +mechanism to preserve source compatibility. + +<H2>Keyboard Navigation</H2> + +<P>FLTK 1.1.x now supports keyboard navigation and control with +all widgets. To restore the old FLTK 1.0.x behavior so that only +text widgets get keyboard focus, call the <A +HREF="Fl.html#Fl.visible_focus"><CODE>Fl::visible_focus()</CODE></A> +method to disable it: + +<UL><PRE> +Fl::visible_focus(0); +</PRE></UL> + +*/ diff --git a/documentation/migration_1_3.dox b/documentation/migration_1_3.dox new file mode 100644 index 000000000..386afa6a4 --- /dev/null +++ b/documentation/migration_1_3.dox @@ -0,0 +1,11 @@ +/** + + \page migration_1_3 H - Migrating Code from FLTK 1.1 to 1.3 + +<P>This appendix describes the differences between the FLTK +1.1.x and FLTK 1.3.x functions and classes.</P> + +If you want to migrate your code from FLTK 1.0 to FLTK 1.3, +then you should also consult Appendix \ref migration_1_1. + +*/ diff --git a/documentation/opengl.dox b/documentation/opengl.dox new file mode 100644 index 000000000..87a5c50c2 --- /dev/null +++ b/documentation/opengl.dox @@ -0,0 +1,463 @@ +/** + + \page opengl 8 - Using OpenGL + +<P>This chapter discusses using FLTK for your OpenGL applications. + +<H2>Using OpenGL in FLTK</H2> + +<P>The easiest way to make an OpenGL display is to subclass <A +href="Fl_Gl_Window.html#Fl_Gl_Window"><TT>Fl_Gl_Window</TT></A>. +Your subclass must implement a <TT>draw()</TT> method which uses +OpenGL calls to draw the display. Your main program should call +<TT>redraw()</TT> when the display needs to change, and +(somewhat later) FLTK will call <TT>draw()</TT>. + +<P>With a bit of care you can also use OpenGL to draw into +normal FLTK windows. This allows you to use Gouraud shading for +drawing your widgets. To do this you use the <A +href="#gl_start"><TT>gl_start()</TT></A> and <A +href=#gl_finish><TT>gl_finish()</TT></A> functions around your +OpenGL code.</P> + +<P>You must include FLTK's <TT><FL/gl.h></TT> header +file. It will include the file <TT><GL/gl.h></TT>, define +some extra drawing functions provided by FLTK, and include the +<TT><windows.h></TT> header file needed by WIN32 +applications.</P> + +<H2>Making a Subclass of Fl_Gl_Window</H2> + +<P>To make a subclass of Fl_Gl_Window, you must provide: + +<UL> + + <LI>A class definition.</LI> + + <LI>A <TT>draw()</TT> method.</LI> + + <LI>A <TT>handle()</TT> method if you need to receive + input from the user.</LI> + +</UL> + +<P>If your subclass provides static controls in the window, they +must be redrawn whenever the <tt>FL_DAMAGE_ALL</tt> bit is set +in the value returned by <tt>damage()</tt>. For double-buffered +windows you will need to surround the drawing code with the +following code to make sure that both buffers are redrawn: + +<UL><PRE> +#ifndef MESA +glDrawBuffer(GL_FRONT_AND_BACK); +#endif // !MESA +... draw stuff here ... +#ifndef MESA +glDrawBuffer(GL_BACK); +#endif // !MESA +</PRE></UL> + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>If you are using the Mesa graphics library, the call + to <tt>glDrawBuffer()</tt> is not required and will slow + down drawing considerably. The preprocessor instructions + shown above will optimize your code based upon the + graphics library used. + + </TD> + +</TR> +</TABLE></CENTER> + +<H3>Defining the Subclass</H3> + +<P>To define the subclass you just subclass the +<TT>Fl_Gl_Window</TT> class: + +<UL><PRE> +class MyWindow : public Fl_Gl_Window { + void draw(); + int handle(int); + +public: + MyWindow(int X, int Y, int W, int H, const char *L) + : Fl_Gl_Window(X, Y, W, H, L) {} +}; +</PRE></UL> + +<P>The <TT>draw()</TT> and <TT>handle()</TT> methods are +described below. Like any widget, you can include additional +private and public data in your class (such as scene graph +information, etc.) + +<H3>The draw() Method</H3> + +<P>The <TT>draw()</TT> method is where you actually do your +OpenGL drawing: + +<UL><PRE> +void MyWindow::draw() { + if (!valid()) { + ... set up projection, viewport, etc ... + ... window size is in w() and h(). + ... valid() is turned on by FLTK after draw() returns + } + ... draw ... +} +</PRE></UL> + +<H3>The handle() Method</H3> + +<P>The <TT>handle()</TT> method handles mouse and keyboard +events for the window: + +<UL><PRE> +int MyWindow::handle(int event) { + switch(event) { + case FL_PUSH: + ... mouse down event ... + ... position in Fl::event_x() and Fl::event_y() + return 1; + case FL_DRAG: + ... mouse moved while down event ... + return 1; + case FL_RELEASE: + ... mouse up event ... + return 1; + case FL_FOCUS : + case FL_UNFOCUS : + ... Return 1 if you want keyboard events, 0 otherwise + return 1; + case FL_KEYBOARD: + ... keypress, key is in Fl::event_key(), ascii in Fl::event_text() + ... Return 1 if you understand/use the keyboard event, 0 otherwise... + return 1; + case FL_SHORTCUT: + ... shortcut, key is in Fl::event_key(), ascii in Fl::event_text() + ... Return 1 if you understand/use the shortcut event, 0 otherwise... + return 1; + default: + // pass other events to the base class... + return Fl_Gl_Window::handle(event); + } +} +</PRE></UL> + +<P>When <TT>handle()</TT> is called, the OpenGL context is not +set up! If your display changes, you should call +<TT>redraw()</TT> and let <TT>draw()</TT> do the work. Don't +call any OpenGL drawing functions from inside <TT>handle()</TT>! + +<P>You can call <I>some</I> OpenGL stuff like hit detection and texture +loading functions by doing: </P> + +<UL><PRE> + case FL_PUSH: + make_current(); // make OpenGL context current + if (!valid()) { + ... set up projection exactly the same as draw ... + valid(1); // stop it from doing this next time + } + ... ok to call NON-DRAWING OpenGL code here, such as hit + detection, loading textures, etc... +</PRE></UL> + +<P>Your main program can now create one of your windows by doing +<TT>new MyWindow(...)</TT>. You can also use <A +href="fluid.html#FLUID">FLUID</A> by: + +<OL> + + <LI>Putting your class definition in a + <tt>MyWindow.H</tt> file.</LI> + + <LI>Creating a <tt>Fl_Box</tt> widget in FLUID.</LI> + + <LI>In the widget panel fill in the "class" + field with <tt>MyWindow</tt>. This will make FLUID + produce constructors for your new class.</LI> + + <LI>In the "Extra Code" field put <TT>#include + "MyWindow.H"</TT>, so that the FLUID output + file will compile.</LI> + +</OL> + +<P>You must put <TT>glwindow->show()</TT> in your main code +after calling <TT>show()</TT> on the window containing the +OpenGL window. + +<H2>Using OpenGL in Normal FLTK Windows</H2> + +<P>You can put OpenGL code into an <A +href="subclassing.html#draw"><TT>Fl_Widget::draw()</TT></A> +method or into the code for a <A +href="common.html#boxtypes">boxtype</A> or other places with some +care. + +<P>Most importantly, before you show <I>any</I> windows, +including those that don't have OpenGL drawing, you <B>must</B> +initialize FLTK so that it knows it is going to use OpenGL. You +may use any of the symbols described for <A +href="Fl_Gl_Window.html#Fl_Gl_Window.mode"><TT>Fl_Gl_Window::mode()</TT></A> +to describe how you intend to use OpenGL:</P> + +<UL><PRE> +Fl::gl_visual(FL_RGB); +</PRE></UL> + +<P>You can then put OpenGL drawing code anywhere you can draw +normally by surrounding it with: + +<UL><PRE> +gl_start(); +... put your OpenGL code here ... +gl_finish(); +</PRE></UL> + +<P><A name="gl_start"><TT>gl_start()</TT></A> and <A +name="gl_finish"><TT>gl_finish()</TT></A> set up an OpenGL +context with an orthographic projection so that 0,0 is the +lower-left corner of the window and each pixel is one unit. The +current clipping is reproduced with OpenGL <TT>glScissor()</TT> +commands. These functions also synchronize the OpenGL graphics stream +with the drawing done by other X, WIN32, or FLTK functions. + +<P>The same context is reused each time. If your code changes +the projection transformation or anything else you should use +<TT>glPushMatrix()</TT> and <TT>glPopMatrix()</TT> functions to +put the state back before calling <TT>gl_finish()</TT>.</P> + +<P>You may want to use <TT>Fl_Window::current()->h()</TT> to +get the drawable height so that you can flip the Y +coordinates.</P> + +<P>Unfortunately, there are a bunch of limitations you must +adhere to for maximum portability: </P> + +<UL> + + <LI>You must choose a default visual with <A + href="Fl.html#Fl.gl_visual"><TT>Fl::gl_visual()</TT></A>.</LI> + + <LI>You cannot pass <TT>FL_DOUBLE</TT> to + <TT>Fl::gl_visual()</TT>.</LI> + + <LI>You cannot use <TT>Fl_Double_Window</TT> or + <TT>Fl_Overlay_Window</TT>.</LI> + +</UL> + +<P>Do <I>not</I> call <TT>gl_start()</TT> or +<TT>gl_finish()</TT> when drawing into an <TT>Fl_Gl_Window</TT>! + +<H2>OpenGL Drawing Functions</H2> + +<P>FLTK provides some useful OpenGL drawing functions. They can +be freely mixed with any OpenGL calls, and are defined by +including <TT><FL/gl.H></TT> which you should include +instead of the OpenGL header <TT><GL/gl.h></TT>. + +<H4>void gl_color(Fl_Color)</H4> + +<P>Sets the current OpenGL color to a FLTK color. <I>For +color-index modes it will use <TT>fl_xpixel(c)</TT>, which is +only right if this window uses the default colormap!</I> + +<H4>void gl_rect(int x, int y, int w, int h) +<BR>void gl_rectf(int x, int y, int w, int h)</H4> + +<P>Outlines or fills a rectangle with the current color. If <A +HREF="Fl_Gl_Window.html#Fl_Gl_Window.ortho"><TT>Fl_Gl_Window::ortho()</TT></A> +has been called, then the rectangle will exactly fill the pixel +rectangle passed. + +<H4>void gl_font(Fl_Font fontid, int size)</H4> + +<P>Sets the current OpenGL font to the same font you get by +calling <A href="drawing.html#fl_font"><TT>fl_font()</TT></A>. + +<H4>int gl_height() +<BR>int gl_descent() +<BR>float gl_width(const char *) +<BR>float gl_width(const char *, int n) +<BR>float gl_width(uchar)</H4> + +<P>Returns information about the current OpenGL font. + +<H4>void gl_draw(const char *) +<BR>void gl_draw(const char *, int n)</H4> + +<P>Draws a nul-terminated string or an array of <TT>n</TT> +characters in the current OpenGL font at the current raster +position. + +<H4>void gl_draw(const char *, int x, int y) +<BR>void gl_draw(const char *, int n, int x, int y) +<BR>void gl_draw(const char *, float x, float y) +<BR>void gl_draw(const char *, int n, float x, float y)</H4> + +<P>Draws a nul-terminated string or an array of <TT>n</TT> +characters in the current OpenGL font at the given position. + +<H4>void gl_draw(const char *, int x, int y, int w, int h, Fl_Align)</H4> + +<P>Draws a string formatted into a box, with newlines and tabs +expanded, other control characters changed to ^X, and aligned +with the edges or center. Exactly the same output as <A +href="drawing.html#text"><TT>fl_draw()</TT></A>. + +<h2>Speeding up OpenGL</h2> + +<P>Performance of Fl_Gl_Window may be improved on some types of +OpenGL implementations, in particular MESA and other software +emulators, by setting the <tt>GL_SWAP_TYPE</tt> environment +variable. This variable declares what is in the backbuffer after +you do a swapbuffers. + +<ul> + + <li><tt>setenv GL_SWAP_TYPE COPY</tt> + + <p>This indicates that the back buffer is copied to the + front buffer, and still contains it's old data. This is + true of many hardware implementations. Setting this + will speed up emulation of overlays, and widgets that + can do partial update can take advantage of this as + damage() will not be cleared to -1. <p> + + <li><tt>setenv GL_SWAP_TYPE NODAMAGE</tt> + + <p>This indicates that nothing changes the back buffer + except drawing into it. This is true of MESA and Win32 + software emulation and perhaps some hardware emulation + on systems with lots of memory. <p> + + <li>All other values for <tt>GL_SWAP_TYPE</tt>, and not + setting the variable, cause FLTK to assume that the + back buffer must be completely redrawn after a swap. + +</ul> + +<p>This is easily tested by running the <TT>gl_overlay</TT> demo +program and seeing if the display is correct when you drag +another window over it or if you drag the window off the screen +and back on. You have to exit and run the program again for it +to see any changes to the environment variable. + +<H2>Using OpenGL Optimizer with FLTK</H2> + +<P><A href="http://www.sgi.com/software/optimizer">OpenGL +Optimizer</A> is a scene graph toolkit for OpenGL available from +Silicon Graphics for IRIX and Microsoft Windows. It allows you +to view large scenes without writing a lot of OpenGL code. + +<H4>OptimizerWindow Class Definition</H4> + +<P>To use OpenGL Optimizer with FLTK you'll need to create a +subclass of <TT>Fl_Gl_Widget</TT> that includes several state +variables: + +<UL><PRE> +class OptimizerWindow : public Fl_Gl_Window { + csContext *context_; // Initialized to 0 and set by draw()... + csDrawAction *draw_action_; // Draw action... + csGroup *scene_; // Scene to draw... + csCamara *camera_; // Viewport for scene... + + void draw(); + +public: + OptimizerWindow(int X, int Y, int W, int H, const char *L) + : Fl_Gl_Window(X, Y, W, H, L) { + context_ = (csContext *)0; + draw_action_ = (csDrawAction *)0; + scene_ = (csGroup *)0; + camera_ = (csCamera *)0; + } + + void scene(csGroup *g) { scene_ = g; redraw(); } + + void camera(csCamera *c) { + camera_ = c; + if (context_) { + draw_action_->setCamera(camera_); + camera_->draw(draw_action_); + redraw(); + } + } +}; +</PRE></UL> + +<H4>The camera() Method</H4> + +<P>The <TT>camera()</TT> method sets the camera (projection and +viewpoint) to use when drawing the scene. The scene is redrawn after +this call. + +<H4>The draw() Method</H4> + +<P>The <TT>draw()</TT> method performs the needed initialization and does +the actual drawing: + +<UL><PRE> +void OptimizerWindow::draw() { + if (!context_) { + // This is the first time we've been asked to draw; create the + // Optimizer context for the scene... + +#ifdef WIN32 + context_ = new csContext((HDC)fl_getHDC()); + context_->ref(); + context_->makeCurrent((HDC)fl_getHDC()); +#else + context_ = new csContext(fl_display, fl_visual); + context_->ref(); + context_->makeCurrent(fl_display, fl_window); +#endif // WIN32 + + ... perform other context setup as desired ... + + // Then create the draw action to handle drawing things... + + draw_action_ = new csDrawAction; + if (camera_) { + draw_action_->setCamera(camera_); + camera_->draw(draw_action_); + } + } else { +#ifdef WIN32 + context_->makeCurrent((HDC)fl_getHDC()); +#else + context_->makeCurrent(fl_display, fl_window); +#endif // WIN32 + } + + if (!valid()) { + // Update the viewport for this context... + context_->setViewport(0, 0, w(), h()); + } + + // Clear the window... + context_->clear(csContext::COLOR_CLEAR | csContext::DEPTH_CLEAR, + 0.0f, // Red + 0.0f, // Green + 0.0f, // Blue + 1.0f); // Alpha + + // Then draw the scene (if any)... + if (scene_) + draw_action_->apply(scene_); +} +</PRE></UL> + +<H4>The scene() Method</H4> + +<P>The <TT>scene()</TT> method sets the scene to be drawn. The scene is +a collection of 3D objects in a <TT>csGroup</TT>. The scene is redrawn +after this call. + +*/ diff --git a/documentation/osissues.dox b/documentation/osissues.dox new file mode 100644 index 000000000..43c13a38c --- /dev/null +++ b/documentation/osissues.dox @@ -0,0 +1,740 @@ +/** + + \page osissues F - Operating System Issues + +<P>This appendix describes the operating system specific interfaces in FLTK. + +<H2>Accessing the OS Interfaces</H2> + +<P>All programs that need to access the operating system +specific interfaces must include the following header file: + +<UL><PRE> +#include <FL/x.H> +</PRE></UL> + +<P>Despite the name, this header file will define the +appropriate interface for your environment. The pages that +follow describe the functionality that is provided for each +operating system. + +<CENTER><TABLE WIDTH="90%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>WARNING:</B> + + <P>The interfaces provided by this header file may + change radically in new FLTK releases. Use them only + when an existing generic FLTK interface is not + sufficient.</P> + + </TD> +</TR> +</TABLE></CENTER> + +<H2>The UNIX (X11) Interface</H2> + +<P>The UNIX interface provides access to the X Window System +state information and data structures. + +<H3>Handling Other X Events</H3> + +<H4><A name="add_handler">void Fl::add_handler(int (*f)(int))</A></H4> + +<P>Installs a function to parse unrecognized events. If FLTK +cannot figure out what to do with an event, it calls each of +these functions (most recent first) until one of them returns +non-zero. If none of them returns non-zero then the event is +ignored. + +<P>FLTK calls this for any X events it does not recognize, or X +events with a window ID that FLTK does not recognize. You can +look at the X event in the <A +href="#fl_xevent"><TT>fl_xevent</TT></A> variable.</P> + +<P>The argument is the FLTK event type that was not handled, or +zero for unrecognized X events. These handlers are also called +for global shortcuts and some other events that the widget they +were passed to did not handle, for example +<TT>FL_SHORTCUT</TT>.</P> + +<H4><A name="fl_xevent">extern XEvent *fl_xvent</A></H4> + +<P>This variable contains the most recent X event. + +<H4><A name="fl_event_time">extern ulong fl_event_time</A></H4> + +<P>This variable contains the time stamp from the most recent X +event that reported it; not all events do. Many X calls like cut +and paste need this value. + +<H4><A name="fl_xid">Window fl_xid(const Fl_Window *)</A></H4> + +<P>Returns the XID for a window, or zero if not <TT>shown()</TT>. + +<H4><A name="fl_find">Fl_Window *fl_find(ulong xid)</A></H4> + +<P>Returns the <TT>Fl_Window</TT> that corresponds to the given +XID, or <TT>NULL</TT> if not found. This function uses a cache +so it is slightly faster than iterating through the windows +yourself.</P> + +<H4><A name="fl_handle">int fl_handle(const XEvent &)</A></H4> + +<P>This call allows you to supply the X events to FLTK, which +may allow FLTK to cooperate with another toolkit or library. The +return value is non-zero if FLTK understood the event. If the +window does not belong to FLTK and the <TT>add_handler()</TT> +functions all return 0, this function will return false. + +<P>Besides feeding events your code should call <A +href="Fl.html#Fl.flush"><TT>Fl::flush()</TT></A> +periodically so that FLTK redraws its windows.</P> + +<P>This function will call the callback functions. It will not +return until they complete. In particular, if a callback pops up +a modal window by calling <A +href="functions.html#fl_ask"><TT>fl_ask()</TT></A>, for +instance, it will not return until the modal function +returns.</P> + +<H3>Drawing using Xlib</H3> + +<P>The following global variables are set before <A +HREF="subclassing.html#draw"><TT>Fl_Widget::draw()</TT></A> is +called, or by <A +href="Fl_Window.html#Fl_Window.make_current"><TT>Fl_Window::make_current()</TT></A>: + +<UL><PRE> +extern Display *fl_display; +extern Window fl_window; +extern GC fl_gc; +extern int fl_screen; +extern XVisualInfo *fl_visual; +extern Colormap fl_colormap; +</PRE></UL> + +<P>You must use them to produce Xlib calls. Don't attempt to change +them. A typical X drawing call is written like this: + +<UL><PRE> +XDrawSomething(fl_display, fl_window, fl_gc, ...); +</PRE></UL> + +<P>Other information such as the position or size of the X +window can be found by looking at <A +href="Fl_Window.html#Fl_Window.make_current"><TT>Fl_Window::current()</TT></A>, +which returns a pointer to the <TT>Fl_Window</TT> being drawn. + +<H4><A name="fl_xpixel">unsigned long fl_xpixel(Fl_Color i)<BR> +unsigned long fl_xpixel(uchar r, uchar g, uchar b)</A></H4> + +<P>Returns the X pixel number used to draw the given FLTK color +index or RGB color. This is the X pixel that <A +href="drawing.html#fl_color"><TT>fl_color()</TT></A> would use. + +<H4><A name="fl_parse_color">int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b)</A></H4> + +<P>Convert a name into the red, green, and blue values of a color +by parsing the X11 color names. On other systems, <tt>fl_parse_color</tt> +can only convert names in hexadecimal encoding, for example <tt>#ff8083</tt>. + +<H4><A name="fl_xfont">extern XFontStruct *fl_xfont</A></H4> + +<P>Points to the font selected by the most recent <A +href="drawing.html#fl_font"><TT>fl_font()</TT></A>. This is not +necessarily the current font of <TT>fl_gc</TT>, which is not set +until <A href="drawing.html#text"><TT>fl_draw()</TT></A> is +called. If FLTK was compiled with Xft support, <TT>fl_xfont</TT> +will usually be 0 and <TT>fl_xftfont</TT> will contain a pointer +to the XftFont structure instead. + +<H4><A name="fl_xftfont">extern void *fl_xftfont</A></H4> + +<P>If FLTK was compiled with Xft support enabled, <tt>fl_xftfont</tt> +Points to the xft font selected by the most recent <A +href="drawing.html#fl_font"><TT>fl_font()</TT></A>. Otherwise +it will be 0. <tt>fl_xftfont</tt> should be cast to +<tt>XftFont*</tt>. + +<H3>Changing the Display, Screen, or X Visual</H3> + +<P>FLTK uses only a single display, screen, X visual, and X +colormap. This greatly simplifies its internal structure and +makes it much smaller and faster. You can change which it uses +by setting global variables <I>before the first +<TT>Fl_Window::show()</TT> is called</I>. You may also want to +call <A href="Fl.html#Fl.visual">Fl::visual()</A>, which is +a portable interface to get a full color and/or double buffered +visual. + +<H4><A name="display">int Fl::display(const char *)</A></H4> + +<P>Set which X display to use. This actually does +<TT>putenv("DISPLAY=...")</TT> so that child programs +will display on the same screen if called with <TT>exec()</TT>. +This must be done before the display is opened. This call is +provided under MacOS and WIN32 but it has no effect. + +<H4><A name="fl_display">extern Display *fl_display</A></H4> + +<P>The open X display. This is needed as an argument to most +Xlib calls. Don't attempt to change it! This is <TT>NULL</TT> +before the display is opened. + +<H4><A name="fl_open_display">void fl_open_display()</A></H4> + +<P>Opens the display. Does nothing if it is already open. This +will make sure <TT>fl_display</TT> is non-zero. You should call +this if you wish to do X calls and there is a chance that your +code will be called before the first <TT>show()</TT> of a +window. + +<P>This may call <TT>Fl::abort()</TT> if there is an error +opening the display.</P> + +<H4><A name="fl_close_display">void fl_close_display()</A></H4> + +<P>This closes the X connection. You do <I>not</I> need to call +this to exit, and in fact it is faster to not do so! It may be +useful to call this if you want your program to continue without +the X connection. You cannot open the display again, and +probably cannot call any FLTK functions. + +<H4><A name="fl_screen">extern int fl_screen</A></H4> + +<P>Which screen number to use. This is set by +<TT>fl_open_display()</TT> to the default screen. You can change +it by setting this to a different value immediately afterwards. +It can also be set by changing the last number in the +<TT>Fl::display()</TT> string to "host:0.#". + +<H4><A name="fl_visual">extern XVisualInfo *fl_visual</A><BR> +<A name="fl_colormap">extern Colormap fl_colormap</A></H4> + +<P>The visual and colormap that FLTK will use for all windows. +These are set by <TT>fl_open_display()</TT> to the default +visual and colormap. You can change them before calling +<TT>show()</TT> on the first window. Typical code for changing +the default visual is: + +<UL><PRE> +Fl::args(argc, argv); // do this first so $DISPLAY is set +fl_open_display(); +fl_visual = find_a_good_visual(fl_display, fl_screen); +if (!fl_visual) Fl::abort("No good visual"); +fl_colormap = make_a_colormap(fl_display, fl_visual->visual, fl_visual->depth); +// it is now ok to show() windows: +window->show(argc, argv); +</PRE></UL> + +<H3>Using a Subclass of Fl_Window for Special X Stuff</H3> + +<P>FLTK can manage an X window on a different screen, visual +and/or colormap, you just can't use FLTK's drawing routines to +draw into it. But you can write your own <TT>draw()</TT> method +that uses Xlib (and/or OpenGL) calls only. + +<P>FLTK can also manage XID's provided by other libraries or +programs, and call those libraries when the window needs to be +redrawn.</P> + +<P>To do this, you need to make a subclass of <A +href="Fl_Window.html#Fl_Window"><TT>Fl_Window</TT></A> and +override some of these virtual functions:</P> + +<H4>virtual void Fl_Window::show()</H4> + +<P>If the window is already <TT>shown()</TT> this must cause it +to be raised, this can usually be done by calling +<TT>Fl_Window::show()</TT>. If not <TT>shown()</TT> your +implementation must call either <TT>Fl_X::set_xid()</TT> or +<TT>Fl_X::make_xid()</TT>. + +<P>An example:</P> + +<UL><PRE> +void MyWindow::show() { + if (shown()) {Fl_Window::show(); return;} // you must do this! + fl_open_display(); // necessary if this is first window + // we only calcualte the necessary visual colormap once: + static XVisualInfo *visual; + static Colormap colormap; + if (!visual) { + visual = figure_out_visual(); + colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), + vis->visual, AllocNone); + } + Fl_X::make_xid(this, visual, colormap); +} +</PRE></UL> + +<H4>Fl_X *Fl_X::set_xid(Fl_Window *, Window xid)</H4> + +<P>Allocate a hidden structure called an <TT>Fl_X</TT>, put the +XID into it, and set a pointer to it from the +<TT>Fl_Window</TT>. This causes <TT>Fl_Window::shown()</TT> to +return true. + +<H4>void Fl_X::make_xid(Fl_Window *, XVisualInfo *= fl_visual, +Colormap = fl_colormap)</H4> + +<P>This static method does the most onerous parts of creating an +X window, including setting the label, resize limitations, etc. +It then does <TT>Fl_X::set_xid()</TT> with this new window and +maps the window. + +<H4>virtual void Fl_Window::flush()</H4> + +<P>This virtual function is called by <TT>Fl::flush()</TT> to +update the window. For FLTK's own windows it does this by +setting the global variables <TT>fl_window</TT> and +<TT>fl_gc</TT> and then calling the <TT>draw()</TT> method. For +your own windows you might just want to put all the drawing code +in here. + +<P>The X region that is a combination of all <TT>damage()</TT> +calls done so far is in <TT>Fl_X::i(this)->region</TT>. If +<TT>NULL</TT> then you should redraw the entire window. The +undocumented function <TT>fl_clip_region(XRegion)</TT> will +initialize the FLTK clip stack with a region or <TT>NULL</TT> +for no clipping. You must set region to <TT>NULL</TT> afterwards +as <TT>fl_clip_region()</TT> will own and delete it when +done.</P> + +<P>If <TT>damage() & FL_DAMAGE_EXPOSE</TT> then only X +expose events have happened. This may be useful if you have an +undamaged image (such as a backing buffer) around.</P> + +<P>Here is a sample where an undamaged image is kept somewhere:</P> + +<UL><PRE> +void MyWindow::flush() { + fl_clip_region(Fl_X::i(this)->region); + Fl_X::i(this)->region = 0; + if (damage() != 2) {... draw things into backing store ...} + ... copy backing store to window ... +} +</PRE></UL> + +<H4>virtual void Fl_Window::hide()</H4> + +<P>Destroy the window server copy of the window. Usually you +will destroy contexts, pixmaps, or other resources used by the +window, and then call <TT>Fl_Window::hide()</TT> to get rid of +the main window identified by <TT>xid()</TT>. If you override +this, you must also override the destructor as shown: + +<UL><PRE> +void MyWindow::hide() { + if (mypixmap) { + XFreePixmap(fl_display,mypixmap); + mypixmap = 0; + } + Fl_Window::hide(); // you must call this +} +</PRE></UL> + +<H4>virtual void Fl_Window::~Fl_Window()</H4> + +<P>Because of the way C++ works, if you override <TT>hide()</TT> +you <I>must</I> override the destructor as well (otherwise only +the base class <TT>hide()</TT> is called): + +<UL><PRE> +MyWindow::~MyWindow() { + hide(); +} +</PRE></UL> + +<H3>Setting the Icon of a Window</H3> + +<P>FLTK currently supports setting a window's icon <b>before</b> it +is shown using the <TT>Fl_Window::icon()</TT> method. + +<H4>void Fl_Window::icon(char *)</H4> + +<P>Sets the icon for the window to the passed pointer. You will +need to cast the icon <TT>Pixmap</TT> to a <TT>char *</TT> when +calling this method. To set a monochrome icon using a bitmap compiled +with your application use: + +<UL><PRE> +#include "icon.xbm" + +fl_open_display(); // needed if display has not been previously opened + +Pixmap p = XCreateBitmapFromData(fl_display, DefaultRootWindow(fl_display), + icon_bits, icon_width, icon_height); + +window->icon((char *)p); +</PRE></UL> + +<P>To use a multi-colored icon, the XPM format and library +should be used as follows: + +<UL><PRE> +#include <X11/xpm.h> +#include "icon.xpm" + +fl_open_display(); // needed if display has not been previously opened + +Pixmap p, mask; + +XpmCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display), + icon_xpm, &p, &mask, NULL); + +window->icon((char *)p); +</PRE></UL> + +<p>When using the Xpm library, be sure to include it in the list +of libraries that are used to link the application (usually +"-lXpm").</p> + +<CENTER><TABLE WIDTH="90%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>NOTE:</B> + + <P>You must call <A + HREF="Fl_Window.html#Fl_Window.show"><TT>Fl_Window::show(argc, + argv)</TT></A> for the icon to be used. The + <TT>Fl_Window::show()</TT> method does not bind the icon + to the window. + + </TD> +</TR> +</TABLE></CENTER> + +<H3>X Resources</H3> + +<P>When the <A +HREF="Fl_Window.html#Fl_Window.show"><TT>Fl_Window::show(argc, +argv)</TT></A> method is called, FLTK looks for the following X +resources: + +<UL> + + <LI><TT>background</TT> - The default background color + for widgets (color). + + <LI><TT>dndTextOps</TT> - The default setting for + drag and drop text operations (boolean). + + <LI><TT>foreground</TT> - The default foreground (label) + color for widgets (color). + + <LI><TT>scheme</TT> - The default scheme to use + (string). + + <LI><TT>selectBackground</TT> - The default selection + color for menus, etc. (color). + + <LI><TT>Text.background</TT> - The default background + color for text fields (color). + + <LI><TT>tooltips</TT> - The default setting for + tooltips (boolean). + + <LI><TT>visibleFocus</TT> - The default setting for + visible keyboard focus on non-text widgets (boolean). + +</UL> + +<P>Resources associated with the first window's <A +HREF="Fl_Window.html#Fl_Window.xclass"><TT>Fl_Window::xclass()</TT></A> +string are queried first, or if no class has been specified then +the class "fltk" is used (e.g. <TT>fltk.background</TT>). If no +match is found, a global search is done (e.g. +<TT>*background</TT>). + +<H2>The Windows (WIN32) Interface</H2> + +<P>The Windows interface provides access to the WIN32 GDI +state information and data structures. + +<H3>Handling Other WIN32 Messages</H3> + +<P>By default a single WNDCLASSEX called "FLTK" is +created. All <TT>Fl_Window</TT>'s are of this class unless you +use <TT>Fl_Window::xclass()</TT>. The window class is created +the first time <TT>Fl_Window::show()</TT> is called. + +<P>You can probably combine FLTK with other libraries that make +their own WIN32 window classes. The easiest way is to call +<TT>Fl::wait()</TT>, as it will call <TT>DispatchMessage</TT> +for all messages to the other windows. If necessary you can let +the other library take over as long as it calls +<TT>DispatchMessage()</TT>, but you will have to arrange for the +function <TT>Fl::flush()</TT> to be called regularly so that +widgets are updated, timeouts are handled, and the idle +functions are called.</P> + +<H4><A name="fl_msg">extern MSG fl_msg</A></H4> + +<P>This variable contains the most recent message read by +<TT>GetMessage</TT>, which is called by <A +href="Fl.html#Fl.wait"><TT>Fl::wait()</TT></A>. This may not be the +most recent message sent to an FLTK window, because silly WIN32 +calls the handle procedures directly for some events (sigh). + +<H4><A name="WIN32.add_handler">void Fl::add_handler(int (*f)(int))</A></H4> + +<P>Installs a function to parse unrecognized messages sent to +FLTK windows. If FLTK cannot figure out what to do with a +message, it calls each of these functions (most recent first) +until one of them returns non-zero. The argument passed to the +functions is the FLTK event that was not handled or zero for +unknown messages. If all the handlers return zero then FLTK +calls <TT>DefWindowProc()</TT>. + +<H4><A name="WIN32.fl_xid">HWND fl_xid(const Fl_Window *)</A></H4> + +<P>Returns the window handle for a <TT>Fl_Window</TT>, or zero +if not <TT>shown()</TT>. + +<H4><A name="WIN32.fl_find">Fl_Window *fl_find(HWND xid)</A></H4> + +<P>Returns the <TT>Fl_Window</TT> that corresponds to the given +window handle, or <TT>NULL</TT> if not found. This function uses +a cache so it is slightly faster than iterating through the +windows yourself. + +<H3><A name="WIN32.gdi">Drawing Things Using the WIN32 GDI</A></H3> + +<P>When the virtual function <A +HREF="subclassing.html#draw"><TT>Fl_Widget::draw()</TT></A> is +called, FLTK stores all the silly extra arguments you need to +make a proper GDI call in some global variables: + +<UL><PRE> +extern HINSTANCE fl_display; +extern HWND fl_window; +extern HDC fl_gc; +COLORREF fl_RGB(); +HPEN fl_pen(); +HBRUSH fl_brush(); +</PRE></UL> + +<P>These global variables are set before <TT>draw()</TT> is +called, or by <A +href="Fl_Window.html#Fl_Window.make_current"><TT>Fl_Window::make_current()</TT></A>. +You can refer to them when needed to produce GDI calls, but don't +attempt to change them. The functions return GDI objects for +the current color set by <TT>fl_color()</TT> and are created as +needed and cached. A typical GDI drawing call is written like +this: + +<UL><PRE> +DrawSomething(fl_gc, ..., fl_brush()); +</PRE></UL> + +<P>It may also be useful to refer to <A +href="Fl_Window.html#Fl_Window.make_current"><TT>Fl_Window::current()</TT></A> +to get the window's size or position. + +<H3>Setting the Icon of a Window</H3> + +<P>FLTK currently supports setting a window's icon *before* it +is shown using the <TT>Fl_Window::icon()</TT> method. + +<H4>void Fl_Window::icon(char *)</H4> + +<P>Sets the icon for the window to the passed pointer. You will +need to cast the <TT>HICON</TT> handle to a <TT>char *</TT> when +calling this method. To set the icon using an icon resource +compiled with your application use: + +<UL><PRE> +window->icon((char *)LoadIcon(fl_display, MAKEINTRESOURCE(IDI_ICON))); +</PRE></UL> + +<P>You can also use the <TT>LoadImage()</TT> and related +functions to load specific resolutions or create the icon from +bitmap data. + +<CENTER><TABLE WIDTH="90%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>NOTE:</B> + + <P>You must call <A + HREF="Fl_Window.html#Fl_Window.show"><TT>Fl_Window::show(argc, + argv)</TT></A> for the icon to be used. The + <TT>Fl_Window::show()</TT> method does not bind the icon + to the window. + + </TD> +</TR> +</TABLE></CENTER> + +<H3>How to Not Get a MSDOS Console Window</H3> + +<P>WIN32 has a really stupid mode switch stored in the +executables that controls whether or not to make a console +window. + +<P>To always get a console window you simply create a console +application (the "/SUBSYSTEM:CONSOLE" option for the +linker). For a GUI-only application create a WIN32 application +(the "/SUBSYSTEM:WINDOWS" option for the linker).</P> + +<P>FLTK includes a <TT>WinMain()</TT> function that calls the +ANSI standard <TT>main()</TT> entry point for you. <I>This +function creates a console window when you use the debug version +of the library.</I></P> + +<P>WIN32 applications without a console cannot write to +<TT>stdout</TT> or <TT>stderr</TT>, even if they are run from a +console window. Any output is silently thrown away. +Additionally, WIN32 applications are run in the background by +the console, although you can use "start /wait program" to run +them in the foreground.</P> + +<H3>Known WIN32 Bugs and Problems</H3> + +<P>The following is a list of known bugs and problems in the WIN32 +version of FLTK: + +<UL> + + <LI>If a program is deactivated, <TT>Fl::wait()</TT> + does not return until it is activated again, even though + many events are delivered to the program. This can cause + idle background processes to stop unexpectedly. This + also happens while the user is dragging or resizing + windows or otherwise holding the mouse down. We were + forced to remove most of the efficiency FLTK uses for + redrawing in order to get windows to update while being + moved. This is a design error in WIN32 and probably + impossible to get around.</LI> + + <LI><TT>Fl_Gl_Window::can_do_overlay()</TT> returns true + until the first time it attempts to draw an overlay, and + then correctly returns whether or not there is overlay + hardware.</LI> + + <LI><TT>SetCapture</TT> (used by <TT>Fl::grab()</TT>) + doesn't work, and the main window title bar turns gray + while menus are popped up.</LI> + + <LI>Compilation with <TT>gcc 3.4.4</TT> and <TT>-Os</TT> exposes an + optimisation bug in gcc. The symptom is that when drawing + filled circles only the perimeter is drawn. This can for instance + be seen in the symbols demo. Other optimisation options such + as -O2 and -O3 seem to work OK. More details can be found + in STR#1656 </LI> +</UL> + +<H2>The MacOS Interface</h2> + +<P>FLTK supports MacOS X using the Apple Carbon library. Older +versions of MacOS are <I>not</I> supported. + +<H4>Control, Option, and Command Modifier Keys</H4> + +<P>FLTK maps the Mac 'control' key to <TT>FL_CTRL</TT>, the +'option' key to <TT>FL_ALT</TT> and the 'Apple' key to +<TT>FL_META</TT>. Keyboard events return the key name in +<TT>Fl::event_key()</TT> and the keystroke translation in +<TT>Fl::event_text()</TT>. For example, typing Option-Y on a Mac +keyboard will set <TT>FL_ALT</TT> in <TT>Fl::event_state()</TT>, +set <TT>Fl::event_key()</TT> to 'y' and return the Yen symbol in +<TT>Fl::event_text()</TT>. + +<H4>WindowRef fl_xid(const Fl_Window *)</H4> + +<P>Returns the window reference for an <tt>Fl_Window</tt>, or +<TT>NULL</TT> if the window has not been shown. + +<h4>Fl_Window *fl_find(WindowRef xid)</h4> + +<P>Returns the <tt>Fl_Window</tt> that corresponds to the give +window handle, or <TT>NULL</TT> if not found. FLTK windows that +are children of top-level windows share the WindowRef of the +top-level window. + +<h3>Apple "Quit" Event</h3> + +<P>When the user press Cmd-Q or requests a termination of the +application, OS X will send a "Quit" Apple Event. FLTK handles +this event by sending an <tt>FL_CLOSE</tt> event to all open +windows. If all windows close, the application will terminate. + +<h3>Apple "Open" Event</h3> + +Whenever the user drops a file onto an application icon, OS X +generates an Apple Event of the type "Open". You can have FLTK +notify you of an Open event by setting the <tt>fl_open_callback</tt>. + +<h4><a name=fl_open_callback>void fl_open_callback(void (*cb)(const char *))</a></h4> + +<tt>cb</tt> will be called with a single iUnix-style file name and path. +If multiple files were dropped, <tt>fl_open_callback</tt> will be called +multiple times. + +<h3>Drawing Things Using QuickDraw</h3> + +<P>When the virtual function <tt>Fl_Widget::draw()</tt> is +called, FLTK has prepared the Window and CGrafPort for drawing. +Clipping and offsets are prepared to allow correct subwindow +drawing. + +<h3>Drawing Things Using Quartz</h3> + +<P>If the FLTK library was compiled using the configuration +flag <tt>--enable-quartz</tt>, all code inside <tt>Fl_Widget::draw()</tt> +is expected to call Quartz drawing functions instead of +QuickDraw. The Quartz coordinate system is flipped to match +FLTK's coordinate system. The origin for all drawing is in the top +left corner of the enclosing <tt>Fl_Window</tt>. + +<h3>Fl_Double_Window</h3> + +<P>OS X double-buffers all windows automatically. On OS X, +<tt>Fl_Window</tt> and <tt>Fl_Double_Window</tt> are handled +internally in the same way. + +<h3>Mac File System Specifics</h3> + +<h4>Resource Forks</h4> + +<P>FLTK does not access the resource fork of an application. +However, a minimal resource fork must be created for OS X +applications + +<CENTER><TABLE WIDTH="80%" BORDER="1" BGCOLOR="#cccccc" CELLPADDING="5"> +<TR><TD><B>Caution:</B> + +<P>When using UNIX commands to copy or move executables, OS X +will NOT copy any resource forks! For copying and moving use +CpMac and MvMac respectively. For creating a tar archive, all +executables need to be stripped from their Resource Fork before +packing, e.g. "DeRez fluid > fluid.r". After unpacking the +Resource Fork needs to be reattached, e.g. "Rez fluid.r -o +fluid". +</TD></TR></TABLE></CENTER> + +<P>It is advisable to use the Finder for moving and copying and +Mac archiving tools like Sit for distribution as they will +handle the Resource Fork correctly. + +<h4>Mac File Paths</h4> + +<P>FLTK uses UNIX-style filenames and paths. + +<H3>Known MacOS Bugs and Problems</H3> + +<P>The following is a list of known bugs and problems in the +MacOS version of FLTK: + +<UL> + + <LI>Line styles are not well supported. This is due to + limitations in the QuickDraw interface.</LI> + + <li>Nested subwindows are not supported, i.e. you can + have a <tt>Fl_Window</tt> widget inside a + <tt>Fl_Window</tt>, but not a <tt>Fl_Window</tt> inside a + <tt>Fl_Window</tt> inside a <tt>Fl_Window</tt>.</li> + +</UL> + +*/ diff --git a/documentation/preface.dox b/documentation/preface.dox index 78fca2128..2844d5d66 100644 --- a/documentation/preface.dox +++ b/documentation/preface.dox @@ -40,7 +40,7 @@ HREF="license.html">Appendix A</A>.</B> <LI><A HREF="fluid.html#FLUID">Chapter 9 - Programming With FLUID</A></LI> - <LI><A HREF="widgets.html#widgets">Appendix A - Class Reference</A></LI> + <LI><A HREF="classes.html">Appendix A - Class Reference</A></LI> <LI><A HREF="functions.html#functions">Appendix B - Function Reference</A></LI> diff --git a/documentation/subclassing.dox b/documentation/subclassing.dox new file mode 100644 index 000000000..cb4763be2 --- /dev/null +++ b/documentation/subclassing.dox @@ -0,0 +1,431 @@ +/** + + \page subclassing 7 - Adding and Extending Widgets + +<P>This chapter describes how to add your own widgets or extend existing +widgets in FLTK. +<H2>Subclassing</H2> + New widgets are created by <I>subclassing</I> an existing FLTK widget, +typically <TT>Fl_Widget</TT> for controls and <TT>Fl_Group</TT> for +composite widgets. +<P>A control widget typically interacts with the user to receive and/or +display a value of some sort. </P> +<P>A composite widget widget holds a list of child widgets and handles moving, +sizing, showing, or hiding them as needed. <TT>Fl_Group</TT> is the +main composite widget widget class in FLTK, and all of the other composite widgets (<TT> +Fl_Pack</TT>, <TT>Fl_Scroll</TT>, <TT>Fl_Tabs</TT>, <TT>Fl_Tile</TT>, +and <TT>Fl_Window</TT>) are subclasses of it. </P> +<P>You can also subclass other existing widgets to provide a different +look or user-interface. For example, the button widgets are all +subclasses of <TT>Fl_Button</TT> since they all interact with the user +via a mouse button click. The only difference is the code that draws +the face of the button. </P> +<H2>Making a Subclass of Fl_Widget</H2> + Your subclasses can directly descend from <TT>Fl_Widget</TT> or any +subclass of <TT>Fl_Widget</TT>. <TT>Fl_Widget</TT> has only four +virtual methods, and overriding some or all of these may be necessary. +<H2>The Constructor</H2> + The constructor should have the following arguments: +<UL><PRE> +MyClass(int x, int y, int w, int h, const char *label = 0); +</PRE></UL> + This will allow the class to be used in <A href="fluid.html#FLUID">FLUID</A> + without problems. +<P>The constructor must call the constructor for the base class and +pass the same arguments: </P> +<UL><PRE> +MyClass::MyClass(int x, int y, int w, int h, const char *label) +: Fl_Widget(x, y, w, h, label) { +// do initialization stuff... +} +</PRE></UL> +<TT>Fl_Widget</TT>'s protected constructor sets <TT>x()</TT>, <TT>y()</TT>, +<TT>w()</TT>, <TT>h()</TT>, and <TT>label()</TT> to the passed values +and initializes the other instance variables to: +<UL><PRE> +type(0); +box(FL_NO_BOX); +color(FL_BACKGROUND_COLOR); +selection_color(FL_BACKGROUND_COLOR); +labeltype(FL_NORMAL_LABEL); +labelstyle(FL_NORMAL_STYLE); +labelsize(FL_NORMAL_SIZE); +labelcolor(FL_FOREGROUND_COLOR); +align(FL_ALIGN_CENTER); +callback(default_callback,0); +flags(ACTIVE|VISIBLE); +image(0); +deimage(0); +</PRE></UL> +<H2>Protected Methods of Fl_Widget</H2> + The following methods are provided for subclasses to use: +<UL> +<LI><A href=#clear_visible><TT>Fl_Widget::clear_visible</TT></A></LI> +<LI><A href=#damage><TT>Fl_Widget::damage</TT></A></LI> +<LI><A href=#draw_box><TT>Fl_Widget::draw_box</TT></A></LI> +<LI><A href=#draw_focus><TT>Fl_Widget::draw_focus</TT></A></LI> +<LI><A href=#draw_label><TT>Fl_Widget::draw_label</TT></A></LI> +<LI><A href=#set_flag><TT>Fl_Widget::set_flag</TT></A></LI> +<LI><A href=#set_visible><TT>Fl_Widget::set_visible</TT></A></LI> +<LI><A href=#test_shortcut><TT>Fl_Widget::test_shortcut</TT></A></LI> +<LI><A href=#type><TT>Fl_Widget::type</TT></A></LI> +</UL> +<H4><A name=damage>void Fl_Widget::damage(uchar mask) +<BR> void Fl_Widget::damage(uchar mask, int x, int y, int w, int h) +<BR> uchar Fl_Widget::damage()</A></H4> +The first form indicates that a partial update of the object is +needed. The bits in mask are OR'd into <TT>damage()</TT>. Your <TT> +draw()</TT> routine can examine these bits to limit what it is +drawing. The public method <TT>Fl_Widget::redraw()</TT> simply does +<TT> Fl_Widget::damage(FL_DAMAGE_ALL)</TT>, but the implementation of +your widget can call the private <TT>damage(n)</TT>. +<P>The second form indicates that a region is damaged. If only these +calls are done in a window (no calls to <TT>damage(n)</TT>) then FLTK +will clip to the union of all these calls before drawing anything. + This can greatly speed up incremental displays. The mask bits are +OR'd into <TT>damage()</TT> unless this is a <TT>Fl_Window</TT> widget. </P> +<P>The third form returns the bitwise-OR of all <TT>damage(n)</TT> +calls done since the last <TT>draw()</TT>.</P> +<P><I>When redrawing your widgets you should look at the damage bits to +see what parts of your widget need redrawing.</I> The <tt>handle()</tt> +method can then set individual damage bits to limit the amount of drawing +that needs to be done: +<UL><PRE> +MyClass::handle(int event) { + ... + if (change_to_part1) damage(1); + if (change_to_part2) damage(2); + if (change_to_part3) damage(4); +} + +MyClass::draw() { + if (damage() & FL_DAMAGE_ALL) { + ... draw frame/box and other static stuff ... + } + + if (damage() & (FL_DAMAGE_ALL | 1)) draw_part1(); + if (damage() & (FL_DAMAGE_ALL | 2)) draw_part2(); + if (damage() & (FL_DAMAGE_ALL | 4)) draw_part3(); +} +</PRE></UL> +<H4><A name=draw_box>void Fl_Widget::draw_box() const +<BR></A>void Fl_Widget::draw_box(Fl_Boxtype b, ulong c) const</H4> + The first form draws this widget's <TT>box()</TT>, using the +dimensions of the widget. The second form uses <TT>b</TT> as the box +type and <TT>c</TT> as the color for the box. + +<H4><A name="draw_focus">void Fl_Widget::draw_focus() const +<BR>void Fl_Widget::draw_focus(Fl_Boxtype b, int x, int y, int w, int h) const</A></H4> + +<P>Draws a focus box inside the widgets bounding box. The second +form allows you to specify a different bounding box. + +<H4><A name=draw_label>void Fl_Widget::draw_label() const +<BR> void Fl_Widget::draw_label(int x, int y, int w, int h) const +<BR> void Fl_Widget::draw_label(int x, int y, int w, int h, Fl_Align +align) const</A></H4> + This is the usual function for a <TT>draw()</TT> method to call to +draw the widget's label. It does not draw the label if it is supposed +to be outside the box (on the assumption that the enclosing group will +draw those labels). +<P>The second form uses the passed bounding box instead of the widget's +bounding box. This is useful so "centered" labels are aligned with some +feature, like a moving slider. </P> +<P>The third form draws the label anywhere. It acts as though <TT> +FL_ALIGN_INSIDE</TT> has been forced on so the label will appear inside +the passed bounding box. This is designed for parent groups to draw +labels with. </P> +<H4><A name=set_flag>void Fl_Widget::set_flag(SHORTCUT_LABEL)</A></H4> +Modifies <TT>draw_label()</TT> so that '&' characters cause an underscore +to be printed under the next letter. +<H4><A name=set_visible>void Fl_Widget::set_visible()</A> +<BR><A name=clear_visible>void Fl_Widget::clear_visible()</A></H4> + Fast inline versions of <TT>Fl_Widget::hide()</TT> and <TT> +Fl_Widget::show()</TT>. These do not send the <TT>FL_HIDE</TT> and <TT> +FL_SHOW</TT> events to the widget. +<H4><A name=test_shortcut>int Fl_Widget::test_shortcut() const +<BR> static int Fl_Widget::test_shortcut(const char *s)</A></H4> + The first version tests <TT>Fl_Widget::label()</TT> against the +current event (which should be a <TT>FL_SHORTCUT</TT> event). If the +label contains a '&' character and the character after it matches the key +press, this returns true. This returns false if the <TT>SHORTCUT_LABEL</TT> +flag is off, if the label is <TT>NULL</TT> or does not have a +'&' character in it, or if the keypress does not match the character. +<P>The second version lets you do this test against an arbitrary +string. </P> +<H4><A name=type>uchar Fl_Widget::type() const +<BR> void Fl_Widget::type(uchar t)</A></H4> + The property <TT>Fl_Widget::type()</TT> can return an arbitrary 8-bit +identifier, and can be set with the protected method <TT>type(uchar t)</TT> +. This value had to be provided for Forms compatibility, but you can +use it for any purpose you want. Try to keep the value less than 100 +to not interfere with reserved values. +<P>FLTK does not use RTTI (Run Time Typing Infomation), to enhance +portability. But this may change in the near future if RTTI becomes +standard everywhere. </P> +<P>If you don't have RTTI you can use the clumsy FLTK mechanisim, by +having <TT>type()</TT> use a unique value. These unique values must +be greater than the symbol <TT>FL_RESERVED_TYPE</TT> (which is 100). +Look through the header files for <TT>FL_RESERVED_TYPE</TT> to find an +unused number. If you make a subclass of <TT>Fl_Window</TT> +you must use <TT>FL_WINDOW + n</TT> (<TT>n</tt> must be in the +range 1 to 7). </P> +<H2><A NAME="handle">Handling Events</A></H2> + The virtual method <TT>int Fl_Widget::handle(int event)</TT> is called +to handle each event passed to the widget. It can: +<UL> +<LI>Change the state of the widget. </LI> +<LI>Call <A href=Fl_Widget.html#Fl_Widget.redraw><TT>Fl_Widget::redraw()</TT> +</A> if the widget needs to be redisplayed. </LI> +<LI>Call <A href=Fl_Widget.html#Fl_Widget.damage><TT> +Fl_Widget::damage(n)</TT></A> if the widget needs a partial-update +(assuming you provide support for this in your <A HREF="#draw"><TT>Fl_Widget::draw()</TT></A> + method). </LI> +<LI>Call <A href=Fl_Widget.html#Fl_Widget.do_callback><TT> +Fl_Widget::do_callback()</TT></A> if a callback should be generated. </LI> +<LI>Call <TT>Fl_Widget::handle()</TT> on child widgets. </LI> +</UL> + Events are identified by the integer argument. Other information +about the most recent event is stored in static locations and aquired +by calling the <A href=events.html#events><TT>Fl::event_*()</TT></A> + functions. This information remains valid until another event is +handled. +<P>Here is a sample <TT>handle()</TT> method for a widget that acts as +a pushbutton and also accepts the keystroke 'x' to cause the callback: </P> +<UL><PRE> +int MyClass::handle(int event) { + switch(event) { + case FL_PUSH: + highlight = 1; + redraw(); + return 1; + case FL_DRAG: { + int t = Fl::event_inside(this); + if (t != highlight) { + highlight = t; + redraw(); + } + } + return 1; + case FL_RELEASE: + if (highlight) { + highlight = 0; + redraw(); + do_callback(); + // never do anything after a callback, as the callback + // may delete the widget! + } + return 1; + case FL_SHORTCUT: + if (Fl::event_key() == 'x') { + do_callback(); + return 1; + } + return 0; + default: + return Fl_Widget::handle(event); + } +} +</PRE></UL> + +<P>You must return non-zero if your <TT>handle()</TT> method +uses the event. If you return zero, the parent widget will try +sending the event to another widget. + +<H2><A NAME="draw">Drawing the Widget</A></H2> + +<P>The <TT>draw()</TT> virtual method is called when FLTK wants +you to redraw your widget. It will be called if and only if +<TT>damage()</TT> is non-zero, and <TT>damage()</TT> will be +cleared to zero after it returns. The <TT>draw()</TT> method +should be declared protected so that it can't be called from +non-drawing code. + +<P>The <TT>damage()</TT> value contains the bitwise-OR of all +the <TT>damage(n)</TT> calls to this widget since it was last +drawn. This can be used for minimal update, by only redrawing +the parts whose bits are set. FLTK will turn on the +<TT>FL_DAMAGE_ALL</TT> bit if it thinks the entire widget must +be redrawn, e.g. for an expose event. </P> + +<P>Expose events (and the above <TT>damage(b,x,y,w,h)</TT>) will cause <TT> +draw()</TT> to be called with FLTK's <A href=drawing.html#clipping> +clipping</A> turned on. You can greatly speed up redrawing in some +cases by testing <TT>fl_not_clipped(x,y,w,h)</TT> or <TT>fl_clip_box(...)</TT> and +skipping invisible parts. </P> +<P>Besides the protected methods described above, FLTK provides a large +number of basic drawing functions, which are described <A href=drawing.html#drawing> +below</A>. </P> +<H2>Resizing the Widget</H2> + The <TT>resize(int x, int y, int w, int h)</TT> method is called when +the widget is being resized or moved. The arguments are the new +position, width, and height. <TT>x()</TT>, <TT>y()</TT>, <TT>w()</TT>, +and <TT>h()</TT> still remain the old size. You must call <TT>resize()</TT> + on your base class with the same arguments to get the widget size to +actually change. +<P>This should <I>not</I> call <TT>redraw()</TT>, at least if only the <TT> +x()</TT> and <TT>y()</TT> change. This is because composite widgets like <A href=Fl_Scroll.html#Fl_Scroll> +<TT>Fl_Scroll</TT></A> may have a more efficient way of drawing the new +position. </P> +<H2>Making a Composite Widget</H2> + A "composite" widget contains one or more "child" widgets. + To make a composite widget you should subclass <A href=Fl_Group.html#Fl_Group><TT>Fl_Group</TT></A> +. It is possible to make a composite object that is not a subclass of <TT> +Fl_Group</TT>, but you'll have to duplicate the code in <TT>Fl_Group</TT> + anyways. +<P>Instances of the child widgets may be included in the parent: </P> +<UL><PRE> +class MyClass : public Fl_Group { + Fl_Button the_button; + Fl_Slider the_slider; + ... +}; +</PRE></UL> + The constructor has to initialize these instances. They are +automatically <TT>add()</TT>ed to the group, since the <TT>Fl_Group</TT> + constructor does <TT>begin()</TT>. <I>Don't forget to call <TT>end()</TT> + or use the <A href=Fl_End.html#Fl_End><TT>Fl_End</TT></A> pseudo-class:</I> +<UL><PRE> +MyClass::MyClass(int x, int y, int w, int h) : + Fl_Group(x, y, w, h), + the_button(x + 5, y + 5, 100, 20), + the_slider(x, y + 50, w, 20) +{ + ...(you could add dynamically created child widgets here)... + end(); // don't forget to do this! +} +</PRE></UL> + The child widgets need callbacks. These will be called with a pointer +to the children, but the widget itself may be found in the <TT>parent()</TT> + pointer of the child. Usually these callbacks can be static private +methods, with a matching private method: +<UL><PRE> +void MyClass::static_slider_cb(Fl_Widget* v, void *) { // static method + ((MyClass*)(v->parent())->slider_cb(); +} +void MyClass::slider_cb() { // normal method + use(the_slider->value()); +} +</PRE></UL> + If you make the <TT>handle()</TT> method, you can quickly pass all the +events to the children using the <TT>Fl_Group::handle()</TT> method. +You don't need to override <TT>handle()</TT> if your composite widget +does nothing other than pass events to the children: +<UL><PRE> +int MyClass::handle(int event) { + if (Fl_Group::handle(event)) return 1; + ... handle events that children don't want ... +} +</PRE></UL> + +<P>If you override <TT>draw()</TT> you need to draw all the +children. If <TT>redraw()</TT> or <TT>damage()</TT> is called +on a child, <TT>damage(FL_DAMAGE_CHILD)</TT> is done to the +group, so this bit of <TT>damage()</TT> can be used to indicate +that a child needs to be drawn. It is fastest if you avoid +drawing anything else in this case: + +<UL><PRE> +int MyClass::draw() { + Fl_Widget *const*a = array(); + if (damage() == FL_DAMAGE_CHILD) { // only redraw some children + for (int i = children(); i --; a ++) update_child(**a); + } else { // total redraw + ... draw background graphics ... + // now draw all the children atop the background: + for (int i = children_; i --; a ++) { + draw_child(**a); + draw_outside_label(**a); // you may not need to do this + } + } +} +</PRE></UL> +<TT>Fl_Group</TT> provides some protected methods to make drawing +easier: +<UL> +<LI><A href=#draw_child>draw_child</A></LI> +<LI><A href=#draw_outside_label>draw_outside_label</A></LI> +<LI><A href=#update_child>update_child</A></LI> +</UL> +<H4><A name=draw_child>void Fl_Group::draw_child(Fl_Widget&)</A></H4> + This will force the child's <TT>damage()</TT> bits all to one and call <TT> +draw()</TT> on it, then clear the <TT>damage()</TT>. You should call +this on all children if a total redraw of your widget is requested, or +if you draw something (like a background box) that damages the child. + Nothing is done if the child is not <TT>visible()</TT> or if it is +clipped. +<H4><A name=draw_outside_label>void +Fl_Group::draw_outside_label(Fl_Widget&) const</A></H4> + Draw the labels that are <I>not</I> drawn by <A href=#draw_label><TT> +draw_label()</TT></A>. If you want more control over the label +positions you might want to call <TT>child->draw_label(x,y,w,h,a)</TT>. +<H4><A name=update_child>void Fl_Group::update_child(Fl_Widget&)</A></H4> + Draws the child only if its <TT>damage()</TT> is non-zero. You +should call this on all the children if your own damage is equal to +FL_DAMAGE_CHILD. Nothing is done if the child is not <TT>visible()</TT> + or if it is clipped. + +<H2>Cut and Paste Support</H2> +FLTK provides routines to cut and paste 8-bit text (in the future this +may be UTF-8) between applications: +<UL> +<LI><A href="Fl.html#Fl.paste"><TT>Fl::paste</TT></A></LI> +<LI><A href="Fl.html#Fl.selection"><TT>Fl::selection</TT></A></LI> +<LI><A href="Fl.html#Fl.selection_owner"><TT>Fl::selection_owner</TT></A></LI> +</UL> +It may be possible to cut/paste non-text data by using <A href=osissues.html#add_handler> +<TT>Fl::add_handler()</TT></A>. + +<H2>Drag And Drop Support</H2> + +FLTK provides routines to drag and drop 8-bit text between applications: + +<P>Drag'n'drop operations are are initiated by copying data to the +clipboard and calling the function +<A href="Fl.html#Fl.dnd"><TT>Fl::dnd()</TT></A>. + +<P>Drop attempts are handled via <A href="events.html#dnd">events</A>: +<UL> +<LI><TT>FL_DND_ENTER</TT></LI> +<LI><TT>FL_DND_DRAG</TT></LI> +<LI><TT>FL_DND_LEAVE</TT></LI> +<LI><TT>FL_DND_RELEASE</TT></LI> +<LI><TT>FL_PASTE</TT></LI> +</UL> + +<H2>Making a subclass of Fl_Window</H2> + +<P>You may want your widget to be a subclass of +<TT>Fl_Window</TT>, <TT>Fl_Double_Window</TT>, or +<TT>FL_Gl_Window</TT>. This can be useful if your widget wants +to occupy an entire window, and can also be used to take +advantage of system-provided clipping, or to work with a library +that expects a system window ID to indicate where to draw. + +<P>Subclassing <TT>Fl_Window</TT>is almost exactly like +subclassing <TT>Fl_Group</TT>, and in fact you can easily +switch a subclass back and forth. Watch out for the following +differences: </P> + +<OL> + + <LI><TT>Fl_Window</TT> is a subclass of + <TT>Fl_Group</TT> so <I>make sure your constructor calls + <TT>end()</TT></I> unless you actually want children + added to your window.</LI> + + <LI>When handling events and drawing, the upper-left + corner is at 0,0, not <TT>x(),y()</TT> as in other + <TT>Fl_Widget</TT>'s. For instance, to draw a box + around the widget, call <TT>draw_box(0, 0, w(), + h())</TT>, rather than <TT>draw_box(x(), y(), w(), + h())</TT>.</LI> + +</OL> + +<P>You may also want to subclass <TT>Fl_Window</TT> in order to +get access to different visuals or to change other attributes of +the windows. See <A href="osissues.html">"Appendix F - Operating +System Issues"</A> for more information. + +*/ |
