/****************************************************************************
 * Copyright (c) 1998-2007 Luna Imaging, Inc.  All Rights Reserved.
 *
 * This software is confidential and proprietary information of
 * Luna Imaging, Inc.  ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Luna Imaging, Inc.
 *
 * The software may not be copied, reproduced, translated or reduced to
 * any electronic medium or machine-readable form without
 * the prior written consent of Luna Imaging.
 *
 * You are not allowed to distribute the binary and source code
 * (if released) to third parties, without the prior written consent from
 * Luna Imaging.
 *
 * You are not allowed to reverse engineer, disassemble or decompile
 * code, or make any modifications of the binary or source code, remove
 * or alter any trademark, logo, copyright or other proprietary notices,
 * legends, symbols, or labels in the Software.
 *
 * You are not allowed to sub-license the Software or any derivative
 * work based on or derived from the Software.
 *
 * LUNA IMAGING MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
 * A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, LUNA IMAGING SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
 * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 *  cruiz10020@yahoo.com
 *
 *  TemplatedPanelControls.js
 *
 *  Description:
 *    Set of controls for use with an ImagePanel that live within the mediaPanel.
 *
 *  Structure:
 *
 *
 *  Requires:
 *    prototype.js - http://www.prototypejs.org/
 *
 *  Development History:
 *    5-14-2007       - created
 *
 *******************************************************************************/

function TemplatedPanelControls( manager, notifyOfActionChangeFunction, notifyOfCancelActionFunction )
{
  // html elemets
  this.mContainer = null;
  this.mButtons = null
  this.mResizer = $( new Array() );
  this.mGrips = $( new Array() );

  // js elements
  this.mManager = manager;
  this.mSlider = null;
  this.mMediaPanel = null;

  this.mLastActionSet = null;
  this.mMediaPanel = null;
  this.mNotifyOfActionChange = notifyOfActionChangeFunction;
  this.mNotifyOfCancelAction = notifyOfCancelActionFunction;
  this.mIsInitalized = false;
  this.mShowingControls = true;
  this.mAnimate = true;
  this.mLastSetLunaLevelTimeout = null;
  this.mLastLevel = null;
  this.mUseSmartPannerDisplay = false;
  this.mPannerClosed = false;

  this.mInternalGrips = true;


  this.ACTION_MOVE = 'ACTION_MOVE';
  this.ACTION_PAN = 'ACTION_PAN';
  this.ACTION_RESIZE_TOP_LEFT = 'ACTION_RESIZE_TOP_LEFT';
  this.ACTION_RESIZE_TOP_RIGHT = 'ACTION_RESIZE_TOP_RIGHT';
  this.ACTION_RESIZE_BOTTOM_RIGHT = 'ACTION_RESIZE_BOTTOM_RIGHT';
  this.ACTION_RESIZE_BOTTOM_LEFT = 'ACTION_RESIZE_BOTTOM_LEFT';

  this.ACTION_ZOOM_IN = 'ACTION_ZOOM_IN';
  this.ACTION_ZOOM_OUT = 'ACTION_ZOOM_OUT';
  this.ACTION_ZOOM_BOX = 'ACTION_ZOOM_BOX';
  this.ACTION_RESET = 'ACTION_RESET';
  this.ACTION_TOGGLE_POSITION = 'ACTION_TOGGLE_POSITION';
  this.ACTION_HELP = 'ACTION_HELP';
  this.ACTION_CLOSE_PANEL = 'ACTION_CLOSE_PANEL';
  this.ACTION_MAXIMIZE_TO_FRAME = 'ACTION_MAXIMIZE_TO_FRAME';
  this.ACTION_MAXIMIZE_TO_CONTAINER = 'ACTION_MAXIMIZE_TO_CONTAINER';
  this.ACTION_INFORMATION = 'ACTION_INFORMATION';
  this.ACTION_THUMBNAIL_PANNER = 'ACTION_THUMBNAIL_PANNER';
  this.ACTION_DEFAULT = this.ACTION_PAN;

  this.GRIP_CLASSNAME = 'grip';
  this.CLOSE_BUTTON_CLASSNAME = 'closeButton';
  this.MAXIMIZE_TO_FRAME_BUTTON_CLASSNAME = 'maximizeToFrameButton';
  this.MAXIMIZE_TO_CONTAINER_BUTTON_CLASSNAME = 'maximizeToContainerButton';
  this.RESIZER_TOP_RIGHT_CLASSNAME = 'resizerTopRight';
  this.RESIZER_TOP_LEFT_CLASSNAME = 'resizerTopLeft';
  this.RESIZER_BOTTOM_RIGHT_CLASSNAME = 'resizerBottomRight';
  this.RESIZER_BOTTOM_LEFT_CLASSNAME = 'resizerBottomLeft';
  this.HELP_BUTTON_CLASSNAME = 'helpButton';
  this.INFO_BUTTON_CLASSNAME = 'imageInformationButton';
  this.THUMBNAIL_PANNER_BUTTON_CLASSNAME = 'thumbnailPannerButton';

  this.GRIP_INSTRUCTIONS = 'Drag here to move the image around';
  this.CLOSE_BUTTON_INSTRUCTIONS = 'Remove image from workspace';
  this.MAXIMIZE_TO_FRAME_INSTRUCTIONS = 'Force fit the image to the frame';
  this.MAXIMIZE_TO_CONTAINER_INSTRUCTIONS = 'Maximize the image to the workspace';
  this.HELP_INSTRUCTIONS = 'View help';
  this.INFORMATION_INSTRUCTION = 'View Image Information';
  this.THUMBNAIL_PANNER_INSTRCUTION = 'Show/Hide Thumbnail Navigator.'

  this.GRIP_MIN_SIZE = 24;
  this.GRIP_MAX_SIZE = 30;
  this.GRIP_PRECENTAGE_SIZE = .065;
  this.BUTTON_GAP =  $( [ 6, 3 ] );
  this.RESIZER_OPACITY = .60;
  this.GRIP_OPACITY = .50;
  this.IDLE_TIME = 15000; // 15 seconds
  this.SCROLLWHEEL_ZOOM_DELAY = 500; // .5 sec

  this.init = function()
  {
    this.mButtons = {};

    // create close button
    if( ( ! this.mSkipClose == true ) )
    {
      this.mButtons['closeButton'] = $( document.createElement( 'a' ) );
      this.mButtons['closeButton'].actionName = this.ACTION_CLOSE_PANEL;
      this.mButtons['closeButton'].templatedPanelControls = this;
      this.mButtons['closeButton'].mediaPanel = this.mMediaPanel;
      this.mButtons['closeButton'].title = this.CLOSE_BUTTON_INSTRUCTIONS;
      this.mContainer.appendChild( this.mButtons['closeButton'] );
      this.mButtons['closeButton'].addClassName( this.CLOSE_BUTTON_CLASSNAME );
      this.mButtons['closeButton'].href = 'javascript:var aButton;';
      this.mButtons['closeButton'].onclick = Static_TemplatedPanelControls_ButtonPressed;
      this.mButtons['closeButton'].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
      this.mButtons['closeButton'].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
      this.mButtons['closeButton'].style.position = 'absolute';
      this.mButtons['closeButton'].style.zIndex = 50;
    }

    this.mButtons['maximizeToContainer'] = $( document.createElement( 'a' ) );
    this.mButtons['maximizeToContainer'].actionName = this.ACTION_MAXIMIZE_TO_CONTAINER;
    this.mButtons['maximizeToContainer'].templatedPanelControls = this;
    this.mButtons['maximizeToContainer'].mediaPanel = this.mMediaPanel;
    this.mButtons['maximizeToContainer'].title = this.MAXIMIZE_TO_CONTAINER_INSTRUCTIONS;
    this.mContainer.appendChild( this.mButtons['maximizeToContainer'] );
    this.mButtons['maximizeToContainer'].addClassName( this.MAXIMIZE_TO_CONTAINER_BUTTON_CLASSNAME );
    this.mButtons['maximizeToContainer'].href = 'javascript:var aButton;';
    this.mButtons['maximizeToContainer'].onclick = Static_TemplatedPanelControls_ButtonPressed;
    this.mButtons['maximizeToContainer'].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
    this.mButtons['maximizeToContainer'].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
    this.mButtons['maximizeToContainer'].style.position = 'absolute';
    this.mButtons['maximizeToContainer'].style.zIndex = 50;

    if( ! ( this.mSkipForceFitToFrame == true ) )
    {
      this.mButtons['maximizeToPanel'] = $( document.createElement( 'a' ) );
      this.mButtons['maximizeToPanel'].actionName = this.ACTION_MAXIMIZE_TO_FRAME;
      this.mButtons['maximizeToPanel'].templatedPanelControls = this;
      this.mButtons['maximizeToPanel'].mediaPanel = this.mMediaPanel;
      this.mButtons['maximizeToPanel'].title = this.MAXIMIZE_TO_FRAME_INSTRUCTIONS;
      this.mContainer.appendChild( this.mButtons['maximizeToPanel'] );
      this.mButtons['maximizeToPanel'].addClassName( this.MAXIMIZE_TO_FRAME_BUTTON_CLASSNAME );
      this.mButtons['maximizeToPanel'].href = 'javascript:var aButton;';
      this.mButtons['maximizeToPanel'].onclick = Static_TemplatedPanelControls_ButtonPressed;
      this.mButtons['maximizeToPanel'].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
      this.mButtons['maximizeToPanel'].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
      this.mButtons['maximizeToPanel'].style.position = 'absolute';
      this.mButtons['maximizeToPanel'].style.zIndex = 50;
    }

    if( ! ( this.mSkipThumbnailPanel == true ) )
    {
      this.mButtons['thumbnailPannerButton'] = $( document.createElement( 'a' ) );
      this.mButtons['thumbnailPannerButton'].actionName = this.ACTION_THUMBNAIL_PANNER ;
      this.mButtons['thumbnailPannerButton'].templatedPanelControls = this;
      this.mButtons['thumbnailPannerButton'].mediaPanel = this.mMediaPanel;
      this.mButtons['thumbnailPannerButton'].title = this.THUMBNAIL_PANNER_INSTRCUTION;
      this.mContainer.appendChild( this.mButtons['thumbnailPannerButton'] );
      this.mButtons['thumbnailPannerButton'].addClassName( this.THUMBNAIL_PANNER_BUTTON_CLASSNAME );
      this.mButtons['thumbnailPannerButton'].href = 'javascript:var aButton;';
      this.mButtons['thumbnailPannerButton'].onclick = Static_TemplatedPanelControls_ButtonPressed;
      this.mButtons['thumbnailPannerButton'].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
      this.mButtons['thumbnailPannerButton'].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
      this.mButtons['thumbnailPannerButton'].style.position = 'absolute';
      this.mButtons['thumbnailPannerButton'].style.zIndex = 50;
    }

    if( !( this.mSkipInfoPanel == true ) )
    {
      this.mButtons['infoButton'] = $( document.createElement( 'a' ) );
      this.mButtons['infoButton'].actionName = this.ACTION_INFORMATION;
      this.mButtons['infoButton'].templatedPanelControls = this;
      this.mButtons['infoButton'].mediaPanel = this.mMediaPanel;
      this.mButtons['infoButton'].title = this.INFORMATION_INSTRUCTION;
      this.mContainer.appendChild( this.mButtons['infoButton'] );
      this.mButtons['infoButton'].addClassName( this.INFO_BUTTON_CLASSNAME );
      this.mButtons['infoButton'].href = 'javascript:var aButton;';
      this.mButtons['infoButton'].onclick = Static_TemplatedPanelControls_ButtonPressed;
      this.mButtons['infoButton'].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
      this.mButtons['infoButton'].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
      this.mButtons['infoButton'].style.position = 'absolute';
      this.mButtons['infoButton'].style.zIndex = 50;
    }

    this.mButtons['helpButton'] = $( document.createElement( 'a' ) );
    this.mButtons['helpButton'].actionName = this.ACTION_HELP;
    this.mButtons['helpButton'].templatedPanelControls = this;
    this.mButtons['helpButton'].mediaPanel = this.mMediaPanel;
    this.mButtons['helpButton'].title = this.HELP_INSTRUCTIONS;
    this.mContainer.appendChild( this.mButtons['helpButton'] );
    this.mButtons['helpButton'].addClassName( this.HELP_BUTTON_CLASSNAME );
    this.mButtons['helpButton'].href = 'javascript:var aButton;';
    this.mButtons['helpButton'].onclick = Static_TemplatedPanelControls_ButtonPressed;
    this.mButtons['helpButton'].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
    this.mButtons['helpButton'].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
    this.mButtons['helpButton'].style.position = 'absolute';
    this.mButtons['helpButton'].style.zIndex = 50;

    // create resizer
    if( !( this.mSkipResizer == true ) )
    {
      this.constructResizers();
    }

    // create grips
    if( !( this.mSkipGrips == true ) )
    {
      this.constructGrips();
    }

    // create slider
    if( !( this.mSkipSlider == true ) )
    {
      var oipc = this;
      this.mSlider = new Slider( function( newLevel ){ oipc.setImagePanelLevel( newLevel, null, null, true ); } );
      this.mSlider.setAnimate( this.mAnimate );
      this.mSlider.render(
        this.mMediaPanel.mPanel,
        this.mMediaPanel.mGlassPlate,
        this.mMediaPanel.getLunaLevelRange(),
        this.mMediaPanel.getLunaLevel() );
      this.mSlider.mBody.templatedPanelControls = this;
      this.mSlider.mBody.mediaPanel = this.mMediaPanel;
      this.mSlider.mSegments.mediaPanel = this.mMediaPanel;
    }

    // mark it Initalized
    this.mIsInitalized = true;

    // position all controls
    this.positionControls();

    // by default hide all controls
    this.hideControls();

    // set the action
    this.setAction( this.ACTION_DEFAULT );

    // scroll wheel zoom
    jshRegisterScrollWheelEvent( this.mContainer, Static_TemplatedPanelControls_ScrollWheel );

    //YAHOO.util.Event.addListener( this.mContainer, "dblclick", Static_TemplatedPanelControls_DblClick );

    // notify of cacnel if esc is pressed
    var oipc = this;
    new YAHOO.util.KeyListener(
    document,
    { keys:27 }, // esc key
    { fn:function(){ if( oipc.mNotifyOfCancelAction ){ oipc.mNotifyOfCancelAction( oipc ); } }, correctScope:false },
    "keyup" ).enable();

    // key listern for zoom box
    new YAHOO.util.KeyListener(
    document,
    { keys:90 }, // z key
    { fn:function(){ oipc.setAction( oipc.ACTION_ZOOM_BOX ); }, correctScope:false },
    "keydown" ).enable();


    new YAHOO.util.KeyListener(
    document,
    { keys:90 }, // z key
    { fn:function(){ if( oipc.mNotifyOfCancelAction ){ oipc.mNotifyOfCancelAction( oipc ); } oipc.setAction( null ); oipc.mSlider.setValue( oipc.mMediaPanel.getLunaLevel(), false ); }, correctScope:false },
    "keyup" ).enable();
  };

  this.constructResizers = function()
  {
    this.mResizer[0] = $( document.createElement( 'div' ) );
    this.mResizer[0].templatedPanelControls = this;
    this.mResizer[0].mediaPanel = this.mMediaPanel;
    this.mResizer[0].actionName = this.ACTION_RESIZE_TOP_LEFT;
    this.mContainer.appendChild( this.mResizer[0] );
    this.mResizer[0].className = ( this.RESIZER_TOP_LEFT_CLASSNAME );
    this.mResizer[0].style.position = 'absolute';
    this.mResizer[0].style.zIndex = 200;
    this.mResizer[0].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
    this.mResizer[0].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
    this.mResizer[0].onmousedown = Static_TemplatedPanel_StartMove;

    this.mResizer[1] = this.mResizer[0].cloneNode( true );
    this.mResizer[1].templatedPanelControls = this;
    this.mResizer[1].mediaPanel = this.mMediaPanel;
    this.mResizer[1].actionName = this.ACTION_RESIZE_TOP_RIGHT;
    this.mContainer.appendChild( this.mResizer[1] );
    this.mResizer[1].className = ( this.RESIZER_TOP_RIGHT_CLASSNAME );
    this.mResizer[1].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
    this.mResizer[1].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
    this.mResizer[1].onmousedown = Static_TemplatedPanel_StartMove;

    this.mResizer[2] = this.mResizer[0].cloneNode( true );
    this.mResizer[2].templatedPanelControls = this;
    this.mResizer[2].mediaPanel = this.mMediaPanel;
    this.mResizer[2].actionName = this.ACTION_RESIZE_BOTTOM_RIGHT;
    this.mContainer.appendChild( this.mResizer[2] );
    this.mResizer[2].className = ( this.RESIZER_BOTTOM_RIGHT_CLASSNAME );
    this.mResizer[2].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
    this.mResizer[2].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
    this.mResizer[2].onmousedown = Static_TemplatedPanel_StartMove;

    this.mResizer[3] = this.mResizer[0].cloneNode( true );
    this.mResizer[3].templatedPanelControls = this;
    this.mResizer[3].mediaPanel = this.mMediaPanel;
    this.mResizer[3].actionName = this.ACTION_RESIZE_BOTTOM_LEFT;
    this.mContainer.appendChild( this.mResizer[3] );
    this.mResizer[3].className = ( this.RESIZER_BOTTOM_LEFT_CLASSNAME );
    this.mResizer[3].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
    this.mResizer[3].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
    this.mResizer[3].onmousedown = Static_TemplatedPanel_StartMove;
  };

  this.constructGrips = function()
  {
    // grips on all 4 sides of the image panel
    this.mGrips[0] = $( document.createElement( 'div' ) );
    this.mContainer.appendChild( this.mGrips[0] );
    this.mGrips[0].addClassName( this.GRIP_CLASSNAME );
    this.mGrips[0].style.position = 'absolute';
    this.mGrips[0].style.zIndex = '100';
    this.mGrips[0].hide();

    this.mGrips[1] = this.mGrips[0].cloneNode( true );
    this.mContainer.appendChild( this.mGrips[1] );
    jshSetOpacity( this.mGrips[1], 0 );

    this.mGrips[2] = this.mGrips[0].cloneNode( true );
    this.mContainer.appendChild( this.mGrips[2] );
    jshSetOpacity( this.mGrips[2], 0 );

    this.mGrips[3] = this.mGrips[0].cloneNode( true );
    this.mContainer.appendChild( this.mGrips[3] );
    jshSetOpacity( this.mGrips[3], 0 );

    for( var i = 0; i <  this.mGrips.length; i++ )
    {
      this.mGrips[i].templatedPanelControls = this;
      this.mGrips[i].mediaPanel = this.mMediaPanel;
      this.mGrips[i].title = this.GRIP_INSTRUCTIONS;
      this.mGrips[i].actionName = this.ACTION_MOVE;
      this.mGrips[i].onmouseover = Static_TemplatedPanelControls_Action_Element_MouseOver;
      this.mGrips[i].onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
      this.mGrips[i].onmousedown = Static_TemplatedPanel_StartMove;
      jshSetOpacity( this.mGrips[i], this.GRIP_OPACITY );
    }

  };

  this.positionControls = function()
  {
    if(this.mIsInitalized == true )
    {
      this.positionGrips();
      this.positionButtons();
      this.positionResizer();

      if( this.mSlider )
      {
        this.mSlider.reposition();
      }
    }
  };

  /**
   * Positions the resize control to its correct posotion based on the current container size
   */
  this.positionResizer = function()
  {
    if( this.mContainer && this.mResizer && ( this.mResizer.length > 0 ) )
    {
      var mediaPanelDimensions = $( [ this.mMediaPanel.mPanel.getWidth(), this.mMediaPanel.mPanel.getHeight() ] );

      var gripSize = Math.round( this.GRIP_PRECENTAGE_SIZE * Math.max( mediaPanelDimensions[0], mediaPanelDimensions[1] ) );
      gripSize = Math.max( gripSize, this.GRIP_MIN_SIZE );
      gripSize = Math.min( gripSize, this.GRIP_MAX_SIZE );

      var parentOffset = Position.cumulativeOffset( this.mMediaPanel.mPanel );
      parentOffset[0] -= gripSize;
      parentOffset[1] -= gripSize;

      this.mResizer[0].style.left = ( parentOffset[0] ) + 'px';
      this.mResizer[0].style.top = ( parentOffset[1] ) + 'px';

      this.mResizer[1].style.left = ( parentOffset[0] + mediaPanelDimensions[0] + gripSize ) + 'px';
      this.mResizer[1].style.top = ( parentOffset[1] ) + 'px';

      this.mResizer[2].style.left = ( parentOffset[0] + mediaPanelDimensions[0] + gripSize ) + 'px';
      this.mResizer[2].style.top = ( parentOffset[1] + mediaPanelDimensions[1] + gripSize ) + 'px';

      this.mResizer[3].style.left = (  parentOffset[0] ) + 'px';
      this.mResizer[3].style.top = ( parentOffset[1] + mediaPanelDimensions[1] + gripSize ) + 'px';
    }
  };

  this.positionButtons = function()
  {
    if( this.mContainer && this.mButtons )
    {
      var mediaPanelDimensions = $( [ this.mMediaPanel.mPanel.getWidth(), this.mMediaPanel.mPanel.getHeight() ] );
      var parentOffset = Position.cumulativeOffset( this.mMediaPanel.mPanel );

      var gap = this.BUTTON_GAP;
      var count = 1;
      for( var button in this.mButtons )
      {
        this.mButtons[button].style.left = ( (  parentOffset[0] + mediaPanelDimensions[0] )  - ( ( count + 1 ) * gap[0] ) - ( count * this.mButtons[button].getWidth() ) ) + 'px';
        this.mButtons[button].style.top = ( parentOffset[1] + gap[1] ) + 'px';
        count++;
      }
    }
  };

  this.isWithinButtons = function( x, y )
  {
    for( var button in this.mButtons )
    {
      if( Position.within( this.mButtons[button], x, y ) )
      {
        return true;
      }
    }

    return false;
  }

  this.positionGrips = function()
  {
    if( this.mMediaPanel && this.mContainer && this.mGrips && ( this.mGrips.length > 0 ) )
    {
      var parentOffset = Position.cumulativeOffset( this.mMediaPanel.mPanel );
      var borderDimensions = jshBorderOffset( this.mMediaPanel.mPanel, [0, 0] );
      var mediaPanelDimensions = $( [ this.mMediaPanel.mPanel.getWidth(), this.mMediaPanel.mPanel.getHeight() ] );

      parentOffset[0] += Math.round( borderDimensions[0] / 2);
      parentOffset[1] += Math.round( borderDimensions[1] / 2 );

      mediaPanelDimensions[0] -= borderDimensions[0];
      mediaPanelDimensions[1] -= borderDimensions[1];

      var gapSize = 0;
      var gripSize = Math.round( this.GRIP_PRECENTAGE_SIZE * Math.max( mediaPanelDimensions[0], mediaPanelDimensions[1] ) );
      gripSize = Math.max( gripSize, this.GRIP_MIN_SIZE );
      gripSize = Math.min( gripSize, this.GRIP_MAX_SIZE );

      parentOffset[0] -= gripSize;
      parentOffset[1] -= gripSize;
      mediaPanelDimensions[0] += ( 2 * gripSize );
      mediaPanelDimensions[1] += ( 2 * gripSize );

      this.mGrips[0].style.left = ( parentOffset[0] + gapSize ) + 'px';
      this.mGrips[0].style.top = ( parentOffset[1] + gapSize ) + 'px';
      this.mGrips[0].style.width = mediaPanelDimensions[0] - ( 2 * gapSize ) + 'px';
      this.mGrips[0].style.height = gripSize + 'px';

      this.mGrips[1].style.left = ( parentOffset[0] + this.mGrips[0].getWidth() - gripSize + gapSize ) + 'px';
      this.mGrips[1].style.top = ( this.mGrips[0].getHeight() + parentOffset[1] + gapSize )  + 'px';
      this.mGrips[1].style.width = gripSize + 'px';
      this.mGrips[1].style.height = ( mediaPanelDimensions[1] - this.mGrips[0].getHeight() - ( 2 * gapSize ) ) + 'px';

      this.mGrips[2].style.left = ( parentOffset[0] + gapSize ) + 'px';
      this.mGrips[2].style.top = ( parentOffset[1] + mediaPanelDimensions[1] - ( gapSize + gripSize ) ) + 'px';
      this.mGrips[2].style.width = ( mediaPanelDimensions[0] - this.mGrips[1].getWidth() - ( 2 * gapSize ) ) + 'px';
      this.mGrips[2].style.height = gripSize + 'px';

      this.mGrips[3].style.left = ( parentOffset[0] + gapSize ) + 'px';
      this.mGrips[3].style.top = ( this.mGrips[0].getHeight() + parentOffset[1] + gapSize )  + 'px';
      this.mGrips[3].style.width = gripSize + 'px';
      this.mGrips[3].style.height = ( mediaPanelDimensions[1] - this.mGrips[0].getHeight() - gripSize - ( 2 * gapSize ) ) + 'px';
    }
  };

  this.render = function( mediaPanel )
  {
    if( mediaPanel && ( ! this.mMediaPanel ) )
    {
      this.mMediaPanel = mediaPanel;
      this.mContainer = mediaPanel.mContainer;
      this.init();
    }
  };

  this.showControls = function()
  {
    if( ( this.mIsInitalized == true ) && ( this.mShowingControls == false ) )
    {
      this.mShowingControls = true;

      this.positionControls();

      if( this.mSlider )
      {
        this.mSlider.showControls();
      }

      if( this.mResizer )
      {
        for( var i = 0; i <  this.mResizer.length; i++ )
        {
          if( this.mAnimate == true )
          {
            jshFadeElement( this.mResizer[i], 50, 15, true, this.RESIZER_OPACITY );
          }
          else
          {
            this.mResizer[i].show();
          }
        }
      }

      if( this.mGrips )
      {
        for( var i = 0; i <  this.mGrips.length; i++ )
        {
          this.mGrips[i].show();

          if( this.mAnimate == true )
          {
            jshFadeElement( this.mGrips[i], 100, 30, true, this.GRIP_OPACITY );
          }
          else
          {
            jshSetOpacity( this.mGrips[i], this.GRIP_OPACITY );
          }
        }
      }

      if( this.mButtons )
      {
        for( var button in this.mButtons )
        {
          if( this.mAnimate == true )
          {
            jshFadeElement( this.mButtons[button], 50, 15, true, .9 );
          }
          else
          {
            this.mButtons[button].show();
          }
        }
      }
    }
  };

  this.hideControls = function()
  {
    if( ( this.mIsInitalized == true ) && ( this.mShowingControls == true ) )
    {
      this.mShowingControls = false;

      if( this.mSlider )
      {
        this.mSlider.hideControls();
      }

      if( this.mResizer )
      {
        for( var i = 0; i <  this.mResizer.length; i++ )
        {
          if( this.mAnimate == true )
          {
            jshFadeElement( this.mResizer[i], 100, 30, false );
          }
          else
          {
            this.mResizer[i].hide();
          }
        }
      }

      if( this.mGrips )
      {
        for( var i = 0; i <  this.mGrips.length; i++ )
        {
          if( this.mAnimate == true )
          {
            jshFadeElement( this.mGrips[i], 100, 30, false );
          }
          else
          {
            jshSetOpacity( this.mGrips[i], 0 );
          }
        }
      }

      if( this.mButtons )
      {
        for( var button in this.mButtons )
        {
          if( this.mAnimate == true )
          {
            jshFadeElement( this.mButtons[button], 100, 30, false );
          }
          else
          {
            this.mButtons[button].hide();
          }
        }
      }
    }
  };

  /**
   * If true the panel will animate certain actions like close and open
   */
  this.setAnimate = function( animate )
  {
    this.mAnimate = animate;

    if( this.mSlider )
    {
      this.mSlider.setAnimate( this.mAnimate );
    }
  };

  this.hideIfIdle = function()
  {
    if( this.mMediaPanel.mLastIdleTime )
    {
      if( ( new Date() - this.mMediaPanel.mLastIdleTime ) >= this.IDLE_TIME )
      {
        this.hideControls();
      }
    }
  };

  this.getCurrentAction = function()
  {
    return this.mLastActionSet;
  };

  this.setAction = function( anAction )
  {
    if( ! anAction )
      anAction = this.ACTION_PAN;

    var oldAction = this.mLastActionSet;
    this.mLastActionSet = anAction;

    // notify manager of action change
    if( this.mLastActionSet && ( oldAction != this.mLastActionSet ) )
    {
      if( this.mNotifyOfActionChange )
      {
        this.mNotifyOfActionChange( this, oldAction, this.mLastActionSet );
      }
    }
  };

  this.setManager = function( manager )
  {
    this.mManager = manager;
  };

  this.setImagePanelLevel = function( newLevel, postPanPoint, translatePoint, forceUpdate )
  {
    if( this.mMediaPanel )
    {
      if( forceUpdate != true )
      {
        // clear any existing request to build body
        if( this.mLastSetLunaLevelTimeout != null )
        {
          clearTimeout( this.mLastSetLunaLevelTimeout );
        }

        // lets wait a bit ebfore constrcuting to see if they change sizes again
        var oipc = this;
        var nl = newLevel;
        var ppp = postPanPoint;
        var tp = translatePoint;
        this.mLastSetLunaLevelTimeout = setTimeout( function(){ oipc.setImagePanelLevel( nl, ppp, tp, true ); }, this.SCROLLWHEEL_ZOOM_DELAY );
      }
      else
      {
        //alert( newLevel + ' ; ' + postPanPoint + ' ; ' + translatePoint );
        this.mLastLevel = null;
        this.mMediaPanel.setLunaLevel( newLevel, postPanPoint, translatePoint );

        // be smart about showing panner
        if( this.mManager &&
            this.mManager.mThumbnailPanner &&
          ( this.mUseSmartPannerDisplay == true ) )
        {
          if( this.mPannerClosed != true )
          {
            if( this.mMediaPanel.isPartialImage( true ) )
            {
              this.mManager.mThumbnailPanner.show();
            }
            else
            {
              this.mManager.mThumbnailPanner.hide();
            }
          }
        }
      }
    }
  }

  this.useSmartPannerDisplay = function( useSmartPannerDisplay )
  {
    this.mUseSmartPannerDisplay = ( useSmartPannerDisplay == true );
  }

};

function Static_TemplatedPanelControls_Action_Element_MouseOver( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );

  if( sourceElement && sourceElement.templatedPanelControls )
  {
    var templatedPanelControls = sourceElement.templatedPanelControls;

    templatedPanelControls.setAction( sourceElement.actionName );

    var mediaPanel = templatedPanelControls.mMediaPanel;
    mediaPanel.showControls();

    // over ride mouse down with the panel's down so the events singls the panel to action
    sourceElement.onmouseout = Static_TemplatedPanel_MouseOut;
  }
}

function Static_TemplatedPanelControls_Action_Element_MouseOut( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );

  if( sourceElement && sourceElement.templatedPanelControls )
  {
    var templatedPanelControls = sourceElement.templatedPanelControls;

    if( templatedPanelControls.mMediaPanel.mActionInProgress != true )
    {
      templatedPanelControls.setAction( null );
    }

    // reset mouse out so that we can work properly
    sourceElement.onmouseout = Static_TemplatedPanelControls_Action_Element_MouseOut;
  }
}

/**
 * Static event passthrough funciton for closing a panel
 */
function Static_TemplatedPanelControls_ButtonPressed( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );

  if( sourceElement && sourceElement.templatedPanelControls )
  {
    var templatedPanelControls = sourceElement.templatedPanelControls;

    if( sourceElement.actionName )
    {
      sourceElement.blur();

      if( sourceElement.actionName == templatedPanelControls.ACTION_CLOSE_PANEL )
      {
        templatedPanelControls.mMediaPanel.close();
      }
      else if( sourceElement.actionName == templatedPanelControls.ACTION_MAXIMIZE_TO_FRAME )
      {
        templatedPanelControls.mMediaPanel.maximizeImageToPanel();
      }
      else if( sourceElement.actionName == templatedPanelControls.ACTION_MAXIMIZE_TO_CONTAINER )
      {
        templatedPanelControls.mMediaPanel.maximizePanelToContainer();
      }
      else if( sourceElement.actionName == templatedPanelControls.ACTION_HELP )
      {
        if( templatedPanelControls.mManager )
          templatedPanelControls.mManager.showHelpPage();
      }
      else if( sourceElement.actionName == templatedPanelControls.ACTION_INFORMATION )
      {
        if( templatedPanelControls.mManager && templatedPanelControls.mManager.mMediaPanelInfo )
          templatedPanelControls.mManager.mMediaPanelInfo.toggle();
      }
      else if( sourceElement.actionName == templatedPanelControls.ACTION_THUMBNAIL_PANNER )
      {
        if( templatedPanelControls.mManager && templatedPanelControls.mManager.mThumbnailPanner )
        {
          templatedPanelControls.mManager.mThumbnailPanner.toggle();
          if( templatedPanelControls.mManager.mThumbnailPanner.isHidden() )
          {
            templatedPanelControls.mPannerClosed = true;
          }
        }
      }
    }
  }
}

function Static_TemplatedPanelControls_DblClick( e )
{
  var point = $( new Array() );
  var position = $( new Array() );
  var offset = null;
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );

  if( sourceElement && sourceElement.mediaPanel )
  {
    var mediaPanel = sourceElement.mediaPanel;
    var templatedPanelControls = mediaPanel.mControl;

    // lets cal the on screen mouse xy
    position = [ Event.pointerX(e), Event.pointerY(e) ];
    offset = Position.page( mediaPanel.mPanel );
    point[0] = position[0] - offset[0];
    point[1] = position[1] - offset[1];
    var bak = $( [ point[0], point[1] ] );

    // now that we have the on screen xy
    // lets transalate that into image coordinate
    var actualImage = mediaPanel.getActualViewPoint();
    var panelDimensions = mediaPanel.getDimensions();
    point[0] += Math.round( actualImage[0] );
    point[1] += Math.round( actualImage[1] );

    // lets cal the next level based on the
    // direction of the scroll
    var scrolledUp = true;
    var newLevel = mediaPanel.getLunaLevel();
    newLevel = (scrolledUp)? newLevel - 1 : newLevel + 1;

    // lets update
    templatedPanelControls.setImagePanelLevel( newLevel, point, true, true );
    //mediaPanel.setLunaLevel( newLevel, point, true );

    // update slider
    if( mediaPanel.mControl && mediaPanel.mControl.mSlider )
    {
      mediaPanel.mControl.mSlider.setValue( newLevel, false );
    }

    // stop event so that browser doesnt also scroll
    Event.stop( e );
  }
}

function Static_TemplatedPanelControls_ScrollWheel( e )
{
  var point = $( new Array() );
  var position = $( new Array() );
  var offset = null;
  var containerOffset = null;
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );

  if( sourceElement && sourceElement.mediaPanel )
  {
    var mediaPanel = sourceElement.mediaPanel;
    var templatedPanelControls = mediaPanel.mControl;
    var newLevel = ( templatedPanelControls.mLastLevel == null ) ? mediaPanel.getLunaLevel() : templatedPanelControls.mLastLevel;
    var scrolledUp = jshScrolledUp( e );
    var panelDimensions = mediaPanel.getDimensions();
    var imageSize = mediaPanel.getCurrentImageSize

    // lets calc the on screen mouse xy
    position = jshGetMousePositionFromScrollEvent( e, mediaPanel.mContainer );
    if( mediaPanel.mScaleFactor ||
        ( ( panelDimensions[0] > imageSize[0] ) || ( panelDimensions[1] > imageSize[1] ) ) )
    {
      // dealing with a centered image
      offset = Position.page( mediaPanel.mImage );
      point[0] = position[0] - offset[0];
      point[1] = position[1] - offset[1];

      // adjust if scale factor, if any
      if(  mediaPanel.mScaleFactor &&
         ( mediaPanel.mScaleFactor[0] || mediaPanel.mScaleFactor[1]  ) )
      {
        // if we scaled then we upspampled so we dont need to change levels
        newLevel = (scrolledUp)? newLevel - 1 : newLevel + 1;

        // adjust by scale factor
        point[0] = Math.round( point[0] * Math.pow( mediaPanel.mScaleFactor[0], -1 ) );
        point[1] = Math.round( point[1] * Math.pow( mediaPanel.mScaleFactor[1], -1 ) );
      }
      else
      {
        // no scale factor so level up.
        newLevel = (scrolledUp)? newLevel - 1 : newLevel + 1;
      }
    }
    else
    {
      // typical situation where image is larger than view port
      var actualImage = mediaPanel.getActualViewPoint();
      offset = Position.page( mediaPanel.mPanel );
      point[0] = position[0] - offset[0];
      point[1] = position[1] - offset[1];

      // adjust for pan offset
      point[0] += Math.round( actualImage[0] );
      point[1] += Math.round( actualImage[1] );

      newLevel = (scrolledUp)? newLevel - 1 : newLevel + 1;
    }

    // lets update the image level
    templatedPanelControls.mLastLevel = newLevel;
    templatedPanelControls.setImagePanelLevel( newLevel, point, true, true );

    // stop event so that browser doesnt also scroll
    Event.stop( e );
  }
}









