Index: extensions/GMaps/gmaps.css
===================================================================
--- extensions/GMaps/gmaps.css	(revision 7125)
+++ extensions/GMaps/gmaps.css	(revision 7128)
@@ -51,3 +51,19 @@
 }
 
-
+#iDialogGMapNfo {
+  height:18px;
+  margin:5px 5px 0 60px;
+  text-align:left;
+}
+#iDialogGMapNfo span {
+  position:relative;
+  top:-3px;
+  margin-left:3px;
+}
+#iDialogGMapWaiting {
+  position:absolute;
+  z-index:1500;
+  background:#000000;
+  opacity:0.55;
+  filter:alpha(opacity:55);
+}
Index: extensions/GMaps/gmaps2.css
===================================================================
--- extensions/GMaps/gmaps2.css	(revision 7125)
+++ extensions/GMaps/gmaps2.css	(revision 7128)
@@ -118,3 +118,28 @@
 }
 
+#gmapsNbPhotos {
+  font-size:80%;
+  font-weight:normal;
+  margin-left:3px;
+  position:relative;
+  top:-3px;
+}
+#gmapsLoading {
+  background:none repeat scroll 0 0 #FFFFFF;
+  position:absolute;
+  top:0;
+  width:90%;
+}
+#gmapsLoading span {
+  margin-left:3px;
+  position:relative;
+  top:-3px;
+}
 
+#iDialogGMapWaiting {
+  position:absolute;
+  z-index:1500;
+  background:#000000;
+  opacity:0.55;
+  filter:alpha(opacity:55);
+}
Index: extensions/GMaps/gmaps_aip.class.inc.php
===================================================================
--- extensions/GMaps/gmaps_aip.class.inc.php	(revision 7125)
+++ extensions/GMaps/gmaps_aip.class.inc.php	(revision 7128)
@@ -53,9 +53,9 @@
     $this->tabsheet->add('kml_files',
                           l10n('gmaps_kml_files_management'),
-                          $this->getAdminLink()."&amp;fGMaps_tabsheet=kml_files");
+                          $this->getAdminLink()."&amp;fGMaps_tabsheet=kml_files"); */
     $this->tabsheet->add('search',
                           l10n('gmaps_search'),
                           $this->getAdminLink()."&amp;fGMaps_tabsheet=search");
-    $this->tabsheet->add('help',
+/*    $this->tabsheet->add('help',
                           l10n('gmaps_help'),
                           $this->getAdminLink()."&amp;fGMaps_tabsheet=help");
@@ -74,8 +74,13 @@
   public function initEvents()
   {
+    parent::initEvents();
+
+    if($_REQUEST['fGMaps_tabsheet']=='search')
+    {
+      // load request builder JS only on the search page
+      GPCRequestBuilder::loadJSandCSS();
+    }
     add_event_handler('loc_end_page_header', array(&$this->css, 'applyCSS'));
     GPCCss::applyGpcCss();
-
-    parent::initEvents();
   }
 
@@ -254,9 +259,10 @@
     global $template;
 
-    /*$template->set_filename('body_page',
-                dirname($this->getFileLocation()).'/admin/plugin_admin_maps.tpl');
-
-
-    $template->assign_var_from_handle('GMAPS_BODY_PAGE', 'body_page');*/
+    $template->set_filename('body_page',
+                dirname($this->getFileLocation()).'/admin/gmaps_search.tpl');
+
+    $template->assign('gmaps_search_page', GPCRequestBuilder::displaySearchPage($this->getPluginName()));
+
+    $template->assign_var_from_handle('GMAPS_BODY_PAGE', 'body_page');
   }
 
Index: extensions/GMaps/gmaps_ajax.php
===================================================================
--- extensions/GMaps/gmaps_ajax.php	(revision 7125)
+++ extensions/GMaps/gmaps_ajax.php	(revision 7128)
@@ -72,6 +72,6 @@
 
            $_REQUEST['ajaxfct']=='public.maps.init' or
-           $_REQUEST['ajaxfct']=='public.maps.getMarkers' or
-           $_REQUEST['ajaxfct']=='public.maps.getMarkerInfos'
+           $_REQUEST['ajaxfct']=='public.maps.getMarkers' //or
+           //$_REQUEST['ajaxfct']=='public.maps.getMarkerInfos'
            )) $_REQUEST['ajaxfct']='';
 
@@ -234,4 +234,11 @@
               $_REQUEST['ajaxfct']='';
             }
+            else
+            {
+              if(!isset($_REQUEST['datas']['levelInfo'])) $_REQUEST['datas']['levelInfo']=1;
+
+              if(!($_REQUEST['datas']['levelInfo']==0 or
+                   $_REQUEST['datas']['levelInfo']==1)) $_REQUEST['datas']['levelInfo']=1;
+            }
           }
         }
@@ -246,4 +253,6 @@
             $_REQUEST['ajaxfct']='';
           }
+
+
         }
 
@@ -787,4 +796,6 @@
      *                       'width' : width of maps in pixels
      *                       'height' : height of maps in pixels
+     *                       'levelInfo' : 0 = don't return pictures info (name, url, ...)
+     *                                     1 = return pictures informations
      * @return Array|String : a JSON string of an array of points (nbPictures, lat, lng)
      */
@@ -793,5 +804,10 @@
       global $user, $page;
 
-      $returned=array();
+      $returned=array(
+        'markers' => array(),
+        'datas' => array(
+          'nbPhotos' => 0
+        )
+      );
 
       /*
@@ -907,12 +923,12 @@
         {
           $coords=array(
-            'nbImagesTxt' => '',
+            'nbImgTxt' => '',
             'nbImages' => 0,
-            'latitude' => 0,
-            'longitude' => 0,
-            'imagesTnFile' => array(),
-            'imagesCatsNames' => array(),
-            'imagesName' => array(),
-            'imagesCatsUrl' => array(),
+            'lat' => 0,                   // 'lat' rather than 'latitude'
+            'lng' => 0,                   // 'lng' rather than 'longitude'
+            'imgTn' => array(),
+            'imgCatsNames' => array(),
+            'imgName' => array(),
+            'imgCatsUrl' => array(),
           );
 
@@ -938,27 +954,46 @@
             }
 
+            if(count($tmpCatsId)<=1) $tmpCatsNames='';
+
             $coords['nbImages']++;
-            $coords['latitude']+=$point['latitude'];
-            $coords['longitude']+=$point['longitude'];
-            $coords['imagesTnFile'][]=$point['imageTnFile'];
-            $coords['imagesCatsNames'][]=$tmpCatsNames;
-            $coords['imagesName'][]=$point['imageName'];
-            $coords['imagesCatsUrl'][]=$tmpCatsUrl;
-          }
-          $coords['latitude']=$coords['latitude']/count($group);
-          $coords['longitude']=$coords['longitude']/count($group);
-          $coords['uniqueId']=md5($coords['latitude'].$coords['latitude']);
+
+            $coords['lat']+=$point['latitude'];
+            $coords['lng']+=$point['longitude'];
+
+            if($datas['levelInfo']==1)
+            {
+              $coords['imgTn'][]=substr($point['imageTnFile'],12);
+              $coords['imgCatsNames'][]=$tmpCatsNames;
+              $coords['imgName'][]=$point['imageName'];
+              $coords['imgCatsUrl'][]=$tmpCatsUrl;
+            }
+          }
+          $coords['lat']=$coords['lat']/count($group);
+          $coords['lng']=$coords['lng']/count($group);
+          $coords['uniqueId']=md5($coords['lat'].$coords['lng']);
 
           if($coords['nbImages']==1)
           {
-            $coords['nbImagesTxt']=l10n('gmaps_1_picture');
+            $coords['nbImgTxt']=l10n('gmaps_1_picture');
           }
           else
           {
-            $coords['nbImagesTxt']=sprintf(l10n('gmaps_nb_pictures'), $coords['nbImages']);
-          }
-
-          $returned[]=$coords;
-        }
+            $coords['nbImgTxt']=sprintf(l10n('gmaps_nb_pictures'), $coords['nbImages']);
+          }
+
+
+
+          $returned['markers'][]=$coords;
+          $returned['datas']['nbPhotos']+=$coords['nbImages'];
+        }
+      }
+
+      if($returned['datas']['nbPhotos']>1)
+      {
+        $returned['datas']['nbPhotos']=sprintf(l10n('gmaps_nb_pictures'), $returned['datas']['nbPhotos']);
+      }
+      else
+      {
+        $returned['datas']['nbPhotos']=l10n('gmaps_1_picture');
       }
 
Index: extensions/GMaps/gmaps_install.class.inc.php
===================================================================
--- extensions/GMaps/gmaps_install.class.inc.php	(revision 7125)
+++ extensions/GMaps/gmaps_install.class.inc.php	(revision 7128)
@@ -130,4 +130,5 @@
 
       GPCCore::register($this->getPluginName(), GMAPS_VERSION, GMAPS_GPC_NEEDED);
+      GPCRequestBuilder::register($this->getPluginName(), dirname($this->getFileLocation()).'/gmaps_rb_callback.class.inc.php');
       return('');
     }
Index: extensions/GMaps/gmaps_pip.class.inc.php
===================================================================
--- extensions/GMaps/gmaps_pip.class.inc.php	(revision 7125)
+++ extensions/GMaps/gmaps_pip.class.inc.php	(revision 7128)
@@ -209,5 +209,6 @@
       lang:{
         boundmap:'".l10n('gmaps_i_boundmap')."',
-        boundkml:'".l10n('gmaps_i_boundkml')."'
+        boundkml:'".l10n('gmaps_i_boundkml')."',
+        loading:'".l10n('gmaps_loading')."'
       },
       requestId:'',
@@ -246,5 +247,5 @@
     if($this->picture['geolocated']==false) return(false);
 
-    if(count($this->picture['content']['MP'])>0)
+    if(isset($this->picture['content']['MP']) and count($this->picture['content']['MP'])>0)
     {
       // there is maps in meta display mode
@@ -270,5 +271,5 @@
     }
 
-    if(count($this->picture['content']['IP'])>0)
+    if(isset($this->picture['content']['IP']) and count($this->picture['content']['IP'])>0)
     {
       // there is maps in icon display mode
@@ -361,5 +362,5 @@
         'height' => $map['height'],
         'style' => $map['style'],
-        'mode' => $map['displayType']
+        'displayType' => $map['displayType']
       );
 
Index: extensions/GMaps/gmaps_rb_callback.class.inc.php
===================================================================
--- extensions/GMaps/gmaps_rb_callback.class.inc.php	(revision 7128)
+++ extensions/GMaps/gmaps_rb_callback.class.inc.php	(revision 7128)
@@ -0,0 +1,198 @@
+<?php
+/* -----------------------------------------------------------------------------
+  Plugin     : GMaps
+  Author     : Grum
+    email    : grum@piwigo.org
+    website  : http://photos.grum.fr
+
+    << May the Little SpaceFrog be with you ! >>
+  ------------------------------------------------------------------------------
+  See main.inc.php for release information
+
+
+  --------------------------------------------------------------------------- */
+
+  if(!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+
+  include_once(PHPWG_PLUGINS_PATH.'GrumPluginClasses/classes/GPCRequestBuilder.class.inc.php');
+
+load_language('plugin.lang', GMAPS_PATH);
+
+class RBCallBackGMaps extends GPCSearchCallback {
+
+  /**
+   * the getImageId returns the name of the image id attribute
+   * return String
+   */
+  static public function getImageId()
+  {
+    return("pgc.imageId");
+  }
+
+  /**
+   * the getSelect function must return an attribute list separated with a comma
+   *
+   * "att1, att2, att3, att4"
+   */
+  static public function getSelect($param="")
+  {
+    return("pgc.latitude, pgc.longitude");
+  }
+
+  /**
+   * the getFrom function must return a tables list separated with a comma
+   *
+   * "table1, (table2 left join table3 on table2.key = table3.key), table4"
+   */
+  static public function getFrom($param="")
+  {
+    global $prefixeTable;
+
+    return($prefixeTable."gmaps_cache pgc");
+  }
+
+  /**
+   * the getWhere function must return a ready to use where clause
+   *
+   * "(att1 = value0 OR att2 = value1) AND att4 LIKE value2 "
+   */
+  static public function getWhere($param="")
+  {
+    global $user;
+
+    $returned='';
+
+    if($param['bounds']['east']<$param['bounds']['west'])
+    {
+      $returned=" (pgc.longitude <= ".$param['bounds']['east']." OR pgc.longitude >= ".$param['bounds']['west'].") ";
+    }
+    else
+    {
+      $returned=" (pgc.longitude >= ".$param['bounds']['west']." AND pgc.longitude <= ".$param['bounds']['east'].") ";
+    }
+
+    $returned.=" AND pgc.latitude >= ".$param['bounds']['south']."
+                 AND pgc.latitude <= ".$param['bounds']['north']."
+                 AND pgc.userId='".$user['id']."'
+                 AND pgc.requestId='".$param['requestId']."' ";
+
+    return($returned);
+  }
+
+  /**
+   * the getJoin function must return a ready to use where allowing to join the
+   * IMAGES table (key : id) with given conditions
+   *
+   * "att3 = pit.id "
+   */
+  static public function getJoin($param="")
+  {
+    return("pgc.imageId = pit.id");
+  }
+
+
+  /**
+   * the getFilter function must return a ready to use where clause
+   * this where clause is used to filter the cache when the used tables can
+   * return more than one result
+   *
+   * the filter can be empty, can be equal to the where clause, or can be equal
+   * to a sub part of the where clause
+   *
+   */
+  static public function getFilter($param="")
+  {
+    return(self::getWhere($param));
+  }
+
+  /**
+   * this function is called by the request builder, allowing to display plugin
+   * data with a specific format
+   *
+   * @param Array $attributes : array of ('attribute_name' => 'attribute_value')
+   * @return String : HTML formatted value
+   */
+  static public function formatData($attributes)
+  {
+    /* attributes is an array :
+     *    Array(
+     *      'csColors' => 'color1,color2,color3,...,colorN',
+     *      'csColorsPct' => 'pct1,pct2,pct3,...,pctN'
+     *    );
+     */
+    $returned=l10n('gmaps_geolocation')."&nbsp;:&nbsp;";
+
+    if($attributes['latitude']<0)
+    {
+      $returned.=GMaps_functions::DDtoDMS(abs($attributes['latitude'])).'&nbsp;'.l10n('gmaps_south');
+    }
+    else
+    {
+      $returned.=GMaps_functions::DDtoDMS($attributes['latitude']).'&nbsp;'.l10n('gmaps_north');
+    }
+
+    $returned.=', ';
+
+    if($attributes['longitude']<0)
+    {
+      $returned.=GMaps_functions::DDtoDMS(abs($attributes['longitude'])).'&nbsp;'.l10n('gmaps_west');
+    }
+    else
+    {
+      $returned.=GMaps_functions::DDtoDMS($attributes['longitude']).'&nbsp;'.l10n('gmaps_east');
+    }
+
+    return($returned);
+  }
+
+
+
+  /**
+   * this function is called by the request builder to make the search page, and
+   * must return the HTML & JS code of the dialogbox used to select criterion
+   *
+   * Notes :
+   *  - the dialogbox is a JS object with a public method 'show'
+   *  - when the method show is called, one parameter is given by the request
+   *    builder ; the parameter is an object defined as this :
+   *      {
+   *        cBuilder: an instance of the criteriaBuilder object used in the page,
+   *        eventOK : a callback function, called when the OK button is pushed
+   *        id:
+   *      }
+   *
+   *
+   *
+   *
+   * @param String $mode : can take 'admin' or 'public' values, allowing to
+   *                       return different interface if needed
+   * @return String : HTML formatted value
+   */
+  static public function getInterfaceContent($mode='admin')
+  {
+    return(GMaps_functions::dialogBoxGMaps());
+  }
+
+  /**
+   * this function returns the label displayed in the criterion menu
+   *
+   * @return String : label displayed in the criterions menu
+   */
+  static public function getInterfaceLabel()
+  {
+    return(l10n('gmaps_add_geographic_area'));
+  }
+
+  /**
+   * this function returns the name of the dialog box class
+   *
+   * @return String : name of the dialogbox class
+   */
+  static public function getInterfaceDBClass()
+  {
+    return('dialogChooseGMapsBox');
+  }
+
+}
+
+?>
Index: extensions/GMaps/gmaps_root.class.inc.php
===================================================================
--- extensions/GMaps/gmaps_root.class.inc.php	(revision 7125)
+++ extensions/GMaps/gmaps_root.class.inc.php	(revision 7128)
@@ -276,3 +276,66 @@
   } //class
 
+
+
+class GMaps_functions
+  {
+    static private $tables = Array();
+    static private $config = Array();
+
+    /**
+     * initialise the class
+     *
+     * @param String $prefixeTable : the piwigo prefixe used on tables name
+     * @param String $pluginNameFile : the plugin name used for tables name
+     */
+    static public function init($prefixeTable)
+    {
+      GPCCore::loadConfig(GMaps_root::$pluginNameFile, self::$config);
+      $list=GMaps_root::$pluginTables;
+
+      for($i=0;$i<count($list);$i++)
+      {
+        self::$tables[$list[$i]]=$prefixeTable.GMaps_root::$pluginNameFile.'_'.$list[$i];
+      }
+    }
+
+
+    /**
+     *  return all HTML&JS code necessary to display a dialogbox to choose
+     *  geographic area
+     */
+    static public function dialogBoxGMaps()
+    {
+      global $template;
+
+      $template->set_filename('gmaps_choose',
+                    dirname(__FILE__).'/templates/gmaps_dialog_area_choose.tpl');
+
+      $datas=Array();
+
+      $template->assign('datas', $datas);
+
+      return($template->parse('gmaps_choose', true));
+    }
+
+    /**
+     * convert a decimal degree to D°M'S'
+     *
+     * @param Float $value : the value to convert
+     * @return String : value converted in DMS
+     */
+    static public function DDtoDMS($value)
+    {
+      $degrees=(int)$value;
+      $value=($value-$degrees)*60;
+      $minutes=(int)$value;
+      $seconds=($value-$minutes)*60;
+
+      return(sprintf('%d° %d\' %.2f"', $degrees, $minutes, $seconds));
+    }
+
+  } //GMaps_functions
+
+
+
 ?>
Index: extensions/GMaps/js/gmapsCategory.js
===================================================================
--- extensions/GMaps/js/gmapsCategory.js	(revision 7125)
+++ extensions/GMaps/js/gmapsCategory.js	(revision 7128)
@@ -65,8 +65,20 @@
     width:$(map.getDiv()).width(),
     height:$(map.getDiv()).height(),
-    distanceTreshold:25
+    distanceTreshold:20
   }
 
   currentMapLoad=map;
+
+  $('#gmapsLoading').css('display', 'inline-block');
+  $('#gmapsNbPhotos').html('');
+  $('#iDialogGMapWaiting').css(
+    {
+      width:$('#iGMapsIcon').width()+'px',
+      height:$('#iGMapsIcon').height()+'px',
+      top:$('#iGMapsIcon').position().top+'px',
+      left:$('#iGMapsIcon').position().left+'px',
+      display:'block'
+    }
+  );
 
   $.ajax(
@@ -80,6 +92,9 @@
         {
           tmp=$.parseJSON(msg);
-          tmp.sort(compareMarkers);
-          applyMarkers(currentMapLoad, tmp);
+          tmp.markers.sort(compareMarkers);
+          applyMarkers(currentMapLoad, tmp.markers);
+          $('#gmapsLoading').css('display', 'none');
+          $('#gmapsNbPhotos').html('['+tmp.datas.nbPhotos+']');
+          $('#iDialogGMapWaiting').css('display', 'none');
         }
     }
@@ -128,7 +143,7 @@
     var marker = new google.maps.Marker(
       {
-        position:new google.maps.LatLng(markers[i].latitude, markers[i].longitude),
+        position:new google.maps.LatLng(markers[i].lat, markers[i].lng),
         map: currentMapLoad,
-        title:markers[i].nbImagesTxt
+        title:markers[i].nbImgTxt
       }
     );
@@ -204,5 +219,5 @@
 {
   gmaps.currentInfo.displayed=index;
-  if(gmaps.currentInfo.imagesName[index]=='')
+  if(gmaps.currentInfo.imgName[index]=='')
   {
     $('#ciGMIWC_title').html('&nbsp;');
@@ -210,15 +225,15 @@
   else
   {
-    $('#ciGMIWC_title').html(gmaps.currentInfo.imagesName[index]);
-  }
-  $('#ciGMIWC_img').attr('src', gmaps.currentInfo.imagesTnFile[index]);
+    $('#ciGMIWC_title').html(gmaps.currentInfo.imgName[index]);
+  }
+  $('#ciGMIWC_img').attr('src', './galleries/'+gmaps.currentInfo.imgTn[index]);
 
   $('#ciGMIWC_img').unbind();
-  if(gmaps.currentInfo.imagesCatsUrl[index].length==1)
+  if(gmaps.currentInfo.imgCatsUrl[index].length==1)
   {
     $('#ciGMIWC_img').bind('click',
       function ()
       {
-        window.location=gmaps.currentInfo.imagesCatsUrl[gmaps.currentInfo.displayed][0];
+        window.location=gmaps.currentInfo.imgCatsUrl[gmaps.currentInfo.displayed][0];
       }
     );
@@ -227,8 +242,8 @@
   {
     $('#ciGMIWC_showcatList').html('');
-    for(var i=0;i<gmaps.currentInfo.imagesCatsUrl[index].length;i++)
+    for(var i=0;i<gmaps.currentInfo.imgCatsUrl[index].length;i++)
     {
       $('#ciGMIWC_showcatList')
-        .append('<li><a href="'+gmaps.currentInfo.imagesCatsUrl[index][i]+'">'+gmaps.currentInfo.imagesCatsNames[index][i]+'</a></li>');
+        .append('<li><a href="'+gmaps.currentInfo.imgCatsUrl[index][i]+'">'+gmaps.currentInfo.imgCatsNames[index][i]+'</a></li>');
     }
     $('#ciGMIWC_img, #ciGMIWC_showcat')
@@ -239,10 +254,10 @@
   if(gmaps.currentInfo.nbImages>1)
   {
-    $('#ciGMIWC_picnum').html((index+1)+'/'+gmaps.currentInfo.nbImagesTxt);
+    $('#ciGMIWC_picnum').html((index+1)+'/'+gmaps.currentInfo.nbImgTxt);
     $('#ciWALeft, #ciWARight').css('display', 'inline-block');
   }
   else
   {
-    $('#ciGMIWC_picnum').html(gmaps.currentInfo.nbImagesTxt);
+    $('#ciGMIWC_picnum').html(gmaps.currentInfo.nbImgTxt);
     $('#ciWALeft, #ciWARight').css('display', 'none');
   }
@@ -416,4 +431,10 @@
       }
 
+      $('div.gmapsPopup div.ui-dialog-titlebar')
+      .append('<span id="gmapsLoading" style="display:none;"><img src="./plugins/GrumPluginClasses/icons/processing.gif"><span>'+gmaps.lang.loading+'</span></span>');
+
+      $('#ui-dialog-title-iGMapsIconContent')
+      .append('<span id="gmapsNbPhotos"></span>');
+
 
     }
Index: extensions/GMaps/language/fr_FR/plugin.lang.php
===================================================================
--- extensions/GMaps/language/fr_FR/plugin.lang.php	(revision 7125)
+++ extensions/GMaps/language/fr_FR/plugin.lang.php	(revision 7128)
@@ -121,3 +121,16 @@
 $lang['gmaps_i_show_this_picture_in']="Voir cette photo dans la catégorie :";
 
+$lang['gmaps_north']="Nord";
+$lang['gmaps_south']="Sud";
+$lang['gmaps_east']="Est";
+$lang['gmaps_west']="Ouest";
+$lang['gmaps_add_geographic_area']="Ajouter une zone géographique";
+$lang['gmaps_choose_geographic_area']="Sélectionner la zone géographique";
+$lang['gmaps_search_by_geographic_area']="Effectuer une recherche par zone géographique";
+$lang['gmaps_geographic_coords_between']="Les coordonnées géographiques sont situées entre :";
+$lang['gmaps_of_lat']="de latitude";
+$lang['gmaps_of_lng']="de longitude";
+$lang['gmaps_and']="et";
+
+
 ?>
Index: extensions/GMaps/templates/gmaps_category.tpl
===================================================================
--- extensions/GMaps/templates/gmaps_category.tpl	(revision 7125)
+++ extensions/GMaps/templates/gmaps_category.tpl	(revision 7128)
@@ -8,4 +8,5 @@
   <div id='iGMapsIconContent' style='display:none;'>
       <div id='iGMapsIcon' style='width:{$map.width}px;height:{$map.height}px;{$map.style}'></div>
+      <div id='iDialogGMapWaiting' style="display:none;"></div>
   </div>
 {/foreach}
Index: extensions/GMaps/templates/gmaps_dialog_area_choose.tpl
===================================================================
--- extensions/GMaps/templates/gmaps_dialog_area_choose.tpl	(revision 7128)
+++ extensions/GMaps/templates/gmaps_dialog_area_choose.tpl	(revision 7128)
@@ -0,0 +1,477 @@
+{known_script id="jquery.ui" src=$ROOT_URL|@cat:"themes/default/js/ui/packed/ui.core.packed.js"}
+{known_script id="jquery.ui.dialog" src=$ROOT_URL|@cat:"themes/default/js/ui/packed/ui.dialog.packed.js"}
+{known_script id="maps.google.com/api" src="http://maps.google.com/maps/api/js?sensor=false"}
+
+
+{literal}
+<script type="text/javascript">
+
+/**
+ * include this template in a page and use dialogChooseGMapsBox.show({options}) to display
+ * the dialog box
+ *
+ */
+dialogChooseGMapsBox = function()
+{
+  var bounds = {
+    north:0,
+    south:0,
+    east:0,
+    west:0
+  }
+  var requestId = '';
+
+  var dialogGMapsOptions = {
+      id:'',
+      eventOk:null,
+      cBuilder:null,
+      gMap:null,
+    };
+
+
+  /**
+   * initialize the dialog box
+   */
+  var initDialogBox = function()
+  {
+    initializeMap();
+
+    $.ajax(
+      {
+        type: "POST",
+        url: "plugins/GMaps/gmaps_ajax.php",
+        async: true,
+        data: { ajaxfct:"public.maps.init", category:0 },
+        success: function (msg)
+          {
+            requestId=msg;
+          }
+      }
+    );
+
+    $("#iDialogGMapsChoose")
+    .dialog(
+      {
+        autoOpen: false,
+        resizable: false,
+        width:$(window).width()*0.8,
+        height:$(window).height()*0.8,
+        modal: true,
+        draggable:true,
+        dialogClass: 'gcBgTabSheet gcBorder',
+        title: '{/literal}{"gmaps_choose_geographic_area"|@translate}{literal}',
+        open: function(event, ui)
+        {
+          google.maps.event.trigger(dialogGMapsOptions.gMap, 'resize');
+
+          if(bounds.north!=0 && bounds.south!=0 && bounds.east!=0 && bounds.west!=0)
+          {
+            dialogGMapsOptions.gMap.fitBounds(
+              new google.maps.LatLngBounds(
+                new google.maps.LatLng(bounds.south, bounds.west),
+                new google.maps.LatLng(bounds.north, bounds.east)
+              )
+            );
+          }
+          else
+          {
+            dialogGMapsOptions.gMap.setZoom(2);
+            dialogGMapsOptions.gMap.setCenter(new google.maps.LatLng(0, 0));
+            updateBounds();
+          }
+
+          loadMarkers();
+        },
+        buttons:
+        {
+          '{/literal}{"gmaps_ok"|@translate}{literal}':
+            function()
+            {
+              updateBounds();
+
+              if(dialogGMapsOptions.cBuilder!=null)
+              {
+                setCBuilderItem(dialogGMapsOptions.id, bounds, requestId);
+              }
+
+              if(dialogGMapsOptions.eventOk!=null)
+              {
+                dialogGMapsOptions.eventOk(dialogGMapsOptions.id, bounds, requestId);
+              }
+
+
+              $(this).dialog('close');
+            },
+          '{/literal}{"gmaps_cancel"|@translate}{literal}':
+            function()
+            {
+              $(this).dialog('close');
+            }
+        }
+      }
+    );
+
+  }
+
+
+  /**
+   * initialize the map
+   */
+  var initializeMap = function ()
+  {
+    var latlng=new google.maps.LatLng(0, 0);
+
+    var map = new google.maps.Map($("#iDialogGMapsMap").get(0),
+      {
+        mapTypeId:google.maps.MapTypeId.HYBRID,
+        zoom:2,
+        center:latlng,
+        navigationControl: true,
+        navigationControlOptions:
+          {
+            style:google.maps.NavigationControlStyle.ZOOM_PAN,
+          },
+        scaleControl: true,
+        mapTypeControl:true,
+        mapTypeControlOptions:
+          {
+            style:google.maps.MapTypeControlStyle.DROPDOWN_MENU,
+          },
+        markerTitle:'',
+      }
+    );
+
+    map.markers=new Array();
+    dialogGMapsOptions.gMap=map;
+
+    google.maps.event.addListener(
+      dialogGMapsOptions.gMap,
+      'dragend',
+      function()
+      {
+        updateBounds();
+        loadMarkers();
+      }
+    );
+
+    google.maps.event.addListener(
+      dialogGMapsOptions.gMap,
+      'zoom_changed',
+      function()
+      {
+        updateBounds();
+        loadMarkers();
+      }
+    );
+  }
+
+
+  /**
+   * update the bounds properties from the map bounds
+   */
+  var updateBounds = function ()
+  {
+    var mapBounds=dialogGMapsOptions.gMap.getBounds();
+    bounds.north=mapBounds.getNorthEast().lat();
+    bounds.south=mapBounds.getSouthWest().lat();
+    bounds.east=mapBounds.getNorthEast().lng();
+    bounds.west=mapBounds.getSouthWest().lng();
+  }
+
+  /**
+   * set the request Id
+   */
+  var setRequestId = function(msg)
+  {
+    dialogGMapsOptions.requestId=msg;
+    requestId=msg;
+    dialogGMapsOptions.requestId=msg;
+  }
+
+
+  /**
+   * load markers from the server
+   */
+  function loadMarkers()
+  {
+    datas={
+      requestId:requestId,
+      bounds:{
+          north:bounds.north,
+          east:bounds.east,
+          south:bounds.south,
+          west:bounds.west
+        },
+      width:$(dialogGMapsOptions.gMap.getDiv()).width(),
+      height:$(dialogGMapsOptions.gMap.getDiv()).height(),
+      distanceTreshold:20,
+      levelInfo:0
+    }
+
+    $('#iDialogGMapNfo').html('<img src="./plugins/GrumPluginClasses/icons/processing.gif"><span>{/literal}{"gmaps_loading"|@translate}{literal}</span>');
+    $('#iDialogGMapWaiting').css(
+      {
+        width:$('#iDialogGMapsMap').width()+'px',
+        height:$('#iDialogGMapsMap').height()+'px',
+        top:(1+$('#iDialogGMapsMap').position().top)+'px',
+        left:(1+$('#iDialogGMapsMap').position().left)+'px',
+        display:'block'
+      }
+    );
+
+    $.ajax(
+      {
+        type: "POST",
+        url: "plugins/GMaps/gmaps_ajax.php",
+        async: true,
+        data: { ajaxfct:"public.maps.getMarkers", datas:datas },
+        success:
+          function(msg)
+          {
+            tmp=$.parseJSON(msg);
+            tmp.markers.sort(compareMarkers);
+            applyMarkers(tmp.markers);
+            $('#iDialogGMapNfo').html(tmp.datas.nbPhotos);
+            $('#iDialogGMapWaiting').css('display', 'none');
+          }
+      }
+    );
+  }
+
+  /**
+   * apply markers to map
+   *
+   * @param Array markers : array of markers properties
+   *                        each marker is an object with properties :
+   *                          latitude, longitude, nbImages
+   */
+  function applyMarkers(markers)
+  {
+    /*
+     * deleting markers from the map only if they are not in the new list
+     */
+    if(dialogGMapsOptions.gMap.markers.length>0)
+    {
+      var i=0;
+      while(i<dialogGMapsOptions.gMap.markers.length)
+      {
+        newListIndex=markerInList(dialogGMapsOptions.gMap.markers[i].uniqueId, markers);
+        if(newListIndex==-1)
+        {
+          dialogGMapsOptions.gMap.markers[i].marker.setMap(null);
+          dialogGMapsOptions.gMap.markers.splice(i, 1);
+        }
+        else
+        {
+          markers.splice(newListIndex,1);
+          i++;
+        }
+      }
+    }
+
+    /*
+     * add new markers on the map
+     */
+    for(var i=0;i<markers.length;i++)
+    {
+      var marker = new google.maps.Marker(
+        {
+          position:new google.maps.LatLng(markers[i].lat, markers[i].lng),
+          map: dialogGMapsOptions.gMap,
+          title:markers[i].nbImgTxt
+        }
+      );
+
+      marker.info=markers[i];
+      marker.info.displayed=0;
+
+      dialogGMapsOptions.gMap.markers.push(
+        {
+          marker:marker,
+          uniqueId:markers[i].uniqueId
+        }
+      );
+    }
+  }
+
+  function compareMarkers(m1,m2)
+  {
+    if(m1.uniqueId<m2.uniqueId)
+    {
+      return(-1);
+    }
+    else if(m1.uniqueId<m2.uniqueId)
+    {
+      return(1);
+    }
+    return(0);
+  }
+
+  function markerInList(uniqueId, markerList)
+  {
+    for(var i=0;i<markerList.length;i++)
+    {
+      if(markerList[i].uniqueId==uniqueId) return(i)
+    }
+    return(-1);
+  }
+
+
+  /**
+   * the show() function display and manage a dialog box to choose
+   * a geographic area
+   *
+   * @param options : properties to manage the dialog box
+   *                  - bounds : an object with properties 'north', 'south', 'east'
+   *                             and 'west'
+   *                  - id : a string to identify a DOM object ; this parameter
+   *                         is given to the callback when the OK button is pushed
+   *                  - eventOK : a callback function, with 2 parameters : id of
+   *                              the given DOM object and the bounds object
+   *                  - cBuilder : a criteriaBuilder object
+   *                               if set, the dialog box manage automaticaly
+   *                               the criteria builder interface
+   */
+  this.show = function (options)
+  {
+    showDialog(options);
+  }
+
+  /**
+   * private function used to show the dialog box
+   */
+  var showDialog = function(options)
+  {
+    if(options.bounds!=null)
+    {
+      bounds=options.bounds;
+    }
+    else
+    {
+      bounds={
+        north:0,
+        south:0,
+        east:0,
+        west:0
+      };
+    }
+
+    if(options.id!=null)
+    {
+      dialogGMapsOptions.id=options.id;
+    }
+    else
+    {
+      dialogGMapsOptions.id='';
+    }
+
+    if(options.eventOk!=null)
+    {
+      dialogGMapsOptions.eventOk=options.eventOk;
+    }
+
+    if(options.cBuilder!=null)
+    {
+      dialogGMapsOptions.cBuilder=options.cBuilder;
+      dialogGMapsOptions.cBuilder.doAction('setOptions',
+        {
+          onEdit:function (e) { editGA(e.data); },
+          onDelete:function (e) { deleteGA(e.data); },
+        }
+      );
+    }
+
+    $("#iDialogGMapsChoose").dialog('open');
+  }
+
+
+
+  /**
+   * manage the 'edit' button from criteria builder interface
+   * @param String itemId : the itemId
+   */
+  var editGA = function (itemId)
+  {
+    extraData=dialogGMapsOptions.cBuilder.doAction('getExtraData', itemId);
+    showDialog(
+      {
+        id:itemId,
+        bounds:extraData.param.bounds,
+        requestId:extraData.param.requestId
+      }
+    );
+  }
+
+  /**
+   * manage the 'delete' button from criteria builder interface
+   * @param String itemId : the itemId
+   */
+  var deleteGA = function (itemId)
+  {
+    dialogGMapsOptions.cBuilder.doAction('delete', itemId);
+  }
+
+  /**
+   * set the content for the cBuilder item
+   */
+  var setCBuilderItem = function(id, bounds)
+  {
+
+    content="<div>{/literal}{'gmaps_geographic_coords_between'|@translate}{literal}<br>";
+    content+="<span style='margin-left:20px;'>&bull;&nbsp;"+DDtoDMS(bounds.south)+" {/literal}{'gmaps_south'|@translate} {'gmaps_and'|@translate} "+DDtoDMS(bounds.north)+" {'gmaps_north'|@translate}{literal}</span><br>";
+
+    if(bounds.east<bounds.west)
+    {
+      content+="<span style='margin-left:20px;'>&bull;&nbsp;"+DDtoDMS(bounds.east)+" {/literal}{'gmaps_east'|@translate} {'gmaps_and'|@translate} "+DDtoDMS(bounds.west)+" {'gmaps_west'|@translate}{literal}</span>";
+    }
+    else
+    {
+      content+="<span style='margin-left:20px;'>&bull;&nbsp;"+DDtoDMS(bounds.west)+" {/literal}{'gmaps_west'|@translate} {'gmaps_and'|@translate} "+DDtoDMS(bounds.east)+" {'gmaps_east'|@translate}{literal}</span>";
+    }
+    content+="</div>";
+
+
+    if(id=='')
+    {
+      //no id:add a new item in the list
+      dialogGMapsOptions.cBuilder.doAction('add', content, criteriaBuilder.makeExtendedData('GMaps', {bounds:$.extend({}, bounds), requestId:requestId } ) );
+    }
+    else
+    {
+      // update item
+      dialogGMapsOptions.cBuilder.doAction('edit', id,  content, criteriaBuilder.makeExtendedData('GMaps', {bounds:$.extend({}, bounds), requestId:requestId } ) );
+    }
+  }
+
+  /**
+   * convert a decimal degree to D°M'S'
+   * note : negative values are converted in positive values, assuming North/South
+   * and East/West are managed outside this function
+   *
+   * @param Float $value : the value to convert
+   * @return String : value converted in DMS
+   */
+  var DDtoDMS = function (value)
+  {
+    value=Math.abs(value);
+    degrees=Math.floor(value);
+    tmp=(value-degrees)*60;
+    minutes=Math.floor(tmp);
+    seconds=Math.round((tmp-minutes)*6000)/100;
+    return(degrees+"° "+minutes+"' "+seconds+'"');
+  }
+
+  initDialogBox();
+}
+
+
+</script>
+{/literal}
+
+<div id="iDialogGMapsChoose" style='display:none;'>
+  <div id='iDialogGMapNfo'>&nbsp;</div>
+  <div id='iDialogGMapsMap' style='width:95%; height:95%;margin-left:auto;margin-right:auto;border:1px solid;'></div>
+  <div id='iDialogGMapWaiting' style="display:none;"></div>
+</div>
+
+
Index: extensions/GMaps/templates/gmaps_picture_icon.tpl
===================================================================
--- extensions/GMaps/templates/gmaps_picture_icon.tpl	(revision 7125)
+++ extensions/GMaps/templates/gmaps_picture_icon.tpl	(revision 7128)
@@ -7,3 +7,4 @@
 <div id='iGMapsIconContent' style='display:none;'>
     <div id='iGMapsIcon' style='width:{$map.width}px;height:{$map.height}px;{$map.style}'></div>
+    <div id='iDialogGMapWaiting' style="display:none;"></div>
 </div>
