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