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);
          
}