diff options
| author | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:21:25 +0000 |
|---|---|---|
| committer | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:21:25 +0000 |
| commit | f9039b2ae21988783feae9b362818e7923e82d14 (patch) | |
| tree | 6d6fe3679d73448758f9794e7d4d4f6b22a4adad /src/Fl_Tile.cxx | |
| parent | 67e89232f9ba067825a158734a09e0fa21aacbe3 (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.cxx | 173 |
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 |
