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 2020/08/08 07:55:47 UTC

[royale-asjs] 01/01: Initial sweep of various issues in Jewel Datagrid. Some updates in Tour de Jewel.

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

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

commit 6b6702999d11d9d43ef62527f790ed88efe5c0d8
Author: greg-dove <gr...@gmail.com>
AuthorDate: Sat Aug 8 17:45:17 2020 +1200

    Initial sweep of various issues in Jewel Datagrid.
    Some updates in Tour de Jewel.
---
 .../src/main/royale/DataGridPlayGround.mxml        |   6 +-
 .../org/apache/royale/utils/ClassSelectorList.as   |  32 ++++-
 .../projects/Jewel/src/main/resources/defaults.css |  26 +++-
 .../projects/Jewel/src/main/royale/JewelClasses.as |  12 +-
 .../main/royale/org/apache/royale/jewel/HSlider.as |   2 +
 .../royale/jewel/beads/layouts/ButtonBarLayout.as  |   8 +-
 ...{ButtonBarLayout.as => DataGridColumnLayout.as} | 147 ++++++++++----------
 .../royale/jewel/beads/layouts/DataGridLayout.as   | 115 ++++++++++------
 .../royale/jewel/beads/views/DataGridView.as       |  34 ++++-
 .../jewel/itemRenderers/DatagridHeaderRenderer.as  |  77 +++++++++++
 .../supportClasses/datagrid/DataGridButtonBar.as   |   1 +
 .../supportClasses/datagrid/DataGridColumn.as      |  79 ++++++-----
 .../supportClasses/datagrid/DataGridColumnWidth.as | 153 +++++++++++++++++++++
 ...ridButtonBar.as => DataGridWidthDenominator.as} |  38 ++---
 .../jewel/supportClasses/table/ITableColumn.as     |   7 +
 .../org/apache/royale/utils/observeElementSize.as  | 142 +++++++++++++++++++
 .../Jewel/src/main/sass/components/_datagrid.sass  |  23 +++-
 .../Jewel/src/main/sass/components/_layout.sass    |   2 +-
 .../JewelTheme/src/main/resources/defaults.css     |  22 ++-
 .../main/sass/components-primary/_datagrid.sass    |  31 ++++-
 20 files changed, 749 insertions(+), 208 deletions(-)

diff --git a/examples/jewel/TourDeJewel/src/main/royale/DataGridPlayGround.mxml b/examples/jewel/TourDeJewel/src/main/royale/DataGridPlayGround.mxml
index dd38563..2d2dc20 100644
--- a/examples/jewel/TourDeJewel/src/main/royale/DataGridPlayGround.mxml
+++ b/examples/jewel/TourDeJewel/src/main/royale/DataGridPlayGround.mxml
@@ -224,7 +224,11 @@ limitations under the License.
 						<html:H3 text="Percentage Width and Height" className="primary-normal"/>
 					</j:BarSection>
 					<j:BarSection itemsHorizontalAlign="itemsRight">
-						<j:HSlider minimum="200" maximum="600" value="400" valueChange="card2.height = event.target.value"/>
+						<j:HSlider minimum="200" maximum="600"
+								   width="170"
+								   value="400"
+								   change="card2.height = event.target.value"
+								   valueChange="card2.height = event.target.value"/>
 					</j:BarSection>
 				</j:CardHeader>
 				<j:CardPrimaryContent>
diff --git a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ClassSelectorList.as b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ClassSelectorList.as
index 4a06468..c04e32f 100644
--- a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ClassSelectorList.as
+++ b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ClassSelectorList.as
@@ -18,7 +18,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.utils
 {
-    import org.apache.royale.core.IUIBase;
+import org.apache.royale.core.HTMLElementWrapper;
+import org.apache.royale.core.IUIBase;
 
     /**
 	 *  The ClassSelectorList class is used to manage the list of class selectors
@@ -37,6 +38,23 @@ package org.apache.royale.utils
 		}
 
         private var component:IUIBase;
+
+        COMPILE::JS
+        private var _override:HTMLElement
+
+        COMPILE::JS
+        private function get classSelectorTarget():HTMLElement{
+            return _override || component.positioner;
+        }
+
+        /**
+         * @royaleignorecoercion HTMLElement
+         */
+        public function setOverride(value:Object):void{
+            COMPILE::JS{
+                _override = value as HTMLElement;
+            }
+        }
         
         private var startIndex:int = 0;
         private var count:int = 0;
@@ -55,7 +73,7 @@ package org.apache.royale.utils
         {
             COMPILE::JS
             {
-            component.positioner.classList.add(name);
+            classSelectorTarget.classList.add(name);
             if (!component.parent)
                 startIndex++;
             }
@@ -78,7 +96,7 @@ package org.apache.royale.utils
         {
             COMPILE::JS
             {
-            var positioner:HTMLElement = component.positioner as HTMLElement;
+            var positioner:HTMLElement = classSelectorTarget as HTMLElement;
             var classList:DOMTokenList = positioner.classList;
             for (var i:int = 0; i < startIndex; i++)
             {
@@ -107,9 +125,9 @@ package org.apache.royale.utils
             //IE11 does not support second value so instead of
             //component.positioner.classList.toggle(name, value);
             if(value)
-                component.positioner.classList.add(name);
+                classSelectorTarget.classList.add(name);
             else
-                component.positioner.classList.remove(name);
+                classSelectorTarget.classList.remove(name);
 
             if (!component.parent && value)
                 startIndex++;
@@ -131,7 +149,7 @@ package org.apache.royale.utils
         {
             COMPILE::JS
             {
-            return component.positioner.classList.contains(name);
+            return classSelectorTarget.classList.contains(name);
             }
             COMPILE::SWF
             {//not implemented
@@ -156,7 +174,7 @@ package org.apache.royale.utils
         {
             COMPILE::JS
             {
-                var positioner:HTMLElement = component.positioner as HTMLElement;
+                var positioner:HTMLElement = classSelectorTarget as HTMLElement;
                 var classList:DOMTokenList = positioner.classList;
                 if (component.parent)
                 {
diff --git a/frameworks/projects/Jewel/src/main/resources/defaults.css b/frameworks/projects/Jewel/src/main/resources/defaults.css
index 79f33fe..c52645f 100644
--- a/frameworks/projects/Jewel/src/main/resources/defaults.css
+++ b/frameworks/projects/Jewel/src/main/resources/defaults.css
@@ -561,14 +561,30 @@ j|VirtualComboBoxPopUp {
 }
 .jewel.datagrid .jewel.buttonbar.header {
   width: 100%;
+  flex: 0 0 auto;
+}
+.jewel.datagrid .jewel.buttonbar.header .jewel.button {
+  padding-left: 2px;
+  padding-right: 2px;
+  justify-content: flex-start;
+  width: 100%;
 }
 .jewel.datagrid .listarea {
   width: 100%;
-  flex: 1 1 0%;
+  flex: 1 1 auto;
+}
+.jewel.datagrid .jewel.list.column {
+  padding-left: 0;
+  padding-right: 0;
+  position: relative;
+  min-height: 100%;
 }
 .jewel.datagrid .jewel.list.column .jewel.item.datagrid {
   width: 100%;
 }
+.jewel.datagrid span:empty:before {
+  content: "\200b";
+}
 
 j|DataGrid {
   IDataGridPresentationModel: ClassReference("org.apache.royale.jewel.beads.models.DataGridPresentationModel");
@@ -576,7 +592,7 @@ j|DataGrid {
   IBeadModel: ClassReference("org.apache.royale.html.beads.models.DataGridCollectionViewModel");
   IBeadLayout: ClassReference("org.apache.royale.jewel.beads.layouts.DataGridLayout");
   headerClass: ClassReference("org.apache.royale.jewel.supportClasses.datagrid.DataGridButtonBar");
-  headerLayoutClass: ClassReference("org.apache.royale.jewel.beads.layouts.ButtonBarLayout");
+  headerLayoutClass: ClassReference("org.apache.royale.jewel.beads.layouts.DataGridColumnLayout");
   listAreaClass: ClassReference("org.apache.royale.jewel.supportClasses.datagrid.DataGridListArea");
   columnClass: ClassReference("org.apache.royale.jewel.supportClasses.datagrid.DataGridColumnList");
 }
@@ -596,6 +612,10 @@ j|DataGridColumnList {
   IViewport: ClassReference("org.apache.royale.jewel.supportClasses.Viewport");
 }
 
+j|DataGridButtonBar {
+  IItemRenderer: ClassReference("org.apache.royale.jewel.itemRenderers.DatagridHeaderRenderer");
+}
+
 .jewel.datechooser .jewel.table {
   min-width: 324px;
   min-height: 364px;
@@ -1141,7 +1161,7 @@ j|Label {
 .layout.horizontal.pixelWidths > * {
   flex: none;
 }
-.layout.horizontal.proportinalWidths > * {
+.layout.horizontal.proportionalWidths > * {
   flex: 1 0;
 }
 .layout.horizontal.percentWidths > * {
diff --git a/frameworks/projects/Jewel/src/main/royale/JewelClasses.as b/frameworks/projects/Jewel/src/main/royale/JewelClasses.as
index c53a67a..c56d1e0 100644
--- a/frameworks/projects/Jewel/src/main/royale/JewelClasses.as
+++ b/frameworks/projects/Jewel/src/main/royale/JewelClasses.as
@@ -18,8 +18,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 package
 {
+import org.apache.royale.utils.observeElementSize;
 
-    /**
+/**
      *  @private
      *  This class is used to link additional classes into jewel.swc
      *  beyond those that are found by dependecy analysis starting
@@ -131,10 +132,13 @@ package
 
         COMPILE::JS
         {
-        import dialogPolyfill; dialogPolyfill;
-        import org.apache.royale.utils.transparentPixelElement; transparentPixelElement;
+            import dialogPolyfill; dialogPolyfill;
+            import org.apache.royale.utils.transparentPixelElement; transparentPixelElement;
+            import org.apache.royale.utils.observeElementSize; observeElementSize;
         }
-        
+
+        import org.apache.royale.jewel.itemRenderers.DatagridHeaderRenderer; DatagridHeaderRenderer;
+
         import org.apache.royale.jewel.beads.itemRenderers.IndexedItemRendererInitializer; IndexedItemRendererInitializer;
         import org.apache.royale.jewel.beads.itemRenderers.ClassSelectorListSelectableItemRendererBead; ClassSelectorListSelectableItemRendererBead;
         import org.apache.royale.jewel.beads.itemRenderers.ClassSelectorListHoverOnlySelectableItemRendererBead; ClassSelectorListHoverOnlySelectableItemRendererBead;
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/HSlider.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/HSlider.as
index 71d976a..7fadbdf 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/HSlider.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/HSlider.as
@@ -33,6 +33,8 @@ package org.apache.royale.jewel
 
 	/**
      *  Dispatched when Slider change its value.
+	 *  Note that this event is not fired correctly on IE11, use 'change' event as well to
+	 *  get 'continuous' updates for IE11
      *
      *  @langversion 3.0
      *  @playerversion Flash 10.2
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/ButtonBarLayout.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/ButtonBarLayout.as
index 637e4aa..c4f148b 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/ButtonBarLayout.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/ButtonBarLayout.as
@@ -102,8 +102,8 @@ package org.apache.royale.jewel.beads.layouts
 				{
 					if (hostComponent.containsClass("pixelWidths"))
 						hostComponent.removeClass("pixelWidths");
-					if (hostComponent.containsClass("proportinalWidths"))
-						hostComponent.removeClass("proportinalWidths");
+					if (hostComponent.containsClass("proportionalWidths"))
+						hostComponent.removeClass("proportionalWidths");
 					if (hostComponent.containsClass("percentWidths"))
 						hostComponent.removeClass("percentWidths");
 					if (hostComponent.containsClass("naturalWidths"))
@@ -122,7 +122,7 @@ package org.apache.royale.jewel.beads.layouts
 								hostComponent.addClass("pixelWidths");
 								break;
 							case ButtonBarModel.PROPORTIONAL_WIDTHS:
-								hostComponent.addClass("proportinalWidths");
+								hostComponent.addClass("proportionalWidths");
 								break;
 							case ButtonBarModel.PERCENT_WIDTHS:
 								hostComponent.addClass("percentWidths");
@@ -163,6 +163,8 @@ package org.apache.royale.jewel.beads.layouts
 					
 					if (model.widthType == ButtonBarModel.PIXEL_WIDTHS) {
 						if (widthValue != null) ilc.width = Number(widthValue);
+					} else {
+						ilc.width = NaN;
 					}
 					// else if (_widthType == ButtonBarModel.PROPORTIONAL_WIDTHS) {
 					// 	if (widthValue != null) ilc.element.style["flex-grow"] = String(widthValue);
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/ButtonBarLayout.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/DataGridColumnLayout.as
similarity index 58%
copy from frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/ButtonBarLayout.as
copy to frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/DataGridColumnLayout.as
index 637e4aa..d24cf94 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/ButtonBarLayout.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/DataGridColumnLayout.as
@@ -18,12 +18,18 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.jewel.beads.layouts
 {
+	import org.apache.royale.core.IBeadLayout;
 	import org.apache.royale.core.ILayoutChild;
 	import org.apache.royale.core.ILayoutView;
 	import org.apache.royale.core.IStrand;
+	import org.apache.royale.core.IUIBase;
+	import org.apache.royale.core.UIBase;
 	import org.apache.royale.core.IStyleableObject;
 	import org.apache.royale.events.Event;
 	import org.apache.royale.html.beads.models.ButtonBarModel;
+	import org.apache.royale.html.beads.IDataGridView;
+	import org.apache.royale.jewel.supportClasses.datagrid.DataGridColumnWidth;
+	import org.apache.royale.jewel.supportClasses.datagrid.IDataGridColumn;
 
 	/**
 	 *  The Jewel ButtonBarLayout class bead sizes and positions the button
@@ -37,9 +43,14 @@ package org.apache.royale.jewel.beads.layouts
 	 *  @playerversion Flash 10.2
 	 *  @playerversion AIR 2.6
 	 *  @productversion Royale 0.9.7
+	 *
+	 *  @royalesuppressexport
 	 */
-	public class ButtonBarLayout extends HorizontalLayout
+	public class DataGridColumnLayout extends HorizontalLayout  implements IBeadLayout
 	{
+
+
+
 		/**
 		 *  constructor.
 		 *
@@ -48,7 +59,7 @@ package org.apache.royale.jewel.beads.layouts
 		 *  @playerversion AIR 2.6
 		 *  @productversion Royale 0.9.7
 		 */
-		public function ButtonBarLayout()
+		public function DataGridColumnLayout()
 		{
 			super();
 		}
@@ -74,69 +85,57 @@ package org.apache.royale.jewel.beads.layouts
 			super.beadsAddedHandler();
 
 			model = (host as IStrand).getBeadByType(ButtonBarModel) as ButtonBarModel;
-			if (model) {
-				widthType = model.buttonWidths != null ? model.widthType : NaN;
-			}
+			hostComponent.addEventListener("headerLayout", onHeaderLayoutCheck);
+			hostComponent.addEventListener("headerLayoutReset", onHeaderLayoutCheck);
+		}
+
+		/**
+		 * @royaleignorecoercion org.apache.royale.core.UIBase
+		 */
+		protected function get datagrid():UIBase
+		{
+			return (_strand as UIBase).parent as UIBase;
 		}
 
+		COMPILE::JS
+		private var _vScrollerHOffset:Number = 0;
+
+		COMPILE::JS
+		private var _vScrollChange:Boolean;
+
+
 		/**
-		 *  Switch between four different types of width
 		 *
-		 *  @langversion 3.0
-		 *  @playerversion Flash 10.2
-		 *  @playerversion AIR 2.6
-		 *  @productversion Royale 0.9.7
+		 * @royaleignorecoercion org.apache.royale.html.beads.IDataGridView
 		 */
-		public function get widthType():Number
-        {
-            return model.widthType;
-        }
-		public function set widthType(value:Number):void
-        {
-			if (model.widthType != value)
-            {
-				model.widthType = value;
-                COMPILE::JS
-                {
-				if(hostComponent)
-				{
-					if (hostComponent.containsClass("pixelWidths"))
-						hostComponent.removeClass("pixelWidths");
-					if (hostComponent.containsClass("proportinalWidths"))
-						hostComponent.removeClass("proportinalWidths");
-					if (hostComponent.containsClass("percentWidths"))
-						hostComponent.removeClass("percentWidths");
-					if (hostComponent.containsClass("naturalWidths"))
-						hostComponent.removeClass("naturalWidths");
-					if (hostComponent.containsClass("sameWidths"))
-						hostComponent.removeClass("sameWidths");
-					if(isNaN(model.widthType))
-					{
-						hostComponent.addClass("sameWidths");
-					}
-					else
-					{
-						switch(model.widthType)
-						{
-							case ButtonBarModel.PIXEL_WIDTHS:
-								hostComponent.addClass("pixelWidths");
-								break;
-							case ButtonBarModel.PROPORTIONAL_WIDTHS:
-								hostComponent.addClass("proportinalWidths");
-								break;
-							case ButtonBarModel.PERCENT_WIDTHS:
-								hostComponent.addClass("percentWidths");
-								break;
-							case ButtonBarModel.NATURAL_WIDTHS:
-								hostComponent.addClass("naturalWidths");
-								break;
-						}
-					}
-				}
+		private function onHeaderLayoutCheck(event:Event):void{
+			var view:IDataGridView = datagrid.view as IDataGridView;
+			var listArea:IUIBase = view.listArea;
+			COMPILE::JS {
+				var LA_Element:HTMLElement = listArea.element;
+				var latestHOffset:Number = LA_Element.offsetWidth - LA_Element.clientWidth;
+
+				if (latestHOffset != _vScrollerHOffset || event.type == 'headerLayoutReset') {
+					_vScrollerHOffset = latestHOffset;
+					_vScrollChange = true;
+					layout();
 				}
 			}
+
 		}
 
+
+		private var _defaultWidth:DataGridColumnWidth;
+
+		public function get defaultWidth():DataGridColumnWidth{
+			return _defaultWidth;
+		}
+
+		public function set defaultWidth(value:DataGridColumnWidth):void{
+			_defaultWidth = value;
+		}
+
+
 		/**
 		 * @copy org.apache.royale.core.IBeadLayout#layout
 		 * @royaleignorecoercion org.apache.royale.core.ILayoutChild
@@ -148,32 +147,32 @@ package org.apache.royale.jewel.beads.layouts
 			var contentView:ILayoutView = layoutView;
 			var n:int = contentView.numElements;
 			if (n <= 0) return false;
-
+			var last:ILayoutChild;
+			var lastWidthConfig:DataGridColumnWidth;
 			for (var i:int=0; i < n; i++)
 			{	
 				var ilc:ILayoutChild = contentView.getElementAt(i) as ILayoutChild;
 				if (ilc == null || !ilc.visible) continue;
 				if (!(ilc is IStyleableObject)) continue;
-				
+				last = ilc;
 				COMPILE::JS
 				{
-				// otherwise let the flexbox layout handle matters on its own.
-				if (model.buttonWidths) {
-					var widthValue:* = model.buttonWidths[i];
-					
-					if (model.widthType == ButtonBarModel.PIXEL_WIDTHS) {
-						if (widthValue != null) ilc.width = Number(widthValue);
+					// otherwise let the flexbox layout handle matters on its own.
+					if (model.buttonWidths) {
+						lastWidthConfig = model.buttonWidths[i];
+						lastWidthConfig.configureWidth(ilc);
+					} else {
+						if (_defaultWidth) {
+							_defaultWidth.configureWidth(ilc);
+							lastWidthConfig = _defaultWidth;
+						}
 					}
-					// else if (_widthType == ButtonBarModel.PROPORTIONAL_WIDTHS) {
-					// 	if (widthValue != null) ilc.element.style["flex-grow"] = String(widthValue);
-					// }
-					// else if (_widthType == ButtonBarModel.PERCENT_WIDTHS) {
-					// 	if (widthValue != null) ilc.percentWidth = Number(widthValue);
-					// }
-				} 
-				// else if (!_widthType == ButtonBarModel.NATURAL_WIDTHS) {
-				// 	ilc.element.style["flex-grow"] = "1";
-				// }
+				}
+			}
+			COMPILE::JS{
+				if (last && _vScrollChange) {
+					lastWidthConfig.applyRightOffset(last, _vScrollerHOffset);
+					_vScrollChange = false;
 				}
 			}
 
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/DataGridLayout.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/DataGridLayout.as
index 4f3eae2..6f65bd9 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/DataGridLayout.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/layouts/DataGridLayout.as
@@ -30,6 +30,9 @@ package org.apache.royale.jewel.beads.layouts
     import org.apache.royale.html.beads.models.ButtonBarModel;
     import org.apache.royale.jewel.supportClasses.datagrid.IDataGridColumn;
     import org.apache.royale.jewel.supportClasses.datagrid.IDataGridPresentationModel;
+
+	import org.apache.royale.jewel.supportClasses.datagrid.DataGridColumnWidth;
+	import org.apache.royale.jewel.supportClasses.datagrid.DataGridWidthDenominator;
 	
 	/**
 	 * DataGridLayout is a class that handles the size and positioning of the
@@ -124,13 +127,13 @@ package org.apache.royale.jewel.beads.layouts
 			// so we call requestAnimationFrame until get right values
 			COMPILE::JS
 			{
-			if(initLayout && model.dataProvider){
-				if(datagrid.height == 0 && !isNaN(datagrid.percentHeight)) {
-					requestAnimationFrame(layout);
-					return true;
-				} else
-					initLayout = false;
-			}
+				if(initLayout && model.dataProvider){
+					if(datagrid.height == 0 && !isNaN(datagrid.percentHeight)) {
+						requestAnimationFrame(layout);
+						return true;
+					} else
+						initLayout = false;
+				}
 			}
 
 			var view:IDataGridView = datagrid.view as IDataGridView
@@ -140,62 +143,96 @@ package org.apache.royale.jewel.beads.layouts
             // in the bbmodel, so do all layout based on the bbmodel, not the set
             // of columns that may contain invisible columns
             var bbmodel:ButtonBarModel = header.getBeadByType(ButtonBarModel) as ButtonBarModel;
-            var bblayout:ButtonBarLayout = header.getBeadByType(ButtonBarLayout) as ButtonBarLayout;
+			bbmodel.dataProvider.source = model.columns;
+            var bblayout:DataGridColumnLayout = header.getBeadByType(DataGridColumnLayout) as DataGridColumnLayout;
 			var listArea:IUIBase = view.listArea;
 			
 			var displayedColumns:Array = view.columnLists;
 			
 			// Width
-			var defaultColumnWidth:Number = 0;
+			//var defaultColumnWidth:Number = 0;
+			var defaultColumnWidth:DataGridColumnWidth = null;
+
+			var l:uint = bbmodel.dataProvider.length;
+			var i:int;
+			var columnDef:IDataGridColumn;
+			var isDGWidthSizedToContent:Boolean = datagrid.isWidthSizedToContent();
+			var denominatorInst:DataGridWidthDenominator = new DataGridWidthDenominator();
+
+			denominatorInst.value = l;
+			var explicitWidths:Number = 0;
+			var explicitPercents:uint = 0;
+			for(i=0; i < l; i++) {
+				columnDef = (bbmodel.dataProvider as ArrayList).getItemAt(i) as IDataGridColumn;
+				if (!isNaN(columnDef.explicitColumnWidth)) {
+					denominatorInst.value--;
+					explicitWidths += columnDef.explicitColumnWidth;
+				} else if(!isNaN(columnDef.percentColumnWidth)) {
+					explicitPercents += columnDef.percentColumnWidth;
+				}
+			}
 
 			// When still don't have header buttonWidths, we need a defaultColumnWidth
 			if(!bbmodel.buttonWidths)
 			{
-				if(datagrid.percentWidth)
-					defaultColumnWidth = datagrid.percentWidth / bbmodel.dataProvider.length;
-				else 
-					defaultColumnWidth = datagrid.width / bbmodel.dataProvider.length;
-				
-				// special case when no width is set at all, defaultColumnWidth will be 0
-				if(defaultColumnWidth == 0 && datagrid.isWidthSizedToContent())
-					defaultColumnWidth = 80;
+				if (denominatorInst.value) {
+					defaultColumnWidth = new DataGridColumnWidth();
+					defaultColumnWidth.denominator = denominatorInst;
+					bblayout.defaultWidth = defaultColumnWidth;
+					//not sure about the logic behind these default assessments:
+					if (datagrid.percentWidth) {
+						defaultColumnWidth.value = ((100 - explicitPercents) * .01 * datagrid.percentWidth) / denominatorInst.value ;
+						if (defaultColumnWidth.value) defaultColumnWidth.widthType = DataGridColumnWidth.EXPLICIT_PERCENT;
+					} else if (datagrid.explicitWidth){
+						defaultColumnWidth.value = ((100 - explicitPercents)/100 * datagrid.width - explicitWidths) / denominatorInst.value;
+						if (defaultColumnWidth.value) defaultColumnWidth.widthType = DataGridColumnWidth.EXPLICIT_PIXELS;
+					}
+					// special case when no width is set at all, defaultColumnWidth will be 0
+					if (defaultColumnWidth.value == 0 && isDGWidthSizedToContent) {
+						defaultColumnWidth.value = 80 ;
+						defaultColumnWidth.widthType = DataGridColumnWidth.EXPLICIT_PIXELS;
+					}
+				}
 			}
 			
 			var columnWidths:Array = [];
-			var totalWidth:Number = 0;
 
-			for(var i:int=0; i < bbmodel.dataProvider.length; i++)
+			var existing:Boolean = bbmodel.buttonWidths != null;
+			for(i=0; i < l; i++)
 			{
-				var columnDef:IDataGridColumn = (bbmodel.dataProvider as ArrayList).getItemAt(i) as IDataGridColumn;
+				columnDef = (bbmodel.dataProvider as ArrayList).getItemAt(i) as IDataGridColumn;
 				var columnList:UIBase = displayedColumns[i] as UIBase;
-				var columnWidth:Number = defaultColumnWidth != 0 ? defaultColumnWidth : bbmodel.buttonWidths[i];
-				
-				// Column's Width
-				// if just one isNaN(columnDef.columnWidth) make it true so widthType = ButtonBarModel.PIXEL_WIDTHS
-				if (!isNaN(columnDef.columnWidth)) {
-					columnWidth = columnDef.columnWidth;
-					bblayout.widthType = ButtonBarModel.PIXEL_WIDTHS;
+
+				var columnWidth:DataGridColumnWidth = existing ? bbmodel.buttonWidths[i] || new DataGridColumnWidth() : new DataGridColumnWidth() ;
+				columnWidth.denominator = denominatorInst;
+
+				if (!isNaN(columnDef.explicitColumnWidth)) {
+					columnWidth.widthType = DataGridColumnWidth.EXPLICIT_PIXELS;
+					columnWidth.value = columnDef.columnWidth;
+					columnWidth.column = columnDef;
+				} else {
+					if (!isNaN(columnDef.percentColumnWidth)) {
+						columnWidth.widthType = DataGridColumnWidth.EXPLICIT_PERCENT;
+						columnWidth.value = columnDef.percentColumnWidth;
+						columnWidth.column = columnDef;
+					} else {
+						columnWidth.setFrom(defaultColumnWidth);
+					}
+
 				}
-				
-				if(datagrid.percentWidth)
-					columnList.percentWidth = columnWidth;
-				else
-					columnList.width = columnWidth;
-				
-				totalWidth += columnWidth;
+				columnWidth.configureWidth(columnList);
+
 				columnWidths.push(columnWidth);
 				
 				// Column's Height - remove columns height if rows not surround datagrid height (and this one is set to pixels)
-				if(model.dataProvider && (model.dataProvider.length * presentationModel.rowHeight) > (datagrid.height - header.height))
+				/*if(model.dataProvider && (model.dataProvider.length * presentationModel.rowHeight) > (datagrid.height - header.height))
 					columnList.height = NaN;
 				else 
-					columnList.percentHeight = 100;
+					columnList.percentHeight = 100;*/
 			}
 
 			bbmodel.buttonWidths = columnWidths;
-			
-			if(isNaN(datagrid.percentWidth))
-				datagrid.width = totalWidth;
+
 			
 			header.dispatchEvent(new Event("layoutNeeded"));
 			listArea.dispatchEvent(new Event("layoutNeeded"));
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/DataGridView.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/DataGridView.as
index cc54a22..88bfd9c 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/DataGridView.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/DataGridView.as
@@ -39,7 +39,8 @@ package org.apache.royale.jewel.beads.views
 	import org.apache.royale.html.beads.IDataGridView;
 	import org.apache.royale.jewel.DataGrid;
 	import org.apache.royale.jewel.beads.layouts.ButtonBarLayout;
-	import org.apache.royale.jewel.beads.models.ListPresentationModel;
+import org.apache.royale.jewel.beads.models.IJewelSelectionModel;
+import org.apache.royale.jewel.beads.models.ListPresentationModel;
 	import org.apache.royale.jewel.supportClasses.Viewport;
 	import org.apache.royale.jewel.supportClasses.datagrid.DataGridButtonBar;
 	import org.apache.royale.jewel.supportClasses.datagrid.IDataGridColumn;
@@ -48,6 +49,7 @@ package org.apache.royale.jewel.beads.views
 	import org.apache.royale.jewel.supportClasses.list.IListPresentationModel;
 	import org.apache.royale.utils.IEmphasis;
 	import org.apache.royale.utils.loadBeadFromValuesManager;
+    import org.apache.royale.utils.observeElementSize;
     
     /**
      *  The DataGridView class is the visual bead for the org.apache.royale.jewel.DataGrid.
@@ -117,8 +119,8 @@ package org.apache.royale.jewel.beads.views
             _header.labelField = "label";
             
             var headerLayoutClass:Class = ValuesManager.valuesImpl.getValue(host, "headerLayoutClass") as Class;
-            var bblayout:ButtonBarLayout = new headerLayoutClass() as ButtonBarLayout;
-            _header.addBead(bblayout as IBead);
+            var bblayout:IBead = new headerLayoutClass() as IBeadLayout;
+            _header.addBead(bblayout /*as IBead*/);
             _header.addBead(new Viewport() as IBead);
             sharedModel.headerModel = _header.model as IBeadModel;
             _dg.strandChildren.addElement(_header as IChild);
@@ -131,8 +133,27 @@ package org.apache.royale.jewel.beads.views
 
             if (sharedModel.columns)
                 createLists();
+
+            COMPILE::JS{
+                observeElementSize(_listArea.element, onInternalSizeChange);
+                _listArea.element.addEventListener('scroll', synchHScroll)
+            }
+        }
+
+
+        COMPILE::JS
+        protected function onInternalSizeChange():void{
+            //check for vertical scrollbar presence
+            _header.dispatchEvent(new Event("headerLayout"));
         }
 
+        COMPILE::JS
+        protected function synchHScroll(event:Event):void{
+            _header.element.scrollLeft = _listArea.element.scrollLeft;
+            if (!event) {
+                _header.dispatchEvent(new Event("headerLayoutReset"));
+            }
+        }
         /**
          * @private
          * @royaleignorecoercion Class
@@ -148,6 +169,7 @@ package org.apache.royale.jewel.beads.views
             
             for (var i:int=0; i < sharedModel.columns.length; i++)
             {
+
                 var dataGridColumn:IDataGridColumn = sharedModel.columns[i] as IDataGridColumn;
                 IEventDispatcher(dataGridColumn).addEventListener("labelChanged", labelChangedHandler);
 
@@ -258,6 +280,10 @@ package org.apache.royale.jewel.beads.views
 			    layout = loadBeadFromValuesManager(IBeadLayout, "iBeadLayout", _strand) as IBeadLayout;
             }
             host.dispatchEvent(new Event("layoutNeeded"));
+
+            COMPILE::JS{
+                synchHScroll(null);
+            }
         }
 
         private var layout:IBeadLayout;
@@ -326,7 +352,7 @@ package org.apache.royale.jewel.beads.views
         {
             var list:IDataGridColumnList = event.target as IDataGridColumnList;
             sharedModel.rollOverIndex = list.rollOverIndex;
-
+            var columnLists:Array = this.columnLists;
             for(var i:int=0; i < columnLists.length; i++) {
                 if (list != columnLists[i]) {
                     var otherList:IDataGridColumnList = columnLists[i] as IDataGridColumnList;
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/itemRenderers/DatagridHeaderRenderer.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/itemRenderers/DatagridHeaderRenderer.as
new file mode 100644
index 0000000..9dfe55a
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/itemRenderers/DatagridHeaderRenderer.as
@@ -0,0 +1,77 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.jewel.itemRenderers
+{
+	import org.apache.royale.core.IItemRendererOwnerView;
+	import org.apache.royale.core.IOwnerViewItemRenderer;
+	import org.apache.royale.core.SimpleCSSStylesWithFlex;
+	import org.apache.royale.events.ItemClickedEvent;
+	import org.apache.royale.events.MouseEvent;
+	import org.apache.royale.html.beads.ITextItemRenderer;
+	import org.apache.royale.html.util.getLabelFromData;
+	import org.apache.royale.jewel.Button;
+COMPILE::JS{
+	import org.apache.royale.html.util.addElementToWrapper;
+	import org.apache.royale.core.WrappedHTMLElement;
+}
+
+	/**
+	 *  The DatagridHeaderRenderer class extends ButtonBarItemRenderer and turns it into an itemRenderer
+	 *  suitable for use in most DataContainer/List/DataGrid applications.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10.2
+     *  @playerversion AIR 2.6
+     *  @productversion Royale 0.9.7
+	 */
+	public class DatagridHeaderRenderer extends ButtonBarItemRenderer
+	{
+		public function DatagridHeaderRenderer()
+		{
+			super()
+			COMPILE::JS{
+				classSelectorList.setOverride(_button);
+			}
+		}
+
+		COMPILE::JS
+		override protected function setClassName(value:String):void
+		{
+			_button.className = value;
+		}
+
+		COMPILE::JS
+		private var _button:WrappedHTMLElement
+
+
+
+		/**
+		 * @royaleignorecoercion org.apache.royale.core.WrappedHTMLElement
+		 */
+		COMPILE::JS
+		override protected function createElement():WrappedHTMLElement
+		{
+			_button = super.createElement();
+
+			element = document.createElement('div') as WrappedHTMLElement;
+			element.appendChild(_button)
+			return element;
+		}
+	}
+}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridButtonBar.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridButtonBar.as
index 414d11d..e95e35b 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridButtonBar.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridButtonBar.as
@@ -49,5 +49,6 @@ package org.apache.royale.jewel.supportClasses.datagrid
 			super();
 			typeNames = "jewel buttonbar header";
 		}
+
 	}
 }
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridColumn.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridColumn.as
index a3170fd..2996fb0 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridColumn.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridColumn.as
@@ -18,47 +18,60 @@
 ////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.jewel.supportClasses.datagrid
 {
-	import org.apache.royale.core.IStyledUIBase;
-	import org.apache.royale.jewel.supportClasses.table.TableColumn;
+import org.apache.royale.core.IStyledUIBase;
+import org.apache.royale.jewel.supportClasses.table.TableColumn;
 
+/**
+ *  The DataGridColumn class is the collection of properties that describe
+ *  a column of the org.apache.royale.jewel.DataGrid: which renderer
+ *  to use for each cell in the column, the width of the column, the label for the
+ *  column, and the name of the field in the data containing the value to display
+ *  in the column.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10.2
+ *  @playerversion AIR 2.6
+ *  @productversion Royale 0.9.7
+ */
+public class DataGridColumn extends TableColumn implements IDataGridColumn
+{
 	/**
-	 *  The DataGridColumn class is the collection of properties that describe
-	 *  a column of the org.apache.royale.jewel.DataGrid: which renderer 
-	 *  to use for each cell in the column, the width of the column, the label for the 
-	 *  column, and the name of the field in the data containing the value to display 
-	 *  in the column.
-	 *  
+	 *  constructor.
+	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10.2
 	 *  @playerversion AIR 2.6
 	 *  @productversion Royale 0.9.7
 	 */
-	public class DataGridColumn extends TableColumn implements IDataGridColumn
+	public function DataGridColumn()
 	{
-		/**
-		 *  constructor.
-		 *
-		 *  @langversion 3.0
-		 *  @playerversion Flash 10.2
-		 *  @playerversion AIR 2.6
-		 *  @productversion Royale 0.9.7
-		 */
-		public function DataGridColumn()
-		{
-		}
-		
-		/**
-		 * Returns a new instance of a UIBase component to be used as the actual
-		 * column in the grid.
-		 *
-		 *  @langversion 3.0
-		 *  @playerversion Flash 10.2
-		 *  @playerversion AIR 2.6
-		 *  @productversion Royale 0.9.7
-		 */
-		public function createColumn():IStyledUIBase
-		{
-			return new DataGridColumnList();
+	}
+
+	/**
+	 * Returns a new instance of a UIBase component to be used as the actual
+	 * column in the grid.
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10.2
+	 *  @playerversion AIR 2.6
+	 *  @productversion Royale 0.9.7
+	 */
+	public function createColumn():IStyledUIBase
+	{
+		return new DataGridColumnList();
+	}
+
+
+	private var _visible:Boolean = true;
+	public function set visible(value:Boolean):void{
+		if (value != _visible) {
+			_visible = value;
+			//somehow, invalidate layout
 		}
 	}
+
+	public function get visible():Boolean{
+		return _visible;
+	}
+}
 }
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridColumnWidth.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridColumnWidth.as
new file mode 100644
index 0000000..8821dce
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridColumnWidth.as
@@ -0,0 +1,153 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.jewel.supportClasses.datagrid {
+
+	COMPILE::JS{
+		import org.apache.royale.core.WrappedHTMLElement;
+		import org.apache.royale.core.HTMLElementWrapper
+	}
+
+	import org.apache.royale.core.ILayoutView;
+	import org.apache.royale.core.ILayoutChild;
+
+	/**
+	 * internal use only
+	 *
+	 *  @langversion 3.0
+	 *  @royalesuppressexport
+	 */
+	public class DataGridColumnWidth {
+		public static const DEFAULT:String = null;
+		public static const EXPLICIT_PERCENT:String = '%';
+		public static const EXPLICIT_PIXELS:String = '#';
+
+
+		public static function createFromColumn(size:Number, type:String, denominator:DataGridWidthDenominator):DataGridColumnWidth{
+			var ret:DataGridColumnWidth = new DataGridColumnWidth();
+			ret._value = size;
+			ret.widthType = type;
+			ret.denominator = denominator;
+			return ret;
+		}
+
+
+		//public var value:Number = 0;
+		private var _value:Number = 0;
+
+		public var widthType:String;
+		public var denominator:DataGridWidthDenominator;
+
+		public var column:IDataGridColumn;
+
+		public function isPixel():Boolean {
+			return widthType == EXPLICIT_PIXELS;
+		}
+
+		public function isPercent():Boolean {
+			return widthType == EXPLICIT_PERCENT;
+		}
+
+		public function isDefault():Boolean {
+			return widthType == DEFAULT;
+		}
+
+		public function getValue():Number {
+			if (isPercent() && denominator && denominator.value > 0) {
+				return _value * 0.01 * denominator.value;
+			}
+			return _value;
+		}
+
+		public function setFrom(other:DataGridColumnWidth):void{
+			if (other) {
+				_value = other._value;
+				widthType = other.widthType;
+				denominator = other.denominator;
+			}
+		}
+
+
+		COMPILE::JS
+		/**
+		 * @royaleignorecoercion org.apache.royale.core.HTMLElementWrapper;
+		 * @royaleignorecoercion HTMLElement;
+		 */
+		public function configureWidth(content:ILayoutChild/*, header:Boolean*/):void{
+			//this is necessary to
+			var targetElement:HTMLElement = (content as HTMLElementWrapper).element;
+
+			if (isPercent() && denominator && denominator.value > 0){
+				var assigned:Number = uint(_value);//value/100 * denominator.value;
+				targetElement.style['flex'] = assigned + ' ' + assigned + ' 0px';
+				targetElement.style['minWidth'] = '';
+				targetElement.style['maxWidth'] = '';
+				content.width = NaN;
+			} else if (isPixel()) {
+				targetElement.style['flex'] =  '0 0 '  + _value +'px';
+				targetElement.style['minWidth'] =  _value +'px';
+				targetElement.style['maxWidth'] =  _value +'px';
+				content.width = _value;
+			} else if (isDefault()) {
+				targetElement.style['flex'] = '';
+				targetElement.style['minWidth'] = '';
+				targetElement.style['maxWidth'] = '';
+				content.width = NaN;
+			}
+		}
+
+		COMPILE::SWF
+		public function configureWidth(content:ILayoutChild):void{
+			//only for option-with-swf compilation of Jewel, for now.
+		}
+
+
+		COMPILE::JS
+		public function applyRightOffset(content:ILayoutChild, offset:Number):void{
+			//this is to support the rightmost button width variation when the list area has a vertical scrollbar
+			var targetElement:HTMLElement = (content as HTMLElementWrapper).element;
+			if (!offset) {
+				configureWidth(content);
+				targetElement.style['paddingRight'] = '';
+				return;
+			}
+			var orig:Number = _value;
+			if (isPixel() || isDefault()) {
+				_value = _value + offset;
+				configureWidth(content);
+				_value = orig;
+			}
+			targetElement.style['paddingRight'] = offset + 'px'
+
+			/*} else {
+				console.log('todo...investigate rightmost');
+			}*/
+
+		}
+
+
+		public function get value():Number {
+			return _value;
+		}
+
+		public function set value(value:Number):void {
+			_value = value;
+		}
+	}
+
+}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridButtonBar.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridWidthDenominator.as
similarity index 58%
copy from frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridButtonBar.as
copy to frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridWidthDenominator.as
index 414d11d..c53b346 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridButtonBar.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/datagrid/DataGridWidthDenominator.as
@@ -16,38 +16,16 @@
 //  limitations under the License.
 //
 ////////////////////////////////////////////////////////////////////////////////
-package org.apache.royale.jewel.supportClasses.datagrid
-{
-    import org.apache.royale.jewel.ButtonBar;
-
-    COMPILE::JS
-    {
-    import org.apache.royale.core.WrappedHTMLElement;            
-    }
+package org.apache.royale.jewel.supportClasses.datagrid {
 
 	/**
-	 *  The DataGridButtonBar class extends ButtonBar and provides a class for styling
-	 *  the header region of the DataGrid.
-	 *  
+	 * internal use only
+	 *
 	 *  @langversion 3.0
-	 *  @playerversion Flash 10.2
-	 *  @playerversion AIR 2.6
-	 *  @productversion Royale 0.9.7
+	 *  @royalesuppressexport
 	 */
-	public class DataGridButtonBar extends ButtonBar
-	{
-		/**
-		 *  constructor.
-		 *
-		 *  @langversion 3.0
-		 *  @playerversion Flash 10.2
-		 *  @playerversion AIR 2.6
-		 *  @productversion Royale 0.9.7
-		 */
-		public function DataGridButtonBar()
-		{
-			super();
-			typeNames = "jewel buttonbar header";
-		}
+	public class DataGridWidthDenominator {
+		public var value:int = -1;
 	}
-}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/table/ITableColumn.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/table/ITableColumn.as
index 438cc22..9e31f63 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/table/ITableColumn.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/supportClasses/table/ITableColumn.as
@@ -109,5 +109,12 @@ package org.apache.royale.jewel.supportClasses.table
 		 */
 		function get columnLabelAlign():String;
 		function set columnLabelAlign(value:String):void;
+
+
+		function get percentColumnWidth():Number
+
+
+		function get explicitColumnWidth():Number
+
 	}
 }
\ No newline at end of file
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/utils/observeElementSize.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/utils/observeElementSize.as
new file mode 100644
index 0000000..7e6ce77
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/utils/observeElementSize.as
@@ -0,0 +1,142 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.utils{
+    
+    /**
+     *
+     * @royaleignorecoercion Class
+     */
+    COMPILE::JS
+    public function observeElementSize(target:HTMLElement , callback:Function, stop:Boolean=false):Boolean{
+        var isNative:Boolean = true;
+        if (window['ResizeObserver'] !== undefined) {
+            var existing:Object /* ResizeObserver */ = referenceMap.get(callback);
+            if (existing) {
+                if (stop) existing['unobserve'](target)
+                else existing['observe'](target)
+            } else {
+                if (!stop) {
+                    var RO:Class = window['ResizeObserver'] as Class;
+                    existing = new RO(callback);
+                    referenceMap.set(callback, existing);
+                    existing['observe'](target);
+                }
+            }
+        } else {
+            isNative = false;
+            var callbacks:Array ;
+            if (timerFunc == null) {
+                if (stop) return false;
+                callbacks = [];
+                referenceMap.set(observeElementSize, callbacks);
+
+                checkFunc = function(el:HTMLElement ,callback:Function):void{
+                    var checks:Object;
+                    var change:Boolean;
+                    if (referenceMap.has(el)) {
+                        checks = referenceMap.get(el);
+                        var latest:Number = el.offsetHeight;
+                        if (latest != checks['h'] || checks['ch'] != el.clientHeight) {
+                            change = true;
+                            checks['h'] = latest;
+                            checks['ch'] = el.clientHeight;
+                        }
+                        latest = el.offsetWidth;
+                        if (latest != checks['w'] || checks['cw'] != el.clientWidth) {
+                            change = true;
+                            checks['w'] = latest;
+                            checks['cw'] = el.clientWidth;
+                        }
+                    } else {
+                        //setup
+                        checks = {
+                            'h' : el.offsetHeight,
+                            'ch': el.clientHeight,
+                            'w' : el.offsetWidth,
+                            'cw': el.clientWidth
+                        };
+                        referenceMap.set(el, checks);
+                        change = true;
+                    }
+                    if (change) {
+                        try{
+                            callback();
+                        } catch(e:Error){}
+                    }
+                }
+                timerFunc = function():void{
+                    var l:uint = callbacks.length;
+                    for (var i:uint = 0; i<l;i++) {
+                        var cb:Function = callbacks[i]
+                        var els:Array = referenceMap.get(cb);
+                        if (els) {
+                            var l2:uint = els.length;
+                            for (var ii:uint = 0; ii<l2;ii++) {
+                                checkFunc(els[ii], cb);
+                            }
+                        }
+                    }
+                }
+                timerFunc['interval'] = setInterval(timerFunc, 50);
+            } else {
+                callbacks = referenceMap.get(observeElementSize);
+            }
+            var elements:Array;
+            var idcb:int = callbacks.indexOf(callback);
+            if (stop) {
+                if (idcb != -1) {
+                    callbacks.splice(idcb,1);
+                    if (callbacks.indexOf(callback) == -1) {
+                        referenceMap.delete(callback);
+                    }
+                    if (callbacks.length == 0) {
+                        referenceMap = new WeakMap();
+                        if (timerFunc) {
+                            clearInterval(timerFunc['interval']);
+                            timerFunc = null;
+                        }
+                        checkFunc = null;
+                    }
+                }
+
+            } else {
+                callbacks.push(callback);
+                elements = referenceMap.get(callback);
+                if (!elements) {
+                    elements = [];
+                    referenceMap.set(callback, elements);
+                }
+                if (elements.indexOf(target) == -1) elements.push(target);
+            }
+
+        }
+        return isNative;
+    }
+
+}
+
+
+COMPILE::JS
+var referenceMap:WeakMap = new WeakMap();
+
+COMPILE::JS
+var timerFunc:Function;
+
+COMPILE::JS
+var checkFunc:Function;
\ No newline at end of file
diff --git a/frameworks/projects/Jewel/src/main/sass/components/_datagrid.sass b/frameworks/projects/Jewel/src/main/sass/components/_datagrid.sass
index 71b3254..5ee6669 100644
--- a/frameworks/projects/Jewel/src/main/sass/components/_datagrid.sass
+++ b/frameworks/projects/Jewel/src/main/sass/components/_datagrid.sass
@@ -16,7 +16,6 @@
 //  limitations under the License.
 //
 ////////////////////////////////////////////////////////////////////////////////
-
 // Jewel DataGrid
 
 // DataGrid variables
@@ -28,12 +27,23 @@
     
     .jewel.buttonbar.header
         width: 100%
+        flex: 0 0 auto
+
+        .jewel.button
+            padding-left: 2px
+            padding-right: 2px
+            justify-content: flex-start
+            width: 100%
 
     .listarea
         width: 100%
-        flex: 1 1 0%
+        flex: 1 1 auto
 
     .jewel.list.column
+        padding-left: 0
+        padding-right: 0
+        position: relative
+        min-height: 100%
 
         &.first
         
@@ -43,14 +53,18 @@
         
         .jewel.item.datagrid
             width: 100%
-        
+
+    span:empty:before
+        content: "@@ZERO_WIDTH_SPACE"
+        //content: "\200b" <-- this does not survive sass compilation, so instead using a token for replacement in a post-sass processing step above
+
 j|DataGrid
     IDataGridPresentationModel: ClassReference("org.apache.royale.jewel.beads.models.DataGridPresentationModel")
     IBeadView: ClassReference("org.apache.royale.jewel.beads.views.DataGridView")
     IBeadModel: ClassReference("org.apache.royale.html.beads.models.DataGridCollectionViewModel")
     IBeadLayout: ClassReference("org.apache.royale.jewel.beads.layouts.DataGridLayout")
     headerClass: ClassReference("org.apache.royale.jewel.supportClasses.datagrid.DataGridButtonBar")
-    headerLayoutClass: ClassReference("org.apache.royale.jewel.beads.layouts.ButtonBarLayout")
+    headerLayoutClass: ClassReference("org.apache.royale.jewel.beads.layouts.DataGridColumnLayout")
     listAreaClass: ClassReference("org.apache.royale.jewel.supportClasses.datagrid.DataGridListArea")
     columnClass: ClassReference("org.apache.royale.jewel.supportClasses.datagrid.DataGridColumnList")
 
@@ -69,3 +83,4 @@ j|DataGridColumnList
 
 //Nothing to change from j|ButtonBar
 j|DataGridButtonBar
+    IItemRenderer: ClassReference("org.apache.royale.jewel.itemRenderers.DatagridHeaderRenderer")
diff --git a/frameworks/projects/Jewel/src/main/sass/components/_layout.sass b/frameworks/projects/Jewel/src/main/sass/components/_layout.sass
index fa0981e..4ef7be2 100644
--- a/frameworks/projects/Jewel/src/main/sass/components/_layout.sass
+++ b/frameworks/projects/Jewel/src/main/sass/components/_layout.sass
@@ -94,7 +94,7 @@ $gap-size: 10px !default
 		&.pixelWidths
 			> *
 				flex: none
-		&.proportinalWidths
+		&.proportionalWidths
 			> *
 				flex: 1 0
 		&.percentWidths
diff --git a/frameworks/themes/JewelTheme/src/main/resources/defaults.css b/frameworks/themes/JewelTheme/src/main/resources/defaults.css
index 8beba8e..f081b97 100644
--- a/frameworks/themes/JewelTheme/src/main/resources/defaults.css
+++ b/frameworks/themes/JewelTheme/src/main/resources/defaults.css
@@ -463,6 +463,19 @@ j|CardActions {
   background: url("data:image/svg+xml,%3Csvg viewBox='0 0 12 8' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg transform='translate(0.000000, -1.000000)' fill='%23cccccc' fill-rule='nonzero'%3E%3Cg transform='translate(-2.000000, 0.000000)'%3E%3Cpolygon transform='translate(8.000000, 4.705000) scale(1, -1) translate(-8.000000, -4.705000) ' points='3.41 8.41 8 3.83 12.59 8.41 14 7 8 1 2 7'%3E%3C/polygon%3E%3C/g [...]
 }
 
+.jewel.datagrid {
+  background: linear-gradient(white, #f3f3f3);
+  border: 1px solid #b3b3b3;
+  box-shadow: inset 0 1px 0 white;
+  border-radius: 0.25rem;
+}
+.jewel.datagrid .jewel.buttonbar.header {
+  background: linear-gradient(#f3f3f3, #e6e6e6);
+  border: 0 none;
+  box-shadow: none;
+  border-top-left-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
 .jewel.datagrid .jewel.buttonbar.header .jewel.button.first {
   border-bottom-left-radius: 0;
 }
@@ -470,10 +483,10 @@ j|CardActions {
   border-bottom-right-radius: 0;
 }
 .jewel.datagrid .listarea {
-  border-top-width: 0px;
+  border-top-width: 1px;
   border-left-width: 0px;
   border-right-width: 0px;
-  border-bottom-width: 1px;
+  border-bottom-width: 0px;
   border-bottom-left-radius: 0.25rem;
   border-bottom-right-radius: 0.25rem;
   border-style: solid;
@@ -497,7 +510,12 @@ j|CardActions {
   border-bottom-right-radius: 0.25rem;
 }
 .jewel.datagrid .jewel.list.column .jewel.item.datagrid {
+  border-top: none;
+  border-left: none;
+  border-right: none;
   border-bottom: 1px solid #ededed;
+  border-right: 0;
+  border-radius: 0;
 }
 .jewel.datagrid .jewel.list.column .jewel.item.datagrid.primary.hovered {
   background: #75c5f5;
diff --git a/frameworks/themes/JewelTheme/src/main/sass/components-primary/_datagrid.sass b/frameworks/themes/JewelTheme/src/main/sass/components-primary/_datagrid.sass
index 616d80b..6152d7f 100644
--- a/frameworks/themes/JewelTheme/src/main/sass/components-primary/_datagrid.sass
+++ b/frameworks/themes/JewelTheme/src/main/sass/components-primary/_datagrid.sass
@@ -21,9 +21,29 @@
 
 // DataGrid variables
 .jewel.datagrid
+    @if $flat
+        background: lighten($default-color, 15%)
+        border: 1px solid $default-color
+        box-shadow: none
+    @else
+        background: linear-gradient(lighten($default-color, 15%), lighten($default-color, 10%))
+        border: 1px solid darken($default-color, 15%)
+        box-shadow: inset 0 1px 0 lighten($default-color, 20%)
+        border-radius: $border-radius
+
 
     .jewel.buttonbar.header
-    
+        @if $flat
+            background: $default-color
+            border: 0 none
+            box-shadow: none
+        @else
+            background: linear-gradient(lighten($default-color, 10%), lighten($default-color, 5%))
+            border: 0 none
+            box-shadow: none
+            border-top-left-radius: $border-radius
+            border-top-right-radius: $border-radius
+
         .jewel.button
             &.first
                 border-bottom-left-radius: 0
@@ -32,10 +52,10 @@
                 border-bottom-right-radius: 0
     
     .listarea
-        border-top-width: 0px
+        border-top-width: 1px
         border-left-width: 0px
         border-right-width: 0px
-        border-bottom-width: 1px
+        border-bottom-width: 0px
         border-bottom-left-radius: $border-radius
         border-bottom-right-radius: $border-radius
         border-style: solid
@@ -74,7 +94,12 @@
                 border-bottom-right-radius: $border-radius
             
             .jewel.item.datagrid
+                border-top: none
+                border-left: none
+                border-right: none
                 border-bottom: 1px solid lighten($default-color, 8%)
+                border-right: 0
+                border-radius: 0
                 
                 &.primary
                     &.hovered