// 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);
}
}