~ubuntu-branches/ubuntu/hardy/texmacs/hardy

« back to all changes in this revision

Viewing changes to src/Window/Widget/Button/popup_button.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Treinen
  • Date: 2004-04-19 20:34:00 UTC
  • Revision ID: james.westby@ubuntu.com-20040419203400-g4e34ih0315wcn8v
Tags: upstream-1.0.3-R2
ImportĀ upstreamĀ versionĀ 1.0.3-R2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
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
******************************************************************************/
 
12
 
 
13
#include "timer.hpp"
 
14
#include "window.hpp"
 
15
#include "Widget/make_widget.hpp"
 
16
#include "Widget/Button/button_widget.hpp"
 
17
 
 
18
/******************************************************************************
 
19
* Popup buttons
 
20
******************************************************************************/
 
21
 
 
22
class popup_button_rep: public button_widget_rep {
 
23
  make_widget mw;
 
24
  widget      popup_w;
 
25
  window      popup;
 
26
  gravity     where;
 
27
  time_t      entered_at;
 
28
  bool        require_map;
 
29
  bool        stick;
 
30
 
 
31
private:
 
32
  void map_popup ();
 
33
  void unmap_popup ();
 
34
  void consistent (string s);
 
35
public:
 
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);
 
41
};
 
42
 
 
43
gravity opposite (gravity grav);
 
44
 
 
45
/******************************************************************************
 
46
* Routines for popup buttons
 
47
******************************************************************************/
 
48
 
 
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)
 
53
{
 
54
  if ((where!=east) && (where!=south) && (where!=south_east))
 
55
    fatal_error ("direction not implemented",
 
56
                 "popup_button_rep::popup_button_rep");
 
57
}
 
58
 
 
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)
 
63
{
 
64
  if ((where!=east) && (where!=south) && (where!=south_east))
 
65
    fatal_error ("direction not implemented",
 
66
                 "popup_button_rep::popup_button_rep");
 
67
}
 
68
 
 
69
void
 
70
popup_button_rep::consistent (string s) {
 
71
  // status= true
 
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
 
75
 
 
76
  bool flag;
 
77
  if (status) flag=
 
78
                (require_map && (popup != NULL)) ||
 
79
                ((!require_map) && (popup == NULL));
 
80
  else flag= (!require_map) && (popup != NULL);
 
81
  if (flag) {
 
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");
 
86
  }
 
87
}
 
88
 
 
89
void
 
90
popup_button_rep::map_popup () {
 
91
  require_map= false;
 
92
  stick      = false;
 
93
 
 
94
  if (!nil (mw)) {
 
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";
 
98
  }
 
99
 
 
100
  // int start_2= texmacs_time ();
 
101
  SI x, y, w=0, h=0;
 
102
  win->get_position (x, y);
 
103
  popup_w << get_size (w, h);
 
104
 
 
105
  switch (where) {
 
106
  case east:
 
107
    x += x2()-12*PIXEL;
 
108
    y += y2()+3*PIXEL;
 
109
    break;
 
110
  case south_east:
 
111
    x += x1()-3*PIXEL;
 
112
    y += y1();
 
113
    break;
 
114
  case south:
 
115
    x += ((x1()+x2())>>1)- (w>>1)- 3*PIXEL;
 
116
    y += y1();
 
117
    break;
 
118
  default:
 
119
    break;
 
120
  }
 
121
  // cout << "Positioning required " << (texmacs_time ()-start_2) << " ms\n";
 
122
 
 
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 ();
 
127
  popup->map ();
 
128
  // cout << "Mapping required " << (texmacs_time ()-start_4) << " ms\n";
 
129
 
 
130
  this << emit_invalidate_all ();
 
131
  this << emit_mouse_grab (true);
 
132
}
 
133
 
 
134
void
 
135
popup_button_rep::unmap_popup () {
 
136
  if (popup == NULL)
 
137
    fatal_error ("Unexpected situation", "popup_button_rep::unmap_popup");
 
138
  popup->unmap ();
 
139
  delete popup;
 
140
  popup= NULL;
 
141
  if (!nil (mw)) popup_w= widget ();
 
142
 
 
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);
 
148
}
 
149
 
 
150
void
 
151
popup_button_rep::handle_attach_window (attach_window_event ev) {
 
152
  if ((ev->win==NULL) && status) {
 
153
    consistent ("handle_attach_window (1)");
 
154
    status= false;
 
155
    if (require_map) require_map= false;
 
156
    else unmap_popup ();
 
157
    stick= false;    
 
158
    consistent ("handle_attach_window (2)");
 
159
  }
 
160
  basic_widget_rep::handle_attach_window (ev);
 
161
}
 
162
 
 
163
void
 
164
popup_button_rep::handle_mouse (mouse_event ev) {
 
165
  string type= ev->type;
 
166
  SI     x= ev->x, y= ev->y;
 
167
 
 
168
  consistent ("handle_mouse (start)");
 
169
 
 
170
  if (type == "leave") {
 
171
    if (require_map) {
 
172
      inside= false;
 
173
      status= false;
 
174
      require_map= false;
 
175
    }
 
176
  }
 
177
 
 
178
  /*************************** button is inactive ****************************/
 
179
  else if (!status) {
 
180
    consistent ("handle_mouse (1)");
 
181
    inside= (y>=0) && (y<h) && (x>=0) && (x<w);
 
182
    status= inside && (ev->pressed ("left") || ev->pressed ("right"));
 
183
    if (status) {
 
184
      entered_at= texmacs_time ();
 
185
      require_map= true;
 
186
    }
 
187
  }
 
188
 
 
189
  /**************************** button is active *****************************/
 
190
  else {
 
191
    bool inside_popup=
 
192
      ((where == east) && (x > w-12*PIXEL)) ||
 
193
      ((where == south) && (y<0)) ||
 
194
      ((where == south_east) && (y<0));
 
195
    inside=
 
196
      (y>=0) && (y<h) && (x>=0) && (x<w);
 
197
    status=
 
198
      (inside || ((!stick) && inside_popup)) &&
 
199
      (ev->pressed ("left") || ev->pressed ("right"));
 
200
 
 
201
    // activate
 
202
    if (status) {
 
203
      if (inside_popup) {
 
204
        if (require_map) map_popup ();
 
205
        if (status) {
 
206
          consistent ("handle_mouse (2)");
 
207
          popup_w << set_integer ("grabbed", 1);
 
208
          popup_w << emit_mouse_grab (true);
 
209
        }
 
210
      }
 
211
    }
 
212
 
 
213
    // stick or disactivate
 
214
    else {
 
215
      if (inside /* && false */) {
 
216
        status= true;
 
217
        if (require_map) { map_popup (); stick= true; }
 
218
        if (status) {
 
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);
 
223
        }
 
224
      }
 
225
      else {
 
226
        if (require_map) require_map= false;
 
227
        else unmap_popup ();
 
228
      }
 
229
    }
 
230
  }
 
231
 
 
232
  consistent ("handle_mouse (*)");
 
233
 
 
234
  /**************************** wait to be mapped ****************************/
 
235
  if (require_map) {
 
236
    time_t now;
 
237
    do {
 
238
      now= texmacs_time ();
 
239
      if (win->check_event (MENU_EVENT)) return;
 
240
    } while ((now-entered_at)<100);
 
241
    map_popup ();
 
242
  }
 
243
 
 
244
  consistent ("handle_mouse (end)");
 
245
}
 
246
 
 
247
bool
 
248
popup_button_rep::handle (event ev) {
 
249
  switch (ev->type) {
 
250
  case GET_WIDGET_EVENT:
 
251
  case SET_WIDGET_EVENT:
 
252
  case CLEAN_EVENT:
 
253
  case INSERT_EVENT:
 
254
  case REMOVE_EVENT:
 
255
    if (!nil (popup_w)) popup_w << ev;
 
256
    return true;
 
257
  case GET_COORD2_EVENT:
 
258
  case SET_COORD2_EVENT:
 
259
    return button_widget_rep::handle (ev);
 
260
  default:
 
261
    return basic_widget_rep::handle (ev);
 
262
  }
 
263
}
 
264
 
 
265
gravity
 
266
opposite (gravity grav) {
 
267
  switch (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;
 
277
  }
 
278
  fatal_error ("unknown gravity", "operator -", "popup_button.cpp");
 
279
  return center; // Because of bug in certain versions of g++
 
280
}
 
281
 
 
282
/******************************************************************************
 
283
* Interface
 
284
******************************************************************************/
 
285
 
 
286
widget
 
287
pulldown_button (widget w, widget pw) {
 
288
  return new popup_button_rep (w, pw, south_east);
 
289
}
 
290
 
 
291
widget
 
292
pullright_button (widget w, widget pw) {
 
293
  return new popup_button_rep (w, pw, east);
 
294
}
 
295
 
 
296
widget
 
297
pulldown_button (widget w, make_widget mw) {
 
298
  return new popup_button_rep (w, mw, south_east);
 
299
}
 
300
 
 
301
widget
 
302
pullright_button (widget w, make_widget mw) {
 
303
  return new popup_button_rep (w, mw, east);
 
304
}