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.

215 lines
5.9KB

  1. //
  2. // "$Id: Fl_Tile.cxx 7903 2010-11-28 21:06:39Z matt $"
  3. //
  4. // Tile widget 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. // Group of 2 or 4 "tiles" that can be resized by dragging border
  28. // The size of the first child determines where the resize border is.
  29. // The resizebox is used to limit where the border can be dragged to.
  30. #include <FL/Fl.H>
  31. #include <FL/Fl_Tile.H>
  32. #include <FL/Fl_Window.H>
  33. #include <stdlib.h>
  34. // Drag the edges that were initially at oldx,oldy to newx,newy:
  35. // pass zero as oldx or oldy to disable drag in that direction:
  36. /**
  37. Drag the intersection at from_x,from_y to to_x,to_y.
  38. This redraws all the necessary children.
  39. */
  40. void Fl_Tile::position(int oix, int oiy, int newx, int newy) {
  41. Fl_Widget*const* a = array();
  42. int *p = sizes();
  43. p += 8; // skip group & resizable's saved size
  44. for (int i=children(); i--; p += 4) {
  45. Fl_Widget* o = *a++;
  46. if (o == resizable()) continue;
  47. int X = o->x();
  48. int R = X+o->w();
  49. if (oix) {
  50. int t = p[0];
  51. if (t == oix || (t>oix && X<newx) || (t<oix && X>newx) ) X = newx;
  52. t = p[1];
  53. if (t == oix || (t>oix && R<newx) || (t<oix && R>newx) ) R = newx;
  54. }
  55. int Y = o->y();
  56. int B = Y+o->h();
  57. if (oiy) {
  58. int t = p[2];
  59. if (t == oiy || (t>oiy && Y<newy) || (t<oiy && Y>newy) ) Y = newy;
  60. t = p[3];
  61. if (t == oiy || (t>oiy && B<newy) || (t<oiy && B>newy) ) B = newy;
  62. }
  63. o->damage_resize(X,Y,R-X,B-Y);
  64. }
  65. }
  66. // move the lower-right corner (sort of):
  67. void Fl_Tile::resize(int X,int Y,int W,int H) {
  68. //Fl_Group::resize(X, Y, W, H);
  69. //return;
  70. // remember how much to move the child widgets:
  71. int dx = X-x();
  72. int dy = Y-y();
  73. int dw = W-w();
  74. int dh = H-h();
  75. int *p = sizes();
  76. // resize this (skip the Fl_Group resize):
  77. Fl_Widget::resize(X,Y,W,H);
  78. // find bottom-right of resiable:
  79. int OR = p[5];
  80. int NR = X+W-(p[1]-OR);
  81. int OB = p[7];
  82. int NB = Y+H-(p[3]-OB);
  83. // move everything to be on correct side of new resizable:
  84. Fl_Widget*const* a = array();
  85. p += 8;
  86. for (int i=children(); i--;) {
  87. Fl_Widget* o = *a++;
  88. int xx = o->x()+dx;
  89. int R = xx+o->w();
  90. if (*p++ >= OR) xx += dw; else if (xx > NR) xx = NR;
  91. if (*p++ >= OR) R += dw; else if (R > NR) R = NR;
  92. int yy = o->y()+dy;
  93. int B = yy+o->h();
  94. if (*p++ >= OB) yy += dh; else if (yy > NB) yy = NB;
  95. if (*p++ >= OB) B += dh; else if (B > NB) B = NB;
  96. o->resize(xx,yy,R-xx,B-yy);
  97. // do *not* call o->redraw() here! If you do, and the tile is inside a
  98. // scroll, it'll set the damage areas wrong for all children!
  99. }
  100. }
  101. static void set_cursor(Fl_Tile*t, Fl_Cursor c) {
  102. static Fl_Cursor cursor;
  103. if (cursor == c || !t->window()) return;
  104. cursor = c;
  105. #ifdef __sgi
  106. t->window()->cursor(c,FL_RED,FL_WHITE);
  107. #else
  108. t->window()->cursor(c);
  109. #endif
  110. }
  111. static Fl_Cursor cursors[4] = {
  112. FL_CURSOR_DEFAULT,
  113. FL_CURSOR_WE,
  114. FL_CURSOR_NS,
  115. FL_CURSOR_MOVE};
  116. int Fl_Tile::handle(int event) {
  117. static int sdrag;
  118. static int sdx, sdy;
  119. static int sx, sy;
  120. #define DRAGH 1
  121. #define DRAGV 2
  122. #define GRABAREA 4
  123. int mx = Fl::event_x();
  124. int my = Fl::event_y();
  125. switch (event) {
  126. case FL_MOVE:
  127. case FL_ENTER:
  128. case FL_PUSH:
  129. // don't potentially change the mouse cursor if inactive:
  130. if (!active()) break; // will cascade inherited handle()
  131. {
  132. int mindx = 100;
  133. int mindy = 100;
  134. int oldx = 0;
  135. int oldy = 0;
  136. Fl_Widget*const* a = array();
  137. int *q = sizes();
  138. int *p = q+8;
  139. for (int i=children(); i--; p += 4) {
  140. Fl_Widget* o = *a++;
  141. if (o == resizable()) continue;
  142. if (p[1]<q[1] && o->y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) {
  143. int t = mx - (o->x()+o->w());
  144. if (abs(t) < mindx) {
  145. sdx = t;
  146. mindx = abs(t);
  147. oldx = p[1];
  148. }
  149. }
  150. if (p[3]<q[3] && o->x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) {
  151. int t = my - (o->y()+o->h());
  152. if (abs(t) < mindy) {
  153. sdy = t;
  154. mindy = abs(t);
  155. oldy = p[3];
  156. }
  157. }
  158. }
  159. sdrag = 0; sx = sy = 0;
  160. if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;}
  161. if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;}
  162. set_cursor(this, cursors[sdrag]);
  163. if (sdrag) return 1;
  164. return Fl_Group::handle(event);
  165. }
  166. case FL_LEAVE:
  167. set_cursor(this, FL_CURSOR_DEFAULT);
  168. break;
  169. case FL_DRAG:
  170. // This is necessary if CONSOLIDATE_MOTION in Fl_x.cxx is turned off:
  171. // if (damage()) return 1; // don't fall behind
  172. case FL_RELEASE: {
  173. if (!sdrag) return 0; // should not happen
  174. Fl_Widget* r = resizable(); if (!r) r = this;
  175. int newx;
  176. if (sdrag&DRAGH) {
  177. newx = Fl::event_x()-sdx;
  178. if (newx < r->x()) newx = r->x();
  179. else if (newx > r->x()+r->w()) newx = r->x()+r->w();
  180. } else
  181. newx = sx;
  182. int newy;
  183. if (sdrag&DRAGV) {
  184. newy = Fl::event_y()-sdy;
  185. if (newy < r->y()) newy = r->y();
  186. else if (newy > r->y()+r->h()) newy = r->y()+r->h();
  187. } else
  188. newy = sy;
  189. position(sx,sy,newx,newy);
  190. if (event == FL_DRAG) set_changed();
  191. do_callback();
  192. return 1;}
  193. }
  194. return Fl_Group::handle(event);
  195. }
  196. //
  197. // End of "$Id: Fl_Tile.cxx 7903 2010-11-28 21:06:39Z matt $".
  198. //