com.extjs.gxt.ui.client.widget.treegrid.TreeGridView.java Source code

Java tutorial

Introduction

Here is the source code for com.extjs.gxt.ui.client.widget.treegrid.TreeGridView.java

Source

/*
 * Sencha GXT 2.3.1 - Sencha for GWT
 * Copyright(c) 2007-2013, Sencha, Inc.
 * licensing@sencha.com
 * 
 * http://www.sencha.com/products/gxt/license/
 */
package com.extjs.gxt.ui.client.widget.treegrid;

import java.util.Date;
import java.util.List;

import com.extjs.gxt.ui.client.GXT;
import com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.core.DomQuery;
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.core.XDOM;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.SortInfo;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.util.IconHelper;
import com.extjs.gxt.ui.client.util.SafeGxt;
import com.extjs.gxt.ui.client.util.Util;
import com.extjs.gxt.ui.client.widget.grid.BufferView;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid.TreeNode;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.Joint;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Widget;

@SuppressWarnings({ "unchecked", "rawtypes" })
public class TreeGridView extends BufferView {

    protected TreeGrid tree;
    protected TreeStore treeStore;

    private int treeColumn = -1;

    public TreeGridView() {
        setRowSelectorDepth(20);
        setCellSelectorDepth(10);
    }

    public void collapse(TreeNode node) {
        ModelData p = node.m;
        ModelData lc = treeStore.getLastChild(p);

        int start = ds.indexOf(p);
        int end = tree.findLastOpenChildIndex(lc);

        if (GXT.isAriaEnabled()) {
            getRow(start).setAttribute("aria-expanded", "false");
        }

        for (int i = end; i > start; i--) {
            ds.remove(i);
        }
        tree.refresh(node.m);
    }

    public void expand(TreeNode node) {
        ModelData p = node.m;
        List<ModelData> children = treeStore.getChildren(p);
        int idx = ds.indexOf(p);

        ds.insert(children, idx + 1);

        if (GXT.isAriaEnabled()) {
            getRow(idx).setAttribute("aria-expanded", "true");
        }

        for (ModelData child : children) {
            TreeNode cn = findNode(child);
            if (cn.isExpanded()) {
                expand(cn);
            }
        }
        tree.refresh(node.m);
    }

    public Element getIconElement(TreeNode node) {
        if (node.icon == null) {
            Element row = getRowElement(node);
            if (row != null) {
                node.icon = DomQuery.selectNode(".x-tree3-node-icon", row);
            }
        }
        return node.icon;
    }

    public Element getJointElement(TreeNode node) {
        if (node.joint == null) {
            Element row = getRowElement(node);
            if (row != null) {
                node.joint = DomQuery.selectNode(".x-tree3-node-joint", row);
            }
        }
        return node.joint;
    }

    public SafeHtml getTemplate(ModelData m, String id, SafeHtml text, AbstractImagePrototype icon,
            boolean checkable, Joint joint, int level) {

        StringBuilder sb = new StringBuilder();
        sb.append("<div role=\"presentation\" unselectable=\"on\" id=\"");
        sb.append(id);
        sb.append("\" class=\"x-tree3-node\">");

        String cls = "x-tree3-el";
        if (GXT.isHighContrastMode) {
            switch (joint) {
            case COLLAPSED:
                cls += " x-tree3-node-joint-collapse";
                break;
            case EXPANDED:
                cls += " x-tree3-node-joint-expand";
                break;
            }
        }

        sb.append("<div role=\"presentation\" unselectable=\"on\" class=\"" + cls + "\">");

        Element jointElement = null;
        switch (joint) {
        case COLLAPSED:
            jointElement = (Element) tree.getStyle().getJointCollapsedIcon().createElement().cast();
            break;
        case EXPANDED:
            jointElement = (Element) tree.getStyle().getJointExpandedIcon().createElement().cast();
            break;
        }
        if (jointElement != null) {
            El.fly(jointElement).addStyleName("x-tree3-node-joint");
        }

        sb.append("<img src=\"");
        sb.append(GXT.BLANK_IMAGE_URL);
        sb.append("\" style=\"height:18px;width:");
        sb.append(level * getIndenting(findNode(m)));
        sb.append("px;\" />");
        sb.append(jointElement == null
                ? "<img src=\"" + GXT.BLANK_IMAGE_URL + "\" style=\"width: 16px\" class=\"x-tree3-node-joint\" />"
                : DOM.toString(jointElement));
        if (checkable) {
            Element e = (Element) GXT.IMAGES.unchecked().createElement().cast();
            El.fly(e).addStyleName("x-tree3-node-check");
            sb.append(DOM.toString(e));
        } else {
            sb.append("<span class=\"x-tree3-node-check\"></span>");
        }
        if (icon != null) {
            Element e = icon.createElement().cast();
            El.fly(e).addStyleName("x-tree3-node-icon");
            sb.append(DOM.toString(e));
        } else {
            sb.append("<span class=\"x-tree3-node-icon\"></span>");
        }
        sb.append("<span unselectable=\"on\" class=\"x-tree3-node-text\">");
        sb.append(text.asString());
        sb.append("</span>");

        sb.append("</div>");
        sb.append("</div>");

        return SafeHtmlUtils.fromTrustedString(sb.toString());
    }

    public SafeHtml getWidgetTemplate(ModelData m, String id, SafeHtml text, AbstractImagePrototype icon,
            boolean checkable, Joint joint, int level) {

        StringBuffer sb = new StringBuffer();
        sb.append("<div unselectable=\"on\" id=\"");
        sb.append(id);
        sb.append("\" class=\"x-tree3-node\">");
        // jumping content when inserting in column with cell widget the column
        // extra width fixes
        sb.append(
                "<div role=\"presentation\" unselectable=\"on\" class=\"x-tree3-el\" style=\"width: 1000px;height: auto;\">");

        sb.append(
                "<table cellpadding=0 cellspacing=0 role=presentation><tr role=presentation><td role=presentation>");

        Element jointElement = null;
        switch (joint) {
        case COLLAPSED:
            jointElement = (Element) tree.getStyle().getJointCollapsedIcon().createElement().cast();
            break;
        case EXPANDED:
            jointElement = (Element) tree.getStyle().getJointExpandedIcon().createElement().cast();
            break;
        }
        if (jointElement != null) {
            El.fly(jointElement).addStyleName("x-tree3-node-joint");
        }

        sb.append("</td><td><img src=\"");
        sb.append(GXT.BLANK_IMAGE_URL);
        sb.append("\" style=\"height:18px;width:");
        sb.append(level * getIndenting(findNode(m)));
        sb.append("px;\" /></td><td  class='x-tree3-el-jnt'>");

        sb.append(jointElement == null
                ? "<img src=\"" + GXT.BLANK_IMAGE_URL + "\" style=\"width: 16px\" class=\"x-tree3-node-joint\" />"
                : DOM.toString(jointElement));

        if (checkable) {
            Element e = (Element) GXT.IMAGES.unchecked().createElement().cast();
            El.fly(e).addStyleName("x-tree3-node-check");
            sb.append(DOM.toString(e));
        } else {
            sb.append("<span class=\"x-tree3-node-check\"></span>");
        }

        sb.append("</td><td>");

        if (icon != null) {
            Element e = icon.createElement().cast();
            El.fly(e).addStyleName("x-tree3-node-icon");
            sb.append(DOM.toString(e));
        } else {
            sb.append("<span class=\"x-tree3-node-icon\"></span>");
        }

        sb.append("</td><td>");
        sb.append("<span unselectable=\"on\" class=\"x-tree3-node-text\">");
        sb.append(text.asString());
        sb.append("</span>");
        sb.append("</td></tr></table>");

        sb.append("</div>");
        sb.append("</div>");

        return SafeHtmlUtils.fromTrustedString(sb.toString());
    }

    public boolean isSelectableTarget(ModelData model, Element target) {
        TreeNode node = findNode(model);
        if (node != null) {

            Element j = getJointElement(node);
            if (j != null && DOM.isOrHasChild(j, target)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public void refresh(boolean headerToo) {
        if (grid != null && grid.isViewReady()) {
            for (Object node : tree.nodes.values()) {
                if (node instanceof TreeNode) {
                    ((TreeNode) node).clearElements();
                }
            }
        }
        super.refresh(headerToo);
    }

    public void onIconStyleChange(TreeNode node, AbstractImagePrototype icon) {
        Element iconEl = getIconElement(node);
        if (iconEl != null) {
            Element e;
            if (icon != null) {
                e = (Element) icon.createElement().cast();
            } else {
                e = DOM.createSpan();
            }
            El.fly(e).addStyleName("x-tree3-node-icon");
            node.icon = (Element) iconEl.getParentElement().insertBefore(e, iconEl);
            El.fly(iconEl).remove();
        }
    }

    public void onJointChange(TreeNode node, Joint joint) {
        Element jointEl = getJointElement(node);
        if (jointEl != null) {
            switch (joint) {
            case EXPANDED:
                node.joint = (Element) jointEl.getParentElement()
                        .insertBefore(tree.getStyle().getJointExpandedIcon().createElement(), jointEl);
                if (GXT.isHighContrastMode) {
                    El.fly(jointEl.getParentElement()).addStyleName("x-tree3-node-joint-expand")
                            .removeStyleName("x-tree3-node-joint-collapse");
                }
                break;
            case COLLAPSED:
                node.joint = (Element) jointEl.getParentElement()
                        .insertBefore(tree.getStyle().getJointCollapsedIcon().createElement(), jointEl);
                if (GXT.isHighContrastMode) {
                    El.fly(jointEl.getParentElement()).addStyleName("x-tree3-node-joint-collapse")
                            .removeStyleName("x-tree3-node-joint-expand");
                }
                break;
            default:
                node.joint = (Element) jointEl.getParentElement().insertBefore(
                        XDOM.create("<img src=\"" + GXT.BLANK_IMAGE_URL + "\" style='width: 16px'>"), jointEl);
                if (GXT.isHighContrastMode) {
                    El.fly(jointEl.getParentElement()).removeStyleName("x-tree3-node-joint-collapse")
                            .removeStyleName("x-tree3-node-joint-expand");
                }
            }
            El.fly(node.joint).addStyleName("x-tree3-node-joint");
            El.fly(jointEl).remove();
        }
    }

    public void onLoading(TreeNode node) {
        onIconStyleChange(node, IconHelper.createStyle("x-tree3-loading"));
    }

    @Override
    protected void cleanModel(ModelData at) {
        TreeNode node = findNode(at);
        if (node != null) {
            node.clearElements();
        }
    }

    @Override
    protected void doSort(int colIndex, SortDir sortDir) {
        treeStore.sort(cm.getDataIndex(colIndex), sortDir);
    }

    protected TreeNode findNode(ModelData m) {
        return tree.findNode(m);
    }

    protected int getIndenting(TreeNode node) {
        return 18;
    }

    @Override
    protected SafeHtml getRenderedValue(ColumnData data, int rowIndex, int colIndex, ModelData m, String property) {
        GridCellRenderer<ModelData> r = cm.getRenderer(colIndex);
        List<Widget> rowMap = widgetList.get(rowIndex);
        rowMap.add(colIndex, null);
        if (r != null) {
            return r.render(ds.getAt(rowIndex), property, data, rowIndex, colIndex, ds, grid);
        }
        Object val = m.get(property);

        ColumnConfig c = cm.getColumn(colIndex);

        if (val != null && c.getNumberFormat() != null) {
            Number n = (Number) val;
            NumberFormat nf = cm.getColumn(colIndex).getNumberFormat();
            return SafeHtmlUtils.fromString(nf.format(n.doubleValue()));

        } else if (val != null && c.getDateTimeFormat() != null) {
            DateTimeFormat dtf = c.getDateTimeFormat();
            return SafeHtmlUtils.fromString(dtf.format((Date) val));
        }

        String text = null;
        if (val != null) {
            text = val.toString();
        }
        return SafeGxt.emptyToNbSpace(text);
    }

    protected Element getRowElement(TreeNode node) {
        return (Element) getRow(ds.indexOf(node.m));
    }

    @Override
    protected SortInfo getSortState() {
        return treeStore.getSortState();
    }

    protected Element getWidgetCell(int row, int col) {
        if (col == treeColumn) {
            Element cell = (Element) getCell(row, col);
            if (cell != null) {
                cell = El.fly(cell).selectNode(".x-tree3-node-text").dom;
                cell.setClassName("x-tree3-node-text x-tree3-node-text-widget");
                cell.getParentElement().getStyle().setProperty("padding", "2px 0px 2px 4px");
                return cell;
            }
        }
        return super.getWidgetCell(row, col).cast();
    }

    @Override
    protected void init(Grid grid) {
        super.init(grid);
        tree = (TreeGrid) grid;
        treeStore = tree.getTreeStore();
        selectable = !grid.isDisableTextSelection();
    }

    @Override
    protected void initData(ListStore ds, ColumnModel cm) {
        super.initData(ds, cm);
        treeColumn = -1;
        List<ColumnConfig> l = cm.getColumns();
        for (int i = 0; i < l.size(); i++) {
            ColumnConfig c = l.get(i);
            GridCellRenderer r = c.getRenderer();
            if (r != null && r instanceof TreeGridCellRenderer) {
                assert treeColumn == -1 : "You may only specify one TreeGridCellRenderer";
                treeColumn = i;
            }
        }
        assert treeColumn != -1 : "No TreeGridCellRenderer specified";
    }

    @Override
    protected void insertRows(ListStore<ModelData> store, int firstRow, int lastRow, boolean isUpdate) {
        super.insertRows(store, firstRow, lastRow, isUpdate);
        if (GXT.isAriaEnabled()) {
            for (int i = firstRow; i <= lastRow; i++) {
                ModelData m = store.getAt(i);
                getRow(i).setAttribute("aria-level", "" + treeStore.getDepth(m));
            }
        }
    }

    @Override
    protected void onClick(GridEvent<ModelData> ce) {
        if (ce.getModel() != null && !isSelectableTarget(ce.getModel(), ce.getTarget())) {
            return;
        }
        super.onClick(ce);
    }

    @Override
    protected void onRemove(ListStore<ModelData> ds, ModelData m, int index, boolean isUpdate) {
        super.onRemove(ds, m, index, isUpdate);
        TreeNode node = findNode(m);
        if (node != null) {
            node.clearElements();
        }
    }

    @Override
    protected void onRowSelect(int rowIndex) {
        super.onRowSelect(rowIndex);
        tree.setExpanded(treeStore.getParent(tree.getStore().getAt(rowIndex)), true);
    }

}