﻿///<reference path="MicrosoftAjax.debug.js" > 
///<reference path="shared.js" > 
///<reference path="control.js" > 


Type.registerNamespace("SLx");


SLx.Control = function( visual , xamlTemplate , templateParts ) 
{
    /// <summary>
    /// Baseclass for all controls 
    /// </summary>
    /// <param name="visual" type="UIElement">An Existing Visual to wrap</param>  
    /// <param name="xamlTemplate" type="string">XAML tempate for instantiation </param>  
    /// <param name="templateParts" type="object">Array w/ part mappings to xamltemplate</param>  
    
    
    // _uniqueSystemId  is for debug/ ref counting..     
    this._uniqueSystemId = SLx.Application.Current.get_UniqueSystemId();      
    
    Sys.Debug.assert ( visual != null || xamlTemplate != null ); 
    
   
       
    //Layout defaults 
    this._supressInvalidateLayout = true ; 
    this._isLayoutRegistered = false ; 
    this._sizeToParent = false;   
    this._sizeToContent = false; 
    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; 
    
    if ( visual != null ) 
    { 
        this._visualElement = visual ;               
    } 
    else if ( xamlTemplate != null && xamlTemplate != "" ) 
    { 
        //TODO: templated objects are always created in separate scope  
        this._visualElement = SLx.Application.Current.createElement ( xamlTemplate , true );     
        
        if ( templateParts == null ) 
        { 
             templateParts  = Object.getType(this).DefaultTemplate; 
        } 
    } 
    this._eventTokens = [] ;  
    this._attachedProperties = [] ;     
    
  
    this._bindParts ( templateParts );         
  
    Sys.Debug.assert ( this._visualElement != null || SLx.Error.NonVisualControl , "We should not have a control with out a visual" ); 
        
    
    this._id = this._visualElement.Name;
    this._visible = this._visualElement.Visibility.toLowerCase() == "visible" ;  
  
    this._enabled = true ; 
         
    this._parseTags ()  ; 
     
    
    this._supressInvalidateLayout = false; 
    
    
    // TODO: this is a hack... 
    // The problem is for templateParts, elements are already Loaded 
    /* 
    if (   ( visual == null && templateParts != null && this._visualElement != null  && xamlTemplate == null ) || 
            visual != null 
       ) 
    { 
        this._onLoaded ( ) ; 
    } 
    else 
    */ 
        this._visualElement.addEventListener ( "Loaded" , $delegate ( this, this._onLoaded) );   
}


SLx.Control.prototype = 
{
// Layout Begin 
    
    
    _registerForLayout :  function SLx$Control$_registerForLayout( ) 
    { 
    /// <summary>
    /// registers control in Layout Sub System 
    /// </summary>                
        if ( !this._isLayoutRegistered ) 
        { 
            SLx.Application.Current.get_layoutManager().register ( this ) ;                     
            if ( this._logicalParent != null ) 
            { 
                SLx.Application.Current.get_layoutManager().updateLogicalParent ( this, this._logicalParent  );                           
            } 
            this._isLayoutRegistered = true ; 
        }
    }, 
    
    get_isMeasureDirty : function ( )  
    {  
        return this._isMeasureInvalidated ;  
    }, 
    
    get_isArrangeDirty : function () 
    { 
        return this._isArrangeInvalided ; 
    }, 
    
    get_isLayoutDirty : function ()
    { 
        return this.get_isMeasureDirty() || this.get_isArrangeDirty() ;  
    }, 
    
    /// <summary>
    /// Notify layout invalidation to any one subscribed explicitly.. 
    /// </summary>    
    _fireInvalidateLayout : function () 
    { 
        this._fireEvent  ( this._layoutInvalidatedListeners , null );               
    }, 
    
    _fireEvent : function ( subscriberslist ,   args ) 
    { 
        for ( var i = 0, len=  subscriberslist.length ; i < len ; i++ ) 
        { 
            subscriberslist[i] ( this , args ); 
        } 
    }, 
    
    _removeHandler : function ( eventlist,  handler ) 
    { 
    
      for ( var i = 0 , len = eventlist.length ; i < len ; i++ ) 
        { 
            if ( eventlist[i] === handler ) 
            { 
                Array.remove (eventlist, handler ); 
            } 
        } 
    }, 
    
    suspendLayout : function SLx$Control$suspendLayout () 
    { 
        this._supressInvalidateLayout = true ;
    }, 
    
    resumeLayour : function  SLx$Control$resumeLayout () 
    { 
        this._supressInvalidateLayout = false; 
    },  
   
    invalidateLayout :  function SLx$Control$invalidateLayout () 
    {
      /// <summary>
      /// Invalidates layout by setting right vars (for cache) and notifying layout manager; also explicitly notifies listeners
      /// </summary>     
        if ( ! this._supressInvalidateLayout ) 
        { 
            this._isMeasureInvalidated = true ; 
            this._isArrangeInvalidated = true ;         
            SLx.Application.Current.get_layoutManager().invalidate ( this );         
            this._fireInvalidateLayout () ; 
        } 
    }, 
    
   
    updateLayout : function SLx$Control$updateLayout (  ) 
    {    
    /// <summary>
    /// measures and arranges a control. Called by layout manager when layout has been invalidated ...   can be called explictly too (parents call it on children) 
    /// </summary>      
        
        
        if ( SLx.VisualTreeHelper.NeedsAlignment( this ) && SLx.VisualTreeHelper.isContainer (  this.get_logicalParent () )) 
        { 
            this.get_logicalParent().updateLayout(); 
        } 
        else 
        { 
            this.measure ( this.get_width(), this.get_height () ) ;             
            var size = this.get_desiredSize (); 
            this.arrange (  this.get_left() , this.get_top(), size.get_width(), size.get_height () ) ; 
        } 
        /* 
        
        if ( this._sizeToParent && 
                ( this._verticalAlignment == SLx.VerticalAlignment.Stretch || 
                 this._horizontalAlignment == SLx.HorizontalAlignment.Stretch )                                                
            ) 
           { 
                Sys.Debug.assert ( this._isArrangeInvalidated  || SLx.Warning.UpdateLayoutSizesToParent , "This scenario should be handled by the parent.. if the arrange is invalid it means it was not"); 
                return ; 
           }             
        else 
            this.measure (  this.get_width(), this.get_height () ) ;         
        
        
        var size = this.get_desiredSize (); 
        this.arrange (  this.get_left() , this.get_top(), size.get_width(), size.get_height () ) ; 
        */  
    }, 
    
    _calculateDesiredSizeonSizeToParent : function ( availableWidth, availableHeight ) 
    { 
        // Margins are done by the parent in layout .. 
        if ( this._horizontalAlignment != SLx.HorizontalAlignment.Stretch ) 
        {                 
            this._desiredSize.Width = this.get_width()  ; 
        } 
        else 
        { 
            Sys.Debug.assert( availableWidth <= ( Number.MAX_VALUE - 1024) , "stretching on panel that sizes to content" ) ; 
            this._desiredSize.Width = availableWidth  ; 
        }
        
        if ( this._verticalAlignment != SLx.VerticalAlignment.Stretch ) 
        { 
        
            this._desiredSize.Height  = this.get_height()  ; 
        } 
        else 
        { 
            Sys.Debug.assert( availableWidth <= ( Number.MAX_VALUE - 1024) , "stretching on panel that sizes to content") ; 
            this._desiredSize.Height = availableHeight; 
        }        
        return this._desiredSize ;                      
    }, 
    
    
    isCacheValueCloseEnough : function  (  newvalue , knownvalues, allowedrange  ) 
    { 
        if ( allowedrange == undefined ) 
            allowedrange = 1; 
            
        for ( var i = 0; i < knownvalues.length ; i++ ) 
        { 
            if ( Math.abs ( knownvalues[i] - newvalue ) < allowedrange ) 
                return true ; 
        } 
        return false; 
    }, 
    
    measure : function ( availableWidth , availableHeight ) 
    {  
    /// <summary>
    /// measures the control to figure out its desired size
    /// </summary>  
    /// <param name="availableWidth" type="Number" > Available Width </param> 
    /// <param name="availableHeight" type="Number" > Available Height </param> 
       
        if ( ! this._isMeasureInvalidated && SLx.Application.Current.get_cacheLayout() ) 
        { 
            Sys.Debug.assert ( this._lastWidthMeasure  == availableWidth && this._lastHeightMeasure == availableHeight , "temp for debug" );   
            Sys.Debug.trace ( this.toString()  + "cached measure" ) ;
            return ;  
        } 
        
        // Debug stuff to be removed... 
        this._lastWidthMeasure  = availableWidth ; 
        this._lastHeightMeasure = availableHeight ;   
        
        
        if ( this._sizeToParent ) 
        { 
            this._desiredSize = this._calculateDesiredSizeonSizeToParent ( availableWidth, availableHeight); 
            
        } 
        else if ( this._sizeToContent ) 
        {  
            if ( this.get_hasContent () ) 
            { 
                this._content.measure ( availableWidth, availableHeight );                 
                this._desiredSize.Width = this._content.get_desiredSize().Width ; 
                this._desiredSize.Height = this._content.get_desiredSize().Height ; 
                            
            } 
            else 
            { 
                Sys.Debug.assert( SLx.Error.AllControlsSizeToContent, "This is not an error, but by design controls do not sizeToContent; to do that override measure (like Panels and ContentPresenter do) " );     
                this._desiredSize.Width  = this.get_width () ; 
                this._desiredSize.Height  = this.get_height () ;
            } 
        } 
        else 
        {         
            this._desiredSize.Width  = this.get_width () ; 
            this._desiredSize.Height  = this.get_height () ;             
        }         
        
        this._isMeasureInvalidated = false ;                
    }, 
    

     
    get_desiredSize : function SLx$Control$get_desiredSize ( ) 
    {
    /// <summary>
    /// returns desired Size; this property is calculated during measure and 'cached' 
    /// </summary>         
        if ( !SLx.VisualTreeHelper.isValidSize (  this._desiredSize )) 
            this._isMeasureInvalidated  = true ; 
                    
        if ( this._isMeasureInvalidated ) 
        {             
            this.measure( this.get_width() , this.get_height() );             
            
            // Getting the desiredSize is NOT a measure.. 
             this._isMeasureInvalidated  = true ; 
             Sys.Debug.assert ( ( this._desiredSize.Width != -1 && this._desiredSize.Height!= -1 )&& 
                                ( this._desiredSize.Width != undefined && this._desiredSize.Height!= undefined )   , "this should not happen"); 
        } 
        
        return this._desiredSize ; 
    },
    
    
   
    arrange : function (left, top, width, height ) 
    {
    /// <summary>
    /// arranges the control at the left,top offset and sizes it to width & height 
    /// </summary> 
    /// <param name="left" type="Number" > left </param> 
    /// <param name="top" type="Number" > top </param> 
    /// <param name="width" type="Number" > width </param> 
    /// <param name="height " type="Number" > height </param> 
                
    
        // these are meant for debug...  but might stay to make sure we never miss an arrange.. 
        var moved =   (  this._visualElement["Canvas.Left"]   != left || this._visualElement["Canvas.Top"] != top ) ; 
        var sized =  ( this._visualElement["width"] != width  || this._visualElement["height"] != height  );            
         Sys.Debug.assert ( sized == false || SLx.Warning.ArrangeResizes , "Does this imply a relationship is missing?" ); 
         
         if ( this._isArrangeInvalidated  || sized || moved || (!SLx.Application.Current.get_cacheLayout()) ) 
         {  
             Sys.Debug.assert ( this._isMeasureInvalidated == false ) ;         
             this._visualElement["Canvas.Left"] = left ;
             this._visualElement["Canvas.Top"]  = top; 
             this._visualElement["width"] = width ; 
             this._visualElement["height"] = height  ;                               
         } 
         else 
         {  
            Sys.Debug.trace ( this.toString  ()  + "cached arrange" ) ;            
         }  
         this._isArrangeInvalidated = false ;         
    }, 
    
    // Layout End 

    // attached properties are good for extensibility; it is a decoupled way to extend the control. 
    
    setAttachedProperty  : function ( key, value ) 
    {       
        this._attachedProperties[key] = value ; 
    }, 
    

    getAttachedProperty  : function ( key  ) 
    { 
        return this._attachedProperties[key] ; 
    }, 
        
        
    // Properties Begin  
    set_Tags : function ( value ) 
    { 
        /// <summary>
        /// sets Tags for the main visualElement; it parses in the set 
        /// <param name="value" type="string" > string representing new tags </param> 
        /// </summary>      
        Sys.Debug.assert ( this._visualElement != null ) ; 
        this._visualElement.Tag = value ; 
        this._parseTags (); 
    }, 
    
    get_Tags : function  ( ) 
    { 
        Sys.Debug.assert ( false , "This is a temporary assert since Tags should not be used for now " ); 
        return this._visualElement.Tag ; 
    } , 
    
    
    set_clipToBounds : function ( value ) 
    { 
         /// <summary>
    /// set clipToBounts ( true = clip, false = no clip ) 
    /// <param name="value" type="boolean" > value </param>      
    /// </summary>      
        this._clipToBounds=  value; 
        
        if ( value ) 
        { 
            this._clip(); 
        } 
        else 
        { 
            this._visualElement.Clip = null ; 
        } 
    }, 
    
    get_clipToBounds : function ( ) 
    {  
        return this._clipToBounds ; 
    }, 
    
     get_logicalParent : function () 
    { 
        return this._logicalParent ; 
    }, 
    
    set_logicalParent : function ( value ) 
    { 
        this._logicalParent = value ; 
        if (this._isLayoutRegistered ) 
            SLx.Application.Current.get_layoutManager().updateLogicalParent ( this, value );               
        
    },   
    
    set_sizeToParent : function ( value ) 
    { 
        var oldvalue = this._sizeToParent ;         
        this._sizeToParent = value ; 
        if ( oldvalue != value ) 
            this.invalidateLayout(); 
    }, 
    
    get_sizeToParent : function () 
    {         
        return this._sizeToParent ; 
    }, 
    
    
    set_sizeToContent: function ( value ) 
    { 
        /// <summary>
        /// sizeToContent means the control will size to the visual or content (if it is a control) it contains
        /// <param name="value" type="Boolean" > value </param> 
        /// </summary>              
        if ( this._sizeToContent != value ) 
        {  
             this._sizeToContent = value ; 
            this.invalidateLayout(); 
        } 
    }, 
    
    get_sizeToContent : function () 
    { 
        return this._sizeToContent ; 
    }, 



    set_margin : function ( value ) 
    { 
        if ( Object.getTypeName(value).toLowerCase() == "string" )
        {             
            var values = value.split ( "|") ; 
            var left =  parseFloat ( values[0] || 0) ; 
            var top =  parseFloat ( values[1] || 0 ) ; 
            var right = parseFloat  ( values[2] || 0 ) ; 
            var bottom = parseFloat ( values[3] || 0 ) ; 
            value = new SLx.Thickness ( left, top, right, bottom ); 
        }
        // TODO: should this be cloned. .         
        this._margin = value ; 
        this.invalidateLayout () ; 
    } , 
    
    get_margin : function ( ) 
    { 
        if ( this._margin == null ) 
            this._margin = new SLx.Thickness ( 0,0,0,0 ); 
        return this._margin ; 
    },  
   
    toString : function  () 
    { 
        return this._uniqueSystemId.toString ()  + "    " + Object.getTypeName(this) + "    " + this._id ; 
    } , 
    
    get_parent: function()
    { 
        return this._visualElement.getParent();
    },
    
      
    get_visual: function() { return this._visualElement; },
  
    
    get_name : function ()  { return this._id ; } , 
    
   
    get_visible: function() { return this._visualElement.Visibility == SLx.Visibility.Visible ; },
    
    set_visible: function(value)
    {
        Sys.Debug.assert( value != null ) ; 
        
        if( value != this._visible)
        { 
            this._visible = value ;
        
            if(this._visible)
            {
                this._visualElement.visibility = SLx.Visibility.Visible ;
                this._playAnimation("_Show");
                return;
            }
        
            if(!this._find(this._id + "_Hide"))
            {
                this._visualElement.visibility = SLx.Visibility.Collapsed ;
                return;
            }

            if(!this._hideListener)
            {
                this._hideListener = this._find(this._id + "_Hide").addEventListener("Completed", Function.createDelegate(this, this._onHideComplete));
            }

            this._playAnimation("_Hide");
        }
    },
    
    set_width: function(width)
    {
        if ( this._visualElement.width != width) 
        { 
            this._visualElement.width = width; 
            this.invalidateLayout();
         }
    },
    
    set_size : function ( width , height ) 
    { 
        this._supressInvalidateLayout  = true ; 
        this.set_width ( width ); 
        this._supressInvalidateLayout  = false ; 
        this.set_height ( height ) ; 
    }, 
    
    move : function ( left, top ) 
    { 
        this._supressInvalidateLayout  = true ; 
        this.set_left( left ); 
        this._supressInvalidateLayout  = false ; 
        this.set_top  ( top ) ; 
    }, 
    
    
    set_isEnabled : function ( value ) 
    { 
        if ( this._enabled != value ) 
        { 
            this._enabled = value; 
            this._playAnimation( value ? "_Enabled" : "_Disabled" ); 
        } 
    },  
    
    
    get_isEnabled : function ( ) 
    { 
        return this._enabled; 
    }, 
    
   
     
    get_width: function() { return this._visualElement.width; },
    
    set_height: function(height) 
    { 
        if ( this._visualElement.height != height ) 
        { 
            this._visualElement.height = height; 
            this.invalidateLayout(); 
        }
    },
    
    get_height: function() { return this._visualElement.height; },
    
    set_left: function(left) { this._visualElement["Canvas.Left"] =  left;  },
    get_left: function() { return this._visualElement["Canvas.Left"]; },
    
    set_top: function(top) { this._visualElement["Canvas.Top"] = top; },
    get_top: function() { return this._visualElement["Canvas.Top"]; },
   
    set_horizontalAlignment: function ( value ) 
    {  
        if ( this._horizontalAlignment != value ) 
        { 
            this._horizontalAlignment = value ; 
            this.invalidateLayout ();             
        } 
    }, 
    
    get_horizontalAlignment : function ()  { return this._horizontalAlignment; } , 
    
    
     set_verticalAlignment: function ( value ) 
    { 
        var oldvalue = this._verticalAlignment; 
        ; 
        if ( this._verticalAlignment != value ) 
        { 
            this._verticalAlignment = value 
            this.invalidateLayout ();             
        } 
    }, 
    
    get_verticalAlignment : function ()  { return this._verticalAlignment ; } , 
    
    
   
     get_hasChildren : function ( ) 
     { 
        return false; 
     }, 
     
     get_hasContent : function () 
     { 
        return false; 
     }, 
    
    //Properties End 
   
   
    //methods begin     
    _parseTags :  function ( ) 
    { 
        /// <summary>Parses Tag property of _visualElement, setting values to existing members in the class </summary>       
        if ( this._visualElement.Tag != null  && this._visualElement.Tag != "" ) 
        { 
             var props = this._visualElement.Tag.split ( "," ) ;              
             for ( var i = 0 ; i < props.length  ; i++ ) 
             { 
                var values = props[i].split ( ":" ); 
                if ( values.length == 2 ) 
                { 
                    var trimmed=  values[0].trim (); 
                    switch ( trimmed ) 
                    { 
                        //Here are the properties that are straight sets.. 
                        case "hAlign" : 
                        case "_horizontalAlignment" :                            
                        case "vAlign" : 
                        case "_verticalAlignment" : 
                        case "_sizeToParent" :                                                      
                        case "_sizeToContent" :      
                            try
                            {                         
                                this[ values[0]] = eval  ( "(" + values[1] + ")" );                             
                                
                            }
                            catch(ex) 
                            { 
                                Sys.Debug.assert ( SLx.Error.AllowEvalFailures ); 
                            }  
                         break; 
                       case "_margin" : 
                            this.set_margin ( values[1] ); 
                            break; 
                        case "Dock" : 
                            this.setAttachedProperty ( values[0], eval  ("(" + values[1] + ")" )); 
                            break; 
                        default: 
                            Sys.Debug.assert ( SLx.Warning.AllowUnknownAttachedProperties   , "this is not an error, it is here for catching mistakes and typos") 
                            this.setAttachedProperty ( values[0], values[1] ); 
                            break; 
                                                                                                                         
                    } 
                }                
            } 
            // most of these tags invalidate Layout so I dumbly invalidate here
            this.invalidateLayout ();            
        } 
    }, 
    
    
 
    _bindParts : function SLx$Control$_bindParts ( templateParts ) 
    { 
        ///<summary> binds the parts of a JS template to existing visual elements </summary>    
        
        
        //ContentPresenter has no parts but it is a Control
        if ( templateParts == null  ) 
            return ;             
            
        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 ( item.type == "element" ) 
            { 
                this[item.ref] = element ;                             
            } 
            else if ( item.type == "ContentPresenter") 
            { 
                var cp = new SLx.ContentPresenter ( element ) ;                 
                //TODO: is there a scenario where there is a differnet logical parent??  How to handle ? 
                cp.set_logicalParent ( this ); 
                this[item.ref] = cp ; 
            }             
        } 
    }, 
    
    
   
    
    _onLoaded : function ( sender, args ) 
    { 
        ///<summary>Fires when UIElement is Loaded. Registers triggers and Layout  </summary> 
        this._registerForLayout ( this ) ;   
        this._wireTriggers ();         
    }, 
    
    // methods end 
   
  
    
    _onHideComplete: function(sender, eventArgs)
    {
        this._visualElement.visibility = "Collapsed";
        
    },

    _wireTriggers : function ( )
    { 
       this.add_MouseEnter ( $delegate ( this, this._onMouseEnter )); 
       this.add_MouseLeave ( $delegate ( this, this._onMouseLeave ));     
    }, 
    
    
    
    _onMouseEnter : function ( sender, args ) 
    { 
        if ( this.get_isEnabled () ) 
            this._playAnimation("_MouseEnter");
    }, 
    
    _onMouseLeave : function ( sender, args ) 
    {      
        if ( this.get_isEnabled () )     
            this._playAnimation("_MouseLeave"); 
    },
    
  
    
    _addHandler: function( element , eventName, handler )
    {
        if ( eventName == null || eventName == "" ) 
            return; 
            
        Sys.Debug.assert ( Object.getType( handler ).getName() == "Function" ); 
                        
        var token = element.addEventListener ( eventName , handler );                 
        Array.add ( this._eventTokens ,  { Name: eventName, Handler: handler, Token: token , Element: element }) ; 
                
    },
    
    _removeHandler: function(eventType, handler)
    {
        for ( var i = 0 , len = this._eventTokens.length; i < len ; i++ ) 
        { 
            var evnt = this._eventTokens[i]; 
            if (eventType == evnt.Name  && handler == evnt.Handler ) 
            { 
                evnt.Element.removeEventListener ( evnt.Name, evnt.Token );   
                Array.remove ( this._eventTokens, evnt ); 
                break; 
            } 
        } 
    },

    dispose: function()
    {
        if(this._eventTokens)
        {
            for(var i = 0, len = this._eventTokens.length; i < len; i++)
            {
                var evnt  = this._eventTokens[i];
                evnt.Element.removeEventListener ( evnt.Name, evnt.Token ); 
                this._eventTokens[i] = null;
            }
            Array.clear ( this._eventTokens ); 
            this._eventTokens = null;
        }

        if(this._visualElements)
        {
            for (i = 0, l = this._visualElements.length; i < l; i++)
            {
                this._visualElements[i].dispose();
            }
            this._visualElements = null;
        }
       
        SLx.Control.callBaseMethod(this, "dispose");
    },
    
  
     
    _playAnimation: function(name)
    {
        var anim = this._find( this._id + name);
        if(anim)
        {
            anim.begin();
            return anim;
        }
        return null;
    },
        
    
    _find: function(name)
    {
        if(!this._findCache)
        {
            this._findCache = {};
        }
        if(!this._findCache[name])
        {
            var el = this._visualElement.findName(name);
            if(!el)
            {
                return null;
            }
            this._findCache[name] = el;
        }
        return this._findCache[name];
    },

    _clip : function ( ) 
    {     
        var xaml = "<RectangleGeometry Rect='0,0," + this.get_width() + "," + this.get_height()  + "' />" ; 
        this._visualElement.Clip = this._visualElement.getHost().content.createFromXaml ( xaml );              
    }, 
    
   //methods end 
    

    //Events Begin 
    add_layoutInvalidated : function  ( callback ) 
    { 
        Sys.Debug.assert( callback != null ); 
        Array.add ( this._layoutInvalidatedListeners , callback ); 
        
    }, 
    
    remove_layoutInvalidated : function  ( callback ) 
    { 
        Array.remove ( this._layoutInvalidatedListeners, callback );         
    }, 
    
    add_MouseLeftButtonDown: function(handler) { this._addHandler( this._visualElement, "MouseLeftButtonDown", handler); },        
    remove_MouseLeftButtonDown: function(handler) { this._removeHandler("MouseLeftButtonDown", handler); },

    add_MouseLeftButtonUp: function(handler) { this._addHandler( this._visualElement, "MouseLeftButtonUp", handler); },
    remove_MouseLeftButtonUp: function(handler) { this._removeHandler("MouseLeftButtonUp", handler); },
    
    add_MouseEnter: function(handler) { this._addHandler( this._visualElement, "MouseEnter", handler); },
    remove_MouseEnter: function(handler) { this._removeHandler("MouseEnter", handler); },
    
    add_MouseLeave: function(handler) { this._addHandler( this._visualElement, "MouseLeave", handler); },
    remove_MouseLeave: function(handler) { this._removeHandler("MouseLeave", handler); },
    
    add_MouseMove: function(handler) { this._addHandler( this._visualElement, "MouseMove", handler); },
    remove_MouseMove: function(handler) { this._removeHandler("MouseMove", handler); },
    
    add_GotFocus: function(handler) { this._addHandler( this._visualElement, "GotFocus", handler); },
    remove_GotFocus: function(handler) { this._removeHandler("GotFocus", handler); },
    
    add_LostFocus: function(handler) { this._addHandler( this._visualElement, "LostFocus", handler); },
    remove_LostFocus: function(handler) { this._removeHandler("LostFocus", handler); },
    
    add_KeyDown: function(handler) { this._addHandler( this._visualElement, "KeyDown", handler); },
    remove_KeyDown: function(handler) { this._removeHandler("KeyDown", handler); },
    
    add_KeyUp: function(handler) { this._addHandler( this._visualElement, "KeyUp", handler); },
    remove_KeyUp: function(handler) { this._removeHandler("KeyUp", handler); },
    
    add_Loaded: function(handler) { this._addHandler( this._visualElement, "Loaded", handler); },
    remove_Loaded: function(handler) { this._removeHandler("Loaded", handler); } 
    
}

SLx.Control.registerClass('SLx.Control', null, Sys.IDisposable, SLx.ILayout); 

