Index: panels.install
===================================================================
RCS file: /cvs/drupal/contributions/modules/panels/panels.install,v
retrieving revision 1.1.6.11
diff -u -F^f -r1.1.6.11 panels.install
--- panels.install	8 Jul 2007 04:46:55 -0000	1.1.6.11
+++ panels.install	14 Aug 2007 21:10:47 -0000
@@ -38,7 +38,8 @@ function panels_install() {
         CREATE TABLE {panels_display} (
           did INT(10) NOT NULL DEFAULT 0 PRIMARY KEY,
           layout VARCHAR(32),
-          layout_settings longtext
+          layout_settings longtext,
+          panel_settings longtext
         ) /*!40100 DEFAULT CHARACTER SET utf8 */
 EOT
       );
@@ -140,3 +141,9 @@ function panels_update_1002() {
   $ret[] = update_sql("ALTER TABLE {panels_page} ADD COLUMN css longtext AFTER css_id");
   return $ret;
 }
+
+// Create a field for the panel settings.
+function panels_update_1003() {
+  $ret[] = update_sql("ALTER TABLE {panels_display} ADD COLUMN panel_settings longtext");
+  return $ret;
+}
Index: panels.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/panels/panels.module,v
retrieving revision 1.10.4.33
diff -u -F^f -r1.10.4.33 panels.module
--- panels.module	23 Jul 2007 16:15:58 -0000	1.10.4.33
+++ panels.module	14 Aug 2007 21:10:48 -0000
@@ -1349,12 +1349,12 @@ function panels_load_display($did, $cont
  */
 function panels_save_display(&$display) {
   if ($display->did && $display->did != 'new') {
-    db_query("UPDATE {panels_display} SET layout = '%s', layout_settings = '%s' WHERE did = %d", $display->layout, $display->layout_settings, $display->did);
+    db_query("UPDATE {panels_display} SET layout = '%s', layout_settings = '%s', panel_settings = '%s' WHERE did = %d", $display->layout, $display->layout_settings, $display->panel_settings, $display->did);
     db_query("DELETE FROM {panels_pane} WHERE did = %d", $display->did);
   }
   else {
     $display->did = db_next_id("{panels_display}_id");
-    db_query("INSERT INTO {panels_display} (did, layout, layout_settings) VALUES (%d, '%s', '%s')", $display->did, $display->layout, $display->layout_settings);
+    db_query("INSERT INTO {panels_display} (did, layout, layout_settings, panel_settings) VALUES (%d, '%s', '%s', '%s')", $display->did, $display->layout, $display->layout_settings, $display->panel_settings);
   }
 
   // update all the panes
@@ -1463,26 +1463,53 @@ function panels_sanitize_display(&$displ
  */
 function panels_render_display(&$display) {
   $layout = panels_get_layout($display->layout);
-  
   if (!$layout) {
     return NULL;
   }
 
   panels_sanitize_display($display);
 
-  foreach ($display->content as $pid => $pane) {
-    if ($result = panels_get_pane_content($pane, $display->args, $display->context, $display->incoming_content)) {
-      if (!empty($content[$pane->panel])) {
-        $content[$pane->panel] .= theme('panels_separator', $display);
-      }
-      if (panels_pane_access($pane)) {
-        $content[$pane->panel] .= theme('panels_pane', $result, $display); 
-      }
+  // Loop through all panels, put all panes that belong to the current panel
+  // in an array, then render the panel.
+  foreach ($display->panels as $panel_name => $panes) {
+    $panes_in_panel = array_intersect_key($display->content, array_flip($panes));
+    $content[$panel_name] = panels_render_panel($panes_in_panel, $display);    
+  }
+  
+  return panels_render_layout($layout, $content, $display->css_id, unserialize($display->layout_settings));
+}
+
+/**
+ * Render a panel, by storing the content of each pane in an appropriate array
+ * and then passing through to the theme function that will render the panel
+ * in the configured panel style.
+ *
+ * @param $panes
+ *   An array of panes that are assigned to the panel that's being rendered.
+ * @param $display
+ *   A display object.
+ * @return
+ *   The rendered HTML for a panel.
+ */
+function panels_render_panel($panes_in_panel, $display) {
+  $panel_settings = unserialize($display->panel_settings);
+  $style = (is_array($panel_settings)) ? panels_get_panel_style($panel_settings['style']) : array('name' => 'default', 'module' => 'panels');
+
+  // Store all panes in an array, sorted by their position in the panel.
+  foreach ($panes_in_panel as $pane_id => $pane) {
+    if (panels_pane_access($pane)) {
+      $panes[$pane->position] = panels_get_pane_content($pane, $display->args, $display->context, $display->incoming_content);
     }
   }
 
-  $output = panels_render_layout($layout, $content, $display->css_id, unserialize($display->layout_settings));
-  return $output;
+  // Retrieve the pid (can be a panel page id, a mini panel id, etc.), this
+  // might be used (or even necessary) for some panel display styles.
+  $pid = 0;
+  if (isset($display->owner) && is_object($display->owner) && isset($display->owner->pid)) {
+    $panel_id = $display->owner->pid;
+  }
+
+  return module_invoke($style['module'], 'panels_panel_style_render', $display, $style['name'], $panel_id, $panes);
 }
 
 // ---------------------------------------------------------------------------
@@ -1534,6 +1561,51 @@ function panels_get_layouts($layout = NU
   return $layouts;
 }
 
+/**
+ * Collate information about a specific panel style.
+ *
+ * @param $style
+ *   Name of a panel style.
+ * @return
+ *   An array with information about the requested panel style.
+ */
+function panels_get_panel_style($style) {
+  return panels_get_panel_styles($style);
+}
+
+/**
+ * Collate information about all available panel styles.
+ *
+ * @param $style
+ *   Name of a panel style.
+ * @return
+ *   An array of arrays with information about all available panel styles. If
+ *   the $style parameter specified an available panel style, only this array
+ *   would be returned.
+ */
+function panels_get_panel_styles($style = NULL) {
+  static $styles;
+  
+  if (!isset($styles)) {
+    foreach (module_list() as $module) {
+      $module_panel_styles = module_invoke($module, 'panels_panel_style_info');
+      if ($module_panel_styles) {
+        foreach ($module_panel_styles as $name => $panel_style_info) {
+          $styles[$name] = $panel_style_info;
+          $styles[$name]['name'] = $name;
+          $styles[$name]['module'] = $module;
+        }
+      }
+    }
+  }
+
+  if ($style) {
+    return isset($styles[$style]) ? $styles[$style] : NULL;
+  }
+
+  return $styles;
+}
+
 function panels_get_content_type($content_type) {
   return panels_get_content_types($content_type);
 }
@@ -1580,6 +1652,38 @@ function _panels_js_files() {
 }
 
 // ---------------------------------------------------------------------------
+// Panels hooks
+
+/**
+ * Implementation of hook_panels_panel_style_info().
+ */
+function panels_panels_panel_style_info() {
+  return array(
+    'default' => array(
+      'label' => t('Default'),
+      'panels implementations' => array(),
+    ),
+    'list' => array(
+      'label' => t('List'),
+      'panels implementations' => array(),
+    ),
+  );
+}
+
+/**
+ * Implementation of hook_panels_panel_style_render().
+ */
+function panels_panels_panel_style_render($display, $style, $panel_id, $panes) {
+  switch ($style) {
+    case 'default':
+      return theme('panels_panel_default', $display, $panel_id, $panes);
+
+    case 'list':
+      return theme('panels_panel_list', $display, $panel_id, $panes);
+  }
+}
+
+// ---------------------------------------------------------------------------
 // Panels theming functions
 
 function theme_panels_dnd($content) {
@@ -1623,10 +1727,6 @@ function theme_panels_pane_collapsible($
   return $output;
 }
 
-function theme_panels_separator($display) {
-  return '<div class="panel-separator"></div>';
-}
-
 /**
  * Print the layout link. Sends out to a theme function.
  */
@@ -1701,6 +1801,33 @@ function theme_panels_hidden() {
 }
 
 /**
+ * Panel style: default (panes separated by whitespace).
+ */
+function theme_panels_panel_default($display, $panel_id, $panes) {
+  $output = '';
+
+  foreach ($panes as $pane) {
+    if (isset($output)) {
+      $output .= '<div class="panel-separator"></div>';
+    }
+    $output .= theme('panels_pane', $pane, $display); 
+  }
+  return $output;
+}
+
+/**
+ * Panel style: list of panes (panes are items in an unordered list).
+ */
+function theme_panels_panel_list($display, $panel_id, $panes) {
+  $items = array();
+
+  foreach ($panes as $pane_id => $pane) {
+    $items[] = theme('panels_pane', $pane, $display);
+  }
+  return theme('item_list', $items);
+}
+
+/**
  * Helper function for autocompletion of node titles.
  * This is mostly stolen from clipper.
  */
@@ -1753,3 +1880,35 @@ function panels_title_sort($a, $b) {
   }
   return ($a['weight'] < $b['weight']) ? -1 : 1;
 }
+
+/**
+ * For PHP 4 compatibility. The array_intersect_key is used in the
+ * panels_render_display function.
+ *
+ * Borrowed from http://php.net/manual/en/function.array-intersect-key.php#74956.
+ */
+if (!function_exists('array_intersect_key')) {
+  function array_intersect_key($isec, $keys) {
+    $argc = func_num_args();
+    if ($argc > 2) {
+      for ($i = 1; !empty($isec) && $i < $argc; $i++) {
+        $arr = func_get_arg($i);
+        foreach (array_keys($isec) as $key) {
+          if (!isset($arr[$key])) {
+            unset($isec[$key]);
+          }
+        }
+      }
+      return $isec;
+    }
+    else {
+      $res = array();
+      foreach (array_keys($isec) as $key) {
+        if (isset($keys[$key])) {
+          $res[$key] = $isec[$key];
+        }
+      }
+      return $res;
+    }
+  }
+}
Index: panels_common.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/panels/Attic/panels_common.inc,v
retrieving revision 1.1.2.3
diff -u -F^f -r1.1.2.3 panels_common.inc
--- panels_common.inc	7 Jul 2007 21:17:36 -0000	1.1.2.3
+++ panels_common.inc	14 Aug 2007 21:10:48 -0000
@@ -128,3 +128,112 @@ function panels_common_get_allowed_types
   }
   return $content_types;
 }
+
+/**
+ * The layout information fieldset displayed at admin/build/panel-%implementation%/add/%layout%.
+ */
+function panels_common_get_layout_information($panel_implementation) {
+  $form = array();
+  $layout = panels_get_layout($panel_implementation->display->layout);
+
+  $form = array(
+    '#type' => 'fieldset',
+    '#title' => t('Layout'),
+  );
+
+  $form['layout-icon'] = array(
+    '#value' => panels_print_layout_icon($panel_implementation->display->layout, $layout),
+  );
+
+  $form['layout-display'] = array(
+    '#value' => check_plain($layout['title']),
+  );
+  $content = '<dl class="content-list">';
+
+  foreach (panels_get_panels($layout, $panel_implementation->display) as $panel_id => $title) {
+    $content .= "<dt>$title</dt><dd>";
+    if ($panel_implementation->display->panels[$panel_id]) {
+      $content .= '<ol>';
+      foreach ($panel_implementation->display->panels[$panel_id] as $pid) {
+        $content .= '<li>'. panels_get_pane_title($panel_implementation->display->content[$pid]) .'</li>';
+      }
+      $content .= '</ol>';
+    }
+    else {
+      $content .= t('Empty');      
+    }
+    $content .= '</dd>';
+  }
+  $content .= '</dl>';
+
+  $form['layout-content'] = array(
+    '#value' => $content,
+  );
+
+  return $form;
+}
+
+/**
+ * The panel settings fieldset that can optionally be added to
+ * admin/build/panel-%implementation%/%panel_id%/edit, if the panels
+ * implementation wants to support panel settings.
+ */
+function panels_common_panel_settings($display, $panels_implementation = '', $panels_implementation_human = '') {
+  $panel_settings = unserialize($display->panel_settings);
+  $style_name = ($panel_settings['style']) ? $panel_settings['style'] : 'default';
+  $style = panels_get_panel_style($style_name);
+
+  // Let the user choose between panel styles that are available for any
+  // panels implementation or specifically to this one.
+  $options = array();
+  foreach (panels_get_panel_styles() as $name => $properties) {
+    $implementations = $properties['panels implementations'];
+    if (!is_array($implementations) || count($implementations) == 0 || in_array($panels_implementation, $implementations)) {
+      $options[$name] = $properties['label'];
+    }
+  }
+
+  $form = array();
+  $form['display'] = array('#type' => 'value', '#value' => $display);
+  $form['panel_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Panel settings'),
+    '#tree' => TRUE,
+  );
+  $form['panel_settings']['style'] = array(
+    '#type' => 'radios',
+    '#title' => t('Panel style'),
+    '#options' => $options,
+    '#description' => t(
+      'The style in which the panes of each panel in this %panels-implementation-human will be displayed.',
+      array('%panels-implementation-human' => $panels_implementation_human)
+    ),
+    '#default_value' => $style['name'],
+  );
+  $form['panel_settings']['style_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Panel style settings'),
+  );
+  if (in_array($style['module'], module_list()) && function_exists($style['module'] .'_panels_panel_style_settings_form')) {
+    $style_settings = module_invoke($style['module'], 'panels_panel_style_settings_form', $style['name'], unserialize($display->panel_settings));
+    if (is_array($style_settings)) {
+      $form['panel_settings']['style_settings'] += $style_settings;
+    }
+  }
+  else {
+    $form['panel_settings']['style_settings']['#description'] = t('The currently active style does not have any settings.');
+  }
+  $form['#validate']['panels_common_panel_settings_validate'] = array($style['module'], $style['name']);
+
+  return $form;
+}
+
+/**
+ * Allows panel styles to validate their style settings.
+ */
+function panels_common_panel_settings_validate($form, $module, $style) {
+  global $form_values;
+
+  $panel_settings = unserialize($form_values['display']->panel_settings);
+  module_invoke($module, 'panels_panel_style_settings_validate', $style, $panel_settings, $form['panel_settings']['style_settings'], $form_values['panel_settings']['style_settings']);
+}
Index: panels_mini.info
===================================================================
RCS file: panels_mini.info
diff -N panels_mini.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panels_mini.info	14 Aug 2007 21:10:48 -0000
@@ -0,0 +1,5 @@
+; $Id $
+name = Mini panels
+description = Create mini panels that can be used as blocks.
+package = "Panels"
+dependencies = panels
\ No newline at end of file
Index: panels_mini.install
===================================================================
RCS file: panels_mini.install
diff -N panels_mini.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panels_mini.install	14 Aug 2007 21:10:48 -0000
@@ -0,0 +1,39 @@
+<?php
+// $Id $
+
+/**
+ * Implementation of hook_install().
+ */
+function panels_mini_install() {
+  switch ($GLOBALS['dbtype']) {
+    case 'pgsql':
+    case 'mysql':
+    case 'mysqli':
+    default:
+      db_query(<<<EOT
+        CREATE TABLE {panels_mini} (
+          pid int(10) NOT NULL DEFAULT 0 PRIMARY KEY,
+          did int(10),
+          title varchar(128)
+        )/*!40100 DEFAULT CHARACTER SET utf8 */
+EOT
+      );
+  }
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function panels_mini_uninstall() {
+  $result = db_query("SELECT * FROM {panels_mini} ORDER BY title");
+  while ($panel_mini = db_fetch_object($result)) {
+    // Delete all associated displays.
+    panels_delete_display($panel_mini->did);
+
+    // Delete all configured blocks.
+    db_query("DELETE FROM {blocks} WHERE module = 'panels_mini' AND delta = %d", $panel_mini->pid);
+  }
+  
+  // Finally, delete all mini panels.
+  db_query("DROP TABLE IF EXISTS {panels_mini}");
+}
Index: panels_mini.module
===================================================================
RCS file: panels_mini.module
diff -N panels_mini.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panels_mini.module	14 Aug 2007 21:10:49 -0000
@@ -0,0 +1,449 @@
+<?php
+// $Id $
+
+/**
+ * Implementation of hook_help()
+ */
+function panels_mini_help($section = '') {
+  switch ($section) {
+    case 'admin/build/panel-mini':
+    case 'admin/build/panel-mini/list':
+      return t('<p>You can edit existing mini panels, or click add to create a new one.</p>');
+    case 'admin/build/panel-mini/add':
+      return t('<p>Mini panels are the small variants of panel pages. Instead of pages, they define blocks.</p>');
+  }
+}
+
+/**
+ * Implementation of hook_perm().
+ */
+function panels_mini_perm() {
+  return array('create mini panels', 'administer mini panels');
+}
+
+/**
+ * Implementation of hook_menu()
+ */
+function panels_mini_menu($may_cache) {
+  if ($may_cache) {
+    $access = user_access('create mini panels');
+    
+    $items[] = array(
+      'path' => 'admin/build/panel-mini',
+      'title' => t('Mini panels'),
+      'access' => $access,    
+      'callback' => 'panels_mini_list_page',
+      'description' => t('Create and administer mini panels (panels exposed as blocks)'),
+    );
+    $items[] = array(
+      'path' => 'admin/build/panel-mini/list',
+      'title' => t('List'),
+      'access' => $access,    
+      'callback' => 'panels_mini_list_page',
+      'weight' => -10,
+      'type' => MENU_DEFAULT_LOCAL_TASK,
+    );
+    $items[] = array(
+      'path' => 'admin/build/panel-mini/add',
+      'title' => t('Add'),
+      'access' => $access,
+      'callback' => 'panels_mini_add_page',
+      'type' => MENU_LOCAL_TASK,
+    );
+    $items[] = array(
+      'path' => 'admin/build/panel-mini/settings',
+      'title' => t('Settings'),
+      'access' => $access,    
+      'callback' => 'panels_mini_settings',
+      'type' => MENU_LOCAL_TASK,
+    );
+  }
+  else {
+    $result = db_query("SELECT * FROM {panels_mini}");
+    while ($panel_mini = db_fetch_object($result)) {
+      panels_mini_menu_items($items, "admin/build/panel-mini/$panel_mini->pid", $panel_mini);
+    }
+  }
+  return $items;
+}
+
+function panels_mini_menu_items(&$items, $base, $panel_mini) {
+  $access = user_access('administer mini panels');
+
+  if ($access) {
+    $items[] = array(
+      'path' => $base,
+      'title' => t('Edit'),
+      'access' => $access,    
+      'callback' => 'panels_mini_edit',
+      'callback arguments' => array($panel_mini->pid),
+      'weight' => -5,
+      'type' => MENU_CALLBACK,
+    );
+    $items[] = array(
+      'path' => $base .'/edit',
+      'title' => t('Edit'),
+      'access' => $access,    
+      'callback' => 'panels_mini_edit',
+      'callback arguments' => array($panel_mini->pid),
+      'weight' => -5,
+      'type' => MENU_LOCAL_TASK,
+    );
+    $items[] = array(
+      'path' => $base .'/edit/general',
+      'title' => t('General'),
+      'access' => $access,    
+      'callback' => 'panels_mini_edit',
+      'callback arguments' => array($panel_mini->pid),
+      'weight' => -5,
+      'type' => MENU_DEFAULT_LOCAL_TASK,
+    );
+    $items[] = array(
+      'path' => $base .'/edit/layout',
+      'title' => t('Layout'),
+      'access' => $access,    
+      'callback' => 'panels_mini_edit_layout',
+      'callback arguments' => array($panel_mini->pid),
+      'weight' => -3,
+      'type' => MENU_LOCAL_TASK,
+    );
+
+    $display = panels_load_display($panel_mini->did);
+    $layout = panels_get_layout($display->layout);
+    if (!empty($layout['settings form'])) {
+      $items[] = array(
+        'path' => $base .'/edit/settings',
+        'title' => t('Layout settings'),
+        'access' => $access,    
+        'callback' => 'panels_mini_edit_layout_settings',
+        'callback arguments' => array($panel_mini->pid),
+        'weight' => -3,
+        'type' => MENU_LOCAL_TASK,
+      );
+    }
+
+    $items[] = array(
+      'path' => $base .'/edit/content',
+      'title' => t('Content'),
+      'access' => $access,
+      'callback' => 'panels_mini_edit_content',
+      'callback arguments' => array($panel_mini->pid),
+      'weight' => -1,
+      'type' => MENU_LOCAL_TASK,
+    );
+    $items[] = array(
+      'path' => $base .'/delete',
+      'title' => t('Delete mini panel'),
+      'access' => user_access('create mini panels'),    
+      'callback' => 'drupal_get_form',
+      'callback arguments' => array('panels_mini_delete_confirm', $panel_mini->pid),
+      'type' => MENU_CALLBACK,
+    );
+  }
+}
+
+// ---------------------------------------------------------------------------
+// Mini panel administrative pages.
+
+/**
+ * Settings for mini panels.
+ */
+function panels_mini_settings() {
+  require_once drupal_get_path('module', 'panels') .'/panels_common.inc';
+  return drupal_get_form('panels_common_settings', 'panels_mini');
+}
+
+/**
+ * Provide a list of mini panels, with links to edit or delete them.
+ */
+function panels_mini_list_page() {
+  $result = db_query("SELECT * FROM {panels_mini} ORDER BY title");
+
+  while ($panel_mini = db_fetch_object($result)) {
+    $item = array();
+    $item[] = check_plain($panel_mini->title);
+    $item[] = implode(' | ', array(
+      l(t('Edit'), "admin/build/panel-mini/$panel_mini->pid/edit"),
+      l(t('Delete'), "admin/build/panel-mini/$panel_mini->pid/delete"),
+    ));
+    $items[] = $item;
+  }
+  $header = array(
+    t('Title'),
+    t('Operations'),
+  );
+
+  $output = theme('table', $header, $items);
+
+  return $output;
+}
+
+/**
+ * Provide a form to confirm deletion of a mini panel.
+ */
+function panels_mini_delete_confirm($panel_mini) {
+  if (!is_object($panel_mini)) {
+    $panel_mini = panels_mini_load($panel_mini);
+  }
+  $form['pid'] = array('#type' => 'value', '#value' => $panel_mini->pid);
+  $form['did'] = array('#type' => 'value', '#value' => $panel_mini->did);
+  return confirm_form($form,
+    t('Are you sure you want to delete the mini panel "@title"?', array('@title' => $panel_mini->title)),
+    $_GET['destination'] ? $_GET['destination'] : 'admin/build/panel-mini',
+    t('This action cannot be undone.'),
+    t('Delete'), t('Cancel')
+  );
+}
+
+/**
+ * Handle the submit button to delete a mini panel.
+ */
+function panels_mini_delete_confirm_submit($formid, $form) {
+  if ($form['confirm']) {
+    panels_mini_delete((object) $form);
+    return 'admin/build/panel-mini';
+  }
+}
+
+/**
+ * Handle the add mini panel page.
+ */
+function panels_mini_add_page($layout = NULL) {
+  $layouts = panels_get_layouts();
+
+  if ($layout === NULL) {
+    foreach ($layouts as $id => $layout) {
+      $output .= panels_print_layout_link($id, $layout, $_GET['q'] .'/'. $id);
+    }
+    return $output;
+  }
+
+  if (!$layouts[$layout]) {
+    return drupal_not_found();
+  }
+
+  $panel_mini->display = panels_new_display();
+  $panel_mini->display->layout = $layout;
+  $panel_mini->pid = 'new';
+  $panel_mini->did = 'new';
+  return panels_mini_edit($panel_mini);
+}
+
+/**
+ * Edit a mini panel. Called from both the add and edit points to provide for
+ * common flow.
+ */
+function panels_mini_edit($panel_mini) {
+  if (!is_object($panel_mini)) {
+    $panel_mini = panels_mini_load($panel_mini);
+  }
+  return drupal_get_form('panels_mini_edit_form', $panel_mini);
+}
+
+/**
+ * The form to edit the settings of a mini panel.
+ */
+function panels_mini_edit_form($panel_mini) {
+  require_once drupal_get_path('module', 'panels') .'/panels_common.inc';
+  drupal_add_css(panels_get_path('css/panels_admin.css'));
+
+  $form['pid'] = array(
+    '#type' => 'value',
+    '#value' => $panel_mini->pid,
+  );
+  $form['panel_mini'] = array(
+    '#type' => 'value', 
+    '#value' => $panel_mini
+  );
+
+  $form['right'] = array(
+    '#prefix' => '<div class="layout-container">',
+    '#suffix' => '</div>',
+  );
+  $form['left'] = array(
+    '#prefix' => '<div class="info-container">',
+    '#suffix' => '</div>',
+  );
+
+  $form['left']['settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Settings'),
+  );
+  $form['left']['settings']['title'] = array(
+    '#type' => 'textfield',
+    '#size' => 24,
+    '#default_value' => $panel_mini->title,
+    '#title' => t('Mini panel title'),
+    '#description' => t('The title for this mini panel. It can be overridden in the block configuration.'),
+  );
+  
+  // Add the "panel settings" section of the form and the accompanying submit
+  // handler.
+  $form['left'] += panels_common_panel_settings($panel_mini->display, 'panels_mini', 'mini panel');
+
+  $form['right']['layout'] = panels_common_get_layout_information($panel_mini);
+
+  $label = ($panel_mini->pid == 'new') ? t('Next') : t('Save');
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => $label,
+  );
+
+  return $form;
+}
+
+/**
+ * Process submission of the mini panel edit form.
+ */
+function panels_mini_edit_form_submit($form_id, $form_values) {
+  $panel_mini = $form_values['panel_mini'];
+  $panel_mini->title  = $form_values['title'];
+  $panel_mini->display->panel_settings = serialize($form_values['panel_settings']);
+
+  if ($panel_mini->pid == 'new') {
+    panels_mini_save($panel_mini);
+    // TODO: Why not use form_set_value()?
+    $GLOBALS['form_values']['pid'] = $panel_mini->pid;
+
+    return "admin/build/panel-mini/$panel_mini->pid/edit/content";
+  }
+  else {
+    drupal_set_message(t('Your changes have been saved.'));
+    panels_mini_save($panel_mini);
+  }
+}
+
+/**
+ * Pass through to the panels content editor.
+ */
+function panels_mini_edit_content($panel_mini) {
+  if (!is_object($panel_mini)) {
+    $panel_mini = panels_mini_load($panel_mini);
+  }
+  require_once drupal_get_path('module', 'panels') .'/panels_common.inc';
+  $content_types = panels_common_get_allowed_types('panels_mini');
+
+  // Print this with theme('page') so that blocks are disabled while editing a display.
+  // This is important because negative margins in common block layouts (i.e, Garland)
+  // messes up the drag & drop.
+  print theme('page', panels_edit($panel_mini->display, "admin/build/panel-mini/$panel_mini->pid/edit/content", $content_types), FALSE);
+}
+
+/**
+ * Pass through to the panels layout editor.
+ */
+function panels_mini_edit_layout($panel_mini) {
+  if (!is_object($panel_mini)) {
+    $panel_mini = panels_page_load($panel_mini);
+  }
+  return panels_edit_layout($panel_mini->display, t('Save'), "admin/build/panel-mini/$panel_mini->pid/edit/layout");
+}
+
+/**
+ * Pass through to the panels layout settings editor.
+ */
+function panels_mini_edit_layout_settings($panel_mini) {
+  if (!is_object($panel_mini)) {
+    $panel_mini = panels_mini_load($panel_mini);
+  }
+  return panels_edit_layout_settings($panel_mini->display, t('Save'), "admin/build/panel-mini/$panel_mini->pid/edit/settings");
+}
+
+// ---------------------------------------------------------------------------
+// The actual panel_mini code.
+
+/**
+ * Implementation of hook_block().
+ */
+function panels_mini_block($op = 'list', $delta = 0, $edit = array()) {
+  if ($op == 'list') {
+    $blocks = array();
+    
+    $result = db_query("SELECT * FROM {panels_mini} ORDER BY title");
+    while ($panel_mini = db_fetch_object($result)) {
+      $blocks[$panel_mini->pid] = array(
+        'info' => t('Mini panel: "@title"', array('@title' => $panel_mini->title)),
+      );
+    }
+
+    return $blocks;
+  }
+  elseif ($op == 'view') {
+    $panel_mini = panels_mini_load($delta);
+    $block = array(
+      'subject' => $panel_mini->title,
+      'content' => panels_render_display($panel_mini->display)
+    );
+    return $block;
+  }
+}
+
+// ---------------------------------------------------------------------------
+// Database functions.
+
+/**
+ * Load a mini panel.
+ */
+function panels_mini_load($pid) {
+  static $cache = array();
+
+  if (!isset($cache[$pid])) {
+    $panel_mini = db_fetch_object(db_query("SELECT * FROM {panels_mini} WHERE pid = %d", $pid));
+    $cache[$pid] = drupal_clone($panel_mini);
+    if (!$cache[$pid]) {
+      return;
+    }
+
+    $cache[$pid]->display = panels_load_display($cache[$pid]->did);
+    $cache[$pid]->display->owner = drupal_clone($panel_mini);
+  }
+  return $cache[$pid];
+}
+
+/**
+ * Save a mini panel. 
+ */
+function panels_mini_save(&$panel_mini) {
+  $display = panels_save_display($panel_mini->display);
+
+  if ($panel_mini->pid && $panel_mini->pid != 'new') {
+    db_query(
+      "UPDATE {panels_mini} SET " .
+      "did = %d, " .
+      "title = '%s' " .
+      "WHERE pid = %d", 
+        $panel_mini->did,
+        $panel_mini->title, 
+      $panel_mini->pid
+    );
+  }
+  else {
+    $panel_mini->pid = db_next_id("{panels_mini}_pid");
+    db_query(
+      "INSERT INTO {panels_mini} ( " .
+        "pid, " .
+        "did, " .
+        "title " .
+      ") " .
+      "VALUES (" .
+        "%d, " .
+        "%d, " .
+        "'%s'" .
+      ")",
+        $panel_mini->pid,
+        $display->did,
+        $panel_mini->title
+    );
+  }
+
+  return $panel_mini->pid;
+}
+
+/**
+ * Delete a mini panel.
+ */
+function panels_mini_delete($panel_mini) {
+  db_query("DELETE FROM {panels_mini} WHERE pid = %d", $panel_mini->pid);
+  db_query("DELETE FROM {blocks} WHERE module = 'panels_mini' AND delta = %d", $panel_mini->pid);
+  return panels_delete_display($panel_mini->did);
+}
Index: css/panels_admin.css
===================================================================
RCS file: /cvs/drupal/contributions/modules/panels/css/Attic/panels_admin.css,v
retrieving revision 1.1.2.6
diff -u -F^f -r1.1.2.6 panels_admin.css
--- css/panels_admin.css	24 Jun 2007 21:11:37 -0000	1.1.2.6
+++ css/panels_admin.css	14 Aug 2007 21:10:49 -0000
@@ -17,20 +17,20 @@
   margin-bottom: 1em;
 }
 
-/* styles for the basic panel-page edit page */
+/* styles for the basic panel-%implementation% edit page */
 .layout-container {
   float: right;
   padding: 0 0 0 1em;
   margin: 0;
-  width: 50%;
+  width: 49%;
 }
 
-.panels-page-info-container {
+.info-container {
   padding-right: 1em;
+  width: 49%;
 }
 
-.layout-container fieldset,
-.panels-page-info-container fieldset {
+.layout-container fieldset {
   margin-top: 0;
   width: 98%;
 }
@@ -102,4 +102,3 @@
 #panels-edit-display .helperclass {
   margin: .5em;
 }
-
