using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using Zhaizj.Framework.Web;
namespace Zhaizj.Framework {
///
/// 树状节点接口
///
public interface INode {
///
/// 节点的 Id
///
int Id { get; set; }
///
/// 节点的名称
///
String Name { get; set; }
///
/// 上级节点的 Id
///
int ParentId { get; set; }
}
///
/// 节点绑定器
///
public interface INodeBinder {
String Bind( INode node );
}
///
/// 树状节点(将 T 做了封装,便于操作)
///
/// 节点必须实现了 INode 接口
public class Node where T : INode {
public Node() {
}
public Node( T node ) {
_rawNode = node;
}
private T _rawNode;
///
/// 获取原始节点数据
///
///
public T getNode() {
return _rawNode;
}
//-----------------------------------------------------
private Tree _tree;
public void setTree( Tree tree ) {
_tree = tree;
}
private Node _parent;
///
/// 获取上级节点
///
///
public Node getParent() {
if (this.getNode().ParentId == 0) return null;
if (_parent == null) {
_parent = _tree.FindById( this.getNode().ParentId );
}
return _parent;
}
private int _depth = -1;
///
/// 获取节点的深度
///
///
public int getDepth() {
if (_depth < 0) {
if (this.getNode().ParentId == 0) {
_depth = 0;
}
else {
if (this.getParent() == null) {
_depth = 0;
}
else {
_depth = this.getParent().getDepth() + 1;
}
}
}
return _depth;
}
private List> _children = new List>();
///
/// 获取所有子节点
///
///
public List> getChildren() {
return _children;
}
internal void addChildren( Node node ) {
_children.Add( node );
}
//-------------------------------------------------------------
private Node _prevNode;
private Node _nextNode;
///
/// 获取前一个节点
///
///
public Node getPrev() {
return _prevNode;
}
///
/// 获取后一个节点
///
///
public Node getNext() {
return _nextNode;
}
internal void setPrev( Node node ) {
_prevNode = node;
}
internal void setNext( Node node ) {
_nextNode = node;
}
internal Boolean indent() {
if (getPrev() == null) return true;
return getDepth() > getPrev().getDepth();
}
internal Boolean outdent() {
if (getPrev() == null) return false;
return getDepth() < getPrev().getDepth();
}
internal int getOutdentCount() {
return getPrev().getDepth() - getDepth();
}
}
///
/// 树状结构
///
/// 节点必须实现了 INode 接口
public class Tree where T : INode {
private static readonly ILog logger = LogManager.GetLogger( "Zhaizj.Framework.Tree" );
private List _rawList;
public Tree( List nodeList ) {
_rawList = nodeList;
initProxyList();
}
//------------------------------------------------------------
///
/// 根据 Id 检索节点
///
///
///
public Node FindById( int id ) {
return getById( id );
}
///
/// 根据 Id 获取它的上级节点
///
///
///
public Node FindParent( int id ) {
Node proxy = getById( id );
if (proxy == null) return default( Node );
return proxy.getParent();
}
///
/// 根据 Id,获取它的节点路径(从根级开始到当前节点)
///
///
///
public List> FindPath( int id ) {
List> nodePath = new List>();
Node proxy = getById( id );
if (proxy == null) return nodePath;
nodePath.Add( proxy );
Node currentNode = proxy;
while (true) {
Node parent = currentNode.getParent();
if (parent == null) break;
nodePath.Add( parent );
currentNode = parent;
}
nodePath.Reverse();
return nodePath;
}
///
/// 获取所有根节点
///
///
public List> FindRoots() {
return getRoots();
}
///
/// 根据 Id,获取所有子节点
///
///
///
public List> FindChildren( int id ) {
Node proxy = getById( id );
if (proxy == null) return new List>();
return proxy.getChildren();
}
private List> _allOrdered;
///
/// 获取所有节点(经过排序)
///
///
public List> FindAllOrdered() {
if (_allOrdered == null) {
List> results = new List>();
List> roots = this.FindRoots();
foreach (Node node in roots) {
addSubProxyNodes( results, node );
}
_allOrdered = results;
}
return _allOrdered;
}
private void addSubProxyNodes( List> results, Node parentnode ) {
results.Add( parentnode );
List> subnodes = parentnode.getChildren();
foreach (Node node in subnodes) {
addSubProxyNodes( results, node );
}
}
//------------------------------------------------------------
///
/// 根据 Id 获取节点
///
///
///
public T GetById( int id ) {
Node proxy = getById( id );
if (proxy != null) return proxy.getNode();
return default( T );
}
///
/// 根据 Id 获取节点的深度
///
///
///
public int GetDepth( int id ) {
Node proxy = getById( id );
if (proxy != null) return proxy.getDepth();
return 0;
}
///
/// 根据 Id 获取上级节点
///
///
///
public T GetParent( int id ) {
Node proxy = getById( id );
if (proxy == null) return default( T );
Node parentProxy = proxy.getParent();
if (parentProxy != null) return parentProxy.getNode();
return default( T );
}
///
/// 根据 Id,获取节点的路径(从根级开始到当前节点)
///
///
///
public List GetPath( int id ) {
List nodePath = new List();
Node proxy = getById( id );
if (proxy == null) return nodePath;
nodePath.Add( proxy.getNode() );
Node tempNode = proxy;
while (true) {
Node parent = tempNode.getParent();
if (parent == null) break;
nodePath.Add( parent.getNode() );
tempNode = parent;
}
nodePath.Reverse();
return nodePath;
}
///
/// 根据 Id,获取所有下级节点
///
///
///
public List GetChildren( int id ) {
Node proxy = getById( id );
if (proxy == null) return new List();
List> children = proxy.getChildren();
List results = new List();
foreach (Node px in children) results.Add( px.getNode() );
return results;
}
///
/// 获取所有根节点
///
///
public List GetRoots() {
List> nodes = this.FindRoots();
List results = new List();
foreach (Node px in nodes) {
results.Add( px.getNode() );
}
return results;
}
private List _allOrderedNode;
///
/// 获取所有排序过的节点
///
///
public List GetAllOrdered() {
if (_allOrderedNode == null) {
List> nodes = this.FindAllOrdered();
List results = new List();
foreach (Node px in nodes) {
results.Add( px.getNode() );
}
_allOrderedNode = results;
}
return _allOrderedNode;
}
//----------------------------------------------------------------
///
/// 树状下拉列表控件
///
/// 下拉列表name
/// 当前选定的值
///
public String DropList( String dropName, int selectValue ) {
return DropList( dropName, selectValue, 0, null );
}
///
/// 获取下拉列表select
///
/// 下拉列表的name和id
/// 当前选中项的值
/// 当select用于设置父节点之时,此参数表示将节点自己排除在下拉列表之外,防止将自己作为自己的父节点
/// 根节点(并不存在,但你可以给它取个名称)
///
public String DropList( String dropName, int selectValue, int nodeId, String rootSelectName ) {
List> list = this.FindAllOrdered();
StringBuilder builder = new StringBuilder();
builder.AppendFormat( "" );
return builder.ToString();
}
private static String getBlank( int depth ) {
StringBuilder builder = new StringBuilder();
int length = depth * 4;
for (int i = 0; i <= length; i++) {
builder.Append( " " );
}
return builder.ToString();
}
private static int getSelectedValue( String dropName, int val ) {
if (CurrentRequest.getHttpMethod().Equals( "POST" )) {
return cvt.ToInt( CurrentRequest.getForm( dropName ) );
}
return val;
}
///
/// 获取树状结构的 html
///
///
///
public String RenderList( String treeId ) {
return RenderList( treeId, true, null, 0 );
}
///
/// 获取树状结构的 html
///
///
///
///
///
///
public String RenderList( String treeId, Boolean showChildren, INodeBinder binder, int currentNodeId ) {
List> list = this.FindAllOrdered();
StringBuilder builder = new StringBuilder();
int indent = 0;
for (int i = 0; i < list.Count; i++) {
Node node = list[i];
// 是否添加 ul 以及是否隐藏
if (i == 0) {
builder.Append( "" );
indent++;
}
else if (node.indent()) {
String displayCls = getDisplayCls( showChildren, currentNodeId, node.getNode().Id );
builder.Append( "" );
indent++;
}
else if (node.outdent()) {
int outdentCount = node.getOutdentCount();
for (int x = 0; x < outdentCount; x++) {
builder.Append( "
" );
indent--;
}
}
// li 的 class
builder.Append( "- " );
String item = (binder == null ? node.getNode().Name : binder.Bind( node.getNode() ));
builder.Append( item );
builder.Append( "
" );
}
for (int y = 0; y < indent; y++) {
builder.Append( "
" );
}
return builder.ToString();
}
private String getListClass( Boolean showChildren, int currentNodeId, Node node ) {
String cls = "";
if (node.getChildren().Count > 0) {
cls += "parentNode";
if (isOpenedNode( currentNodeId, node.getNode().Id, showChildren ))
cls += " collapseNode";
else
cls += " expandNode";
}
if (node.getNode().Id == currentNodeId) cls += " currentNode";
return cls.Trim();
}
private String getDisplayCls( Boolean showChildren, int currentNodeId, int nodeId ) {
if (showChildren) return "";
List> path = FindPath( currentNodeId );
foreach (Node parent in path) {
if (parent.getNext() == null) continue;
if (nodeId == parent.getNext().getNode().Id) return "";
}
return " class=\"hide\"";
}
private Boolean isOpenedNode( int currentNodeId, int nodeId, Boolean showChildren ) {
if (showChildren) return true;
List> path = FindPath( currentNodeId );
foreach (Node parent in path) {
if (nodeId == parent.getNode().Id) return true;
}
return false;
}
//----------------------------------------------------------------
private Node getById( int id ) {
if (getIdCache().ContainsKey( id ) == false) return default( Node );
return getIdCache()[id];
}
//----------------------------------------------------------------
private List> _proxyList;
private Dictionary> _idcache;
private List> _roots;
private List> getNodeList() {
return _proxyList;
}
private Dictionary> getIdCache() {
return _idcache;
}
private List> getRoots() {
return _roots;
}
private void initProxyList() {
_proxyList = new List>();
_idcache = new Dictionary>();
_roots = new List>();
// 缓存id
foreach (T node in _rawList) {
Node proxy = new Node( node );
proxy.setTree( this );
_proxyList.Add( proxy );
_idcache.Add( node.Id, proxy );
}
// 缓存children
foreach (Node node in _proxyList) {
if (node.getNode().ParentId == 0) {
_roots.Add( node );
}
else {
Node p = node.getParent();
if (p == null) {
logger.Error( string.Format( "parent does not exist: id={0}, name={1}, parentId={2}", node.getNode().Id, node.getNode().Name, node.getNode().ParentId ) );
}
else {
p.addChildren( node );
}
}
}
// 排序并缓存pre和next
List> orderedList = FindAllOrdered();
for (int i = 0; i < orderedList.Count; i++) {
if (i == 0) continue;
Node node = orderedList[i];
Node pre = orderedList[i - 1];
node.setPrev( pre );
pre.setNext( node );
}
}
}
}