From 8416a4012ecb985d150fad566659cf59ee1dc3aa Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Sat, 13 Sep 2008 15:55:32 +0000 Subject: Doxygen documentation - WP12 and WP13 - first step. Converted the descriptive chapters of the html docs to doxygen format and modified index.dox accordingly. This checkin includes only trivial reformatting, no major rewriting. Added a chapter "Migrating Code from FLTK 1.1 to 1.3". All links on the main page are working now. Todo: - Check doxygen error messages, rewrite pages (html tags, contents). - Fill the new "Migrating..." chapter. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6224 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- documentation/subclassing.dox | 431 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 documentation/subclassing.dox (limited to 'documentation/subclassing.dox') diff --git a/documentation/subclassing.dox b/documentation/subclassing.dox new file mode 100644 index 000000000..cb4763be2 --- /dev/null +++ b/documentation/subclassing.dox @@ -0,0 +1,431 @@ +/** + + \page subclassing 7 - Adding and Extending Widgets + +

This chapter describes how to add your own widgets or extend existing +widgets in FLTK. +

Subclassing

+ New widgets are created by subclassing an existing FLTK widget, +typically Fl_Widget for controls and Fl_Group for +composite widgets. +

A control widget typically interacts with the user to receive and/or +display a value of some sort.

+

A composite widget widget holds a list of child widgets and handles moving, +sizing, showing, or hiding them as needed. Fl_Group is the +main composite widget widget class in FLTK, and all of the other composite widgets ( +Fl_Pack, Fl_Scroll, Fl_Tabs, Fl_Tile, +and Fl_Window) are subclasses of it.

+

You can also subclass other existing widgets to provide a different +look or user-interface. For example, the button widgets are all +subclasses of Fl_Button since they all interact with the user +via a mouse button click. The only difference is the code that draws +the face of the button.

+

Making a Subclass of Fl_Widget

+ 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. +

The Constructor

+ The constructor should have the following arguments: + + This will allow the class to be used in FLUID + without problems. +

The constructor must call the constructor for the base class and +pass the same arguments:

+ +Fl_Widget's protected constructor sets x(), y(), +w(), h(), and label() to the passed values +and initializes the other instance variables to: + +

Protected Methods of Fl_Widget

+ The following methods are provided for subclasses to use: + +

void Fl_Widget::damage(uchar mask) +
void Fl_Widget::damage(uchar mask, int x, int y, int w, int h) +
uchar Fl_Widget::damage()

+The first form indicates 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(FL_DAMAGE_ALL), but the implementation of +your widget can call the private damage(n). +

The second form indicates that a region is damaged. If only these +calls are done in a window (no calls to damage(n)) then FLTK +will clip to the union of all these calls before drawing anything. + This can greatly speed up incremental displays. The mask bits are +OR'd into damage() unless this is a Fl_Window widget.

+

The third form returns the bitwise-OR of all damage(n) +calls done since the last draw().

+

When redrawing your widgets you should look at the damage bits to +see what parts of your widget need redrawing. The handle() +method can then set individual damage bits to limit the amount of drawing +that needs to be done: +

+

void Fl_Widget::draw_box() const +
void Fl_Widget::draw_box(Fl_Boxtype b, ulong c) const

+ The first form draws this widget's box(), using the +dimensions of the widget. The second form uses b as the box +type and c as the color for the box. + +

void Fl_Widget::draw_focus() const +
void Fl_Widget::draw_focus(Fl_Boxtype b, int x, int y, int w, int h) const

+ +

Draws a focus box inside the widgets bounding box. The second +form allows you to specify a different bounding box. + +

void Fl_Widget::draw_label() const +
void Fl_Widget::draw_label(int x, int y, int w, int h) const +
void Fl_Widget::draw_label(int x, int y, int w, int h, Fl_Align +align) const

+ 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 outside the box (on the assumption that the enclosing group will +draw those labels). +

The second form uses the passed bounding box instead of the widget's +bounding box. This is useful so "centered" labels are aligned with some +feature, like a moving slider.

+

The third form draws the label anywhere. It acts as though +FL_ALIGN_INSIDE has been forced on so the label will appear inside +the passed bounding box. This is designed for parent groups to draw +labels with.

+

void Fl_Widget::set_flag(SHORTCUT_LABEL)

+Modifies draw_label() so that '&' characters cause an underscore +to be printed under the next letter. +

void Fl_Widget::set_visible() +
void Fl_Widget::clear_visible()

+ 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. +

int Fl_Widget::test_shortcut() const +
static int Fl_Widget::test_shortcut(const char *s)

+ 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. +

The second version lets you do this test against an arbitrary +string.

+

uchar Fl_Widget::type() const +
void Fl_Widget::type(uchar t)

+ The property Fl_Widget::type() can return an arbitrary 8-bit +identifier, and can be set with the protected method type(uchar t) +. 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. +

FLTK does not use RTTI (Run Time Typing Infomation), to enhance +portability. But this may change in the near future if RTTI becomes +standard everywhere.

+

If you don't have RTTI you can use the clumsy FLTK mechanisim, by +having type() use a unique value. These unique values must +be greater than the symbol FL_RESERVED_TYPE (which is 100). +Look through the header files for FL_RESERVED_TYPE to find an +unused number. If you make a subclass of Fl_Window +you must use FL_WINDOW + n (n must be in the +range 1 to 7).

+

Handling Events

+ The virtual method int Fl_Widget::handle(int event) is called +to handle each event passed to the widget. It can: + + Events are identified by the integer argument. Other information +about the most recent event is stored in static locations and aquired +by calling the Fl::event_*() + functions. This information remains valid until another event is +handled. +

Here is a sample handle() method for a widget that acts as +a pushbutton and also accepts the keystroke 'x' to cause the callback:

+ + +

You must return non-zero if your handle() method +uses the event. If you return zero, the parent widget will try +sending the event to another widget. + +

Drawing the Widget

+ +

The draw() virtual method is called when FLTK wants +you to redraw your widget. It will be called if and only if +damage() is non-zero, and damage() will be +cleared to zero after it returns. The draw() method +should be declared protected so that it can't be called from +non-drawing code. + +

The damage() value contains the bitwise-OR of all +the damage(n) calls to this widget since it was last +drawn. This can be used for minimal update, by only redrawing +the parts whose bits are set. FLTK will turn on the +FL_DAMAGE_ALL bit if it thinks the entire widget must +be redrawn, e.g. for an expose event.

+ +

Expose events (and the above damage(b,x,y,w,h)) will cause +draw() to be called with FLTK's +clipping turned on. You can greatly speed up redrawing in some +cases by testing fl_not_clipped(x,y,w,h) or fl_clip_box(...) and +skipping invisible parts.

+

Besides the protected methods described above, FLTK provides a large +number of basic drawing functions, which are described +below.

+

Resizing the Widget

+ The resize(int x, int y, int w, int h) method 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 remain the old size. You must call resize() + on your base class with the same arguments to get the widget size to +actually change. +

This should not call redraw(), at least if only the +x() and y() change. This is because composite widgets like +Fl_Scroll may have a more efficient way of drawing the new +position.

+

Making a Composite Widget

+ A "composite" widget contains one or more "child" widgets. + To make a composite widget you should subclass Fl_Group +. It is possible to make a composite object that is not a subclass of +Fl_Group, but you'll have to duplicate the code in Fl_Group + anyways. +

Instances of the child widgets may be included in the parent:

+ + The constructor has to initialize these instances. They are +automatically add()ed to the group, since the Fl_Group + constructor does begin(). Don't forget to call end() + or use the Fl_End pseudo-class: + + 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: + + If you make the handle() method, you can quickly pass all the +events to the children using the Fl_Group::handle() method. +You don't need to override handle() if your composite widget +does nothing other than pass events to the children: + + +

If you override draw() you need to draw all the +children. If redraw() or damage() is called +on a child, damage(FL_DAMAGE_CHILD) is done to the +group, so this bit of damage() can be used to indicate +that a child needs to be drawn. It is fastest if you avoid +drawing anything else in this case: + +

+Fl_Group provides some protected methods to make drawing +easier: + +

void Fl_Group::draw_child(Fl_Widget&)

+ 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. +

void +Fl_Group::draw_outside_label(Fl_Widget&) const

+ Draw the labels that are not drawn by +draw_label(). If you want more control over the label +positions you might want to call child->draw_label(x,y,w,h,a). +

void Fl_Group::update_child(Fl_Widget&)

+ Draws the child only if its damage() 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 visible() + or if it is clipped. + +

Cut and Paste Support

+FLTK provides routines to cut and paste 8-bit text (in the future this +may be UTF-8) between applications: + +It may be possible to cut/paste non-text data by using +Fl::add_handler(). + +

Drag And Drop Support

+ +FLTK provides routines to drag and drop 8-bit text between applications: + +

Drag'n'drop operations are are initiated by copying data to the +clipboard and calling the function +Fl::dnd(). + +

Drop attempts are handled via events: +

+ +

Making a subclass of Fl_Window

+ +

You may want your widget to be a subclass of +Fl_Window, Fl_Double_Window, or +FL_Gl_Window. This can be useful if your widget wants +to occupy an entire window, and can also be used to take +advantage of system-provided clipping, or to work with a library +that expects a system window ID to indicate where to draw. + +

Subclassing Fl_Windowis almost exactly like +subclassing Fl_Group, and in fact you can easily +switch a subclass back and forth. Watch out for the following +differences:

+ +
    + +
  1. Fl_Window is a subclass of + Fl_Group so make sure your constructor calls + end() unless you actually want children + added to your window.
  2. + +
  3. When handling events and drawing, the upper-left + corner is at 0,0, not x(),y() as in other + Fl_Widget's. For instance, to draw a box + around the widget, call draw_box(0, 0, w(), + h()), rather than draw_box(x(), y(), w(), + h()).
  4. + +
+ +

You may also want to subclass Fl_Window in order to +get access to different visuals or to change other attributes of +the windows. See "Appendix F - Operating +System Issues" for more information. + +*/ -- cgit v1.2.3