14.9. GTK: the Deadband Type Window - create_dbtype_win, db_labels, db_options

The Deadband Type window displays text entry widgets that let the user modify the deadband types on either of the two histories (MV_001, or PV_001). The OK button applies entered values to the appropriate deadband and closes the window. The entered values are maintained and displayed the next time the window is opened. The Cancel button cancels all changes made since the window was opened, and closes the window. Each time a new deadband type is applied the system prints the return value from the Cascade Historian in STDOUT.

The create_dbtype_win function uses the ! argument syntax to prevent evaluation of its first argument (point_list). This is because the function requires a list of DeadbandSettings instances. When you pass a list that is not protected from evaluation by the ! operator, it gets evaluated by the Lisp engine, which expects every list to begin with either a symbol, a class, or a function. But an instance of the DeadbandSettings class is none of these, so passing an unprotected list will generate error messages.

   /*--------------------------------------------------------------------
    * Function:    create_dbtype_win
    * Returns:     A GtkWindow, or a destroyed instance
    * Description: Creates the Deadband Type window.
    *------------------------------------------------------------------*/
   function create_dbtype_win (!point_list, button)
   {
     local db1, db2, db3, vbox, table, pa1, pa2, pa3;
     local label, separator, box2, abut, cbut, okbut;
   
     if (((undefined_p(win_db) || (win_db == nil))
          && (button.get_active() == TRUE)))
       {
         db1 = car(point_list);
         db2 = cadr(point_list);
   
         win_db = new (GtkWindow);
         send_message("6.50");
         win_db.signal ("destroy", #win_db = nil);
         win_db.title = "Deadband Type";
         win_db.set_uposition(20, 440);
         win_db.set_color(1, GTK_STATE_NORMAL, 0xdddddd);
         win_db.width = 500;
   
         table = gtk_table_new(7, 4, FALSE);
         table.border_width = 15;
         table.set_col_spacings(15);
         table.set_row_spacings(3);
         table.set_row_spacing(0, 10);
         table.set_row_spacing(3, 10);
         table.set_row_spacing(5, 10);
   
         db_labels(table, "Set up deadband types", 0, 4, 0, 1);
         db_labels(table, "MV", 1, 2, 1, 2);
         db_labels(table, "PV", 2, 3, 1, 2);
   
         db_labels(table, "Absolute:", 0, 1, 2, 3);
         db_labels(table, "Percent:", 0, 1, 3, 4);
         db_labels(table, "Time Limit:", 0, 1, 4, 5);
         db_labels(table, "Count Limit:", 0, 1, 5, 6);
   
         db_labels(table, string("Deadband range is set to this ",
                                 "value.                  "), 3, 4, 2, 3);
         db_labels(table, string("Range set to percent of last logged ",
                                 "value.          "), 3, 4, 3, 4);
         db_labels(table, string("The maximum time period to deadband.",
                                 "               "), 3, 4, 4, 5);
         db_labels(table, string("The max number of received values to",
                                 " deadband."), 3, 4, 5, 6);
         db_labels(table, string("Note: These settings don't take effect",
                                 " until the next record session."), 0, 4, 6, 7);
   

At this point we need to address a problem of maintaining a copy of the existing entries to support the Cancel and OK buttons' functionality. The solution is to store entered data in an array, and assign it (using the .set_parms method) only when the OK button is pressed. Otherwise, the values don't change. This array is one of the arguments need by the db_options function to create the entry widgets.

         pa1 = array(db1.absolute, db1.percent,
                     db1.timelimit, db1.countlimit);
   
         pa2 = array(db2.absolute, db2.percent,
                     db2.timelimit, db2.countlimit);
   
         db_options(table, pa1, 1, 2);
         db_options(table, pa2, 2, 3);
   
         vbox = new(GtkVBox);
         win_db.add(vbox);
         vbox.pack_start(table, TRUE, TRUE, 0);
   
         separator = new(GtkHSeparator);
         vbox.pack_start(separator, TRUE, TRUE, 0);
   
         box2 = new(GtkHButtonBox);
         box2.border_width = 10;
         box2.set_layout(GTK_BUTTONBOX_SPREAD);
         vbox.pack_start(box2, TRUE, TRUE, 0);
   
         cbut = new(GtkButton);
         cbut.label = "Cancel";
         cbut.signal("clicked", `(@button).set_active(FALSE));
         cbut.signal("clicked", `(@win_db).destroy());
         button_messages (cbut, "6.55", "6.50");
         box2.pack_start(cbut, TRUE, TRUE, 0);
         cbut.show();
     
         okbut = new(GtkButton);
         okbut.label = "OK";
         okbut.signal("clicked", `(@db1).set_parms(@okbut, @pa1));
         okbut.signal("clicked", `(@db2).set_parms(@okbut, @pa2));
         okbut.signal("clicked", `(@button).set_active(FALSE));
         okbut.signal("clicked", `(@win_db).destroy());
         button_messages (okbut, "6.56", "6.50");
         box2.pack_start(okbut, TRUE, TRUE, 0);
         okbut.show();
   
         win_db.signal("destroy", `(@button).set_active(FALSE));
         win_db.show_all();
         win_db;
       }
     else
         if(instance_p(win_db))
           win_db.destroy();
   }
   
   

The db_labels function creates the labels for the window.

   /*--------------------------------------------------------------------
    * Function:    db_labels
    * Returns:     t or nil
    * Description: Creates labels and puts them in a table.
    *------------------------------------------------------------------*/
   function db_labels(tbl, title, left, right, top, bottom)
   {
     local label;
     
     label = new(GtkLabel);
     label.set_text(title);
     tbl.attach_defaults(label, left, right, top, bottom);
   }
   

The db_options function adds the GtkEntry widgets.

   /*--------------------------------------------------------------------
    * Function:    db_options
    * Returns:     t or nil
    * Description: Creates a GtkEntry widget and puts it into a table.
    *              The widget calls the update_value() function when it
    *              gets changed.
    *------------------------------------------------------------------*/
   function db_options(tbl, p_array, left, right)
   {
     local entry;
   
     for (i=0; i<=3; i++)
       {
         entry = new(GtkEntry);
         entry.width = 40;
         entry.set_text(string(p_array[i]));
         entry.signal("changed", `(@p_array)[@i] = number((@entry).get_text()));
         tbl.attach_defaults(entry, left, right, i + 2, i + 3);
       }
   }