diff options
Diffstat (limited to 'branch-3.0-2011/documentation/src/subclassing.dox')
| -rw-r--r-- | branch-3.0-2011/documentation/src/subclassing.dox | 565 |
1 files changed, 0 insertions, 565 deletions
diff --git a/branch-3.0-2011/documentation/src/subclassing.dox b/branch-3.0-2011/documentation/src/subclassing.dox deleted file mode 100644 index 3b6afb7e5..000000000 --- a/branch-3.0-2011/documentation/src/subclassing.dox +++ /dev/null @@ -1,565 +0,0 @@ -/** - - \page subclassing Adding and Extending Widgets - - -This chapter describes how to add your own widgets or extend existing -widgets in FLTK. - -\section subclassing_subclassing Subclassing - -New widgets are created by \e 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 holds a list of child widgets and handles moving, -sizing, showing, or hiding them as needed. Fl_Group is the main -composite 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. - -\section subclassing_fl_widget 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. - -\section subclassing_constructor The Constructor - -The constructor should have the following arguments: - -\code -MyClass(int x, int y, int w, int h, const char *label = 0); -\endcode - -This will allow the class to be used in -\ref fluid "FLUID" -without problems. - -The constructor must call the constructor for the base class and -pass the same arguments: - -\code -MyClass::MyClass(int x, int y, int w, int h, const char *label) -: Fl_Widget(x, y, w, h, label) { -// do initialization stuff... -} -\endcode - -Fl_Widget's protected constructor sets \p x(), \p y(), -\p w(), \p h(), and \p label() to the passed values -and initializes the other instance variables to: - -\code -type(0); -box(FL_NO_BOX); -color(FL_BACKGROUND_COLOR); -selection_color(FL_BACKGROUND_COLOR); -labeltype(FL_NORMAL_LABEL); -labelstyle(FL_NORMAL_STYLE); -labelsize(FL_NORMAL_SIZE); -labelcolor(FL_FOREGROUND_COLOR); -align(FL_ALIGN_CENTER); -callback(default_callback,0); -flags(ACTIVE|VISIBLE); -image(0); -deimage(0); -\endcode - -\section subclassing_protected Protected Methods of Fl_Widget - -The following methods are provided for subclasses to use: - -\li \ref subclassing_clear_visible "clear_visible()" -\li \ref subclassing_damage "damage()" -\li \ref subclassing_draw_box "draw_box()" -\li \ref subclassing_draw_focus "draw_focus()" -\li \ref subclassing_draw_label "draw_label()" -\li \ref subclassing_set_flag "set_flag()" -\li \ref subclassing_set_visible "set_visible()" -\li \ref subclassing_test_shortcut "test_shortcut()" -\li \ref subclassing_type "type()" - -\anchor subclassing_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() - -\par -The first form indicates that a partial update of the object is -needed. The bits in mask are OR'd into -\ref subclassing_damage "damage()". -Your \p draw() routine can examine these bits to limit what it is -drawing. The public method Fl_Widget::redraw() simply does -\p Fl_Widget::damage(FL_DAMAGE_ALL), -but the implementation of your widget can call the public -\p damage(n). - -\par -The second form indicates that a region is damaged. If only these -calls are done in a window (no calls to \p 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 \p damage() unless this is a Fl_Window widget. - -\par -The third form returns the bitwise-OR of all \p damage(n) -calls done since the last \p draw(). - -\par -<I>When redrawing your widgets you should look at the damage bits to -see what parts of your widget need redrawing.</I> The \p handle() -method can then set individual damage bits to limit the amount of drawing -that needs to be done: -\code -MyClass::handle(int event) { - ... - if (change_to_part1) damage(1); - if (change_to_part2) damage(2); - if (change_to_part3) damage(4); -} - -MyClass::draw() { - if (damage() & FL_DAMAGE_ALL) { - ... draw frame/box and other static stuff ... - } - - if (damage() & (FL_DAMAGE_ALL | 1)) draw_part1(); - if (damage() & (FL_DAMAGE_ALL | 2)) draw_part2(); - if (damage() & (FL_DAMAGE_ALL | 4)) draw_part3(); -} -\endcode - -\todo Clarify Fl_Window::damage(n) handling - seems confused/wrong? - ORing value doesn't match setting behaviour in FL_Widget.H! - -\anchor subclassing_draw_box -void Fl_Widget::draw_box() const <br> -void Fl_Widget::draw_box(Fl_Boxtype t, Fl_Color c) const - -\par -The first form draws this widget's \p box(), using the -dimensions of the widget. The second form uses \p t as the box -type and \p c as the color for the box. - -\anchor subclassing_draw_focus -void Fl_Widget::draw_focus() <br> -void Fl_Widget::draw_focus(Fl_Boxtype t, int x, int y, int w, int h) const - -\par -Draws a focus box inside the widget's bounding box. The second -form allows you to specify a different bounding box. - -\anchor subclassing_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 - -\par -The first form is the usual function for a \p 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). - -\par -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. - -\par -The third form draws the label anywhere. It acts as though -\p 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. - -\anchor subclassing_set_flag -void Fl_Widget::set_flag(int c) <br> - -\par -Calling \p set_flag(SHORTCUT_LABEL) modifies the behavior of -\ref subclassing_draw_label "draw_label()" so that '\&' characters -cause an underscore to be printed under the next letter. - -\anchor subclassing_clear_visible -\anchor subclassing_set_visible -void Fl_Widget::set_visible() <br> -void Fl_Widget::clear_visible() - -\par -Fast inline versions of Fl_Widget::hide() and Fl_Widget::show(). -These do not send the \p FL_HIDE and \p FL_SHOW events to the widget. - -\anchor subclassing_test_shortcut -int Fl_Widget::test_shortcut() <br> -static int Fl_Widget::test_shortcut(const char *s) - -\par -The first version tests Fl_Widget::label() against the current event -(which should be a \p FL_SHORTCUT event). If the label contains a '&' -character and the character after it matches the keypress, this returns -true. This returns false if the \p SHORTCUT_LABEL flag is off, if the -label is \p NULL, or does not have a '&' character in it, or if the -keypress does not match the character. - -\par -The second version lets you do this test against an arbitrary string. - -\todo Clarify Fl_Widget::test_shortcut() explanations. Fl_Widget.h - says Internal Use only, but subclassing chapter gives details! - -\anchor subclassing_type -uchar Fl_Widget::type() const <br> -void Fl_Widget::type(uchar t) - -\par -The property Fl_Widget::type() 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. - -\par -FLTK does not use RTTI (Run Time Typing Information), to enhance -portability. But this may change in the near future if RTTI becomes -standard everywhere. - -\par -If you don't have RTTI you can use the clumsy FLTK mechanism, by -having \p type() use a unique value. These unique values must -be greater than the symbol \p FL_RESERVED_TYPE (which is 100) and -less than \p FL_WINDOW (unless you make a subclass of Fl_Window). -Look through the header files for \p FL_RESERVED_TYPE to find an -unused number. If you make a subclass of Fl_Window you must use -<tt>FL_WINDOW + n</tt> (where \p n must be in the range 1 to 7). - -\section subclassing_events Handling Events - -The virtual method Fl_Widget::handle(int event) is called -to handle each event passed to the widget. It can: - -\li Change the state of the widget. -\li Call Fl_Widget::redraw() if the widget needs to be redisplayed. -\li Call Fl_Widget::damage(uchar c) if the widget needs a partial-update - (assuming you provide support for this in your - \ref subclassing_drawing "draw()" - method). -\li Call Fl_Widget::do_callback() if a callback should be generated. -\li Call Fl_Widget::handle() on child widgets. - -Events are identified by the integer argument. Other information -about the most recent event is stored in static locations and acquired -by calling the -\ref events_event_xxx. -This information remains valid until another event is handled. - -Here is a sample \p handle() method for a widget that acts as -a pushbutton and also accepts the keystroke \p 'x' to cause the callback: - -\code -int MyClass::handle(int event) { - switch(event) { - case FL_PUSH: - highlight = 1; - redraw(); - return 1; - case FL_DRAG: { - int t = Fl::event_inside(this); - if (t != highlight) { - highlight = t; - redraw(); - } - } - return 1; - case FL_RELEASE: - if (highlight) { - highlight = 0; - redraw(); - do_callback(); - // never do anything after a callback, as the callback - // may delete the widget! - } - return 1; - case FL_SHORTCUT: - if (Fl::event_key() == 'x') { - do_callback(); - return 1; - } - return 0; - default: - return Fl_Widget::handle(event); - } -} -\endcode - -You must return non-zero if your \p handle() method -uses the event. If you return zero, the parent widget will try -sending the event to another widget. - -For debugging purposes, event numbers can be printed as their actual event names -using the \ref fl_eventnames[] array, e.g.: -\code - #include <FL/names.h> // defines fl_eventnames[] - [..] - int MyClass::handle(int e) { - printf("Event was %s (%d)\n", fl_eventnames[e], e); // e.g. "Event was FL_PUSH (1)" - [..] -\endcode - -\section subclassing_drawing Drawing the Widget - -The \p draw() virtual method is called when FLTK wants -you to redraw your widget. It will be called if and only if -\p damage() is non-zero, and \p damage() will be -cleared to zero after it returns. The \p draw() method -should be declared protected so that it can't be called from -non-drawing code. - -The \p damage() value contains the bitwise-OR of all -the \p 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 -\p FL_DAMAGE_ALL bit if it thinks the entire widget must -be redrawn, e.g. for an expose event. - -Expose events (and the -\ref subclassing_damage "damage(mask,x,y,w,h)" function described -above) will cause \p draw() to be called with FLTK's -\ref ssect_Clipping "clipping" -turned on. You can greatly speed up redrawing in some -cases by testing \p fl_not_clipped(x,y,w,h) or \p %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 in the chapter -\ref drawing. - -\section subclassing_resizing Resizing the Widget - -The \p resize(x,y,w,h) method is called when -the widget is being resized or moved. The arguments are the new -position, width, and height. \p x(), \p y(), \p w(), -and \p h() still remain the old size. You must call \p resize() -on your base class with the same arguments to get the widget size to -actually change. - -This should \e not call \p redraw(), at least if only the -\p x() and \p y() change. This is because composite widgets like -Fl_Scroll may have a more efficient way of drawing the new position. - -\section subclassing_composite 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: - -\code -class MyClass : public Fl_Group { - Fl_Button the_button; - Fl_Slider the_slider; - ... -}; -\endcode - -The constructor has to initialize these instances. They are automatically -added to the group, since the Fl_Group constructor does -Fl_Group::begin(). -<I>Don't forget to call Fl_Group::end() or use the Fl_End pseudo-class:</I> - -\code -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! -} -\endcode - -The child widgets need callbacks. These will be called with a pointer -to the children, but the widget itself may be found in the \p parent() -pointer of the child. Usually these callbacks can be static private -methods, with a matching private method: - -\code -void MyClass::static_slider_cb(Fl_Widget* v, void *) { // static method - ((MyClass*)(v->parent())->slider_cb(); -} -void MyClass::slider_cb() { // normal method - use(the_slider->value()); -} -\endcode - -If you make the \p handle() method, you can quickly pass all the -events to the children using the Fl_Group::handle() method. -You don't need to override \p handle() if your composite widget -does nothing other than pass events to the children: - -\code -int MyClass::handle(int event) { - if (Fl_Group::handle(event)) return 1; - ... handle events that children don't want ... -} -\endcode - -If you override \p draw() you need to draw all the children. -If \p redraw() or \p damage() is called on a child, -\p damage(FL_DAMAGE_CHILD) is done to the group, -so this bit of \p 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: - -\code -int MyClass::draw() { - Fl_Widget *const*a = array(); - if (damage() == FL_DAMAGE_CHILD) { // only redraw some children - for (int i = children(); i --; a ++) update_child(**a); - } else { // total redraw - ... draw background graphics ... - // now draw all the children atop the background: - for (int i = children_; i --; a ++) { - draw_child(**a); - draw_outside_label(**a); // you may not need to do this - } - } -} -\endcode - -Fl_Group provides some protected methods to make drawing easier: - -\li \ref subclassing_draw_child "draw_child()" -\li \ref subclassing_draw_children "draw_children()" -\li \ref subclassing_draw_outside_label "draw_outside_label()" -\li \ref subclassing_update_child "update_child()" - -\anchor subclassing_draw_child -void Fl_Group::draw_child(Fl_Widget &widget) const - -\par -This will force the child's \p damage() bits all to one and call -\p draw() on it, then clear the \p 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 \p visible() or if it is -clipped. - -\anchor subclassing_draw_children -void Fl_Group::draw_children() - -\par -A convenience function that draws all children of the group. -This is useful if you derived a widget from Fl_Group and want to draw -a special border or background. You can call \p draw_children() from the -derived \p draw() method after drawing the box, border, or background. - -\anchor subclassing_draw_outside_label -void Fl_Group::draw_outside_label(const Fl_Widget &widget) const - -\par -Draw the labels that are \e not drawn by -\ref subclassing_draw_label "draw_label()". -If you want more control over the label positions you might want to call -<tt>child->draw_label(x,y,w,h,a)</tt>. - -\anchor subclassing_update_child -void Fl_Group::update_child(Fl_Widget& widget) const - -\par -Draws the child only if its \p damage() is non-zero. You -should call this on all the children if your own damage is equal to -\p FL_DAMAGE_CHILD. Nothing is done if the child is not \p visible() -or if it is clipped. - -\section subclassing_cutnpaste Cut and Paste Support - -FLTK provides routines to cut and paste 8-bit text (in the future this -may be UTF-8) between applications: - -\li Fl::paste() -\li Fl::selection() -\li Fl::selection_owner() - -It may be possible to cut/paste non-text data by using Fl::add_handler(). -Note that handling events beyond those provided by FLTK may be operating -system specific. See \ref osissues for more details. - -\section subclassing_dragndrop Drag And Drop Support - -FLTK provides routines to drag and drop 8-bit text between applications: - -Drag'n'drop operations are initiated by copying data to the -clipboard and calling the function Fl::dnd(). - -Drop attempts are handled via the following events, -already described under \ref events_dnd in a previous chapter: - -\li \p FL_DND_ENTER -\li \p FL_DND_DRAG -\li \p FL_DND_LEAVE -\li \p FL_DND_RELEASE -\li \p FL_PASTE - -\section subclassing_fl_window 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_Window is almost exactly like -subclassing Fl_Group, and in fact you can easily -switch a subclass back and forth. Watch out for the following -differences: - --# Fl_Window is a subclass of Fl_Group so - <I>make sure your constructor calls</I> \p end() - unless you actually want children added to your window. --# When handling events and drawing, the upper-left corner is at - 0,0, not <tt>x(),y()</tt> as in other Fl_Widget'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>. - -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 the -\ref osissues chapter for more information. - - -\htmlonly -<hr> -<table summary="navigation bar" width="100%" border="0"> -<tr> - <td width="45%" align="LEFT"> - <a class="el" href="events.html"> - [Prev] - Handling Events - </a> - </td> - <td width="10%" align="CENTER"> - <a class="el" href="main.html">[Index]</a> - </td> - <td width="45%" align="RIGHT"> - <a class="el" href="opengl.html"> - Using OpenGL - [Next] - </a> - </td> -</tr> -</table> -\endhtmlonly - -*/ |
