﻿///<reference path="MicrosoftAjax.debug.js" > 
///<reference path="shared.js" > 
///<reference path="control.js" > 


Type.registerNamespace("SLx");

SLx.ElementCollection = function  (  validChildrenCallback , addCallback , removeCallback, isChildCallback ) 
{ 
    this._children = [] ;        
    
    this._isValidChildrenCallback = validChildrenCallback; 
    this._addChildCallback  = addCallback; 
    this._removeChildCallback = removeCallback ; 
    this._isChildCallback = isChildCallback;     
       
    this._childAddedListeners = [] ;     
    
} 

SLx.ElementCollection.prototype = 
{ 
    add : function ( item ) 
    { 
        var retval = this._isValidChildrenCallback ( item ); 
        if ( retval ) 
        { 
            retval = this._addChildCallback ( item ) ;   
            Sys.Debug.assert ( retval == true ); //                             
            if ( retval ) 
            { 
                Array.add ( this._children , item ); 
                retval = this._onChildrenAdded    ( item ) ;             
                Sys.Debug.assert ( retval == true ); // 
             } 
                
        } 
        Sys.Debug.assert ( retval == true ); // 
        return retval ; 
    }, 
    
    add_ChildAdded : function ( callback  ) 
    { 
        Array.add ( this._childAddedListeners, callback ); 
    } , 
    
    remove_childAdded : function ( callback  ) 
    { 
        Array.remove ( this._childAddedListeners , callback );
    } , 
    
     
    _onChildrenAdded     : function ( item ) 
    { 
        for ( var  i = 0, len= this._childAddedListeners.length  ; i < len ; i++ ) 
        { 
            this._childAddedListeners [i] ( item ) ; 
        } 
        return true; 
    }, 
    
    _onChildrenRemoved    : function ( item ) 
    { 
        return true; 
    }, 
    
     
    remove : function ( item ) 
    { 
         var ok = this._isexistingChildCallback ( item ); 
         if ( ok ) 
         { 
            ok = this._removeChildCallback ( item  ) ;     
                                              
            if ( ok ) 
            { 
                Array.remove ( this._children, item ) ; 
                this._onChildrenRemoved    ( item ) ;                   
            } 
        }        
        return ok ;
    }, 
    
    get_length : function ( ) 
    { 
        return this._children.length ; 
    }, 
    
    getItem : function ( index ) 
    {     
        return this._children [index] ; 
    } 
}  
 


SLx.Panel = function( visual , sizeToContent )
{    
    if ( visual == null  ) 
    { 
        visual  = SLx.Application.Current.createUniqueElement (); 
        //TODO: should we add it or not ???  I think not because we often end up moving it later.. 
        // SLx.Application.Current.get_host().content.root.Children.add ( visual );         
    } 
    
    
    this._uniqueSystemId = SLx.Application.Current.get_UniqueSystemId();      
    this._visualElement = visual ; 
    this._id = visual.Name; 
    
    this._eventTokens = [] ; 
    this._attachedProperties = [] ; 
    this._margin = null ; 
    
    // Layout 
    this._supressInvalidateLayout = true;        
    this._isLayoutRegistered = false ; 
    this._sizeToParent = false;     
    this._sizeToContent = sizeToContent; 
    this._clipToBounds  = false ; 
    this._isArrangeInvalidated = true;  
    this._isMeasureInvalidated = true;  
    this._logicalParent = null ; 
    this._layoutInvalidatedListeners = [] ; 
    this._desiredSize = new SLx.Size ( -1,-1 ) ;
    this._horizontalAlignment = SLx.HorizontalAlignment.Left; 
    this._verticalAlignment = SLx.VerticalAlignment.Top; 
    
    
    this._children = new SLx.ElementCollection (  $delegate (this, this._validChildrenCallback ) , 
        $delegate (this, this._addCallback ) , $delegate (this, this._removeCallback ) , $delegate (this, this._isChildCallback ) );      
        
    // if  (this._sizeToContent ) 
        this._children.add_ChildAdded ( $delegate ( this, this._onChildAdded )) ; 
        
    if ( this._visualElement != null ) 
    { 
        this._addHandler ( this._visualElement , "Loaded" , $delegate ( this, this._onLoaded) );         
    }  
        
    this._supressInvalidateLayout = false;         
} 

SLx.Panel.prototype = 
{            
     _onLoaded : function ( sender, args ) 
    { 
        this._registerForLayout ( this ) ;         
    }, 
    
    _registerForLayout : function ( ) 
    {             
        SLx.Application.Current.get_layoutManager().register ( this ) ;         
    
    }, 


    
     get_hasChildren : function ( ) 
     { 
        return this._children.length > 0 ; 
     }, 
     
     get_hasContent : function () 
     { 
        return false; 
     }, 
    
    _onChildAdded : function (  item ) 
    { 
      //TODO: check that item is control? 
      if ( SLx.VisualTreeHelper.isControl ( item )) 
      { 
          if ( this._sizeToContent ) 
          { 
            item.add_layoutInvalidated ( $delegate ( this, this._onChildInvalidated )) ;  
            this.invalidateLayout();  
          }
          item.set_logicalParent ( this ); 
          
       }  
    }, 
    
    
    _onChildInvalidated : function ( item ) 
    { 
        if ( this._sizeToContent ) 
        { 
            this.invalidateLayout (); 
        } 
    }, 
    
    _addCallback : function (  item ) 
    {         
         
        var visual = SLx.VisualTreeHelper.getVisualFromItem ( item );         
        var ok = false; 
        if ( visual != null ) 
        { 
            ok = SLx.VisualTreeHelper.reParent ( visual , this._visualElement ); 
            
        } 
        return ok ; 
    }, 
    
    _removeCallback : function ( item ) 
    { 
        
        var visual = this._getVisualFromItem ( item ) ; 
        var ok = false; 
        if( visual != null ) 
        { 
            ok = this._visualElement.Children.remove ( visual ) ; 
        } 
        return ok ; 
        
    }, 
    
    _validChildrenCallback : function   ( item ) 
    { 
        return true  ; 
    }, 
    
    _isChildCallback : function ( item ) 
    { 
        var visual = this._getVisualFromItem ( item ) ; 
        var ok = false; 
                
        for ( var i = 0 ; i < this._visualElement.Children.Count ; i++ ) 
        { 
            var obj = this.visualElement.Children.GetItem ( i ); 
            if ( obj == visual ) 
            { 
                ok = true ; 
                break ; 
            } 
        } 
        return ok ; 
    },  
   
   
    measure : function SLx$Panel$measure (  constrainwidth , constrainheight )        
    { 
         throw new Error.notImplemented ("abstract method, you must override");         
    }, 
    
   
    set_background : function  ( brush ) 
    { 
       Sys.Debug.assert ( this._visualElement != null && this._visualElement.toString() == "Canvas"); 
       this._visualElement.Background = brush ; 
    }, 
    
    
    arrange : function SLx$Panel$arrange ( left, top, width , height ) 
    { 
        Sys.Debug.assert ( false, "this is an abstract method, you must override");                
    },
    
    
    get_children : function ( ) { return this._children ;  }, 
    
        
    invalidateLayout : function () 
    { 
        if (  this._supressInvalidateLayout ) 
            return ; 
            
            
        this._isMeasureInvalidated = true ; 
        this._isArrangeInvalidated = true ;         
        SLx.Application.Current.get_layoutManager().invalidate ( this );         
        
        if( !this._sizeToContent ) 
        { 
            for ( var i = 0 ; i < this._children.get_length() ; i++ ) 
            { 
                this._children.getItem(i).invalidateLayout();             
            } 
        } 
        
         this._fireInvalidateLayout () ; 
    }, 
     
      
    toString : function  () 
    { 
        return this._uniqueSystemId.toString ()  + "    " + Object.getTypeName(this) + "    " + this._id ; 
    }
} 

SLx.Panel.registerClass ( 'SLx.Panel', SLx.Control , SLx.ILayout ); 