Index: /extensions/GThumb/admin.php
===================================================================
--- /extensions/GThumb/admin.php	(revision 12678)
+++ /extensions/GThumb/admin.php	(revision 12678)
@@ -0,0 +1,65 @@
+<?php
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+global $template, $conf;
+
+load_language('plugin.lang', GTHUMB_PATH);
+include_once(GTHUMB_PATH.'functions.inc.php');
+include(dirname(__FILE__).'/config_default.inc.php');
+$params = $conf['GThumb'];
+
+// Save configuration
+if (isset($_POST['submit']))
+{
+  $params  = array(
+    'height'          => $_POST['height'],
+    'margin'          => $_POST['margin'],
+    'nb_image_page'   => $_POST['nb_image_page'],
+    'big_thumb'       => !empty($_POST['big_thumb']),
+    'cache_big_thumb' => !empty($_POST['cache_big_thumb']),
+    'method'          => $_POST['method'],
+  );
+
+  if (!is_numeric($params['height']))
+  {
+    array_push($page['errors'], 'Thumbnails max height must be an integer.');
+  }
+  if (!is_numeric($params['margin']))
+  {
+    array_push($page['errors'], 'Margin between thumbnails must be an integer.');
+  }
+  if (!is_numeric($params['nb_image_page']))
+  {
+    array_push($page['errors'], 'Number of photos per page must be an integer.');
+  }
+
+  if (empty($page['errors']))
+  {
+    $query = '
+  UPDATE ' . CONFIG_TABLE . '
+    SET value="' . addslashes(serialize($params)) . '"
+    WHERE param="GThumb"
+    LIMIT 1';
+    pwg_query($query);
+    
+    array_push($page['infos'], l10n('Information data registered in database'));
+  }
+}
+
+// Configuration du template
+$template->assign(
+  array(
+    'HEIGHT'          => $params['height'],
+    'MARGIN'          => $params['margin'],
+    'NB_IMAGE_PAGE'   => $params['nb_image_page'],
+    'BIG_THUMB'       => $params['big_thumb'],
+    'CACHE_BIG_THUMB' => $params['cache_big_thumb'],
+    'METHOD'          => $params['method'],
+  )
+);
+
+$template->set_filenames(array('plugin_admin_content' => dirname(__FILE__) . '/template/admin.tpl'));
+$template->assign_var_from_handle('ADMIN_CONTENT', 'plugin_admin_content');
+
+?>
Index: /extensions/GThumb/config_default.inc.php
===================================================================
--- /extensions/GThumb/config_default.inc.php	(revision 12678)
+++ /extensions/GThumb/config_default.inc.php	(revision 12678)
@@ -0,0 +1,12 @@
+<?php
+
+$config_default = array(
+  'height'          => 200,
+  'margin'          => 10,
+  'nb_image_page'   => 80,
+  'big_thumb'       => true,
+  'cache_big_thumb' => true,
+  'method'          => 'crop',
+);
+
+?>
Index: /extensions/GThumb/functions.inc.php
===================================================================
--- /extensions/GThumb/functions.inc.php	(revision 12678)
+++ /extensions/GThumb/functions.inc.php	(revision 12678)
@@ -0,0 +1,133 @@
+<?php
+
+function ws_images_getGThumbPlusThumbnail($params, &$service)
+{
+  global $conf;
+
+  if (empty($params['image_id']))
+  {
+    return new PwgError(403, "image_id is required");
+  }
+
+  include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
+
+  $forbidden = get_sql_condition_FandF(
+    array(
+      'forbidden_categories' => 'ic.category_id',
+      'visible_categories' => 'ic.category_id',
+      'visible_images' => 'i.id'
+    ),
+    'AND'
+  );
+
+  $query = 'SELECT i.*
+FROM '.IMAGES_TABLE.' AS i
+  INNER JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON i.id = ic.image_id
+  INNER JOIN '.CATEGORIES_TABLE.' AS c ON ic.category_id = c.id
+WHERE i.id = '.$params['image_id'].'
+'.$forbidden.'
+;';
+
+  $picture = pwg_db_fetch_assoc(pwg_query($query));
+
+  if (empty($picture))
+  {
+    return new PwgError(404, "image not found");
+  }
+
+  $data = get_gthumb_data($picture, $params['size']);
+  $result = array();
+ 
+  if (empty($data['src']))
+  {
+    $cache_dir = GTHUMB_CACHE_DIR.'/';
+    if ($params['size'] == 'small' or $conf['GThumb']['cache_big_thumb'])
+    {
+      $cache_dir = $data['cache_path'];
+    }
+    $file = $cache_dir.'/'.md5($picture['path']).'.'.$picture['tn_ext'];
+
+    if (!is_dir($cache_dir))
+    {
+      mkgetdir($cache_dir, MKGETDIR_DEFAULT&~MKGETDIR_DIE_ON_ERROR);
+      if (!is_writable($cache_dir))
+      {
+        die("Give write access (chmod 777) to $cache_dir directory at the root of your Piwigo installation");
+      }
+    }
+
+    $filepath = $picture['path'];
+    if ($data['use_high'])
+    {
+      include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php');
+      $filepath = file_path_for_type($filepath, 'high');
+    }
+    $img = new pwg_image($filepath);
+    $result = $img->pwg_resize($file, $data['width'], $data['height'], $conf['upload_form_thumb_quality'], false, true, ($params['size'] == 'big'), false);
+    $img->destroy();
+  }
+  else
+  {
+    $file = $data['src'];
+    $result['width'] = $data['width'];
+    $result['height'] = $data['height'];
+  }
+
+  if ($params['return'])
+  {
+    switch (get_extension($file))
+    {
+      case 'jpg':
+      case 'jpeg':
+        header('Content-type: image/jpeg'); break;
+      case 'gif':
+        header('Content-type: image/gif'); break;
+      case 'png':
+        header('Content-type: image/png'); break;
+      default:
+        header('Content-type: unknow'); break;
+    }  
+    
+    header('Last-Modified: '.date('r', filemtime($file)));
+    readfile($file);
+    if (!$conf['GThumb']['cache_big_thumb'])
+    {
+      @unlink($file);
+    }
+    exit();
+  }
+
+  return array(
+    'id' => $picture['id'],
+    'src' => $file,
+    'width' => $result['width'],
+    'height' => $result['height'],
+  );
+}
+
+function gtdeltree($path)
+{
+  if (is_dir($path))
+  {
+    $fh = opendir($path);
+    while ($file = readdir($fh))
+    {
+      if ($file != '.' and $file != '..')
+      {
+        $pathfile = $path . '/' . $file;
+        if (is_dir($pathfile))
+        {
+          gtdeltree($pathfile);
+        }
+        else
+        {
+          @unlink($pathfile);
+        }
+      }
+    }
+    closedir($fh);
+    return @rmdir($path);
+  }
+}
+
+?>
Index: /extensions/GThumb/js/gthumb.js
===================================================================
--- /extensions/GThumb/js/gthumb.js	(revision 12678)
+++ /extensions/GThumb/js/gthumb.js	(revision 12678)
@@ -0,0 +1,202 @@
+var GThumb = {
+
+  selector: null,
+  max_height: 200,
+  margin: 10,
+  max_first_thumb_width: 0.7,
+  big_thumb: null,
+  small_thumb: null,
+  method: 'crop',
+  t: new Array,
+
+  queue: jQuery.manageAjax.create('queued', {
+    queue: true,  
+    cacheResponse: false,
+    maxRequests: 2,
+    preventDoubleRequests: false
+  }),
+
+  build: function (selector) {
+
+    this.selector = selector;
+    jQuery(selector+' img').each(function() {
+      id = parseInt(this.id.substring(2));
+      width = parseInt(jQuery(this).attr('width'));
+      height = parseInt(jQuery(this).attr('height'));
+      GThumb.t.push({id:id,width:width,height:height});
+
+      if (jQuery(this).attr('src') == '' && id != GThumb.big_thumb.id) {
+        GThumb.addToQueue(id, 1);
+      }
+    });
+
+    jQuery.resize.throttleWindow = false;
+    jQuery.resize.delay = 50;
+    jQuery(selector).resize(function() { GThumb.process(); });
+    this.process();
+  },
+
+  addToQueue: function (id, loop) {
+
+    this.queue.add({
+      type: 'GET', 
+      url: 'ws.php', 
+      data: {
+        method: 'pwg.images.getGThumbPlusThumbnail',
+        image_id: id,
+        format: 'json'
+      },
+      dataType: 'json',
+      success: function(data) {
+        if (data.stat == 'ok') {
+          jQuery('#gt'+data.result.id).prop('src', data.result.src).show();
+        } else if (loop < 4) {
+          GThumb.addToQueue(id, ++loop);
+        }
+      },
+      error: function() {
+        if (loop < 4) GThumb.addToQueue(id, ++loop);
+      }
+    });
+  },
+
+  process: function() {
+
+    var width_count = this.margin;
+    var line = 1;
+    var round_rest = 0;
+    var main_width = jQuery(this.selector).width();
+    var first_thumb = jQuery(this.selector+' img:first');
+    var best_size = {width:1,height:1};
+
+    if (this.big_thumb != null && this.big_thumb.height < main_width * this.max_first_thumb_width) {
+
+      // Compute best size for landscape picture (we choose bigger height)
+      min_ratio = Math.min(1, this.big_thumb.width/this.big_thumb.height);
+
+      for(width = this.big_thumb.width; width/best_size.height>=min_ratio; width--) {
+        width_count = this.margin;
+        height = this.margin;
+        available_width = main_width - (width + this.margin);
+        line = 1;
+        for (i=1;i<this.t.length;i++) {
+
+          width_count += this.t[i].width + this.margin;
+
+          if (width_count > available_width) {
+            ratio = width_count / available_width;
+            height += Math.round(this.t[i].height / ratio);
+            line++;
+            width_count = this.margin;
+            if (line > 2) {
+              if (height > best_size.height && width/height > min_ratio && height<=this.big_thumb.height) {
+                best_size = {width:width,height:height}
+              }
+              break;
+            }
+          }
+        }
+        if (line <= 2) {
+          best_size = {width:width,height:this.big_thumb.height};
+        }
+      }
+
+      if (this.big_thumb.src != first_thumb.attr('src')) {
+        first_thumb.attr('src', this.big_thumb.src).attr({width:this.big_thumb.width,height:this.big_thumb.height});
+        this.t[0].width = this.big_thumb.width;
+        this.t[0].height = this.big_thumb.height;
+      }
+      this.t[0].crop = best_size.width;
+      this.resize(first_thumb, this.big_thumb.width, this.big_thumb.height, best_size.width, best_size.height, 'crop');
+
+    }
+
+    if (best_size.width == 1) {
+      if (this.small_thumb != null && this.small_thumb.src != first_thumb.attr('src')) {  
+        first_thumb.prop('src', this.small_thumb.src).attr({width:this.small_thumb.width,height:this.small_thumb.height});
+        this.t[0].width = this.small_thumb.width;
+        this.t[0].height = this.small_thumb.height;
+      }
+      this.t[0].crop = false;
+    }
+
+    width_count = this.margin;
+    max_height = 0;
+    line = 1;
+    thumb_process = new Array;
+
+    for (i=this.t[0].crop!=false?1:0;i<this.t.length;i++) {
+
+      width_count += this.t[i].width + this.margin;
+      max_height = Math.max(this.t[i].height, max_height);
+      thumb_process.push(this.t[i]);
+
+      available_width = main_width;
+      if (line <= 2 && this.t[0].crop !== false) {
+        available_width -= (this.t[0].crop + this.margin);
+      }
+
+      if (width_count > available_width) {
+
+        last_thumb = this.t[i].id;
+        ratio = width_count / available_width;
+        new_height = Math.round(max_height / ratio);
+        round_rest = 0;
+        width_count = this.margin;
+
+        for (j=0;j<thumb_process.length;j++) {
+
+          if (thumb_process[j].id == last_thumb) {
+            new_width = available_width - width_count - this.margin;
+          } else {
+            new_width = (thumb_process[j].width + round_rest) / ratio;
+            round_rest = new_width - Math.round(new_width);
+            new_width = Math.round(new_width);
+          }
+          this.resize(jQuery('#gt'+thumb_process[j].id), thumb_process[j].width, thumb_process[j].height, new_width, new_height, this.method);
+
+          width_count += new_width + this.margin;
+        }
+        thumb_process = new Array;
+        width_count = this.margin;
+        max_height = 0;
+        line++;
+      }
+    }
+
+    // Last line does not need to be cropped
+    for (j=0;j<thumb_process.length;j++) {
+      this.resize(jQuery('#gt'+thumb_process[j].id), thumb_process[j].width, thumb_process[j].height, thumb_process[j].width, max_height, this.method);
+    }
+
+    if (main_width != jQuery(this.selector).width()) {
+      this.process();
+    }
+  },
+
+  resize: function(thumb, width, height, new_width, new_height, method) {
+
+    if (method == 'resize') {
+      thumb.css({
+        height: new_height+'px',
+        width: new_width+'px'
+      });
+      height_crop = 0;
+      width_crop = 0;
+    } else {
+      thumb.css({height: '', width: ''});
+      height_crop = Math.round((height - new_height)/2);
+      width_crop = Math.round((width - new_width)/2);
+    }
+
+    thumb.parents('li').css({
+      height: new_height+'px',
+      width: new_width+'px'
+    });
+    thumb.parent('a').css({
+      clip: 'rect('+height_crop+'px, '+(new_width+width_crop)+'px, '+(new_height+height_crop)+'px, '+width_crop+'px)',
+      top: -height_crop+'px',
+      left: -width_crop+'px'
+    });
+  }
+}
Index: /extensions/GThumb/js/jquery.ba-resize.min.js
===================================================================
--- /extensions/GThumb/js/jquery.ba-resize.min.js	(revision 12678)
+++ /extensions/GThumb/js/jquery.ba-resize.min.js	(revision 12678)
@@ -0,0 +1,9 @@
+/*
+ * jQuery resize event - v1.1 - 3/14/2010
+ * http://benalman.com/projects/jquery-resize-plugin/
+ * 
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+(function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this);
Index: /extensions/GThumb/language/en_UK/plugin.lang.php
===================================================================
--- /extensions/GThumb/language/en_UK/plugin.lang.php	(revision 12678)
+++ /extensions/GThumb/language/en_UK/plugin.lang.php	(revision 12678)
@@ -0,0 +1,9 @@
+<?php
+
+$lang['Thumbnails max height'] = 'Thumbnails max height';
+$lang['Margin between thumbnails'] = 'Margin between thumbnails';
+$lang['Double the size of the first thumbnail'] = 'Double the size of the first thumbnail';
+$lang['Cache the big thumbnails (recommended)'] = 'Cache the big thumbnails (recommended)';
+$lang['Scale thumbnails'] = 'Scale thumbnails';
+
+?>
Index: /extensions/GThumb/language/fr_FR/plugin.lang.php
===================================================================
--- /extensions/GThumb/language/fr_FR/plugin.lang.php	(revision 12678)
+++ /extensions/GThumb/language/fr_FR/plugin.lang.php	(revision 12678)
@@ -0,0 +1,9 @@
+<?php
+
+$lang['Thumbnails max height'] = 'Hauteur maximum des miniatures';
+$lang['Margin between thumbnails'] = 'Marge entre les miniatures';
+$lang['Double the size of the first thumbnail'] = 'Doubler la taille de la première miniature';
+$lang['Cache the big thumbnails (recommended)'] = 'Mettre en cache les grosse miniatures (recommandé)';
+$lang['Scale thumbnails'] = 'Redimensionner les miniatures';
+
+?>
Index: /extensions/GThumb/main.inc.php
===================================================================
--- /extensions/GThumb/main.inc.php	(revision 12678)
+++ /extensions/GThumb/main.inc.php	(revision 12678)
@@ -0,0 +1,195 @@
+<?php
+/*
+Plugin Name: GThumb+
+Version: auto
+Description: Display thumbnails as patchwork
+Plugin URI: auto
+Author: P@t
+Author URI: http://www.gauchon.com
+*/
+
+global $conf;
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+define('GTHUMB_PATH' , PHPWG_PLUGINS_PATH . basename(dirname(__FILE__)) . '/');
+define('GTHUMB_CACHE_DIR', PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'GThumb');
+
+$conf['GThumb'] = unserialize($conf['GThumb']);
+
+add_event_handler('loc_begin_index', 'GThumb_init', 60);
+add_event_handler('ws_add_methods', 'add_gthumb_thumbnails_method');
+add_event_handler('get_admin_plugin_menu_links', 'GThumb_admin_menu');
+
+function GThumb_init()
+{
+  global $conf, $user, $page, $template;
+
+  $template->set_prefilter('index', 'GThumb_prefilter');
+
+  $user['nb_image_page'] = $conf['GThumb']['nb_image_page'];
+  $page['nb_image_page'] = $conf['GThumb']['nb_image_page'];
+
+  add_event_handler('loc_end_index_thumbnails', 'process_GThumb', 50, 2);
+
+  if (is_dir(GTHUMB_CACHE_DIR) and !is_dir(GTHUMB_CACHE_DIR.'/'.$conf['GThumb']['height']))
+  {
+    // We clean cache dir because configuration has changed
+    include_once(GTHUMB_PATH.'functions.inc.php');
+    gtdeltree(GTHUMB_CACHE_DIR);
+  }
+}
+
+function process_GThumb($tpl_vars, $pictures)
+{
+  global $template, $conf;
+
+  $template->set_filename( 'index_thumbnails', realpath(GTHUMB_PATH.'template/gthumb.tpl'));
+  $template->assign('GThumb', $conf['GThumb']);
+
+  include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
+
+  foreach ($tpl_vars as $key => &$tpl_var)
+  {
+    $data = get_gthumb_data($pictures[$key]);
+
+    $tpl_var['TN_SRC'] = $data['src'];
+    $tpl_var['TN_WIDTH'] = $data['width'];
+    $tpl_var['TN_HEIGHT'] = $data['height'];
+  }
+
+  if ($conf['GThumb']['big_thumb'])
+  {
+    $ft = &$tpl_vars[0];
+
+    // Small thumb data
+    $small_thumb = array(
+      'id' => $ft['ID'],
+      'src' => $ft['TN_SRC'],
+      'width' => $ft['TN_WIDTH'],
+      'height' => $ft['TN_HEIGHT'],
+    );
+    if (empty($small_thumb['src']))
+    {
+      $small_thumb['src'] = 'ws.php?method=pwg.images.getGThumbPlusThumbnail&image_id='.$small_thumb['id'].'&return=true';
+    }
+
+    // Big thumb data
+    $data = get_gthumb_data($pictures[0], 'big');
+
+    $big_thumb = array(
+      'id' => $ft['ID'],
+      'src' => $data['src'],
+      'width' => $data['width'],
+      'height' => $data['height'],
+    );
+    if (empty($data['src']))
+    {
+      $big_thumb['src'] = 'ws.php?method=pwg.images.getGThumbPlusThumbnail&image_id='.$ft['ID'].'&size=big&return=true';
+    }
+
+    $template->assign(
+      array(
+        'small_thumb' => $small_thumb,
+        'big_thumb' => $big_thumb,
+      )
+    );
+    $ft['TN_SRC'] = $big_thumb['src'];
+    $ft['TN_WIDTH'] = $big_thumb['width'];
+    $ft['TN_HEIGHT'] = $big_thumb['height'];
+  }
+  
+  return $tpl_vars;
+}
+
+function add_gthumb_thumbnails_method($arr)
+{
+  include_once(GTHUMB_PATH.'functions.inc.php');
+
+  $service = &$arr[0];
+  $service->addMethod(
+    'pwg.images.getGThumbPlusThumbnail',
+    'ws_images_getGThumbPlusThumbnail',
+    array(
+      'image_id' => array(),
+      'size' => array('default'=>'small'),
+      'return' => array('default'=>false),
+    ),
+    'Get thumbnail for GThumb+ plugin. Size parameter can be "small" or "big".'
+  );
+}
+
+function get_gthumb_data($picture, $size='small')
+{
+  global $conf;
+
+  if (empty($picture['width']))
+  {
+    $file = get_thumbnail_url($picture);
+    list($width, $height) = getimagesize($file);
+
+    return array(
+      'src' => $file,
+      'width' => $width,
+      'height' => $height,
+    );
+  }
+
+  $new_height = $size == 'small' ? $conf['GThumb']['height'] : $conf['GThumb']['height'] * 2 + $conf['GThumb']['margin'];
+  $file = GTHUMB_CACHE_DIR.'/'.$new_height.'/'.md5($picture['path']).'.'.$picture['tn_ext'];
+
+  if (file_exists($file))
+  {
+    list($width, $height) = getimagesize($file);
+
+    return array(
+      'src' => $file,
+      'width' => $width,
+      'height' => $height,
+    );
+  }
+
+  $width = $picture['width'];
+  $height = $picture['height'];
+  $use_high = false;
+
+  if ($height < $new_height and $picture['has_high'] == 'true')
+  {
+    $width = $picture['high_width'];
+    $height = $picture['high_height'];
+    $use_high = true;
+  }
+
+  if ($size == 'big')
+  {
+    $width = min($width, round($height * 1.15));
+  }
+
+  $result = pwg_image::get_resize_dimensions($width, $height, 5000, $new_height);
+  $result['src'] = '';
+  $result['use_high'] = $use_high;
+  $result['cache_path'] = GTHUMB_CACHE_DIR.'/'.$new_height.'/';
+
+  return $result;
+}
+
+function GThumb_prefilter($content, $smarty)
+{
+  $pattern = '#\<div.*?id\="thumbnails".*?\>\{\$THUMBNAILS\}\</div\>#';
+  $replacement = '<ul id="thumbnails">{$THUMBNAILS}</ul>';
+
+  return preg_replace($pattern, $replacement, $content);
+}
+
+function GThumb_admin_menu($menu)
+{
+  array_push($menu,
+    array(
+      'NAME' => 'GThumb+',
+      'URL' => get_root_url().'admin.php?page=plugin-'.basename(dirname(__FILE__)),
+    )
+  );
+  return $menu;
+}
+
+?>
Index: /extensions/GThumb/maintain.inc.php
===================================================================
--- /extensions/GThumb/maintain.inc.php	(revision 12678)
+++ /extensions/GThumb/maintain.inc.php	(revision 12678)
@@ -0,0 +1,24 @@
+<?php
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+function plugin_install()
+{
+  include(dirname(__FILE__).'/config_default.inc.php');
+
+  $query = '
+INSERT INTO ' . CONFIG_TABLE . ' (param,value,comment)
+VALUES ("GThumb" , "'.addslashes(serialize($config_default)).'" , "GThumb plugin parameters");';
+  pwg_query($query);
+}
+
+function plugin_uninstall()
+{
+  include_once(dirname(__FILE__).'/functions.inc.php');
+  gtdeltree(GTHUMB_CACHE_DIR);
+  
+  $query = 'DELETE FROM ' . CONFIG_TABLE . ' WHERE param="GThumb" LIMIT 1;';
+  pwg_query($query);
+}
+
+?>
Index: /extensions/GThumb/template/admin.tpl
===================================================================
--- /extensions/GThumb/template/admin.tpl	(revision 12678)
+++ /extensions/GThumb/template/admin.tpl	(revision 12678)
@@ -0,0 +1,54 @@
+<div class="titrePage">
+<h2>GThumb+</h2>
+</div>
+
+<form action="" method="post">
+
+<fieldset id="GThumb">
+<legend>{'Configuration'|@translate}</legend>
+<table>
+  <tr>
+    <td align="right">{'Thumbnails max height'|@translate} : &nbsp;&nbsp;</td>
+    <td><input type="text" size="2" maxlength="3" name="height" value="{$HEIGHT}">&nbsp;px</td></td>
+  </tr>
+
+  <tr>
+    <td align="right">{'Margin between thumbnails'|@translate} : &nbsp;&nbsp;</td>
+    <td><input type="text" size="2" maxlength="3" name="margin" value="{$MARGIN}">&nbsp;px</td>
+  </tr>
+
+  <tr>
+    <td align="right">{'Number of photos per page'|@translate} : &nbsp;&nbsp;</td>
+    <td><input type="text" size="2" maxlength="3" name="nb_image_page" value="{$NB_IMAGE_PAGE}"></td>
+  </tr>
+
+  <tr>
+    <td align="right">{'Double the size of the first thumbnail'|@translate} : &nbsp;&nbsp;</td>
+    <td><input type="radio" name="big_thumb" value="1" {if $BIG_THUMB}checked="checked"{/if}> {'Yes'|@translate} &nbsp;
+        <input type="radio" name="big_thumb" value="0" {if !$BIG_THUMB}checked="checked"{/if}> {'No'|@translate}
+    </td>
+  </tr>
+
+  <tr>
+    <td align="right">{'Cache the big thumbnails (recommended)'|@translate} : &nbsp;&nbsp;</td>
+    <td><input type="radio" name="cache_big_thumb" value="1" {if $CACHE_BIG_THUMB}checked="checked"{/if}> {'Yes'|@translate} &nbsp;
+        <input type="radio" name="cache_big_thumb" value="0" {if !$CACHE_BIG_THUMB}checked="checked"{/if}> {'No'|@translate}
+    </td>
+  </tr>
+
+  <tr>
+    <td align="right">{'Scale thumbnails'|@translate} : &nbsp;&nbsp;</td>
+    <td><input type="radio" name="method" value="crop" {if $METHOD == 'crop'}checked="checked"{/if}> {'Crop'|@translate} &nbsp;
+        <input type="radio" name="method" value="resize" {if $METHOD == 'resize'}checked="checked"{/if}> {'Resize'|@translate}
+    </td>
+  </tr>
+
+</table>
+</fieldset>
+
+<p><input type="submit" name="submit" value="{'Submit'|@translate}"></p>
+</form>
+
+{html_head}{literal}
+<style type="text/css">#GThumb td { padding-bottom: 12px; }</style>
+{/literal}{/html_head}
Index: /extensions/GThumb/template/gthumb.css
===================================================================
--- /extensions/GThumb/template/gthumb.css	(revision 12678)
+++ /extensions/GThumb/template/gthumb.css	(revision 12678)
@@ -0,0 +1,17 @@
+#thumbnails {
+  padding: 0;
+  width:auto;
+  overflow:hidden;
+}
+
+#thumbnails li {
+  position: relative;
+  overflow:hidden;
+  float: left;
+  display: inline;
+  background: none !important;
+}
+
+#thumbnails li a {
+  position: absolute;
+}
Index: /extensions/GThumb/template/gthumb.tpl
===================================================================
--- /extensions/GThumb/template/gthumb.tpl	(revision 12678)
+++ /extensions/GThumb/template/gthumb.tpl	(revision 12678)
@@ -0,0 +1,32 @@
+{if !empty($thumbnails)}
+{strip}{foreach from=$thumbnails item=thumbnail}
+<li>
+  <a href="{$thumbnail.URL}">
+    <img id="gt{$thumbnail.ID}" class="thumbnail" src="{$thumbnail.TN_SRC}" alt="{$thumbnail.TN_ALT}" title="{$thumbnail.TN_TITLE}"
+         width="{$thumbnail.TN_WIDTH}" height="{$thumbnail.TN_HEIGHT}" {if empty($thumbnail.TN_SRC)}style="display:none;"{/if}>
+  </a>
+</li>
+{/foreach}{/strip}
+
+{combine_css path="plugins/GThumb/template/gthumb.css"}
+{combine_script id='jquery.ajaxmanager' path='themes/default/js/plugins/jquery.ajaxmanager.js'}
+{combine_script id='jquery.ba-resize' path='plugins/GThumb/js/jquery.ba-resize.min.js'}
+{combine_script id='gthumb' require='jquery,jquery.ajaxmanager,jquery.ba-resize' path='plugins/GThumb/js/gthumb.js'}
+
+{footer_script require="gthumb"}
+GThumb.max_height = {$GThumb.height};
+GThumb.margin = {$GThumb.margin};
+GThumb.method = '{$GThumb.method}';
+
+{if isset($big_thumb)}
+GThumb.big_thumb = {ldelim}id:{$big_thumb.id},src:'{$big_thumb.src}',width:{$big_thumb.width},height:{$big_thumb.height}{rdelim};
+GThumb.small_thumb = {ldelim}id:{$small_thumb.id},src:'{$small_thumb.src}',width:{$small_thumb.width},height:{$small_thumb.height}{rdelim};
+{/if}
+
+GThumb.build('#thumbnails');
+{/footer_script}
+
+{html_head}
+<style type="text/css">#thumbnails li {ldelim} margin:0 0 {$GThumb.margin}px {$GThumb.margin}px !important; }</style>
+{/html_head}
+{/if}
