DO NOT REPLY TO THIS MESSAGE. INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.
[STR New]
Link: http://www.fltk.org/str.php?L2791
Version: 1.3-feature
Attached file "tiletest2.cxx"...
Link: http://www.fltk.org/str.php?L2791
Version: 1.3-feature
/**
This is an override of Fl_Tile that enforces a minimum tile size of thresh
in each direction.
By Robert Strickland Tue Dec 13 22:39:20 CST 2011
*/
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Tile.H>
#include <FL/Fl_Box.H>
//#define TEST_INACTIVE
/**
Fl_TileM inherits from Fl_Tile. It functions similarly, but it
enforces a minimum tile size of thresh. If one tile squishes another
to oblivion, only one extra border appears at the margin, so you can't
TODO: Resizing the parent tile smaller doesn't enforce the minimum tile size.
Need to override resize().
*/
class Fl_TileM : public Fl_Tile {
protected:
// The cursor stuff has nothing to do with the minimum tile size code;
// it just encapsulates what used to be static in the original Fl_Tile
Fl_Cursor cursors[4];
Fl_Cursor cursor;
int thresh; // minimum window width or height in pixels
public:
// minimum threshold to zero so behaves like Fl_Tile by default
Fl_TileM(int x, int y, int w, int h, const char*l=0, int t=0)
: Fl_Tile(x, y, w, h, l) {
thresh = t;
cursors[0] = FL_CURSOR_DEFAULT;
cursors[1] = FL_CURSOR_WE;
cursors[2] = FL_CURSOR_NS;
cursors[3] = FL_CURSOR_MOVE;
};
void position(int oix, int oiy, int newx, int newy); // override
int handle(int event); // override. See note below.
void set_thresh(int t) { thresh = t; };
int get_thresh() { return thresh; };
protected:
// This replaces static function in original Fl_Tile
void set_cursor(Fl_Cursor c) {
if (cursor == c || !window()) return;
cursor = c;
#ifdef __sgi
window()->cursor(c,FL_RED,FL_WHITE);
#else
window()->cursor(c);
#endif
};
};
/**
Drag the edges that were initially (that is, when constructed) at
oix,oiy to newx,newy.
Pass zero as oix or oiy to disable drag in that direction.
This redraws all the necessary children.
*/
void Fl_TileM::position(int oix, int oiy, int newx, int newy) {
// Enforce size threshold at border
if (newx < thresh) newx = thresh;
if (newx > w()-thresh) newx = w()-thresh;
if (newy < thresh) newy = thresh;
if (newy > h()-thresh) newy = h()-thresh;
// used if skinny box is found
int oix2 = 0;
int oiy2 = 0;
int newx2 = 0;
int newy2 = 0;
Fl_Widget*const* a = array();
int *p = sizes();
p += 8; // skip group & resizable's saved size
for (int i=children(); i--; p += 4) {
Fl_Widget* o = *a++;
if (o == resizable()) continue;
int L = o->x();
int R = L+o->w();
bool damage = false;
if (oix) {
int t = p[0];
if (t==oix || (t>oix && L<newx) || (t<oix && L>newx)) {
L = newx;
damage = true;
}
t = p[1];
if (t==oix || (t>oix && R<newx) || (t<oix && R>newx)) {
R = newx;
damage = true;
}
if (R-L < thresh && newx > thresh && newx < w()-thresh) { // skinny
if (L == newx) {
oix2 = p[1];
newx2 = L + thresh;
}
else if (R == newx) {
oix2 = p[0];
newx2 = R - thresh;
}
}
}
int T = o->y();
int B = T+o->h();
if (oiy) {
int t = p[2];
if (t==oiy || (t>oiy && T<newy) || (t<oiy && T>newy)) {
T = newy;
damage = true;
}
t = p[3];
if (t==oiy || (t>oiy && B<newy) || (t<oiy && B>newy)) {
B = newy;
damage = true;
}
if (B-T < thresh && newy > thresh && newy < h()-thresh) { // shorty
if (T == newy) {
oiy2 = p[3];
newy2 = T + thresh;
}
else if (B == newy) {
oiy2 = p[2];
newy2 = B - thresh;
}
}
}
if (damage) o->damage_resize(L,T,R-L,B-T);
}
// If there is a skinny box, move other side to keep its size at thresh
if (oix2 || oiy2) position(oix2, oiy2, newx2, newy2); // recursion
}
//
// Note (Strickland): The changes to Fl_Tile::handle() have nothing to do
// with the minimum size threshold. They are to encapsulate the
// formerly static set_cursor() and associated cursor data.
// I couldn't figure out how to override Fl_Tile::position()
// without also overriding Fl_Tile::handle()
//
int Fl_TileM::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:
// don't potentially change the mouse cursor if inactive:
if (!active()) break; // will cascade inherited handle()
{
int mindx = 100;
int mindy = 100;
int oix = 0;
int oiy = 0;
Fl_Widget*const* a = array();
int *q = sizes();
int *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);
oix = 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);
oiy = p[3];
}
}
}
sdrag = 0; sx = sy = 0;
if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oix;}
if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oiy;}
set_cursor(cursors[sdrag]);
if (sdrag) return 1;
return Fl_Group::handle(event);
}
case FL_LEAVE:
set_cursor(FL_CURSOR_DEFAULT);
break;
case FL_DRAG:
// This is necessary if CONSOLIDATE_MOTION in Fl_x.cxx is turned off:
// 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);
if (event == FL_DRAG) set_changed();
do_callback();
return 1;}
}
return Fl_Group::handle(event);
}
// Mostly straight from fltk1.3.0/test/tile.cxx with changes marked with RWS
int main(int argc, char** argv) {
Fl_Double_Window window(300,300);
window.box(FL_NO_BOX);
window.resizable(window);
Fl_TileM tile(0,0,300,300); // RWS
tile.set_thresh(3); // RWS: 3 pixel minimum tile size
Fl_Box box0(0,0,150,150,"0");
box0.box(FL_DOWN_BOX);
box0.color(9);
box0.labelsize(36);
box0.align(FL_ALIGN_CLIP);
Fl_Double_Window w1(150,0,150,150,"1");
w1.box(FL_NO_BOX);
Fl_Box box1(0,0,150,150,"1\nThis is a\nchild\nwindow");
box1.box(FL_DOWN_BOX);
box1.color(19);
box1.labelsize(18);
box1.align(FL_ALIGN_CLIP);
w1.resizable(box1);
w1.end();
// Fl_Tile tile2(0,150,150,150);
Fl_Box box2a(0,150,70,150,"2a");
box2a.box(FL_DOWN_BOX);
box2a.color(12);
box2a.labelsize(36);
box2a.align(FL_ALIGN_CLIP);
Fl_Box box2b(70,150,80,150,"2b");
box2b.box(FL_DOWN_BOX);
box2b.color(13);
box2b.labelsize(36);
box2b.align(FL_ALIGN_CLIP);
//tile2.end();
//Fl_Tile tile3(150,150,150,150);
Fl_Box box3a(150,150,150,70,"3a");
box3a.box(FL_DOWN_BOX);
box3a.color(12);
box3a.labelsize(36);
box3a.align(FL_ALIGN_CLIP);
Fl_Box box3b(150,150+70,150,80,"3b");
box3b.box(FL_DOWN_BOX);
box3b.color(13);
box3b.labelsize(36);
box3b.align(FL_ALIGN_CLIP);
//tile3.end();
// TODO: RWS Resizable not tested yet
//Fl_Box r(10,0,300-10,300-10);
//tile.resizable(r);
// r.box(FL_BORDER_FRAME);
tile.end();
window.end();
#ifdef TEST_INACTIVE // test inactive case
tile.deactivate();
#endif
w1.show();
window.show(argc,argv);
return Fl::run();
}
_______________________________________________
fltk-bugs mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-bugs