phhistory.g - The History program in Photon

Cogent Tools Demo and Tutorials: Version 4.0
Prev | Chapter 3. View the Code | Next

# 3.11. `phhistory.g` - The History program in Photon

    /*--------------------------------------------------------------------
     * File:        phhistory.g
     *
     * Description: Demonstrates the Cascade Historian
     *
     * Classes:     HistoryWindow
     *              DeadbandType
     *
     * Functions and methods by category:
     *
     * Int & Query: InterpolatorSettings.assign_values
     *              InterpolatorSettings.get_data
     *              send_query
     *              countdown
     *              record_data
     *              show_data
     *              query_refresh
     * Deadbanding: reset_deadbands
     *              db_prep_query
     *              DeadbandType.constructor
     *              db_options
     *              create_dbtype_win
     * Plotting:    make_CwGraph_points
     *              make_graph
     * Window:      HistoryWindow.constructor
     *              PtText.set_sensitive
     *              PtComboBox.set_sensitive
     *              HistoryWindow.allow_entry_values
     *              HistoryWindow.change_int
     *              create_history
     * Main         main
     *------------------------------------------------------------------*/

    /* Get access to the library of common functions. */
    require("lib/common.g");
    require_lisp("Profile");
    anyver_loadlibs();

    /* Keep track of all child processes that this process has started.*/
    Children := nil;

    /********************************************************
     *           INTERPOLATOR and QUERY Code                *
     ********************************************************/

    /*--------------------------------------------------------------------
     * Method:      InterpolatorSettings.assign_values
     * Returns:     t or nil
     * Description: Assigns the values from the interpolator entry widgets
     *              to the appropriate instance variables of the class.
     *------------------------------------------------------------------*/
    method InterpolatorSettings.assign_values(e1, e2, e3, e4, e5, e6)
    {
      .y_history = assign_history(.dbflag, .y_history, e1.text_string);
      .start = number(e2.text_string);
      .duration = number(e3.text_string);
      .x_history = assign_history(.dbflag, .x_history, e4.text_string);
      .interval = number(e5.text_string);
      .max_gap = number(e6.text_string);
    }

    /*--------------------------------------------------------------------
     * Method:      InterpolatorSettings.get_data
     * Returns:     a list of x-data and y-data, as strings
     * Description: Sends a query to the Historian and receives the data.
     *              Activated by the send_query function.
     *------------------------------------------------------------------*/
    method InterpolatorSettings.get_data()
    {
      local tsk, intpl, buf_length, alldata, count, dur, data, outfile;
      local xdata = list();
      local ydata = list();
      local midnite = find_midnite();

      /* Make sure there are valid values in the entry widgets.*/
      if (undefined_p(.start) || (!number_p(.start)))
        {
          .start = 0;
          hw.StartEnt.text_string = "0";
        }
      if (undefined_p(.duration) || (!number_p(.duration))
          || (.duration <= 0))
        {
          .duration = 10;
          hw.DurEnt.text_string = "10";
        }
      if (undefined_p(.interval) || (!number_p(.interval))
          || (.interval < .01))
        {
          .interval = .01;
          hw.IntEnt.text_string = "0.01";
        }

      if ((tsk = locate_task("demohistdb", nil)) != nil)
        {
          intpl = self.set_interpolator(tsk);

          buf_length = caddr(send(tsk, `bufferIdLength(intpl)));
          if(!((.fn == "TimeSetup") || (.fn == "RelSetup")))
            hw.NumPts.text_string = string(buf_length);

          alldata = list();
          count = 0;

          while (count < buf_length)
            {
              if((buf_length - count) > 100)
                dur = 100;
              else
                dur = buf_length - count;
              data = send(tsk, `bufferIdDataAscii(intpl, @count, @dur));
              data = cddr(cdr(data));
              alldata = append(alldata, data);
              count = count + 100;
            }

          if (outfile = open("/tmp/cogentdemo/hsoutput.dat", "w"))
            if (buf_length == 0)
              {
                writec(outfile, "# Sorry, no data matched your query.");
                writec(outfile, string("\n", midnite, " 0",
                                       "\n", (midnite + 1), " 0"));
                close(outfile);
              }
            else
              {
                with d in alldata do
                  writec(outfile, string(car(d), " ", cadr(d), "\n"));
                close(outfile);
              }

          while (alldata != nil)
            {
              if(.fn == "TimeSetup" ||
                 .fn == "NoInterpolator" || .fn == "Periodic")
                xdata = cons(caar(alldata) - midnite, xdata);
              else
                xdata = cons(caar(alldata), xdata);
              ydata = cons(cadar(alldata), ydata);
              alldata = cdr(alldata);
            }
          xdata = reverse(xdata);
          ydata = reverse(ydata);
          send(tsk, #bufferIdDestroy(intpl));
        }
      list(xdata, ydata);
    }

    /*--------------------------------------------------------------------
     * Function:    send_query
     * Returns:     t or nil
     * Description: Calls the necessary functions to send a query to the
     *              Historian, and handles the data returned.  It is activated
     *              by the "Record" button popping out, or any radio button.
     *------------------------------------------------------------------*/
    function send_query(iset, text, parent, ent1, ent2,
                        ent3, ent4, ent5, ent6, button)
    {
      local fnholder, datalist, minmaxlist;

      if ((button == hw.NoIntBut || button == hw.PeriodBut ||
           button == hw.RelBut || button  == hw.FixRelBut ||
           button == hw.DisplayBut || button  == hw.RecBut))
        iset.dbflag = "NONE";

      iset.assign_values(ent1, ent2, ent3, ent4, ent5, ent6);

      datalist = list();
      fnholder = iset.fn;

      /* Assign a name for the setup query. */
      if ((iset.fn == "NoInterpolator") || (iset.fn == "Periodic"))
        iset.fn = "TimeSetup";
      else
        iset.fn = "RelSetup";

      /* Make the setup query and assign minimum and maximum values. */
      datalist = iset.get_data();
      if (car(datalist) && cadr(datalist))
        minmaxlist = list(min_max(car(datalist)), min_max(cadr(datalist)));
      else
        minmaxlist = nil;

      /* Make the actual query. */
      iset.fn = fnholder;
      datalist = iset.get_data();
      show_data(text, iset, parent, button, datalist, minmaxlist);
    }

    /*--------------------------------------------------------------------
     * Function:    countdown
     * Returns:     an integer
     * Description: Called by record_data to facilitate the time count-down.
     *              This functionality had to be separated out from the callback.
     *------------------------------------------------------------------*/
    function countdown(starttime)
    {
      starttime - clock();
    }

    RECORD_TIME = 5;

    /*--------------------------------------------------------------------
     * Function:    record_data
     * Returns:     an integer (timer number), or nil
     * Description: Records data for the specified time, then sends a query.
     *------------------------------------------------------------------*/
    function record_data(but1, but2, iset, text, window, e1, e2, e3, e4, e5, e6)
    {
      if (but1.switched_on())
        {
          local time = clock() + RECORD_TIME;
          text.text_string = string("Recording,please wait.\nSeconds remaining: ",
                                    RECORD_TIME);
          numtimer = every (1, `((@text).text_string = string(substr((@text).text_string, 0, 42),
                                                              string((countdown(@time))))));
          e3.text_string = string(RECORD_TIME + 1);
          iset.set_defaults(but1, e2);
          send_hs_command(but1, "enable", e1.text_string, nil);
          after(RECORD_TIME, `((@but1).flags = cons(Pt_SET, nil)));
          after((RECORD_TIME + .1), `(send_hs_command(@but1, "enable", (@e1).text_string, nil)));
          after((RECORD_TIME + .1), `(cancel(numtimer)));
          after((RECORD_TIME + .15), `(query_refresh(nil, nil)));
          after((RECORD_TIME + .25), `PtFlush());
        }
    }

    /*--------------------------------------------------------------------
     * Function:    show_data
     * Returns:     t or nil
     * Description: Shows interpolated query results from the Cascade Historian
     *              in the text widget and plots the results in the CwGraph widget.
     *------------------------------------------------------------------*/
    function show_data(txt_wgt, int_set, parent, button, datalist, minmaxlist)
    {
      local start_time, infile, line, string_list, line_ret;
      local x_is_time, x_min, x_max, y_min, y_max, x_list, y_list;
      local outstring = open_string ("");

      x_list = car(datalist);
      y_list = cadr(datalist);
      txt_wgt.text_string = "";
      start_time = find_midnite();

      if (int_set.fn == "NoInterpolator"  || int_set.fn == "Periodic")
        {
          x_is_time = t;
          txt_wgt.text_string = "Query results: \n     Time         Y History\n";
        }
      else
        {
          x_is_time = nil;
          txt_wgt.text_string = "Query results: \nX-hist / Y-hist\n";
        }

      infile = open("/tmp/cogentdemo/hsoutput.dat", "r");
      if (infile)
        {
          line = nil;
          while(line != _eof_)
            {
              line = read_line(infile);
              line_ret = "";
              if (line != "Unexpected end of file")
                {
                  if ((strstr(line,"#") != -1))
                    {
                      writec (outstring, line);
                      read_line(infile);
                      read_line(infile);
                    }
                  else
                    {
                      string_list = string_split(line, " ", 2);
                      if (x_is_time)
                        {
                          line_ret = string(number(car(string_list)) - start_time,
                                            " ", cadr(string_list),"\n");
                        }
                      else
                        {
                          line_ret = string(number(car(string_list)),
                                            "   ", cadr(string_list),"\n");
                        }
                      writec (outstring, line_ret);
                    }
                }
            }

          txt_wgt.text_string = string(txt_wgt.text_string, string_file_buffer(outstring));

          if(x_list && y_list && minmaxlist != nil)
            {
              if (x_is_time)
                {
                  x_min = caar(minmaxlist);
                  x_max = cadar(minmaxlist);
                }
              else
                {
                  x_min = floor(caar(minmaxlist));
                  x_max = ceil(cadar(minmaxlist));
                }

              y_min = floor(caadr(minmaxlist));
              y_max = ceil(car(cdadr(minmaxlist))) + 1;

              PtSetParentWidget(parent);

              make_graph(x_min, x_max, y_min, y_max,
                                x_list, y_list, int_set.dbflag);
            }
          close(infile);
        }
    }

    /*--------------------------------------------------------------------
     * Function:    query_refresh
     * Returns:     t or nil
     * Description: Sets the interpolator, resets the deadband, and sends a
     *              query.  Used by callbacks on the four interpolator buttons,
     *              the Update display button, and a timer on the Record button.
     *------------------------------------------------------------------*/
    function query_refresh(button, title_string)
    {
      if (title_string)
        hw.change_int(button, title_string);

      reset_deadbands();
      send_query(hw.int_set, hw.Text, hw.PtHist, hw.YHistEnt,
                 hw.StartEnt, hw.DurEnt, hw.XHistEnt, hw.IntEnt,
                 hw.GapEnt, button);
    }

    /********************************************************
     *               DEADBANDING Code                       *
     ********************************************************/

    /*--------------------------------------------------------------------
     * Function:    reset_deadbands
     * Returns:     an integer
     * Description: Clears all traces and sets the Full data set (no deadband)
     *              option.  Called when non-deadband buttons are activated.
     *------------------------------------------------------------------*/
    function reset_deadbands()
    {
      hw.DBBut.flags = cons(Pt_SET, nil);
      hw.DBPBut.flags = cons(Pt_SET, nil);

      if(!undefined_p(GraphWidget))
        {
          CwGraphClearTrace (GraphWidget, 0);
          CwGraphClearTrace (GraphWidget, 1);
          CwGraphClearTrace (GraphWidget, 2);
        }
      hw.DBNoneBut.flags = Pt_SET;
    }

    /*--------------------------------------------------------------------
     * Function:    db_prep_query
     * Returns:     t or nil
     * Description: Sends a query when a Deadband button is toggled on, and
     *              erases the corresponding graph trace when a Deadband button
     *              is untoggled.
     *------------------------------------------------------------------*/
    function db_prep_query(button)
    {
      if ((button.flags & Pt_SET) != 0)
        send_query(hw.int_set, hw.Text, hw.PtHist, hw.YHistEnt,
                   hw.StartEnt, hw.DurEnt, hw.XHistEnt, hw.IntEnt,
                   hw.GapEnt, button);
      else
        {
          if(!undefined_p(GraphWidget))
            {
              if(button == hw.DBNoneBut)
                CwGraphClearTrace (GraphWidget, 0);
              else if(button == hw.DBBut)
                CwGraphClearTrace (GraphWidget, 1);
              else if(button == hw.DBPBut)
                CwGraphClearTrace (GraphWidget, 2);
            }
        }
    }

    /********************************************************
     *          DEADBAND TYPE WINDOW Code                   *
     ********************************************************/

    /*--------------------------------------------------------------------
     * Class:       DeadbandType
     * Description: Creates the Deadband Type window using PhabAttachWidgets.
     *------------------------------------------------------------------*/
    class DeadbandType
    {
      window;
    }

    PhabAttachWidgets (DeadbandType, anyos_assign("deadband_widgetfile"));

    /*--------------------------------------------------------------------
     * Method:      DeadbandType.constructor
     * Returns:     the root widget of a widget hierarchy
     * Description: Instantiates a DeadbandType window.
     *------------------------------------------------------------------*/
    method DeadbandType.constructor ()
    {
      .window = PhabRoot(.PhabInstantiate (t));
    }

    /*--------------------------------------------------------------------
     * Function:    db_options
     * Returns:     a PtText widget
     * Description: Creates a PtText widget, gives it a position, and gives
     *              it a callback to update the corresponding value in the
     *              parameter array.
     *------------------------------------------------------------------*/
    function db_options (p_array, index, col, row)
    {
      local option;
      local cols = [86, 148];
      local rows = [55, 86, 127, 157];

      option = new(PtText);
      option.SetDim(40, 20);
      option.fill_color = 0xffffee;
      option.border_width = 1;
      option.text_string = (string(p_array[index]));
      option.SetPos(cols[col], rows[row]);
      PtAttachCallback(option, Pt_CB_TEXT_CHANGED,
                       `((@p_array)[@index] = number((@option).text_string)));
      option;
    }

    /*--------------------------------------------------------------------
     * Function:    create_dbtype_win
     * Returns:     a Deadband Type window, or a destroyed instance
     * Description: Creates the Deadband Type window.
     *------------------------------------------------------------------*/
    function create_dbtype_win (!point_list, button)
    {
      local db1, db2, pa1, pa2;
      if ((button.flags & Pt_SET) != 0)
        {
          if (undefined_p(db) || db.window == nil)
            {
              db = new (DeadbandType);
              db.DeadBandWindow.SetPos(150, 300);
              attach_msg(db.DeadBandWindow, "6.54", "6");

              db1 = car(point_list);
              db2 = cadr(point_list);

              pa1 = array(db1.absolute, db1.percent, db1.timelimit, db1.countlimit);
              pa2 = array(db2.absolute, db2.percent, db2.timelimit, db2.countlimit);

              db_options(pa1, 0, 0, 0);
              db_options(pa1, 1, 0, 1);
              db_options(pa1, 2, 0, 2);
              db_options(pa1, 3, 0, 3);

              db_options(pa2, 0, 1, 0);
              db_options(pa2, 1, 1, 1);
              db_options(pa2, 2, 1, 2);
              db_options(pa2, 3, 1, 3);

              attach_msg(db.CancelBut, "6.55", "6.5");
              attach_msg(db.OKBut, "6.56", "6.5");

              PtAttachCallback(db.CancelBut, Pt_CB_ACTIVATE,
                               `((@button).flags = cons(Pt_SET, nil)));
              PtAttachCallback(db.CancelBut, Pt_CB_ACTIVATE,
                               `PtDestroyWidget((@db).window));

              PtAttachCallback(db.OKBut, Pt_CB_ACTIVATE,
                               `(@db1).set_parms((@db).OKBut, @pa1));
              PtAttachCallback(db.OKBut, Pt_CB_ACTIVATE,
                               `(@db2).set_parms((@db).OKBut, @pa2));
              PtAttachCallback(db.OKBut, Pt_CB_ACTIVATE,
                               `((@button).flags = cons(Pt_SET, nil)));
              PtAttachCallback(db.OKBut, Pt_CB_ACTIVATE,
                               `PtDestroyWidget((@db).window));

              PtAttachCallback(db.window, Pt_CB_DESTROYED,
                               `((@button).flags = cons(Pt_SET, nil)));
              PtAttachCallback(db.window, Pt_CB_DESTROYED,
                               `((@db).window = nil));
            }
          if(db)
            PtRealizeWidget (db.window);
          db;
        }
      else
        PtDestroyWidget (db.window);
    }

    /********************************************************
     *                     PLOTTING                         *
     ********************************************************/

    /*--------------------------------------------------------------------
     * Function:    make_CwGraph_points
     * Returns:     a list
     * Description: Applied to the x and y arguments of the CwGraphAddXYPoints()
     *              function, which are lists. This function destructively
     *              modifies those lists, adding extra values that, when plotted
     *              by CwGraph, render as small, diamond-shaped points. The xval
     *              parameter must be set to t for the x-coordinate, and to nil
     *              for the y coordinate.
     *------------------------------------------------------------------*/
    function make_CwGraph_points (ptlist, ptsize, xval)
    {
      parray = list_to_array(ptlist);
      i = 0;
      if(xval)
        {
          /* Add x-values to the trace. */
          while (i < length(parray))
            {
              insert(parray, i+1, parray[i] + (ptsize));
              insert(parray, i+2, parray[i]);
              insert(parray, i+3, parray[i] - (ptsize));
              insert(parray, i+4, parray[i]);
              insert(parray, i+5, parray[i] + (ptsize));
              insert(parray, i+6, parray[i]);
              i = i + 7;
            }
        }
      else
        {
          /* Add y-values to the trace. */
          while (i < length(parray))
            {
              insert(parray, i+1, parray[i]);
              insert(parray, i+2, parray[i] - (ptsize));
              insert(parray, i+3, parray[i]);
              insert(parray, i+4, parray[i] + (ptsize));
              insert(parray, i+5, parray[i]);
              insert(parray, i+6, parray[i]);
              i = i + 7;
            }
        }
      ret = array_to_list(parray);
    }

    /*--------------------------------------------------------------------
     * Function:    make_graph
     * Returns:     a CwGraph widget
     * Description: Sets up a CwGraph widget to plot the query results.
     *------------------------------------------------------------------*/
    function make_graph (xmin, xmax, ymin, ymax, xlist, ylist, dband)
    {
      local grf;

      /* Set a size for the points created by make_CwGraph_points. */
      local xdist = (xmax - xmin) * .007;
      local ydist = (ymax - ymin) * .007;

      if (undefined_p(GraphWidget) || !GraphWidget)
        {
          /* Make a new graph, if one doesn't already exist. */
          PtSetParentWidget (hw.GraphPane);
          GraphWidget = new(CwGraph);

          GraphWidget.SetArea(0, 0, hw.GraphPane.dim.w, hw.GraphPane.dim.h);
          GraphWidget.fill_color = 0xffffe5;
          GraphWidget.bot_border_color = 0x000000;
          GraphWidget.graph_y_label_left = "Y history";
          GraphWidget.graph_x_font = anyos_assign("graph_font");
          GraphWidget.graph_y_font_left = anyos_assign("graph_font");
          GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_AXIS_RIGHT);
          GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_AXIS_LABEL_RIGHT);
          GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_AXIS_TITLE_RIGHT);
          GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_MAJOR_TICK_RIGHT);
          GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_MINOR_TICK_RIGHT);

          PtAttachCallback (hw.GraphPane, Pt_CB_RESIZE,
                            `GraphWidget.SetArea(0, 0, hw.GraphPane.dim.w,
                                                 hw.GraphPane.dim.h));
        }

      /* Change the tick size and scale of the existing graph for a new data plot. */
      grf = GraphWidget;

      grf.graph_x_major_tick = (xmax - xmin) / 5;
      grf.graph_x_minor_tick = (xmax - xmin) / 25;
      grf.graph_y_major_tick_left = (ymax - ymin) / 5;
      grf.graph_y_minor_tick_left = (ymax - ymin) / 25;
      grf.graph_xmin = xmin;
      grf.graph_xmax = xmax;
      grf.graph_ymin_left = ymin;
      grf.graph_ymax_left = ymax;
      grf.graph_traces = 3;

      if (xmax > 1000)
        grf.graph_x_label = "Time (number of seconds after midnight)";
      else
        grf.graph_x_label = "X history";

      /* Assign trace limits and colors for the new data plot. */
      CwGraphSetYLimits(grf, 0, ymin, ymax);
      CwGraphSetYLimits(grf, 1, ymin, ymax);
      CwGraphSetYLimits(grf, 2, ymin, ymax);

      CwGraphSetTraceColor(grf, 0, 0xdd00aa);
      CwGraphSetTraceColor(grf, 1, 0x0000aa);
      CwGraphSetTraceColor(grf, 2, 0x00aa00);

      /* Create the traces for the new data plot. */
      if(dband == "NONE")
        CwGraphAddXYPoints(grf, 0, make_CwGraph_points(xlist, xdist, t),
                           make_CwGraph_points(ylist, ydist, nil));
      else if(dband == "DB")
        CwGraphAddXYPoints(grf, 1, make_CwGraph_points(xlist, xdist, t),
                           make_CwGraph_points(ylist, ydist, nil));
      else if(dband == "DBP")
        CwGraphAddXYPoints(grf, 2, make_CwGraph_points(xlist, xdist, t),
                           make_CwGraph_points(ylist, ydist, nil));

      PtRealizeWidget(grf);
    }

    /********************************************************
     *               HISTORY WINDOW Code                    *
     ********************************************************/

    /*--------------------------------------------------------------------
     * Class:       HistoryWindow
     * Description: Creates the History window using PhabAttachWidgets.
     *------------------------------------------------------------------*/
    class HistoryWindow
    {
      window;
      int_set;
    }

    PhabAttachWidgets (HistoryWindow, anyos_assign("history_widgetfile"));

    /*--------------------------------------------------------------------
     * Method:      HistoryWindow.constructor
     * Returns:     the root widget of a widget hierarchy
     * Description: Instantiates a HistoryWindow.
     *------------------------------------------------------------------*/
    method HistoryWindow.constructor ()
    {
      .window = PhabRoot(.PhabInstantiate (t));
    }

    /*--------------------------------------------------------------------
     * Method:      PtText.set_sensitive
     * Returns:     an integer
     * Description: Changes the sensitivity of a PtText widget.  Called by
     *              HistoryWindow.allow_entry_values.
     *------------------------------------------------------------------*/
    method PtText.set_sensitive (val)
    {
      if (val != 0)
        {
          self.text_flags = Pt_EDITABLE;
          self.fill_color = 0xffffe5;
        }
      else
        {
          self.text_flags = cons(Pt_EDITABLE, nil);
          self.fill_color = 0xd0d0d0;
        }
    }

    /*--------------------------------------------------------------------
     * Method:      PtComboBox.set_sensitive
     * Returns:     an integer
     * Description: Changes the fill color of a PtComboBox widget.  Called
     *              by HistoryWindow.allow_entry_values.
     *------------------------------------------------------------------*/
    method PtComboBox.set_sensitive (val)
    {
      if (val != 0)
        {
          self.list_flags = cons (Pt_LIST_INACTIVE, nil);
          self.fill_color = 0xffffe5;
        }
      else
        {
          self.list_flags = Pt_LIST_INACTIVE;
          self.fill_color = 0xd0d0d0;
        }
    }

    /*--------------------------------------------------------------------
     * Method:      HistoryWindow.allow_entry_values
     * Returns:     t or nil
     * Description: Sets the three specialized parameter entry widgets sensitive
     *              or non-sensitive.  Called by HistoryWindow.change_int().
     *------------------------------------------------------------------*/
    method HistoryWindow.allow_entry_values(e1, e2, e3)
    {
      .XHistEnt.set_sensitive(e1);
      .IntEnt.set_sensitive(e2);
      .GapEnt.set_sensitive(e3);
    }

    /*--------------------------------------------------------------------
     * Method:      HistoryWindow.change_int
     * Returns:     t
     * Description: Responding to a click on a "Choose an Interpolator" radio
     *              button, this method calls the allow_entry_values() function
     *              on the active button.
     *------------------------------------------------------------------*/
    method HistoryWindow.change_int(button, str)
    {

      if (button.switched_on())
        {
          .int_set.fn = str;
          switch (str)
            {
            case "NoInterpolator":
              .allow_entry_values(0, 0, 0);
            case "Periodic":
              .allow_entry_values(0, 1, 1);
            case "Relative":
              .allow_entry_values(1, 0, 0);
            case "FixedRelative":
              .allow_entry_values(1, 1, 0);
            }
        }
      /* To allow for a slow processor */
      usleep(10000);
    }

    /*--------------------------------------------------------------------
     * Function:    create_history
     * Returns:     doesn't return
     * Description: Creates the History window.
     *------------------------------------------------------------------*/
    function create_history ()
    {
      local buttons, version_string;
      local        hw = new (HistoryWindow);

      hw.GraphPane.anchor_flags = Pt_LEFT_ANCHORED_LEFT |
        Pt_RIGHT_ANCHORED_RIGHT | Pt_BOTTOM_ANCHORED_BOTTOM |
          Pt_TOP_ANCHORED_TOP;
      hw.int_set = new(InterpolatorSettings);
      hw.change_int(hw.NoIntBut, "NoInterpolator");
      hw.SecsEnt.numeric_value = RECORD_TIME;
      hw.YHistEnt.text_string = hw.int_set.y_history;
      hw.StartEnt.text_string = hw.int_set.start;
      hw.DurEnt.text_string = hw.int_set.duration;
      hw.XHistEnt.text_string = hw.int_set.x_history;
      hw.IntEnt.text_string = hw.int_set.interval;
      hw.GapEnt.text_string = hw.int_set.max_gap;
      hw.YHistEnt.items = array ("MV_001", "PV_001");
      hw.XHistEnt.items = array ("PV_001", "MV_001");

      /*Attach message callbacks to buttons and entry widgets.*/
      attach_msg(hw.PtHist, "6", "1");
      attach_msg(hw.RecBut, "6.2", "6");
      attach_msg(hw.DisplayBut, "6.3", "6");
      attach_msg(hw.NoIntBut, "6.31", "6");
      attach_msg(hw.PeriodBut, "6.32", "6");
      attach_msg(hw.RelBut, "6.33", "6");
      attach_msg(hw.FixRelBut, "6.34", "6");
      attach_msg(hw.YHistEnt, "6.35", "6");
      attach_msg(hw.StartEnt, "6.36", "6");
      attach_msg(hw.DurEnt, "6.37", "6");
      attach_msg(hw.XHistEnt, "6.35", "6");
      attach_msg(hw.IntEnt, "6.38", "6");
      attach_msg(hw.GapEnt, "6.39", "6");
      attach_msg(hw.SetupBut, "6.5", "6");
      attach_msg(hw.DBNoneBut, "6.51", "6");
      attach_msg(hw.DBBut, "6.52", "6");
      attach_msg(hw.DBPBut, "6.53", "6");

      /* Display version info and start-up message.*/
      display_hs_info(hw.Text);

      /* Callback for the PtComboBox entry, number of seconds to record.*/
      PtAttachCallback(hw.SecsEnt, Pt_CB_NUMERIC_CHANGED,
                       `(RECORD_TIME = (@hw).SecsEnt.numeric_value));

      /* Callbacks for non-deadband buttons to send a query.*/
      PtAttachCallback(hw.NoIntBut, Pt_CB_ACTIVATE,
                       `query_refresh(@hw.NoIntBut, "NoInterpolator"));
      PtAttachCallback(hw.PeriodBut, Pt_CB_ACTIVATE,
                       `query_refresh(@hw.PeriodBut, "Periodic"));
      PtAttachCallback(hw.RelBut, Pt_CB_ACTIVATE,
                       `query_refresh(@hw.RelBut, "Relative"));
      PtAttachCallback(hw.FixRelBut, Pt_CB_ACTIVATE,
                       `query_refresh(@hw.FixRelBut, "FixedRelative"));
      PtAttachCallback(hw.DisplayBut, Pt_CB_ACTIVATE,
                       `query_refresh(@hw.DisplayBut, nil));

      /* A callback to record data, which includes sending a query. */
      PtAttachCallback(hw.RecBut, Pt_CB_ACTIVATE,
                       `(record_data((@hw).RecBut, (@hw).DisplayBut,
                                     (@hw).int_set, (@hw).Text,
                                     (@hw).PtHist, (@hw).YHistEnt,
                                     (@hw).StartEnt, (@hw).DurEnt,
                                     (@hw).XHistEnt, (@hw).IntEnt,
                                     (@hw).GapEnt)));

      /* Callbacks to set the deadband flag.*/
      PtAttachCallback(hw.DBNoneBut, Pt_CB_ACTIVATE, `((@hw).int_set.dbflag = "NONE"));
      PtAttachCallback(hw.DBBut, Pt_CB_ACTIVATE, `((@hw).int_set.dbflag = "DB"));
      PtAttachCallback(hw.DBPBut, Pt_CB_ACTIVATE, `((@hw).int_set.dbflag = "DBP"));

      /* A callback for deadband buttons to prepare for and send a query.*/
      buttons = list(hw.DBNoneBut, hw.DBBut, hw.DBPBut);
      with b in buttons do
        {
          PtAttachCallback(b, Pt_CB_ACTIVATE, `db_prep_query(@b));
        }

      /* Deadband setup.*/
      dbmv_set = new(DeadbandSettings);
      dbmv_set.history = "MV_001";

      dbpv_set = new(DeadbandSettings);
      dbpv_set.history = "PV_001";

      db_list = list(dbmv_set, dbpv_set);

      PtAttachCallback(hw.SetupBut, Pt_CB_ACTIVATE,
                       `create_dbtype_win(@db_list, (@hw).SetupBut));

      PtAttachCallback(hw.ExitBut, Pt_CB_ACTIVATE, #exit_program(-1));

      hw.PtHist.SetPos(320, 250);
      PtRealizeWidget (hw.window);
      send_message("nsnames");
      hw;

      /* Loop forever handling events. */
      while(t) next_event();

    }

    /********************************************************
     *                 MAIN FUNCTION Code                   *
     ********************************************************/

    /*--------------------------------------------------------------------
     * Function:    main
     * Returns:     doesn't return
     * Description: Calls the common.g program_startup() function.
     *------------------------------------------------------------------*/
    function main()
    {
      program_startup("history", "historyq", #create_history(), "6");

    }

Prev | Home | Next
`gtkhistory.g` - The History program in GTK | Up | `lib/common.g` - Common library

Copyright 1995-2002 by Cogent Real-Time Systems, Inc.