// 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();
  }
  // 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);
  }
  /**
   * Saves all outliner documents that are currently modified and are not imported. We don't want to
   * save imported docs since they won't have a valid current save format, i.e. they're imported.
   */
  protected static void saveAllOutlinerDocuments() {
    for (int i = 0; i < Outliner.documents.openDocumentCount(); i++) {
      OutlinerDocument doc = (OutlinerDocument) Outliner.documents.getDocument(i);

      if (doc.isModified()
          && !PropertyContainerUtil.getPropertyAsBoolean(
              doc.getDocumentInfo(), DocumentInfo.KEY_IMPORTED)) {
        SaveFileMenuItem.saveOutlinerDocument(doc);
      }
    }
  }
  // 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();
  }