fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Group.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Group.cxx 8184 2011-01-04 18:28:01Z matt $"
00003 //
00004 // Group widget for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 // The Fl_Group is the only defined container type in FLTK.
00029 
00030 // Fl_Window itself is a subclass of this, and most of the event
00031 // handling is designed so windows themselves work correctly.
00032 
00033 #include <stdio.h>
00034 #include <FL/Fl.H>
00035 #include <FL/Fl_Group.H>
00036 #include <FL/Fl_Window.H>
00037 #include <FL/fl_draw.H>
00038 #include <stdlib.h>
00039 
00040 Fl_Group* Fl_Group::current_;
00041 
00042 // Hack: A single child is stored in the pointer to the array, while
00043 // multiple children are stored in an allocated array:
00044 
00049 Fl_Widget*const* Fl_Group::array() const {
00050   return children_ <= 1 ? (Fl_Widget**)(&array_) : array_;
00051 }
00052 
00057 int Fl_Group::find(const Fl_Widget* o) const {
00058   Fl_Widget*const* a = array();
00059   int i; for (i=0; i < children_; i++) if (*a++ == o) break;
00060   return i;
00061 }
00062 
00063 // Metrowerks CodeWarrior and others can't export the static
00064 // class member: current_, so these methods can't be inlined...
00065 
00074 void Fl_Group::begin() {current_ = this;}
00075 
00080 void Fl_Group::end() {current_ = parent();}
00081 
00089 Fl_Group *Fl_Group::current() {return current_;}
00090 
00095 void Fl_Group::current(Fl_Group *g) {current_ = g;}
00096 
00097 extern Fl_Widget* fl_oldfocus; // set by Fl::focus
00098 
00099 // For back-compatibility, we must adjust all events sent to child
00100 // windows so they are relative to that window.
00101 
00102 static int send(Fl_Widget* o, int event) {
00103   if (o->type() < FL_WINDOW) return o->handle(event);
00104   switch ( event )
00105   {
00106   case FL_DND_ENTER: /* FALLTHROUGH */
00107   case FL_DND_DRAG:
00108     // figure out correct type of event:
00109     event = (o->contains(Fl::belowmouse())) ? FL_DND_DRAG : FL_DND_ENTER;
00110   }
00111   int save_x = Fl::e_x; Fl::e_x -= o->x();
00112   int save_y = Fl::e_y; Fl::e_y -= o->y();
00113   int ret = o->handle(event);
00114   Fl::e_y = save_y;
00115   Fl::e_x = save_x;
00116   switch ( event )
00117   {
00118   case FL_ENTER: /* FALLTHROUGH */
00119   case FL_DND_ENTER:
00120     // Successful completion of FL_ENTER means the widget is now the
00121     // belowmouse widget, but only call Fl::belowmouse if the child
00122     // widget did not do so:
00123     if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o);
00124     break;
00125   }
00126   return ret;
00127 }
00128 
00129 // translate the current keystroke into up/down/left/right for navigation:
00130 #define ctrl(x) (x^0x40)
00131 static int navkey() {
00132   switch (Fl::event_key()) {
00133   case 0: // not an FL_KEYBOARD/FL_SHORTCUT event
00134     break;
00135   case FL_Tab:
00136     if (!Fl::event_state(FL_SHIFT)) return FL_Right;
00137     return FL_Left;
00138   case FL_Right:
00139     return FL_Right;
00140   case FL_Left:
00141     return FL_Left;
00142   case FL_Up:
00143     return FL_Up;
00144   case FL_Down:
00145     return FL_Down;
00146   }
00147   return 0;
00148 }
00149 
00150 int Fl_Group::handle(int event) {
00151 
00152   Fl_Widget*const* a = array();
00153   int i;
00154   Fl_Widget* o;
00155 
00156   switch (event) {
00157 
00158   case FL_FOCUS:
00159     switch (navkey()) {
00160     default:
00161       if (savedfocus_ && savedfocus_->take_focus()) return 1;
00162     case FL_Right:
00163     case FL_Down:
00164       for (i = children(); i--;) if ((*a++)->take_focus()) return 1;
00165       break;
00166     case FL_Left:
00167     case FL_Up:
00168       for (i = children(); i--;) if (a[i]->take_focus()) return 1;
00169       break;
00170     }
00171     return 0;
00172 
00173   case FL_UNFOCUS:
00174     savedfocus_ = fl_oldfocus;
00175     return 0;
00176 
00177   case FL_KEYBOARD:
00178     return navigation(navkey());
00179 
00180   case FL_SHORTCUT:
00181     for (i = children(); i--;) {
00182       o = a[i];
00183       if (o->takesevents() && Fl::event_inside(o) && send(o,FL_SHORTCUT))
00184         return 1;
00185     }
00186     for (i = children(); i--;) {
00187       o = a[i];
00188       if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_SHORTCUT))
00189         return 1;
00190     }
00191     if ((Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)) return navigation(FL_Down);
00192     return 0;
00193 
00194   case FL_ENTER:
00195   case FL_MOVE:
00196     for (i = children(); i--;) {
00197       o = a[i];
00198       if (o->visible() && Fl::event_inside(o)) {
00199         if (o->contains(Fl::belowmouse())) {
00200           return send(o,FL_MOVE);
00201         } else {
00202           Fl::belowmouse(o);
00203           if (send(o,FL_ENTER)) return 1;
00204         }
00205       }
00206     }
00207     Fl::belowmouse(this);
00208     return 1;
00209 
00210   case FL_DND_ENTER:
00211   case FL_DND_DRAG:
00212     for (i = children(); i--;) {
00213       o = a[i];
00214       if (o->takesevents() && Fl::event_inside(o)) {
00215         if (o->contains(Fl::belowmouse())) {
00216           return send(o,FL_DND_DRAG);
00217         } else if (send(o,FL_DND_ENTER)) {
00218           if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o);
00219           return 1;
00220         }
00221       }
00222     }
00223     Fl::belowmouse(this);
00224     return 0;
00225 
00226   case FL_PUSH:
00227     for (i = children(); i--;) {
00228       o = a[i];
00229       if (o->takesevents() && Fl::event_inside(o)) {
00230         Fl_Widget_Tracker wp(o);
00231         if (send(o,FL_PUSH)) {
00232           if (Fl::pushed() && wp.exists() && !o->contains(Fl::pushed())) Fl::pushed(o);
00233           return 1;
00234         }
00235       }
00236     }
00237     return 0;
00238 
00239   case FL_RELEASE:
00240   case FL_DRAG:
00241     o = Fl::pushed();
00242     if (o == this) return 0;
00243     else if (o) send(o,event);
00244     else {
00245       for (i = children(); i--;) {
00246         o = a[i];
00247         if (o->takesevents() && Fl::event_inside(o)) {
00248           if (send(o,event)) return 1;
00249         }
00250       }
00251     }
00252     return 0;
00253 
00254   case FL_MOUSEWHEEL:
00255     for (i = children(); i--;) {
00256       o = a[i];
00257       if (o->takesevents() && Fl::event_inside(o) && send(o,FL_MOUSEWHEEL))
00258         return 1;
00259     }
00260     for (i = children(); i--;) {
00261       o = a[i];
00262       if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_MOUSEWHEEL))
00263         return 1;
00264     }
00265     return 0;
00266 
00267   case FL_DEACTIVATE:
00268   case FL_ACTIVATE:
00269     for (i = children(); i--;) {
00270       o = *a++;
00271       if (o->active()) o->handle(event);
00272     }
00273     return 1;
00274 
00275   case FL_SHOW:
00276   case FL_HIDE:
00277     for (i = children(); i--;) {
00278       o = *a++;
00279       if (event == FL_HIDE && o == Fl::focus()) {
00280         // Give up input focus...
00281         int old_event = Fl::e_number;
00282         o->handle(Fl::e_number = FL_UNFOCUS);
00283         Fl::e_number = old_event;
00284         Fl::focus(0);
00285       }
00286       if (o->visible()) o->handle(event);
00287     }
00288     return 1;
00289 
00290   default:
00291     // For all other events, try to give to each child, starting at focus:
00292     for (i = 0; i < children(); i ++)
00293       if (Fl::focus_ == a[i]) break;
00294 
00295     if (i >= children()) i = 0;
00296 
00297     if (children()) {
00298       for (int j = i;;) {
00299         if (a[j]->takesevents()) if (send(a[j], event)) return 1;
00300         j++;
00301         if (j >= children()) j = 0;
00302         if (j == i) break;
00303       }
00304     }
00305 
00306     return 0;
00307   }
00308 }
00309 
00310 //void Fl_Group::focus(Fl_Widget *o) {Fl::focus(o); o->handle(FL_FOCUS);}
00311 
00312 #if 0
00313 const char *nameof(Fl_Widget *o) {
00314   if (!o) return "NULL";
00315   if (!o->label()) return "<no label>";
00316   return o->label();
00317 }
00318 #endif
00319 
00320 // try to move the focus in response to a keystroke:
00321 int Fl_Group::navigation(int key) {
00322   if (children() <= 1) return 0;
00323   int i;
00324   for (i = 0; ; i++) {
00325     if (i >= children_) return 0;
00326     if (array_[i]->contains(Fl::focus())) break;
00327   }
00328   Fl_Widget *previous = array_[i];
00329 
00330   for (;;) {
00331     switch (key) {
00332     case FL_Right:
00333     case FL_Down:
00334       i++;
00335       if (i >= children_) {
00336         if (parent()) return 0;
00337         i = 0;
00338       }
00339       break;
00340     case FL_Left:
00341     case FL_Up:
00342       if (i) i--;
00343       else {
00344         if (parent()) return 0;
00345         i = children_-1;
00346       }
00347       break;
00348     default:
00349       return 0;
00350     }
00351     Fl_Widget* o = array_[i];
00352     if (o == previous) return 0;
00353     switch (key) {
00354     case FL_Down:
00355     case FL_Up:
00356       // for up/down, the widgets have to overlap horizontally:
00357       if (o->x() >= previous->x()+previous->w() ||
00358           o->x()+o->w() <= previous->x()) continue;
00359     }
00360     if (o->take_focus()) return 1;
00361   }
00362 }
00363 
00365 
00366 Fl_Group::Fl_Group(int X,int Y,int W,int H,const char *l)
00367 : Fl_Widget(X,Y,W,H,l) {
00368   align(FL_ALIGN_TOP);
00369   children_ = 0;
00370   array_ = 0;
00371   savedfocus_ = 0;
00372   resizable_ = this;
00373   sizes_ = 0; // this is allocated when first resize() is done
00374   // Subclasses may want to construct child objects as part of their
00375   // constructor, so make sure they are add()'d to this object.
00376   // But you must end() the object!
00377   begin();
00378 }
00379 
00386 void Fl_Group::clear() {
00387   savedfocus_ = 0;
00388   resizable_ = this;
00389   init_sizes();
00390 
00391   // we must change the Fl::pushed() widget, if it is one of
00392   // the group's children. Otherwise fl_fix_focus() would send
00393   // lots of events to children that are about to be deleted
00394   // anyway.
00395 
00396   Fl_Widget *pushed = Fl::pushed();     // save pushed() widget
00397   if (contains(pushed)) pushed = this;  // set it to be the group, if it's a child
00398   Fl::pushed(this);                     // for fl_fix_focus etc.
00399 
00400   // okay, now it is safe to destroy the children:
00401 
00402 #define REVERSE_CHILDREN
00403 #ifdef  REVERSE_CHILDREN
00404   // Reverse the order of the children. Doing this and deleting
00405   // always the last child is much faster than the other way around.
00406   if (children_ > 1) {
00407     Fl_Widget *temp;
00408     Fl_Widget **a = (Fl_Widget**)array();
00409     for (int i=0,j=children_-1; i<children_/2; i++,j--) {
00410       temp = a[i];
00411       a[i] = a[j];
00412       a[j] = temp;
00413     }
00414   }
00415 #endif // REVERSE_CHILDREN
00416 
00417   while (children_) {                   // delete all children
00418     int idx = children_-1;              // last child's index
00419     Fl_Widget* w = child(idx);          // last child widget
00420     if (w->parent()==this) {            // should always be true
00421       if (children_>2) {                // optimized removal
00422         w->parent_ = 0;                 // reset child's parent
00423         children_--;                    // update counter
00424       } else {                          // slow removal
00425         remove(idx);
00426       }
00427       delete w;                         // delete the child
00428     } else {                            // should never happen
00429       remove(idx);                      // remove it anyway
00430     }
00431   }
00432 
00433   if (pushed != this) Fl::pushed(pushed); // reset pushed() widget
00434 
00435 }
00436 
00451 Fl_Group::~Fl_Group() {
00452   clear();
00453 }
00454 
00461 void Fl_Group::insert(Fl_Widget &o, int index) {
00462   if (o.parent()) {
00463     Fl_Group* g = o.parent();
00464     int n = g->find(o);
00465     if (g == this) {
00466       if (index > n) index--;
00467       if (index == n) return;
00468     }
00469     g->remove(n);
00470   }
00471   o.parent_ = this;
00472   if (children_ == 0) { // use array pointer to point at single child
00473     array_ = (Fl_Widget**)&o;
00474   } else if (children_ == 1) { // go from 1 to 2 children
00475     Fl_Widget* t = (Fl_Widget*)array_;
00476     array_ = (Fl_Widget**)malloc(2*sizeof(Fl_Widget*));
00477     if (index) {array_[0] = t; array_[1] = &o;}
00478     else {array_[0] = &o; array_[1] = t;}
00479   } else {
00480     if (!(children_ & (children_-1))) // double number of children
00481       array_ = (Fl_Widget**)realloc((void*)array_,
00482                                     2*children_*sizeof(Fl_Widget*));
00483     int j; for (j = children_; j > index; j--) array_[j] = array_[j-1];
00484     array_[j] = &o;
00485   }
00486   children_++;
00487   init_sizes();
00488 }
00489 
00494 void Fl_Group::add(Fl_Widget &o) {insert(o, children_);}
00495 
00506 void Fl_Group::remove(int index) {
00507   if (index < 0 || index >= children_) return;
00508   Fl_Widget &o = *child(index);
00509   if (&o == savedfocus_) savedfocus_ = 0;
00510   if (o.parent_ == this) {      // this should always be true
00511     o.parent_ = 0;
00512   } 
00513 
00514   // remove the widget from the group
00515 
00516   children_--;
00517   if (children_ == 1) { // go from 2 to 1 child
00518     Fl_Widget *t = array_[!index];
00519     free((void*)array_);
00520     array_ = (Fl_Widget**)t;
00521   } else if (children_ > 1) { // delete from array
00522     for (; index < children_; index++) array_[index] = array_[index+1];
00523   }
00524   init_sizes();
00525 }
00526 
00540 void Fl_Group::remove(Fl_Widget &o) {
00541   if (!children_) return;
00542   int i = find(o);
00543   if (i < children_) remove(i);
00544 }
00545 
00547 
00548 // Rather lame kludge here, I need to detect windows and ignore the
00549 // changes to X,Y, since all children are relative to X,Y.  That
00550 // is why I check type():
00551 
00552 // sizes array stores the initial positions of widgets as
00553 // left,right,top,bottom quads.  The first quad is the group, the
00554 // second is the resizable (clipped to the group), and the
00555 // rest are the children.  This is a convenient order for the
00556 // algorithm.  If you change this be sure to fix Fl_Tile which
00557 // also uses this array!
00558 
00575 void Fl_Group::init_sizes() {
00576   delete[] sizes_; sizes_ = 0;
00577 }
00578 
00593 int* Fl_Group::sizes() {
00594   if (!sizes_) {
00595     int* p = sizes_ = new int[4*(children_+2)];
00596     // first thing in sizes array is the group's size:
00597     if (type() < FL_WINDOW) {p[0] = x(); p[2] = y();} else {p[0] = p[2] = 0;}
00598     p[1] = p[0]+w(); p[3] = p[2]+h();
00599     // next is the resizable's size:
00600     p[4] = p[0]; // init to the group's size
00601     p[5] = p[1];
00602     p[6] = p[2];
00603     p[7] = p[3];
00604     Fl_Widget* r = resizable();
00605     if (r && r != this) { // then clip the resizable to it
00606       int t;
00607       t = r->x(); if (t > p[0]) p[4] = t;
00608       t +=r->w(); if (t < p[1]) p[5] = t;
00609       t = r->y(); if (t > p[2]) p[6] = t;
00610       t +=r->h(); if (t < p[3]) p[7] = t;
00611     }
00612     // next is all the children's sizes:
00613     p += 8;
00614     Fl_Widget*const* a = array();
00615     for (int i=children_; i--;) {
00616       Fl_Widget* o = *a++;
00617       *p++ = o->x();
00618       *p++ = o->x()+o->w();
00619       *p++ = o->y();
00620       *p++ = o->y()+o->h();
00621     }
00622   }
00623   return sizes_;
00624 }
00625 
00637 void Fl_Group::resize(int X, int Y, int W, int H) {
00638 
00639   int dx = X-x();
00640   int dy = Y-y();
00641   int dw = W-w();
00642   int dh = H-h();
00643   
00644   int *p = sizes(); // save initial sizes and positions
00645 
00646   Fl_Widget::resize(X,Y,W,H); // make new xywh values visible for children
00647 
00648   if (!resizable() || (dw==0 && dh==0) ) {
00649 
00650     if (type() < FL_WINDOW) {
00651       Fl_Widget*const* a = array();
00652       for (int i=children_; i--;) {
00653         Fl_Widget* o = *a++;
00654         o->resize(o->x()+dx, o->y()+dy, o->w(), o->h());
00655       }
00656     }
00657 
00658   } else if (children_) {
00659 
00660     // get changes in size/position from the initial size:
00661     dx = X - p[0];
00662     dw = W - (p[1]-p[0]);
00663     dy = Y - p[2];
00664     dh = H - (p[3]-p[2]);
00665     if (type() >= FL_WINDOW) dx = dy = 0;
00666     p += 4;
00667 
00668     // get initial size of resizable():
00669     int IX = *p++;
00670     int IR = *p++;
00671     int IY = *p++;
00672     int IB = *p++;
00673 
00674     Fl_Widget*const* a = array();
00675     for (int i=children_; i--;) {
00676       Fl_Widget* o = *a++;
00677 #if 1
00678       int XX = *p++;
00679       if (XX >= IR) XX += dw;
00680       else if (XX > IX) XX = IX+((XX-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX);
00681       int R = *p++;
00682       if (R >= IR) R += dw;
00683       else if (R > IX) R = IX+((R-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX);
00684 
00685       int YY = *p++;
00686       if (YY >= IB) YY += dh;
00687       else if (YY > IY) YY = IY+((YY-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY);
00688       int B = *p++;
00689       if (B >= IB) B += dh;
00690       else if (B > IY) B = IY+((B-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY);
00691 #else // much simpler code from Francois Ostiguy:
00692       int XX = *p++;
00693       if (XX >= IR) XX += dw;
00694       else if (XX > IX) XX += dw * (XX-IX)/(IR-IX);
00695       int R = *p++;
00696       if (R >= IR) R += dw;
00697       else if (R > IX) R = R + dw * (R-IX)/(IR-IX);
00698 
00699       int YY = *p++;
00700       if (YY >= IB) YY += dh;
00701       else if (YY > IY) YY = YY + dh*(YY-IY)/(IB-IY);
00702       int B = *p++;
00703       if (B >= IB) B += dh;
00704       else if (B > IY) B = B + dh*(B-IY)/(IB-IY);
00705 #endif
00706       o->resize(XX+dx, YY+dy, R-XX, B-YY);
00707     }
00708   }
00709 }
00710 
00718 void Fl_Group::draw_children() {
00719   Fl_Widget*const* a = array();
00720 
00721   if (clip_children()) {
00722     fl_push_clip(x() + Fl::box_dx(box()),
00723                  y() + Fl::box_dy(box()),
00724                  w() - Fl::box_dw(box()),
00725                  h() - Fl::box_dh(box()));
00726   }
00727 
00728   if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing:
00729     for (int i=children_; i--;) {
00730       Fl_Widget& o = **a++;
00731       draw_child(o);
00732       draw_outside_label(o);
00733     }
00734   } else {      // only redraw the children that need it:
00735     for (int i=children_; i--;) update_child(**a++);
00736   }
00737 
00738   if (clip_children()) fl_pop_clip();
00739 }
00740 
00741 void Fl_Group::draw() {
00742   if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing:
00743     draw_box();
00744     draw_label();
00745   }
00746   draw_children();
00747 }
00748 
00757 void Fl_Group::update_child(Fl_Widget& widget) const {
00758   if (widget.damage() && widget.visible() && widget.type() < FL_WINDOW &&
00759       fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) {
00760     widget.draw();      
00761     widget.clear_damage();
00762   }
00763 }
00764 
00771 void Fl_Group::draw_child(Fl_Widget& widget) const {
00772   if (widget.visible() && widget.type() < FL_WINDOW &&
00773       fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) {
00774     widget.clear_damage(FL_DAMAGE_ALL);
00775     widget.draw();
00776     widget.clear_damage();
00777   }
00778 }
00779 
00780 extern char fl_draw_shortcut;
00781 
00783 void Fl_Group::draw_outside_label(const Fl_Widget& widget) const {
00784   if (!widget.visible()) return;
00785   // skip any labels that are inside the widget:
00786   if (!(widget.align()&15) || (widget.align() & FL_ALIGN_INSIDE)) return;
00787   // invent a box that is outside the widget:
00788   Fl_Align a = widget.align();
00789   int X = widget.x();
00790   int Y = widget.y();
00791   int W = widget.w();
00792   int H = widget.h();
00793   int wx, wy;
00794   if (const_cast<Fl_Group*>(this)->as_window()) {
00795     wx = wy = 0;
00796   } else {
00797     wx = x(); wy = y();
00798   }
00799   if ( (a & 0x0f) == FL_ALIGN_LEFT_TOP ) {
00800     a = (a &~0x0f ) | FL_ALIGN_TOP_RIGHT;
00801     X = wx;
00802     W = widget.x()-X-3;
00803   } else if ( (a & 0x0f) == FL_ALIGN_LEFT_BOTTOM ) {
00804     a = (a &~0x0f ) | FL_ALIGN_BOTTOM_RIGHT; 
00805     X = wx;
00806     W = widget.x()-X-3;
00807   } else if ( (a & 0x0f) == FL_ALIGN_RIGHT_TOP ) {
00808     a = (a &~0x0f ) | FL_ALIGN_TOP_LEFT; 
00809     X = X+W+3;
00810     W = wx+this->w()-X;
00811   } else if ( (a & 0x0f) == FL_ALIGN_RIGHT_BOTTOM ) {
00812     a = (a &~0x0f ) | FL_ALIGN_BOTTOM_LEFT; 
00813     X = X+W+3;
00814     W = wx+this->w()-X;
00815   } else if (a & FL_ALIGN_TOP) {
00816     a ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP);
00817     Y = wy;
00818     H = widget.y()-Y;
00819   } else if (a & FL_ALIGN_BOTTOM) {
00820     a ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP);
00821     Y = Y+H;
00822     H = wy+h()-Y;
00823   } else if (a & FL_ALIGN_LEFT) {
00824     a ^= (FL_ALIGN_LEFT|FL_ALIGN_RIGHT);
00825     X = wx;
00826     W = widget.x()-X-3;
00827   } else if (a & FL_ALIGN_RIGHT) {
00828     a ^= (FL_ALIGN_LEFT|FL_ALIGN_RIGHT);
00829     X = X+W+3;
00830     W = wx+this->w()-X;
00831   }
00832   widget.draw_label(X,Y,W,H,(Fl_Align)a);
00833 }
00834 
00835 //
00836 // End of "$Id: Fl_Group.cxx 8184 2011-01-04 18:28:01Z matt $".
00837 //