function tsgqc_GUI
% tsgqc_GUI
%
% TSG (Thermosalinograph) Quality Control software
%
% $Id$
%

%% COPYRIGHT & LICENSE
%  Copyright 2007 - IRD US191, all rights reserved.
%
%  This file is part of tsgqc_GUI.
%
%    Datagui is free software; you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation; either version 2 of the License, or
%    (at your option) any later version.
%
%    tsgqc_GUI is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with Datagui; if not, write to the Free Software
%    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


%%  Initialization tasks
%   ********************

% Clear Command Window display, giving up a "clean screen."
% ---------------------------------------------------------
clc;

% Find program directory.
% functions (icons) should be store at a lower level
% add directories to Matlab search path, works on UNIX
% and Windows host
% ---------------------------------------------------
tsgqcname = mfilename;
fulltsgqcname = mfilename('fullpath');
DEFAULT_PATH_FILE = strrep(fulltsgqcname, tsgqcname, '') ;
p = [pathsep,...
  DEFAULT_PATH_FILE,[filesep 'tsg_util' pathsep],...
  DEFAULT_PATH_FILE,[filesep 'tsg_data' pathsep],...
  DEFAULT_PATH_FILE,[filesep 'tsg_io' pathsep]
  ];
addpath( p, '-END' );
rehash;

% get screen dimensions (pixels)
% ------------------------------
set(0,'Units','pixels');
screenSize = get(0,'ScreenSize');

% define default font size based on screen resolution
% ---------------------------------------------------
if screenSize(3) <= 1024
  tsg.fontSize = 9;
end

% Screen limits for the GUI
% -------------------------
set(0,'Units','normalized');
guiLimits = get(0,'ScreenSize');
guiLimits(1) = guiLimits(1) + 0.01;
guiLimits(2) = guiLimits(2) + 0.05;
guiLimits(3) = guiLimits(3) - 0.02;
guiLimits(4) = guiLimits(4) - 0.15;

%% Create and then hide the GUI as it is being constructed.
% --------------------------------------------------------
hMainFig = figure(...
  'Name', 'TSG Validation', ...
  'NumberTitle', 'off', ...
  'Resize', 'on', ...
  'Menubar','none', ...
  'Toolbar', 'none', ...
  'UserData', 'ButtonMotionOff', ...
  'WindowButtonMotionFcn', @MouseMotion, ...
  'CloseRequestFcn', @QuitProgram,...
  'HandleVisibility','callback',...
  'Visible','on',...
  'Units', 'normalized',...
  'Position',guiLimits, ...
  'Color', get( 0, 'DefaultUIControlBackgroundColor' ));

% Initialize tsg structure
% ------------------------
tsg_initialisation(hMainFig)

% Retrieve named application data
% -------------------------------
tsg = getappdata( hMainFig, 'tsg_data');

%%  Construct the Menu
%   -----------------
hFileMenu = uimenu(...
  'Parent', hMainFig,...
  'HandleVisibility','callback',...
  'Label', 'File');
hOpenMenu = uimenu(...
  'Parent', hFileMenu,...
  'Label','Open',...
  'Accelerator','O',...
  'HandleVisibility','callback',...
  'UserData', 'off',...
  'Callback', @OpenMenuCallback);
hSaveMenu = uimenu(...
  'Parent', hFileMenu,...
  'Label','Save',...
  'Accelerator','S',...
  'Enable', 'off',...
  'UserData', 'off',...
  'HandleVisibility','callback',...
  'Callback',@SaveMenuCallback);
hQuitMenu = uimenu(...
  'Parent',hFileMenu,...
  'Label','Quit',...
  'Separator','on',...
  'Accelerator','Q',...
  'HandleVisibility','callback',...
  'Callback',@QuitMenuCallback);

% Edit menu with Undo/Redo submenu 
% --------------------------------
hEditMenu = uimenu(hMainFig,'Label','Edit');
uimenu(hEditMenu,'Label','Undo',...
  'Accelerator','Z',...
  'Tag','Undo',...
  'Enable', 'off',...
  'Callback',@UndoMenuCallback);
uimenu(hEditMenu,'Label','Redo',...
  'Accelerator','R',...
  'Tag','Redo',...
  'Enable', 'off',...
  'Callback',@RedoMenuCallback);


%%  Construct the Toolbar
%   -----------------
hToolbar       =   uitoolbar(...   % Toolbar for Open and Print buttons
  'Parent',hMainFig, ...
  'HandleVisibility','callback');
hOpenPushtool  =   uipushtool(...   % Opendoc toolbar button
  'Parent',hToolbar,...
  'TooltipString','Open file',...
  'CData', iconRead(fullfile(matlabroot, ...
  '/toolbox/matlab/icons/opendoc.mat')),...
  'HandleVisibility','callback', ...
  'Tag','PUSHTOOL_OPEN',...
  'UserData', 'off',...
  'Enable', 'on',...
  'ClickedCallback', @OpenMenuCallback);
hSavePushtool  =   uipushtool(...   % Open Save toolbar button
  'Parent',hToolbar,...
  'TooltipString','Save NetCDF file',...
  'CData',iconRead( ...
  [DEFAULT_PATH_FILE 'tsg_icon' filesep 'savedoc.mat']),...
  'HandleVisibility','callback', ...
  'Tag','PUSHTOOL_SAVE',...
  'Enable', 'off',...
  'ClickedCallback', @SaveMenuCallback);
hZoomToggletool  =   uitoggletool(...   % Open Zoom toolbar button
  'Parent',hToolbar,...
  'Separator', 'on', ...
  'TooltipString','Zoom',...
  'CData', iconRead(fullfile(matlabroot, ...
  '/toolbox/matlab/icons/zoom.mat')),...
  'HandleVisibility','callback', ...
  'Tag','PUSHTOOL_ZOOM',...
  'Enable', 'off',...
  'OffCallback', @Zoom_OffMenuCallback,...
  'ONCallback',  @Zoom_OnMenuCallback);
hPanToggletool  =   uitoggletool(...   % Open Pan toolbar button
  'Parent',hToolbar,...
  'TooltipString','Pan',...
  'CData',iconRead(fullfile(matlabroot, ...
  '/toolbox/matlab/icons/pan.mat')),...
  'HandleVisibility','callback', ...
  'Tag','PUSHTOOL_PAN',...
  'Enable', 'off',...
  'OffCallback', @Pan_OffMenuCallback,...
  'ONCallback',  @Pan_OnMenuCallback);
  %'ClickedCallback', @PanMenuCallback);
hQCToggletool  =   uitoggletool(...   % Open QC toolbar button
  'Parent',hToolbar,...
  'TooltipString','Validation codes',...
  'Separator', 'on', ...
  'CData',iconRead(...
  [DEFAULT_PATH_FILE 'tsg_icon' filesep 'qcicon.mat']),...
  'HandleVisibility','callback', ...
  'Tag','PUSHTOOL_QC',...
  'UserData', 'off',...
  'Enable', 'off',...
  'OffCallback', @QC_OffMenuCallback,...
  'ONCallback',  @QC_OnMenuCallback);
hMapToggletool  =   uitoggletool(...   % Open Map toolbar button
  'Parent',hToolbar,...
  'TooltipString','Map and ship track',...
  'Separator', 'on', ...
  'CData',iconRead(...
  [DEFAULT_PATH_FILE 'tsg_icon' filesep 'mapicon.mat']),...
  'HandleVisibility','callback', ...
  'Tag','PUSHTOOL_MAP',...
  'UserData', 'off', ...
  'Enable', 'off',...
  'OffCallback', @Map_OffMenuCallback,...
  'ONCallback',  @Map_OnMenuCallback);
hClimToggletool  =   uitoggletool(...   % Open Climatology toolbar button
  'Parent',hToolbar,...
  'TooltipString','Climatology',...
  'Separator', 'on', ...
  'CData',iconRead(...
  [DEFAULT_PATH_FILE 'tsg_icon' filesep 'climicon.mat']),...
  'HandleVisibility','callback', ...
  'Tag','PUSHTOOL_CLIM',...
  'UserData', 'off',...
  'Enable', 'off',...
  'OffCallback', @Clim_OffMenuCallback,...
  'ONCallback',  @Clim_OnMenuCallback);

hBottlePushtool  = uitoggletool(...   % Open toolbar button
  'Parent',hToolbar,...
  'TooltipString','Correct the SSS TSG data',...
  'Separator', 'on', ...
  'CData',iconRead(...
  [DEFAULT_PATH_FILE 'tsg_icon' filesep 'bottleicon.mat']),...
  'HandleVisibility','callback', ...
  'Tag','PUSHTOOL_BOTTLE',...
  'UserData', 'off',...
  'Enable', 'off',...
  'OffCallback', @Bottle_OffMenuCallback,...
  'ONCallback', @Bottle_OnMenuCallback);

hHeaderPushtool  = uipushtool(...   % Open headerForm button
  'Parent',hToolbar,...
  'TooltipString','Fill the header form',...
  'Separator', 'on', ...
  'CData',iconRead(...
  [DEFAULT_PATH_FILE 'tsg_icon' filesep 'hdricon.mat']),...
  'HandleVisibility','callback', ...
  'Tag','PUSHTOOL_HEADER',...
  'Enable', 'off',...
  'ClickedCallback', @HeaderMenuCallback);

%% Dynamic text area that displays the loaded filename, date, position and
%  salinity, temperature
% ---------------------------------------------------

% create an uipanel
% -----------------
hInfoPanel = uipanel( ...
  'Parent', hMainFig, ...
  'Units', 'normalized', ...
  'BorderType', 'none',...
  'Visible', 'on', ...
  'Position',[.01, .95, .98, .04]);

% Dynamic text area that displays the date
% ----------------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.01, .25, .04, .5], ...
  'String', 'File:');

hInfoFileText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'No file loaded', ...
  'Position', [.05, .25, .1, .5]);

% Text area that displays the date
% --------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.16, .25, .03, .5], ...
  'String', 'Date:');

hInfoDateText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.20, .25, .13, .5]);

% Text area that displays the latitude
% ------------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.34, .25, .05, .5], ...
  'String', 'Latitude:');

hInfoLatText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.4, .25, .9, .5]);

% Text area that displays the longitude
% -------------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.50, .25, .06, .5], ...
  'String', 'Longitude:');

hInfoLongText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.57, .25, .07, .5]);

% Text area that display salinity and temperature
% -----------------------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.65, .25, .04, .5], ...
  'String', 'SSPS:');

hInfoSSPSText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.69, .25, .05, .5]);

uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.75, .25, .04, .5], ...
  'String', 'SSJT:');

hInfoSSJTText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.79, .25, .05, .5]);

uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.85, .25, .04, .5], ...
  'String', 'SSTP:');

hInfoSSTPText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.89, .25, .05, .5]);

%% Construct the plot axes
% -----------------------
% The axes 1,2 and 3 will be plot in a uipanel
% axe 1 as propertie 'HandleVisibility' set to 'on' to prevent hidden 
% visibility when first plot is empty
%--------------------------------------------------------------------
hPlotsPanel = uipanel( ...
  'Parent', hMainFig, ...
  'Units', 'normalized', ...
  'BorderType', 'etchedin',...
  'Visible', 'on', ...
  'Position',[0.15, 0, .85, .95]);
 
hPlotAxes(1) = axes(...     % the axes for plotting Salinity
  'Parent', hPlotsPanel, ...
  'Units', 'normalized', ...
  'Visible', 'off', ...
  'HandleVisibility','on', ...  % set to callback after first plot
  'Position',[.05, .64, .93, .35]);

hPlotAxes(2) = axes(...     % the axes for plotting temperature
  'Parent', hPlotsPanel, ...
  'Units', 'normalized', ...
  'Visible', 'off', ...
  'HandleVisibility','callback', ...
  'Position',[.05, .32, .93, .27]);

hPlotAxes(3) = axes(...     % the axes for plotting ship velocity
  'Parent', hPlotsPanel, ...
  'Units', 'normalized', ...
  'Visible', 'off', ...
  'HandleVisibility','callback', ...
  'Position',[.05, .06, .93, .22]);

% The map will be plot in a uipanel
hMapPanel = uipanel( ...
  'Parent', hMainFig, ...
  'Units', 'normalized', ...
  'Visible', 'off', ...
  'Position',[0.15, 0, .85, .57]);

hPlotAxes(4) = axes(...     % the axes for plotting ship track map
  'Parent', hMapPanel, ...
  'Units', 'normalized', ...
  'Visible', 'off', ...
  'Color', 'none', ...
  'UserData', 'off', ...
  'HandleVisibility','on', ...
  'Position',[.05, .05, .9, .9]);


% Construct display Quality codes panel
% -------------------------------------
hQcPanel = uipanel(...
  'Parent', hMainFig, ...
  'tag', 'TAG_QC_DISPLAY_PANEL',...
  'HandleVisibility','on',...
  'Visible', 'on',...
  'BorderType', 'etchedin',...
  'Position', [.0, .70, .15, .25]);

% Construct the context menu for the Quality control codes
% -------------------------------------------------------
hQcCmenu = uicontextmenu(...
  'Parent', hMainFig, ...
  'HandleVisibility','on' );

% get list of keys from hashtable tsg.qc.hash, defined inside
% tsg_initialisation.m
% -----------------------------------------------------------
qc_list = get(tsg.qc.hash);

% internal loop count with state to on
% ------------------------------------
count = 0;

% iterate (loop) on each key store inside hastable
% ------------------------------------------------
for i=1:numel(qc_list)
  
  % get key and some values in hashtable
  % ------------------------------------
  key   = qc_list{i};
  label = get(tsg.qc.hash, key, 'label');
  color = get(tsg.qc.hash, key, 'color');
  state = get(tsg.qc.hash, key, 'state');
  
  % construct context menu with only code set to 'on' (valid)
  % ---------------------------------------------------------
  if strcmp( state, 'on')
    
    % add menu to uicontextmenu
    % -------------------------
    uimenu(...
      'Parent', hQcCmenu,...
      'HandleVisibility','on', ...
      'Label', label,...
      'ForegroundColor', color,...
      'Callback', {@Qc, key});
    
    % add text QC display label on hQcPanel
    % ------------------------------------
    uicontrol(...
      'Parent', hQcPanel,...
      'Style', 'text',...
      'Units', 'normalized', ...
      'Style', 'Text', ...
      'Fontsize', tsg.fontSize-1, ...
      'HorizontalAlignment', 'left', ...
      'HandleVisibility','on', ...
      'String', label,...
      'ForegroundColor', color,...
      'Position', [.01, .85-count*.12, .6, 0.08]);
    
    % add text QC display statistic on hQcPanel
    % -----------------------------------------
    uicontrol(...
      'Parent', hQcPanel,...
      'Style', 'text',...
      'Units', 'normalized', ...
      'Style', 'Text', ...
      'Fontsize', tsg.fontSize-1, ...
      'HorizontalAlignment', 'right', ...
      'HandleVisibility','on', ...
      'String', 'N/A',...
      'ForegroundColor', color,...
      'Tag', ['TAG_QC_TEXT_' key],...
      'Position', [.61, .85-count*.12, .37, 0.08]);
    
    % increment count
    % ---------------
    count = count + 1;
  end
end


% -------------------------
%  Callbacks for tsgcqc_GUI
%  ------------------------

  %----------------------------------------------------------------------
  % Callback function run when the Open menu item is selected
  %----------------------------------------------------------------------
  function OpenMenuCallback(hObject, eventdata)
 
    % Pointer set to watch during reading and plotting
    % ------------------------------------------------
    set( hMainFig, 'Pointer', 'watch' );

    % Make the fileName
    % ATTENTION : function OpenMenuCallback(hObject, eventdata)
    % This has to be made general for UNIX and WINDOWS system
    % ---------------------------------------------------------
    [fileName, pathname, filterIndex] = uigetfile( ...
      {'*.txt';'*.xml';'*.nc';'*.lbv';'*.btl'}, 'Pick a file');

    error1 = -1;
    error2 = -1;

    if ~isequal(fileName, 0)

      % Read the data
      % -------------
      switch filterIndex

        case 1
          error1 = readTsgDataTxt( hMainFig, fileName );
        case 2
          error1 = readTsgDataXML( hMainFig, fileName );
        case 3
          error1 = readTsgDataNetCDF( hMainFig, fileName );       
          %# a modifier
          if error1 == 1
            error2 = error1;
          end
        case 4
          error1 = readTsgDataLabview( hMainFig, fileName );  
        case 5
          error2 = readBucketData(hMainFig, fileName );
        otherwise
          return;

      end

      % A TSG file has been read. Plot the data.
      % ----------------------------------------
      if error1 ~= -1

        % A TSG file has been open and read
        % ---------------------------------
        set( hOpenMenu, 'UserData', 'on' );
        
        % enable toolbar menu pushtool
        % ----------------------------
        hdl_pushtool = findobj('-regexp','Tag', 'PUSHTOOL_');
        set(hdl_pushtool, 'Enable', 'on');
        
        % enable Save menu
        % ----------------
        set(hSaveMenu, 'Enable', 'on');

        % update the filename display
        % ---------------------------
        set( hInfoFileText, 'String', fileName);
        
        % update some fields in tsg structure
        % -----------------------------------
        updateTsgStruct(hMainFig);
        
        % Running average of TSG time series
        % ----------------------------------
        tsg_moveaverage(hMainFig);

        % The callback to detect the mouse motion can be set to on
        % --------------------------------------------------------
        set( hMainFig, 'UserData', 'ButtonMotionOn');

        % Make the Salinity, temperature and velocity plot
        % ------------------------------------------------
        plot_SalTempVel( hMainFig, hPlotAxes );

        % Plot the Map with the ship trackline
        % ------------------------------------
        plotmap( hMainFig, hPlotAxes)

      end
    end

    % Merge the different water sample (NetCdf or ASCII files) in
    % a unique structure : 'sample'
    % -----------------------------------------------------------
    %@ desactive le merge pour l'instant en attente d'une structure de
    %donn�es validee
    %@[sample] = tsg_mergesample( hMainFig );

    %@ Save the 'sample' struct. as an application data
    % ------------------------------------------------
    %if ~isempty( sample )
    %    setappdata( hMainFig, 'sample', sample );
    %end

    % Plot Salinity bucket 
    % NOT at that step. It will interfere with the QC process
    % Maybe use a new pushbutton to draw or delete the bucket
    % -------------------------------------------------------
    if error2 ~= -1
      plot_WS( hMainFig, hPlotAxes );
      plot_EXT( hMainFig, hPlotAxes );
    end
    
    % Pointer reset to arrow
    % ----------------------
    set( hMainFig, 'Pointer', 'arrow' );

  end

 %----------------------------------------------------------------------
  % Callback function run when the zoom toggle toolbar is released
  %----------------------------------------------------------------------
  function Zoom_OffMenuCallback(hObject, eventdata)
    
    % returns the plot to its initial zoom setting
    % --------------------------------------------
    %zoom out;
    
    % turns interactive zooming off
    % -----------------------------
    zoom off;
    
  end

  %----------------------------------------------------------------------
  % Callback function run when the zoom toggle toolbar is released
  %----------------------------------------------------------------------
  function Zoom_OnMenuCallback(hObject, eventdata)
    
    % cursor back to normal
    % ---------------------
    set(hMainFig,'Pointer','arrow');
    
    % returns a zoom mode object for the figure hMainFig handle
    % --------------------------------------------------------
    hZoom = zoom(hMainFig);
    
    % turns on interactive zooming (same effect than zoom on) but prevent
    % side effect on another figure
    % -------------------------------------------------------------------
    set(hZoom,'enable', 'on');
    %zoom on;
    
    % Turns on the automatic adaptation of date ticks
    % -----------------------------------------------
    zoomAdaptiveDateTicks('on');
 
    % Desactivate the QC and Pan toggle buttons
    % -----------------------------------------
    set(hQCToggletool,  'state', 'off' );
    set(hPanToggletool, 'state', 'off' );
    
  end

  %----------------------------------------------------------------------
  % Callback function run when the pan toggle toolbar is released
  %----------------------------------------------------------------------
  function Pan_OffMenuCallback(hObject, eventdata)
    
    % turns interactive pan off
    % -------------------------
    pan off;
    
    % reset to original figure
    % ------------------------
    %zoom out;
    
  end

  %----------------------------------------------------------------------
  % Callback function run when the pan toggle toolbar is selected
  %----------------------------------------------------------------------
  function Pan_OnMenuCallback(hObject, eventdata)
    
    % cursor back to normal
    % ---------------------
    set(hMainFig,'Pointer','arrow');
    
    % Returns a pan mode object for the figure handle
    % -----------------------------------------------
    hPan = pan(hMainFig);
    
    % turns on interactive pan (same effect than pan on) but prevent
    % side effect on another figure
    % -------------------------------------------------------------------
    set(hPan,'enable', 'on');
    
    % Turns on the automatic adaptation of date ticks
    % -----------------------------------------------
    panAdaptiveDateTicks('on');
    
    % Desactivate the QC and pan toggle button
    % ----------------------------------------
    set(hQCToggletool,   'state', 'off' );
    set(hZoomToggletool, 'state', 'off' );
    
  end

  %----------------------------------------------------------------------
  % Callback function run when the QC toggle tool is released
  %----------------------------------------------------------------------
  function QC_OffMenuCallback(gcbo, eventdata)
    
    % Desactive right clic menu on first axes (salinity)
    % ---------------------------------------------------
    set(hPlotAxes(1),'UIContextMenu', []);
    
    % Desactive clic mouse menu (zoom) on first axes (salinity)
    % ----------------------------------------------------------
    set(hPlotAxes(1),'ButtonDownFcn', []);
    
    % cursor back to normal
    % ---------------------
    set(hMainFig,'Pointer','arrow');
    
  end

  %----------------------------------------------------------------------
  % Callback function run when the QC toggle tool is pressed
  %----------------------------------------------------------------------
  function QC_OnMenuCallback(gcbo, eventdata)
    
    % Desactivate Zoom and Pan functions.
    % ----------------------------------
    zoom off; pan off;
    panAdaptiveDateTicks('off');zoomAdaptiveDateTicks('off');
    set(hZoomToggletool, 'state', 'off' );
    set(hPanToggletool, 'state', 'off' );
    
    % Activate right clic context menu on first axes (salinity)
    % ---------------------------------------------------------
    set(hPlotAxes(1),'UIContextMenu', hQcCmenu);

    % Activate clic mouse menu on first axes (salinity)
    % -------------------------------------------------
    set(hPlotAxes(1),'ButtonDownFcn', @QC_SelectCallback);
    
    % change cursor to crosshair aspect
    % ---------------------------------
    set( hMainFig, 'Pointer', 'crosshair');
    
    % -------------------------------------------------------------
    % nested function on mouse clic when QC toggle tool is selected
    % -------------------------------------------------------------
    function QC_SelectCallback(gcbo, eventdata)

      % disable ButtonMotion on main fig during select
      % prevent drawing to map
      % ----------------------------------------------
      set( hMainFig, 'WindowButtonMotionFcn', []);
      
      % Retrieve named application data
      % -------------------------------
      tsg = getappdata( hMainFig, 'tsg_data');
      
      % Selection of the data within the figure
      % ---------------------------------------
      point1 = get(gca,'CurrentPoint');    % button down detected
      finalRect = rbbox;                   % return figure units
      point2 = get(gca,'CurrentPoint');    % button up detected

      point1 = point1(1,1:2);              % extract x and y
      point2 = point2(1,1:2);
      
      p1 = min(point1,point2);
      p2 = max(point1,point2);             % calculate locations

      % get index on selected zone
      % ---------------------------
      ind = find(tsg.DAYD > p1(1,1) & tsg.DAYD < p2(1,1) & ...
                 tsg.SSPS > p1(1,2) & tsg.SSPS < p2(1,2));

      tsg.SSPS_QC(ind) = tsg.qc.active.Code;

      % set current axes and plot
      % -------------------------
      axes(hPlotAxes(1));
      hold on
      color = ['.' tsg.qc.active.Color];
      
      % plot selected data with selected code
      % --------------------------------------
      plot(tsg.DAYD(ind), tsg.SSPS(ind), color );
      hold off

      % As soon as a modification took place the data should be saved
      % -------------------------------------------------------------
      set( hSaveMenu, 'UserData', 'on' );
      
      % Save the modifications
      % ----------------------
      setappdata( hMainFig, 'tsg_data', tsg);
      
      % refresh QC statistic panel
      % --------------------------
      display_QC( hMainFig, hPlotAxes );
      
      % enable ButtonMotion on main fig after select QC area
      % ----------------------------------------------------
      set( hMainFig, 'WindowButtonMotionFcn', @MouseMotion);
    end
    
  end

  %----------------------------------------------------------------------
  % Callback function run when the QC context menu is selected
  %---------------------------------------------------------------------
  function Qc(hObject, eventdata, key)  
    
      % Retrieve Default Quality Code and Color
      % ---------------------------------------
      tsg = getappdata( hMainFig, 'tsg_data');
      
      % get key and some values in hashtable
      % ------------------------------------
      code  = get(tsg.qc.hash, key, 'code');
      color = get(tsg.qc.hash, key, 'color');
       
      % set active code and color from selected context menu
      % ----------------------------------------------------
      tsg.qc.active.Code  = code;
      tsg.qc.active.Color = color;

      setappdata( hMainFig, 'tsg_data', tsg );
            
  end

  %---------------------------------------------------------------------
  % Callback function run when mouse pointer is moving on temperature plot
  % draw corresponding measurement position on map
  %---------------------------------------------------------------------
  function MouseMotion(hObject, eventdata)

    % Test if the callback can be activated
    % -------------------------------------
    if strcmp( get( hMainFig, 'UserData'), 'ButtonMotionOn')

      % Retrieve named application data
      % -------------------------------
      tsg = getappdata( hMainFig, 'tsg_data');

      % Get the mouse position
      % ----------------------
      point = get(gcf,'CurrentPoint');

      if point(1) > .05 && point(2) > .6 && point(1) < .95 && point(2) < .92

        % Get current position of cusor and return its coordinates in
        % axes with handle h_axes
        % -----------------------------------------------------------
        [x, y] = gpos(hPlotAxes(1));

        % Dynamically display data in uicontrol
        % -------------------------------------
        if x > tsg.DAYD(1) && x < tsg.DAYD(end)
          indCursor = find( tsg.DAYD > x);
          set( hInfoDateText, 'String',...
            datestr(tsg.DAYD(indCursor(1)),'dd/mm/yyyy   HH:MM'));
          set( hInfoLatText,  'String', dd2dm(tsg.LATX(indCursor(1)),0));
          set( hInfoLongText, 'String', dd2dm(tsg.LONX(indCursor(1)),1));
          set( hInfoSSPSText, 'String', tsg.SSPS(indCursor(1)));
          set( hInfoSSJTText, 'String', tsg.SSJT(indCursor(1)));
          if ~isempty(tsg.SSTP)
            set( hInfoSSTPText, 'String', tsg.SSTP(indCursor(1)));
          end
          
          % Plot the position on the map if this one is active
          % --------------------------------------------------
          if strcmp( get(hMapPanel, 'Visible'), 'on')

            % Select the map axes
            % -------------------
            axes( hPlotAxes(4));

            if isempty( get(hMapPanel, 'UserData'))
              hMarker = m_line( ...
                tsg.LONX(indCursor(1)), tsg.LATX(indCursor(1)),...
                'Marker','o','MarkerSize',5, ...
                'Color','r', 'MarkerFaceColor','r');
              set(hMapPanel, 'UserData', hMarker)
            else
              delete(get(hMapPanel, 'UserData'));
              hMarker = m_line( ...
                tsg.LONX(indCursor(1)), tsg.LATX(indCursor(1)),...
                'Marker','o','MarkerSize',5, ...
                'Color','r', 'MarkerFaceColor','r');
              set(hMapPanel, 'UserData', hMarker);
            end
          end
        end
      end
    end
  end

  %---------------------------------------------------------------------
  % Callback function run when the Map tool bar item is unselected
  %---------------------------------------------------------------------
  function Map_OffMenuCallback(hObject, eventdata)
    
    % Make the earth map invisible
    % ----------------------------
    set(hMapPanel, 'Visible', 'off' );   
    
  end

  %---------------------------------------------------------------------
  % Callback function run when the Map tool bar item is selected
  %---------------------------------------------------------------------
  function Map_OnMenuCallback(hObject, eventdata)
     
    % Desactivate Zoom and Pan toggle buttons
    % may be change in the futur ...
    % ---------------------------------------
    set(hZoomToggletool,  'state', 'off' );
    set(hPanToggletool,  'state', 'off' );
    
    % Make the earth map visible
    % --------------------------
    set(hMapPanel, 'Visible', 'on' );
    
  end

  %---------------------------------------------------------------------
  % Callback function run when the bootle push tool is selected
  %---------------------------------------------------------------------
  function Bottle_OnMenuCallback(hObject, eventdata)
    % Callback function run when the Bottle tool bar item is selected

    % Desactivate the Climatology button
    % ----------------------------------
    set( hClimToggletool, 'Enable', 'off');
    
    % Test if tsg and sample data have been loaded
    % --------------------------------------------
    if ~isempty( tsg.SSPS_WS ) || ~isempty( tsg.SSPS_EXT )
      
      % Merge bucket and external samples
      % ---------------------------------
      tsg_mergesample( hMainFig );
                    
      % Compute the sample-TSG differences
      % ----------------------------------
      diffTsgSample( hMainFig );

      % plot Salinity Difference
      % ------------------------
      plot_Sample( hMainFig, hPlotAxes );
      
      % Call the GUI for tsg correction
      % -------------------------------
      msgbox('Correction module not yet implemented', 'modal');
      % tsgcor_GUI( hMainFig );    
    else
      msgbox('TSG or Sample data not loaded in the program', 'modal');
    end
  end

  %---------------------------------------------------------------------
  % Callback function run when the bootle push tool is selected
  %---------------------------------------------------------------------
  function Bottle_OffMenuCallback(hObject, eventdata)
 
    % Activate the Climatology button
    % -------------------------------
    set( hClimToggletool, 'Enable', 'on');

    % Plot the SSS, SST and Velocity
    % ------------------------------
    plot_SalTempVel( hMainFig, hPlotAxes );
    plot_WS( hMainFig, hPlotAxes );
    plot_EXT( hMainFig, hPlotAxes );
 
  end

 %------------------------------------------------------------------------
  % Callback function run when the Levitus climatology toolbar is unselected
  %------------------------------------------------------------------------
  function Clim_OffMenuCallback(hObject, eventdata)

    % Get line handles
    % ----------------------------------------------
    hLine1 = get( hPlotAxes(1), 'UserData');
    hLine2 = get( hPlotAxes(2), 'UserData');
    
    % Delete climatology lines on axes
    % -----------------------------------
    try
      delete(hLine1.stdClimMinus);
      delete(hLine1.stdClimPlus);
      delete(hLine1.meanClim);
      delete(hLine2.stdClimMinus);
      delete(hLine2.stdClimPlus);
      delete(hLine2.meanClim);
      
    % if handle is missing, prevent warning message on console
    % --------------------------------------------------------
    catch
    end
    
  end

  %------------------------------------------------------------------------
  % Callback function run when the Levitus climatology toolbar is unselected
  %------------------------------------------------------------------------
  function Clim_OnMenuCallback(hObject, eventdata)

    % Test if the TSG and bucket files have been read
    % -----------------------------------------------
    if strcmp( get(hOpenMenu, 'UserData'), 'on' )

      % Get data
      % -----------------------
      tsg = getappdata( hMainFig, 'tsg_data' );

      % Get line handles
      % ----------------
      hLine1 = get( hPlotAxes(1), 'UserData');
      hLine2 = get( hPlotAxes(2), 'UserData');

      % Read Climatology
      % ----------------
      if isempty( tsg.levitus.data)
        levitus = read_file_woa01( 'woa01an.nc' );
        if ~isstruct(levitus)
          errordlg({'NetCDF climatology file not present in you path',...
            'Check your matlab path or download it from',...
            'ftp://ftp.ifremer.fr/ifremer/ird/us191/oceano/lib/matlab/woa01an.nc'},...
            'NetCDF climatology file access error');
          return;
        else
          tsg.levitus.data = levitus;
          tsg.levitus.type = 'woa01an';
        end
        setappdata( hMainFig, 'tsg_data', tsg );
      end

      % round positive latitude and Longitude toward zero
      % -------------------------------------------------
      ind = find(tsg.LATX > 0);
      lat(ind) = fix(tsg.LATX(ind)) + 0.5;

      ind = find(tsg.LONX > 0);
      lon(ind) = fix(tsg.LONX(ind)) + 0.5;

      % rounds negative latitude and Longitudeto the nearest lowest integers
      % ---------------------------------------------------------------------
      ind = find(tsg.LATX <= 0);
      lat(ind) = floor(tsg.LATX(ind)) + 0.5;

      ind = find(tsg.LONX <= 0);
      lon(ind) = floor(tsg.LONX(ind)) + 0.5;

      % Calculates differences between adjacent elements of X.
      % 0 if adajacent latitude or longitude are equal
      % - 1 or -1 otherwise
      % ------------------------------------------------------------
      lat_diff = [diff( lat )'; 0];
      lon_diff = [diff( lon )'; 0];

      % Select latitude and longitude
      % -----------------------------
      ind  = find(abs(lat_diff) == 1 | abs(lon_diff == 1));
      lat2 = lat( ind );
      lon2 = lon( ind );
      time = tsg.DAYD( ind );
      temp = tsg.SSJT( ind );
      psal = tsg.SSPS( ind );

      % Get Climatology
      %           LATX(80)  = -0.5 et LATX(81)  = 0.5
      %           LONX(180) = -0.5 et LONX(181) = 0.5
      % ----------------
      axes( hPlotAxes(1) );
      mean_temp = zeros(size(ind));
      mean_psal = zeros(size(ind));
      std_temp  = zeros(size(ind));
      std_psal  = zeros(size(ind));
      for i=1:length(ind)
        ilat         = find(tsg.levitus.data.WOA01_LATX == lat2(i));
        ilon         = find(tsg.levitus.data.WOA01_LONX == lon2(i));
        mean_temp(i) = tsg.levitus.data.WOA01_MEAN_TEMP(ilat,ilon,1);
        mean_psal(i) = tsg.levitus.data.WOA01_MEAN_PSAL(ilat,ilon,1);
        std_temp(i)  = tsg.levitus.data.WOA01_STD_TEMP(ilat,ilon,1);
        std_psal(i)  = tsg.levitus.data.WOA01_STD_PSAL(ilat,ilon,1);
      end

      % Plot mean salinity climatology
      % ------------------------------
      hLine1.meanClim = line( ...
        time, mean_psal,'Linestyle', '-', 'Color','k');
      
      % Plot with 3 standard deviation
      % ------------------------------
      hLine1.stdClimPlus = line( ...
        time,  mean_psal + 3 * std_psal ,'Linestyle', '-', 'Color','r');
      hLine1.stdClimMinus = line( ...
        time,  mean_psal - 3 * std_psal ,'Linestyle', '-', 'Color','r');
      
      % Plot mean temperature climatology
      % ---------------------------------
      axes( hPlotAxes(2));
      hLine2.meanClim = line( ...
        time, mean_temp,'Linestyle', '-', 'Color','k');
      hLine2.stdClimPlus = line( ...
        time,  mean_temp + 3 * std_temp ,'Linestyle', '-', 'Color','r');
      hLine2.stdClimMinus = line( ...
        time,  mean_temp - 3 * std_temp ,'Linestyle', '-', 'Color','r');

      % Store the handle of the bucketline
      % ----------------------------------
      set( hPlotAxes(1), 'UserData', hLine1 );
      set( hPlotAxes(2), 'UserData', hLine2 );
    end
  end

  % -------------------------------------------------------------------
  % Callback function run when the headerForm tool bar item is selected
  % -------------------------------------------------------------------
  function HeaderMenuCallback(hObject, eventdata)
   
    % call header form function
    % -------------------------
    headerForm(hMainFig);
    
  end

  % -------------------------------------------------------------------
  % Callback function run when the Save menu item is selected
  % -------------------------------------------------------------------
  function SaveMenuCallback(hObject, eventdata)
    
    % Retrieve named application data
    % -------------------------------
    tsg = getappdata( hMainFig, 'tsg_data');

    % get fileName without extension in cell
    % --------------------------------------
    file = textscan( tsg.file.name,'%s','delimiter','.');

    % fill or append header form
    % -------------------------
    error = headerForm(hMainFig);

    % if user press continue button, ask for netcdf file
    % ------------------------------------------------
    if error ~= -1
      [fileName, pathName, filterIndex] = uiputfile('*.nc', ...
        'Save file name', [file{1}{1} '.nc']);

      % if user press cancel button, all var set to zero
      % ------------------------------------------------
      if fileName == 0
        return;
      end

      % Pointer set to watch during reading and plotting
      % ------------------------------------------------
      set( hMainFig, 'Pointer', 'watch' );

      % flushes the event queue and updates the closed uiputfile window
      % ---------------------------------------------------------------
      drawnow;

      % write netcdf file
      % -----------------
      error = writeTSGDataNetCDF( hMainFig, [pathName fileName] );

      % Pointer reset to arrow
      % ----------------------
      set( hMainFig, 'Pointer', 'arrow' );

      % Check for a writing pb to NetCDF
      % must to be rewriting
      % --------------------------------
      if error == -1
        warning(['NetCDF writing error:'  [pathName fileName]]);
        return;
      end
      
      % update the display
      % ------------------
      set( hInfoFileText, 'String', fileName);
      
      % enable Quality Control mode
      % ---------------------------
      hdl_pushtool = findobj('Tag', 'QC');
      set(hdl_pushtool, 'Enable', 'on');
    end
    
  end

  % -----------------------------------------------------------------
  % Callback function run when the Quit menu item is selected
  % -----------------------------------------------------------------
  function QuitMenuCallback(hObject, eventdata)  

    % If the data have been modified and not save, the program
    % ask to save the data
    % --------------------------------------------------------
    if  strcmp( get( hSaveMenu, 'UserData' ), 'on')
      selection = ...
        questdlg('The file has been modified.  Do you want to save it ?',...
        'Save before Quit?',...
        'Yes', 'No', 'Yes');
      if strcmp(selection, 'Yes')
        return;
      else
        QuitProgram;
      end
    else
      selection = ...
        questdlg(['Quit ' get(hMainFig, 'Name') '?'],...
        ['Quit ' get(hMainFig, 'Name') '?'],...
        'Yes', 'No', 'Yes');
      if strcmp(selection, 'No')
        return;
      else
        QuitProgram;
      end
    end

  end

  % -----------------------------------------------------------------------
  % Callback function run when the Edit/Undo menu item is selected (Ctrl+Z)
  % -----------------------------------------------------------------------
  function UndoMenuCallback(hObject, eventdata)  
 
    % Undo module not yet implemented
    % -------------------------------
    msgbox('Undo module not yet implemented', 'modal');
    
  end

 % -----------------------------------------------------------------------
  % Callback function run when the Edit/Redo menu item is selected (Ctrl+R)
  % -----------------------------------------------------------------------
  function RedoMenuCallback(hObject, eventdata)  
 
    % Redo module not yet implemented
    % -------------------------------
    msgbox('Redo module not yet implemented', 'modal');
    
  end
  % -----------------------------------------------------------------
  % call from: 
  %   QuitMenuCallback
  %   callback 'CloseRequestFcn', @QuitProgram
  % -----------------------------------------------------------------
  function QuitProgram(hObject, eventdata)
    
    % close the main windows
    % ----------------------
    delete(hMainFig);

    % reset Matlab search path to default
    % -----------------------------------
    rmpath( [DEFAULT_PATH_FILE filesep 'tsg_util'] );
    rmpath( [DEFAULT_PATH_FILE filesep 'tsg_data'] );
    rmpath( [DEFAULT_PATH_FILE filesep 'tsg_io'] );
    
    % Refresh file system caches
    % --------------------------
    rehash;
    
  end

% end of tsgqc_GUI
% ----------------
end  
