Commits

Anonymous committed 8e0d54a

Some rendering/presentation fixes.

Comments (0)

Files changed (10)

asmathema/src/asmathema/flex/layouts/TableCell.as

 		 * @defaultValue 1
 		 */
 		function get rowSpan():uint;
+		function validateNow():void;
 	}
 }

asmathema/src/asmathema/flex/layouts/TableLayout.as

 package asmathema.flex.layouts
 {
+	import flash.events.Event;
 	import mx.core.IVisualElement;
 	import asmathema.collections.sets.FiniteSetBuilder;
 	import asmathema.collections.sets.HashSetBuilder;
 		{
 			super();
 		}
+		private var _horizontalGap:uint = 0;
+		private var _paddingBottom:uint = 0;
+		private var _paddingLeft:uint = 0;
+		private var _paddingRight:uint = 0;
+		private var _paddingTop:uint = 0;
+		private var _verticalGap:uint = 0;
 		private var measuredHeight:Number;
 		private var measuredWidth:Number;
 
+		public function set gap(v:uint):void
+		{
+			horizontalGap = verticalGap = v;
+		}
+
+		[Bindable(event="horizontalGapChanged")]
+		public function get horizontalGap():uint
+		{
+			return _horizontalGap;
+		}
+
+		public function set horizontalGap(value:uint):void
+		{
+			if (_horizontalGap != value)
+			{
+				_horizontalGap = value;
+				invalidateTargetSizeAndDisplayList();
+				dispatchEvent(new Event("horizontalGapChanged"));
+			}
+		}
+
 		override public function measure():void
 		{
 			target.measuredHeight = measuredHeight;
 			target.measuredWidth = measuredWidth;
 		}
 
+		public function set padding(value:uint):void
+		{
+			paddingBottom = value;
+			paddingLeft = value;
+			paddingRight = value;
+			paddingTop = value;
+		}
+
+		[Bindable(event="paddingBottomChanged")]
+		public function get paddingBottom():uint
+		{
+			return _paddingBottom;
+		}
+
+		public function set paddingBottom(value:uint):void
+		{
+			if (_paddingBottom != value)
+			{
+				_paddingBottom = value;
+				invalidateTargetSizeAndDisplayList();
+				dispatchEvent(new Event("paddingBottomChanged"));
+			}
+		}
+
+		public function set paddingHorizontal(value:uint):void
+		{
+			paddingLeft = value;
+			paddingRight = value;
+		}
+
+		[Bindable(event="paddingLeftChanged")]
+		public function get paddingLeft():uint
+		{
+			return _paddingLeft;
+		}
+
+		public function set paddingLeft(value:uint):void
+		{
+			if (_paddingLeft != value)
+			{
+				_paddingLeft = value;
+				invalidateTargetSizeAndDisplayList();
+				dispatchEvent(new Event("paddingLeftChanged"));
+			}
+		}
+
+		[Bindable(event="paddingRightChanged")]
+		public function get paddingRight():uint
+		{
+			return _paddingRight;
+		}
+
+		public function set paddingRight(value:uint):void
+		{
+			if (_paddingRight != value)
+			{
+				_paddingRight = value;
+				invalidateTargetSizeAndDisplayList();
+				dispatchEvent(new Event("paddingRightChanged"));
+			}
+		}
+
+		[Bindable(event="paddingTopChanged")]
+		public function get paddingTop():uint
+		{
+			return _paddingTop;
+		}
+
+		public function set paddingTop(value:uint):void
+		{
+			if (_paddingTop != value)
+			{
+				_paddingTop = value;
+				invalidateTargetSizeAndDisplayList();
+				dispatchEvent(new Event("paddingTopChanged"));
+			}
+		}
+
+		public function set paddingVertical(value:uint):void
+		{
+			paddingBottom = value;
+			paddingTop = value;
+		}
+
 		/// :TODO: Add padding & gaps.
 		override public function updateDisplayList(containerWidth:Number,
 												   containerHeight:Number):void
 			for (var i:int = 0; i < n; ++i)
 			{
 				var element:IVisualElement = target.getElementAt(i);
-				if (element is TableCell)
+				if (element is TableCell && element.includeInLayout)
 					matrix.addCell(element as TableCell);
 			}
-			var y:Number = 0.0;
+			var y:Number = paddingTop;
+			measuredWidth = 0;
 			const traversedCells:FiniteSetBuilder = new HashSetBuilder();
 			for (var row:uint = 0; row < matrix.rows; ++row)
 			{
-				var x:Number = 0.0;
+				var x:Number = paddingLeft;
 				var rowHeight:Number = matrix.getPreferredHeight(row);
 				for (var col:uint = 0; col < matrix.columns; ++col)
 				{
 						cell.setLayoutBoundsPosition(x, y);
 						cell.setLayoutBoundsSize(colWidth, rowHeight);
 					}
-					x += colWidth;
+					x += colWidth + horizontalGap;
 				}
-				y += rowHeight;
+				measuredWidth =
+					Math.max(measuredWidth, x + paddingRight - horizontalGap);
+				y += rowHeight + verticalGap;
 			}
-			measuredWidth = x;
-			measuredHeight = y;
-			target.setLayoutBoundsSize(x, y);
-			target.setContentSize(x, y);
+			measuredHeight = y + paddingBottom - verticalGap;
+			target.setLayoutBoundsSize(measuredWidth, measuredHeight);
+			target.setContentSize(measuredWidth, measuredHeight);
+		}
+
+		[Bindable(event="verticalGapChanged")]
+		public function get verticalGap():uint
+		{
+			return _verticalGap;
+		}
+
+		public function set verticalGap(value:uint):void
+		{
+			if (_verticalGap != value)
+			{
+				_verticalGap = value;
+				invalidateTargetSizeAndDisplayList();
+				dispatchEvent(new Event("verticalGapChanged"));
+			}
+		}
+
+		private function invalidateTargetSizeAndDisplayList():void
+		{
+			if (target)
+			{
+				target.invalidateSize();
+				target.invalidateDisplayList();
+			}
 		}
 	}
 }

asmathema/src/asmathema/flex/layouts/TableMatrix.as

 package asmathema.flex.layouts
 {
 	import flash.sampler.getMemberNames;
+	import spark.layouts.TileLayout;
 
 	public final class TableMatrix
 	{

asmathema/src/asmathema/flex/renderers/BlockPresentationConverter.as

 	import asmathema.mathML.MathMLPresentation;
 	import spark.components.DataRenderer;
 	import spark.layouts.BasicLayout;
+	import spark.layouts.HorizontalLayout;
+	import spark.layouts.VerticalAlign;
 	import spark.layouts.VerticalLayout;
+	import spark.layouts.supportClasses.LayoutBase;
 
 	public final class BlockPresentationConverter
 	{
 		private static const RENDERER_FACTORIES:Dictionary =
 			createRendererDictionary();
 
+		public static function createDefaultLayout():LayoutBase
+		{
+			const layout:HorizontalLayout = new HorizontalLayout();
+			layout.gap = 0;
+			layout.verticalAlign = VerticalAlign.MIDDLE;
+			return layout;
+		}
+
 		private static function createRendererDictionary():Dictionary
 		{
 			const d:Dictionary = new Dictionary();
 			else
 			{
 				renderer = new BlockRenderer();
-				renderer.percentWidth = 100;
-				renderer.layout = new HorizontalFlowLayout();
-				HorizontalFlowLayout(renderer.layout).verticalGap = 6;
+				renderer.layout = createDefaultLayout();
 			}
 			renderer.data = data;
 			return renderer;

asmathema/src/asmathema/flex/renderers/BlockRenderer.mxml

 				xmlns:s="library://ns.adobe.com/flex/spark"
 				xmlns:mx="library://ns.adobe.com/flex/halo"
 				xmlns:layouts="asmathema.flex.layouts.*"
-				dataChange="dataInvalid = true; invalidateDisplayList()"
+				dataChange="dataChangeHandler(event)"
 				xmlns:renderers="asmathema.flex.renderers.*">
 
 	<fx:Script>
 		<![CDATA[
+			import mx.events.FlexEvent;
 			import asmathema.flex.renderers.RendererData;
 			private var _converter:BlockPresentationConverter;
 			private var dataInvalid:Boolean = false;
 				}
 			}
 
+			override public function getPreferredBoundsHeight(postLayoutTransform:Boolean =
+				true):Number
+			{
+				if (numElements == 0 && data != null)
+					validateNow();
+				if (numElements == 0)
+					return 0;
+				return getElementAt(0).getPreferredBoundsHeight(postLayoutTransform);
+			}
+
+			override public function getPreferredBoundsWidth(postLayoutTransform:Boolean =
+				true):Number
+			{
+				if (numElements == 0 && data != null)
+					validateNow();
+				if (numElements == 0)
+					return 0;
+				return getElementAt(0).getPreferredBoundsWidth(postLayoutTransform);
+			}
+
+			protected function dataChangeHandler(event:FlexEvent):void
+			{
+				dataInvalid = true;
+				includeInLayout = data != null
+				invalidateDisplayList();
+				invalidateSize();
+				invalidateParentSizeAndDisplayList();
+			}
+
 			override protected function updateDisplayList(unscaledWidth:Number,
 														  unscaledHeight:Number):void
 			{
 
 	<s:layout>
 
-		<s:VerticalLayout/>
+		<s:BasicLayout/>
 	</s:layout>
 </s:DataRenderer>

asmathema/src/asmathema/flex/renderers/InlinePresentationConverter.as

 			if (element.attribute(MathMLAttributes.MATHSIZE).length() == 1)
 			{
 				const baseSize:Number =
-					format.fontSize is Number ? format.fontSize : 12;
-				switch (element.attribute(MathMLAttributes.MATHSIZE).toXMLString())
+					isNaN(format.fontSize) ? 12 : format.fontSize;
+				const mathSize:String =
+					element.attribute(MathMLAttributes.MATHSIZE).toXMLString();
+				switch (mathSize)
 				{
 					case MathMLMathSize.BIG:
 					{
-						format.fontSize = baseSize * 1.25;
+						format.fontSize = baseSize * 4 / 3;
 						break;
 					}
 					case MathMLMathSize.NORMAL:
 					}
 					case MathMLMathSize.SMALL:
 					{
-						format.fontSize = baseSize * 0.75;
+						format.fontSize = baseSize * 3 / 4;
 						break;
 					}
 					default:
 					{
-						// :TODO:Calculate size
+						format.fontSize = parseFloat(mathSize);
+							// :TODO:Calculate other units
 					}
 				}
 			}
 			else if (data.presentation.nodeKind() == "text")
 			{
 				const span:SpanElement = new SpanElement();
+				span.whiteSpaceCollapse = WhiteSpaceCollapse.PRESERVE;
 				span.format = data.formatBase;
 				span.text = data.presentation.toXMLString();
 				return Vector.<FlowLeafElement>([span]);
 
 		private function convertElement(data:RendererData):Vector.<FlowLeafElement>
 		{
+			default xml namespace=MathML.NAMESPACE.uri;
 			const format:ITextLayoutFormat = readTextFormat(data);
 			var vector:Vector.<FlowLeafElement> =
 				new Vector.<FlowLeafElement>();
 					convert(new RendererData(child, format));
 				vector = vector.concat(subvector);
 			}
-			if (data.presentation.attribute(MathMLAttributes.SEPARATOR) == "true")
+			if (data.presentation.@separator == "true")
 				vector =
 					vector.concat(space(new RendererData(<mspace width="8"/>,
 														 data.formatBase)));
-			else if (data.presentation.attribute(MathMLAttributes.FORM) == MathMLForm.INFIX)
+			else if (data.presentation.@form == MathMLForm.INFIX)
 			{
 				vector =
 					space(new RendererData(<mspace width="8"/>,

asmathema/src/asmathema/flex/renderers/InlineRenderer.mxml

 			import flashx.textLayout.elements.SpanElement;
 			import flashx.textLayout.elements.TextFlow;
 			import flashx.textLayout.formats.ITextLayoutFormat;
+			import flashx.textLayout.formats.WhiteSpaceCollapse;
 			import asmathema.flex.renderers.*;
 			[Bindable]
 			public var formatBase:ITextLayoutFormat = null;
 				}
 			}
 
+			override public function getPreferredBoundsHeight(postLayoutTransform:Boolean =
+				true):Number
+			{
+				return label.getPreferredBoundsHeight(postLayoutTransform) + 6;
+			}
+
+			override public function getPreferredBoundsWidth(postLayoutTransform:Boolean =
+				true):Number
+			{
+				return label.getExplicitOrMeasuredWidth();
+			}
+
 			private function createTextFlow(data:RendererData):TextFlow
 			{
 				const flow:TextFlow = new TextFlow();
+				flow.whiteSpaceCollapse = WhiteSpaceCollapse.PRESERVE;
 				const p:ParagraphElement = new ParagraphElement();
+				p.whiteSpaceCollapse = WhiteSpaceCollapse.PRESERVE;
 				try
 				{
 					if (data != null)
 	</s:layout>
 
 	<s:RichText id="label"
+				whiteSpaceCollapse="preserve"
 				textFlow="{createTextFlow(data as RendererData)}"/>
 </s:DataRenderer>

asmathema/src/asmathema/flex/renderers/TableCellRenderer.as

 		public function TableCellRenderer(row:uint, columns:uint, rows:uint)
 		{
 			super();
-			layout = new HorizontalFlowLayout();
-			HorizontalFlowLayout(layout).verticalGap = 6;
+			minHeight = 12 * columns;
+			minWidth = 12 * rows;
+			layout = BlockPresentationConverter.createDefaultLayout();
 			_row = row;
 			_columns = columns;
 			_rows = rows;

asmathema/src/asmathema/flex/renderers/TableRenderer.as

 
 		override protected function createLayout():LayoutBase
 		{
-			return new TableLayout();
+			const layout:TableLayout = new TableLayout();
+			layout.gap = 6;
+			return layout;
 		}
 
 		override protected function render(data:RendererData):void

asmathema/src/asmathema/mathML/presenters/MathMLPresenter.as

 			row.appendChild(operator);
 			// :TODO: Reinstate after entities are implemented.
 			//row.appendChild(CommonElements.APPLY_FUNCTION.copy());
+			// :TODO: Remove after entities are implemented.
+			row.appendChild(<mspace xmlns={MathML.NAMESPACE} width="4px"/>);
 			if (args.length == 1)
-			{
-				// :TODO: Remove after entities are implemented.
-				row.appendChild(<mspace xmlns={MathML.NAMESPACE} width="4px"/>);
 				row.appendChild(args[0]);
-			}
 			else
 			{
 				const fenced:XML = <mfenced xmlns={MathML.NAMESPACE}/>;