From 8416a4012ecb985d150fad566659cf59ee1dc3aa Mon Sep 17 00:00:00 2001
From: Albrecht Schlosser This chapter teaches you the basics of compiling programs
+that use FLTK. All programs must include the file <FL/Fl.H>.
+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. Listing 1 - "hello.cxx"
+ After including the required header files, the program then creates a
+window. All following widgets will automatically be children of this window. Then we create a box with the "Hello, World!" string in it. FLTK automatically adds
+the new box to window, the current grouping widget. Next, we set the type of box and the size, font, and style of the label: We tell FLTK that we will not add any more widgets to window. Finally, we show the window and enter the FLTK event loop: The resulting program will display the window in Figure 2-1.
+You can quit the program by closing the window or pressing the
+ESCape key. The widgets are created using the C++ new operator. For
+most widgets the arguments to the constructor are: The x and y 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. The width and height 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. label is a pointer to a character string to label
+the widget with or NULL. If not specified the label
+defaults to NULL. 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. 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 myGroup->begin() and
+myGroup->end(). In this example, myGroup
+would be the current group. Newly created groups and their derived widgets implicitly call
+begin() in the constructor, effectively adding all
+subsequently created widgets to itself until end()
+is called. Setting the current group to NULL will stop automatic
+hierarchies. New widgets can now be added manually using
+Fl_Group::add(...) and Fl_Group::insert(...). box->box(FL_UP_BOX) sets the type of box the
+Fl_Box draws, changing it from the default of
+FL_NO_BOX, which means that no box is drawn. In our
+"Hello, World!" example we use FL_UP_BOX,
+which means that a raised button border will be drawn around
+the widget. You can learn more about boxtypes in
+Chapter 3. You could examine the boxtype in by doing
+box->box(). 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". Almost all of the set/get pairs are very fast, short inline
+functions and thus very efficient. However, the "set" methods
+do not call redraw() - you have to call it
+yourself. This greatly reduces code size and execution time. The
+only common exceptions are value() which calls
+redraw() and label() which calls
+redraw_label() if necessary. 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
+labelfont,
+ labelsize,
+and labeltype
+methods. The labelfont method sets the typeface and style
+that is used for the label, which for this example we are using
+FL_BOLD and FL_ITALIC. You can also specify
+typefaces directly. The labelsize method sets
+the height of the font in pixels. The labeltype
+method sets the type of label. FLTK supports normal, embossed,
+and shadowed labels internally, and more types can be added as
+desired. A complete list of all label options can be found in
+Chapter 3. The show() 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. 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. 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. 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. 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. FLTK applications must periodically check
+(Fl::check()) or wait (Fl::wait()) for events
+or use the Fl::run()
+method to enter a standard event processing loop. Calling
+Fl::run() is equivalent to the following code: Fl::run() does not return until all of the windows
+under FLTK control are closed by the user or your program. 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 -I option: The fltk-config script included with FLTK can be
+used to get the options that are required by your compiler: Similarly, when linking your application you will need to tell the
+compiler to use the FLTK library: 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, The libraries are named "fltk.lib", "fltkgl.lib", "fltkforms.lib",
+ and "fltkimages.lib", respectively under Windows.
+ As before, the fltk-config script included with FLTK can be
+used to get the options that are required by your linker: The forms, GL, and images libraries are included with the "--use-foo"
+options, as follows:
+
+ Finally, you can use the fltk-config script to
+compile a single source file as a FLTK program:
+
+ Any of these will create an executable named filename.
+
+ 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. You can build your Microsoft Windows applications as Console or
+WIN32 applications. If you want to use the standard C main()
+function as the entry point, FLTK includes a WinMain()
+function that will call your main() function for you. 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. The Visual C++ 6.0 optimizer seems to be much
+better and can be used with the "optimized for speed" setting. All public symbols in FLTK start with the characters 'F' and 'L': The proper way to include FLTK header files is: Case is significant on many operating systems,
+ and the C standard uses the forward slash (/) to
+ separate directories. Do not use any of the following
+ include lines: This chapter describes many of the widgets that are provided
+with FLTK and covers how to query and set the standard
+attributes. FLTK provides many types of buttons: All of these buttons just need the corresponding
+<FL/Fl_xyz_Button.H> header file. The constructor
+takes the bounding box of the button and optionally a label
+string: Each button has an associated
+type()
+which allows it to behave as a push button, toggle button, or
+radio button: For toggle and radio buttons, the
+value()
+method returns the current button state (0 = off, 1 = on). The
+set() and
+clear()
+methods can be used on toggle buttons to turn a toggle button
+on or off, respectively. Radio buttons can be turned on with
+the
+setonly()
+method; this will also turn off other radio buttons in the same
+group. FLTK provides several text widgets for displaying and receiving text: The Fl_Output and Fl_Multiline_Output
+widgets allow the user to copy text from the output field but
+not change it. The value()
+method is used to get or set the string that is displayed: The string is copied to the widget's own storage when you set
+the value() of the widget. The Fl_Text_Display and Fl_Text_Editor
+widgets use an associated Fl_Text_Buffer class for the
+value, instead of a simple string. Unlike text widgets, valuators keep track of numbers instead of
+strings. FLTK provides the following valuators: The value()
+method gets and sets the current value of the widget. The
+minimum()
+and maximum()
+methods set the range of values that are reported by the
+widget. The Fl_Group 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: The size and position of widgets is usually set when you
+create them. You can access them with the x(),
+y(), w(), and h() methods. You can change the size and position by using the
+position(), resize(), and size()
+methods: If you change a widget's size or position after it is
+displayed you will have to call redraw() on the
+widget's parent. 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 not
+the X or WIN32 colormap, but instead is an internal table with
+fixed contents. There are symbols for naming some of the more common colors: These symbols are the default colors for all FLTK widgets. They are
+explained in more detail in the chapter
+Enumerations RGB colors can be set using the fl_rgb_color()
+function: The widget color is set using the color() method: Similarly, the label color is set using the labelcolor()
+method: The type Fl_Boxtype stored and returned in
+Fl_Widget::box()
+is an enumeration defined in <Enumerations.H>.
+Figure 3-3 shows the standard box types included with FLTK. FL_NO_BOX means nothing is drawn at all, so whatever is
+already on the screen remains. The FL_..._FRAME 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. You can define your own boxtypes by making a small function that draws
+the box and adding it to the table of boxtypes. This interface has changed in FLTK 2.0! The drawing function is passed the bounding box and background color
+for the widget: A simple drawing function might fill a rectangle with the
+given color and then draw a black outline: fl_down 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: fl_frame drawing.
+
+ fl_frame 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: fl_frame drawing.
+
+ fl_box 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: fl_frame.
+
+ The Fl::set_boxtype() method adds or replaces the
+specified box type: The last 4 arguments to Fl::set_boxtype() are the
+offsets for the x, y, width, and height values that should be
+subtracted when drawing the label inside the box. A complete box design contains four box types in this order:
+a filled, neutral box (UP_BOX), a filled, depressed box
+(DOWN_BOX), and the same as outlines only (UP_FRAME
+and DOWN_FRAME). The function
+fl_down(Fl_Boxtype)
+expects the neutral design on a boxtype with a numerical
+value evenly divideable by two.
+fl_frame(Fl_Boxtype)
+expects the UP_BOX design at a value divideable by four. The label(), align(), labelfont(),
+labelsize(), labeltype(), image(), and
+deimage() methods control the labeling of widgets. The label() 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. The @ sign may also be followed by the following optional
+"formatting" characters, in this order: Thus, to show a very large arrow pointing downward you would use the
+label string "@+92->".
+
+ The align() method positions the label. The following
+constants are defined and may be OR'd together as needed: The labeltype() method sets the type of the label. The
+following standard label types are included: The image() and deimage() methods set an image that
+will be displayed with the widget. The deimage() method sets the
+image that is shown when the widget is inactive, while the image()
+method sets the image that is shown when the widget is active. To make an image you use a subclass of
+Fl_Image. 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
+fl_font mechanisim (e.g. FL_ENGRAVED_LABEL) or
+with program-generated letters or symbology. This interface has changed in FLTK 2.0! 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 Fl_Label
+structure containing the label information, the bounding box for
+the label, and the label alignment: The label should be drawn inside this bounding box,
+even if FL_ALIGN_INSIDE is not enabled. The function
+is not called if the label value is NULL. The measure function is called with a pointer to a
+Fl_Label structure and references to the width and
+height: The function should measure the size of the label and set
+w and h to the size it will occupy. The Fl::set_labeltype method creates a label type
+using your draw and measure functions: The label type number n can be any integer value
+starting at the constant FL_FREE_LABELTYPE. Once you
+have added the label type you can use the labeltype()
+method to select your label type. The Fl::set_labeltype method can also be used to overload
+an existing label type such as FL_NORMAL_LABEL. 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. To create a new symbol, you implement a drawing function
+void drawit(Fl_Color c) which typically uses the
+complex drawing functions
+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 fl_add_symbol: name is the name of the symbol without the "@"; scalable
+must be set to 1 if the symbol is generated using scalable vector drawing
+functions. This function draw a named symbol fitting the given rectangle.
+
+ Callbacks are functions that are called when the value of a
+widget changes. A callback function is sent a Fl_Widget
+pointer of the widget that changed and a pointer to data that
+you provide: The callback() method sets the callback function for a
+widget. You can optionally pass a pointer to some data needed for the
+callback: Normally callbacks are performed only when the value of the
+widget changes. You can change this using the
+when()
+method: 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 Fl::delete_widget()
+ method to mark your widget for deletion when it is safe
+ to do so. Hint:
+
+ 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 this pointer is not
+ initialized for class methods. 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
+ callback() method of the widget can be a
+ pointer to the instance of your class. Shortcuts are key sequences that activate widgets such as
+buttons or menu items. The shortcut() method sets the
+shortcut for a widget: The shortcut value is the key event value - the ASCII value
+or one of the special keys like
+FL_Enter -
+combined with any modifiers like Shift,
+Alt, and Control. This chapter covers the drawing functions that are provided with FLTK.
+
+ There are only certain places you can execute drawing code in FLTK.
+Calling these functions at other places will result in undefined
+behavior!
+
+ To use the drawing functions you must first include the
+<FL/fl_draw.H> header file. FLTK provides the
+following types of drawing functions:
+
+ 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.
+
+ The first box drawing function is The The only difference between this function and
+ See also: fl_frame boxtype.
+
+ The The only difference between this function and
+ You can limit all your drawing to a rectangular region by calling
+fl_push_clip, and put the drawings back by using fl_pop_clip.
+This rectangle is measured in pixels and is unaffected by the current
+transformation matrix.
+
+ In addition, the system may provide clipping when updating windows
+which may be more complex than a simple rectangle. Intersect the current clip region with a rectangle and push this new
+region onto the stack. The Pushes an empty clip region on the stack so nothing will be clipped.
+
+ Restore the previous clip region.
+
+ You must call fl_pop_clip() once for every
+ time you call fl_push_clip(). If you return to FLTK
+ with the clip stack not empty unpredictable results
+ occur.
+
+ 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.
+
+ Under X this returns 2 if the rectangle is partially
+ clipped, and 1 if it is entirely inside the clip region.
+
+ Intersect the rectangle x,y,w,h with the current
+clip region and returns the bounding box of the result in
+X,Y,W,H. Returns non-zero if the resulting rectangle is
+different than the original. This can be used to limit the
+necessary drawing to a rectangle. W and H are
+set to zero if the rectangle is completely outside the region.
+
+ 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.
+
+ 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 Fl_Color enumeration type defines the
+standard colors and color cube for the first 256 colors. All of
+these are named with symbols in <FL/Enumerations.H>.
+
+ 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 fl_rgb_color()
+function.
+
+ Sets the color for all subsequent drawing operations.
+
+ For colormapped displays, a color cell will be allocated out
+of fl_colormap the first time you use a color. If the
+colormap fills up then a least-squares algorithm is used to find
+the closest color. Returns the last fl_color() that was set. This can
+be used for state save/restore.
+
+ 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.
+
+ 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.
+
+ Set how to draw lines (the "pen"). If you change this it is your
+responsibility to set it back to the default with
+fl_line_style(0).
+
+ Because of how line styles are implemented on WIN32
+ systems, you must set the line style after
+ setting the drawing color. If you set the color after
+ the line style you will lose the line style settings!
+
+ style 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.
+
+ width 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.
+
+
+
+ dashes 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 NULL pointer or a zero-length
+array results in a solid line. Odd array sizes are not supported and
+result in undefined behavior.
+
+ The dashes array does not work under Windows 95, 98,
+ or Me, since those operating systems do not support
+ complex line styles.
+
+ 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 transformation matrix, so you should only
+call these while the matrix is set to the identity matrix (the
+default).
+
+ Draw a single pixel at the given coordinates.
+
+ Color a rectangle that exactly fills the given bounding box.
+
+ Color a rectangle with "exactly" the passed
+r,g,b color. On screens with less than 24 bits of
+color this is done by drawing a solid-colored block using fl_draw_image() so that
+the correct color shade is produced.
+
+ Draw a 1-pixel border inside this bounding box.
+
+ Draw one or two lines between the given points.
+
+ Outline a 3 or 4-sided polygon with lines.
+
+ Fill a 3 or 4-sided polygon. The polygon must be convex.
+
+ Draw horizontal and vertical lines. A horizontal line is
+drawn first, then a vertical, then a horizontal.
+
+ Draw vertical and horizontal lines. A vertical line is drawn
+first, then a horizontal, then a vertical.
+
+ Draw ellipse sections using integer coordinates. These
+functions match the rather limited circle drawing code provided
+by X and WIN32. The advantage over using fl_arc 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.
+
+ 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, a2
+must be greater or equal to a1. fl_arc() draws a series of lines to approximate the arc.
+Notice that the integer version of fl_arc() has a different
+number of arguments than the fl_arc()
+function described later in this chapter. fl_pie() draws a filled-in pie slice. This slice may
+extend outside the line drawn by fl_arc; to avoid this
+use w - 1 and h - 1. Scroll a rectangle and draw the newly exposed portions. The contents
+of the rectangular area is first shifted by dx and
+dy pixels. The callback is then called for every newly
+exposed rectangular area,
+
+ The complex drawing functions let you draw arbitrary shapes
+with 2-D linear transformations. The functionality matches that
+found in the Adobe® PostScriptTM 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.
+
+ Save and restore the current transformation. The maximum
+depth of the stack is 4.
+
+ Concatenate another transformation onto the current one. The rotation
+angle is in degrees (not radians) and is counter-clockwise.
+
+ 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 fl_transformed_vertex.
+
+ Start and end drawing a list of points. Points are added to
+the list with fl_vertex.
+
+ Start and end drawing lines.
+
+ Start and end drawing a closed sequence of lines.
+
+ Start and end drawing a convex filled polygon.
+
+ 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 fl_gap() to seperate loops of
+the path. It is unnecessary but harmless to call
+fl_gap() before the first vertex, after the last one,
+or several times in a row.
+
+ 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.
+
+ fl_gap() should only be called between
+fl_begin_complex_polygon() and
+fl_end_complex_polygon(). To outline the polygon, use
+fl_begin_loop() and replace each fl_gap() with
+fl_end_loop();fl_begin_loop(). Add a series of points on a Bezier curve to the path. The curve ends
+(and two of the points) are at x,y and x3,y3.
+
+ 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 fl_arc(). x,y are the center of
+the circle, and r is its radius. fl_arc()
+takes start and end angles that are measured
+in degrees counter-clockwise from 3 o'clock. If end is
+less than start then it draws the arc in a clockwise
+direction.
+
+ fl_circle() is equivalent to fl_arc(...,0,360) but
+may be faster. It must be the only thing in the path: if you
+want a circle as part of a complex polygon you must use fl_arc().
+
+ fl_circle() draws incorrectly if the
+ transformation is both rotated and non-square scaled.
+
+ All text is drawn in the current font.
+It is undefined whether this location or the characters are
+modified by the current transformation.
+
+ Draw a nul-terminated string or an array of n 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
+y. 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.
+
+ 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 x, y, w and h. See Fl_Widget::align()
+for values for align. The value
+FL_ALIGN_INSIDE is ignored, as this function always
+prints inside the box.
+
+ If img is provided and is not NULL, the
+image is drawn above or below the text as specified by the
+align value.
+
+ The draw_symbols argument specifies whether or not
+to look for symbol names starting with the "@" character.
+
+ The text length is limited to 1024 caracters per line.
+
+ Measure how wide and tall the string will be when printed by
+the fl_draw(...align) function. If the incoming
+w is non-zero it will wrap to that width.
+
+ Recommended minimum line spacing for the current font. You
+can also just use the value of size passed to fl_font().
+
+ Recommended distance above the bottom of a
+fl_height() tall box to draw the text at so it looks
+centered vertically in that box.
+
+ Return the pixel width of a nul-terminated string, a sequence of n
+characters, or a single character in the current font.
+
+ Unparse a shortcut value as used by Fl_Button
+or Fl_Menu_Item
+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.
+
+ 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.
+
+ Initially only the first 16 faces are filled in. There are
+symbolic names for them: FL_HELVETICA,
+FL_TIMES, FL_COURIER, and modifier values
+FL_BOLD and FL_ITALIC which can be added to
+these, and FL_SYMBOL and FL_ZAPF_DINGBATS.
+Faces greater than 255 cannot be used in Fl_Widget
+labels, since Fl_Widget stores the index as a byte. 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 fl_width(), but on X this will open
+the display.
+
+ The font is identified by a face and a
+size. The size of the font is measured in
+pixels and not "points". Lines should be spaced
+size pixels apart or more. Returns the face and size set by the most recent call to
+fl_font(a,b). This can be used to save/restore the
+font.
+
+ 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.
+
+ FLTK provides the functions fl_latin1_to_local,
+fl_local_to_latin1, fl_mac_roman_to_local, and
+fl_local_to_mac_roman 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.
+
+ 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
+Fahrvergn¸gen with a deformed umlaut u.
+ 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.
+
+ These functions allow you to draw interactive selection rectangles
+without using the overlay hardware. FLTK will XOR a single rectangle
+outline over a window.
+
+ fl_overlay_rect() draws a selection rectangle, erasing any
+previous rectangle by XOR'ing it first. fl_overlay_clear()
+will erase the rectangle without drawing a new one.
+
+ Using these functions is tricky. You should make a widget
+with both a handle() and draw() method.
+draw() should call fl_overlay_clear() before
+doing anything else. Your handle() method should call
+window()->make_current() and then
+fl_overlay_rect() after FL_DRAG events, and
+should call fl_overlay_clear() after a
+FL_RELEASE event. To draw images, you can either do it directly from data in
+your memory, or you can create a Fl_Image 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 much faster.
+
+ 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.
+
+ 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 r,g,b order. X,Y are where to
+put the top-left corner. W and H define the
+size of the image. D is the delta to add to the pointer
+between pixels, it may be any value greater or equal to
+3, or it can be negative to flip the image
+horizontally. LD is the delta to add to the pointer
+between lines (if 0 is passed it uses W * D), and may
+be larger than W * D to crop data, or negative to flip
+the image vertically.
+
+ It is highly recommended that you put the following code before the
+first show() of any window in your program to get rid
+of the dithering if possible: Gray scale (1-channel) images may be drawn. This is done if
+abs(D) is less than 3, or by calling
+fl_draw_image_mono(). 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
+D greater than 1 will let you display one channel of a
+color image.
+
+ 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. 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.
+
+ The callback is called with the void * user data
+pointer which can be used to point at a structure of information
+about the image, and the x, y, and w
+of the scan line desired from the image. 0,0 is the upper-left
+corner of the image, not X,Y. A pointer to a
+buffer to put the data into is passed. You must copy w
+pixels from scanline y, starting at pixel x,
+to this buffer. Due to cropping, less than the whole image may be requested.
+So x may be greater than zero, the first y may
+be greater than zero, and w may be less than
+W. The buffer is long enough to store the entire W
+* D 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 x is not
+zero, copy the data over so the x'th pixel is at the
+start of the buffer. You can assume the y's will be consecutive, except
+the first one may be greater than zero. If D is 4 or more, you must fill in the unused bytes
+with zero. 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.
+
+ To use an XPM, do: Transparent colors are replaced by the optional
+Fl_Color argument. To draw with true transparency you must
+use the Fl_Pixmap class.
+
+ 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.
+
+ FLTK provides a single function for reading from the current
+window or off-screen buffer into a RGB(A) image buffer. Read a RGB(A) image from the current window or off-screen
+buffer. The p argument points to a buffer that can hold
+the image and must be at least W*H*3 bytes when reading
+RGB images and W*H*4 bytes when reading RGBA images. If
+NULL, fl_read_image() will create an array of
+the proper size which can be freed using delete[]. The alpha 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. FLTK provides a base image class called Fl_Image 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 image() and
+deimage()
+methods or drawn directly.
+
+ The Fl_Image class
+does almost nothing by itself, but is instead supported by three
+basic image types:
+
+ The Fl_Bitmap class encapsulates a mono-color bitmap image.
+The draw() method draws the image using the current drawing
+color.
+
+ The Fl_Pixmap class encapsulates a colormapped image.
+The draw() method draws the image using the colors in the
+file, and masks off any transparent colors automatically.
+
+ The Fl_RGB_Image 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 draw() 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.
+
+ fl_can_do_alpha_blending() will return 1, if your
+platform supports true alpha blending for RGBA images, or 0,
+if FLTK will use screen door transparency.
+
+ FLTK also provides several image classes based on the three
+standard image types for common file formats:
+
+ Each of these image classes load a named file of the
+corresponding format. The Fl_Shared_Image class
+can be used to load any type of image file - the class examines
+the file and constructs an image of the appropriate type.
+
+ Finally, FLTK provides a special image class called Fl_Tiled_Image to tile
+another image object in the specified area. This class can be
+used to tile a background image in a Fl_Group widget,
+for example.
+
+ The copy() 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.
+
+ The draw() method draws the image object.
+x,y,w,h indicates a destination rectangle.
+ox,oy,w,h is a source rectangle. This source rectangle
+is copied to the destination. The source rectangle may extend
+outside the image, i.e. ox and oy may be
+negative and w and h may be bigger than the
+image, and this area is left unchanged.
+
+ Draws the image with the upper-left corner at x,y.
+This is the same as doing draw(x,y,img->w(),img->h(),0,0).
+
+ Create an RGB offscreen buffer with w*h pixels.
+
+ Delete a previously created offscreen buffer. All drawings are lost.
+
+ 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.
+
+ Quit sending drawing commands to this offscreen buffer.
+
+ Copy a rectangular area of the size w*h from srcx, srcy in the offscreen
+buffer into the current buffer at x, y.
+
+*/
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
+
+ This chapter takes you through the design of a simple
+FLTK-based text editor.
+
+ Since this will be the first big project you'll be doing with FLTK,
+lets define what we want our text editor to do:
+
+ 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 EditorWindow:
+
+ Our text editor will need some global variables to keep track of
+things:
+
+ The textbuf variable is the text editor buffer for
+our window class described previously. We'll cover the other
+variables as we build the application. The first goal requires us to use a menubar and menus that
+define each function the editor needs to perform. The Fl_Menu_Item structure is
+used to define the menus and items in a menubar: Once we have the menus defined we can create the
+Fl_Menu_Bar widget and assign the menus to it with: We'll define the callback functions later.
+
+ To keep things simple our text editor will use the
+Fl_Text_Editor
+widget to edit the text:
+
+ So that we can keep track of changes to the file, we also want to add
+a "modify" callback: Finally, we want to use a mono-spaced font like FL_COURIER:
+
+ 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
+Fl_Input widgets, the "replace all" and
+"cancel" buttons are Fl_Button widgets, and
+the "replace next " button is a
+Fl_Return_Button widget: Now that we've defined the GUI components of our editor, we
+need to define our callback functions. This function will be called whenever the user changes any text in the
+editor widget:
+
+ The set_title() 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.
+
+ This callback function will call kf_copy()
+to copy the currently selected text to the clipboard: This callback function will call kf_cut()
+to cut the currently selected text to the clipboard: This callback function will call remove_selection()
+to delete the currently selected text to the clipboard: This callback function asks for a search string using the fl_input()
+convenience function and then calls the find2_cb()
+function to find the string:
+
+ 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:
+
+ If the search string cannot be found we use the fl_alert()
+convenience function to display a message to that effect.
+
+ This callback function will clear the editor widget and current
+filename. It also calls the check_save() function to give the
+user the opportunity to save the current file first as needed:
+
+ 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 check_save() function to give the user the
+opportunity to save the current file first as needed:
+
+ We call the load_file() function to actually load the file.
+
+ This callback function will call kf_paste()
+to paste the clipboard at the current position: 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:
+
+ The replace callback just shows the replace dialog:
+
+ 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:
+
+ This callback will replace all occurences of the search
+string in the file:
+
+ This callback just hides the replace dialog:
+
+ This callback saves the current file. If the current filename is
+blank it calls the "save as" callback:
+
+ The save_file() function saves the current file to the
+specified filename.
+
+ This callback asks the user for a filename and saves the current file:
+
+ The save_file() function saves the current file to the
+specified filename.
+
+ Now that we've defined the callback functions, we need our support
+functions to make it all work:
+
+ 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:
+
+ This function loads the specified file into the textbuf class:
+
+ When loading the file we use the loadfile()
+method to "replace" the text in the buffer, or the insertfile()
+method to insert text in the buffer from the named file.
+
+ This function saves the current buffer to the specified file:
+
+ This function checks the changed variable and updates the
+window label accordingly:
+ Once we've created all of the support functions, the only thing left
+is to tie them all together with the main() function.
+The main() 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:
+
+ The complete source for our text editor can be found in the test/editor.cxx 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:
+
+ or by using the fltk-config script with:
+
+ As noted in Chapter 1, you may need to
+include compiler and linker options to tell them where to find the FLTK
+library. Also, the CC command may also be called gcc
+or c++ on your system.
+
+ Congratulations, you've just built your own text editor! Now that we've implemented the basic functionality, it is
+time to show off some of the advanced features of the
+ The Styles are defined using the
+ The For our text editor we'll define 7 styles for plain code,
+comments, keywords, and preprocessor directives:
+
+ 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'.
+
+ You call the 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:
+
+ The The This appendix lists the enumerations provided in the
+<FL/Enumerations.H> header file, organized by
+section. Constants whose value is zero are marked with "(0)",
+this is often useful to know when programming.
+
+ The following constants define the button numbers for FL_PUSH and
+FL_RELEASE events:
+
+ The Fl_Color 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.
+
+ 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.
+
+ The following color constants can be used to access the user-defined
+colors:
+
+ The following color constants can be used to access the colors from the
+FLTK standard color cube:
+
+ The inline methods for getting a grayscale, color cube, or
+RGB color value are described in Appendix B - Function
+Reference.
+
+ 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. This chapter discusses the FLTK event model and how to handle
+events in your program or widget.
+
+ 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.
+
+ Events are identified by the integer argument passed to the
+Fl_Widget::handle() virtual
+method. Other information about the most recent event is stored in
+static locations and acquired by calling the Fl::event_*() 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 handle()
+method.
+
+ A mouse button has gone down with the mouse pointing at this
+widget. You can find out what button by calling
+Fl::event_button(). You find out the mouse position by
+calling Fl::event_x() and Fl::event_y().
+
+ A widget indicates that it "wants" the mouse click
+by returning non-zero from its handle() method. It
+will then become the
+Fl::pushed() widget and will get FL_DRAG and
+the matching FL_RELEASE events. If handle()
+returns zero then FLTK will try sending the FL_PUSH to
+another widget. The mouse has moved with a button held down. The current
+button state is in Fl::event_state().
+The mouse position is in Fl::event_x() and Fl::event_y().
+
+ In order to receive FL_DRAG events, the widget must
+return non-zero when handling FL_PUSH. A mouse button has been released. You can find out what
+button by calling Fl::event_button().
+
+ In order to receive the FL_RELEASE event, the widget must
+return non-zero when handling FL_PUSH. The mouse has moved without any mouse buttons held down.
+This event is sent to the Fl::belowmouse()
+widget. In order to receive FL_MOVE events, the widget must
+return non-zero when handling FL_ENTER. The user has moved the mouse wheel. The Fl::event_dx() and Fl::event_dy() methods
+can be used to find the amount to scroll horizontally and
+vertically.
+
+ 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 handle() method. It then
+becomes the Fl::belowmouse()
+widget and will receive FL_MOVE and FL_LEAVE
+events.
+
+ The mouse has moved out of the widget.
+
+ In order to receive the FL_LEAVE event, the widget must
+return non-zero when handling FL_ENTER. This indicates an attempt to give a widget the
+keyboard focus.
+
+ 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 handle()
+method. It then becomes the Fl::focus() widget and gets
+FL_KEYDOWN, FL_KEYUP, and FL_UNFOCUS
+events.
+
+ 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 Fl::event_key() to
+figure out why it moved. For navigation it will be the key
+pressed and interaction with the window manager it will be
+zero.
+
+ This event is sent to the previous Fl::focus() widget when
+another widget gets the focus or the window loses focus.
+
+ A key was pressed or released. The key can be found in Fl::event_key(). The
+text that the key should insert can be found with Fl::event_text() and
+its length is in Fl::event_length().
+If you use the key handle() 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 FL_SHORTCUT event.
+
+ To receive If you are writing a text-editing widget you may also want to
+call the Fl::compose()
+function to translate individual keystrokes into foreign
+characters.
+
+ If the Fl::focus()
+widget is zero or ignores an FL_KEYBOARD event then
+FLTK tries sending this event to every widget it can, until one
+of them returns non-zero. FL_SHORTCUT is first sent to
+the Fl::belowmouse() 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!
+
+ You can also make "global" shortcuts by using Fl::add_handler(). A
+global shortcut will work no matter what windows are displayed
+or which one has the focus. This widget is no longer active, due to deactivate()
+being called on it or one of its parents. active() may
+still be true after this, the widget is only active if
+active() is true on it and all its parents (use active_r() to check this).
+
+ This widget is now active, due to activate()
+being called on it or one of its parents.
+
+ This widget is no longer visible, due to hide() being
+called on it or one of its parents, or due to a parent window
+being minimized. visible() may still be true after
+this, but the widget is visible only if visible() is
+true for it and all its parents (use visible_r() to
+check this).
+
+ This widget is visible again, due to show() being
+called on it or one of its parents, or due to a parent window
+being restored. Child Fl_Windows respond to this by
+actually creating the window if not done already, so if you
+subclass a window, be sure to pass FL_SHOW to the base
+class handle() method!
+
+ You should get this event some time after you call Fl::paste(). The contents
+of Fl::event_text()
+is the text to insert and the number of characters is in Fl::event_length().
+
+ The Fl::selection_owner()
+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.
+
+ 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 file://.
+
+ The drag and drop data is available in Fl::event_text()
+at the concluding FL_PASTE. On some platforms, the
+event text is also available for the FL_DND_* events,
+however application must not depend on that behavior because it
+depends on the protocol used on each platform.
+
+ FL_DND_* events cannot be used in widgets derived
+from Fl_Group or Fl_Window.
+
+ 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.
+
+ 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.
+
+ The mouse has moved out of the widget.
+
+ 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.
+
+
+
+ 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 handle() and
+callback() methods.
+
+ These are all trivial inline functions and thus very fast and small: FLTK follows very simple and unchangeable rules for sending
+events. The major innovation is that widgets can indicate (by
+returning 0 from the handle() 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.
+
+ Most events are sent directly to the handle() method
+of the Fl_Window that the window system says they
+belong to. The window (actually the Fl_Group that
+Fl_Window is a subclass of) is responsible for sending
+the events on to any child widgets. To make the
+Fl_Group code somewhat easier, FLTK sends some events
+(FL_DRAG, FL_RELEASE, FL_KEYBOARD,
+FL_SHORTCUT, FL_UNFOCUS, and
+FL_LEAVE) directly to leaf widgets. These procedures
+control those leaf widgets:
+
+ The foreign-letter compose processing done by the Fl_Input widget is provided in
+a function that you can call if you are writing your own text editor
+widget.
+
+ FLTK uses its own compose processing to allow "preview" of
+the partially composed sequence, which is impossible with the
+usual "dead key" processing.
+
+ 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.
+
+ The following methods are provided for character composition:
+
+ March 19, 2005 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
+http://fltk.org/software.php. 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. The tabs application shows the Fl_Tabs widget
+on the left and the Fl_Wizard widget on the right side
+for direct comparison of these two panel management widgets.
+
+ This chapter shows how to use the Fast Light User-Interface Designer
+("FLUID") to create your GUIs. Subchapters:
+Writing Your First FLTK Program
+
+
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Box.H>
+
+int main(int argc, char **argv) {
+ Fl_Window *window = new Fl_Window(300,180);
+ Fl_Box *box = new Fl_Box(20,40,260,100,"Hello, World!");
+ box->box(FL_UP_BOX);
+ box->labelsize(36);
+ box->labelfont(FL_BOLD+FL_ITALIC);
+ box->labeltype(FL_SHADOW_LABEL);
+ window->end();
+ window->show(argc, argv);
+ return Fl::run();
+}
+
+
+
+
+
+Fl_Window *window = new Fl_Window(300,180);
+
+
+
+Fl_Box *box = new Fl_Box(20,40,260,100,"Hello, World!");
+
+
+
+box->box(FL_UP_BOX);
+box->labelsize(36);
+box->labelfont(FL_BOLD+FL_ITALIC);
+box->labeltype(FL_SHADOW_LABEL);
+
+
+
+window->end();
+
+
+
+window->show(argc, argv);
+return Fl::run();
+
+
+
+Figure 2-1: The Hello, World! WindowCreating the Widgets
+
+
+Fl_Widget(x, y, width, height, label)
+
+
+Creating Widget hierarchies
+
+Get/Set Methods
+
+Redrawing After Changing Attributes
+
+Labels
+
+Showing the Window
+
+The Main Event Loop
+
+
+while (Fl::wait());
+
+
+Compiling Programs with Standard Compilers
+
+
+CC -I/usr/local/include ...
+gcc -I/usr/local/include ...
+
+
+
+CC `fltk-config --cxxflags` ...
+
+
+
+CC ... -L/usr/local/lib -lfltk -lXext -lX11 -lm
+gcc ... -L/usr/local/lib -lfltk -lXext -lX11 -lm
+
+
+Fl_Help_Dialog
+widget, and system icon support.
+
+
+
+
+Note:
+
+
+CC ... `fltk-config --ldflags`
+
+
+
+
+
+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`
+
+
+
+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
+
+
+Compiling Programs with Microsoft Visual C++
+
+Naming
+
+
+
+
+
+
+
+Header Files
+
+
+#include <FL/Fl_xyz.H>
+
+
+
+
+
+Note:
+
+
+
+ #include <FL\Fl_xyz.H>
+ #include <fl/fl_xyz.h>
+ #include <Fl/fl_xyz.h>
+
+
+ Buttons
+
+
+
+
+
+
+Figure 3-1: FLTK Button Widgets
+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");
+
+
+
+button->type(FL_NORMAL_BUTTON);
+lbutton->type(FL_TOGGLE_BUTTON);
+rbutton->type(FL_RADIO_BUTTON);
+
+
+Text
+
+
+
+
+
+
+Fl_Input *input = new Fl_Input(x, y, width, height, "label");
+input->value("Now is the time for all good men...");
+
+
+Valuators
+
+
+
+
+
+
+Figure 3-2: FLTK valuator widgetsGroups
+
+
+
+
+
+Setting the Size and Position of Widgets
+
+
+button->position(x, y);
+group->resize(x, y, width, height);
+window->size(width, height);
+
+
+Colors
+
+
+
+
+
+
+
+
+Fl_Color c = fl_rgb_color(85, 170, 255);
+
+
+
+button->color(FL_RED);
+
+
+
+button->labelcolor(FL_WHITE);
+
+
+Box Types
+
+
+Figure 3-3: FLTK box typesMaking Your Own Boxtypes
+
+
+
+
+Note:
+
+The Drawing Function
+
+
+void xyz_draw(int x, int y, int w, int h, Fl_Color c) {
+...
+}
+
+
+
+
+
+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);
+}
+
+
+Fl_Boxtype fl_down(Fl_Boxtype)
+
+Fl_Boxtype fl_frame(Fl_Boxtype)
+
+Fl_Boxtype fl_box(Fl_Boxtype)
+
+Adding Your Box Type
+
+
+#define XYZ_BOX FL_FREE_BOXTYPE
+
+Fl::set_boxtype(XYZ_BOX, xyz_draw, 1, 1, 2, 2);
+
+
+Labels and Label Types
+
+label()
+
+
+Figure 3-4: FLTK label symbols
+
+
+
+align()
+
+
+
+
+
+labeltype()
+
+
+
+
+
+image() and deimage()
+
+Making Your Own Label Types
+
+
+
+
+Note:
+
+Label Type Functions
+
+
+void xyz_draw(const Fl_Label *label, int x, int y, int w, int h, Fl_Align align) {
+...
+}
+
+
+
+void xyz_measure(const Fl_Label *label, int &w, int &h) {
+...
+}
+
+
+Adding Your Label Type
+
+
+#define XYZ_LABEL FL_FREE_LABELTYPE
+
+Fl::set_labeltype(XYZ_LABEL, xyz_draw, xyz_measure);
+
+
+Making your own symbols
+
+
+int fl_add_symbol(const char *name, void (*drawit)(Fl_Color), int scalable)
+
+
+
+int fl_draw_symbol(const char *name,int x,int y,int w,int h,Fl_Color col)
+
+
+Callbacks
+
+
+void xyz_callback(Fl_Widget *w, void *data) {
+...
+}
+
+
+
+int xyz_data;
+
+button->callback(xyz_callback, &xyz_data);
+
+
+
+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);
+
+
+
+
+
+Note:
+
+
+
+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);
+
+ Shortcuts
+
+
+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
+
+
+When Can You Draw Things in FLTK?
+
+
+
+
+
+FLTK Drawing Functions
+
+
+
+
+
+Boxes
+
+void fl_draw_box(Fl_Boxtype b, int x, int y, int w, int h, Fl_Color c);
+
+fl_draw_box()
+which draws a standard boxtype c in the specified
+color c.
+
+void fl_frame(const char *s, int x, int y, int w, int h);
+
+fl_frame() function draws a series of line
+segments around the given box. The string s 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 fl_frame() with a string that is
+not a multiple of 4 characters in length are undefined.
+
+fl_frame2() is the order of the line segments.
+
+void fl_frame2(const char *s, int x, int y, int w, int h);
+
+fl_frame2() function draws a series of line
+segments around the given box. The string s 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 fl_frame2() with a string that is
+not a multiple of 4 characters in length are undefined.
+
+fl_frame() is the order of the line segments.
+
+Clipping
+
+void fl_clip(int x, int y, int w, int h)
+
+
+void fl_push_clip(int x, int y, int w, int h)fl_clip() name is deprecated and
+will be removed from future releases.
+
+void fl_push_no_clip()
+
+void fl_pop_clip()
+
+
+
+
+Note:
+
+
+int fl_not_clipped(int x, int y, int w, int h)
+
+
+
+
+Note:
+
+
+int fl_clip_box(int x, int y, int w, int h, int &X, int &Y, int &W,
+int &H)
+
+void fl_clip_region(Fl_Region r)
+
+
+
Fl_Region fl_clip_region()Colors
+
+void fl_color(Fl_Color)
+
+Fl_Color fl_color()
+
+void fl_color(uchar r, uchar g, uchar b)
+
+Line Dashes and Thickness
+
+void fl_line_style(int style, int width=0, char* dashes=0)
+
+
+
+
+Note:
+
+
+
+
+
+
+
+
+
+Note:
+
+
+Drawing Fast Shapes
+
+void fl_point(int x, int y)
+
+void fl_rectf(int x, int y, int w, int h)
+
+
+
void fl_rectf(int x, int y, int w, int h)void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b)
+
+void fl_rect(int x, int y, int w, int h)
+
+
+
void fl_rect(int x, int y, int w, int h, Fl_Color c)void fl_line(int x, int y, int x1, int y1)
+
+
+
void fl_line(int x, int y, int x1, int y1, int x2, int y2)void fl_loop(int x, int y, int x1, int y1, int x2, int y2)
+
+
+
void fl_loop(int x, int y, int x1, int y1, int x2, int y2, int x3,
+int y3)void fl_polygon(int x, int y, int x1, int y1, int x2, int y2)
+
+
+
void fl_polygon(int x, int y, int x1, int y1, int x2, int y2, int
+x3, int y3)void fl_xyline(int x, int y, int x1)
+
+
+
void fl_xyline(int x, int y, int x1, int y2)
+
void fl_xyline(int x, int y, int x1, int y2, int x3)void fl_yxline(int x, int y, int y1)
+
+
+
void fl_yxline(int x, int y, int y1, int x2)
+
void fl_yxline(int x, int y, int y1, int x2, int y3)void fl_arc(int x, int y, int w, int h, double a1, double a2)
+
+
+
void fl_pie(int x, int y, int w, int h, double a1, double a2)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)
+
+Drawing Complex Shapes
+
+void fl_push_matrix()
+
+
+
void fl_pop_matrix()void fl_scale(float x, float y)
+
+
+
void fl_scale(float x)
+
void fl_translate(float x, float y)
+
void fl_rotate(float d)
+
void fl_mult_matrix(float a, float b, float c, float d, float
+x, float y)double fl_transform_x(double x, double y)
+
+
+
double fl_transform_y(double x, double y)
+
double fl_transform_dx(double x, double y)
+
double fl_transform_dy(double x, double y)
+
void fl_transformed_vertex(double xf, double yf)void fl_begin_points()
+
+
+
void fl_end_points()void fl_begin_line()
+
+
+
void fl_end_line()void fl_begin_loop()
+
+
+
void fl_end_loop()void fl_begin_polygon()
+
+
+
void fl_end_polygon()void fl_begin_complex_polygon()
+
+
+
void fl_gap()
+
void fl_end_complex_polygon()
+
+
+Note:
+
+
+void fl_vertex(float x, float y)
+Add a single vertex to the current path.
+
+void fl_curve(float x, float y, float x1, float y1, float x2, float
+y2, float x3, float y3)
+
+void fl_arc(float x, float y, float r, float start, float end)
+
+void fl_circle(float x, float y, float r)
+
+
+
+
+Note:
+
+
+Drawing Text
+
+void fl_draw(const char *, int x, int y)
+
+
+
void fl_draw(const char *, int n, int x, int y)void fl_draw(const char *, int x, int y, int w, int h,
+Fl_Align align, Fl_Image *img = 0, int draw_symbols = 1)
+
+void fl_measure(const char *, int &w,
+int &h, int draw_symbols = 1)
+
+int fl_height()
+
+int fl_descent()
+
+float fl_width(const char*)
+
+
+
float fl_width(const char*, int n)
+
float fl_width(uchar)const char *fl_shortcut_label(ulong)
+
+Fonts
+
+void fl_font(int face, int size)
+
+int fl_font()
+
+
+
int fl_size()Character Encoding
+
+
+ btn = new Fl_Button(10, 10, 300, 25);
+ btn->copy_label(fl_latin1_to_local("Fahrvergnügen"));
+
+
+Drawing Overlays
+
+void fl_overlay_rect(int x, int y, int w, int h);
+
+
+
void fl_overlay_clear();Drawing Images
+
+Direct Image Drawing
+
+void fl_draw_image(const uchar *, int X, int Y, int W, int H, int D
+= 3, int LD = 0)
+
+
+
void fl_draw_image_mono(const uchar *, int X, int Y, int W, int H,
+int D = 1, int LD = 0)
+Fl::visual(FL_RGB);
+
+
+
+
+
+Note:
+
+
+typedef void (*fl_draw_image_cb)(void *, int x, int y, int w, uchar
+*)
+
+
+
void fl_draw_image(fl_draw_image_cb, void *, int X, int Y, int W,
+int H, int D = 3)
+
void fl_draw_image_mono(fl_draw_image_cb, void *, int X, int Y,
+int W, int H, int D = 1)int fl_draw_pixmap(char **data, int X, int Y, Fl_Color = FL_GRAY)
+
+
+#include "foo.xpm"
+...
+fl_draw_pixmap(foo, X, Y);
+
+
+int fl_measure_pixmap(char **data, int &w, int &h)
+
+Direct Image Reading
+
+uchar *fl_read_image(uchar *p, int
+X, int Y, int W, int H, int alpha = 0);
+
+Image Classes
+
+
+
+
+
+char fl_can_do_alpha_blending()
+
+
+
+
+
+virtual void copy();
+
+
+virtual void copy(int w, int h);void draw(int x, int y, int w, int h, int ox = 0, int oy = 0);
+
+void draw(int x, int y)
+
+Offscreen Drawing
+
+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. Fl_Double_Window uses offscreen rendering
+to avoid flickering on systems that don't support
+double-buffering natively.
+
+Fl_Offscreen fl_create_offscreen(int w, int h)
+
+void fl_delete_offscreen(Fl_Offscreen)
+
+void fl_begin_offscreen(Fl_Offscreen)
+
+void fl_end_offscreen()
+
+void fl_copy_offscreen(int x, int y,
+int w, int h, Fl_Offscreen osrc, int srcx, int srcy)
+
+Determining the Goals of the Text Editor
+
+
+
+
+
+
+
+Designing the Main Window
+
+
+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];
+};
+
+
+Variables
+
+
+int changed = 0;
+char filename[256] = "";
+Fl_Text_Buffer *textbuf;
+
+
+Menubars and Menus
+
+
+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 }
+};
+
+
+
+Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, 640, 30);
+m->copy(menuitems);
+
+
+Editing the Text
+
+
+w->editor = new Fl_Text_Editor(0, 30, 640, 370);
+w->editor->buffer(textbuf);
+
+
+
+textbuf->add_modify_callback(changed_cb, w);
+textbuf->call_modify_callbacks();
+
+
+
+w->editor->textfont(FL_COURIER);
+
+
+The Replace Dialog
+
+
+Figure 4-1: The search and replace dialog.
+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");
+
+
+Callbacks
+
+changed_cb()
+
+
+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();
+}
+
+
+copy_cb()
+
+
+void copy_cb(Fl_Widget*, void* v) {
+ EditorWindow* e = (EditorWindow*)v;
+ Fl_Text_Editor::kf_copy(0, e->editor);
+}
+
+
+cut_cb()
+
+
+void cut_cb(Fl_Widget*, void* v) {
+ EditorWindow* e = (EditorWindow*)v;
+ Fl_Text_Editor::kf_cut(0, e->editor);
+}
+
+
+delete_cb()
+
+
+void delete_cb(Fl_Widget*, void* v) {
+ textbuf->remove_selection();
+}
+
+
+find_cb()
+
+
+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);
+ }
+
+
+find2_cb()
+
+
+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);
+}
+
+
+new_cb()
+
+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();
+}
+
+
+open_cb()
+
+
+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);
+}
+
+
+paste_cb()
+
+
+void paste_cb(Fl_Widget*, void* v) {
+ EditorWindow* e = (EditorWindow*)v;
+ Fl_Text_Editor::kf_paste(0, e->editor);
+}
+
+
+quit_cb()
+
+
+void quit_cb(Fl_Widget*, void*) {
+ if (changed && !check_save())
+ return;
+
+ exit(0);
+}
+
+
+replace_cb()
+
+
+void replace_cb(Fl_Widget*, void* v) {
+ EditorWindow* e = (EditorWindow*)v;
+ e->replace_dlg->show();
+}
+
+
+replace2_cb()
+
+
+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);
+}
+
+
+replall_cb()
+
+
+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);
+}
+
+
+replcan_cb()
+
+
+void replcan_cb(Fl_Widget*, void* v) {
+ EditorWindow* e = (EditorWindow*)v;
+ e->replace_dlg->hide();
+}
+
+
+save_cb()
+
+
+void save_cb(void) {
+ if (filename[0] == '\0') {
+ // No filename - get one!
+ saveas_cb();
+ return;
+ }
+ else save_file(filename);
+}
+
+
+saveas_cb()
+
+
+void saveas_cb(void) {
+ char *newfile;
+
+ newfile = fl_file_chooser("Save File As?", "*", filename);
+ if (newfile != NULL) save_file(newfile);
+}
+
+
+Other Functions
+
+check_save()
+
+
+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;
+}
+
+
+load_file()
+
+
+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();
+}
+
+
+save_file()
+
+
+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();
+}
+
+
+set_title()
+
+
+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);
+}
+
+
+The main() Function
+
+
+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();
+}
+
+
+Compiling the Editor
+
+
+CC -o editor editor.cxx -lfltk -lXext -lX11 -lm
+
+
+
+fltk-config --compile editor.cxx
+
+
+The Final Product
+
+The final editor window should look like the image in Figure 4-2.
+
+
+Figure 4-2: The completed editor windowAdvanced Features
+
+Fl_Text_Editor widget.
+
+Syntax Highlighting
+
+Fl_Text_Editor widget supports highlighting
+of text with different fonts, colors, and sizes. The
+implementation is based on the excellent NEdit text editor core, which
+uses a parallel "style" buffer which tracks the font, color, and
+size of the text that is drawn.
+
+Fl_Text_Display::Style_Table_Entry structure
+defined in <FL/Fl_Text_Display.H>:
+
+
+struct Style_Table_Entry {
+ Fl_Color color;
+ Fl_Font font;
+ int size;
+ unsigned attr;
+};
+
+
+color member sets the color for the text,
+the font member sets the FLTK font index to use,
+and the size member sets the pixel size of the
+text. The attr member is currently not used.
+
+
+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
+};
+
+
+highlight_data() method to associate the
+style data and buffer with the text editor widget:
+
+
+Fl_Text_Buffer *stylebuf;
+
+w->editor->highlight_data(stylebuf, styletable,
+ sizeof(styletable) / sizeof(styletable[0]),
+ 'A', style_unfinished_cb, 0);
+
+
+
+textbuf->add_modify_callback(style_update, w->editor);
+
+
+style_update() function, like the change_cb()
+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:
+
+
+//
+// '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);
+}
+
+
+style_parse() 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:
+
+
+//
+// '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';
+ }
+ }
+}
+
+
+*/
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
+
+Version Numbers
+ The FLTK version number is stored in a number of compile-time
+constants:
+
+
+Events
+ Events are identified by an Fl_Event enumeration value. The
+following events are currently defined:
+
+
+Callback "When" Conditions
+ The following constants determine when a callback is performed:
+
+
+Fl::event_button() Values
+
+
+
+
+Fl::event_key() Values
+ The following constants define the non-ASCII keys on the keyboard for
+FL_KEYBOARD and FL_SHORTCUT events:
+
+
+Fl::event_state() Values
+ The following constants define bits in the Fl::event_state()
+ value:
+
+
+
+Alignment Values
+ The following constants define bits that can be used with
+Fl_Widget::align() to control the positioning of the
+label:
+
+
+Fonts
+ The following constants define the standard FLTK fonts:
+
+
+
+Colors
+
+Color Constants
+
+
+
+
+
+
+
+
+
+Cursors
+
+
+
+
+
+FD "When" Conditions
+
+
+
+
+
+Damage Masks
+ The following damage mask bits are used by the standard FLTK widgets:
+
+
+
+*/
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
+
+The FLTK Event Model
+
+Mouse Events
+
+FL_PUSH
+
+FL_DRAG
+
+FL_RELEASE
+
+FL_MOVE
+
+FL_MOUSEWHEEL
+
+Focus Events
+
+FL_ENTER
+
+FL_LEAVE
+
+FL_FOCUS
+
+FL_UNFOCUS
+
+Keyboard Events
+
+FL_KEYDOWN, FL_KEYUP
+
+FL_KEYBOARD events you must also
+respond to the FL_FOCUS and FL_UNFOCUS
+events.
+
+FL_KEYUP events are sent to the widget that
+currently has focus. This is not necessarily the same widget
+that received the corresponding FL_KEYDOWN event
+because focus may have changed between events.
+
+FL_SHORTCUT
+
+Widget Events
+
+FL_DEACTIVATE
+
+FL_ACTIVATE
+
+FL_HIDE
+
+FL_SHOW
+
+Clipboard Events
+
+FL_PASTE
+
+FL_SELECTIONCLEAR
+
+Drag And Drop Events
+
+FL_DND_ENTER
+
+FL_DND_DRAG
+
+FL_DND_LEAVE
+
+FL_DND_RELEASE
+
+Fl::event_*() methods
+
+
+
+
+
+Event Propagation
+
+
+
+
+
+FLTK Compose-Character Sequences
+
+
+
+
+
+*/
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
+
+
+
+
+Example Applications
+
+
+adjuster
+arc
+ask
+bitmap
+blocks
+boxtype
+
+
+browser
+button
+buttons
+checkers
+clock
+colbrowser
+
+
+color_chooser
+cube
+CubeView
+cursor
+curve
+demo
+
+
+doublebuffer
+editor
+fast_slow
+file_chooser
+fluid
+fonts
+
+
+forms
+fractals
+fullscreen
+gl_overlay
+glpuzzle
+hello
+
+
+help
+iconize
+image
+inactive
+input
+input_choice
+
+
+keyboard
+label
+line_style
+list_visuals
+mandelbrot
+menubar
+
+
+message
+minimum
+navigation
+output
+overlay
+pack
+
+
+pixmap_browser
+pixmap
+preferences
+radio
+resizebox
+resize
+
+
+scroll
+shape
+subwindow
+sudoku
+symbols
+tabs
+
+
+threads
+tile
+tiled_image
+valuators
+adjuster
+adjuster shows a nifty little widget for quickly
+setting values in a great range.
+
+arc
+The arc 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.
+
+ask
+ask 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... .
+
+bitmap
+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.
+
+blocks
+A wonderful and addictive game that shows the usage of FLTK
+timers, graphics, and how to implement sound on all platforms.
+blocks is also a good example for the Mac OS X specific
+bundle format.
+
+boxtype
+boxtype 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.
+
+browser
+browser shows the capabilities of the Fl_Browser widget.
+Important features tested are loading of files, line formatting, and
+correct positioning of the browser data window.
+
+button
+The button test is a simple demo of push-buttons and callbacks.
+
+buttons
+buttons shows a sample of FLTK button types.
+
+checkers
+Written by Steve Poulsen in early 1979, checkers 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.
+
+clock
+The clock demo shows two analog clocks. The innards of
+the Fl_Clock widget are pretty interesting, explaining
+the use of timeouts and matrix based drawing.
+
+colbrowser
+colbrowser runs only on X11 systems. It reads
+/usr/lib/X11/rgb.txt 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 Motif.
+
+color_chooser
+The color_chooser gives a short demo of FLTK's palette based
+color chooser and of the RGB based color wheel.
+
+cube
+The cube demo shows the speed of OpenGL. It also tests
+the ability to render two OpenGL buffers into a single window,
+and shows OpenGL text.
+
+CubeView
+CubeView shows how to create a UI containing OpenGL with Fluid.
+
+cursor
+The cursor demo show all mouse cursor shapes that come standard
+with FLTK. The fgcolor and bgcolor sliders work only
+on few systems (some version of Irix for example).
+
+curve
+curve draws a nice Bezier curve into a custom widget. The
+points option for splines is not supported on all platforms.
+
+demo
+This tool allows quick access to all programs in the test directory.
+demo is based on the visuals of the IrixGL demo program. The menu
+tree can be changed by editing test/demo.menu.
+
+doublebuffer
+The doublebuffer 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.
+
+editor
+FLTK has two very different text input widgets. Fl_Input
+and derived classes are rather leight weight, however
+Fl_Text_Editor is a complete port of nedit (with permission).
+The editor test is almost a full application, showing custom
+syntax highlighting and dialog creation.
+
+fast_slow
+fast_slow shows how an application can use then when()
+setting to receive different kinds of callbacks.
+
+file_chooser
+The standard FLTK file_chooser is the result of many
+iterations, trying to find a middle ground between a complex
+browser and a fast light implementation.
+
+fonts
+fonts 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.
+
+forms
+forms 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.
+
+fractals
+fractals 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.
+
+fullscreen
+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.
+
+gl_overlay
+gl_overlay shows OpenGL overlay plane rendering. If no
+hardware overlay plane is available, FLTK will simulate it
+for you.
+
+glpuzzle
+The glpuzzle test shows how most Glut source code compiles
+easily under FLTK.
+
+hello
+hello: 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.
+
+help
+help displays the built-in FLTK help browser. The
+Fl_Help_Dialog 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.
+
+iconize
+iconize demonstrates the effect of the window functions
+hide(), iconize(), and show().
+
+image
+The image 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).
+
+inactive
+inactive tests the correct rendering of inactive widgets.
+To see the inactive version of images, you can check out the pixmap
+or image test.
+
+input
+This tool shows and tests different types of text input fields based on
+Fl_Input_. The input program also tests various
+settings of Fl_Input::when().
+
+input_choice
+input_choice tests the latest addition to FLTK1, a text input
+field with an attached pulldown menu. Windows users will recognize
+similarities to the 'ComboBox'. input_choice starts up in
+'plastic' scheme, but the traditional scheme is also supported.
+
+keyboard
+FLTK unifies keyboard events for all platforms. The keyboard
+test can be used to check the return values of Fl::event_key()
+and Fl::event_text(). 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.
+
+label
+Every FLTK widget can have a label attached to it. The label
+demo shows alignment, clipping and wrapping of text labels. Labels
+can contain symbols at the start and end of the text, like @FLTK
+or @circle uh-huh @square.
+
+line_style
+Advanced line drawing can be tested with line_style.
+Not all platforms support all line styles.
+
+list_visuals
+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.
+
+mandelbrot
+mandelbrot shows two advanced topics in one test. It creates
+grayscale images on the fly, updating them via the idle callback
+system. This is one of the few occasions where the idle callback
+is very useful by giving all available processor time to the application
+without blocking the UI or other apps.
+
+menubar
+The menubar 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.
+
+message
+message pops up a few of FLTK's standars message boxes.
+
+minimum
+The minimum 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.
+
+navigation
+navigation demonstrates how the text cursor moves from
+text field to text field when using the arrow keys, tab, and shift-tab.
+
+output
+output shows the difference between the single line and
+multi line mode of the Fl_Output widget. Fonts can be
+selected from the FLTK standard list of fonts.
+
+overlay
+The overlay 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 Fl_Overly_WIndow and
+provides a new function to draw custom overlays.
+
+pack
+The pack test program demonstrates the resizing
+and repositioning of children of the Fl_Pack group.
+Putting an Fl_Pack into an Fl_Scroll is
+a useful way to create a browser for large sets of data.
+
+pixmap_browser
+pixmap_browser tests the shared-image interface. When using
+the same image multiple times, Fl_Shared_Image will keep it
+only once in memory.
+
+pixmap
+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.
+
+preferences
+I do have my preferences in the morning, but sometimes I
+just can't remember a thing. This is where the Fl_Preferences
+come in handy. They remember any kind of data between program launches.
+
+radio
+The radio tool was created entirely with fluid. It
+shows some of the available button types and tests radio
+button behavior.
+
+resizebox
+resizebox shows some possible ways of FLTK's automatic
+resize bahavior..
+
+resize
+The resize demo tests size and position functions with
+the given window manager.
+
+scroll
+scroll shows how to scroll an area of widgets, one of
+them beeing a slow custom drawing. Fl_Scroll uses
+clipping and smart window area copying to improve redraw speed.
+The buttons at the bottom of the window control decoration rendering
+and updates.
+
+shape
+shape 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.
+
+subwindow
+The subwindow 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.
+
+sudoku
+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.
+
+symbols
+symbols 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.).
+
+tabs
+The tabs tool was created with fluid. It tests
+correct hiding and redisplaying of tabs, navigation across tabs,
+resize behavior, and no unneeded redrawing of invisible widgets.
+
+threads
+FLTK can be used in a multithreading environment. There are some
+limitations, mostly due to the underlying operating system.
+threads show how to use Fl::lock(),
+Fl::unlock(), and Fl::awake() in secondary threads
+to keep FLTK happy. Although locking works on all platforms,
+this demo is not available on every machine.
+
+tile
+The tile tool shows a nice way of using Fl_Tile.
+To test correct resizing of subwindows, the widget for region
+1 is created from an Fl_Window class.
+
+tiled_image
+The tiled_image 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.
+
+valuators
+valuators shows all of FLTK's nifty widgets to change
+numeric values.
+
+fluid
+fuid is not only a big test program, but also a very
+useful visual UI designer. Many parts of fluid were
+created using fluid.
+
+*/
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
+
+
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 .fl files. These files +are text, and you can (with care) edit them in a text editor, +perhaps to get some special effects.
+ +FLUID can "compile" the .fl file into a +.cxx and a .h file. The .cxx file +defines all the objects from the .fl file and the +.h file declares all the global ones. FLUID also +supports localization (Internationalization) +of label strings using message files and the GNU gettext or +POSIX catgets interfaces. + +
A simple program can be made by putting all your code (including a +main() function) into the .fl file and thus making the .cxx file a +single source file to compile. Most programs are more complex than +this, so you write other .cxx files that call the FLUID functions. +These .cxx files must #include the .h file or they can +#include the .cxx file so it still appears to be a single source +file. + +

+Figure 9-1: FLUID organization.
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.
+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.
+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 .cxx file.
++fluid filename.fl &+ +to edit the .fl file filename.fl. 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). +
You can provide any of the standard FLTK switches before the filename:
++-display host:n.n +-geometry WxH+X+Y +-title windowtitle +-name classname +-iconic +-fg color +-bg color +-bg2 color +-scheme schemename ++ + +
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. + +
In the current version, if you don't put FLUID into the +background with '&' then you will be able to abort FLUID by +typing CTRL-C on the terminal. It will exit +immediately, losing any changes.
+ +To run FLUID under WIN32, double-click on the FLUID.exe +file. You can also run FLUID from the Command Prompt window. +FLUID always runs in the background under WIN32. + +
FLUID can also be called as a command-line +"compiler" to create the .cxx and .h +file from a .fl file. To do this type: + +
+fluid -c filename.fl ++ +
This will read the filename.fl file and write +filename.cxx and filename.h. Any leading +directory on filename.fl 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: + +
+my_panels.h my_panels.cxx: my_panels.fl + fluid -c my_panels.fl ++ +
Most versions of make support rules that cause .fl +files to be compiled: + +
+.SUFFIXES: .fl .cxx .h +.fl.h .fl.cxx: + fluid -c $< ++ +
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. + +

+Figure 9-2: CubeView demo.
The window is of class CubeViewUI, and is completely generated by FLUID, including +class member functions. The central display of the cube is a separate +subclass of Fl_Gl_Window called CubeView. CubeViewUI manages CubeView +using callbacks from the various sliders and rollers to manipulate the +viewing angle and zoom of CubeView. +
At the completion of this tutorial you will (hopefully) understand +how to: +
You can safely skip this section as long as you realize the CubeView +is a sublass of Fl_Gl_Window and will respond to calls from +CubeViewUI, generated by FLUID. +
+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];
+};
+
+
+Here is the CubeView implementation. It is very similar to the +"cube" demo included with FLTK. + +
+#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();
+};
+
+
+We will completely construct a window to display and control the +CubeView defined in the previous section using FLUID. + +
Once you have started FLUID, the first step in defining a class is to +create a new class within FLUID using the New->Code->Class +menu item. Name the class "CubeViewUI" and leave the +subclass blank. We do not need any inheritance for this +window. You should see the new class declaration in the FLUID +browser window. + +

+Figure 9-3: FLUID file for CubeView.
Click on the CubeViewUI class in the FLUID window and add a new method +by selecting New->Code->Function/Method. The name of the +function will also be CubeViewUI. FLUID will understands that this will +be the constructor for the class and will generate the appropriate +code. Make sure you declare the constructor public. + +
Then add a window to the CubeViewUI class. Highlight the name of +the constructor in the FLUID browser window and click on +New->Group->Window. In a similar manner add the +following to the CubeViewUI constructor: + +
None of these additions need be public. And they shouldn't be +unless you plan to expose them as part of the interface for +CubeViewUI. + +
When you are finished you should have something like this: + +

+Figure 9-4: FLUID window containing CubeView demo.
We will talk about the show() method that is highlighted +shortly. + +
What we have is nice, but does little to show our cube. We have already +defined the CubeView class and we would like to show it within the +CubeViewUI. + +
The CubeView class inherits the Fl_Gl_Window class, which +is created in the same way as a Fl_Box widget. Use +New->Other->Box to add a square box to the main window. +This will be no ordinary box, however. + +
The Box properties window will appear. The key to letting CubeViewUI +display CubeView is to enter CubeView in the "Class:" text +entry box. This tells FLUID that it is not an Fl_Box, but a +similar widget with the same constructor. In the "Extra +Code:" field enter #include "CubeView.h" + +
This #include is important, as we have just included +CubeView as a member of CubeViewUI, so any public CubeView methods are +now available to CubeViewUI. + +

+Figure 9-5: CubeView methods.
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 +ypan slider is: + +
+cube->pany(((Fl_Slider *)o)->value()); +cube->redraw(); ++ +
We call cube->redraw() after changing the value to update +the CubeView window. CubeView could easily be modified to do this, but +it is nice to keep this exposed in the case where you may want to do +more than one view change only redrawing once saves a lot of time. + +
There is no reason 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. + +
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. + +
Make sure the top level CubeViewUI is selected and select +New->Code->Function/Method. Just use the name +show(). We don't need a return value here, and since we will +not be adding any widgets to this method FLUID will assign it a return +type of void. + +

+Figure 9-6: CubeView constructor.
Once the new method has been added, highlight its name and select +New->Code->Code. Enter the method's code in the code window. + +
If you need to add code to initialize class, for example setting +initial values of the horizontal and vertical angles in the +CubeView, you can simply highlight the Constructor and select +New->Code->Code. Add any required code. + +
Now that we have completely defined the CubeViewUI, we have to generate +the code. There is one last trick to ensure this all works. Open the +preferences dialog from Edit->Preferences. + +
At the bottom of the preferences dialog box is the key: "Include +Header from Code". Select that option and set your desired file +extensions and you are in business. You can include the CubeViewUI.h +(or whatever extension you prefer) as you would any other C++ class. + + + +
The following sections describe each of the windows in FLUID. + +
The main window shows a menu bar and a scrolling browser of +all the defined widgets. The name of the .fl file being +edited is shown in the window title. + +
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 parents, and all the widgets +listed below them are their children. Parents don't have to have +any children.
+ +The top level of the hierarchy is composed of functions and +classes. Each of these will produce a single C++ public +function or class in the output .cxx file. Calling the function or +instantiating the class will create all of the child widgets.
+ +The second level of the hierarchy contains the windows. Each of these +produces an instance of class Fl_Window.
+ +Below that are either widgets (subclasses of Fl_Widget) or +groups of widgets (including other groups). Plain groups are for +layout, navigation, and resize purposes. Tab groups provide the +well-known file-card tab interface.
+ +Widgets are shown in the browser by either their name (such +as "main_panel" in the example), or by their type +and label (such as "Button "the green"").
+ +You select 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. + +
You open 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).
+ +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:
+ +Discards the current editing session and reads in a different +.fl file. You are asked for confirmation if you have +changed the current file. + +
FLUID can also read .fd 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 .fd 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 +.fd file with its own format, which fdesign cannot +read!
+ +Inserts the contents of another .fl file, without +changing the name of the current .fl 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. + +
Writes the current data to the .fl file. If the +file is unnamed then FLUID will ask for a filename. + +
Asks for a new filename and saves the file. + +
"Compiles" the data into a .cxx and .h +file. These are exactly the same as the files you get when you run +FLUID with the -c switch. + +
The output file names are the same as the .fl file, with +the leading directory and trailing ".fl" stripped, and +".h" or ".cxx" appended.
+ +Writes a message file for all of the text labels defined in +the current file. + +
The output file name is the same as the .fl file, +with the leading directory and trailing ".fl" +stripped, and ".txt", ".po", or +".msg" appended depending on the Internationalization Mode.
+ +Exits FLUID. You are asked for confirmation if you have +changed the current file. + +
This isn't implemented yet. You should do save often so you can +recover from any mistakes you make. + +
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. + +
Copies the selected widgets and all of their children to the +"clipboard" file. + +
Pastes the widgets from the clipboard file. + +
If the widget is a window, it is added to whatever function +is selected, or contained in the current selection.
+ +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.
+ +To avoid confusion, it is best to select exactly one widget +before doing a paste.
+ +Cut/paste is the only way to change the parent of a +widget.
+ +Selects all widgets in the same group as the current +selection. + +
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.
+ +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. + +
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. + +
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. + +
Moves all of the selected widgets one later in order among +the children of their parent (if possible). + +
Creates a new Fl_Group and make all the currently +selected widgets children of it. + +
Deletes the parent group if all the children of a group are +selected. + +
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. + +
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. + +
The internationalization options are described later in this chapter. + +

+Figure 9-7: FLUID Preferences Window.
Displays the GUI settings panel. This panel is used +to control the user interface settings. + +
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. + +
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 (void).
+ +It is possible to make the .cxx output be a +self-contained program that can be compiled and executed. This +is done by deleting the function name so +main(argc,argv) is used. The function will call +show() on all the windows it creates and then call +Fl::run(). This can also be used to test resize +behavior or other parts of the user interface.
+ +You can change the function name by double-clicking on the +function.
+ +Creates a new Fl_Window 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. + +
The widget panel will also appear and is described later in +this chapter.
+ +All other items on the New menu are subclasses of +Fl_Widget. 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. + +
When you create the widget you will get the widget's control +panel, which is described later in this chapter.
+ + +Align all selected widgets to the first widget in the selection. + +
Space all selected widgets evenly inside the selected space. +Widgets will be sorted from first to last. + +
Make all slected widgets the same size as the first selected widget. + +
Center all selected widgets relative to their parent widget + +
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. + + +
Displays the shell command panel. The shell command +is commonly used to run a 'make' script to compile the FLTK output. + +
Run the shell command again. + +
Pops up a panel showing the version of FLUID. + +
Shows this chapter of the manual. + +
Shows the contents page of the manual + +
When you double-click on a widget or a set of widgets you +will get the "widget attribute panel". + +
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. + +
If you have several widgets selected, they may have different +values for the fields. In this case the value for one of +the widgets is shown. But if you change this value, all +of the selected widgets are changed to the new value. + +
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. + +
"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. + + +

+Figure 9-8: The FLUID widget GUI attributes.
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.
+ +Symbols can be added to the +label using the at sign ("@"). + +
How to draw the label. Normal, shadowed, engraved, and +embossed change the appearance of the text. + +
The active image for the widget. Click on the +Browse... button to pick an image file using the file +chooser. + +
The inactive image for the widget. Click on the +Browse... button to pick an image file using the file +chooser. + +
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. + +
The clip button clips the label to the widget box, the +wrap button wraps any text in the label, and the text +image button puts the text over the image instead of under +the image. + +
The position fields show the current position and size of the +widget box. Enter new values to move and/or resize a widget. + +
The values and limits of the current widget. Depending on the +type of widget, some or all of these fields may be inactive. + +
The shortcut key to activate the widget. Click on the +shortcut button and press any key sequence to set the shortcut. + +
The Visible 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. + +
The Active button controls whether the widget is +activated (on) or deactivated (off) initially. Most widgets +appear greyed out when deactivated. + +
The Resizable 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 +not the same as what will happen in the user program.
+ +The Hotspot button causes the parent window to be +positioned with that widget centered on the mouse. This +position is determined when the FLUID function is called, +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 +show(). + +
The Border 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. + +
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. + + +

+Figure 9-9: The FLUID widget Style attributes.
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. + +
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. + +
Color to draw the label. Ignored by pixmaps (bitmaps, +however, do use this color as the foreground color). + +
The boxtype to draw as a background for the widget. + +
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.
+ +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.
+ +The boxtype to draw when a button is pressed or for some +parts of other widgets like scrollbars and valuators. + +
The color to draw the box with.
+ +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.
+ +Some widgets display text, such as input fields, pull-down +menus, and browsers. + + +

+Figure 9-10: The FLUID widget C++ attributes.
This is how you use your own subclasses of +Fl_Widget. Whatever identifier you type in here will +be the class that is instantiated. + +
In addition, no #include header file is put in the +.h file. You must provide a #include line as +the first line of the "Extra Code" which declares your +subclass.
+ +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.
+ +Some classes have subtypes that modify their appearance or behavior. +You pick the subtype off of this menu. + +
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. + +
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.
+ +Controls whether the widget is publicly accessible. When +embedding widgets in a C++ class, this controls whether the +widget is public or private in the class. +Otherwise is controls whether the widget is declared +static or global (extern). + +
These four fields let you type in literal lines of code to +dump into the .h or .cxx files. + +
If the text starts with a # or the word +extern then FLUID thinks this is an "include" +line, and it is written to the .h file. If the same +include line occurs several times then only one copy is +written.
+ +All other lines are "code" lines. The current +widget is pointed to by the local variable o. The +window being constructed is pointed to by the local variable +w. You can also access any arguments passed to the +function here, and any named widgets that are before this +one.
+ +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 .cxx +code.
+ +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. + +
A name names a function in your own code. It must be +declared as void name(<class>*,void*).
+ +A code snippet is inserted into a static function in the +.cxx output file. The function prototype is void +name(class *o, void *v) so that you can refer to the +widget as o and the user_data() as +v. 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 the callback is blank then no callback is set.
+ +This is a value for the user_data() 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 void pointer. + +
The void * in the callback function prototypes is +replaced with this. You may want to use long for old +XForms code. Be warned that anything other than void * +is not guaranteed to work! However on most architectures other +pointer types are ok, and long is usually ok, too. + +
When to do the callback. This can be Never, +Changed, Release, or Enter Key. The value of +Enter Key is only useful for text input fields. + +
There are other rare but useful values for the +when() field that are not in the menu. You should use +the extra code fields to put these values in.
+ +The No Change button means the callback is done on the +matching event even if the data is not changed. + +
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 ESC. + +
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.
+ +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.
+ +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.
+ +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.
+ +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.
+ +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.
+ +Type Ctrl+o to temporarily toggle the overlay off without +changing the selection, so you can see the widget borders.
+ +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.
+ +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:
+ +The contents of the image files in the Image +and Inactive text fields are written to the .cxx +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.
+ +However, the filenames are stored in the .fl +file so you will need the image files as well to read the +.fl file. Filenames are relative to the location of the +.fl file and not necessarily the current directory. We +recommend you either put the images in the same directory as the +.fl file, or use absolute path names.
+ +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. + +
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.
+ +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 +.fl file.
+ +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.
+ +To more accurately place images, make a new "box" +widget and put the image in that as the label.
+ +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. + +
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.
+ +The program "bitmap" on the X distribution does an +adequate job of editing bitmaps.
+ +FLUID reads X pixmap files as used by the libxpm +library. These files use C source code to define a pixmap. The +filenames usually have the ".xpm" extension. + +
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.
+ +We have not found any good editors for small iconic pictures. +For pixmaps we have used XPaint +and the KDE icon editor.
+ +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 .bmp file.
+ +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 .gif file. Only +the first image of an animated GIF file is used.
+ +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. + +
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. + +
FLUID supports internationalization (I18N for short) of label +strings used by widgets. The preferences window +(Ctrl+p) provides access to the I18N options. + +
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. + +
The "GNU gettext" method uses GNU gettext (or a similar +text-based I18N library) to retrieve a localized string before +calling the widget constructor. + +
The "POSIX catgets" method uses the POSIX catgets function to +retrieve a numbered message from a message catalog before +calling the widget constructor. + +
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 setlocale() and textdomain() or +bindtextdomain() to select the appropriate language and +message file. + +
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. + +

+Figure 9-11: Internationalization using GNU gettext.
The "#include" field controls the header file to include for +I18N; by default this is <libintl.h>, the +standard I18N file for GNU gettext. + +
The "Function" field controls the function (or macro) that +will retrieve the localized message; by default the +gettext function will be called. + +
FLUID's code support for POSIX catgets allows you to use a +global message file for all interfaces or a file specific to +each .fl file; you still need to call +setlocale() to select the appropriate language. + +
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. + +

+Figure 9-12: Internationalization using POSIX catgets.
The "#include" field controls the header file to include for +I18N; by default this is <nl_types.h>, the +standard I18N file for POSIX catgets. + +
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 +.fl file. + +
The "Set" field controls the set number in the catalog file. +The default set is 1 and rarely needs to be changed. + +
#if 0 and #endif
+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
+
+This appendix describes the Forms compatibility included with FLTK. +
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, +<FL/forms.H>.
+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.
+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.
+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 forms.H a lot.
+Many parts of XForms use X-specific structures like XEvent + 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.
+Fl_Free widgets emulate +the old Forms "free" widget. It may be useful for porting +programs that change the handle() function on widgets, but you +will still need to rewrite things.
+Fl_Timer widgets are +provided to emulate the XForms timer. These work, but are quite +inefficient and inaccurate compared to using +Fl::add_timeout().
+All instance variables are hidden. 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()".
+const char * arguments to most FLTK methods are simply +stored, while Forms would strdup() 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 +label(). If you are using labels to display program output you +may want to try the Fl_Output + widget.
+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.
+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 user_data() + 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.
+The prototype for the functions passed to fl_add_timeout() + and fl_set_idle_callback() callback are different.
+All the following XForms calls are missing:
+None of this works with FLTK. Nor will it compile, the necessary +calls are not in the interface.
+You have to make a subclass of +Fl_Gl_Window and write a draw() method and +handle() method. This may require anywhere from a trivial to a +major rewrite.
+If you draw into the overlay planes you will have to also write a +draw_overlay() method and call redraw_overlay() on the +OpenGL window.
+One easy way to hack your program so it works is to make the +draw() and handle() methods on your window set some +static variables, storing what event happened. Then in the main loop +of your program, call Fl::wait() and then check these +variables, acting on them as though they are events read from +fl_queue.
+The file <FL/gl.h> defines replacements for a lot of IRISGL +calls, translating them to OpenGL. There are much better translators +available that you might want to investigate.
+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.
+If your subclass draws into the overlay you are in trouble and will +have to rewrite things a lot.
+| Forms | FLTK |
|---|---|
| MOUSE_X | Fl::event_x_root() |
| MOUSE_Y | Fl::event_y_root() |
| LEFTSHIFTKEY,RIGHTSHIFTKEY | Fl::event_shift() |
| CAPSLOCKKEY | Fl::event_capslock() |
| LEFTCTRLKEY,RIGHTCTRLKEY | Fl::event_ctrl() |
| LEFTALTKEY,RIGHTALTKEY | Fl::event_alt() |
| MOUSE1,RIGHTMOUSE | Fl::event_state() |
| MOUSE2,MIDDLEMOUSE | Fl::event_state() |
| MOUSE3,LEFTMOUSE | Fl::event_state() |
+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*"); ++ +*/ 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 + +
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.
+You should be able to compile existing GLUT source code by including <FL/glut.H> instead of <GL/glut.h>. This can be done by editing the source, by changing the -I switches to the compiler, or by providing a symbolic link from GL/glut.h to FL/glut.H.
+All files calling GLUT procedures must be compiled with C++. 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.
+You must link with the FLTK library. Most of FL/glut.H is inline functions. You should take a look at it (and maybe at test/glpuzzle.cxx in the FLTK source) if you are having trouble porting your GLUT program.
+This has been tested with most of the demo programs that come with the GLUT and FreeGLUT distributions.
+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: +
The strings passed as menu labels are not copied.
+glutPostRedisplay() does not work if called from inside a +display function. You must use glutIdleFunc() if you want +your display to update continuously.
+glutSwapBuffers() does not work from inside a display +function. This is on purpose, because FLTK swaps the buffers for you.
+glutUseLayer() does not work well, and should only be used +to initialize transformations inside a resize callback. You should +redraw overlays by using glutOverlayDisplayFunc().
+Overlays are cleared before the overlay display function is called. +glutLayerGet(GLUT_OVERLAY_DAMAGED) always returns true for +compatibility with some GLUT overlay programs. You must rewrite your +code so that gl_color() is used to choose colors in an +overlay, or you will get random overlay colors.
+glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR) just results in a +small crosshair.
+The fonts used by glutBitmapCharacter() and glutBitmapWidth() + may be different.
+glutInit(argc,argv) will consume different switches than +GLUT does. It accepts the switches recognized by +Fl::args(), and will accept any abbreviation of these +switches (such as "-di" for "-display").
++Fl_Gl_Window + | + +----Fl_Glut_Window ++ +
+#include <FL/glut.H> ++ +
The current GLUT window is available in the global variable +glut_window.
+new Fl_Glut_Window(...) is the same as +glutCreateWindow() except it does not show() the window +or make the window current.
+window->make_current() is the same as +glutSetWindow(number). If the window has not had show() + called on it yet, some functions that assumme an OpenGL context will +not work. If you do show() the window, call make_current() + again to set the context.
+~Fl_Glut_Window() is the same as glutDestroyWindow() +.
+| member | +description | +
|---|---|
| display | +A pointer to the function to call to draw the normal planes. | +
| entry | +A pointer to the function to call when the mouse moves into + or out of the window. | +
| keyboard | +A pointer to the function to call when a regular key is pressed. | +
| menu[3] | +The menu to post when one of the mouse buttons is pressed. | +
| mouse | +A pointer to the function to call when a button is pressed or + released. | +
| motion | +A pointer to the function to call when the mouse is moved with + a button down. | +
| overlaydisplay | +A pointer to the function to call to draw the overlay planes. | +
| passivemotion | +A pointer to the function to call when the mouse is moved with + no buttons down. | +
| reshape | +A pointer to the function to call when the window is resized. | +
| special | +A pointer to the function to call when a special key is pressed. | +
| visibility | +A pointer to the function to call when the window is iconified + or restored (made visible.) | +
| + |
+
\subpage preface
-
- - - 1 - Introduction to FLTK - - - 2 - FLTK Basics - - - 3 - Common Widgets and Attributes + + \subpage intro + + \subpage basics + + \subpage common +
- - 5 - Drawing Things in FLTK - - - 6 - Handling Events + + + \subpage editor + + \subpage drawing + + \subpage events + - 7 - Adding and Extending - Widgets - - - 8 - Using OpenGL + + + \subpage subclassing + + \subpage opengl + |
+
- 9 - Programming with FLUID
+
+ \subpage fluid
+
-
+
+
\subpage advanced
-
- - + A - Class Reference - - + B - Function Reference - - - C - FLTK Enumerations.H - - - - D - GLUT Compatibility + + \subpage enumerations + + \subpage glut + - E - Forms Compatibility - - - F - Operating System Issues - - - G - Migrating Code from FLTK 1.0.x - - - H - Software License - - - I - Example Source Code - |
+
+
+ \subpage forms
+
+ \subpage osissues
+
+ \subpage migration_1_1
+
+ \subpage migration_1_3
+
+ \subpage license
+
+ \subpage examples
+
+
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.
+ +It has always been Bill's belief that the GUI API of all +modern systems is much too high level. Toolkits (even FLTK) are +not 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 unalterable 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.
+ +Many of the ideas in FLTK were developed on a NeXT (but +not 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.
+ +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.
+ +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.
+ +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.
+ +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.
+ +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.
+ +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.
+ +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.
+ +Here are some of the core features unique to FLTK:
+ +FLTK comes with complete free source code. FLTK is available +under the terms of the GNU Library +General Public License with exceptions that allow for static +linking. Contrary to popular belief, it can be used in +commercial software - even Bill Gates could use it!
+ +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".
+ +In most cases you can just type "make". This will +run configure with the default of no options and then compile +everything.
+ +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 CFLAGS, +CXXFLAGS, and LDFLAGS environment variables. +For the Bourne and Korn shells you'd use:
+ ++CFLAGS=-Iincludedir; export CFLAGS +CXXFLAGS=-Iincludedir; export CXXFLAGS +LDFLAGS=-Llibdir; export LDFLAGS ++ +
For C shell and tcsh, use:
+ ++setenv CFLAGS "-Iincludedir" +setenv CXXFLAGS "-Iincludedir" +setenv LDFLAGS "-Llibdir" ++ +
By default configure will look for a C++ compiler named +CC, c++, g++, or gcc in that +order. To use another compiler you need to set the CXX +environment variable:
+ ++CXX=xlC; export CXX +setenv CXX "xlC" ++ +
The CC environment variable can also be used to +override the default C compiler (cc or gcc), +which is used for a few FLTK source files.
+ +You can run configure yourself to get the exact setup you +need. Type "./configure <options>", where +options are:
+ +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.
+ +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".
+ +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.
+ +The second method is to use the configure script +included with the FLTK software; this has only been tested with +the CygWin tools:
+ ++sh configure --prefix=C:/FLTK +make ++ +
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:
+ ++copy makefiles\Makefile.<env> Makefile +make ++ +
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.
+ +When compiling an application or DLL that uses the FLTK DLL, +you will need to define the FL_DLL preprocessor symbol +to get the correct linkage commands embedded within the FLTK +header files.
+ +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!).
+ +The current set of Makefiles/configuration failes assumes that +EMX 0.9d and libExt +(from posix2.sourceforge.net) +is installed. + +
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:
+ ++copy makefiles\Makefile.os2x Makefile +make ++ +
FLTK is available on the 'net in a bunch of locations:
+ +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.
+ +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.
+ +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.
+ +Bugs can also be reported to the "fltk.bugs" newsgroup or on the +SourceForge bug tracker pages.
+ +For general support and questions, please use the FLTK mailing list +at "fltk@fltk.org" or one of the newsgroups.
+ +*/ 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 + +December 11, 2001
+ +The FLTK library and included programs are provided under the terms +of the GNU Library General Public License (LGPL) with the following +exceptions:
+ +GNU LIBRARY GENERAL PUBLIC LICENSE
+Version 2, June 1991
+
Copyright (C) 1991 Free Software Foundation, Inc.
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
Everyone is permitted to copy and distribute verbatim copies of
+this license document, but changing it is not allowed.
+
[This is the first released version of the library GPL. It is
+numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
+ 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. +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.
+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.
+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.
+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.
+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.
+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.
+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.
+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.
+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.
+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.
+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.
+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.
+Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one.
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND +MODIFICATION
+0. 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". +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.
+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".)
+"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.
+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.
+1. 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.
+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.
+2. 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:
+a) The modified work must itself be a software +library. ++b) You must cause the files modified to carry +prominent notices stating that you changed the files and the date of +any change.
+c) You must cause the whole of the work to be +licensed at no charge to all third parties under the terms of this +License.
+d) 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.
+(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.)
+
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.
+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.
+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.
+3. 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.
+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.
+This option is useful when you wish to copy part of the code of the +Library into a program that is not a library.
+4. 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.
+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.
+5. 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.
+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.
+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.
+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.)
+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.
+6. 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.
+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:
a) 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.) ++b) 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.
+c) 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.
+d) Verify that the user has already received a copy +of these materials or that you have already sent this user a copy.
+
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.
+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.
+7. 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:
+a) 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. ++b) 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.
+
8. 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.
+9. 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.
+10. 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.
+11. 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.
+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.
+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.
+This section is intended to make thoroughly clear what is believed +to be a consequence of the rest of this License.
+12. 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.
+13. 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.
+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.
+14. 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.
+NO WARRANTY
+15. 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.
+16. 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.
+END OF TERMS AND CONDITIONS
+ +*/ 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 + +This appendix describes the differences between the FLTK +1.0.x and FLTK 1.1.x functions and classes.
+ +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. + +
FL_BLACK and FL_WHITE now remain black and +white, even if the base color of the gray ramp is changed using +Fl::background(). +FL_DARK3 and FL_LIGHT3 can be used instead to +draw a very dark or a very bright background hue.
+ +Widgets use the new color symbols FL_FORGROUND_COLOR, +FL_BACKGROUND_COLOR, FL_BACKGROUND2_COLOR, +FL_INACTIVE_COLOR, and FL_SELECTION_COLOR. +More details can be found in the chapter +Enumerations.
+ +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. + +
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 FCB class or members will need +to be ported to the new Fl_File_Chooser +class.
+ +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 FLTK_1_0_COMPAT
+symbol on the command-line when you compile
+(-DFLTK_1_0_COMPAT) or in your source, e.g.:
+
+
+#define FLTK_1_0_COMPAT +#include <FL/Fl.H> +#include <FL/Enumerations.H> +#include <FL/filename.H> ++ +
The following table shows the old and new function names:
+ +| Old 1.0.x Name | +New 1.1.x Name | +
|---|---|
| contrast() | +fl_contrast() | +
| down() | +fl_down() | +
| filename_absolute() | +fl_filename_absolute() | +
| filename_expand() | +fl_filename_expand() | +
| filename_ext() | +fl_filename_ext() | +
| filename_isdir() | +fl_filename_isdir() | +
| filename_list() | +fl_filename_list() | +
| filename_match() | +fl_filename_match() | +
| filename_name() | +fl_filename_name() | +
| filename_relative() | +fl_filename_relative() | +
| filename_setext() | +fl_filename_setext() | +
| frame() | +fl_frame() | +
| inactive() | +fl_inactive() | +
| numericsort() | +fl_numericsort() | +
Image support in FLTK has been significantly revamped in +1.1.x. The Fl_Image class +is now a proper base class, with the core image drawing +functionality in the Fl_Bitmap, Fl_Pixmap, and Fl_RGB_Image classes. + +
BMP, GIF, JPEG, PNG, XBM, and XPM image files can now be +loaded using the appropriate image classes, and the Fl_Shared_Image class +can be used to cache images in memory. + +
Image labels are no longer provided as an add-on label type. +If you use the old label() methods on an image, the +widget's image() method is called to set the image +as the label. + +
Image labels in menu items must still use the old labeltype +mechanism to preserve source compatibility. + +
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 Fl::visible_focus()
+method to disable it:
+
+
+Fl::visible_focus(0); ++ +*/ 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 + +
This appendix describes the differences between the FLTK +1.1.x and FLTK 1.3.x functions and classes.
+ +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 + +This chapter discusses using FLTK for your OpenGL applications. + +
The easiest way to make an OpenGL display is to subclass Fl_Gl_Window. +Your subclass must implement a draw() method which uses +OpenGL calls to draw the display. Your main program should call +redraw() when the display needs to change, and +(somewhat later) FLTK will call draw(). + +
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 gl_start() and gl_finish() functions around your +OpenGL code.
+ +You must include FLTK's <FL/gl.h> header +file. It will include the file <GL/gl.h>, define +some extra drawing functions provided by FLTK, and include the +<windows.h> header file needed by WIN32 +applications.
+ +To make a subclass of Fl_Gl_Window, you must provide: + +
If your subclass provides static controls in the window, they +must be redrawn whenever the FL_DAMAGE_ALL bit is set +in the value returned by damage(). For double-buffered +windows you will need to surround the drawing code with the +following code to make sure that both buffers are redrawn: + +
+#ifndef MESA +glDrawBuffer(GL_FRONT_AND_BACK); +#endif // !MESA +... draw stuff here ... +#ifndef MESA +glDrawBuffer(GL_BACK); +#endif // !MESA ++ +
| Note:
+
+ If you are using the Mesa graphics library, the call + to glDrawBuffer() is not required and will slow + down drawing considerably. The preprocessor instructions + shown above will optimize your code based upon the + graphics library used. + + |
+
+
To define the subclass you just subclass the +Fl_Gl_Window class: + +
+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) {}
+};
+
+
+The draw() and handle() methods are +described below. Like any widget, you can include additional +private and public data in your class (such as scene graph +information, etc.) + +
The draw() method is where you actually do your +OpenGL drawing: + +
+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 ...
+}
+
+
+The handle() method handles mouse and keyboard +events for the window: + +
+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);
+ }
+}
+
+
+When handle() is called, the OpenGL context is not +set up! If your display changes, you should call +redraw() and let draw() do the work. Don't +call any OpenGL drawing functions from inside handle()! + +
You can call some OpenGL stuff like hit detection and texture +loading functions by doing:
+ +
+ 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...
+
+
+Your main program can now create one of your windows by doing +new MyWindow(...). You can also use FLUID by: + +
You must put glwindow->show() in your main code +after calling show() on the window containing the +OpenGL window. + +
You can put OpenGL code into an Fl_Widget::draw() +method or into the code for a boxtype or other places with some +care. + +
Most importantly, before you show any windows, +including those that don't have OpenGL drawing, you must +initialize FLTK so that it knows it is going to use OpenGL. You +may use any of the symbols described for Fl_Gl_Window::mode() +to describe how you intend to use OpenGL:
+ ++Fl::gl_visual(FL_RGB); ++ +
You can then put OpenGL drawing code anywhere you can draw +normally by surrounding it with: + +
+gl_start(); +... put your OpenGL code here ... +gl_finish(); ++ +
gl_start() and gl_finish() 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 glScissor() +commands. These functions also synchronize the OpenGL graphics stream +with the drawing done by other X, WIN32, or FLTK functions. + +
The same context is reused each time. If your code changes +the projection transformation or anything else you should use +glPushMatrix() and glPopMatrix() functions to +put the state back before calling gl_finish().
+ +You may want to use Fl_Window::current()->h() to +get the drawable height so that you can flip the Y +coordinates.
+ +Unfortunately, there are a bunch of limitations you must +adhere to for maximum portability:
+ +Do not call gl_start() or +gl_finish() when drawing into an Fl_Gl_Window! + +
FLTK provides some useful OpenGL drawing functions. They can +be freely mixed with any OpenGL calls, and are defined by +including <FL/gl.H> which you should include +instead of the OpenGL header <GL/gl.h>. + +
Sets the current OpenGL color to a FLTK color. For +color-index modes it will use fl_xpixel(c), which is +only right if this window uses the default colormap! + +
Outlines or fills a rectangle with the current color. If Fl_Gl_Window::ortho() +has been called, then the rectangle will exactly fill the pixel +rectangle passed. + +
Sets the current OpenGL font to the same font you get by +calling fl_font(). + +
Returns information about the current OpenGL font. + +
Draws a nul-terminated string or an array of n +characters in the current OpenGL font at the current raster +position. + +
Draws a nul-terminated string or an array of n +characters in the current OpenGL font at the given position. + +
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 fl_draw(). + +
Performance of Fl_Gl_Window may be improved on some types of +OpenGL implementations, in particular MESA and other software +emulators, by setting the GL_SWAP_TYPE environment +variable. This variable declares what is in the backbuffer after +you do a swapbuffers. + +
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.
+ +
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.
+ +
This is easily tested by running the gl_overlay 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. + +
OpenGL +Optimizer 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. + +
To use OpenGL Optimizer with FLTK you'll need to create a +subclass of Fl_Gl_Widget that includes several state +variables: + +
+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();
+ }
+ }
+};
+
+
+The camera() method sets the camera (projection and +viewpoint) to use when drawing the scene. The scene is redrawn after +this call. + +
The draw() method performs the needed initialization and does +the actual drawing: + +
+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_);
+}
+
+
+The scene() method sets the scene to be drawn. The scene is +a collection of 3D objects in a csGroup. 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 + +
This appendix describes the operating system specific interfaces in FLTK. + +
All programs that need to access the operating system +specific interfaces must include the following header file: + +
+#include <FL/x.H> ++ +
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. + +
| WARNING:
+
+ 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. + + |
+
The UNIX interface provides access to the X Window System +state information and data structures. + +
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. + +
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 fl_xevent variable.
+ +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 +FL_SHORTCUT.
+ +This variable contains the most recent X event. + +
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. + +
Returns the XID for a window, or zero if not shown(). + +
Returns the Fl_Window that corresponds to the given +XID, or NULL if not found. This function uses a cache +so it is slightly faster than iterating through the windows +yourself.
+ +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 add_handler() +functions all return 0, this function will return false. + +
Besides feeding events your code should call Fl::flush() +periodically so that FLTK redraws its windows.
+ +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 fl_ask(), for +instance, it will not return until the modal function +returns.
+ +The following global variables are set before Fl_Widget::draw() is +called, or by Fl_Window::make_current(): + +
+extern Display *fl_display; +extern Window fl_window; +extern GC fl_gc; +extern int fl_screen; +extern XVisualInfo *fl_visual; +extern Colormap fl_colormap; ++ +
You must use them to produce Xlib calls. Don't attempt to change +them. A typical X drawing call is written like this: + +
+XDrawSomething(fl_display, fl_window, fl_gc, ...); ++ +
Other information such as the position or size of the X +window can be found by looking at Fl_Window::current(), +which returns a pointer to the Fl_Window being drawn. + +
Returns the X pixel number used to draw the given FLTK color +index or RGB color. This is the X pixel that fl_color() would use. + +
Convert a name into the red, green, and blue values of a color +by parsing the X11 color names. On other systems, fl_parse_color +can only convert names in hexadecimal encoding, for example #ff8083. + +
Points to the font selected by the most recent fl_font(). This is not +necessarily the current font of fl_gc, which is not set +until fl_draw() is +called. If FLTK was compiled with Xft support, fl_xfont +will usually be 0 and fl_xftfont will contain a pointer +to the XftFont structure instead. + +
If FLTK was compiled with Xft support enabled, fl_xftfont +Points to the xft font selected by the most recent fl_font(). Otherwise +it will be 0. fl_xftfont should be cast to +XftFont*. + +
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 before the first +Fl_Window::show() is called. You may also want to +call Fl::visual(), which is +a portable interface to get a full color and/or double buffered +visual. + +
Set which X display to use. This actually does +putenv("DISPLAY=...") so that child programs +will display on the same screen if called with exec(). +This must be done before the display is opened. This call is +provided under MacOS and WIN32 but it has no effect. + +
The open X display. This is needed as an argument to most +Xlib calls. Don't attempt to change it! This is NULL +before the display is opened. + +
Opens the display. Does nothing if it is already open. This +will make sure fl_display 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 show() of a +window. + +
This may call Fl::abort() if there is an error +opening the display.
+ +This closes the X connection. You do not 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. + +
Which screen number to use. This is set by +fl_open_display() 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 +Fl::display() string to "host:0.#". + +
The visual and colormap that FLTK will use for all windows. +These are set by fl_open_display() to the default +visual and colormap. You can change them before calling +show() on the first window. Typical code for changing +the default visual is: + +
+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);
+
+
+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 draw() method +that uses Xlib (and/or OpenGL) calls only. + +
FLTK can also manage XID's provided by other libraries or +programs, and call those libraries when the window needs to be +redrawn.
+ +To do this, you need to make a subclass of Fl_Window and +override some of these virtual functions:
+ +If the window is already shown() this must cause it +to be raised, this can usually be done by calling +Fl_Window::show(). If not shown() your +implementation must call either Fl_X::set_xid() or +Fl_X::make_xid(). + +
An example:
+ +
+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);
+}
+
+
+Allocate a hidden structure called an Fl_X, put the +XID into it, and set a pointer to it from the +Fl_Window. This causes Fl_Window::shown() to +return true. + +
This static method does the most onerous parts of creating an +X window, including setting the label, resize limitations, etc. +It then does Fl_X::set_xid() with this new window and +maps the window. + +
This virtual function is called by Fl::flush() to +update the window. For FLTK's own windows it does this by +setting the global variables fl_window and +fl_gc and then calling the draw() method. For +your own windows you might just want to put all the drawing code +in here. + +
The X region that is a combination of all damage() +calls done so far is in Fl_X::i(this)->region. If +NULL then you should redraw the entire window. The +undocumented function fl_clip_region(XRegion) will +initialize the FLTK clip stack with a region or NULL +for no clipping. You must set region to NULL afterwards +as fl_clip_region() will own and delete it when +done.
+ +If damage() & FL_DAMAGE_EXPOSE then only X +expose events have happened. This may be useful if you have an +undamaged image (such as a backing buffer) around.
+ +Here is a sample where an undamaged image is kept somewhere:
+ +
+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 ...
+}
+
+
+Destroy the window server copy of the window. Usually you +will destroy contexts, pixmaps, or other resources used by the +window, and then call Fl_Window::hide() to get rid of +the main window identified by xid(). If you override +this, you must also override the destructor as shown: + +
+void MyWindow::hide() {
+ if (mypixmap) {
+ XFreePixmap(fl_display,mypixmap);
+ mypixmap = 0;
+ }
+ Fl_Window::hide(); // you must call this
+}
+
+
+Because of the way C++ works, if you override hide() +you must override the destructor as well (otherwise only +the base class hide() is called): + +
+MyWindow::~MyWindow() {
+ hide();
+}
+
+
+FLTK currently supports setting a window's icon before it +is shown using the Fl_Window::icon() method. + +
Sets the icon for the window to the passed pointer. You will +need to cast the icon Pixmap to a char * when +calling this method. To set a monochrome icon using a bitmap compiled +with your application use: + +
+#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); ++ +
To use a multi-colored icon, the XPM format and library +should be used as follows: + +
+#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); ++ +
When using the Xpm library, be sure to include it in the list +of libraries that are used to link the application (usually +"-lXpm").
+ +| NOTE:
+
+ You must call Fl_Window::show(argc, + argv) for the icon to be used. The + Fl_Window::show() method does not bind the icon + to the window. + + |
+
When the Fl_Window::show(argc, +argv) method is called, FLTK looks for the following X +resources: + +
Resources associated with the first window's Fl_Window::xclass() +string are queried first, or if no class has been specified then +the class "fltk" is used (e.g. fltk.background). If no +match is found, a global search is done (e.g. +*background). + +
The Windows interface provides access to the WIN32 GDI +state information and data structures. + +
By default a single WNDCLASSEX called "FLTK" is +created. All Fl_Window's are of this class unless you +use Fl_Window::xclass(). The window class is created +the first time Fl_Window::show() is called. + +
You can probably combine FLTK with other libraries that make +their own WIN32 window classes. The easiest way is to call +Fl::wait(), as it will call DispatchMessage +for all messages to the other windows. If necessary you can let +the other library take over as long as it calls +DispatchMessage(), but you will have to arrange for the +function Fl::flush() to be called regularly so that +widgets are updated, timeouts are handled, and the idle +functions are called.
+ +This variable contains the most recent message read by +GetMessage, which is called by Fl::wait(). 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). + +
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 DefWindowProc(). + +
Returns the window handle for a Fl_Window, or zero +if not shown(). + +
Returns the Fl_Window that corresponds to the given +window handle, or NULL if not found. This function uses +a cache so it is slightly faster than iterating through the +windows yourself. + +
When the virtual function Fl_Widget::draw() is +called, FLTK stores all the silly extra arguments you need to +make a proper GDI call in some global variables: + +
+extern HINSTANCE fl_display; +extern HWND fl_window; +extern HDC fl_gc; +COLORREF fl_RGB(); +HPEN fl_pen(); +HBRUSH fl_brush(); ++ +
These global variables are set before draw() is +called, or by Fl_Window::make_current(). +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 fl_color() and are created as +needed and cached. A typical GDI drawing call is written like +this: + +
+DrawSomething(fl_gc, ..., fl_brush()); ++ +
It may also be useful to refer to Fl_Window::current() +to get the window's size or position. + +
FLTK currently supports setting a window's icon *before* it +is shown using the Fl_Window::icon() method. + +
Sets the icon for the window to the passed pointer. You will +need to cast the HICON handle to a char * when +calling this method. To set the icon using an icon resource +compiled with your application use: + +
+window->icon((char *)LoadIcon(fl_display, MAKEINTRESOURCE(IDI_ICON))); ++ +
You can also use the LoadImage() and related +functions to load specific resolutions or create the icon from +bitmap data. + +
| NOTE:
+
+ You must call Fl_Window::show(argc, + argv) for the icon to be used. The + Fl_Window::show() method does not bind the icon + to the window. + + |
+
WIN32 has a really stupid mode switch stored in the +executables that controls whether or not to make a console +window. + +
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).
+ +FLTK includes a WinMain() function that calls the +ANSI standard main() entry point for you. This +function creates a console window when you use the debug version +of the library.
+ +WIN32 applications without a console cannot write to +stdout or stderr, 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.
+ +The following is a list of known bugs and problems in the WIN32 +version of FLTK: + +
FLTK supports MacOS X using the Apple Carbon library. Older +versions of MacOS are not supported. + +
FLTK maps the Mac 'control' key to FL_CTRL, the +'option' key to FL_ALT and the 'Apple' key to +FL_META. Keyboard events return the key name in +Fl::event_key() and the keystroke translation in +Fl::event_text(). For example, typing Option-Y on a Mac +keyboard will set FL_ALT in Fl::event_state(), +set Fl::event_key() to 'y' and return the Yen symbol in +Fl::event_text(). + +
Returns the window reference for an Fl_Window, or +NULL if the window has not been shown. + +
Returns the Fl_Window that corresponds to the give +window handle, or NULL if not found. FLTK windows that +are children of top-level windows share the WindowRef of the +top-level window. + +
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 FL_CLOSE event to all open +windows. If all windows close, the application will terminate. + +
When the virtual function Fl_Widget::draw() is +called, FLTK has prepared the Window and CGrafPort for drawing. +Clipping and offsets are prepared to allow correct subwindow +drawing. + +
If the FLTK library was compiled using the configuration +flag --enable-quartz, all code inside Fl_Widget::draw() +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 Fl_Window. + +
OS X double-buffers all windows automatically. On OS X, +Fl_Window and Fl_Double_Window are handled +internally in the same way. + +
FLTK does not access the resource fork of an application. +However, a minimal resource fork must be created for OS X +applications + +
| Caution:
+
+ 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". + |
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. + +
FLTK uses UNIX-style filenames and paths. + +
The following is a list of known bugs and problems in the +MacOS version of FLTK: + +
This chapter describes how to add your own widgets or extend existing +widgets in FLTK. +
A control widget typically interacts with the user to receive and/or +display a value of some sort.
+A composite widget widget holds a list of child widgets and handles moving, +sizing, showing, or hiding them as needed. Fl_Group is the +main composite widget widget class in FLTK, and all of the other composite widgets ( +Fl_Pack, Fl_Scroll, Fl_Tabs, Fl_Tile, +and Fl_Window) are subclasses of it.
+You can also subclass other existing widgets to provide a different +look or user-interface. For example, the button widgets are all +subclasses of Fl_Button 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.
++MyClass(int x, int y, int w, int h, const char *label = 0); ++ This will allow the class to be used in FLUID + without problems. +
The constructor must call the constructor for the base class and +pass the same arguments:
+
+MyClass::MyClass(int x, int y, int w, int h, const char *label)
+: Fl_Widget(x, y, w, h, label) {
+// do initialization stuff...
+}
+
+Fl_Widget's protected constructor sets x(), y(),
+w(), h(), and label() to the passed values
+and initializes the other instance variables to:
++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); ++
The second form indicates that a region is damaged. If only these +calls are done in a window (no calls to damage(n)) 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 damage() unless this is a Fl_Window widget.
+The third form returns the bitwise-OR of all damage(n) +calls done since the last draw().
+When redrawing your widgets you should look at the damage bits to +see what parts of your widget need redrawing. The handle() +method can then set individual damage bits to limit the amount of drawing +that needs to be done: +
+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();
+}
+
+Draws a focus box inside the widgets bounding box. The second +form allows you to specify a different bounding box. + +
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.
+The third form draws the label anywhere. It acts as though +FL_ALIGN_INSIDE has been forced on so the label will appear inside +the passed bounding box. This is designed for parent groups to draw +labels with.
+The second version lets you do this test against an arbitrary +string.
+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.
+If you don't have RTTI you can use the clumsy FLTK mechanisim, by +having type() use a unique value. These unique values must +be greater than the symbol FL_RESERVED_TYPE (which is 100). +Look through the header files for FL_RESERVED_TYPE to find an +unused number. If you make a subclass of Fl_Window +you must use FL_WINDOW + n (n must be in the +range 1 to 7).
+Here is a sample handle() method for a widget that acts as +a pushbutton and also accepts the keystroke 'x' to cause the callback:
+
+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);
+ }
+}
+
+
+You must return non-zero if your handle() method +uses the event. If you return zero, the parent widget will try +sending the event to another widget. + +
The draw() virtual method is called when FLTK wants +you to redraw your widget. It will be called if and only if +damage() is non-zero, and damage() will be +cleared to zero after it returns. The draw() method +should be declared protected so that it can't be called from +non-drawing code. + +
The damage() value contains the bitwise-OR of all +the damage(n) 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 +FL_DAMAGE_ALL bit if it thinks the entire widget must +be redrawn, e.g. for an expose event.
+ +Expose events (and the above damage(b,x,y,w,h)) will cause +draw() to be called with FLTK's +clipping turned on. You can greatly speed up redrawing in some +cases by testing fl_not_clipped(x,y,w,h) or fl_clip_box(...) and +skipping invisible parts.
+Besides the protected methods described above, FLTK provides a large +number of basic drawing functions, which are described +below.
+This should not call redraw(), at least if only the +x() and y() change. This is because composite widgets like +Fl_Scroll may have a more efficient way of drawing the new +position.
+Instances of the child widgets may be included in the parent:
+
+class MyClass : public Fl_Group {
+ Fl_Button the_button;
+ Fl_Slider the_slider;
+ ...
+};
+
+ The constructor has to initialize these instances. They are
+automatically add()ed to the group, since the Fl_Group
+ constructor does begin(). Don't forget to call end()
+ or use the Fl_End pseudo-class:
+
+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!
+}
+
+ The child widgets need callbacks. These will be called with a pointer
+to the children, but the widget itself may be found in the parent()
+ pointer of the child. Usually these callbacks can be static private
+methods, with a matching private method:
+
+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());
+}
+
+ If you make the handle() method, you can quickly pass all the
+events to the children using the Fl_Group::handle() method.
+You don't need to override handle() if your composite widget
+does nothing other than pass events to the children:
+
+int MyClass::handle(int event) {
+ if (Fl_Group::handle(event)) return 1;
+ ... handle events that children don't want ...
+}
+
+
+If you override draw() you need to draw all the +children. If redraw() or damage() is called +on a child, damage(FL_DAMAGE_CHILD) is done to the +group, so this bit of damage() can be used to indicate +that a child needs to be drawn. It is fastest if you avoid +drawing anything else in this case: + +
+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
+ }
+ }
+}
+
+Fl_Group provides some protected methods to make drawing
+easier:
+
+Drag'n'drop operations are are initiated by copying data to the +clipboard and calling the function +Fl::dnd(). + +
Drop attempts are handled via events: +
You may want your widget to be a subclass of +Fl_Window, Fl_Double_Window, or +FL_Gl_Window. 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. + +
Subclassing Fl_Windowis almost exactly like +subclassing Fl_Group, and in fact you can easily +switch a subclass back and forth. Watch out for the following +differences:
+ +You may also want to subclass Fl_Window in order to +get access to different visuals or to change other attributes of +the windows. See "Appendix F - Operating +System Issues" for more information. + +*/ -- cgit v1.2.3