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.

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