Improve subclassing cababilities of Fl_Tile (STR 2791)

- remove static variables and functions
- make move_intersection() virtual
- add (protected) cursor access methods

These changes were inspired by STR 2791 where the user proposing an
enhancement was not able to subclass Fl_Tile properly. This commit
fixes the mentioned issues and enables subclassing without copying
internal code.
This commit is contained in:
Albrecht Schlosser
2023-10-16 10:53:18 +02:00
parent da5331b592
commit 6ba7b49baf
3 changed files with 67 additions and 36 deletions
+17 -3
View File
@@ -1,7 +1,7 @@
// //
// Tile header file for the Fast Light Tool Kit (FLTK). // Tile header file for the Fast Light Tool Kit (FLTK).
// //
// Copyright 1998-2016 by Bill Spitzak and others. // Copyright 1998-2023 by Bill Spitzak and others.
// //
// This library is free software. Distribution and use rights are outlined in // This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this // the file "COPYING" which should have been included with this file. If this
@@ -29,10 +29,24 @@ public:
int handle(int event) FL_OVERRIDE; int handle(int event) FL_OVERRIDE;
Fl_Tile(int X, int Y, int W, int H, const char *L=0); Fl_Tile(int X, int Y, int W, int H, const char *L=0);
void resize(int X, int Y, int W, int H) FL_OVERRIDE; void resize(int X, int Y, int W, int H) FL_OVERRIDE;
void move_intersection(int oldx, int oldy, int newx, int newy); virtual void move_intersection(int oldx, int oldy, int newx, int newy);
FL_DEPRECATED("in 1.4.0 - use move_intersection(p) instead", FL_DEPRECATED("in 1.4.0 - use move_intersection(p) instead",
void position(int oldx, int oldy, int newx, int newy)) { return move_intersection(oldx, oldy, newx, newy); } void position(int oldx, int oldy, int newx, int newy)) { move_intersection(oldx, oldy, newx, newy); }
void position(int x, int y) { Fl_Group::position(x, y); } void position(int x, int y) { Fl_Group::position(x, y); }
protected:
int cursor_; ///< current cursor index (0..3)
Fl_Cursor *cursors_; ///< points at the array of 4 cursors (may be overridden)
/** Returns the cursor for cursor index n.
\see Fl_Tile::set_cursor(int)
*/
Fl_Cursor cursor(int n) {
return cursors_[n];
}
void set_cursor(int n); // set one of n (0..3) cursors
}; };
#endif #endif
+41 -25
View File
@@ -87,6 +87,13 @@
#include <FL/Fl_Rect.H> #include <FL/Fl_Rect.H>
#include <stdlib.h> #include <stdlib.h>
static Fl_Cursor Fl_Tile_cursors[4] = {
FL_CURSOR_DEFAULT, // 0 normal
FL_CURSOR_WE, // 1 drag horizontally
FL_CURSOR_NS, // 2 drag vertically
FL_CURSOR_MOVE // 3 move intersection
};
/** /**
Drags the intersection at (\p oldx,\p oldy) to (\p newx,\p newy). Drags the intersection at (\p oldx,\p oldy) to (\p newx,\p newy).
This redraws all the necessary children. This redraws all the necessary children.
@@ -173,30 +180,33 @@ void Fl_Tile::resize(int X,int Y,int W,int H) {
} }
} }
static void set_cursor(Fl_Tile*t, Fl_Cursor c) { /**
static Fl_Cursor cursor; Set one of four cursors used for dragging etc..
if (cursor == c || !t->window()) return;
cursor = c; Fl_Tile uses an array of four cursors that are set depending on user actions:
#ifdef __sgi - 0: normal cursor
t->window()->cursor(c,FL_RED,FL_WHITE); - 1: horizontal dragging
#else - 2: vertical dragging
t->window()->cursor(c); - 3: dragging an intersection
#endif
This method sets the window cursor for the given index \p n.
*/
void Fl_Tile::set_cursor(int n) {
if (n < 0 || n > 3) n = 0; // check array index
cursor_ = n; // always store the index
if (cursor_ == n || !window())
return;
window()->cursor(cursor(n));
} }
static Fl_Cursor cursors[4] = { #define DRAGH 1
FL_CURSOR_DEFAULT, #define DRAGV 2
FL_CURSOR_WE, #define GRABAREA 4
FL_CURSOR_NS,
FL_CURSOR_MOVE};
int Fl_Tile::handle(int event) { int Fl_Tile::handle(int event) {
static int sdrag; static int sdrag;
static int sdx, sdy; static int sdx, sdy;
static int sx, sy; static int sx, sy;
#define DRAGH 1
#define DRAGV 2
#define GRABAREA 4
int mx = Fl::event_x(); int mx = Fl::event_x();
int my = Fl::event_y(); int my = Fl::event_y();
@@ -239,13 +249,13 @@ int Fl_Tile::handle(int event) {
sdrag = 0; sx = sy = 0; sdrag = 0; sx = sy = 0;
if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;} if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;}
if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;} if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;}
set_cursor(this, cursors[sdrag]); set_cursor(sdrag);
if (sdrag) return 1; if (sdrag) return 1;
return Fl_Group::handle(event); return Fl_Group::handle(event);
} }
case FL_LEAVE: case FL_LEAVE:
set_cursor(this, FL_CURSOR_DEFAULT); set_cursor(0); // set default cursor
break; break;
case FL_DRAG: case FL_DRAG:
@@ -264,10 +274,13 @@ int Fl_Tile::handle(int event) {
int newy; int newy;
if (sdrag&DRAGV) { if (sdrag&DRAGV) {
newy = Fl::event_y()-sdy; newy = Fl::event_y()-sdy;
if (newy < r->y()) newy = r->y(); if (newy < r->y())
else if (newy > r->y()+r->h()) newy = r->y()+r->h(); newy = r->y();
} else else if (newy > r->y()+r->h())
newy = r->y()+r->h();
} else {
newy = sy; newy = sy;
}
move_intersection(sx, sy, newx, newy); move_intersection(sx, sy, newx, newy);
if (event == FL_DRAG) { if (event == FL_DRAG) {
set_changed(); set_changed();
@@ -275,9 +288,10 @@ int Fl_Tile::handle(int event) {
} else { } else {
do_callback(FL_REASON_CHANGED); do_callback(FL_REASON_CHANGED);
} }
return 1;} return 1;
} // case FL_RELEASE
} } // switch()
return Fl_Group::handle(event); return Fl_Group::handle(event);
} }
@@ -297,6 +311,8 @@ int Fl_Tile::handle(int event) {
*/ */
Fl_Tile::Fl_Tile(int X,int Y,int W,int H,const char*L) Fl_Tile::Fl_Tile(int X,int Y,int W,int H,const char*L)
: Fl_Group(X,Y,W,H,L) : Fl_Group(X,Y,W,H,L),
cursor_(0),
cursors_(Fl_Tile_cursors)
{ {
} }
+9 -8
View File
@@ -1,7 +1,7 @@
// //
// Fl_Tile test program for the Fast Light Tool Kit (FLTK). // Fl_Tile test program for the Fast Light Tool Kit (FLTK).
// //
// Copyright 1998-2016 by Bill Spitzak and others. // Copyright 1998-2023 by Bill Spitzak and others.
// //
// This library is free software. Distribution and use rights are outlined in // This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this // the file "COPYING" which should have been included with this file. If this
@@ -19,18 +19,19 @@
#include <FL/Fl_Tile.H> #include <FL/Fl_Tile.H>
#include <FL/Fl_Box.H> #include <FL/Fl_Box.H>
//#define TEST_INACTIVE // #define TEST_INACTIVE
int main(int argc, char** argv) { int main(int argc, char** argv) {
Fl_Double_Window window(300,300); Fl_Double_Window window(300, 300);
window.box(FL_NO_BOX); window.box(FL_NO_BOX);
window.resizable(window); window.resizable(window);
int dx = 20, dy = dx; // border width of resizable() - see below Fl_Tile tile(0, 0, 300, 300);
Fl_Tile tile(0,0,300,300);
// create the symmetrical resize box with dx and dy pixels distance, resp. // create the symmetrical resize box with dx and dy pixels distance, resp.
// from the borders of the Fl_Tile widget before all other children // from the borders of the Fl_Tile widget before all other children
int dx = 20, dy = dx; // border width of resizable()
Fl_Box r(tile.x()+dx,tile.y()+dy,tile.w()-2*dx,tile.h()-2*dy); Fl_Box r(tile.x()+dx,tile.y()+dy,tile.w()-2*dx,tile.h()-2*dy);
tile.resizable(r); tile.resizable(r);
@@ -62,9 +63,9 @@ int main(int argc, char** argv) {
box2b.color(13); box2b.color(13);
box2b.labelsize(36); box2b.labelsize(36);
box2b.align(FL_ALIGN_CLIP); box2b.align(FL_ALIGN_CLIP);
//tile2.end(); // tile2.end();
//Fl_Tile tile3(150,150,150,150); // Fl_Tile tile3(150,150,150,150);
Fl_Box box3a(150,150,150,70,"3a"); Fl_Box box3a(150,150,150,70,"3a");
box3a.box(FL_DOWN_BOX); box3a.box(FL_DOWN_BOX);
box3a.color(12); box3a.color(12);
@@ -76,7 +77,7 @@ int main(int argc, char** argv) {
box3b.color(13); box3b.color(13);
box3b.labelsize(36); box3b.labelsize(36);
box3b.align(FL_ALIGN_CLIP); box3b.align(FL_ALIGN_CLIP);
//tile3.end(); // tile3.end();
tile.end(); tile.end();
window.end(); window.end();