Package swingtree

Class UIForTable<T extends JTable>


public final class UIForTable<T extends JTable> extends UIForAnySwing<UIForTable<T>,T>
A SwingTree declarative builder designed for configuring JTable instances allowing for a fluent API to build tables in a declarative way.
  • Method Details

    • _state

      protected swingtree.BuilderState<T> _state()
      Description copied from class: UIForAnything
      Returns the state of the builder, which is a container for the wrapped component as well as it's type and current EventProcessor.
      Specified by:
      _state in class UIForAnything<UIForTable<T extends JTable>,T extends JTable,JComponent>
      Returns:
      The state of the builder.
    • _newBuilderWithState

      protected UIForTable<T> _newBuilderWithState(swingtree.BuilderState<T> newState)
      Description copied from class: UIForAnything
      An internal wither method which creates a new builder instance with the provided BuilderState stored inside it.
      Specified by:
      _newBuilderWithState in class UIForAnything<UIForTable<T extends JTable>,T extends JTable,JComponent>
      Parameters:
      newState - The new state which should be stored inside the new builder instance.
      Returns:
      A new builder instance with the provided state stored inside it.
    • withHeader

      public final UIForTable<T> withHeader(UIForTableHeader<?> header)
      Use this to set the table header.
      Parameters:
      header - The table header to be set.
      Returns:
      This builder node.
    • withHeader

      public final UIForTable<T> withHeader(JTableHeader header)
      Use this to set the table header.
      Parameters:
      header - The table header to be set.
      Returns:
      This builder node.
    • withCellsForColumn

      public final UIForTable<T> withCellsForColumn(String columnName, Configurator<CellBuilder<T,Object>> renderBuilder)
      Use this to build a table cell renderer for a particular column. The second argument accepts a lambda function which exposes the builder API for a cell renderer. Here is an example of how to use this method:
      
           UI.table(myModel)
           .withCellsForColumn("column1", it -> it
               .when(String.class)
               .asText( cell -> "[" + cell.valueAsString().orElse("") + "]" ) )
           )
           .withCellsForColumn("column2", it -> it
               .when(Float.class)
               .asText( cell -> "(" + cell.valueAsString().orElse("") + "f)" ) )
               .when(Double.class)
               .asText( cell -> "(" + cell.valueAsString().orElse("") + "d)" ) )
           );
       
      The above example would render the first column of the table as a string surrounded by square brackets, and the second column as a float or double value surrounded by parentheses. Note that the API allows you to specify how specific types of table entry values should be rendered. This is done by calling the CellBuilder.when(Class) method before calling the RenderAs.asText(Function) method.
      Due to this method being inherently based on the expectation of type ambiguity it is a rather verbose way of defining how your cells should look and behave. The simpler and preferred way of defining cell views is through the withCell(Configurator), withCellForColumn(String, Configurator) and withCellForColumn(int, Configurator) methods.
      Parameters:
      columnName - The name of the column for which the cell renderer will be built.
      renderBuilder - A lambda function which exposes a fluent builder API for a cell renderer and returns the builder API for a cell renderer. Call the appropriate methods on the builder API to configure the cell renderer.
      Returns:
      This builder node.
    • withCellForColumn

      public final UIForTable<T> withCellForColumn(String columnName, Configurator<CellConf<T,Object>> cellConfigurator)
      Use this to build a basic table cell renderer for a particular column. The second argument passed to this method is a lambda function which accepts a CellConf representing the cell to be rendered. You may then return an updated cell with a desired view component through methods like CellConf.view(Component) or CellConf.updateView(Configurator). Here an example of how this method may be used:
      
           UI.table(UI.ListData.ROW_MAJOR_EDITABLE, ()->List.of(List.of(1, 2, 3), List.of(7, 8, 9)) )
           .withCellForColumn(0, cell -> cell
                .updateView( comp -> comp
                    .orGet(JLabel::new) // initialize a new JLabel if not already present
                    .updateIf(JLabel.class, l -> {
                        l.setText(cell.valueAsString().orElse(""));
                        l.setBackground(cell.isSelected() ? Color.YELLOW : Color.WHITE);
                        return l;
                    })
                    //...
                )
           )
           .withCellForColumn(1, cell -> cell
                .updateView( comp -> comp
                    //...
                )
           );
       
      Also see withCellForColumn(int, Configurator) method to build a cell renderer for a column by index, and withCell(Configurator) method to build a cell renderer for all columns of the table.
      This API also supports the configuration of cell editors as the supplied lambda will also be called by an underlying TableCellEditor implementation when the cell is in editing mode. The cell will indicate that it needs an editor component by having the CellConf.isEditing() set to true. You can then decide to return a different view component for the cell editor by checking this property. The next time the lambda is invoked with the CellConf.isEditing() flag is set to true, then the cell will still contain the same editor component as previously specified. In case of the flag being false, the cell will contain the view component that was provided the last time the cell was not in editing mode.
      Parameters:
      columnName - The name of the column for which the cell renderer will be built.
      cellConfigurator - A lambda function which configures the cell view.
      Returns:
      This builder node.
    • withCellsForColumn

      public final UIForTable<T> withCellsForColumn(int columnIndex, Configurator<CellBuilder<T,Object>> renderBuilder)
      Use this to build a table cell renderer for a particular column. The second argument accepts a lambda function which exposes the builder API for a cell renderer. Here an example of how this method may be used:
      
           UI.table(myModel)
           .withCellForColumn(0, it -> it
               .when(String.class)
               .asText( cell -> "[" + cell.valueAsString().orElse("") + "]" ) )
           )
           .withCellForColumn(1, it -> it
               .when(Float.class)
               .asText( cell -> "(" + cell.valueAsString().orElse("") + "f)" ) )
               .when(Double.class)
               .asText( cell -> "(" + cell.valueAsString().orElse("") + "d)" ) )
           );
       
      The above example would render the first column of the table as a string surrounded by square brackets, and the second column as a float or double value surrounded by parentheses. Note that the API allows you to specify how specific types of table entry values should be rendered. This is done by calling the CellBuilder.when(Class) method before calling the RenderAs.asText(Function) method.

      Due to this method being inherently based on the expectation of type ambiguity it is a rather verbose way of defining how your cells should look and behave. The simpler and preferred way of defining cell views is through the withCell(Configurator), withCellForColumn(String, Configurator) and withCellForColumn(int, Configurator) methods.
      Parameters:
      columnIndex - The index of the column for which the cell renderer will be built.
      renderBuilder - A lambda function which exposes a fluent builder API for a cell renderer and returns the builder API for a cell renderer. Call the appropriate methods on the builder API to configure the cell renderer.
      Returns:
      This builder node.
    • withCellForColumn

      public final UIForTable<T> withCellForColumn(int columnIndex, Configurator<CellConf<T,Object>> cellConfigurator)
      Use this to build a basic table cell view for a particular column. The second argument passed to this method is a lambda function which accepts a CellConf representing the cell to be rendered and possibly even edited. You may then return an updated cell with a desired view component through methods like CellConf.view(Component) or CellConf.updateView(Configurator). Here an example of how this method may be used:
      
           UI.table(UI.ListData.ROW_MAJOR_EDITABLE, ()->List.of(List.of(1, 2, 3), List.of(7, 8, 9)) )
           .withCellForColumn(0, cell -> cell
                .updateView( comp -> comp
                    .orGet(JLabel::new) // initialize a new JLabel if not already present
                    .updateIf(JLabel.class, l -> {
                        l.setText(cell.valueAsString().orElse(""));
                        l.setBackground(cell.isSelected() ? Color.YELLOW : Color.WHITE);
                        return l;
                    })
                    //...
                )
           )
           .withCellForColumn(1, cell -> cell
                .updateView( comp -> comp
                    //...
                )
           );
       
      Also see withCellForColumn(String, Configurator) method to build a cell renderer for a column by name, and withCell(Configurator) method to build a cell renderer for all columns of the table.
      This API also supports the configuration of cell editors as the supplied lambda will also be called by an underlying TableCellEditor implementation when the cell is in editing mode. The cell will indicate that it needs an editor component by having the CellConf.isEditing() set to true. You can then decide to return a different view component for the cell editor by checking this property. The next time the lambda is invoked with the CellConf.isEditing() flag is set to true, then the cell will still contain the same editor component as previously specified. In case of the flag being false, the cell will contain the view component that was provided the last time the cell was not in editing mode.
      Parameters:
      columnIndex - The index of the column for which the cell renderer will be built.
      cellConfigurator - A lambda function which configures the cell view. The lambda is invoked in two main situations: when the cell is in editing mode and when the cell is not in editing mode (only rendering). You may decide what to store in the cell based on its state.
      Returns:
      This instance of the builder, to allow for declarative method chaining.
    • withCellRendererForColumn

      public final UIForTable<T> withCellRendererForColumn(String columnName, TableCellRenderer renderer)
      Use this to register a table cell renderer for a particular column. A TableCellRenderer is a supplier of Component instances which are used to render the cells of a table. Note that in SwingTree, the preferred way of defining a cell renderer for a particular column is through the withCellForColumn(String, Configurator) method, which allows for a more fluent and declarative way of defining cell renderers as well as editors.
      Parameters:
      columnName - The name of the column for which the cell renderer will be registered.
      renderer - The cell renderer to be registered.
      Returns:
      This builder node, to allow for builder-style method chaining.
    • withCellRendererForColumn

      public final UIForTable<T> withCellRendererForColumn(int columnIndex, TableCellRenderer renderer)
      Use this to register a table cell renderer for a particular column.
      A TableCellRenderer is a supplier of Component instances which are used to render the cells of a table. Note that in SwingTree, the preferred way of defining a cell renderer for a particular column is through the withCellForColumn(int, Configurator) method, which allows for a more fluent and declarative way of defining cell renderers. It also supports both cell rendering and editing.
      Parameters:
      columnIndex - The index of the column for which the cell renderer will be registered.
      renderer - The cell renderer to be registered.
      Returns:
      This builder instance, to allow for method chaining.
    • withCellRenderer

      public final UIForTable<T> withCellRenderer(TableCellRenderer renderer)
      Use this to register a TableCellRenderer for all columns of this table.
      A TableCellRenderer is a supplier of Component instances which are used to render the cells of a table.

      Note that in SwingTree, the preferred way of defining a cell renderer is through the withCell(Configurator) method, which allows for a more fluent and declarative way of defining cell renderers and also supports both cell rendering and editing.
      Parameters:
      renderer - A provider of Component instances which are used to render the cells of a table.
      Returns:
      This builder instance, to allow for method chaining.
    • withCells

      public final UIForTable<T> withCells(Configurator<CellBuilder<T,Object>> renderBuilder)
      Use this to define a table cell renderer for all columns of this table using the fluent builder API exposed to the provided lambda function.
      Here is an example of how this method is used:
      
          UI.table()
          .withCells( it -> it
              .when(SomeDataType.class)
              .asText( cell -> cell.value().get().toString() )
          )
          // ...
        
      You may want to know that a similar API is also available for the JList and JComboBox components, see UIForList.withCells(Configurator), UIForCombo.withCells(Configurator) for more information.

      Also see withCell(Configurator) method, which constitutes the preferred way to build a list cell renderer as it is simpler, more concise and less error-prone.

      Parameters:
      renderBuilder - A lambda function which exposes the builder API for a cell renderer and returns the builder API for a cell renderer. Call the appropriate methods on the builder API to configure the cell renderer.
      Returns:
      This builder node.
    • withCell

      public final <V> UIForTable<T> withCell(Configurator<CellConf<T,V>> cellConfigurator)
      Allows for the configuration of a cell view for the items of the JTable instance. The Configurator lambda function passed to this method receives a CellConf exposing a wide range of properties describing the state of the cell, like its current item, its index, its selection state, etc. You may update return an updated cell with a desired view component through methods like CellConf.view(Component) or CellConf.updateView(Configurator).

      Here code snippet demonstrating how this method may be used as part of a UI declaration:

      
            UI.table(UI.MapData.EDITABLE,()->{
                Map<String, List<String>> data = new LinkedHashMap<>();
                data.put("A", List.of("A1", "A2", "A3"));
                data.put("B", List.of("B1", "B2", "B3"));
                data.put("C", List.of("C1", "C2", "C3"));
                return data;
            })
            .withCell( cell -> cell
                .updateView( comp -> comp
                    .orGet(JLabel::new) // initialize a new JLabel if not already present
                    .updateIf(JLabel.class, tf -> {
                        tf.setText(cell.valueAsString().orElse(""));
                        tf.setBackground(cell.isSelected() ? Color.YELLOW : Color.WHITE);
                        return tf;
                    })
                )
            )
        
      In this example, a new JTable is created from a map of column names to lists of strings. The Configurator lambda function passed to this method configures the cell view by setting the text of a JLabel to the value of the cell, and setting the background color of the label to yellow if the cell is selected, and white otherwise.
      This API also supports the configuration of cell editors as the supplied lambda will also be called by an underlying TableCellEditor implementation when the cell is in editing mode. The cell will indicate that it needs an editor component by having the CellConf.isEditing() set to true. You can then decide to return a different view component for the cell editor by checking this property. The next time the lambda is invoked with the CellConf.isEditing() flag is set to true, then the cell will still contain the same editor component as previously specified. In case of the flag being false, the cell will contain the view component that was provided the last time the cell was not in editing mode.
      Type Parameters:
      V - The type of the value that is being rendered in this combo box.
      Parameters:
      cellConfigurator - The Configurator lambda function that configures the cell view.
      Returns:
      This instance of the builder node to allow for fluent method chaining.
    • withCellEditorForColumn

      public final UIForTable<T> withCellEditorForColumn(String columnName, TableCellEditor editor)
      Use this to register a table cell editor for a particular column. Note that in SwingTree, the preferred way of defining a cell editor for a particular column is through the withCellForColumn(String, Configurator) method, which allows for a more fluent and declarative way of defining cell editors.
      Parameters:
      columnName - The name of the column for which the cell editor will be registered.
      editor - The cell editor to be registered.
      Returns:
      This builder instance, to allow for method chaining.
    • withCellEditorForColumn

      public final UIForTable<T> withCellEditorForColumn(int columnIndex, TableCellEditor editor)
      Use this to register a table cell editor for a particular column. Note that in SwingTree, the preferred way of defining a cell editor for a particular column is through the withCellForColumn(int, Configurator) method, which allows for a more fluent and declarative way of defining cell editors.
      Parameters:
      columnIndex - The index of the column for which the cell editor will be registered.
      editor - The cell editor to be registered.
      Returns:
      This builder node, to allow for builder-style method chaining.
    • withModel

      public final UIForTable<T> withModel(Buildable<BasicTableModel> dataModelBuilder)
      Use this to set a table model. The provided argument is a builder object whose build method will be called for you instead of having to call the build method on the builder object yourself. The preferred way of setting a table model is through the withModel(Configurator) which exposes a fluent builder API for binding the table model to a data source without any boilerplate code.
      Parameters:
      dataModelBuilder - The builder object which will be used to build and then set the table model.
      Returns:
      This builder object.
    • withModel

      public final UIForTable<T> withModel(Configurator<BasicTableModel.Builder<Object>> dataModelBuilder)
      Exposes a fluent builder API for a table model.
      Here an example demonstrating how this API is typically used as part of a UI declaration:
      
        UI.table().withModel( m -> m
            .colName( col -> new String[]{"X", "Y", "Z"}[col] )
            .colCount( () -> 3 )
            .rowCount( () -> data.size() )
            .getsEntryAt( (r, c) -> data[r][c] )
            .updateOn(update)
        )
        
      The builder API is exposed to the lambda function passed to this method. The actually TableModel is built internally and then set on the table.
      Parameters:
      dataModelBuilder - A lambda function which receives a builder API for a table model
      Returns:
      This builder instance, to allow for further method chaining.
    • withModel

      public final <E> UIForTable<T> withModel(Class<E> itemType, Configurator<BasicTableModel.Builder<E>> dataModelBuilder)
      Exposes a fluent builder API for a table model holding a specific type of entry.
      Here an example demonstrating how this API is typically used as part of a UI declaration:
      
        UI.table().withModel(Double.class, m -> m
            .colName( col -> new String[]{"X", "Y", "Z"}[col] )
            .colCount( () -> 3 )
            .rowCount( () -> data.size() )
            .getsEntryAt( (r, c) -> data[r][c] )
            .updateOn(update)
        )
        
      In this example, the table model is built for a Double based data source. So here the data array is a two-dimensional array of Doubles.

      Note that the builder API is exposed to the lambda function passed to this method. The actual TableModel is built internally and then installed on the table component.

      You can also use the UIFactoryMethods.table(Configurator) factory method to directly create a table with a custom table model.

      Type Parameters:
      E - The type of the table entry Objects.
      Parameters:
      itemType - The type of the table entry Objects.
      dataModelBuilder - A lambda function which receives a builder API for a table model
      Returns:
      This builder instance, to allow for further method chaining.
    • withModel

      public final UIForTable<T> withModel(BasicTableModel model)
      Use this to set a basic table model for this table.
      Parameters:
      model - The model for the table model.
      Returns:
      This builder object.
    • withModel

      public final <E> UIForTable<T> withModel(UI.ListData mode, TableListDataSource<E> dataSource)
      Use this instead of JTable.setModel(TableModel) if your table data can be represented by either a row major List of Lists of entry Objects (a list of rows)
      or a columns major List of Lists of entry Objects (a list of columns).
      This method will automatically create a AbstractTableModel instance for you.

      Please note that when the data of the provided data source changes (i.e. when the data source is a List and the list is modified), the table model will not be updated automatically! Use updateTableOn(sprouts.Event) to bind an update Event to the table model.

      Type Parameters:
      E - The type of the table entry Objects.
      Parameters:
      mode - An enum which configures the layout as well as modifiability of the table in a readable fashion.
      dataSource - The TableListDataSource returning a list matrix which will be used to populate the table.
      Returns:
      This builder node.
    • withModel

      public final <E> UIForTable<T> withModel(UI.MapData mode, TableMapDataSource<E> dataSource)
      Use this instead of JTable.setModel(TableModel) if your table data can be represented based on a map of column names to lists of table entries (basically a column major matrix).
      This method will automatically create a AbstractTableModel instance for you.

      Please note that when the data of the provided data source changes (i.e. when the data source is a Map which gets modified), the table model will not be updated automatically! Use updateTableOn(sprouts.Event) to bind an update Event to the table model.

      Type Parameters:
      E - The type of the table entry Objects.
      Parameters:
      mode - An enum which configures the modifiability of the table in a readable fashion.
      dataSource - The TableMapDataSource returning a column major map based matrix which will be used to populate the table.
      Returns:
      This builder node.
    • updateTableOn

      public final UIForTable<T> updateTableOn(sprouts.Event event)
      Use this to bind an Event to the TableModel of this table which will trigger the AbstractTableModel.fireTableDataChanged() method. This is useful if you want to update the table when the data source changes.
      Parameters:
      event - The event to be bound.
      Returns:
      This builder node, for chaining.