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

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Type.cxx 8172 2011-01-03 08:28:38Z matt $"
00003 //
00004 // Widget type code for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Each object described by Fluid is one of these objects.  They
00007 // are all stored in a double-linked list.
00008 //
00009 // They "type" of the object is covered by the virtual functions.
00010 // There will probably be a lot of these virtual functions.
00011 //
00012 // The type browser is also a list of these objects, but they
00013 // are "factory" instances, not "real" ones.  These objects exist
00014 // only so the "make" method can be called on them.  They are
00015 // not in the linked list and are not written to files or
00016 // copied or otherwise examined.
00017 //
00018 // Copyright 1998-2010 by Bill Spitzak and others.
00019 //
00020 // This library is free software; you can redistribute it and/or
00021 // modify it under the terms of the GNU Library General Public
00022 // License as published by the Free Software Foundation; either
00023 // version 2 of the License, or (at your option) any later version.
00024 //
00025 // This library is distributed in the hope that it will be useful,
00026 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00028 // Library General Public License for more details.
00029 //
00030 // You should have received a copy of the GNU Library General Public
00031 // License along with this library; if not, write to the Free Software
00032 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00033 // USA.
00034 //
00035 // Please report all bugs and problems on the following page:
00036 //
00037 //     http://www.fltk.org/str.php
00038 //
00039 
00040 #include <FL/Fl.H>
00041 #include <FL/Fl_Browser_.H>
00042 #include <FL/fl_draw.H>
00043 #include <stdlib.h>
00044 #include "../src/flstring.h"
00045 #include <stdio.h>
00046 
00047 #include "Fl_Type.h"
00048 #include "undo.h"
00049 
00050 #include <FL/Fl_Pixmap.H>
00051 #include "pixmaps/lock.xpm"
00052 #include "pixmaps/protected.xpm"
00053 //#include "pixmaps/unlock.xpm"
00054 
00055 static Fl_Pixmap        lock_pixmap(lock_xpm);
00056 static Fl_Pixmap        protected_pixmap(protected_xpm);
00057 //static Fl_Pixmap      unlock_pixmap(unlock_xpm);
00058 
00059 #include "pixmaps/flWindow.xpm"
00060 #include "pixmaps/flButton.xpm"
00061 #include "pixmaps/flCheckButton.xpm"
00062 #include "pixmaps/flRoundButton.xpm"
00063 #include "pixmaps/flBox.xpm"
00064 #include "pixmaps/flGroup.xpm"
00065 #include "pixmaps/flFunction.xpm"
00066 #include "pixmaps/flCode.xpm"
00067 #include "pixmaps/flCodeBlock.xpm"
00068 #include "pixmaps/flComment.xpm"
00069 #include "pixmaps/flData.xpm"
00070 #include "pixmaps/flDeclaration.xpm"
00071 #include "pixmaps/flDeclarationBlock.xpm"
00072 #include "pixmaps/flClass.xpm"
00073 #include "pixmaps/flTabs.xpm"
00074 #include "pixmaps/flInput.xpm"
00075 #include "pixmaps/flChoice.xpm"
00076 #include "pixmaps/flMenuitem.xpm"
00077 #include "pixmaps/flMenubar.xpm"
00078 #include "pixmaps/flSubmenu.xpm"
00079 #include "pixmaps/flScroll.xpm"
00080 #include "pixmaps/flTile.xpm"
00081 #include "pixmaps/flWizard.xpm"
00082 #include "pixmaps/flPack.xpm"
00083 #include "pixmaps/flReturnButton.xpm"
00084 #include "pixmaps/flLightButton.xpm"
00085 #include "pixmaps/flRepeatButton.xpm"
00086 #include "pixmaps/flMenuButton.xpm"
00087 #include "pixmaps/flOutput.xpm"
00088 #include "pixmaps/flTextDisplay.xpm"
00089 #include "pixmaps/flTextEdit.xpm"
00090 #include "pixmaps/flFileInput.xpm"
00091 #include "pixmaps/flBrowser.xpm"
00092 #include "pixmaps/flCheckBrowser.xpm"
00093 #include "pixmaps/flFileBrowser.xpm"
00094 #include "pixmaps/flClock.xpm"
00095 #include "pixmaps/flHelp.xpm"
00096 #include "pixmaps/flProgress.xpm"
00097 #include "pixmaps/flSlider.xpm"
00098 #include "pixmaps/flScrollBar.xpm"
00099 #include "pixmaps/flValueSlider.xpm"
00100 #include "pixmaps/flAdjuster.xpm"
00101 #include "pixmaps/flCounter.xpm"
00102 #include "pixmaps/flDial.xpm"
00103 #include "pixmaps/flRoller.xpm"
00104 #include "pixmaps/flValueInput.xpm"
00105 #include "pixmaps/flValueOutput.xpm"
00106 #include "pixmaps/flSpinner.xpm"
00107 #include "pixmaps/flWidgetClass.xpm"
00108 #include "pixmaps/flTree.xpm"
00109 #include "pixmaps/flTable.xpm"
00110 
00111 static Fl_Pixmap        window_pixmap(flWindow_xpm);
00112 static Fl_Pixmap        button_pixmap(flButton_xpm);
00113 static Fl_Pixmap        checkbutton_pixmap(flCheckButton_xpm);
00114 static Fl_Pixmap        roundbutton_pixmap(flRoundButton_xpm);
00115 static Fl_Pixmap        box_pixmap(flBox_xpm);
00116 static Fl_Pixmap        group_pixmap(flGroup_xpm);
00117 static Fl_Pixmap        function_pixmap(flFunction_xpm);
00118 static Fl_Pixmap        code_pixmap(flCode_xpm);
00119 static Fl_Pixmap        codeblock_pixmap(flCodeBlock_xpm);
00120 static Fl_Pixmap        comment_pixmap(flComment_xpm);
00121 static Fl_Pixmap        declaration_pixmap(flDeclaration_xpm);
00122 static Fl_Pixmap        declarationblock_pixmap(flDeclarationBlock_xpm);
00123 static Fl_Pixmap        class_pixmap(flClass_xpm);
00124 static Fl_Pixmap        tabs_pixmap(flTabs_xpm);
00125 static Fl_Pixmap        input_pixmap(flInput_xpm);
00126 static Fl_Pixmap        choice_pixmap(flChoice_xpm);
00127 static Fl_Pixmap        menuitem_pixmap(flMenuitem_xpm);
00128 static Fl_Pixmap        menubar_pixmap(flMenubar_xpm);
00129 static Fl_Pixmap        submenu_pixmap(flSubmenu_xpm);
00130 static Fl_Pixmap        scroll_pixmap(flScroll_xpm);
00131 static Fl_Pixmap        tile_pixmap(flTile_xpm);
00132 static Fl_Pixmap        wizard_pixmap(flWizard_xpm);
00133 static Fl_Pixmap        pack_pixmap(flPack_xpm);
00134 static Fl_Pixmap        returnbutton_pixmap(flReturnButton_xpm);
00135 static Fl_Pixmap        lightbutton_pixmap(flLightButton_xpm);
00136 static Fl_Pixmap        repeatbutton_pixmap(flRepeatButton_xpm);
00137 static Fl_Pixmap        menubutton_pixmap(flMenuButton_xpm);
00138 static Fl_Pixmap        output_pixmap(flOutput_xpm);
00139 static Fl_Pixmap        textdisplay_pixmap(flTextDisplay_xpm);
00140 static Fl_Pixmap        textedit_pixmap(flTextEdit_xpm);
00141 static Fl_Pixmap        fileinput_pixmap(flFileInput_xpm);
00142 static Fl_Pixmap        browser_pixmap(flBrowser_xpm);
00143 static Fl_Pixmap        checkbrowser_pixmap(flCheckBrowser_xpm);
00144 static Fl_Pixmap        filebrowser_pixmap(flFileBrowser_xpm);
00145 static Fl_Pixmap        clock_pixmap(flClock_xpm);
00146 static Fl_Pixmap        help_pixmap(flHelp_xpm);
00147 static Fl_Pixmap        progress_pixmap(flProgress_xpm);
00148 static Fl_Pixmap        slider_pixmap(flSlider_xpm);
00149 static Fl_Pixmap        scrollbar_pixmap(flScrollBar_xpm);
00150 static Fl_Pixmap        valueslider_pixmap(flValueSlider_xpm);
00151 static Fl_Pixmap        adjuster_pixmap(flAdjuster_xpm);
00152 static Fl_Pixmap        counter_pixmap(flCounter_xpm);
00153 static Fl_Pixmap        dial_pixmap(flDial_xpm);
00154 static Fl_Pixmap        roller_pixmap(flRoller_xpm);
00155 static Fl_Pixmap        valueinput_pixmap(flValueInput_xpm);
00156 static Fl_Pixmap        valueoutput_pixmap(flValueOutput_xpm);
00157 static Fl_Pixmap        spinner_pixmap(flSpinner_xpm);
00158 static Fl_Pixmap        widgetclass_pixmap(flWidgetClass_xpm);
00159 static Fl_Pixmap        data_pixmap(flData_xpm);
00160 static Fl_Pixmap        tree_pixmap(flTree_xpm);
00161 static Fl_Pixmap        table_pixmap(flTable_xpm);
00162 
00163 Fl_Pixmap *pixmap[] = { 0, &window_pixmap, &button_pixmap, &checkbutton_pixmap, &roundbutton_pixmap, /* 0..4 */
00164  &box_pixmap, &group_pixmap, &function_pixmap, &code_pixmap, &codeblock_pixmap, &declaration_pixmap, /* 5..10 */ 
00165  &declarationblock_pixmap, &class_pixmap, &tabs_pixmap, &input_pixmap, &choice_pixmap,               /* 11..15 */
00166  &menuitem_pixmap, &menubar_pixmap, &submenu_pixmap, &scroll_pixmap, &tile_pixmap, &wizard_pixmap,   /* 16..21 */
00167  &pack_pixmap, &returnbutton_pixmap, &lightbutton_pixmap, &repeatbutton_pixmap, &menubutton_pixmap,  /* 22..26 */
00168  &output_pixmap, &textdisplay_pixmap, &textedit_pixmap, &fileinput_pixmap, &browser_pixmap,          /* 27..32 */
00169  &checkbrowser_pixmap, &filebrowser_pixmap, &clock_pixmap, &help_pixmap, &progress_pixmap,           /* 33..36 */
00170  &slider_pixmap, &scrollbar_pixmap, &valueslider_pixmap, &adjuster_pixmap, &counter_pixmap,          /* 37..41 */
00171  &dial_pixmap, &roller_pixmap, &valueinput_pixmap, &valueoutput_pixmap, &comment_pixmap,             /* 42..46 */
00172  &spinner_pixmap, &widgetclass_pixmap, &data_pixmap, &tree_pixmap, &table_pixmap };                  /* 47..51 */
00173 
00174 extern int show_comments;
00175 
00177 
00178 class Widget_Browser : public Fl_Browser_ {
00179   friend class Fl_Type;
00180 
00181   // required routines for Fl_Browser_ subclass:
00182   void *item_first() const ;
00183   void *item_next(void *) const ;
00184   void *item_prev(void *) const ;
00185   int item_selected(void *) const ;
00186   void item_select(void *,int);
00187   int item_width(void *) const ;
00188   int item_height(void *) const ;
00189   void item_draw(void *,int,int,int,int) const ;
00190   int incr_height() const ;
00191 
00192 public: 
00193 
00194   int handle(int);
00195   void callback();
00196   Widget_Browser(int,int,int,int,const char * =0);
00197 };
00198 
00199 static Widget_Browser *widget_browser;
00200 Fl_Widget *make_widget_browser(int x,int y,int w,int h) {
00201   return (widget_browser = new Widget_Browser(x,y,w,h));
00202 }
00203 
00204 void select(Fl_Type *o, int v) {
00205   widget_browser->select(o,v,1);
00206   //  Fl_Type::current = o;
00207 }
00208 
00209 void select_only(Fl_Type *o) {
00210   widget_browser->select_only(o,1);
00211 }
00212 
00213 void deselect() {
00214   widget_browser->deselect();
00215   //Fl_Type::current = 0; // this breaks the paste & merge functions
00216 }
00217 
00218 Fl_Type *Fl_Type::first;
00219 Fl_Type *Fl_Type::last;
00220 
00221 static void Widget_Browser_callback(Fl_Widget *o,void *) {
00222   ((Widget_Browser *)o)->callback();
00223 }
00224 
00225 Widget_Browser::Widget_Browser(int X,int Y,int W,int H,const char*l)
00226 : Fl_Browser_(X,Y,W,H,l) {
00227   type(FL_MULTI_BROWSER);
00228   Fl_Widget::callback(Widget_Browser_callback);
00229   when(FL_WHEN_RELEASE);
00230 }
00231 
00232 void *Widget_Browser::item_first() const {return Fl_Type::first;}
00233 
00234 void *Widget_Browser::item_next(void *l) const {return ((Fl_Type*)l)->next;}
00235 
00236 void *Widget_Browser::item_prev(void *l) const {return ((Fl_Type*)l)->prev;}
00237 
00238 int Widget_Browser::item_selected(void *l) const {return ((Fl_Type*)l)->new_selected;}
00239 
00240 void Widget_Browser::item_select(void *l,int v) {((Fl_Type*)l)->new_selected = v;}
00241 
00242 int Widget_Browser::item_height(void *l) const {
00243   Fl_Type *t = (Fl_Type*)l;
00244   if (t->visible) {
00245     if (show_comments && t->comment())
00246       return textsize()*2+1;
00247     else
00248       return textsize()+2;
00249   } else {
00250     return 0;
00251   }
00252   return ((Fl_Type *)l)->visible ? textsize()+2 : 0;
00253 }
00254 
00255 int Widget_Browser::incr_height() const {return textsize()+2;}
00256 
00257 static Fl_Type* pushedtitle;
00258 
00259 // Generate a descriptive text for this item, to put in browser & window titles
00260 const char* Fl_Type::title() {
00261   const char* c = name(); if (c) return c;
00262   return type_name();
00263 }
00264 
00265 extern const char* subclassname(Fl_Type*);
00266 
00267 void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const {
00268   Fl_Type *l = (Fl_Type *)v;
00269   X += 3 + 18 + l->level * 12;
00270   int comment_incr = 0;
00271   if (show_comments && l->comment()) {
00272     char buf[82], *d = buf;
00273     const char *s = l->comment();
00274     for (int i=0; i<80; i++) {
00275       char c = *s++;
00276       if (c==0 || c=='\n') break;
00277       *d++ = c;
00278     }
00279     *d = 0;
00280     comment_incr = textsize()-1;
00281     if (l->new_selected) fl_color(fl_contrast(FL_DARK_GREEN,FL_SELECTION_COLOR));
00282     else fl_color(fl_contrast(FL_DARK_GREEN,color()));
00283     fl_font(textfont()+FL_ITALIC, textsize()-2);
00284     fl_draw(buf, (l->is_parent())?X+12:X, Y+12);
00285     Y += comment_incr/2;
00286     comment_incr -= comment_incr/2;
00287   }
00288   if (l->new_selected) fl_color(fl_contrast(FL_FOREGROUND_COLOR,FL_SELECTION_COLOR));
00289   else fl_color(FL_FOREGROUND_COLOR);
00290   Fl_Pixmap *pm = pixmap[l->pixmapID()];
00291   if (pm) pm->draw(X-18, Y);
00292   switch (l->is_public()) {
00293     case 0: lock_pixmap.draw(X - 17, Y); break;
00294     case 2: protected_pixmap.draw(X - 17, Y); break;
00295   }
00296   if (l->is_parent()) {
00297     if (!l->next || l->next->level <= l->level) {
00298       if (l->open_!=(l==pushedtitle)) {
00299         fl_loop(X,Y+7,X+5,Y+12,X+10,Y+7);
00300       } else {
00301         fl_loop(X+2,Y+2,X+7,Y+7,X+2,Y+12);
00302       }
00303     } else {
00304       if (l->open_!=(l==pushedtitle)) {
00305         fl_polygon(X,Y+7,X+5,Y+12,X+10,Y+7);
00306       } else {
00307         fl_polygon(X+2,Y+2,X+7,Y+7,X+2,Y+12);
00308       }
00309     }
00310     X += 10;
00311   }
00312   Y += comment_incr;
00313   if (l->is_widget() || l->is_class()) {
00314     const char* c = subclassname(l);
00315     if (!strncmp(c,"Fl_",3)) c += 3;
00316     fl_font(textfont(), textsize());
00317     fl_draw(c, X, Y+13);
00318     X += int(fl_width(c)+fl_width('n'));
00319     c = l->name();
00320     if (c) {
00321       fl_font(textfont()|FL_BOLD, textsize());
00322       fl_draw(c, X, Y+13);
00323     } else if ((c=l->label())) {
00324       char buf[50]; char* p = buf;
00325       *p++ = '"';
00326       for (int i = 20; i--;) {
00327         if (! (*c & -32)) break;
00328         *p++ = *c++;
00329       }
00330       if (*c) {strcpy(p,"..."); p+=3;}
00331       *p++ = '"';
00332       *p = 0;
00333       fl_draw(buf, X, Y+13);
00334     }
00335   } else {
00336     const char* c = l->title();
00337     char buf[60]; char* p = buf;
00338     for (int i = 55; i--;) {
00339       if (! (*c & -32)) break;
00340       *p++ = *c++;
00341     }
00342     if (*c) {strcpy(p,"..."); p+=3;}
00343     *p = 0;
00344     fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
00345     fl_draw(buf, X, Y+13);
00346   }
00347 }
00348 
00349 int Widget_Browser::item_width(void *v) const {
00350   Fl_Type *l = (Fl_Type *)v;
00351 
00352   if (!l->visible) return 0;
00353 
00354   int W = 3 + 16 + 18 + l->level*10;
00355   if (l->is_parent()) W += 10;
00356 
00357   if (l->is_widget() || l->is_class()) {
00358     const char* c = l->type_name();
00359     if (!strncmp(c,"Fl_",3)) c += 3;
00360     fl_font(textfont(), textsize());
00361     W += int(fl_width(c) + fl_width('n'));
00362     c = l->name();
00363     if (c) {
00364       fl_font(textfont()|FL_BOLD, textsize());
00365       W += int(fl_width(c));
00366     } else if ((c=l->label())) {
00367       char buf[50]; char* p = buf;
00368       *p++ = '"';
00369       for (int i = 20; i--;) {
00370         if (! (*c & -32)) break;
00371         *p++ = *c++;
00372       }
00373       if (*c) {strcpy(p,"..."); p+=3;}
00374       *p++ = '"';
00375       *p = 0;
00376       W += int(fl_width(buf));
00377     }
00378   } else {
00379     const char* c = l->title();
00380     char buf[60]; char* p = buf;
00381     for (int i = 55; i--;) {
00382       if (! (*c & -32)) break;
00383       *p++ = *c++;
00384     }
00385     if (*c) {strcpy(p,"..."); p+=3;}
00386     *p = 0;
00387     fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
00388     W += int(fl_width(buf));
00389   }
00390 
00391   return W;
00392 }
00393 
00394 void redraw_browser() {
00395   widget_browser->redraw();
00396 }
00397 
00398 void Widget_Browser::callback() {
00399   selection_changed((Fl_Type*)selection());
00400 }
00401 
00402 int Widget_Browser::handle(int e) {
00403   static Fl_Type *title;
00404   Fl_Type *l;
00405   int X,Y,W,H; bbox(X,Y,W,H);
00406   switch (e) {
00407   case FL_PUSH:
00408     if (!Fl::event_inside(X,Y,W,H)) break;
00409     l = (Fl_Type*)find_item(Fl::event_y());
00410     if (l) {
00411       X += 12*l->level + 18 - hposition();
00412       if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) {
00413         title = pushedtitle = l;
00414         redraw_line(l);
00415         return 1;
00416       }
00417     }
00418     break;
00419   case FL_DRAG:
00420     if (!title) break;
00421     l = (Fl_Type*)find_item(Fl::event_y());
00422     if (l) {
00423       X += 12*l->level + 18 - hposition();
00424       if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) ;
00425       else l = 0;
00426     }
00427     if (l != pushedtitle) {
00428       if (pushedtitle) redraw_line(pushedtitle);
00429       if (l) redraw_line(l);
00430       pushedtitle = l;
00431     }
00432     return 1;
00433   case FL_RELEASE:
00434     if (!title) {
00435       l = (Fl_Type*)find_item(Fl::event_y());
00436       if (l && l->new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL)))
00437         l->open();
00438       break;
00439     }
00440     l = pushedtitle;
00441     title = pushedtitle = 0;
00442     if (l) {
00443       if (l->open_) {
00444         l->open_ = 0;
00445         for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next)
00446           k->visible = 0;
00447       } else {
00448         l->open_ = 1;
00449         for (Fl_Type*k=l->next; k&&k->level>l->level;) {
00450           k->visible = 1;
00451           if (k->is_parent() && !k->open_) {
00452             Fl_Type *j;
00453             for (j = k->next; j && j->level>k->level; j = j->next);
00454             k = j;
00455           } else
00456             k = k->next;
00457         }
00458       }
00459       redraw();
00460     }
00461     return 1;
00462   }
00463   return Fl_Browser_::handle(e);
00464 }
00465 
00466 Fl_Type::Fl_Type() {
00467   factory = 0;
00468   parent = 0;
00469   next = prev = 0;
00470   selected = new_selected = 0;
00471   visible = 0;
00472   name_ = 0;
00473   label_ = 0;
00474   user_data_ = 0;
00475   user_data_type_ = 0;
00476   callback_ = 0;
00477   comment_ = 0;
00478   rtti = 0;
00479   level = 0;
00480   code_position = header_position = -1;
00481   code_position_end = header_position_end = -1;
00482 }
00483 
00484 static void fixvisible(Fl_Type *p) {
00485   Fl_Type *t = p;
00486   for (;;) {
00487     if (t->parent) t->visible = t->parent->visible && t->parent->open_;
00488     else t->visible = 1;
00489     t = t->next;
00490     if (!t || t->level <= p->level) break;
00491   }
00492 }
00493 
00494 // turn a click at x,y on this into the actual picked object:
00495 Fl_Type* Fl_Type::click_test(int,int) {return 0;}
00496 void Fl_Type::add_child(Fl_Type*, Fl_Type*) {}
00497 void Fl_Type::move_child(Fl_Type*, Fl_Type*) {}
00498 void Fl_Type::remove_child(Fl_Type*) {}
00499 
00500 // add a list of widgets as a new child of p:
00501 void Fl_Type::add(Fl_Type *p) {
00502   if (p && parent == p) return;
00503   undo_checkpoint();
00504   parent = p;
00505   Fl_Type *end = this;
00506   while (end->next) end = end->next;
00507   Fl_Type *q;
00508   int newlevel;
00509   if (p) {
00510     for (q = p->next; q && q->level > p->level; q = q->next);
00511     newlevel = p->level+1;
00512   } else {
00513     q = 0;
00514     newlevel = 0;
00515   }
00516   for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level);
00517   level = newlevel;
00518   if (q) {
00519     prev = q->prev;
00520     prev->next = this;
00521     q->prev = end;
00522     end->next = q;
00523   } else if (first) {
00524     prev = last;
00525     prev->next = this;
00526     end->next = 0;
00527     last = end;
00528   } else {
00529     first = this;
00530     last = end;
00531     prev = end->next = 0;
00532   }
00533   if (p) p->add_child(this,0);
00534   open_ = 1;
00535   fixvisible(this);
00536   set_modflag(1);
00537   widget_browser->redraw();
00538 }
00539 
00540 // add to a parent before another widget:
00541 void Fl_Type::insert(Fl_Type *g) {
00542   Fl_Type *end = this;
00543   while (end->next) end = end->next;
00544   parent = g->parent;
00545   int newlevel = g->level;
00546   visible = g->visible;
00547   for (Fl_Type *t = this->next; t; t = t->next) t->level += newlevel-level;
00548   level = newlevel;
00549   prev = g->prev;
00550   if (prev) prev->next = this; else first = this;
00551   end->next = g;
00552   g->prev = end;
00553   fixvisible(this);
00554   if (parent) parent->add_child(this, g);
00555   widget_browser->redraw();
00556 }
00557 
00558 // Return message number for I18N...
00559 int
00560 Fl_Type::msgnum() {
00561   int           count;
00562   Fl_Type       *p;
00563 
00564   for (count = 0, p = this; p;) {
00565     if (p->label()) count ++;
00566     if (p != this && p->is_widget() && ((Fl_Widget_Type *)p)->tooltip()) count ++;
00567 
00568     if (p->prev) p = p->prev;
00569     else p = p->parent;
00570   }
00571 
00572   return count;
00573 }
00574 
00575 
00576 // delete from parent:
00577 Fl_Type *Fl_Type::remove() {
00578   Fl_Type *end = this;
00579   for (;;) {
00580     if (!end->next || end->next->level <= level) break;
00581     end = end->next;
00582   }
00583   if (prev) prev->next = end->next;
00584   else first = end->next;
00585   if (end->next) end->next->prev = prev;
00586   else last = prev;
00587   Fl_Type *r = end->next;
00588   prev = end->next = 0;
00589   if (parent) parent->remove_child(this);
00590   parent = 0;
00591   widget_browser->redraw();
00592   selection_changed(0);
00593   return r;
00594 }
00595 
00596 // update a string member:
00597 int storestring(const char *n, const char * & p, int nostrip) {
00598   if (n == p) return 0;
00599   undo_checkpoint();
00600   int length = 0;
00601   if (n) { // see if blank, strip leading & trailing blanks
00602     if (!nostrip) while (isspace(*n)) n++;
00603     const char *e = n + strlen(n);
00604     if (!nostrip) while (e > n && isspace(*(e-1))) e--;
00605     length = e-n;
00606     if (!length) n = 0;
00607   }    
00608   if (n == p) return 0;
00609   if (n && p && !strncmp(n,p,length) && !p[length]) return 0;
00610   if (p) free((void *)p);
00611   if (!n || !*n) {
00612     p = 0;
00613   } else {
00614     char *q = (char *)malloc(length+1);
00615     strlcpy(q,n,length+1);
00616     p = q;
00617   }
00618   set_modflag(1);
00619   return 1;
00620 }
00621 
00622 void Fl_Type::name(const char *n) {
00623   int nostrip = is_comment();
00624   if (storestring(n,name_,nostrip)) {
00625     if (visible) widget_browser->redraw();
00626   }
00627 }
00628 
00629 void Fl_Type::label(const char *n) {
00630   if (storestring(n,label_,1)) {
00631     setlabel(label_);
00632     if (visible && !name_) widget_browser->redraw();
00633   }
00634 }
00635 
00636 void Fl_Type::callback(const char *n) {
00637   storestring(n,callback_);
00638 }
00639 
00640 void Fl_Type::user_data(const char *n) {
00641   storestring(n,user_data_);
00642 }
00643 
00644 void Fl_Type::user_data_type(const char *n) {
00645   storestring(n,user_data_type_);
00646 }
00647 
00648 void Fl_Type::comment(const char *n) {
00649   storestring(n, comment_, 1);
00650 }
00651 
00652 void Fl_Type::open() {
00653   printf("Open of '%s' is not yet implemented\n",type_name());
00654 }
00655 
00656 void Fl_Type::setlabel(const char *) {}
00657 
00658 Fl_Type::~Fl_Type() {
00659   // warning: destructor only works for widgets that have been add()ed.
00660   if (widget_browser) widget_browser->deleting(this);
00661   if (prev) prev->next = next; else first = next;
00662   if (next) next->prev = prev; else last = prev;
00663   if (current == this) current = 0;
00664   if (parent) parent->remove_child(this);
00665   if (name_) free((void*)name_);
00666   if (label_) free((void*)label_);
00667   if (callback_) free((void*)callback_);
00668   if (user_data_) free((void*)user_data_);
00669   if (user_data_type_) free((void*)user_data_type_);
00670   if (comment_) free((void*)comment_);
00671 }
00672 
00673 int Fl_Type::is_parent() const {return 0;}
00674 int Fl_Type::is_widget() const {return 0;}
00675 int Fl_Type::is_valuator() const {return 0;}
00676 int Fl_Type::is_spinner() const {return 0;}
00677 int Fl_Type::is_button() const {return 0;}
00678 int Fl_Type::is_input() const {return 0;}
00679 int Fl_Type::is_value_input() const {return 0;}
00680 int Fl_Type::is_text_display() const {return 0;}
00681 int Fl_Type::is_menu_item() const {return 0;}
00682 int Fl_Type::is_menu_button() const {return 0;}
00683 int Fl_Type::is_group() const {return 0;}
00684 int Fl_Type::is_window() const {return 0;}
00685 int Fl_Type::is_code_block() const {return 0;}
00686 int Fl_Type::is_decl_block() const {return 0;}
00687 int Fl_Type::is_comment() const {return 0;}
00688 int Fl_Type::is_class() const {return 0;}
00689 int Fl_Type::is_public() const {return 1;}
00690 
00691 int Fl_Code_Type::is_public()const { return -1; }
00692 int Fl_CodeBlock_Type::is_public()const { return -1; }
00693 
00694 
00696 
00697 Fl_Type *in_this_only; // set if menu popped-up in window
00698 
00699 void select_all_cb(Fl_Widget *,void *) {
00700   Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
00701   if (in_this_only) {
00702     Fl_Type *t = p;
00703     for (; t && t != in_this_only; t = t->parent);
00704     if (t != in_this_only) p = in_this_only;
00705   }
00706   for (;;) {
00707     if (p) {
00708       int foundany = 0;
00709       for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
00710         if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;}
00711       }
00712       if (foundany) break;
00713       p = p->parent;
00714     } else {
00715       for (Fl_Type *t = Fl_Type::first; t; t = t->next)
00716         widget_browser->select(t,1,0);
00717       break;
00718     }
00719   }
00720   selection_changed(p);
00721 }
00722 
00723 void select_none_cb(Fl_Widget *,void *) {
00724   Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
00725   if (in_this_only) {
00726     Fl_Type *t = p;
00727     for (; t && t != in_this_only; t = t->parent);
00728     if (t != in_this_only) p = in_this_only;
00729   }
00730   for (;;) {
00731     if (p) {
00732       int foundany = 0;
00733       for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
00734         if (t->new_selected) {widget_browser->select(t,0,0); foundany = 1;}
00735       }
00736       if (foundany) break;
00737       p = p->parent;
00738     } else {
00739       for (Fl_Type *t = Fl_Type::first; t; t = t->next)
00740         widget_browser->select(t,0,0);
00741       break;
00742     }
00743   }
00744   selection_changed(p);
00745 }
00746 
00747 static void delete_children(Fl_Type *p) {
00748   Fl_Type *f;
00749   for (f = p; f && f->next && f->next->level > p->level; f = f->next);
00750   for (; f != p; ) {
00751     Fl_Type *g = f->prev;
00752     delete f;
00753     f = g;
00754   }
00755 }
00756 
00757 void delete_all(int selected_only) {
00758   for (Fl_Type *f = Fl_Type::first; f;) {
00759     if (f->selected || !selected_only) {
00760       delete_children(f);
00761       Fl_Type *g = f->next;
00762       delete f;
00763       f = g;
00764     } else f = f->next;
00765   }
00766   if(!selected_only) {
00767                 include_H_from_C=1;
00768                 use_FL_COMMAND=0;
00769         }
00770 
00771   selection_changed(0);
00772 }
00773 
00774 // move f (and it's children) into list before g:
00775 // returns pointer to whatever is after f & children
00776 void Fl_Type::move_before(Fl_Type* g) {
00777   if (level != g->level) printf("move_before levels don't match! %d %d\n",
00778                                 level, g->level);
00779   Fl_Type* n;
00780   for (n = next; n && n->level > level; n = n->next);
00781   if (n == g) return;
00782   Fl_Type *l = n ? n->prev : Fl_Type::last;
00783   prev->next = n;
00784   if (n) n->prev = prev; else Fl_Type::last = prev;
00785   prev = g->prev;
00786   l->next = g;
00787   if (prev) prev->next = this; else Fl_Type::first = this;
00788   g->prev = l;
00789   if (parent && is_widget()) parent->move_child(this,g);
00790   widget_browser->inserting(g, this);
00791   widget_browser->display(this);
00792   widget_browser->redraw();
00793 }
00794 
00795 // move selected widgets in their parent's list:
00796 void earlier_cb(Fl_Widget*,void*) {
00797   Fl_Type *f;
00798   int mod = 0;
00799   for (f = Fl_Type::first; f; ) {
00800     Fl_Type* nxt = f->next;
00801     if (f->selected) {
00802       Fl_Type* g;
00803       for (g = f->prev; g && g->level > f->level; g = g->prev);
00804       if (g && g->level == f->level && !g->selected) {
00805         f->move_before(g);
00806         mod = 1;
00807       }
00808     }
00809     f = nxt;
00810   }
00811   if (mod) set_modflag(1);
00812 }
00813 
00814 void later_cb(Fl_Widget*,void*) {
00815   Fl_Type *f;
00816   int mod = 0;
00817   for (f = Fl_Type::last; f; ) {
00818     Fl_Type* prv = f->prev;
00819     if (f->selected) {
00820       Fl_Type* g;
00821       for (g = f->next; g && g->level > f->level; g = g->next);
00822       if (g && g->level == f->level && !g->selected) {
00823         g->move_before(f);
00824         mod = 1;
00825       }
00826     }
00827     f = prv;
00828   }
00829   if (mod) set_modflag(1);
00830 }
00831 
00833 
00834 // write a widget and all it's children:
00835 void Fl_Type::write() {
00836     write_indent(level);
00837     write_word(type_name());
00838     
00839     if (is_class()) {
00840       const char * p =  ((Fl_Class_Type*)this)->prefix();
00841       if (p &&  strlen(p))
00842         write_word(p);
00843     }
00844 
00845     write_word(name());
00846     write_open(level);
00847     write_properties();
00848     write_close(level);
00849     if (!is_parent()) return;
00850     // now do children:
00851     write_open(level);
00852     Fl_Type *child;
00853     for (child = next; child && child->level > level; child = child->next)
00854         if (child->level == level+1) child->write();
00855     write_close(level);
00856 }
00857 
00858 void Fl_Type::write_properties() {
00859   // repeat this for each attribute:
00860   if (label()) {
00861     write_indent(level+1);
00862     write_word("label");
00863     write_word(label());
00864   }
00865   if (user_data()) {
00866     write_indent(level+1);
00867     write_word("user_data");
00868     write_word(user_data());
00869   }
00870   if (user_data_type()) {
00871     write_word("user_data_type");
00872     write_word(user_data_type());
00873   }
00874   if (callback()) {
00875     write_indent(level+1);
00876     write_word("callback");
00877     write_word(callback());
00878   }
00879   if (comment()) {
00880     write_indent(level+1);
00881     write_word("comment");
00882     write_word(comment());
00883   }
00884   if (is_parent() && open_) write_word("open");
00885   if (selected) write_word("selected");
00886 }
00887 
00888 void Fl_Type::read_property(const char *c) {
00889   if (!strcmp(c,"label"))
00890     label(read_word());
00891   else if (!strcmp(c,"user_data"))
00892     user_data(read_word());
00893   else if (!strcmp(c,"user_data_type"))
00894     user_data_type(read_word());
00895   else if (!strcmp(c,"callback"))
00896     callback(read_word());
00897   else if (!strcmp(c,"comment"))
00898     comment(read_word());
00899   else if (!strcmp(c,"open"))
00900     open_ = 1;
00901   else if (!strcmp(c,"selected"))
00902     select(this,1);
00903   else
00904     read_error("Unknown property \"%s\"", c);
00905 }
00906 
00907 int Fl_Type::read_fdesign(const char*, const char*) {return 0;}
00908 
00912 int has_toplevel_function(const char *rtype, const char *sig) {
00913   Fl_Type *child;
00914   for (child = Fl_Type::first; child; child = child->next) {
00915     if (!child->is_in_class() && strcmp(child->type_name(), "Function")==0) {
00916       const Fl_Function_Type *fn = (const Fl_Function_Type*)child;
00917       if (fn->has_signature(rtype, sig))
00918         return 1;
00919     }
00920   }
00921   return 0;
00922 }
00923 
00927 void Fl_Type::write_comment_h(const char *pre)
00928 {
00929   if (comment()) {
00930     write_h("%s/**\n", pre);
00931     const char *s = comment();
00932     write_h("%s   ", pre);
00933     while(*s) {
00934       if (*s=='\n') {
00935         if (s[1]) {
00936           write_h("\n%s   ", pre);
00937         }
00938       } else {
00939         write_h("%c", *s); // FIXME this is much too slow!
00940       }
00941       s++;
00942     }
00943     write_h("\n%s*/\n", pre);
00944   }
00945 }
00946 
00950 void Fl_Type::write_comment_c(const char *pre)
00951 {
00952   if (comment()) {
00953     write_c("%s/**\n", pre);
00954     const char *s = comment();
00955     write_c("%s   ", pre);
00956     while(*s) {
00957       if (*s=='\n') {
00958         if (s[1]) {
00959           write_c("\n%s   ", pre);
00960         }
00961       } else {
00962         write_c("%c", *s); // FIXME this is much too slow!
00963       }
00964       s++;
00965     }
00966     write_c("\n%s*/\n", pre);
00967   }
00968 }
00969 
00974 void reveal_in_browser(Fl_Type *t) {
00975   Fl_Type *p = t->parent;
00976   if (p) {
00977     for (;;) {
00978       if (!p->open_)
00979         p->open_ = 1;
00980       if (!p->parent) break;
00981       p = p->parent;
00982     }
00983     fixvisible(p);
00984   }
00985   widget_browser->display(t);
00986   redraw_browser();
00987 }
00988 
00994 Fl_Widget *Fl_Type::enter_live_mode(int) {
00995   return 0L;
00996 }
00997 
01002 void Fl_Type::leave_live_mode() {
01003 }
01004 
01008 void Fl_Type::copy_properties() {
01009 }
01010 
01019 int Fl_Type::user_defined(const char* cbname) const {
01020   for (Fl_Type* p = Fl_Type::first; p ; p = p->next)
01021     if (strcmp(p->type_name(), "Function") == 0 && p->name() != 0)
01022       if (strncmp(p->name(), cbname, strlen(cbname)) == 0)
01023         if (p->name()[strlen(cbname)] == '(')
01024           return 1;
01025   return 0;
01026 }
01027 
01028 
01029 //
01030 // End of "$Id: Fl_Type.cxx 8172 2011-01-03 08:28:38Z matt $".
01031 //