1 /*
2 * *********************************************************************
3 * * Copyright (C) 1988, 1990 Stanford University. *
4 * * Permission to use, copy, modify, and distribute this *
5 * * software and its documentation for any purpose and without *
6 * * fee is hereby granted, provided that the above copyright *
7 * * notice appear in all copies. Stanford University *
8 * * makes no representations about the suitability of this *
9 * * software for any purpose. It is provided "as is" without *
10 * * express or implied warranty. Export of this software outside *
11 * * of the United States of America may require an export license. *
12 * *********************************************************************
13 */
14
15 /*
16 * Scrollbar manager.
17 */
18 #include "ana.h"
19 #include "ana_glob.h"
20 #include "graphics.h"
21
22 public
23 #define SCROLLBARHEIGHT 16
24 public
25 #define ARROW_WIDTH 32
26
27
28 private void StretchLeft(), StretchRight(), MoveBar();
29 private void MoveLeft(), MoveRight();
30
31
DrawScrollBar(isExpose)32 public void DrawScrollBar( isExpose )
33 int isExpose;
34 {
35 static Coord lastLeft = 0;
36 static Coord lastRight = 0;
37
38 if( isExpose or (scrollBox.left > lastLeft) )
39 FillAREA( window, 0, scrollBox.top, scrollBox.left, SCROLLBARHEIGHT,
40 gcs.white );
41 if( isExpose or (scrollBox.right < lastRight) )
42 FillAREA( window, scrollBox.right, scrollBox.top,
43 XWINDOWSIZE - scrollBox.right, SCROLLBARHEIGHT, gcs.white );
44 HLine( window, textBox.left, textBox.right, textBox.top, gcs.black );
45 lastLeft = scrollBox.left;
46 lastRight = scrollBox.right;
47 XCopyArea( display, pix.left_arrows, window, gcs.black, 0, 0, ARROW_WIDTH,
48 SCROLLBARHEIGHT, scrollBox.left, scrollBox.top );
49 XCopyArea( display, pix.right_arrows, window, gcs.black, 0, 0, ARROW_WIDTH,
50 SCROLLBARHEIGHT, scrollBox.right - ARROW_WIDTH, scrollBox.top );
51 UpdateScrollBar();
52 }
53
54
55 /*
56 * Update and redraw the scrollbar.
57 */
UpdateScrollBar()58 public void UpdateScrollBar()
59 {
60 float tmp;
61
62 if( tims.last == tims.first )
63 {
64 barPos.left = traceBox.left;
65 barPos.right = traceBox.right;
66 }
67 else
68 {
69 TimeType maxTime;
70
71 maxTime = max( tims.last, tims.end );
72 tmp = (float)(traceBox.right - traceBox.left) / (maxTime-tims.first);
73 barPos.left = traceBox.left + round( tmp * (tims.start-tims.first) );
74 barPos.right = barPos.left + round( tmp * tims.steps );
75 if( barPos.right - barPos.left < 3 )
76 {
77 if( barPos.left + 3 > traceBox.right )
78 barPos.left = barPos.right - 3;
79 else
80 barPos.right = barPos.left + 3;
81 }
82 }
83 FillAREA( window, traceBox.left + 1, scrollBox.top + 1,
84 traceBox.right - traceBox.left - 1, SCROLLBARHEIGHT - 2, gcs.gray );
85 VLine( window, traceBox.left, scrollBox.bot, scrollBox.top, gcs.black );
86 VLine( window, traceBox.right, scrollBox.bot, scrollBox.top, gcs.black );
87
88 FillBox( window, barPos, gcs.white );
89 OutlineBox( window, barPos, gcs.black );
90 }
91
92
93
94 /*
95 * Handle button clicks within the scrollbar.
96 */
DoScrollBar(ev)97 public void DoScrollBar( ev )
98 XButtonEvent *ev;
99 {
100 TimeType oldStart, oldSteps;
101
102 if( (ev->x < scrollBox.left) or (ev->x > scrollBox.right) )
103 return;
104
105 if( ev->x < scrollBox.left + (ARROW_WIDTH / 2 - 1) )
106 MoveLeft( 2 );
107 else if( ev->x < traceBox.left )
108 MoveLeft( 1 );
109 else if( ev->x <= traceBox.right )
110 {
111 oldStart = tims.start;
112 oldSteps = tims.steps;
113
114 switch( ev->button & (Button1 | Button2 | Button3) )
115 {
116 case Button1 :
117 StretchLeft( ev->x );
118 break;
119 case Button2 :
120 MoveBar( ev->x );
121 break;
122 case Button3 :
123 StretchRight( ev->x );
124 break;
125 }
126 UpdateScrollBar();
127 if( (oldStart != tims.start) or (oldSteps != tims.steps) )
128 {
129 DrawTraces( tims.start, tims.end );
130 RedrawTimes();
131 }
132 }
133 else if( ev->x < scrollBox.right - (ARROW_WIDTH / 2 - 1) )
134 {
135 MoveRight( 1 );
136 }
137 else /* ( x < scrol.right ) */
138 MoveRight( 2 );
139 }
140
141
142 /*
143 * Stretch the scroll bar to the left, up to the current right side.
144 */
StretchLeft(x)145 private void StretchLeft( x )
146 Coord x;
147 {
148 Coord xmax;
149 XEvent ev;
150 float tmp;
151 TimeType maxTime, ti;
152 BBox b;
153
154 maxTime = max( tims.last, tims.end );
155 if( maxTime <= tims.first )
156 return;
157
158 tmp = (float)(maxTime - tims.first) / (traceBox.right - traceBox.left);
159 xmax = barPos.right - max( 3, round( 10.0 / tmp ) );
160
161 b.top = barPos.top + 1;
162 b.bot = barPos.bot - 1;
163 b.left = barPos.left;
164 b.right = barPos.right - 1;
165 FillBox( window, b, gcs.gray );
166 b.left = min( x, xmax );
167 FillBox( window, b, gcs.white );
168
169 GrabMouse( window, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
170 None );
171
172 UpdateTimes( tims.start, tims.end ); /* initialize it */
173
174 do
175 {
176 XNextEvent( display, &ev );
177 if( ev.type == MotionNotify )
178 x = ev.xmotion.x;
179 else if( ev.type == ButtonRelease )
180 x = ev.xbutton.x;
181 else
182 continue;
183
184 FillBox( window, b, gcs.gray );
185 if( x < traceBox.left )
186 b.left = traceBox.left;
187 else if( x > xmax )
188 b.left = xmax;
189 else
190 b.left = x;
191 FillBox( window, b, gcs.white );
192 ti = tims.first + round( (b.left - traceBox.left) * tmp );
193 UpdateTimes( ti, tims.end );
194 }
195 while( ev.type != ButtonRelease );
196
197 XUngrabPointer( display, CurrentTime );
198 XFlush( display );
199
200 barPos.left = b.left;
201 tims.start = tims.first + round( (b.left - traceBox.left) * tmp );
202 tims.steps = tims.end - tims.start;
203 }
204
205
206
207 /*
208 * Stretch the scroll bar to the right, up to the current left side.
209 */
StretchRight(x)210 private void StretchRight( x )
211 Coord x;
212 {
213 Coord xmin;
214 XEvent ev;
215 float tmp;
216 TimeType maxTime, ti;
217 BBox b;
218
219 maxTime = max( tims.last, tims.end );
220 if( maxTime <= tims.first )
221 return;
222
223 tmp = (float)(maxTime - tims.first) / (traceBox.right - traceBox.left);
224 xmin = barPos.left + max( 3, round( 10.0/tmp ) );
225
226 b.top = barPos.top + 1;
227 b.bot = barPos.bot - 1;
228 b.left = barPos.left + 1;
229 b.right = barPos.right;
230 FillBox( window, b, gcs.gray );
231 b.right = max( x, xmin );
232 FillBox( window, b, gcs.white );
233
234 GrabMouse( window, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
235 None );
236
237 UpdateTimes( tims.start, tims.end ); /* initialize it */
238
239 do
240 {
241 XNextEvent( display, &ev );
242 if( ev.type == MotionNotify )
243 x = ev.xmotion.x;
244 else if( ev.type == ButtonRelease )
245 x = ev.xbutton.x;
246 else
247 continue;
248
249 FillBox( window, b, gcs.gray );
250 if( x < xmin )
251 b.right = xmin;
252 else if( x > traceBox.right )
253 b.right = traceBox.right;
254 else
255 b.right = x;
256 FillBox( window, b, gcs.white );
257 ti = tims.first + round( (b.right - traceBox.left) * tmp );
258 UpdateTimes( tims.start, ti );
259 }
260 while( ev.type != ButtonRelease );
261
262 XUngrabPointer( display, CurrentTime );
263 XFlush( display );
264
265 barPos.right = b.right;
266 tims.end = tims.first + round( (b.right - traceBox.left) * tmp );
267 tims.steps = tims.end - tims.start;
268 }
269
270
271 /*
272 * Move the scrollbar left or right, always within the scrollbar bounds.
273 */
MoveBar(x)274 private void MoveBar( x )
275 Coord x;
276 {
277 XEvent ev;
278 Coord width, handle;
279 Coord top, height;
280 float tmp;
281 TimeType maxTime, t1, t2;
282
283 maxTime = max( tims.last, tims.end );
284 if( maxTime <= tims.first )
285 return;
286
287 tmp = (float)(maxTime - tims.first) / (traceBox.right - traceBox.left);
288
289 top = barPos.top + 1;
290 height = barPos.bot - barPos.top - 1; /* bot - top - 1 - 1 + 1 */
291 width = barPos.right - barPos.left + 1;
292
293 if( x >= barPos.left and x <= barPos.right )
294 handle = x - barPos.left;
295 else if( (x > barPos.right) and (x + width - 1 > traceBox.right) )
296 handle = x + width - traceBox.right - 1;
297 else
298 handle = 0;
299
300 FillAREA( window, barPos.left, top, width, height, gcs.gray );
301 FillAREA( window, x - handle, top, width, height, gcs.white );
302
303 GrabMouse( window, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
304 None );
305
306 UpdateTimes( tims.start, tims.end ); /* initialize it */
307
308 do
309 {
310 XNextEvent( display, &ev );
311 if( ev.type != MotionNotify and ev.type != ButtonRelease )
312 continue;
313
314 FillAREA( window, x - handle, top, width, height, gcs.gray );
315 x = (ev.type == MotionNotify) ? ev.xmotion.x : ev.xbutton.x;
316 if( x - handle + width - 1 > traceBox.right )
317 {
318 if( x > traceBox.right )
319 x = traceBox.right;
320 handle = x - (traceBox.right - width + 1);
321 }
322 else if( x - handle < traceBox.left )
323 {
324 if( x < traceBox.left )
325 x = traceBox.left;
326 handle = x - traceBox.left;
327 }
328 FillAREA( window, x - handle, top, width, height, gcs.white );
329 t1 = round( (x - handle - traceBox.left) * tmp ) + tims.first;
330 t2 = t1 + tims.steps;
331 UpdateTimes( t1, t2 );
332 }
333 while( ev.type != ButtonRelease );
334
335 XUngrabPointer( display, CurrentTime );
336 XFlush( display );
337
338 barPos.left = x - handle;
339 barPos.right = x - handle + width - 1;
340
341 tims.start = round( (barPos.left - traceBox.left) * tmp ) + tims.first;
342 tims.end = tims.start + tims.steps;
343 }
344
345
346 /*
347 * Scroll left by 'hpages' half-pages.
348 */
MoveLeft(hpages)349 private void MoveLeft( hpages )
350 int hpages;
351 {
352 TimeType start;
353
354 start = tims.start - (hpages * tims.steps) / 2;
355
356 if( start < tims.first )
357 start = tims.first;
358
359 if( start == tims.start )
360 return;
361
362 tims.start = start;
363 tims.end = start + tims.steps;
364
365 RedrawTimes();
366 UpdateScrollBar();
367 DrawTraces( start, tims.end );
368 }
369
370
371 /*
372 * Scroll right by 'hpages' half-pages.
373 */
MoveRight(hpages)374 private void MoveRight( hpages )
375 int hpages;
376 {
377 TimeType start;
378
379 start = tims.start + (hpages * tims.steps) / 2;
380
381 if( (start >= tims.last) or (start == tims.start) or
382 (start + tims.steps >= MAX_TIME ) )
383 return;
384
385 tims.start = start;
386 tims.end = start + tims.steps;
387 RedrawTimes();
388 UpdateScrollBar();
389 DrawTraces( start, tims.end );
390 }
391