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. >
>MyClass(int x, int y, int w, int h, const char *label = 0); >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: >
>MyClass::MyClass(int x, int y, int w, int h, const char *label)
>: Fl_Widget(x, y, w, h, label) {
>// do initialization stuff...
>}
>
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); >
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: >
>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();
>}
>
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. >
The >second >version >lets >you >do >this >test > against >an >arbitrary > string. >
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). >
Here >is >a >sample >handle()> method >for >a > widget >that >acts >as > a >pushbutton >and >also > accepts >the >keystroke >'x' >to >cause >the >callback: >
>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);
> }
>}
>
You >must >return >non-zero >if >your >handle()>
method >uses >the > event. >If >you >return >zero >it >
indicates >to >the >parent >widget >that >it >can > try >
sending >the >event >to >another >widget. >
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). >
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>. >
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. >
Instances >of >the >child >widgets >may >be >included > in >the >parent: >
>class MyClass : public Fl_Group {
> Fl_Button the_button;
> Fl_Slider the_slider;
> ...
>};
>
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:>
>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!
>}
>
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: >
>void MyClass::slider_cb(Fl_Widget* v, void *) { // static method
> ((MyClass*)(v->parent())->slider_cb();
>}
>void MyClass::slider_cb() { // normal method
> use(the_slider->value());
>}
>
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: >
>int MyClass::handle(int event) {
> if (Fl_Group::handle(event)) return 1;
> ... handle events that children don't want ...
>}
>
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: >
>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 want to do this
> }
> }
>}
>
Fl_Group> provides >some >protected >methods >to >
make >drawing > easier: >
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: >