"Final" changes for first draft of 1.0 documentation.

git-svn-id: file:///fltk/svn/fltk/trunk@187 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Michael R Sweet 1999-01-07 16:36:11 +00:00
parent 85e6f44959
commit 367f908d8e
19 changed files with 3363 additions and 4035 deletions

View File

@ -53,11 +53,11 @@ after these.
<li><a href="#Fl_Widget.argument">argument</a>
<li><a href="#Fl_Widget.box">box</a>
<li><a href="#Fl_Widget.callback">callback</a>
<li><a href="#Fl_Widget.changed">changed</a>
</ul>
</td>
<td align=left valign=top>
<ul>
<li><a href="#Fl_Widget.changed">changed</a>
<li><a href="#Fl_Widget.clear_changed">clear_changed</a>
<li><a href="#Fl_Widget.color">color</a>
<li><a href="#Fl_Widget.contains">contains</a>
@ -66,27 +66,22 @@ after these.
<li><a href="#Fl_Widget.default_callback">default_callback</a>
<li><a href="#Fl_Widget.do_callback">do_callback</a>
<li><a href="#Fl_Widget.h">h</a>
<li><a href="#Fl_Widget.hide">hide</a>
<li><a href="#Fl_Widget.ih">ih</a>
</ul>
</td>
<td align=left valign=top>
<ul>
<li><a href="#Fl_Widget.init_size">init_size</a>
<li><a href="#Fl_Widget.hide">hide</a>
<li><a href="#Fl_Widget.inside">inside</a>
<li><a href="#Fl_Widget.iw">iw</a>
<li><a href="#Fl_Widget.ix">ix</a>
<li><a href="#Fl_Widget.iy">iy</a>
<li><a href="#Fl_Widget.label">label</a>
<li><a href="#Fl_Widget.labelcolor">labelcolor</a>
<li><a href="#Fl_Widget.labelfont">labelfont</a>
<li><a href="#Fl_Widget.labelsize">labelsize</a>
<li><a href="#Fl_Widget.labeltype">labeltype</a>
<li><a href="#Fl_Widget.parent">parent</a>
</ul>
</td>
<td align=left valign=top>
<ul>
<li><a href="#Fl_Widget.parent">parent</a>
<li><a href="#Fl_Widget.position">position</a>
<li><a href="#Fl_Widget.redraw">redraw</a>
<li><a href="#Fl_Widget.resize">resize</a>
@ -94,12 +89,13 @@ after these.
<li><a href="#Fl_Widget.set_changed">set_changed</a>
<li><a href="#Fl_Widget.show">show</a>
<li><a href="#Fl_Widget.size">size</a>
<li><a href="#Fl_Widget.type">type</a>
<li><a href="#Fl_Widget.user_data">user_data</a>
<li><a href="#Fl_Widget.take_focus">take_focus</a>
</ul>
</td>
<td align=left valign=top>
<ul>
<li><a href="#Fl_Widget.type">type</a>
<li><a href="#Fl_Widget.user_data">user_data</a>
<li><a href="#Fl_Widget.visible">visible</a>
<li><a href="#Fl_Widget.w">w</a>
<li><a href="#Fl_Widget.when">when</a>
@ -150,27 +146,11 @@ way to update the display, such as scrolling from the old position).
<p><tt>position(x,y)</tt> is a shortcut for <tt>resize(x,y,w(),h())</tt>,
and <tt>size(w,h)</tt> is a shortcut for <tt>resize(x(),y(),w,h)</tt>.
<h4><a name="Fl_Widget.ix">short Fl_Widget::ix() const</a><br>
<a name="Fl_Widget.iy">short Fl_Widget::iy() const</a><br>
<a name="Fl_Widget.iw">short Fl_Widget::iw() const</a><br>
<a name="Fl_Widget.ih">short Fl_Widget::ih() const</a><br>
<a name="Fl_Widget.init_size">void Fl_Widget::init_size(int,int,int,int)</a></h4>
The initial size and position of the widget. This is a copy of the
arguments that the constructor was called with. This information is
used by <a href="#Fl_Group"><tt>Fl_Group</tt></a> to calculate new sizes of
the children when they are resized.
<p><tt>init_size()</tt> calls <tt>resize()</tt> with the passed sizes,
and then replaces the initial size with the new values. If this widget
is a group you will have to init_size all the children as well or
unpredictable results will occur.
<h4><a name="Fl_Widget.window">Fl_Window* Fl_Widget::window() const;</a></h4>
Return a pointer to the <a href="#Fl_Window"><tt>Fl_Window</tt></a>
that this widget is in (it will skip any and all parent widgets between
this and the window). Returns NULL if none. Note: for an
this and the window). Returns <tt>NULL</tt> if none. Note: for an
<tt>Fl_Window</tt>, this returns it's <i>parent</i> window (if any),
not <i>this</i> window.
@ -376,5 +356,13 @@ this widget. Returns false if <tt>b</tt> is <tt>NULL</tt>.
Returns true if this is a child of <tt>a</tt>, or is equal to <tt>a</tt>.
Returns false if <tt>a</tt> is <tt>NULL</tt>.
<h4><a name="Fl_Widget.take_focus">int Fl_Widget::take_focus()</a></h4>
Tries to make this widget be the <tt>Fl::focus()</tt> widget, by first
sending it an <tt>FL_FOCUS</tt> event, and if it returns non-zero,
setting <tt>Fl::focus()</tt> to this widget. You should use this
method to assign the focus to an widget. Returns true if the widget
accepted the focus.
</body>
</html>

View File

@ -1,5 +1,5 @@
#
# "$Id: Makefile,v 1.2 1998/12/29 14:58:59 mike Exp $"
# "$Id: Makefile,v 1.3 1999/01/07 16:36:05 mike Exp $"
#
# Documentation makefile for the Fast Light Tool Kit (FLTK).
#
@ -29,6 +29,8 @@ HTMLFILES = \
src/basics.html \
src/common.html \
src/editor.html \
src/drawing.html \
src/events.html \
src/subclassing.html \
src/fluid.html \
src/opengl.html \
@ -113,14 +115,14 @@ index.html: $(HTMLFILES)
fltk.ps.gz: $(HTMLFILES)
@echo "Generating PostScript documentation..."
@rm -f fltk.ps fltk.ps.gz
@htmldoc -f fltk.ps --no-compression --jpeg=90 --duplex --verbose --toclevels 2 --title src/FL.gif $(HTMLFILES)
@htmldoc -f fltk.ps --jpeg=90 --duplex --verbose --toclevels 2 --title src/FL.gif $(HTMLFILES)
@gzip -9 fltk.ps
fltk.pdf: $(HTMLFILES)
@echo "Generating PDF documentation..."
@rm -f fltk.pdf
@htmldoc -f fltk.pdf --no-compression --jpeg=90 --duplex --verbose --toclevels 2 --title src/FL.gif $(HTMLFILES)
@htmldoc -f fltk.pdf --compression=9 --jpeg=90 --duplex --verbose --toclevels 2 --title src/FL.gif $(HTMLFILES)
#
# End of "$Id: Makefile,v 1.2 1998/12/29 14:58:59 mike Exp $".
# End of "$Id: Makefile,v 1.3 1999/01/07 16:36:05 mike Exp $".
#

View File

@ -31,7 +31,7 @@ The proper way to include FLTK header files is:
#include &lt;FL/Fl_xyz.H>
</pre></ul>
Microsoft Windows developers please note: case *is* significant
<b>Microsoft Windows developers please note:</b> case *is* significant
under other operating systems, and the C standard uses the forward
slash (/) to separate directories. The following <tt>#include</tt>
directives are *not* recommended for portability reasons:
@ -71,9 +71,8 @@ header files. This can be done by selecting "Settings" from the
<p>You can build your Microsoft Windows applications as Console or
WIN32 applications. If you want to use the standard C <tt>main()</tt>
function as the entry point, enter the name <tt>mainCRTStartup</tt> in
the "Entry-point symbol" field in the "Output" settings under the
"Link" tab.
function as the entry point, FLTK includes a <tt>WinMain()</tt> function
that will call your <tt>main()</tt> function for you.
<p><i>Note: The Visual C++ optimizer is known to cause problems with
many programs. We only recommend using the "Favor Small Code"
@ -155,7 +154,7 @@ The <tt>boxtype</tt> value is the style of the box that is drawn around
the widget. Usually this is <tt>FL_NO_BOX</tt>, which means that no
box is drawn. In our "Hello, World!" example we use <tt>FL_UP_BOX</tt>,
which means that a raised button border will be drawn around the
widget. You can learn more about boxtypes in <a href="#common">Chapter
widget. You can learn more about boxtypes in <a href="#boytypes">Chapter
3</a>.
<p>The <tt>x</tt> and <tt>y</tt> parameters determine where the widget
@ -170,7 +169,7 @@ governed by the underlying window system or hardware.
<H3>Labels</H3>
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
is used for the label in the title bar. Our example program calls the
<a href="#Fl_Widget.labelfont"><tt>labelfont</tt></a>,
<a href="#Fl_Widget.labelsize"><tt>labelsize</tt></a>, and
<a href="#Fl_Widget.labeltype"><tt>labeltype</tt></a> methods.
@ -185,7 +184,7 @@ directly.
<p>The <tt>labeltype</tt> method sets the type of label. FLTK supports
normal, embossed, shadowed, symbol, and image labels.
<p>A complete list of all label options can be found in <a href="#common">
<p>A complete list of all label options can be found in <a href="#labels">
Chapter 3</a>.
<H3>Showing the Window</H3>

View File

@ -1,7 +1,7 @@
<HTML>
<BODY>
<H1 ALIGN=RIGHT>3 - Common Widgets and Attributes</H1>
<H1 ALIGN=RIGHT><A NAME="common">3 - Common Widgets and Attributes</A></H1>
This chapter describes many of the widgets that are provided with FLTK and covers how
to query and set the standard attributes.
@ -119,7 +119,7 @@ window->size(width, height);
Changing the size or position of a widget will cause a redraw of that widget
and its children.
<H2>Colors</H2>
<H2><A NAME="colors">Colors</A></H2>
FLTK manages a virtual color palette of "standard" colors. The
standard colors are:
@ -148,7 +148,7 @@ Similarly, the label color can be set using the <tt>labelcolor()</tt> method:
button->labelcolor(FL_WHITE);
</pre></ul>
<H2>Box Types</H2>
<H2><A NAME="boxtypes">Box Types</A></H2>
<p>The type <tt>Fl_Boxtype</tt> stored and returned in <a href="#Fl_Widget.box">
<tt>Fl_Widget::box()</tt></a> is an enumeration defined in
@ -204,9 +204,9 @@ The last 4 arguments to <tt>Fl::set_boxtype()</tt> are the offsets
for the bounding box that should be subtracted when drawing the label
inside the box.
<H2>Labels and Label Types</H2>
<H2><A NAME="labels">Labels and Label Types</A></H2>
The <tt>label()</tt>, <tt>align</tt>, <tt>labelfont()</tt>, <tt>labelsize()<tt>,
The <tt>label()</tt>, <tt>align</tt>, <tt>labelfont()</tt>, <tt>labelsize()</tt>,
and <tt>labeltype()</tt> methods control the labeling of widgets.
<H3>label()</H3>

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
<HTML>
<BODY>
<H1 ALIGN=RIGHT>4 - Designing a Simple Text Editor</H1>
<H1 ALIGN=RIGHT><A NAME="editor">4 - Designing a Simple Text Editor</A></H1>
This chapter takes you through the design of a simple FLTK-based text editor.
@ -295,7 +295,7 @@ We call the <tt>load_file()</tt> function to actually load the file.
<H3>paste_cb()</H3>
This callback function will send a FL_PASTE message to the <tt>input</tt>
widget using the <a href="#paste"><tt>Fl::paste()</tt> method:
widget using the <a href="#paste"><tt>Fl::paste()</tt></a> method:
<ul><pre>
void paste_cb(void) {
@ -514,7 +514,7 @@ void load_file(char *newfile) {
</pre></ul>
When loading the file we use the <a href="#Fl_Input_.replace">
<tt>input->replace()</tt> method to "replace" the text at the end of
<tt>input->replace()</tt></a> method to "replace" the text at the end of
the buffer. The <tt>pos</tt> variable keeps track of the end of the
buffer.

View File

@ -1,328 +1,373 @@
<HTML>
<BODY>
<H1><A NAME="enumerations">C - FLTK Enumerations.H</A></H1>
<H1 ALIGN=RIGHT><A NAME="enumerations">C - FLTK Enumerations.H</A></H1>
Here are the values of all the public-visible enumerations used by fltk:
This appendix lists the enumerations provided in the
<tt>&lt;FL/Enumerations.H></tt> header file, organized by section.
<pre>
#include &lt;FL/Enumerations.H>
<H2>Version Numbers</H2>
//
// The FLTK version number; this is changed slightly from the beta versions
// because the old "const double" definition would not allow for conditional
// compilation...
//
// FL_VERSION is a double that describes the major and minor version numbers.
// Version 1.1 is actually stored as 1.01 to allow for more than 9 minor
// releases.
//
// The FL_MAJOR_VERSION, FL_MINOR_VERSION, and FL_PATCH_VERSION constants
// give the integral values for the major, minor, and patch releases
// respectively.
//
The FLTK version number is stored in a number of compile-time constants:
#define FL_MAJOR_VERSION 1
#define FL_MINOR_VERSION 0
#define FL_PATCH_VERSION 0
#define FL_VERSION ((double)FL_MAJOR_VERSION + \
(double)FL_MINOR_VERSION * 0.01)
<ul>
typedef unsigned char uchar;
typedef unsigned long ulong;
typedef unsigned int u32; // you must fix if not 32 bits on your machine!
<li><tt>FL_MAJOR_VERSION</tt> - The major release number, currently
1.
enum Fl_Event { // events
FL_NO_EVENT = 0,
FL_PUSH = 1,
FL_RELEASE = 2,
FL_ENTER = 3,
FL_LEAVE = 4,
FL_DRAG = 5,
FL_FOCUS = 6,
FL_UNFOCUS = 7,
FL_KEYBOARD = 8,
FL_CLOSE = 9,
FL_MOVE = 10,
FL_SHORTCUT = 11,
FL_DEACTIVATE = 13,
FL_ACTIVATE = 14,
FL_HIDE = 15,
FL_SHOW = 16,
FL_PASTE = 17,
FL_SELECTIONCLEAR = 18
};
<li><tt>FL_MINOR_VERSION</tt> - The minor release number, currently
0.
enum Fl_When { // Fl_Widget::when():
FL_WHEN_NEVER = 0,
FL_WHEN_CHANGED = 1,
FL_WHEN_RELEASE = 4,
FL_WHEN_RELEASE_ALWAYS= 6,
FL_WHEN_ENTER_KEY = 8,
FL_WHEN_ENTER_KEY_ALWAYS=10,
FL_WHEN_NOT_CHANGED = 2 // modifier bit to disable changed() test
};
<li><tt>FL_PATCH_VERSION</tt> - The patch release number, currently
0.
// Fl::event_key() and Fl::get_key(n) (use ascii letters for all other keys):
#define FL_Button 0xfee8 // use Fl_Button+n for mouse button n
#define FL_BackSpace 0xff08
#define FL_Tab 0xff09
#define FL_Enter 0xff0d
#define FL_Pause 0xff13
#define FL_Scroll_Lock 0xff14
#define FL_Escape 0xff1b
#define FL_Home 0xff50
#define FL_Left 0xff51
#define FL_Up 0xff52
#define FL_Right 0xff53
#define FL_Down 0xff54
#define FL_Page_Up 0xff55
#define FL_Page_Down 0xff56
#define FL_End 0xff57
#define FL_Print 0xff61
#define FL_Insert 0xff63
#define FL_Menu 0xff67 // the "menu/apps" key on XFree86
#define FL_Num_Lock 0xff7f
#define FL_KP 0xff80 // use FL_KP+'x' for 'x' on numeric keypad
#define FL_KP_Enter 0xff8d // same as Fl_KP+'\r'
#define FL_KP_Last 0xffbd // use to range-check keypad
#define FL_F 0xffbd // use FL_F+n for function key n
#define FL_F_Last 0xffe0 // use to range-check function keys
#define FL_Shift_L 0xffe1
#define FL_Shift_R 0xffe2
#define FL_Control_L 0xffe3
#define FL_Control_R 0xffe4
#define FL_Caps_Lock 0xffe5
#define FL_Meta_L 0xffe7 // the left MSWindows key on XFree86
#define FL_Meta_R 0xffe8 // the right MSWindows key on XFree86
#define FL_Alt_L 0xffe9
#define FL_Alt_R 0xffea
#define FL_Delete 0xffff
<li><tt>FL_VERSION</tt> - A combined floating-point version
number for the major and minor release numbers, currently 1.0.
// Fl::event_state():
#define FL_SHIFT 0x00010000
#define FL_CAPS_LOCK 0x00020000
#define FL_CTRL 0x00040000
#define FL_ALT 0x00080000
#define FL_NUM_LOCK 0x00100000 // most X servers do this?
#define FL_META 0x00400000 // correct for XFree86
#define FL_SCROLL_LOCK 0x00800000 // correct for XFree86
#define FL_BUTTON1 0x01000000
#define FL_BUTTON2 0x02000000
#define FL_BUTTON3 0x04000000
</ul>
enum Fl_Boxtype { // boxtypes (if you change these you must fix fl_boxtype.C):
FL_NO_BOX = 0, FL_FLAT_BOX,
<H2>Events</H2>
FL_UP_BOX, FL_DOWN_BOX,
FL_UP_FRAME, FL_DOWN_FRAME,
FL_THIN_UP_BOX, FL_THIN_DOWN_BOX,
FL_THIN_UP_FRAME, FL_THIN_DOWN_FRAME,
FL_ENGRAVED_BOX, FL_EMBOSSED_BOX,
FL_ENGRAVED_FRAME, FL_EMBOSSED_FRAME,
FL_BORDER_BOX, _FL_SHADOW_BOX,
FL_BORDER_FRAME, _FL_SHADOW_FRAME,
_FL_ROUNDED_BOX, _FL_RSHADOW_BOX,
_FL_ROUNDED_FRAME, _FL_RFLAT_BOX,
_FL_ROUND_UP_BOX, _FL_ROUND_DOWN_BOX,
_FL_DIAMOND_UP_BOX, _FL_DIAMOND_DOWN_BOX,
_FL_OVAL_BOX, _FL_OSHADOW_BOX,
_FL_OVAL_FRAME, _FL_OFLAT_BOX
};
extern Fl_Boxtype define_FL_ROUND_UP_BOX();
#define FL_ROUND_UP_BOX define_FL_ROUND_UP_BOX()
#define FL_ROUND_DOWN_BOX (Fl_Boxtype)(define_FL_ROUND_UP_BOX()+1)
extern Fl_Boxtype define_FL_SHADOW_BOX();
#define FL_SHADOW_BOX define_FL_SHADOW_BOX()
#define FL_SHADOW_FRAME (Fl_Boxtype)(define_FL_SHADOW_BOX()+2)
extern Fl_Boxtype define_FL_ROUNDED_BOX();
#define FL_ROUNDED_BOX define_FL_ROUNDED_BOX()
#define FL_ROUNDED_FRAME (Fl_Boxtype)(define_FL_ROUNDED_BOX()+2)
extern Fl_Boxtype define_FL_RFLAT_BOX();
#define FL_RFLAT_BOX define_FL_RFLAT_BOX()
extern Fl_Boxtype define_FL_RSHADOW_BOX();
#define FL_RSHADOW_BOX define_FL_RSHADOW_BOX()
extern Fl_Boxtype define_FL_DIAMOND_BOX();
#define FL_DIAMOND_UP_BOX define_FL_DIAMOND_BOX()
#define FL_DIAMOND_DOWN_BOX (Fl_Boxtype)(define_FL_DIAMOND_BOX()+1)
extern Fl_Boxtype define_FL_OVAL_BOX();
#define FL_OVAL_BOX define_FL_OVAL_BOX()
#define FL_OSHADOW_BOX (Fl_Boxtype)(define_FL_OVAL_BOX()+1)
#define FL_OVAL_FRAME (Fl_Boxtype)(define_FL_OVAL_BOX()+2)
#define FL_OFLAT_BOX (Fl_Boxtype)(define_FL_OVAL_BOX()+3)
Events are identified by an <tt>Fl_Event</tt> enumeration value. The
following events are currently defined:
// conversions of box types to other boxtypes:
inline Fl_Boxtype down(Fl_Boxtype b) {return (Fl_Boxtype)(b|1);}
inline Fl_Boxtype frame(Fl_Boxtype b) {return (Fl_Boxtype)(b|2);}
<ul>
// back-compatability box types:
#define FL_FRAME FL_ENGRAVED_FRAME
#define FL_FRAME_BOX FL_ENGRAVED_BOX
#define FL_CIRCLE_BOX FL_ROUND_DOWN_BOX
#define FL_DIAMOND_BOX FL_DIAMOND_DOWN_BOX
<li><tt>FL_NO_EVENT</tt> - No event occurred.
enum Fl_Labeltype { // labeltypes:
FL_NORMAL_LABEL = 0,
FL_NO_LABEL,
_FL_SYMBOL_LABEL,
_FL_SHADOW_LABEL,
_FL_ENGRAVED_LABEL,
_FL_EMBOSSED_LABEL,
_FL_BITMAP_LABEL,
_FL_PIXMAP_LABEL,
_FL_IMAGE_LABEL,
_FL_MULTI_LABEL,
FL_FREE_LABELTYPE
};
extern Fl_Labeltype define_FL_SYMBOL_LABEL();
#define FL_SYMBOL_LABEL define_FL_SYMBOL_LABEL()
extern Fl_Labeltype define_FL_SHADOW_LABEL();
#define FL_SHADOW_LABEL define_FL_SHADOW_LABEL()
extern Fl_Labeltype define_FL_ENGRAVED_LABEL();
#define FL_ENGRAVED_LABEL define_FL_ENGRAVED_LABEL()
extern Fl_Labeltype define_FL_EMBOSSED_LABEL();
#define FL_EMBOSSED_LABEL define_FL_EMBOSSED_LABEL()
<li><tt>FL_PUSH</tt> - A mouse button was pushed.
enum Fl_Align { // align() values
FL_ALIGN_CENTER = 0,
FL_ALIGN_TOP = 1,
FL_ALIGN_BOTTOM = 2,
FL_ALIGN_LEFT = 4,
FL_ALIGN_RIGHT = 8,
FL_ALIGN_INSIDE = 16,
FL_ALIGN_CLIP = 64,
FL_ALIGN_WRAP = 128,
FL_ALIGN_TOP_LEFT = FL_ALIGN_TOP | FL_ALIGN_LEFT,
FL_ALIGN_TOP_RIGHT = FL_ALIGN_TOP | FL_ALIGN_RIGHT,
FL_ALIGN_BOTTOM_LEFT = FL_ALIGN_BOTTOM | FL_ALIGN_LEFT,
FL_ALIGN_BOTTOM_RIGHT = FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT,
FL_ALIGN_LEFT_TOP = FL_ALIGN_TOP_LEFT,
FL_ALIGN_RIGHT_TOP = FL_ALIGN_TOP_RIGHT,
FL_ALIGN_LEFT_BOTTOM = FL_ALIGN_BOTTOM_LEFT,
FL_ALIGN_RIGHT_BOTTOM = FL_ALIGN_BOTTOM_RIGHT,
FL_ALIGN_NOWRAP = 0 // for back compatability
};
<li><tt>FL_RELEASE</tt> - A mouse button was released.
enum Fl_Font { // standard fonts
FL_HELVETICA = 0,
FL_HELVETICA_BOLD,
FL_HELVETICA_ITALIC,
FL_HELVETICA_BOLD_ITALIC,
FL_COURIER,
FL_COURIER_BOLD,
FL_COURIER_ITALIC,
FL_COURIER_BOLD_ITALIC,
FL_TIMES,
FL_TIMES_BOLD,
FL_TIMES_ITALIC,
FL_TIMES_BOLD_ITALIC,
FL_SYMBOL,
FL_SCREEN,
FL_SCREEN_BOLD,
FL_ZAPF_DINGBATS,
<li><tt>FL_ENTER</tt> - The mouse pointer entered a widget.
FL_FREE_FONT = 16, // first one to allocate
FL_BOLD = 1, // add this to helvetica, courier, or times
FL_ITALIC = 2 // add this to helvetica, courier, or times
};
<li><tt>FL_LEAVE</tt> - The mouse pointer left a widget.
#define FL_NORMAL_SIZE 14 // default size of all labels & text
<li><tt>FL_DRAG</tt> - The mouse pointer was moved with a button
pressed.
enum Fl_Color { // standard colors
FL_BLACK = 0,
FL_RED = 1,
FL_GREEN = 2,
FL_YELLOW = 3,
FL_BLUE = 4,
FL_MAGENTA = 5,
FL_CYAN = 6,
FL_WHITE = 7,
FL_INACTIVE_COLOR = 8,
FL_SELECTION_COLOR = 15,
<li><tt>FL_FOCUS</tt> - A widget should receive keyboard focus.
FL_FREE_COLOR = 16,
FL_NUM_FREE_COLOR = 16,
<li><tt>FL_UNFOCUS</tt> - A widget loses keyboard focus.
FL_GRAY_RAMP = 32,
<li><tt>FL_KEYBOARD</tt> - A key was pressed.
// boxtypes limit themselves to these colors so whole ramp is not allocated:
FL_GRAY0 = 32, // 'A'
FL_DARK3 = 39, // 'H'
FL_DARK2 = 45, // 'N'
FL_DARK1 = 47, // 'P'
FL_GRAY = 49, // 'R' default color
FL_LIGHT1 = 50, // 'S'
FL_LIGHT2 = 52, // 'U'
FL_LIGHT3 = 54, // 'W'
<li><tt>FL_CLOSE</tt> - A window was closed.
FL_COLOR_CUBE = 56
};
<li><tt>FL_MOVE</tt> - The mouse pointer was moved with no buttons
pressed.
inline Fl_Color inactive(Fl_Color c) {return (Fl_Color)(c|8);}
Fl_Color contrast(Fl_Color fg, Fl_Color bg);
#define FL_NUM_GRAY 24
inline Fl_Color fl_gray_ramp(int i) {return (Fl_Color)(i+FL_GRAY_RAMP);}
#define FL_NUM_RED 5
#define FL_NUM_GREEN 8
#define FL_NUM_BLUE 5
inline Fl_Color fl_color_cube(int r, int g, int b) {
return (Fl_Color)((b*FL_NUM_RED + r) * FL_NUM_GREEN + g + FL_COLOR_CUBE);}
<li><tt>FL_SHORTCUT</tt> - The user pressed a shortcut key.
enum Fl_Cursor { // standard cursors
FL_CURSOR_DEFAULT = 0,
FL_CURSOR_ARROW = 35,
FL_CURSOR_CROSS = 66,
FL_CURSOR_WAIT = 76,
FL_CURSOR_INSERT = 77,
FL_CURSOR_HAND = 31,
FL_CURSOR_HELP = 47,
FL_CURSOR_MOVE = 27,
// fltk provides bitmaps for these:
FL_CURSOR_NS = 78,
FL_CURSOR_WE = 79,
FL_CURSOR_NWSE = 80,
FL_CURSOR_NESW = 81,
FL_CURSOR_NONE = 255,
// for back compatability (non MSWindows ones):
FL_CURSOR_N = 70,
FL_CURSOR_NE = 69,
FL_CURSOR_E = 49,
FL_CURSOR_SE = 8,
FL_CURSOR_S = 9,
FL_CURSOR_SW = 7,
FL_CURSOR_W = 36,
FL_CURSOR_NW = 68
//FL_CURSOR_NS = 22,
//FL_CURSOR_WE = 55,
};
<li><tt>FL_DEACTIVATE</tt> - The widget has been deactivated.
enum { // values for "when" passed to Fl::add_fd()
FL_READ = 1,
FL_WRITE = 4,
FL_EXCEPT = 8
};
<li><tt>FL_ACTIVATE</tt> - The widget has been activated.
enum Fl_Mode { // visual types and Fl_Gl_Window::mode() (values match Glut)
FL_RGB = 0,
FL_INDEX = 1,
FL_SINGLE = 0,
FL_DOUBLE = 2,
FL_ACCUM = 4,
FL_ALPHA = 8,
FL_DEPTH = 16,
FL_STENCIL = 32,
FL_RGB8 = 64,
FL_MULTISAMPLE= 128
};
<li><tt>FL_HIDE</tt> - The widget has been hidden.
// damage masks
<li><tt>FL_SHOW</tt> - The widget has been shown.
<li><tt>FL_PASTE</tt> - The widget should paste the contents of the
clipboard.
<li><tt>FL_SELECTIONCLEAR</tt> - The widget should clear any selections
made for the clipboard.
</ul>
<H2>Callback "When" Conditions</H2>
The following constants determine when a callback is performed:
<ul>
<li><tt>FL_WHEN_NEVER</tt> - Never call the callback.
<li><tt>FL_WHEN_CHANGED</tt> - Do the callback only when the
widget value changes.
<li><tt>FL_WHEN_NOT_CHANGED</tt> - Do the callback whenever the
user interacts with the widget.
<li><tt>FL_WHEN_RELEASE</tt> - Do the callback when the button or
key is released and the value changes.
<li><tt>FL_WHEN_ENTER_KEY</tt> - Do the callback when the user presses
the ENTER key and the value changes.
<li><tt>FL_WHEN_RELEASE_ALWAYS</tt> - Do the callback when the button
or key is released, even if the value doesn't change.
<li><tt>FL_WHEN_ENTER_KEY_ALWAYS</tt> - Do the callback when the user
presses the ENTER key, even if the value doesn't change.
</ul>
<H2>Fl::event_key() Values</H2>
The following constants define the non-ASCII keys on the keyboard for
<tt>FL_KEYBOARD</tt> and <tt>FL_SHORTCUT</tt> events:
<ul>
<li><tt>FL_Button</tt> - A mouse button; use <tt>Fl_Button +
n</tt> for mouse button <tt>n</tt>.
<li><tt>FL_BackSpace</tt> - The backspace key.
<li><tt>FL_Tab</tt> - The tab key.
<li><tt>FL_Enter</tt> - The enter key.
<li><tt>FL_Pause</tt> - The pause key.
<li><tt>FL_Scroll_Lock</tt> - The scroll lock key.
<li><tt>FL_Escape</tt> - The escape key.
<li><tt>FL_Home</tt> - The home key.
<li><tt>FL_Left</tt> - The left arrow key.
<li><tt>FL_Up</tt> - The up arrow key.
<li><tt>FL_Right</tt> - The right arrow key.
<li><tt>FL_Down</tt> - The down arrow key.
<li><tt>FL_Page_Up</tt> - The page-up key.
<li><tt>FL_Page_Down</tt> - The page-down key.
<li><tt>FL_End</tt> - The end key.
<li><tt>FL_Print</tt> - The print (or print-screen) key.
<li><tt>FL_Insert</tt> - The insert key.
<li><tt>FL_Menu</tt> - The menu key.
<li><tt>FL_Num_Lock</tt> - The num lock key.
<li><tt>FL_KP</tt> - One of the keypad numbers; use <tt>FL_KP +
n</tt> for number <tt>n</tt>.
<li><tt>FL_KP_Enter</tt> - The enter key on the keypad.
<li><tt>FL_F</tt> - One of the function keys; use <tt>FL_F +
n</tt> for function key <tt>n</tt>.
<li><tt>FL_Shift_L</tt> - The lefthand shift key.
<li><tt>FL_Shift_R</tt> - The righthand shift key.
<li><tt>FL_Control_L</tt> - The lefthand control key.
<li><tt>FL_Control_R</tt> - The righthand control key.
<li><tt>FL_Caps_Lock</tt> - The caps lock key.
<li><tt>FL_Meta_L</tt> - The left meta/Windows key.
<li><tt>FL_Meta_R</tt> - The right meta/Windows key.
<li><tt>FL_Alt_L</tt> - The left alt key.
<li><tt>FL_Alt_R</tt> - The right alt key.
<li><tt>FL_Delete</tt> - The delete key.
</ul>
<H2>Fl::event_state() Values</H2>
The following constants define bits in the <tt>Fl::event_state()</tt>
value:
<ul>
<li><tt>FL_SHIFT</tt> - One of the shift keys is down.
<li><tt>FL_CAPS_LOCK</tt> - The caps lock is on.
<li><tt>FL_CTRL</tt> - One of the ctrl keys is down.
<li><tt>FL_ALT</tt> - One of the alt keys is down.
<li><tt>FL_NUM_LOCK</tt> - The num lock is on.
<li><tt>FL_META</tt> - One of the meta/Windows keys is down.
<li><tt>FL_SCROLL_LOCK</tt> - The scroll lock is on.
<li><tt>FL_BUTTON1</tt> - Mouse button 1 is pushed.
<li><tt>FL_BUTTON2</tt> - Mouse button 2 is pushed.
<li><tt>FL_BUTTON3</tt> - Mouse button 3 is pushed.
</ul>
<H2>Alignment Values</H2>
The following constants define bits that can be used with <a
href="#Fl_Widget.align"><tt>Fl_Widget::align()</tt></a> to control the
positioning of the label:
<ul>
<li><tt>FL_ALIGN_CENTER</tt> - The label is centered.
<li><tt>FL_ALIGN_TOP</tt> - The label is top-aligned.
<li><tt>FL_ALIGN_BOTTOM</tt> - The label is bottom-aligned.
<li><tt>FL_ALIGN_LEFT</tt> - The label is left-aligned.
<li><tt>FL_ALIGN_RIGHT</tt> - The label is right-aligned.
<li><tt>FL_ALIGN_INSIDE</tt> - The label is put inside the widget.
<li><tt>FL_ALIGN_CLIP</tt> - The label is clipped to the widget.
<li><tt>FL_ALIGN_WRAP</tt> - The label text is wrapped as needed.
</ul>
<H2>Fonts</H2>
The following constants define the standard FLTK fonts:
</ul>
<li><tt>FL_HELVETICA</tt> - Helvetica (or Arial) normal.
<li><tt>FL_HELVETICA_BOLD</tt> - Helvetica (or Arial) bold.
<li><tt>FL_HELVETICA_ITALIC</tt> - Helvetica (or Arial) oblique.
<li><tt>FL_HELVETICA_BOLD_ITALIC</tt> - Helvetica (or Arial) bold-oblique.
<li><tt>FL_COURIER</tt> - Courier normal.
<li><tt>FL_COURIER_BOLD</tt> - Courier bold.
<li><tt>FL_COURIER_ITALIC</tt> - Courier italic.
<li><tt>FL_COURIER_BOLD_ITALIC</tt> - Courier bold-italic.
<li><tt>FL_TIMES</tt> - Times roman.
<li><tt>FL_TIMES_BOLD</tt> - Times bold.
<li><tt>FL_TIMES_ITALIC</tt> - Times italic.
<li><tt>FL_TIMES_BOLD_ITALIC</tt> - Times bold-italic.
<li><tt>FL_SYMBOL</tt> - Standard symbol font.
<li><tt>FL_SCREEN</tt> - Default monospaced screen font.
<li><tt>FL_SCREEN_BOLD</tt> - Default monospaced bold screen font.
<li><tt>FL_ZAPF_DINGBATS</tt> - Zapf-dingbats font.
</ul>
<H2>Colors</H2>
The following color constants can be used to access the colors in the FLTK
standard color palette:
<ul>
<li><tt>FL_BLACK</tt>
<li><tt>FL_RED</tt>
<li><tt>FL_GREEN</tt>
<li><tt>FL_YELLOW</tt>
<li><tt>FL_BLUE</tt>
<li><tt>FL_MAGENTA</tt>
<li><tt>FL_CYAN</tt>
<li><tt>FL_WHITE</tt>
<li><tt>FL_GRAY0</tt>
<li><tt>FL_DARK3</tt>
<li><tt>FL_DARK2</tt>
<li><tt>FL_DARK1</tt>
<li><tt>FL_GRAY</tt>
<li><tt>FL_LIGHT1</tt>
<li><tt>FL_LIGHT2</tt>
<li><tt>FL_LIGHT3</tt>
</ul>
<H2>Cursors</H2>
The following constants define the mouse cursors that are available in
FLTK:
<ul>
<li><tt>FL_CURSOR_DEFAULT</tt> - the default cursor, usually an arrow
<li><tt>FL_CURSOR_ARROW</tt> - an arrow pointer
<li><tt>FL_CURSOR_CROSS</tt> - crosshair
<li><tt>FL_CURSOR_WAIT</tt> - watch or hourglass
<li><tt>FL_CURSOR_INSERT</tt> - I-beam
<li><tt>FL_CURSOR_HAND</tt> - hand (uparrow on MSWindows)
<li><tt>FL_CURSOR_HELP</tt> - question mark
<li><tt>FL_CURSOR_MOVE</tt> - 4-pointed arrow
<li><tt>FL_CURSOR_NS</tt> - up/down arrow
<li><tt>FL_CURSOR_WE</tt> - left/right arrow
<li><tt>FL_CURSOR_NWSE</tt> - diagonal arrow
<li><tt>FL_CURSOR_NESW</tt> - diagonal arrow
<li><tt>FL_CURSOR_NONE</tt> - invisible
</ul>
<H2>FD "When" Conditions</H2>
<ul>
<li><tt>FL_READ</tt> - Call the callback when there is data to be
read.
<li><tt>FL_WRITE</tt> - Call the callback when data can be written
without blocking.
<li><tt>FL_EXCEPT</tt> - Call the callback if an exception occurs on
the file.
</ul>
<H2>Damage Masks</H2>
The following damage mask bits are used by the standard FLTK widgets:
<ul>
<li><tt>FL_DAMAGE_CHILD</tt> - A child needs to be redrawn.
<li><tt>FL_DAMAGE_EXPOSE</tt> - The window was exposed.
<li><tt>FL_DAMAGE_SCROLL</tt> - The <tt>Fl_Scroll</tt> widget was
scrolled.
<li><tt>FL_DAMAGE_OVERLAY</tt> - The overlay planes need to be redrawn.
<li><tt>FL_DAMAGE_ALL</tt> - Everything needs to be redrawn.
</ul>
enum Fl_Damage {
FL_DAMAGE_CHILD = 0x01,
FL_DAMAGE_EXPOSE = 0x02,
FL_DAMAGE_SCROLL = 0x04,
FL_DAMAGE_OVERLAY = 0x08,
FL_DAMAGE_ALL = 0x80
};
</pre>
</BODY>
</HTML>

View File

@ -1,499 +1,225 @@
<HTML>
<BODY>
<H1 ALIGN=RIGHT>4 - Handling Events</H1>
<H1 ALIGN=RIGHT><A NAME="events">6 - Handling Events</A></H1>
This chapter discusses the FLTK event model and how to handle events in your program or
widget.
<H2>The FLTK Event Model</H2>
Events are identified the small integer argument passed to the <a
href="#handle"><tt>Fl_Widget::handle()</tt></a> virtual method. Other
information about the most recent event is stored in static locations
and acquired by calling the <a
href="#event_xxx"><tt>Fl::event_*()</tt></a> methods. This static
information remains valid until the next event is read from window
system (i.e. it is ok to look at it outside of the <tt>handle()</tt> method).
<H2>Mouse Events</H2>
<H3><TT>FL_PUSH</TT></H3>
<H3><TT>FL_RELEASE</TT></H3>
<H3><TT>FL_DRAG</TT></H3>
<H3><TT>FL_MOVE</TT></H3>
<H2>Keyboard Events</H2>
<H3><TT>FL_KEYBOARD</TT></H3>
<H3><TT>FL_SHORTCUT</TT></H3>
<H2>Widget Events</H2>
<H3><TT>FL_ACTIVATE</TT></H3>
<H3><TT>FL_DEACTIVATE</TT></H3>
<H3><TT>FL_HIDE</TT></H3>
<H3><TT>FL_SHOW</TT></H3>
<H3><TT>FL_FOCUS</TT></H3>
<H3><TT>FL_UNFOCUS</TT></H3>
<H3><TT>FL_ENTER</TT></H3>
<H3><TT>FL_LEAVE</TT></H3>
<H3><TT>FL_PASTE</TT></H3>
<H3><TT>FL_SELECTIONCLEAR</TT></H3>
</BODY>
</HTML>
<title>Events in Fltk</title>
<a name=types>
<h2>Events in Fltk</h2>
<p>Events are identified the small integer argument passed to the <a
href=subclass.html#handle>Fl_Widget::handle()</a> virtual method.
Other information about the most recent event is stored in static
locations and aquired by calling <a
href=#information><code>Fl::event_*()</code></a>. This static
information remains valid until the next event is read from the X
server (that is, it is ok to look at it outside the handle() method).
</ul><h4><code>FL_PUSH (1)</code></h4><ul>
<h3>FL_PUSH</h3>
A mouse button has gone down with the mouse pointing at this widget.
You can find out what button by calling <a
href=#event_button>Fl::event_button()</a>. You find out the mouse
position by calling <a href=#event_x>Fl::event_x() and
Fl::event_y()</a>.
href="#event_button"><tt>Fl::event_button()</tt></a>. You find out the
mouse position by calling <a href="#event_x"><tt>Fl::event_x()</tt></a>
and <a href="#event_y"><tt>Fl::event_y()</tt></a>.
<p>A widget indicates that it "wants" the mouse click by returning
non-zero from it's <a href=subclass.html#handle>handle()</a> method.
It will then become the <a href=#pushed>Fl::pushed()</a> 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.
non-zero from its <a href="#handle"><tt>handle()</tt></a> method. It
will then become the <a href="#pushed"><tt>Fl::pushed()</tt></a> widget
and will get <tt>FL_DRAG</tt> and the matching <tt>FL_RELEASE</tt>
events. If <tt>handle()</tt> returns zero then FLTK will try sending
the <tt>FL_PUSH</tt> to another widget.
</ul><h4><code>FL_DRAG (5)</code></h4><ul>
<h3>FL_DRAG</h3>
The mouse has moved with the button held down.
The mouse has moved with a button held down.
</ul><h4><code>FL_RELEASE (2)</code></h4><ul>
<h3>FL_RELEASE</h3>
A mouse button has been released. You can find out what button by
calling <a href=#event_button>Fl::event_button()</a>.
calling <a href="#event_button"><tt>Fl::event_button()</tt></a>.
</ul><h4><code>FL_ENTER (3)</code></h4><ul>
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 it's <a href=subclass.html#handle>handle()</a> method.
It then becomes the <a href=#belowmouse>Fl::belowmouse()</a> widget
and will receive FL_MOVE and FL_EXIT events.
</ul><h4><code>FL_MOVE (10)</code></h4><ul>
<h3>FL_MOVE</h3>
The mouse has moved without any mouse buttons held down. This event
is sent (sort of) to the belowmouse() widget.
is sent to the <tt>belowmouse()</tt> widget.
</ul><h4><code>FL_LEAVE (4)</code></h4><ul>
<H2>Focus Events</H2>
<h3>FL_ENTER</h3>
The mouse has been moved to point at this widget. This can be used for
highlighting feedback. If a widget wants to highlight or otherwise
track the mouse, it indicates this by returning non-zero from its <a
href="#handle"><tt>handle()</tt></a> method. It then becomes the <a
href="#belowmouse"><tt>Fl::belowmouse()</tt></a> widget and will
receive <tt>FL_MOVE</tt> and <tt>FL_LEAVE</tt> events.
<h3>FL_LEAVE</h3>
The mouse has moved out of the widget.
</ul><h4><code>FL_FOCUS (6)</code></h4><ul>
<h3>FL_FOCUS</h3>
This indicates an <i>attempt</i> to give a widget the keyboard
focus.
<p>If a widget wants the focus, it should change itself to display the
fact that it has the focus, and return non-zero from it's <a
href=subclass.html#handle>handle()</a> method. It then becomes the <a
href=#focus>Fl::focus()</a> widget and gets FL_KEYBOARD and FL_UNFOCUS
events.
fact that it has the focus, and return non-zero from its <a
href="#handle"><tt>handle()</tt></a> method. It then becomes the <a
href="#focus"><tt>Fl::focus()</tt></a> widget and gets <tt>FL_KEYBOARD</tt>
and <tt>FL_UNFOCUS</tt> events.
<p>The focus will change either because the window manager changed
which window gets the focus, or because the user tried to navigate
using tab, arrows, or other keys. You can check <a
href=#event_key>Fl::event_key()</a> to figure out why it moved. For
navigation it will be the key pressed, for instructions from the
href="#event_key"><tt>Fl::event_key()</tt></a> to figure out why it moved. For
navigation it will be the key pressed and for instructions from the
window manager it will be zero.
</ul><h4><code>FL_UNFOCUS (7)</code></h4><ul>
<h3>FL_UNFOCUS</h3>
Sent to the old <a href=#focus>Fl::focus()</a> when something else
gets the focus.
Sent to the previous <a href="#focus"><tt>Fl::focus()</tt></a> when
another widget gets the focus.
</ul><h4><code>FL_KEYBOARD (8)</code></h4><ul>
<H2>Keyboard Events</H2>
<h3>FL_KEYBOARD</h3>
A key press. The key pressed can be found in <a
href=#event_key>Fl::event_key()</a>, or, more usefully, the text that
the key should insert can be found with <a
href=#event_text>Fl::event_text()</a> and it's length is in <a
href=#event_length>Fl::event_length()</a>. If you use the key
handle() should return 1. If you return zero then fltk assummes you
ignored the key. It 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.
href="#event_key"><tt>Fl::event_key()</tt></a>. The text that the key
should insert can be found with <a
href="#event_text"><tt>Fl::event_text()</tt></a> and its length is in
<a href="#event_length"><tt>Fl::event_length()</tt></a>. If you use
the key <tt>handle()</tt> should return 1. If you return zero then
FLTK assummes you ignored the key. It will then attempt to send it to
a parent widget. If none of them want it, it will change the event into
a <tt>FL_SHORTCUT</tt> event.
</ul><h4><code>FL_SHORTCUT (11)</code></h4><ul>
<h3>FL_SHORTCUT</h3>
If the <a href=#focus>Fl::focus()</a> 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 belowmouse widget, then it's parents and siblings, and
eventually to every widget in the window, trying to find an object
that returns non-zero. Fltk tries real hard to not let any keystrokes
be ignored!
<p>If the <a href=#event_text>Fl::event_text()</a> is a lower or
upper-case letter, and nothing wants the shortcut
If the <a href="#focus"><tt>Fl::focus()</tt></a> is zero or ignores an
<tt>FL_KEYBOARD</tt> event then FLTK tries sending this event to every
widget it can, until one of them returns non-zero.
<tt>FL_SHORTCUT</tt> is first sent to the <tt>belowmouse()</tt> widget,
then its parents and siblings, and eventually to every widget in the
window, trying to find an object that returns non-zero. FLTK tries
really hard to not to ignore any keystrokes!
<p>You can also make "global" shortcuts by using <a
href=#add_handler>Fl::add_handler()</a>. A global shortcut will work
no matter what windows are displayed or which one has the focus.
href="#add_handler"><tt>Fl::add_handler()</tt></a>. A global shortcut
will work no matter what windows are displayed or which one has the
focus.
</ul><h4><code>FL_DEACTIVATE (13)</code></h4><ul>
<H2>Widget Events</H2>
<h3>FL_DEACTIVATE</h3>
This widget is no longer active, due to <a
href=Fl_Widget.html#active>deactivate()</a> being called on it or one
of it's parents. active() may still be true after this, the widget is
only active if active() is true on it and all it's parents.
href="#Fl_Widget.deactivate"><tt>deactivate()</tt></a> being called on
it or one of its parents. <tt>active()</tt> may still be true after this, the
widget is only active if <tt>active()</tt> is true on it and all its parents
(use <tt>active_r()</tt> to check this).
</ul><h4><code>FL_ACTIVATE (14)</code></h4><ul>
<h3>FL_ACTIVATE</h3>
This widget is now active, due to <a
href=Fl_Widget.html#activate>active()</a> being called on it or one
of it's parents.
href="#Fl_Widget.activate"><tt>activate()</tt></a> being called on it
or one of its parents.
</ul><h4><code>FL_HIDE (15)</code></h4><ul>
<h3>FL_HIDE</h3>
This widget is no longer visible, due to <a
href=Fl_Widget.html#visible>hide()</a> being called, or a parent group
or window having hide() be called, or due to a parent window being
iconized. visible() may still be true after this, the widget is
visible only if visible() is true for it and all it's parents.
href="#Fl_Widget.hide><tt>hide()</a> being called on it or one of its
parents, or due to a parent window being minimized. <tt>visible()</tt>
may still be true after this, but the widget is visible only if
<tt>visible()</tt> is true for it and all its parents (use
<tt>visible_r()</tt> to check this).
</ul><h4><code>FL_SHOW (16)</code></h4><ul>
<h3>FL_SHOW</h3>
This widget is visible again, due to <a
href=Fl_Widget.html#visible>show()</a> being called on it or one of
it's parents, or due to a parent window being deiconized. <i>Child
Fl_Windows respond to this by actually creating the X window if not
done already, so if you subclass a window, be sure to pass FL_SHOW to
the base class handle() method!</i>
href="#Fl_Widget.show"><tt>show()</tt></a> being called on it or one of
its parents, or due to a parent window being restored. <i>Child
<tt>Fl_Window</tt>s respond to this by actually creating the window if not
done already, so if you subclass a window, be sure to pass <tt>FL_SHOW</tt> to
the base class <tt>handle()</tt> method!</i>
<a name=paste>
</ul><h4><code>FL_PASTE (17)</code></h4><ul>
<H2>Clipboard Events</H2>
<h3>FL_PASTE</h3>
You should get this event some time after you call <a
href=cutpaste.html>Fl::paste()</a>. The contents of <a
href=#event_text>Fl::event_text()</a> is the text to insert and the
number of characters is in <a href=#event_length>Fl::event_length()</a>.
href="#paste"><tt>Fl::paste()</tt></a>. The contents of <a
href="#event_text"><tt>Fl::event_text()</tt></a> is the text to insert
and the number of characters is in <a
href="#event_length"><tt>Fl::event_length()</tt></a>.
</ul><h4><code>FL_SELECTIONCLEAR (18)</code></h4><ul>
<h3>FL_SELECTIONCLEAR</h3>
The <a href=cutpaste.html>Fl::selection_owner()</a> will get this
The <a href="#selection_owner">Fl::selection_owner()</a> will get this
event before the selection is moved to another widget. This indicates
that some other widget or program has claimed the selection.
</ul>
<h2><a name="event_xxx">Fl::event_*() methods</a></h2>
<a name=information>
<h2>Fl::event_*() methods</h2>
Fltk keeps the information about the most recent event in static
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.
Thus it is valid inside <tt>handle()</tt> and <tt>callback()</tt> methods.
<p>These are all trivial inline functions and thus very fast and
small. The data is stored in static locations and remains valid until
the next X event is handled.
<a name=event_button>
</ul><h4><code>int Fl::event_button();</code></h4><ul>
Returns which mouse button was pressed. This returns garbage if the
most recent event was not a FL_PUSH or FL_RELEASE.
<a name=event_x>
</ul><h4><code>int Fl::event_x()</code>
<br><code>int Fl::event_y()</code></h4><ul>
Returns the mouse position of the event (relative to the Fl_Window it
was passed to).
</ul><h4><code>int Fl::event_x_root()</code>
<br><code>int Fl::event_y_root()</code></h4><ul>
Returns the mouse position on the screen of the event. To find the
absolute position of an Fl_Window on the screen, use the difference
between event_x_root and event_x.
<a name=get_mouse>
</ul><h4><code>void Fl::get_mouse(int &,int &)</code></h4><ul>
<p>Return where the mouse is on the screen by doing a round-trip query
to the server. You should use <a
href=#event_x>Fl::event_x/y_root()</a> if possible, but this is
necessary if you are not sure if a mouse event has been processed
recently (such as to position your first window). If the display is
not open, this will open it.
<a name=event_state>
</ul><h4><code>ulong Fl::event_state();
<br>unsigned int Fl::event_state(int);</code></h4><ul>
This is a bitfield of what shift states were on and what mouse buttons
were held down during the most recent event. The second version
returns non-zero if any of the passed bits are turned on. The legal
bits are <code>FL_SHIFT, FL_CAPS_LOCK, FL_CTRL, FL_ALT, FL_NUM_LOCK,
FL_META, FL_SCROLL_LOCK, FL_BUTTON1, FL_BUTTON2, FL_BUTTON3</code>.
<i><p>X servers do not agree on shift states and FL_NUM_LOCK, FL_META,
and FL_SCROLL_LOCK may not work. The values were selected to match
the XFree86 server on Linux. In addition there is a bug in the way
Xlib works so that the shift state is not correctly reported until the
first event <b>after</b> the shift key is pressed or released.</i>
<a name=event_key>
</ul><h4><code>int Fl::event_key();
<br>int Fl::event_key(int);
<br>int Fl::get_key(int);</code></h4><ul>
Fl::event_key() returns which key on the keyboard was last pushed.
<p>Fl::event_key(int) returns true if the given key was held down (or
pressed) <i>during</i> the last event. This is constant until the
next event is read from the server.
<p>Fl::get_key(int) returns true if the given key is held down
<i>now</i>. Under X this requires a round-trip to the server and is
<i>much</i> slower than Fl::event_key(int).
<p>Keys are identified by the <i>unshifted</i> X keysym values.
However fltk defines a set of symbols that should work on most modern
machines for every key on the generic PC keyboard:
<p><ul>
<li>All keys on the main keyboard producing a printable ASCII
character use the value of that ASCII character (as though shift,
ctrl, and caps lock were not on). The space bar is 32.
<li>All keys on the numeric keypad producing a printable ASCII
character use the value of that ASCII character plus
<code>FL_KP</code>. The highest possible value is
<code>FL_KP_Last</code> so you can range-check to see if something is
on the keypad.
<li>All numbered function keys use the number on the function key plus
<code>FL_F</code>. The highest possible number is
<code>FL_F_Last</code>, so you can range-check a value.
<li>Buttons on the mouse are considered keys, and use the button
number (where the left button is 1) plus <code>FL_Button</code>.
<li>All other keys on the keypad have a symbol: <code>FL_Escape,
FL_BackSpace, FL_Tab, FL_Enter, FL_Print, FL_Scroll_Lock, FL_Pause,
FL_Insert, FL_Home, FL_Page_Up, FL_Delete, FL_End, FL_Page_Down,
FL_Left, FL_Up, FL_Right, FL_Down, FL_Shift_L, FL_Shift_R,
FL_Control_L, FL_Control_R, FL_Caps_Lock, FL_Alt_L, FL_Alt_R,
FL_Meta_L, FL_Meta_R, FL_Menu, FL_Num_Lock, FL_KP_Enter</code>. Be
careful not to confuse these with the very similar, but all-caps,
symbols used by <a href=#event_state>Fl::event_state()</a>.
small:
<ul>
<li><a name="event_button">Fl::event_button</a>
<li><a name="event_clicks">Fl::event_clicks</a>
<li><a name="event_inside">Fl::event_inside</a>
<li><a name="event_is_click">Fl::event_is_click</a>
<li><a name="event_key">Fl::event_key</a>
<li><a name="event_length">Fl::event_length</a>
<li><a name="event_state">Fl::event_state</a>
<li><a name="event_text">Fl::event_text</a>
<li><a name="event_x">Fl::event_x</a>
<li><a name="event_x_root">Fl::event_x_root</a>
<li><a name="event_y">Fl::event_y</a>
<li><a name="event_y_root">Fl::event_y_root</a>
<li><a name="get_key">Fl::get_key</a>
<li><a name="get_mouse">Fl::get_mouse</a>
<li><a name="test_shortcut">Fl::test_shortcut</a>
</ul>
<p>Known bugs: on X <code>Fl::get_key(FL_Button+n)</code> does not
work. On MSWindows <code>Fl::get_key(FL_KP_Enter)</code> and
<code>Fl::event_key(FL_KP_Enter)</code> do not work.
<h2><a name="propagation">Event Propagation</a></h2>
<a name=event_text>
</ul><h4><code>char * Fl::event_text()</code></h4><ul>
<p>ASCII text (in the future this may be UTF-8) produced by the last
FL_KEYBOARD or FL_PASTE or possibly other event. A zero-length string
is returned for any keyboard function keys that do not produce text.
This pointer points at a static buffer and is only valid until the
next event is processed.
<p>Under X this is the result of XLookupString.
<a name=event_length>
</ul><h4><code>char * Fl::event_length()</code></h4><ul>
<p>Length of the text in Fl::event_text(). There will always be a
null at this position in the text. However there may be a nul before
that if the keystroke translates to a nul character or you paste a nul
character.
</ul><h4><code>int Fl::event_is_click()</code></h4><ul>
Returns non-zero if the mouse has not moved far enough and not enough
time has passed since the last FL_PUSH or FL_KEYBOARD event for it
to be considered a "drag" rather than a "click". You can test this on
FL_DRAG, FL_RELEASE, and FL_MOVE events.
</ul><h4><code>void Fl::event_is_click(0)</code></h4><ul>
Clear the value returned by Fl::event_is_click(). Useful to prevent
the <i>next</i> click from being counted as a double-click or to make
a popup menu pick an item with a single click. Don't pass non-zero to
this.
</ul><h4><code>int Fl::event_clicks()</code></h4><ul>
Returns non-zero if the most recent FL_PUSH or FL_KEYBOARD was a
"double click". Returns N-1 for N clicks. A double click is counted
if the same button is pressed again while event_is_click() is true.
</ul><h4><code>void Fl::event_clicks(int)</code></h4><ul>
Directly set the number returned by Fl::event_clicks(). This can be
used to set it to zero so that later code does not think an item was
double-clicked.
</ul><h4><code>int Fl::event_inside(const Fl_Widget *) const ;
<br>int Fl::event_inside(int,int,int,int);</code></h4><ul>
Returns non-zero if the current event_x and event_y put it inside the
widget or inside an arbitrary bounding box. You should always call
this rather than doing your own comparison so you are consistent about
edge effects.
</ul><h4><code>int Fl::test_shortcut(ulong) const ;</code></h4><ul>
Test the current event, which must be an FL_KEYBOARD or FL_SHORTCUT,
against a shortcut value (described in <a
href=Fl_Button.html#shortcut>Fl_Button</a>). Returns non-zero if
there is a match. Not to be confused with <a
href=subclass.html#test_shortcut>Fl_Widget::test_shortcut()</a>.
</ul>
<a name=propagation>
<h2>Event Propagation</h2>
<p>Fltk follows very simple and unchangeable rules for sending events.
The major innovation is that widgets can indicate (by returning 0 from
the handle() method) that they are not interested in an event, and fltk
can then send that event elsewhere. This eliminates the need for
FLTK follows very simple and unchangeable rules for sending events. The
major innovation is that widgets can indicate (by returning 0 from the
<tt>handle()</tt> method) that they are not interested in an event, and
FLTK can then send that event elsewhere. This eliminates the need for
"interests" (event masks or tables), and this is probably the main
reason fltk is much smaller than other X toolkits.
reason FLTK is much smaller than other toolkits.
<p>Most events are sent directly to the handle() method of the
Fl_Window that X 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, FL_LEAVE) directly to leaf
widgets. These procedures control those leaf widgets:
<p>Most events are sent directly to the <tt>handle()</tt> method of the
<tt>Fl_Window</tt> that the window system says they belong to. The
window (actually the <tt>Fl_Group</tt> that <tt>Fl_Window</tt> is a
subclass of) is responsible for sending the events on to any child
widgets. To make the <tt>Fl_Group</tt> code somewhat easier, FLTK
sends some events (<tt>FL_DRAG</tt>, <tt>FL_RELEASE</tt>,
<tt>FL_KEYBOARD</tt>, <tt>FL_SHORTCUT</tt>, <tt>FL_UNFOCUS</tt>, and
<tt>FL_LEAVE</tt>) directly to leaf widgets. These procedures control
those leaf widgets:
<a name=focus>
</ul><h4><code>Fl_Widget *Fl::focus() const;
<br>void Fl::focus(Fl_Widget *);</code></h4><ul>
Get or set the widget that will receive FL_KEYBOARD events.
<p>If you change Fl::focus(), the old one and all parents (that don't
contain the new widget) are sent FL_UNFOCUS events. Changing the
focus does <i>not</i> send FL_FOCUS to this or any widget, because
sending FL_FOCUS is supposed to <i>test</i> if the widget wants the
focus (by it returning non-zero from handle()).
</ul><h4><code>int Fl_Widget::take_focus();</code></h4><ul>
<p>Try to make this widget be the Fl::focus(), by first sending it an
FL_FOCUS event, and if it returns non-zero, setting Fl::focus() to
this widget. You should use this method to assign the focus to an
widget. Returns true if the widget accepted the focus.
<a name=belowmouse>
</ul><h4><code>Fl_Widget *Fl::belowmouse() const;
<br>void Fl::belowmouse(Fl_Widget *);</code></h4><ul>
Get or set the widget that is below the mouse. This is for
highlighting buttons. It is not used to send FL_PUSH or FL_MOVE
directly, for several obscure reasons, but those events typically go
to this widget. This is also the first widget tried for FL_SHORTCUT
events.
<p>If you change the belowmouse widget, the old one and all parents (that
don't contain the new widget) are sent FL_LEAVE events. Changing this
does <i>not</i> send FL_ENTER to this or any widget, because
sending FL_ENTER is supposed to <i>test</i> if the widget wants the
mouse (by it returning non-zero from handle()).
<a name=pushed>
</ul><h4><code>Fl_Widget *Fl::pushed() const;
<br>void Fl::pushed(Fl_Widget *);</code></h4><ul>
<p>Get or set the widget that is being pushed. FL_DRAG or FL_RELEASE
(and any more FL_PUSH) events will be sent to this widget.
<p>If you change the pushed widget, the old one and all parents (that
don't contain the new widget) are sent FL_RELEASE events. Changing
this does <i>not</i> send FL_PUSH to this or any widget, because
sending FL_PUSH is supposed to <i>test</i> if the widget wants the
mouse (by it returning non-zero from handle()).
<a name=add_handler>
</ul><h4><code>void Fl::add_handler(int (*f)(int));</code></h4><ul>
Install 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. Events that cause this to
be called are:
<p><ul>
<li>FL_SHORTCUT events that are not recognized by any widget. This
lets you provide global shortcut keys.
<li>System events that fltk does not recognize. See <a
href=x.html#fl_xevent>fl_xevent</a>.
<li><i>Some</i> other events when the widget fltk selected returns zero
from it's handle() method. Exactly which ones may change in future
versions, however.
<ul>
<li><a href="#add_handler">Fl::add_handler</a>
<li><a href="#belowmouse">Fl::belowmouse</a>
<li><a href="#focus">Fl::focus</a>
<li><a href="#grab">Fl::grab</a>
<li><a href="#modal">Fl::modal</a>
<li><a href="#pushed">Fl::pushed</a>
<li><a href="#release">Fl::release</a>
<li><a href="#Fl_Widget.take_focus">Fl_Widget::take_focus</a>
</ul>
<a name=modal>
</ul><h4><code>Fl_Window* Fl::modal();</code></h4><ul>
The modal() window has it's handle() method called for all events, and
no other windows will have handle() called. If <a
href=#grab>grab()</a> has been done then this is equal to grab().
Otherwise this is the most recently shown() window with <a
href=Fl_Window.html#modal>modal()</a> true, or null if there are no
modal() windows shown().
<a name=grab>
</ul><h4><code>void Fl::grab(Fl_Window&);<br>
Fl_Window* Fl::grab();</code></h4><ul>
This is used when pop-up menu systems are active. Send all events to
the passed window no matter where the pointer or focus is (including
in other programs). The window <i>does not have to be shown()</i>,
this lets the handle() method of a "dummy" window override all event
handling and allows you to map and unmap a complex set of windows
(under both X and NT <i>some</i> window must be mapped because the
system interface needs a window id).
<p>Fl::event_x() and y() are undefiend if the passed widget is not a
mapped Fl_Window. Use Fl::event_x_root() and Fl::event_y_root()
instead.
<p><i>Be careful that your program does not enter an infinite loop
while grab() is on. On X this will lock up your screen!</i>
<p>The second function returns the current grab window, or null if
none.
<a name=release>
</ul><h4><code>void Fl::release()</code></h4><ul>
Turn off the grab() behavior.
</ul><p><a href = index.html>(back to contents)</a>
</BODY>
</HTML>

File diff suppressed because it is too large Load Diff

View File

@ -3,182 +3,193 @@
<H1 ALIGN=RIGHT><A NAME="forms">E - Forms Compatibility</A></H1>
<a href="#fluid">Fluid</a> (the Fast Light User Interface Designer)
can read the .fd files put out by all versions of Forms and XForms
fdesign. However, it will mangle them a bit, but it prints a warning
message about anything it does not understand. Fluid cannot write
fdesign files, so you should save to a new name so you don't write
over the old one.
This appendix describes the Forms compatibility included with FLTK.
<H2>Importing Forms Layout Files</H2>
<a href="#FLUID">FLUID</a> can read the .fd files put out by all
versions of Forms and XForms fdesign. However, it will mangle them a
bit, but it prints a warning message about anything it does not
understand. FLUID cannot write fdesign files, so you should save to a
new name so you don't write over the old one.
<p>You will need to edit your main code considerably to get it to link
with the output from fluid. If you are not interested in this you may
have more immediate luck with the forms compatability header,
with the output from FLUID. If you are not interested in this you may
have more immediate luck with the forms compatibility header,
<tt>&lt;FL/forms.H></tt>.
<p>You should be able to compile existing Forms or XForms source code
by changing the -I switch to your compiler so that the forms.h file
supplied with FLTK is included. Take a look at forms.h to see how it
works, but the basic trick is lots of inline functions.
Most of the XForms demo programs work without changes.
<H2>Using the Compatibility Header File</H2>
You should be able to compile existing Forms or XForms source code
by changing the include directory switch to your compiler so that the
<tt>forms.h</tt> file supplied with FLTK is included. Take a look at
<tt>forms.h</tt> to see how it works, but the basic trick is lots of
inline functions. Most of the XForms demo programs work without
changes.
<p>You will also have to compile your Forms or XForms program using a
C++ compiler. The FLTK library does not provide C bindings or header
files.
<p>Although FLTK was designed to be compatable with the GL Forms library
(version 0.3 or so), XForms has bloated severely and it's interface is
X specific. Therefore, XForms compatability is no longer a goal of
FLTK. Compatability was limited to things that were free, or that
would add code that would not be linked in if the feature is unused.
I did not add anything that would make the FLTK widgets bigger, or that
used X types as arguments.
X-specific. Therefore, XForms compatibility is no longer a goal of
FLTK. Compatibility was limited to things that were free, or that
would add code that would not be linked in if the feature is unused,
or that was not X-specific.
<p>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 I
expeceted and even our inhouse code still uses forms.H a lot.
use the inline functions and instead use "pure" FLTK. This will make
it a lot cleaner and make it easier to figure out how to call the FLTK
functions. Unfortunately this conversion is harder than expected and
even Digital Domain's inhouse code still uses <tt>forms.H</tt> a lot.
<h2>Problems you will encounter</h2>
<ul>
<p><li>Many parts of XForms use X-specific structures like XEvent in
their interface. I did not emulate these! Unfortunately these
<p>Many parts of XForms use X-specific structures like <tt>XEvent</tt>
in their interface. I did not emulate these! Unfortunately these
features (such as the "canvas" widget) are needed by most large
programs. You will need to rewrite these to use FLTK subclasses.
<p><li><a href=Fl_Free.html>Fl_Free</a> widgets emulate the <i>old</i>
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.
<p><a href="#Fl_Free"><tt>Fl_Free</tt></a> widgets emulate the
<i>old</i> Forms "free" widget. It may be useful for porting programs
that change the <tt>handle()</tt> function on widgets, but you will
still need to rewrite things.
<P><li><a href=Fl_Timer.html>Fl_Timer</a> widgets are provided to
emulate the XForms timer. These work, but are quite inefficient
and inaccurate compared to using Fl::add_timeout().
<p><a href="#Fl_Timer"><tt>Fl_Timer</tt></a> widgets are provided to
emulate the XForms timer. These work, but are quite inefficient and
inaccurate compared to using <a
href="#add_timeout"><tt>Fl::add_timeout()</tt></a>.
<p><li><i>All instance variables are hidden.</i>
<p><i>All instance variables are hidden.</i>
If you directly refer to the x, y, w, h, label, or other fields of
your Forms widgets you will have to add empty parenthesis after each
reference. The easiest way to do this is to globally replace "->x"
with "->x()", etc. Replace "boxtype" with box().
with "->x()", etc. Replace "boxtype" with "box()".
<p><li>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 <a
href=Fl_Output.html>Fl_Output</a> widget.
<p><tt>const char *</tt> arguments to most FLTK methods are simply
stored, while Forms would <tt>strdup()</tt> the passed string. This is
most noticable with the label of widgets. Your program must always
pass static data such as a string constant or malloc'd buffer to
<tt>label()</tt>. If you are using labels to display program output
you may want to try the <a href="#Fl_Output"><tt>Fl_Output</tt></a> widget.
<p><li>The default fonts and sizes are matched to the older GL version of
<p>The default fonts and sizes are matched to the older GL version of
Forms, so all labels will draw somewhat larger than an XForms program
does.
<p><li>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.
<p>fdesign outputs a setting of a "fdui" instance variable to the main
window. I did not emulate this because I wanted all instance variables
to be hidden. You can store the same information in the
<tt>user_data()</tt> field of a window. To do this, search through
the fdesign output for all occurances of "->fdui" and edit to use
"->user_data()" instead. This will require casts and is not trivial.
<p><li>The prototype for the functions passed to fl_add_timeout() and
fl_set_idle_callback() callback are different.
<p>The prototype for the functions passed to <tt>fl_add_timeout()</tt>
and <tt>fl_set_idle_callback()</tt> callback are different.
<p><li><b>All the following XForms calls are missing:</b><p>
<p><b>All the following XForms calls are missing:</b><p>
<li><code>FL_VERSION, FL_REVISION</code>, fl_library_version()
<li><code>FL_RETURN_DBLCLICK</code> (use Fl::event_clicks())
<li>fl_add_signal_callback()
<li>fl_set_form_atactivate() & fl_set_form_atdeactivate()
<li>fl_set_form_property()
<li>fl_set_app_mainform(), fl_get_app_mainform()
<li>fl_set_form_minsize(), fl_set_form_maxsize()
<li>fl_set_form_event_cmask(), fl_get_form_event_cmask()
<li>fl_set_form_dblbuffer(), fl_set_object_dblbuffer() (use an
Fl_Double_Window instead)
<li>fl_adjust_form_size()
<li>fl_register_raw_callback()
<li>fl_set_object_bw(), fl_set_border_width()
<li>fl_set_object_resize(), fl_set_object_gravity()
<li>fl_set_object_shortcutkey()
<li>fl_set_object_automatic()
<li>fl_get_object_bbox() (maybe FLTK should do this)
<li>fl_set_object_prehandler(), fl_set_object_posthandler()
<li>fl_enumerate_fonts()
<li>Most drawing functions
<li>fl_set_coordunit() (FLTK uses pixels all the time)
<li>fl_ringbell()
<li>fl_gettime()
<li>fl_win*() (all these functions)
<li>fl_initialize(argc,argv,x,y,z) ignores last 3 arguments
<li>fl_read_bitmapfile(), fl_read_pixmapfile()
<li>fl_addto_browser_chars()
<li>FL_MENU_BUTTON just draws normally
<li>fl_set_bitmapbutton_file(), fl_set_pixmapbutton_file()
<li>FL_CANVAS objects
<li>FL_DIGITAL_CLOCK (comes out analog)
<li>fl_create_bitmap_cursor(), fl_set_cursor_color()
<li>fl_set_dial_angles()
<li>fl_show_oneliner()
<li>fl_set_choice_shortcut(a,b,c)
<li>command log
<li>Only some of file selector is emulated
<li>FL_DATE_INPUT
<li>fl_pup*() (all these functions)
<li>textbox object (should be easy but I had no sample programs)
<li>xyplot object
<ul>
<li><tt>FL_REVISION</tt>, <tt>fl_library_version()</tt>
<li><tt>FL_RETURN_DBLCLICK</tt> (use <tt>Fl::event_clicks()</tt>)
<li><tt>fl_add_signal_callback()</tt>
<li><tt>fl_set_form_atactivate()</tt> & <tt>fl_set_form_atdeactivate()</tt>
<li><tt>fl_set_form_property()</tt>
<li><tt>fl_set_app_mainform()</tt>, <tt>fl_get_app_mainform()</tt>
<li><tt>fl_set_form_minsize()</tt>, <tt>fl_set_form_maxsize()</tt>
<li><tt>fl_set_form_event_cmask()</tt>, <tt>fl_get_form_event_cmask()</tt>
<li><tt>fl_set_form_dblbuffer()</tt>, <tt>fl_set_object_dblbuffer()</tt> (use an
<tt>Fl_Double_Window</tt> instead)
<li><tt>fl_adjust_form_size()</tt>
<li><tt>fl_register_raw_callback()</tt>
<li><tt>fl_set_object_bw()</tt>, <tt>fl_set_border_width()</tt>
<li><tt>fl_set_object_resize()</tt>, <tt>fl_set_object_gravity()</tt>
<li><tt>fl_set_object_shortcutkey()</tt>
<li><tt>fl_set_object_automatic()</tt>
<li><tt>fl_get_object_bbox()</tt> (maybe FLTK should do this)
<li><tt>fl_set_object_prehandler()</tt>, <tt>fl_set_object_posthandler()</tt>
<li><tt>fl_enumerate_fonts()</tt>
<li>Most drawing functions
<li><tt>fl_set_coordunit()</tt> (FLTK uses pixels all the time)
<li><tt>fl_ringbell()</tt>
<li><tt>fl_gettime()</tt>
<li><tt>fl_win*()</tt> (all these functions)
<li><tt>fl_initialize(argc,argv,x,y,z)</tt> ignores last 3 arguments
<li><tt>fl_read_bitmapfile()</tt>, <tt>fl_read_pixmapfile()</tt>
<li><tt>fl_addto_browser_chars()</tt>
<li><tt>FL_MENU_BUTTON</tt> just draws normally
<li><tt>fl_set_bitmapbutton_file()</tt>, <tt>fl_set_pixmapbutton_file()</tt>
<li><tt>FL_CANVAS</tt> objects
<li><tt>FL_DIGITAL_CLOCK</tt> (comes out analog)
<li><tt>fl_create_bitmap_cursor()</tt>, <tt>fl_set_cursor_color()</tt>
<li><tt>fl_set_dial_angles()</tt>
<li><tt>fl_show_oneliner()</tt>
<li><tt>fl_set_choice_shortcut(a,b,c)
<li>command log
<li>Only some of file selector is emulated
<li><tt>FL_DATE_INPUT</tt>
<li><tt>fl_pup*()</tt> (all these functions)
<li>textbox object (should be easy but I had no sample programs)
<li>xyplot object
</ul>
<h2>Additional notes for porting old Forms programs</h2>
<h2>Additional Notes</h2>
<p>These notes were written for porting programs written with the
older GL version of Forms. Most of these problems are the same ones
These notes were written for porting programs written with the older
IRISGL version of Forms. Most of these problems are the same ones
encountered when going from old Forms to XForms:
<h4>Does not go into background</h4>
<h3>Does Not Run In Background</h3>
The GL library always forked when you created the first window, unless
The IRISGL library always forked when you created the first window, unless
"foreground()" was called. FLTK acts like "foreground()" is called all
the time. If you really want the fork behavior do "if (fork())
exit(0)" right at the start of your program.
<h4>You cannot use GL windows or fl_queue</h4>
<h3>You Cannot Use IRISGL windows or fl_queue</h3>
<P>If a Forms (not XForms) program if you wanted your own window for
displaying things you would create a GL window and draw in it,
If a Forms (not XForms) program if you wanted your own window for
displaying things you would create a IRISGL window and draw in it,
periodically calling Forms to check if the user hit buttons on the
panels. If the user did things to the GL window, you would find this
out by having the value FL_EVENT returned from the call to Forms.
panels. If the user did things to the IRISGL window, you would find
this out by having the value FL_EVENT returned from the call to Forms.
<p>None of this works with FLTK. Nor will it compile, the necessary
calls are not in the interface.
<p>You have to make a subclass of <a
href=Fl_Gl_Window.html>Fl_Gl_Window</a> and write a draw() method and
handle() method. This may require anywhere from a trivial to a major
rewrite. See the example program <a href=shape.C.html>shape.C</a> for
how this is structured.
href="#Fl_Gl_Window"><tt>Fl_Gl_Window</tt></a> and write a <tt>draw()</tt>
method and <tt>handle()</tt> method. This may require anywhere from a trivial
to a major rewrite.
<p>If you draw into the overlay planes you will have to also write a
draw_overlay() routine and call redraw_overlay() on the gl window.
<tt>draw_overlay()</tt> method and call <tt>redraw_overlay()</tt> on the
OpenGL window.
<p>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.
<p>One easy way to hack your program so it works is to make the
<tt>draw()</tt> and <tt>handle()</tt> methods on your window set some
static variables, storing what event happened. Then in the main loop
of your program, call <tt>Fl::wait()</tt> and then check these
variables, acting on them as though they are events read from
<tt>fl_queue</tt>.
<h4>You must use OpenGL to draw everything</h4>
<h3>You Must Use OpenGL to Draw Everything</h3>
<p>The file &lt;FL/gl.h> defines replacements for a lot of gl calls,
translating them to OpenGL. There are much better translators
available that you might want to investigate.
<p>The file <tt>&lt;FL/gl.h></tt> defines replacements for a lot of
IRISGL calls, translating them to OpenGL. There are much better
translators available that you might want to investigate.
<h4>You cannot make Forms subclasses</h4>
<h3>You Cannot Make Forms Subclasses</h3>
Programs that call fl_make_object or directly setting the handle
routine will not compile. You have to rewrite them to use a subclass
of Fl_Widget. It is important to note that the handle() method is not
exactly the same as the handle() function of Forms. Where a Forms
handle() returned non-zero, your handle() must call do_callback().
And your handle() must return non-zero if it "understood" the event.
Programs that call <tt>fl_make_object</tt> or directly setting the
handle routine will not compile. You have to rewrite them to use a
subclass of <tt>Fl_Widget</tt>. It is important to note that the
<tt>handle()</tt> method is not exactly the same as the
<tt>handle()</tt> function of Forms. Where a Forms <tt>handle()</tt>
returned non-zero, your <tt>handle()</tt> must call
<tt>do_callback()</tt>. And your <tt>handle()</tt> must return non-zero
if it "understood" the event.
<p>An attempt has been made to emulate the "free" widget. This
appears to work quite well. It may be quicker to modify your subclass
@ -187,34 +198,64 @@ into a "free" widget, since the "handle" functions match.
<p>If your subclass draws into the overlay you are in trouble and will
have to rewrite things a lot.
<h4>You cannot use &lt;device.h></h4>
<h3>You Cannot Use &lt;device.h></h3>
If you have written your own "free" widgets you will probably get a
lot of errors about "getvaluator". You should substitute:
<table>
<tr><td align=center>Forms <td align=center>FLTK
<tr><td>MOUSE_X <td>Fl::event_x_root()
<tr><td>MOUSE_Y<td> Fl::event_y_root()
<tr><td>LEFTSHIFTKEY,RIGHTSHIFTKEY<td> Fl::event_shift()
<tr><td>CAPSLOCKKEY<td> Fl::event_capslock()
<tr><td>LEFTCTRLKEY,RIGHTCTRLKEY<td> Fl::event_ctrl()
<tr><td>LEFTALTKEY,RIGHTALTKEY<td> Fl::event_alt()
<tr><td>MOUSE1,RIGHTMOUSE<td> Fl::event_state()&(1<<10)
<tr><td>MOUSE2,MIDDLEMOUSE<td> Fl::event_state()&(1<<9)
<tr><td>MOUSE3,LEFTMOUSE<td> Fl::event_state()&(1<<8)
<table border=1>
<tr>
<th align=center>Forms</th>
<th align=center>FLTK</th>
</tr>
<tr>
<td>MOUSE_X</td>
<td>Fl::event_x_root()</td>
</tr>
<tr>
<td>MOUSE_Y</td>
<td>Fl::event_y_root()</td>
</tr>
<tr>
<td>LEFTSHIFTKEY,RIGHTSHIFTKEY</td>
<td>Fl::event_shift()</td>
</tr>
<tr>
<td>CAPSLOCKKEY</td>
<td>Fl::event_capslock()</td>
</tr>
<tr>
<td>LEFTCTRLKEY,RIGHTCTRLKEY</td>
<td>Fl::event_ctrl()</td>
</tr>
<tr>
<td>LEFTALTKEY,RIGHTALTKEY</td>
<td>Fl::event_alt()</td>
</tr>
<tr>
<td>MOUSE1,RIGHTMOUSE</td>
<td>Fl::event_state()&FL_BUTTON3</td>
</tr>
<tr>
<td>MOUSE2,MIDDLEMOUSE</td>
<td>Fl::event_state()&FL_BUTTON2</td>
</tr>
<tr>
<td>MOUSE3,LEFTMOUSE</td>
<td>Fl::event_state()&FL_BUTTON1</td>
</tr>
</table>
<p>Anything else in getvaluator and you are on your own...
Anything else in <tt>getvaluator</tt> and you are on your own...
<h4>Font numbers are different</h4>
<h3>Font Numbers Are Different</h3>
The "style" numbers have been changed because I wanted to insert
bold-italic versions of the normal fonts. If you use Times, Courier,
or Bookman to display any text you will get a different font out of
FLTK. If you are really desperate to fix this use the following code:<ul>
FLTK. If you are really desperate to fix this use the following code:
<pre>
<ul><pre>
fl_font_name(3,"*courier-medium-r-no*");
fl_font_name(4,"*courier-bold-r-no*");
fl_font_name(5,"*courier-medium-o-no*");

File diff suppressed because it is too large Load Diff

View File

@ -3,143 +3,192 @@
<H1 ALIGN=RIGHT><A NAME="glut">D - GLUT Compatibility</A></H1>
You should be able to compile existing Glut source code by
including &lt;FL/glut.H> instead of &lt;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.
This appendix describes the GLUT compatibility header file supplied with
FLTK.
<p>All files calling glut procedures must be compiled with C++. You may
<H2>Using the GLUT Compatibility Header File</H2>
You should be able to compile existing GLUT source code by including
<tt>&lt;FL/glut.H></tt> instead of <tt>&lt;GL/glut.h></tt>. This can
be done by editing the source, by changing the <tt>-I</tt> switches to
the compiler, or by providing a symbolic link from <tt>GL/glut.h</tt>
to <tt>FL/glut.H</tt>.
<p><i>All files calling GLUT procedures must be compiled with C++</i>. You may
have to alter them slightly to get them to compile without warnings,
and you may have to rename them to get make to use the C++ compiler.
I was unable to get some calls to glu to compile without adding some
casts, apparently due to errors in the glu header files.
<p>You must link with -lFl. If you call any glut drawing functions
that fltk does not emulate (<code>glutExtensionsSupported(), glutWire*(),
glutSolid*(), and glutStroke*()</code>), you will also have to link with
-lglut, <i>after</i> -lFl.
<p>You must link with the FLTK library. If you call any GLUT drawing
functions that FLTK does not emulate
(<tt>glutExtensionsSupported()</tt>, <tt>glutWire*()</tt>,
<tt>glutSolid*()</tt>, and <tt>glutStroke*()</tt>), you will also have
to link with the GLUT library (<i>after</i> the FLTK library!)
<p>Most of glut.H is inline functions. You should take a look at it
(and maybe at glut.C in the fltk source) if you are having trouble
porting your Glut program.
<p>Most of <tt>FL/glut.H</tt> is inline functions. You should take a
look at it (and maybe at <tt>test/glut.cxx</tt> in the FLTK source) if
you are having trouble porting your GLUT program.
<p>This has been tested with most of the demo programs that come with
the Glut 3.3 distribution.
the GLUT 3.3 distribution.
<h2>Known Problems</h2>
The following functions and/or arguments to functions are missing,
and you will have to replace them or comment them out for your code to
compile:
<ul>
<li>The following functions and/or arguments to functions are missing,
and you will have to replace them or comment them out for your code to
compile:<ul>
<li><code>glutLayerGet(GLUT_LAYER_IN_USE)</code>
<li><code>glutLayerGet(GLUT_HAS_OVERLAY)</code>
<li><code>glutSetColor(), glutGetColor(), glutCopyColormap()</code>
<li><code>glutInitDisplayMode(GLUT_STEREO)</code>
<li><code>glutInitDisplayMode(GLUT_LUMINANCE)</code>
<li><code>glutPushWindow()</code>
<li><code>glutWarpPointer()</code>
<li>Spaceball, buttonbox, dials, tablet functions, <code>glutDeviceGet()</code>
<li><code>glutWindowStatusFunc()</code>
<li><code>glutGet(GLUT_WINDOW_NUM_CHILDREN)</code>
<li><code>glutGet(GLUT_SCREEN_WIDTH_MM)</code>
<li><code>glutGet(GLUT_SCREEN_HEIGHT_MM)</code>
<li><code>glutGet(GLUT_ELAPSED_TIME)</code>
<li><code>glutVideoResize()</code> missing.
<li><tt>glutLayerGet(GLUT_LAYER_IN_USE)</tt>
<li><tt>glutLayerGet(GLUT_HAS_OVERLAY)</tt>
<li><tt>glutSetColor(), glutGetColor(), glutCopyColormap()</tt>
<li><tt>glutInitDisplayMode(GLUT_STEREO)</tt>
<li><tt>glutInitDisplayMode(GLUT_LUMINANCE)</tt>
<li><tt>glutPushWindow()</tt>
<li><tt>glutWarpPointer()</tt>
<li>Spaceball, buttonbox, dials, tablet functions,
<tt>glutDeviceGet()</tt>
<li><tt>glutWindowStatusFunc()</tt>
<li><tt>glutGet(GLUT_WINDOW_NUM_CHILDREN)</tt>
<li><tt>glutGet(GLUT_SCREEN_WIDTH_MM)</tt>
<li><tt>glutGet(GLUT_SCREEN_HEIGHT_MM)</tt>
<li><tt>glutGet(GLUT_ELAPSED_TIME)</tt>
<li><tt>glutVideoResize()</tt> missing.
</ul>
<li>Most of the symbols/enumerations have different values than
Glut uses. This will break code that relies on the actual values.
Most of the symbols/enumerations have different values than
GLUT uses. This will break code that relies on the actual values.
The only symbols guaranteed to have the same values are true/false
pairs like <code>GLUT_DOWN</code> and <code>GLUT_UP</code>, mouse
buttons <code>GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON,
GLUT_RIGHT_BUTTON</code>, and <code>GLUT_KEY_F1</code> thru
<code>F12</code>.
pairs like <tt>GLUT_DOWN</tt> and <tt>GLUT_UP</tt>, mouse
buttons <tt>GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON,
GLUT_RIGHT_BUTTON</tt>, and <tt>GLUT_KEY_F1</tt> thru
<tt>F12</tt>.
<li><i>The strings passed as menu labels are not copied</i>.
<p>The strings passed as menu labels are not copied.
<li><code>glutPostRedisplay()</code> does not work if called from
inside a display function. You must use <code>glutIdleFunc()</code>
<p><tt>glutPostRedisplay()</tt> does not work if called from
inside a display function. You must use <tt>glutIdleFunc()</tt>
if you want your display to update continuously.
<li><code>glutSwapBuffers()</code> does not work from inside a display
function. This is on purpose, because fltk swaps the buffers for you.
<p><tt>glutSwapBuffers()</tt> does not work from inside a display
function. This is on purpose, because FLTK swaps the buffers for you.
<li><code>glutUseLayer()</code> does not work well, and should only be
<p><tt>glutUseLayer()</tt> does not work well, and should only be
used to initialize transformations inside a resize callback. You
should redraw overlays by using <code>glutOverlayDisplayFunc()</code>.
should redraw overlays by using <tt>glutOverlayDisplayFunc()</tt>.
<li>Overlays are cleared before the overlay display function is
called. <code>glutLayerGet(GLUT_OVERLAY_DAMAGED)</code> always
returns true, this fixed 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.
<p>Overlays are cleared before the overlay display function is called.
<tt>glutLayerGet(GLUT_OVERLAY_DAMAGED)</tt> always returns true for
compatibility with some GLUT overlay programs. You must rewrite your
code so that <tt>gl_color()</tt> is used to choose colors in an
overlay, or you will get random overlay colors.
<li><code>glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR)</code> just
<p><tt>glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR)</tt> just
results in a small crosshair.
<li>The fonts used by <code>glutBitmapCharacter() and
glutBitmapWidth()</code> may be different.
<p>The fonts used by <tt>glutBitmapCharacter() and
glutBitmapWidth()</tt> may be different.
<li><code>glutInit(argc,argv)</code> will consume different switches than glut
<p><tt>glutInit(argc,argv)</tt> will consume different switches than GLUT
does. It accepts the switches recognized by <a
href=Fl.html>Fl_Window::arg()</a>, and will accept any
abbreviation of these switches (such as -d for -display).
href="#args"><tt>Fl::args()</tt></a>, and will accept any
abbreviation of these switches (such as "-di" for "-display").
<h2>Mixing GLUT and FLTK Code</h2>
You can make your GLUT window a child of a <tt>Fl_Window</tt> with the
following scheme. The biggest trick is that GLUT insists on
<tt>show()</tt>'ing the window at the point it is created, which means the
<tt>Fl_Window</tt> parent window must already be shown.
<ul>
<li>Don't call <tt>glutInit()</tt>.
<li>Create your <tt>Fl_Window</tt>, and any FLTK widgets.
Leave a blank area in the window for your GLUT window.
<li><tt>show()</tt> the <tt>Fl_Window</tt>. Perhaps call
<tt>show(argc,argv)</tt>.
<li>Call <tt>window->begin()</tt> so that the GLUT window will
be automatically added to it.
<li>Use <tt>glutInitWindowSize()</tt> and
<tt>glutInitWindowPosition()</tt> to set the location in the
parent window to put the GLUT window.
<li>Put your GLUT code next. It probably does not need many changes.
Call <tt>window->end()</tt> immediately after the <tt>glutCreateWindow()</tt>!
<li>You can call either <tt>glutMainLoop()</tt>,
<tt>Fl::run()</tt>, or loop calling <tt>Fl::wait()</tt> to run
the program.
</ul>
<h2>Mixing Glut code and Fltk code</h2>
<hr break>
You can make your Glut window a child of a Fl_Window with the
following scheme. The biggest trick is that Glut insists on
show()'ing the window at the point it is created, which means the
Fl_Window parent window must already be show()n.
<h2><a name="Fl_Glut_Window">class Fl_Glut_Window</a></h2>
<p>Don't call glutInit().
<hr>
<p>Create your Fl_Window, and any fltk widgets. Leave a blank area in
the window for your glut window.
<h3>Class Hierarchy</h3>
<p>show() the Fl_Window. Perhaps call show(argc,argv).
<ul><pre>
<a href="#Fl_Gl_Window">Fl_Gl_Window</a>
|
+----<b>Fl_Glut_Window</b>
</pre></ul>
<p>Call window->begin() so the glut window will be automatically added
to it.
<h3>Include Files</h3>
<p>Use glutInitWindowSize() and glutInitWindowPosition() to set the
location in the parent window to put the glut window.
<ul><pre>
#include &lt;FL/glut.H>
</pre></ul>
<p>Put your glut code next. It probably does not need many changes.
Call window->end() immediately after the glutCreateWindow()!
<h3>Description</h3>
<p>You can call either glutMainLoop() or Fl::run() or loop calling
Fl::wait() to run the program.
<h2>class Fl_Glut_Window : public <a href=Fl_Gl_Window.html>Fl_Gl_Window</a></h2>
Each Glut window is an instance of this class, which is a subclass of
<a href=Fl_Gl_Window.html>Fl_Gl_Window</a>. You may find it useful to
manipulate instances directly rather than use glut window id's. These
Each GLUT window is an instance of this class. You may find it useful to
manipulate instances directly rather than use GLUT window id's. These
may be created without opening the display, and thus can fit better
into FL's method of creating windows.
into FLTK's method of creating windows.
<p>The current glut window is available in <code>Fl_Glut_Window
*glut_window</code>.
<p>The current GLUT window is available in the global variable
<tt>glut_window</tt>.
<p><code>new Fl_Glut_Window(...)</code> is the same as
<code>glutCreateWindow()</code> except it does not show() the window
<p><tt>new Fl_Glut_Window(...)</tt> is the same as
<tt>glutCreateWindow()</tt> except it does not <tt>show()</tt> the window
or make the window current.
<p><code>window->make_current()</code> is the same as
<code>glutSetWindow(number)</code>. If the window has not had show()
called on it yet, some functions that assumme a gl context will not
work. If you do show() the window, call make_current() again to set
the context.
<p><tt>window->make_current()</tt> is the same as
<tt>glutSetWindow(number)</tt>. If the window has not had
<tt>show()</tt> called on it yet, some functions that assumme an OpenGL
context will not work. If you do <tt>show()</tt> the window, call
<tt>make_current()</tt> again to set the context.
<p><code>~Fl_Glut_Window()</code> is the same as
<code>glutDestroyWindow()</code>.
<p><tt>~Fl_Glut_Window()</tt> is the same as
<tt>glutDestroyWindow()</tt>.
<h3>Methods</h3>
<ul>
<li><a href="#Fl_Glut_Window.Fl_Glut_Window">Fl_Glut_Window</a>
<li><a href="#Fl_Glut_Window.~Fl_Glut_Window">~Fl_Glut_Window</a>
</ul>
<h4><a name="Fl_Glut_Window.Fl_Glut_Window">Fl_Glut_Window::Fl_Glut_Window(int x, int y, int w, int h, const char *title = 0)<br>
Fl_Glut_Window::Fl_Glut_Window(int w, int h, const char *title = 0)</a></h4>
The first constructor takes 4 int arguments to create the window with
a preset position and size. The second constructor with 2 arguments
will create the window with a preset size, but the window manager
will choose the position according to it's own whims.
<h4><a name="Fl_Glut_Window.~Fl_Glut_Window">virtual Fl_Glut_Window::~Fl_Glut_Window()</a></h4>
Destroys the GLUT window.
</BODY>
</HTML>

View File

@ -78,7 +78,7 @@ has started being included on Linux distributions.
<p>Here are some of the core features unique to FLTK:
<ul>
<li>sizeof(Fl_Widget) == 48.</li>
<li>sizeof(Fl_Widget) == 40 to 48.</li>
<li>The "core" (the "hello" program compiled &amp; linked with a static FLTK
library using gcc on a 486 and then stripped) is 39.5K.</li>
@ -112,9 +112,9 @@ has started being included on Linux distributions.
<li>Text input fields with Emacs key bindings, X cut &amp;
paste, and foreign letter compose!</li>
<li>Compatability header file for the GLUT library.</li>
<li>Compatibility header file for the GLUT library.</li>
<li>Compatability header file for the XForms library.</li>
<li>Compatibility header file for the XForms library.</li>
<li>Much too much to list here...</li>
</ul>
@ -228,9 +228,11 @@ FLTK is available on the 'net in a bunch of locations:
<dt>FTP</dt>
<dd><a href="ftp://ftp.easysw.com/pub/fltk">ftp://ftp.easysw.com/pub/fltk</a><br>
<a href="ftp://ftp.funet.fi/mirrors/ftp.easysw.com/pub/fltk">ftp://ftp.funet.fi/mirrors/ftp.easysw.com/pub/fltk</a><br>
<a href="ftp://ftp.northamerica.net/pub/ESP/fltk">ftp.northamerica.net/pub/ESP/fltk</a><br></dd>
<dd><a href="ftp://ftp.easysw.com/pub/fltk">ftp://ftp.easysw.com/pub/fltk</a></dd>
<dd><a href="ftp://ftp.funet.fi/mirrors/ftp.easysw.com/pub/fltk">ftp://ftp.funet.fi/mirrors/ftp.easysw.com/pub/fltk</a></dd>
<dd><a href="ftp://ftp.northamerica.net/pub/ESP/fltk">ftp.northamerica.net/pub/ESP/fltk</a><br></dd>
<dt>EMail</dt>

View File

@ -5,7 +5,7 @@
<H2>GNU LIBRARY GENERAL PUBLIC LICENSE</H2>
<P>Version 2, June 1991<BR>
<P ALIGN=CENTER>Version 2, June 1991<BR>
Copyright (C) 1991 Free Software Foundation, Inc.<BR>
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA<BR>
Everyone is permitted to copy and distribute verbatim copies
@ -103,7 +103,7 @@ works together with the library.
<P>Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
<H2>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H2>
<H2 ALIGN=CENTER>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H2>
<STRONG>0.</STRONG> This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
@ -437,7 +437,7 @@ 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.
<H2>NO WARRANTY</H2>
<H2 ALIGN=CENTER>NO WARRANTY</H2>
<P><STRONG>15.</STRONG>
BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
@ -462,7 +462,7 @@ 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.
<H2>END OF TERMS AND CONDITIONS</H2>
<H2 ALIGN=CENTER>END OF TERMS AND CONDITIONS</H2>
</BODY>
</HTML>

View File

@ -1,486 +1,360 @@
<HTML>
<BODY>
<H1 ALIGN=RIGHT><A NAME="opengl">7 - Using OpenGL</A></H1>
<H1 ALIGN=RIGHT><A NAME="opengl">9 - Using OpenGL</A></H1>
This chapter discusses using FLTK for your OpenGL applications.
<H2>The OpenGL Widget</H2>
<h2>Using OpenGL in FLTK</h2>
<H2>Making a Simple OpenGL Wrapper Widget</H2>
The easiest way to make an OpenGL display is to subclass <a
href="#Fl_Gl_Window"><tt>Fl_Gl_Window</tt></a>. Your subclass must
implement a <tt>draw()</tt> method which uses OpenGL calls to draw the
display. Your main program should call <tt>redraw()</tt> when the
display needs to change, and (somewhat later) FLTK will call
<tt>draw()</tt>.
<H2>A Simple Flight Simulator</H2>
<p>With a bit of care you can also use OpenGL to draw into normal FLTK
windows. This is mostly useful because you can use Gourand shading for
drawing your widgets. To do this you use the <a
href="#gl_start"><tt>gl_start()</tt></a> and <a
href="#gl_finish"><tt>gl_finish()</tt></a> functions around your OpenGL
code.
<H2>Using FLTK with OpenGL Optimizer</H2>
<p>You must include FLTK's <tt>&lt;FL/gl.h></tt> header file. It will include
the file <tt>&lt;GL/gl.h></tt>, define some extra drawing functions
provided by FLTK, and include the <tt>&lt;windows.h></tt> header file needed
by WIN32 applications.
<H2>Using OpenGL Optimizer for the Flight Simulator</H2>
<h2>Making a Subclass of Fl_Gl_Window</h2>
</BODY>
</HTML>
<title>Using OpenGL in Fltk</title>
To make a subclass of Fl_Gl_Window, you must provide:
<h2>Using OpenGL in Fltk<br>#include &lt;FL/gl.h></h2>
<ul>
The easiest way to make an OpenGL display is to subclass Fl_Gl_Window.
Your subclass should implement a draw() method which uses OpenGL calls
to draw the display. Your main program should call w->redraw() when
the display needs to change, and (somewhat later) fltk will call
draw().
<li>A class definition.
<li>A <tt>draw()</tt> method.
<li>A <tt>handle()</tt> method (if you need to recieve input from
the user).
</ul>
<p>With a bit of care you can also use OpenGL to draw into normal fltk
windows. This is mostly useful because you can access Gourand shading
for drawing your widgets. To do this you use the <a
href=#gl_start>gl_start() and gl_finish()</a> functions around your
OpenGL code.
<h3>Defining the Subclass</h3>
<p>You must include fltk's &lt;FL/gl.h> header file. It will include
the file &lt;GL/gl.h>, plus it defines some extra drawing functions
provided by fltk, and also gets around a horrid screwup by our friends
in Seattle.
To define the subclass you just subclass <tt>Fl_Gl_Window</tt> class:
<h2>Sample code for subclassing Fl_Gl_Window</h2>
<ul><pre>
class MyWindow : public Fl_Gl_Window {
void draw();
int handle(int);
<p><pre>
class MyWindow : public Fl_Gl_Window {
void draw();
int handle(int);
public:
MyWindow(int X, int Y, int W, int H, const char* L)
: Fl_Gl_Window(X,Y,W,H,L) {}
};
public:
MyWindow(int X, int Y, int W, int H, const char *L)
: Fl_Gl_Window(X, Y, W, H, L) {}
};
</pre></ul>
void MyWindow::draw() {
The <tt>draw()</tt> and <tt>handle()</tt> methods are described below. Like
any widget, you can include additional private and public data in your class
(such as scene graph information, etc.)
<h3>The draw() Method</H3>
The <tt>draw()</tt> method is where you actually do your OpenGL drawing:
<ul><pre>
void MyWindow::draw() {
if (!valid()) {
... set up projection, viewport, etc ...
... window size is in w() and h().
... valid() is turned on by FLTK after draw() returns
}
... draw ...
}
</pre></ul>
<h3>The handle() Method</h3>
The <tt>handle()</tt> method handles mouse and keyboard events for the
window:
<ul><pre>
int MyWindow::handle(int event) {
switch(event) {
case FL_PUSH:
... mouse down event ...
... position in Fl::event_x() and Fl::event_y()
return 1;
case FL_DRAG:
... mouse moved while down event ...
return 1;
case FL_RELEASE:
... mouse up event ...
return 1;
case FL_FOCUS :
case FL_UNFOCUS :
... Return 1 if you want keyboard events, 0 otherwise
return 1;
case FL_KEYBOARD:
... keypress, key is in Fl::event_key(), ascii in Fl::event_text()
... Return 1 if you understand/use the keyboard event, 0 otherwise...
return 1;
default:
// tell FLTK that I don't understand other events
return 0;
}
}
</pre></ul>
When <tt>handle()</tt> is called, the OpenGL context is not set up! If your
display changes, you should call <tt>redraw()</tt> and let <tt>draw()</tt> do the work.
Don't call any OpenGL drawing functions from inside <tt>handle()</tt>!
<p>You can call some OpenGL stuff like hit detection and texture loading
functions by doing:
<ul><pre>
case FL_PUSH:
make_current(); // make OpenGL context current
if (!valid()) {
... set up projection, viewport, etc ...
... window size is in w() and h().
... valid() is turned on by fltk after draw() returns
... set up projection exactly the same as draw ...
valid(1); // stop it from doing this next time
}
... draw ...
}
... ok to call NON-DRAWING OpenGL code here, such as hit
detection, loading textures, etc...
</pre></ul>
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_KEYBOARD:
... keypress, key is in Fl::event_key(), ascii in Fl::event_text()
return 1;
default:
// tell fltk that I don't understand other events
return 0;
}
}
</pre>
<p>When handle() is called, the glx context is not set up! If your
display changes, you should call redraw() and let draw() do the work.
Don't call any gl functions from inside handle()!
<p>This may mean you cannot call some OpenGl stuff like hit detection.
You can fix this by doing:
<p><pre>
case FL_PUSH:
make_current(); // make glx 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 ...
</pre>
<p>Your main program can now create one of your windows by doing "new
MyWindow(...)". You can also use <a href=fluid.html>fluid</a>:
Your main program can now create one of your windows by doing <tt>new
MyWindow(...)</tt>. You can also use <a href="#fluid">fluid</a> by:
<ol>
<li>Put your class definition in a MyWindow.H file.
<li>In fluid create a box object, resize & place where you want.
<li>In the control panel, fill in the "class" field with MyWindow.H.
This will make fluid produce constructors for your new class.
<li>In the "extra code" put "#include "MyWindow.H"", so that the fluid
output file will compile.
<li>Put your class definition in a MyWindow.H file.
<li>In fluid create a box object, resize & place where you want.
<li>In the control panel, fill in the "class" field with MyWindow.H.
This will make fluid produce constructors for your new class.
<li>In the "extra code" put <tt>#include "MyWindow.H"</tt>, so
that the fluid output file will compile.
</ol>
<p>You must put glwindow->show() in your main code after calling
show() on the window containing the gl window.
You must put <tt>glwindow->show()</tt> in your main code after calling
<tt>show()</tt> on the window containing the OpenGL window.
<p><hr>
<h2>class Fl_Gl_Window : public <a href=Fl_Window.html>Fl_Window</a></h2>
<h2>Using OpenGL in Normal FLTK Windows</h2>
<p>An Fl_Gl_Window sets things up so OpenGL works, and also keeps an
OpenGL "context" for that window, so that changes to the lighting and
projection may be reused between redraws. Fl_Gl_Window also flushes
the OpenGL streams and swaps buffers after draw() returns.
<p>Fl_Gl_Window::draw() is a pure virtual method. You must subclass
Fl_Gl_Window and provide an implementation for draw(). You may also
provide an implementation of draw_overlay() if you want to draw into
the overlay planes. You can avoid reinitializing the viewport and
lights and other things by checking valid() at the start of draw() and
only doing the initialization if it is false.
<p>The draw() method can <i>only</i> use OpenGL calls. Do not attempt to
call X, any of the functions in &lt;FL/fl_draw.H>, or glX directly. Do
not call gl_start() or gl_finish().
<h2>Methods:</h2>
<h4><code>Fl_Gl_Window::Fl_Gl_Window(int W, int H, const char *l=0);
<br>Fl_Gl_Window::Fl_Gl_Window(int X, int Y, int W, int H, const char
*l=0)</code></h4><ul>
The constructors. Fl_Gl_Window::mode() defaults to
<code>FL_RGB|FL_DOUBLE|FL_DEPTH</code>.
<a name=mode>
</ul><h4><code>const int Fl_Gl_Window::mode() const;
<br>int Fl_Gl_Window::mode(int);</code></h4><ul>
Set or change the OpenGL capabilites of the window. The value can be
any of the following or'd together:
<p><ul>
<li><code>FL_RGB</code> - Color (not indexed)
<li><code>FL_RGB8</code> - Color with at least 8 bits of each color
<li><code>FL_INDEX</code> - Indexed mode
<li><code>FL_SINGLE</code> - not double buffered
<li><code>FL_DOUBLE</code> - double buffered
<li><code>FL_ACCUM</code> - accumulation buffer
<li><code>FL_ALPHA</code> - alpha channel in color
<li><code>FL_DEPTH</code> - depth buffer
<li><code>FL_STENCIL</code> - stencil buffer
<li><code>FL_MULTISAMPLE</code> - multisample antialiasing
</ul>
<p><code>FL_RGB</code> and <code>FL_SINGLE</code> have a
value of zero, they are "on" <i>unless</i> you give
<code>FL_INDEX</code> or <code>FL_DOUBLE</code>.
<p>If the desired combination cannot be done, fltk will try turning off
the <code>FL_MULTISAMPLE</code>. If this also fails show() will call
Fl::error() and not show the window.
<p>You can change the mode while the window is displayed. This
is most useful for turning double-buffering on and off. <i>Under
X this will cause the old X window to be destroyed and a new one
created. If this is a top-level window this will unfortunately also
cause the window to blink, raise to the top, and be de-iconized, and
the xid() will change, possibly breaking other code. It is best to
make the GL window a child of another window if you wish to do this!</i>
</ul><h4><code>int Fl_Gl_Window::mode(const int *);</code></h4><ul>
<p><i>This call only works on systems using glX.</i> This value is
passed unchanged to glXChooseVisual(), superceeding the value
calculated from mode(int). See "man glXChooseVisual" if you wish to
construct your own mode. Fltk assummes that the pointer is to static
const data, and caches the pointer with the found visual.
glXChooseVisual is not called until show() or can_do()
is called. To restore the use of mode(int), call
<code>mode((int*)0)</code>.
</ul><h4><code>static int Fl_Gl_Window::can_do(int);
<br>static int Fl_Gl_Window::can_do(const int *mode);
<br>int Fl_Gl_Window::can_do() const;</code></h4><ul>
Returns non-zero if show() will not call Fl::error() if called with
the given or current mode.
</ul><h4><code>char Fl_Gl_Window::valid() const;
<br>void Fl_Gl_Window::invalidate();
<br>void Fl_Gl_Window::valid(char i);</code></h4><ul>
<code>Fl_Gl_Window::valid()</code> is turned off when fltk creates a
new context for this window and by the window resizing, and is turned
on <i>after</i> draw() is called. You can use this inside your draw()
method to avoid unneccessarily initializing the OpenGL context. Just
do this:
<ul><pre><code>void mywindow::draw() {
if (!valid()) {
glViewport(0,0,w(),h());
glFrustum(...);
glLight(...);
...other initilization...
}
... draw your geometry here ...
}
</code></pre></ul>
<p>You can also turn valid() off yourself (for instance if you know
the current projection has changed). To do this call
<code>invalidate()</code>.
<p>You can turn valid() on by calling valid(1). You should only do
this after fixing the transformation inside a draw() or after
make_current(). This is done automatically after draw() returns.
</ul><h4><code>void Fl_Gl_Window::ortho();</code></h4><ul>
Set the projection so 0,0 is in the lower left of the window and each
pixel is 1 unit wide/tall. If you are drawing 2D images, your draw()
method may want to call this if valid() is false.
</ul><h4><code>void Fl_Gl_Window::make_current();
<br>void Fl_Gl_Window::make_overlay_current();
<br>void Fl_Gl_Window::swap_buffers();</code></h4><ul>
These functions can be used to set the current GL context to a window
and draw into it incrementally, rather than using the draw() method.
You will also need to call make_current() to do OpenGL feedback or hit
detection in response to events. After calling make_current(), be
sure to test valid(), and if false, initialize the transformation and
call valid(1).
</ul><h4><code>void Fl_Gl_Window::hide();
<br>Fl_Gl_Window::~Fl_Gl_Window();</code></h4><ul>
Hiding the window or destroying it also destroys the OpenGL context it
uses.
</ul><h2>Fl_Gl_Window overlay</h2>
GL hardware typically provides some overlay bit planes, which are very
useful for drawing UI controls atop your 3D graphics. If the overlay
hardware is not provided, fltk tries to simulate the overlay, this works
pretty well if your graphics are double buffered, but not very well
for single-buffered.
</ul><h4><code>int Fl_Gl_Window::can_do_overlay();</code></h4><ul>
Returns true if the hardware overlay is possible. If this is false,
fltk will try to simulate the overlay, with significant loss of update
speed. Calling this will cause fltk to open the display.
</ul><h4><code>void Fl_Gl_Window::redraw_overlay();</code></h4><ul>
Call this if what is drawn in the overlay needs to change, this will
cause draw_overlay to be called at a later time. Initially the
overlay is clear, if you want the window to display something in the
overlay when it first appears, you must call this immediately after
you show() your window.
</ul><h4><code>virtual void Fl_Gl_Window::draw_overlay();</code></h4><ul>
You must implement this virtual function if you want to draw into the
overlay. The overlay is cleared before this is called. You should
draw anything that is not clear, using OpenGl. You must use
gl_color(i) to choose colors (it allocates them from the colormap
using system-specific calls), and remember that you are in an indexed
OpenGL mode and drawing anything other than flat-shaded will probably
not work.
<p>Both this function and Fl_Gl_Window::draw() must check
Fl_Gl_Window::valid(), and set the same transformation. If you don't
your code may not work on other systems. Depending on the OS, and on
whether overlays are real or simulated, the OpenGL context may be the
same or different between the overlay and main window.
</ul><p><hr>
<a name=gl_start>
<h2>Using OpenGL in normal Fltk windows</h2>
<p>You can put OpenGL code into an <a
href=subclass.html#draw>Fl_Widget::draw()</a> method or into the code
for a <a href=Boxtypes.html>boxtype</a> or other places, with some care.
You can put OpenGL code into an <a
href="#draw"><tt>Fl_Widget::draw()</tt></a> method or into the code for
a <a href="#boxtypes">boxtype</a> or other places with some care.
<p>Most important, before you show <i>any</i> windows (including those
that don't have OpenGL drawing) you must initialize fltk/X so that it
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 <a href=#mode>Fl_Gl_Window::mode()</a> to describe how
you intend to use OpenGL:
described for <a
href="#Fl_Gl_Window.mode"><tt>Fl_Gl_Window::mode()</tt></a> to describe
how you intend to use OpenGL:
<ul><p><code> Fl::gl_visual(FL_RGB);</code></ul>
<ul><pre>
Fl::gl_visual(FL_RGB);
</pre></ul>
<p>You can then put OpenGL drawing code anywhere you can draw normally
You can then put OpenGL drawing code anywhere you can draw normally
by surrounding it with:
<ul><p><code>gl_start();</code><br>
<i>... put your OpenGL code here ...</i><br>
<code>gl_finish();</code></ul>
<ul><pre>
gl_start();
... put your OpenGL code here ...
gl_finish();
</pre></ul>
<p>gl_start() and gl_finish() set up a GL 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
scissor commands. These also synchronize the OpenGL graphics stream
with the drawing done by other X or fltk functions.
<a name="gl_start"><tt>gl_start()</tt></a> and <a
name="gl_finish"><tt>gl_finish()</tt></a> set up an OpenGL context with
an orthographic projection so that 0,0 is the lower-left corner of the
window and each pixel is one unit. The current clipping is reproduced
with OpenGL <tt>glScissor()</tt> commands. These also synchronize the
OpenGL graphics stream with the drawing done by other X, WIN32, or FLTK
functions.
<p>The same context is reused each time. If your code changes the
projection transformation or anything else you should use glPush/glPop
to put the state back before calling gl_finish().
projection transformation or anything else you should use
<tt>glPushMatrix()</tt> and <tt>glPopMatrix()</tt> functions to put the
state back before calling <tt>gl_finish()</tt>.
<p>You may want to use <code>Fl_Window::current()->h()</code> to get
the drawable height so you can flip the coordinate system.
<p>You may want to use <tt>Fl_Window::current()->h()</tt> to get
the drawable height so you can flip the Y coordinates.
<p>Unfortunately there are a bunch of limitations you must adhere to for
maximum portability:<ul>
<p>Unfortunately, there are a bunch of limitations you must adhere to for
maximum portability:
<li>You must choose a default visual with <a
href=Fl.html#gl_visual>Fl::gl_visual()</a>.
<ul>
<li>You cannot pass FL_DOUBLE to Fl::gl_visual().
<li>You must choose a default visual with <a
href="#gl_visual"><tt>Fl::gl_visual()</tt></a>.
<li>You cannot use Fl_Double_Window (or Fl_Overlay_Window).
<li>You cannot pass <tt>FL_DOUBLE</tt> to <tt>Fl::gl_visual()</tt>.
<li>You cannot use <tt>Fl_Double_Window</tt> or
<tt>Fl_Overlay_Window</tt>.
</ul>
<p>Do <i>not</i> call gl_start()/gl_finish() when drawing an
Fl_Gl_Window!
Do <i>not</i> call <tt>gl_start()</tt> or <tt>gl_finish()</tt> when drawing
into an <tt>Fl_Gl_Window</tt>!
</ul><p><hr>
<a name=drawing>
<h2>OpenGL drawing functions
<br>#include &lt;FL/gl_draw.H></h2>
<h2>OpenGL drawing functions</h2>
Fltk provides some useful gl drawing functions. They can be freely
mixed with any OpenGL calls, and are defined by including &lt;FL/gl.H>
(which you should include instead of the OpenGL header &lt;GL/gl.h>).
FLTK provides some useful OpenGL drawing functions. They can be freely
mixed with any OpenGL calls, and are defined by including
<tt>&lt;FL/gl.H></tt> (which you should include instead of the OpenGL
header <tt>&lt;GL/gl.h></tt>).
</ul><h4><code>void gl_color(Fl_Color);</code></h4><ul>
<h3>void gl_color(Fl_Color)</h3>
Set the current color to a fltk color index. <i>For color-index modes
it will use fl_xpixel(c), which is only right if this window uses the
default X colormap</i>.
Set the current color to a FLTK color index. <i>For color-index modes
it will use <tt>fl_xpixel(c)</tt>, which is only right if this window
uses the default colormap!</i>
</ul><h4><code>void gl_rect(int x,int y,int w,int h);
<br>void gl_rectf(int x,int y,int w,int h);</code></h4><ul>
<h3>void gl_rect(int x, int y, int w, int h)<br>
void gl_rectf(int x, int y, int w, int h)</h3>
Outline or fill a rectangle with the current color. If ortho() has
been called, then the rectangle will exactly fill the pixel rectangle
passed.
Outline or fill a rectangle with the current color. If
<tt>ortho()</tt> has been called, then the rectangle will exactly fill
the pixel rectangle passed.
</ul><h4><code>void gl_font(Fl_Font fontid, int size);</code></h4><ul>
<h3>void gl_font(Fl_Font fontid, int size)</h3>
Set the "current GL font" to the same font you get by calling
<a href=Draw.html#fl_font>fl_font()</a>.
Set the "current OpenGL font" to the same font you get by calling
<a href="#fl_font"><tt>fl_font()</tt></a>.
</ul><h4><code>int gl_height();
<br>int gl_descent();
<br>float gl_width(const char *);
<br>float gl_width(const char *, int n);
<br>float gl_width(uchar);</code></h4><ul>
<h3>int gl_height()<br>
int gl_descent()<br>
float gl_width(const char *)<br>
float gl_width(const char *, int n)<br>
float gl_width(uchar)</h3>
Return information about the current GL font.
Return information about the current OpenGL font.
</ul><h4><code>void gl_draw(const char *);
<br>void gl_draw(const char *, int n);</code></h4><ul>
<h3>void gl_draw(const char *)<br>
void gl_draw(const char *, int n)</h3>
Draw a null-terminated string or an array of <i>n</i> characters in
the current GL font at the current glRasterPos.
Draw a nul-terminated string or an array of <tt>n</tt> characters in
the current OpenGL font at the current <tt>glRasterPos</tt>.
</ul><h4><code>void gl_draw(const char *, int x, int y);
<br>void gl_draw(const char *, int n, int x, int y);</code></h4><ul>
<h3>void gl_draw(const char *, int x, int y)<br>
void gl_draw(const char *, int n, int x, int y)<br>
void gl_draw(const char *, float x, float y)<br>
void gl_draw(const char *, int n, float x, float y)</h3>
Draw a null-terminated string or an array of <i>n</i> characters in
the current GL font at the given position.
Draw a nul-terminated string or an array of <tt>n</tt> characters in
the current OpenGL font at the given position.
</ul><h4><code>void gl_draw(const char *, int x, int y, int w, int h, Fl_Align);</code></h4><ul>
<h3>void gl_draw(const char *, int x, int y, int w, int h, Fl_Align)</h3>
Draw a string formatted into a box, with newlines and tabs expanded,
other control characters changed to ^X, and aligned with the edges or
center. Exactly the same output as <a href=Draw.html#fl_draw>fl_draw()</a>.
center. Exactly the same output as <a href="#fl_draw"><tt>fl_draw()</tt></a>.
</ul>
<p><a href = index.html>(back to contents)</a>
<title>Fltk example: shape.C</title>
<h2>shape.C</h2>
<h2>Using OpenGL Optimizer with FLTK</h2>
<p>Of course GL is no fun unless you can draw your own graphics. This
is done with a subclass that you create:
<a href="http://www.sgi.com/software/optimizer">OpenGL Optimizer</a> is
a scene graph toolkit for OpenGL available from Silicon Graphics for
IRIX and Microsoft Windows. Versions are in the works for Solaris and
HP-UX. It allows you to view large scenes without writing a lot of
OpenGL code.
<p><img src = shape.C.gif align=top>
<h3>OptimizerWindow Class Definition</h3>
<pre>
#include &lt;FL/Fl.H>
#include &lt;FL/Fl_Window.H>
#include &lt;FL/Fl_Hor_Slider.H>
#include &lt;FL/math.h>
#include &lt;FL/gl.h>
#include &lt;FL/Fl_Gl_Window.H>
To use OpenGL Optimizer with FLTK you'll need to create a subclass of
<tt>Fl_Gl_Widget</tt> that includes several state variables:
<ul><pre>
class OptimizerWindow : public Fl_Gl_Window {
csContext *context_; // Initialized to 0 and set by draw()...
csDrawAction *draw_action_; // Draw action...
csGroup *scene_; // Scene to draw...
csCamara *camera_; // Viewport for scene...
class shape_window : public Fl_Gl_Window {
void draw();
public:
int sides;
shape_window(int x,int y,int w,int h,const char *l=0);
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();
}
}
};
</ul><pre>
shape_window::shape_window(int x,int y,int w,int h,const char *l) :
Fl_Gl_Window(x,y,w,h,l) {
sides = 3;
}
<H3>The camera() Method</H3>
The <tt>camera()</tt> method sets the camera (projection and viewpoint)
to use when drawing the scene. The scene is redrawn after this call.
<h3>The draw() Method</h3>
The <tt>draw()</tt> method performs the needed initialization
and does the actual drawing:
<ul><pre>
void OptimizerWindow::draw() {
if (!context_) {
// This is the first time we've been asked to draw; create the
// Optimizer context for the scene...
context_ = new csContext(fl_display, fl_visual);
context_->ref();
context_->makeCurrent(fl_display, fl_window);
... 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_);
}
}
void shape_window::draw() {
// the valid() property may be used to avoid reinitializing your
// GL transformation for each redraw:
if (!valid()) {
valid(1);
glLoadIdentity();
glViewport(0,0,w(),h());
// Update the viewport for this context...
context_->setViewport(0, 0, w(), h());
}
// draw an amazing graphic:
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(.5,.6,.7);
glBegin(GL_POLYGON);
for (int i=0; i&lt;sides; i++) {
double ang = i*2*M_PI/sides;
glVertex3f(cos(ang),sin(ang),0);
}
glEnd();
// Clear the window...
context_->clear(csContext::COLOR_CLEAR | csContext::DEPTH_CLEAR,
0.0f, // Red
0.0f, // Green
0.0f, // Blue
1.0f); // Alpha
// Then draw the scene (if any)...
if (scene_)
draw_action_->apply(scene_);
}
</pre></ul>
// when you change the data, as in this callback, you must call redraw():
void sides_cb(Fl_Widget *o, void *p) {
shape_window *sw = (shape_window *)p;
sw->sides = int(((Fl_Slider *)o)->value());
sw->redraw();
}
<H3>The scene() Method</H3>
int main(int argc, char **argv) {
The <tt>scene()</tt> method sets the scene to be drawn. The scene is
a collection of 3D objects in a <tt>csGroup</tt>. The scene is redrawn
after this call.
Fl_Window window(300, 330);
shape_window sw(10, 10, 280, 280);
window.resizable(&sw);
Fl_Hor_Slider slider(50, 295, window.w()-60, 30, "Sides:");
slider.align(FL_ALIGN_LEFT);
slider.callback(sides_cb,&sw);
slider.value(sw.sides);
slider.step(1);
slider.bounds(3,40);
window.show(argc,argv);
return Fl::run();
}
</pre>
<p>To do your own drawing, you must subclass <a
href=Fl_Gl_Window.html>Fl_Gl_Window</a>. The virtual method <a
href=subclass.html#draw>draw()</a> is called when the window should
update. You can only draw into the window inside a draw() method.
You call the method <a href=Fl_Widget.html#redraw>redraw()</a> on the
window to indicate that draw() needs to be called. It won't actually
be called until <a href=Fl.html#wait>Fl::wait()</a> is called.
<P>The window may be made a child of another window, as it is here.
This is done by add()ing it to a parent before you show() it. <i>If
you don't want to make a child window, be sure to end() the previous
window!</i> The Fl_Gl_Window constructor automatically does end() so
you don't accidentally add children to it.
<p>The files &lt;FL/math.h> and &lt;FL/gl.h> are wrappers for the
normal header files. You should use them to port to MSWindows because
the MicroSoft header files have errors or ommisions in them.
<p><a href = index.html>[back to contents]</a>
</BODY>
</HTML>

View File

@ -1,184 +1,171 @@
<HTML>
<BODY>
<H1 ALIGN=RIGHT>F - Operating System Specific Issues</H1
<H1 ALIGN=RIGHT><A NAME="osissues">F - Operating System Issues</A></H1>
</BODY>
</HTML>
<title>Fltk X-specific interface</title>
<h2>Fltk X-specific interface</h2>
This appendix describes the X and WIN32 specific interfaces in FLTK.
<b>#include &lt;FL/x.H></b>
<h2>X-Specific Interface</h2>
<p>On Unix/X you can include this file to access fltk's X-specific
functions. Be warned that some of the structures and calls in it are
subject to change in future version of fltk. Try to avoid doing this
so your code is portable.
<ul><pre>
#include &lt;FL/x.H>
</pre></ul>
<p><hr>
On X you can include this file to access FLTK's X-specific functions.
Be warned that some of the structures and calls in it are subject to
change in future version of FLTK. Try to avoid doing this so your code
is portable.
<h2>Handling other X events</h2>
<h3>Handling Other X Events</h3>
<a name=add_handler>
</ul><h4><code>void Fl::add_handler(int (*f)(int));</code></h4><ul>
<h4><a name="add_handler">void Fl::add_handler(int (*f)(int))</a></h4>
Install a function to parse unrecognized events. If fltk cannot figure
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.
returns non-zero then the event is ignored.
<p>Fltk calls this for any X events it does not recognize, or X events
with a window id that fltk does not recognize. You can look at the X
event with the <a href=#fl_xevent><code>fl_xevent</code></a>.
<p>FLTK calls this for any X events it does not recognize, or X events
with a window id that FLTK does not recognize. You can look at the X
event with the <a href="#fl_xevent"><tt>fl_xevent</tt></a> variable.
<p>The argument is 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. In this case the argument is
non-zero (for instance FL_SHORTCUT).
non-zero (for example <tt>FL_SHORTCUT</tt>).
<a name=fl_xevent>
</ul><h4><code>extern XEvent* fl_xvent;</code></h4><ul>
<h4><a name="fl_xevent">extern XEvent *fl_xvent</a></h4>
The most current X event.
The most recent X event.
<a name=fl_event_time>
</ul><h4><code>extern ulong fl_event_time;</code></h4><ul>
<h4><a name="fl_event_time">extern ulong fl_event_time</a></h4>
This is the time stamp from the most recent X event that reported it
(not all do). Many X calls (like cut and paste) need this value.
</ul><h4><code>Window fl_xid(const Fl_Window*);</code></h4><ul>
<h4><a name="fl_xid">Window fl_xid(const Fl_Window *)</a></h4>
Returns the xid for a window, or zero if not shown().
Returns the XID for a window, or zero if not <tt>shown()</tt>.
</ul><h4><code>Fl_Window* fl_find(ulong xid);</code></h4><ul>
<h4><a name="fl_find">Fl_Window *fl_find(ulong xid)</a></h4>
<p>Return the Fl_Window that corresponds to the given xid, or
null if not found. This uses a cache so it is slightly faster than
iterating through the windows yourself.
Returns the <tt>Fl_Window</tt> that corresponds to the given XID, or
<tt>NULL</tt> if not found. This uses a cache so it is slightly faster
than iterating through the windows yourself.
</ul><h4><code>int fl_handle(const XEvent&);</code></h4><ul>
<h4><a name="fl_handle">int fl_handle(const XEvent &amp;)</a></h4>
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 true if fltk understood the event (if the window does not belong to
fltk and the add_handler() functions all ignore it this returns
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 true if FLTK understood the event (if the window does not belong to
FLTK and the <tt>add_handler()</tt> functions all ignore it this returns
false).
<p>Besides feeding events your code should call <a
href=Fl.html#flush>Fl::flush()</a> periodically so that fltk redraws
it's windows.
href="#flush"><tt>Fl::flush()</tt></a> periodically so that FLTK
redraws its windows.
<p>This function will call the callback functions. It will not return
until they complete. In particular if a callback pops up a modal
window (by calling <a href=utilities.html#fl_ask>fl_ask()</a>, for
window (by calling <a href="#fl_ask"><tt>fl_ask()</tt></a>, for
instance) it will not return until the modal function returns.
</ul>
<p><hr>
<h3>Drawing using Xlib</h3>
<a name=draw>
<h2>Drawing using Xlib</h2>
The following global variables are set before
<tt>Fl_Widget::draw()</tt> is called, or by <a
href="#Fl_Window.make_current"><tt>Fl_Window::make_current()</tt></a>:
</ul><h4><code>
extern Display* fl_display;<br>
extern Window fl_window;<br>
extern GC fl_gc;<br>
extern int fl_screen;<br>
extern XVisualInfo* fl_visual;<br>
extern Colormap fl_colormap;</code></h4><ul>
<ul><pre>
extern Display *fl_display;
extern Window fl_window;
extern GC fl_gc;
extern int fl_screen;
extern XVisualInfo *fl_visual;
extern Colormap fl_colormap;
</pre></ul>
These global variables are set before Fl_Widget::draw() is called, or
by <a href=Fl_Window.html#make_current>Fl_Window::make_current()</a>
You must use them to produce Xlib calls. Don't attempt to change
them. A typical X drawing call is written like this:
<ul><p><code>XDrawSomething(fl_display, fl_window, fl_gc, ...);</code></ul>
<ul><pre>
XDrawSomething(fl_display, fl_window, fl_gc, ...);
</pre></ul>
<p>Other information such as the position or size of the X window can be
Other information such as the position or size of the X window can be
found by looking at <a
href=Fl_Window.html#make_current><code>Fl_Window::current()</code></a>,
which returns a pointer to the Fl_Window being drawn.
href="#Fl_Window.make_current"><tt>Fl_Window::current()</tt></a>, which
returns a pointer to the <tt>Fl_Window</tt> being drawn.
</ul><h4><code>unsigned long fl_xpixel(Fl_Color i);</code></h4><ul>
<h4><a name="fl_xpixel">unsigned long fl_xpixel(Fl_Color i)<br>
unsigned long fl_xpixel(uchar r, uchar g, uchar b)</a></h4>
Returns the X pixel number used to draw the given fltk color index.
This is the X pixel that <a href=Draw.html#fl_color>fl_color(i)</a> would use.
Returns the X pixel number used to draw the given FLTK color index or
RGB color. This is the X pixel that <a
href="#fl_color"><tt>fl_color()</tt></a> would use.
</ul><h4><code>unsigned long fl_xpixel(uchar r, uchar g, uchar
b);</code></h4><ul>
Return the X pixel number used to draw the given rgb color. This is
the X pixel that <a href=Draw.html#fl_rgbcolor>fl_color(r,g,b)</a> would use.
</ul><h4><code>extern XFontStruct* fl_xfont;</code></h4><ul>
<h4><a name="fl_xfont">extern XFontStruct *fl_xfont</a></h4>
Points at the font selected by the most recent <a
href=Draw.html#fl_font>fl_font(font,size)</a>. This is not
necessarily the current font of fl_gc (that's not set until <a
href=Draw.html#text>fl_draw(const char*,...)</a> is called).
href="#fl_font"><tt>fl_font()</tt></a>. This is not necessarily the
current font of <tt>fl_gc</tt>, which is not set until <a
href="#fl_draw"><tt>fl_draw()</tt></a> is called.
</ul>
<h3>Changing the Display, Screen, or X Visual</h3>
<p><hr>
FLTK uses only a single display, screen, X visual, and X colormap. This
greatly simplifies its internal structure and makes it much smaller and
faster. You can change which it uses by setting global variables
<i>before the first <tt>Fl_Window::show()</tt> is called</i>. You may
also want to call <a href="#visual">Fl::visual()</a>, which is a
portable interface to get a full color and/or double buffered visual.
<a name=visuals>
<h2>Changing the display, screen, or X visual</h2>
<p>Fltk uses only a single display, screen, X visual, and X colormap.
This greatly simplifies it's internal structure and makes it much
smaller and faster. You can change which it uses by setting global
variables <i>before the first Fl_Window::show() is called</i>.
You may also want to call <a
href=Fl.html#visual>Fl::visual(int)</a>, which is a portable interface
to get a full color and/or double buffered visual.
</ul><h4><code>int Fl::display(const char *)</code></h4><ul>
<h4><a name="display">int Fl::display(const char *)</a></h4>
Set which X display to use. This actually does
<code>setenv("DISPLAY",&nbsp;x)</code> 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 on MSWindows, but
it just sets the environment variable and has no other effect.
<tt>putenv("DISPLAY=...")</tt> so that child programs will display on
the same screen if called with <tt>exec()</tt>. This must be done
before the display is opened. This call is provided under WIN32 but
it has no effect.
</ul><h4><code>extern Display* fl_display;</code></h4><ul>
<h4><a name="fl_display">extern Display *fl_display</a></h4>
The open X display. This is needed as an argument to most Xlib calls.
Don't attempt to change it! This is zero before the display is opened.
Don't attempt to change it! This is <tt>NULL</tt> before the display is opened.
</ul><h4><code>void fl_open_display();</code></h4><ul>
<h4><a name="fl_open_display">void fl_open_display()</a></h4>
Open the display. Does nothing if it is already open. This will make
sure <code>fl_display</code> is non-zero. You should call this if you
Opens the display. Does nothing if it is already open. This will make
sure <tt>fl_display</tt> is non-zero. You should call this if you
wish to do X calls and there is a chance that your code will be called
before the first show() of a window.
before the first <tt>show()</tt> of a window.
<p>This may call Fl::abort() if there is an error opening the display.
<p>This may call <tt>Fl::abort()</tt> if there is an error opening the display.
</ul><h4><code>void fl_close_display();</code></h4><ul>
<h4><a name="fl_close_display">void fl_close_display()</a></h4>
This closes the X connection. You do <i>not</i> need to call this to
exit, and in fact it is faster to not do so! It may be useful to call
this if you want your program to continue without the X connection.
You cannot open the display again, and probably cannot call any fltk
You cannot open the display again, and probably cannot call any FLTK
functions.
</ul><h4><code>extern int fl_screen;</code></h4><ul>
<h4><a name="fl_screen">extern int fl_screen</a></h4>
Which screen 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: host:0,#.
Which screen number to use. This is set by <tt>fl_open_display()</tt>
to the default screen. You can change it by setting this to a
different value immediately afterwards. It can also be set by changing
the last number in the <tt>Fl::display()</tt> string to "host:0,#".
</ul><h4><code>extern XVisualInfo* fl_visual;<br>
extern Colormap fl_colormap;</code></h4><ul>
<h4><a name="fl_visual">extern XVisualInfo *fl_visual</a><br>
<a name="fl_colormap">extern Colormap fl_colormap</a></h4>
<p>The visual and colormap that fltk will use for all windows. These
are set by 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:
The visual and colormap that FLTK will use for all windows. These
are set by <tt>fl_open_display()</tt> to the default visual and colormap. You
can change them before calling <tt>show()</tt> on the first window. Typical
code for changing the default visual is:
<ul><code><pre>
<ul><pre>
Fl::args(argc, argv); // do this first so $DISPLAY is set
fl_open_display();
fl_visual = find_a_good_visual(fl_display, fl_screen);
@ -186,50 +173,32 @@ if (!fl_visual) Fl::abort("No good visual");
fl_colormap = make_a_colormap(fl_display, fl_visual->visual, fl_visual->depth);
// it is now ok to show() windows:
window->show(argc, argv);
</pre></code></ul>
</pre></ul>
</ul>
<h3>Using a Subclass of Fl_Window for Special X Stuff</h3>
<p><hr>
<a name=window>
<h2>Using a subclass of Fl_Window for special X stuff</h2>
FLTK can manage an X window on a different screen, visual and/or
colormap, you just can't use FLTK's drawing routines to draw into it.
But you can write your own <tt>draw()</tt> method that uses Xlib
(and/or OpenGL) calls only.
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 calls only.
<p>Fltk can also manage xid's provided by other libraries or programs,
<p>FLTK can also manage XID's provided by other libraries or programs,
and call those libraries when the window needs to be redrawn.
<p>To do this, you need to make a subclass of <a
href=Fl_Window.html>Fl_Window</a> and override some of these virtual
href="#Fl_Window"><tt>Fl_Window</tt></a> and override some of these virtual
functions:
</ul><h4><code>virtual void Fl_Window::show()</code></h4><ul>
<h4>virtual void Fl_Window::show()</h4>
<p>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():
If the window is already <tt>shown()</tt> this must cause it to be raised,
this can usually be done by calling <tt>Fl_Window::show()</tt>. If not <tt>shown()</tt>
your implementation must call either <tt>Fl_X::set_xid()</tt> or
<tt>Fl_X::make_xid()</tt>.
<h4><code>Fl_X* Fl_X::set_xid(Fl_Window*, Window xid);</code></h4><ul>
<p>An example:
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.
</ul><h4><code>void Fl_X::make_xid(Fl_Window*, XVisualInfo* =
fl_visual, Colormap = fl_colormap);</code></h4><ul>
This static method does the most onerous parts of creating an X window,
including setting the label, resize limitations, etc. It then does
set_xid with this new window and maps the window.
</ul>
<p>Example:
<pre>
<ul><pre>
void MyWindow::show() {
if (shown()) {Fl_Window::show(); return;} // you must do this!
fl_open_display(); // necessary if this is first window
@ -243,47 +212,60 @@ void MyWindow::show() {
}
Fl_X::make_xid(this, visual, colormap);
}
</pre>
</pre></ul>
</ul><h4><code>virtual void Fl_Window::flush()</code></h4><ul>
<h4>Fl_X *Fl_X::set_xid(Fl_Window *, Window xid)</h4>
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.
Allocate a hidden structure called an <tt>Fl_X</tt>, put the XID into it, and
set a pointer to it from the <tt>Fl_Window</tt>. This causes
<tt>Fl_Window::shown()</tt> to return true.
<p>The X region that is a combination of all damage() calls done so
far is in <code>Fl_X::i(this)->region</code>. If null then
you should redraw the entire window. The undocumented function
<code>fl_clip_region(XRegion)</code> will initialize the fl clip stack
with a region or null for no clipping. You must set region to null
afterwards as fl_clip_region() now owns it and will delete it when
done.
<h4>void Fl_X::make_xid(Fl_Window *, XVisualInfo *= fl_visual, Colormap = fl_colormap)</h4>
<p>If <code>damage()==2</code> then only X expose events have
happened. This may be useful if you have an undamaged image (such as
a backing buffer) around.
This static method does the most onerous parts of creating an X window,
including setting the label, resize limitations, etc. It then does
<tt>Fl_X::set_xid()</tt> with this new window and maps the window.
<h4>virtual void Fl_Window::flush()</h4>
This virtual function is called by <tt>Fl::flush()</tt> to update the
window. For FLTK's own windows it does this by setting the global
variables <tt>fl_window</tt> and <tt>fl_gc</tt> and then calling the
<tt>draw()</tt> method. For your own windows you might just want to
put all the drawing code in here.
<p>The X region that is a combination of all <tt>damage()</tt> calls
done so far is in <tt>Fl_X::i(this)->region</tt>. If <tt>NULL</tt>
then you should redraw the entire window. The undocumented function
<tt>fl_clip_region(XRegion)</tt> will initialize the FLTK clip stack
with a region or <tt>NULL</tt> for no clipping. You must set region to
<tt>NULL</tt> afterwards as <tt>fl_clip_region()</tt> now owns it and
will delete it when done.
<p>If <tt>damage() & FL_DAMAGE_EXPOSE</tt> then only X expose events
have happened. This may be useful if you have an undamaged image (such
as a backing buffer) around.
<p>Here is a sample where an undamaged image is kept somewhere:
<pre>
<ul><pre>
void MyWindow::flush() {
fl_clip_region(Fl_X::i(this)->region);
Fl_X::i(this)->region = 0;
if (damage() != 2) {... draw things into backing store ...}
... copy backing store to window ...
}
</pre>
</pre></ul>
</ul><h4><code>virtual void Fl_Window::hide()</code></h4><ul>
<h4>virtual void Fl_Window::hide()</h4>
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:
Destroy the window server copy of the window. Usually you will destroy
contexts, pixmaps, or other resources used by the window, and then call
<tt>Fl_Window::hide()</tt> to get rid of the main window identified by
<tt>xid()</tt>. If you override this, you must also override the
destructor as shown:
<pre>
<ul><pre>
void MyWindow::hide() {
if (mypixmap) {
XFreePixmap(fl_display,mypixmap);
@ -291,165 +273,183 @@ void MyWindow::hide() {
}
Fl_Window::hide(); // you must call this
}
</pre>
</pre></ul>
</ul><h4><code>virtual void Fl_Window::~Fl_Window()</code></h4><ul>
<h4>virtual void Fl_Window::~Fl_Window()</h4>
Because of the way C++ works, if you override hide() you <i>must</i>
override the destructor as well (otherwise only the base class hide()
Because of the way C++ works, if you override <tt>hide()</tt> you <i>must</i>
override the destructor as well (otherwise only the base class <tt>hide()</tt>
is called):
<pre>
<ul><pre>
MyWindow::~MyWindow() {
hide();
}
</pre>
</pre></ul>
</ul>
<h3>Setting the Icon of a Window</h3>
<p><a href = index.html>(back to contents)</a>
<title>Fltk MSWindows-specific interface</title>
<h2>#include &lt;FL/x.H><br>
Fltk MSWindows-specific interface</h2>
FLTK currently supports setting a window's icon *before* it is shown using
the <tt>Fl_Window::icon()</tt> method.
The &lt;FL/x.H> header file defines the interface to fltk's
MSWindows-specific functions. Be warned that some of the structures
and calls in it are subject to change in future version of fltk. Try
<h4>void Fl_Window::icon(char *)</h4>
Sets the icon for the window to the passed pointer. You will need to
cast the icon <tt>Pixmap</tt> to a <tt>char *</tt> when calling this
method. To set the icon using a bitmap compiled with your application
use:
<ul><pre>
#include "icon.xbm"
Pixmap p = XCreatePixmapFromBitmapData(fl_display,
DefaultRootWindow(fl_display), icon_bits,
icon_width, icon_height,
BlackPixel(fl_display, DefaultScreen(fl_display)),
WhitePixel(fl_display, DefaultScreen(fl_display)),
DefaultDepth(fl_display, DefaultScreen(fl_display)))
window->icon((char *)p);
</ul></pre>
<h2>WIN32-Specific Interface</h2>
<ul><pre>
#include &lt;FL/x.H>
</pre></ul>
The <tt>&lt;FL/x.H></tt> header file defines the interface to FLTK's
WIN32-specific functions. Be warned that some of the structures
and calls in it are subject to change in future version of FLTK. Try
to avoid doing this so your code is portable.
<p><hr>
<h3>Handling Other WIN32 Messages</h3>
<h2>Handling other MSWindows messages</h2>
By default a single WNDCLASSEX called "FLTK" is created. All
<tt>Fl_Windows</tt> are of this class unless you use
<tt>Fl_Window::xclass()</tt>. The window class is created the first
time <tt>Fl_Window::show()</tt> is called.
<p>A single WNDCLASSEX called "FLTK" is created. All
Fl_Windows are of this class. This window class is created the first
time Fl_Window::show() is called.
<p>You can probably combine fltk with other libraries that make their
own MSWindows window classes. The easiest way is to call Fl::wait(), it
will call DispatchMessage for all messages to the other windows. If
<p>You can probably combine FLTK with other libraries that make their
own WIN32 window classes. The easiest way is to call <tt>Fl::wait()</tt>, it
will call <tt>DispatchMessage</tt> for all messages to the other windows. If
necessary you can let the other library take over (as long as it calls
DispatchMessage()), but you will have to arrange for the function
Fl::flush() to be called regularily (otherwise widgets will not
update), and timeouts and the idle function will not work.
<tt>DispatchMessage()</tt>), but you will have to arrange for the function
<tt>Fl::flush()</tt> to be called regularily so that widgets are updated,
timeouts are handled, and the idle functions are called.
<a name=fl_msg>
</ul><h4><code>extern MSG fl_msg;</code></h4><ul>
<h4><a name="fl_msg">extern MSG fl_msg</a></h4>
The most recent message read by GetMessage (which is called by
<a href=Fl.html#wait>Fl::wait()</a>. This may not be the most recent
message sent to an fltk window, because silly MSWindows calls the
The most recent message read by <tt>GetMessage</tt> (which is called by
<a href="#wait"><tt>Fl::wait()</tt></a>. This may not be the most
recent message sent to an FLTK window, because silly WIN32 calls the
handle procedures directly for some events (sigh).
<a name=add_handler>
</ul><h4><code>void Fl::add_handler(int (*f)(int));</code></h4><ul>
<h4><a name="WIN32.add_handler">void Fl::add_handler(int (*f)(int))</a></h4>
Install a function to parse unrecognized messages sent to fltk
windows. If fltk cannot figure out what to do with a message, it
Install 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 fuctions is zero. If
all the handlers return zero then fltk calls DefWindowProc(...).
all the handlers return zero then FLTK calls <tt>DefWindowProc()</tt>.
</ul><h4><code>HWND fl_xid(const Fl_Window*);</code></h4><ul>
<h4><a name="WIN32.fl_xid">HWND fl_xid(const Fl_Window *)</a></h4>
Returns the window handle for a Fl_Window, or zero if not shown().
Returns the window handle for a <tt>Fl_Window</tt>, or zero if not
<tt>shown()</tt>.
</ul><h4><code>Fl_Window* fl_find(HWND xid)</code></h4><ul>
<h4><a name="WIN32.fl_find">Fl_Window *fl_find(HWND xid)</a></h4>
<p>Return the Fl_Window that corresponds to the given window handle,
or null if not found. This uses a cache so it is slightly faster than
iterating through the windows yourself.
Return the <tt>Fl_Window</tt> that corresponds to the given window
handle, or <tt>NULL</tt> if not found. This uses a cache so it is
slightly faster than iterating through the windows yourself.
</ul>
<h3>Drawing Things Using the WIN32 GDI</h3>
<p><hr>
<a name=gdi>
<h2>Drawing things using the MSWindows GDI</h2>
<p>When the virtual function Fl_Widget::draw() is called, fltk has
When the virtual function <tt>Fl_Widget::draw()</tt> is called, FLTK has
stashed in some global variables all the silly extra arguments you
need to make a proper GDI call. These are:
</ul><h4><code>
extern HINSTANCE fl_display;<br>
extern HWND fl_window;<br>
extern HDC fl_gc;<br>
COLORREF fl_RGB();<br>
HPEN fl_pen();<br>
HBRUSH fl_brush();</code></h4><ul>
<ul><pre>
extern HINSTANCE fl_display;
extern HWND fl_window;
extern HDC fl_gc;
COLORREF fl_RGB();
HPEN fl_pen();
HBRUSH fl_brush();
</pre></ul>
These global variables are set before draw() is called, or by <a
href=Fl_Window.html#make_current>Fl_Window::make_current()</a> You can
These global variables are set before <tt>draw()</tt> is called, or by <a
href="#Fl_Window.make_current"><tt>Fl_Window::make_current()</tt></a>. You can
refer to them when needed to produce GDI calls. Don't attempt to
change them. The functions return GDI objects for the current color
set by fl_color(), these are created as needed and cached. A typical
set by <tt>fl_color()</tt> and are created as needed and cached. A typical
GDI drawing call is written like this:
<ul><p><code>DrawSomething(fl_gc, ..., fl_brush());</code></ul>
<ul><pre>
DrawSomething(fl_gc, ..., fl_brush());
</pre></ul>
<p>It may also be useful to refer to <a
href=Fl_Window.html#make_current><code>Fl_Window::current()</code></a>
to get the window's size or position.
It may also be useful to refer to <a
href="#Fl_Window.make_current"><tt>Fl_Window::current()</tt></a> to get
the window's size or position.
</ul>
<p><hr>
<h2>How to not get a MSDOS console window</h2>
<h3>Setting the Icon of a Window</h3>
MSWindows has a really stupid mode switch stored in the executables that
controls whether or not to make a console window (hint to Mr Gates:
why not leave it hidden until the program prints something?).
FLTK currently supports setting a window's icon *before* it is shown using
the <tt>Fl_Window::icon()</tt> method.
<p>To not produce a "console" window when you run your program add the
following secret incantation to the Micro$oft linker:
<h4>void Fl_Window::icon(char *)</h4>
<p><pre> /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup</pre>
Sets the icon for the window to the passed pointer. You will need to
cast the <tt>HICON</tt> handle to a <tt>char *</tt> when calling this
method. To set the icon using an icon resource compiled with your
application use:
<p>Unfortunately this seems to completely disable stdin/stdout, even
if you run the program from a console. So don't do this until you
have debugged your program!
<ul><pre>
window->icon((char *)LoadIcon(fl_display, MAKEINTRESOURCE(IDI_ICON)));
</ul></pre>
<p><hr>
<h2>Other hints</h2>
<h3>How to Not Get a MSDOS Console Window</h3>
<p>I use capital C as the extension for c++ source code, for instace
for Fluid output. Unfortunately there is no way to convince VC++ to
use this except to tell it to compile *everything* using C++ by
putting the switch "/TP" in the options. This makes it impossible to
combine old C code and fltk code.
WIN32 has a really stupid mode switch stored in the executables that
controls whether or not to make a console window.
<p><hr>
<h2>Known bugs</h2>
<p>To always get a console window you simply create a console
application (the "/SUBSYSTEM:CONSOLE" option for the linker). For a
GUI-only application create a WIN32 application (the
"/SUBSYSTEM:WINDOWS" option for the linker).
<p>If program is deactivated, Fl::wait() does not return until it is
activated again, even though many events are delivered to the program.
This can cause idle background processes to stop unexpectedly. This
also happens while the user is dragging or resizing windows or
otherwise holding the mouse down. I was forced to remove most of the
efficiency fltk uses for redrawing in order to get windows to update
while being moved. This is a design error in MSWindows and probably
impossible to get around.
<p>FLTK includes a <tt>WinMain()</tt> function that calls the ANSI
standard <tt>main()</tt> entry point for you. <i>This function creates
a console window when you use the debug version of the library.</i>
<p>Fl_Gl_Window::can_do_overlay() returns true until the first time it
attempts to draw an overlay, and then correctly returns whether or not
there is overlay hardware.
<p>WIN32 applications without a console cannot write to <tt>stdout</tt> or
<tt>stderr</tt>, even if they are run from a console window. Any output
is silently thrown away.
<h3>Known Bugs</h3>
If a program is deactivated, <tt>Fl::wait()</tt> does not return until
it is activated again, even though many events are delivered to the
program. This can cause idle background processes to stop
unexpectedly. This also happens while the user is dragging or resizing
windows or otherwise holding the mouse down. I was forced to remove
most of the efficiency FLTK uses for redrawing in order to get windows
to update while being moved. This is a design error in WIN32 and
probably impossible to get around.
<p><tt>Fl_Gl_Window::can_do_overlay()</tt> returns true until the first
time it attempts to draw an overlay, and then correctly returns whether
or not there is overlay hardware.
<p>Cut text contains ^J rather than ^M^J to break lines. This is a
feature, not a bug.
<p>I can't seem to get SetCapture (used by Fl::grab()) to work, and I
can't find a way to stop the main window title from turning gray while
menus are popped up.
<p>glpuzzle program does not animate unless you resize it first. Unknown why.
<p>Fl_Window::fullscreen() not implemented (should take over the screen
without a title bar). Currently does maximize instead.
<p>Import .bmp files into fluid. Wonko has the specs.
<p>Can't set icon of windows.
<p><tt>SetCapture</tt> (used by <tt>Fl::grab()</tt>) doesn't work, and
the main window title bar turns gray while menus are popped up.
<p>FLUID does not support BMP files yet.
</BODY>
</HTML>

View File

@ -1,7 +1,7 @@
<HTML>
<HEAD>
<META NAME="Author" CONTENT="Michael Sweet">
<META NAME="Copyright" CONTENT="Copyright 1998 by Bill Spizak and Others.">
<META NAME="Copyright" CONTENT="Copyright 1998-1999 by Bill Spizak and Others.">
<META NAME="DocNumber" CONTENT="Revision 0">
<TITLE>FLTK 1.0 Programming Manual</TITLE>
</HEAD>
@ -23,15 +23,18 @@ This manual is organized into the following chapters and appendices:
<LI><A HREF="#basics">Chapter 2 - FLTK Basics</A>
<LI><A HREF="#common">Chapter 3 - Common Widgets and Attributes</A>
<LI><A HREF="#editor">Chapter 4 - Designing a Simple Text Editor</A>
<LI><A HREF="#subclasseing">Chapter 5 - Extending and Adding Widgets</A>
<LI><A HREF="#fluid">Chapter 6 - Programming With FLUID</A>
<LI><A HREF="#opengl">Chapter 7 - Using OpenGL</A>
<LI><A HREF="#drawing">Chapter 5 - Drawing Things in FLTK</A>
<LI><A HREF="#events">Chapter 6 - Handling Events</A>
<LI><A HREF="#subclassing">Chapter 7 - Extending and Adding Widgets</A>
<LI><A HREF="#fluid">Chapter 8 - Programming With FLUID</A>
<LI><A HREF="#opengl">Chapter 9 - Using OpenGL</A>
<LI><A HREF="#widgets">Appendix A - Widget Reference</A>
<LI><A HREF="#functions">Appendix B - Function Reference</A>
<LI><A HREF="#enumerations">Appendix C - Enumeration Reference</A>
<LI><A HREF="#glut">Appendix D - GLUT Compatibility</A>
<LI><A HREF="#forms">Appendix E - Forms Compatibility</A>
<LI><A HREF="#license">Appendix F - Software License</A>
<LI><A HREF="#license">Appendix F - Operating System Issues</A>
<LI><A HREF="#license">Appendix G - Software License</A>
</UL>
<H2>Conventions</H2>
@ -63,7 +66,7 @@ The following abbreviations are used in this manual:
<H2>Copyrights and Trademarks</H2>
FLTK is Copyright 1998 by Bill Spitzak and others. Use and distribution of FLTK is
FLTK is Copyright 1998-1999 by Bill Spitzak and others. Use and distribution of FLTK is
governed by the GNU Library General Public License, located in
<A HREF=#license>Appendix D</A>.

View File

@ -1,427 +1,338 @@
<HTML>
<BODY>
<H1 ALIGN=RIGHT><A NAME="subclassing">5 - Adding and Extending Widgets</A></H1>
<H1 ALIGN=RIGHT><A NAME="subclassing">7 - Adding and Extending Widgets</A></H1>
This chapter describes how to add your own widgets or extend existing widgets in FLTK.
This chapter describes how to add your own widgets or extend existing
widgets in FLTK.
<H2>Subclassing</H2>
<H2>Adding Syntax Highlighting to the Fl_Input Widget</H2>
New widgets are created by <i>subclassing</i> an existing FLTK widget,
typically <tt>Fl_Widget</tt> for controls and <tt>Fl_Group</tt> for
containers.
<H2>Drawing Functions</H2>
<p>A control widget typically interacts with the user to receive and/or
display a value of some sort.
<H3>Lines, Rectangles, and Curves, Oh, My!</H3>
<p>A container widget holds a list of child widgets and handles moving,
sizing, showing, or hiding them as needed. <tt>Fl_Group</tt> is the
main container widget class in FLTK, and all of the other containers
(<tt>Fl_Pack</tt>, <tt>Fl_Scroll</tt>, <tt>Fl_Tabs</tt>, <tt>Fl_Tile</tt>,
and <tt>Fl_Window</tt>) are subclasses of it.
<H3>Colors</H3>
<p>You can also subclass other existing widgets to provide a different look
or user-interface. For example, the button widgets are all subclasses of
<tt>Fl_Button</tt> since they all interact with the user via a mouse button
click. The only difference is the code that draws the face of the button.
<H3>Fonts</H3>
<H2>Making a Subclass of Fl_Widget</H2>
<H3>Images</H3>
Your subclasses can directly descend from <tt>Fl_Widget</tt> or any
subclass of <tt>Fl_Widget</tt>. <tt>Fl_Widget</tt> has only four
virtual methods, and overriding some or all of these may be necessary.
<H2><A NAME="Fl_Table">Writing a Table Widget</A></H2>
<H2>The Constructor</H2>
<H3>Methods</H3>
The constructor should access the following arguments:
<H3>Cut and Paste Support</H3>
<ul><pre>
MyClass(int x, int y, int w, int h, const char *label = 0);
</pre></ul>
</BODY>
</HTML>
<title>Cut & paste</title>
<h2>Cut & paste</h2>
Fltk provides routines to cut and paste ASCII text (in the future this
may be UTF-8) between applications. It may be possible to cut/paste
non-ascii data under X by using <a
href=events.html#add_handler>Fl::add_handler()</a>.
</ul><h4><code>void Fl::paste(Fl_Widget *receiver)</code></h4><ul>
<P>Set things up so the receiver widget will be called with an <a
href=events.html#paste>FL_PASTE</a> event some time in the future.
The reciever should be prepared to be called <i>directly</i> by this,
or for it to happen <i>later</i>, or possibly <i>not at all</i>. This
allows the window system to take as long as necessary to retrieve the
paste buffer (or even to screw up completely) without complex and
error-prone synchronization code in fltk.
</ul><h4><code>void Fl::selection(Fl_Widget *owner, const char *stuff, int len);
</code></h4><ul>
<p>Change the current selection. The block of text is copied to an
internal buffer by Fltk (be careful if doing this in response to an
FL_PASTE as this <i>may</i> be the same buffer returned by
event_text()). The selection_owner is set to the passed owner
(possibly sending FL_SELECTIONCLEAR to the previous owner).
</ul><h4><code>const char* Fl::selection();
<br>int Fl::selection_length();</code></h4><ul>
You can look at the buffer containing the current selection. Contents
of this buffer are undefined if this program does not own the X
selection.
</ul><h4><code>Fl_Widget *Fl::selection_owner() const;
<br>void Fl::selection_owner(Fl_Widget *);</code></h4><ul>
<p>The single-argument selection_owner(x) call can be used to move the
selection to another widget or to set the owner to NULL, without
changing the actual text of the selection. FL_SELECTIONCLEAR is sent
to the old selection owner, if any.
</ul>
<p><i>Copying the buffer every time the selection is changed is
obviously wasteful, especially for large selections. I expect an
interface will be added in a future version to allow the selection to
be made by a callback function. The current interface will be
emulated on top of this.</i>
<title>Making a subclass of Fl_Widget</title>
</ul><h2>Making a subclass of Fl_Widget</h2>
<p>Your subclasses can directly descend from Fl_Widget or any
subclass of Fl_Widget. Fl_Widget has only four virtual methods, and
overriding some or all of these may be necessary.
<p>Parts of this document:
<ul>
<li><a href=#constructor>Constructing your Fl_Widget</a>
<li><a href=#protected>Protected methods of Fl_Widget</a>
<li>Virtual functions to override:
<ul>
<li><code><a href=#handle>int Fl_Widget::handle(int
event);</a></code>
<li><code><a href=#draw>void Fl_Widget::draw();</a></code>
<li><code><a href=#resize>void
Fl_Widget::resize(int,int,int,int);</a></code>
<li><code><a href=#destructor>Fl_Widget::~Fl_Widget();</a></code>
</ul>
<li><a href=#composite>Making a Composite/Group Widget</a>
<li><a href=#window>Making a subclass of Fl_Window</a>
</ul>
<a name=constructor>
<h2>Constructing your Fl_Widget</h2>
I recommend your constructor be of this form:
<p><pre>
Class(int x, int y, int w, int h, const char* label = 0);
</pre>
<p>This will allow the class name to be typed into <a
href=fluid.html>fluid</a> and it will produce the correct call.
This will allow the class to be used in <a href="#fluid">Fluid</a> without
problems.
<p>The constructor must call the constructor for the base class and
pass the same arguments. Fl_Widget's protected constructor sets x(),
y(), w(), h(), and label() to the passed values and initializes the
other instance variables to:
pass the same arguments:
<p><pre>
type(0);
box(FL_NO_BOX);
color(FL_GRAY);
selection_color(FL_GRAY);
labeltype(FL_NORMAL_LABEL);
labelstyle(FL_NORMAL_STYLE);
labelsize(FL_NORMAL_SIZE);
labelcolor(FL_BLACK);
align(FL_ALIGN_CENTER);
callback(default_callback,0);
flags(ACTIVE|VISIBLE);
</pre>
<ul><pre>
MyClass::MyClass(int x, int y, int w, int h, const char *label)
: Fl_Widget(x, y, w, h, label) {
// do initialization stuff...
}
</pre></ul>
<a name=protected>
<h2>Protected methods of Fl_Widget</h2>
<tt>Fl_Widget</tt>'s protected constructor sets <tt>x()</tt>,
<tt>y()</tt>, <tt>w()</tt>, <tt>h()</tt>, and <tt>label()</tt> to the
passed values and initializes the other instance variables to:
<p>These methods are provided for subclasses to use.
<ul><pre>
type(0);
box(FL_NO_BOX);
color(FL_GRAY);
selection_color(FL_GRAY);
labeltype(FL_NORMAL_LABEL);
labelstyle(FL_NORMAL_STYLE);
labelsize(FL_NORMAL_SIZE);
labelcolor(FL_BLACK);
align(FL_ALIGN_CENTER);
callback(default_callback,0);
flags(ACTIVE|VISIBLE);
</pre></ul>
</ul><h4><code>uchar Fl_Widget::type() const;
<br>void Fl_Widget::type(uchar);
</code></h4><ul>
<H2>Protected Methods of Fl_Widget</H2>
The property Fl_Widget::type() can return an arbitrary 8-bit
identifier, and can be set with the protected method type(uchar).
This value had to be provided for Forms compatability, but you can use
it for any purpose you want. Try to keep the value less than 100 to
not interfere with reserved values.
The following methods are provided for subclasses to use:
<p>Fltk does not use RTTI (Run Time Typing Infomation), to enhance
portability. But this may change in the near future if RTTI becomes
standard everywhere.
<ul>
<li><a name="#clear_visible">clear_visible</a>
<li><a name="#damage">damage</a>
<li><a name="#draw_box">draw_box</a>
<li><a name="#draw_label">draw_label</a>
<li><a name="#set_flag">set_flag</a>
<li><a name="#set_visible">set_visible</a>
<li><a name="#test_shortcut">test_shortcut</a>
<li><a name="#type">type</a>
</ul>
<p>If you don't have RTTI you can use the clumsy fltk mechanisim, by
having type() have a unique value. These unique values must be
greater than the symbol FL_RESERVED_TYPE (which is 100). Grep through
the header files for "FL_RESERVED_TYPE" to find an unused number. If
you make a subclass of Fl_Group you must use FL_GROUP+n, and if you
make a subclass of Fl_Window you must use FL_WINDOW+n (in both cases n
is in the range 1-7).
<H3><a name="damage">void Fl_Widget::damage(uchar mask)<br>
void Fl_Widget::damage(uchar mask, int x, int y, int w, int h)<br>
uchar Fl_Widget::damage()</a></H3>
<a name=test_shortcut>
</ul><h4><code>void Fl_Widget::set_flag(SHORTCUT_LABEL);</code></h4><ul>
The first form indicates that a partial update of the object is
needed. The bits in mask are OR'd into <tt>damage()</tt>. Your
<tt>draw()</tt> routine can examine these bits to limit what it is
drawing. The public method <tt>Fl_Widget::redraw()</tt> simply does
<tt>Fl_Widget::damage(FL_DAMAGE_ALL)</tt>.
If your constructor calls this it modifies draw_label() so that '&'
characters cause an underscore to be printed under the next letter.
<p>The second form indicates that a region is damaged. If only these
calls are done in a window (no calls to <tt>damage(n)</tt>) then FLTK
will clip to the union of all these calls before drawing anything.
This can greatly speed up incremental displays. The mask bits are or'd
into <tt>damage()</tt> unless this is a <tt>Fl_Window</tt> widget.
</ul><h4><code>int Fl_Widget::test_shortcut() const;<br>
static int Fl_Widget::test_shortcut(const char *);</code></h4><ul>
<p>The third form returns the bitwise-OR of all <tt>damage(n)</tt>
calls done since the last <tt>draw()</tt>. The public method
<tt>redraw()</tt> does <tt>damage(FL_DAMAGE_ALL)</tt>, but the
implementation of your widget can call the private <tt>damage(n)</tt>.
The first version tests Fl_Widget::label() against the current event
(which should be a FL_SHORTCUT event). If the label contains a '&'
character and the character after it matches the key press, this
returns true. This returns false if the SHORTCUT_LABEL flag is off,
if the label is null or does not have a '&' character in it, or if the
keypress does not match the character.
<H3><a name="draw_box">void Fl_Widget::draw_box() const<br>
</a>void Fl_Widget::draw_box(Fl_Boxtype b, ulong c) const</H3>
<p>The second version lets you do this test to an arbitrary string.
The first form draws this widget's <tt>box()</tt>, using the dimensions
of the widget.
</ul><h4><code>void Fl_Widget::x(short);
<br>void Fl_Widget::y(short);
<br>void Fl_Widget::w(short);
<br>void Fl_Widget::h(short);</code></h4><ul>
The second form uses <tt>b</tt> as the box type and <tt>c</tt> as the
color for the box.
You can directly clobber the values for <a
href=Fl_Widget.html#xywh>x(), y(), w(), and h()</a>. Make sure you
know what you are doing. This is most useful for temporarily
replacing the values before calling handle() or draw() on the base
class to "fool" it into working in a different area.
<H3><a name="draw_label">void Fl_Widget::draw_label() const<br>
void Fl_Widget::draw_label(int x, int y, int w, int h) const<br>
void Fl_Widget::draw_label(int x, int y, int w, int h, Fl_Align align) const</a></H3>
<a name=damage>
</ul><h4><code>void Fl_Widget::damage(uchar mask);</code></h4><ul>
Indicate that a partial update of the object is needed. The bits in
mask are or'd into damage(). Your draw() routine can examine these
bits to limit what it is drawing. The public method
Fl_Widget::redraw() simply does Fl_Widget::damage(-1).
</ul><h4><code>void Fl_Widget::damage(uchar mask,int x,int y,int w,int
h);</code></h4><ul>
Indicate 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, in which case they are forced to the value 6 for
internal reasons).
</ul><h4><code>void Fl_Widget::clear_damage(uchar value = 0);</code></h4><ul>
Directly set damage() to the passed value. This is provided for
kludges only.
</ul><h4><code>uchar Fl_Widget::damage()</code></h4><ul>
Return the bitwise-or of all damage(n) calls done since the last
draw(). The public method redraw() does damage(-1), but the
implementation of your widget can call the private damage(n).
</ul><h4><code>void Fl_Widget::set_visible();
<br>void Fl_Widget::clear_visible();</code></h4><ul>
Fast inline versions of Fl_Widget::hide() and Fl_Widget::show().
These do not send the FL_HIDE and FL_SHOW events to the widget.
</ul><h4><code>void Fl_Widget::draw_box() const ;</code></h4><ul>
Draw this widget's box(), using the dimensions of the widget.
</ul><h4><code>void Fl_Widget::draw_box(Fl_Boxtype b,ulong c) const
;</code></h4><ul>
Pretend the box()==b and the color()==c and draw this widget's box.
<a name=draw_label>
</ul><h4><code>void Fl_Widget::draw_label() const ;</code></h4><ul>
This is the usual function for a draw() method to call to draw the
widget's label. It does not draw the label if it is supposed to be
This is the usual function for a <tt>draw()</tt> method to call to draw
the widget's label. It does not draw the label if it is supposed to be
outside the box (on the assumption that the enclosing group will draw
those labels).
</ul><h4><code>void Fl_Widget::draw_label(int x,int y,int w,int h) const
;</code></h4><ul>
<p>The second form uses the passed bounding box instead of the widget's
bounding box. This is useful so "centered" labels are aligned with some
feature, such as a moving slider.
Do the same thing except use the passed bounding box. This is useful
so "centered" labels are aligned with some feature, such as a moving
slider.
<p>The third form draws the label anywhere. It acts as though
<tt>FL_ALIGN_INSIDE</tt> has been forced on, the label will appear
inside the passed bounding box. This is designed for parent groups to
draw labels with.
</ul><h4><code>void Fl_Widget::draw_label(int x,int y,int w,int
h,Fl_Align align) const ;</code></h4><ul>
<H3><a name="set_flag">void Fl_Widget::set_flag(SHORTCUT_LABEL)</a></H3>
Draw the label anywhere. It acts as though FL_ALIGN_INSIDE has been
forced on, the label will appear inside the passed bounding box. This
is designed for parent groups to draw labels with.
If your constructor calls this it modifies <tt>draw_label()</tt> so
that '&' characters cause an underscore to be printed under the next
letter.
</ul>
<a name=handle>
<h2>virtual int Fl_Widget::handle()</h2>
<H3><a name="set_visible">void Fl_Widget::set_visible()</a><br>
<a name="clear_visible">void Fl_Widget::clear_visible()</a></H3>
The virtual method <b><code>int Fl_Widget::handle(int
event)</code></b> is called to handle each event passed to the widget.
It can:<ul>
Fast inline versions of <tt>Fl_Widget::hide()</tt> and
<tt>Fl_Widget::show()</tt>. These do not send the <tt>FL_HIDE</tt> and
<tt>FL_SHOW</tt> events to the widget.
<li>Change the state of the widget.
<H3><a name="test_shortcut">int Fl_Widget::test_shortcut() const<br>
static int Fl_Widget::test_shortcut(const char *s)</a></H3>
<li>Call <a href=Fl_Widget.html>Fl_Widget::redraw()</a> if the widget
needs to be redisplayed.
The first version tests <tt>Fl_Widget::label()</tt> against the current
event (which should be a <tt>FL_SHORTCUT</tt> event). If the label
contains a '&' character and the character after it matches the key
press, this returns true. This returns false if the
<tt>SHORTCUT_LABEL</tt> flag is off, if the label is <tt>NULL</tt> or
does not have a '&' character in it, or if the keypress does not match
the character.
<li>Call <a href=#damage>Fl_Widget::damage(n)</a> if the widget needs
a partial-update (assumming you provide support for this in your
Fl_Widget::draw() method).
<p>The second version lets you do this test against an arbitrary string.
<li>Call <a href=Fl_Widget.html>Fl_Widget::do_callback()</a> if a
callback should be generated.
<H3><a name="type">uchar Fl_Widget::type() const<br>
void Fl_Widget::type(uchar t)</a></H3>
<li>Call Fl_Widget::handle() on child widgets.
The property <tt>Fl_Widget::type()</tt> can return an arbitrary 8-bit
identifier, and can be set with the protected method <tt>type(uchar t)</tt>.
This value had to be provided for Forms compatibility, but you can use
it for any purpose you want. Try to keep the value less than 100 to
not interfere with reserved values.
<p>FLTK does not use RTTI (Run Time Typing Infomation), to enhance
portability. But this may change in the near future if RTTI becomes
standard everywhere.
<p>If you don't have RTTI you can use the clumsy FLTK mechanisim, by
having <tt>type()</tt> have a unique value. These unique values must
be greater than the symbol <tt>FL_RESERVED_TYPE</tt> (which is 100).
Look through the header files for <tt>FL_RESERVED_TYPE</tt> to find an
unused number. If you make a subclass of <tt>Fl_Group</tt> you must
use <tt>FL_GROUP + n</tt>, and if you make a subclass of
<tt>Fl_Window<tt> you must use <tt>FL_WINDOW + n</tt> (in both cases
<tt>n is in the range 1 to 7).
<H2>Handling Events</H2>
The virtual method <tt>int Fl_Widget::handle(int event)</tt> is called
to handle each event passed to the widget. It can:
<ul>
<li>Change the state of the widget.
<li>Call <a href="#Fl_Widget.redraw"><tt>Fl_Widget::redraw()</tt></a>
if the widget needs to be redisplayed.
<li>Call <a
href="#Fl_Widget.damage"><tt>Fl_Widget::damage(n)</tt></a> if
the widget needs a partial-update (assumming you provide
support for this in your <tt>Fl_Widget::draw()</tt> method).
<li>Call <a
href="#Fl_Widget.do_callback"><tt>Fl_Widget::do_callback()</tt></a>
if a callback should be generated.
<li>Call <tt>Fl_Widget::handle()</tt> on child widgets.
</ul>
<p>Events are identified the small integer argument. Other
information about the most recent event is stored in static locations
and aquired by calling <a href=events.html><code>Fl::event_*()</code></a>.
This other information remains valid until another event is read from
the X server.
Events are identified by the integer argument. Other information about
the most recent event is stored in static locations and aquired by
calling the <a href="#events"><tt>Fl::event_*()</tt></a> functions.
This information remains valid until another event is handled.
<p>Here is a sample Fl_Widget::handle(), for a widget that acts as a
<p>Here is a sample <tt>handle()</tt> method for a widget that acts as a
pushbutton and also accepts the keystroke 'x' to cause the callback:
<ul><pre>int Fl_Pushbutton::handle(int event) {
<ul><pre>
int MyClass::handle(int event) {
switch(event) {
case FL_PUSH:
highlight = 1; redraw();
highlight = 1;
redraw();
return 1;
case FL_DRAG:
{int t = Fl::event_inside(this);
if (t != highlight) {highlight = t; redraw();}}
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();
highlight = 0;
redraw();
do_callback();
// never do anything after a callback, so that the 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;}
if (Fl::event_key() == 'x') {
do_callback();
return 1;
}
return 0;
default:
return 0;
}
}
}
</pre></ul>
<p>You must return non-zero if your handle() method used the event.
If you return zero it indicates to the parent that it can try sending
another widget the event.
You must return non-zero if your <tt>handle()</tt> method uses the
event. If you return zero it indicates to the parent widget that it can
try sending the event to another widget.
<p>It looks like it is best to make the handle() method public.
<H2>Drawing the Widget</H2>
<a name=draw>
<h2>virtual void Fl_Widget::draw()</h2>
The <tt>draw()</tt> virtual method is called when FLTK wants you to
redraw your widget. It will be called if and only if <tt>damage()</tt>
is non-zero, and <tt>damage()</tt> will be cleared to zero after it
returns. <tt>draw()</tt> should be declared protected, so that it can't
be called from non-drawing code.
<p>The virtual method Fl_Widget::draw() 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.
draw() should be declared protected, so that subclasses may call it
but it can't be called from non-drawing code.
<p>damage() contains the bitwise-or of all the damage(n) calls to this
<p><tt>damage()</tt> contains the bitwise-OR of all the <tt>damage(n)</tt> calls to this
widget since it was last drawn. This can be used for minimal update,
by only redrawing the parts whose bits are set. Fltk will turn
by only redrawing the parts whose bits are set. FLTK will turn
<i>all</i> the bits on if it thinks the entire widget must be redrawn
(for instance due to an expose event). It is easiest to program to
handle this by pretending a bit (usually damage()&128) draw the
non-minimal-update parts of your widget (such as the box()).
(for instance due to an expose event).
<p>Expose events (and the above damage(b,x,y,w,h)) will cause draw()
to be called with fltk's <a href=Draw.html#clipping>clipping</a>
turned on. You can greatly speed up redrawing in some cases by
testing <code>fl_clipped</code> and <code>fl_current_clip</code>
and skipping invisible parts.
<p>Expose events (and the above <tt>damage(b,x,y,w,h)</tt>) will cause
<tt>draw()</tt> to be called with FLTK's <a
href="#clipping">clipping</a> turned on. You can greatly speed up
redrawing in some cases by testing <tt>fl_clipped</tt> and
<tt>fl_current_clip</tt> and skipping invisible parts.
<p>The functions you can use to draw are described in <a
href=Draw.html>&lt;FL/fl_draw.H></a> or any of the protected
Fl_Widget::draw_* methods described above.
<p>Besides the protected methods described above, FLTK provide a large
number of basic drawing functions, which are described <a
href=#drawing>below</a>.
<a name=resize>
<h2>virtual void Fl_Widget::resize(int,int,int,int);</h2>
<H2>Resizing the Widget</H2>
This is called when the widget is being resized or moved. The
arguments are the new position, width, and height. x(), y(), w(), and
h() still return the old size. You must call resize() on your
base class with the same arguments to get the widget size to actually
change.
The <tt>resize(int x, int y, int w, int h)</tt> method is called when
the widget is being resized or moved. The arguments are the new
position, width, and height. <tt>x()</tt>, <tt>y()</tt>, <tt>w()</tt>,
and <tt>h()</tt> still remain the old size. You must call
<tt>resize()</tt> on your base class with the same arguments to get the
widget size to actually change.
<p>This should <i>not</i> call redraw(), at least if only the x() and
y() change. This is because group objects like <a
href=Fl_Scroll.html>Fl_Scroll</a> may have a more efficient way of
drawing the new position.
<p>This should <i>not</i> call <tt>redraw()</tt>, at least if only the
<tt>x()</tt> and <tt>y()</tt> change. This is because group objects
like <a href="#Fl_Scroll"><tt>Fl_Scroll</tt></a> may have a more
efficient way of drawing the new position.
<p>It may be useful to refer to the size the widget was constructed
at, these are stored in Fl_Widget::ix(), iy(), iw(), and ih().
<p>Resize should be declared public.
<a name=destructor>
<h2>virtual Fl_Widget::~Fl_Widget();</h2>
We all know why the destructor must be virtual don't we? Don't forget
to make it public.
<a name=composite>
<h2>Making a Composite/Group Widget</h2>
<H2>Making a Composite/Group Widget</H2>
A "composite" widget contains one or more "child" widgets. To do this
you should subclass <a href=Fl_Group.html>Fl_Group</a> (it is
you should subclass <a href="#Fl_Group"><tt>Fl_Group</tt></a>. It is
possible to make a composite object that is not a subclass of
Fl_Group, but this is very difficult).
<tt>Fl_Group</tt>, but you'll have to duplicate the code in <tt>Fl_Group</tt>
anyways.
<p>Instances of the child widgets may be included in the parent:
<ul><pre>class MyClass : public Fl_Group {
<ul><pre>
class MyClass : public Fl_Group {
Fl_Button the_button;
Fl_Slider the_slider;
...
};
</pre></ul>
<p>The constructor has to initialize these instances. They are
automatically add()ed to the group, since the Fl_Group constructor
does begin(). <i>Don't forget to call end():</i>
The constructor has to initialize these instances. They are
automatically <tt>add()</tt>ed to the group, since the
<tt>Fl_Group</tt> constructor does <tt>begin()</tt>. <i>Don't forget
to call <tt>end()</tt> or use the <a href="#Fl_End"><tt>Fl_End</tt></a>
pseudo-class:</i>
<ul><pre>MyClass::MyClass(int x,int y,int w,int h) :
Fl_Group(x,y,w,h),
the_button(x+5,y+5,100,20),
the_slider(x,y+50,w,20)
<ul><pre>
MyClass::MyClass(int x, int y, int w, int h) :
Fl_Group(x, y, w, h),
the_button(x + 5, y + 5, 100, 20),
the_slider(x, y + 50, w, 20)
{
...(you could add dynamically created child widgets here)...
end(); // don't forget to do this!
}
</pre></ul>
<p>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:
The child widgets need callbacks. These will be called with a pointer
to the children, but the widget itself may be found in the
<tt>parent()</tt> pointer of the child. Usually these callbacks can be
static private methods, with a matching private method:
<ul><pre>void MyClass::slider_cb(Fl_Widget* v, void *) { // static method
<ul><pre>
void MyClass::slider_cb(Fl_Widget* v, void *) { // static method
((MyClass*)(v->parent())->slider_cb();
}
void MyClass::slider_cb() { // normal method
@ -429,31 +340,33 @@ void MyClass::slider_cb() { // normal method
}
</pre></ul>
<p>If you make the handle() method, you can quickly pass all the
events to the children (notice that you don't need to override
handle() if your composite widget does nothing other than pass events
to the children):
If you make the <tt>handle()</tt> method, you can quickly pass all the
events to the children using the <tt>Fl_Group::handle()</tt> method.
Note that you don't need to override <tt>handle()</tt> if your
composite widget does nothing other than pass events to the children:
<ul><pre>int MyClass::handle(int event) {
<ul><pre>
int MyClass::handle(int event) {
if (Fl_Group::handle(event)) return 1;
... handle events that children don't want ...
}
</pre></ul>
<p>If you override draw() you need to draw all the children. If
redraw() or damage() is called on a child, damage(1) is done to the
group. Thus the 1 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:
If you override <tt>draw()</tt> you need to draw all the children. If
<tt>redraw()</tt> or <tt>damage()</tt> is called on a child,
<tt>damage(FL_DAMAGE_CHILD)</tt> is done to the group, so this bit of
<tt>damage()</tt> can be used to indicate that a child needs to be
drawn. It is fastest if you avoid drawing anything else in this case:
<ul><pre>int MyClass::draw() {
Fl_Widget*const* a = array();
if (damage()==1) { // only redraw some children
for (int i=children(); i--; a++) update_child(**a);
<ul><pre>
int MyClass::draw() {
Fl_Widget *const*a = array();
if (damage() == FL_DAMAGE_CHILD) { // only redraw some children
for (int i = children(); i --; a ++) update_child(**a);
} else { // total redraw
... draw background graphics ...
// now draw all the children atop the background:
for (int i=children_; i--; a++) {
for (int i = children_; i --; a ++) {
draw_child(**a);
draw_outside_label(**a); // you may not want to do this
}
@ -461,59 +374,84 @@ else in this case:
}
</pre></ul>
<p>Fl_Group provides some protected methods to make drawing easier:
</ul><h4><code>void Fl_Group::draw_outside_label(Fl_Widget&) const;</code></h4><ul>
Draw the labels that are <i>not</i> drawn by <a
href=#draw_label>draw_label()</a>. If you want more control over the
label positions you might want to call child->draw_label(x,y,w,h,a).
</ul><h4><code>void Fl_Group::draw_child(Fl_Widget&);</code></h4><ul>
This will force the child's damage() bits all to one and call draw()
on it, then clear the damage(). You should call this on all children
if a total redraw of your widget is requested, or if you draw
something (like a background box) that damages the child. Nothing is
done if the child is not visible() or if it is clipped.
</ul><h4><code>void Fl_Group::update_child(Fl_Widget&);</code></h4><ul>
Draws the child only if it's damage() is non-zero. You should call
this on all the children if your own damage is equal to 1. Nothing is
done if the child is not visible() or if it is clipped.
<tt>Fl_Group</tt> provides some protected methods to make drawing easier:
<ul>
<li><a href="#draw_child">draw_child</a>
<li><a href="#draw_outside_label">draw_outside_label</a>
<li><a href="#update_child">update_child</a>
</ul>
<a name=window>
<h2>Making a subclass of Fl_Window</h2>
<H3><a name="draw_child">void Fl_Group::draw_child(Fl_Widget&amp;)</a></H3>
<p>You may want your widget to be a subclass of Fl_Window. This can
be useful if your widget wants to occupy an entire window, and can
This will force the child's <tt>damage()</tt> bits all to one and call
<tt>draw()</tt> on it, then clear the <tt>damage()</tt>. You should
call this on all children if a total redraw of your widget is
requested, or if you draw something (like a background box) that
damages the child. Nothing is done if the child is not
<tt>visible()</tt> or if it is clipped.
<H3><a name="draw_outside_label">void Fl_Group::draw_outside_label(Fl_Widget&amp;) const</a></H3>
Draw the labels that are <i>not</i> drawn by
<a href="#draw_label"><tt>draw_label()</tt></a>. If you want more control
over the label positions you might want to call
<tt>child->draw_label(x,y,w,h,a)</tt>.
<H3><a name="update_child">void Fl_Group::update_child(Fl_Widget&amp;)</a></H3>
Draws the child only if it's <tt>damage()</tt> is non-zero. You should
call this on all the children if your own damage is equal to
FL_DAMAGE_CHILD. Nothing is done if the child is not
<tt>visible()</tt> or if it is clipped.
<H2>Cut and Paste Support</H2>
FLTK provides routines to cut and paste ASCII text (in the future this
may be UTF-8) between applications:
<ul>
<li><a href="#paste">Fl::paste</a>
<li><a href="#selection">Fl::selection</a>
<li><a href="#selection_length">Fl::selection_length</a>
<li><a href="#selection_owner">Fl::selection_owner</a>
</ul>
It may be possible to cut/paste non-ASCII data by using <a
href="#add_handler"><tt>Fl::add_handler()</tt></a>.
<H2>Making a subclass of Fl_Window</H2>
You may want your widget to be a subclass of <tt>Fl_Window</tt>. This
can be useful if your widget wants to occupy an entire window, and can
also be used to take advantage of system-provided clipping, or to work
with a library that expects a system window id to indicate where to
draw.
<p>Subclassing Fl_Window is almost exactly like subclassing Fl_Widget,
in fact you can easily switch a subclass back and forth. Watch out
for the following differences:
<p>Subclassing <tt>Fl_Window</tt> is almost exactly like subclassing
<tt>Fl_Widget</tt>, in fact you can easily switch a subclass back and
forth. Watch out for the following differences:
<ol>
<li>Fl_Window is a subclass of Fl_Group so <i>make sure your constructor
calls end()</i> (unless you actually want children added to your
window).
<li>When handling events and drawing, the lower-left corner is at 0,0,
not x(),y() as in other Fl_Widgets. For instance, to draw a box
around the widget, call draw_box(0,0,w(),h()), rather than
draw_box(x(),y(),w(),h()).
<li><tt>Fl_Window</tt> is a subclass of <tt>Fl_Group</tt> so
<i>make sure your constructor calls <tt>end()</tt></i> (unless
you actually want children added to your window).
<li>When handling events and drawing, the upper-left corner is
at 0,0, not <tt>x(),y()</tt> as in other <tt>Fl_Widget</tt>s.
For instance, to draw a box around the widget, call
<tt>draw_box(0, 0, w(), h())</tt>, rather than
<tt>draw_box( x(), y(), w(), h())</tt>.
</ol>
<p>You may also want to subclass Fl_Window in order to get access to
different X visuals or to change other X attributes of the windows,
<a href=x.html#window>See here for details</a>.
You may also want to subclass <tt>Fl_Window</tt> in order to get access to
different visuals or to change other attributes of the windows. See
<a href="#osissues">Appendix F - Operating System Issues</a> for more
information.
</BODY>
</HTML>
<p><a href = index.html>(back to contents)</a>

View File

@ -1,6 +1,11 @@
<HTML>
<BODY>
<H1 ALIGN=RIGHT>A - Widget Reference</H1>
This appendix describes all of the widget classes in FLTK. For a
description of the <tt>fl_</tt> functions and <tt>Fl::</tt> methods,
see <a href="#functions"> Appendix B</a>.
</BODY>
</HTML>