Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 42 additions & 57 deletions Cirrious.FluentLayout/Cirrious.FluentLayouts.Touch.csproj
Original file line number Diff line number Diff line change
@@ -1,59 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{75D2DA9D-DFD4-49A1-98FB-FE0F0677EF0F}</ProjectGuid>
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<RootNamespace>Cirrious.FluentLayouts.Touch</RootNamespace>
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
<AssemblyName>Cirrious.FluentLayouts.Touch</AssemblyName>
<TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<MtouchLink>None</MtouchLink>
<MtouchDebug>true</MtouchDebug>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhoneSimulator\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<MtouchLink>None</MtouchLink>
</PropertyGroup>
<ItemGroup>
<Compile Include="AdvancedFluentLayoutExtensions.cs" />
<Compile Include="FluentLayout.cs" />
<Compile Include="FluentLayoutExtensions.cs" />
<Compile Include="Margins.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RowSet-WorkInProgress\RowSet.cs" />
<Compile Include="UIViewAndLayoutAttribute.cs" />
<Compile Include="NfloatExtensions.cs" />
<Compile Include="Extensions\ArrayExtensions.cs" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="Xamarin.iOS" />
</ItemGroup>
<ItemGroup>
<Folder Include="Extensions\" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
<Project Sdk="MSBuild.Sdk.Extras/2.0.41">
<PropertyGroup>
<TargetFrameworks>xamarin.ios10;xamarin.mac20</TargetFrameworks>
<PackageProjectUrl>https://github.com/FluentLayout/Cirrious.FluentLayout</PackageProjectUrl>
<Product>$(AssemblyName) ($(TargetFramework))</Product>
<PackageTags>xamarin ios mac constraints</PackageTags>
<PackageLicenseExpression>MS-PL</PackageLicenseExpression>
<LangVersion>7.3</LangVersion>
<NoWarn>$(NoWarn);1591;1701;1591;1702;1705;VSX1000;NU1603</NoWarn>
<RepositoryUrl>https://github.com/FluentLayout/Cirrious.FluentLayout</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<IncludeSymbols>True</IncludeSymbols>
<IncludeSource>True</IncludeSource>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<Compile Remove="Platforms\**\*.*" />
<None Include="Platforms\**\*.*" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('xamarin.ios')) ">
<Compile Include="Platforms\Shared\**\*.cs" />
<Compile Include="Platforms\iOS\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('xamarin.mac')) ">
<Compile Include="Platforms\Shared\**\*.cs" />
<Compile Include="Platforms\Mac\**\*.cs" />
</ItemGroup>
</Project>
227 changes: 227 additions & 0 deletions Cirrious.FluentLayout/Platforms/Mac/AdvancedFluentLayoutExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
// AdvancedFluentLayoutExtensions.cs
// (c) Copyright Cirrious Ltd. http://www.cirrious.com
// MvvmCross is licensed using Microsoft Public License (Ms-PL)
// Contributions and inspirations noted in readme.md and license.txt
//
// Project Lead - Stuart Lodge, @slodge, [email protected]

using System;
using System.Collections.Generic;
using System.Linq;
using AppKit;
using Cirrious.FluentLayouts.Touch.Extensions;

namespace Cirrious.FluentLayouts.Touch
{
public static class AdvancedFluentLayoutExtensions
{
const float DefaultMargin = 0;
const float DefaultScale = 1;

public static FluentLayout AtTopOf(this NSView view, NSView parentView, nfloat? margin = null) =>
view.Top().EqualTo().TopOf(parentView).Plus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout AtLeftOf(this NSView view, NSView parentView, nfloat? margin = null) =>
view.Left().EqualTo().LeftOf(parentView).Plus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout AtRightOf(this NSView view, NSView parentView, nfloat? margin = null) =>
view.Right().EqualTo().RightOf(parentView).Minus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout AtBottomOf(this NSView view, NSView parentView, nfloat? margin = null) =>
view.Bottom().EqualTo().BottomOf(parentView).Minus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout AtLeadingOf(this NSView view, NSView parentView, nfloat? margin = null) =>
view.Leading().EqualTo().LeadingOf(parentView).Plus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout AtTrailingOf(this NSView view, NSView parentView, nfloat? margin = null) =>
view.Trailing().EqualTo().TrailingOf(parentView).Minus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout Below(this NSView view, NSView previous, nfloat? margin = null) =>
view.Top().EqualTo().BottomOf(previous).Plus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout Above(this NSView view, NSView previous, nfloat? margin = null) =>
view.Bottom().EqualTo().TopOf(previous).Minus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout WithSameLeft(this NSView view, NSView previous) => view.Left().EqualTo().LeftOf(previous);

public static FluentLayout WithSameTop(this NSView view, NSView previous) => view.Top().EqualTo().TopOf(previous);

public static FluentLayout WithSameCenterX(this NSView view, NSView previous) => view.CenterX().EqualTo().CenterXOf(previous);

public static FluentLayout WithSameCenterY(this NSView view, NSView previous) => view.CenterY().EqualTo().CenterYOf(previous);

public static FluentLayout WithSameRight(this NSView view, NSView previous) => view.Right().EqualTo().RightOf(previous);

public static FluentLayout WithSameWidth(this NSView view, NSView previous) => view.Width().EqualTo().WidthOf(previous);

public static FluentLayout WithSameBottom(this NSView view, NSView previous) => view.Bottom().EqualTo().BottomOf(previous);

public static FluentLayout WithSameLeading(this NSView view, NSView previous) => view.Leading().EqualTo().LeadingOf(previous);

public static FluentLayout WithSameTrailing(this NSView view, NSView previous) => view.Trailing().EqualTo().TrailingOf(previous);

public static FluentLayout WithRelativeWidth(this NSView view, NSView previous, nfloat? scale = null) =>
view.Width().EqualTo().WidthOf(previous).WithMultiplier(scale.GetValueOrDefault(DefaultScale));

public static FluentLayout WithSameHeight(this NSView view, NSView previous) => view.Height().EqualTo().HeightOf(previous);

public static FluentLayout WithRelativeHeight(this NSView view, NSView previous, nfloat? scale = null) =>
view.Height().EqualTo().HeightOf(previous).WithMultiplier(scale.GetValueOrDefault(DefaultScale));

public static FluentLayout ToRightOf(this NSView view, NSView previous, nfloat? margin = null) =>
view.Left().EqualTo().RightOf(previous).Plus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout ToLeftOf(this NSView view, NSView previous, nfloat? margin = null) =>
view.Right().EqualTo().LeftOf(previous).Minus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout ToTrailingOf(this NSView view, NSView previous, nfloat? margin = null) =>
view.Leading().EqualTo().TrailingOf(previous).Plus(margin.GetValueOrDefault(DefaultMargin));

public static FluentLayout ToLeadingOf(this NSView view, NSView previous, nfloat? margin = null) =>
view.Trailing().EqualTo().LeadingOf(previous).Minus(margin.GetValueOrDefault(DefaultMargin));

//public static FluentLayout ToLeftMargin(this NSView view, NSView previous) =>
// view.Leading().EqualTo().LeadingMarginOf(previous);

//public static FluentLayout ToRightMargin(this NSView view, NSView previous) =>
// view.Trailing().EqualTo().TrailingMarginOf(previous);

//public static FluentLayout ToTopMargin(this NSView view, NSView previous) =>
// view.Top().EqualTo().TopMarginOf(previous);

//public static FluentLayout ToBottomMargin(this NSView view, NSView previous) =>
// view.Bottom().EqualTo().BottomMarginOf(previous);

public static FluentLayout ToLeftOfCenterOf(this NSView view, NSView previous, nfloat? margin = null) =>
view.Right().EqualTo().CenterXOf(previous).Minus(margin.GetValueOrDefault(0));

public static FluentLayout ToRightOfCenterOf(this NSView view, NSView previous, nfloat? margin = null) =>
view.Left().EqualTo().CenterXOf(previous).Plus(margin.GetValueOrDefault(0));

public static FluentLayout AboveCenterOf(this NSView view, NSView previous, nfloat? margin = null) =>
view.Bottom().EqualTo().CenterYOf(previous).Minus(margin.GetValueOrDefault(0));

public static FluentLayout BelowCenterOf(this NSView view, NSView previous, nfloat? margin = null) =>
view.Top().EqualTo().CenterYOf(previous).Plus(margin.GetValueOrDefault(0));

public static IEnumerable<FluentLayout> FullWidthOf(this NSView view, NSView parent, nfloat? margin = null)
{
var marginValue = margin.GetValueOrDefault(DefaultMargin);

return new List<FluentLayout>
{
view.AtLeftOf(parent, marginValue).WithIdentifier("Left"),
view.AtRightOf(parent, marginValue).WithIdentifier("Right")
};
}

public static IEnumerable<FluentLayout> FullHeightOf(this NSView view, NSView parent, nfloat? margin = null)
{
var marginValue = margin.GetValueOrDefault(DefaultMargin);

return new List<FluentLayout>
{
view.AtTopOf(parent, marginValue).WithIdentifier("Top"),
view.AtBottomOf(parent, marginValue).WithIdentifier("Bottom")
};
}

public static IEnumerable<FluentLayout> FullSizeOf(this NSView view, NSView parent, nfloat? margin = null) =>
FullSizeOf(view, parent, new Margins((float)margin.GetValueOrDefault(DefaultMargin)));

public static IEnumerable<FluentLayout> FullSizeOf(this NSView view, NSView parent, Margins margins)
{
margins = margins ?? new Margins();

return new List<FluentLayout>
{
view.AtTopOf(parent, margins.Top).WithIdentifier("Top"),
view.AtBottomOf(parent, margins.Bottom).WithIdentifier("Bottom"),
view.AtLeftOf(parent, margins.Left).WithIdentifier("Left"),
view.AtRightOf(parent, margins.Right).WithIdentifier("Right")
};
}

public static FluentLayout GetLayoutById(this IEnumerable<FluentLayout> layouts, string identifier) =>
layouts.FirstOrDefault(x => x.Identifier.Equals(identifier));

public static IEnumerable<FluentLayout> VerticalStackPanelConstraints(this NSView parentView, Margins margins, params NSView[] views) =>
AdvancedVerticalStackPanelConstraints(parentView, margins, views: views);

/// <summary>
/// Vertical stack panel constraints with support for children independent left, right and top margins
/// and a multiplier factor for all margins applied. The multiplier can be useful when dealing with iPad screens.
/// Example:
///
/// scrollView.AddConstraints(scrollView.AdvancedVerticalStackPanelConstraints(null,
/// childrenLeftMargins: new float[] { 15, 0, 15, 0, 0, 15 },
/// childrenTopMargins: new float[] { 15, 5, 15, 5, 8, 15, 22, 8, 8, 28, 28 },
/// marginMultiplier: 2f,
/// views: scrollView.Subviews)
/// );
/// </summary>
public static IEnumerable<FluentLayout> AdvancedVerticalStackPanelConstraints(this NSView parentView,
Margins margins,
float[] childrenLeftMargins = null,
float[] childrenTopMargins = null,
float[] childrenRightMargins = null,
float marginMultiplier = 1,
params NSView[] views)
{
string previousIdentifierPrefix = null;
margins = margins ?? new Margins();
var layouts = new List<FluentLayout>();

var count = views.Length;
for (var i = 0; i < count; i++)
{
var view = views[i];
var viewIdentifierPrefix = $"{parentView.AccessibilityIdentifier ?? "VerticalStackPanel"}-{view.AccessibilityIdentifier ?? i.ToString()}-";

float childLeftMargin;
childrenLeftMargins.TryGetElement(i, out childLeftMargin);
var marginLeft = Math.Max(margins.Left, childLeftMargin) * marginMultiplier;
layouts.Add(view.Left()
.EqualTo()
.LeftOf(parentView)
.Plus(marginLeft)
.WithIdentifier(viewIdentifierPrefix + "Left"));

float childRightMargin;
childrenRightMargins.TryGetElement(i, out childRightMargin);
var marginRight = Math.Max(margins.Right, childRightMargin) * marginMultiplier;
layouts.Add(view.Width()
.EqualTo()
.WidthOf(parentView)
.Minus(marginRight + marginLeft)
.WithIdentifier(viewIdentifierPrefix + "Width"));

float childTopMargin;
childrenTopMargins.TryGetElement(i, out childTopMargin);

layouts.Add(i == 0
? view.Top()
.EqualTo()
.TopOf(parentView)
.Plus(Math.Max(margins.Top, childTopMargin)*marginMultiplier)
.WithIdentifier(viewIdentifierPrefix + "Top")
: view.Top()
.EqualTo()
.BottomOf(views[i - 1])
.Plus(Math.Max(margins.VSpacing, childTopMargin)*marginMultiplier)
.WithIdentifier(viewIdentifierPrefix + "Top"));

previousIdentifierPrefix = viewIdentifierPrefix;
}

if (parentView is NSScrollView)
layouts.Add(views[views.Length - 1].Bottom()
.EqualTo()
.BottomOf(parentView)
.Minus(margins.Bottom * marginMultiplier)
.WithIdentifier(previousIdentifierPrefix + "Bottom"));

return layouts;
}
}
}
13 changes: 13 additions & 0 deletions Cirrious.FluentLayout/Platforms/Mac/Extensions/NSViewExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using AppKit;

namespace Cirrious.FluentLayouts.Touch.Extensions
{
public static class NSViewExtensions
{
public static void AddSubviews(this NSView view, params NSView[] subviews)
{
foreach (var subview in subviews)
view.AddSubview(subview);
}
}
}
Loading