Package com.extjs.gxt.ui.client.dnd

Source Code of com.extjs.gxt.ui.client.dnd.TreeGridDropTarget

/*
* 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.dnd;

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

import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.TreeModel;
import com.extjs.gxt.ui.client.dnd.DND.Feedback;
import com.extjs.gxt.ui.client.event.DNDEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.TreeGridEvent;
import com.extjs.gxt.ui.client.util.Rectangle;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid.TreeNode;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Timer;

/**
* DropTarget implementation for TreeGrid.
* <p />
* Supported drag data:
* <ul>
* <li>A single ModelData instance.</li>
* <li>A List of ModelData instances.</li>
* <li>A List of TreeStoreModel instances (children are ignored).
* </ul>
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class TreeGridDropTarget extends DropTarget {

  protected TreeGrid<ModelData> treeGrid;
  protected TreeNode activeItem, appendItem;
  protected int status;

  private boolean allowDropOnLeaf = false;
  private boolean autoExpand = true, autoScroll = true;
  private int autoExpandDelay = 800;
  private boolean addChildren;
  private ScrollSupport scrollSupport;

  public TreeGridDropTarget(TreeGrid tree) {
    super(tree);
    this.treeGrid = tree;
    bind(tree);
  }

  /**
   * Returns the target's tree.
   *
   * @return the tree
   */
  public TreeGrid<?> getTreeGrid() {
    return treeGrid;
  }

  /**
   * Returns true if children are being added when inserting into the TreeStore.
   *
   * @return the add children state
   */
  public boolean isAddChildren() {
    return addChildren;
  }

  /**
   * Returns whether drops are allowed on leaf nodes.
   *
   * @return true of drops on leafs are allowed
   */
  public boolean isAllowDropOnLeaf() {
    return allowDropOnLeaf;
  }

  /**
   * Returns true if auto expand is enabled (defaults to true).
   *
   * @return the auto expand state
   */
  public boolean isAutoExpand() {
    return autoExpand;
  }

  /**
   * Returns true if auto scroll is enabled (defaults to true).
   *
   * @return true if auto scroll enabled
   */
  public boolean isAutoScroll() {
    return autoScroll;
  }

  /**
   * True to add children when inserting models into the TreeStore (defaults to
   * false).
   *
   * @param addChildren true to add children
   */
  public void setAddChildren(boolean addChildren) {
    this.addChildren = addChildren;
  }

  /**
   * True to allow drops on leaf nodes (defaults to false).
   *
   * @param allowDropOnLeaf true to enable drops on leaf nodes
   */
  public void setAllowDropOnLeaf(boolean allowDropOnLeaf) {
    this.allowDropOnLeaf = allowDropOnLeaf;
  }

  /**
   * True to automatically expand the active tree item when the user hovers over
   * a collapsed item (defaults to true). Use {@link #setAutoExpandDelay(int)}
   * to set the delay.
   *
   * @param autoExpand true to auto expand
   */
  public void setAutoExpand(boolean autoExpand) {
    this.autoExpand = autoExpand;
  }

  /**
   * Sets the delay used to auto expand items (defaults to 800).
   *
   * @param autoExpandDelay the delay in milliseconds
   */
  public void setAutoExpandDelay(int autoExpandDelay) {
    this.autoExpandDelay = autoExpandDelay;
  }

  /**
   * True to automatically scroll the tree when the user hovers over the top and
   * bottom of the tree grid (defaults to true).
   *
   * @see ScrollSupport
   *
   * @param autoScroll true to enable auto scroll
   */
  public void setAutoScroll(boolean autoScroll) {
    this.autoScroll = autoScroll;
  }

  protected void appendModel(ModelData p, List<ModelData> models, int index) {
    if (models.size() == 0) return;
    if (models.get(0) instanceof TreeModel) {
      TreeModel test = (TreeModel) models.get(0);
      // drop is in form from tree store
      if (test.getPropertyNames().contains("model")) {

        List<ModelData> children = new ArrayList<ModelData>();
        for (ModelData tm : models) {
          ModelData child = tm.get("model");
          children.add(child);
        }
        if (p == null) {
          treeGrid.getTreeStore().insert(children, index, false);
        } else {
          treeGrid.getTreeStore().insert(p, children, index, false);
        }
        for (ModelData tm : models) {
          ModelData child = tm.get("model");
          List sub = (List) ((TreeModel) tm).getChildren();
          appendModel(child, sub, 0);

        }
        return;
      }
    }
    if (p == null) {
      treeGrid.getTreeStore().insert(models, index, false);
    } else {
      treeGrid.getTreeStore().insert(p, models, index, false);
    }
  }

  protected void bind(TreeGrid tree) {
    tree.addListener(Events.Unregister, new Listener<TreeGridEvent>() {
      public void handleEvent(TreeGridEvent be) {
        if (activeItem == be.getTreeNode()) {
          activeItem = null;
        }
      }
    });
  }

  protected void clearStyle(TreeNode node) {
    El.fly(treeGrid.getView().getRow(node.getModel())).removeStyleName("x-ftree2-node-drop");
  }

  protected void handleAppend(DNDEvent event, final TreeNode item) {
    // clear any active append item
    if (activeItem != null && activeItem != item) {
      clearStyle(activeItem);
    }
    status = -1;

    Insert.get().hide();
    event.getStatus().setStatus(true);
    if (activeItem != null) {
      clearStyle(activeItem);
    }

    if (item != null && item != appendItem && autoExpand && !item.isExpanded()) {
      Timer t = new Timer() {
        @Override
        public void run() {
          if (item == appendItem) {
            item.setExpanded(true);
          }
        }
      };
      t.schedule(autoExpandDelay);
    }
    appendItem = item;
    activeItem = item;
    if (activeItem != null) {
      El.fly(treeGrid.getView().findRow(event.getTarget())).addStyleName("x-ftree2-node-drop");
    }
  }

  protected void handleAppendDrop(DNDEvent event, TreeNode item) {
    List<ModelData> models = prepareDropData(event.getData(), false);
    if (models.size() > 0) {
      ModelData p = null;
      if (item != null) {
        p = item.getModel();
        appendModel(p, models, treeGrid.getTreeStore().getChildCount(item.getModel()));
      } else {
        appendModel(p, models, 0);
      }

    }
  }

  protected void handleInsert(DNDEvent event, final TreeNode item) {
    int height = treeGrid.getView().getRow(item.getModel()).getOffsetHeight();
    int mid = height / 2;
    int top = treeGrid.getView().getRow(item.getModel()).getAbsoluteTop();
    mid += top;
    int y = event.getClientY();
    boolean before = y < mid;

    if ((!item.isLeaf() || allowDropOnLeaf) && (feedback == Feedback.BOTH || feedback == Feedback.APPEND)
        && ((before && y > top + 4) || (!before && y < top + height - 4))) {
      handleAppend(event, item);
      return;
    }

    // clear any active append item
    if (activeItem != null && activeItem != item) {
      clearStyle(activeItem);
    }

    appendItem = null;

    status = before ? 0 : 1;

    if (activeItem != null) {
      clearStyle(activeItem);
    }

    activeItem = item;

    if (activeItem != null) {
      int idx = 0;
      if (activeItem.getParent() != null) {
        idx = activeItem.getParent().indexOf(item);
      } else {
        idx = treeGrid.getTreeStore().indexOf(activeItem.getModel());
      }

      String status = "x-tree-drop-ok-between";
      if (before && idx == 0) {
        status = "x-tree-drop-ok-above";
      } else if (idx > 1 && !before && item.getParent() != null && idx == item.getParent().getItemCount() - 1) {
        status = "x-tree-drop-ok-below";
      }
      event.getStatus().setStatus(true, status);

      if (before) {
        showInsert(event, (Element) treeGrid.getView().getRow(item.getModel()), true);
      } else {
        showInsert(event, (Element) treeGrid.getView().getRow(item.getModel()), false);
      }
    }
  }

  protected void handleInsertDrop(DNDEvent event, TreeNode item, int index) {
    List sel = event.getData();
    if (sel.size() > 0) {
      int idx = treeGrid.getTreeStore().indexOf(item.getModel());
      idx = status == 0 ? idx : idx + 1;
      if (item.getParent() != null) {
        ModelData p = item.getParent().getModel();
        appendModel(p, sel, idx);
      } else {
        appendModel(null, sel, idx);
      }
    }
  }

  @Override
  protected void onDragCancelled(DNDEvent event) {
    super.onDragCancelled(event);
    if (autoScroll) {
      scrollSupport.stop();
    }
  }

  @Override
  protected void onDragFail(DNDEvent event) {
    super.onDragFail(event);
    if (autoScroll) {
      scrollSupport.stop();
    }
  }

  @Override
  protected void onDragDrop(DNDEvent event) {
    super.onDragDrop(event);

    if (activeItem != null && status == -1) {
      clearStyle(activeItem);
      if (event.getData() != null) {
        handleAppendDrop(event, activeItem);
      }
    } else if (activeItem != null && status != -1) {
      if (event.getData() != null) {
        handleInsertDrop(event, activeItem, status);
      }
    } else if (activeItem == null && status == -1) {
      if (event.getData() != null) {
        handleAppendDrop(event, activeItem);
      }
    } else {
      event.setCancelled(true);
    }
    status = -1;
    activeItem = null;
    appendItem = null;

    if (autoScroll) {
      scrollSupport.stop();
    }
  }

  @Override
  protected void onDragEnter(DNDEvent e) {
    super.onDragEnter(e);
    e.getStatus().setStatus(false);

    if (autoScroll) {
      if (scrollSupport == null) {
        scrollSupport = new ScrollSupport(treeGrid.el().selectNode(".x-grid3-scroller"));
      } else if (scrollSupport.getScrollElement() == null) {
        scrollSupport.setScrollElement(treeGrid.el().selectNode(".x-grid3-scroller"));
      }
      scrollSupport.start();
    }
  }

  @Override
  protected void onDragLeave(DNDEvent e) {
    super.onDragLeave(e);
    if (activeItem != null) {
      clearStyle(activeItem);
      activeItem = null;
    }

    if (autoScroll) {
      scrollSupport.stop();
    }
  }

  @Override
  protected void onDragMove(DNDEvent event) {
    event.setCancelled(false);
  }

  @Override
  protected void showFeedback(DNDEvent event) {
    final TreeNode item = treeGrid.findNode(event.getTarget());
    if (item == null) {
      if (activeItem != null) {
        clearStyle(activeItem);
      }
    }

    if (item != null && event.getDropTarget().component == event.getDragSource().component) {
      TreeGrid source = (TreeGrid) event.getDragSource().component;
      List<ModelData> list = source.getSelectionModel().getSelection();
      ModelData overModel = item.getModel();
      for (int i = 0; i < list.size(); i++) {
        ModelData sel = list.get(i);
        if (overModel == sel) {
          Insert.get().hide();
          event.getStatus().setStatus(false);
          return;
        }
        List<ModelData> children = treeGrid.getTreeStore().getChildren(sel, true);
        if (children.contains(item.getModel())) {
          Insert.get().hide();
          event.getStatus().setStatus(false);
          return;
        }
      }
    }

    boolean append = feedback == Feedback.APPEND || feedback == Feedback.BOTH;
    boolean insert = feedback == Feedback.INSERT || feedback == Feedback.BOTH;

    if (item == null) {
      handleAppend(event, item);
    } else if (insert) {
      handleInsert(event, item);
    } else if ((!item.isLeaf() || allowDropOnLeaf) && append) {
      handleAppend(event, item);
    } else {
      if (activeItem != null) {
        clearStyle(activeItem);
      }
      status = -1;
      activeItem = null;
      appendItem = null;
      Insert.get().hide();
      event.getStatus().setStatus(false);
    }
  }

  private void showInsert(DNDEvent event, Element elem, boolean before) {
    Insert insert = Insert.get();
    insert.show(elem);
    Rectangle rect = El.fly(elem).getBounds();
    int y = before ? rect.y - 2 : (rect.y + rect.height - 4);
    insert.setBounds(rect.x, y, rect.width, 6);
  }
}
TOP

Related Classes of com.extjs.gxt.ui.client.dnd.TreeGridDropTarget

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.