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/11/26 18:56:14 UTC
[royale-asjs] branch develop updated: implement divided box layout
handling from Flex DividedBox updateDisplayList. Should fix #592
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
The following commit(s) were added to refs/heads/develop by this push:
new 5a037ed implement divided box layout handling from Flex DividedBox updateDisplayList. Should fix #592
5a037ed is described below
commit 5a037edf3c9f857708de964ac9e0cffbed7d8fb4
Author: Alex Harui <ah...@apache.org>
AuthorDate: Tue Nov 26 10:55:58 2019 -0800
implement divided box layout handling from Flex DividedBox updateDisplayList. Should fix #592
---
.../MXRoyale/src/main/royale/MXRoyaleClasses.as | 1 +
.../MXRoyale/src/main/royale/mx/containers/Box.as | 10 +-
.../src/main/royale/mx/containers/DividedBox.as | 8 +
.../royale/mx/containers/beads/DividedBoxLayout.as | 298 +++++++++++++++++++++
4 files changed, 314 insertions(+), 3 deletions(-)
diff --git a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
index bc9bd47..ccf0a0b 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
@@ -52,6 +52,7 @@ internal class MXRoyaleClasses
import mx.events.ValidationResultEvent; ValidationResultEvent;
import mx.containers.beads.ApplicationLayout; ApplicationLayout;
import mx.containers.beads.BoxLayout; BoxLayout;
+ import mx.containers.beads.DividedBoxLayout; DividedBoxLayout;
import mx.containers.beads.CanvasLayout; CanvasLayout;
import mx.containers.beads.layouts.BasicLayout; BasicLayout;
import mx.controls.beads.AlertView; AlertView;
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/Box.as b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/Box.as
index 923d0dd..e9e945b 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/Box.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/Box.as
@@ -133,18 +133,22 @@ public class Box extends Container
// For Flex compatibility, the BoxLayout is immediately created and added
// rather than being loaded from a style
- _layout = new BoxLayout();
- _layout.direction = _direction;
+ createLayout();
+ _layout.direction = _direction;
addBead(_layout);
}
+ protected function createLayout():void
+ {
+ _layout = new BoxLayout();
+ }
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
- private var _layout:BoxLayout;
+ protected var _layout:BoxLayout;
protected function get layoutObject():BoxLayout
{
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/DividedBox.as b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/DividedBox.as
index 1a71752..35c84d4 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/DividedBox.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/DividedBox.as
@@ -31,8 +31,11 @@ import mx.core.IFlexDisplayObject;
import mx.core.IFlexModuleFactory;
import mx.core.IInvalidating;
*/
+import mx.containers.beads.BoxLayout;
+import mx.containers.beads.DividedBoxLayout;
import mx.core.IUIComponent;
import mx.core.UIComponent;
+
/*
import mx.core.mx_internal;
import mx.events.ChildExistenceChangedEvent;
@@ -219,6 +222,11 @@ public class DividedBox extends Box
// addEventListener(ChildExistenceChangedEvent.CHILD_REMOVE,
// childRemoveHandler);
}
+
+ override protected function createLayout():void
+ {
+ _layout = new DividedBoxLayout();
+ }
//--------------------------------------------------------------------------
//
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/containers/beads/DividedBoxLayout.as b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/beads/DividedBoxLayout.as
new file mode 100644
index 0000000..6f9f93a
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/containers/beads/DividedBoxLayout.as
@@ -0,0 +1,298 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.beads
+{
+
+ import mx.containers.BoxDirection;
+ import mx.containers.DividedBox;
+ import mx.containers.utilityClasses.Flex;
+ import mx.controls.Image;
+ import mx.core.Container;
+ import mx.core.EdgeMetrics;
+ import mx.core.IUIComponent;
+ import mx.core.UIComponent;
+
+ import org.apache.royale.core.IBorderPaddingMarginValuesImpl;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.core.LayoutBase;
+ import org.apache.royale.core.UIBase;
+ import org.apache.royale.core.ValuesManager;
+ import org.apache.royale.core.layout.EdgeData;
+
+ //import mx.core.mx_internal;
+ //import mx.core.ScrollPolicy;
+
+ //use namespace mx_internal;
+
+ [ExcludeClass]
+
+ /**
+ * @private
+ * The BoxLayout class is for internal use only.
+ */
+ public class DividedBoxLayout extends BoxLayout
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function DividedBoxLayout()
+ {
+ super();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ private var _strand:IStrand;
+ private var dividedBox:DividedBox;
+
+ override public function set strand(value:IStrand):void
+ {
+ _strand = value;
+ dividedBox = _strand as DividedBox;
+ super.strand = value;
+
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+
+ override public function layout():Boolean
+ {
+ preLayoutAdjustment();
+ return super.layout();
+ postLayoutAdjustment();
+ }
+
+ /**
+ * @private
+ * Algorithm employed pre-layout to ensure that
+ * we don't leave any dangling space and to ensure
+ * that only explicit min/max values are honored.
+ *
+ * We first compute the sum of %'s across all
+ * children to ensure that we have at least 100%.
+ * If so, we are done. If not, then we attempt
+ * to attach the remaining amount to the last
+ * component, if not, then we distribute the
+ * percentages evenly across all % components.
+ *
+ */
+ private function preLayoutAdjustment():void
+ {
+ // Calculate the total %
+ var vertical:Boolean = dividedBox.direction == BoxDirection.VERTICAL;
+
+ var totalPerc:Number = 0;
+ var percCount:Number = 0;
+
+ var n:int = dividedBox.numChildren;
+ var i:int;
+ var child:IUIComponent;
+ var perc:Number;
+
+ for (i = 0; i < n; i++)
+ {
+ child = dividedBox.getLayoutChildAt(i);
+
+ if (!child.includeInLayout)
+ continue;
+
+ // Clear out measured min/max
+ // so super.layout() doesn't use them.
+ child.measuredMinWidth = 0;
+ child.measuredMinHeight = 0;
+
+ perc = vertical ? child.percentHeight : child.percentWidth;
+
+ if (!isNaN(perc))
+ {
+ totalPerc += perc;
+ percCount++;
+ }
+ }
+
+ // during preLayoutAdjustment, we make some changes to the children's
+ // widths and heights. We keep track of the original values in postLayoutChanges
+ // so we can later go back and reset them so another layout pass is working
+ // with the correct values rather than these modified values.
+ postLayoutChanges = [];
+ var changeObject:Object;
+
+ // No flexible children, so we make the last one 100%.
+ if (totalPerc == 0 && percCount == 0)
+ {
+ // Everyone is fixed and we can give 100% to the last
+ // included in layout one without concern.
+ for (i = n-1; i >= 0; i--)
+ {
+ child = UIComponent(dividedBox.getChildAt(i));
+ if (child.includeInLayout)
+ {
+ // create a changeObject to keep track of the original values
+ // that this child had for width and height
+ changeObject = {child: child};
+ if (vertical)
+ {
+ // we know there's no percentHeight originally
+ if (child.explicitHeight)
+ changeObject.explicitHeight = child.explicitHeight;
+ else
+ changeObject.percentHeight = NaN;
+
+ child.percentHeight = 100;
+ }
+ else
+ {
+ // we know there's no percentWidth originally
+ if (child.explicitWidth)
+ changeObject.explicitWidth = child.explicitWidth;
+ else if (child.percentWidth)
+ changeObject.percentWidth = NaN;
+
+ child.percentWidth = 100;
+ }
+ postLayoutChanges.push(changeObject);
+ break;
+ }
+ }
+ }
+ else if (totalPerc < 100)
+ {
+ // We have some %s but they don't total to 100, so lets
+ // distribute the delta across all of them and in the
+ // meantime normalize all %s to unscaledHeight/Width.
+ // The normalization takes care of the case where any one
+ // of the components hits a min/max limit on their size,
+ // which could result in the others filling less than 100%.
+ var delta:Number = Math.ceil((100 - totalPerc) / percCount);
+ for (i = 0; i < n; i++)
+ {
+ child = dividedBox.getLayoutChildAt(i);
+
+ if (!child.includeInLayout)
+ continue;
+
+ changeObject = {child: child};
+
+ if (vertical)
+ {
+ perc = child.percentHeight;
+ if (!isNaN(perc))
+ {
+ changeObject.percentHeight = child.percentHeight;
+ postLayoutChanges.push(changeObject);
+
+ child.percentHeight = (perc + delta) * target.height;
+ }
+ }
+ else
+ {
+ perc = child.percentWidth;
+ if (!isNaN(perc))
+ {
+ changeObject.percentWidth = child.percentWidth;
+ postLayoutChanges.push(changeObject);
+
+ child.percentWidth = (perc + delta) * target.width;
+ }
+ }
+ }
+ }
+
+ // OK after all this magic we still can't guarantee that the space is
+ // entirely filled. For example, all percent components hit their max
+ // values. In this case, the layout will include empty space at the end,
+ // and once the divider is touched, the non-percent based components
+ // will be converted into percent based ones and fill the remaining
+ // space. It seems to me that this scenario is highly unlikely.
+ // Thus I've choosen the route of stretching the percent based
+ // components and not touching the explicitly sized or default
+ // sized ones.
+ //
+ // Another option would be to stretch the default sized components
+ // either in addition to the percent based ones or instead of.
+ // This seemed a little odd to me as the user never indicated
+ // that these components are to be stretched initially, so in the end
+ // I choose to tweak the components that the user has indicated
+ // as being stretchable.
+ }
+
+ /**
+ * @private
+ * During preLayoutAdjustment, we make some changes to the children's
+ * widths and heights. We keep track of the original values in postLayoutChanges
+ * so we can later go back and reset them so another layout pass is working
+ * with the correct values rather than these modified values.
+ */
+ private var postLayoutChanges:Array;
+
+ /**
+ * @private
+ * Post layout work. In preLayoutAdjustment()
+ * sometimes we set a child's percentWidth/percentHeight.
+ * postLayoutAdjustment() will reset the child's width or height
+ * back to what it was.
+ */
+ private function postLayoutAdjustment():void
+ {
+ // each object has a child property and may have a set of width/height
+ // properties that it would like to be set
+ var len:int = postLayoutChanges.length;
+ for (var i:int = 0; i < len; i++)
+ {
+ var changeObject:Object = postLayoutChanges[i];
+
+ if (changeObject.percentWidth !== undefined)
+ changeObject.child.percentWidth = changeObject.percentWidth;
+
+ if (changeObject.percentHeight !== undefined)
+ changeObject.child.percentHeight = changeObject.percentHeight;
+
+ if (changeObject.explicitWidth !== undefined)
+ changeObject.child.explicitWidth = changeObject.explicitWidth;
+
+ if (changeObject.explicitHeight !== undefined)
+ changeObject.child.explicitHeight = changeObject.explicitHeight;
+ }
+ postLayoutChanges = null;
+ }
+
+ }
+
+}