diff --git a/css/panels_dnd.css b/css/panels_dnd.css
index c6ead09..e754621 100644
--- a/css/panels_dnd.css
+++ b/css/panels_dnd.css
@@ -325,9 +325,10 @@ a.close img {
 }
 
 .panels-categories-description {
-  padding: 0 1em;
   text-align: center;
   vertical-align: center;
+  line-height: 1.1em;
+  margin-bottom: 1em;
 }
 
 * html .panels-section-column-categories {
diff --git a/js/display_editor.js b/js/display_editor.js
index e9554e8..d6a6785 100644
--- a/js/display_editor.js
+++ b/js/display_editor.js
@@ -441,6 +441,112 @@ Drupal.Panels.DraggableHandler = function() {
   $(this).mousedown(mouseDown);
 };
 
+Drupal.behaviors.PanelsSearchOptions = {};
+
+Drupal.behaviors.PanelsSearchOptions.attach = function (context) {
+  var $ = jQuery;
+  var $form = $(context).find('#panels-select-content-search').first();
+  // Make sure we don't add more than one event handler to the same form.
+  $form = $form.once('panels-select-content-search');
+  if ($form.length) {
+    var $content = $(context).find('.panels-select-content-categories .vertical-tabs-panes').first();
+    new Drupal.Panels.OptionsSearch($form, $content);
+  }
+};
+
+Drupal.Panels.OptionsSearch = function($searchBox, $content) {
+  this.$searchBox = $searchBox;
+  this.$content = $content;
+  // Add a keyup,focus handler to the search box.
+  this.$searchBox.keyup(jQuery.proxy(this.handleKeyup, this));
+  this.$searchBox.focus(jQuery.proxy(this.handleFocus, this));
+  // Get a list of option labels and their corresponding divs and maintain it
+  // in memory, so we have as little overhead as possible at keyup time.
+  this.options = this.getOptions(this.$content);
+  // Restripe on initial loading.
+  this.handleKeyup();
+  // Trap the ENTER key in the search box so that it doesn't submit the form.
+  this.$searchBox.keypress(function(event) {
+    if (event.which == 13) {
+      event.preventDefault();
+    }
+  });
+};
+
+/**
+ * Assemble a list of all the filterable options on the form.
+ *
+ * @param $allOptions
+ *   A jQuery object representing the rows of filterable options to be
+ *   shown and hidden depending on the user's search terms.
+ */
+Drupal.Panels.OptionsSearch.prototype.getOptions = function ($content) {
+  var $ = jQuery;
+  var i, $label, $option;
+  var options = [];
+  var $allOptions = $content.find('a.panels-add-content-text');
+  var length = $allOptions.length;
+  for (i = 0; i < length; i++) {
+    $option = $($allOptions[i]);
+    $label = $option;
+    options[i] = {
+      // Search on the lowercase version of the label text
+      'searchText': $label.text().toLowerCase(),
+      // Maintain a reference to the jQuery object for each row, so we don't
+      // have to create a new object inside the performance-sensitive keyup
+      // handler.
+      '$div': $option.parents('div.content-type-button')
+    }
+  }
+  return options;
+};
+
+/**
+ * Keyup handler for the search box that hides or shows the relevant options.
+ */
+Drupal.Panels.OptionsSearch.prototype.handleKeyup = function (event) {
+  var found, i, j, option, search, words, wordsLength;
+
+  // Select the all vertical tab when searching
+
+  // Determine the user's search query. The search text has been converted to
+  // lowercase.
+  search = this.$searchBox.val().toLowerCase();
+  words = search.split(' ');
+  wordsLength = words.length;
+
+  // Search through the search texts in the form for matching text.
+  var length = this.options.length;
+  for (i = 0; i < length; i++) {
+    // Use a local variable for the option being searched, for performance.
+    option = this.options[i];
+    found = true;
+    // Each word in the search string has to match the item in order for the
+    // item to be shown.
+    for (j = 0; j < wordsLength; j++) {
+      if (option.searchText.indexOf(words[j]) === -1) {
+        found = false;
+      }
+    }
+    if (found) {
+      // Show the checkbox row, and restripe it.
+      option.$div.show();
+    }
+    else {
+      // The search string wasn't found; hide this item.
+      option.$div.hide();
+    }
+  }
+};
+
+/**
+ * Handle focus to enable the all tab and render show every column.
+ */
+Drupal.Panels.OptionsSearch.prototype.handleFocus = function (event) {
+  var $verticalTabs = this.$content.siblings('.vertical-tabs-list').find('.first a').click();
+};
+
+
 $.fn.extend({
   panelsDraggable: Drupal.Panels.DraggableHandler
 });
diff --git a/plugins/display_renderers/panels_renderer_editor.class.php b/plugins/display_renderers/panels_renderer_editor.class.php
index 6c1fce6..8388325 100644
--- a/plugins/display_renderers/panels_renderer_editor.class.php
+++ b/plugins/display_renderers/panels_renderer_editor.class.php
@@ -508,16 +508,46 @@ class panels_renderer_editor extends panels_renderer_standard {
       $output = t('There are no content types you may add to this display.');
     }
     else {
-      $output = '<div class="panels-add-content-modal">';
-      $selector = $this->render_category_selector($categories, $category, $region);
+      $output = '';
+
+      $element = array();
+      $element['search'] = array(
+        '#title' => t('Search'),
+        '#type' => 'textfield',
+        '#size' => 25,
+        '#id' => 'panels-select-content-search',
+      );
+      $element['categories'] = array(
+        '#type' => 'vertical_tabs',
+        '#prefix' => '<div class="panels-select-content-categories">',
+        '#suffix' => '</div>',
+      );
+
+      // Render the content of each category.
+      $all_content = '';
+      foreach ($categories as $category => $info) {
+        $content = !empty($categories[$category]['content']) ? $categories[$category]['content'] : array();
+        $center = $this->render_category($content, $category, $region);
+        $all_content .= $center;
+        $element['categories'][$category] = array(
+          '#type' => 'fieldset',
+          '#title' => filter_xss_admin($info['title']),
+          '#children' => $center,
+          '#weight' => $category ==  'root' ? -10 : 0,
+        );
+      }
+
+      $description = '<div class="panels-categories-description">';
+      $description .= t("Content options are divided by category.<br /> Please select a category from the left to proceed or search.");
+      $description .= '</div>';
 
-      $content = !empty($categories[$category]['content']) ? $categories[$category]['content'] : array();
-      $center = $this->render_category($content, $category, $region);
+      $element['categories']['root']['#children'] = $description . $all_content;
+
+      $output .= drupal_render($element);
+
+      $other_links = $this->render_other_links($categories, $region);
+      $output .= $selector;
 
-      $output .= '<div class="panels-section-column panels-section-column-categories">'
-        . '<div class="inside">' . $selector . '</div></div>';
-      $output .= $center;
-      $output .= '</div>'; // panels-add-content-modal
     }
 
     $this->commands[] = ctools_modal_command_display($title, $output);
@@ -570,7 +600,7 @@ class panels_renderer_editor extends panels_renderer_standard {
 
         if (empty($categories[$category_key])) {
           $categories[$category_key] = array(
-            'title' => $category,
+            'title' => $category == 'root' ? t('All') : $category,
             'content' => array(),
           );
           $category_names[$category_key] = $category;
@@ -608,8 +638,8 @@ class panels_renderer_editor extends panels_renderer_standard {
     $url = $this->get_url('add-pane', $region, $content_type['type_name'], $content_type['subtype_name']);
 
     $output = '<div class="content-type-button clearfix">';
-    $output .= ctools_ajax_image_button($icon, $url, $description, 'panels-modal-add-config');
-    $output .= '<div>' . ctools_ajax_text_button($title, $url, $description, 'panels-modal-add-config') . '</div>';
+    $output .= ctools_ajax_image_button($icon, $url, $description, 'panels-modal-add-config panels-add-content-image');
+    $output .= '<div>' . ctools_ajax_text_button($title, $url, $description, 'panels-modal-add-config panels-add-content-text') . '</div>';
     $output .= '</div>';
 
     return $output;
@@ -618,26 +648,9 @@ class panels_renderer_editor extends panels_renderer_standard {
   /**
    * Render the selector widget in the add content modal to select categories.
    */
-  function render_category_selector($categories, $category, $region) {
-    $output = '<div class="panels-categories-box">';
-
-    // Render our list of categories in column 0.
-    foreach ($categories as $key => $category_info) {
-      if ($key == 'root') {
-        continue;
-      }
-
-      $class = 'panels-modal-add-category';
-      if ($key == $category) {
-        $class .= ' active';
-      }
-
-      $url = $this->get_url('select-content', $region, $key);
-      $output .= ctools_ajax_text_button($category_info['title'], $url, '', $class);
-    }
-
-    $output .= '</div>'; // panels-categories-box
-
+  function render_other_links($categories, $region) {
+    $url = $this->get_url('select-content', $region, $key);
+    $output .= ctools_ajax_text_button($category_info['title'], $url, '', $class);
     if (!empty($categories['root'])) {
       foreach ($categories['root']['content'] as $content_type) {
         $output .= $this->render_add_content_link($region, $content_type);
@@ -651,34 +664,27 @@ class panels_renderer_editor extends panels_renderer_standard {
    * Render all of the content links in a category.
    */
   function render_category($content, $category, $region) {
-    if (empty($category) || empty($content) || $category == 'root') {
-      $output = '<div class="panels-categories-description">';
-      $output .= t('Content options are divided by category. Please select a category from the left to proceed.');
-      $output .= '</div>';
+    $titles = array_keys($content);
+    natcasesort($titles);
+
+    // Fill out the info for our current category.
+    $columns = 2;
+    $col[1] = '';
+    $col[2] = '';
+
+    $col_size = count($titles) / $columns;
+    $count = 0;
+    foreach ($titles as $title) {
+      $which = floor($count++ / $col_size) + 1; // we leave 0 for the categories.
+      $col[$which] .= $this->render_add_content_link($region, $content[$title]);
     }
-    else {
-      $titles = array_keys($content);
-      natcasesort($titles);
-
-      // Fill out the info for our current category.
-      $columns = 2;
-      $col[1] = '';
-      $col[2] = '';
-
-      $col_size = count($titles) / $columns;
-      $count = 0;
-      foreach ($titles as $title) {
-        $which = floor($count++ / $col_size) + 1; // we leave 0 for the categories.
-        $col[$which] .= $this->render_add_content_link($region, $content[$title]);
-      }
 
-      $output = '<div class="panels-section-columns">';
-      foreach ($col as $id => $column) {
-        $output .= '<div class="panels-section-column panels-section-column-' . $id . '">'
-        . '<div class="inside">' . $column . '</div></div>';
-      }
-      $output .= '</div>'; // columns
+    $output = '<div class="panels-section-columns">';
+    foreach ($col as $id => $column) {
+      $output .= '<div class="panels-section-column panels-section-column-' . $id . '">'
+      . '<div class="inside">' . $column . '</div></div>';
     }
+    $output .= '</div>'; // columns
 
     if ($messages = theme('status_messages')) {
       $output = '<div class="messages">' . $messages . '</div>' . $output;
diff --git a/plugins/task_handlers/panel_context.inc b/plugins/task_handlers/panel_context.inc
index 03b34bd..14c9633 100644
--- a/plugins/task_handlers/panel_context.inc
+++ b/plugins/task_handlers/panel_context.inc
@@ -251,10 +251,6 @@ function panels_panel_context_render($handler, $base_contexts, $args, $test = TR
     return;
   }
 
-  if (isset($handler->handler)) {
-    ctools_context_handler_pre_render($handler, $contexts, $args);
-  }
-
   // Load the display
   $display = panels_panel_context_get_display($handler);
 
