// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.collide.client.ui.tree; import com.google.collide.client.ui.tree.TreeNodeMutator.Css; import elemental.html.Element; /** * Utility for mutating the String name for the model object backing a * {@link TreeNodeElement}, in place in a {@link Tree}. * * In other words, this is a utility class that facilitates renaming of * {@link TreeNodeElement}s. */ public class TreeNodeLabelRenamer<D> { /** * Callback that gets invoked right after the model has been changed. */ public interface LabelRenamerCallback<D> { void onCommit(String oldLabel, TreeNodeElement<D> node); boolean passValidation(TreeNodeElement<D> node, String newLabel); } private final NodeDataAdapter<D> dataAdapter; /** * The {@link NodeRenderer} that we use to re-render the label portions of the * {@link TreeNodeElement}. */ private final NodeRenderer<D> renderer; private LabelRenamerCallback<D> callback; private final TreeNodeMutator<D> treeNodeMutator; private final TreeNodeMutator.MutationAction<D> mutationAction = new TreeNodeMutator.MutationAction<D>() { @Override public Element getElementForMutation(TreeNodeElement<D> node) { return renderer.getNodeKeyTextContainer(node.getNodeLabel()); } @Override public void onBeforeMutation(TreeNodeElement<D> node) { // Nothing to do. } @Override public void onMutationCommit(TreeNodeElement<D> node, String oldLabel, String newLabel) { if (callback != null) { mutateNodeKey(node, newLabel); callback.onCommit(oldLabel, node); callback = null; } } @Override public boolean passValidation(TreeNodeElement<D> node, String newLabel) { return callback == null || callback.passValidation(node, newLabel); } }; public TreeNodeLabelRenamer( NodeRenderer<D> renderer, NodeDataAdapter<D> dataAdapter, Css treeMutatorCss) { this.renderer = renderer; this.dataAdapter = dataAdapter; this.treeNodeMutator = new TreeNodeMutator<D>(treeMutatorCss); } public boolean isMutating() { return treeNodeMutator.isMutating(); } /** * Replaces the nodes text label with an input box to allow the user to * rename the node. */ public void enterMutation(TreeNodeElement<D> node, LabelRenamerCallback<D> callback) { // If we are already mutating, return. if (isMutating()) { return; } this.callback = callback; treeNodeMutator.enterMutation(node, mutationAction); } public void cancel() { treeNodeMutator.cancel(); } public NodeDataAdapter<D> getDataAdapter() { return dataAdapter; } public NodeRenderer<D> getRenderer() { return renderer; } public TreeNodeMutator<D> getTreeNodeMutator() { return treeNodeMutator; } /** * Commits the current text if it passes validation, or cancels the mutation. */ public void forceCommit() { treeNodeMutator.forceCommit(); } /** * Updates the name value for the model object for a node, and then replaces * the label's contents with the new value. */ public void mutateNodeKey(TreeNodeElement<D> node, String newName) { getDataAdapter().setNodeName(node.getData(), newName); Element elem = getRenderer().getNodeKeyTextContainer(node.getNodeLabel()); elem.setTextContent(newName); } }