align_widget.cxx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. //
  2. // "$Id: align_widget.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $"
  3. //
  4. // Alignment code for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2010 by Bill Spitzak and others.
  7. //
  8. // This library is free software. Distribution and use rights are outlined in
  9. // the file "COPYING" which should have been included with this file. If this
  10. // file is missing or damaged, see the license at:
  11. //
  12. // http://www.fltk.org/COPYING.php
  13. //
  14. // Please report all bugs and problems on the following page:
  15. //
  16. // http://www.fltk.org/str.php
  17. //
  18. #include <FL/Fl.H>
  19. #include <FL/Fl_Window.H>
  20. #include "Fl_Widget_Type.h"
  21. #include "undo.h"
  22. /**
  23. * the first behaviour always uses the first selected widget as a reference
  24. * the second behaviour uses the largest widget (most extreme positions) as
  25. * a reference.
  26. */
  27. #define BREAK_ON_FIRST break
  28. //#define BREAK_ON_FIRST
  29. void align_widget_cb(Fl_Widget*, long how)
  30. {
  31. const int max = 32768, min = -32768;
  32. int left, right, top, bot, wdt, hgt, n;
  33. int fill_parent, use_parent, parent_is_window, use_x, use_y;
  34. Fl_Type *o;
  35. int changed = 0;
  36. switch ( how )
  37. {
  38. //---- align
  39. case 10: // align left
  40. left = max;
  41. for (o = Fl_Type::first; o; o = o->next)
  42. if (o->selected && o->is_widget())
  43. {
  44. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  45. if (w->x()<left)
  46. left = w->x();
  47. BREAK_ON_FIRST;
  48. }
  49. if (left!=max)
  50. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  51. if (o->selected && o->is_widget())
  52. {
  53. if (!changed) {
  54. changed = 1;
  55. set_modflag(1);
  56. undo_checkpoint();
  57. }
  58. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  59. if (o->next && o->next->level > o->level && !o->next->selected &&
  60. !o->is_menu_button()) {
  61. // When resizing a group, make sure we also move the children...
  62. ((igroup *)w)->full_resize(left, w->y(), w->w(), w->h());
  63. } else {
  64. // Otherwise, just do the widget...
  65. w->resize(left, w->y(), w->w(), w->h());
  66. }
  67. w->redraw();
  68. if (w->window()) w->window()->redraw();
  69. }
  70. break;
  71. case 11: // align h.center
  72. left = max; right = min;
  73. for (o = Fl_Type::first; o; o = o->next)
  74. if (o->selected && o->is_widget())
  75. {
  76. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  77. if (w->x()<left)
  78. left = w->x();
  79. if (w->x()+w->w()>right)
  80. right = w->x()+w->w();
  81. BREAK_ON_FIRST;
  82. }
  83. if (left!=max)
  84. {
  85. int center2 = left+right;
  86. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  87. if (o->selected && o->is_widget())
  88. {
  89. if (!changed) {
  90. changed = 1;
  91. set_modflag(1);
  92. undo_checkpoint();
  93. }
  94. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  95. if (o->next && o->next->level > o->level && !o->next->selected &&
  96. !o->is_menu_button()) {
  97. // When resizing a group, make sure we also move the children...
  98. ((igroup *)w)->full_resize((center2-w->w())/2, w->y(), w->w(), w->h());
  99. } else {
  100. // Otherwise, just do the widget...
  101. w->resize((center2-w->w())/2, w->y(), w->w(), w->h());
  102. }
  103. w->redraw();
  104. if (w->window()) w->window()->redraw();
  105. }
  106. }
  107. break;
  108. case 12: // align right
  109. right = min;
  110. for (o = Fl_Type::first; o; o = o->next)
  111. if (o->selected && o->is_widget())
  112. {
  113. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  114. if (w->x()+w->w()>right)
  115. right = w->x()+w->w();
  116. BREAK_ON_FIRST;
  117. }
  118. if (right!=min)
  119. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  120. if (o->selected && o->is_widget())
  121. {
  122. if (!changed) {
  123. changed = 1;
  124. set_modflag(1);
  125. undo_checkpoint();
  126. }
  127. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  128. if (o->next && o->next->level > o->level && !o->next->selected &&
  129. !o->is_menu_button()) {
  130. // When resizing a group, make sure we also move the children...
  131. ((igroup *)w)->full_resize(right-w->w(), w->y(), w->w(), w->h());
  132. } else {
  133. // Otherwise, just do the widget...
  134. w->resize(right-w->w(), w->y(), w->w(), w->h());
  135. }
  136. w->redraw();
  137. if (w->window()) w->window()->redraw();
  138. }
  139. break;
  140. case 13: // align top
  141. top = max;
  142. for (o = Fl_Type::first; o; o = o->next)
  143. if (o->selected && o->is_widget())
  144. {
  145. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  146. if (w->y()<top)
  147. top = w->y();
  148. BREAK_ON_FIRST;
  149. }
  150. if (top!=max)
  151. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  152. if (o->selected && o->is_widget())
  153. {
  154. if (!changed) {
  155. changed = 1;
  156. set_modflag(1);
  157. undo_checkpoint();
  158. }
  159. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  160. if (o->next && o->next->level > o->level && !o->next->selected &&
  161. !o->is_menu_button()) {
  162. // When resizing a group, make sure we also move the children...
  163. ((igroup *)w)->full_resize(w->x(), top, w->w(), w->h());
  164. } else {
  165. // Otherwise, just do the widget...
  166. w->resize(w->x(), top, w->w(), w->h());
  167. }
  168. w->redraw();
  169. if (w->window()) w->window()->redraw();
  170. }
  171. break;
  172. case 14: // align v.center
  173. top = max; bot = min;
  174. for (o = Fl_Type::first; o; o = o->next)
  175. if (o->selected && o->is_widget())
  176. {
  177. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  178. if (w->y()<top)
  179. top = w->y();
  180. if (w->y()+w->h()>bot)
  181. bot = w->y()+w->h();
  182. BREAK_ON_FIRST;
  183. }
  184. if (top!=max)
  185. {
  186. int center2 = top+bot;
  187. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  188. if (o->selected && o->is_widget())
  189. {
  190. if (!changed) {
  191. changed = 1;
  192. set_modflag(1);
  193. undo_checkpoint();
  194. }
  195. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  196. if (o->next && o->next->level > o->level && !o->next->selected &&
  197. !o->is_menu_button()) {
  198. // When resizing a group, make sure we also move the children...
  199. ((igroup *)w)->full_resize(w->x(), (center2-w->h())/2, w->w(), w->h());
  200. } else {
  201. // Otherwise, just do the widget...
  202. w->resize(w->x(), (center2-w->h())/2, w->w(), w->h());
  203. }
  204. w->redraw();
  205. if (w->window()) w->window()->redraw();
  206. }
  207. }
  208. break;
  209. case 15: // align bottom
  210. bot = min;
  211. for (o = Fl_Type::first; o; o = o->next)
  212. if (o->selected && o->is_widget())
  213. {
  214. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  215. if (w->y()+w->h()>bot)
  216. bot = w->y()+w->h();
  217. BREAK_ON_FIRST;
  218. }
  219. if (bot!=min)
  220. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  221. if (o->selected && o->is_widget())
  222. {
  223. if (!changed) {
  224. changed = 1;
  225. set_modflag(1);
  226. undo_checkpoint();
  227. }
  228. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  229. if (o->next && o->next->level > o->level && !o->next->selected &&
  230. !o->is_menu_button()) {
  231. // When resizing a group, make sure we also move the children...
  232. ((igroup *)w)->full_resize( w->x(), bot-w->h(), w->w(), w->h());
  233. } else {
  234. // Otherwise, just do the widget...
  235. w->resize( w->x(), bot-w->h(), w->w(), w->h());
  236. }
  237. w->redraw();
  238. if (w->window()) w->window()->redraw();
  239. }
  240. break;
  241. //---- space evently
  242. case 20: // space evenly across
  243. left = max; right = min; wdt = 0, n = 0;
  244. for (o = Fl_Type::first; o; o = o->next)
  245. if (o->selected && o->is_widget())
  246. {
  247. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  248. if (w->x()<left)
  249. left = w->x();
  250. if (w->x()+w->w()>right)
  251. right = w->x()+w->w();
  252. wdt += w->w();
  253. n++;
  254. }
  255. wdt = (right-left)-wdt;
  256. n--;
  257. if (n>0)
  258. {
  259. int cnt = 0, wsum = 0;
  260. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  261. if (o->selected && o->is_widget())
  262. {
  263. if (!changed) {
  264. changed = 1;
  265. set_modflag(1);
  266. undo_checkpoint();
  267. }
  268. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  269. if (o->next && o->next->level > o->level && !o->next->selected &&
  270. !o->is_menu_button()) {
  271. // When resizing a group, make sure we also move the children...
  272. ((igroup *)w)->full_resize(left+wsum+wdt*cnt/n, w->y(), w->w(), w->h());
  273. } else {
  274. // Otherwise, just do the widget...
  275. w->resize(left+wsum+wdt*cnt/n, w->y(), w->w(), w->h());
  276. }
  277. w->redraw();
  278. if (w->window()) w->window()->redraw();
  279. cnt++;
  280. wsum += w->w();
  281. }
  282. }
  283. break;
  284. case 21: // space evenly down
  285. top = max; bot = min; hgt = 0, n = 0;
  286. for (o = Fl_Type::first; o; o = o->next)
  287. if (o->selected && o->is_widget())
  288. {
  289. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  290. if (w->y()<top)
  291. top = w->y();
  292. if (w->y()+w->h()>bot)
  293. bot = w->y()+w->h();
  294. hgt += w->h();
  295. n++;
  296. }
  297. hgt = (bot-top)-hgt;
  298. n--;
  299. if (n>0)
  300. {
  301. int cnt = 0, hsum = 0;
  302. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  303. if (o->selected && o->is_widget())
  304. {
  305. if (!changed) {
  306. changed = 1;
  307. set_modflag(1);
  308. undo_checkpoint();
  309. }
  310. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  311. if (o->next && o->next->level > o->level && !o->next->selected &&
  312. !o->is_menu_button()) {
  313. // When resizing a group, make sure we also move the children...
  314. ((igroup *)w)->full_resize(w->x(), top+hsum+hgt*cnt/n, w->w(), w->h());
  315. } else {
  316. // Otherwise, just do the widget...
  317. w->resize(w->x(), top+hsum+hgt*cnt/n, w->w(), w->h());
  318. }
  319. w->redraw();
  320. if (w->window()) w->window()->redraw();
  321. cnt++;
  322. hsum += w->h();
  323. }
  324. }
  325. break;
  326. //---- make same size
  327. case 30: // same width
  328. case 300: // same parent width
  329. //case 3000: // fill parent width same size
  330. //fill_parent = how == 3000;
  331. use_parent = parent_is_window = 0;
  332. wdt = min;
  333. for (o = Fl_Type::first; o; o = o->next)
  334. if (o->selected && o->is_widget())
  335. {
  336. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  337. if((how == 300) && w->parent()) {
  338. wdt = w->parent()->w();
  339. use_parent = 1;
  340. parent_is_window = !w->parent()->parent();
  341. }
  342. else if (w->w()>wdt) wdt = w->w();
  343. BREAK_ON_FIRST;
  344. }
  345. if (wdt!=min)
  346. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  347. if (o->selected && o->is_widget())
  348. {
  349. if (!changed) {
  350. changed = 1;
  351. set_modflag(1);
  352. undo_checkpoint();
  353. }
  354. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  355. use_x = use_parent ? (parent_is_window ? 0 : w->parent()->x()) : w->x();
  356. if (o->next && o->next->level > o->level && !o->next->selected &&
  357. !o->is_menu_button()) {
  358. // When resizing a group, make sure we also move the children...
  359. ((igroup *)w)->full_resize(use_x, w->y(), wdt, w->h());
  360. } else {
  361. // Otherwise, just do the widget...
  362. w->resize(use_x, w->y(), wdt, w->h());
  363. }
  364. w->redraw();
  365. if (w->window()) w->window()->redraw();
  366. }
  367. break;
  368. case 31: // same height
  369. case 310: // same parent height
  370. //case 3100: // fill parent same parent height
  371. //fill_parent = how == 3100;
  372. use_parent = parent_is_window = 0;
  373. hgt = min;
  374. for (o = Fl_Type::first; o; o = o->next)
  375. if (o->selected && o->is_widget())
  376. {
  377. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  378. if((how == 310) && w->parent()) {
  379. hgt = w->parent()->h();
  380. use_parent = 1;
  381. parent_is_window = !w->parent()->parent();
  382. }
  383. else if (w->h()>hgt) hgt = w->h();
  384. BREAK_ON_FIRST;
  385. }
  386. if (hgt!=min)
  387. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  388. if (o->selected && o->is_widget())
  389. {
  390. if (!changed) {
  391. changed = 1;
  392. set_modflag(1);
  393. undo_checkpoint();
  394. }
  395. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  396. use_y = use_parent ? (parent_is_window ? 0 : w->parent()->y()) : w->y();
  397. if (o->next && o->next->level > o->level && !o->next->selected &&
  398. !o->is_menu_button()) {
  399. // When resizing a group, make sure we also move the children...
  400. ((igroup *)w)->full_resize( w->x(), use_y, w->w(), hgt);
  401. } else {
  402. // Otherwise, just do the widget...
  403. w->resize( w->x(), use_y, w->w(), hgt);
  404. }
  405. w->redraw();
  406. if (w->window()) w->window()->redraw();
  407. }
  408. break;
  409. case 32: // same size
  410. case 320: // same parent size
  411. //case 3200: // fill parent same parent size
  412. //fill_parent = how == 3200;
  413. use_parent = parent_is_window = 0;
  414. hgt = min; wdt = min;
  415. for (o = Fl_Type::first; o; o = o->next)
  416. if (o->selected && o->is_widget())
  417. {
  418. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  419. if((how == 320) && w->parent()) {
  420. use_parent = 1;
  421. parent_is_window = !w->parent()->parent();
  422. wdt = w->parent()->w();
  423. hgt = w->parent()->h();
  424. } else {
  425. if (w->w()>wdt)
  426. wdt = w->w();
  427. if (w->h()>hgt)
  428. hgt = w->h();
  429. }
  430. BREAK_ON_FIRST;
  431. }
  432. if (hgt!=min)
  433. for (Fl_Type *o = Fl_Type::first; o; o = o->next)
  434. if (o->selected && o->is_widget())
  435. {
  436. if (!changed) {
  437. changed = 1;
  438. set_modflag(1);
  439. undo_checkpoint();
  440. }
  441. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  442. use_x = use_parent ? (parent_is_window ? 0 : w->parent()->x()) : w->x();
  443. use_y = use_parent ? (parent_is_window ? 0 : w->parent()->y()) : w->y();
  444. if (o->next && o->next->level > o->level && !o->next->selected &&
  445. !o->is_menu_button()) {
  446. // When resizing a group, make sure we also move the children...
  447. ((igroup *)w)->full_resize(use_x , use_y, wdt, hgt);
  448. } else {
  449. // Otherwise, just do the widget...
  450. w->resize(use_x , use_y, wdt, hgt);
  451. }
  452. w->redraw();
  453. if (w->window()) w->window()->redraw();
  454. }
  455. break;
  456. //---- center in group
  457. case 40: // center hor
  458. for (o = Fl_Type::first; o; o = o->next)
  459. if (o->selected && o->is_widget() && o->parent)
  460. {
  461. if (!changed) {
  462. changed = 1;
  463. set_modflag(1);
  464. undo_checkpoint();
  465. }
  466. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  467. Fl_Widget *p = ((Fl_Widget_Type *)o->parent)->o;
  468. int center2;
  469. if (w->window() == p) center2 = p->w();
  470. else center2 = 2*p->x()+p->w();
  471. if (o->next && o->next->level > o->level && !o->next->selected &&
  472. !o->is_menu_button() && !o->is_menu_button()) {
  473. // When resizing a group, make sure we also move the children...
  474. ((igroup *)w)->full_resize((center2-w->w())/2, w->y(), w->w(), w->h());
  475. } else {
  476. // Otherwise, just do the widget...
  477. w->resize((center2-w->w())/2, w->y(), w->w(), w->h());
  478. }
  479. w->redraw();
  480. if (w->window()) w->window()->redraw();
  481. }
  482. break;
  483. case 41: // center vert
  484. for (o = Fl_Type::first; o; o = o->next)
  485. if (o->selected && o->is_widget() && o->parent)
  486. {
  487. if (!changed) {
  488. changed = 1;
  489. set_modflag(1);
  490. undo_checkpoint();
  491. }
  492. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  493. Fl_Widget *p = ((Fl_Widget_Type *)o->parent)->o;
  494. int center2;
  495. if (w->window() == p) center2 = p->h();
  496. else center2 = 2*p->y()+p->h();
  497. if (o->next && o->next->level > o->level && !o->next->selected &&
  498. !o->is_menu_button()) {
  499. // When resizing a group, make sure we also move the children...
  500. ((igroup *)w)->full_resize(w->x(), (center2-w->h())/2, w->w(), w->h());
  501. } else {
  502. // Otherwise, just do the widget...
  503. w->resize(w->x(), (center2-w->h())/2, w->w(), w->h());
  504. }
  505. set_modflag(1);
  506. w->redraw();
  507. if (w->window()) w->window()->redraw();
  508. }
  509. break;
  510. }
  511. }
  512. // Set sizes of selected widgets...
  513. void widget_size_cb(Fl_Widget *, long size) {
  514. // Update any selected widgets...
  515. int changed = 0;
  516. for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
  517. if (o->selected && o->is_widget()) {
  518. if (!changed) {
  519. changed = 1;
  520. set_modflag(1);
  521. undo_checkpoint();
  522. }
  523. Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
  524. w->labelsize((Fl_Font)size);
  525. Fl_Font f;
  526. int s = (int)size;
  527. Fl_Color c;
  528. ((Fl_Widget_Type *)o)->textstuff(2, f, s, c);
  529. w->redraw();
  530. // since this may be a major change, the whole window should be redrawn
  531. if (w->window()) w->window()->redraw();
  532. }
  533. }
  534. }
  535. //
  536. // End of "$Id: align_widget.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $".
  537. //