/*--------------------------------------------------------------------
* File: gtkhistory.g
*
* Description: Demonstrates the Cascade Historian
*
* Functions and methods by category
*
* Interpolator: InterpolatorSettings.change_int
* InterpolatorSettings.assign_values
* InterpolatorSettings.get_data
* Query: allow_entry_values
* countdown
* record_data
* reset_deadbands
* plot_prep
* send_query
* write_minmax
* file_add
* show_data
* Deadbanding: db_options
* db_labels
* create_dbtype_win
* Window: make_toggle_button
* qry_radio_but
* qry_entry
* create_history
* Main: main
*------------------------------------------------------------------*/
/********************************************************
* GENERAL UTILITY Code *
********************************************************/
/* 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;
/********************************************************
* INTERPOLATOR Code *
********************************************************/
/*--------------------------------------------------------------------
* Method: InterpolatorSettings.change_int
* Returns: t or nil
* Description: Responding to a click on a "Choose an Interpolator"
* radio button, this method calls the allow_entry_values()
* function on the active button. The callback is set up
* in qry_radio_but().
*------------------------------------------------------------------*/
method InterpolatorSettings.change_int(button, str, w1, w2, w3, e1, e2, e3)
{
if (button.switched_on())
{
.fn = str;
allow_entry_values(w1, w2, w3, e1, e2, e3);
}
}
/*--------------------------------------------------------------------
* 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.
* Called by send_query().
*------------------------------------------------------------------*/
method InterpolatorSettings.assign_values(e1, e2, e3, e4, e5, e6)
{
.y_history = assign_history(.dbflag, .y_history, e1.get_text());
.start = number(e2.get_text());
.duration = number(e3.get_text());
.x_history = assign_history(.dbflag, .x_history, e4.get_text());
.interval = number(e5.get_text());
.max_gap = number(e6.get_text());
}
/*--------------------------------------------------------------------
* Method: InterpolatorSettings.get_data
* Returns: a list of two lists
* Description: Sends the query and retrieves the data. Activated by
* the send_query() function.
*------------------------------------------------------------------*/
method InterpolatorSettings.get_data(e1, e2, e3, e4, e5, e6, e7)
{
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;
e2.set_text("0");
}
if (undefined_p(.duration) || (!number_p(.duration))
|| (.duration <= 0))
{
.duration = 10;
e3.set_text("10");
}
if (undefined_p(.interval) || (!number_p(.interval))
|| (.interval < .01))
{
.interval = .01;
e5.set_text("0.01");
}
if ((tsk = locate_task("demohistdb", nil)) != nil)
{
alldata = list();
count = 0;
intpl = self.set_interpolator(tsk);
buf_length = caddr(send(tsk, `bufferIdLength(intpl)));
if(!((.fn == "TimeSetup") || (.fn == "RelSetup")))
e7.set_text(string(buf_length));
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(.dbflag == "NONE")
outfile = open("/tmp/cogentdemo/hsoutput.dat", "w");
if(.dbflag == "DB")
outfile = open("/tmp/cogentdemo/hsoutput2.dat", "w");
if(.dbflag == "DBP")
outfile = open("/tmp/cogentdemo/hsoutput3.dat", "w");
if (outfile)
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);
}
/********************************************************
* QUERY Code *
********************************************************/
/*--------------------------------------------------------------------
* Function: allow_entry_values
* Returns: t or nil
* Description: Sets the three optional parameter entry widgets
* (X history, Time Interval, and Max. gap) sensitive or
* non-sensitive. Called by qry_radio_but() and
* InterpolatorSettings.change_int(). The possible values
* for e1 - e3 are 0 (FALSE) or 1 (TRUE).
*------------------------------------------------------------------*/
function allow_entry_values(w1, w2, w3, e1, e2, e3)
{
w1.set_sensitive(e1);
w2.set_sensitive(e2);
w3.set_sensitive(e3);
}
/*--------------------------------------------------------------------
* Function: countdown
* Returns: t or nil
* Description: Called by record_data() to do the time count-down.
*------------------------------------------------------------------*/
function countdown(txt_wgt, time)
{
txt_wgt.set_point(42);
txt_wgt.forward_delete(txt_wgt.get_length() - 42);
txt_wgt.insert(FONT, nil, nil, string(time - clock()), -1);
}
/* Assign a global variable for recording time, and a font. */
RECORD_TIME = 5;
FONT = gdk_font_load ("-adobe-courier-medium-r-normal--*-120-*-*-*-*-*-*");
/*--------------------------------------------------------------------
* Function: record_data
* Returns: t or nil
* Description: Records data for the specified time, then sends a query.
* Arguments: button: The Record button
* iset: An InterpolatorSettings instance
* e1 - e6: The six Interpolator options entry widgets
* e7: The "Number of points from last query" display
* but_db1 - 3: The three Deadband options buttons
* b1 - b4: The four Interpolator options buttons
* b6: The Update display button
*------------------------------------------------------------------*/
function record_data(button, iset, but_db1, but_db2, but_db3, text,
e1, e2, e3, e4, e5, e6, e7, b1, b2, b3, b4, b6)
{
if (button.switched_on())
{
local time = clock() + RECORD_TIME;
text.backward_delete(text.get_length());
text.insert(FONT, nil, nil,
(string("Recording,please wait.\nSeconds remaining: ", RECORD_TIME)),
-1);
numtimer = every (1, `countdown(@text, @time));
e3.set_text(string(RECORD_TIME + 1));
iset.set_defaults(button, e2);
send_hs_command(button, "enable", e1.get_text(), nil);
after(RECORD_TIME, `(@button).set_active(FALSE));
after((RECORD_TIME + .1), `(send_hs_command(@button, "enable",
(@e1).get_text(), nil)));
after((RECORD_TIME + .1), `(cancel(numtimer)));
after((RECORD_TIME + .15),
`(reset_deadbands(nil, @iset, @but_db1, @but_db2, @but_db3, @text,
@e1, @e2, @e3, @e4, @e5, @e6, @e7, @b1,
@b2, @b3, @b4, @button, @b6)));
}
}
/*--------------------------------------------------------------------
* Function: reset_deadbands
* Returns: t or nil
* Description: Clears all traces and sets the Full data set (no deadband)
* option. Called when non-deadband buttons are activated.
*------------------------------------------------------------------*/
function reset_deadbands(button, iset, but1, but2, but3, text, e1, e2,
e3, e4, e5, e6, e7, b1, b2, b3, b4, b5, b6)
{
but2.set_active(FALSE);
but3.set_active(FALSE);
but1.set_active(TRUE);
if(is_file("/tmp/cogentdemo/hsoutput2.dat"))
unlink("/tmp/cogentdemo/hsoutput2.dat");
if(is_file("/tmp/cogentdemo/hsoutput3.dat"))
unlink("/tmp/cogentdemo/hsoutput3.dat");
plot_prep(but1, iset, but1, but2, but3, text, e1, e2,
e3, e4, e5, e6, e7, b1, b2, b3, b4, b5, b6);
}
/*--------------------------------------------------------------------
* Function: plot_prep
* Returns: t or nil
* Description: Writes to the plhistsetup.dat file the relevant values
* for the time of midnight, x-axis label, and deadband
* status.
*------------------------------------------------------------------*/
function plot_prep (button, iset, but_db1, but_db2, but_db3, text,
e1, e2, e3, e4, e5, e6, e7, b1, b2, b3, b4, b5, b6)
{
local fp, histtime, line;
/* Write the time. */
fp = open("/tmp/cogentdemo/plhistsetup.dat", "w", nil);
histtime = find_midnite();
line = string("histtime = ", histtime, "\n");
writec(fp, line);
/* Set up the X-axis label. */
if ((iset.fn == "NoInterpolator") || (iset.fn == "Periodic"))
line = "xlab = 1\n";
else line = "xlab = 2\n";
writec(fp, line);
/* Set the deadband flag in the InterpolatorSettings instance. */
if(button.switched_on() && button == but_db1)
iset.dbflag = "NONE";
if(button.switched_on() && button == but_db2)
iset.dbflag = "DB";
if(button.switched_on() && button == but_db3)
iset.dbflag = "DBP";
/* Write the on or off value for each deadband. */
if (but_db1.switched_on())
line = "db1 = 1\n";
else line = "db1 = 0\n";
writec(fp, line);
if (but_db2.switched_on())
line = "db2 = 1\n";
else line = "db2 = 0\n";
writec(fp, line);
if (but_db3.switched_on())
line = "db3 = 1\n";
else line = "db3 = 0\n";
writec(fp, line);
close(fp);
send_query(button, iset, text, e1, e2, e3, e4,
e5, e6, e7, b1, b2, b3, b4, b5, b6);
}
/*--------------------------------------------------------------------
* Function: send_query
* Returns: t or nil
* Description: Calls the necessary functions to send a query to the
* Historian, and handle the data returned. It is activated
* by the "Record" button popping out, or any radio button.
* It sends two queries, the first to calculate the minimum
* and maximum values for use in creating plots, and the
* second to get the actual data.
* Arguments: button: The button that activated the function
* iset: An InterpolatorSettings instance
* e1 - e6: The six Interpolator options entry widgets
* e7: The "Number of points from last query" display
* b1 - b4: The four Interpolator options buttons
* b5: The Record button
* b6: The Update display button
*------------------------------------------------------------------*/
function send_query(button, iset, text, e1, e2, e3, e4,
e5, e6, e7, b1, b2, b3, b4, b5, b6)
{
local fnholder, datalist, minmaxlist;
if ((button == nil) || (button == b6) || (button.switched_on()))
{
if ((button == b1 || button == b2 ||
button == b3 || button == b4 ||
button == b5 || button == b6))
iset.dbflag = "NONE";
iset.assign_values(e1, e2, e3, e4, e5, e6);
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(e1, e2, e3, e4, e5, e6, e7);
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(e1, e2, e3, e4, e5, e6, e7);
show_data(text, iset, button, datalist, minmaxlist);
}
else
{
write_minmax(iset.misc_info);
}
}
/*--------------------------------------------------------------------
* Function: write_minmax
* Returns: t or nil
* Description: Writes a string to the plhistsetup.dat file containing
* four lines, each line assigning a value for an X or Y axis
* minimum or maximum variable, which are used by gnuplot.
*------------------------------------------------------------------*/
function write_minmax(minmax_string)
{
local fp = open("/tmp/cogentdemo/plhistsetup.dat", "a", nil);
writec(fp, minmax_string);
close(fp);
}
/*--------------------------------------------------------------------
* Function: file_add
* Returns: t or nil
* Description: Adds content from a file previously opened for reading
* (inptr) to a file previously opened for writing (outptr).
* Adds extra newlines, which gnuplot uses to mark the beginning
* of a new index file. Called only by show_data().
*------------------------------------------------------------------*/
function file_add(inptr, outptr)
{
local line;
while(line != _eof_)
{
line = read_line(inptr);
if (line != "Unexpected end of file")
writec(outptr, string(line, "\n"));
}
writec(outptr, "\n\n");
close(inptr);
}
/*--------------------------------------------------------------------
* Function: show_data
* Returns: t or nil
* Description: Shows interpolated query results from the Cascade Historian
* in the text widget. Sets up a single file (hsoutputpl.dat)
* that contains the content of all existing hsoutput files.
* This is necessary because gnuplot must read from a single file.
* Uses file_add() to do the actual reading and writing of the files.
*------------------------------------------------------------------*/
function show_data(txt_wgt, int_set, button, datalist, minmaxlist)
{
local start_time, tsk, infile, line, string_list, line_ret;
local title_string, x_list, y_list;
local f1, f2, f3, f4;
x_list = car(datalist);
y_list = cadr(datalist);
midnite = find_midnite();
if (int_set.fn == "NoInterpolator" || int_set.fn == "Periodic")
{
x_is_time = t;
title_string = "Query results: \n Time Y History\n";
}
else
{
x_is_time = nil;
title_string = "Query results: \nX-hist / Y-hist\n";
}
midnite = find_midnite();
txt_wgt.freeze();
txt_wgt.backward_delete(txt_wgt.get_length());
txt_wgt.insert(FONT, nil, nil, title_string, -1);
if(int_set.dbflag == "NONE")
infile = open("/tmp/cogentdemo/hsoutput.dat", "r");
if(int_set.dbflag == "DB")
infile = open("/tmp/cogentdemo/hsoutput2.dat", "r");
if(int_set.dbflag == "DBP")
infile = open("/tmp/cogentdemo/hsoutput3.dat", "r");
if (infile)
{
line = nil;
while(line != _eof_)
{
line = read_line(infile);
if (line != "Unexpected end of file")
{
if ((strstr(line,"#") != -1))
{
txt_wgt.insert(FONT, nil, nil, line, -1);
read_line(infile);
read_line(infile);
}
else
{
string_list = string_split(line, " ", 2);
if (int_set.fn == "NoInterpolator"
|| int_set.fn == "Periodic")
line_ret = string(number(car(string_list)) - midnite,
" ", cadr(string_list),"\n");
else
line_ret = string(number(car(string_list)),
" ", cadr(string_list),"\n");
txt_wgt.insert(FONT, nil, nil, line_ret, -1);
}
}
}
close(infile);
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;
int_set.misc_info = string("x_min = ", x_min, "\n",
"x_max = ", x_max, "\n",
"y_min = ", y_min, "\n",
"y_max = ", y_max, "\n");
write_minmax(int_set.misc_info);
}
}
txt_wgt.thaw();
if(is_file("/tmp/cogentdemo/hsoutput.dat"))
f1 = open("/tmp/cogentdemo/hsoutput.dat", "r");
if(is_file("/tmp/cogentdemo/hsoutput2.dat"))
f2 = open("/tmp/cogentdemo/hsoutput2.dat", "r");
if(is_file("/tmp/cogentdemo/hsoutput3.dat"))
f3 = open("/tmp/cogentdemo/hsoutput3.dat", "r");
f4 = open("/tmp/cogentdemo/hsoutputpl.dat", "w");
if(f1)
{
file_add(f1, f4);
if(f2)
file_add(f2, f4);
else
/* Put in a spacer line so gnuplot starts a new plot. */
writec(f4, "999 999\n\n\n");
if(f3)
file_add(f3, f4);
}
close(f4);
}
/********************************************************
* DEADBANDING Code *
********************************************************/
/*--------------------------------------------------------------------
* 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);
}
}
/*--------------------------------------------------------------------
* 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);
}
/*--------------------------------------------------------------------
* 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);
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();
}
/********************************************************
* HISTORY WINDOW Code *
********************************************************/
/*--------------------------------------------------------------------
* Function: make_toggle_button
* Returns: A GtkToggleButton
* Description: Creates toggle buttons.
*------------------------------------------------------------------*/
function make_toggle_button(lbl, color)
{
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));
button;
}
/*--------------------------------------------------------------------
* Function: qry_radio_but
* Returns: A GtkRadioButton
* Description: Creates the "Choose an Interpolator" radio buttons and
* puts them into a table. The last 6 parameters simply
* get passed along to the allow_entry_values() function
* and the .change_int() method.
*------------------------------------------------------------------*/
function qry_radio_but(tbl, txt, butlist, int_set, msg,
top, bottom, w1, w2, w3, e1, e2, e3)
{
local button;
button = gtk_radio_button_new_with_label(butlist, txt);
if (txt == "NoInterpolator")
{
button.set_active(TRUE);
allow_entry_values(w1, w2, w3, e1, e2, e3);
}
button.signal("clicked", `((@int_set).change_int(@button, @txt, @w1, @w2,
@w3, @e1, @e2, @e3)));
button_messages (button, msg, "6");
tbl.attach_defaults(button, 0, 1, top, bottom);
button;
}
/*--------------------------------------------------------------------
* Function: qry_entry
* Returns: A GtkEntry or GtkCombo widget, as specified
* Description: Creates a GtkEntry or GtkCombo widget, sets defaut values,
* and puts it into a table.
*------------------------------------------------------------------*/
function qry_entry(tbl, txt, value, top, bottom)
{
local box, label, entry, cbitems, cmb, ent_but = nil;
box = new(GtkHBox);
label = new(GtkLabel);
label.set_text(txt);
label.width = 80;
box.pack_start(label, TRUE, TRUE, 0);
if ((strstr(txt, "history")) == -1)
{
entry = new(GtkEntry);
entry.width = 75;
if (value == nil)
entry.set_text("");
else
entry.set_text(string(value));
box.pack_start(entry, TRUE, TRUE, 0);
}
else
{
cbitems = list("MV_001", "PV_001");
cmb = new(GtkCombo);
cmb.width = 75;
cmb.use_arrows = 0;
cmb.set_popdown_strings(cbitems);
entry = car(cmb.children());
ent_but = cadr(cmb.children());
entry.set_editable(FALSE);
if (value == nil)
entry.set_text("");
else
entry.set_text(string(value));
box.pack_start(cmb, TRUE, TRUE, 0);
}
tbl.attach_defaults(box, 1, 2, top, bottom);
entry;
}
/*--------------------------------------------------------------------
* Function: create_history
* Returns: A GtkWindow
* Description: Creates the History window.
*------------------------------------------------------------------*/
function create_history ()
{
local history_win, title, frame, box1, box2, box3, table;
local label, label1, label2, but_int1, but_int2, but_int3, but_int4;
local recbut, entry, qubut, dbsbut, text, but_db1, but_db2, but_db3;
local spinner, adj, xbut, iset, ent_yhs, ent_str, ent_dur;
local ent_xhs, ent_int, ent_max, ent_res, dbmv_set, dbpv_set, db_list;
local dbsbut, plbut, swin, buttons;
history_win = new (GtkWindow);
send_message("6");
history_win.signal ("destroy", #history_win = nil);
history_win.title = "Cogent Tools Demo: History";
history_win.set_color(1, GTK_STATE_NORMAL, 0xdddddd);
history_win.border_width = 10;
history_win.width = 380;
/* Title frame. */
box1 = new(GtkVBox);
title = new (GtkLabel);
title.set_text("Cogent Tools Demo - History");
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, 0);
history_win.add (box1);
/* Record Values and Exit buttons. */
table = gtk_table_new(5, 1, FALSE);
table.border_width = 5;
table.set_homogeneous(FALSE);
recbut = make_toggle_button("Record", 0xddccee);
recbut.signal("clicked", `send_hs_command(@recbut, "enable", nil, nil));
button_messages (recbut, "6.2", "6");
label1 = new(GtkLabel);
label1.set_text("data for");
adj = gtk_adjustment_new (0, 1, 200, 1, 5, 0.0);
spinner = new(GtkSpinButton);
spinner.set_adjustment(adj);
spinner.set_value(RECORD_TIME);
adj.signal("value_changed", `(RECORD_TIME = (@adj).value));
label2 = new(GtkLabel);
label2.set_text("seconds. ");
xbut = new(GtkButton);
xbut.label = "Exit";
xbut.signal("clicked", `(@history_win).destroy());
iset = new(InterpolatorSettings);
table.attach_defaults(recbut, 0, 1, 0, 1);
table.attach_defaults(label1, 1, 2, 0, 1);
table.attach_defaults(spinner, 2, 3, 0, 1);
table.attach_defaults(label2, 3, 4, 0, 1);
table.attach_defaults(xbut, 4, 5, 0, 1);
box1.pack_start(table, TRUE, TRUE, 5);
text = new(GtkText);
text.set_editable(FALSE);
/* Interpolator options. */
frame = new(GtkFrame);
frame.border_width = 5;
frame.set_color(1, GTK_STATE_NORMAL, 0xddccee);
frame.set_label(" Interpolator options: ");
frame.set_label_align(.05, 1);
frame.set_shadow_type(GTK_SHADOW_IN);
box1.pack_start(frame, TRUE, TRUE, 0);
table = gtk_table_new(2, 6, FALSE);
table.border_width = 10;
table.set_col_spacing(0, 20);
table.set_row_spacings(3);
frame.add(table);
ent_yhs = qry_entry(table, "Y history:", iset.y_history, 0, 1);
ent_str = qry_entry(table, "Start:", iset.start, 1, 2);
ent_dur = qry_entry(table, "Duration:", iset.duration, 2, 3);
ent_xhs = qry_entry(table, "X history:", iset.x_history, 3, 4);
ent_int = qry_entry(table, "Time Interval:", iset.interval, 4, 5);
ent_max = qry_entry(table, "Max. gap:", iset.max_gap, 5, 6);
but_int1 = qry_radio_but(table, "NoInterpolator", nil, iset,
"6.31", 0, 1, ent_xhs, ent_int, ent_max,
0, 0, 0);
but_int2 = qry_radio_but(table, "Periodic", list(but_int1), iset,
"6.32", 1, 2, ent_xhs, ent_int, ent_max,
0, 1, 1);
but_int3 = qry_radio_but(table, "Relative", list(but_int1, but_int2),
iset, "6.33", 2, 3, ent_xhs, ent_int,
ent_max, 1, 0, 0);
but_int4 = qry_radio_but(table, "FixedRelative",
list(but_int1, but_int2, but_int3), iset, "6.34",
3, 4, ent_xhs, ent_int, ent_max, 1, 1, 0);
ent_res = new(GtkEntry);
ent_res.width = 45;
qubut = new(GtkButton);
qubut.label = "Update display";
qubut.set_color(1, GTK_STATE_NORMAL, 0xddccee);
qubut.set_color(1, GTK_STATE_PRELIGHT, 0xeeddff);
button_messages (qubut, "6.3", "6");
table.attach_defaults(qubut, 0, 1, 5, 6);
/* Deadband options. */
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);
box2 = new(GtkHBox);
box1.pack_start(box2, TRUE, TRUE, 0);
frame = new(GtkFrame);
frame.border_width = 5;
frame.set_color(1, GTK_STATE_NORMAL, 0xddccee);
frame.set_label(" Deadband options: ");
frame.set_label_align(.05, 1);
frame.set_shadow_type(GTK_SHADOW_IN);
box2.pack_start(frame, TRUE, TRUE, 0);
table = gtk_table_new(1, 4, FALSE);
table.border_width = 10;
table.set_row_spacings(3);
frame.add(table);
but_db1 = gtk_check_button_new_with_label ("Full data set (no deadband)");
but_db2 = gtk_check_button_new_with_label ("Deadband on, prior value off");
but_db3 = gtk_check_button_new_with_label ("Deadband on, prior value on");
but_db1.signal("enter", `send_message("6.51"));
but_db2.signal("enter", `send_message("6.52"));
but_db3.signal("enter", `send_message("6.53"));
dbsbut = make_toggle_button("Set up deadband types", 0xddccee);
dbsbut.signal("toggled", `create_dbtype_win(@db_list, @dbsbut));
dbsbut.signal("enter", `send_message("6.5"));
table.attach_defaults(but_db1, 0, 1, 0, 1);
table.attach_defaults(but_db2, 0, 1, 1, 2);
table.attach_defaults(but_db3, 0, 1, 2, 3);
table.attach_defaults(dbsbut, 0, 1, 3, 4);
/* Plot and text display. */
box3 = new(GtkVBox);
box2.pack_start(box3, TRUE, TRUE, 30);
local button;
plbut = new(GtkToggleButton);
plbut.height = 20;
plbut.label = "Plot Data";
plbut.set_color(1, GTK_STATE_NORMAL, 0xccccb0);
plbut.set_color(1, GTK_STATE_PRELIGHT, 0xddddbb);
plbut.set_color(1, GTK_STATE_ACTIVE, 0xbbbb99);
plbut.signal("toggled", `start_stop(@plbut, "gnuplot", "plothist1",
"-background", "gray", "-geometry",
"500x400-10-30", "plhist.cfg", nil, nil, nil));
plbut.signal("toggled", `anygui_move_window(@plbut, @history_win,
380, 45, 100, 45));
button_messages (plbut, "6.4", "6");
label = new(GtkLabel);
label.set_text("Number\nof points\nfrom last\nquery:");
box3.pack_end(ent_res, FALSE, FALSE, 5);
box3.pack_end(label, TRUE, TRUE, 5);
box3.pack_end(plbut, 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);
recbut.signal("clicked",
`record_data(@recbut, @iset, @but_db1, @but_db2, @but_db3, @text,
@ent_yhs, @ent_str, @ent_dur, @ent_xhs,
@ent_int, @ent_max, @ent_res,
@but_int1, @but_int2,
@but_int3, @but_int4, @qubut));
/* Callbacks for non-deadband buttons to send a query. */
buttons = list(but_int1, but_int2, but_int3, but_int4, qubut);
with b in buttons do
{
b.signal("clicked",
`reset_deadbands(@b, @iset, @but_db1, @but_db2, @but_db3, @text,
@ent_yhs, @ent_str, @ent_dur, @ent_xhs,
@ent_int, @ent_max, @ent_res,
@but_int1, @but_int2, @but_int3,
@but_int4, @recbut, @qubut));
}
/* Callbacks for deadband buttons to prepare for and send a query. */
buttons = list(but_db1, but_db2, but_db3);
with b in buttons do
{
b.signal("clicked",
`plot_prep(@b, @iset, @but_db1, @but_db2, @but_db3, @text,
@ent_yhs, @ent_str, @ent_dur, @ent_xhs,
@ent_int, @ent_max, @ent_res,
@but_int1, @but_int2, @but_int3,
@but_int4, @recbut, @qubut));
}
/* Display version info and start-up message.*/
ret = display_hs_info(text);
history_win.show_all();
history_win.reposition(380, 45);
history_win;
}
/********************************************************
* MAIN FUNCTION Code *
********************************************************/
/*--------------------------------------------------------------------
* Function: main
* Returns: doesn't return
* Description: Calls the common.g program_startup() function and loops.
*------------------------------------------------------------------*/
function main()
{
program_startup("history", "historyq", #create_history(), "6");
atexit(#stop_processes());
/* Loop forever handling events. */
gtk_main ();
}