3.8. gtklog.g - The Log program in GTK

/*--------------------------------------------------------------------
 * File:        gtklog.g
 *
 * Description: Demonstrates the Cascade TextLogger
 *
 * Functions:
 *                prepare_times
 *                get_recent_data
 *                control_button
 *                create_log
 *                main
 *------------------------------------------------------------------*/

/* Get access to the library of common functions. */
require("lib/common.g");
  
/* Keep track of all child processes that this process has started. */
Children := nil;

/* Create global variables for timers related to plots in gnuplot.
 * These timers are used in the lib/common.g log_toggle() function.
 */
PT_TIMER = nil;
RCNT_TIMER = nil;

/*--------------------------------------------------------------------
 * Function:    prepare_times
 * Returns:     t or nil
 * Description: Writes time data to the gnuplot load file pllogtimes.dat.
 *              The data is used to create x-axis labels for time, and
 *              to update the top and bottom range, to give a scrolling
 *              "trend" effect to the plot.
 *------------------------------------------------------------------*/
function prepare_times ()
{
  local line, time, top, bottom;
  local fp = open("/tmp/cogentdemo/pllogtimes.dat", "w", nil);

  cuttime = (floor(clock() / 10000) * 10000);
  line = string("cuttime = ", cuttime, "\n");
  writec(fp, line);

  top = nanoclock() - cuttime;
  line = string("top = ", top, "\n");
  writec(fp, line);

  bottom = top - 15;
  line = string("bottom = ", bottom, "\n");
  writec(fp, line);
  close(fp);
}

/*--------------------------------------------------------------------
 * Function:    get_recent_data
 * Returns:     t or nil
 * Description: disables the tldemorecent log, renames the tlrecent.dat
 *              file, and restarts logging to a new tlrecent.dat file.
 *------------------------------------------------------------------*/
function get_recent_data()
{
  local tsk, fr, fw, line = "";

  if ((tsk = locate_task("tlog", nil)) != nil)
    {
      send(tsk, `disable (tldemorecent));
      rename("/tmp/cogentdemo/tlrecent.dat", "/tmp/cogentdemo/tlold.dat");
      
      /* Ensure that tlrecent.dat file gets closed and deleted. */
      send(tsk, `file("/tmp/cogentdemo/null.dat", tldemorecent));
      
      send(tsk, `file("/tmp/cogentdemo/tlrecent.dat", tldemorecent));
      send(tsk, `enable(tldemorecent));
    }
}

/*--------------------------------------------------------------------
 * Function:    control_button
 * Returns:     A GtkToggleButton
 * Description: Builds control buttons.
 *------------------------------------------------------------------*/
function control_button(lbl, color, prog, process_name, arg1, arg2,
                        arg3, arg4, arg5, arg6, arg7, msgno, container)
{
  local button;
  button = new(GtkToggleButton);
  button.label = lbl;
  button.set_color(1, GTK_STATE_NORMAL, color);
  button.set_color(1, GTK_STATE_PRELIGHT, (color + 0x111111));
  button.set_color(1, GTK_STATE_ACTIVE, (color - 0x111111));
  if (container != nil)
    container.pack_start(button, TRUE, TRUE, 0);
  button.signal("toggled", `start_stop(@button, @prog, @process_name,
                                       @arg1, @arg2, @arg3, @arg4,
                                       @arg5, @arg6, @arg7));
  button.signal("enter", `send_message(@msgno));
  button.signal("leave", `send_message("5"));
  button.show();
  button;
}

/*--------------------------------------------------------------------
 * Function:    create_log
 * Returns:     A GtkWindow
 * Description: Creates the Log window.
 *------------------------------------------------------------------*/
function create_log ()
{
  local log_win, title, frame, box1, box2, box3, rbut1, rbut2, rbut3;
  local cbut1, cbut2, label, entry, table, tlbut, ibut, sbut, text;
  local pbut1, pbut2, swin;
  
  log_win = new (GtkWindow);
  log_win.signal ("destroy", #log_win = nil);
  log_win.title = "Cogent Tools Demo: Log";
  log_win.set_color(1, GTK_STATE_NORMAL, 0xdddddd);
  log_win.border_width = 10;
  log_win.width = 420;
  
  /* Title frame. */
  
  box1 = new(GtkVBox);
  title = new (GtkLabel);
  title.set_text("Cogent Tools Demo - Log");
  title.set_color(1, GTK_STATE_NORMAL, 0xff0000);
  title.height = 25;

  frame = new(GtkFrame);
  frame.set_color(1, GTK_STATE_NORMAL, 0xff0000);
  frame.add(title);
  frame.border_width = 5;
  box1.pack_start(frame, TRUE, TRUE, 5);
  log_win.add (box1);
  
  /* "Cascade TextLogger" frame and widgets. */
  
  box2 = new (GtkHBox);
  box1.pack_start(box2, TRUE, TRUE, 0);
  box2.border_width = 0;

  frame = new(GtkFrame);
  frame.border_width = 5;
  frame.set_color(1, GTK_STATE_NORMAL, 0xaaccee);
  frame.set_label("Cascade TextLogger");
  frame.set_label_align(.5, 1);
  frame.set_shadow_type(GTK_SHADOW_IN);
  box2.pack_start(frame, TRUE, TRUE, 0);

  table = gtk_table_new(3, 2, FALSE);
  table.border_width = 5;
  table.set_col_spacings(25);
  table.set_row_spacings(3);

  /* Collect: Any, All, and Fill buttons. */
  
  box3 = new (GtkHBox);
  box3.spacing = 0;

  label = new(GtkLabel);
  label.set_text("Collect: ");
  box3.pack_start (label, TRUE, TRUE, 0);
  
  rbut1 = gtk_radio_button_new_with_label(nil, "Any");
  rbut1.set_active(TRUE);
  box3.pack_start (rbut1, TRUE, TRUE, 0);
  rbut1.signal("clicked", `send_command(@rbut1, "collect", #any));
  button_messages (rbut1, "5.1", "5");
  
  rbut2 = gtk_radio_button_new_with_label(list(rbut1), "Fill");
  box3.pack_start (rbut2, TRUE, TRUE, 0);
  rbut2.signal("clicked", `send_command(@rbut2, "collect", #fill));
  button_messages (rbut2, "5.2", "5");
  
  rbut3 = gtk_radio_button_new_with_label(list(rbut1, rbut2), "All");
  box3.pack_start (rbut3, TRUE, TRUE, 0);
  rbut3.signal("clicked", `send_command(@rbut3, "collect", #all));
  button_messages (rbut3, "5.3", "5");
  
  table.attach_defaults(box3, 1, 2, 0, 1);

  /* Insert Text button and text entry. */
  
  box3 = new (GtkHBox);
  entry = new(GtkEntry);
  entry.set_text("# A line of text.");
  entry.width = 110;

  ibut = new(GtkButton);
  ibut.label = "Insert Text";
  ibut.set_color(1, GTK_STATE_NORMAL, 0xaaccee);
  ibut.set_color(1, GTK_STATE_PRELIGHT, 0xbbddff);
  ibut.width = 70;
  ibut.signal("clicked", `send_command(@entry, "send-text", nil));
  button_messages (ibut, "5.4", "5");
  
  box3.pack_start (ibut, FALSE, TRUE, 0);
  box3.pack_start(entry, TRUE, TRUE, 5);
  table.attach_defaults(box3, 1, 2, 1, 2);
  
  /* Send Cmd button and text entry. */
  
  box3 = new (GtkHBox);
  entry = new(GtkEntry);
  entry.set_text("(exit)");
  entry.width = 110;

  sbut = new(GtkButton);
  sbut.label = "Send Cmd";
  sbut.set_color(1, GTK_STATE_NORMAL, 0xaaccee);
  sbut.set_color(1, GTK_STATE_PRELIGHT, 0xbbddff);
  sbut.width = 70;
  sbut.signal("clicked", `send_command(@entry, "send-cmd", nil));
  button_messages (sbut, "5.5", "5");
  
  box3.pack_start (sbut, FALSE, TRUE, 0);
  box3.pack_start(entry, TRUE, TRUE, 5);  
  table.attach_defaults(box3, 1, 2, 2, 3);
  
  /* Log to, file, and stdout buttons. */
  
  text = new(GtkText);
  text.set_editable(FALSE);
  anygui_show_text(text, string("To start the demo, ensure the PID Emulator\n", 
                                "is running, then press the Log to: button\n\n",
                                read_msg("5.11")), 1);
  
  tlbut = control_button("Log to:", 0xaaccee, "textlog", "tlog",
                         "-n", "tlog", "-d", "toolsdemo", "-f", "tl.cfg",
                         "-D", "5.6", nil);
  
  cbut1 = gtk_check_button_new_with_label("file");
  cbut1.signal("clicked", `send_command(@cbut1, "file-stdout", "tldemoboth"));
  button_messages (cbut1, "5.7", "5");
  cbut1.set_active(TRUE);
  
  cbut2 = gtk_check_button_new_with_label("stdout");
  cbut2.signal("clicked", `send_command(@cbut2, "file-stdout", "tldemostdout"));
  button_messages (cbut2, "5.8", "5");
  cbut2.set_active(FALSE);

  tlbut.signal("toggled", `log_toggle(@tlbut, @text, @cbut1, @cbut2,
                                      @rbut1, @rbut2, @rbut3));
  
  table.attach_defaults(tlbut, 0, 1, 0, 1);
  table.attach_defaults(cbut1, 0, 1, 1, 2);
  table.attach_defaults(cbut2, 0, 1, 2, 3);
  frame.add(table);
  
  /* "Plot" frame, Recent and All buttons. */
  
  box3 = new(GtkVBox);
  box3.border_width = 5;
  box2.pack_start(box3, TRUE, TRUE, 0);
  
  frame = new(GtkFrame);
  frame.border_width = 0;
  frame.set_color(1, GTK_STATE_NORMAL, 0xccccaa);
  frame.set_label("Make plots");
  frame.set_label_align(.5, 1);
  frame.set_shadow_type(GTK_SHADOW_IN);
  box3.pack_start(frame, TRUE, TRUE, 0);

  table = gtk_table_new(2, 1, FALSE);
  table.border_width = 5;
  table.set_row_spacings(3);

  pbut1 = control_button("Recent", 0xccccaa, "gnuplot",
                         "plotlog1", "-background", "gray",
                           "-geometry", "600x345-10-30",
                           "plrecent.cfg", nil, nil, "5.9", nil);
  
  pbut2 = control_button("All", 0xccccaa, "gnuplot",
                         "plotlog2", "-background", "gray",
                           "-geometry", "600x345-10+10",
                           "plall.cfg", nil, nil, "5.10", nil);
  
  pbut2.signal("toggled", `anygui_move_window(@pbut2, @log_win,
                                              380, 25, 0, 25));

  table.attach_defaults(pbut1, 0, 1, 0, 1);
  table.attach_defaults(pbut2, 0, 1, 1, 2);  
  frame.add(table);
  
  /* Exit button and text window. */
  
  xbut = new(GtkButton);
  xbut.label = "Exit";
  xbut.signal("clicked", `(@log_win).destroy());
  box3.pack_start (xbut, TRUE, TRUE, 5);

  swin = new(GtkScrolledWindow);
  swin.set_policy(GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
  swin.border_width = 5;
  swin.height = 200;
  swin.width = 400;
  swin.add(text);
  box1.pack_start(swin, TRUE, TRUE, 0);

  /* Create an empty data file needed by gnuplot.*/
  if(!is_file("/tmp/cogentdemo/tlold.dat"))
    system("touch /tmp/cogentdemo/tlold.dat");

  log_win.show_all();
  log_win.reposition(380, 25);
  log_win;
}

/*--------------------------------------------------------------------
 * Function:    main
 * Returns:     doesn't return
 * Description: Calls the common.g program_startup() function and loops.
 *------------------------------------------------------------------*/
function main()
{
  program_startup("log", "logq", #create_log(), "6");
  
  atexit(#stop_processes());

  /* Loop forever handling events. */
  gtk_main ();
}