<?xml version="1.0" encoding="utf-8"?>
<!--

Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" 
    alpha.disabledStates="0.5" blendMode="normal">

    <fx:Metadata>
    <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.TextInput")]
    ]]>
    </fx:Metadata> 
    
    <fx:Script fb:purpose="styling">
        <![CDATA[
        import mx.core.FlexVersion;
        
        private var paddingChanged:Boolean;
        
        
        /**
         *  @private
         */
        override protected function commitProperties():void
        {
            super.commitProperties();
            
            if (paddingChanged)
            {
                updatePadding();
                paddingChanged = false;
            }
        }
        
        
        /**
         *  @private
         */
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            if (getStyle("borderVisible") == true)
            {
                border.visible = true;
				borderGradient.visible = true;
                background.left = background.top = background.right = background.bottom = 1;
                textDisplay.left = textDisplay.top = textDisplay.right = textDisplay.bottom = 1;
                if (promptDisplay)
                {
                    promptDisplay.setLayoutBoundsSize(unscaledWidth - 2, unscaledHeight - 2);
                    promptDisplay.setLayoutBoundsPosition(1, 1);
                }
            }
            else
            {
                border.visible = false;
				borderGradient.visible = false;
                background.left = background.top = background.right = background.bottom = 0;
                textDisplay.left = textDisplay.top = textDisplay.right = textDisplay.bottom = 0;
                if (promptDisplay)
                {
                    promptDisplay.setLayoutBoundsSize(unscaledWidth, unscaledHeight);
                    promptDisplay.setLayoutBoundsPosition(0, 0);
                }
            }
            
            borderStroke.color = getStyle("borderColor");
            borderStroke.alpha = getStyle("borderAlpha");
            
            super.updateDisplayList(unscaledWidth, unscaledHeight);
        }

        /**
         *  @private
         */
        private function updatePadding():void
        {
            if (!textDisplay)
                return;
            
            // Push padding styles into the textDisplay
            var padding:Number;
            
            padding = getStyle("paddingLeft");
            if (textDisplay.getStyle("paddingLeft") != padding)
                textDisplay.setStyle("paddingLeft", padding);
            
            padding = getStyle("paddingTop");
            if (textDisplay.getStyle("paddingTop") != padding)
                textDisplay.setStyle("paddingTop", padding);
            
            padding = getStyle("paddingRight");
            if (textDisplay.getStyle("paddingRight") != padding)
                textDisplay.setStyle("paddingRight", padding);
            
            padding = getStyle("paddingBottom");
            if (textDisplay.getStyle("paddingBottom") != padding)
                textDisplay.setStyle("paddingBottom", padding);
            
            if (!promptDisplay)
                return;
            
            padding = getStyle("paddingLeft");
            if (promptDisplay.getStyle("paddingLeft") != padding)
                promptDisplay.setStyle("paddingLeft", padding);
            
            padding = getStyle("paddingTop");
            if (promptDisplay.getStyle("paddingTop") != padding)
                promptDisplay.setStyle("paddingTop", padding);
            
            padding = getStyle("paddingRight");
            if (promptDisplay.getStyle("paddingRight") != padding)
                promptDisplay.setStyle("paddingRight", padding);
            
            padding = getStyle("paddingBottom");
            if (promptDisplay.getStyle("paddingBottom") != padding)
                promptDisplay.setStyle("paddingBottom", padding);
        }
        
        /**
         *  @private
         */
        override public function styleChanged(styleProp:String):void
        {
            var allStyles:Boolean = !styleProp || styleProp == "styleName";

            super.styleChanged(styleProp);
            
            if (allStyles || styleProp.indexOf("padding") == 0)
            {
                paddingChanged = true;
                invalidateProperties();
            }
        }
        ]]>
    </fx:Script>
    
    <fx:Script>
        <![CDATA[
        /** 
         * @private 
         */     
        private static const focusExclusions:Array = ["textDisplay"];

        /**
         *  @private
         */
        override public function get focusSkinExclusions():Array { return focusExclusions;};
        ]]>
    </fx:Script>
    
    <s:states>
        <s:State name="normal"/>
        <s:State name="disabled" stateGroups="disabledStates"/>
        <s:State name="normalWithPrompt"/>
        <s:State name="disabledWithPrompt" stateGroups="disabledStates"/>
    </s:states>
    
    <!-- border --> 
    <!--- @private -->
    <s:Rect left="0" right="0" top="0" bottom="0" id="border"
			radiusX="2" radiusY="2">
        <s:stroke>     
            <!--- @private -->
            <s:SolidColorStroke id="borderStroke" weight="1" />
        </s:stroke>
    </s:Rect>

	<!-- border gradient -->
	<!--- @private -->
	<s:Rect left="0" right="0" top="0" bottom="0" id="borderGradient"
			radiusX="2" radiusY="2">
		<s:fill>
			<s:LinearGradient rotation="90">
				<s:GradientEntry color="0xffffff" alpha="0"/>
				<s:GradientEntry color="0xffffff" alpha="1"/>
			</s:LinearGradient>
		</s:fill>
	</s:Rect>
	
    <!-- fill -->
    <!--- Defines the appearance of the TextInput component's background. -->
    <s:Rect id="background" left="1" right="1" top="1" bottom="1"
			radiusX="1" radiusY="1">
        <s:fill>
            <!--- @private Defines the background fill color. -->
            <s:SolidColor id="bgFill" color="0xFFFFFF" />
        </s:fill>
    </s:Rect>
	
    <!-- text -->
    <!--- @copy spark.components.supportClasses.SkinnableTextBase#textDisplay -->
    <s:RichEditableText id="textDisplay"
              verticalAlign="middle"
              widthInChars="10"
              left="1" right="1" top="1" bottom="1" />
    <!--- Defines the Label that is used for prompt text. The includeInLayout property is false so the prompt text does not affect measurement. -->
    <s:Label id="promptDisplay" maxDisplayedLines="1"
                verticalAlign="middle"
                mouseEnabled="false" mouseChildren="false"
                includeIn="normalWithPrompt,disabledWithPrompt" 
                includeInLayout="false"
				fontFamily="openSansSemibold"
                />

</s:Skin>
