using System; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Collections; using System.Data; using CMS.ExtendedControls; using CMS.FormControls; using CMS.GlobalHelper; using CMS.SettingsProvider; using CMS.UIControls; using CMS.URLRewritingEngine; public partial class CMSAdminControls_UI_Trees_UniTree : CMSUserControl, IPostBackEventHandler { #region "Variables" private bool mEnableRootAction = true; private bool mCollapseAll = false; private bool mExpandAll = false; private bool mUsePostBack = true; private string mSelectedItem = null; private string mExpandPath = string.Empty; private string mSelectPath = string.Empty; private string mNodeTemplate = "##ICON####NODENAME##"; private string mSelectedNodeTemplate = "##ICON####NODENAME##"; private string mDefaultItemTemplate = "##ICON####NODENAME##"; private string mSelectedDefaultItemTemplate = "##ICON####NODENAME##"; private UniTreeProvider mProviderObject = null; private TreeNode mCustomRootNode = null; private TreeNode mRootNode = null; private bool mLocalize = false; private bool mDisplayPopulatingindicator = true; private string selectedPath = string.Empty; private string mCollapseTooltip = null; private string mExpandTooltip = null; private string mLineImagesFolder = string.Empty; private string mDefaultImagePath = string.Empty; private int mExpandLevel = 0; private ArrayList defaultItems = new ArrayList(); #endregion #region "Public properties" /// /// Gets or sets the value which indicates whether pupulating indicator should be displayed or not. /// public bool DisplayPopulatingIndicator { get { return mDisplayPopulatingindicator; } set { mDisplayPopulatingindicator = value; } } /// /// Indicates if the root element action should be None or Select. /// public bool EnableRootAction { get { return mEnableRootAction; } set { mEnableRootAction = value; } } /// /// Indicates if all nodes should be expanded. /// public bool ExpandAll { get { return mExpandAll; } set { mExpandAll = value; } } /// /// Indicates if all nodes should be collapsed. /// public bool CollapseAll { get { return mCollapseAll; } set { mCollapseAll = value; } } /// /// Gets or sets the ToolTip for the image that is displayed for the expandable node indicator. /// public string ExpandTooltip { get { return mExpandTooltip; } set { mExpandTooltip = value; treeElem.ExpandImageToolTip = value; } } /// /// Gets or sets the ToolTip for the image that is displayed for the collapsible node indicator. /// public string CollapseTooltip { get { return mCollapseTooltip; } set { treeElem.CollapseImageToolTip = value; mCollapseTooltip = value; } } /// /// Gets or sets the path to a folder that contains the line images that are used to connect child nodes to parent nodes. /// public string LineImagesFolder { get { if (string.IsNullOrEmpty(mLineImagesFolder)) { if ((IsLiveSite && CultureHelper.IsPreferredCultureRTL()) || (!IsLiveSite && CultureHelper.IsUICultureRTL())) { mLineImagesFolder = "~" + URLHelper.CurrentRelativePath + "?cmsimg=/rt"; // GetImageUrl("RTL/Design/Controls/Tree", IsLiveSite, true); } else { mLineImagesFolder = "~" + URLHelper.CurrentRelativePath + "?cmsimg=/t"; // GetImageUrl("Design/Controls/Tree", IsLiveSite, true); } } return mLineImagesFolder; } set { mLineImagesFolder = value; treeElem.LineImagesFolder = value; } } /// /// Indicates number of expanded levels. /// public int ExpandLevel { get { return mExpandLevel; } set { mExpandLevel = value; } } /// /// Indicates if ##NODENAME## should be localized. /// public bool Localize { get { return mLocalize; } set { mLocalize = value; } } /// /// Gets ors sets the value which determines whether the tree will generate postbacks on node click. /// public bool UsePostBack { get { return mUsePostBack; } set { mUsePostBack = value; } } /// /// Gets or sets selected item. /// public string SelectedItem { get { if (mSelectedItem == null) { mSelectedItem = hdnSelectedItem.Value; } return mSelectedItem; } set { hdnSelectedItem.Value = value; mSelectedItem = value; } } /// /// Gets the client ID of hidden field with selected item value. /// public string SelectedItemFieldId { get { return hdnSelectedItem.ClientID; } } /// /// Gets or sets expand path. /// public string ExpandPath { get { return mExpandPath; } set { mExpandPath = value; } } /// /// Gets or sets select path. /// public string SelectPath { get { return mSelectPath; } set { mSelectPath = value; } } /// /// Gets or sets node template. You can use following macros: /// ##NODEID## (ID of item),##PARENTNODEID## (ID of parent), ##NODEJAVA## (encoded item name for using in javascript), /// ##NODECHILDNODESCOUNT## (count of children of node), ##NODENAME## (name of item), ##ICON## (image), ##OBJECTTYPE## (object type). /// public string NodeTemplate { get { return mNodeTemplate; } set { mNodeTemplate = value; } } /// /// Gets or sets node template. You can use following macros: /// ##NODEID## (ID of item), ##PARENTNODEID## (ID of parent), ##NODEJAVA## (encoded item name for using in javascript), /// ##NODECHILDNODESCOUNT## (count of children of node), ##NODENAME## (name of item), ##ICON## (image), ##OBJECTTYPE## (object type). /// public string SelectedNodeTemplate { get { return mSelectedNodeTemplate; } set { mSelectedNodeTemplate = value; } } /// /// Gets or sets node template. You can use following macros: /// ##NODEJAVA## (encoded item name for using in javascript), /// ##NODENAME## (name of item), ##ICON## (image) /// public string DefaultItemTemplate { get { return mDefaultItemTemplate; } set { mDefaultItemTemplate = value; } } /// /// Gets or sets node template. You can use following macros: /// ##NODEJAVA## (encoded item name for using in javascript), /// ##NODENAME## (name of item), ##ICON## (image) /// public string SelectedDefaultItemTemplate { get { return mSelectedDefaultItemTemplate; } set { mSelectedDefaultItemTemplate = value; } } /// /// Gets or sets TreeProvider object. /// public UniTreeProvider ProviderObject { get { return mProviderObject; } set { mProviderObject = value; } } /// /// Gets or sets default image path. /// public string DefaultImagePath { get { return mDefaultImagePath; } set { mDefaultImagePath = value; } } /// /// Gets custom root node. /// public TreeNode CustomRootNode { get { return mCustomRootNode; } } /// /// Gets root node from provider object. /// public TreeNode RootNode { get { if (mRootNode == null) { return CustomRootNode; } return mRootNode; } } #endregion #region "Custom events" /// /// Image delegate. /// public delegate string GetImageEventHandler(UniTreeNode node); /// /// Gets image Url. /// public event GetImageEventHandler OnGetImage; /// /// On selected item event handler. /// public delegate void ItemSelectedEventHandler(string selectedValue); /// /// On selected item event handler. /// public event ItemSelectedEventHandler OnItemSelected; /// /// Node created delegate. /// public delegate TreeNode NodeCreatedEventHandler(DataRow itemData, TreeNode defaultNode); /// /// Node created event handler. /// public event NodeCreatedEventHandler OnNodeCreated; #endregion #region "Events" /// /// Page load event. /// /// Sender /// Arguments protected void Page_Load(object sender, EventArgs e) { mCollapseTooltip = GetString("general.collapse"); mExpandTooltip = GetString("general.expand"); treeElem.ExpandImageToolTip = ExpandTooltip; treeElem.CollapseImageToolTip = CollapseTooltip; treeElem.LineImagesFolder = LineImagesFolder; btnItemSelected.Style.Add("display", "none"); } /// /// Tree populate. /// /// Sender /// Arguments protected void treeElem_TreeNodePopulate(object sender, TreeNodeEventArgs e) { OnNodePopulate(e.Node); } /// /// Page PreRender. /// /// Arguments protected override void OnPreRender(EventArgs e) { int index = 0; foreach (object item in defaultItems) { string[] defaultItem = (string[])item; if (defaultItem != null) { // Generate link HTML tag string link = null; string selectedItem = ValidationHelper.GetString(SelectedItem, "").ToLowerCSafe(); if (selectedItem == defaultItem[2].ToLowerCSafe()) { link = ReplaceMacros(SelectedDefaultItemTemplate, 0, 0, defaultItem[0], defaultItem[1], 0, "", ""); } else { link = ReplaceMacros(DefaultItemTemplate, 0, 0, defaultItem[0], defaultItem[1], 0, "", ""); } // Add complete HTML code to page if (UsePostBack) { link = "" + link + ""; } TreeNode tn = new TreeNode(); tn.Text = link; tn.NavigateUrl = URLRewriter.CurrentURL + "#"; treeElem.Nodes.AddAt(index, tn); index++; } } if (DisplayPopulatingIndicator && !Page.IsCallback) { // Register tree progress icon ScriptHelper.RegisterTreeProgress(Page); } base.OnPreRender(e); } #endregion #region "Methods" /// /// Adds default item to control (link over the tree). /// /// Item name /// Value /// Image path public void AddDefaultItem(string itemName, string value, string imagePath) { string imgTag = ""; // Generate image HTML tag if (!string.IsNullOrEmpty(imagePath)) { imgTag = "\"""; } // Insert default item to arraylist string[] defaultItem = new string[3]; defaultItem[0] = HTMLHelper.HTMLEncode(ResHelper.LocalizeString(itemName)); defaultItem[1] = imgTag; defaultItem[2] = value; defaultItems.Add(defaultItem); } /// /// Adds root node (allows customization of the root item). /// /// Root text /// Root value /// Image path public void SetRoot(string rootText, string value, string imagePath) { mCustomRootNode = new TreeNode(rootText, value, imagePath); } /// /// Adds root node (allows customization of the root item). /// /// Root text /// Root value /// Image path /// Navigate URL /// Target public void SetRoot(string rootText, string value, string imagePath, string navigateUrl, string target) { mCustomRootNode = new TreeNode(rootText, value, imagePath, navigateUrl, target); } /// /// Reloads data. /// public void ReloadData() { if (!StopProcessing && (ProviderObject != null)) { treeElem.Nodes.Clear(); treeElem.EnableViewState = false; // Add custom root node if (mCustomRootNode != null) { if (!EnableRootAction) { mCustomRootNode.SelectAction = TreeNodeSelectAction.None; } treeElem.Nodes.Add(mCustomRootNode); RaiseOnPopulateRootNode(); } else { // Add root node from provider if (ProviderObject.RootNode != null) { mRootNode = CreateNode((UniTreeNode)ProviderObject.RootNode); treeElem.Nodes.Add(mRootNode); } } } } /// /// Creates node. /// /// Node to create protected TreeNode CreateNode(UniTreeNode uniNode) { DataRow dr = (DataRow)uniNode.ItemData; if (dr != null) { TreeNode node = new TreeNode(); // Get data int childNodesCount = 0; if (!string.IsNullOrEmpty(ProviderObject.ChildCountColumn)) { childNodesCount = ValidationHelper.GetInteger(dr[ProviderObject.ChildCountColumn], 0); } // Node ID int nodeID = 0; if (!string.IsNullOrEmpty(ProviderObject.IDColumn)) { nodeID = ValidationHelper.GetInteger(dr[ProviderObject.IDColumn], 0); } // Node value string nodeValue = string.Empty; if (!string.IsNullOrEmpty(ProviderObject.ValueColumn)) { nodeValue = nodeID.ToString(); } string objectType = string.Empty; if (!string.IsNullOrEmpty(ProviderObject.ObjectTypeColumn)) { objectType = ValidationHelper.GetString(dr[ProviderObject.ObjectTypeColumn], ""); // Add object type to value nodeValue += "_" + objectType; } // Display name string displayName = string.Empty; if (!string.IsNullOrEmpty(ProviderObject.DisplayNameColumn)) { displayName = HTMLHelper.HTMLEncode(ResHelper.LocalizeString(ValidationHelper.GetString(dr[ProviderObject.DisplayNameColumn], ""))); } // Path string nodePath = string.Empty; if (!string.IsNullOrEmpty(ProviderObject.PathColumn)) { nodePath = HTMLHelper.HTMLEncode(ValidationHelper.GetString(dr[ProviderObject.PathColumn], "")).ToLowerCSafe(); } // Parent ID int parentID = 0; if (!string.IsNullOrEmpty(ProviderObject.ParentIDColumn)) { parentID = ValidationHelper.GetInteger(dr[ProviderObject.ParentIDColumn], 0); } // Parameter string parameter = string.Empty; if (!string.IsNullOrEmpty(ProviderObject.ParameterColumn)) { parameter = HTMLHelper.HTMLEncode(ValidationHelper.GetString(dr[ProviderObject.ParameterColumn], "")).ToLowerCSafe(); } int nodeLevel = 0; if (!String.IsNullOrEmpty(ProviderObject.LevelColumn)) { nodeLevel = ValidationHelper.GetInteger(dr[ProviderObject.LevelColumn], 0); } node.NavigateUrl = URLRewriter.CurrentURL + "#"; // Set value node.Value = nodeValue; // Get image html tag string imgPath = string.Empty; if (!string.IsNullOrEmpty(ProviderObject.ImageColumn)) { imgPath = ResolveUrl(ValidationHelper.GetString(dr[ProviderObject.ImageColumn], "")); } if (string.IsNullOrEmpty(imgPath)) { imgPath = ResolveUrl(DefaultImagePath); } if (OnGetImage != null) { imgPath = ResolveUrl(OnGetImage(uniNode)); } string imgTag = string.Empty; if (!string.IsNullOrEmpty(imgPath)) { imgTag = "\"""; } // Set text string text = null; string selectedItem = ValidationHelper.GetString(SelectedItem, ""); string selectPathLowered = SelectPath.ToLowerCSafe(); if (nodeValue.EqualsCSafe(selectedItem, true) || ((selectPathLowered == nodePath) && string.IsNullOrEmpty(selectedItem))) { text = ReplaceMacros(SelectedNodeTemplate, nodeID, childNodesCount, displayName, imgTag, parentID, objectType, parameter); } else { text = ReplaceMacros(NodeTemplate, nodeID, childNodesCount, displayName, imgTag, parentID, objectType, parameter); } if (UsePostBack) { text = "" + text + ""; } node.Text = text; // Set populate node automatically if (childNodesCount != 0) { node.PopulateOnDemand = true; } // Expand tree if (ExpandAll) { node.Expanded = true; } else if (CollapseAll) { node.Expanded = false; } else { // Handle expand path if (!nodePath.EndsWith("/")) { nodePath += "/"; } string expandPathLowered = ExpandPath.ToLowerCSafe(); // SelectPath property if (selectPathLowered.StartsWithCSafe(nodePath) && (selectPathLowered != nodePath)) { node.Expanded = true; } // ExpandPath property else if ((expandPathLowered.StartsWithCSafe(nodePath))) { node.Expanded = true; } // Path expanded by user else if (selectedPath.StartsWithCSafe(nodePath) && (selectedPath != nodePath)) { node.Expanded = true; } else { node.Expanded = false; } } // Expand level if ((ExpandLevel != 0) && !CollapseAll) { node.Expanded = nodeLevel <= ExpandLevel; } return node; } return null; } /// /// Replaces all macros in template by values. /// /// Template with macros /// Item ID /// Child count /// Node name /// Parent item ID /// Icon /// Object type /// Additional parameter public string ReplaceMacros(string template, int itemID, int childCount, string nodeName, string icon, int parentNodeID, string objectType, string parameter) { template = template.Replace("##NODEID##", itemID.ToString()); template = template.Replace("##NODEJAVA##", ScriptHelper.GetString(nodeName)); template = template.Replace("##NODECHILDNODESCOUNT##", childCount.ToString()); if (Localize) { template = template.Replace("##NODENAME##", ResHelper.LocalizeString(nodeName)); } else { template = template.Replace("##NODENAME##", nodeName); } template = template.Replace("##ICON##", icon); template = template.Replace("##PARENTNODEID##", parentNodeID.ToString()); template = template.Replace("##OBJECTTYPE##", objectType); template = template.Replace("##PARAMETER##", parameter); return template; } /// /// Returns javascript code raising postback and OnItemSelected event. /// /// Postback parameter public string GetOnSelectedItemBackEventReference() { return ControlsHelper.GetPostBackEventReference(btnItemSelected, null, false); } /// /// Handles simulated hidden button click and raises OnItemSelected event with value from hidden field. /// protected void btnItemSelected_Click(object sender, EventArgs e) { RaiseOnItemSelected(hdnSelectedItem.Value); } /// /// Raises on selected item event. /// /// Selected value public void RaiseOnItemSelected(string selectedValue) { SelectedItem = selectedValue; if (OnItemSelected != null) { OnItemSelected(selectedValue); } } /// /// Populates root node. /// public void RaiseOnPopulateRootNode() { TreeNode node = treeElem.Nodes[0]; if (node != null) { if (!string.IsNullOrEmpty(ExpandPath)) { node.Expanded = true; OnNodePopulate(node); } } } /// /// Handle node is populated. /// private void OnNodePopulate(TreeNode node) { if ((ProviderObject != null) && (node != null)) { string[] splitted = node.Value.Split('_'); int nodeID = ValidationHelper.GetInteger(splitted[0], 0); // Get node object type string nodeObjectType = string.Empty; if (splitted.Length == 2) { nodeObjectType = splitted[1]; } // Get child nodes SiteMapNodeCollection childNodes = ProviderObject.GetChildNodes(node.Value, node.Depth + 1); // Add to treeview foreach (UniTreeNode childNode in childNodes) { // Get ID int childNodeId = (int)(((DataRow)childNode.ItemData)[ProviderObject.IDColumn]); // Get object type string childNodeType = string.Empty; if (!string.IsNullOrEmpty(ProviderObject.ObjectTypeColumn)) { childNodeType = ValidationHelper.GetString((((DataRow)childNode.ItemData)[ProviderObject.ObjectTypeColumn]), ""); } // Don't insert one object more than once if ((childNodeId != nodeID) || (nodeObjectType != childNodeType)) { TreeNode createdNode = CreateNode(childNode); if (OnNodeCreated != null) { createdNode = OnNodeCreated((DataRow)childNode.ItemData, createdNode); } if (createdNode != null) { node.ChildNodes.Add(createdNode); } } } } } #endregion #region "IPostBackEventHandler Members" /// /// Raises event postback event. /// public void RaisePostBackEvent(string eventArgument) { // Get argument string arg = HttpUtility.HtmlDecode(eventArgument); // Get value string[] selectedItem = arg.Split(';'); string value = selectedItem[0]; // Get path if (selectedItem.Length >= 2) { selectedPath = selectedItem[1].ToLowerCSafe(); } // Raise event RaiseOnItemSelected(value); } #endregion }