Fl_Type.cxx 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065
  1. //
  2. // "$Id: Fl_Type.cxx 9992 2013-09-24 19:58:24Z greg.ercolano $"
  3. //
  4. // Widget type code for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Each object described by Fluid is one of these objects. They
  7. // are all stored in a double-linked list.
  8. //
  9. // They "type" of the object is covered by the virtual functions.
  10. // There will probably be a lot of these virtual functions.
  11. //
  12. // The type browser is also a list of these objects, but they
  13. // are "factory" instances, not "real" ones. These objects exist
  14. // only so the "make" method can be called on them. They are
  15. // not in the linked list and are not written to files or
  16. // copied or otherwise examined.
  17. //
  18. // Copyright 1998-2010 by Bill Spitzak and others.
  19. //
  20. // This library is free software. Distribution and use rights are outlined in
  21. // the file "COPYING" which should have been included with this file. If this
  22. // file is missing or damaged, see the license at:
  23. //
  24. // http://www.fltk.org/COPYING.php
  25. //
  26. // Please report all bugs and problems on the following page:
  27. //
  28. // http://www.fltk.org/str.php
  29. //
  30. #include <FL/Fl.H>
  31. #include <FL/Fl_Browser_.H>
  32. #include <FL/fl_draw.H>
  33. #include <stdlib.h>
  34. #include "../src/flstring.h"
  35. #include <stdio.h>
  36. #include "Fl_Type.h"
  37. #include "undo.h"
  38. #include <FL/Fl_Pixmap.H>
  39. #include "pixmaps/lock.xpm"
  40. #include "pixmaps/protected.xpm"
  41. //#include "pixmaps/unlock.xpm"
  42. static Fl_Pixmap lock_pixmap(lock_xpm);
  43. static Fl_Pixmap protected_pixmap(protected_xpm);
  44. //static Fl_Pixmap unlock_pixmap(unlock_xpm);
  45. #include "pixmaps/flWindow.xpm"
  46. #include "pixmaps/flButton.xpm"
  47. #include "pixmaps/flCheckButton.xpm"
  48. #include "pixmaps/flRoundButton.xpm"
  49. #include "pixmaps/flBox.xpm"
  50. #include "pixmaps/flGroup.xpm"
  51. #include "pixmaps/flFunction.xpm"
  52. #include "pixmaps/flCode.xpm"
  53. #include "pixmaps/flCodeBlock.xpm"
  54. #include "pixmaps/flComment.xpm"
  55. #include "pixmaps/flData.xpm"
  56. #include "pixmaps/flDeclaration.xpm"
  57. #include "pixmaps/flDeclarationBlock.xpm"
  58. #include "pixmaps/flClass.xpm"
  59. #include "pixmaps/flTabs.xpm"
  60. #include "pixmaps/flInput.xpm"
  61. #include "pixmaps/flChoice.xpm"
  62. #include "pixmaps/flMenuitem.xpm"
  63. #include "pixmaps/flMenubar.xpm"
  64. #include "pixmaps/flSubmenu.xpm"
  65. #include "pixmaps/flScroll.xpm"
  66. #include "pixmaps/flTile.xpm"
  67. #include "pixmaps/flWizard.xpm"
  68. #include "pixmaps/flPack.xpm"
  69. #include "pixmaps/flReturnButton.xpm"
  70. #include "pixmaps/flLightButton.xpm"
  71. #include "pixmaps/flRepeatButton.xpm"
  72. #include "pixmaps/flMenuButton.xpm"
  73. #include "pixmaps/flOutput.xpm"
  74. #include "pixmaps/flTextDisplay.xpm"
  75. #include "pixmaps/flTextEdit.xpm"
  76. #include "pixmaps/flFileInput.xpm"
  77. #include "pixmaps/flBrowser.xpm"
  78. #include "pixmaps/flCheckBrowser.xpm"
  79. #include "pixmaps/flFileBrowser.xpm"
  80. #include "pixmaps/flClock.xpm"
  81. #include "pixmaps/flHelp.xpm"
  82. #include "pixmaps/flProgress.xpm"
  83. #include "pixmaps/flSlider.xpm"
  84. #include "pixmaps/flScrollBar.xpm"
  85. #include "pixmaps/flValueSlider.xpm"
  86. #include "pixmaps/flAdjuster.xpm"
  87. #include "pixmaps/flCounter.xpm"
  88. #include "pixmaps/flDial.xpm"
  89. #include "pixmaps/flRoller.xpm"
  90. #include "pixmaps/flValueInput.xpm"
  91. #include "pixmaps/flValueOutput.xpm"
  92. #include "pixmaps/flSpinner.xpm"
  93. #include "pixmaps/flWidgetClass.xpm"
  94. #include "pixmaps/flTree.xpm"
  95. #include "pixmaps/flTable.xpm"
  96. static Fl_Pixmap window_pixmap(flWindow_xpm);
  97. static Fl_Pixmap button_pixmap(flButton_xpm);
  98. static Fl_Pixmap checkbutton_pixmap(flCheckButton_xpm);
  99. static Fl_Pixmap roundbutton_pixmap(flRoundButton_xpm);
  100. static Fl_Pixmap box_pixmap(flBox_xpm);
  101. static Fl_Pixmap group_pixmap(flGroup_xpm);
  102. static Fl_Pixmap function_pixmap(flFunction_xpm);
  103. static Fl_Pixmap code_pixmap(flCode_xpm);
  104. static Fl_Pixmap codeblock_pixmap(flCodeBlock_xpm);
  105. static Fl_Pixmap comment_pixmap(flComment_xpm);
  106. static Fl_Pixmap declaration_pixmap(flDeclaration_xpm);
  107. static Fl_Pixmap declarationblock_pixmap(flDeclarationBlock_xpm);
  108. static Fl_Pixmap class_pixmap(flClass_xpm);
  109. static Fl_Pixmap tabs_pixmap(flTabs_xpm);
  110. static Fl_Pixmap input_pixmap(flInput_xpm);
  111. static Fl_Pixmap choice_pixmap(flChoice_xpm);
  112. static Fl_Pixmap menuitem_pixmap(flMenuitem_xpm);
  113. static Fl_Pixmap menubar_pixmap(flMenubar_xpm);
  114. static Fl_Pixmap submenu_pixmap(flSubmenu_xpm);
  115. static Fl_Pixmap scroll_pixmap(flScroll_xpm);
  116. static Fl_Pixmap tile_pixmap(flTile_xpm);
  117. static Fl_Pixmap wizard_pixmap(flWizard_xpm);
  118. static Fl_Pixmap pack_pixmap(flPack_xpm);
  119. static Fl_Pixmap returnbutton_pixmap(flReturnButton_xpm);
  120. static Fl_Pixmap lightbutton_pixmap(flLightButton_xpm);
  121. static Fl_Pixmap repeatbutton_pixmap(flRepeatButton_xpm);
  122. static Fl_Pixmap menubutton_pixmap(flMenuButton_xpm);
  123. static Fl_Pixmap output_pixmap(flOutput_xpm);
  124. static Fl_Pixmap textdisplay_pixmap(flTextDisplay_xpm);
  125. static Fl_Pixmap textedit_pixmap(flTextEdit_xpm);
  126. static Fl_Pixmap fileinput_pixmap(flFileInput_xpm);
  127. static Fl_Pixmap browser_pixmap(flBrowser_xpm);
  128. static Fl_Pixmap checkbrowser_pixmap(flCheckBrowser_xpm);
  129. static Fl_Pixmap filebrowser_pixmap(flFileBrowser_xpm);
  130. static Fl_Pixmap clock_pixmap(flClock_xpm);
  131. static Fl_Pixmap help_pixmap(flHelp_xpm);
  132. static Fl_Pixmap progress_pixmap(flProgress_xpm);
  133. static Fl_Pixmap slider_pixmap(flSlider_xpm);
  134. static Fl_Pixmap scrollbar_pixmap(flScrollBar_xpm);
  135. static Fl_Pixmap valueslider_pixmap(flValueSlider_xpm);
  136. static Fl_Pixmap adjuster_pixmap(flAdjuster_xpm);
  137. static Fl_Pixmap counter_pixmap(flCounter_xpm);
  138. static Fl_Pixmap dial_pixmap(flDial_xpm);
  139. static Fl_Pixmap roller_pixmap(flRoller_xpm);
  140. static Fl_Pixmap valueinput_pixmap(flValueInput_xpm);
  141. static Fl_Pixmap valueoutput_pixmap(flValueOutput_xpm);
  142. static Fl_Pixmap spinner_pixmap(flSpinner_xpm);
  143. static Fl_Pixmap widgetclass_pixmap(flWidgetClass_xpm);
  144. static Fl_Pixmap data_pixmap(flData_xpm);
  145. static Fl_Pixmap tree_pixmap(flTree_xpm);
  146. static Fl_Pixmap table_pixmap(flTable_xpm);
  147. Fl_Pixmap *pixmap[] = { 0, &window_pixmap, &button_pixmap, &checkbutton_pixmap, &roundbutton_pixmap, /* 0..4 */
  148. &box_pixmap, &group_pixmap, &function_pixmap, &code_pixmap, &codeblock_pixmap, &declaration_pixmap, /* 5..10 */
  149. &declarationblock_pixmap, &class_pixmap, &tabs_pixmap, &input_pixmap, &choice_pixmap, /* 11..15 */
  150. &menuitem_pixmap, &menubar_pixmap, &submenu_pixmap, &scroll_pixmap, &tile_pixmap, &wizard_pixmap, /* 16..21 */
  151. &pack_pixmap, &returnbutton_pixmap, &lightbutton_pixmap, &repeatbutton_pixmap, &menubutton_pixmap, /* 22..26 */
  152. &output_pixmap, &textdisplay_pixmap, &textedit_pixmap, &fileinput_pixmap, &browser_pixmap, /* 27..32 */
  153. &checkbrowser_pixmap, &filebrowser_pixmap, &clock_pixmap, &help_pixmap, &progress_pixmap, /* 33..36 */
  154. &slider_pixmap, &scrollbar_pixmap, &valueslider_pixmap, &adjuster_pixmap, &counter_pixmap, /* 37..41 */
  155. &dial_pixmap, &roller_pixmap, &valueinput_pixmap, &valueoutput_pixmap, &comment_pixmap, /* 42..46 */
  156. &spinner_pixmap, &widgetclass_pixmap, &data_pixmap, &tree_pixmap, &table_pixmap }; /* 47..51 */
  157. extern int show_comments;
  158. ////////////////////////////////////////////////////////////////
  159. class Widget_Browser : public Fl_Browser_ {
  160. friend class Fl_Type;
  161. // required routines for Fl_Browser_ subclass:
  162. void *item_first() const ;
  163. void *item_next(void *) const ;
  164. void *item_prev(void *) const ;
  165. int item_selected(void *) const ;
  166. void item_select(void *,int);
  167. int item_width(void *) const ;
  168. int item_height(void *) const ;
  169. void item_draw(void *,int,int,int,int) const ;
  170. int incr_height() const ;
  171. public:
  172. int handle(int);
  173. void callback();
  174. Widget_Browser(int,int,int,int,const char * =0);
  175. };
  176. static Widget_Browser *widget_browser;
  177. Fl_Widget *make_widget_browser(int x,int y,int w,int h) {
  178. return (widget_browser = new Widget_Browser(x,y,w,h));
  179. }
  180. void select(Fl_Type *o, int v) {
  181. widget_browser->select(o,v,1);
  182. // Fl_Type::current = o;
  183. }
  184. void select_only(Fl_Type *o) {
  185. widget_browser->select_only(o,1);
  186. }
  187. void deselect() {
  188. widget_browser->deselect();
  189. //Fl_Type::current = 0; // this breaks the paste & merge functions
  190. }
  191. Fl_Type *Fl_Type::first;
  192. Fl_Type *Fl_Type::last;
  193. static void Widget_Browser_callback(Fl_Widget *o,void *) {
  194. ((Widget_Browser *)o)->callback();
  195. }
  196. Widget_Browser::Widget_Browser(int X,int Y,int W,int H,const char*l)
  197. : Fl_Browser_(X,Y,W,H,l) {
  198. type(FL_MULTI_BROWSER);
  199. Fl_Widget::callback(Widget_Browser_callback);
  200. when(FL_WHEN_RELEASE);
  201. }
  202. void *Widget_Browser::item_first() const {return Fl_Type::first;}
  203. void *Widget_Browser::item_next(void *l) const {return ((Fl_Type*)l)->next;}
  204. void *Widget_Browser::item_prev(void *l) const {return ((Fl_Type*)l)->prev;}
  205. int Widget_Browser::item_selected(void *l) const {return ((Fl_Type*)l)->new_selected;}
  206. void Widget_Browser::item_select(void *l,int v) {((Fl_Type*)l)->new_selected = v;}
  207. int Widget_Browser::item_height(void *l) const {
  208. Fl_Type *t = (Fl_Type*)l;
  209. if (t->visible) {
  210. if (show_comments && t->comment())
  211. return textsize()*2+1;
  212. else
  213. return textsize()+2;
  214. } else {
  215. return 0;
  216. }
  217. return ((Fl_Type *)l)->visible ? textsize()+2 : 0;
  218. }
  219. int Widget_Browser::incr_height() const {return textsize()+2;}
  220. static Fl_Type* pushedtitle;
  221. // Generate a descriptive text for this item, to put in browser & window titles
  222. const char* Fl_Type::title() {
  223. const char* c = name(); if (c) return c;
  224. return type_name();
  225. }
  226. extern const char* subclassname(Fl_Type*);
  227. void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const {
  228. Fl_Type *l = (Fl_Type *)v;
  229. X += 3 + 18 + l->level * 12;
  230. int comment_incr = 0;
  231. if (show_comments && l->comment()) {
  232. char buf[82], *d = buf;
  233. const char *s = l->comment();
  234. for (int i=0; i<80; i++) {
  235. char c = *s++;
  236. if (c==0 || c=='\n') break;
  237. *d++ = c;
  238. }
  239. *d = 0;
  240. comment_incr = textsize()-1;
  241. if (l->new_selected) fl_color(fl_contrast(FL_DARK_GREEN,FL_SELECTION_COLOR));
  242. else fl_color(fl_contrast(FL_DARK_GREEN,color()));
  243. fl_font(textfont()+FL_ITALIC, textsize()-2);
  244. fl_draw(buf, (l->is_parent())?X+12:X, Y+12);
  245. Y += comment_incr/2;
  246. comment_incr -= comment_incr/2;
  247. }
  248. if (l->new_selected) fl_color(fl_contrast(FL_FOREGROUND_COLOR,FL_SELECTION_COLOR));
  249. else fl_color(FL_FOREGROUND_COLOR);
  250. Fl_Pixmap *pm = pixmap[l->pixmapID()];
  251. if (pm) pm->draw(X-18, Y);
  252. switch (l->is_public()) {
  253. case 0: lock_pixmap.draw(X - 17, Y); break;
  254. case 2: protected_pixmap.draw(X - 17, Y); break;
  255. }
  256. if (l->is_parent()) {
  257. if (!l->next || l->next->level <= l->level) {
  258. if (l->open_!=(l==pushedtitle)) {
  259. fl_loop(X,Y+7,X+5,Y+12,X+10,Y+7);
  260. } else {
  261. fl_loop(X+2,Y+2,X+7,Y+7,X+2,Y+12);
  262. }
  263. } else {
  264. if (l->open_!=(l==pushedtitle)) {
  265. fl_polygon(X,Y+7,X+5,Y+12,X+10,Y+7);
  266. } else {
  267. fl_polygon(X+2,Y+2,X+7,Y+7,X+2,Y+12);
  268. }
  269. }
  270. X += 10;
  271. }
  272. Y += comment_incr;
  273. if (l->is_widget() || l->is_class()) {
  274. const char* c = subclassname(l);
  275. if (!strncmp(c,"Fl_",3)) c += 3;
  276. fl_font(textfont(), textsize());
  277. fl_draw(c, X, Y+13);
  278. X += int(fl_width(c)+fl_width('n'));
  279. c = l->name();
  280. if (c) {
  281. fl_font(textfont()|FL_BOLD, textsize());
  282. fl_draw(c, X, Y+13);
  283. } else if ((c=l->label())) {
  284. char buf[100]; char* p = buf;
  285. *p++ = '"';
  286. int b,l=strlen(c); // size in bytes
  287. for (int i = 20; i>0;i--) { // maximum 20 characters
  288. if (*c==0) break; // end of string
  289. fl_utf8decode(c, c+l, &b); // b=size of char in bytes
  290. if (b==-1) break; // some error - leave
  291. l-=b; // l = bytes left in string
  292. while (b--)*p++ = *c++; // copy that character into the buffer
  293. }
  294. if (*c) {strcpy(p,"..."); p+=3;} // there would be more to this string
  295. *p++ = '"';
  296. *p = 0;
  297. fl_draw(buf, X, Y+13);
  298. }
  299. } else {
  300. const char* c = l->title();
  301. char buf[60]; char* p = buf;
  302. for (int i = 55; i--;) {
  303. if (! (*c & -32)) break;
  304. *p++ = *c++;
  305. }
  306. if (*c) {strcpy(p,"..."); p+=3;}
  307. *p = 0;
  308. fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
  309. fl_draw(buf, X, Y+13);
  310. }
  311. }
  312. int Widget_Browser::item_width(void *v) const {
  313. Fl_Type *l = (Fl_Type *)v;
  314. if (!l->visible) return 0;
  315. int W = 3 + 16 + 18 + l->level*10;
  316. if (l->is_parent()) W += 10;
  317. if (l->is_widget() || l->is_class()) {
  318. const char* c = l->type_name();
  319. if (!strncmp(c,"Fl_",3)) c += 3;
  320. fl_font(textfont(), textsize());
  321. W += int(fl_width(c) + fl_width('n'));
  322. c = l->name();
  323. if (c) {
  324. fl_font(textfont()|FL_BOLD, textsize());
  325. W += int(fl_width(c));
  326. } else if ((c=l->label())) {
  327. char buf[50]; char* p = buf;
  328. *p++ = '"';
  329. for (int i = 20; i--;) {
  330. if (! (*c & -32)) break;
  331. *p++ = *c++;
  332. }
  333. if (*c) {strcpy(p,"..."); p+=3;}
  334. *p++ = '"';
  335. *p = 0;
  336. W += int(fl_width(buf));
  337. }
  338. } else {
  339. const char* c = l->title();
  340. char buf[60]; char* p = buf;
  341. for (int i = 55; i--;) {
  342. if (! (*c & -32)) break;
  343. *p++ = *c++;
  344. }
  345. if (*c) {strcpy(p,"..."); p+=3;}
  346. *p = 0;
  347. fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
  348. W += int(fl_width(buf));
  349. }
  350. return W;
  351. }
  352. void redraw_browser() {
  353. widget_browser->redraw();
  354. }
  355. void Widget_Browser::callback() {
  356. selection_changed((Fl_Type*)selection());
  357. }
  358. int Widget_Browser::handle(int e) {
  359. static Fl_Type *title;
  360. Fl_Type *l;
  361. int X,Y,W,H; bbox(X,Y,W,H);
  362. switch (e) {
  363. case FL_PUSH:
  364. if (!Fl::event_inside(X,Y,W,H)) break;
  365. l = (Fl_Type*)find_item(Fl::event_y());
  366. if (l) {
  367. X += 12*l->level + 18 - hposition();
  368. if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) {
  369. title = pushedtitle = l;
  370. redraw_line(l);
  371. return 1;
  372. }
  373. }
  374. break;
  375. case FL_DRAG:
  376. if (!title) break;
  377. l = (Fl_Type*)find_item(Fl::event_y());
  378. if (l) {
  379. X += 12*l->level + 18 - hposition();
  380. if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) ;
  381. else l = 0;
  382. }
  383. if (l != pushedtitle) {
  384. if (pushedtitle) redraw_line(pushedtitle);
  385. if (l) redraw_line(l);
  386. pushedtitle = l;
  387. }
  388. return 1;
  389. case FL_RELEASE:
  390. if (!title) {
  391. l = (Fl_Type*)find_item(Fl::event_y());
  392. if (l && l->new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL)))
  393. l->open();
  394. break;
  395. }
  396. l = pushedtitle;
  397. title = pushedtitle = 0;
  398. if (l) {
  399. if (l->open_) {
  400. l->open_ = 0;
  401. for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next)
  402. k->visible = 0;
  403. } else {
  404. l->open_ = 1;
  405. for (Fl_Type*k=l->next; k&&k->level>l->level;) {
  406. k->visible = 1;
  407. if (k->is_parent() && !k->open_) {
  408. Fl_Type *j;
  409. for (j = k->next; j && j->level>k->level; j = j->next);
  410. k = j;
  411. } else
  412. k = k->next;
  413. }
  414. }
  415. redraw();
  416. }
  417. return 1;
  418. }
  419. return Fl_Browser_::handle(e);
  420. }
  421. Fl_Type::Fl_Type() {
  422. factory = 0;
  423. parent = 0;
  424. next = prev = 0;
  425. selected = new_selected = 0;
  426. visible = 0;
  427. name_ = 0;
  428. macro_name_ = 0;
  429. dirty_name_ = 0;
  430. label_ = 0;
  431. user_data_ = 0;
  432. user_data_type_ = 0;
  433. callback_ = 0;
  434. comment_ = 0;
  435. rtti = 0;
  436. level = 0;
  437. code_position = header_position = -1;
  438. code_position_end = header_position_end = -1;
  439. }
  440. static void fixvisible(Fl_Type *p) {
  441. Fl_Type *t = p;
  442. for (;;) {
  443. if (t->parent) t->visible = t->parent->visible && t->parent->open_;
  444. else t->visible = 1;
  445. t = t->next;
  446. if (!t || t->level <= p->level) break;
  447. }
  448. }
  449. // turn a click at x,y on this into the actual picked object:
  450. Fl_Type* Fl_Type::click_test(int,int) {return 0;}
  451. void Fl_Type::add_child(Fl_Type*, Fl_Type*) {}
  452. void Fl_Type::move_child(Fl_Type*, Fl_Type*) {}
  453. void Fl_Type::remove_child(Fl_Type*) {}
  454. // add a list of widgets as a new child of p:
  455. void Fl_Type::add(Fl_Type *p) {
  456. if (p && parent == p) return;
  457. undo_checkpoint();
  458. parent = p;
  459. Fl_Type *end = this;
  460. while (end->next) end = end->next;
  461. Fl_Type *q;
  462. int newlevel;
  463. if (p) {
  464. for (q = p->next; q && q->level > p->level; q = q->next);
  465. newlevel = p->level+1;
  466. } else {
  467. q = 0;
  468. newlevel = 0;
  469. }
  470. for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level);
  471. level = newlevel;
  472. if (q) {
  473. prev = q->prev;
  474. prev->next = this;
  475. q->prev = end;
  476. end->next = q;
  477. } else if (first) {
  478. prev = last;
  479. prev->next = this;
  480. end->next = 0;
  481. last = end;
  482. } else {
  483. first = this;
  484. last = end;
  485. prev = end->next = 0;
  486. }
  487. if (p) p->add_child(this,0);
  488. open_ = 1;
  489. fixvisible(this);
  490. set_modflag(1);
  491. widget_browser->redraw();
  492. }
  493. // add to a parent before another widget:
  494. void Fl_Type::insert(Fl_Type *g) {
  495. Fl_Type *end = this;
  496. while (end->next) end = end->next;
  497. parent = g->parent;
  498. int newlevel = g->level;
  499. visible = g->visible;
  500. for (Fl_Type *t = this->next; t; t = t->next) t->level += newlevel-level;
  501. level = newlevel;
  502. prev = g->prev;
  503. if (prev) prev->next = this; else first = this;
  504. end->next = g;
  505. g->prev = end;
  506. fixvisible(this);
  507. if (parent) parent->add_child(this, g);
  508. widget_browser->redraw();
  509. }
  510. // Return message number for I18N...
  511. int
  512. Fl_Type::msgnum() {
  513. int count;
  514. Fl_Type *p;
  515. for (count = 0, p = this; p;) {
  516. if (p->label()) count ++;
  517. if (p != this && p->is_widget() && ((Fl_Widget_Type *)p)->tooltip()) count ++;
  518. if (p->prev) p = p->prev;
  519. else p = p->parent;
  520. }
  521. return count;
  522. }
  523. // delete from parent:
  524. Fl_Type *Fl_Type::remove() {
  525. Fl_Type *end = this;
  526. for (;;) {
  527. if (!end->next || end->next->level <= level) break;
  528. end = end->next;
  529. }
  530. if (prev) prev->next = end->next;
  531. else first = end->next;
  532. if (end->next) end->next->prev = prev;
  533. else last = prev;
  534. Fl_Type *r = end->next;
  535. prev = end->next = 0;
  536. if (parent) parent->remove_child(this);
  537. parent = 0;
  538. widget_browser->redraw();
  539. selection_changed(0);
  540. return r;
  541. }
  542. // update a string member:
  543. int storestring(const char *n, const char * & p, int nostrip) {
  544. if (n == p) return 0;
  545. undo_checkpoint();
  546. int length = 0;
  547. if (n) { // see if blank, strip leading & trailing blanks
  548. if (!nostrip) while (isspace((int)(unsigned char)*n)) n++;
  549. const char *e = n + strlen(n);
  550. if (!nostrip) while (e > n && isspace((int)(unsigned char)*(e-1))) e--;
  551. length = e-n;
  552. if (!length) n = 0;
  553. }
  554. if (n == p) return 0;
  555. if (n && p && !strncmp(n,p,length) && !p[length]) return 0;
  556. if (p) free((void *)p);
  557. if (!n || !*n) {
  558. p = 0;
  559. } else {
  560. char *q = (char *)malloc(length+1);
  561. strlcpy(q,n,length+1);
  562. p = q;
  563. }
  564. set_modflag(1);
  565. return 1;
  566. }
  567. void Fl_Type::name(const char *n) {
  568. int nostrip = is_comment();
  569. if (storestring(n,name_,nostrip)) {
  570. if (visible) widget_browser->redraw();
  571. }
  572. }
  573. void Fl_Type::macro_name(const char *n) {
  574. storestring(n,macro_name_);
  575. macro_name2name();
  576. }
  577. const char *Fl_Type::macro_name2name() {
  578. if(macro_name_){
  579. char buf[256];
  580. snprintf(buf, sizeof(buf), "%s", macro_name_);
  581. for(char *p=buf; *p; ++p){
  582. if(*p == ' ') *p = '_';
  583. }
  584. name(buf);
  585. }
  586. return name_;
  587. }
  588. void Fl_Type::dirty_name(const char *n) {
  589. storestring(n,dirty_name_);
  590. }
  591. void Fl_Type::label(const char *n) {
  592. if (storestring(n,label_,1)) {
  593. setlabel(label_);
  594. if (visible && !name_) widget_browser->redraw();
  595. }
  596. }
  597. void Fl_Type::callback(const char *n) {
  598. storestring(n,callback_);
  599. }
  600. void Fl_Type::user_data(const char *n) {
  601. storestring(n,user_data_);
  602. }
  603. void Fl_Type::user_data_type(const char *n) {
  604. storestring(n,user_data_type_);
  605. }
  606. void Fl_Type::comment(const char *n) {
  607. storestring(n, comment_, 1);
  608. }
  609. void Fl_Type::open() {
  610. printf("Open of '%s' is not yet implemented\n",type_name());
  611. }
  612. void Fl_Type::setlabel(const char *) {}
  613. Fl_Type::~Fl_Type() {
  614. // warning: destructor only works for widgets that have been add()ed.
  615. if (widget_browser) widget_browser->deleting(this);
  616. if (prev) prev->next = next; else first = next;
  617. if (next) next->prev = prev; else last = prev;
  618. if (current == this) current = 0;
  619. if (parent) parent->remove_child(this);
  620. if (name_) free((void*)name_);
  621. if (macro_name_) free((void*)macro_name_);
  622. if (dirty_name_) free((void*)dirty_name_);
  623. if (label_) free((void*)label_);
  624. if (callback_) free((void*)callback_);
  625. if (user_data_) free((void*)user_data_);
  626. if (user_data_type_) free((void*)user_data_type_);
  627. if (comment_) free((void*)comment_);
  628. }
  629. int Fl_Type::is_parent() const {return 0;}
  630. int Fl_Type::is_widget() const {return 0;}
  631. int Fl_Type::is_valuator() const {return 0;}
  632. int Fl_Type::is_spinner() const {return 0;}
  633. int Fl_Type::is_button() const {return 0;}
  634. int Fl_Type::is_input() const {return 0;}
  635. int Fl_Type::is_value_input() const {return 0;}
  636. int Fl_Type::is_text_display() const {return 0;}
  637. int Fl_Type::is_menu_item() const {return 0;}
  638. int Fl_Type::is_menu_button() const {return 0;}
  639. int Fl_Type::is_group() const {return 0;}
  640. int Fl_Type::is_window() const {return 0;}
  641. int Fl_Type::is_code_block() const {return 0;}
  642. int Fl_Type::is_decl_block() const {return 0;}
  643. int Fl_Type::is_comment() const {return 0;}
  644. int Fl_Type::is_class() const {return 0;}
  645. int Fl_Type::is_public() const {return 1;}
  646. int Fl_Code_Type::is_public()const { return -1; }
  647. int Fl_CodeBlock_Type::is_public()const { return -1; }
  648. ////////////////////////////////////////////////////////////////
  649. Fl_Type *in_this_only; // set if menu popped-up in window
  650. void select_all_cb(Fl_Widget *,void *) {
  651. Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
  652. if (in_this_only) {
  653. Fl_Type *t = p;
  654. for (; t && t != in_this_only; t = t->parent);
  655. if (t != in_this_only) p = in_this_only;
  656. }
  657. for (;;) {
  658. if (p) {
  659. int foundany = 0;
  660. for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
  661. if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;}
  662. }
  663. if (foundany) break;
  664. p = p->parent;
  665. } else {
  666. for (Fl_Type *t = Fl_Type::first; t; t = t->next)
  667. widget_browser->select(t,1,0);
  668. break;
  669. }
  670. }
  671. selection_changed(p);
  672. }
  673. void select_none_cb(Fl_Widget *,void *) {
  674. Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
  675. if (in_this_only) {
  676. Fl_Type *t = p;
  677. for (; t && t != in_this_only; t = t->parent);
  678. if (t != in_this_only) p = in_this_only;
  679. }
  680. for (;;) {
  681. if (p) {
  682. int foundany = 0;
  683. for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
  684. if (t->new_selected) {widget_browser->select(t,0,0); foundany = 1;}
  685. }
  686. if (foundany) break;
  687. p = p->parent;
  688. } else {
  689. for (Fl_Type *t = Fl_Type::first; t; t = t->next)
  690. widget_browser->select(t,0,0);
  691. break;
  692. }
  693. }
  694. selection_changed(p);
  695. }
  696. static void delete_children(Fl_Type *p) {
  697. Fl_Type *f;
  698. for (f = p; f && f->next && f->next->level > p->level; f = f->next);
  699. for (; f != p; ) {
  700. Fl_Type *g = f->prev;
  701. delete f;
  702. f = g;
  703. }
  704. }
  705. void delete_all(int selected_only) {
  706. for (Fl_Type *f = Fl_Type::first; f;) {
  707. if (f->selected || !selected_only) {
  708. delete_children(f);
  709. Fl_Type *g = f->next;
  710. delete f;
  711. f = g;
  712. } else f = f->next;
  713. }
  714. if(!selected_only) {
  715. include_H_from_C=1;
  716. use_FL_COMMAND=0;
  717. }
  718. selection_changed(0);
  719. }
  720. // move f (and it's children) into list before g:
  721. // returns pointer to whatever is after f & children
  722. void Fl_Type::move_before(Fl_Type* g) {
  723. if (level != g->level) printf("move_before levels don't match! %d %d\n",
  724. level, g->level);
  725. Fl_Type* n;
  726. for (n = next; n && n->level > level; n = n->next);
  727. if (n == g) return;
  728. Fl_Type *l = n ? n->prev : Fl_Type::last;
  729. prev->next = n;
  730. if (n) n->prev = prev; else Fl_Type::last = prev;
  731. prev = g->prev;
  732. l->next = g;
  733. if (prev) prev->next = this; else Fl_Type::first = this;
  734. g->prev = l;
  735. if (parent && is_widget()) parent->move_child(this,g);
  736. widget_browser->inserting(g, this);
  737. widget_browser->display(this);
  738. widget_browser->redraw();
  739. }
  740. // move selected widgets in their parent's list:
  741. void earlier_cb(Fl_Widget*,void*) {
  742. Fl_Type *f;
  743. int mod = 0;
  744. for (f = Fl_Type::first; f; ) {
  745. Fl_Type* nxt = f->next;
  746. if (f->selected) {
  747. Fl_Type* g;
  748. for (g = f->prev; g && g->level > f->level; g = g->prev);
  749. if (g && g->level == f->level && !g->selected) {
  750. f->move_before(g);
  751. mod = 1;
  752. }
  753. }
  754. f = nxt;
  755. }
  756. if (mod) set_modflag(1);
  757. }
  758. void later_cb(Fl_Widget*,void*) {
  759. Fl_Type *f;
  760. int mod = 0;
  761. for (f = Fl_Type::last; f; ) {
  762. Fl_Type* prv = f->prev;
  763. if (f->selected) {
  764. Fl_Type* g;
  765. for (g = f->next; g && g->level > f->level; g = g->next);
  766. if (g && g->level == f->level && !g->selected) {
  767. g->move_before(f);
  768. mod = 1;
  769. }
  770. }
  771. f = prv;
  772. }
  773. if (mod) set_modflag(1);
  774. }
  775. ////////////////////////////////////////////////////////////////
  776. // write a widget and all it's children:
  777. void Fl_Type::write() {
  778. write_indent(level);
  779. write_word(type_name());
  780. if (is_class()) {
  781. const char * p = ((Fl_Class_Type*)this)->prefix();
  782. if (p && strlen(p))
  783. write_word(p);
  784. }
  785. write_word(name());
  786. write_open(level);
  787. write_properties();
  788. write_close(level);
  789. if (!is_parent()) return;
  790. // now do children:
  791. write_open(level);
  792. Fl_Type *child;
  793. for (child = next; child && child->level > level; child = child->next)
  794. if (child->level == level+1) child->write();
  795. write_close(level);
  796. }
  797. void Fl_Type::write_properties() {
  798. // repeat this for each attribute:
  799. if (label()) {
  800. write_indent(level+1);
  801. write_word("label");
  802. write_word(label());
  803. }
  804. if (user_data()) {
  805. write_indent(level+1);
  806. write_word("user_data");
  807. write_word(user_data());
  808. }
  809. if (user_data_type()) {
  810. write_word("user_data_type");
  811. write_word(user_data_type());
  812. }
  813. if (callback()) {
  814. write_indent(level+1);
  815. write_word("callback");
  816. write_word(callback());
  817. }
  818. if (comment()) {
  819. write_indent(level+1);
  820. write_word("comment");
  821. write_word(comment());
  822. }
  823. if (macro_name()) {
  824. write_indent(level+1);
  825. write_word("macro_name");
  826. write_word(macro_name());
  827. }
  828. if (dirty_name()) {
  829. write_indent(level+1);
  830. write_word("dirty_name");
  831. write_word(dirty_name());
  832. }
  833. if (is_parent() && open_) write_word("open");
  834. if (selected) write_word("selected");
  835. }
  836. void Fl_Type::read_property(const char *c) {
  837. if (!strcmp(c,"label"))
  838. label(read_word());
  839. else if (!strcmp(c,"user_data"))
  840. user_data(read_word());
  841. else if (!strcmp(c,"user_data_type"))
  842. user_data_type(read_word());
  843. else if (!strcmp(c,"callback"))
  844. callback(read_word());
  845. else if (!strcmp(c,"comment"))
  846. comment(read_word());
  847. else if (!strcmp(c,"macro_name"))
  848. macro_name(read_word());
  849. else if (!strcmp(c,"dirty_name"))
  850. dirty_name(read_word());
  851. else if (!strcmp(c,"open"))
  852. open_ = 1;
  853. else if (!strcmp(c,"selected"))
  854. select(this,1);
  855. else
  856. read_error("Unknown property \"%s\"", c);
  857. }
  858. int Fl_Type::read_fdesign(const char*, const char*) {return 0;}
  859. /**
  860. * Return 1 if the list contains a function with the given signature at the top level
  861. */
  862. int has_toplevel_function(const char *rtype, const char *sig) {
  863. Fl_Type *child;
  864. for (child = Fl_Type::first; child; child = child->next) {
  865. if (!child->is_in_class() && strcmp(child->type_name(), "Function")==0) {
  866. const Fl_Function_Type *fn = (const Fl_Function_Type*)child;
  867. if (fn->has_signature(rtype, sig))
  868. return 1;
  869. }
  870. }
  871. return 0;
  872. }
  873. /**
  874. * Write a comment inot the header file.
  875. */
  876. void Fl_Type::write_comment_h(const char *pre)
  877. {
  878. if (comment()) {
  879. write_h("%s/**\n", pre);
  880. const char *s = comment();
  881. write_h("%s ", pre);
  882. while(*s) {
  883. if (*s=='\n') {
  884. if (s[1]) {
  885. write_h("\n%s ", pre);
  886. }
  887. } else {
  888. write_h("%c", *s); // FIXME this is much too slow!
  889. }
  890. s++;
  891. }
  892. write_h("\n%s*/\n", pre);
  893. }
  894. }
  895. /**
  896. * Write a comment inot the header file.
  897. */
  898. void Fl_Type::write_comment_c(const char *pre)
  899. {
  900. if (comment()) {
  901. write_c("%s/**\n", pre);
  902. const char *s = comment();
  903. write_c("%s ", pre);
  904. while(*s) {
  905. if (*s=='\n') {
  906. if (s[1]) {
  907. write_c("\n%s ", pre);
  908. }
  909. } else {
  910. write_c("%c", *s); // FIXME this is much too slow!
  911. }
  912. s++;
  913. }
  914. write_c("\n%s*/\n", pre);
  915. }
  916. }
  917. /**
  918. * Make sure that the given item is visible in the browser by opening
  919. * all parent groups and moving the item into the visible space.
  920. */
  921. void reveal_in_browser(Fl_Type *t) {
  922. Fl_Type *p = t->parent;
  923. if (p) {
  924. for (;;) {
  925. if (!p->open_)
  926. p->open_ = 1;
  927. if (!p->parent) break;
  928. p = p->parent;
  929. }
  930. fixvisible(p);
  931. }
  932. widget_browser->display(t);
  933. redraw_browser();
  934. }
  935. /**
  936. * Build widgets and dataset needed in live mode.
  937. * \return a widget pointer that the live mode initiator can 'show()'
  938. * \see leave_live_mode()
  939. */
  940. Fl_Widget *Fl_Type::enter_live_mode(int) {
  941. return 0L;
  942. }
  943. /**
  944. * Release all resources created when enetring live mode.
  945. * \see enter_live_mode()
  946. */
  947. void Fl_Type::leave_live_mode() {
  948. }
  949. /**
  950. * Copy all needed properties for this tye into the live object.
  951. */
  952. void Fl_Type::copy_properties() {
  953. }
  954. /**
  955. * Check whether callback name is declared anywhere else by the user
  956. *
  957. * \b Warning: this just checks that the name is declared somewhere,
  958. * but it should probably also check that the name corresponds to a
  959. * plain function or a member function within the same class and that
  960. * the parameter types match.
  961. */
  962. int Fl_Type::user_defined(const char* cbname) const {
  963. for (Fl_Type* p = Fl_Type::first; p ; p = p->next)
  964. if (strcmp(p->type_name(), "Function") == 0 && p->name() != 0)
  965. if (strncmp(p->name(), cbname, strlen(cbname)) == 0)
  966. if (p->name()[strlen(cbname)] == '(')
  967. return 1;
  968. return 0;
  969. }
  970. //
  971. // End of "$Id: Fl_Type.cxx 9992 2013-09-24 19:58:24Z greg.ercolano $".
  972. //