You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by gr...@apache.org on 2026/03/25 05:30:05 UTC

(royale-asjs) 01/02: Numerous updates and tweaks

This is an automated email from the ASF dual-hosted git repository.

gregdove pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git

commit 5512fb2e1f1ddcd26320dffa4fe6f41d88e1cc30
Author: greg-dove <gr...@gmail.com>
AuthorDate: Wed Mar 25 18:26:44 2026 +1300

    Numerous updates and tweaks
---
 .../royale/org/apache/royale/style/CheckBox.as     |  5 ++
 .../main/royale/org/apache/royale/style/Divider.as | 17 +++++-
 .../royale/org/apache/royale/style/IStyleSkin.as   |  2 +
 .../royale/org/apache/royale/style/IStyleUIBase.as |  5 +-
 .../royale/org/apache/royale/style/StyleSkin.as    |  4 ++
 .../royale/org/apache/royale/style/StyleUIBase.as  | 22 ++++++-
 .../apache/royale/style/colors/ThemeColorSet.as    |  4 +-
 .../org/apache/royale/style/skins/CheckBoxSkin.as  | 48 ++++++++++++---
 .../org/apache/royale/style/skins/DividerSkin.as   | 37 ++++++++++--
 .../royale/style/stylebeads/ILeafStyleBead.as      |  1 +
 .../apache/royale/style/stylebeads/IStyleBead.as   |  1 +
 .../royale/style/stylebeads/StyleBeadBase.as       | 11 +++-
 .../royale/style/stylebeads/states/HasState.as     | 70 +++++++++++++++++++++-
 .../royale/style/stylebeads/states/HoverState.as   |  3 +-
 .../style/stylebeads/states/LeafDecorator.as       | 33 +++++++++-
 .../royale/style/stylebeads/states/NotState.as     | 70 ++++++++++++++++++++--
 16 files changed, 301 insertions(+), 32 deletions(-)

diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/CheckBox.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/CheckBox.as
index 830c292d14..ff5656ab35 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/CheckBox.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/CheckBox.as
@@ -18,6 +18,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.style
 {
+	import org.apache.royale.style.stylebeads.states.HasState;
 	
 	COMPILE::JS{
 		import org.apache.royale.core.WrappedHTMLElement;
@@ -315,6 +316,10 @@ package org.apache.royale.style
 		{
 			_quiet = value;
 		}
+		override public function getChildInputType():String
+		{
+			return HasState.CHECKBOX_INPUT;
+		}
 	}
 }
 
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Divider.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Divider.as
index df448215eb..e8d142f458 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Divider.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Divider.as
@@ -18,6 +18,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.style
 {
+	import org.apache.royale.core.IBead;
 	import org.apache.royale.core.IMXMLDocument;
 	import org.apache.royale.core.ValuesManager;
 	import org.apache.royale.events.Event;
@@ -29,6 +30,7 @@ package org.apache.royale.style
 		public function Divider()
 		{
 			super();
+			unit = 'px';
 		}
 		override protected function requiresView():Boolean{
 			return false;
@@ -40,6 +42,16 @@ package org.apache.royale.style
 			return false;
 		}*/
 		
+		private var _edgePadding:Number = 0;
+		public function get edgePadding():uint{
+			return _edgePadding;
+		}
+		public function set edgePadding(value:uint):void{
+			if (_edgePadding != value) {
+				_edgePadding = value;
+				if (skin) skin.update();
+			}
+		}
 		
 		private var _vertical:Boolean;
 		
@@ -54,9 +66,10 @@ package org.apache.royale.style
 		public function set vertical(value:Boolean):void
 		{
 			if(value != !!_vertical){
-				
+				_vertical = value;
+				if (skin) skin.update();
 			}
-			_vertical = value;
+			
 		}
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/IStyleSkin.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/IStyleSkin.as
index 82c148b4aa..ada8fc846b 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/IStyleSkin.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/IStyleSkin.as
@@ -23,5 +23,7 @@ package org.apache.royale.style
 	public interface IStyleSkin extends IBead
 	{
 		function get styles():Array;
+		
+		function update():void;
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/IStyleUIBase.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/IStyleUIBase.as
index 4e7350a155..ffcb2f1b67 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/IStyleUIBase.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/IStyleUIBase.as
@@ -40,6 +40,9 @@ package org.apache.royale.style
 		function set unit(value:String):void;
 		function get size():String;
 		function set size(value:String):void;
-
+		/**
+		 * support for component classes that wrap a native input element, useful in skins for creating Has states
+		 */
+		function getChildInputType():String;
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/StyleSkin.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/StyleSkin.as
index 51d46fa2a5..ceb79ef980 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/StyleSkin.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/StyleSkin.as
@@ -76,5 +76,9 @@ package org.apache.royale.style
 			var pixelValue:Number = value;
 			return CSSUnit.convert(pixelValue, CSSUnit.PX, unit) + unit;
 		}
+		
+		public function update():void{
+			
+		}
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/StyleUIBase.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/StyleUIBase.as
index 4084447a8f..4f0f2f27b5 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/StyleUIBase.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/StyleUIBase.as
@@ -172,11 +172,19 @@ package org.apache.royale.style
 			styleBeads = null;
 			_stylesLoaded = true;
 			if(!_skin)
-				_skin = loadBeadFromValuesManager(IStyleSkin, "iStyleSkin", this) as IStyleSkin;				
+				_skin = loadBeadFromValuesManager(IStyleSkin, "iStyleSkin", this) as IStyleSkin;
+			else {
+				COMPILE::JS{
+					if (!_beads || _beads.indexOf(_skin) == -1) addBead(_skin);
+				}
+				COMPILE::SWF{
+					//it seems that _beads is protected in js and private in swf.... see above
+					addBead(_skin);
+				}
+			}
 			
 			if(_skin)
 			{
-				addBead(_skin);
 				applySkin();
 			}
 			refreshSuspended = false;
@@ -431,6 +439,16 @@ package org.apache.royale.style
 				removeAttribute("tabindex");
 			}
 		}
+		
+		/**
+		 * for components that wrap a native input element, this should return the type of the element.
+		 * this can be useful in skinning.
+		 * Null if not applicable
+		 * @return
+		 */
+		public function getChildInputType():String{
+			return null;
+		}
 
 		/**
 		 * Returns the tag name to use for this component.
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/colors/ThemeColorSet.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/colors/ThemeColorSet.as
index 467bda9287..76480f9496 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/colors/ThemeColorSet.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/colors/ThemeColorSet.as
@@ -104,7 +104,7 @@ package org.apache.royale.style.colors
 			const lookupVal:String = getThemeBaseColor(key);
 			assert(!ColorSwatch.isExceptionValue(lookupVal), 'no swatch or variation for '+key+":"+lookupVal);
 			var specifier:String = lookupVal + "-" + shade + '/' + opacity;
-			trace(key,specifier);
+			//trace(key,specifier);
 			var lookupKey:String = key +':'+ specifier;
 			var swatch:ColorSwatch;
 			var swatchStoreMap:Object;
@@ -131,7 +131,7 @@ package org.apache.royale.style.colors
 					swatchStoreMap.light = swatch;
 				}
 			}
-			trace(swatch);
+			//trace(swatch);
 			return swatch;
 		}
 		
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/CheckBoxSkin.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/CheckBoxSkin.as
index eb0faa8eaa..f5d04f16d3 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/CheckBoxSkin.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/CheckBoxSkin.as
@@ -33,12 +33,16 @@ package org.apache.royale.style.skins
 	import org.apache.royale.style.stylebeads.flexgrid.RowGap;
 	import org.apache.royale.style.stylebeads.interact.UserSelect;
 	import org.apache.royale.style.stylebeads.states.DisabledState;
+	import org.apache.royale.style.stylebeads.states.HasState;
 	import org.apache.royale.style.stylebeads.flexgrid.GridColumn;
 	import org.apache.royale.style.stylebeads.flexgrid.GridColumnStart;
 	import org.apache.royale.style.stylebeads.flexgrid.GridRowStart;
 	import org.apache.royale.style.stylebeads.sizing.HeightStyle;
 	import org.apache.royale.style.stylebeads.sizing.WidthStyle;
 	import org.apache.royale.style.stylebeads.border.BorderRadius;
+	import org.apache.royale.style.stylebeads.states.LeafDecorator;
+	import org.apache.royale.style.stylebeads.states.NotState;
+	import org.apache.royale.style.stylebeads.states.HoverState;
 	import org.apache.royale.style.util.ThemeManager;
 	import org.apache.royale.style.stylebeads.border.BorderWidth;
 	import org.apache.royale.style.stylebeads.border.BorderColor;
@@ -85,21 +89,49 @@ package org.apache.royale.style.skins
 			var size:Number = 16 * getMultiplier();
 			var box:String = computeSize(size * 1.25, host.unit);
 			var gap:String = computeSize(size * 0.75, host.unit);
-			var disabledStyle:DisabledState = new DisabledState();
-			disabledStyle.styles = [
-				//@todo: observed that this disabled style seems not to be working ('pointer' stays active):
-				new Cursor("auto")
-			];
+			
+			
+			var nativeInput:String = host.getChildInputType();
+			
+			//active cursor options, both currently working at time of testing:
+			//1. using NotState - 
+			// :not(:has(input[type="checkbox"]:disabled):hover {cursor:pointer} 
+			/*var disabledCondition:LeafDecorator = new HasState(nativeInput, [new DisabledState()]);
+			var activeCursor:LeafDecorator = new NotState(disabledCondition, [
+				new HoverState([
+					new Cursor("pointer")
+				])
+			]);
+			_styles = [
+				new Display("inline-grid"),
+				new GridTemplateColumns(box + " auto"),
+				new AlignItems("center"),
+				new ColumnGap(gap),
+				new UserSelect("none"),
+				new Cursor("auto"),
+				activeCursor
+			];*/
+			
+			//using has - 
+			// :has(input[type="checkbox"]:disabled) {
+			//    cursor: auto;
+			//}
+			var disabledState:LeafDecorator = new HasState(nativeInput, [
+				new DisabledState([
+					new Cursor("auto")
+				])
+			]);
 			_styles = [
 				new Display("inline-grid"),
-				new Cursor("pointer"),
 				new GridTemplateColumns(box + " auto"),
 				new AlignItems("center"),
 				new ColumnGap(gap),
 				new UserSelect("none"),
-				disabledStyle
+				new Cursor("pointer"),
+				disabledState
 			];
-			host.setStyles(_styles);
+			
+			host.setStyles(_styles, true);
 		}
 		private function getMultiplier():Number
 		{
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/DividerSkin.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/DividerSkin.as
index 38b072db63..ad9a5e1543 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/DividerSkin.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/DividerSkin.as
@@ -20,6 +20,8 @@ package org.apache.royale.style.skins
 {
 	import org.apache.royale.style.StyleSkin;
 	import org.apache.royale.core.IStrand;
+	import org.apache.royale.style.stylebeads.background.BackgroundClip;
+	import org.apache.royale.style.stylebeads.border.Border;
 	import org.apache.royale.style.stylebeads.sizing.HeightStyle;
 	import org.apache.royale.style.stylebeads.sizing.WidthStyle;
 	import org.apache.royale.style.stylebeads.border.BorderRadius;
@@ -50,26 +52,53 @@ package org.apache.royale.style.skins
 			processStyles();
 		}
 		
+		override public function update():void{
+			processStyles()
+		}
+		
 		private function processStyles():void{
 			var host:Divider = getHost();
 			var hostSize:String = getHost().size;
 			var size:Number =  getAppliedSize(hostSize);
 			var colorAdjust:Number = getShading(hostSize);
-			var appliedSize:String = computeSize(size , host.unit);
+			var edgePadding:Number = host.edgePadding;
+			var appliedSize:String = computeSize(size + edgePadding * 2 , host.unit);
+			//edgePadding will be applied with transparent borders;
+			var borderPadding:Border
+			if (edgePadding) {
+				var appliedEdgePadding:String = computeSize(edgePadding,host.unit);
+				borderPadding = new Border();
+				borderPadding.color = 'transparent';
+			}
+			
 			var styles:Array = [
 					new BackgroundColor("slate-"+colorAdjust),
-				    new BorderRadius(ThemeManager.instance.activeTheme.radiusSM)
+				    new BorderRadius(ThemeManager.instance.activeTheme.radiusSM),
 			]
+			if (borderPadding) {
+				styles.push(borderPadding);
+				styles.push(new BackgroundClip('padding-box'));
+			}
 			if (getHost().vertical) {
 				styles.push(new HeightStyle('100%'));
-				styles.push(new WidthStyle())
+				styles.push(new WidthStyle(appliedSize));
+				if (borderPadding) {
+					//there seems to be no way to configure top and bottom border...tbd
+					borderPadding.width = appliedEdgePadding;
+				}
+				
 			} else {
+				
+				if (borderPadding) {
+					//there seems to be no way to configure left and right border...tbd
+					borderPadding.width = appliedEdgePadding;
+				}
 				styles.push(new WidthStyle('100%'));
 				styles.push(new HeightStyle(appliedSize));
 			}
 			_styles = styles;
 			
-			host.setStyles(_styles);
+			host.setStyles(_styles, true);
 		}
 		
 		private function getShading(size:String):Number{
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/ILeafStyleBead.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/ILeafStyleBead.as
index 581846f53c..e0ef3e3434 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/ILeafStyleBead.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/ILeafStyleBead.as
@@ -35,6 +35,7 @@ package org.apache.royale.style.stylebeads
 		function get ruleSuffix():String;
 		function set ruleSuffix(value:String):void;
 		function isDecorated():Boolean;
+		function get ruleBase():String;
 
 
 	}
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/IStyleBead.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/IStyleBead.as
index 917a077294..23610021c7 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/IStyleBead.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/IStyleBead.as
@@ -37,5 +37,6 @@ package org.apache.royale.style.stylebeads
 		function get parentStyle():IStyleBead;
 		function set parentStyle(value:IStyleBead):void;
 		function decorateChildStyle(style:ILeafStyleBead,decorations:Array):void;
+		function get ruleDecorator():String;
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/StyleBeadBase.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/StyleBeadBase.as
index 75286da4c4..4fff129691 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/StyleBeadBase.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/StyleBeadBase.as
@@ -53,7 +53,12 @@ package org.apache.royale.style.stylebeads
 		 */
 		public function getLeaves():Array
 		{
-			assert(styles && styles.length > 0, "Non-leaf style beads must have child styles");
+			if (!isLeaf && (!styles || styles.length == 0))
+			{
+				// If we don't have children, we can't gather leaves.
+				// This can happen if a LeafDecorator is used as a selector source for HasState/NotState.
+				return [];
+			}
 			preprocessStyle();
 			return gatherLeaves(this);
 		}
@@ -105,6 +110,10 @@ package org.apache.royale.style.stylebeads
 		{
 			_parentStyle = value;
 		}
+		public function get ruleDecorator():String
+		{
+			return null;
+		}
 		abstract public function decorateChildStyle(style:ILeafStyleBead, decorations:Array):void;
 		public function get isLeaf():Boolean
 		{
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/HasState.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/HasState.as
index 53efce7772..9db7f59700 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/HasState.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/HasState.as
@@ -18,14 +18,78 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.style.stylebeads.states
 {
-	public class HasState extends StyleStateBase
+	import org.apache.royale.style.stylebeads.ILeafStyleBead;
+	import org.apache.royale.style.util.StyleDecoration;
+	import org.apache.royale.style.stylebeads.LeafStyleBase;
+
+	public class HasState extends LeafDecorator
 	{
+
+		public static const CHECKBOX_INPUT:String = 'input[type=checkbox]';
+
 		/**
-		 * TODO Figure :has out.
+		 * HasState is a decorator that adds a :has() pseudo-class to the rule.
+		 * It can be used to style a parent based on the state of a child.
 		 */
-		public function HasState()
+		public function HasState(selector:* = null, styles:Array = null)
 		{
 			super();
+			selectorDecorator = "has-";
+			if (selector is LeafDecorator)
+			{
+				_nestedDecorator = selector as LeafDecorator;
+			}
+			else
+			{
+				ruleDecorator = selector as String;
+			}
+			this.styles = styles;
+
+			decoratorType = COMBINER;
+		}
+
+		private var _nestedDecorator:LeafDecorator;
+
+		/**
+		 * @royaleignorecoercion org.apache.royale.style.stylebeads.LeafStyleBase
+		 */
+		override public function decorateChildStyle(style:ILeafStyleBead, decorations:Array):void
+		{
+			style.selectorPrefix = selectorDecorator + style.selectorPrefix;
+
+			var leafStyle:LeafStyleBase = style as LeafStyleBase;
+
+			//TODO figure out more complex combinations. For now, just handle limited nesting.
+			var decorationStr:String = ""
+			var len:int = decorations.length;
+			for(var i:int = 0; i < len; i++)
+			{
+				decorationStr += decorations[i].decoration;
+			}
+
+			var rule:String = ruleDecorator || "";
+			if (_nestedDecorator)
+			{
+				rule = _nestedDecorator.getFullRule();
+				if (_nestedDecorator is HasState)
+				{
+					rule = ":has(" + rule + ")";
+				}
+				else if (_nestedDecorator is NotState)
+				{
+					rule = ":not(" + rule + ")";
+				}
+			}
+
+			decorations.push(new StyleDecoration(decoratorType, rule + decorationStr));
+
+			if(!parentStyle || parentStyle.isGroup)
+			{
+				leafStyle.ruleSuffix = leafStyle.ruleSuffix + ":has(" + rule + decorationStr + ")";
+			}
+
+			if(parentStyle)
+				parentStyle.decorateChildStyle(style, decorations);
 		}
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/HoverState.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/HoverState.as
index ab4a23af12..74cdf953ea 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/HoverState.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/HoverState.as
@@ -20,11 +20,12 @@ package org.apache.royale.style.stylebeads.states
 {
 	public class HoverState extends LeafDecorator
 	{
-		public function HoverState()
+		public function HoverState(styles:Array = null)
 		{
 			super();
 			selectorDecorator = "hover:";
 			ruleDecorator = ":hover";
+			this.styles = styles;
 		}
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/LeafDecorator.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/LeafDecorator.as
index 9162db0958..37bca49b3d 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/LeafDecorator.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/LeafDecorator.as
@@ -37,7 +37,15 @@ package org.apache.royale.style.stylebeads.states
 		}
 		protected var decoratorType:String = STATE;
 		protected var selectorDecorator:String;
-		protected var ruleDecorator:String;
+		protected var _ruleDecorator:String;
+		override public function get ruleDecorator():String
+		{
+			return _ruleDecorator;
+		}
+		public function set ruleDecorator(value:String):void
+		{
+			_ruleDecorator = value;
+		}
 		override public function get styleType():String
 		{
 			return selectorDecorator;
@@ -51,18 +59,37 @@ package org.apache.royale.style.stylebeads.states
 			var leafStyle:LeafStyleBase = style as LeafStyleBase;
 			leafStyle.selectorPrefix = selectorDecorator + leafStyle.selectorPrefix;
 
-			decorations.push(new StyleDecoration(decoratorType, ruleDecorator));
+			decorations.push(new StyleDecoration(decoratorType, _ruleDecorator));
 			/**
 			 * Default behavior is for state decorators. In that case, the decoration is added as a suffix.
 			 * Otherwise, the decoration is passed to the parent which handles the decoration based on the type.
 			 */
 			if(!parentStyle || parentStyle.isGroup)
 			{
-				leafStyle.ruleSuffix = leafStyle.ruleSuffix + ruleDecorator;
+				leafStyle.ruleSuffix = leafStyle.ruleSuffix + _ruleDecorator;
 			}
 			if(parentStyle)
 				parentStyle.decorateChildStyle(style, decorations);
 
 		}
+		public function getFullRule():String
+		{
+			var rule:String = ruleDecorator || "";
+			if (styles && styles.length > 0)
+			{
+				for each (var style:IStyleBead in styles)
+				{
+					if (style is LeafDecorator)
+					{
+						rule += (style as LeafDecorator).getFullRule();
+					}
+					else if (style is ILeafStyleBead)
+					{
+						rule += (style as ILeafStyleBead).ruleSuffix;
+					}
+				}
+			}
+			return rule;
+		}
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/NotState.as b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/NotState.as
index 39d86cfef2..2df530c36c 100644
--- a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/NotState.as
+++ b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/NotState.as
@@ -18,14 +18,74 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.style.stylebeads.states
 {
-	public class NotState extends StyleStateBase
+	import org.apache.royale.style.stylebeads.ILeafStyleBead;
+	import org.apache.royale.style.util.StyleDecoration;
+	import org.apache.royale.style.stylebeads.LeafStyleBase;
+
+	public class NotState extends LeafDecorator
 	{
-		public function NotState()
+		/**
+		 * NotState is a decorator that adds a :not() pseudo-class to the rule.
+		 */
+		public function NotState(selector:* = null, styles:Array = null)
 		{
 			super();
+			selectorDecorator = "not-";
+			if (selector is LeafDecorator)
+			{
+				_nestedDecorator = selector as LeafDecorator;
+			}
+			else
+			{
+				ruleDecorator = selector as String;
+			}
+			this.styles = styles;
+
+			decoratorType = COMBINER;
+		}
+
+		private var _nestedDecorator:LeafDecorator;
+
+		/**
+		 * @royaleignorecoercion org.apache.royale.style.stylebeads.LeafStyleBase
+		 */
+		override public function decorateChildStyle(style:ILeafStyleBead, decorations:Array):void
+		{
+			style.selectorPrefix = selectorDecorator + style.selectorPrefix;
+
+			var leafStyle:LeafStyleBase = style as LeafStyleBase;
+
+			//TODO figure out more complex combinations. For now, just handle limited nesting.
+			var decorationStr:String = ""
+			var len:int = decorations.length;
+			for(var i:int = 0; i < len; i++)
+			{
+				decorationStr += decorations[i].decoration;
+			}
+
+			var rule:String = ruleDecorator || "";
+			if (_nestedDecorator)
+			{
+				rule = _nestedDecorator.getFullRule();
+				if (_nestedDecorator is HasState)
+				{
+					rule = ":has(" + rule + ")";
+				}
+				else if (_nestedDecorator is NotState)
+				{
+					rule = ":not(" + rule + ")";
+				}
+			}
+
+			decorations.push(new StyleDecoration(decoratorType, rule + decorationStr));
+
+			if(!parentStyle || parentStyle.isGroup)
+			{
+				leafStyle.ruleSuffix = leafStyle.ruleSuffix + ":not(" + rule + decorationStr + ")";
+			}
+
+			if(parentStyle)
+				parentStyle.decorateChildStyle(style, decorations);
 		}
-		//TODO Figure this out.
-		// ":not"
-		//".lg\\:not-first\\:border-l:not(:first-child)"
 	}
 }
\ No newline at end of file