blob: fce81fa66b2106c6bdd86780d0be0f7d29738d8c [file] [log] [blame]
Dave Barach52642c32016-02-11 19:28:19 -05001/*
2 *------------------------------------------------------------------
3 * Copyright (c) 2006-2016 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <gtk/gtk.h>
19#define GTK_ENABLE_BROKEN // DGMS
20#include <gtk/gtktext.h>
21#include <stdlib.h>
22#include "g2.h"
23#include <string.h>
24
25/*
26 * locals
27 */
28static GtkWidget *s_mainmenubar;
29static GtkWidget *s_filemenu;
30static GtkWidget *s_readdefs;
31static GtkWidget *s_readevents;
32static GtkWidget *s_readeventsclock;
33static GtkWidget *s_readcpel;
34static GtkWidget *s_readclib;
35static GtkWidget *s_print;
36static GtkWidget *s_quit;
37
38static GtkWidget *s_mainfilemenu;
39static GtkWidget *s_help_general;
40static GtkWidget *s_help_about;
41static GtkWidget *s_mainhelpmenu;
42static GtkWidget *s_helpmenu;
43
44static GtkWidget *s_filesel;
45static GtkWidget *s_eventsel;
46
47typedef struct md_ {
48 GtkWidget *entry;
49 GtkWidget *label;
50 GtkWidget *dialog;
51 boolean (*callback)(char *);
52 char *retry_text;
53} md_t;
54
55char *general_help = "\n"
56"G2 is a performance event visualization tool.\n"
57"\n"
58"To view CPEL-format event data:\n"
59"g2 --cpel <filename>\n"
60"or use the File Menu->Read CPEL file option.\n"
61"\n"
62"To view vppinfra-format (.../open-repo/vppinfra/vppinfra/elog.h) event data:\n"
63"g2 --clib <filename>\n"
64"or use the File Menu->Read clib file option.\n"
65"\n"
66"To toggle event detail boxes, left-mouse-click on an event.\n"
67"\n"
68"To zoom to an area, depress the left mouse button. Move the\n"
69"mouse. Release the mouse.\n"
70"\n"
71"To use the time ruler, depress the right mouse button. Move the\n"
72"mouse. Release when done.\n"
73"\n"
74"To push a track to the bottom, <ctrl><left-mouse>\n"
75"\n"
76"To pull a track to the top, <shift><left-mouse>\n"
77"\n"
78"To selectively color/uncolor a track, <ctrl><shift><left-mouse>\n"
79"\n"
80"To make the mouse scrollwheel faster, press <shift>\n"
81"\n"
82"Hotkeys, supposedly Quake-like:\n"
83" w - zoom-in\n"
84" s - zoom-out\n"
85" a - pan-left\n"
86" d - pan-right\n"
87" r - pan-up\n"
88" f - pan-down\n"
89" t - less traces\n"
90" g - more traces\n"
91"\n"
92" e - toggle summary-mode\n"
93" c - toggle color-mode\n"
94"\n"
95" x - take snapshot\n"
96" z - go to next snapshot\n"
97" p - put snapshots to snapshots.g2 \n"
98" l - load snapshots from snapshots.g2\n"
99"\n"
100"<ctrl>q - quit\n"
101"Send comments / bug reports to the \"fd.io\" mailing list.\n";
102
103/****************************************************************************
104* debug_dialog_callback
105****************************************************************************/
106
107boolean debug_dialog_callback (char *s)
108{
109 g_print("Dialog result: %s", s);
110 return (TRUE);
111}
112
113/****************************************************************************
114* get_dialog_value
115****************************************************************************/
116
117static void get_dialog_value (GtkWidget *dialog, gpointer user_data)
118{
119 md_t *md = (md_t *)user_data;
120 char * cb_arg;
121
122 cb_arg = (char *) gtk_entry_get_text(GTK_ENTRY(md->entry));
123
124 if ((*md->callback)(cb_arg)) {
125 gtk_grab_remove(md->dialog);
126 gtk_widget_destroy(md->dialog);
127 } else {
128 gtk_label_set_text (GTK_LABEL(md->label), md->retry_text);
129 }
130}
131
132/****************************************************************************
133* modal_dialog
134****************************************************************************/
135
136void modal_dialog (char *label_text, char *retry_text, char *default_value,
137 boolean (*cb)(char *))
138{
139 GtkWidget *dialog, *label, *ok_button, *entry;
140 static md_t dlg;
141 md_t *md = &dlg;
142
143 dialog = gtk_dialog_new();
144 label = gtk_label_new(label_text);
145
146 entry = gtk_entry_new();
147 if (default_value)
148 gtk_entry_set_text(GTK_ENTRY(entry), default_value);
149
150 ok_button = gtk_button_new_with_label("OK");
151
152 md->entry = entry;
153 md->label = label;
154 md->retry_text = retry_text;
155 md->dialog = dialog;
156 if (cb)
157 md->callback = cb;
158 else
159 md->callback = debug_dialog_callback;
160
161 gtk_signal_connect (GTK_OBJECT (ok_button), "clicked",
162 GTK_SIGNAL_FUNC(get_dialog_value), (gpointer) md);
163
164 gtk_signal_connect (GTK_OBJECT (entry), "activate",
165 GTK_SIGNAL_FUNC(get_dialog_value), (gpointer) md);
166
167 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
168 entry);
169
170 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
171 ok_button);
172 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
173 gtk_widget_show_all(dialog);
174 gtk_widget_grab_focus(entry);
175 gtk_grab_add(dialog);
176}
177
178/****************************************************************************
179* get_eventdef_name
180****************************************************************************/
181
182static void get_eventdef_name (GtkFileSelection *sel, gpointer user_data)
183{
184 char *filename = (char *) gtk_file_selection_get_filename (
185 GTK_FILE_SELECTION(s_filesel));
186 read_event_definitions(filename);
187 set_window_title(filename);
188}
189
190/****************************************************************************
191* read_eventdef_callback
192****************************************************************************/
193
194static void read_eventdef_callback(GtkToggleButton *item, gpointer data)
195{
196
197 s_filesel = gtk_file_selection_new("Read Event Definitions From...");
198
199 gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel),
200 "../h/elog.h");
201
202 gtk_signal_connect (GTK_OBJECT (
203 GTK_FILE_SELECTION(s_filesel)->ok_button),
204 "clicked",
205 GTK_SIGNAL_FUNC(get_eventdef_name), NULL);
206
207 gtk_signal_connect_object (GTK_OBJECT (
208 GTK_FILE_SELECTION(s_filesel)->ok_button),
209 "clicked",
210 GTK_SIGNAL_FUNC (gtk_widget_destroy),
211 (gpointer) s_filesel);
212
213 gtk_signal_connect_object (GTK_OBJECT (
214 GTK_FILE_SELECTION(s_filesel)->cancel_button),
215 "clicked",
216 GTK_SIGNAL_FUNC (gtk_widget_destroy),
217 (gpointer) s_filesel);
218 gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel));
219 gtk_widget_show (s_filesel);
220}
221
222/****************************************************************************
223* get_events_name
224****************************************************************************/
225
226static void get_events_name (GtkFileSelection *sel, gpointer user_data)
227{
228 char *filename = (char *) gtk_file_selection_get_filename (
229 GTK_FILE_SELECTION(s_eventsel));
230 read_events(filename);
231 view1_display_when_idle();
232}
233
234
235/****************************************************************************
236* get_ticks_per_ns
237****************************************************************************/
238
239static boolean get_ticks_per_ns (char *value)
240{
241 double rv;
242
243 rv = atof (value);
244
245 if (rv == 0.0 || rv > 100000)
246 return(FALSE);
247
248 ticks_per_ns = rv;
249 ticks_per_ns_set = TRUE;
250
251 gtk_widget_show(s_eventsel);
252 return(TRUE);
253}
254
255/****************************************************************************
256* read_events_callback
257****************************************************************************/
258
259static void read_events_callback(GtkToggleButton *item, gpointer data)
260{
261 char tmpbuf [32];
262
263 s_eventsel = gtk_file_selection_new("Read Events From...");
264
265 gtk_signal_connect (GTK_OBJECT (
266 GTK_FILE_SELECTION(s_eventsel)->ok_button),
267 "clicked",
268 GTK_SIGNAL_FUNC(get_events_name), NULL);
269
270 gtk_signal_connect_object (GTK_OBJECT (
271 GTK_FILE_SELECTION(s_eventsel)->ok_button),
272 "clicked",
273 GTK_SIGNAL_FUNC (gtk_widget_destroy),
274 (gpointer) s_eventsel);
275
276 gtk_signal_connect_object (GTK_OBJECT (
277 GTK_FILE_SELECTION(s_eventsel)->cancel_button),
278 "clicked",
279 GTK_SIGNAL_FUNC (gtk_widget_destroy),
280 (gpointer) s_eventsel);
281 gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_eventsel));
282
283 if (ticks_per_ns_set)
284 gtk_widget_show (s_eventsel);
285 else {
286 sprintf(tmpbuf, "%.3f", ticks_per_ns);
287 modal_dialog ("Please enter clock ticks per nanosecond",
288 "Invalid: Please enter clock ticks per nanosecond",
289 tmpbuf, get_ticks_per_ns);
290 }
291}
292
293/****************************************************************************
294* read_eventclock_callback
295****************************************************************************/
296
297static void read_eventsclock_callback(GtkToggleButton *item, gpointer data)
298{
299 ticks_per_ns_set = FALSE;
300 read_events_callback(item, data);
301}
302
303/****************************************************************************
304* infobox_size_request
305****************************************************************************/
306
307void infobox_size_request (GtkWidget *widget, GtkRequisition *req,
308 gpointer user_data)
309{
310 char *text = (char *)user_data;
311 char *cp;
312 int widest_line_in_chars;
313 int w;
314 int nlines;
315
316 /*
317 * You'd think that the string extent function would work here.
318 * You'd be wrong.
319 */
320 nlines = w = widest_line_in_chars = 0;
321 for (cp = text; *cp; cp++) {
322 if (*cp == '\n') {
323 if (w > widest_line_in_chars) {
324 widest_line_in_chars = w;
325 }
326 w = 0;
327 nlines++;
328 }
329 w++;
330 }
331
332 nlines++;
333
334 req->width = (widest_line_in_chars * 8) + 20;
335 req->height = (nlines * 13) + 10;
336}
337
338/****************************************************************************
339* infobox
340****************************************************************************/
341
342void infobox(char *label_text, char *text)
343{
344 GtkWidget *dialog, *label, *ok_button, *entry;
345 GtkWidget *box;
346
347 dialog = gtk_dialog_new();
348 label = gtk_label_new(label_text);
349
350 entry = gtk_text_new(NULL, NULL);
351
352 gtk_signal_connect (GTK_OBJECT (entry), "size-request",
353 GTK_SIGNAL_FUNC(infobox_size_request),
354 (gpointer) text);
355
356 gtk_text_insert(GTK_TEXT(entry), g_font, &fg_black, &bg_white,
357 text, -1);
358
359 gtk_text_set_editable(GTK_TEXT(entry), FALSE);
360
361 ok_button = gtk_button_new_with_label("OK");
362
363 gtk_signal_connect_object (GTK_OBJECT (ok_button), "clicked",
364 GTK_SIGNAL_FUNC(gtk_widget_destroy),
365 (gpointer) GTK_OBJECT(dialog));
366
367 box = gtk_vbox_new(FALSE, 5);
368
369
370 gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
371 gtk_box_pack_start(GTK_BOX(box), ok_button, FALSE, FALSE, 0);
372
373 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
374 box);
375
376 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
377 gtk_widget_show_all(dialog);
378}
379
380/****************************************************************************
381* help_general_callback
382****************************************************************************/
383
384static void help_general_callback(GtkToggleButton *item, gpointer data)
385{
386 infobox("General Help", general_help);
387}
388
389/****************************************************************************
390* help_about_callback
391****************************************************************************/
392
393static void help_about_callback(GtkToggleButton *item, gpointer data)
394{
395 char tmpbuf [1024];
396 sprintf (tmpbuf, "G2 -- Graphical Event Viewer\n\n");
397 view1_about(tmpbuf);
398 pointsel_about(tmpbuf);
399 events_about(tmpbuf);
400 sprintf (tmpbuf+strlen(tmpbuf), "\n%s\n", version_string);
401 sprintf (tmpbuf+strlen(tmpbuf), "%s\n", minor_v_string);
402 infobox("About", tmpbuf);
403}
404
405
406/****************************************************************************
407* get_cpel_name
408****************************************************************************/
409
410static void get_cpel_name (GtkFileSelection *sel, gpointer user_data)
411{
412 char *filename = (char *)gtk_file_selection_get_filename (
413 GTK_FILE_SELECTION(s_filesel));
414 read_cpel_file(filename);
415 set_window_title(filename);
416}
417
418/****************************************************************************
419* get_clib_name
420****************************************************************************/
421
422static void get_clib_name (GtkFileSelection *sel, gpointer user_data)
423{
424 char *filename = (char *) gtk_file_selection_get_filename (
425 GTK_FILE_SELECTION(s_filesel));
426 read_clib_file(filename);
427 set_window_title(filename);
428}
429
430/****************************************************************************
431* read_cpel_callback
432****************************************************************************/
433
434static void read_cpel_callback(GtkToggleButton *item, gpointer data)
435{
436
437 s_filesel = gtk_file_selection_new("Read CPEL data from...");
438
439 gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel),
440 "cpel.out");
441
442 gtk_signal_connect (GTK_OBJECT (
443 GTK_FILE_SELECTION(s_filesel)->ok_button),
444 "clicked",
445 GTK_SIGNAL_FUNC(get_cpel_name), NULL);
446
447 gtk_signal_connect_object (GTK_OBJECT (
448 GTK_FILE_SELECTION(s_filesel)->ok_button),
449 "clicked",
450 GTK_SIGNAL_FUNC (gtk_widget_destroy),
451 (gpointer) s_filesel);
452
453 gtk_signal_connect_object (GTK_OBJECT (
454 GTK_FILE_SELECTION(s_filesel)->cancel_button),
455 "clicked",
456 GTK_SIGNAL_FUNC (gtk_widget_destroy),
457 (gpointer) s_filesel);
458 gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel));
459 gtk_widget_show (s_filesel);
460}
461
462/****************************************************************************
463* read_clib_callback
464****************************************************************************/
465
466static void read_clib_callback(GtkToggleButton *item, gpointer data)
467{
468
469 s_filesel = gtk_file_selection_new("Read clib data From...");
470
471 gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel),
472 "clib.out");
473
474 gtk_signal_connect (GTK_OBJECT (
475 GTK_FILE_SELECTION(s_filesel)->ok_button),
476 "clicked",
477 GTK_SIGNAL_FUNC(get_clib_name), NULL);
478
479 gtk_signal_connect_object (GTK_OBJECT (
480 GTK_FILE_SELECTION(s_filesel)->ok_button),
481 "clicked",
482 GTK_SIGNAL_FUNC (gtk_widget_destroy),
483 (gpointer) s_filesel);
484
485 gtk_signal_connect_object (GTK_OBJECT (
486 GTK_FILE_SELECTION(s_filesel)->cancel_button),
487 "clicked",
488 GTK_SIGNAL_FUNC (gtk_widget_destroy),
489 (gpointer) s_filesel);
490 gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel));
491 gtk_widget_show (s_filesel);
492}
493
494/****************************************************************************
495* menu1_init
496****************************************************************************/
497
498void menu1_init(void)
499{
500
501 s_filemenu = gtk_menu_new();
502
503 s_readcpel = gtk_menu_item_new_with_label
504 ("Read CPEL file");
505 gtk_menu_append(GTK_MENU(s_filemenu), s_readcpel);
506 gtk_signal_connect(GTK_OBJECT(s_readcpel), "activate",
507 GTK_SIGNAL_FUNC(read_cpel_callback), 0);
508
509 s_readclib = gtk_menu_item_new_with_label
510 ("Read CLIB file");
511 gtk_menu_append(GTK_MENU(s_filemenu), s_readclib);
512 gtk_signal_connect(GTK_OBJECT(s_readclib), "activate",
513 GTK_SIGNAL_FUNC(read_clib_callback), 0);
514
515 s_readdefs = gtk_menu_item_new_with_label ("Read Event Definitions");
516 gtk_menu_append(GTK_MENU(s_filemenu), s_readdefs);
517 gtk_signal_connect(GTK_OBJECT(s_readdefs), "activate",
518 GTK_SIGNAL_FUNC(read_eventdef_callback), 0);
519
520 s_readevents = gtk_menu_item_new_with_label ("Read Event Log");
521 gtk_menu_append(GTK_MENU(s_filemenu), s_readevents);
522 gtk_signal_connect(GTK_OBJECT(s_readevents), "activate",
523 GTK_SIGNAL_FUNC(read_events_callback), 0);
524
525 s_readeventsclock = gtk_menu_item_new_with_label
526 ("Read Event Log with Different Clock Rate");
527 gtk_menu_append(GTK_MENU(s_filemenu), s_readeventsclock);
528 gtk_signal_connect(GTK_OBJECT(s_readeventsclock), "activate",
529 GTK_SIGNAL_FUNC(read_eventsclock_callback), 0);
530
531 s_print = gtk_menu_item_new_with_label ("Print");
532 gtk_menu_append(GTK_MENU(s_filemenu), s_print);
533 gtk_signal_connect(GTK_OBJECT(s_print), "activate",
534 GTK_SIGNAL_FUNC(view1_print_callback), 0);
535
536 s_quit = gtk_menu_item_new_with_label ("Exit");
537 gtk_menu_append(GTK_MENU(s_filemenu), s_quit);
538 gtk_signal_connect(GTK_OBJECT(s_quit), "activate",
539 GTK_SIGNAL_FUNC(gtk_main_quit), 0);
540
541 s_mainfilemenu = gtk_menu_item_new_with_label("File");
542 gtk_menu_item_set_submenu(GTK_MENU_ITEM(s_mainfilemenu), s_filemenu);
543
544 s_helpmenu = gtk_menu_new();
545
546 s_help_general = gtk_menu_item_new_with_label ("General");
547 gtk_menu_append(GTK_MENU(s_helpmenu), s_help_general);
548 gtk_signal_connect(GTK_OBJECT(s_help_general), "activate",
549 GTK_SIGNAL_FUNC(help_general_callback), 0);
550
551 s_help_about = gtk_menu_item_new_with_label ("About");
552 gtk_menu_append(GTK_MENU(s_helpmenu), s_help_about);
553 gtk_signal_connect(GTK_OBJECT(s_help_about), "activate",
554 GTK_SIGNAL_FUNC(help_about_callback), 0);
555
556 s_mainhelpmenu = gtk_menu_item_new_with_label("Help");
557 gtk_menu_item_set_submenu(GTK_MENU_ITEM(s_mainhelpmenu), s_helpmenu);
558
559 s_mainmenubar = gtk_menu_bar_new();
560 gtk_menu_bar_append(GTK_MENU_BAR(s_mainmenubar), s_mainfilemenu);
561 gtk_menu_bar_append(GTK_MENU_BAR(s_mainmenubar), s_mainhelpmenu);
562 gtk_widget_show_all(s_mainmenubar);
563
564 gtk_box_pack_start(GTK_BOX(g_mainvbox), s_mainmenubar, FALSE, FALSE, 0);
565}