1 /*
2 * Copyright (c) Tony Bybell 1999-2016.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 */
9
10 #include <config.h>
11 #include "globals.h"
12 #include "pixmaps.h"
13 #include "currenttime.h"
14 #include "debug.h"
15
16
fix_wavehadj(void)17 void fix_wavehadj(void)
18 {
19 GtkAdjustment *hadj;
20 gfloat pageinc;
21
22 hadj=GTK_ADJUSTMENT(GLOBALS->wave_hslider);
23 hadj->lower=GLOBALS->tims.first;
24 hadj->upper=GLOBALS->tims.last+2.0;
25
26 pageinc=(gfloat)(((gdouble)GLOBALS->wavewidth)*GLOBALS->nspx);
27 hadj->page_size=hadj->page_increment=(pageinc>=1.0)?pageinc:1.0;
28
29 /* hadj->step_increment=(GLOBALS->nspx>=1.0)?GLOBALS->nspx:1.0; */
30
31 hadj->step_increment = pageinc / 10.0;
32 if(hadj->step_increment < 1.0) hadj->step_increment = 1.0;
33
34 if(hadj->page_size >= (hadj->upper-hadj->lower)) hadj->value=hadj->lower;
35 if(hadj->value+hadj->page_size>hadj->upper)
36 {
37 hadj->value=hadj->upper-hadj->page_size;
38 if(hadj->value<hadj->lower)
39 hadj->value=hadj->lower;
40 }
41 }
42
service_zoom_left(GtkWidget * text,gpointer data)43 void service_zoom_left(GtkWidget *text, gpointer data)
44 {
45 (void)text;
46 (void)data;
47
48 GtkAdjustment *hadj;
49
50 if(GLOBALS->helpbox_is_active)
51 {
52 help_text_bold("\n\nZoom To Start");
53 help_text(
54 " is used to jump scroll to the trace's beginning."
55 );
56 return;
57 }
58
59 hadj=GTK_ADJUSTMENT(GLOBALS->wave_hslider);
60 hadj->value=GLOBALS->tims.timecache=GLOBALS->tims.first;
61 time_update();
62 }
63
service_zoom_right(GtkWidget * text,gpointer data)64 void service_zoom_right(GtkWidget *text, gpointer data)
65 {
66 (void)text;
67 (void)data;
68
69 GtkAdjustment *hadj;
70 TimeType ntinc;
71
72 if(GLOBALS->helpbox_is_active)
73 {
74 help_text_bold("\n\nZoom To End");
75 help_text(
76 " is used to jump scroll to the trace's end."
77 );
78 return;
79 }
80
81 ntinc=(TimeType)(((gdouble)GLOBALS->wavewidth)*GLOBALS->nspx);
82
83 GLOBALS->tims.timecache=GLOBALS->tims.last-ntinc+1;
84 if(GLOBALS->tims.timecache<GLOBALS->tims.first) GLOBALS->tims.timecache=GLOBALS->tims.first;
85
86 hadj=GTK_ADJUSTMENT(GLOBALS->wave_hslider);
87 hadj->value=GLOBALS->tims.timecache;
88 time_update();
89 }
90
service_zoom_out(GtkWidget * text,gpointer data)91 void service_zoom_out(GtkWidget *text, gpointer data)
92 {
93 (void)text;
94 (void)data;
95
96 TimeType middle=0, width;
97
98 if(GLOBALS->helpbox_is_active)
99 {
100 help_text_bold("\n\nZoom Out");
101 help_text(
102 " is used to decrease the zoom factor around the marker."
103 #ifdef WAVE_USE_GTK2
104 " Alt + Scrollwheel Up also hits this button in non-alternative wheel mode."
105 #endif
106 );
107 return;
108 }
109
110 if(GLOBALS->do_zoom_center)
111 {
112 if((GLOBALS->tims.marker<0)||(GLOBALS->tims.marker<GLOBALS->tims.first)||(GLOBALS->tims.marker>GLOBALS->tims.last))
113 {
114 if(GLOBALS->tims.end>GLOBALS->tims.last) GLOBALS->tims.end=GLOBALS->tims.last;
115 middle=(GLOBALS->tims.start/2)+(GLOBALS->tims.end/2);
116 if((GLOBALS->tims.start&1)&&(GLOBALS->tims.end&1)) middle++;
117 }
118 else
119 {
120 middle=GLOBALS->tims.marker;
121 }
122 }
123
124 GLOBALS->tims.prevzoom=GLOBALS->tims.zoom;
125
126 GLOBALS->tims.zoom--;
127 calczoom(GLOBALS->tims.zoom);
128
129 if(GLOBALS->do_zoom_center)
130 {
131 width=(TimeType)(((gdouble)GLOBALS->wavewidth)*GLOBALS->nspx);
132 GLOBALS->tims.start=time_trunc(middle-(width/2));
133 if(GLOBALS->tims.start+width>GLOBALS->tims.last) GLOBALS->tims.start=time_trunc(GLOBALS->tims.last-width);
134 if(GLOBALS->tims.start<GLOBALS->tims.first) GLOBALS->tims.start=GLOBALS->tims.first;
135 GTK_ADJUSTMENT(GLOBALS->wave_hslider)->value=GLOBALS->tims.timecache=GLOBALS->tims.start;
136 }
137 else
138 {
139 GLOBALS->tims.timecache=0;
140 }
141
142 fix_wavehadj();
143
144 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed"); /* force zoom update */
145 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed"); /* force zoom update */
146
147 DEBUG(printf("Zoombuttons out\n"));
148 }
149
service_zoom_in(GtkWidget * text,gpointer data)150 void service_zoom_in(GtkWidget *text, gpointer data)
151 {
152 (void)text;
153 (void)data;
154
155 if(GLOBALS->helpbox_is_active)
156 {
157 help_text_bold("\n\nZoom In");
158 help_text(
159 " is used to increase the zoom factor around the marker."
160 #ifdef WAVE_USE_GTK2
161 " Alt + Scrollwheel Down also hits this button in non-alternative wheel mode."
162 #endif
163 );
164 return;
165 }
166
167 if(GLOBALS->tims.zoom<0) /* otherwise it's ridiculous and can cause */
168 { /* overflow problems in the scope */
169 TimeType middle=0, width;
170
171 if(GLOBALS->do_zoom_center)
172 {
173 if((GLOBALS->tims.marker<0)||(GLOBALS->tims.marker<GLOBALS->tims.first)||(GLOBALS->tims.marker>GLOBALS->tims.last))
174 {
175 if(GLOBALS->tims.end>GLOBALS->tims.last) GLOBALS->tims.end=GLOBALS->tims.last;
176 middle=(GLOBALS->tims.start/2)+(GLOBALS->tims.end/2);
177 if((GLOBALS->tims.start&1)&&(GLOBALS->tims.end&1)) middle++;
178 }
179 else
180 {
181 middle=GLOBALS->tims.marker;
182 }
183 }
184
185 GLOBALS->tims.prevzoom=GLOBALS->tims.zoom;
186
187 GLOBALS->tims.zoom++;
188 calczoom(GLOBALS->tims.zoom);
189
190 if(GLOBALS->do_zoom_center)
191 {
192 width=(TimeType)(((gdouble)GLOBALS->wavewidth)*GLOBALS->nspx);
193 GLOBALS->tims.start=time_trunc(middle-(width/2));
194 if(GLOBALS->tims.start+width>GLOBALS->tims.last) GLOBALS->tims.start=time_trunc(GLOBALS->tims.last-width);
195 if(GLOBALS->tims.start<GLOBALS->tims.first) GLOBALS->tims.start=GLOBALS->tims.first;
196 GTK_ADJUSTMENT(GLOBALS->wave_hslider)->value=GLOBALS->tims.timecache=GLOBALS->tims.start;
197 }
198 else
199 {
200 GLOBALS->tims.timecache=0;
201 }
202
203 fix_wavehadj();
204
205 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed"); /* force zoom update */
206 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed"); /* force zoom update */
207
208 DEBUG(printf("Zoombuttons in\n"));
209 }
210 }
211
service_zoom_undo(GtkWidget * text,gpointer data)212 void service_zoom_undo(GtkWidget *text, gpointer data)
213 {
214 (void)text;
215 (void)data;
216
217 gdouble temp;
218
219 if(GLOBALS->helpbox_is_active)
220 {
221 help_text_bold("\n\nZoom Undo");
222 help_text(
223 " is used to revert to the previous zoom value used. Undo"
224 " only works one level deep."
225 );
226 return;
227 }
228
229
230 temp=GLOBALS->tims.zoom;
231 GLOBALS->tims.zoom=GLOBALS->tims.prevzoom;
232 GLOBALS->tims.prevzoom=temp;
233 GLOBALS->tims.timecache=0;
234 calczoom(GLOBALS->tims.zoom);
235 fix_wavehadj();
236
237 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed"); /* force zoom update */
238 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed"); /* force zoom update */
239
240 DEBUG(printf("Zoombuttons Undo\n"));
241 }
242
service_zoom_fit(GtkWidget * text,gpointer data)243 void service_zoom_fit(GtkWidget *text, gpointer data)
244 {
245 (void)text;
246 (void)data;
247
248 gdouble estimated;
249 int fixedwidth;
250
251 if(GLOBALS->helpbox_is_active)
252 {
253 help_text_bold("\n\nZoom Best Fit");
254 help_text(
255 " attempts a \"best fit\" to get the whole trace onscreen."
256 " Note that the trace may be more or less than a whole screen since"
257 " this isn't a \"perfect fit.\" Also, if the middle button baseline"
258 " marker is nailed down, the zoom instead of getting the whole trace"
259 " onscreen will use the part of the trace between the primary"
260 " marker and the baseline marker."
261 );
262 return;
263 }
264
265 if((GLOBALS->tims.baseline>=0)&&(GLOBALS->tims.marker>=0))
266 {
267 service_dragzoom(GLOBALS->tims.baseline, GLOBALS->tims.marker); /* new semantics added to zoom between the two */
268 }
269 else
270 {
271 if(GLOBALS->wavewidth>4) { fixedwidth=GLOBALS->wavewidth-4; } else { fixedwidth=GLOBALS->wavewidth; }
272 estimated=-log(((gdouble)(GLOBALS->tims.last-GLOBALS->tims.first+1))/((gdouble)fixedwidth)*((gdouble)200.0))/log(GLOBALS->zoombase);
273 if(estimated>((gdouble)(0.0))) estimated=((gdouble)(0.0));
274
275 GLOBALS->tims.prevzoom=GLOBALS->tims.zoom;
276 GLOBALS->tims.timecache=0;
277
278 calczoom(estimated);
279 GLOBALS->tims.zoom=estimated;
280
281 fix_wavehadj();
282
283 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed"); /* force zoom update */
284 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed"); /* force zoom update */
285 }
286
287 DEBUG(printf("Zoombuttons Fit\n"));
288 }
289
service_zoom_full(GtkWidget * text,gpointer data)290 void service_zoom_full(GtkWidget *text, gpointer data)
291 {
292 (void)text;
293 (void)data;
294
295 gdouble estimated;
296 int fixedwidth;
297
298 if(GLOBALS->helpbox_is_active)
299 {
300 help_text_bold("\n\nZoom Full");
301 help_text(
302 " attempts a \"best fit\" to get the whole trace onscreen."
303 " Note that the trace may be more or less than a whole screen since"
304 " this isn't a \"perfect fit.\""
305 );
306 return;
307 }
308
309 if(GLOBALS->wavewidth>4) { fixedwidth=GLOBALS->wavewidth-4; } else { fixedwidth=GLOBALS->wavewidth; }
310 estimated=-log(((gdouble)(GLOBALS->tims.last-GLOBALS->tims.first+1))/((gdouble)fixedwidth)*((gdouble)200.0))/log(GLOBALS->zoombase);
311 if(estimated>((gdouble)(0.0))) estimated=((gdouble)(0.0));
312
313 GLOBALS->tims.prevzoom=GLOBALS->tims.zoom;
314 GLOBALS->tims.timecache=0;
315
316 calczoom(estimated);
317 GLOBALS->tims.zoom=estimated;
318
319 fix_wavehadj();
320
321 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed"); /* force zoom update */
322 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed"); /* force zoom update */
323
324 DEBUG(printf("Zoombuttons Full\n"));
325 }
326
327
service_dragzoom(TimeType time1,TimeType time2)328 void service_dragzoom(TimeType time1, TimeType time2) /* the function you've been waiting for... */
329 {
330 gdouble estimated;
331 int fixedwidth;
332 TimeType temp;
333 GtkAdjustment *hadj;
334 Trptr t;
335 int dragzoom_ok = 1;
336
337 if(time2<time1)
338 {
339 temp=time1;
340 time1=time2;
341 time2=temp;
342 }
343
344 if(GLOBALS->dragzoom_threshold)
345 {
346 TimeType tdelta = time2 - time1;
347 gdouble x = tdelta * GLOBALS->pxns;
348 if(x<GLOBALS->dragzoom_threshold)
349 {
350 dragzoom_ok = 0;
351 }
352 }
353
354 if((time2>time1)&&(dragzoom_ok)) /* ensure at least 1 tick and dragzoom_threshold if set */
355 {
356 if(GLOBALS->wavewidth>4) { fixedwidth=GLOBALS->wavewidth-4; } else { fixedwidth=GLOBALS->wavewidth; }
357 estimated=-log(((gdouble)(time2-time1+1))/((gdouble)fixedwidth)*((gdouble)200.0))/log(GLOBALS->zoombase);
358 if(estimated>((gdouble)(0.0))) estimated=((gdouble)(0.0));
359
360 GLOBALS->tims.prevzoom=GLOBALS->tims.zoom;
361 GLOBALS->tims.timecache=GLOBALS->tims.laststart=GLOBALS->tims.start=time_trunc(time1);
362
363 for(t=GLOBALS->traces.first;t;t=t->t_next) /* have to nuke string refs so printout is ok! */
364 {
365 if(t->asciivalue) { free_2(t->asciivalue); t->asciivalue=NULL; }
366 }
367
368 for(t=GLOBALS->traces.buffer;t;t=t->t_next)
369 {
370 if(t->asciivalue) { free_2(t->asciivalue); t->asciivalue=NULL; }
371 }
372
373 if(!((GLOBALS->tims.baseline>=0)&&(GLOBALS->tims.marker>=0)))
374 {
375 update_markertime(GLOBALS->tims.marker=-1);
376 }
377 GLOBALS->signalwindow_width_dirty=1;
378 MaxSignalLength();
379
380
381 hadj=GTK_ADJUSTMENT(GLOBALS->wave_hslider);
382 hadj->value=time1;
383
384 calczoom(estimated);
385 GLOBALS->tims.zoom=estimated;
386
387 fix_wavehadj();
388
389 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed"); /* force zoom update */
390 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed"); /* force zoom update */
391
392 DEBUG(printf("Drag Zoom\n"));
393 }
394 }
395
396 /* Create actual buttons */
397 GtkWidget *
create_zoom_buttons(void)398 create_zoom_buttons (void)
399 {
400 GtkWidget *table;
401 GtkWidget *table2;
402 GtkWidget *frame;
403 GtkWidget *main_vbox;
404 GtkWidget *b1;
405 GtkWidget *b2;
406 GtkWidget *b3;
407 GtkWidget *b4;
408 GtkWidget *b5;
409 GtkWidget *b6;
410 GtkWidget *pixmapzout, *pixmapzin, *pixmapzfit, *pixmapzundo;
411 GtkWidget *pixmapzleft, *pixmapzright;
412
413 GtkTooltips *tooltips;
414
415 tooltips=gtk_tooltips_new_2();
416 gtk_tooltips_set_delay_2(tooltips,1500);
417
418 pixmapzin=gtk_pixmap_new(GLOBALS->zoomin_pixmap, GLOBALS->zoomin_mask);
419 gtk_widget_show(pixmapzin);
420 pixmapzout=gtk_pixmap_new(GLOBALS->zoomout_pixmap, GLOBALS->zoomout_mask);
421 gtk_widget_show(pixmapzout);
422 pixmapzfit=gtk_pixmap_new(GLOBALS->zoomfit_pixmap, GLOBALS->zoomfit_mask);
423 gtk_widget_show(pixmapzfit);
424 pixmapzundo=gtk_pixmap_new(GLOBALS->zoomundo_pixmap, GLOBALS->zoomundo_mask);
425 gtk_widget_show(pixmapzundo);
426
427 pixmapzleft=gtk_pixmap_new(GLOBALS->zoom_larrow_pixmap, GLOBALS->zoom_larrow_mask);
428 gtk_widget_show(pixmapzleft);
429 pixmapzright=gtk_pixmap_new(GLOBALS->zoom_rarrow_pixmap, GLOBALS->zoom_rarrow_mask);
430 gtk_widget_show(pixmapzright);
431
432
433 /* Create a table to hold the text widget and scrollbars */
434 table = gtk_table_new (1, 1, FALSE);
435
436 main_vbox = gtk_vbox_new (FALSE, 1);
437 gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
438 gtk_container_add (GTK_CONTAINER (table), main_vbox);
439
440 frame = gtk_frame_new ("Zoom ");
441 gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
442 gtk_widget_show (frame);
443 gtk_widget_show (main_vbox);
444
445 table2 = gtk_table_new (2, 3, FALSE);
446
447 b1 = gtk_button_new();
448 gtk_container_add(GTK_CONTAINER(b1), pixmapzin);
449 gtk_table_attach (GTK_TABLE (table2), b1, 0, 1, 0, 1,
450 GTK_FILL | GTK_EXPAND,
451 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
452 gtk_signal_connect_object (GTK_OBJECT (b1), "clicked", GTK_SIGNAL_FUNC(service_zoom_out), GTK_OBJECT (table2));
453 gtk_tooltips_set_tip_2(tooltips, b1, "Zoom Out", NULL);
454 gtk_widget_show(b1);
455
456 b2 = gtk_button_new();
457 gtk_container_add(GTK_CONTAINER(b2), pixmapzout);
458 gtk_table_attach (GTK_TABLE (table2), b2, 0, 1, 1, 2,
459 GTK_FILL | GTK_EXPAND,
460 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
461 gtk_signal_connect_object (GTK_OBJECT (b2), "clicked", GTK_SIGNAL_FUNC(service_zoom_in), GTK_OBJECT (table2));
462 gtk_tooltips_set_tip_2(tooltips, b2, "Zoom In", NULL);
463 gtk_widget_show(b2);
464
465 b3 = gtk_button_new();
466 gtk_container_add(GTK_CONTAINER(b3), pixmapzfit);
467 gtk_table_attach (GTK_TABLE (table2), b3, 1, 2, 0, 1,
468 GTK_FILL | GTK_EXPAND,
469 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
470 gtk_signal_connect_object (GTK_OBJECT (b3), "clicked", GTK_SIGNAL_FUNC(service_zoom_fit), GTK_OBJECT (table2));
471 gtk_tooltips_set_tip_2(tooltips, b3, "Zoom Best Fit", NULL);
472 gtk_widget_show(b3);
473
474 b4 = gtk_button_new();
475 gtk_container_add(GTK_CONTAINER(b4), pixmapzundo);
476 gtk_table_attach (GTK_TABLE (table2), b4, 1, 2, 1, 2,
477 GTK_FILL | GTK_EXPAND,
478 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
479 gtk_signal_connect_object (GTK_OBJECT (b4), "clicked", GTK_SIGNAL_FUNC(service_zoom_undo), GTK_OBJECT (table2));
480 gtk_tooltips_set_tip_2(tooltips, b4, "Undo Last Zoom", NULL);
481 gtk_widget_show(b4);
482
483 b5 = gtk_button_new();
484 gtk_container_add(GTK_CONTAINER(b5), pixmapzleft);
485 gtk_table_attach (GTK_TABLE (table2), b5, 2, 3, 0, 1,
486 GTK_FILL | GTK_EXPAND,
487 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
488 gtk_signal_connect_object (GTK_OBJECT (b5), "clicked", GTK_SIGNAL_FUNC(service_zoom_left), GTK_OBJECT (table2));
489 gtk_tooltips_set_tip_2(tooltips, b5, "Zoom To Start", NULL);
490 gtk_widget_show(b5);
491
492 b6 = gtk_button_new();
493 gtk_container_add(GTK_CONTAINER(b6), pixmapzright);
494 gtk_table_attach (GTK_TABLE (table2), b6, 2, 3, 1, 2,
495 GTK_FILL | GTK_EXPAND,
496 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
497 gtk_signal_connect_object (GTK_OBJECT (b6), "clicked", GTK_SIGNAL_FUNC(service_zoom_right), GTK_OBJECT (table2));
498 gtk_tooltips_set_tip_2(tooltips, b6, "Zoom To End", NULL);
499 gtk_widget_show(b6);
500
501
502 gtk_container_add (GTK_CONTAINER (frame), table2);
503
504 gtk_widget_show(table2);
505
506 return table;
507 }
508
509