Index: /trunk/grails-app/controllers/TaskDetailedController.groovy
===================================================================
--- /trunk/grails-app/controllers/TaskDetailedController.groovy	(revision 195)
+++ /trunk/grails-app/controllers/TaskDetailedController.groovy	(revision 196)
@@ -14,5 +14,5 @@
     static allowedMethods = [save:'POST', update:'POST', restore:'POST', trash:'POST', approve:'POST', renegeApproval:'POST', complete:'POST', reopen:'POST']
 
-    def index = { redirect(action:search,params:params) }
+    def index = { redirect(action: 'search', params: params) }
 
     def list = {
@@ -163,5 +163,5 @@
         if(!taskInstance) {
             flash.message = "Task not found with id ${params.id}"
-            redirect(action:search)
+            redirect(action: 'search')
         }
         else {
@@ -180,6 +180,6 @@
                                                         }
 
-            def subTaskInstanceList = Task.findAllByParentTask(taskInstance, params)
-            def subTaskInstanceTotal = Task.countByParentTask(taskInstance)
+            def subTaskInstanceList = Task.findAllByParentTaskAndTrash(taskInstance, false, params)
+            def subTaskInstanceTotal = Task.countByParentTaskAndTrash(taskInstance, false)
             def showTaskTab = new String("true")
 
@@ -225,5 +225,5 @@
         if(!Task.exists(params.id)) {
             flash.message = "Task not found with id ${params.id}"
-            redirect(action:'search')
+            redirect(action: 'search')
         }
 
@@ -232,13 +232,13 @@
         if(!result.error) {
                 flash.message = "Task ${params.id} has been restored."
-                redirect(action:show,id:result.taskInstance.id)
-        }
-        else {
-            if(result.taskInstance) {
-                render(view:'edit',model:[taskInstance:result.taskInstance])
-            }
-            else {
-                flash.message = "Task could not be updated."
-                redirect(action:'search')
+                redirect(action: 'show', id: result.taskInstance.id)
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'edit',model:[taskInstance:result.taskInstance])
+            }
+            else {
+                flash.message = "Task could not be updated."
+                redirect(action: 'search')
             }
         }
@@ -250,5 +250,5 @@
         if(!Task.exists(params.id)) {
             flash.message = "Task not found with id ${params.id}."
-            redirect(action:'search')
+            redirect(action: 'search')
         }
 
@@ -257,13 +257,13 @@
         if(!result.error) {
                 flash.message = "Task ${params.id} has been moved to trash."
-                redirect(action:'search')
-        }
-        else {
-            if(result.taskInstance) {
-                render(view:'edit',model:[taskInstance:result.taskInstance])
-            }
-            else {
-                flash.message = "Task could not be updated."
-                redirect(action:'search')
+                redirect(action: 'search')
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'edit',model:[taskInstance:result.taskInstance])
+            }
+            else {
+                flash.message = "Task could not be updated."
+                redirect(action: 'search')
             }
         }
@@ -275,5 +275,5 @@
         if(!Task.exists(params.id)) {
             flash.message = "Task not found with id ${params.id}."
-            redirect(action:'search')
+            redirect(action: 'search')
         }
 
@@ -282,13 +282,13 @@
         if(!result.error) {
                 flash.message = "Task ${params.id} has been approved."
-                redirect(action:show,id:result.taskInstance.id)
-        }
-        else {
-            if(result.taskInstance) {
-                render(view:'edit',model:[taskInstance:result.taskInstance])
-            }
-            else {
-                flash.message = "Task could not be updated."
-                redirect(action:'search')
+                redirect(action: 'show', id: result.taskInstance.id)
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'edit',model:[taskInstance:result.taskInstance])
+            }
+            else {
+                flash.message = "Task could not be updated."
+                redirect(action: 'search')
             }
         }
@@ -300,5 +300,5 @@
         if(!Task.exists(params.id)) {
             flash.message = "Task not found with id ${params.id}."
-            redirect(action:'search')
+            redirect(action: 'search')
         }
 
@@ -307,13 +307,13 @@
         if(!result.error) {
                 flash.message = "Task ${params.id} has had approval removed."
-                redirect(action:show,id:result.taskInstance.id)
-        }
-        else {
-            if(result.taskInstance) {
-                render(view:'edit',model:[taskInstance:result.taskInstance])
-            }
-            else {
-                flash.message = "Task could not be updated."
-                redirect(action:'search')
+                redirect(action: 'show', id: result.taskInstance.id)
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'edit',model:[taskInstance:result.taskInstance])
+            }
+            else {
+                flash.message = "Task could not be updated."
+                redirect(action: 'search')
             }
         }
@@ -325,5 +325,5 @@
         if(!Task.exists(params.id)) {
             flash.message = "Task not found with id ${params.id}."
-            redirect(action:'search')
+            redirect(action: 'search')
         }
 
@@ -332,13 +332,13 @@
         if(!result.error) {
                 flash.message = "Task ${params.id} has been completed."
-                redirect(action:show,id:result.taskInstance.id)
-        }
-        else {
-            if(result.taskInstance) {
-                render(view:'edit',model:[taskInstance:result.taskInstance])
-            }
-            else {
-                flash.message = "Task could not be updated."
-                redirect(action:'search')
+                redirect(action: 'show', id: result.taskInstance.id)
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'edit',model:[taskInstance:result.taskInstance])
+            }
+            else {
+                flash.message = "Task could not be updated."
+                redirect(action: 'search')
             }
         }
@@ -350,5 +350,5 @@
         if(!Task.exists(params.id)) {
             flash.message = "Task not found with id ${params.id}."
-            redirect(action:'search')
+            redirect(action: 'search')
         }
 
@@ -357,13 +357,13 @@
         if(!result.error) {
                 flash.message = "Task ${params.id} has been reopened."
-                redirect(action:show,id:result.taskInstance.id)
-        }
-        else {
-            if(result.taskInstance) {
-                render(view:'edit',model:[taskInstance:result.taskInstance])
-            }
-            else {
-                flash.message = "Task could not be updated."
-                redirect(action:'search')
+                redirect(action: 'show', id: result.taskInstance.id)
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'edit',model:[taskInstance:result.taskInstance])
+            }
+            else {
+                flash.message = "Task could not be updated."
+                redirect(action: 'search')
             }
         }
@@ -381,18 +381,13 @@
         if(!taskInstance) {
             flash.message = "Task not found with id ${params.id}"
-            redirect(action:search)
+            redirect(action: 'search')
         }
         else {
             if(taskInstance.trash) {
-                flash.message = "You may not edit items in the trash."
-                redirect(action:show,id:taskInstance.id)
-            }
-            def criteria = taskInstance.createCriteria()
-            def possibleParentList = criteria {
-                and {
-                    notEqual('id', taskInstance.id)
-                    taskInstance.subTasks.each() { notEqual('id', it.id) }
-                    }
-            }
+                flash.message = "You may not edit tasks that are in the trash."
+                redirect(action: 'show', id: taskInstance.id)
+                return
+            }
+            def possibleParentList = taskService.possibleParentList(taskInstance)
             return [ taskInstance : taskInstance, possibleParentList: possibleParentList ]
         }
@@ -403,5 +398,5 @@
         if(!Task.exists(params.id)) {
             flash.message = "Task not found with id ${params.id}"
-            redirect(action:'search')
+            redirect(action: 'search')
         }
 
@@ -410,13 +405,13 @@
         if(!result.error) {
                 flash.message = "Task ${params.id} updated"
-                redirect(action:show,id:result.taskInstance.id)
-        }
-        else {
-            if(result.taskInstance) {
-                render(view:'edit',model:[taskInstance:result.taskInstance])
-            }
-            else {
-                flash.message = "Task could not be updated."
-                redirect(action:'search')
+                redirect(action: 'show', id: result.taskInstance.id)
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'edit',model:[taskInstance:result.taskInstance])
+            }
+            else {
+                flash.message = "Task could not be updated."
+                redirect(action: 'search')
             }
         }
@@ -453,8 +448,8 @@
     def create = {
         def taskInstance = new Task()
-        // Default leadPerson to current user.
+        // Default leadPerson to current user, unless supplied in params.
         taskInstance.leadPerson = personService.currentUser()
         taskInstance.properties = params
-        return ['taskInstance':taskInstance]
+        return ['taskInstance': taskInstance]
     }
 
@@ -464,13 +459,13 @@
         if(!result.error) {
             flash.message = "Task ${result.taskInstance.id} created."
-            redirect(action: show,id: result.taskInstance.id)
-        }
-        else {
-            if(result.taskInstance) {
-                render(view:'create',model:[taskInstance:result.taskInstance])
+            redirect(action: 'show', id: result.taskInstance.id)
+        }
+        else {
+            if(result.taskInstance) {
+                render(view:'create', model:[taskInstance:result.taskInstance])
             }
             else {
                 flash.message = "Could not create task."
-                redirect(action:"search")
+                redirect(action: 'search')
             }
 
@@ -483,10 +478,10 @@
         if(!parentTaskInstance) {
             flash.message = "Task not found with id ${params.id}"
-            redirect(action:search)
+            redirect(action: 'search')
         }
         else {
         params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
-        def subTaskInstanceList = Task.findAllByParentTask(parentTaskInstance, params)
-        def subTaskInstanceTotal = Task.countByParentTask(parentTaskInstance)
+        def subTaskInstanceList = Task.findAllByParentTaskAndTrash(parentTaskInstance, false, params)
+        def subTaskInstanceTotal = Task.countByParentTaskAndTrash(parentTaskInstance, false)
 
         [ taskInstanceList: subTaskInstanceList,
@@ -496,3 +491,30 @@
     }
 
-}
+    def createSubTask = {
+        def parentTaskInstance = Task.get(params.id)
+
+        if(parentTaskInstance) {
+
+            def result = taskService.createSubTask(parentTaskInstance)
+            if(!result.error) {
+                flash.message = "Sub Task ${result.taskInstance.id} created, please edit and update to your requirements."
+                redirect(action: 'edit', id: result.taskInstance.id)
+            }
+            else {
+                if(result.taskInstance.errors.hasFieldErrors("parentTask")) {
+                    flash.message = g.message(code:"task.operationNotPermittedOnTaskInTrash")
+                    redirect(action: 'show', id:  parentTaskInstance.id)
+                }
+                else {
+                    render(view: 'create', model:[taskInstance: result.taskInstance])
+                }
+            }
+        }
+
+        else {
+            flash.message = "Task not found with id ${params.id}"
+            redirect(action: 'search')
+        }
+    }
+
+} // end of class.
Index: /trunk/grails-app/i18n/messages.properties
===================================================================
--- /trunk/grails-app/i18n/messages.properties	(revision 195)
+++ /trunk/grails-app/i18n/messages.properties	(revision 196)
@@ -27,4 +27,5 @@
 task.modifications.failedToSave=Could not complete operation, as task modification record failed to save.
 task.operationNotPermittedOnCompleteTask=This operation is not permitted on a complete task.
+task.operationNotPermittedOnTaskInTrash=This operation is not permitted on a task that is in the trash.
 
 task.assignedPersons=Assigned Persons
Index: /trunk/grails-app/services/TaskService.groovy
===================================================================
--- /trunk/grails-app/services/TaskService.groovy	(revision 195)
+++ /trunk/grails-app/services/TaskService.groovy	(revision 196)
@@ -1,2 +1,6 @@
+/*
+* Provides a service for the Task domain class.
+*
+*/
 class TaskService {
 
@@ -6,4 +10,25 @@
     def personService
 
+    /*
+    * Determines and returns a possible parent list
+    * @taskInstance The task to use when determining the possible parent list.
+    * @returns A list of the possible parents.
+    */
+    def possibleParentList(taskInstance) {
+        def criteria = taskInstance.createCriteria()
+        def possibleParentList = criteria {
+            and {
+                notEqual('trash', true)
+                notEqual('id', taskInstance.id)
+                taskInstance.subTasks.each() { notEqual('id', it.id) }
+                }
+        }
+    }
+
+    /*
+    * Creates a new task with the given params.
+    * @params The params to use when creating the new task.
+    * @returns A map containing result.error=true (if any error) and result.taskInstance.
+    */
     def create(params) {
         Task.withTransaction { status ->
@@ -13,4 +38,11 @@
             def taskInstance = new Task(params)
             result.taskInstance = taskInstance
+
+            if(result.taskInstance.parentTask?.trash) {
+                status.setRollbackOnly()
+                result.taskInstance.errors.rejectValue("parentTask", "task.operationNotPermittedOnTaskInTrash")
+                result.error = true
+                return result
+            }
 
             if(taskInstance.save()) {
@@ -26,4 +58,5 @@
                 }
 
+                // If we get here all went well.
                 return result
             }
@@ -36,4 +69,48 @@
     } // end create()
 
+    /*
+    * Creates a subTask copying attributes from the parentTask unless otherwise specified.
+    * @param parentTask The parent task to get attributes from, also set as the parent.
+    * @param params Overrides the parent task values if specified.
+    * @returns A map containing result.error=true (if any error) and result.taskInstance.
+    */
+    def createSubTask(parentTask, params = [:]) {
+
+        def result = [:]
+
+        //Make our new Task a subTask and set the required properites.
+        def p = [:]
+        p.parentTask = parentTask
+        p.description = params.description ?: parentTask.description
+        p.comment = params.comment ?: parentTask.comment
+
+        p.taskGroup = params.taskGroup ?: parentTask.taskGroup
+        p.taskStatus = TaskStatus.get(1) // A new subTask must always be "Not Started".
+        p.taskPriority = parentTask.taskPriority
+        p.taskType = params.taskType ?: parentTask.taskType
+        p.leadPerson = params.leadPerson ?: parentTask.leadPerson
+        p.primaryAsset = params.primaryAsset ?: parentTask.primaryAsset
+
+        p.targetStartDate = params.targetStartDate ?: parentTask.targetStartDate
+        p.targetCompletionDate = params.targetCompletionDate ?: parentTask.targetCompletionDate
+
+                    //Set the assignedPersons
+//                     taskInstance.assignedPersons.each() {
+// 
+//                     def assignedPerson = new AssignedPerson(person: it.person,
+//                                                                                             task: subTaskInstance,
+//                                                                                             estimatedHour: it.estimatedHour,
+//                                                                                             estimatedMinute: it.estimatedMinute).save()
+//                     }
+
+        result = create(p)
+
+    } // end createSubTask()
+
+    /*
+    * Creates a new task entry.
+    * @params The params to use when creating the new entry.
+    * @returns A map containing result.error=true (if any error), result.entryInstance and result.taskId.
+    */
     def createEntry(params) {
         Task.withTransaction { status ->
Index: /trunk/grails-app/views/taskDetailed/create.gsp
===================================================================
--- /trunk/grails-app/views/taskDetailed/create.gsp	(revision 195)
+++ /trunk/grails-app/views/taskDetailed/create.gsp	(revision 196)
@@ -122,5 +122,5 @@
                                 </td>
                                 <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'parentTask','errors')}">
-                                    <g:select optionKey="id" from="${Task.list()}" name="parentTask.id" value="${taskInstance?.parentTask?.id}" noSelection="['null':'--None--']"></g:select>
+                                    <g:select optionKey="id" from="${Task.findAllByTrash(false)}" name="parentTask.id" value="${taskInstance?.parentTask?.id}" noSelection="['null':'--None--']"></g:select>
                                 </td>
                             </tr> 
Index: /trunk/grails-app/views/taskDetailed/edit.gsp
===================================================================
--- /trunk/grails-app/views/taskDetailed/edit.gsp	(revision 195)
+++ /trunk/grails-app/views/taskDetailed/edit.gsp	(revision 196)
@@ -5,5 +5,5 @@
         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
         <meta name="layout" content="main" />
-        <title>Edit Task</title>
+        <title>Edit Task #${taskInstance.id}</title>
         <nav:resources override="true"/>
         <resource:dateChooser />
Index: /trunk/grails-app/views/taskDetailed/listSubTasks.gsp
===================================================================
--- /trunk/grails-app/views/taskDetailed/listSubTasks.gsp	(revision 195)
+++ /trunk/grails-app/views/taskDetailed/listSubTasks.gsp	(revision 196)
@@ -11,8 +11,14 @@
         </div>
         <div class="body">
-            <h1>Task #${parentTaskInstance.id} sub tasks</h1>
+             <g:link action="show" id="${parentTaskInstance.id}">
+                <h1>Task #${parentTaskInstance.id} sub tasks.</h1>
+            </g:link>
             <g:if test="${flash.message}">
                 <div class="message">${flash.message}</div>
             </g:if>
+
+            <div class="paginateButtons">
+                Results:${taskInstanceTotal}
+            </div>
             <div class="list">
                 <input type="hidden" name="parentTaskId" value="${parentTaskInstance?.id}" />
Index: /trunk/grails-app/views/taskDetailed/show.gsp
===================================================================
--- /trunk/grails-app/views/taskDetailed/show.gsp	(revision 195)
+++ /trunk/grails-app/views/taskDetailed/show.gsp	(revision 196)
@@ -3,5 +3,5 @@
         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
         <meta name="layout" content="main" />
-        <title>Show Task</title>
+        <title>Show Task #${taskInstance.id}</title>
         <g:javascript src="overlayPane.js" />
         <nav:resources override="true"/>
@@ -677,5 +677,5 @@
                             <div class="buttons">
                                 <g:form>
-                                    <input type="hidden" name="id" value="${taskInstance?.id}" />
+                                    <g:hiddenField name="id" value="${taskInstance?.id}" />
                                     <g:if test="${subTaskInstanceTotal > subTaskInstanceMax}">
                                         Showing ${subTaskInstanceMax} of ${subTaskInstanceTotal}
@@ -686,5 +686,6 @@
                                         <br />
                                     </g:else>
-                                    <span class="button"><g:actionSubmit action="listSubTasks" class="table" value="Sortable List" /></span>
+                                    <span class="button"><g:actionSubmit action="listSubTasks" class="table" value="List" /></span>
+                                    <span class="button"><g:actionSubmit action="createSubTask" class="add" value="Add" /></span>
                                 </g:form>
                             </div>
@@ -694,4 +695,13 @@
                             <br />
                             No Sub Tasks.
+                            <br />
+                            <br />
+
+                            <div class="buttons">
+                                <g:form>
+                                    <g:hiddenField name="id" value="${taskInstance?.id}" />
+                                    <span class="button"><g:actionSubmit action="createSubTask" class="add" value="Add" /></span>
+                                </g:form>
+                            </div>
                         </g:else>
 
