public TableViewRowEditor() {
    setContent(scrollPane);
    scrollPane.getStyles().put("backgroundColor", null);
    scrollPane.setView(cardPane);
    scrollPane
        .getViewportListeners()
        .add(
            new ViewportListener.Adapter() {
              @Override
              public void scrollLeftChanged(Viewport viewport, int previousScrollLeft) {
                if (tableViewScrollPane != null) {
                  tableViewScrollPane.setScrollLeft(viewport.getScrollLeft());
                }
              }
            });

    cardPane.add(new ImageView(rowImage));
    cardPane.add(tablePane);
    cardPane
        .getCardPaneListeners()
        .add(
            new CardPaneListener.Adapter() {
              @Override
              public void selectedIndexChanged(
                  CardPane cardPaneArgument, int previousSelectedIndex) {
                if (previousSelectedIndex == IMAGE_CARD_INDEX) {
                  editorRow.get(columnIndex).requestFocus();
                } else {
                  endEdit(false);
                }
              }
            });

    tablePane.getStyles().put("horizontalSpacing", 1);
    tablePane.getRows().add(editorRow);
  }
  @Override
  public void beginEdit(
      TableView tableViewArgument, int rowIndexArgument, int columnIndexArgument) {
    this.tableView = tableViewArgument;
    this.rowIndex = rowIndexArgument;
    this.columnIndex = columnIndexArgument;

    Container tableViewParent = tableViewArgument.getParent();
    tableViewScrollPane =
        (tableViewParent instanceof ScrollPane) ? (ScrollPane) tableViewParent : null;

    // Add/create the editor components
    TableView.ColumnSequence tableViewColumns = tableViewArgument.getColumns();
    TablePane.ColumnSequence tablePaneColumns = tablePane.getColumns();

    for (int i = 0, n = tableViewColumns.getLength(); i < n; i++) {
      // Add a new column to the table pane to match the table view column
      TablePane.Column tablePaneColumn = new TablePane.Column();
      tablePaneColumn.setWidth(tableViewArgument.getColumnBounds(i).width);
      tablePaneColumns.add(tablePaneColumn);

      // Determine which component to use as the editor for this column
      String columnName = tableViewColumns.get(i).getName();
      Component editorComponent = null;
      if (columnName != null) {
        editorComponent = cellEditors.get(columnName);
      }

      // Default to a read-only text input editor
      if (editorComponent == null) {
        TextInput editorTextInput = new TextInput();
        editorTextInput.setTextKey(columnName);
        editorTextInput.setEnabled(false);
        editorTextInput.setTextBindType(BindType.LOAD);
        editorComponent = editorTextInput;
      }

      // Add the editor component to the table pane
      editorRow.add(editorComponent);
    }

    // Get the data being edited
    List<?> tableData = tableViewArgument.getTableData();
    Object tableRow = tableData.get(rowIndexArgument);

    // Load the row data into the editor components
    tablePane.load(tableRow);

    // Get the row bounds
    Bounds rowBounds = tableViewArgument.getRowBounds(rowIndexArgument);
    rowImage.bounds = rowBounds;

    // Scroll to make the row as visible as possible
    tableViewArgument.scrollAreaToVisible(
        rowBounds.x, rowBounds.y, rowBounds.width, rowBounds.height);

    // Constrain the bounds by what is visible through viewport ancestors
    rowBounds = tableViewArgument.getVisibleArea(rowBounds);
    Point location =
        tableViewArgument.mapPointToAncestor(
            tableViewArgument.getDisplay(), rowBounds.x, rowBounds.y);

    // Set size and location and match scroll left
    setPreferredWidth(rowBounds.width);
    setLocation(location.x, location.y + (rowBounds.height - getPreferredHeight(-1)) / 2);

    if (tableViewScrollPane != null) {
      scrollPane.setScrollLeft(tableViewScrollPane.getScrollLeft());
    }

    // Open the editor
    open(tableViewArgument.getWindow());

    // Start the transition
    cardPane.setSelectedIndex(EDITOR_CARD_INDEX);
  }