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.

542 lines
14KB

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