fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Tile.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Tile.cxx 7903 2010-11-28 21:06:39Z matt $"
00003 //
00004 // Tile widget for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 
00029 // Group of 2 or 4 "tiles" that can be resized by dragging border
00030 // The size of the first child determines where the resize border is.
00031 // The resizebox is used to limit where the border can be dragged to.
00032 
00033 #include <FL/Fl.H>
00034 #include <FL/Fl_Tile.H>
00035 #include <FL/Fl_Window.H>
00036 #include <stdlib.h>
00037 
00038 // Drag the edges that were initially at oldx,oldy to newx,newy:
00039 // pass zero as oldx or oldy to disable drag in that direction:
00044 void Fl_Tile::position(int oix, int oiy, int newx, int newy) {
00045   Fl_Widget*const* a = array();
00046   int *p = sizes();
00047   p += 8; // skip group & resizable's saved size
00048   for (int i=children(); i--; p += 4) {
00049     Fl_Widget* o = *a++;
00050     if (o == resizable()) continue;
00051     int X = o->x();
00052     int R = X+o->w();
00053     if (oix) {
00054       int t = p[0];
00055       if (t == oix || (t>oix && X<newx) || (t<oix && X>newx) ) X = newx;
00056       t = p[1];
00057       if (t == oix || (t>oix && R<newx) || (t<oix && R>newx) ) R = newx;
00058     }
00059     int Y = o->y();
00060     int B = Y+o->h();
00061     if (oiy) {
00062       int t = p[2];
00063       if (t == oiy || (t>oiy && Y<newy) || (t<oiy && Y>newy) ) Y = newy;
00064       t = p[3];
00065       if (t == oiy || (t>oiy && B<newy) || (t<oiy && B>newy) ) B = newy;
00066     }
00067     o->damage_resize(X,Y,R-X,B-Y);
00068   }
00069 }
00070 
00071 // move the lower-right corner (sort of):
00072 void Fl_Tile::resize(int X,int Y,int W,int H) {
00073   //Fl_Group::resize(X, Y, W, H);
00074   //return;
00075   // remember how much to move the child widgets:
00076   int dx = X-x();
00077   int dy = Y-y();
00078   int dw = W-w();
00079   int dh = H-h();
00080   int *p = sizes();
00081   // resize this (skip the Fl_Group resize):
00082   Fl_Widget::resize(X,Y,W,H);
00083   // find bottom-right of resiable:
00084   int OR = p[5];
00085   int NR = X+W-(p[1]-OR);
00086   int OB = p[7];
00087   int NB = Y+H-(p[3]-OB);
00088   // move everything to be on correct side of new resizable:
00089   Fl_Widget*const* a = array();
00090   p += 8;
00091   for (int i=children(); i--;) {
00092     Fl_Widget* o = *a++;
00093     int xx = o->x()+dx;
00094     int R = xx+o->w();
00095     if (*p++ >= OR) xx += dw; else if (xx > NR) xx = NR;
00096     if (*p++ >= OR) R += dw; else if (R > NR) R = NR;
00097     int yy = o->y()+dy;
00098     int B = yy+o->h();
00099     if (*p++ >= OB) yy += dh; else if (yy > NB) yy = NB;
00100     if (*p++ >= OB) B += dh; else if (B > NB) B = NB;
00101     o->resize(xx,yy,R-xx,B-yy);
00102     // do *not* call o->redraw() here! If you do, and the tile is inside a 
00103     // scroll, it'll set the damage areas wrong for all children!
00104   }
00105 }
00106 
00107 static void set_cursor(Fl_Tile*t, Fl_Cursor c) {
00108   static Fl_Cursor cursor;
00109   if (cursor == c || !t->window()) return;
00110   cursor = c;
00111 #ifdef __sgi
00112   t->window()->cursor(c,FL_RED,FL_WHITE);
00113 #else
00114   t->window()->cursor(c);
00115 #endif
00116 }
00117 
00118 static Fl_Cursor cursors[4] = {
00119   FL_CURSOR_DEFAULT,
00120   FL_CURSOR_WE,
00121   FL_CURSOR_NS,
00122   FL_CURSOR_MOVE};
00123 
00124 int Fl_Tile::handle(int event) {
00125   static int sdrag;
00126   static int sdx, sdy;
00127   static int sx, sy;
00128 #define DRAGH 1
00129 #define DRAGV 2
00130 #define GRABAREA 4
00131 
00132   int mx = Fl::event_x();
00133   int my = Fl::event_y();
00134 
00135   switch (event) {
00136 
00137   case FL_MOVE:
00138   case FL_ENTER:
00139   case FL_PUSH:
00140     // don't potentially change the mouse cursor if inactive:
00141     if (!active()) break; // will cascade inherited handle()
00142     {
00143     int mindx = 100;
00144     int mindy = 100;
00145     int oldx = 0;
00146     int oldy = 0;
00147     Fl_Widget*const* a = array();
00148     int *q = sizes();
00149     int *p = q+8;
00150     for (int i=children(); i--; p += 4) {
00151       Fl_Widget* o = *a++;
00152       if (o == resizable()) continue;
00153       if (p[1]<q[1] && o->y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) {
00154         int t = mx - (o->x()+o->w());
00155         if (abs(t) < mindx) {
00156           sdx = t;
00157           mindx = abs(t);
00158           oldx = p[1];
00159         }
00160       }
00161       if (p[3]<q[3] && o->x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) {
00162         int t = my - (o->y()+o->h());
00163         if (abs(t) < mindy) {
00164           sdy = t;
00165           mindy = abs(t);
00166           oldy = p[3];
00167         }
00168       }
00169     }
00170     sdrag = 0; sx = sy = 0;
00171     if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;}
00172     if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;}
00173     set_cursor(this, cursors[sdrag]);
00174     if (sdrag) return 1;
00175     return Fl_Group::handle(event);
00176   }
00177 
00178   case FL_LEAVE:
00179     set_cursor(this, FL_CURSOR_DEFAULT);
00180     break;
00181 
00182   case FL_DRAG:
00183     // This is necessary if CONSOLIDATE_MOTION in Fl_x.cxx is turned off:
00184     // if (damage()) return 1; // don't fall behind
00185   case FL_RELEASE: {
00186     if (!sdrag) return 0; // should not happen
00187     Fl_Widget* r = resizable(); if (!r) r = this;
00188     int newx;
00189     if (sdrag&DRAGH) {
00190       newx = Fl::event_x()-sdx;
00191       if (newx < r->x()) newx = r->x();
00192       else if (newx > r->x()+r->w()) newx = r->x()+r->w();
00193     } else
00194       newx = sx;
00195     int newy;
00196     if (sdrag&DRAGV) {
00197       newy = Fl::event_y()-sdy;
00198       if (newy < r->y()) newy = r->y();
00199       else if (newy > r->y()+r->h()) newy = r->y()+r->h();
00200     } else
00201       newy = sy;
00202     position(sx,sy,newx,newy);
00203     if (event == FL_DRAG) set_changed();
00204     do_callback();
00205     return 1;}
00206 
00207   }
00208 
00209   return Fl_Group::handle(event);
00210 }
00211 
00212 //
00213 // End of "$Id: Fl_Tile.cxx 7903 2010-11-28 21:06:39Z matt $".
00214 //