﻿///<reference path="MicrosoftAjax.debug.js" > 
///<reference path="shared.js" > 
///<reference path="control.js" > 

//STEP 1: Replace ScrollViewer w/ your controls' name 
//STEP  2: Move Constants.ScrollViewer to shared.js 
//STEP 3: Modify your DefaultTemplate so it matches 
//STEP 4: Update manifest.xaml ... 
//STEP 5:  Add this JS file as a reference in default.html  (or your entry point) 


SLx.ControlFactory.ScrollViewer = function () 
{ 
    var template = SLx.Application.Current.get_resources().findName ( SLx.Constants.ScrollViewer); 
    if ( template  != "" ) 
    {     
        var ScrollViewer= new SLx.ScrollViewer ( null,  template , SLx.ScrollViewer.DefaultTemplate );          
        return ScrollViewer ; 
        
    } 
    Sys.Debug.assert( false , "this should not fail");     
    return null ; 
} 


SLx.ScrollViewer = function ( visual , xamlTemplate , templateParts )
{  
    this._panel = null ; 
    this._content = null ; 
    this._verticalScrollbar = null ;    
    this._horizontalScrollbar = null ; 
    this._horHeight = 16; 
    this._verWidth = 16; 
    SLx.ScrollViewer.initializeBase (this , [ visual , xamlTemplate , templateParts ] );   
    
    Sys.Debug.assert ( this._panel != null ); 
    Sys.Debug.assert ( this._verticalScrollbar != null ); 
    Sys.Debug.assert ( this._horizontalScrollbar != null ); 
    Sys.Debug.assert (this._content != null ); 
    
    
    
    this._content.add_contentChanged ( $delegate ( this, this._onContentChanged ) ); 
    this._content.add_layoutInvalidated ( $delegate ( this, this._onContentLayoutChanged )) ; 
    
    this._verticalScrollbar.add_valueChanged ( $delegate ( this, this._onVerticalScroll )); 
    this._horizontalScrollbar.add_valueChanged ( $delegate ( this, this._onHorizontalScroll )); 
}, 

SLx.ScrollViewer.DefaultTemplate = [ 
{ name: "ScrollViewer" , ref: "_visualElement", type: "element"  } , 
{ name: "PART_Container" , ref: "_panel", type: "BasicDockPanel" , instantiate: true   }, 
{ name: "PART_VerticalScroll" , ref: "_verticalScrollbar", type: "VerticalScrollbar"  , instantiate: true }, 
{ name: "PART_HorizontalScroll" , ref: "_horizontalScrollbar", type: "HorizontalScrollbar" , instantiate: true  } ,
{ name: "PART_Content" , ref: "_content", type: "ContentPresenter"  }   
]; 

SLx.ScrollViewer.prototype = 
{   
    _onContentLayoutChanged : function ( sender ) 
    { 
        //TODO: I have not cracked this...  
        // here we need to realculate our scrollviewer... but with out triggering layoutChanged on content  I tried the 3 lines below and did not work.. 
        
        /* 
        this._content._supressInvalidateLayout = true ; 
        this.invalidateLayout(); 
        window.setTimeout (  $delegate ( this, this._allowChildLayout ), 2000 ); 
        */ 
           
    }, 
    
    _allowChildLayout : function () 
    { 
        this._content._supressInvalidateLayout = false ; 
    }, 
    
    
    _onContentChanged : function ( sender ) 
    { 
        
        if ( this._content != null ) 
        { 
            if  ( this._content.get_hasContent() ) 
            { 
                var width  = this._content.get_content().get_width (); 
                var height = this._content.get_content().get_height ();                 
            } 
            else 
            { 
                var width  = this._content.get_width (); 
                var height = this._content.get_height (); 
                
             } 
            
            if ( width <= ( this.get_width () - this._verticalScrollbar.get_width ()) )             
            { 
                this._horizontalScrollbar.set_visible( false ) ;                                
            } 
            
            if ( height <= ( this.get_height () - this._horizontalScrollbar.get_height ()) ) 
            { 
                this._verticalScrollbar.set_visible( false ) ;   
            }             
        } 
    }, 
    
    
    set_content : function SLx$Button$set_content (  value ) 
    {
        if ( this._content ==  null )            
        { 
            if ( !SLx.VisualTreeHelper.isControl ( value )) 
            {  
                this._content = new SLx.ContentPresenter ( value ); 
            } 
            else 
            { 
                Sys.Debug.assert ( Object.getType(value).inheritsFrom  ( SLx.Control ) || Object.getType(value).inheritsFrom ( SLx.Panel ), 
                    "sanity check to make sure we don't miss a visual ");  
                
                 this._content = value ; 
            } 
        } 
        else 
        { 
            if ( !SLx.VisualTreeHelper.isControl ( value )) 
            { 
                this._content = value ; 
            } 
            else
            { 
                this._content.set_visual (value)   ; 
            } 
        }   
        
        
            
      this.invalidateLayout (); 
    }, 
    
    get_content : function SLx$Button_get_content ()
    { 
        if ( this._content == null  ) 
        { 
            return this._visualElement.findName ("PART_Content"); 
        } 
        return this._content; 
    },  
    
    _bindParts : function SLx$ScrollViewer$_bindParts ( templateParts  ) 
    {    
         var tag ; 
                         
         for ( var i = 0 ; i < templateParts.length ; i++ ) 
        { 
            var item = templateParts [i];              
              var element; 
                if ( this._visualElement != null ) 
                    element = this._visualElement.findName ( item.name ) ; 
                
                if ( element == null )  
                    element = SLx.Application.Current.get_host().content.findName ( item.name ) ;  
                
                if ( element != null && element.Tag != "" ) 
                { 
                    tag = eval ( "({" + element.Tag + "})" ) ; 
                } 
                else 
                    tag = null ; 
                    
                    
            if ( item.type == "element" ) 
            { 
                this[item.ref] = element ;                             
            } 
            else if  ( item.type == "BasicDockPanel" ) 
            { 
                if ( tag != null && tag["class"] != null ) 
                { 
                    Sys.Debug.Asssert ( tag["class"] == "BasicDockPanel") ;                                         
                } 
                var panel = new SLx.BasicDockPanel ( element , false ); 
                // panel.set_Tags ( element.Tag ) ; 
                
                this[item.ref] = panel ; 
                if ( element != null ) 
                this._visualElement.Children.remove ( element ) ;                 
                this._visualElement.Children.Add ( panel.get_visual() ) ; 
                                
            } 
            else if ( item.type == "VerticalScrollbar" ) 
            { 
                var scb = SLx.ControlFactory.ResizableVerticalScrollbar ( ); 
                this[item.ref]  = scb ; 
                scb.set_Tags ( element.Tag ); 
                if ( this._panel != null ) 
                { 
                    this._panel.get_children().add ( scb ); 
                } 
                
                /* 
                        element , 
                        SLx.Application.Current.get_resources().findName ( SLx.Constants.HorizontalScrollbar), 
                        SLx.Scrollbar.DefaultTemplate ); 
                 */ 
            }
            else if ( item.type == "HorizontalScrollbar" ) 
            { 
              var scb  = SLx.ControlFactory.ResizableHorizontalScrollbar ( ); 
              this[item.ref]  = scb ; 
                scb.set_Tags ( element.Tag ); 
                if ( this._panel != null ) 
                { 
                    this._panel.get_children().add ( scb ); 
                } 
              /*  element , 
                    SLx.Application.Current.get_resources().findName ( SLx.Constants.HorizontalScrollbar), 
                    SLx.Scrollbar.DefaultTemplate); */ 
            }  
            else if ( item.type == "ContentPresenter") 
            { 
                var cp = new SLx.ContentPresenter ( element ) ;                                 
                this[item.ref] = cp ; 
                
                if ( this._panel != null ) 
                { 
                    this._panel.get_children().add ( cp ); 
                } 
            }
            else 
            { 
                Sys.Debug.assert(false, "we skipped a type"); 
            }                   
        }         
        
        //TODO: RemOVE this is DEBUG stuff ) 
        if ( this._isLayoutRegistered ) 
        { 
            Sys.Debug.assert ( false, "what's the scenario? applyTemplate, but has not been implemented"); 
            this.invalidateLayout (); 
        } 
    } , 
    
    measure: function SLx$Scrollviewer$measure ( width, height ) 
    { 
        if ( !this._isMeasureInvalidated ) 
            return ; 
        
        Sys.Debug.assert ( width == this.get_width() , "scrollviewer is meant as a root; should always be same size" ) ; 
        Sys.Debug.assert ( height == this.get_height () , "scrollviewer is a root; should always be same size" ) ; 
        
        
        this._desiredSize.Width = width ; 
        this._desiredSize.Height = height ; 


            
        Sys.Debug.assert ( this._sizeToParent == false || SLx.Warning.ScrollViewerCantSizeToParentIsByDesign, "ScrollViewerCantSizeToParentIsByDesign For now"); 
        
        if ( this._content != null ) 
        { 
            contentsize  = this._content.get_containedSize(); 
            var  showhorizontal  = contentsize.Width > this._desiredSize.Width ; 
            var showvertical = contentsize.Height > this._desiredSize.Height ; 
            if ( !showhorizontal ) 
            { 
                this._horHeight = this._horizontalScrollbar.get_height(); 
                this._horizontalScrollbar.set_height(0); 
                this._horizontalScrollbar.set_visible ( false ); 
                
            }
            else /* if ( !this._horizontalScrollbar.get_visible ()) */ 
            {
                this._horizontalScrollbar.set_height(0); 
                this._horizontalScrollbar.set_visible (false );  
                /*
                RADEK_COMMENT
                this._horizontalScrollbar.set_visible (true );  
                // we must set size because measures are cached..     
                var horizontalwidth = this._desiredSize.Width; 
                if ( showvertical ) 
                    horizontalwidth -= this._verticalScrollbar.get_width(); 
                   
                this._horizontalScrollbar.set_size ( horizontalwidth , Math.max( 16, this._horHeight) );                      
                // this._horizontalScrollbar.measure ( horizontalwidth, Math.max( 16, this._horHeight) ); 
                */
            }  
            
            if ( !showvertical ) 
            { 
                this._verWidth =  this._verticalScrollbar.get_width(); 
                this._verticalScrollbar.set_width( 0); 
                this._verticalScrollbar.set_visible ( false ); 
            }
            else /* if ( !this._horizontalScrollbar.get_visible ()) */
            { 
                this._verticalScrollbar.set_visible (true ); 
                
                var verticalheight = this._desiredSize.Height; 
                if ( showvertical ) 
                    verticalheight -= this._horizontalScrollbar.get_height();
                    
                this._verticalScrollbar.set_size (Math.max( 16, this._verWidth), verticalheight);  
                //this._verticalScrollbar.measure (Math.max( 16, this._verWidth), verticalheight );  
            }              
        } 
                
        Sys.Debug.assert ( this._panel != null ) ; 
        
        this._panel.set_size( this._desiredSize.Width, this._desiredSize.Height ); 
        this._panel.measure ( this._desiredSize.Width, this._desiredSize.Height ) ; 
        
        
        this._desiredSize = this._panel.get_desiredSize(); 
        
        // this._desiredSize.Width = this.get_width (); 
        // this._desiredSize.Height = this.get_height (); 
        
        this._isMeasureInvalidated = false ;     
    }, 
    
    arrange : function SLx$Scrollviewer$arrange ( left, top, width , height ) 
    { 
    
        var moved =   (  this._visualElement["Canvas.Left"]   != left || this._visualElement["Canvas.Top"] != top ) ; 
        var sized =  ( this._visualElement["width"] != width  || this._visualElement["height"] != height  ); 
        
        
        if ( !moved && !sized && !this._isArrangeInvalidated && SLx.Application.Current.get_cacheLayout()  ) 
         { 
         Sys.Debug.trace ( this.toString ()  + "  cached arrange" ); 
            return ; 
         } 
         
           this._visualElement["Canvas.Left"] = left ;
           this._visualElement["Canvas.Top"]  = top; 
           this._visualElement["width"] = width ; 
           this._visualElement["height"] = height  ;       
           this._panel.arrange ( 0, 0, width , height );   
          
          if ( this._panel != null )  
          {      
            var showhorizontal = this._horizontalScrollbar.get_visible (); 
            var showvertical = this._verticalScrollbar.get_visible (); 
            if ( showvertical) 
            {             
                var size = this._verticalScrollbar.get_desiredSize ();                     
                this._verticalScrollbar.arrange(
                    width - size.Width ,  0 , size.Width , size.Height );                 
            }  
            
            if ( showhorizontal) 
            {                
                var size = this._horizontalScrollbar.get_desiredSize ();                     
                this._horizontalScrollbar.arrange(
                    0,  height - size.Height , size.Width , size.Height ); 
            } 
         
            
            if ( showhorizontal && showvertical ) 
            { 
                this._corner = this._visualElement.findName ("PART_Corner") ;  
                this._visualElement.Children.remove ( this._corner); 
                this._visualElement.Children.add ( this._corner ); 
                this._corner.visibility = SLx.Visibility.Visible; 
                this._corner["Canvas.Top"] = this._verticalScrollbar.get_height ();  
                this._corner["Canvas.Left"] = this._horizontalScrollbar.get_width (); 
            } 
            else 
            { 
                if ( this._corner != null ) 
                    this._corner.visibility = SLx.Visibility.Collapsed; 
            } 
            
            
            if ( this.get_clipToBounds  ( ) ) 
            { 
                this.set_clipToBounds ( true ); 
            } 
            
          }                    
        this._isArrangeInvalidated = false ;     
    },
    
    
    
    invalidateLayout : function () 
    { 
        if (  this._supressInvalidateLayout ) 
            return ;
                        
        this._isMeasureInvalidated = true ; 
        this._isArrangeInvalidated = true ;         
        SLx.Application.Current.get_layoutManager().invalidate ( this );   
       
        if ( this._panel != null ) 
            this._panel.invalidateLayout(); 
            // These two lines make a difference.. one queues the panel (below ) the other one invalidates panel and children.. 
            // SLx.Application.Current.get_layoutManager().invalidate ( this._panel ); 
              
        this._fireInvalidateLayout () ; 
    },  
    
    _onVerticalScroll : function  ( sender , args ) 
    { 
        var pct = this._verticalScrollbar.get_percent ();  
       
        var size; 
        if ( this._content != null ) 
        { 
            if ( this._content.get_hasContent () ) 
            { 
                size = this._content.get_content().get_containedSize(); 
            } 
            else 
                size = this._content.get_containedSize();                 
        } 
        
        var containerheight =  this._content.get_height () ;
        
        
        if ( this._content != null )         
            this._content.set_top ( 0 - ( ( size.Height - containerheight) * pct ) ); 
                    
    }, 
    
    _onHorizontalScroll : function  ( sender , args ) 
    { 
        var pct = sender.get_percent ();  
       
        var size; 
        if ( this._content != null ) 
        { 
            if ( this._content.get_hasContent () ) 
            { 
                size = this._content.get_content().get_containedSize(); 
            } 
            else 
                size = this._content.get_containedSize();                 
        } 
        
        var containerwidth =  this._content.get_width () ;
        
        
        if ( this._content != null )         
            this._content.set_left( 0 - ( ( size.Width - containerwidth) * pct ) ); 
            
 
        
    }, 
    
    toString : function  () 
    { 
        return this._uniqueSystemId.toString ()  + "    " + Object.getTypeName(this) + "    " + this._id ; 
    }
    
    /* 
    arrange : function  ( left, top, width, height ) 
    { 
         SLx.ScrollViewer.callBaseMethod ( this, "arrange", [left, top, width, height] ); 
        
        if ( this._content != null ) 
        { 
         this._onContentChanged ( );     
        } 
    } */ 
       
}  


SLx.ScrollViewer.registerClass('SLx.ScrollViewer', SLx.Control ); 



// TODO : PLEASE MOVE to Shared.JS 
SLx.Constants.ScrollViewer = "ScrollViewer" ; 


