You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ah...@apache.org on 2019/12/23 06:52:39 UTC
[royale-asjs] 01/09: FormItemSkin clean compilation. But will it
work?
This is an automated email from the ASF dual-hosted git repository.
aharui pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
commit 8047afb888a484e5d71dc4663536ba0a1611d9eb
Author: Alex Harui <ah...@apache.org>
AuthorDate: Tue Dec 10 11:43:59 2019 -0800
FormItemSkin clean compilation. But will it work?
---
.../org/apache/royale/html/beads/ContainerView.as | 28 +-
.../MXRoyale/src/main/resources/defaults.css | 1 +
.../MXRoyale/src/main/royale/MXRoyaleClasses.as | 3 +
.../royale/mx/containers/errors/ConstraintError.as | 58 +
.../containers/utilityClasses/ConstraintColumn.as | 6 +-
.../mx/containers/utilityClasses/ConstraintRow.as | 6 +-
.../MXRoyale/src/main/royale/mx/controls/Button.as | 11 -
.../src/main/royale/mx/core/ILayoutElement.as | 5 +-
.../src/main/royale/mx/core/UIComponent.as | 70 +-
.../SparkRoyale/src/main/resources/defaults.css | 12 +-
.../src/main/resources/spark-royale-manifest.xml | 4 +
.../src/main/royale/SparkRoyaleClasses.as | 5 +
.../src/main/royale/spark/components/Label.as | 11 +-
.../components/beads/SkinnableContainerView.as | 26 +-
...nableContainerView.as => SparkContainerView.as} | 9 +-
.../components/beads/SparkSkinScrollingViewport.as | 168 ++
.../spark/components/supportClasses/ButtonBase.as | 9 -
.../supportClasses/SkinnableComponent.as | 6 +-
.../components/supportClasses/SkinnableTextBase.as | 16 +-
.../spark/components/supportClasses/TextBase.as | 13 +-
.../main/royale/spark/layouts/ConstraintLayout.as | 1984 ++++++++++++++++++++
.../main/royale/spark/layouts/FormItemLayout.as | 10 +-
.../src/main/royale/spark/layouts/FormLayout.as | 6 +-
.../royale/spark/skins/spark/FormItemSkin.mxml | 188 ++
.../main/royale/spark/skins/spark/FormSkin.mxml | 97 +
25 files changed, 2651 insertions(+), 101 deletions(-)
diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ContainerView.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ContainerView.as
index fae6a90..0d242a6 100644
--- a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ContainerView.as
+++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ContainerView.as
@@ -136,12 +136,17 @@ package org.apache.royale.html.beads
createViewport();
- var chost:IContainer = host as IContainer;
- chost.strandChildren.addElement(viewport.contentView);
+ addViewport();
super.strand = value;
}
+ protected function addViewport():void
+ {
+ var chost:IContainer = host as IContainer;
+ chost.strandChildren.addElement(viewport.contentView);
+ }
+
/**
* Called when the host is ready to complete its setup (usually after its size has been
* determined).
@@ -368,14 +373,19 @@ package org.apache.royale.html.beads
_viewport = loadBeadFromValuesManager(IViewport, "iViewport", _strand) as IViewport;
if (_viewport) {
- var chost:IContainer = host as IContainer;
- // add the viewport's contentView to this host ONLY if
- // the contentView is not the host itself, which is likely
- // most situations.
- if (chost != null && chost != _viewport.contentView) {
- chost.addElement(_viewport.contentView);
- }
+ addViewport();
}
}
+
+ protected function addViewport():void
+ {
+ var chost:IContainer = host as IContainer;
+ // add the viewport's contentView to this host ONLY if
+ // the contentView is not the host itself, which is likely
+ // most situations.
+ if (chost != null && chost != _viewport.contentView) {
+ chost.addElement(_viewport.contentView);
+ }
+ }
}
}
diff --git a/frameworks/projects/MXRoyale/src/main/resources/defaults.css b/frameworks/projects/MXRoyale/src/main/resources/defaults.css
index a1dea0c..be9e88f 100644
--- a/frameworks/projects/MXRoyale/src/main/resources/defaults.css
+++ b/frameworks/projects/MXRoyale/src/main/resources/defaults.css
@@ -124,6 +124,7 @@ Alert
Button
{
IBeadModel: ClassReference("org.apache.royale.html.beads.models.ImageAndTextModel");
+ font-weight: bold;
}
Canvas
diff --git a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
index c001742..77e4881 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
@@ -57,6 +57,9 @@ internal class MXRoyaleClasses
import mx.containers.beads.CanvasLayout; CanvasLayout;
import mx.containers.beads.layouts.BasicLayout; BasicLayout;
import mx.controls.beads.AlertView; AlertView;
+ import mx.containers.errors.ConstraintError; ConstraintError;
+ import mx.containers.utilityClasses.ConstraintColumn; ConstraintColumn;
+ import mx.containers.utilityClasses.ConstraintRow; ConstraintRow;
import mx.containers.gridClasses.GridColumnInfo; GridColumnInfo;
import mx.containers.gridClasses.GridRowInfo; GridRowInfo;
import mx.events.CloseEvent; CloseEvent;
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/errors/ConstraintError.as b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/errors/ConstraintError.as
new file mode 100644
index 0000000..da029e5
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/errors/ConstraintError.as
@@ -0,0 +1,58 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.containers.errors
+{
+
+/**
+ * This error is thrown when a constraint expression is not configured properly;
+ * for example, if the GridColumn reference is invalid.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+public class ConstraintError extends Error
+{
+// include "../../core/Version.as";
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param message A message providing information about the error cause.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function ConstraintError(message:String)
+ {
+ super(message);
+ }
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/utilityClasses/ConstraintColumn.as b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/utilityClasses/ConstraintColumn.as
index 4e8de23..527b0af 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/utilityClasses/ConstraintColumn.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/utilityClasses/ConstraintColumn.as
@@ -27,13 +27,13 @@ import flash.events.Event;
import flash.events.IEventDispatcher;
*/
import mx.core.IInvalidating;
-/*
import mx.core.mx_internal;
+/*
import mx.core.IMXMLObject;
import flash.events.EventDispatcher;
-use namespace mx_internal;
*/
+use namespace mx_internal;
/**
* The ConstraintColumn class partitions an absolutely
@@ -76,7 +76,7 @@ public class ConstraintColumn extends EventDispatcher //implements IMXMLObject
// Variables
//
//--------------------------------------------------------------------------
- protected var contentSize:Boolean = false;
+ mx_internal var contentSize:Boolean = false;
//--------------------------------------------------------------------------
//
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/utilityClasses/ConstraintRow.as b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/utilityClasses/ConstraintRow.as
index 706a69e..92ef5a3 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/utilityClasses/ConstraintRow.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/utilityClasses/ConstraintRow.as
@@ -27,12 +27,12 @@ import flash.events.Event;
import flash.events.IEventDispatcher;
*/
import mx.core.IInvalidating;
-/*
import mx.core.mx_internal;
+use namespace mx_internal;
+/*
import mx.core.IMXMLObject;
import flash.events.EventDispatcher;
-use namespace mx_internal;
*/
/**
@@ -75,7 +75,7 @@ public class ConstraintRow extends EventDispatcher //implements IMXMLObject
// Variables
//
//--------------------------------------------------------------------------
- protected var contentSize:Boolean = false;
+ mx_internal var contentSize:Boolean = false;
//--------------------------------------------------------------------------
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Button.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Button.as
index 75baacb..e97663f 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Button.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Button.as
@@ -277,17 +277,6 @@ public class Button extends UIComponent implements IDataRenderer
}
// ------------------------------------------------
- // fontStyle
- // ------------------------------------------------
-
- public function get fontStyle():String
- {
- return "BOLD";
- }
- public function set fontStyle(value:String):void
- {
- }
- // ------------------------------------------------
// icon
// ------------------------------------------------
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/core/ILayoutElement.as b/frameworks/projects/MXRoyale/src/main/royale/mx/core/ILayoutElement.as
index 786b73b..ecb8ec3 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/core/ILayoutElement.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/core/ILayoutElement.as
@@ -224,13 +224,14 @@ public interface ILayoutElement extends IEventDispatcher
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
- function get baseline():Object;
*/
+ function get baseline():Object;
+
/**
* @private
- function set baseline(value:Object):void;
*/
+ function set baseline(value:Object):void;
/**
* The y-coordinate of the baseline
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/core/UIComponent.as b/frameworks/projects/MXRoyale/src/main/royale/mx/core/UIComponent.as
index 8494e90..12d7914 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/core/UIComponent.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/core/UIComponent.as
@@ -3112,7 +3112,12 @@ COMPILE::JS
addEventListener("stateChangeComplete", stateChangeCompleteHandler);
dispatchEvent(event);
}
-
+
+ public function setCurrentState(stateName:String, playTransition:Boolean=true):void
+ {
+ currentState = stateName;
+ }
+
private function stateChangeCompleteHandler(event:Event):void
{
callLater(dispatchUpdateComplete);
@@ -4679,6 +4684,52 @@ COMPILE::JS
{
this._uid = uid;
}
+
+ /*
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get showErrorSkin():Object
+ {
+ return ValuesManager.valuesImpl.getValue(this, "showErrorSkin");
+ }
+ public function set showErrorSkin(value:Object):void
+ {
+ setStyle("showErrorSkin", value);
+ }
+
+ /*
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get showErrorTip():Object
+ {
+ return ValuesManager.valuesImpl.getValue(this, "showErrorTip");
+ }
+ public function set showErrorTip(value:Object):void
+ {
+ setStyle("showErrorTip", value);
+ }
+
+ /*
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get baseline():Object
+ {
+ return ValuesManager.valuesImpl.getValue(this, "baseline");
+ }
+ public function set baseline(value:Object):void
+ {
+ setStyle("baseline", value);
+ }
+
[Inspectable(category="General")]
/*
@@ -4695,6 +4746,23 @@ COMPILE::JS
{
setStyle("fontSize", value);
}
+ [Inspectable(category="General")]
+
+ /*
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get fontStyle():Object
+ {
+ return ValuesManager.valuesImpl.getValue(this, "fontStyle");
+ }
+ public function set fontStyle(value:Object):void
+ {
+ setStyle("fontStyle", value);
+ }
+
[Inspectable(category="General")]
/*
diff --git a/frameworks/projects/SparkRoyale/src/main/resources/defaults.css b/frameworks/projects/SparkRoyale/src/main/resources/defaults.css
index b28ab14..48705da 100644
--- a/frameworks/projects/SparkRoyale/src/main/resources/defaults.css
+++ b/frameworks/projects/SparkRoyale/src/main/resources/defaults.css
@@ -117,9 +117,19 @@ DropDownList
border: 1px solid #333333
}
+Form
+{
+ skinClass: ClassReference("spark.skins.spark.FormSkin");
+}
+
+FormItem
+{
+ skinClass: ClassReference("spark.skins.spark.FormItemSkin");
+}
+
List
{
- IBeadView: ClassReference("spark.components.beads.SkinnableContainerView");
+ IBeadView: ClassReference("spark.components.beads.SparkContainerView");
IBeadLayout: ClassReference("spark.layouts.supportClasses.SparkLayoutBead");
IViewport: ClassReference("org.apache.royale.html.supportClasses.ScrollingViewport");
IViewportModel: ClassReference("org.apache.royale.html.beads.models.ViewportModel");
diff --git a/frameworks/projects/SparkRoyale/src/main/resources/spark-royale-manifest.xml b/frameworks/projects/SparkRoyale/src/main/resources/spark-royale-manifest.xml
index 265edde..6918347 100644
--- a/frameworks/projects/SparkRoyale/src/main/resources/spark-royale-manifest.xml
+++ b/frameworks/projects/SparkRoyale/src/main/resources/spark-royale-manifest.xml
@@ -75,6 +75,9 @@
<component id="HorizontalLayout" class="spark.layouts.HorizontalLayout"/>
<component id="TileLayout" class="spark.layouts.TileLayout"/>
<component id="Module" class="spark.modules.Module" />
+ <component id="FormItemLayout" class="spark.layouts.FormItemLayout"/>
+ <component id="ConstraintColumn" class="mx.containers.utilityClasses.ConstraintColumn" lookupOnly="true"/>
+ <component id="ConstraintRow" class="mx.containers.utilityClasses.ConstraintRow" lookupOnly="true"/>
<component id="ArrayCollection" class="mx.collections.ArrayCollection" lookupOnly="true"/>
@@ -115,6 +118,7 @@
<component id="TabBarView" class="spark.components.beads.TabBarView"/>
<component id="MXAdvancedDataGridItemRenderer" class="spark.controls.advancedDataGridClasses.MXAdvancedDataGridItemRenderer"/>
<component id="SparkTextButtonItemRenderer" class="spark.components.supportClasses.SparkTextButtonItemRenderer"/>
+ <component id="Skin" class="spark.components.supportClasses.Skin"/>
</componentPackage>
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/SparkRoyaleClasses.as b/frameworks/projects/SparkRoyale/src/main/royale/SparkRoyaleClasses.as
index 82ec840..bea2c7f 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/SparkRoyaleClasses.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/SparkRoyaleClasses.as
@@ -36,8 +36,12 @@ internal class SparkRoyaleClasses
import spark.skins.spark.TitleWindowCloseButtonSkin; TitleWindowCloseButtonSkin;
import spark.skins.spark.ComboBoxButtonSkin; ComboBoxButtonSkin;
import spark.skins.spark.ComboBoxTextInputSkin; ComboBoxTextInputSkin;
+ import spark.skins.spark.FormSkin; FormSkin;
+ import spark.skins.spark.FormItemSkin; FormItemSkin;
import spark.layouts.supportClasses.SparkLayoutBead; SparkLayoutBead;
+ import spark.layouts.FormLayout; FormLayout;
+ import spark.layouts.FormItemLayout; FormItemLayout;
import spark.components.supportClasses.RegExPatterns; RegExPatterns;
@@ -77,6 +81,7 @@ internal class SparkRoyaleClasses
import spark.components.beads.PanelView; PanelView;
import spark.components.beads.GroupView; GroupView;
import spark.components.beads.SkinnableContainerView; SkinnableContainerView;
+ import spark.components.beads.SparkSkinScrollingViewport; SparkSkinScrollingViewport;
import spark.components.beads.DropDownListView; DropDownListView;
import spark.components.beads.TitleWindowView; TitleWindowView;
import spark.components.beads.controllers.DropDownListController; DropDownListController;
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/Label.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/Label.as
index cf07f26..f1faad0 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/Label.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/Label.as
@@ -419,16 +419,7 @@ public class Label extends TextBase
{
}
-
- public function get fontStyle():String
- {
- return "";
- }
- public function set fontStyle(value:String):void
- {
-
- }
-
+
public function get textDecoration():String
{
return "";
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SkinnableContainerView.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SkinnableContainerView.as
index f02ae43..ca63c80 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SkinnableContainerView.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SkinnableContainerView.as
@@ -22,18 +22,19 @@ package spark.components.beads
import spark.components.SkinnableContainer;
import spark.components.supportClasses.GroupBase;
+import spark.components.supportClasses.SkinnableComponent;
import org.apache.royale.core.IBead;
+import org.apache.royale.core.IContainer;
import org.apache.royale.core.ILayoutChild;
import org.apache.royale.core.IStrand;
import org.apache.royale.core.UIBase;
-import org.apache.royale.html.beads.ContainerView;
/**
* @private
* The SkinnableContainerView for emulation.
*/
-public class SkinnableContainerView extends ContainerView
+public class SkinnableContainerView extends SparkContainerView
{
//--------------------------------------------------------------------------
//
@@ -54,22 +55,15 @@ public class SkinnableContainerView extends ContainerView
super();
}
- /**
- */
- override public function set strand(value:IStrand):void
+ override protected function addViewport():void
{
- super.strand = value;
- var host:SkinnableContainer = _strand as SkinnableContainer;
- var g:GroupBase = (contentView as GroupBase);
- g.layout = host.layout;
-
- if (!host.isWidthSizedToContent())
- g.percentWidth = 100;
- if (!host.isHeightSizedToContent())
- g.percentHeight = 100;
-
+ var chost:IContainer = host as IContainer;
+ var skinhost:SkinnableComponent = host as SkinnableComponent;
+ if (chost != null && chost != viewport.contentView) {
+ chost.addElement(skinhost.skin);
+ }
}
-
+
}
}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SkinnableContainerView.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SparkContainerView.as
similarity index 92%
copy from frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SkinnableContainerView.as
copy to frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SparkContainerView.as
index f02ae43..e27a832 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SkinnableContainerView.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SparkContainerView.as
@@ -24,6 +24,7 @@ import spark.components.SkinnableContainer;
import spark.components.supportClasses.GroupBase;
import org.apache.royale.core.IBead;
+import org.apache.royale.core.IContainer;
import org.apache.royale.core.ILayoutChild;
import org.apache.royale.core.IStrand;
import org.apache.royale.core.UIBase;
@@ -31,9 +32,9 @@ import org.apache.royale.html.beads.ContainerView;
/**
* @private
- * The SkinnableContainerView for emulation.
+ * The SparkContainerView for emulation.
*/
-public class SkinnableContainerView extends ContainerView
+public class SparkContainerView extends ContainerView
{
//--------------------------------------------------------------------------
//
@@ -49,7 +50,7 @@ public class SkinnableContainerView extends ContainerView
* @playerversion AIR 1.1
* @productversion Flex 3
*/
- public function SkinnableContainerView()
+ public function SparkContainerView()
{
super();
}
@@ -69,7 +70,7 @@ public class SkinnableContainerView extends ContainerView
g.percentHeight = 100;
}
-
+
}
}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SparkSkinScrollingViewport.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SparkSkinScrollingViewport.as
new file mode 100644
index 0000000..d2fa6cf
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/beads/SparkSkinScrollingViewport.as
@@ -0,0 +1,168 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.components.beads
+{
+
+import mx.core.mx_internal;
+use namespace mx_internal;
+
+import spark.components.supportClasses.GroupBase;
+import spark.components.supportClasses.SkinnableComponent;
+
+import org.apache.royale.core.IBead;
+import org.apache.royale.core.IContentView;
+import org.apache.royale.core.IStrand;
+import org.apache.royale.core.IUIBase;
+import org.apache.royale.core.IViewport;
+import org.apache.royale.core.UIBase;
+import org.apache.royale.core.ValuesManager;
+import org.apache.royale.geom.Size;
+
+COMPILE::SWF
+{
+ import flash.geom.Rectangle;
+}
+
+/**
+ * @private
+ * The viewport that loads a Spark Skin.
+ */
+public class SparkSkinScrollingViewport implements IViewport
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function SparkSkinScrollingViewport()
+ {
+ super();
+ }
+
+ protected var contentArea:UIBase;
+
+ /**
+ * Get the actual parent of the container's content.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public function get contentView():IUIBase
+ {
+ return contentArea;
+ }
+
+ protected var host:SkinnableComponent;
+
+ /**
+ */
+ public function set strand(value:IStrand):void
+ {
+ host = value as SkinnableComponent;
+
+ var c:Class = ValuesManager.valuesImpl.getValue(value, "skinClass") as Class;
+ host.setSkin(new c());
+
+ contentArea = host.skin["contentGroup"];
+
+ COMPILE::JS
+ {
+ setScrollStyle();
+ }
+
+ }
+
+ /**
+ * Subclasses override this method to change scrolling behavior
+ */
+ COMPILE::JS
+ protected function setScrollStyle():void
+ {
+ contentArea.element.style.overflow = "auto";
+ }
+
+ /**
+ * @copy org.apache.royale.core.IViewport#setPosition()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public function setPosition(x:Number, y:Number):void
+ {
+ COMPILE::SWF {
+ contentArea.x = x;
+ contentArea.y = y;
+ }
+ }
+
+ /**
+ * @copy org.apache.royale.core.IViewport#layoutViewportBeforeContentLayout()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public function layoutViewportBeforeContentLayout(width:Number, height:Number):void
+ {
+ COMPILE::SWF {
+ if (!isNaN(width))
+ contentArea.width = width;
+ if (!isNaN(height))
+ contentArea.height = height;
+ }
+ }
+
+ /**
+ * @copy org.apache.royale.core.IViewport#layoutViewportAfterContentLayout()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public function layoutViewportAfterContentLayout(contentSize:Size):void
+ {
+ COMPILE::SWF {
+ var hostWidth:Number = UIBase(host).width;
+ var hostHeight:Number = UIBase(host).height;
+
+ var rect:flash.geom.Rectangle = new flash.geom.Rectangle(0, 0, hostWidth, hostHeight);
+ contentArea.scrollRect = rect;
+
+ return;
+ }
+ }
+}
+
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/ButtonBase.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/ButtonBase.as
index 7338e2f..9393500 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/ButtonBase.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/ButtonBase.as
@@ -451,15 +451,6 @@ public class ButtonBase extends SkinnableComponent implements IFocusManagerCompo
return element;
}
- public function set fontStyle(value:String):void
- {
-
- }
- public function get fontStyle():String
- {
- return "NORMAL";
- }
-
public function get lineThrough():Boolean
{
return true;
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/SkinnableComponent.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/SkinnableComponent.as
index e6fb4ba..e96269f 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/SkinnableComponent.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/SkinnableComponent.as
@@ -32,16 +32,16 @@ import flash.utils.*;
import mx.core.FlexVersion;
import mx.core.ILayoutElement;
import mx.core.IVisualElement;
-import mx.core.mx_internal;
import mx.events.PropertyChangeEvent;
import spark.events.SkinPartEvent;
import spark.utils.FTETextUtil;
-use namespace mx_internal;
*/
import mx.core.IFactory;
+import mx.core.mx_internal;
import mx.collections.IList;
+use namespace mx_internal;
import mx.core.UIComponent;
import spark.components.DataGroup;
@@ -282,7 +282,7 @@ public class SkinnableComponent extends UIComponent
* Setter for the skin instance. This is so the bindable event
* is dispatched
*/
- private function setSkin(value:UIComponent):void
+ mx_internal function setSkin(value:UIComponent):void
{
if (value === _skin)
return;
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/SkinnableTextBase.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/SkinnableTextBase.as
index 8f6f098..521a5d2 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/SkinnableTextBase.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/SkinnableTextBase.as
@@ -940,21 +940,7 @@ public class SkinnableTextBase extends SkinnableComponent
invalidateProperties();
} */
-
- //----------------------------------
- // fontStyle
- //----------------------------------
-
- public function get fontStyle():String
- {
- return "";
- }
-
- public function set fontStyle(value:String):void
- {
-
- }
-
+
//----------------------------------
// typicalText
//----------------------------------
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/TextBase.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/TextBase.as
index 9274153..aaed390 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/TextBase.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/supportClasses/TextBase.as
@@ -32,7 +32,6 @@ import mx.core.IFlexModuleFactory;
import mx.resources.IResourceManager;
import mx.resources.ResourceManager;
-import spark.core.IDisplayText;
import spark.utils.TextUtil;
*/
@@ -58,6 +57,8 @@ import org.apache.royale.core.ITextModel;
use namespace mx_internal;
+import spark.core.IDisplayText;
+
//--------------------------------------
// Styles
//--------------------------------------
@@ -113,9 +114,9 @@ use namespace mx_internal;
* @royalesuppresspublicvarwarning
*/
-public class TextBase extends UIComponent
-{ //implements IDisplayText
+public class TextBase extends UIComponent implements IDisplayText
+{
// include "../../core/Version.as";
//--------------------------------------------------------------------------
@@ -343,7 +344,7 @@ public class TextBase extends UIComponent
* @private
* Storage for the isTruncated property.
*/
- //private var _isTruncated:Boolean = false;
+ private var _isTruncated:Boolean = false;
/**
* A read-only property reporting whether the text has been truncated.
@@ -377,12 +378,12 @@ public class TextBase extends UIComponent
* @playerversion AIR 1.5
* @productversion Royale 0.9.4
*/
- /* public function get isTruncated():Boolean
+ public function get isTruncated():Boolean
{
// For some reason, the compiler needs an explicit cast to Boolean
// to avoid a warning even though at runtime "is Boolean" is true.
return Boolean(_isTruncated);
- } */
+ }
/**
* @private
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/ConstraintLayout.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/ConstraintLayout.as
new file mode 100644
index 0000000..069c55f
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/ConstraintLayout.as
@@ -0,0 +1,1984 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.layouts
+{
+COMPILE::SWF
+{
+ import flash.utils.Dictionary;
+}
+
+import mx.containers.errors.ConstraintError;
+import mx.containers.utilityClasses.ConstraintColumn;
+import mx.containers.utilityClasses.ConstraintRow;
+import mx.containers.utilityClasses.Flex;
+import mx.core.ILayoutElement;
+import mx.core.mx_internal;
+import mx.resources.ResourceManager;
+
+import spark.components.supportClasses.GroupBase;
+import spark.layouts.supportClasses.LayoutBase;
+import spark.layouts.supportClasses.LayoutElementHelper;
+
+import org.apache.royale.geom.Point;
+
+use namespace mx_internal;
+
+//[ResourceBundle("layout")]
+
+/**
+ * The ConstraintLayout class arranges the layout elements based on their individual
+ * settings and a set of constraint regions defined by constraint columns and
+ * constraint rows. Although you can use all of the properties and constraints from
+ * BasicLayout to position and size elements, ConstraintLayout gives you the ability
+ * to create sibling-relative layouts by constraining elements to the specified
+ * columns and rows.
+ *
+ * <p><b>Note: </b>The Spark list-based controls (the Spark List control and its subclasses
+ * such as ButtonBar, ComboBox, DropDownList, and TabBar) do not support the ConstraintLayout class.
+ * Do not use ConstraintLayout with the Spark list-based controls.</p>
+ *
+ * <p>Per-element supported constraints are <code>left</code>, <code>right</code>,
+ * <code>top</code>, <code>bottom</code>, <code>baseline</code>,
+ * <code>percentWidth</code>, and <code>percentHeight</code>.
+ * Element's minimum and maximum sizes will always be respected.</p>
+ *
+ * <p>Columns and rows may have an explicit size or content size (no explicit size).
+ * Explicit size regions will be fixed at their specified size, while content size
+ * regions will stretch to fit only the elements constrained to them. If multiple
+ * content size regions are spanned by an element, the space will be divided
+ * equally among the content size regions.</p>
+ *
+ * <p>The measured size of the container is calculated from the elements, their
+ * constraints, their preferred sizes, and the sizes of the rows and columns.
+ * The size of each row and column is just big enough to hold all of the elements
+ * constrained to it at their preferred sizes with constraints satisfied. The measured
+ * size of the container is big enough to hold all of the columns and rows as well as
+ * any other elements left at their preferred sizes with constraints satisfied. </p>
+ *
+ * <p>During a call to the <code>updateDisplayList()</code> method,
+ * the element's size is determined according to
+ * the rules in the following order of precedence (the element's minimum and
+ * maximum sizes are always respected):</p>
+ * <ul>
+ * <li>If the element has <code>percentWidth</code> or <code>percentHeight</code> set,
+ * then its size is calculated as a percentage of the available size, where the available
+ * size is the region or container size minus any <code>left</code>, <code>right</code>,
+ * <code>top</code>, or <code>bottom</code> constraints.</li>
+ *
+ * <li>If the element has both left and right constraints, it's width is
+ * set to be the region's or container's width minus the <code>left</code>
+ * and <code>right</code> constraints.</li>
+ *
+ * <li>If the element has both <code>top</code> and <code>bottom</code> constraints,
+ * it's height is set to be the container's height minus the <code>top</code>
+ * and <code>bottom</code> constraints.</li>
+ *
+ * <li>The element is set to its preferred width and/or height.</li>
+ * </ul>
+ *
+ * <p>The element's position is determined according to the rules in the following
+ * order of precedence:</p>
+ * <ul>
+ * <li>If element's baseline is specified, then the element is positioned in
+ * the vertical direction such that its <code>baselinePosition</code> (usually the base line
+ * of its first line of text) is aligned with <code>baseline</code> constraint.</li>
+ *
+ * <li>If element's <code>top</code> or <code>left</code> constraints
+ * are specified, then the element is
+ * positioned such that the top-left corner of the element's layout bounds is
+ * offset from the top-left corner of the container by the specified values.</li>
+ *
+ * <li>If element's <code>bottom</code> or <code>right</code> constraints are specified,
+ * then the element is positioned such that the bottom-right corner
+ * of the element's layout bounds is
+ * offset from the bottom-right corner of the container by the specified values.</li>
+ *
+ * <li>When no constraints determine the position in the horizontal or vertical
+ * direction, the element is positioned according to its x and y coordinates.</li>
+ * </ul>
+ *
+ * <p>The content size of the container is calculated as the maximum of the
+ * coordinates of the bottom-right corner of all the layout elements and
+ * constraint regions.</p>
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4.5
+ */
+public class ConstraintLayout extends LayoutBase
+{
+
+ //See FLEX-33311 for more details on why this is used
+ private var constraintCacheNeeded:int = 0;
+
+ //--------------------------------------------------------------------------
+ //
+ // Class methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ *
+ * @return true if the constraints determine the element's width;
+ */
+ private static function constraintsDetermineWidth(elementInfo:ElementConstraintInfo):Boolean
+ {
+ return !isNaN(elementInfo.left) && !isNaN(elementInfo.right);
+ }
+
+ /**
+ * @private
+ *
+ * @return true if the constraints determine the element's height;
+ */
+ private static function constraintsDetermineHeight(elementInfo:ElementConstraintInfo):Boolean
+ {
+ return !isNaN(elementInfo.top) && !isNaN(elementInfo.bottom);
+ }
+
+ /**
+ * @private
+ * @return Returns the maximum value for an element's dimension so that the component doesn't
+ * spill out of the container size. Calculations are based on the layout rules.
+ * Pass in unscaledWidth, left, right, childX to get a maxWidth value.
+ * Pass in unscaledHeight, top, bottom, childY to get a maxHeight value.
+ */
+ private static function maxSizeToFitIn(totalSize:Number,
+ lowConstraint:Number,
+ highConstraint:Number,
+ position:Number):Number
+ {
+ if (!isNaN(lowConstraint))
+ {
+ // childWidth + left <= totalSize
+ return totalSize - lowConstraint;
+ }
+ else if (!isNaN(highConstraint))
+ {
+ // childWidth + right <= totalSize
+ return totalSize - highConstraint;
+ }
+ else
+ {
+ // childWidth + childX <= totalSize
+ return totalSize - position;
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4.5
+ */
+ public function ConstraintLayout()
+ {
+ super();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * Vectors that keep track of children spanning
+ * content size columns or rows or whether the
+ * elements don't use columns or rows at all.
+ */
+ private var colSpanElements:Vector.<ElementConstraintInfo> = null;
+ private var rowSpanElements:Vector.<ElementConstraintInfo> = null;
+ private var otherElements:Vector.<ElementConstraintInfo> = null;
+
+ /**
+ * @private
+ * Vectors to store the baseline property of the rows, and
+ * the maximum ascent of the elements in each row.
+ *
+ * In rowBaselines, the value is stored as
+ * [value, maxAscent] if the baseline is maxAscent:value,
+ * and [value, null] if the baseline is just a value.
+ */
+ private var rowBaselines:Vector.<Array> = null;
+ private var rowMaxAscents:Vector.<Number> = null;
+
+ /**
+ * @private
+ * Hashtable that maps elements to their constraint
+ * information. The mapping has type:
+ * ILayoutElement -> ElementConstraintInfo
+ *
+ * This cache is always discarded after measure() or
+ * updateDisplayList() because the constraints may have changed.
+ */
+ COMPILE::JS
+ private var constraintCache:Object = null;
+ COMPILE::SWF
+ private var constraintCache:Dictionary = null;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // constraintColumns
+ //----------------------------------
+
+ private var _constraintColumns:Vector.<ConstraintColumn> = new Vector.<ConstraintColumn>(0, true);
+ // An associative array of column id --> column index
+ private var columnsObject:Object = {};
+
+ /**
+ * A Vector of ConstraintColumn instances that partition the target container.
+ * The ConstraintColumn instance at index 0 is the left-most column;
+ * indices increase from left to right.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4.5
+ */
+ public function get constraintColumns():Vector.<ConstraintColumn>
+ {
+ // make defensive copy
+ return _constraintColumns.slice();
+ }
+
+ /**
+ * @private
+ */
+ public function set constraintColumns(value:Vector.<ConstraintColumn>):void
+ {
+ // clear constraintColumns
+ if (value == null)
+ {
+ _constraintColumns = new Vector.<ConstraintColumn>(0, true);
+ columnsObject = {};
+ return;
+ }
+
+ var n:int = value.length;
+ var col:ConstraintColumn;
+ var temp:Vector.<ConstraintColumn> = value.slice();
+ var obj:Object = {};
+
+ for (var i:int = 0; i < n; i++)
+ {
+ col = temp[i];
+ col.container = this.target;
+ obj[col.id] = i;
+ }
+
+ _constraintColumns = temp;
+ columnsObject = obj;
+
+ if (target)
+ {
+ target.invalidateSize();
+ target.invalidateDisplayList();
+ }
+ }
+
+ //----------------------------------
+ // constraintRows
+ //----------------------------------
+
+ private var _constraintRows:Vector.<ConstraintRow> = new Vector.<ConstraintRow>(0, true);
+ // An associative array of row id --> row index
+ private var rowsObject:Object = {};
+
+ /**
+ * A Vector of ConstraintRow instances that partition the target container.
+ * The ConstraintRow instance at index 0 is the top-most column;
+ * indices increase from top to bottom.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4.5
+ */
+ public function get constraintRows():Vector.<ConstraintRow>
+ {
+ return _constraintRows.slice();
+ }
+
+ /**
+ * @private
+ */
+ public function set constraintRows(value:Vector.<ConstraintRow>):void
+ {
+ // clear constraintRows
+ if (value == null)
+ {
+ _constraintRows = new Vector.<ConstraintRow>(0, true);
+ rowsObject = {};
+ return;
+ }
+
+ var n:int = value.length;
+ var row:ConstraintRow;
+ var temp:Vector.<ConstraintRow> = value.slice();
+ var obj:Object = {};
+ rowBaselines = new Vector.<Array>();
+
+ for (var i:int = 0; i < n; i++)
+ {
+ row = temp[i];
+ row.container = this.target;
+ obj[row.id] = i;
+ rowBaselines[i] = LayoutElementHelper.parseConstraintExp(row.baseline);
+
+ var maxAscentStr:String = rowBaselines[i][1];
+ if (maxAscentStr && maxAscentStr != "maxAscent")
+ throw new Error(ResourceManager.getInstance().getString("layout", "invalidBaselineOnRow",
+ [ row.id, row.baseline ]));
+ }
+
+ _constraintRows = temp;
+ rowsObject = obj;
+
+ if (target)
+ {
+ target.invalidateSize();
+ target.invalidateDisplayList();
+ }
+ }
+
+ /**
+ * @private
+ * Resets the target on the constraintColumns and constraintRows.
+ */
+ override public function set target(value:GroupBase):void
+ {
+ super.target = value;
+
+ // setting a new target means we need to reset the targets of
+ // our columns and rows
+ var i:int;
+ var n:int = _constraintColumns.length;
+
+ for (i = 0; i < n; i++)
+ {
+ _constraintColumns[i].container = value;
+ }
+
+ n = _constraintRows.length;
+ for (i = 0; i < n; i++)
+ {
+ _constraintRows[i].container = value;
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden Methods: LayoutBase
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ *
+ * 1) Parse each element constraint and populate the constraintCache
+ * 2) Measure the columns and rows based on only the elements that use them
+ * and get the sum of the column widths and row heights.
+ * 3) Measure the size of this container based on elements that don't use
+ * either columns or rows or both.
+ * 4) Take the max of 2 and 3 to find the measuredWidth.
+ */
+ override public function measure():void
+ {
+ checkUseVirtualLayout();
+ super.measure();
+
+ var layoutTarget:GroupBase = target;
+ if (!layoutTarget)
+ return;
+
+ var width:Number = 0;
+ var height:Number = 0;
+ var minWidth:Number = 0;
+ var minHeight:Number = 0;
+
+ parseConstraints();
+
+ // Find preferred column widths and row heights.
+ var colWidths:Vector.<Number> = measureColumns();
+ var rowHeights:Vector.<Number> = measureRows();
+ var n:Number;
+
+ for each (n in colWidths)
+ {
+ width += n;
+ }
+
+ for each (n in rowHeights)
+ {
+ height += n;
+ }
+
+ // Find minimum measured width/height by passing in 0 for the constrained size.
+ // This means that percent size regions will be set to their min size.
+ constrainPercentRegionSizes(colWidths, 0, true);
+ for each (n in colWidths)
+ {
+ minWidth += n;
+ }
+
+ constrainPercentRegionSizes(rowHeights, 0, false);
+ for each (n in rowHeights)
+ {
+ minHeight += n;
+ }
+
+ if (otherElements)
+ {
+ var vec:Vector.<Number> = measureOtherContent();
+
+ width = Math.max(width, vec[0]);
+ height = Math.max(height, vec[1]);
+ minWidth = Math.max(minWidth, vec[2]);
+ minHeight = Math.max(minHeight, vec[3]);
+ }
+
+ layoutTarget.measuredWidth = Math.ceil(width);
+ layoutTarget.measuredHeight = Math.ceil(height);
+ layoutTarget.measuredMinWidth = Math.ceil(minWidth);
+ layoutTarget.measuredMinHeight = Math.ceil(minHeight);
+
+ // clear out cache
+ clearConstraintCache();
+ }
+
+ /**
+ * @private
+ *
+ * 1) Re-parse element constraints because they may have changed.
+ * 2) Resize and reposition the columns and rows based on new constraints.
+ * 3) Size and position the elements in the available space.
+ */
+ override public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ checkUseVirtualLayout();
+ super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+ var layoutTarget:GroupBase = target;
+ if (!layoutTarget)
+ return;
+
+ // Need to measure in case of explicit width and height on target.
+ // Also need to reparse constraints in case of something changing.
+ measureAndPositionColumnsAndRows(unscaledWidth, unscaledHeight);
+
+ layoutContent(unscaledWidth, unscaledHeight);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods: Used by FormItemLayout
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Lays out the elements of the layout target using the current
+ * widths and heights of the columns and rows. Used by FormItemLayout
+ * after setting new column widths to lay elements using those new widths.
+ *
+ * @param unscaledWidth Specifies the width of the component, in pixels,
+ * in the component's coordinates, regardless of the value of the
+ * <code>scaleX</code> property of the component.
+ *
+ * @param unscaledHeight Specifies the height of the component, in pixels,
+ * in the component's coordinates, regardless of the value of the
+ * <code>scaleY</code> property of the component.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4.5
+ */
+ protected function layoutContent(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ var layoutTarget:GroupBase = target;
+ if (!layoutTarget)
+ return;
+
+ var count:int = layoutTarget.numElements;
+ var layoutElement:ILayoutElement;
+
+ var maxX:Number = 0;
+ var maxY:Number = 0;
+
+ // update children
+ for (var i:int = 0; i < count; i++)
+ {
+ layoutElement = layoutTarget.getElementAt(i) as ILayoutElement;
+ if (!layoutElement || !layoutElement.includeInLayout)
+ continue;
+
+ applyConstraintsToElement(unscaledWidth, unscaledHeight, layoutElement);
+
+ // update content limits
+ maxX = Math.max(maxX, layoutElement.getLayoutBoundsX() +
+ layoutElement.getLayoutBoundsWidth());
+ maxY = Math.max(maxY, layoutElement.getLayoutBoundsY() +
+ layoutElement.getLayoutBoundsHeight());
+ }
+
+ // Make sure that if the content spans partially over a pixel to the right/bottom,
+ // the content size includes the whole pixel.
+ layoutTarget.setContentSize(Math.ceil(maxX), Math.ceil(maxY));
+
+ // clear out cache
+ clearConstraintCache();
+ }
+
+ /**
+ * Used by FormItemLayout to measure and set new column widths
+ * and row heights before laying out the elements.
+ *
+ * @param constrainedWidth The total width available for columns to stretch
+ * or shrink their percent width columns. If NaN, percent width columns
+ * are unconstrained and fit to their content.
+ * @param constrainedHeight The total height available for rows to stretch
+ * or shrink their percent height rows. If NaN, percent height rows
+ * are unconstrained and fit to their content.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @productversion Flex 4.5
+ */
+ protected function measureAndPositionColumnsAndRows(constrainedWidth:Number = NaN, constrainedHeight:Number = NaN):void
+ {
+ parseConstraints();
+ setColumnWidths(measureColumns(constrainedWidth));
+ setRowHeights(measureRows(constrainedHeight));
+ }
+
+ /**
+ * @private
+ * This function is mx_internal so that FormItemLayout can use it
+ * in its updateDisplayList.
+ */
+ mx_internal function checkUseVirtualLayout():void
+ {
+ if (useVirtualLayout)
+ throw new Error(ResourceManager.getInstance().getString("layout", "constraintLayoutNotVirtualized"));
+ }
+
+ /**
+ * @private
+ */
+ override mx_internal function get virtualLayoutSupported():Boolean
+ {
+ return false;
+ }
+
+ /**
+ * @private
+ * Used to set new column widths before laying out the elements.
+ * Used by FormItemLayout to set column widths provided by the
+ * Form.
+ */
+ mx_internal function setColumnWidths(value:Vector.<Number>):void
+ {
+ if (value == null)
+ return;
+
+ var constraintColumns:Vector.<ConstraintColumn> = this._constraintColumns;
+ var numCols:int = constraintColumns.length;
+ var totalWidth:Number = 0;
+
+ for (var i:int = 0; i < numCols; i++)
+ {
+ constraintColumns[i].setActualWidth(value[i]);
+ constraintColumns[i].x = totalWidth;
+ totalWidth += value[i];
+ }
+ }
+
+ /**
+ * @private
+ * Used to set new row heights before laying out the elements.
+ */
+ mx_internal function setRowHeights(value:Vector.<Number>):void
+ {
+ if (value == null)
+ return;
+
+ var constraintRows:Vector.<ConstraintRow> = this._constraintRows;
+ var numRows:int = constraintRows.length;
+ var totalHeight:Number = 0;
+
+ for (var i:int = 0; i < numRows; i++)
+ {
+ constraintRows[i].setActualHeight(value[i]);
+ constraintRows[i].y = totalHeight;
+ totalHeight += value[i];
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ private var constraintElementId:int = 0;
+
+ /**
+ * @private
+ * Sizes and positions the element based on the given size of the container
+ * and the element's constraints.
+ *
+ * 1) Retrieves element constraints from the constraint cache.
+ * 2) Determines the x and y boundaries of each side.
+ * 3) Sizes the element based on constraints and its preferred
+ * size. The precedence for sizing is as follows: percent,
+ * top and bottom constraints, preferred size.
+ * 4) Positions the element based on its constraints. The precedence
+ * for positioning is as follows: baseline, left and top, right and bottom,
+ * x and y.
+ */
+ private function applyConstraintsToElement(unscaledWidth:Number,
+ unscaledHeight:Number,
+ layoutElement:ILayoutElement):void
+ {
+ COMPILE::JS
+ {
+ if (layoutElement['constraintElementId'] == null)
+ layoutElement['constraintElementId'] = constraintElementId.toString();
+ var elementInfo:ElementConstraintInfo = constraintCache[layoutElement['constraintElementId']];
+ }
+ COMPILE::SWF
+ {
+ var elementInfo:ElementConstraintInfo = constraintCache[layoutElement];
+ }
+
+ var left:Number = elementInfo.left;
+ var right:Number = elementInfo.right;
+ var top:Number = elementInfo.top;
+ var bottom:Number = elementInfo.bottom;
+ var baseline:Number = elementInfo.baseline;
+
+ var leftBoundary:String = elementInfo.leftBoundary;
+ var rightBoundary:String = elementInfo.rightBoundary;
+ var topBoundary:String = elementInfo.topBoundary;
+ var bottomBoundary:String = elementInfo.bottomBoundary;
+ var baselineBoundary:String = elementInfo.baselineBoundary;
+
+ var percentWidth:Number = layoutElement.percentWidth;
+ var percentHeight:Number = layoutElement.percentHeight;
+
+ var availableWidth:Number;
+ var availableHeight:Number;
+
+ var elementWidth:Number = NaN;
+ var elementHeight:Number = NaN;
+ var elementMaxWidth:Number = NaN;
+ var elementMaxHeight:Number = NaN;
+ var elementX:Number = 0;
+ var elementY:Number = 0;
+
+ var leftHolder:Number = 0;
+ var rightHolder:Number = unscaledWidth;
+ var topHolder:Number = 0;
+ var bottomHolder:Number = unscaledHeight;
+ var baselineHolder:Number = 0;
+
+ var i:Number;
+
+ var col:ConstraintColumn;
+ var row:ConstraintRow;
+
+ if (leftBoundary)
+ {
+ col = _constraintColumns[elementInfo.colSpanLeftIndex];
+ leftHolder = col.x;
+ }
+
+ if (rightBoundary)
+ {
+ col = _constraintColumns[elementInfo.colSpanRightIndex];
+ rightHolder = col.x + col.width;
+ }
+
+ if (topBoundary)
+ {
+ row = _constraintRows[elementInfo.rowSpanTopIndex];
+ topHolder = row.y;
+ }
+
+ if (bottomBoundary)
+ {
+ row = _constraintRows[elementInfo.rowSpanBottomIndex];
+ bottomHolder = row.y + row.height;
+ }
+
+ if (baselineBoundary)
+ {
+ var baselineIndex:Number = elementInfo.baselineIndex;
+ var rowBaseline:Array = rowBaselines[baselineIndex];
+ row = _constraintRows[baselineIndex];
+
+ // add baseline offset from row.
+ baselineHolder = row.y + Number(rowBaseline[0]);
+
+ // add maxAscent. maxAscent defaults to 0 if not specified.
+ if (rowMaxAscents)
+ baselineHolder += rowMaxAscents[baselineIndex];
+
+ // If bottom doesn't exist, then the bottom should be restricted to the
+ // baseline row.
+ if (isNaN(bottom))
+ bottomHolder = row.y + row.height;
+ }
+
+ // available width
+ availableWidth = Math.round(rightHolder - leftHolder);
+
+ // cases are baseline with top and bottom,
+ // baseline with top, baseline with bottom, no baseline
+ if (!isNaN(baseline) && (isNaN(top) || isNaN(bottom)))
+ availableHeight = Math.round(bottomHolder - baselineHolder);
+ else
+ availableHeight = Math.round(bottomHolder - topHolder);
+
+ // set width
+ if (!isNaN(percentWidth))
+ {
+ if (!isNaN(left))
+ availableWidth -= left;
+ if (!isNaN(right))
+ availableWidth -= right;
+
+ elementWidth = Math.round(availableWidth * Math.min(percentWidth * 0.01, 1));
+ elementMaxWidth = Math.min(layoutElement.getMaxBoundsWidth(),
+ maxSizeToFitIn(unscaledWidth, left, right, layoutElement.getLayoutBoundsX()));
+ }
+ else if (!isNaN(left) && !isNaN(right))
+ {
+ elementWidth = availableWidth - left - right;
+ }
+
+ // set height
+ if (!isNaN(percentHeight))
+ {
+ if (!isNaN(top))
+ availableHeight -= top;
+ if (!isNaN(bottom))
+ availableHeight -= bottom;
+
+ elementHeight = Math.round(availableHeight * Math.min(percentHeight * 0.01, 1));
+ elementMaxHeight = Math.min(layoutElement.getMaxBoundsHeight(),
+ maxSizeToFitIn(unscaledHeight, top, bottom, layoutElement.getLayoutBoundsY()));
+ }
+ else if (!isNaN(top) && !isNaN(bottom))
+ {
+ elementHeight = availableHeight - top - bottom;
+ }
+
+ // Apply min and max constraints, make sure min is applied last. In the cases
+ // where elementWidth and elementHeight are NaN, setLayoutBoundsSize will use preferredSize
+ // which is already constrained between min and max.
+ if (!isNaN(elementWidth))
+ {
+ if (isNaN(elementMaxWidth))
+ elementMaxWidth = layoutElement.getMaxBoundsWidth();
+ elementWidth = Math.max(layoutElement.getMinBoundsWidth(), Math.min(elementMaxWidth, elementWidth));
+ }
+
+ if (!isNaN(elementHeight))
+ {
+ if (isNaN(elementMaxHeight))
+ elementMaxHeight = layoutElement.getMaxBoundsHeight();
+ elementHeight = Math.max(layoutElement.getMinBoundsHeight(), Math.min(elementMaxHeight, elementHeight));
+ }
+
+ layoutElement.setLayoutBoundsSize(elementWidth, elementHeight);
+ // update temp variables
+ elementWidth = layoutElement.getLayoutBoundsWidth();
+ elementHeight = layoutElement.getLayoutBoundsHeight();
+
+ // Horizontal Position
+ if (!isNaN(left))
+ elementX = leftHolder + left;
+ else if (!isNaN(right))
+ elementX = rightHolder - right - elementWidth;
+ else
+ elementX = layoutElement.getLayoutBoundsX();
+
+ // Vertical Position
+ if (!isNaN(baseline))
+ elementY = baselineHolder + baseline - layoutElement.baselinePosition;
+ else if (!isNaN(top))
+ elementY = topHolder + top;
+ else if (!isNaN(bottom))
+ elementY = bottomHolder - bottom - elementHeight;
+ else
+ elementY = layoutElement.getLayoutBoundsY();
+
+ layoutElement.setLayoutBoundsPosition(elementX, elementY);
+ }
+
+ /**
+ * @private
+ * Updates the widths of content size and percent size columns that are spanned
+ * by the specified element. This method updates the provided column widths
+ * vector in place. The algorithm is as follows:
+ *
+ * 1) Determine the space needed by the element to satisfy its constraints
+ * and be at its preferred size.
+ *
+ * 2) Calculate the number of columns the element will span.
+ *
+ * 3) If the element causes a column to expand, update the column width to match.
+ * a) For the single spanning case, we only need to check if this element's
+ * required width is larger than the column's current width.
+ * b) For the multiple spanning case, we distribute the remaining width after
+ * subtracting the fixed size columns across the content/percent size columns.
+ * Then, we only update a column's width if the new divided width would cause
+ * the column's width to expand.
+ *
+ * @param elementInfo The constraint information of the element.
+ * @param colWidths The vector of column widths to update.
+ */
+ private function updateColumnWidthsForElement(colWidths:Vector.<Number>, elementInfo:ElementConstraintInfo):void
+ {
+ var layoutElement:ILayoutElement = elementInfo.layoutElement;
+ var numCols:int = _constraintColumns.length;
+ var col:ConstraintColumn;
+
+ var leftIndex:int = -1;
+ var rightIndex:int = -1;
+ var span:int;
+
+ var extX:Number = 0;
+ var preferredWidth:Number = layoutElement.getPreferredBoundsWidth();
+ var maxExtent:Number;
+ var remainingWidth:Number;
+
+ var j:int;
+ var colWidth:Number = 0;
+
+ // 1) Determine how much space the element needs to satisfy its
+ // constraints and be at its preferred width.
+ if (!isNaN(elementInfo.left))
+ {
+ extX += elementInfo.left;
+ if (elementInfo.leftBoundary)
+ leftIndex = elementInfo.colSpanLeftIndex;
+ else
+ leftIndex = 0; // constrained to parent
+ }
+
+ if (!isNaN(elementInfo.right))
+ {
+ extX += elementInfo.right;
+ if (elementInfo.rightBoundary)
+ rightIndex = elementInfo.colSpanRightIndex;
+ else
+ rightIndex = numCols - 1; // constrained to parent
+ }
+
+ maxExtent = extX + preferredWidth;
+ remainingWidth = maxExtent;
+
+ // 2) If either the left or the right constraint doesn't exist,
+ // we must find the span of the element. We do this by
+ // determining the index of the last column that the element
+ // occupies in the unconstrained direction.
+ if (leftIndex < 0 || rightIndex < 0)
+ {
+ var isLeft:Boolean = leftIndex < 0;
+ var startIndex:int = isLeft ? rightIndex : leftIndex;
+ var endIndex:int = isLeft ? -1 : numCols;
+ var increment:int = isLeft ? -1 : 1;
+
+ if (isLeft) // defaults to 0
+ leftIndex = 0;
+ else // defaults to numCols - 1
+ rightIndex = numCols - 1;
+
+ for (j = startIndex; j != endIndex ; j += increment)
+ {
+ col = _constraintColumns[j];
+
+ // subtract fixed columns
+ if (!isNaN(col.explicitWidth))
+ remainingWidth -= col.explicitWidth;
+
+ if ((col.contentSize || !isNaN(col.percentWidth)) || remainingWidth < 0)
+ {
+ if (isLeft)
+ leftIndex = j;
+ else
+ rightIndex = j;
+ break;
+ }
+ }
+ }
+ // always 1 or positive.
+ span = rightIndex - leftIndex + 1;
+
+ // 3) If the element causes a column to expand, update the column width to match.
+ if (span == 1)
+ {
+ // a) For the single spanning case, we only need to check if this element's
+ // required width is larger than the column's current width.
+ col = _constraintColumns[leftIndex];
+
+ if (col.contentSize || !isNaN(col.percentWidth))
+ {
+ colWidth = Math.max(colWidths[leftIndex], extX + preferredWidth);
+
+ if (constraintsDetermineWidth(elementInfo))
+ colWidth = Math.max(colWidth, extX + layoutElement.getMinBoundsWidth());
+
+ // bound with max width of column
+ if (!isNaN(col.maxWidth))
+ colWidth = Math.min(colWidth, col.maxWidth);
+
+ colWidths[leftIndex] = Math.ceil(colWidth);
+ }
+ }
+ else
+ {
+ // b) multiple spanning case when span >= 2.
+ // 1) start from leftIndex and subtract fixed columns.
+ // 2) divide space evenly into content/percent size columns.
+ var contentCols:Vector.<ConstraintColumn> = new Vector.<ConstraintColumn>();
+ var contentColsIndices:Vector.<int> = new Vector.<int>();
+
+ remainingWidth = maxExtent;
+ for (j = leftIndex; j <= rightIndex; j++)
+ {
+ col = _constraintColumns[j];
+
+ if (!isNaN(col.explicitWidth))
+ {
+ if (remainingWidth < col.width)
+ break;
+
+ remainingWidth -= col.width;
+ }
+ else if (col.contentSize || !isNaN(col.percentWidth))
+ {
+ contentCols.push(col);
+ contentColsIndices.push(j);
+ }
+ }
+
+ var numContentCols:Number = contentCols.length;
+ if (numContentCols > 0)
+ {
+ var splitWidth:Number = remainingWidth / numContentCols;
+
+ for (j = 0; j < numContentCols; j++)
+ {
+ col = contentCols[j];
+
+ colWidth = Math.max(colWidths[contentColsIndices[j]], splitWidth);
+ if (!isNaN(col.maxWidth))
+ colWidth = Math.min(colWidth, col.maxWidth);
+
+ colWidths[contentColsIndices[j]] = Math.ceil(colWidth);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adjusts the sizes of percent size columns or rows to fill the constrainedSize.
+ * This method updates the provided column widths or row heights vector in place.
+ *
+ * The term, "region", refers to a column or row.
+ * The percent size region sizes are first reset to their minimum size.
+ * If the given region sizes from the content and fixed size regions already
+ * fill the available space, then the percent size region sizes stay at their
+ * minimum size. Otherwise, the remaining space is distributed to the percent
+ * size regions based on the ratio of its percent size to the sum of all the
+ * percent sizes.
+ */
+ private function constrainPercentRegionSizes(sizes:Vector.<Number>, constrainedSize:Number, isColumns:Boolean):void
+ {
+ var col:ConstraintColumn;
+ var row:ConstraintRow;
+ var numSizes:int = isColumns ? _constraintColumns.length : _constraintRows.length;
+
+ var childInfoArray:Array /* of ConstraintRegionFlexChildInfo */ = [];
+ var childInfo:ConstraintRegionFlexChildInfo;
+ var remainingSpace:Number = constrainedSize;
+ var percentMinSizes:Number = 0;
+ var totalPercent:Number = 0;
+
+ // Set percent size regions back to minSize and
+ // find the remaining space.
+ for (var i:int = 0; i < numSizes; i++)
+ {
+ var percentSize:Number;
+ var minSize:Number;
+ var maxSize:Number;
+
+ if (isColumns)
+ {
+ col = _constraintColumns[i];
+ percentSize = col.percentWidth;
+ minSize = col.minWidth;
+ maxSize = col.maxWidth;
+ }
+ else
+ {
+ row = _constraintRows[i];
+ percentSize = row.percentHeight;
+ minSize = row.minHeight;
+ maxSize = row.maxHeight;
+ }
+
+ if (!isNaN(percentSize))
+ {
+ sizes[i] = (!isNaN(minSize)) ? Math.ceil(Math.max(minSize, 0)) : 0;
+ percentMinSizes += sizes[i];
+ totalPercent += percentSize;
+
+ // Fill childInfoArray for distributing the width.
+ childInfo = new ConstraintRegionFlexChildInfo();
+ childInfo.index = i;
+ childInfo.percent = percentSize;
+ childInfo.min = minSize;
+ childInfo.max = maxSize;
+ childInfoArray.push(childInfo);
+ }
+ else
+ {
+ remainingSpace -= sizes[i];
+ }
+ }
+
+ // If there's space remaining, distribute the width to the percent size
+ // columns based on their ratio of percentWidth to sum of all the percentWidths.
+ if (remainingSpace > percentMinSizes)
+ {
+ Flex.flexChildrenProportionally(constrainedSize,
+ remainingSpace,
+ totalPercent,
+ childInfoArray);
+
+ var roundOff:Number = 0;
+ for each (childInfo in childInfoArray)
+ {
+ // Make sure the calculated widths are rounded to pixel boundaries
+ var size:Number = Math.round(childInfo.size + roundOff);
+ roundOff += childInfo.size - size;
+
+ sizes[childInfo.index] = size;
+
+ // remainingSpace -= size;
+ }
+ // TODO (klin): What do we do if there's remainingSpace after all this?
+ }
+ }
+
+ /**
+ * @private
+ * This function measures the ConstraintColumns partitioning
+ * the target and returns their new widths. The calculations
+ * are based on the current constraintCache and other derived
+ * data structures. To update the constraintCache, one needs to
+ * call the parseConstraints() method.
+ *
+ * The widths are measured with the following requirements:
+ * 1. Fixed size columns honor their pixel values.
+ *
+ * 2. Content size columns whose children only span that column
+ * assumes the width of the widest child.
+ *
+ * 3. Content size columns whose children span more than one column
+ * assumes the widest width possible when the child's size is divided
+ * among the spanned columns.
+ * a. Each child divides its preferred width among the content size
+ * columns that it spans. A child also always honors fixed size
+ * columns that it spans.
+ * b. The column takes the widest width given by its children.
+ *
+ * 4. Percent size columns measure exactly like content size columns
+ * at first, but after measurement, if availableWidth is provided,
+ * the percent size columns are remeasured to allow the columns to
+ * fit exactly in the remaining width in accordance with their given
+ * percentage.
+ * a. The percentages given are treated as ratios for how the width
+ * should be divided among the percent size columns.
+ * b. If no remaining space is available or the measured size of all
+ * the content and fixed size columns are greater than the
+ * constrainedWidth, percent size columns are set to their minimum.
+ *
+ * 5. Columns always honor their max and min widths.
+ *
+ * 6. If constrainedWidth is not specified, sum the column widths to find
+ * the total measured width of the target.
+ *
+ * @param constrainedWidth The constraining width to be used when measuring
+ * percent size columns. The default is NaN.
+ *
+ * @return A vector of the new column widths.
+ */
+ mx_internal function measureColumns(constrainedWidth:Number = NaN):Vector.<Number>
+ {
+ // TODO (klin): Parameterize this to work for both columns and rows.
+ // This may mean we need to add some mx_internal properties to
+ // the columns for "major size", etc... Question is, what about
+ // 1-D properties like baseline? What parts can we parameterize and
+ // what parts aren't possible.
+
+ // Parse constraints if it hasn't been done yet, make sure to clear
+ // the cache afterwards.
+ var clearCache:Boolean = false;
+ if (!constraintCache)
+ {
+ parseConstraints();
+ clearCache = true;
+ }
+
+ if (_constraintColumns.length <= 0)
+ return new Vector.<Number>();
+
+ var measuredWidth:Number = 0;
+ var i:Number;
+ var numCols:Number = _constraintColumns.length;
+ var col:ConstraintColumn;
+ var hasContentSize:Boolean = false;
+ var hasPercentSize:Boolean = false;
+ var colWidths:Vector.<Number> = new Vector.<Number>(numCols);
+
+ // Start column widths at the minWidth of each column or
+ // its explicit width.
+ for (i = 0; i < numCols; i++)
+ {
+ col = _constraintColumns[i];
+
+ if (col.contentSize || !isNaN(col.percentWidth))
+ {
+ hasContentSize ||= col.contentSize;
+ hasPercentSize ||= !isNaN(col.percentWidth);
+
+ if (!isNaN(col.minWidth))
+ colWidths[i] = Math.ceil(Math.max(col.minWidth, 0));
+ else
+ colWidths[i] = 0;
+ }
+ else if (!isNaN(col.explicitWidth))
+ {
+ var w:Number = col.explicitWidth;
+
+ if (!isNaN(col.minWidth))
+ w = Math.max(w, col.minWidth);
+
+ if (!isNaN(col.maxWidth))
+ w = Math.min(w, col.maxWidth);
+
+ colWidths[i] = Math.ceil(w);
+ }
+ }
+
+ // Assumption: elements in colSpanElements have one or more constraints touching a column.
+ // This is enforced in parseElementConstraints().
+ if (colSpanElements && (hasContentSize || hasPercentSize))
+ {
+ // Measure content/percent size columns.
+ for each (var elementInfo:ElementConstraintInfo in colSpanElements)
+ {
+ updateColumnWidthsForElement(colWidths, elementInfo);
+ }
+ }
+
+ // Adjust percent size columns to account for constraining width.
+ if (!isNaN(constrainedWidth) && hasPercentSize)
+ {
+ constrainPercentRegionSizes(colWidths, constrainedWidth, true);
+ }
+
+ // Clear the cache only if we created it just for this method call.
+ if (clearCache)
+ clearConstraintCache();
+
+ return colWidths;
+ }
+
+ /**
+ * @private
+ * Updates the heights of content size and percent size rows that are spanned
+ * by the specified element. This method updates the provided row heights
+ * vector in place. The algorithm is as follows:
+ *
+ * 1) Determine the space needed by the element to satisfy its constraints
+ * and be at its preferred size.
+ *
+ * 2) Calculate the number of rows the element will span.
+ *
+ * 3) If the element causes a row to expand, update the row height to match.
+ * a) For the single spanning case, we only need to check if this element's
+ * required height is larger than the row's current height.
+ * b) For the multiple spanning case, we distribute the remaining height after
+ * subtracting the fixed size rows across the content/percent size rows.
+ * Then, we only update a row's height if the new divided height would cause
+ * the row's height to expand.
+ *
+ * @param elementInfo The constraint information of the element.
+ * @param colWidths The vector of column widths to update.
+ */
+ private function updateRowHeightsForElement(rowHeights:Vector.<Number>, elementInfo:ElementConstraintInfo):void
+ {
+ var layoutElement:ILayoutElement = elementInfo.layoutElement;
+ var numRows:int = _constraintRows.length;
+ var row:ConstraintRow;
+
+ var topIndex:int = -1;
+ var bottomIndex:int = -1;
+ var span:int;
+
+ var extY:Number = 0;
+ var preferredHeight:Number = layoutElement.getPreferredBoundsHeight();
+ var maxExtent:Number;
+ var remainingHeight:Number;
+
+ var j:int;
+ var rowHeight:Number = 0;
+
+ // 1) Determine how much space the element needs to satisfy its
+ // constraints and be at its preferred height.
+ if (!isNaN(elementInfo.top))
+ {
+ extY += elementInfo.top;
+ if (elementInfo.topBoundary)
+ topIndex = elementInfo.rowSpanTopIndex;
+ else
+ topIndex = 0; // constrained to parent
+ }
+
+ if (!isNaN(elementInfo.bottom))
+ {
+ extY += elementInfo.bottom;
+ if (elementInfo.bottomBoundary)
+ bottomIndex = elementInfo.rowSpanBottomIndex;
+ else
+ bottomIndex = numRows - 1; // constrained to parent
+ }
+
+ // Only include baseline if at least one of top or bottom don't
+ // exist.
+ if (!isNaN(elementInfo.baseline) && (topIndex < 0 || bottomIndex < 0))
+ {
+ extY += elementInfo.baseline - layoutElement.baselinePosition;
+
+ if (!isNaN(elementInfo.top))
+ extY -= elementInfo.top;
+
+ if (elementInfo.baselineBoundary)
+ {
+ topIndex = elementInfo.baselineIndex;
+
+ // add baseline offset.
+ extY += Number(rowBaselines[topIndex][0]);
+
+ // add maxAscent. maxAscent is 0 if not specified on the row.
+ if (rowMaxAscents)
+ extY += rowMaxAscents[topIndex];
+ }
+ else
+ {
+ topIndex = 0;
+ }
+ }
+
+ maxExtent = extY + preferredHeight;
+ remainingHeight = maxExtent;
+
+ // 2) If either the top or the bottom constraint doesn't exist,
+ // we must find the span of the element. We do this by
+ // determining the index of the last row that the element
+ // occupies in the unconstrained direction.
+ if (topIndex < 0 || bottomIndex < 0)
+ {
+ var isTop:Boolean = topIndex < 0;
+ var startIndex:int = isTop ? bottomIndex : topIndex;
+ var endIndex:int = isTop ? -1 : numRows;
+ var increment:int = isTop ? -1 : 1;
+
+ if (isTop) // defaults to 0
+ topIndex = 0;
+ else // defaults to numRows - 1
+ bottomIndex = numRows - 1;
+
+ for (j = startIndex; j != endIndex ; j += increment)
+ {
+ row = _constraintRows[j];
+
+ // subtract fixed rows
+ if (!isNaN(row.explicitHeight))
+ remainingHeight -= row.explicitHeight;
+
+ if ((row.contentSize || !isNaN(row.percentHeight)) || remainingHeight < 0)
+ {
+ if (isTop)
+ topIndex = j;
+ else
+ bottomIndex = j;
+ break;
+ }
+ }
+ }
+ // always 1 or positive.
+ span = bottomIndex - topIndex + 1;
+
+ // 3) If the element causes a row to expand, update the row height to match.
+ if (span == 1)
+ {
+ // a) For the single spanning case, we only need to check if this element's
+ // required height is larger than the row's current height.
+ row = _constraintRows[topIndex];
+
+ if (row.contentSize || !isNaN(row.percentHeight))
+ {
+ rowHeight = Math.max(rowHeights[topIndex], extY + preferredHeight);
+
+ if (constraintsDetermineHeight(elementInfo))
+ rowHeight = Math.max(rowHeight, extY + layoutElement.getMinBoundsHeight());
+
+ // bound with max height of row
+ if (!isNaN(row.maxHeight))
+ rowHeight = Math.min(rowHeight, row.maxHeight);
+
+ rowHeights[topIndex] = Math.ceil(rowHeight);
+ }
+ }
+ else
+ {
+ // b) multiple spanning case. span >= 2.
+ // 1) start from topIndex and subtract fixed rows
+ // 2) divide space evenly into content/percent size rows.
+ var contentRows:Vector.<ConstraintRow> = new Vector.<ConstraintRow>();
+ var contentRowsIndices:Vector.<int> = new Vector.<int>();
+
+ remainingHeight = maxExtent;
+ for (j = topIndex; j <= bottomIndex; j++)
+ {
+ row = _constraintRows[j];
+
+ if (!isNaN(row.explicitHeight))
+ {
+ if (remainingHeight < row.height)
+ break;
+
+ remainingHeight -= row.height;
+ }
+ else if (row.contentSize || !isNaN(row.percentHeight))
+ {
+ contentRows.push(row);
+ contentRowsIndices.push(j);
+ }
+ }
+
+ var numContentRows:Number = contentRows.length;
+ if (numContentRows > 0)
+ {
+ var splitHeight:Number = remainingHeight / numContentRows;
+
+ for (j = 0; j < numContentRows; j++)
+ {
+ row = contentRows[j];
+
+ rowHeight = Math.max(rowHeights[contentRowsIndices[j]], splitHeight);
+ if (!isNaN(row.maxHeight))
+ rowHeight = Math.min(rowHeight, row.maxHeight);
+
+ rowHeights[contentRowsIndices[j]] = Math.ceil(rowHeight);
+ }
+ }
+ }
+ }
+
+ /**
+ * @private
+ * Synonymous to measureColumns(), but with added baseline constraint.
+ * Baseline is only included in the measurement if at least one of the element's
+ * top or bottom constraint doesn't exist. The calculations are based on the
+ * current constraintCache. To update the constraintCache, one needs to call
+ * the parseConstraints() method.
+ */
+ private function measureRows(constrainedHeight:Number = NaN):Vector.<Number>
+ {
+ if (_constraintRows.length <= 0)
+ return new Vector.<Number>();
+
+ var measuredHeight:Number = 0;
+ var i:Number;
+ var numRows:Number = _constraintRows.length;
+ var row:ConstraintRow;
+ var hasContentSize:Boolean = false;
+ var hasPercentSize:Boolean = false;
+ var rowHeights:Vector.<Number> = new Vector.<Number>(numRows);
+
+ // Start row heights at the minHeight of each row or
+ // its explicit height.
+ for (i = 0; i < numRows; i++)
+ {
+ row = _constraintRows[i];
+
+ if (row.contentSize || !isNaN(row.percentHeight))
+ {
+ hasContentSize ||= row.contentSize;
+ hasPercentSize ||= !isNaN(row.percentHeight);
+
+ if (!isNaN(row.minHeight))
+ rowHeights[i] = Math.ceil(Math.max(row.minHeight, 0));
+ else
+ rowHeights[i] = 0;
+ }
+ else if (!isNaN(row.explicitHeight))
+ {
+ var h:Number = row.explicitHeight;
+
+ if (!isNaN(row.minHeight))
+ h = Math.max(h, row.minHeight);
+
+ if (!isNaN(row.maxHeight))
+ h = Math.min(h, row.maxHeight);
+
+ rowHeights[i] = Math.ceil(h);
+ }
+ }
+
+ // Assumption: elements in rowSpanElements have one or more constraints touching a row.
+ // This is enforced in parseElementConstraints().
+ if (rowSpanElements && (hasContentSize || hasPercentSize))
+ {
+ // Measure content/percent size columns.
+ for each (var elementInfo:ElementConstraintInfo in rowSpanElements)
+ {
+ updateRowHeightsForElement(rowHeights, elementInfo);
+ }
+ }
+
+ // Adjust percent size rows to account for constraining height.
+ if (!isNaN(constrainedHeight) && hasPercentSize)
+ {
+ constrainPercentRegionSizes(rowHeights, constrainedHeight, false);
+ }
+
+ return rowHeights;
+ }
+
+ /**
+ * @private
+ * Measures the size of target based on content not included in the columns and rows.
+ * Basically, applies BasicLayout to other content to determine measured size.
+ * Returns a vector with the measured [width, height, minWidth, minHeight].
+ */
+ private function measureOtherContent():Vector.<Number>
+ {
+ var width:Number = 0;
+ var height:Number = 0;
+ var minWidth:Number = 0;
+ var minHeight:Number = 0;
+ var count:int = otherElements.length;
+
+ for (var i:int = 0; i < count; i++)
+ {
+ var elementInfo:ElementConstraintInfo = otherElements[i];
+ var layoutElement:ILayoutElement = elementInfo.layoutElement;
+
+ // Only measure width if not constrained to columns.
+ if (!elementInfo.leftBoundary && !elementInfo.rightBoundary)
+ {
+ var left:Number = elementInfo.left;
+ var right:Number = elementInfo.right;
+ var extX:Number;
+
+ if (!isNaN(left) && !isNaN(right))
+ {
+ // If both left & right are set, then the extents is always
+ // left + right so that the element is resized to its preferred
+ // size (if it's the one that pushes out the default size of the container).
+ extX = left + right;
+ }
+ else if (!isNaN(left) || !isNaN(right))
+ {
+ extX = isNaN(left) ? 0 : left;
+ extX += isNaN(right) ? 0 : right;
+ }
+ else
+ {
+ extX = layoutElement.getBoundsXAtSize(NaN, NaN);
+ }
+
+ var preferredWidth:Number = layoutElement.getPreferredBoundsWidth();
+ width = Math.max(width, extX + preferredWidth);
+
+ // Find the minimum default extents, we take the minimum height only
+ // when the element size is determined by the parent size
+ var elementMinWidth:Number =
+ constraintsDetermineWidth(elementInfo) ? layoutElement.getMinBoundsWidth() :
+ preferredWidth;
+
+ minWidth = Math.max(minWidth, extX + elementMinWidth);
+ }
+
+ // only measure height if not constrained to rows.
+ var noVerticalBoundaries:Boolean = !elementInfo.topBoundary && !elementInfo.bottomBoundary;
+ var noBaselineBoundary:Boolean = !elementInfo.baselineBoundary;
+
+ if (noVerticalBoundaries || noBaselineBoundary)
+ {
+ var top:Number;
+ var bottom:Number;
+ var baseline:Number;
+ var extY:Number;
+
+ if (noVerticalBoundaries)
+ {
+ top = elementInfo.top;
+ bottom = elementInfo.bottom;
+ }
+
+ if (noBaselineBoundary)
+ baseline = elementInfo.baseline;
+
+ if (!isNaN(top) && !isNaN(bottom))
+ {
+ // If both top & bottom are set, then the extents is always
+ // top + bottom so that the element is resized to its preferred
+ // size (if it's the one that pushes out the default size of the container).
+ extY = top + bottom;
+ }
+ else if (!isNaN(baseline))
+ {
+ extY = Math.round(baseline - layoutElement.baselinePosition);
+ }
+ else if (!isNaN(top) || !isNaN(bottom))
+ {
+ extY = isNaN(top) ? 0 : top;
+ extY += isNaN(bottom) ? 0 : bottom;
+ }
+ else
+ {
+ extY = layoutElement.getBoundsYAtSize(NaN, NaN);
+ }
+
+ var preferredHeight:Number = layoutElement.getPreferredBoundsHeight();
+ height = Math.max(height, extY + preferredHeight);
+
+ // Find the minimum default extents, we take the minimum height only
+ // when the element size is determined by the parent size
+ var elementMinHeight:Number =
+ constraintsDetermineHeight(elementInfo) ? layoutElement.getMinBoundsHeight() :
+ preferredHeight;
+
+ minHeight = Math.max(minHeight, extY + elementMinHeight);
+ }
+ }
+
+ var vec:Vector.<Number> = new Vector.<Number>(4, true);
+ vec[0] = Math.max(width, minWidth);
+ vec[1] = Math.max(height, minHeight);
+ vec[2] = minWidth;
+ vec[3] = minHeight;
+
+ return vec;
+ }
+
+ /**
+ * @private
+ * Iterates over elements and calls parseElementConstraints on each.
+ */
+ private function parseConstraints():void
+ {
+ var layoutTarget:GroupBase = target;
+ if (!layoutTarget)
+ return;
+
+ constraintCacheNeeded++;
+
+ var count:Number = layoutTarget.numElements;
+ var layoutElement:ILayoutElement;
+
+ COMPILE::SWF
+ {
+ var cache:Dictionary = new Dictionary(true);
+ }
+ COMPILE::JS
+ {
+ var cache:Object = {};
+ }
+ var i:int;
+
+ // Populate rowBaselines with baseline information from rows.
+ var n:int = _constraintRows.length;
+ var row:ConstraintRow;
+
+ if (rowBaselines == null)
+ rowBaselines = new Vector.<Array>();
+ else
+ rowBaselines.length = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ row = _constraintRows[i];
+ rowBaselines[i] = LayoutElementHelper.parseConstraintExp(row.baseline);
+
+ var maxAscentStr:String = rowBaselines[i][1];
+ if (maxAscentStr && maxAscentStr != "maxAscent")
+ throw new Error(ResourceManager.getInstance().getString("layout", "invalidBaselineOnRow",
+ [ row.id, row.baseline ]));
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ layoutElement = layoutTarget.getElementAt(i) as ILayoutElement;
+ if (!layoutElement || !layoutElement.includeInLayout)
+ continue;
+
+ parseElementConstraints(layoutElement, cache);
+ }
+
+ this.constraintCache = cache;
+ constraintCacheNeeded--;
+ }
+
+ /**
+ * @private
+ * This function parses the constraints of a single element, creates an
+ * ElementConstraintInfo object for the element, and throws errors if the
+ * columns or rows are not found for each constraint.
+ */
+ private function parseElementConstraints(layoutElement:ILayoutElement, constraintCache:Object /*Dictionary*/):void
+ {
+ // Variables to track the offsets
+ var left:Number;
+ var right:Number;
+ var top:Number;
+ var bottom:Number;
+ var baseline:Number;
+
+ // Variables to track the boundaries from which
+ // the offsets are calculated from. If null, the
+ // boundary is the parent container edge.
+ var leftBoundary:String;
+ var rightBoundary:String;
+ var topBoundary:String;
+ var bottomBoundary:String;
+ var baselineBoundary:String;
+
+ var message:String;
+
+ var temp:Array = LayoutElementHelper.parseConstraintExp(layoutElement.left);
+ left = temp[0];
+ leftBoundary = temp[1];
+
+ temp = LayoutElementHelper.parseConstraintExp(layoutElement.right, temp);
+ right = temp[0];
+ rightBoundary = temp[1];
+
+ temp = LayoutElementHelper.parseConstraintExp(layoutElement.top, temp);
+ top = temp[0];
+ topBoundary = temp[1];
+
+ temp = LayoutElementHelper.parseConstraintExp(layoutElement.bottom, temp);
+ bottom = temp[0];
+ bottomBoundary = temp[1];
+
+ temp = LayoutElementHelper.parseConstraintExp(layoutElement.baseline, temp);
+ baseline = temp[0];
+ baselineBoundary = temp[1];
+
+ // save values into a Dictionary based on element name.
+ var elementInfo:ElementConstraintInfo = new ElementConstraintInfo(layoutElement,
+ left, right, top, bottom, baseline,
+ leftBoundary, rightBoundary,
+ topBoundary, bottomBoundary, baselineBoundary);
+ COMPILE::SWF
+ {
+ constraintCache[layoutElement] = elementInfo;
+ }
+ COMPILE::JS
+ {
+ constraintCache[layoutElement['constraintElementId']] = elementInfo;
+
+ }
+
+
+ // If some pair of boundaries don't exist, we will need to measure
+ // the container size based on the element's other properties like
+ // x, y, width, height.
+ var i:Number;
+ if ((!leftBoundary && !rightBoundary) ||
+ (!topBoundary && !bottomBoundary) ||
+ !baselineBoundary)
+ {
+ if (!otherElements)
+ otherElements = new Vector.<ElementConstraintInfo>();
+
+ otherElements.push(elementInfo);
+ }
+
+ // match columns
+ if (leftBoundary || rightBoundary)
+ {
+ var numColumns:Number = _constraintColumns.length;
+ var colIndex:Object;
+
+ if (!colSpanElements)
+ colSpanElements = new Vector.<ElementConstraintInfo>();
+
+ colSpanElements.push(elementInfo);
+
+ if (leftBoundary)
+ {
+ colIndex = columnsObject[leftBoundary];
+
+ if (colIndex != null)
+ elementInfo.colSpanLeftIndex = int(colIndex);
+
+ // throw error if no match.
+ if (elementInfo.colSpanLeftIndex < 0)
+ {
+ message = ResourceManager.getInstance().getString(
+ "layout", "columnNotFound", [ leftBoundary ]);
+ throw new ConstraintError(message);
+ }
+ }
+
+ // can we assume rightIndex >= leftIndex?
+ if (rightBoundary)
+ {
+ colIndex = columnsObject[rightBoundary];
+
+ if (colIndex != null)
+ elementInfo.colSpanRightIndex = int(colIndex);
+
+ // throw error if no match.
+ if (elementInfo.colSpanRightIndex < 0)
+ {
+ message = ResourceManager.getInstance().getString(
+ "layout", "columnNotFound", [ rightBoundary ]);
+ throw new ConstraintError(message);
+ }
+ }
+ }
+
+ // match rows.
+ if (topBoundary || bottomBoundary || baselineBoundary)
+ {
+ var rowIndex:Object;
+
+ if (!rowSpanElements)
+ rowSpanElements = new Vector.<ElementConstraintInfo>();
+
+ rowSpanElements.push(elementInfo);
+
+ if (topBoundary)
+ {
+ rowIndex = rowsObject[topBoundary];
+
+ if (rowIndex != null)
+ elementInfo.rowSpanTopIndex = int(rowIndex);
+
+ // throw error if no match.
+ if (elementInfo.rowSpanTopIndex < 0)
+ {
+ message = ResourceManager.getInstance().getString(
+ "layout", "rowNotFound", [ topBoundary ]);
+ throw new ConstraintError(message);
+ }
+ }
+
+ if (bottomBoundary)
+ {
+ rowIndex = rowsObject[bottomBoundary];
+
+ if (rowIndex != null)
+ elementInfo.rowSpanBottomIndex = int(rowIndex);
+
+ // throw error if no match.
+ if (elementInfo.rowSpanBottomIndex < 0)
+ {
+ message = ResourceManager.getInstance().getString(
+ "layout", "rowNotFound", [ bottomBoundary ]);
+ throw new ConstraintError(message);
+ }
+ }
+
+ if (baselineBoundary)
+ {
+ rowIndex = rowsObject[baselineBoundary];
+
+ if (rowIndex != null)
+ elementInfo.baselineIndex = int(rowIndex);
+
+ // throw error if no match.
+ if (elementInfo.baselineIndex < 0)
+ {
+ message = ResourceManager.getInstance().getString(
+ "layout", "rowNotFound", [ baselineBoundary ]);
+ throw new ConstraintError(message);
+ }
+
+ // when using maxAscent, calculate maximum baselinePosition for this row.
+ var bIndex:int = elementInfo.baselineIndex;
+ var numRows:Number = _constraintRows.length;
+
+ if (rowBaselines[bIndex][1])
+ {
+ // maxAscents will all default to 0.
+ if (!rowMaxAscents)
+ rowMaxAscents = new Vector.<Number>(numRows, true);
+
+ rowMaxAscents[bIndex] = Math.max(rowMaxAscents[bIndex], layoutElement.baselinePosition);
+ }
+ }
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function clearConstraintCache():void
+ {
+ if(!constraintCacheNeeded)
+ {
+ colSpanElements = null;
+ rowSpanElements = null;
+ otherElements = null;
+ rowBaselines = null;
+ rowMaxAscents = null;
+ constraintCache = null;
+ }
+ }
+}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Helper class: ElementConstraintInfo
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import mx.core.ILayoutElement;
+
+class ElementConstraintInfo
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ public function ElementConstraintInfo(
+ layoutElement:ILayoutElement,
+ left:Number, right:Number,
+ top:Number, bottom:Number,
+ baseline:Number, leftBoundary:String = null,
+ rightBoundary:String = null,
+ topBoundary:String = null, bottomBoundary:String = null,
+ baselineBoundary:String = null,
+ colSpanLeftIndex:int = -1, colSpanRightIndex:int = -1,
+ rowSpanTopIndex:int = -1, rowSpanBottomIndex:int = -1,
+ baselineIndex:int = -1):void
+ {
+ super();
+
+ // pointer to element
+ this.layoutElement = layoutElement;
+
+ // offsets
+ this.left = left;
+ this.right = right;
+ this.top = top;
+ this.bottom = bottom;
+ this.baseline = baseline;
+
+ // boundaries (ie: parent, column or row edge)
+ this.leftBoundary = leftBoundary;
+ this.rightBoundary = rightBoundary;
+ this.topBoundary = topBoundary;
+ this.bottomBoundary = bottomBoundary;
+ this.baselineBoundary = baselineBoundary;
+
+ this.colSpanLeftIndex = colSpanLeftIndex;
+ this.colSpanRightIndex = colSpanRightIndex;
+ this.rowSpanTopIndex = rowSpanTopIndex;
+ this.rowSpanBottomIndex = rowSpanBottomIndex;
+ this.baselineIndex = baselineIndex;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ public var layoutElement:ILayoutElement;
+
+ public var left:Number;
+ public var right:Number;
+ public var top:Number;
+ public var bottom:Number;
+ public var baseline:Number;
+ public var leftBoundary:String;
+ public var rightBoundary:String;
+ public var topBoundary:String;
+ public var bottomBoundary:String;
+ public var baselineBoundary:String;
+
+ public var colSpanLeftIndex:int;
+ public var colSpanRightIndex:int;
+ public var rowSpanTopIndex:int;
+ public var rowSpanBottomIndex:int;
+ public var baselineIndex:int;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Helper class: ConstraintRegionFlexChildInfo
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import mx.containers.utilityClasses.FlexChildInfo;
+
+class ConstraintRegionFlexChildInfo extends FlexChildInfo
+{
+ public var index:int
+}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/FormItemLayout.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/FormItemLayout.as
index 58778ac..b2586d1 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/FormItemLayout.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/FormItemLayout.as
@@ -35,7 +35,7 @@ package spark.layouts
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
- public class FormItemLayout //extends ConstraintLayout
+ public class FormItemLayout extends ConstraintLayout
{
//--------------------------------------------------------------------------
//
@@ -62,7 +62,7 @@ package spark.layouts
* @private
* Only resize columns and rows if setLayoutColumnWidths hasn't been called.
*/
- /*override public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ override public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
checkUseVirtualLayout();
@@ -77,7 +77,7 @@ package spark.layouts
setColumnWidths(layoutColumnWidths);
layoutContent(unscaledWidth, unscaledHeight);
- }*/
+ }
/**
* @private
@@ -85,7 +85,7 @@ package spark.layouts
*/
public function getMeasuredColumnWidths():Vector.<Number>
{
- return null; //measureColumns();
+ return measureColumns();
}
/**
@@ -98,7 +98,7 @@ package spark.layouts
// apply new measurements and position the columns again.
layoutColumnWidths = value;
- // setColumnWidths(layoutColumnWidths);
+ setColumnWidths(layoutColumnWidths);
// target.invalidateDisplayList();
}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/FormLayout.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/FormLayout.as
index 5de74d7..5d6a474 100644
--- a/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/FormLayout.as
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/layouts/FormLayout.as
@@ -369,7 +369,7 @@ package spark.layouts
* percent widths.
*/
private function constrainPercentColumnWidths(colWidths:Vector.<Number>, constrainedWidth:Number, formItems:Vector.<ILayoutElement>):void
- {/*
+ {
if (formItems.length == 0)
return;
@@ -378,7 +378,7 @@ package spark.layouts
const constraintColumns:Vector.<ConstraintColumn> = fiLayout.constraintColumns;
const numCols:int = constraintColumns.length;
var col:ConstraintColumn;
- var childInfoArray:Array*/ /* of ColumnFlexChildInfo *//* = [];
+ var childInfoArray:Array /* of ColumnFlexChildInfo */ = [];
var childInfo:ColumnFlexChildInfo;
var remainingWidth:Number = constrainedWidth;
var percentMinWidths:Number = 0;
@@ -430,7 +430,7 @@ package spark.layouts
remainingWidth -= colWidth;
}
// TODO (klin): What do we do if there's remainingWidth after all this?
- }*/
+ }
}
}
}
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/skins/spark/FormItemSkin.mxml b/frameworks/projects/SparkRoyale/src/main/royale/spark/skins/spark/FormItemSkin.mxml
new file mode 100644
index 0000000..f562d6a
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/skins/spark/FormItemSkin.mxml
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!--- The default skin class for the Spark FormItem component.
+
+@see spark.components.FormItem
+
+@langversion 3.0
+@playerversion Flash 10
+@playerversion AIR 1.5
+@productversion Flex 4.5
+-->
+<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:s="library://ns.apache.org/royale/spark"
+ alpha.disabledStates=".5" creationComplete="init()">
+
+ <!-- host component -->
+ <fx:Metadata>
+ <![CDATA[
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ [HostComponent("spark.components.FormItem")]
+ ]]>
+ </fx:Metadata>
+
+ <fx:Script>
+ <![CDATA[
+ public function init():void {
+ requiredToolTip = resourceManager.getString("components","formItemRequired");
+ }
+
+ private var _requiredToolTip:String;
+ /**
+ * The tooltip of the label showing when the component is required but nothing has been entered.
+ * Subclasses can set or override this property to customize the selected label.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.11
+ */
+ [Bindable]
+ protected function get requiredToolTip():String
+ {
+ return _requiredToolTip;
+ }
+
+ protected function set requiredToolTip(value:String):void
+ {
+ _requiredToolTip = value;
+ }
+
+ /**
+ * @private
+ */
+ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
+ {
+ // Push backgroundColor and backgroundAlpha directly.
+ // Handle undefined backgroundColor by hiding the background object.
+ if (isNaN(getStyle("backgroundColor")))
+ {
+ background.visible = false;
+ }
+ else
+ {
+ background.visible = true;
+ bgFill.color = getStyle("backgroundColor");
+ bgFill.alpha = getStyle("backgroundAlpha");
+ }
+
+ var indicatorSource:Object;
+ if (currentState == "error" || currentState == "requiredAndError")
+ indicatorSource = getStyle("errorIndicatorSource");
+ else if (currentState == "required" || "requiredAndDisabled")
+ indicatorSource = getStyle("requiredIndicatorSource");
+
+ if (indicatorSource && indicatorDisplay)
+ {
+ indicatorDisplay.source = indicatorSource;
+ }
+
+ super.updateDisplayList(unscaledWidth, unscaledHeight);
+ }
+
+ /**
+ * @private
+ */
+ override public function setCurrentState(stateName:String, playTransition:Boolean=true):void
+ {
+ super.setCurrentState(stateName, playTransition);
+ invalidateDisplayList();
+ }
+ ]]>
+ </fx:Script>
+
+ <s:states>
+ <s:State name="normal" />
+ <s:State name="disabled" stateGroups="disabledStates"/>
+ <s:State name="error" stateGroups="errorStates"/>
+ <s:State name="required" stateGroups="requiredStates"/>
+ <s:State name="requiredAndDisabled" stateGroups="requiredStates, disabledStates"/>
+ <s:State name="requiredAndError" stateGroups="requiredStates, errorStates"/>
+ </s:states>
+
+ <s:layout>
+ <s:FormItemLayout>
+ <s:constraintColumns>
+ <!--- The column containing the sequence label. -->
+ <s:ConstraintColumn id="sequenceCol" />
+ <!--- The column containing the FormItem's label. -->
+ <s:ConstraintColumn id="labelCol" />
+ <!--- The column containing the FormItem's content. -->
+ <s:ConstraintColumn id="contentCol" width="100%"/>
+ <!--- The column containing the FormItem's help content. -->
+ <s:ConstraintColumn id="helpCol" maxWidth="200"/>
+ </s:constraintColumns>
+ <s:constraintRows>
+ <!--- @private -->
+ <s:ConstraintRow id="row1" baseline="maxAscent:10" height="100%"/>
+ </s:constraintRows>
+ </s:FormItemLayout>
+ </s:layout>
+
+ <!--- Defines the appearance of the FormItem's background. -->
+ <s:Rect id="background" left="0" right="0" top="0" bottom="0">
+ <s:fill>
+ <!--- @private -->
+ <s:SolidColor id="bgFill" color="#FFFFFF"/>
+ </s:fill>
+ </s:Rect>
+
+ <!--- @copy spark.components.FormItem#sequenceLabelDisplay -->
+ <s:Label id="sequenceLabelDisplay"
+ fontWeight="bold"
+ left="sequenceCol:10" right="sequenceCol:5"
+ bottom="row1:10" baseline="row1:0"/>
+ <!--- @copy spark.components.FormItem#labelDisplay -->
+ <s:Label id="labelDisplay"
+ fontWeight="bold"
+ left="labelCol:0" right="labelCol:5"
+ bottom="row1:10" baseline="row1:0"/>
+ <!--- @copy spark.components.SkinnableContainer#contentGroup -->
+ <!-- Don't show the error tip on the content elements -->
+ <s:Group id="contentGroup" showErrorTip="false" showErrorSkin="true"
+ left="contentCol:0" right="contentCol:1"
+ baseline="row1:0" bottom="row1:10">
+ <s:layout>
+ <s:VerticalLayout/>
+ </s:layout>
+ </s:Group>
+ <!-- Don't include the indicator in layout since we position it ourselves -->
+ <s:Group x="{contentGroup.x + contentGroup.contentWidth + 4}" y="{contentGroup.y}"
+ height="{Math.max(indicatorDisplay.height, contentGroup.contentHeight)}" includeInLayout="false">
+ <!--- @private -->
+ <s:Image id="indicatorDisplay" verticalCenter="0"
+ toolTip="{requiredToolTip}" toolTip.errorStates=""
+ includeIn="requiredStates,errorStates"/>
+ </s:Group>
+
+ <!--- @copy spark.components.FormItem#helpContentGroup -->
+ <s:Group id="helpContentGroup" excludeFrom="errorStates"
+ fontStyle="italic" fontWeight="normal" color="0x666666"
+ left="helpCol:27" right="helpCol:10"
+ bottom="row1:10" baseline="row1:0"/>
+ <!--- @copy spark.components.FormItem#errorTextDisplay -->
+ <s:RichText id="errorTextDisplay" includeIn="errorStates"
+ fontStyle="italic" fontWeight="normal" color="0xFE0000"
+ left="helpCol:27" right="helpCol:10"
+ bottom="row1:10" baseline="row1:0"
+ maxDisplayedLines="-1"/>
+ </s:Skin>
\ No newline at end of file
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/skins/spark/FormSkin.mxml b/frameworks/projects/SparkRoyale/src/main/royale/spark/skins/spark/FormSkin.mxml
new file mode 100644
index 0000000..e5da8cb
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/skins/spark/FormSkin.mxml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!--- The default skin class for a Spark Form container.
+
+This skin defines a contentGroup for the Form container with a
+FormLayout as its layout object. The FormLayout is a VerticalLayout
+that has additional logic to align the columns of FormItems.
+
+@see spark.components.Form
+@see spark.layouts.FormLayout
+
+@langversion 3.0
+@playerversion Flash 10
+@playerversion AIR 1.5
+@productversion Flex 4.5
+-->
+<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:s="library://ns.apache.org/royale/spark"
+ alpha.disabled="0.5">
+
+ <fx:Metadata>
+ <![CDATA[
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ [HostComponent("spark.components.Form")]
+ ]]>
+ </fx:Metadata>
+ <fx:Script >
+
+ <![CDATA[
+ /**
+ * @private
+ */
+ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
+ {
+ // Push backgroundColor and backgroundAlpha directly.
+ // Handle undefined backgroundColor by hiding the background object.
+ if (isNaN(getStyle("backgroundColor")))
+ {
+ background.visible = false;
+ }
+ else
+ {
+ background.visible = true;
+ bgFill.color = getStyle("backgroundColor");
+ bgFill.alpha = getStyle("backgroundAlpha");
+ }
+
+ super.updateDisplayList(unscaledWidth, unscaledHeight);
+ }
+ ]]>
+ </fx:Script>
+
+ <s:states>
+ <s:State name="normal" />
+ <s:State name="error" />
+ <s:State name="disabled" />
+ </s:states>
+
+ <!--- Defines the appearance of the Form class's background. -->
+ <s:Rect id="background" left="0" right="0" top="0" bottom="0">
+ <s:fill>
+ <!--- @private -->
+ <s:SolidColor id="bgFill" color="#FFFFFF"/>
+ </s:fill>
+ </s:Rect>
+ <!--- @copy spark.components.SkinnableContainer#contentGroup -->
+ <!-- We set Form's showErrorTip and showErrorSkin to false, so we set them back
+ to true for the Form's elements -->
+ <s:Group id="contentGroup" showErrorSkin="true" showErrorTip="true"
+ left="10" right="10" top="10" bottom="10">
+ <s:layout>
+ <s:FormLayout gap="7"/>
+ </s:layout>
+ </s:Group>
+
+
+</s:Skin>