2
/******************************************************************************
3
* MODULE : popup_button.cpp
4
* DESCRIPTION: Buttons which trigger a popup window.
5
* COPYRIGHT : (C) 1999 Joris van der Hoeven
6
*******************************************************************************
7
* This software falls under the GNU general public license and comes WITHOUT
8
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
9
* If you don't have this file, write to the Free Software Foundation, Inc.,
10
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
11
******************************************************************************/
15
#include "Widget/make_widget.hpp"
16
#include "Widget/Button/button_widget.hpp"
18
/******************************************************************************
20
******************************************************************************/
22
class popup_button_rep: public button_widget_rep {
34
void consistent (string s);
36
popup_button_rep (widget w, widget pw, gravity where);
37
popup_button_rep (widget w, make_widget mw, gravity where);
38
void handle_attach_window (attach_window_event ev);
39
void handle_mouse (mouse_event ev);
40
bool handle (event ev);
43
gravity opposite (gravity grav);
45
/******************************************************************************
46
* Routines for popup buttons
47
******************************************************************************/
49
popup_button_rep::popup_button_rep (widget w, widget pw, gravity where2):
50
button_widget_rep (w, where2==east),
51
mw (), popup_w (popup_widget (pw, opposite (where2))), popup (NULL),
52
where (where2), require_map (false), stick (false)
54
if ((where!=east) && (where!=south) && (where!=south_east))
55
fatal_error ("direction not implemented",
56
"popup_button_rep::popup_button_rep");
59
popup_button_rep::popup_button_rep (widget w, make_widget mw2, gravity where2):
60
button_widget_rep (w, where2==east),
61
mw (mw2), popup_w (), popup (NULL),
62
where (where2), require_map (false), stick (false)
64
if ((where!=east) && (where!=south) && (where!=south_east))
65
fatal_error ("direction not implemented",
66
"popup_button_rep::popup_button_rep");
70
popup_button_rep::consistent (string s) {
72
// iff (inside button and left or right button pressed) or stick
73
// iff require_map=true or mouse grab activated on button
74
// iff require_map=true or popup window is mapped
78
(require_map && (popup != NULL)) ||
79
((!require_map) && (popup == NULL));
80
else flag= (!require_map) && (popup != NULL);
82
cerr << "status = " << status << "\n";
83
cerr << "require map= " << require_map << "\n";
84
cerr << "popup = " << (popup != NULL) << "\n";
85
fatal_error ("Inconsistency in " * s, "popup_button_rep::consistent");
90
popup_button_rep::map_popup () {
95
// int start_1= texmacs_time ();
96
popup_w= popup_widget (mw (dis), opposite (where));
97
// cout << "Mapping required " << (texmacs_time ()-start_1) << " ms\n";
100
// int start_2= texmacs_time ();
102
win->get_position (x, y);
103
popup_w << get_size (w, h);
115
x += ((x1()+x2())>>1)- (w>>1)- 3*PIXEL;
121
// cout << "Positioning required " << (texmacs_time ()-start_2) << " ms\n";
123
// int start_3= texmacs_time ();
124
popup= popup_window (popup_w, x, y);
125
// cout << "Window creation required " << (texmacs_time ()-start_3) << " ms\n";
126
// int start_4= texmacs_time ();
128
// cout << "Mapping required " << (texmacs_time ()-start_4) << " ms\n";
130
this << emit_invalidate_all ();
131
this << emit_mouse_grab (true);
135
popup_button_rep::unmap_popup () {
137
fatal_error ("Unexpected situation", "popup_button_rep::unmap_popup");
141
if (!nil (mw)) popup_w= widget ();
143
this << emit_invalidate_all ();
144
if (!dis->has_grab_pointer (this))
145
fatal_error ("I do not have the pointer grab",
146
"popup_button_rep::unmap_popup");
147
this << emit_mouse_grab (false);
151
popup_button_rep::handle_attach_window (attach_window_event ev) {
152
if ((ev->win==NULL) && status) {
153
consistent ("handle_attach_window (1)");
155
if (require_map) require_map= false;
158
consistent ("handle_attach_window (2)");
160
basic_widget_rep::handle_attach_window (ev);
164
popup_button_rep::handle_mouse (mouse_event ev) {
165
string type= ev->type;
166
SI x= ev->x, y= ev->y;
168
consistent ("handle_mouse (start)");
170
if (type == "leave") {
178
/*************************** button is inactive ****************************/
180
consistent ("handle_mouse (1)");
181
inside= (y>=0) && (y<h) && (x>=0) && (x<w);
182
status= inside && (ev->pressed ("left") || ev->pressed ("right"));
184
entered_at= texmacs_time ();
189
/**************************** button is active *****************************/
192
((where == east) && (x > w-12*PIXEL)) ||
193
((where == south) && (y<0)) ||
194
((where == south_east) && (y<0));
196
(y>=0) && (y<h) && (x>=0) && (x<w);
198
(inside || ((!stick) && inside_popup)) &&
199
(ev->pressed ("left") || ev->pressed ("right"));
204
if (require_map) map_popup ();
206
consistent ("handle_mouse (2)");
207
popup_w << set_integer ("grabbed", 1);
208
popup_w << emit_mouse_grab (true);
213
// stick or disactivate
215
if (inside /* && false */) {
217
if (require_map) { map_popup (); stick= true; }
219
consistent ("handle_mouse (3)");
220
popup_w << set_integer ("grabbed", 1);
221
popup_w << set_integer ("stick", 1);
222
popup_w << emit_mouse_grab (true);
226
if (require_map) require_map= false;
232
consistent ("handle_mouse (*)");
234
/**************************** wait to be mapped ****************************/
238
now= texmacs_time ();
239
if (win->check_event (MENU_EVENT)) return;
240
} while ((now-entered_at)<100);
244
consistent ("handle_mouse (end)");
248
popup_button_rep::handle (event ev) {
250
case GET_WIDGET_EVENT:
251
case SET_WIDGET_EVENT:
255
if (!nil (popup_w)) popup_w << ev;
257
case GET_COORD2_EVENT:
258
case SET_COORD2_EVENT:
259
return button_widget_rep::handle (ev);
261
return basic_widget_rep::handle (ev);
266
opposite (gravity grav) {
268
case north_west: return south_east;
269
case north : return south;
270
case north_east: return south_west;
271
case west : return east;
272
case center : return center;
273
case east : return west;
274
case south_west: return north_east;
275
case south : return north;
276
case south_east: return north_west;
278
fatal_error ("unknown gravity", "operator -", "popup_button.cpp");
279
return center; // Because of bug in certain versions of g++
282
/******************************************************************************
284
******************************************************************************/
287
pulldown_button (widget w, widget pw) {
288
return new popup_button_rep (w, pw, south_east);
292
pullright_button (widget w, widget pw) {
293
return new popup_button_rep (w, pw, east);
297
pulldown_button (widget w, make_widget mw) {
298
return new popup_button_rep (w, mw, south_east);
302
pullright_button (widget w, make_widget mw) {
303
return new popup_button_rep (w, mw, east);