? .DS_Store
? panels_mini.patch
? layouts/.DS_Store
? layouts/block.css
? layouts/block.inc
? layouts/block.png
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	31 Jul 2007 10:44:38 -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	31 Jul 2007 10:44:39 -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
@@ -1455,36 +1455,66 @@ function panels_sanitize_display(&$displ
 }
 
 /**
- * Render a display by loading the content into an appropriate
- * array and then passing through to panels_render_layout. 
+ * Render a display by rendering each panel, loading the rendered panels in an
+ * appropriate array and then passing through to panels_render_layout. 
  *
  * if $incoming_content is NULL, default content will be applied. Use 
  * an empty string to indicate no content.
  */
 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);    
   }
 
-  $output = panels_render_layout($layout, $content, $display->css_id, unserialize($display->layout_settings));
+  $output = theme($layout['theme'], check_plain($display->css_id), $content, unserialize($display->layout_settings));
+
+  if ($output) {
+    if (file_exists(path_to_theme() .'/'. $layout['css'])) {
+      drupal_add_css(path_to_theme() .'/'. $layout['css']);
+    }
+    else {
+      drupal_add_css(panels_get_path($layout['css'], FALSE, $layout['module']));
+    }
+  }
   return $output;
 }
 
+/**
+ * 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.
+ */
+function panels_render_panel($panes, $display) {
+  $panel_settings = unserialize($display->panel_settings);
+  $style = ($panel_settings['style']) ? $panel_settings['style'] : 'default';
+
+  // Store all panes in an array, sorted by their position in the panel.
+  foreach ($panes as $pane_id => $pane) {
+    if (panels_pane_access($pane)) {
+      $panel_content[$pane->position] = panels_get_pane_content($pane, $display->args, $display->context, $display->incoming_content);
+    }
+  }
+
+  // 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)) {
+    $pid = $display->owner->pid;
+  }
+
+  return theme("panels_panel_$style", $panel_content, $display, $pid);
+}
+
 // ---------------------------------------------------------------------------
 // panels data loading
 
@@ -1623,10 +1653,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 +1727,112 @@ function theme_panels_hidden() {
 }
 
 /**
+ * Panel style: default (panes separated by whitespace).
+ */
+function theme_panels_panel_default($panel_content, $display, $pid) {
+  $output = '';
+
+  foreach ($panel_content 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($panel_content, $display, $pid) {
+  $items = array();
+
+  foreach ($panel_content as $pane_id => $pane) {
+    $items[] = theme('panels_pane', $pane, $display);
+  }
+  return theme('item_list', $items);
+}
+
+/**
+ * Panel style: panes as tabs (depends on tabs.module).
+ */
+function theme_panels_panel_tabs($panel_content, $display, $pid) {
+  if (module_exists('tabs')) {
+    $tabs = array();
+
+    $tabs["panel_mini_$pid"] = array(
+      '#type' => 'tabset',
+    );
+    foreach ($panel_content as $pos => $pane) {
+      $tabs["panel_mini_$pid"]["tab_$pos"] = array(
+        '#type' => 'tabpage',
+        '#title' => $pane->subject,
+        '#content' => $pane->content,
+      );
+    }
+    return tabs_render($tabs);
+  }
+  else {
+    return theme('panels_panel_default', $panel_content, $display, $pid);
+  }
+}
+
+/**
+ * Panel style: panes in a horizontal carousel (depends on jcarousel.module).
+ */
+function theme_panels_panel_carousel_horizontal($panel_content, $display, $pid) {
+  return _panels_carousel_helper($panel_content, $display, $pid, TRUE);
+}
+
+/**
+ * Panel style: panes in a vertical carousel (depends on jcarousel.module).
+ */
+function theme_panels_panel_carousel_vertical($panel_content, $display, $pid) {
+  return _panels_carousel_helper($panel_content, $display, $pid, FALSE);
+}
+
+/**
+ * Helper function for the carousel panel style.
+ */
+function _panels_carousel_helper($panel_content, $display, $pid, $horizontal = TRUE) {
+  $output = '';
+
+  if (module_exists('jcarousel')) {
+    $items = array();
+
+    // Add the JavaScript to make jCarousel do its thing!
+    if (!$horizontal) {
+      $vertical = 'vertical: true,';
+    }
+
+    jcarousel_add();
+    drupal_add_js('
+$(document).ready(function() {
+  jQuery.easing["QuartEaseOut"] = function(p, t, b, c, d) {
+    return -c * ((t=t/d-1)*t*t*t - 1) + b;
+  };
+
+  jQuery("#panel_mini_'. $pid .'").jcarousel({
+    '. $vertical .'
+    scroll: 1,
+    visible: 1,
+    easing: "QuartEaseOut",
+    animation: 750
+  });
+});
+', 'inline');
+
+    // Render the items of the carousel.
+    foreach ($panel_content as $pane_id => $pane) {
+      $items[] = theme('panels_pane', $pane, $display);
+    }
+    return theme('item_list', $items, NULL, 'ul', array('id' => "panel_mini_$pid", 'class' => 'jcarousel jcarousel-skin-tango'));
+  }
+
+  return $output;
+}
+
+/**
  * Helper function for autocompletion of node titles.
  * This is mostly stolen from clipper.
  */
@@ -1753,3 +1885,44 @@ 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	31 Jul 2007 10:44:39 -0000
@@ -128,3 +128,86 @@ 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;
+}
+
+// TODO: Create a hook that allows modules to offer new panel display styles.
+function panels_common_panel_settings($display, $panels_implementation = '') {
+  $panel_settings = unserialize($display->panel_settings);
+
+  $form['panel_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Panel settings'),
+    '#tree' => TRUE,
+  );
+
+  $options['default'] = t('Default');
+  $options['list']    = t('List of panes');
+  if (module_exists('tabs')) {
+    $options['tabs']  = t('Tabs');
+  }
+  if (module_exists('jcarousel')) {
+    $options['carousel_horizontal'] = t('Horizontal carousel');
+    $options['carousel_vertical'] = t('Vertical carousel');
+  }
+
+  $style = ($panel_settings['style']) ? $panel_settings['style'] : 'default';
+
+  $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 will be displayed.<br />
+      The default style inserts whitespace between panes.<br />
+      The list style creates an unordered list of panes.<br />
+      The tabs style creates a tab of each pane (requires the Tabs module, part of the Javascript Tools module).<br />
+      The horizontal/vertical carousel style display the panes one-by-one in either a horizontal or vertical carousel (requires the jCarousel module).',
+      array('%panels-implementation' => $panels_implementation)
+    ),
+    '#default_value' => $style,
+  );
+
+  return $form;  
+}
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	31 Jul 2007 10:44:39 -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	31 Jul 2007 10:44:39 -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	31 Jul 2007 10:44:39 -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' => 35,
+    '#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, '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	31 Jul 2007 10:44:39 -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;
 }
-
