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_Type.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Group_Type.cxx 8172 2011-01-03 08:28:38Z matt $"
00003 //
00004 // Fl_Group object code for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Object describing an Fl_Group and links to Fl_Window_Type.C and
00007 // the Fl_Tabs widget, with special stuff to select tab items and
00008 // insure that only one is visible.
00009 //
00010 // Copyright 1998-2010 by Bill Spitzak and others.
00011 //
00012 // This library is free software; you can redistribute it and/or
00013 // modify it under the terms of the GNU Library General Public
00014 // License as published by the Free Software Foundation; either
00015 // version 2 of the License, or (at your option) any later version.
00016 //
00017 // This library is distributed in the hope that it will be useful,
00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // Library General Public License for more details.
00021 //
00022 // You should have received a copy of the GNU Library General Public
00023 // License along with this library; if not, write to the Free Software
00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00025 // USA.
00026 //
00027 // Please report all bugs and problems on the following page:
00028 //
00029 //     http://www.fltk.org/str.php
00030 //
00031 
00032 
00033 #include <FL/Fl.H>
00034 #include <FL/Fl_Group.H>
00035 #include <FL/Fl_Table.H>
00036 #include <FL/fl_message.H>
00037 #include "Fl_Widget_Type.h"
00038 #include "../src/flstring.h"
00039 
00040 // Override group's resize behavior to do nothing to children:
00041 void igroup::resize(int X, int Y, int W, int H) {
00042   Fl_Widget::resize(X,Y,W,H);
00043   redraw();
00044 }
00045 
00046 Fl_Group_Type Fl_Group_type;    // the "factory"
00047 
00048 Fl_Type *Fl_Group_Type::make() {
00049   return Fl_Widget_Type::make();
00050 }
00051 
00052 void fix_group_size(Fl_Type *tt) {
00053   if (!tt || !tt->is_group()) return;
00054   Fl_Group_Type* t = (Fl_Group_Type*)tt;
00055   int X = t->o->x();
00056   int Y = t->o->y();
00057   int R = X+t->o->w();
00058   int B = Y+t->o->h();
00059   for (Fl_Type *nn = t->next; nn && nn->level > t->level; nn = nn->next) {
00060     if (!nn->is_widget() || nn->is_menu_item()) continue;
00061     Fl_Widget_Type* n = (Fl_Widget_Type*)nn;
00062     int x = n->o->x();  if (x < X) X = x;
00063     int y = n->o->y();  if (y < Y) Y = y;
00064     int r = x+n->o->w();if (r > R) R = r;
00065     int b = y+n->o->h();if (b > B) B = b;
00066   }
00067   t->o->resize(X,Y,R-X,B-Y);
00068 }
00069 
00070 extern int force_parent;
00071 
00072 void group_cb(Fl_Widget *, void *) {
00073   // Find the current widget:
00074   Fl_Type *qq = Fl_Type::current;
00075   while (qq && (!qq->is_widget() || qq->is_menu_item())) qq = qq->parent;
00076   if (!qq || qq->level < 1 || (qq->level == 1 && !strcmp(qq->type_name(), "widget_class"))) {
00077     fl_message("Please select widgets to group");
00078     return;
00079   }
00080   Fl_Widget_Type* q = (Fl_Widget_Type*)qq;
00081   force_parent = 1;
00082   Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make());
00083   n->move_before(q);
00084   n->o->resize(q->o->x(),q->o->y(),q->o->w(),q->o->h());
00085   for (Fl_Type *t = Fl_Type::first; t;) {
00086     if (t->level != n->level || t == n || !t->selected) {
00087       t = t->next; continue;}
00088     Fl_Type *nxt = t->remove();
00089     t->add(n);
00090     t = nxt;
00091   }
00092   fix_group_size(n);
00093 }
00094 
00095 void ungroup_cb(Fl_Widget *, void *) {
00096   // Find the group:
00097   Fl_Type *q = Fl_Type::current;
00098   while (q && (!q->is_widget() || q->is_menu_item())) q = q->parent;
00099   if (q) q = q->parent;
00100   if (!q || q->level < 1 || (q->level == 1 && !strcmp(q->type_name(), "widget_class"))) {
00101     fl_message("Please select widgets in a group");
00102     return;
00103   }
00104   Fl_Type* n;
00105   for (n = q->next; n && n->level > q->level; n = n->next) {
00106     if (n->level == q->level+1 && !n->selected) {
00107       fl_message("Please select all widgets in group");
00108       return;
00109     }
00110   }
00111   for (n = q->next; n && n->level > q->level;) {
00112     Fl_Type *nxt = n->remove();
00113     n->insert(q);
00114     n = nxt;
00115   }
00116   delete q;
00117 }
00118 
00120 
00121 #include <stdio.h>
00122 
00123 void Fl_Group_Type::write_code1() {
00124   Fl_Widget_Type::write_code1();
00125 }
00126 
00127 void Fl_Group_Type::write_code2() {
00128   const char *var = name() ? name() : "o";
00129   write_extra_code();
00130   write_c("%s%s->end();\n", indent(), var);
00131   if (resizable()) {
00132     write_c("%sFl_Group::current()->resizable(%s);\n", indent(), var);
00133   }
00134   write_block_close();
00135 }
00136 
00138 
00139 const char pack_type_name[] = "Fl_Pack";
00140 
00141 Fl_Menu_Item pack_type_menu[] = {
00142   {"HORIZONTAL", 0, 0, (void*)Fl_Pack::HORIZONTAL},
00143   {"VERTICAL", 0, 0, (void*)Fl_Pack::VERTICAL},
00144   {0}};
00145 
00146 Fl_Pack_Type Fl_Pack_type;      // the "factory"
00147 
00149 
00150 static const int MAX_ROWS = 14;
00151 static const int MAX_COLS = 7;
00152 
00153 // this is a minimal table widget used as an example when adding tables in Fluid
00154 class Fluid_Table : public Fl_Table {
00155   int data[MAX_ROWS][MAX_COLS];         // data array for cells
00156   
00157   // Draw the row/col headings
00158   //    Make this a dark thin upbox with the text inside.
00159   //
00160   void DrawHeader(const char *s, int X, int Y, int W, int H) {
00161     fl_push_clip(X,Y,W,H);
00162     fl_draw_box(FL_THIN_UP_BOX, X,Y,W,H, row_header_color());
00163     fl_color(FL_BLACK);
00164     fl_draw(s, X,Y,W,H, FL_ALIGN_CENTER);
00165     fl_pop_clip();
00166   } 
00167   // Draw the cell data
00168   //    Dark gray text on white background with subtle border
00169   //
00170   void DrawData(const char *s, int X, int Y, int W, int H) {
00171     fl_push_clip(X,Y,W,H);
00172     // Draw cell bg
00173     fl_color(FL_WHITE); fl_rectf(X,Y,W,H);
00174     // Draw cell data
00175     fl_color(FL_GRAY0); fl_draw(s, X,Y,W,H, FL_ALIGN_CENTER);
00176     // Draw box border
00177     fl_color(color()); fl_rect(X,Y,W,H);
00178     fl_pop_clip();
00179   } 
00180   // Handle drawing table's cells
00181   //     Fl_Table calls this function to draw each visible cell in the table.
00182   //     It's up to us to use FLTK's drawing functions to draw the cells the way we want.
00183   //
00184   void draw_cell(TableContext context, int ROW=0, int COL=0, int X=0, int Y=0, int W=0, int H=0) {
00185     static char s[40];
00186     switch ( context ) {
00187       case CONTEXT_STARTPAGE:                   // before page is drawn..
00188         fl_font(FL_HELVETICA, 16);              // set the font for our drawing operations
00189         return; 
00190       case CONTEXT_COL_HEADER:                  // Draw column headers
00191         sprintf(s,"%c",'A'+COL);                // "A", "B", "C", etc.
00192         DrawHeader(s,X,Y,W,H);
00193         return; 
00194       case CONTEXT_ROW_HEADER:                  // Draw row headers
00195         sprintf(s,"%03d:",ROW);                 // "001:", "002:", etc
00196         DrawHeader(s,X,Y,W,H);
00197         return; 
00198       case CONTEXT_CELL:                        // Draw data in cells
00199         sprintf(s,"%d",data[ROW][COL]);
00200         DrawData(s,X,Y,W,H);
00201         return;
00202       default:
00203         return;
00204     }
00205   }
00206 public:
00207   Fluid_Table(int x, int y, int w, int h, const char *l=0L)
00208   : Fl_Table(x, y, w, h, l) {
00209     for ( int r=0; r<MAX_ROWS; r++ )
00210       for ( int c=0; c<MAX_COLS; c++ )
00211         data[r][c] = 1000+(r*1000)+c;
00212     // Rows
00213     rows(MAX_ROWS);             // how many rows
00214     row_header(1);              // enable row headers (along left)
00215     row_height_all(20);         // default height of rows
00216     row_resize(0);              // disable row resizing                                // Cols
00217     cols(MAX_COLS);             // how many columns
00218     col_header(1);              // enable column headers (along top)
00219     col_width_all(80);          // default width of columns
00220     col_resize(1);              // enable column resizing
00221   }
00222 };
00223 
00224 const char table_type_name[] = "Fl_Table";
00225 
00226 Fl_Table_Type Fl_Table_type;    // the "factory"
00227 
00228 Fl_Widget *Fl_Table_Type::widget(int X,int Y,int W,int H) {
00229   Fluid_Table *table = new Fluid_Table(X, Y, W, H);
00230   return table;
00231 }
00232 
00234 
00235 const char tabs_type_name[] = "Fl_Tabs";
00236 
00237 // Override group's resize behavior to do nothing to children:
00238 void itabs::resize(int X, int Y, int W, int H) {
00239   Fl_Widget::resize(X,Y,W,H);
00240   redraw();
00241 }
00242 
00243 Fl_Tabs_Type Fl_Tabs_type;      // the "factory"
00244 
00245 // This is called when user clicks on a widget in the window.  See
00246 // if it is a tab title, and adjust visibility and return new selection:
00247 // If none, return o unchanged:
00248 
00249 Fl_Type* Fl_Tabs_Type::click_test(int x, int y) {
00250   Fl_Tabs *t = (Fl_Tabs*)o;
00251   Fl_Widget *a = t->which(x,y);
00252   if (!a) return 0; // didn't click on tab
00253   // changing the visible tab has an impact on the generated
00254   // source code, so mark this project as changed.
00255   int changed = (a!=t->value());
00256   // okay, run the tabs ui until they let go of mouse:
00257   t->handle(FL_PUSH);
00258   Fl::pushed(t);
00259   while (Fl::pushed()==t) Fl::wait();
00260   if (changed) set_modflag(1);
00261   return (Fl_Type*)(t->value()->user_data());
00262 }
00263 
00265 
00266 const char wizard_type_name[] = "Fl_Wizard";
00267 
00268 // Override group's resize behavior to do nothing to children:
00269 void iwizard::resize(int X, int Y, int W, int H) {
00270   Fl_Widget::resize(X,Y,W,H);
00271   redraw();
00272 }
00273 
00274 Fl_Wizard_Type Fl_Wizard_type;  // the "factory"
00275 
00276 // This is called when o is created.  If it is in the tab group make
00277 // sure it is visible:
00278 
00279 void Fl_Group_Type::add_child(Fl_Type* cc, Fl_Type* before) {
00280   Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
00281   Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
00282   ((Fl_Group*)o)->insert(*(c->o), b);
00283   o->redraw();
00284 }
00285 
00286 void Fl_Tabs_Type::add_child(Fl_Type* c, Fl_Type* before) {
00287   Fl_Group_Type::add_child(c, before);
00288 }
00289 
00290 void Fl_Table_Type::add_child(Fl_Type* cc, Fl_Type* before) {
00291   Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
00292   Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
00293   if (((Fl_Table*)o)->children()==1) { // the FLuid_Table has one extra child
00294     fl_message("Inserting child widgets into an Fl_Table is not recommended.\n"
00295                "Please refer to the documentation on Fl_Table.");
00296   }
00297   ((Fl_Table*)o)->insert(*(c->o), b);
00298   o->redraw();
00299 }
00300 
00301 
00302 // This is called when o is deleted.  If it is in the tab group make
00303 // sure it is not visible:
00304 
00305 void Fl_Group_Type::remove_child(Fl_Type* cc) {
00306   Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
00307   ((Fl_Group*)o)->remove(c->o);
00308   o->redraw();
00309 }
00310 
00311 void Fl_Tabs_Type::remove_child(Fl_Type* cc) {
00312   Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
00313   Fl_Tabs *t = (Fl_Tabs*)o;
00314   if (t->value() == c->o) t->value(0);
00315   Fl_Group_Type::remove_child(c);
00316 }
00317 
00318 void Fl_Table_Type::remove_child(Fl_Type* cc) {
00319   Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
00320   ((Fl_Table*)o)->remove(*(c->o));
00321   o->redraw();
00322 }
00323 
00324 // move, don't change selected value:
00325 
00326 void Fl_Group_Type::move_child(Fl_Type* cc, Fl_Type* before) {
00327   Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
00328   Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
00329   ((Fl_Group*)o)->remove(c->o);
00330   ((Fl_Group*)o)->insert(*(c->o), b);
00331   o->redraw();
00332 }
00333 
00334 void Fl_Table_Type::move_child(Fl_Type* cc, Fl_Type* before) {
00335   Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
00336   Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
00337   ((Fl_Table*)o)->remove(*(c->o));
00338   ((Fl_Table*)o)->insert(*(c->o), b);
00339   o->redraw();
00340 }
00341 
00343 // live mode support
00344 
00345 Fl_Widget *Fl_Group_Type::enter_live_mode(int) {
00346   Fl_Group *grp = new Fl_Group(o->x(), o->y(), o->w(), o->h());
00347   live_widget = grp;
00348   if (live_widget) {
00349     copy_properties();
00350     Fl_Type *n;
00351     for (n = next; n && n->level > level; n = n->next) {
00352       if (n->level == level+1)
00353         n->enter_live_mode();
00354     }
00355     grp->end();
00356   }
00357   return live_widget;
00358 }
00359 
00360 Fl_Widget *Fl_Tabs_Type::enter_live_mode(int) {
00361   Fl_Tabs *grp = new Fl_Tabs(o->x(), o->y(), o->w(), o->h());
00362   live_widget = grp;
00363   if (live_widget) {
00364     copy_properties();
00365     Fl_Type *n;
00366     for (n = next; n && n->level > level; n = n->next) {
00367       if (n->level == level+1)
00368         n->enter_live_mode();
00369     }
00370     grp->end();
00371   }
00372   grp->value(((Fl_Tabs*)o)->value());
00373   return live_widget;
00374 }
00375 
00376 Fl_Widget *Fl_Table_Type::enter_live_mode(int) {
00377   Fl_Group *grp = new Fluid_Table(o->x(), o->y(), o->w(), o->h());
00378   live_widget = grp;
00379   if (live_widget) {
00380     copy_properties();
00381     grp->end();
00382   }
00383   return live_widget;
00384 }
00385 
00386 void Fl_Group_Type::leave_live_mode() {
00387 }
00388 
00392 void Fl_Group_Type::copy_properties() {
00393   Fl_Widget_Type::copy_properties();
00394 }
00395 
00397 // some other group subclasses that fluid does not treat specially:
00398 
00399 #include <FL/Fl_Scroll.H>
00400 
00401 const char scroll_type_name[] = "Fl_Scroll";
00402 
00403 Fl_Widget *Fl_Scroll_Type::enter_live_mode(int) {
00404   Fl_Group *grp = new Fl_Scroll(o->x(), o->y(), o->w(), o->h());
00405   grp->show();
00406   live_widget = grp;
00407   if (live_widget) {
00408     copy_properties();
00409     Fl_Type *n;
00410     for (n = next; n && n->level > level; n = n->next) {
00411       if (n->level == level+1)
00412         n->enter_live_mode();
00413     }
00414     grp->end();
00415   }
00416   return live_widget;
00417 }
00418 
00419 Fl_Menu_Item scroll_type_menu[] = {
00420   {"BOTH", 0, 0, 0/*(void*)Fl_Scroll::BOTH*/},
00421   {"HORIZONTAL", 0, 0, (void*)Fl_Scroll::HORIZONTAL},
00422   {"VERTICAL", 0, 0, (void*)Fl_Scroll::VERTICAL},
00423   {"HORIZONTAL_ALWAYS", 0, 0, (void*)Fl_Scroll::HORIZONTAL_ALWAYS},
00424   {"VERTICAL_ALWAYS", 0, 0, (void*)Fl_Scroll::VERTICAL_ALWAYS},
00425   {"BOTH_ALWAYS", 0, 0, (void*)Fl_Scroll::BOTH_ALWAYS},
00426   {0}};
00427 
00428 Fl_Scroll_Type Fl_Scroll_type;  // the "factory"
00429 
00430 void Fl_Scroll_Type::copy_properties() {
00431   Fl_Group_Type::copy_properties();
00432   Fl_Scroll *s = (Fl_Scroll*)o, *d = (Fl_Scroll*)live_widget;
00433   d->position(s->xposition(), s->yposition());
00434   d->type(s->type()); // TODO: get this flag from Fl_Scroll_Type!
00435   d->scrollbar.align(s->scrollbar.align());
00436   d->hscrollbar.align(s->hscrollbar.align());
00437 }
00438 
00440 
00441 const char tile_type_name[] = "Fl_Tile";
00442 
00443 Fl_Tile_Type Fl_Tile_type;      // the "factory"
00444 
00445 void Fl_Tile_Type::copy_properties() {
00446   Fl_Group_Type::copy_properties();
00447   // no additional properties
00448 }
00449 
00450 //
00451 // End of "$Id: Fl_Group_Type.cxx 8172 2011-01-03 08:28:38Z matt $".
00452 //