You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1028 lines
28KB

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