2 // "$Id: Fl_Tile.cxx 7903 2010-11-28 21:06:39Z matt $"
4 // Tile widget for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
29 // Group of 2 or 4 "tiles" that can be resized by dragging border
30 // The size of the first child determines where the resize border is.
31 // The resizebox is used to limit where the border can be dragged to.
34 #include <FL/Fl_Tile.H>
35 #include <FL/Fl_Window.H>
38 // Drag the edges that were initially at oldx,oldy to newx,newy:
39 // pass zero as oldx or oldy to disable drag in that direction:
41 Drag the intersection at from_x,from_y to to_x,to_y.
42 This redraws all the necessary children.
44 void Fl_Tile::position(int oix
, int oiy
, int newx
, int newy
) {
45 Fl_Widget
*const* a
= array();
47 p
+= 8; // skip group & resizable's saved size
48 for (int i
=children(); i
--; p
+= 4) {
50 if (o
== resizable()) continue;
55 if (t
== oix
|| (t
>oix
&& X
<newx
) || (t
<oix
&& X
>newx
) ) X
= newx
;
57 if (t
== oix
|| (t
>oix
&& R
<newx
) || (t
<oix
&& R
>newx
) ) R
= newx
;
63 if (t
== oiy
|| (t
>oiy
&& Y
<newy
) || (t
<oiy
&& Y
>newy
) ) Y
= newy
;
65 if (t
== oiy
|| (t
>oiy
&& B
<newy
) || (t
<oiy
&& B
>newy
) ) B
= newy
;
67 o
->damage_resize(X
,Y
,R
-X
,B
-Y
);
71 // move the lower-right corner (sort of):
72 void Fl_Tile::resize(int X
,int Y
,int W
,int H
) {
73 //Fl_Group::resize(X, Y, W, H);
75 // remember how much to move the child widgets:
81 // resize this (skip the Fl_Group resize):
82 Fl_Widget::resize(X
,Y
,W
,H
);
83 // find bottom-right of resiable:
85 int NR
= X
+W
-(p
[1]-OR
);
87 int NB
= Y
+H
-(p
[3]-OB
);
88 // move everything to be on correct side of new resizable:
89 Fl_Widget
*const* a
= array();
91 for (int i
=children(); i
--;) {
95 if (*p
++ >= OR
) xx
+= dw
; else if (xx
> NR
) xx
= NR
;
96 if (*p
++ >= OR
) R
+= dw
; else if (R
> NR
) R
= NR
;
99 if (*p
++ >= OB
) yy
+= dh
; else if (yy
> NB
) yy
= NB
;
100 if (*p
++ >= OB
) B
+= dh
; else if (B
> NB
) B
= NB
;
101 o
->resize(xx
,yy
,R
-xx
,B
-yy
);
102 // do *not* call o->redraw() here! If you do, and the tile is inside a
103 // scroll, it'll set the damage areas wrong for all children!
107 static void set_cursor(Fl_Tile
*t
, Fl_Cursor c
) {
108 static Fl_Cursor cursor
;
109 if (cursor
== c
|| !t
->window()) return;
112 t
->window()->cursor(c
,FL_RED
,FL_WHITE
);
114 t
->window()->cursor(c
);
118 static Fl_Cursor cursors
[4] = {
124 int Fl_Tile::handle(int event
) {
132 int mx
= Fl::event_x();
133 int my
= Fl::event_y();
140 // don't potentially change the mouse cursor if inactive:
141 if (!active()) break; // will cascade inherited handle()
147 Fl_Widget
*const* a
= array();
150 for (int i
=children(); i
--; p
+= 4) {
152 if (o
== resizable()) continue;
153 if (p
[1]<q
[1] && o
->y()<=my
+GRABAREA
&& o
->y()+o
->h()>=my
-GRABAREA
) {
154 int t
= mx
- (o
->x()+o
->w());
155 if (abs(t
) < mindx
) {
161 if (p
[3]<q
[3] && o
->x()<=mx
+GRABAREA
&& o
->x()+o
->w()>=mx
-GRABAREA
) {
162 int t
= my
- (o
->y()+o
->h());
163 if (abs(t
) < mindy
) {
170 sdrag
= 0; sx
= sy
= 0;
171 if (mindx
<= GRABAREA
) {sdrag
= DRAGH
; sx
= oldx
;}
172 if (mindy
<= GRABAREA
) {sdrag
|= DRAGV
; sy
= oldy
;}
173 set_cursor(this, cursors
[sdrag
]);
175 return Fl_Group::handle(event
);
179 set_cursor(this, FL_CURSOR_DEFAULT
);
183 // This is necessary if CONSOLIDATE_MOTION in Fl_x.cxx is turned off:
184 // if (damage()) return 1; // don't fall behind
186 if (!sdrag
) return 0; // should not happen
187 Fl_Widget
* r
= resizable(); if (!r
) r
= this;
190 newx
= Fl::event_x()-sdx
;
191 if (newx
< r
->x()) newx
= r
->x();
192 else if (newx
> r
->x()+r
->w()) newx
= r
->x()+r
->w();
197 newy
= Fl::event_y()-sdy
;
198 if (newy
< r
->y()) newy
= r
->y();
199 else if (newy
> r
->y()+r
->h()) newy
= r
->y()+r
->h();
202 position(sx
,sy
,newx
,newy
);
203 if (event
== FL_DRAG
) set_changed();
209 return Fl_Group::handle(event
);
213 // End of "$Id: Fl_Tile.cxx 7903 2010-11-28 21:06:39Z matt $".