Index: css/modal.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/css/modal.css,v
retrieving revision 1.5
diff -U3 -r1.5 modal.css
--- css/modal.css	17 Apr 2009 19:16:19 -0000	1.5
+++ css/modal.css	12 Jun 2009 14:58:41 -0000
@@ -77,6 +77,10 @@
   margin-left: 2em;
 }
 
+div.ctools-modal-content .form-item .form-radios {
+  margin-left: 15em;
+}
+
 div.ctools-modal-content .no-float .form-item * {
   float: none;
 }
Index: delegator/plugins/tasks/page.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/delegator/plugins/tasks/page.admin.inc,v
retrieving revision 1.22
diff -U3 -r1.22 page.admin.inc
--- delegator/plugins/tasks/page.admin.inc	19 May 2009 18:52:18 -0000	1.22
+++ delegator/plugins/tasks/page.admin.inc	12 Jun 2009 14:58:45 -0000
@@ -437,6 +437,8 @@
         'id' => '',
         'identifier' => '',
         'argument' => '',
+        'default_action' => 'ignore',
+        'default_argument' => '',
         'settings' => array(),
       );
     }
@@ -1144,6 +1146,8 @@
     'id' => $id,
     'identifier' => $title . ($id > 1 ? ' ' . $id : ''),
     'name' => $argument,
+    'default_action' => 'ignore',
+    'default_argument' => '',
     'settings' => $settings,
   );
 }
@@ -1168,6 +1172,11 @@
     return;
   }
 
+  // Find out if this is an optional argument.
+  $names = delegator_page_get_named_arguments($page->path);
+  $bits = explode('/', $page->path);
+  $optional = ($bits[$names[$keyword]][0] == '!');
+
   ctools_include('context');
   $plugin = ctools_get_argument($conf['name']);
 
@@ -1181,6 +1190,26 @@
     '#description' => t('This is the title of the context used to identify it later in the administrative process. This will never be shown to a user.'),
     '#default_value' => $conf['identifier'],
   );
+  
+  if ($optional) {
+    $options = array(
+      'ignore'    => t('Ignore argument'),
+      'not found' => t('Hide page / Page not found (404)'),
+      'default'   => t('Provide default argument'),
+    );
+    
+    $form['default_action'] = array(
+      '#type' => 'radios',
+      '#title' => t('Action to take if argument is not present'),
+      '#options' => $options,
+      '#default_value' => !empty($conf['default_action']) ? $conf['default_action'] : 'ignore',
+    );
+    $form['default_argument'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Default argument'),
+      '#default_value' => $conf['default_argument'],
+    );
+  }
 
   if (!$plugin) {
     // This should be impossible and thus never seen.
@@ -1202,6 +1231,15 @@
   if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form validate')) {
     $function($form, $form_state);
   }
+
+  if ($form_state['values']['op'] == 'Finish' && isset($form_state['values']['default_action'])) {
+    // Deal with an optional argument
+    if ($form_state['values']['default_action'] == 'default' && empty($form_state['values']['default_argument'])) {
+      // A default argument was set as the option, so make sure a default
+      // argument is actually provided
+      form_set_error('default_argument', t('<em>Provide default argument</em> was select as the action to take if the argument was not present. However, no default was provided.'));
+    }
+  }
 }
 
 /**
@@ -1223,6 +1261,14 @@
   // finished. Yes, finished is always next but finish can happen from other
   // locations so we funnel through that path rather than duplicate.
   $page->temporary_arguments[$keyword]['identifier'] = $form_state['values']['identifier'];
+  if (isset($form_state['values']['default_action'])) {
+    $page->temporary_arguments[$keyword]['default_action'] = $form_state['values']['default_action'];
+    $page->temporary_arguments[$keyword]['default_argument'] = $form_state['values']['default_argument'];
+  }
+  else {
+    $page->temporary_arguments[$keyword]['default_action'] = 'ignore';
+    $page->temporary_arguments[$keyword]['default_argument'] = '';
+  }
   if (isset($form_state['values']['settings'])) {
     $page->temporary_arguments[$keyword]['settings'] = $form_state['values']['settings'];
   }
Index: delegator/plugins/tasks/page.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ctools/delegator/plugins/tasks/page.inc,v
retrieving revision 1.24
diff -U3 -r1.24 page.inc
--- delegator/plugins/tasks/page.inc	8 May 2009 22:36:29 -0000	1.24
+++ delegator/plugins/tasks/page.inc	12 Jun 2009 14:58:45 -0000
@@ -309,11 +309,27 @@
   if ($page->arguments) {
     foreach ($page->arguments as $name => $argument) {
       // Optional arguments must be converted to contexts too, if they exist.
-      if ($bits[$names[$name]][0] == '!' && isset($args[$count])) {
-        $argument['keyword'] = $name;
-        ctools_include('context');
-        $context = ctools_context_get_context_from_argument($argument, $args[$count]);
-        $contexts[$context->id] = $context;
+      if ($bits[$names[$name]][0] == '!') {
+        if (isset($args[$count])) {
+          $argument['keyword'] = $name;
+          ctools_include('context');
+          $context = ctools_context_get_context_from_argument($argument, $args[$count]);
+          $contexts[$context->id] = $context;
+        }
+        elseif (isset($argument['default_action'])) {
+          // No argument was provided in the URL, so let's see if any actions
+          // were specified if no argument was present
+          if ($argument['default_action'] == 'default') {
+            $argument['keyword'] = $name;
+            ctools_include('context');
+            $context = ctools_context_get_context_from_argument($argument, $argument['default_argument']);
+            $contexts[$context->id] = $context;
+          }
+          elseif ($argument['default_action'] == 'not found') {
+            return drupal_not_found();
+          }
+          // Continue as normal if 'ignore' was specified
+        }
       }
       $count++;
     }
