Restructure things to fit upcoming diff

This commit is contained in:
Emil Sjolander
2016-07-25 15:48:39 +01:00
parent 667106e423
commit 93809b69c8
86 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
using System.Diagnostics;
namespace Facebook.CSSLayout
{
static class Assertions
{
public static T assertNotNull<T>(T v) where T : class
{
Debug.Assert(v != null);
return v;
}
public static void assertCondition(bool condition, string explanation)
{
Debug.Assert(condition, explanation);
}
}
}

View File

@@ -0,0 +1,20 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSAlign
{
Auto,
FlexStart,
Center,
FlexEnd,
Stretch,
}
}

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
sealed class CSSCachedMeasurement
{
public float availableWidth;
public float availableHeight;
public CSSMeasureMode? widthMeasureMode = null;
public CSSMeasureMode? heightMeasureMode = null;
public float computedWidth;
public float computedHeight;
}
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public static class CSSConstants
{
public const float Undefined = float.NaN;
public static bool IsUndefined(float value)
{
return float.IsNaN(value);
}
}
}

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSDirection
{
Inherit,
LTR,
RTL
}
}

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSFlexDirection
{
Column,
ColumnReverse,
Row,
RowReverse
}
}

View File

@@ -0,0 +1,20 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSJustify
{
FlexStart,
Center,
FlexEnd,
SpaceBetween,
SpaceAround
}
}

View File

@@ -0,0 +1,89 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
/**
* Where the output of {@link LayoutEngine#layoutNode(CSSNode, float)} will go in the CSSNode.
*/
class CSSLayout
{
// This value was chosen based on empiracle data. Even the most complicated
// layouts should not require more than 16 entries to fit within the cache.
public const int MAX_CACHED_RESULT_COUNT = 16;
public const int POSITION_LEFT = 0;
public const int POSITION_TOP = 1;
public const int POSITION_RIGHT = 2;
public const int POSITION_BOTTOM = 3;
public const int DIMENSION_WIDTH = 0;
public const int DIMENSION_HEIGHT = 1;
public float[] position = new float[4];
public float[] dimensions = {
CSSConstants.Undefined,
CSSConstants.Undefined
};
public CSSDirection direction = CSSDirection.LTR;
public float flexBasis;
public int generationCount;
public CSSDirection? lastParentDirection;
public int nextCachedMeasurementsIndex;
public CSSCachedMeasurement[] cachedMeasurements = new CSSCachedMeasurement[MAX_CACHED_RESULT_COUNT];
public float[] measuredDimensions = {
CSSConstants.Undefined,
CSSConstants.Undefined
};
public CSSCachedMeasurement cachedLayout = new CSSCachedMeasurement();
public void resetResult()
{
FillArray(position, 0);
FillArray(dimensions, CSSConstants.Undefined);
direction = CSSDirection.LTR;
flexBasis = 0;
generationCount = 0;
lastParentDirection = null;
nextCachedMeasurementsIndex = 0;
measuredDimensions[DIMENSION_WIDTH] = CSSConstants.Undefined;
measuredDimensions[DIMENSION_HEIGHT] = CSSConstants.Undefined;
cachedLayout.widthMeasureMode = null;
cachedLayout.heightMeasureMode = null;
}
public override string ToString()
{
return "layout: {" +
"left: " + position[POSITION_LEFT] + ", " +
"top: " + position[POSITION_TOP] + ", " +
"width: " + dimensions[DIMENSION_WIDTH] + ", " +
"height: " + dimensions[DIMENSION_HEIGHT] + ", " +
"direction: " + direction +
"}";
}
static void FillArray<T>(T[] array, T value)
{
for (var i = 0; i != array.Length; ++i)
array[i] = value;
}
}
}

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
/**
* A context for holding values local to a given instance of layout computation.
*
* This is necessary for making layout thread-safe. A separate instance should
* be used when {@link CSSNode#calculateLayout} is called concurrently on
* different node hierarchies.
*/
sealed class CSSLayoutContext
{
/*package*/
public MeasureOutput measureOutput = new MeasureOutput();
public int currentGenerationCount;
}
}

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSMeasureMode
{
Undefined,
Exactly,
AtMost,
}
}

View File

@@ -0,0 +1,558 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Facebook.CSSLayout
{
/**
* Should measure the given node and put the result in the given MeasureOutput.
*/
public delegate MeasureOutput MeasureFunction(CSSNode node, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode);
/**
* A CSS Node. It has a style object you can manipulate at {@link #style}. After calling
* {@link #calculateLayout()}, {@link #layout} will be filled with the results of the layout.
*/
public class CSSNode
{
const int POSITION_LEFT = CSSLayout.POSITION_LEFT;
const int POSITION_TOP = CSSLayout.POSITION_TOP;
const int POSITION_RIGHT = CSSLayout.POSITION_RIGHT;
const int POSITION_BOTTOM = CSSLayout.POSITION_BOTTOM;
const int DIMENSION_WIDTH = CSSLayout.DIMENSION_WIDTH;
const int DIMENSION_HEIGHT = CSSLayout.DIMENSION_HEIGHT;
enum LayoutState
{
/**
* Some property of this node or its children has changes and the current values in
* {@link #layout} are not valid.
*/
DIRTY,
/**
* This node has a new layout relative to the last time {@link #MarkLayoutSeen()} was called.
*/
HAS_NEW_LAYOUT,
/**
* {@link #layout} is valid for the node's properties and this layout has been marked as
* having been seen.
*/
UP_TO_DATE,
}
internal readonly CSSStyle style = new CSSStyle();
internal readonly CSSLayout layout = new CSSLayout();
internal readonly CachedCSSLayout lastLayout = new CachedCSSLayout();
internal int lineIndex = 0;
internal /*package*/ CSSNode nextChild;
// 4 is kinda arbitrary, but the default of 10 seems really high for an average View.
readonly List<CSSNode> mChildren = new List<CSSNode>(4);
[Nullable] CSSNode mParent;
[Nullable] MeasureFunction mMeasureFunction = null;
LayoutState mLayoutState = LayoutState.DIRTY;
bool mIsTextNode = false;
public int ChildCount
{
get { return mChildren.Count; }
}
public CSSNode this[int i]
{
get { return mChildren[i]; }
}
public IEnumerable<CSSNode> Children
{
get { return mChildren; }
}
public void AddChild(CSSNode child)
{
InsertChild(ChildCount, child);
}
public void InsertChild(int i, CSSNode child)
{
if (child.mParent != null)
{
throw new InvalidOperationException("Child already has a parent, it must be removed first.");
}
mChildren.Insert(i, child);
child.mParent = this;
dirty();
}
public void RemoveChildAt(int i)
{
mChildren[i].mParent = null;
mChildren.RemoveAt(i);
dirty();
}
public CSSNode Parent
{
[return: Nullable]
get
{ return mParent; }
}
/**
* @return the index of the given child, or -1 if the child doesn't exist in this node.
*/
public int IndexOf(CSSNode child)
{
return mChildren.IndexOf(child);
}
public MeasureFunction MeasureFunction
{
get { return mMeasureFunction; }
set
{
if (!valuesEqual(mMeasureFunction, value))
{
mMeasureFunction = value;
dirty();
}
}
}
public bool IsTextNode
{
get { return mIsTextNode; }
set { mIsTextNode = value; }
}
public bool IsMeasureDefined
{
get { return mMeasureFunction != null; }
}
internal MeasureOutput measure(MeasureOutput measureOutput, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode)
{
if (!IsMeasureDefined)
{
throw new Exception("Measure function isn't defined!");
}
return Assertions.assertNotNull(mMeasureFunction)(this, width, widthMode, height, heightMode);
}
/**
* Performs the actual layout and saves the results in {@link #layout}
*/
public void CalculateLayout()
{
LayoutEngine.layoutNode(DummyLayoutContext, this, CSSConstants.Undefined, CSSConstants.Undefined, null);
}
static readonly CSSLayoutContext DummyLayoutContext = new CSSLayoutContext();
/**
* See {@link LayoutState#DIRTY}.
*/
public bool IsDirty
{
get { return mLayoutState == LayoutState.DIRTY; }
}
/**
* See {@link LayoutState#HAS_NEW_LAYOUT}.
*/
public bool HasNewLayout
{
get { return mLayoutState == LayoutState.HAS_NEW_LAYOUT; }
}
internal protected virtual void dirty()
{
if (mLayoutState == LayoutState.DIRTY)
{
return;
}
else if (mLayoutState == LayoutState.HAS_NEW_LAYOUT)
{
throw new InvalidOperationException("Previous layout was ignored! MarkLayoutSeen() never called");
}
mLayoutState = LayoutState.DIRTY;
if (mParent != null)
{
mParent.dirty();
}
}
internal void markHasNewLayout()
{
mLayoutState = LayoutState.HAS_NEW_LAYOUT;
}
/**
* Tells the node that the current values in {@link #layout} have been seen. Subsequent calls
* to {@link #hasNewLayout()} will return false until this node is laid out with new parameters.
* You must call this each time the layout is generated if the node has a new layout.
*/
public void MarkLayoutSeen()
{
if (!HasNewLayout)
{
throw new InvalidOperationException("Expected node to have a new layout to be seen!");
}
mLayoutState = LayoutState.UP_TO_DATE;
}
void toStringWithIndentation(StringBuilder result, int level)
{
// Spaces and tabs are dropped by IntelliJ logcat integration, so rely on __ instead.
StringBuilder indentation = new StringBuilder();
for (int i = 0; i < level; ++i)
{
indentation.Append("__");
}
result.Append(indentation.ToString());
result.Append(layout.ToString());
if (ChildCount == 0)
{
return;
}
result.Append(", children: [\n");
for (var i = 0; i < ChildCount; i++)
{
this[i].toStringWithIndentation(result, level + 1);
result.Append("\n");
}
result.Append(indentation + "]");
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
this.toStringWithIndentation(sb, 0);
return sb.ToString();
}
protected bool valuesEqual(float f1, float f2)
{
return FloatUtil.floatsEqual(f1, f2);
}
protected bool valuesEqual<T>([Nullable] T o1, [Nullable] T o2)
{
if (o1 == null)
{
return o2 == null;
}
return o1.Equals(o2);
}
public CSSDirection Direction
{
get { return style.direction; }
set { updateDiscreteValue(ref style.direction, value); }
}
public CSSFlexDirection FlexDirection
{
get { return style.flexDirection; }
set { updateDiscreteValue(ref style.flexDirection, value); }
}
public CSSJustify JustifyContent
{
get { return style.justifyContent; }
set { updateDiscreteValue(ref style.justifyContent, value); }
}
public CSSAlign AlignContent
{
get { return style.alignContent; }
set { updateDiscreteValue(ref style.alignContent, value); }
}
public CSSAlign AlignItems
{
get { return style.alignItems; }
set { updateDiscreteValue(ref style.alignItems, value); }
}
public CSSAlign AlignSelf
{
get { return style.alignSelf; }
set { updateDiscreteValue(ref style.alignSelf, value); }
}
public CSSPositionType PositionType
{
get { return style.positionType; }
set { updateDiscreteValue(ref style.positionType, value); }
}
public CSSWrap Wrap
{
get { return style.flexWrap; }
set { updateDiscreteValue(ref style.flexWrap, value); }
}
public float Flex
{
get { return style.flex; }
set { updateFloatValue(ref style.flex, value); }
}
public CSSOverflow Overflow
{
get { return style.overflow; }
set { updateDiscreteValue(ref style.overflow, value); }
}
public void SetMargin(CSSSpacingType spacingType, float margin)
{
if (style.margin.set((int)spacingType, margin))
dirty();
}
public float GetMargin(CSSSpacingType spacingType)
{
return style.margin.getRaw((int)spacingType);
}
public void SetPadding(CSSSpacingType spacingType, float padding)
{
if (style.padding.set((int)spacingType, padding))
dirty();
}
public float GetPadding(CSSSpacingType spacingType)
{
return style.padding.getRaw((int)spacingType);
}
public void SetBorder(CSSSpacingType spacingType, float border)
{
if (style.border.set((int)spacingType, border))
dirty();
}
public float GetBorder(CSSSpacingType spacingType)
{
return style.border.getRaw((int)spacingType);
}
public float PositionTop
{
get { return style.position[POSITION_TOP]; }
set { updateFloatValue(ref style.position[POSITION_TOP], value); }
}
public float PositionBottom
{
get { return style.position[POSITION_BOTTOM]; }
set { updateFloatValue(ref style.position[POSITION_BOTTOM], value); }
}
public float PositionLeft
{
get { return style.position[POSITION_LEFT]; }
set { updateFloatValue(ref style.position[POSITION_LEFT], value); }
}
public float PositionRight
{
get { return style.position[POSITION_RIGHT]; }
set { updateFloatValue(ref style.position[POSITION_RIGHT], value); }
}
public float Width
{
get { return style.dimensions[DIMENSION_WIDTH]; }
set { updateFloatValue(ref style.dimensions[DIMENSION_WIDTH], value); }
}
public float Height
{
get { return style.dimensions[DIMENSION_HEIGHT]; }
set { updateFloatValue(ref style.dimensions[DIMENSION_HEIGHT], value); }
}
public float MinWidth
{
get { return style.minWidth; }
set { updateFloatValue(ref style.minWidth, value); }
}
public float MinHeight
{
get { return style.minHeight; }
set { updateFloatValue(ref style.minHeight, value); }
}
public float MaxWidth
{
get { return style.maxWidth; }
set { updateFloatValue(ref style.maxWidth, value); }
}
public float MaxHeight
{
get { return style.maxHeight; }
set { updateFloatValue(ref style.maxHeight, value); }
}
public float LayoutX
{
get { return layout.position[POSITION_LEFT]; }
}
public float LayoutY
{
get { return layout.position[POSITION_TOP]; }
}
public float LayoutWidth
{
get { return layout.dimensions[DIMENSION_WIDTH]; }
}
public float LayoutHeight
{
get { return layout.dimensions[DIMENSION_HEIGHT]; }
}
public CSSDirection LayoutDirection
{
get { return layout.direction; }
}
/**
* Set a default padding (left/top/right/bottom) for this node.
*/
public void SetDefaultPadding(CSSSpacingType spacingType, float padding)
{
if (style.padding.setDefault((int)spacingType, padding))
dirty();
}
void updateDiscreteValue<ValueT>(ref ValueT valueRef, ValueT newValue)
{
if (valuesEqual(valueRef, newValue))
return;
valueRef = newValue;
dirty();
}
void updateFloatValue(ref float valueRef, float newValue)
{
if (valuesEqual(valueRef, newValue))
return;
valueRef = newValue;
dirty();
}
}
public static class CSSNodeExtensions
{
/*
Explicitly mark this node as dirty.
Calling this function is required when the measure function points to the same instance,
but changes its behavior.
For all other property changes, the node is automatically marked dirty.
*/
public static void MarkDirty(this CSSNode node)
{
node.dirty();
}
}
internal static class CSSNodeExtensionsInternal
{
public static CSSNode getParent(this CSSNode node)
{
return node.Parent;
}
public static int getChildCount(this CSSNode node)
{
return node.ChildCount;
}
public static CSSNode getChildAt(this CSSNode node, int i)
{
return node[i];
}
public static void addChildAt(this CSSNode node, CSSNode child, int i)
{
node.InsertChild(i, child);
}
public static void removeChildAt(this CSSNode node, int i)
{
node.RemoveChildAt(i);
}
public static void setMeasureFunction(this CSSNode node, MeasureFunction measureFunction)
{
node.MeasureFunction = measureFunction;
}
public static void setIsTextNode(this CSSNode node, bool isTextNode)
{
node.IsTextNode = isTextNode;
}
public static void calculateLayout(this CSSNode node)
{
node.CalculateLayout();
}
public static bool isDirty(this CSSNode node)
{
return node.IsDirty;
}
public static void setMargin(this CSSNode node, int spacingType, float margin)
{
node.SetMargin((CSSSpacingType)spacingType, margin);
}
public static void setPadding(this CSSNode node, int spacingType, float padding)
{
node.SetPadding((CSSSpacingType)spacingType, padding);
}
public static void setBorder(this CSSNode node, int spacingType, float border)
{
node.SetBorder((CSSSpacingType)spacingType, border);
}
}
}

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSOverflow
{
Visible,
Hidden
}
}

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSPositionType
{
Relative,
Absolute
}
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSSpacingType
{
Left = 0,
Top = 1,
Right = 2,
Bottom = 3,
Vertical = 4,
Horizontal = 5,
Start = 6,
End = 7,
All = 8
}
}

View File

@@ -0,0 +1,50 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
/**
* The CSS style definition for a {@link CSSNode}.
*/
sealed class CSSStyle
{
public CSSDirection direction = CSSDirection.Inherit;
public CSSFlexDirection flexDirection = CSSFlexDirection.Column;
public CSSJustify justifyContent = CSSJustify.FlexStart;
public CSSAlign alignContent = CSSAlign.FlexStart;
public CSSAlign alignItems = CSSAlign.Stretch;
public CSSAlign alignSelf = CSSAlign.Auto;
public CSSPositionType positionType = CSSPositionType.Relative;
public CSSWrap flexWrap = CSSWrap.NoWrap;
public CSSOverflow overflow = CSSOverflow.Visible;
public float flex;
public Spacing margin = new Spacing();
public Spacing padding = new Spacing();
public Spacing border = new Spacing();
public float[] position = {
CSSConstants.Undefined,
CSSConstants.Undefined,
CSSConstants.Undefined,
CSSConstants.Undefined
};
public float[] dimensions = {
CSSConstants.Undefined,
CSSConstants.Undefined
};
public float minWidth = CSSConstants.Undefined;
public float minHeight = CSSConstants.Undefined;
public float maxWidth = CSSConstants.Undefined;
public float maxHeight = CSSConstants.Undefined;
}
}

View File

@@ -0,0 +1,16 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSWrap
{
NoWrap,
Wrap
}
}

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
/**
* CSSLayout with additional information about the conditions under which it was generated.
* {@link #RequestedWidth} and {@link #RequestedHeight} are the width and height the parent set on
* this node before calling layout visited us.
*/
class CachedCSSLayout : CSSLayout
{
public float requestedWidth = CSSConstants.Undefined;
public float requestedHeight = CSSConstants.Undefined;
public float parentMaxWidth = CSSConstants.Undefined;
public float parentMaxHeight = CSSConstants.Undefined;
}
}

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Facebook.CSSLayout</RootNamespace>
<AssemblyName>Facebook.CSSLayout</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>5</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
</ItemGroup>
<ItemGroup>
<Compile Include="Assertions.cs" />
<Compile Include="CachedCSSLayout.cs" />
<Compile Include="CSSAlign.cs" />
<Compile Include="CSSCachedMeasurement.cs" />
<Compile Include="CSSConstants.cs" />
<Compile Include="CSSDirection.cs" />
<Compile Include="CSSFlexDirection.cs" />
<Compile Include="CSSJustify.cs" />
<Compile Include="CSSLayout.cs" />
<Compile Include="CSSLayoutContext.cs" />
<Compile Include="CSSMeasureMode.cs" />
<Compile Include="CSSNode.cs" />
<Compile Include="CSSOverflow.cs" />
<Compile Include="CSSPositionType.cs" />
<Compile Include="CSSStyle.cs" />
<Compile Include="CSSWrap.cs" />
<Compile Include="FloatUtil.cs" />
<Compile Include="LayoutEngine.cs" />
<Compile Include="MeasureOutput.cs" />
<Compile Include="NullableAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Spacing.cs" />
<Compile Include="CSSSpacingType.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<licenseUrl>https://github.com/facebook/css-layout/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/facebook/css-layout</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<releaseNotes></releaseNotes>
<copyright>Copyright 2015 Facebook</copyright>
<tags>flexbox flex-box css layout css-layout facebook</tags>
</metadata>
</package>

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
using System;
namespace Facebook.CSSLayout
{
static class FloatUtil
{
const float Epsilon = .00001f;
public static bool floatsEqual(float f1, float f2)
{
if (float.IsNaN(f1) || float.IsNaN(f2))
{
return float.IsNaN(f1) && float.IsNaN(f2);
}
return Math.Abs(f2 - f1) < Epsilon;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
/**
* POJO to hold the output of the measure function.
*/
public struct MeasureOutput
{
public MeasureOutput(float width, float height)
{
Width = width;
Height = height;
}
public readonly float Width;
public readonly float Height;
internal float width
{
get { return Width; }
}
internal float height
{
get { return Height; }
}
}
}

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
using System;
namespace Facebook.CSSLayout
{
/**
* This is here to preserve the @nullable attribute of the original Java API.
*/
[AttributeUsage(AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.Parameter)]
sealed class NullableAttribute : Attribute
{
}
}

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
using System.Resources;
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Facebook.CSSLayout")]
[assembly: AssemblyDescription("A subset of CSS's flexbox layout algorithm and box model.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Facebook")]
[assembly: AssemblyProduct("Facebook.CSSLayout")]
[assembly: AssemblyCopyright("Copyright © 2015 Facebook")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("Facebook.CSSLayout.Tests")]

View File

@@ -0,0 +1,234 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
/**
* Class representing CSS spacing (padding, margin, and borders). This is mostly necessary to
* properly implement interactions and updates for properties like margin, marginLeft, and
* marginHorizontal.
*/
sealed class Spacing
{
/**
* Spacing type that represents the left direction. E.g. {@code marginLeft}.
*/
internal const int LEFT = (int)CSSSpacingType.Left;
/**
* Spacing type that represents the top direction. E.g. {@code marginTop}.
*/
internal const int TOP = (int)CSSSpacingType.Top;
/**
* Spacing type that represents the right direction. E.g. {@code marginRight}.
*/
internal const int RIGHT = (int)CSSSpacingType.Right;
/**
* Spacing type that represents the bottom direction. E.g. {@code marginBottom}.
*/
internal const int BOTTOM = (int)CSSSpacingType.Bottom;
/**
* Spacing type that represents vertical direction (top and bottom). E.g. {@code marginVertical}.
*/
internal const int VERTICAL = (int)CSSSpacingType.Vertical;
/**
* Spacing type that represents horizontal direction (left and right). E.g.
* {@code marginHorizontal}.
*/
internal const int HORIZONTAL = (int)CSSSpacingType.Horizontal;
/**
* Spacing type that represents start direction e.g. left in left-to-right, right in right-to-left.
*/
internal const int START = (int)CSSSpacingType.Start;
/**
* Spacing type that represents end direction e.g. right in left-to-right, left in right-to-left.
*/
internal const int END = (int)CSSSpacingType.End;
/**
* Spacing type that represents all directions (left, top, right, bottom). E.g. {@code margin}.
*/
internal const int ALL = (int)CSSSpacingType.All;
static readonly int[] sFlagsMap = {
1, /*LEFT*/
2, /*TOP*/
4, /*RIGHT*/
8, /*BOTTOM*/
16, /*VERTICAL*/
32, /*HORIZONTAL*/
64, /*START*/
128, /*END*/
256 /*ALL*/
};
float[] mSpacing = newFullSpacingArray();
[Nullable] float[] mDefaultSpacing = null;
int mValueFlags = 0;
bool mHasAliasesSet;
/**
* Set a spacing value.
*
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM},
* {@link #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL}
* @param value the value for this direction
* @return {@code true} if the spacing has changed, or {@code false} if the same value was already
* set
*/
internal bool set(int spacingType, float value)
{
if (!FloatUtil.floatsEqual(mSpacing[spacingType], value))
{
mSpacing[spacingType] = value;
if (CSSConstants.IsUndefined(value))
{
mValueFlags &= ~sFlagsMap[spacingType];
}
else
{
mValueFlags |= sFlagsMap[spacingType];
}
mHasAliasesSet =
(mValueFlags & sFlagsMap[ALL]) != 0 ||
(mValueFlags & sFlagsMap[VERTICAL]) != 0 ||
(mValueFlags & sFlagsMap[HORIZONTAL]) != 0;
return true;
}
return false;
}
/**
* Set a default spacing value. This is used as a fallback when no spacing has been set for a
* particular direction.
*
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}
* @param value the default value for this direction
* @return
*/
internal bool setDefault(int spacingType, float value)
{
if (mDefaultSpacing == null)
mDefaultSpacing = newSpacingResultArray();
if (!FloatUtil.floatsEqual(mDefaultSpacing[spacingType], value))
{
mDefaultSpacing[spacingType] = value;
return true;
}
return false;
}
/**
* Get the spacing for a direction. This takes into account any default values that have been set.
*
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}
*/
internal float get(int spacingType)
{
float defaultValue =
(mDefaultSpacing != null)
? mDefaultSpacing[spacingType]
: (spacingType == START || spacingType == END ? CSSConstants.Undefined : 0);
if (mValueFlags == 0)
{
return defaultValue;
}
if ((mValueFlags & sFlagsMap[spacingType]) != 0)
{
return mSpacing[spacingType];
}
if (mHasAliasesSet)
{
int secondType = spacingType == TOP || spacingType == BOTTOM ? VERTICAL : HORIZONTAL;
if ((mValueFlags & sFlagsMap[secondType]) != 0)
{
return mSpacing[secondType];
}
else if ((mValueFlags & sFlagsMap[ALL]) != 0)
{
return mSpacing[ALL];
}
}
return defaultValue;
}
/**
* Get the raw value (that was set using {@link #set(int, float)}), without taking into account
* any default values.
*
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM},
* {@link #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL}
*/
internal float getRaw(int spacingType)
{
return mSpacing[spacingType];
}
/**
* Try to get start value and fallback to given type if not defined. This is used privately
* by the layout engine as a more efficient way to fetch direction-aware values by
* avoid extra method invocations.
*/
internal float getWithFallback(int spacingType, int fallbackType)
{
return
(mValueFlags & sFlagsMap[spacingType]) != 0
? mSpacing[spacingType]
: get(fallbackType);
}
static float[] newFullSpacingArray()
{
return new[]
{
CSSConstants.Undefined,
CSSConstants.Undefined,
CSSConstants.Undefined,
CSSConstants.Undefined,
CSSConstants.Undefined,
CSSConstants.Undefined,
CSSConstants.Undefined,
CSSConstants.Undefined,
CSSConstants.Undefined
};
}
static float[] newSpacingResultArray()
{
return newSpacingResultArray(0);
}
static float[] newSpacingResultArray(float defaultValue)
{
return new[]
{
defaultValue,
defaultValue,
defaultValue,
defaultValue,
defaultValue,
defaultValue,
CSSConstants.Undefined,
CSSConstants.Undefined,
defaultValue
};
}
}
}