From 09daf20b81cdae78772f07c0af22a571d7cc73eb Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Thu, 29 Nov 2001 19:24:00 +0000 Subject: Documentation updates galore (up to chapter 7, still need to do chapter 8 and 9, tweek the appendices, and recapture the screenshots...) git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@1786 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- documentation/subclassing.html | 375 +++++++++++++++++++++-------------------- 1 file changed, 196 insertions(+), 179 deletions(-) (limited to 'documentation/subclassing.html') diff --git a/documentation/subclassing.html b/documentation/subclassing.html index ad2a1a6f0..9da68b134 100644 --- a/documentation/subclassing.html +++ b/documentation/subclassing.html @@ -1,51 +1,46 @@

7 - Adding and Extending Widgets

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

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

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

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. + 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 + 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: + The following methods are provided for subclasses to use:

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

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 +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: + 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 + 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 + 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. draw() should be declared protected, so that it can't -be called from non-drawing code. -

damage() 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).

+ +

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

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(), + 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. + 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 +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. + 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: - +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 +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). +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 + 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. + 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: +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(). +Fl::add_handler().

Making a subclass of Fl_Window

-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 -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_Window is almost exactly like subclassing -Fl_Widget, and in fact you can easily switch a subclass back and -forth. Watch out for the following differences:

+ +

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. + +
  5. Fl_Window is a subclass of + Fl_Group so make sure your constructor calls + end() unless you actually want children + added to your window.
  6. + +
  7. 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()).
  8. +
- 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. + +

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