Example - DynamicTableView Use
The following script provides an example on how to use the DynamicTableView class, including initialization, updates, sorting and filtering.
#uses "classes/DynamicTableView.ctl"
class Receiver
{
// the update callback just shows the list of received changes
public updateCB(const anytype &userData, const mapping &changes)
{
DebugTN(changes);
}
// callback for static data: just invents some data on the fly
public string staticData(const anytype &userData, const string &rowID, const string &colID)
{
return strtoupper(rowID + "/" + colID);
}
// a simple value converter that converts to ulong
public ulong toUlong(const anytype &userData, const string &rowID, const string &colID, const anytype &value)
{
return (ulong)value;
}
};
main()
{
// preparation: build a list of DPs and IDs, and initialize all DPs
dyn_string names = dpNames("*", "ExampleDP_Float");
dyn_string ids;
dyn_float values;
// generate row IDs out of the DP names
for (int i = 1; i <= names.count(); i++)
{
dyn_string parts = names[i].split("_");
names[i] = names[i] + ".";
ids[i] = parts[2];
values[i] = names.count() - i;
}
dpSetWait(names, values);
delay(1);
// ----------------------------------------------------------------------------------------
// INITALIZING
// ----------------------------------------------------------------------------------------
time startTime = getCurrentTime();
shared_ptr<Receiver> rcv = new Receiver();
DynamicTableView view = DynamicTableView(rcv, Receiver::updateCB);
DebugTN("====================== First update with 5 complete rows when view.setDpeNames() is called");
dyn_mapping columns =
makeDynMapping(
// simple column containing the value
makeMapping(DynamicTableView::COLUMN_CONFIG_KEY, ":_online.._value",
DynamicTableView::COLUMN_ID_KEY, "value"),
// column containing the status, converted to unsigned long by Receiver::toUlong()
makeMapping(DynamicTableView::COLUMN_CONFIG_KEY, ":_online.._status",
DynamicTableView::COLUMN_ID_KEY, "status",
DynamicTableView::COLUMN_CONVERT_KEY, Receiver::toUlong),
// column containing static data that is generated by Receiver::staticData()
makeMapping(DynamicTableView::COLUMN_ID_KEY, "static",
DynamicTableView::COLUMN_CONVERT_KEY, Receiver::staticData),
// simple column containing the time of the update
makeMapping(DynamicTableView::COLUMN_CONFIG_KEY, ":_online.._stime",
DynamicTableView::COLUMN_ID_KEY, "time"));
view.setDpeNames(columns, names, ids);
delay(1);
// instead of setDpeNames(), also setQuery() could be used to connect to data:
// string queryPart = "FROM '*' WHERE _DPT=\"ExampleDP_Float\"";
// view.setQuery(columns, queryPart);
// delay(1);
DebugTN("====================== Changes in view size are reported as updates, not sending values for aalready visible rows");
view.setView(4, 6);
delay(1);
DebugTN("====================== Changes in first visible row index are reported as updates");
view.setView(0);
delay(1);
// ----------------------------------------------------------------------------------------
// VALUE UPDATES
// ----------------------------------------------------------------------------------------
DebugTN("====================== Only changed values are updated");
dpSet("ExampleDP_Arg1.", 3.14);
dpSet("ExampleDP_Rpt1.", 42);
delay(1);
// ----------------------------------------------------------------------------------------
// SORTING
// ----------------------------------------------------------------------------------------
DebugTN("====================== Now sort by value, very likely some rows are reused");
view.setSortColumn("value");
delay(1);
DebugTN("====================== Reverse sorting, again some rows are reused");
view.setSortColumn("value", false);
delay(1);
DebugTN("====================== Sort by static column, again some rows are reused");
view.setSortColumn("static", false);
delay(1);
DebugTN("====================== Sort by two colums (time (newest first), then value (ascending)");
view.setSortColumns(makeDynAnytype(makeDynAnytype("time", false),
makeDynAnytype("value")));
delay(1);
DebugTN("====================== Complete visible data is always available, independent from updates");
DebugTN(view.dataToDisplayAsUpdate());
delay(1);
// ----------------------------------------------------------------------------------------
// FILTERING
// ----------------------------------------------------------------------------------------
DebugTN("====================== Filter to updates after start time - all rows are reused");
view.setFilter(DynamicTableViewFilter("time", DynamicTableViewFilterOp::GTE, startTime));
delay(1);
DebugTN("====================== Modify a value - new row added, row for result updated");
dpSet("ExampleDP_Arg2.", 50);
delay(1);
DebugTN("====================== Filter by two criteria - either changed before start time or greater than 50");
vector<DynamicTableViewFilter> filters;
filters.append(DynamicTableViewFilter("time",
DynamicTableViewFilterOp::LT,
startTime,
true)); // true means OR with next filter
filters.append(DynamicTableViewFilter("value",
DynamicTableViewFilterOp::GTE,
50.0));
view.setFilters(filters);
delay(1);
DebugTN("====================== Reset sorting");
view.resetSorting();
delay(1);
DebugTN("====================== Clear filter");
view.clearFilters();
delay(1);
}