### Eclipse Workspace Patch 1.0
#P tracjsganttplugin
Index: tracjsgantt/tracjsgantt.py
===================================================================
--- tracjsgantt/tracjsgantt.py	(revision 13339)
+++ tracjsgantt/tracjsgantt.py	(working copy)
@@ -152,9 +152,11 @@
 
     """
 
+    # Faster lookups for WBS and scheduling.
+    ticketsByID = {}
     pm = None
     options = {}
-
+    
     # The date part of these formats has to be in sync.  Including
     # hour and minute in the pyDateFormat makes the plugin easier to
     # debug at times because that's how the date shows up in page
@@ -572,6 +574,9 @@
                 else:
                     displayFilter[field] = [ value ]
 
+        self.env.log.debug("Tickets available: %s", len(tickets))
+        self.ticketsByID.clear()
+                
         # If present and 1, true, otherwise false.
         if options.get('omitMilestones') \
                 and int(options['omitMilestones']) == 1:
@@ -599,8 +604,9 @@
                             break
                         display = False
                     fieldDisplay = fieldDisplay & display
-
+            
             if fieldDisplay:
+                self.ticketsByID[ticket['id']] = ticket
                 filteredTickets.append(ticket)
 
         
@@ -681,11 +687,76 @@
 
             # Sort the remaining tickets for display (based on order option).
             displayTickets = self._sortTickets(displayTickets, options)
-
+            
+            self.env.log.debug("Tickets to show (no parent rel): %s", len(displayTickets))
+            parentRel = dict()
+            i = 0
             for ticket in displayTickets:
+                self.env.log.debug("Processing ticket: #%s", ticket['id'])                           
+                parentId = self.pm.parent(ticket)
+                self.env.log.debug("with parent ticket: #%s", parentId)
+                #Is parent ticket visible
+                if parentId in self.ticketsByID:
+                    self.env.log.debug("Parent ticket: #%s is visible", parentId)
+                    t = self._traverse_early_first(parentId, parentRel)
+                    if t != None:
+                        self.env.log.debug("Parent ticket: #%s already exists", parentId)
+                        t.update({(i, ticket['id']): {}})
+                    else:
+                        self.env.log.debug("Parent ticket: #%s doen't exists, adding...", parentId)
+                        parentRel[(i, parentId)] = {(i, ticket['id']): {}}
+                #Parent ticket is not visible
+                else:
+                    self.env.log.debug("Parent ticket: #%s is NOT visible or ticket have no parent", parentId)
+                    t = self._traverse_early_first(ticket['id'], parentRel)
+                    if t == None:
+                        self.env.log.debug("Ticket: #%s doesn't exists, adding", ticket['id'])
+                        parentRel[(i, ticket['id'])] = {}
+                    else:
+                        self.env.log.debug("Ticket: #%s exists already", ticket['id'])
+                i = i + 1
+            
+            self.env.log.debug("Tickets in parentRel (1 Level): %s", len(parentRel))
+            displayTickets = list()
+            self._traverse_deepest_first(parentRel, displayTickets)
+            self.env.log.debug("Tickets to show (with parent rel): %s", len(displayTickets))
+            
+            for ticket in displayTickets:
                 tasks += self._format_ticket(ticket, options)
 
         return tasks
+    
+    def _compare_keys(self, t1, t2):
+        # If t1 seq number is greater than t2, t2 is first
+        if t1[0] > t2[0]:
+            return 1
+        # If t2 seq number is greater than t1, t1 is first
+        elif t2[0] > t1[0]:
+            return -1
+        else:
+            return 0
+    
+    def _traverse_deepest_first(self, src, dst):
+        #Sorting by level
+        keys = src.keys()
+        keys.sort(self._compare_keys)
+        for key in keys:
+            ticketId = key
+            self.env.log.debug("Ticket: #%s doesn't exists, adding", ticketId[1])
+            dst.append(self.ticketsByID[ticketId[1]])
+            self._traverse_deepest_first(src[ticketId], dst)
+            
+    def _traverse_early_first(self, id, dic):
+        for key in dic.iterkeys():
+            if id == key[1]:
+                return dic[key]
+        
+        for sub in dic:
+            t = self._traverse_early_first(id, dic[sub])
+            if t != None:
+                return t
+        
+        return None      
 
     def _parse_options(self, content):
         _, options = parse_args(content, strict=False)
