Package com.extjs.gxt.ui.client.binder

Source Code of com.extjs.gxt.ui.client.binder.TreeBinder

/*
* Ext GWT 2.2.4 - Ext for GWT
* Copyright(c) 2007-2010, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/
package com.extjs.gxt.ui.client.binder;

import java.util.ArrayList;
import java.util.List;

import com.extjs.gxt.ui.client.data.ModelComparer;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.TreeLoader;
import com.extjs.gxt.ui.client.event.CheckChangedEvent;
import com.extjs.gxt.ui.client.event.CheckChangedListener;
import com.extjs.gxt.ui.client.event.CheckProvider;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.TreeEvent;
import com.extjs.gxt.ui.client.store.StoreEvent;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.store.TreeStoreEvent;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.DataListItem;
import com.extjs.gxt.ui.client.widget.tree.Tree;
import com.extjs.gxt.ui.client.widget.tree.TreeItem;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel;

/**
* A <code>StoreBinder</code> implementation for Trees.
*
* @param <M> the model type
*
* @deprecated see {@link TreePanel}
*/
public class TreeBinder<M extends ModelData> extends StoreBinder<TreeStore<M>, Tree, M> implements
    CheckProvider<M> {

  protected Tree tree;
  protected TreeStore<M> store;
  protected TreeLoader<M> loader;
  protected String displayProperty;
  protected boolean autoLoad;

  private List<CheckChangedListener<M>> checkListeners;
  private boolean silent;
  private boolean caching = true;
  private boolean expandOnFilter = true;

  /**
   * Creates a new store binder.
   *
   * @param tree the tree
   * @param store the tree store
   */
  public TreeBinder(final Tree tree, TreeStore<M> store) {
    super(store, tree);
    this.tree = tree;
    this.store = store;
    this.loader = store.getLoader();
  }

  public void addCheckListener(CheckChangedListener<M> listener) {
    if (checkListeners == null) {
      checkListeners = new ArrayList<CheckChangedListener<M>>();
    }
    if (!checkListeners.contains(listener)) {
      checkListeners.add(listener);
    }
  }

  @Override
  public Component findItem(M model) {
    ModelComparer<M> comparer = store.getModelComparer();
    for (TreeItem item : tree.getAllItems()) {
      if (comparer.equals(item.<M>getModel(), model)) {
        return item;
      }
    }
    return null;
  }

  public List<M> getCheckedSelection() {
    List<M> selection = new ArrayList<M>();
    for (TreeItem item : tree.getChecked()) {
      selection.add(item.<M>getModel());
    }
    return selection;
  }

  /**
   * Returns the display property.
   *
   * @return the display property
   */
  public String getDisplayProperty() {
    return displayProperty;
  }

  /**
   * Returns the binder's tree.
   *
   * @return the tree
   */
  public Tree getTree() {
    return tree;
  }

  /**
   * Returns the binder's tree store.
   *
   * @return the tree store
   */
  public TreeStore<M> getTreeStore() {
    return store;
  }

  /**
   * Returns true if auto load is enabled.
   *
   * @return the auto load state
   */
  public boolean isAutoLoad() {
    return autoLoad;
  }

  /**
   * Returns <code>true</code> if the binder is caching.
   *
   * @return the caching state
   */
  public boolean isCaching() {
    return caching;
  }

  public boolean isChecked(M model) {
    DataListItem item = (DataListItem) findItem(model);
    if (item != null) {
      return item.isChecked();
    }
    return false;
  }

  /**
   * Returns the if expand all and collapse all is enabled on filter changes.
   *
   * @return the expand all collapse all state
   */
  public boolean isExpandOnFilter() {
    return expandOnFilter;
  }

  public void removeCheckListener(CheckChangedListener<M> listener) {
    if (checkListeners != null) {
      checkListeners.remove(checkListeners);
    }
  }

  /**
   * Sets whether all children should automatically be loaded. Useful when using
   * filters.
   *
   * @param autoLoad true to auto load
   */
  public void setAutoLoad(boolean autoLoad) {
    this.autoLoad = autoLoad;
  }

  /**
   * Sets whether the children should be cached after first being retrieved from
   * the store (defaults to true). When <code>false</code>, the tree items will
   * be removed when collapsed.
   *
   * @param caching the caching state
   */
  public void setCaching(boolean caching) {
    this.caching = caching;
  }

  public void setCheckedSelection(List<M> selection) {
    silent = true;
    for (TreeItem item : tree.getChecked()) {
      if (item.isChecked()) {
        item.setChecked(false);
      }
    }

    for (M m : selection) {
      TreeItem item = (TreeItem) findItem(m);
      if (item != null) {
        item.setChecked(true);
      }
    }
    silent = false;
    fireCheckChanged(getCheckedSelection());
  }

  /**
   * Sets the display property name used to the item's text.
   *
   * @param displayProperty the property
   */
  public void setDisplayProperty(String displayProperty) {
    this.displayProperty = displayProperty;
  }

  /**
   * Sets whether the tree should expand all and collapse all when filters are
   * applied (defaults to true).
   *
   * @param expandOnFilter true to expand and collapse on filter changes
   */
  public void setExpandOnFilter(boolean expandOnFilter) {
    this.expandOnFilter = expandOnFilter;
  }

  protected void createAll() {
    TreeItem root = tree.getRootItem();
    root.removeAll();

    List<M> list = store.getRootItems();

    for (M element : list) {
      TreeItem item = null;
      if (store.isFiltered()) {
        if (isOrDecendantSelected(null, element)) {
          item = createItem(element);
        }
      } else {
        item = createItem(element);
      }
      tree.getRootItem().add(item);

      if (autoLoad && item != null) {
        item.setData("force", true);
        loadChildren(item, false);
      }
    }

    if (isAutoSelect() && list.size() > 0) {
      setSelection(list.get(0));
    }

  }

  protected TreeItem createItem(M model) {
    TreeItem item = new TreeItem();

    update(item, model);

    if (loader != null) {
      item.setLeaf(!loader.hasChildren(model));
    } else {
      item.setLeaf(!hasChildren(model));
    }

    setModel(item, model);
    return item;
  }

  protected void fireCheckChanged(List<M> selection) {
    if (checkListeners != null) {
      CheckChangedEvent<M> evt = new CheckChangedEvent<M>(this, selection);
      for (CheckChangedListener<M> listener : checkListeners) {
        listener.checkChanged(evt);
      }
    }
  }

  @Override
  protected List<M> getSelectionFromComponent() {
    List<TreeItem> selItems = tree.getSelectedItems();
    List<M> selected = new ArrayList<M>();
    for (TreeItem item : selItems) {
      selected.add(item.<M>getModel());
    }
    return selected;
  }

  protected boolean hasChildren(M parent) {
    return store.getChildCount(parent) != 0;
  }

  @Override
  protected void hook() {
    super.hook();
    component.setData("binder", true);
    component.addListener(Events.CheckChange, new Listener<TreeEvent>() {
      public void handleEvent(TreeEvent be) {
        if (!silent) {
          fireCheckChanged(getCheckedSelection());
        }
      }
    });
    Listener<TreeEvent> l = new Listener<TreeEvent>() {
      public void handleEvent(TreeEvent te) {
        EventType type = te.getType();
        if (type == Events.BeforeExpand) {
          onBeforeExpand(te);
        } else if (type == Events.Collapse) {
          onCollapse(te);
        }
      }
    };
    component.addListener(Events.BeforeExpand, l);
    component.addListener(Events.Collapse, l);
  }

  protected void loadChildren(final TreeItem item, boolean expand) {
    if (loader == null) {
      M model = item.<M>getModel();
      List<M> children = store.getChildren(model);
      renderChildren(model, children);
      return;
    }
    // if there is an async call out for my children already, Make
    // sure not to make another call and load the same items twice
    if (!item.isEnabled()) {
      return;
    }
    item.disable();

    if (item.isRendered() && !item.isRoot()) {
      item.getUI().onLoadingChange(true);
    }

    if (expand) {
      item.setData("expand", expand);
    }

    loader.loadChildren(item.<M>getModel());
  }

  @Override
  protected void onAdd(StoreEvent<M> se) {
    TreeStoreEvent<M> tse = (TreeStoreEvent<M>) se;
    M parent = tse.getParent();
    TreeItem item = null;
    if (parent == null) {
      item = tree.getRootItem();
    } else {
      item = (TreeItem) findItem(parent);
    }

    if (item == null) {
      return;
    }

    if (item.isRendered() && !item.isRoot()) {
      item.updateJointStyle();
      item.updateIconStyle();
    }

    if (item.isRoot() || item.getData("loaded") != null) {
      List<M> children = tse.getChildren();
      if (children.size() > 0) {
        item.setLeaf(false);
      }
      for (int i = children.size() - 1; i >= 0; i--) {
        item.add(createItem(children.get(i)), tse.getIndex());
      }
    } else if (item.getData("loaded") == null) {
      if (hasChildren(item.<M>getModel())) {
        item.setLeaf(false);
        if (item.isRendered()) {
          item.updateJointStyle();
        }
      }
    }
  }
 
  protected void onBeforeExpand(TreeEvent te) {
    TreeItem item = te.getItem();
    if (item.getData("loaded") == null) {
      item.setData("expand", true);
      te.setCancelled(true);
      loadChildren(item, true);
    }
  }

  protected void onCollapse(TreeEvent te) {
    if (!caching) {
      TreeItem item = te.getItem();
      store.removeAll(item.<M>getModel());
      item.setData("loaded", null);
      item.setLeaf(false);
      item.setChildrenRendered(true);
    }
  }

  @Override
  protected void onDataChanged(StoreEvent<M> se) {
    super.onDataChanged(se);
    TreeStoreEvent<M> te = (TreeStoreEvent<M>) se;
    if (te.getParent() == null) {
      createAll();
    } else {
      onRenderChildren(te);
    }
  }

  @Override
  protected void onFilter(StoreEvent<M> se) {
    filterItems(tree.getRootItem());
    boolean animated = tree.getAnimate();
    tree.setAnimate(false);
    if (store.isFiltered() && expandOnFilter) {
      tree.expandAll();
    } else if (!store.isFiltered() && expandOnFilter) {
      tree.collapseAll();
    }
    tree.setAnimate(animated);
  }

  @Override
  protected void onRemove(StoreEvent<M> se) {
    TreeStoreEvent<M> tse = (TreeStoreEvent<M>) se;
    TreeItem p = (TreeItem) findItem(tse.getParent());
    if (p == null) p = tree.getRootItem();
    p.remove((TreeItem) findItem(tse.getChild()));
  }

  protected void onRenderChildren(TreeStoreEvent<M> te) {
    renderChildren(te.getParent(), te.getChildren());
  }

  @Override
  protected void onSort(StoreEvent<M> se) {

  }

  @Override
  protected void onUpdate(StoreEvent<M> se) {
    update(se.getModel());
  }

  @Override
  protected void removeAll() {
    tree.removeAll();
  }

  protected void renderChildren(M parent, List<M> children) {
    TreeItem p = (TreeItem) findItem(parent);
    p.setData("loaded", true);
    p.enable();

    boolean leaf = p.isLeaf();
    p.removeAll();
    p.setLeaf(leaf);

    if (p.isRendered()) {
      p.getUI().onLoadingChange(false);
    }

    boolean f = p.getData("force") != null;
    p.setData("force", null);

    for (M child : children) {
      TreeItem item = createItem(child);
      p.add(item);
      if (f) {
        item.setData("force", true);
        loadChildren(item, false);
      }
    }

    if (!f && p.hasChildren() && p.getData("expand") != null) {
      p.setExpanded(true);
    } else if (p.isLeaf()) {
      p.setLeaf(true);
    }

    if (p.isRendered()) {
      p.updateJointStyle();
    }
    fireEvent(Events.Refresh);
  }

  @Override
  protected void setSelectionFromProvider(List<M> selection) {
    List<TreeItem> selected = new ArrayList<TreeItem>();
    for (M model : selection) {
      selected.add((TreeItem) findItem(model));
    }
    tree.setSelectedItems(selected);
  }

  @Override
  protected void update(M model) {
    update((TreeItem) findItem(model), model);
  }

  protected void update(TreeItem item, M model) {
    if (item != null) {
      setModel(item, model);
      String txt = getTextValue(model, displayProperty);
      if (txt == null && displayProperty != null) {
        txt = model.get(displayProperty);
      } else if (txt == null) {
        txt = model.toString();
      }

      String icon = getIconValue(model, displayProperty);
      String style = (styleProvider == null) ? null : styleProvider.getStringValue(model,
          displayProperty);

      item.setTextStyle(style);
      item.setText(txt);
      item.setIconStyle(icon);
    }

  }

  private void filterItems(TreeItem item) {
    if (item.isRoot() || isOrDecendantSelected(null, item.<M>getModel())) {
      item.setVisible(true);
      int count = item.getItemCount();
      for (int i = 0; i < count; i++) {
        filterItems(item.getItem(i));
      }
    } else {
      item.setVisible(false);
    }
  }

  private boolean isOrDecendantSelected(M parent, M model) {
    if (!isFiltered(parent, model)) {
      return true;
    }
    TreeItem item = (TreeItem) findItem(model);
    if (item != null) {
      for (TreeItem child : item.getItems()) {
        boolean result = isOrDecendantSelected(model, child.<M>getModel());
        if (result) {
          return true;
        }
      }
    }
    return false;
  }

}
TOP

Related Classes of com.extjs.gxt.ui.client.binder.TreeBinder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.