From 87dd7f0d23eba5c09e71ec6efeb34c6844f5e95f Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Tue, 29 Dec 1998 14:21:17 +0000 Subject: Revised documentation files. git-svn-id: file:///fltk/svn/fltk/trunk@177 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- documentation/subclassing.html | 519 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 519 insertions(+) create mode 100644 documentation/subclassing.html (limited to 'documentation/subclassing.html') diff --git a/documentation/subclassing.html b/documentation/subclassing.html new file mode 100644 index 000000000..414cca67b --- /dev/null +++ b/documentation/subclassing.html @@ -0,0 +1,519 @@ + + + +

5 - Adding and Extending Widgets

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

Subclassing

+ +

Adding Syntax Highlighting to the Fl_Input Widget

+ +

Drawing Functions

+ +

Lines, Rectangles, and Curves, Oh, My!

+ +

Colors

+ +

Fonts

+ +

Images

+ +

Writing a Table Widget

+ +

Methods

+ +

Cut and Paste Support

+ + + +Cut & paste +

Cut & paste

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

void Fl::paste(Fl_Widget *receiver)

void Fl::selection(Fl_Widget *owner, const char *stuff, int len); +

const char* Fl::selection(); +
int Fl::selection_length();

Fl_Widget *Fl::selection_owner() const; +
void Fl::selection_owner(Fl_Widget *);

+ +

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. + +Making a subclass of 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. + +

Parts of this document: + +

+ + +

Constructing your Fl_Widget

+ +I recommend your constructor be of this form: + +

+    Class(int x, int y, int w, int h, const char* label = 0);
+
+ +

This will allow the class name to be typed into fluid and it will produce the correct call. + +

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

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

Protected methods of Fl_Widget

+ +

These methods are provided for subclasses to use. + +

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

void Fl_Widget::set_flag(SHORTCUT_LABEL);

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

void Fl_Widget::x(short); +
void Fl_Widget::y(short); +
void Fl_Widget::w(short); +
void Fl_Widget::h(short);

void Fl_Widget::damage(uchar mask);

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

void Fl_Widget::clear_damage(uchar value = 0);

uchar Fl_Widget::damage()

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

void Fl_Widget::draw_box() const ;

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

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 ;

+ +

virtual int Fl_Widget::handle()

+ +The virtual method int Fl_Widget::handle(int +event) is called to handle each event passed to the widget. +It can:
+ +

Events are identified the small integer argument. Other +information about the most recent event is stored in static locations +and aquired by calling Fl::event_*(). +This other information remains valid until another event is read from +the X server. + +

Here is a sample Fl_Widget::handle(), 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 used the event. +If you return zero it indicates to the parent that it can try sending +another widget the event. + +

It looks like it is best to make the handle() method public. + + +

virtual void Fl_Widget::draw()

+ +

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

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 +all 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()). + +

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_clipped and fl_current_clip +and skipping invisible parts. + +

The functions you can use to draw are described in <FL/fl_draw.H> or any of the protected +Fl_Widget::draw_* methods described above. + + +

virtual void Fl_Widget::resize(int,int,int,int);

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

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

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

Resize should be declared public. + + +

virtual Fl_Widget::~Fl_Widget();

+ +We all know why the destructor must be virtual don't we? Don't forget +to make it public. + + +

Making a Composite/Group Widget

+ +A "composite" widget contains one or more "child" widgets. To do this +you should subclass
Fl_Group (it is +possible to make a composite object that is not a subclass of +Fl_Group, but this is very difficult). + +

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(): + +

+ +

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 (notice that 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(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: + +

+ +

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

void Fl_Group::draw_outside_label(Fl_Widget&) const;

void Fl_Group::draw_child(Fl_Widget&);

void Fl_Group::update_child(Fl_Widget&);

+ + +

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

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, +See here for details. + +

(back to contents) -- cgit v1.2.3