// Data Modification
  @Override
  public void newAttribute(
      String key, Object value, boolean isReadOnly, AttributeTableModel model) {
    AttributeContainer node = view.tree;

    if (node == null) {
      return;
    }

    model.keys.add(key);
    model.values.add(value);
    model.readOnly.add(new Boolean(isReadOnly));

    node.setAttribute(key, value);

    OutlinerDocument doc = view.tree.getDocument();
    doc.setModified(true);

    // undo
    Undoable undoable =
        new UndoableDocumentAttributeChange(view.tree, null, null, false, key, value, isReadOnly);
    undoable.setName("New Document Attribute");
    doc.getUndoQueue().add(undoable);

    model.fireTableDataChanged();
  }
  // Data Display
  public void update(DocumentAttributesView view) {
    this.view = view;

    AttributeContainer node = view.tree;

    model.keys.clear();
    model.values.clear();
    model.readOnly.clear();
    clearSelection();

    if (node != null) {
      Iterator it = node.getAttributeKeys();
      if (it != null) {
        while (it.hasNext()) {
          String key = (String) it.next();
          Object value = node.getAttribute(key);
          boolean readOnly = node.isReadOnly(key);
          model.keys.add(key);
          model.values.add(value);
          model.readOnly.add(new Boolean(readOnly));
        }
      }
    }

    if (isEditing()) {
      getCellEditor().cancelCellEditing();
    }

    model.fireTableDataChanged();
  }
  // Set Value
  @Override
  public void setValueAt(Object value, int row, AttributeTableModel model) {
    AttributeContainer node = view.tree;

    if (node == null) {
      return;
    }

    String key = (String) model.keys.get(row);

    boolean readOnly = node.isReadOnly(key);

    Object oldValue = node.getAttribute(key);

    model.values.set(row, value);
    node.setAttribute(key, value);

    OutlinerDocument doc = view.tree.getDocument();
    doc.setModified(true);

    // undo
    Undoable undoable =
        new UndoableDocumentAttributeChange(
            view.tree, key, oldValue, readOnly, key, value, readOnly);
    undoable.setName("Edit Document Attribute");
    doc.getUndoQueue().add(undoable);

    model.fireTableDataChanged();
  }
  // Delete Attribute
  @Override
  public void deleteAttribute(int row, AttributeTableModel model) {
    AttributeContainer node = view.tree;

    if (node == null) {
      return;
    }

    String key = (String) model.keys.get(row);

    Object oldValue = node.getAttribute(key);
    boolean oldReadOnly = node.isReadOnly(key);

    node.removeAttribute(key);
    model.keys.remove(row);
    model.values.remove(row);
    model.readOnly.remove(row);

    OutlinerDocument doc = view.tree.getDocument();
    doc.setModified(true);

    // undo
    Undoable undoable =
        new UndoableDocumentAttributeChange(
            view.tree, key, oldValue, oldReadOnly, null, null, false);
    undoable.setName("Delete Document Attribute");
    doc.getUndoQueue().add(undoable);

    model.fireTableRowsDeleted(row, row);
  }
  @Override
  protected boolean isCellEditable(int row) {
    AttributeContainer node = view.tree;

    if (node == null) {
      return false;
    }

    String key = (String) model.keys.get(row);

    if (node.isReadOnly(key)) {
      return false;
    }

    return true;
  }
  // Toggle Editability
  @Override
  public void toggleEditability(int row, AttributeTableModel model) {
    AttributeContainer node = view.tree;

    if (node == null) {
      return;
    }

    String key = (String) model.keys.get(row);
    Object oldAndNewValue = node.getAttribute(key);

    boolean oldReadOnly = node.isReadOnly(key);
    boolean readOnly = !oldReadOnly;

    boolean oldValue = true;
    ImageIcon isReadOnly = (ImageIcon) model.getValueAt(row, 1);
    if (isReadOnly == OutlineEditableIndicator.ICON_IS_NOT_PROPERTY) {
      oldValue = true;
    } else {
      oldValue = false;
    }

    // boolean oldValue = ((Boolean) model.getValueAt(row, 1)).booleanValue();
    boolean newValue = !oldValue;
    model.readOnly.set(row, new Boolean(newValue));
    node.setReadOnly(key, newValue);

    OutlinerDocument doc = view.tree.getDocument();
    doc.setModified(true);

    // undo
    Undoable undoable =
        new UndoableDocumentAttributeChange(
            view.tree, key, oldAndNewValue, oldReadOnly, key, oldAndNewValue, readOnly);
    undoable.setName("Toggle Document Attribute Editability");
    doc.getUndoQueue().add(undoable);

    model.fireTableDataChanged();
  }