83 changed files with 1480 additions and 650 deletions
@ -1,15 +0,0 @@ |
|||||
using Avalonia.iOS; |
|
||||
using Foundation; |
|
||||
using UIKit; |
|
||||
|
|
||||
namespace ControlCatalog.iOS.Legacy |
|
||||
{ |
|
||||
// The UIApplicationDelegate for the application. This class is responsible for launching the
|
|
||||
// User Interface of the application, as well as listening (and optionally responding) to
|
|
||||
// application events from iOS.
|
|
||||
[Register("AppDelegate")] |
|
||||
public partial class AppDelegate : AvaloniaAppDelegate<App> |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
@ -1,117 +0,0 @@ |
|||||
{ |
|
||||
"images": [ |
|
||||
{ |
|
||||
"scale": "2x", |
|
||||
"size": "20x20", |
|
||||
"idiom": "iphone", |
|
||||
"filename": "Icon40.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "3x", |
|
||||
"size": "20x20", |
|
||||
"idiom": "iphone", |
|
||||
"filename": "Icon60.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "2x", |
|
||||
"size": "29x29", |
|
||||
"idiom": "iphone", |
|
||||
"filename": "Icon58.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "3x", |
|
||||
"size": "29x29", |
|
||||
"idiom": "iphone", |
|
||||
"filename": "Icon87.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "2x", |
|
||||
"size": "40x40", |
|
||||
"idiom": "iphone", |
|
||||
"filename": "Icon80.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "3x", |
|
||||
"size": "40x40", |
|
||||
"idiom": "iphone", |
|
||||
"filename": "Icon120.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "2x", |
|
||||
"size": "60x60", |
|
||||
"idiom": "iphone", |
|
||||
"filename": "Icon120.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "3x", |
|
||||
"size": "60x60", |
|
||||
"idiom": "iphone", |
|
||||
"filename": "Icon180.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "1x", |
|
||||
"size": "20x20", |
|
||||
"idiom": "ipad", |
|
||||
"filename": "Icon20.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "2x", |
|
||||
"size": "20x20", |
|
||||
"idiom": "ipad", |
|
||||
"filename": "Icon40.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "1x", |
|
||||
"size": "29x29", |
|
||||
"idiom": "ipad", |
|
||||
"filename": "Icon29.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "2x", |
|
||||
"size": "29x29", |
|
||||
"idiom": "ipad", |
|
||||
"filename": "Icon58.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "1x", |
|
||||
"size": "40x40", |
|
||||
"idiom": "ipad", |
|
||||
"filename": "Icon40.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "2x", |
|
||||
"size": "40x40", |
|
||||
"idiom": "ipad", |
|
||||
"filename": "Icon80.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "1x", |
|
||||
"size": "76x76", |
|
||||
"idiom": "ipad", |
|
||||
"filename": "Icon76.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "2x", |
|
||||
"size": "76x76", |
|
||||
"idiom": "ipad", |
|
||||
"filename": "Icon152.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "2x", |
|
||||
"size": "83.5x83.5", |
|
||||
"idiom": "ipad", |
|
||||
"filename": "Icon167.png" |
|
||||
}, |
|
||||
{ |
|
||||
"scale": "1x", |
|
||||
"size": "1024x1024", |
|
||||
"idiom": "ios-marketing", |
|
||||
"filename": "Icon1024.png" |
|
||||
} |
|
||||
], |
|
||||
"properties": {}, |
|
||||
"info": { |
|
||||
"version": 1, |
|
||||
"author": "xcode" |
|
||||
} |
|
||||
} |
|
||||
@ -1,99 +0,0 @@ |
|||||
<Project Sdk="Xamarin.Legacy.Sdk"> |
|
||||
<PropertyGroup> |
|
||||
<TargetFramework>xamarin.ios10</TargetFramework> |
|
||||
<SupportedOSPlatformVersion>15.0</SupportedOSPlatformVersion> |
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> |
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|
||||
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform> |
|
||||
<ProjectGuid>{3AF75F00-B497-4517-9491-922173DE216E}</ProjectGuid> |
|
||||
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> |
|
||||
<OutputType>Exe</OutputType> |
|
||||
<RootNamespace>ControlCatalog.iOS.Legacy</RootNamespace> |
|
||||
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix> |
|
||||
<AssemblyName>ControlCatalog.iOS.Legacy</AssemblyName> |
|
||||
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler> |
|
||||
<ProvisioningType>manual</ProvisioningType> |
|
||||
<MtouchInterpreter>-all</MtouchInterpreter> |
|
||||
</PropertyGroup> |
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' "> |
|
||||
<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> |
|
||||
<MtouchArch>x86_64</MtouchArch> |
|
||||
<MtouchLink>None</MtouchLink> |
|
||||
<MtouchDebug>true</MtouchDebug> |
|
||||
</PropertyGroup> |
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' "> |
|
||||
<DebugType>none</DebugType> |
|
||||
<Optimize>true</Optimize> |
|
||||
<OutputPath>bin\iPhoneSimulator\Release</OutputPath> |
|
||||
<ErrorReport>prompt</ErrorReport> |
|
||||
<WarningLevel>4</WarningLevel> |
|
||||
<MtouchLink>None</MtouchLink> |
|
||||
<MtouchArch>x86_64</MtouchArch> |
|
||||
<ConsolePause>false</ConsolePause> |
|
||||
</PropertyGroup> |
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' "> |
|
||||
<DebugSymbols>true</DebugSymbols> |
|
||||
<DebugType>full</DebugType> |
|
||||
<Optimize>false</Optimize> |
|
||||
<OutputPath>bin\iPhone\Debug</OutputPath> |
|
||||
<DefineConstants>DEBUG</DefineConstants> |
|
||||
<ErrorReport>prompt</ErrorReport> |
|
||||
<WarningLevel>4</WarningLevel> |
|
||||
<ConsolePause>false</ConsolePause> |
|
||||
<MtouchArch>ARM64</MtouchArch> |
|
||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> |
|
||||
<MtouchDebug>true</MtouchDebug> |
|
||||
</PropertyGroup> |
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' "> |
|
||||
<DebugType>none</DebugType> |
|
||||
<Optimize>true</Optimize> |
|
||||
<OutputPath>bin\iPhone\Release</OutputPath> |
|
||||
<ErrorReport>prompt</ErrorReport> |
|
||||
<WarningLevel>4</WarningLevel> |
|
||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> |
|
||||
<MtouchArch>ARM64</MtouchArch> |
|
||||
<ConsolePause>false</ConsolePause> |
|
||||
</PropertyGroup> |
|
||||
<ItemGroup> |
|
||||
<None Include="Info.plist" /> |
|
||||
<Content Include="Entitlements.plist" /> |
|
||||
</ItemGroup> |
|
||||
<ItemGroup> |
|
||||
<Reference Include="System" /> |
|
||||
<Reference Include="System.Xml" /> |
|
||||
<Reference Include="System.Core" /> |
|
||||
<Reference Include="Xamarin.iOS" /> |
|
||||
</ItemGroup> |
|
||||
<ItemGroup> |
|
||||
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Contents.json"> |
|
||||
<Visible>false</Visible> |
|
||||
</ImageAsset> |
|
||||
</ItemGroup> |
|
||||
<ItemGroup> |
|
||||
<Folder Include="Resources\" /> |
|
||||
</ItemGroup> |
|
||||
<ItemGroup> |
|
||||
<ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj"> |
|
||||
<Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project> |
|
||||
<Name>Avalonia.Controls</Name> |
|
||||
</ProjectReference> |
|
||||
<ProjectReference Include="..\..\src\iOS\Avalonia.iOS\Avalonia.iOS.csproj"> |
|
||||
<Project>{4488ad85-1495-4809-9aa4-ddfe0a48527e}</Project> |
|
||||
<Name>Avalonia.iOS</Name> |
|
||||
</ProjectReference> |
|
||||
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj"> |
|
||||
<Project>{d0a739b9-3c68-4ba6-a328-41606954b6bd}</Project> |
|
||||
<Name>ControlCatalog</Name> |
|
||||
</ProjectReference> |
|
||||
</ItemGroup> |
|
||||
<!-- <Import Project="..\..\build\LegacyProject.targets" />--> |
|
||||
<!-- <Import Project="..\..\build\SkiaSharp.props" />--> |
|
||||
<!-- <Import Project="..\..\build\HarfBuzzSharp.props" />--> |
|
||||
</Project> |
|
||||
@ -1,6 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|
||||
<plist version="1.0"> |
|
||||
<dict> |
|
||||
</dict> |
|
||||
</plist> |
|
||||
@ -1,47 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|
||||
<plist version="1.0"> |
|
||||
<dict> |
|
||||
<key>CFBundleDisplayName</key> |
|
||||
<string>ControlCatalog</string> |
|
||||
<key>CFBundleIdentifier</key> |
|
||||
<string>com.companyname.ControlCatalog.iOS</string> |
|
||||
<key>CFBundleShortVersionString</key> |
|
||||
<string>1.0</string> |
|
||||
<key>CFBundleVersion</key> |
|
||||
<string>1.0</string> |
|
||||
<key>LSRequiresIPhoneOS</key> |
|
||||
<true/> |
|
||||
<key>MinimumOSVersion</key> |
|
||||
<string>15.0</string> |
|
||||
<key>UIDeviceFamily</key> |
|
||||
<array> |
|
||||
<integer>1</integer><integer>2</integer> |
|
||||
</array> |
|
||||
<key>UILaunchStoryboardName</key> |
|
||||
<string>LaunchScreen</string> |
|
||||
<key>UIRequiredDeviceCapabilities</key> |
|
||||
<array> |
|
||||
<string>armv7</string> |
|
||||
</array> |
|
||||
<key>UISupportedInterfaceOrientations</key> |
|
||||
<array> |
|
||||
<string>UIInterfaceOrientationPortrait</string> |
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string> |
|
||||
<string>UIInterfaceOrientationLandscapeRight</string> |
|
||||
</array> |
|
||||
<key>UISupportedInterfaceOrientations~ipad</key> |
|
||||
<array> |
|
||||
<string>UIInterfaceOrientationPortrait</string> |
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string> |
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string> |
|
||||
<string>UIInterfaceOrientationLandscapeRight</string> |
|
||||
</array> |
|
||||
<key>XSAppIconAssets</key> |
|
||||
<string>Assets.xcassets/AppIcon.appiconset</string> |
|
||||
<key>UIStatusBarHidden</key> |
|
||||
<true/> |
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key> |
|
||||
<false/> |
|
||||
</dict> |
|
||||
</plist> |
|
||||
@ -1,15 +0,0 @@ |
|||||
using UIKit; |
|
||||
|
|
||||
namespace ControlCatalog.iOS.Legacy |
|
||||
{ |
|
||||
public class Application |
|
||||
{ |
|
||||
// This is the main entry point of the application.
|
|
||||
static void Main(string[] args) |
|
||||
{ |
|
||||
// if you want to use a different Application Delegate class from "AppDelegate"
|
|
||||
// you can specify it here.
|
|
||||
UIApplication.Main(args, null, "AppDelegate"); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,43 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6214" systemVersion="14A314h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES"> |
|
||||
<dependencies> |
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207" /> |
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1" /> |
|
||||
</dependencies> |
|
||||
<objects> |
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" /> |
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder" /> |
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB"> |
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480" /> |
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" /> |
|
||||
<subviews> |
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2022 " textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" |
|
||||
minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye"> |
|
||||
<rect key="frame" x="20" y="439" width="441" height="21" /> |
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17" /> |
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor" /> |
|
||||
<nil key="highlightedColor" /> |
|
||||
</label> |
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="ControlCatalog.iOS.Legacy" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" |
|
||||
minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX"> |
|
||||
<rect key="frame" x="20" y="140" width="441" height="43" /> |
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36" /> |
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor" /> |
|
||||
<nil key="highlightedColor" /> |
|
||||
</label> |
|
||||
</subviews> |
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite" /> |
|
||||
<constraints> |
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC" /> |
|
||||
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk" /> |
|
||||
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l" /> |
|
||||
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0" /> |
|
||||
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9" /> |
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g" /> |
|
||||
</constraints> |
|
||||
<nil key="simulatedStatusBarMetrics" /> |
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics" /> |
|
||||
<point key="canvasLocation" x="548" y="455" /> |
|
||||
</view> |
|
||||
</objects> |
|
||||
</document> |
|
||||
@ -0,0 +1,71 @@ |
|||||
|
<UserControl xmlns="https://github.com/avaloniaui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
||||
|
x:Class="RenderDemo.Pages.BrushesPage"> |
||||
|
<Canvas Background="White" Width="480" Height="360"> |
||||
|
<Rectangle Canvas.Left="20" Canvas.Top="20" Width="440" Height="50"> |
||||
|
<Rectangle.Fill> |
||||
|
<LinearGradientBrush StartPoint="0,0" EndPoint="410,0"> |
||||
|
<LinearGradientBrush.Transform> |
||||
|
<TransformGroup> |
||||
|
<ScaleTransform ScaleX="0.5" /> |
||||
|
<SkewTransform /> |
||||
|
<RotateTransform /> |
||||
|
<TranslateTransform X="5" Y="15" /> |
||||
|
</TransformGroup> |
||||
|
</LinearGradientBrush.Transform> |
||||
|
<LinearGradientBrush.GradientStops> |
||||
|
<GradientStop Color="Blue" Offset="0" /> |
||||
|
<GradientStop Color="Green" Offset="0.5" /> |
||||
|
<GradientStop Color="Lime" Offset="1" /> |
||||
|
</LinearGradientBrush.GradientStops> |
||||
|
</LinearGradientBrush> |
||||
|
</Rectangle.Fill> |
||||
|
</Rectangle> |
||||
|
<TextBlock Canvas.Left="20" Canvas.Top="70" FontSize="30" Text="scale(0.5) on gradient" /> |
||||
|
<Rectangle Canvas.Left="20" Canvas.Top="110" Width="440" Height="50"> |
||||
|
<Rectangle.Fill> |
||||
|
<RadialGradientBrush Center="0.0,0.0" GradientOrigin="0.0,0.0" Radius="0.13636364"> |
||||
|
<RadialGradientBrush.Transform> |
||||
|
<TransformGroup> |
||||
|
<ScaleTransform /> |
||||
|
<SkewTransform AngleX="45" /> |
||||
|
<RotateTransform /> |
||||
|
<TranslateTransform X="240" Y="45" /> |
||||
|
</TransformGroup> |
||||
|
</RadialGradientBrush.Transform> |
||||
|
<RadialGradientBrush.GradientStops> |
||||
|
<GradientStop Color="Black" Offset="0" /> |
||||
|
<GradientStop Color="#FFFFA500" Offset="1" /> |
||||
|
</RadialGradientBrush.GradientStops> |
||||
|
</RadialGradientBrush> |
||||
|
</Rectangle.Fill> |
||||
|
</Rectangle> |
||||
|
<TextBlock Canvas.Left="20" Canvas.Top="160" FontSize="30" Text="skewX(45) on gradient" /> |
||||
|
<Rectangle Canvas.Left="20" Canvas.Top="210" Width="440" Height="50"> |
||||
|
<Rectangle.Fill> |
||||
|
<VisualBrush TileMode="Tile" SourceRect="0,0,20,20" DestinationRect="0,0,20,20" Stretch="None"> |
||||
|
<VisualBrush.Transform> |
||||
|
<TransformGroup> |
||||
|
<ScaleTransform ScaleX="2" ScaleY="2" /> |
||||
|
<SkewTransform AngleX="45" /> |
||||
|
<RotateTransform /> |
||||
|
<TranslateTransform X="5" Y="5" /> |
||||
|
</TransformGroup> |
||||
|
</VisualBrush.Transform> |
||||
|
<VisualBrush.Visual> |
||||
|
<Canvas Width="20" Height="20"> |
||||
|
<Rectangle Canvas.Left="0" Canvas.Top="0" Width="10" Height="10" Fill="Maroon" /> |
||||
|
<Rectangle Canvas.Left="10" Canvas.Top="0" Width="10" Height="10" Fill="Green" /> |
||||
|
<Rectangle Canvas.Left="0" Canvas.Top="10" Width="10" Height="10" Fill="Blue" /> |
||||
|
<Rectangle Canvas.Left="10" Canvas.Top="10" Width="10" Height="10" Fill="Yellow" /> |
||||
|
</Canvas> |
||||
|
</VisualBrush.Visual> |
||||
|
</VisualBrush> |
||||
|
</Rectangle.Fill> |
||||
|
</Rectangle> |
||||
|
<TextBlock Canvas.Left="20" Canvas.Top="260" FontSize="30" Text="scale(2), skewX(45) on pattern" /> |
||||
|
</Canvas> |
||||
|
</UserControl> |
||||
@ -0,0 +1,18 @@ |
|||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Markup.Xaml; |
||||
|
|
||||
|
namespace RenderDemo.Pages; |
||||
|
|
||||
|
public class BrushesPage : UserControl |
||||
|
{ |
||||
|
public BrushesPage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
} |
||||
|
|
||||
|
private void InitializeComponent() |
||||
|
{ |
||||
|
AvaloniaXamlLoader.Load(this); |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -1,12 +1,62 @@ |
|||||
namespace Avalonia.Input.TextInput |
namespace Avalonia.Input.TextInput |
||||
{ |
{ |
||||
public enum TextInputContentType |
public enum TextInputContentType |
||||
{ |
{ |
||||
|
/// <summary>
|
||||
|
/// Default keyboard for the users configured input method.
|
||||
|
/// </summary>
|
||||
Normal = 0, |
Normal = 0, |
||||
Email = 1, |
|
||||
Phone = 2, |
/// <summary>
|
||||
Number = 3, |
/// Display a keyboard that only has alphabetic characters.
|
||||
Url = 4, |
/// </summary>
|
||||
Password = 5 |
Alpha, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display a numeric keypad only capable of numbers. i.e. Phone number
|
||||
|
/// </summary>
|
||||
|
Digits, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display a numeric keypad for inputting a PIN.
|
||||
|
/// </summary>
|
||||
|
Pin, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display a numeric keypad capable of inputting numbers including decimal seperator and sign.
|
||||
|
/// </summary>
|
||||
|
Number, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display a keyboard for entering an email address.
|
||||
|
/// </summary>
|
||||
|
Email, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display a keyboard for entering a URL.
|
||||
|
/// </summary>
|
||||
|
Url, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display a keyboard for entering a persons name.
|
||||
|
/// </summary>
|
||||
|
Name, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display a keyboard for entering sensitive data.
|
||||
|
/// </summary>
|
||||
|
Password, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display a keyboard suitable for #tag and @mentions.
|
||||
|
/// Not available on all platforms, will fallback to a suitable keyboard
|
||||
|
/// when not available.
|
||||
|
/// </summary>
|
||||
|
Social, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display a keyboard for entering a search keyword.
|
||||
|
/// </summary>
|
||||
|
Search |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,220 @@ |
|||||
|
namespace Avalonia.Input.TextInput; |
||||
|
|
||||
|
public class TextInputOptions |
||||
|
{ |
||||
|
public static TextInputOptions FromStyledElement(StyledElement avaloniaObject) |
||||
|
{ |
||||
|
var result = new TextInputOptions |
||||
|
{ |
||||
|
ContentType = GetContentType(avaloniaObject), |
||||
|
Multiline = GetMultiline(avaloniaObject), |
||||
|
AutoCapitalization = GetAutoCapitalization(avaloniaObject), |
||||
|
IsSensitive = GetIsSensitive(avaloniaObject), |
||||
|
Lowercase = GetLowercase(avaloniaObject), |
||||
|
Uppercase = GetUppercase(avaloniaObject) |
||||
|
}; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public static readonly TextInputOptions Default = new(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="ContentType"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly AttachedProperty<TextInputContentType> ContentTypeProperty = |
||||
|
AvaloniaProperty.RegisterAttached<TextInputOptions, StyledElement, TextInputContentType>( |
||||
|
"ContentType", |
||||
|
defaultValue: TextInputContentType.Normal, |
||||
|
inherits: true); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the value of the attached <see cref="ContentTypeProperty"/> on a control.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The control.</param>
|
||||
|
/// <param name="value">The property value to set.</param>
|
||||
|
public static void SetContentType(StyledElement avaloniaObject, TextInputContentType value) |
||||
|
{ |
||||
|
avaloniaObject.SetValue(ContentTypeProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value of the attached <see cref="ContentTypeProperty"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The target.</param>
|
||||
|
/// <returns>TextInputContentType</returns>
|
||||
|
public static TextInputContentType GetContentType(StyledElement avaloniaObject) |
||||
|
{ |
||||
|
return avaloniaObject.GetValue(ContentTypeProperty); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The content type (mostly for determining the shape of the virtual keyboard)
|
||||
|
/// </summary>
|
||||
|
public TextInputContentType ContentType { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Multiline"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly AttachedProperty<bool> MultilineProperty = |
||||
|
AvaloniaProperty.RegisterAttached<TextInputOptions, StyledElement, bool>( |
||||
|
"Multiline", |
||||
|
inherits: true); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the value of the attached <see cref="MultilineProperty"/> on a control.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The control.</param>
|
||||
|
/// <param name="value">The property value to set.</param>
|
||||
|
public static void SetMultiline(StyledElement avaloniaObject, bool value) |
||||
|
{ |
||||
|
avaloniaObject.SetValue(MultilineProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value of the attached <see cref="MultilineProperty"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The target.</param>
|
||||
|
/// <returns>true if multiline</returns>
|
||||
|
public static bool GetMultiline(StyledElement avaloniaObject) |
||||
|
{ |
||||
|
return avaloniaObject.GetValue(MultilineProperty); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Text is multiline
|
||||
|
/// </summary>
|
||||
|
public bool Multiline { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Lowercase"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly AttachedProperty<bool> LowercaseProperty = |
||||
|
AvaloniaProperty.RegisterAttached<TextInputOptions, StyledElement, bool>( |
||||
|
"Lowercase", |
||||
|
inherits: true); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the value of the attached <see cref="LowercaseProperty"/> on a control.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The control.</param>
|
||||
|
/// <param name="value">The property value to set.</param>
|
||||
|
public static void SetLowercase(StyledElement avaloniaObject, bool value) |
||||
|
{ |
||||
|
avaloniaObject.SetValue(LowercaseProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value of the attached <see cref="LowercaseProperty"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The target.</param>
|
||||
|
/// <returns>true if Lowercase</returns>
|
||||
|
public static bool GetLowercase(StyledElement avaloniaObject) |
||||
|
{ |
||||
|
return avaloniaObject.GetValue(LowercaseProperty); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Text is in lower case
|
||||
|
/// </summary>
|
||||
|
public bool Lowercase { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Uppercase"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly AttachedProperty<bool> UppercaseProperty = |
||||
|
AvaloniaProperty.RegisterAttached<TextInputOptions, StyledElement, bool>( |
||||
|
"Uppercase", |
||||
|
inherits: true); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the value of the attached <see cref="UppercaseProperty"/> on a control.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The control.</param>
|
||||
|
/// <param name="value">The property value to set.</param>
|
||||
|
public static void SetUppercase(StyledElement avaloniaObject, bool value) |
||||
|
{ |
||||
|
avaloniaObject.SetValue(UppercaseProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value of the attached <see cref="UppercaseProperty"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The target.</param>
|
||||
|
/// <returns>true if Uppercase</returns>
|
||||
|
public static bool GetUppercase(StyledElement avaloniaObject) |
||||
|
{ |
||||
|
return avaloniaObject.GetValue(UppercaseProperty); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Text is in upper case
|
||||
|
/// </summary>
|
||||
|
public bool Uppercase { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="AutoCapitalization"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly AttachedProperty<bool> AutoCapitalizationProperty = |
||||
|
AvaloniaProperty.RegisterAttached<TextInputOptions, StyledElement, bool>( |
||||
|
"AutoCapitalization", |
||||
|
inherits: true); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the value of the attached <see cref="AutoCapitalizationProperty"/> on a control.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The control.</param>
|
||||
|
/// <param name="value">The property value to set.</param>
|
||||
|
public static void SetAutoCapitalization(StyledElement avaloniaObject, bool value) |
||||
|
{ |
||||
|
avaloniaObject.SetValue(AutoCapitalizationProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value of the attached <see cref="AutoCapitalizationProperty"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The target.</param>
|
||||
|
/// <returns>true if AutoCapitalization</returns>
|
||||
|
public static bool GetAutoCapitalization(StyledElement avaloniaObject) |
||||
|
{ |
||||
|
return avaloniaObject.GetValue(AutoCapitalizationProperty); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Automatically capitalize letters at the start of the sentence
|
||||
|
/// </summary>
|
||||
|
public bool AutoCapitalization { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="IsSensitive"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly AttachedProperty<bool> IsSensitiveProperty = |
||||
|
AvaloniaProperty.RegisterAttached<TextInputOptions, StyledElement, bool>( |
||||
|
"IsSensitive", |
||||
|
inherits: true); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the value of the attached <see cref="IsSensitiveProperty"/> on a control.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The control.</param>
|
||||
|
/// <param name="value">The property value to set.</param>
|
||||
|
public static void SetIsSensitive(StyledElement avaloniaObject, bool value) |
||||
|
{ |
||||
|
avaloniaObject.SetValue(IsSensitiveProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value of the attached <see cref="IsSensitiveProperty"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="avaloniaObject">The target.</param>
|
||||
|
/// <returns>true if IsSensitive</returns>
|
||||
|
public static bool GetIsSensitive(StyledElement avaloniaObject) |
||||
|
{ |
||||
|
return avaloniaObject.GetValue(IsSensitiveProperty); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Text contains sensitive data like card numbers and should not be stored
|
||||
|
/// </summary>
|
||||
|
public bool IsSensitive { get; set; } |
||||
|
} |
||||
@ -1,32 +0,0 @@ |
|||||
using Avalonia.Interactivity; |
|
||||
|
|
||||
namespace Avalonia.Input.TextInput |
|
||||
{ |
|
||||
public class TextInputOptionsQueryEventArgs : RoutedEventArgs |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// The content type (mostly for determining the shape of the virtual keyboard)
|
|
||||
/// </summary>
|
|
||||
public TextInputContentType ContentType { get; set; } |
|
||||
/// <summary>
|
|
||||
/// Text is multiline
|
|
||||
/// </summary>
|
|
||||
public bool Multiline { get; set; } |
|
||||
/// <summary>
|
|
||||
/// Text is in lower case
|
|
||||
/// </summary>
|
|
||||
public bool Lowercase { get; set; } |
|
||||
/// <summary>
|
|
||||
/// Text is in upper case
|
|
||||
/// </summary>
|
|
||||
public bool Uppercase { get; set; } |
|
||||
/// <summary>
|
|
||||
/// Automatically capitalize letters at the start of the sentence
|
|
||||
/// </summary>
|
|
||||
public bool AutoCapitalization { get; set; } |
|
||||
/// <summary>
|
|
||||
/// Text contains sensitive data like card numbers and should not be stored
|
|
||||
/// </summary>
|
|
||||
public bool IsSensitive { get; set; } |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -0,0 +1,478 @@ |
|||||
|
// Color conversion portions of this source file are adapted from the WinUI project.
|
||||
|
// (https://github.com/microsoft/microsoft-ui-xaml)
|
||||
|
//
|
||||
|
// Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation.
|
||||
|
|
||||
|
using System; |
||||
|
using Avalonia.Utilities; |
||||
|
|
||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines a color using the hue/saturation/value (HSV) model.
|
||||
|
/// </summary>
|
||||
|
#if !BUILDTASK
|
||||
|
public |
||||
|
#endif
|
||||
|
readonly struct HsvColor : IEquatable<HsvColor> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="HsvColor"/> struct.
|
||||
|
/// </summary>
|
||||
|
/// <param name="alpha">The Alpha (transparency) channel value in the range from 0..1.</param>
|
||||
|
/// <param name="hue">The Hue channel value in the range from 0..360.</param>
|
||||
|
/// <param name="saturation">The Saturation channel value in the range from 0..1.</param>
|
||||
|
/// <param name="value">The Value channel value in the range from 0..1.</param>
|
||||
|
public HsvColor( |
||||
|
double alpha, |
||||
|
double hue, |
||||
|
double saturation, |
||||
|
double value) |
||||
|
{ |
||||
|
A = MathUtilities.Clamp(alpha, 0.0, 1.0); |
||||
|
H = MathUtilities.Clamp(hue, 0.0, 360.0); |
||||
|
S = MathUtilities.Clamp(saturation, 0.0, 1.0); |
||||
|
V = MathUtilities.Clamp(value, 0.0, 1.0); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="HsvColor"/> struct.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// This constructor exists only for internal use where performance is critical.
|
||||
|
/// Whether or not the channel values are in the correct ranges must be known.
|
||||
|
/// </remarks>
|
||||
|
/// <param name="alpha">The Alpha (transparency) channel value in the range from 0..1.</param>
|
||||
|
/// <param name="hue">The Hue channel value in the range from 0..360.</param>
|
||||
|
/// <param name="saturation">The Saturation channel value in the range from 0..1.</param>
|
||||
|
/// <param name="value">The Value channel value in the range from 0..1.</param>
|
||||
|
/// <param name="clampValues">Whether to clamp channel values to their required ranges.</param>
|
||||
|
internal HsvColor( |
||||
|
double alpha, |
||||
|
double hue, |
||||
|
double saturation, |
||||
|
double value, |
||||
|
bool clampValues) |
||||
|
{ |
||||
|
if (clampValues) |
||||
|
{ |
||||
|
A = MathUtilities.Clamp(alpha, 0.0, 1.0); |
||||
|
H = MathUtilities.Clamp(hue, 0.0, 360.0); |
||||
|
S = MathUtilities.Clamp(saturation, 0.0, 1.0); |
||||
|
V = MathUtilities.Clamp(value, 0.0, 1.0); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
A = alpha; |
||||
|
H = hue; |
||||
|
S = saturation; |
||||
|
V = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="HsvColor"/> struct.
|
||||
|
/// </summary>
|
||||
|
/// <param name="color">The RGB color to convert to HSV.</param>
|
||||
|
public HsvColor(Color color) |
||||
|
{ |
||||
|
var hsv = HsvColor.FromRgb(color); |
||||
|
|
||||
|
A = hsv.A; |
||||
|
H = hsv.H; |
||||
|
S = hsv.S; |
||||
|
V = hsv.V; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the Alpha (transparency) channel value in the range from 0..1.
|
||||
|
/// </summary>
|
||||
|
public double A { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the Hue channel value in the range from 0..360.
|
||||
|
/// </summary>
|
||||
|
public double H { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the Saturation channel value in the range from 0..1.
|
||||
|
/// </summary>
|
||||
|
public double S { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the Value channel value in the range from 0..1.
|
||||
|
/// </summary>
|
||||
|
public double V { get; } |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public bool Equals(HsvColor other) |
||||
|
{ |
||||
|
return other.A == A && |
||||
|
other.H == H && |
||||
|
other.S == S && |
||||
|
other.V == V; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Equals(object? obj) |
||||
|
{ |
||||
|
if (obj is HsvColor hsvColor) |
||||
|
{ |
||||
|
return Equals(hsvColor); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a hashcode for this object.
|
||||
|
/// Hashcode is not guaranteed to be unique.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The hashcode for this object.</returns>
|
||||
|
public override int GetHashCode() |
||||
|
{ |
||||
|
// Same algorithm as Color
|
||||
|
// This is used instead of HashCode.Combine() due to .NET Standard 2.0 requirements
|
||||
|
unchecked |
||||
|
{ |
||||
|
int hashCode = A.GetHashCode(); |
||||
|
hashCode = (hashCode * 397) ^ H.GetHashCode(); |
||||
|
hashCode = (hashCode * 397) ^ S.GetHashCode(); |
||||
|
hashCode = (hashCode * 397) ^ V.GetHashCode(); |
||||
|
return hashCode; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the RGB color model equivalent of this HSV color.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The RGB equivalent color.</returns>
|
||||
|
public Color ToRgb() |
||||
|
{ |
||||
|
// Use the by-channel conversion method directly for performance
|
||||
|
return HsvColor.ToRgb(H, S, V, A); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new <see cref="HsvColor"/> from individual color channel values.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// This exists for symmetry with the <see cref="Color"/> struct; however, the
|
||||
|
/// appropriate constructor should commonly be used instead.
|
||||
|
/// </remarks>
|
||||
|
/// <param name="a">The Alpha (transparency) channel value in the range from 0..1.</param>
|
||||
|
/// <param name="h">The Hue channel value in the range from 0..360.</param>
|
||||
|
/// <param name="s">The Saturation channel value in the range from 0..1.</param>
|
||||
|
/// <param name="v">The Value channel value in the range from 0..1.</param>
|
||||
|
/// <returns>A new <see cref="HsvColor"/> built from the individual color channel values.</returns>
|
||||
|
public static HsvColor FromAhsv(double a, double h, double s, double v) |
||||
|
{ |
||||
|
return new HsvColor(a, h, s, v); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the given HSV color to it's RGB color equivalent.
|
||||
|
/// </summary>
|
||||
|
/// <param name="hsvColor">The color in the HSV color model.</param>
|
||||
|
/// <returns>A new RGB <see cref="Color"/> equivalent to the given HSVA values.</returns>
|
||||
|
public static Color ToRgb(HsvColor hsvColor) |
||||
|
{ |
||||
|
return HsvColor.ToRgb(hsvColor.H, hsvColor.S, hsvColor.V, hsvColor.A); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the given HSVA color channel values to it's RGB color equivalent.
|
||||
|
/// </summary>
|
||||
|
/// <param name="hue">The hue channel value in the HSV color model in the range from 0..360.</param>
|
||||
|
/// <param name="saturation">The saturation channel value in the HSV color model in the range from 0..1.</param>
|
||||
|
/// <param name="value">The value channel value in the HSV color model in the range from 0..1.</param>
|
||||
|
/// <param name="alpha">The alpha channel value in the range from 0..1.</param>
|
||||
|
/// <returns>A new RGB <see cref="Color"/> equivalent to the given HSVA values.</returns>
|
||||
|
public static Color ToRgb( |
||||
|
double hue, |
||||
|
double saturation, |
||||
|
double value, |
||||
|
double alpha = 1.0) |
||||
|
{ |
||||
|
// Note: Conversion code is originally based on the C++ in WinUI (licensed MIT)
|
||||
|
// https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/Common/ColorConversion.cpp
|
||||
|
// This was used because it is the best documented and likely most optimized for performance
|
||||
|
// Alpha channel support was added
|
||||
|
|
||||
|
// We want the hue to be between 0 and 359,
|
||||
|
// so we first ensure that that's the case.
|
||||
|
while (hue >= 360.0) |
||||
|
{ |
||||
|
hue -= 360.0; |
||||
|
} |
||||
|
|
||||
|
while (hue < 0.0) |
||||
|
{ |
||||
|
hue += 360.0; |
||||
|
} |
||||
|
|
||||
|
// We similarly clamp saturation, value and alpha between 0 and 1.
|
||||
|
saturation = saturation < 0.0 ? 0.0 : saturation; |
||||
|
saturation = saturation > 1.0 ? 1.0 : saturation; |
||||
|
|
||||
|
value = value < 0.0 ? 0.0 : value; |
||||
|
value = value > 1.0 ? 1.0 : value; |
||||
|
|
||||
|
alpha = alpha < 0.0 ? 0.0 : alpha; |
||||
|
alpha = alpha > 1.0 ? 1.0 : alpha; |
||||
|
|
||||
|
// The first thing that we need to do is to determine the chroma (see above for its definition).
|
||||
|
// Remember from above that:
|
||||
|
//
|
||||
|
// 1. The chroma is the difference between the maximum and the minimum of the RGB channels,
|
||||
|
// 2. The value is the maximum of the RGB channels, and
|
||||
|
// 3. The saturation comes from dividing the chroma by the maximum of the RGB channels (i.e., the value).
|
||||
|
//
|
||||
|
// From these facts, you can see that we can retrieve the chroma by simply multiplying the saturation and the value,
|
||||
|
// and we can retrieve the minimum of the RGB channels by subtracting the chroma from the value.
|
||||
|
var chroma = saturation * value; |
||||
|
var min = value - chroma; |
||||
|
|
||||
|
// If the chroma is zero, then we have a greyscale color. In that case, the maximum and the minimum RGB channels
|
||||
|
// have the same value (and, indeed, all of the RGB channels are the same), so we can just immediately return
|
||||
|
// the minimum value as the value of all the channels.
|
||||
|
if (chroma == 0) |
||||
|
{ |
||||
|
return Color.FromArgb( |
||||
|
(byte)Math.Round(alpha * 255), |
||||
|
(byte)Math.Round(min * 255), |
||||
|
(byte)Math.Round(min * 255), |
||||
|
(byte)Math.Round(min * 255)); |
||||
|
} |
||||
|
|
||||
|
// If the chroma is not zero, then we need to continue. The first step is to figure out
|
||||
|
// what section of the color wheel we're located in. In order to do that, we'll divide the hue by 60.
|
||||
|
// The resulting value means we're in one of the following locations:
|
||||
|
//
|
||||
|
// 0 - Between red and yellow.
|
||||
|
// 1 - Between yellow and green.
|
||||
|
// 2 - Between green and cyan.
|
||||
|
// 3 - Between cyan and blue.
|
||||
|
// 4 - Between blue and purple.
|
||||
|
// 5 - Between purple and red.
|
||||
|
//
|
||||
|
// In each of these sextants, one of the RGB channels is completely present, one is partially present, and one is not present.
|
||||
|
// For example, as we transition between red and yellow, red is completely present, green is becoming increasingly present, and blue is not present.
|
||||
|
// Then, as we transition from yellow and green, green is now completely present, red is becoming decreasingly present, and blue is still not present.
|
||||
|
// As we transition from green to cyan, green is still completely present, blue is becoming increasingly present, and red is no longer present. And so on.
|
||||
|
//
|
||||
|
// To convert from hue to RGB value, we first need to figure out which of the three channels is in which configuration
|
||||
|
// in the sextant that we're located in. Next, we figure out what value the completely-present color should have.
|
||||
|
// We know that chroma = (max - min), and we know that this color is the max color, so to find its value we simply add
|
||||
|
// min to chroma to retrieve max. Finally, we consider how far we've transitioned from the pure form of that color
|
||||
|
// to the next color (e.g., how far we are from pure red towards yellow), and give a value to the partially present channel
|
||||
|
// equal to the minimum plus the chroma (i.e., the max minus the min), multiplied by the percentage towards the new color.
|
||||
|
// This gets us a value between the maximum and the minimum representing the partially present channel.
|
||||
|
// Finally, the not-present color must be equal to the minimum value, since it is the one least participating in the overall color.
|
||||
|
int sextant = (int)(hue / 60); |
||||
|
double intermediateColorPercentage = (hue / 60) - sextant; |
||||
|
double max = chroma + min; |
||||
|
|
||||
|
double r = 0; |
||||
|
double g = 0; |
||||
|
double b = 0; |
||||
|
|
||||
|
switch (sextant) |
||||
|
{ |
||||
|
case 0: |
||||
|
r = max; |
||||
|
g = min + (chroma * intermediateColorPercentage); |
||||
|
b = min; |
||||
|
break; |
||||
|
case 1: |
||||
|
r = min + (chroma * (1 - intermediateColorPercentage)); |
||||
|
g = max; |
||||
|
b = min; |
||||
|
break; |
||||
|
case 2: |
||||
|
r = min; |
||||
|
g = max; |
||||
|
b = min + (chroma * intermediateColorPercentage); |
||||
|
break; |
||||
|
case 3: |
||||
|
r = min; |
||||
|
g = min + (chroma * (1 - intermediateColorPercentage)); |
||||
|
b = max; |
||||
|
break; |
||||
|
case 4: |
||||
|
r = min + (chroma * intermediateColorPercentage); |
||||
|
g = min; |
||||
|
b = max; |
||||
|
break; |
||||
|
case 5: |
||||
|
r = max; |
||||
|
g = min; |
||||
|
b = min + (chroma * (1 - intermediateColorPercentage)); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
return Color.FromArgb( |
||||
|
(byte)Math.Round(alpha * 255), |
||||
|
(byte)Math.Round(r * 255), |
||||
|
(byte)Math.Round(g * 255), |
||||
|
(byte)Math.Round(b * 255)); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the given RGB color to it's HSV color equivalent.
|
||||
|
/// </summary>
|
||||
|
/// <param name="color">The color in the RGB color model.</param>
|
||||
|
/// <returns>A new <see cref="HsvColor"/> equivalent to the given RGBA values.</returns>
|
||||
|
public static HsvColor FromRgb(Color color) |
||||
|
{ |
||||
|
return HsvColor.FromRgb(color.R, color.G, color.B, color.A); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the given RGBA color channel values to it's HSV color equivalent.
|
||||
|
/// </summary>
|
||||
|
/// <param name="red">The red channel value in the RGB color model.</param>
|
||||
|
/// <param name="green">The green channel value in the RGB color model.</param>
|
||||
|
/// <param name="blue">The blue channel value in the RGB color model.</param>
|
||||
|
/// <param name="alpha">The alpha channel value.</param>
|
||||
|
/// <returns>A new <see cref="HsvColor"/> equivalent to the given RGBA values.</returns>
|
||||
|
public static HsvColor FromRgb( |
||||
|
byte red, |
||||
|
byte green, |
||||
|
byte blue, |
||||
|
byte alpha = 0xFF) |
||||
|
{ |
||||
|
// Note: Conversion code is originally based on the C++ in WinUI (licensed MIT)
|
||||
|
// https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/Common/ColorConversion.cpp
|
||||
|
// This was used because it is the best documented and likely most optimized for performance
|
||||
|
// Alpha channel support was added
|
||||
|
|
||||
|
// Normalize RGBA channel values into the 0..1 range used by this algorithm
|
||||
|
double r = red / 255.0; |
||||
|
double g = green / 255.0; |
||||
|
double b = blue / 255.0; |
||||
|
double a = alpha / 255.0; |
||||
|
|
||||
|
double hue; |
||||
|
double saturation; |
||||
|
double value; |
||||
|
|
||||
|
double max = r >= g ? (r >= b ? r : b) : (g >= b ? g : b); |
||||
|
double min = r <= g ? (r <= b ? r : b) : (g <= b ? g : b); |
||||
|
|
||||
|
// The value, a number between 0 and 1, is the largest of R, G, and B (divided by 255).
|
||||
|
// Conceptually speaking, it represents how much color is present.
|
||||
|
// If at least one of R, G, B is 255, then there exists as much color as there can be.
|
||||
|
// If RGB = (0, 0, 0), then there exists no color at all - a value of zero corresponds
|
||||
|
// to black (i.e., the absence of any color).
|
||||
|
value = max; |
||||
|
|
||||
|
// The "chroma" of the color is a value directly proportional to the extent to which
|
||||
|
// the color diverges from greyscale. If, for example, we have RGB = (255, 255, 0),
|
||||
|
// then the chroma is maximized - this is a pure yellow, no gray of any kind.
|
||||
|
// On the other hand, if we have RGB = (128, 128, 128), then the chroma being zero
|
||||
|
// implies that this color is pure greyscale, with no actual hue to be found.
|
||||
|
var chroma = max - min; |
||||
|
|
||||
|
// If the chrome is zero, then hue is technically undefined - a greyscale color
|
||||
|
// has no hue. For the sake of convenience, we'll just set hue to zero, since
|
||||
|
// it will be unused in this circumstance. Since the color is purely gray,
|
||||
|
// saturation is also equal to zero - you can think of saturation as basically
|
||||
|
// a measure of hue intensity, such that no hue at all corresponds to a
|
||||
|
// nonexistent intensity.
|
||||
|
if (chroma == 0) |
||||
|
{ |
||||
|
hue = 0.0; |
||||
|
saturation = 0.0; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// In this block, hue is properly defined, so we'll extract both hue
|
||||
|
// and saturation information from the RGB color.
|
||||
|
|
||||
|
// Hue can be thought of as a cyclical thing, between 0 degrees and 360 degrees.
|
||||
|
// A hue of 0 degrees is red; 120 degrees is green; 240 degrees is blue; and 360 is back to red.
|
||||
|
// Every other hue is somewhere between either red and green, green and blue, and blue and red,
|
||||
|
// so every other hue can be thought of as an angle on this color wheel.
|
||||
|
// These if/else statements determines where on this color wheel our color lies.
|
||||
|
if (r == max) |
||||
|
{ |
||||
|
// If the red channel is the most pronounced channel, then we exist
|
||||
|
// somewhere between (-60, 60) on the color wheel - i.e., the section around 0 degrees
|
||||
|
// where red dominates. We figure out where in that section we are exactly
|
||||
|
// by considering whether the green or the blue channel is greater - by subtracting green from blue,
|
||||
|
// then if green is greater, we'll nudge ourselves closer to 60, whereas if blue is greater, then
|
||||
|
// we'll nudge ourselves closer to -60. We then divide by chroma (which will actually make the result larger,
|
||||
|
// since chroma is a value between 0 and 1) to normalize the value to ensure that we get the right hue
|
||||
|
// even if we're very close to greyscale.
|
||||
|
hue = 60 * (g - b) / chroma; |
||||
|
} |
||||
|
else if (g == max) |
||||
|
{ |
||||
|
// We do the exact same for the case where the green channel is the most pronounced channel,
|
||||
|
// only this time we want to see if we should tilt towards the blue direction or the red direction.
|
||||
|
// We add 120 to center our value in the green third of the color wheel.
|
||||
|
hue = 120 + (60 * (b - r) / chroma); |
||||
|
} |
||||
|
else // blue == max
|
||||
|
{ |
||||
|
// And we also do the exact same for the case where the blue channel is the most pronounced channel,
|
||||
|
// only this time we want to see if we should tilt towards the red direction or the green direction.
|
||||
|
// We add 240 to center our value in the blue third of the color wheel.
|
||||
|
hue = 240 + (60 * (r - g) / chroma); |
||||
|
} |
||||
|
|
||||
|
// Since we want to work within the range [0, 360), we'll add 360 to any value less than zero -
|
||||
|
// this will bump red values from within -60 to -1 to 300 to 359. The hue is the same at both values.
|
||||
|
if (hue < 0.0) |
||||
|
{ |
||||
|
hue += 360.0; |
||||
|
} |
||||
|
|
||||
|
// The saturation, our final HSV axis, can be thought of as a value between 0 and 1 indicating how intense our color is.
|
||||
|
// To find it, we divide the chroma - the distance between the minimum and the maximum RGB channels - by the maximum channel (i.e., the value).
|
||||
|
// This effectively normalizes the chroma - if the maximum is 0.5 and the minimum is 0, the saturation will be (0.5 - 0) / 0.5 = 1,
|
||||
|
// meaning that although this color is not as bright as it can be, the dark color is as intense as it possibly could be.
|
||||
|
// If, on the other hand, the maximum is 0.5 and the minimum is 0.25, then the saturation will be (0.5 - 0.25) / 0.5 = 0.5,
|
||||
|
// meaning that this color is partially washed out.
|
||||
|
// A saturation value of 0 corresponds to a greyscale color, one in which the color is *completely* washed out and there is no actual hue.
|
||||
|
saturation = chroma / value; |
||||
|
} |
||||
|
|
||||
|
return new HsvColor(a, hue, saturation, value, false); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indicates whether the values of two specified <see cref="HsvColor"/> objects are equal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="left">The first object to compare.</param>
|
||||
|
/// <param name="right">The second object to compare.</param>
|
||||
|
/// <returns>True if left and right are equal; otherwise, false.</returns>
|
||||
|
public static bool operator ==(HsvColor left, HsvColor right) |
||||
|
{ |
||||
|
return left.Equals(right); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indicates whether the values of two specified <see cref="HsvColor"/> objects are not equal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="left">The first object to compare.</param>
|
||||
|
/// <param name="right">The second object to compare.</param>
|
||||
|
/// <returns>True if left and right are not equal; otherwise, false.</returns>
|
||||
|
public static bool operator !=(HsvColor left, HsvColor right) |
||||
|
{ |
||||
|
return !(left == right); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Explicit conversion from an <see cref="HsvColor"/> to a <see cref="Color"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="hsvColor">The <see cref="HsvColor"/> to convert.</param>
|
||||
|
public static explicit operator Color(HsvColor hsvColor) |
||||
|
{ |
||||
|
return hsvColor.ToRgb(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using Avalonia.VisualTree; |
||||
|
|
||||
|
namespace Avalonia.Media.Immutable |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Represents a transform on an <see cref="IVisual"/>.
|
||||
|
/// </summary>
|
||||
|
public class ImmutableTransform : ITransform |
||||
|
{ |
||||
|
public Matrix Value { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ImmutableTransform"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="matrix">The transform matrix.</param>
|
||||
|
public ImmutableTransform(Matrix matrix) |
||||
|
{ |
||||
|
Value = matrix; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Media.Immutable; |
||||
|
|
||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Extension methods for transform classes.
|
||||
|
/// </summary>
|
||||
|
public static class TransformExtensions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Converts a transform to an immutable transform.
|
||||
|
/// </summary>
|
||||
|
/// <param name="transform">The transform.</param>
|
||||
|
/// <returns>
|
||||
|
/// The result of calling <see cref="Transform.ToImmutable"/> if the transform is mutable,
|
||||
|
/// otherwise <paramref name="transform"/>.
|
||||
|
/// </returns>
|
||||
|
public static ImmutableTransform ToImmutable(this ITransform transform) |
||||
|
{ |
||||
|
_ = transform ?? throw new ArgumentNullException(nameof(transform)); |
||||
|
|
||||
|
return (transform as Transform)?.ToImmutable() ?? new ImmutableTransform(transform.Value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Media; |
||||
|
using Avalonia.Utilities; |
||||
|
|
||||
|
namespace Avalonia.Rendering.SceneGraph; |
||||
|
|
||||
|
internal static class GeometryBoundsHelper |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Calculates the bounds of a given geometry with respect to the pens <see cref="IPen.LineCap"/>
|
||||
|
/// </summary>
|
||||
|
/// <param name="originalBounds">The calculated bounds without <see cref="IPen.LineCap"/>s</param>
|
||||
|
/// <param name="pen">The pen with information about the <see cref="IPen.LineCap"/>s</param>
|
||||
|
/// <returns></returns>
|
||||
|
public static Rect CalculateBoundsWithLineCaps(this Rect originalBounds, IPen? pen) |
||||
|
{ |
||||
|
if (pen is null || MathUtilities.IsZero(pen.Thickness)) return originalBounds; |
||||
|
|
||||
|
switch (pen.LineCap) |
||||
|
{ |
||||
|
case PenLineCap.Flat: |
||||
|
return originalBounds; |
||||
|
case PenLineCap.Round: |
||||
|
return originalBounds.Inflate(pen.Thickness / 2); |
||||
|
case PenLineCap.Square: |
||||
|
return originalBounds.Inflate(pen.Thickness); |
||||
|
default: |
||||
|
throw new ArgumentOutOfRangeException(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -1,32 +1,146 @@ |
|||||
using Avalonia.Input; |
|
||||
using Avalonia.Input.Raw; |
|
||||
using Foundation; |
using Foundation; |
||||
using ObjCRuntime; |
using ObjCRuntime; |
||||
|
using Avalonia.Input.TextInput; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Input.Raw; |
||||
using UIKit; |
using UIKit; |
||||
|
|
||||
namespace Avalonia.iOS |
namespace Avalonia.iOS; |
||||
|
|
||||
|
#nullable enable |
||||
|
|
||||
|
[Adopts("UITextInputTraits")] |
||||
|
[Adopts("UIKeyInput")] |
||||
|
public partial class AvaloniaView : ITextInputMethodImpl |
||||
{ |
{ |
||||
[Adopts("UIKeyInput")] |
private ITextInputMethodClient? _currentClient; |
||||
public partial class AvaloniaView |
|
||||
|
public override bool CanResignFirstResponder => true; |
||||
|
public override bool CanBecomeFirstResponder => true; |
||||
|
|
||||
|
[Export("hasText")] |
||||
|
public bool HasText |
||||
{ |
{ |
||||
public override bool CanBecomeFirstResponder => true; |
get |
||||
|
{ |
||||
|
if (_currentClient is { } && _currentClient.SupportsSurroundingText && |
||||
|
_currentClient.SurroundingText.Text.Length > 0) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[Export("keyboardType")] public UIKeyboardType KeyboardType { get; private set; } = UIKeyboardType.Default; |
||||
|
|
||||
[Export("hasText")] public bool HasText => false; |
[Export("isSecureTextEntry")] public bool IsSecureEntry { get; private set; } |
||||
|
|
||||
[Export("insertText:")] |
[Export("insertText:")] |
||||
public void InsertText(string text) => |
public void InsertText(string text) |
||||
|
{ |
||||
|
if (KeyboardDevice.Instance is { }) |
||||
|
{ |
||||
_topLevelImpl.Input?.Invoke(new RawTextInputEventArgs(KeyboardDevice.Instance, |
_topLevelImpl.Input?.Invoke(new RawTextInputEventArgs(KeyboardDevice.Instance, |
||||
0, InputRoot, text)); |
0, InputRoot, text)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
[Export("deleteBackward")] |
[Export("deleteBackward")] |
||||
public void DeleteBackward() |
public void DeleteBackward() |
||||
|
{ |
||||
|
if (KeyboardDevice.Instance is { }) |
||||
{ |
{ |
||||
// TODO: pass this through IME infrastructure instead of emulating a backspace press
|
// TODO: pass this through IME infrastructure instead of emulating a backspace press
|
||||
_topLevelImpl.Input?.Invoke(new RawKeyEventArgs(KeyboardDevice.Instance, |
_topLevelImpl.Input?.Invoke(new RawKeyEventArgs(KeyboardDevice.Instance, |
||||
0, InputRoot, RawKeyEventType.KeyDown, Key.Back, RawInputModifiers.None)); |
0, InputRoot, RawKeyEventType.KeyDown, Key.Back, RawInputModifiers.None)); |
||||
|
|
||||
_topLevelImpl.Input?.Invoke(new RawKeyEventArgs(KeyboardDevice.Instance, |
_topLevelImpl.Input?.Invoke(new RawKeyEventArgs(KeyboardDevice.Instance, |
||||
0, InputRoot, RawKeyEventType.KeyUp, Key.Back, RawInputModifiers.None)); |
0, InputRoot, RawKeyEventType.KeyUp, Key.Back, RawInputModifiers.None)); |
||||
} |
} |
||||
} |
} |
||||
} |
|
||||
|
void ITextInputMethodImpl.SetClient(ITextInputMethodClient? client) |
||||
|
{ |
||||
|
_currentClient = client; |
||||
|
|
||||
|
if (client is { }) |
||||
|
{ |
||||
|
BecomeFirstResponder(); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
ResignFirstResponder(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ITextInputMethodImpl.SetCursorRect(Rect rect) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void ITextInputMethodImpl.SetOptions(TextInputOptions options) |
||||
|
{ |
||||
|
IsSecureEntry = false; |
||||
|
|
||||
|
switch (options.ContentType) |
||||
|
{ |
||||
|
case TextInputContentType.Normal: |
||||
|
KeyboardType = UIKeyboardType.Default; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Alpha: |
||||
|
KeyboardType = UIKeyboardType.AsciiCapable; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Digits: |
||||
|
KeyboardType = UIKeyboardType.PhonePad; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Pin: |
||||
|
KeyboardType = UIKeyboardType.NumberPad; |
||||
|
IsSecureEntry = true; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Number: |
||||
|
KeyboardType = UIKeyboardType.PhonePad; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Email: |
||||
|
KeyboardType = UIKeyboardType.EmailAddress; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Url: |
||||
|
KeyboardType = UIKeyboardType.Url; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Name: |
||||
|
KeyboardType = UIKeyboardType.NamePhonePad; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Password: |
||||
|
KeyboardType = UIKeyboardType.Default; |
||||
|
IsSecureEntry = true; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Social: |
||||
|
KeyboardType = UIKeyboardType.Twitter; |
||||
|
break; |
||||
|
|
||||
|
case TextInputContentType.Search: |
||||
|
KeyboardType = UIKeyboardType.WebSearch; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if (options.IsSensitive) |
||||
|
{ |
||||
|
IsSecureEntry = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ITextInputMethodImpl.Reset() |
||||
|
{ |
||||
|
ResignFirstResponder(); |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -1,24 +0,0 @@ |
|||||
using Avalonia.Controls; |
|
||||
using Avalonia.Input; |
|
||||
|
|
||||
namespace Avalonia.iOS |
|
||||
{ |
|
||||
public class SoftKeyboardHelper |
|
||||
{ |
|
||||
private AvaloniaView _oldView; |
|
||||
|
|
||||
public void UpdateKeyboard(IInputElement focusedElement) |
|
||||
{ |
|
||||
if (_oldView?.IsFirstResponder == true) |
|
||||
_oldView?.ResignFirstResponder(); |
|
||||
_oldView = null; |
|
||||
|
|
||||
//TODO: Raise a routed event to determine if any control wants to become the text input handler
|
|
||||
if (focusedElement is TextBox) |
|
||||
{ |
|
||||
var view = ((focusedElement.VisualRoot as TopLevel)?.PlatformImpl as AvaloniaView.TopLevelImpl)?.View; |
|
||||
view?.BecomeFirstResponder(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue