/**
   * Overridden to message super and forward the method to the tree. Since the tree is not actually
   * in the component hierarchy it will never receive this unless we forward it in this manner.
   */
  public void updateUI() {
    super.updateUI();

    if (tree != null) tree.updateUI();

    // Use the tree's default foreground and background colors in the
    // table.
    LookAndFeel.installColorsAndFont(this, "Tree.background", "Tree.foreground", "Tree.font");
  }
  /**
   * Creates a new JTreeTable object.
   *
   * @param treeTableModel The tree table model.
   */
  public JTreeTable(final TreeTableModel treeTableModel) {
    super();

    // Create the tree. It will be used as a renderer and editor.
    tree = new TreeTableCellRenderer(treeTableModel);

    // Install a tableModel representing the visible rows in the tree.
    super.setModel(new TreeTableModelAdapter(treeTableModel, tree));

    // Force the JTable and JTree to share their row selection models.
    ListToTreeSelectionModelWrapper selectionWrapper = new ListToTreeSelectionModelWrapper();
    tree.setSelectionModel(selectionWrapper);
    setSelectionModel(selectionWrapper.getListSelectionModel());

    // Install the tree editor renderer and editor.
    setDefaultRenderer(TreeTableModel.class, tree);
    setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());

    // No grid.
    setShowGrid(false);

    // No intercell spacing
    setIntercellSpacing(new Dimension(0, 0));

    // And update the height of the trees row to match that of
    // the table.
    if (tree.getRowHeight() < 1) {
      // Metal looks better like this.
      setRowHeight(18);
    }
  }
  /**
   * Overridden to pass the new rowHeight to the tree.
   *
   * @param rowHeight the new height of the row
   */
  public void setRowHeight(int rowHeight) {
    super.setRowHeight(rowHeight);

    if ((tree != null) && (tree.getRowHeight() != rowHeight)) {
      tree.setRowHeight(getRowHeight());
    }
  }