@Override
  @SuppressWarnings("unchecked")
  public void endEdit(boolean result) {
    if (result) {
      // Update the row data
      List<Object> tableData = (List<Object>) tableView.getTableData();
      Object tableRow = tableData.get(rowIndex);
      tablePane.store(tableRow);

      if (tableData.getComparator() == null) {
        tableData.update(rowIndex, tableRow);
      } else {
        tableData.remove(rowIndex, 1);
        tableData.add(tableRow);

        // Re-select the item, and make sure it's visible
        rowIndex = tableData.indexOf(tableRow);
        tableView.setSelectedIndex(rowIndex);
        tableView.scrollAreaToVisible(tableView.getRowBounds(rowIndex));
      }
    }

    if (cardPane.getSelectedIndex() == EDITOR_CARD_INDEX) {
      cardPane.setSelectedIndex(IMAGE_CARD_INDEX);
    } else {
      // Remove the editor components
      TablePane.ColumnSequence tablePaneColumns = tablePane.getColumns();
      tablePaneColumns.remove(0, tablePaneColumns.getLength());
      editorRow.remove(0, editorRow.getLength());

      getOwner().moveToFront();
      tableView.requestFocus();

      tableView = null;
      rowIndex = -1;
      columnIndex = -1;

      tableViewScrollPane = null;

      close();
    }
  }
  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);
  }
 /**
  * Sets the edit effect rate.
  *
  * @param effectRate The effect rate.
  */
 public void setEditEffectRate(int effectRate) {
   cardPane.getStyles().put("selectionChangeRate", effectRate);
 }
 /**
  * Returns the edit effect rate.
  *
  * @return The effect rate.
  */
 public int getEditEffectRate() {
   return (Integer) cardPane.getStyles().get("selectionChangeRate");
 }
 /**
  * Sets the edit effect duration.
  *
  * @param effectDuration The effect duration in milliseconds.
  */
 public void setEditEffectDuration(int effectDuration) {
   cardPane.getStyles().put("selectionChangeDuration", effectDuration);
 }
 /**
  * Returns the edit effect duration.
  *
  * @return The effect duration in milliseconds.
  */
 public int getEditEffectDuration() {
   return (Integer) cardPane.getStyles().get("selectionChangeDuration");
 }
 /**
  * Sets the effect that is applied when the editor opens or closes.
  *
  * @param editEffect The edit effect, or <tt>null</tt> for no effect.
  */
 public void setEditEffect(CardPaneSkin.SelectionChangeEffect editEffect) {
   cardPane.getStyles().put("selectionChangeEffect", editEffect);
 }
 /**
  * Returns the effect that is applied when the editor opens or closes.
  *
  * @return The edit effect, or <tt>null</tt> for no effect.
  */
 public CardPaneSkin.SelectionChangeEffect getEditEffect() {
   return (CardPaneSkin.SelectionChangeEffect) cardPane.getStyles().get("selectionChangeEffect");
 }
  @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);
  }