### Eclipse Workspace Patch 1.0
#P tracjsganttplugin
Index: tracjsgantt/tracjsgantt.py
===================================================================
--- tracjsgantt/tracjsgantt.py	(revision 11513)
+++ tracjsgantt/tracjsgantt.py	(working copy)
@@ -129,6 +129,8 @@
     """
 
     pm = None
+    # Faster lookups for WBS and scheduling.
+    ticketsByID = {}
 
     def __init__(self):
         # Instantiate the PM component
@@ -302,11 +304,11 @@
         query = Query.from_string(self.env, query_string)
 
         # Get all tickets 
- 	rawtickets = query.execute(self.req) 
+        rawtickets = query.execute(self.req) 
 
- 	# Do permissions check on tickets 
- 	tickets = [t for t in rawtickets  
-                   if 'TICKET_VIEW' in self.req.perm('ticket', t['id'])] 
+        # Do permissions check on tickets 
+        tickets = [t for t in rawtickets  
+            if 'TICKET_VIEW' in self.req.perm('ticket', t['id'])] 
 
         return tickets
 
@@ -595,28 +597,114 @@
                 displayFilter = {}
                 for f in displayList:
                     field, value = f.split(':')
-                    displayFilter[field] = value
-                    
+                    values = value.split('|')
+                    if field in displayFilter:
+                        displayFilter[field].extend(values)
+                    else:
+                        displayFilter[field] = values
+
                 # Filter the tickets
                 displayTickets = []
+                self.env.log.debug("Tickets available: %s",
+                           len(self.tickets))
+                self.ticketsByID.clear()
                 for ticket in self.tickets:
                     # Default to showing every ticket
-                    display = True
-                    # Process each element and disable display if any
-                    # filter fails to match.
+                    fieldDisplay = True
+                    # Process each element and disable display if all
+                    # filters fails to match. ((or) disjunction)
                     for f in displayFilter:
-                        if ticket[f] != displayFilter[f]:
+                        display = True
+                        for v in displayFilter[f]:
+                            if ticket[f] == v:
+                                #self.env.log.debug("Display filter match '%s': '%s' for ticket #%s",
+                                #   f,
+                                #   v,
+                                #   ticket['id'])
+                                display = True
+                                break
+                            #self.env.log.debug("Display filter '%s' not match: '%s' for ticket #%s",
+                            #    f,
+                            #    v,
+                            #    ticket['id'])
                             display = False
-                    if display:
+                        fieldDisplay = fieldDisplay & display
+                    if fieldDisplay:
                         displayTickets.append(ticket)
+                        self.ticketsByID[ticket['id']] = ticket
 
-                # Sort the tickets
+                # Sort the tickets by date and successor dependencies
                 displayTickets.sort(self._compare_tickets)
-
+            
+            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)
