4 Replies Latest reply on Jul 12, 2010 3:20 PM by Flex harUI

    Bug? Create a branch in a Tree and other rows go blank and get offset

    RustyAxeSys

      Hi

       

      A bit of background on the component first. I have a custom component that extends Tree. The component represents documents  and their pages.   The tree has two levels.  The first level is the  documents and the 2nd level are the documents pages. Conceptually, a document also  represents its first page, so a document that has more than one page is a  branch with leaves/children, while a one page document is a leaf.

      Pressing the [Enter] key down (or [Space] or double clicking the mouse) when on a  page will make that page a document.  In the background Flex may move leaves (i.e. children) of the previous  document to the new document. It will then also set the selectedItem to  be the 2nd page of the new document (i.e. the first child leaf of the  document branch).

       

      Under the hood, when creating a new document I move the relevant pages  of the previous document to be the pages of the new document.  That is, a  sub-section of the children of the previous branch (document) become the children  of the new branch (new document).  Because we can potentially have thousands of pages in the Tree I am using Array functions to move the children rather than ArrayCollection functions.

       

      So my current code is:

       

                  // copy relevant pages from pagesDocument to newDocument
                  // use Array functions rather than ArrayCollection functions to improve performance
                  if (pagesDocument.children.length > (pageIndex+1))
                      newDocument.children = new ArrayCollection(pagesDocument.children.toArray().slice(pageIndex+1, pagesDocument.children.length));
                 
                  // delete newDoc's pages from pagesDocument
                  // use Array functions rather than ArrayCollection functions to improve performance
                  if (pageIndex > 0)
                      pagesDocument.children = new ArrayCollection(pagesDocument.children.toArray().slice(0, pageIndex));
                  else
                      pagesDocument.children = null;

       

      I can confirm that the issue does NOT happen if I use ArrayCollection functions, ala:

       

                  // store the length of pagesDocument's pages in a variable, because the real length will decrease by one each time we remove a child from the document.
                  // In addition to this keep in mind that after removing a child the subsequent child will take its place, thus we retrieve and remove nodes at the same index: pageIndex.
                  var pageCount:int = pagesDocument.children.length;
                  // initialise vars since doing so in a loop can affect performance
                  var pageNode:Object;
                  for (var i:int = pageIndex; i < pageCount; i++)
                  {
                      // create children prop if it doesn't exist
                      if (i == (pageIndex+1))
                          newDocument.children = new ArrayCollection();
                     
                      // copy page into var
                      pageNode = pagesDocument.children.getItemAt(pageIndex);
                     
                      // remove page from document's pages
                      pagesDocument.children.removeItemAt(pageIndex);
                     
                      // add page to end of the new document. Don't add first page since it is becoming the document.
                      if (i != pageIndex)
                          newDocument.children.addItem( pageNode );
                  }

       

      It takes several seconds to create a document using the ArrayCollection functions when there are only 1000 rows in the Tree whilst the Array functions do it in less than a second.  Using the ArrayCollection functions is not an option due to the poor performance when there are a decent amount of rows.

       

      The following is the steps to reproduce the issue in the component along with screenshots.

       

      If I create a new document (by hitting Enter, Space or double clicking on a page, in this instance 0277) and the document is the last one in the list (that is, the issue does not occur if I create a document between two existing documents) the component creates the document and all looks fine on screen.

      PriorToCreatingBranch.jpgBranchCreated.jpg

       

      However, if I scroll up, the first row in the Tree is not actually the first row but  another row that is X rows below what should be the first row (759 rows in this instance).

      ScrollToTop.jpg

      If I then scroll down rows will suddenly go blank or be a repeat of the last row.

      ScrollToBottom.jpg

      The underlying data for each row is still correct, so if the first displayed row is now page 92 its data is page 92 - I know this because we have a click event which calls some external Javascript which loads the file the page represents.  However, if a row has been made blank it does not have any associated data and cannot be selected.

       

      If I then do Ctrl+Home to take me to the top, the display rectifies and the first row is actually displayed.

       

      The issue still exists if the scrolling steps are reversed, i.e. scroll down first then scroll up and the rows are missing / offset, then do Ctrl+End to rectify the data.

       

      I'm at a loss as to what is happening here. I have tried running invalidateList and invalidateDisplayList after manipulating the children of the relevant branches but this does not resolve the issue.

       

      Anyone have any ideas?

       

      I have posted this as a bug a few weeks ago on https://bugs.adobe.com/ (SDK-26677) but have not gotten any response.

       

      I also have what I think is another bug where the scroll bar disappears when I delete a document and use the Array functions, but I'll put that in a separate post later because the boss is pushing me to work on something else.

       

      Thanks

       

      Nathan

        • 1. Re: Bug? Create a branch in a Tree and other rows go blank and get offset
          Flex harUI Adobe Employee

          ArrayCollection dispatches notifications when change are made so the Tree

          can follow along.  Array does not.  In theory, if you reset the dataProvider

          (or maybe fake a CollectionEvent with CollectionEventKind.RESET) the Tree

          will reset after you make all those Array changes.

          • 2. Re: Bug? Create a branch in a Tree and other rows go blank and get offset
            RustyAxeSys Level 1

            Thanks for the prompt reply Alex. I really do appreciate it.

             

            However, if it was the Array methods that were the issue why is it working when the new branch is not the last branch in the tree? The same code is used irrelevant of where the branch is in the tree and the issue only occurs when a new branch is created and it is the last branch in the tree.

             

            I am using ArrayCollections, albeit in association with Array methods.  I set the children of the document branches to be ArrayCollections populated with an Array that is populated with another branch's children, like so:

             

                            newDocument.children = new ArrayCollection(pagesDocument.children.toArray().slice(pageIndex+1, pagesDocument.children.length));

             

            Perhaps it may help to see the relevant code (in a component that extends Tree (only relevant code included)):

             

            private function createDocument(page:Object, pagesDocument:Object, changeSelectedItem:Boolean=true):void { // page = page being converted to a document, pagesDocument = the page's parent document


                        var folder:Object = this.dataProvider[0]; // Folder - contains documents
                        var documents:ArrayCollection = folder.children;
                       
                        var pageIndex:int = pagesDocument.children.getItemIndex(page); // page's index in its parent document's children
                        var docIndex:int = documents.getItemIndex(pagesDocument); // document's index in the folder's children

             

                        // create new document
                        var newDocument:Object = { type:'Document', data:'', label:setFullStartPage(page.label), SHA: SHA, exts:page.exts };
                       
                        // copy relevant pages from pagesDocument to newDocument
                        if (pagesDocument.children.length > (pageIndex+1))
                            newDocument.children = new ArrayCollection(pagesDocument.children.toArray().slice(pageIndex+1, pagesDocument.children.length));
                       
                        // delete newDoc's pages from pagesDocument
                        if (pageIndex > 0)
                            pagesDocument.children = new ArrayCollection(pagesDocument.children.toArray().slice(0, pageIndex));
                        else
                            pagesDocument.children = null;
                       
                        // add the new document after this page's document
                        folder.children.addItemAt( newDocument, ++docIndex );

             

                        // expand the new document
                        this.expandItem(newDocument, true);

            ....

            ....

            }

             

            I'm happy to provide more info if you need.

             

            Thanks

             

            Nathan

            • 3. Re: Bug? Create a branch in a Tree and other rows go blank and get offset
              Flex harUI Adobe Employee

              It might be that the children collection are cached by the

              ITreeDataDescriptor.

              • 4. Re: Bug? Create a branch in a Tree and other rows go blank and get offset
                Flex harUI Adobe Employee

                It might be that the children collection are cached by the

                ITreeDataDescriptor.