summaryrefslogtreecommitdiff
path: root/src/Fl_Tile.cxx
diff options
context:
space:
mode:
authorMichael R Sweet <michael.r.sweet@gmail.com>1998-10-06 18:21:25 +0000
committerMichael R Sweet <michael.r.sweet@gmail.com>1998-10-06 18:21:25 +0000
commitf9039b2ae21988783feae9b362818e7923e82d14 (patch)
tree6d6fe3679d73448758f9794e7d4d4f6b22a4adad /src/Fl_Tile.cxx
parent67e89232f9ba067825a158734a09e0fa21aacbe3 (diff)
Initial revision
git-svn-id: file:///fltk/svn/fltk/trunk@2 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_Tile.cxx')
-rw-r--r--src/Fl_Tile.cxx173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/Fl_Tile.cxx b/src/Fl_Tile.cxx
new file mode 100644
index 000000000..d422b844d
--- /dev/null
+++ b/src/Fl_Tile.cxx
@@ -0,0 +1,173 @@
+// Fl_Tile.C - Group of 2 or 4 "tiles" that can be resized by dragging border
+
+// The size of the first child determines where the resize border is.
+// The resizebox is used to limit where the border can be dragged to.
+
+#include <FL/Fl.H>
+#include <FL/Fl_Tile.H>
+#include <FL/Fl_Window.H>
+#include <stdlib.h>
+
+// Drag the edges that were initially at oldx,oldy to newx,newy:
+// pass zero as oldx or oldy to disable drag in that direction:
+
+void Fl_Tile::position(int oix, int oiy, int newx, int newy) {
+ Fl_Widget*const* a = array();
+ short* p = sizes();
+ p += 8; // skip group & resizable's saved size
+ for (int i=children(); i--;) {
+ Fl_Widget* o = *a++;
+ if (o == resizable()) continue;
+ int X = o->x();
+ int R = X+o->w();
+ if (oix) {
+ int t = p[0];
+ if (t == oix || t>oix && X<newx || t<oix && X>newx) X = newx;
+ t = p[1];
+ if (t == oix || t>oix && R<newx || t<oix && R>newx) R = newx;
+ }
+ int Y = o->y();
+ int B = Y+o->h();
+ if (oiy) {
+ int t = p[2];
+ if (t == oiy || t>oiy && Y<newy || t<oiy && Y>newy) Y = newy;
+ t = p[3];
+ if (t == oiy || t>oiy && B<newy || t<oiy && B>newy) B = newy;
+ }
+ o->damage_resize(X,Y,R-X,B-Y);
+ p += 4;
+ }
+}
+
+// move the lower-right corner (sort of):
+void Fl_Tile::resize(int X,int Y,int W,int H) {
+ // remember how much to move the child widgets:
+ int dx = X-x();
+ int dy = Y-y();
+ int dw = W-w();
+ int dh = H-h();
+ short* p = sizes();
+ // resize this (skip the Fl_Group resize):
+ Fl_Widget::resize(X,Y,W,H);
+ // find bottom-right of resiable:
+ int OR = p[5];
+ int NR = X+W-(p[1]-OR);
+ int OB = p[7];
+ int NB = Y+H-(p[3]-OB);
+ // move everything to be on correct side of new resizable:
+ Fl_Widget*const* a = array();
+ p += 8;
+ for (int i=children(); i--;) {
+ Fl_Widget* o = *a++;
+ int X = o->x()+dx;
+ int R = X+o->w();
+ if (*p++ >= OR) X += dw; else if (X > NR) X = NR;
+ if (*p++ >= OR) R += dw; else if (R > NR) R = NR;
+ int Y = o->y()+dy;
+ int B = Y+o->h();
+ if (*p++ >= OB) Y += dh; else if (Y > NB) Y = NB;
+ if (*p++ >= OB) B += dh; else if (B > NB) B = NB;
+ o->resize(X,Y,R-X,B-Y); o->redraw();
+ }
+}
+
+static void set_cursor(Fl_Tile*t, Fl_Cursor c) {
+ static Fl_Cursor cursor;
+ if (cursor == c) return;
+ cursor = c;
+#ifdef __sgi
+ t->window()->cursor(c,FL_RED,FL_WHITE);
+#else
+ t->window()->cursor(c);
+#endif
+}
+
+static Fl_Cursor cursors[4] = {
+ FL_CURSOR_DEFAULT,
+ FL_CURSOR_WE,
+ FL_CURSOR_NS,
+ FL_CURSOR_MOVE};
+
+int Fl_Tile::handle(int event) {
+ static int sdrag;
+ static int sdx, sdy;
+ static int sx, sy;
+#define DRAGH 1
+#define DRAGV 2
+#define GRABAREA 4
+
+ int mx = Fl::event_x();
+ int my = Fl::event_y();
+
+ switch (event) {
+
+ case FL_MOVE:
+ case FL_ENTER:
+ case FL_PUSH: {
+ int mindx = 100;
+ int mindy = 100;
+ int oldx = 0;
+ int oldy = 0;
+ Fl_Widget*const* a = array();
+ short* q = sizes();
+ short* p = q+8;
+ for (int i=children(); i--; p += 4) {
+ Fl_Widget* o = *a++;
+ if (o == resizable()) continue;
+ if (p[1]<q[1] && o->y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) {
+ int t = mx - (o->x()+o->w());
+ if (abs(t) < mindx) {
+ sdx = t;
+ mindx = abs(t);
+ oldx = p[1];
+ }
+ }
+ if (p[3]<q[3] && o->x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) {
+ int t = my - (o->y()+o->h());
+ if (abs(t) < mindy) {
+ sdy = t;
+ mindy = abs(t);
+ oldy = p[3];
+ }
+ }
+ }
+ sdrag = 0; sx = sy = 0;
+ if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;}
+ if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;}
+ set_cursor(this, cursors[sdrag]);
+ if (sdrag) return 1;
+ return Fl_Group::handle(event);
+ }
+
+ case FL_LEAVE:
+ set_cursor(this, FL_CURSOR_DEFAULT);
+ break;
+
+ case FL_DRAG:
+ if (damage()) return 1; // don't fall behind
+ case FL_RELEASE: {
+ if (!sdrag) return 0; // should not happen
+ Fl_Widget* r = resizable(); if (!r) r = this;
+ int newx;
+ if (sdrag&DRAGH) {
+ newx = Fl::event_x()-sdx;
+ if (newx < r->x()) newx = r->x();
+ else if (newx > r->x()+r->w()) newx = r->x()+r->w();
+ } else
+ newx = sx;
+ int newy;
+ if (sdrag&DRAGV) {
+ newy = Fl::event_y()-sdy;
+ if (newy < r->y()) newy = r->y();
+ else if (newy > r->y()+r->h()) newy = r->y()+r->h();
+ } else
+ newy = sy;
+ position(sx,sy,newx,newy);
+ return 1;}
+
+ }
+
+ return Fl_Group::handle(event);
+}
+
+// end of Fl_Tile.C