/// <summary>
        /// Adds a preference pane.
        /// </summary>
        /// <param name="path">The preference pane path consisting of slash-delimited name segments
        /// specifying tree nodes.</param>
        /// <param name="icon">The preference pane icon, or null if none.</param>
        /// <param name="scope">The preference pane scope, or null if none.</param>
        /// <param name="paneFactory">The preference pane factory.</param>
        public void AddPane(string path, Icon icon, PreferencePaneScope scope, GallioFunc <PreferencePane> paneFactory)
        {
            string[] pathSegments = path.Split('/');
            if (pathSegments.Length == 0)
            {
                throw new ArgumentException("Preference pane path must not be empty.", "path");
            }

            TreeNode treeNode = null;

            foreach (string pathSegment in pathSegments)
            {
                TreeNodeCollection treeNodeCollection = treeNode != null
                    ? treeNode.Nodes
                    : preferencePaneTree.Nodes;

                TreeNode childTreeNode = FindTreeNodeByName(treeNodeCollection, pathSegment);
                if (childTreeNode == null)
                {
                    childTreeNode     = new TreeNode(pathSegment);
                    childTreeNode.Tag = new PaneInfo(CreatePlaceholderPreferencePane, pathSegment);
                    treeNodeCollection.Add(childTreeNode);
                }

                treeNode = childTreeNode;
            }

            string title = pathSegments[pathSegments.Length - 1];

            if (scope == PreferencePaneScope.Machine)
            {
                title += " (machine setting)";
            }

            treeNode.Tag = new PaneInfo(paneFactory, title);

            if (icon != null)
            {
                int imageIndex = preferencePaneIconImageList.Images.Count;
                preferencePaneIconImageList.Images.Add(icon);

                treeNode.ImageIndex         = imageIndex;
                treeNode.SelectedImageIndex = imageIndex;
            }
        }
        /// <summary>
        /// Adds a preference pane.
        /// </summary>
        /// <param name="path">The preference pane path consisting of slash-delimited name segments
        /// specifying tree nodes.</param>
        /// <param name="icon">The preference pane icon, or null if none.</param>
        /// <param name="scope">The preference pane scope, or null if none.</param>
        /// <param name="paneFactory">The preference pane factory.</param>
        public void AddPane(string path, Icon icon, PreferencePaneScope scope, Func<PreferencePane> paneFactory)
        {
            string[] pathSegments = path.Split('/');
            if (pathSegments.Length == 0)
                throw new ArgumentException("Preference pane path must not be empty.", "path");

            TreeNode treeNode = null;
            foreach (string pathSegment in pathSegments)
            {
                TreeNodeCollection treeNodeCollection = treeNode != null
                    ? treeNode.Nodes
                    : preferencePaneTree.Nodes;

                TreeNode childTreeNode = FindTreeNodeByName(treeNodeCollection, pathSegment);
                if (childTreeNode == null)
                {
                    childTreeNode = new TreeNode(pathSegment);
                    childTreeNode.Tag = new PaneInfo(CreatePlaceholderPreferencePane, pathSegment);
                    treeNodeCollection.Add(childTreeNode);
                }

                treeNode = childTreeNode;
            }

            string title = pathSegments[pathSegments.Length - 1];
            if (scope == PreferencePaneScope.Machine)
                title += " (machine setting)";

            treeNode.Tag = new PaneInfo(paneFactory, title);

            if (icon != null)
            {
                int imageIndex = preferencePaneIconImageList.Images.Count;
                preferencePaneIconImageList.Images.Add(icon);

                treeNode.ImageIndex = imageIndex;
                treeNode.SelectedImageIndex = imageIndex;
            }
        }