// 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.code;
import com.google.collide.client.common.BaseResources;
import com.google.collide.client.ui.tree.NodeRenderer;
import com.google.collide.client.ui.tree.Tree;
import com.google.collide.client.ui.tree.TreeNodeElement;
import com.google.collide.client.ui.tree.TreeNodeMutator;
import com.google.collide.client.util.CssUtils;
import com.google.collide.client.util.Elements;
import com.google.collide.client.workspace.FileTreeNode;
import com.google.collide.client.workspace.WorkspaceUtils;
import elemental.events.Event;
import elemental.events.EventListener;
import elemental.events.MouseEvent;
import elemental.html.AnchorElement;
import elemental.html.DivElement;
import elemental.html.Element;
import elemental.html.SpanElement;
/**
* Renderer for nodes in the file tree.
*/
public class FileTreeNodeRenderer implements NodeRenderer<FileTreeNode> {
public static FileTreeNodeRenderer create(Resources res) {
return new FileTreeNodeRenderer(res);
}
public interface Css extends TreeNodeMutator.Css {
String file();
String folder();
String folderOpen();
String folderLoading();
String icon();
String label();
String root();
@Override
String nodeNameInput();
}
public interface Resources extends BaseResources.Resources, Tree.Resources {
@Source({"FileTreeNodeRenderer.css", "com/google/collide/client/common/constants.css"})
Css workspaceNavigationFileTreeNodeRendererCss();
}
/**
* Renders the given information as a node.
*
* @param mouseDownListener an optional listener to be attached to the anchor. If not given, the
* label will not be an anchor.
*/
public static SpanElement renderNodeContents(
Css css, String name, boolean isFile, EventListener mouseDownListener, boolean renderIcon) {
SpanElement root = Elements.createSpanElement(css.root());
if (renderIcon) {
DivElement icon = Elements.createDivElement(css.icon());
icon.addClassName(isFile ? css.file() : css.folder());
root.appendChild(icon);
}
final Element label;
if (mouseDownListener != null) {
label = Elements.createAnchorElement(css.label());
((AnchorElement) label).setHref("javascript:;");
label.addEventListener(Event.MOUSEDOWN, mouseDownListener, false);
} else {
label = Elements.createSpanElement(css.label());
}
label.setTextContent(name);
root.appendChild(label);
return root;
}
private final EventListener mouseDownListener = new EventListener() {
@Override
public void handleEvent(Event evt) {
MouseEvent event = (MouseEvent) evt;
AnchorElement anchor = (AnchorElement) evt.getTarget();
if (event.getButton() == MouseEvent.Button.AUXILIARY) {
Element parent = CssUtils.getAncestorOrSelfWithClassName(anchor, res.treeCss().treeNode());
if (parent != null) {
@SuppressWarnings("unchecked")
TreeNodeElement<FileTreeNode> fileNode = (TreeNodeElement<FileTreeNode>) parent;
anchor.setHref(
WorkspaceUtils.createDeepLinkToFile(fileNode.getData().getNodePath()));
}
}
}
};
private final Css css;
private final Resources res;
private FileTreeNodeRenderer(Resources resources) {
this.res = resources;
this.css = res.workspaceNavigationFileTreeNodeRendererCss();
}
@Override
public Element getNodeKeyTextContainer(SpanElement treeNodeLabel) {
return (Element) treeNodeLabel.getChildNodes().item(1);
}
@Override
public SpanElement renderNodeContents(FileTreeNode data) {
return renderNodeContents(css, data.getName(), data.isFile(), mouseDownListener, true);
}
@Override
public void updateNodeContents(TreeNodeElement<FileTreeNode> treeNode) {
if (treeNode.getData().isDirectory()) {
// Update folder icon based on icon state.
Element icon = treeNode.getNodeLabel().getFirstChildElement();
icon.setClassName(css.icon());
if (treeNode.getData().isLoading()) {
icon.addClassName(css.folderLoading());
} else if (treeNode.isOpen()) {
icon.addClassName(css.folderOpen());
} else {
icon.addClassName(css.folder());
}
}
}
}