Custom Widget: TableDrivenOneClick

The following example creates a TableDrivenOneClick widget, a GUI component placed like a OneClick panel that similarly implements filters on tables and plots. A TableDrivenOneClick panel contains two components: a text box and a combo box. Once the user types an entry into the text box and presses Enter, the combo box is updated with the values from the comboBoxColumn in the associated table.

The TableDrivenOneClick panel uses a common template for custom widgets. The deflate() method creates a Descriptor instance holding all the information we want the GUI component to have, in this case the Table and the two columns. This implements the interface Inflatable<TableDrivenOneClick>, which tells Deephaven how to re-inflate your widget after it has been deflated and shipped.

See Custom Widgets in the User Guide to learn more.

Step 1: Create a Java class for the widget

In order to create your own widget, first create a Java class which implements the com.illumon.iris.db.tables.utils.LiveWidget Class. This class tells Deephaven how to ship the information required to create the GUI component to the client.

import com.fishlib.io.logger.Logger;
import com.illumon.iris.db.tables.Table;
import com.illumon.iris.db.tables.remote.ExportedObjectClient;
import com.illumon.iris.db.tables.remote.Inflatable;
import com.illumon.iris.db.tables.remotequery.QueryProcessorConnection;
import com.illumon.iris.db.tables.utils.LiveWidget;
import com.illumon.iris.gui.widget.AsyncPanel;

import javax.swing.*;

In the code below, baseTable sets the table filtering values are drawn from, textBoxColumn sets the column for text box input, and comboBoxColumn sets the column for ComboBox input.

//The constructor takes a Table and two columns as input.
public class TableDrivenOneClick implements LiveWidget<TableDrivenOneClick> {

    private final Table baseTable;
    private final String textBoxColumn, comboBoxColumn;
//The next segment of code runs on the server and creates a table
//with only the unique value of the two columns, textBoxColumn and comboBoxColumn,
//so that the client has to process less data.
public TableDrivenOneClick(final Table baseTable, final String textBoxColumn,
     final String comboBoxColumn) {
     if (!baseTable.hasColumns(textBoxColumn, comboBoxColumn)) {
     throw new IllegalArgumentException("Base table does not contain columns " +
     textBoxColumn + ", " + comboBoxColumn);
}
//.preemptiveUpdatesTable(1000L) specifies how frequently
//the client side Table will update.
this.baseTable = baseTable.selectDistinct(textBoxColumn,
comboBoxColumn).preemptiveUpdatesTable(1000L);
this.textBoxColumn = textBoxColumn;
this.comboBoxColumn = comboBoxColumn;
}

Step 2: Implement Deflate and Inflate for the LiveWidget

Ticking Deephaven tables are not serializable and are not shipped to the client. All Table objects must be deflated to create a serializable Inflatable<Table> object, which is essentially a table handle, or identifier that the client may use to communicate with the server about a given table. Note: other Java objects do not need to be inflated, or uncompressed, because they use Java serialization.

// Since tables are not serializable and the entire table cannot be shipped to the
// server, we use the table.deflate()method to produce a handle to the table.

@Override
public Inflatable<TableDrivenOneClick> deflate(ExportedObjectClient client) {
     return new Descriptor(baseTable.deflate(client), textBoxColumn, comboBoxColumn);
}
@Override
public JComponent getComponent(AsyncPanel dataPanel, String viewId, String title, Object irisWidgetSupportObject, Logger log) {
      return new TableDrivenOneClickPanel(baseTable, textBoxColumn, comboBoxColumn, log);
     }

The descriptor class holds all the information needed to create a TableDrivenOneClick widget. It defines an inflate() method, which inflates all the deflated tables.

private static class Descriptor implements Inflatable<TableDrivenOneClick> {
         private static final long serialVersionUID = -242821532734185765L;

          private final Inflatable<Table> table;
          private final String textBoxColumn, comboBoxColumn;
         public Descriptor(final Inflatable<Table> table,
final String textBoxColumn, final String comboBoxColumn) {
               this.table = table;
               this.textBoxColumn = textBoxColumn;
               this.comboBoxColumn = comboBoxColumn;
        }

         @Override

The next lines create a proxy Table on the client side, and when this code is run, it creates a TableDrivenOneClick widget on the client.

public TableDrivenOneClick inflate(QueryProcessorConnection queryProcessorConnection) {
             return new TableDrivenOneClick(table.inflate(queryProcessorConnection), textBoxColumn, comboBoxColumn);
          }
      }
}

Step 3: Define the component described by the LiveWidget in the console

Next, the new TableDriveOneClick widget needs to be instantiated in the GUI. It is placed like a OneClick Panel and triggers filters on tables, plots, etc. like a OneClick filter would, and includes a text box and a drop down menu. Here, the getComponent() method is called. The TableDrivenOneClick on the client returns a TableDrivenOneClickPanel, whose code is below:

@SuppressWarnings("WeakerAccess")
public class TableDrivenOneClickPanel extends JPanel {
       private final String textBoxColumn, comboBoxColumn; //The columns whose values drive the filtering.

      private final JTextField textField = new JTextField(10); //This creates a text field that is 10 characters long.

      private final ComboBox comboBox = new ComboBox(); //This creates a drop down menu.

       private final TableMap listColMap; // This maps textBoxColumn values to separate Tables.
      private final Logger log;
      private String currentTextBoxColumnValue = ""; // Current values are based on user input; this is the value from the text box.
      private String currentComboBoxColumnValue = ""; // This is the value from the combo box.
      private Table currentComboBoxColumnTable; //This creates a table of distinct values in the comboBoxColumn for the currentTextBoxColumnValue.
      private InstrumentedListenerAdapter currentListenerAdapter;

// The following parameters create a panel with a text box and drop down menu.
@SuppressWarnings("WeakerAccess")
      public TableDrivenOneClickPanel(Table baseTable, final String textBoxColumn, final String comboBoxColumn, final Logger log) {
         baseTable = baseTable.subscribeToPreemptiveUpdates(); // the table which gives possible filter values

          this.log = log;
         this.textBoxColumn = textBoxColumn; // the column for text box input
         this.comboBoxColumn = comboBoxColumn; // the column for combo box input
          this.listColMap = baseTable.byExternal(textBoxColumn); //creates a TableMap
    }
}

Step 4: Open the widget in the console

import com.illumon.iris.console.Playground.TableDrivenOneClick

t = emptyTable(10).update("USym = `A`"), ("Date = `2018-05-07`")

widget = NewTableDrivenOneClick (t, "USym", "Date")

t2 = emptyTable(10).update("USym = `A`"), ("Date = `2018-05-07`")

The complete code block follows:


Last Updated: 16 February 2021 18:06 -04:00 UTC    Deephaven v.1.20200928  (See other versions)

Deephaven Documentation     Copyright 2016-2020  Deephaven Data Labs, LLC     All Rights Reserved