//------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------
        
        #region Private Methods

        #region Generating Locators

        /// <summary>
        ///     Walks the path through the element tree specified by 'root' and
        ///     produces a set of locators identifying the path based on
        ///     DependencyProperty settings on the tree.
        /// </summary>
        /// <param name="processor">SubTreeProcessor to use on node</param>
        /// <param name="startNode">the PathNode identifying the root of the subtree to process</param>
        /// <param name="selection">selection for which Locators are being generated</param>
        /// <returns>
        ///     a set of locators identifying the path through the element tree;
        ///     can return null if no locators can be generated for this root
        /// </returns>
        /// <exception cref="ArgumentNullException">root is null</exception>
        /// <exception cref="SystemException">no AnnotationStore is available from
        /// the element tree</exception>
        private IList<ContentLocatorBase> GenerateLocators(SubTreeProcessor processor, PathNode startNode, Object selection)
        {
            Debug.Assert(startNode != null, "startNode can not be null");

            List <ContentLocatorBase> locatorsToReturn = new List<ContentLocatorBase> ();
            bool continueProcessing = true;

            // Process the current PathNode, with the possibilty of doing the whole
            // subtree (in which case continueProcessing comes back false).
            ContentLocator list = processor.GenerateLocator(startNode, out continueProcessing);
            bool processSelection = list != null;
            IList<ContentLocatorBase> newLocators = null;

            // If we should continue processing, we look at the children of the 
            // root.  Depending on the number of children we do  different things.
            if (continueProcessing)
            {
                switch (startNode.Children.Count)
                {
                    case 0 :
                        // No children - we just return what we have so far
                        if (list != null)
                        {
                            locatorsToReturn.Add(list);
                        }

                        break;

                    case 1 :
                        // One child - we ask the root of the subtree for the processor
                        // to use and then ask the processor to handle the subtree.
                        SubTreeProcessor newProcessor = GetSubTreeProcessor(startNode.Node);
                        newLocators = GenerateLocators(newProcessor, (PathNode)startNode.Children[0], selection);

                        if (newLocators != null && newLocators.Count > 0)
                            processSelection = false;

                        if (list != null)
                            locatorsToReturn.AddRange(Merge(list, newLocators));
                        else
                            locatorsToReturn.AddRange(newLocators);

                        break;

                    default :
                        // Multiple children - we must process all the children as a
                        // locator set.  This returns one or more locators that all start
                        // start with a ContentLocatorGroup which can have one locator for each
                        // child.
                        ContentLocatorBase newLocator = GenerateLocatorGroup(startNode, selection);

                        if (newLocator != null)
                            processSelection = false;

                        if (list != null)
                            locatorsToReturn.Add(list.Merge(newLocator));
                        else if (newLocator != null)
                            locatorsToReturn.Add(newLocator);
                        break;
                }
            }
            else
            {
                // If we shouldn't continue processing we package up the
                // locator we got from the first GenerateLocator call
                if (list != null)
                {
                    locatorsToReturn.Add(list);
                }
            }

            // If we produced a locator for root and no one below us did as well,
            // we need to process the selection, if any
            if (processSelection && selection != null)
            {
                SelectionProcessor selProcessor = GetSelectionProcessor(selection.GetType());

                if (selProcessor != null)
                {
                    IList <ContentLocatorPart> locatorParts = selProcessor.GenerateLocatorParts(selection, startNode.Node);
                    // Possible bug - AddLocatorPartsToLocator was only written to handle normal locators, not
                    // locator groups. ToDo
                    if (locatorParts != null && locatorParts.Count > 0)
                    {
                        List<ContentLocatorBase> tempLocators = new List<ContentLocatorBase>(locatorsToReturn.Count * locatorParts.Count);

                        foreach (ContentLocatorBase loc in locatorsToReturn)
                        {
                            tempLocators.AddRange(((ContentLocator)loc).DotProduct(locatorParts));  // 
                        }

                        locatorsToReturn = tempLocators;
                    }
                }
            }

            return locatorsToReturn;
        }
        /// <summary>
        ///     Produces a set of locators that uses locator groups to
        ///     span multiple branches in the tree.
        /// </summary>
        /// <param name="node">the PathNode identifying the root of the subtree to process</param>
        /// <param name="selection">the selection we are currently processing</param>
        /// <returns>
        ///     a locator set containing locators identifying the path 
        ///     through the element tree
        /// </returns>
        /// <exception cref="ArgumentNullException">node is null</exception>
        /// <exception cref="SystemException">no AnnotationStore is available from
        /// the element tree</exception>
        private ContentLocatorBase GenerateLocatorGroup(PathNode node, Object selection)
        {
            Debug.Assert(node != null, "node can not be null");

            SubTreeProcessor processor = GetSubTreeProcessor(node.Node);            
            IList<ContentLocatorBase> tempLocators = null;

            ContentLocatorGroup ContentLocatorGroup = new ContentLocatorGroup();

            // Produce a locator representing each child and add it
            // to the locator set.  NOTE - We currently only support one
            // locator per branch.
            foreach (PathNode child in node.Children)
            {
                tempLocators = GenerateLocators(processor, child, selection);
                if (tempLocators != null && tempLocators.Count > 0)
                {
                    // Don't add empty Locators to the ContentLocatorGroup
                    if (tempLocators[0] != null)
                    {
                        ContentLocatorGroup locatorGroup = null;
                        ContentLocator locator = tempLocators[0] as ContentLocator;
                        if (locator != null && locator.Parts.Count != 0)
                        {
                            // NOTE - We currently only support producing one locator
                            // per branch of the locator set.
                            ContentLocatorGroup.Locators.Add(locator);
                        }
                        else if ((locatorGroup = tempLocators[0] as ContentLocatorGroup) != null)
                        {
                            // 

                        }
                    }
                }
            }

            // If the locators set is empty, we return null
            // If only one locator was generated for the children, we return that
            // locator directly.  No need for a ContentLocatorGroup
            // Otherwise return the ContentLocatorGroup
            if (ContentLocatorGroup.Locators.Count == 0)
            {
                return null;
            }
            else if (ContentLocatorGroup.Locators.Count == 1)
            {
                ContentLocator list = ContentLocatorGroup.Locators[0];
                ContentLocatorGroup.Locators.Remove(list);
                return list;
            }            
            else
            {
                return ContentLocatorGroup;
            }
        }
Exemple #3
0
        /// <summary>
        ///     Generates a locator part list identifying node.  If node has a
        ///     value for DataIdProperty, a locator with a single locator part
        ///     containing the id value is returned.  Otherwise null is returned.
        /// </summary>
        /// <param name="node">the node to generate a locator for</param>
        /// <param name="continueGenerating">specifies whether or not generating should 
        /// continue for the rest of the path; always set to true</param>
        /// <returns>if node has a value for DataIdProperty, a locator with a
        /// single locator part containing the id value; null otherwise
        /// </returns>
        /// <exception cref="ArgumentNullException">node is null</exception>
        public override ContentLocator GenerateLocator(PathNode node, out bool continueGenerating)
        {
            if (node == null)
                throw new ArgumentNullException("node");            

            continueGenerating = true;
            
            ContentLocator locator = null;
            ContentLocatorPart newLocatorPart = CreateLocatorPart(node.Node);
            if (newLocatorPart != null)
            {
                locator = new ContentLocator();
                locator.Parts.Add(newLocatorPart);
            }
            
            return locator;
        }
Exemple #4
0
        /// <summary>
        ///     Generates locators identifying 'chunks'.  If node is a chunk, 
        ///     generates a locator with a single locator part containing a 
        ///     fingerprint of the chunk.  Otherwise null is returned.
        /// </summary>
        /// <param name="node">the node to generate a locator for</param>
        /// <param name="continueGenerating">return flag indicating whether the search 
        /// should continue (presumably because the search was not exhaustive). 
        /// This processor will always return true because it is possible to locate 
        /// parts of the node (if it is FixedPage or FixedPageProxy)</param>
        /// <returns>if node is a FixedPage or FixedPageProxy, a ContentLocator 
        /// with  a single locator part containing the page number; null if node is not 
        /// FixedPage or FixedPageProxy </returns>
        /// <exception cref="ArgumentNullException">node is null</exception>
        /// <exception cref="ArgumentException">node points to a Document Page View which
        /// doesn't contain a FixedDocumentPage</exception>
        public override ContentLocator GenerateLocator(PathNode node, out bool continueGenerating)
        {
            if (node == null)
                throw new ArgumentNullException("node");

            // Initial value
            continueGenerating = true;

            ContentLocator locator = null;
            DocumentPageView dpv = node.Node as DocumentPageView;            
            
            int pageNb = -1;

            if (dpv != null)
            {
                // Only produce locator parts for FixedDocumentPages
                if (dpv.DocumentPage is FixedDocumentPage || dpv.DocumentPage is FixedDocumentSequenceDocumentPage)
                {
                    pageNb = dpv.PageNumber;
                }
            }
            else
            {
                FixedTextSelectionProcessor.FixedPageProxy fPage = node.Node as FixedTextSelectionProcessor.FixedPageProxy;
                if (fPage != null)
                {
                    pageNb = fPage.Page;
                }
            }

            if (pageNb >= 0)
            {
                locator = new ContentLocator();
                ContentLocatorPart locatorPart = CreateLocatorPart(pageNb);
                locator.Parts.Add(locatorPart);
            }

            return locator;
        }
Exemple #5
0
 /// <summary>
 ///     Generates a locator part list identifying node.  
 /// </summary>
 /// <remarks>
 ///     Most subclasses will simply return a ContentLocator with one locator
 ///     part in it.  In some cases, more than one locator part may be
 ///     required (e.g., a node which represents path to some data may
 ///     need a separate locator part for each portion of the path).
 /// </remarks>
 /// <param name="node">the node to generate a locator for</param>
 /// <param name="continueGenerating">specifies whether or not generating should 
 /// continue for the rest of the path; a SubTreeProcessor could return false if
 /// it processed the rest of the path itself </param>
 /// <returns>
 ///     a locator identifying 'node'; in most cases this locator will 
 ///     only contain one locator part; can return null if no 
 ///     locator part can be generated for the given node
 /// </returns>
 /// <exception cref="ArgumentNullException">node is null</exception>
 public abstract ContentLocator GenerateLocator(PathNode node, out bool continueGenerating);
        /// <summary>
        ///     Adds a branch to an existing path, removing any duplicate
        ///     nodes as necessary.  Assumes that both paths are full paths 
        ///     up to the root of the same tree.  If the paths are not full, 
        ///     the method will give incorrect results.  If the paths are 
        ///     full but belong to different trees (and therefore have 
        ///     different roots) the method will throw.
        /// </summary>
        /// <param name="path">path to add branch to</param>
        /// <param name="branch">branch to be added; should be a linear path 
        /// (no more than one child for any node)</param>
        /// <returns>the path with branch having been added in and duplicate 
        /// nodes pruned</returns>
        private static PathNode AddBranchToPath(PathNode path, PathNode branch)
        {
            Debug.Assert(path != null, "path can not be null");
            Debug.Assert(branch != null, "branch can not be null");

            // The paths must be in the same tree and therefore have the
            // same root.  
            Debug.Assert(path.Node.Equals(branch.Node), "path.Node is not equal to branch.Node");

            PathNode fp = path;
            PathNode sp = branch;

            // Continue down
            while (fp.Node.Equals(sp.Node) && sp._children.Count > 0)
            {
                // if the firstpath component equals the second path component
                // then we try to find the second path child component
                // inside the first path children
                bool found = false;
                PathNode branchNode = (PathNode)sp._children[0];

                foreach (PathNode fpn in fp._children)
                {
                    if (fpn.Equals(branchNode))
                    {
                        // if we found one we keep moving along both the first path and the second path
                        found = true;
                        sp = branchNode;
                        fp = fpn;
                        break;
                    }
                }

                if (found)
                    continue;

                // if we can not find the second path child in the first
                // path child, we then just add the second path child
                // to the set of first path children
                fp.AddChild(branchNode);
                break;
            }

            return path;
        }
        /// <summary>
        ///      Builds a path from an element to the root of its tree.  Every
        ///      element in between the element and the root is added to the 
        ///      path.
        /// </summary>
        /// <param name="node">the element to build a path for</param>
        /// <returns>the PathNode instance referring to the root of the tree; its 
        /// children/descendants only include the nodes between the root and 
        /// node</returns>
        private static PathNode BuildPathForElement(DependencyObject node)
        {
            Debug.Assert(node != null, "node can not be null");

            PathNode childNode = null;
            while (node != null)
            {
                PathNode pathNode = new PathNode(node);

                if (childNode != null)
                    pathNode.AddChild(childNode);

                childNode = pathNode;
                
                // If we find a node that has the service set on it, we should stop 
                // after processing it.  For cases without a service like unit tests,
                // this node won't be found and we'll continue to the root.
                if (node.ReadLocalValue(AnnotationService.ServiceProperty) != DependencyProperty.UnsetValue)
                    break;

                node = PathNode.GetParent(node);
            }

            return childNode;
        }