committed by
GitHub
41 changed files with 610 additions and 914 deletions
@ -1,27 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Text; |
|
||||
|
|
||||
using Android.App; |
|
||||
using Android.Content; |
|
||||
using Android.OS; |
|
||||
using Android.Runtime; |
|
||||
using Android.Views; |
|
||||
using Android.Widget; |
|
||||
using Avalonia.Controls.Platform.Surfaces; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.Skia |
|
||||
{ |
|
||||
partial class PlatformRenderInterface |
|
||||
{ |
|
||||
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces) |
|
||||
{ |
|
||||
var fb = surfaces?.OfType<IFramebufferPlatformSurface>().FirstOrDefault(); |
|
||||
if (fb == null) |
|
||||
throw new ArgumentException("Avalonia.Skia.Android is only capable of drawing on framebuffer"); |
|
||||
return new FramebufferRenderTarget(fb); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,21 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Text; |
|
||||
using System.Threading.Tasks; |
|
||||
using Avalonia.Controls.Platform.Surfaces; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.Skia |
|
||||
{ |
|
||||
partial class PlatformRenderInterface |
|
||||
{ |
|
||||
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces) |
|
||||
{ |
|
||||
var fb = surfaces?.OfType<IFramebufferPlatformSurface>().FirstOrDefault(); |
|
||||
if (fb == null) |
|
||||
throw new Exception("Avalonia.Skia.Deskop currently only supports framebuffer render target"); |
|
||||
return new FramebufferRenderTarget(fb); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,74 +0,0 @@ |
|||||
using Foundation; |
|
||||
using UIKit; |
|
||||
|
|
||||
namespace Avalonia.Skia.iOS.TestApp |
|
||||
{ |
|
||||
// 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 class AppDelegate : UIApplicationDelegate |
|
||||
{ |
|
||||
// class-level declarations
|
|
||||
|
|
||||
public override UIWindow Window |
|
||||
{ |
|
||||
get; |
|
||||
set; |
|
||||
} |
|
||||
|
|
||||
class Controller : UIViewController |
|
||||
{ |
|
||||
public override void LoadView() |
|
||||
{ |
|
||||
View = new MainView(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) |
|
||||
{ |
|
||||
// create a new window instance based on the screen size
|
|
||||
Window = new UIWindow(UIScreen.MainScreen.Bounds); |
|
||||
|
|
||||
// If you have defined a root view controller, set it here:
|
|
||||
Window.RootViewController = new Controller(); |
|
||||
|
|
||||
// make the window visible
|
|
||||
Window.MakeKeyAndVisible(); |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
public override void OnResignActivation(UIApplication application) |
|
||||
{ |
|
||||
// Invoked when the application is about to move from active to inactive state.
|
|
||||
// This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message)
|
|
||||
// or when the user quits the application and it begins the transition to the background state.
|
|
||||
// Games should use this method to pause the game.
|
|
||||
} |
|
||||
|
|
||||
public override void DidEnterBackground(UIApplication application) |
|
||||
{ |
|
||||
// Use this method to release shared resources, save user data, invalidate timers and store the application state.
|
|
||||
// If your application supports background exection this method is called instead of WillTerminate when the user quits.
|
|
||||
} |
|
||||
|
|
||||
public override void WillEnterForeground(UIApplication application) |
|
||||
{ |
|
||||
// Called as part of the transiton from background to active state.
|
|
||||
// Here you can undo many of the changes made on entering the background.
|
|
||||
} |
|
||||
|
|
||||
public override void OnActivated(UIApplication application) |
|
||||
{ |
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive.
|
|
||||
// If the application was previously in the background, optionally refresh the user interface.
|
|
||||
} |
|
||||
|
|
||||
public override void WillTerminate(UIApplication application) |
|
||||
{ |
|
||||
// Called when the application is about to terminate. Save data, if needed. See also DidEnterBackground.
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
@ -1,143 +0,0 @@ |
|||||
<?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)' == '' ">iPhoneSimulator</Platform> |
|
||||
<ProjectGuid>{DA49C5F3-BE95-461C-B999-072128CCF59E}</ProjectGuid> |
|
||||
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> |
|
||||
<OutputType>Exe</OutputType> |
|
||||
<RootNamespace>Avalonia.Skia.iOS.TestApp</RootNamespace> |
|
||||
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix> |
|
||||
<AssemblyName>AvaloniaSkiaiOSTestApp</AssemblyName> |
|
||||
</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>i386</MtouchArch> |
|
||||
<MtouchLink>SdkOnly</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>i386</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>ARMv7, ARM64</MtouchArch> |
|
||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> |
|
||||
<CodesignKey>iPhone Developer</CodesignKey> |
|
||||
<MtouchDebug>true</MtouchDebug> |
|
||||
<CodesignProvision> |
|
||||
</CodesignProvision> |
|
||||
<CodesignResourceRules /> |
|
||||
<CodesignExtraArgs /> |
|
||||
</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>ARMv7, ARM64</MtouchArch> |
|
||||
<ConsolePause>false</ConsolePause> |
|
||||
<CodesignKey>iPhone Developer</CodesignKey> |
|
||||
</PropertyGroup> |
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' "> |
|
||||
<DebugType>none</DebugType> |
|
||||
<Optimize>True</Optimize> |
|
||||
<OutputPath>bin\iPhone\Ad-Hoc</OutputPath> |
|
||||
<ErrorReport>prompt</ErrorReport> |
|
||||
<WarningLevel>4</WarningLevel> |
|
||||
<ConsolePause>False</ConsolePause> |
|
||||
<MtouchArch>ARMv7, ARM64</MtouchArch> |
|
||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> |
|
||||
<BuildIpa>True</BuildIpa> |
|
||||
<CodesignProvision>Automatic:AdHoc</CodesignProvision> |
|
||||
<CodesignKey>iPhone Distribution</CodesignKey> |
|
||||
</PropertyGroup> |
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|iPhone' "> |
|
||||
<DebugType>none</DebugType> |
|
||||
<Optimize>True</Optimize> |
|
||||
<OutputPath>bin\iPhone\AppStore</OutputPath> |
|
||||
<ErrorReport>prompt</ErrorReport> |
|
||||
<WarningLevel>4</WarningLevel> |
|
||||
<ConsolePause>False</ConsolePause> |
|
||||
<MtouchArch>ARMv7, ARM64</MtouchArch> |
|
||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> |
|
||||
<CodesignProvision>Automatic:AppStore</CodesignProvision> |
|
||||
<CodesignKey>iPhone Distribution</CodesignKey> |
|
||||
</PropertyGroup> |
|
||||
<ItemGroup> |
|
||||
<Compile Include="Main.cs" /> |
|
||||
<Compile Include="AppDelegate.cs" /> |
|
||||
<None Include="GettingStarted.Xamarin" /> |
|
||||
<None Include="Info.plist" /> |
|
||||
<Compile Include="MainView.cs" /> |
|
||||
<Compile Include="Properties\AssemblyInfo.cs" /> |
|
||||
<InterfaceDefinition Include="Resources\LaunchScreen.xib" /> |
|
||||
<Content Include="Entitlements.plist" /> |
|
||||
</ItemGroup> |
|
||||
<ItemGroup> |
|
||||
<Reference Include="System" /> |
|
||||
<Reference Include="System.Xml" /> |
|
||||
<Reference Include="System.Core" /> |
|
||||
<Reference Include="Xamarin.iOS" /> |
|
||||
</ItemGroup> |
|
||||
<ItemGroup> |
|
||||
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj"> |
|
||||
<Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project> |
|
||||
<Name>Avalonia.Animation</Name> |
|
||||
</ProjectReference> |
|
||||
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj"> |
|
||||
<Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project> |
|
||||
<Name>Avalonia.Base</Name> |
|
||||
</ProjectReference> |
|
||||
<ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj"> |
|
||||
<Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project> |
|
||||
<Name>Avalonia.Controls</Name> |
|
||||
</ProjectReference> |
|
||||
<ProjectReference Include="..\..\Avalonia.Input\Avalonia.Input.csproj"> |
|
||||
<Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project> |
|
||||
<Name>Avalonia.Input</Name> |
|
||||
</ProjectReference> |
|
||||
<ProjectReference Include="..\..\Avalonia.Layout\Avalonia.Layout.csproj"> |
|
||||
<Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project> |
|
||||
<Name>Avalonia.Layout</Name> |
|
||||
</ProjectReference> |
|
||||
<ProjectReference Include="..\..\Avalonia.Visuals\Avalonia.Visuals.csproj"> |
|
||||
<Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project> |
|
||||
<Name>Avalonia.Visuals</Name> |
|
||||
</ProjectReference> |
|
||||
<ProjectReference Include="..\..\Avalonia.Styling\Avalonia.Styling.csproj"> |
|
||||
<Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project> |
|
||||
<Name>Avalonia.Styling</Name> |
|
||||
</ProjectReference> |
|
||||
<ProjectReference Include="..\Avalonia.Skia.iOS\Avalonia.Skia.iOS.csproj"> |
|
||||
<Project>{47be08a7-5985-410b-9ffc-2264b8ea595f}</Project> |
|
||||
<Name>Avalonia.Skia.iOS</Name> |
|
||||
<IsAppExtension>false</IsAppExtension> |
|
||||
<IsWatchApp>false</IsWatchApp> |
|
||||
</ProjectReference> |
|
||||
</ItemGroup> |
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> |
|
||||
</Project> |
|
||||
@ -1,26 +0,0 @@ |
|||||
<ProjectConfiguration> |
|
||||
<AutoDetectNugetBuildDependencies>true</AutoDetectNugetBuildDependencies> |
|
||||
<BuildPriority>1000</BuildPriority> |
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace> |
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing> |
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies> |
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking> |
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking> |
|
||||
<AllowCodeAnalysis>false</AllowCodeAnalysis> |
|
||||
<IgnoreThisComponentCompletely>true</IgnoreThisComponentCompletely> |
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents> |
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents> |
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully> |
|
||||
<InstrumentAssembly>true</InstrumentAssembly> |
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly> |
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes> |
|
||||
<DetectStackOverflow>true</DetectStackOverflow> |
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace> |
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout> |
|
||||
<UseBuildConfiguration></UseBuildConfiguration> |
|
||||
<UseBuildPlatform></UseBuildPlatform> |
|
||||
<ProxyProcessPath></ProxyProcessPath> |
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture> |
|
||||
<MSTestThreadApartmentState>STA</MSTestThreadApartmentState> |
|
||||
<BuildProcessArchitecture>x86</BuildProcessArchitecture> |
|
||||
</ProjectConfiguration> |
|
||||
@ -1,5 +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/> |
|
||||
</plist> |
|
||||
@ -1,4 +0,0 @@ |
|||||
<GettingStarted> |
|
||||
<LocalContent>GS\iOS\CS\iOSApp\GettingStarted.html</LocalContent> |
|
||||
<EmbeddedNavigation>false</EmbeddedNavigation> |
|
||||
</GettingStarted> |
|
||||
@ -1,42 +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>Avalonia.Skia.iOS.TestApp</string> |
|
||||
<key>CFBundleIdentifier</key> |
|
||||
<string>com.companyname.Avalonia.Skia.iOS.TestApp</string> |
|
||||
<key>CFBundleShortVersionString</key> |
|
||||
<string>1.0</string> |
|
||||
<key>CFBundleVersion</key> |
|
||||
<string>1.0</string> |
|
||||
<key>LSRequiresIPhoneOS</key> |
|
||||
<true/> |
|
||||
<key>MinimumOSVersion</key> |
|
||||
<string>8.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> |
|
||||
</dict> |
|
||||
</plist> |
|
||||
@ -1,15 +0,0 @@ |
|||||
using UIKit; |
|
||||
|
|
||||
namespace Avalonia.Skia.iOS.TestApp |
|
||||
{ |
|
||||
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,77 +0,0 @@ |
|||||
using System; |
|
||||
using System.Diagnostics; |
|
||||
using System.Drawing; |
|
||||
using CoreAnimation; |
|
||||
using CoreGraphics; |
|
||||
using CoreMedia; |
|
||||
using Foundation; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
using UIKit; |
|
||||
|
|
||||
namespace Avalonia.Skia.iOS.TestApp |
|
||||
{ |
|
||||
[Register("MainView")] |
|
||||
public class MainView : SkiaView |
|
||||
{ |
|
||||
private IRenderTarget _target; |
|
||||
FormattedText _text; |
|
||||
public MainView() |
|
||||
{ |
|
||||
AutoresizingMask = UIViewAutoresizing.All; |
|
||||
SkiaPlatform.Initialize(); |
|
||||
_target = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>() |
|
||||
.CreateRenderTarget(AvaloniaPlatformHandle); |
|
||||
UpdateText(0); |
|
||||
} |
|
||||
double _radians = 0; |
|
||||
|
|
||||
|
|
||||
void UpdateText(int fps) |
|
||||
{ |
|
||||
_text?.Dispose(); |
|
||||
_text = new FormattedText("FPS: " + fps, "Arial", 15, FontStyle.Normal, TextAlignment.Left, |
|
||||
FontWeight.Normal); |
|
||||
} |
|
||||
|
|
||||
double _lastFps; |
|
||||
int _frames; |
|
||||
Stopwatch St = Stopwatch.StartNew(); |
|
||||
protected override void Draw() |
|
||||
{ |
|
||||
_radians += 0.02; |
|
||||
var scale = UIScreen.MainScreen.Scale; |
|
||||
int width = (int) (Bounds.Width*scale), height = (int) (Bounds.Height*scale); |
|
||||
using (var ctx = _target.CreateDrawingContext()) |
|
||||
{ |
|
||||
ctx.FillRectangle(Brushes.Green, new Rect(0, 0, width, height)); |
|
||||
ctx.DrawText(Brushes.Red, new Point(50, 50), _text); |
|
||||
var rc = new Rect(0, 0, width/3, height/3); |
|
||||
using (ctx.PushPostTransform( |
|
||||
Avalonia.Matrix.CreateTranslation(-width/6, -width/6)* |
|
||||
Avalonia.Matrix.CreateRotation(_radians)* |
|
||||
Avalonia.Matrix.CreateTranslation(width/2, height/2))) |
|
||||
{ |
|
||||
ctx.FillRectangle(new LinearGradientBrush() |
|
||||
{ |
|
||||
GradientStops = |
|
||||
{ |
|
||||
new GradientStop() {Color = Colors.Blue}, |
|
||||
new GradientStop(Colors.Red, 1) |
|
||||
} |
|
||||
}, rc, 5); |
|
||||
} |
|
||||
} |
|
||||
_frames++; |
|
||||
var now = St.Elapsed.TotalSeconds; |
|
||||
var elapsed = now - _lastFps; |
|
||||
if (elapsed > 1) |
|
||||
{ |
|
||||
UpdateText((int) (_frames/elapsed)); |
|
||||
_frames = 0; |
|
||||
_lastFps = now; |
|
||||
} |
|
||||
DrawOnNextFrame(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,36 +0,0 @@ |
|||||
using System.Reflection; |
|
||||
using System.Runtime.CompilerServices; |
|
||||
using System.Runtime.InteropServices; |
|
||||
|
|
||||
// General Information about an assembly is controlled through the following
|
|
||||
// set of attributes. Change these attribute values to modify the information
|
|
||||
// associated with an assembly.
|
|
||||
[assembly: AssemblyTitle("Avalonia.Skia.iOS.TestApp")] |
|
||||
[assembly: AssemblyDescription("")] |
|
||||
[assembly: AssemblyConfiguration("")] |
|
||||
[assembly: AssemblyCompany("")] |
|
||||
[assembly: AssemblyProduct("Avalonia.Skia.iOS.TestApp")] |
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")] |
|
||||
[assembly: AssemblyTrademark("")] |
|
||||
[assembly: AssemblyCulture("")] |
|
||||
|
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||
// to COM components. If you need to access a type in this assembly from
|
|
||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||
[assembly: ComVisible(false)] |
|
||||
|
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||
[assembly: Guid("da49c5f3-be95-461c-b999-072128ccf59e")] |
|
||||
|
|
||||
// Version information for an assembly consists of the following four values:
|
|
||||
//
|
|
||||
// Major Version
|
|
||||
// Minor Version
|
|
||||
// Build Number
|
|
||||
// Revision
|
|
||||
//
|
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||
// by using the '*' as shown below:
|
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
|
||||
[assembly: AssemblyVersion("1.0.0.0")] |
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")] |
|
||||
@ -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) 2015 " 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="Avalonia.Skia.iOS.TestApp" 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> |
|
||||
@ -1,18 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Text; |
|
||||
using Avalonia.Platform; |
|
||||
using Foundation; |
|
||||
using UIKit; |
|
||||
|
|
||||
namespace Avalonia.Skia |
|
||||
{ |
|
||||
partial class PlatformRenderInterface |
|
||||
{ |
|
||||
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces) |
|
||||
{ |
|
||||
return new WindowRenderTarget(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,21 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.Shared.PlatformSupport; |
||||
|
using Foundation; |
||||
|
using UIKit; |
||||
|
|
||||
|
namespace Avalonia |
||||
|
{ |
||||
|
public class AppBuilder : AppBuilderBase<AppBuilder> |
||||
|
{ |
||||
|
public AppBuilder() : base(new StandardRuntimePlatform(), |
||||
|
builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType().Assembly)) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
using Avalonia.Media; |
||||
|
using CoreGraphics; |
||||
|
using UIKit; |
||||
|
|
||||
|
namespace Avalonia.iOS |
||||
|
{ |
||||
|
class AvaloniaRootViewController : UIViewController |
||||
|
{ |
||||
|
private object _content; |
||||
|
private Color _statusBarColor = Colors.White; |
||||
|
|
||||
|
public object Content |
||||
|
{ |
||||
|
get { return _content; } |
||||
|
set |
||||
|
{ |
||||
|
_content = value; |
||||
|
var view = (View as AvaloniaView); |
||||
|
if (view != null) |
||||
|
view.Content = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Color StatusBarColor |
||||
|
{ |
||||
|
get { return _statusBarColor; } |
||||
|
set |
||||
|
{ |
||||
|
_statusBarColor = value; |
||||
|
var view = (View as AvaloniaView); |
||||
|
if (view != null) |
||||
|
view.BackgroundColor = value.ToUiColor(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void AutoFit() |
||||
|
{ |
||||
|
var needFlip = !UIDevice.CurrentDevice.CheckSystemVersion(8, 0) && |
||||
|
(InterfaceOrientation == UIInterfaceOrientation.LandscapeLeft |
||||
|
|| InterfaceOrientation == UIInterfaceOrientation.LandscapeRight); |
||||
|
// Bounds here (if top level) needs to correspond with the rendertarget
|
||||
|
var frame = UIScreen.MainScreen.Bounds; |
||||
|
if (needFlip) |
||||
|
frame = new CGRect(frame.Y, frame.X, frame.Height, frame.Width); |
||||
|
((AvaloniaView) View).Padding = |
||||
|
new Thickness(0, UIApplication.SharedApplication.StatusBarFrame.Size.Height, 0, 0); |
||||
|
View.Frame = frame; |
||||
|
} |
||||
|
|
||||
|
public override void LoadView() |
||||
|
{ |
||||
|
View = new AvaloniaView() {Content = Content, BackgroundColor = _statusBarColor.ToUiColor()}; |
||||
|
UIApplication.Notifications.ObserveDidChangeStatusBarOrientation(delegate { AutoFit(); }); |
||||
|
UIApplication.Notifications.ObserveDidChangeStatusBarFrame(delegate { AutoFit(); }); |
||||
|
AutoFit(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,249 +1,51 @@ |
|||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using System.Diagnostics; |
|
||||
using System.Linq; |
|
||||
using System.Reactive.Disposables; |
|
||||
using System.Text; |
using System.Text; |
||||
using CoreAnimation; |
using Avalonia.Controls.Embedding; |
||||
using CoreGraphics; |
using CoreGraphics; |
||||
using Foundation; |
|
||||
using Avalonia.Controls.Platform; |
|
||||
using Avalonia.Input; |
|
||||
using Avalonia.Input.Raw; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.Skia.iOS; |
|
||||
using UIKit; |
using UIKit; |
||||
using Avalonia.iOS.Specific; |
|
||||
using ObjCRuntime; |
|
||||
using Avalonia.Controls; |
|
||||
|
|
||||
namespace Avalonia.iOS |
namespace Avalonia.iOS |
||||
{ |
{ |
||||
[Adopts("UIKeyInput")] |
public class AvaloniaView : UIView |
||||
class AvaloniaView : SkiaView, IWindowImpl |
|
||||
{ |
{ |
||||
private readonly UIWindow _window; |
private EmbeddableImpl _impl; |
||||
private readonly UIViewController _controller; |
private EmbeddableControlRoot _root; |
||||
private IInputRoot _inputRoot; |
private Thickness _padding; |
||||
private readonly KeyboardEventsHelper<AvaloniaView> _keyboardHelper; |
|
||||
private Point _position; |
|
||||
|
|
||||
public AvaloniaView(UIWindow window, UIViewController controller) : base(onFrame => PlatformThreadingInterface.Instance.Render = onFrame) |
public Thickness Padding |
||||
{ |
{ |
||||
if (controller == null) throw new ArgumentNullException(nameof(controller)); |
get { return _padding; } |
||||
_window = window; |
|
||||
_controller = controller; |
|
||||
_keyboardHelper = new KeyboardEventsHelper<AvaloniaView>(this); |
|
||||
AutoresizingMask = UIViewAutoresizing.All; |
|
||||
AutoFit(); |
|
||||
UIApplication.Notifications.ObserveDidChangeStatusBarOrientation(delegate { AutoFit(); }); |
|
||||
UIApplication.Notifications.ObserveDidChangeStatusBarFrame(delegate { AutoFit(); }); |
|
||||
} |
|
||||
|
|
||||
[Export("hasText")] |
|
||||
bool HasText => _keyboardHelper.HasText(); |
|
||||
|
|
||||
[Export("insertText:")] |
|
||||
void InsertText(string text) => _keyboardHelper.InsertText(text); |
|
||||
|
|
||||
[Export("deleteBackward")] |
|
||||
void DeleteBackward() => _keyboardHelper.DeleteBackward(); |
|
||||
|
|
||||
public override bool CanBecomeFirstResponder => _keyboardHelper.CanBecomeFirstResponder(); |
|
||||
|
|
||||
void AutoFit() |
|
||||
{ |
|
||||
var needFlip = !UIDevice.CurrentDevice.CheckSystemVersion(8, 0) && |
|
||||
(_controller.InterfaceOrientation == UIInterfaceOrientation.LandscapeLeft |
|
||||
|| _controller.InterfaceOrientation == UIInterfaceOrientation.LandscapeRight); |
|
||||
|
|
||||
// Bounds here (if top level) needs to correspond with the rendertarget
|
|
||||
var frame = UIScreen.MainScreen.Bounds; |
|
||||
if (needFlip) |
|
||||
Frame = new CGRect(frame.Y, frame.X, frame.Height, frame.Width); |
|
||||
else |
|
||||
Frame = frame; |
|
||||
} |
|
||||
|
|
||||
public Action Activated { get; set; } |
|
||||
public Action Closed { get; set; } |
|
||||
public Action Deactivated { get; set; } |
|
||||
public Action<RawInputEventArgs> Input { get; set; } |
|
||||
public Action<Rect> Paint { get; set; } |
|
||||
public Action<Size> Resized { get; set; } |
|
||||
public Action<double> ScalingChanged { get; set; } |
|
||||
public Action<Point> PositionChanged { get; set; } |
|
||||
|
|
||||
public IPlatformHandle Handle => AvaloniaPlatformHandle; |
|
||||
|
|
||||
public double Scaling |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
// This does not appear to make any difference, but on iOS we
|
|
||||
// have Retina (x2) and we probably want this eventually
|
|
||||
return 1; //UIScreen.MainScreen.Scale;
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public WindowState WindowState |
|
||||
{ |
|
||||
get { return WindowState.Normal; } |
|
||||
set { } |
|
||||
} |
|
||||
|
|
||||
public override void LayoutSubviews() => Resized?.Invoke(ClientSize); |
|
||||
|
|
||||
public Size ClientSize |
|
||||
{ |
|
||||
get { return Bounds.Size.ToAvalonia(); } |
|
||||
set { Resized?.Invoke(ClientSize); } |
|
||||
} |
|
||||
|
|
||||
public void Activate() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
protected override void Draw() |
|
||||
{ |
|
||||
Paint?.Invoke(new Rect(new Point(), ClientSize)); |
|
||||
} |
|
||||
|
|
||||
public void Invalidate(Rect rect) => DrawOnNextFrame(); |
|
||||
|
|
||||
public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot; |
|
||||
|
|
||||
public Point PointToClient(Point point) => point; |
|
||||
|
|
||||
public Point PointToScreen(Point point) => point; |
|
||||
|
|
||||
public void SetCursor(IPlatformHandle cursor) |
|
||||
{ |
|
||||
//Not supported
|
|
||||
} |
|
||||
|
|
||||
public void Show() |
|
||||
{ |
|
||||
_keyboardHelper.ActivateAutoShowKeybord(); |
|
||||
} |
|
||||
|
|
||||
public void BeginMoveDrag() |
|
||||
{ |
|
||||
//Not supported
|
|
||||
} |
|
||||
|
|
||||
public void BeginResizeDrag(WindowEdge edge) |
|
||||
{ |
|
||||
//Not supported
|
|
||||
} |
|
||||
|
|
||||
public Point Position |
|
||||
{ |
|
||||
get { return _position; } |
|
||||
set |
set |
||||
{ |
{ |
||||
_position = value; |
_padding = value; |
||||
PositionChanged?.Invoke(_position); |
SetNeedsLayout(); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
public Size MaxClientSize => Bounds.Size.ToAvalonia(); |
public AvaloniaView() |
||||
|
|
||||
public IEnumerable<object> Surfaces => new object[] { this }; |
|
||||
|
|
||||
public void SetTitle(string title) |
|
||||
{ |
|
||||
//Not supported
|
|
||||
} |
|
||||
|
|
||||
public IDisposable ShowDialog() |
|
||||
{ |
{ |
||||
//Not supported
|
|
||||
return Disposable.Empty; |
_impl = new EmbeddableImpl(); |
||||
} |
AddSubview(_impl); |
||||
|
BackgroundColor = UIColor.White; |
||||
public void Hide() |
AutoresizingMask = UIViewAutoresizing.All; |
||||
{ |
_root = new EmbeddableControlRoot(_impl); |
||||
//Not supported
|
_root.Prepare(); |
||||
} |
|
||||
|
|
||||
public void SetSystemDecorations(bool enabled) |
|
||||
{ |
|
||||
//Not supported
|
|
||||
} |
|
||||
|
|
||||
public override void TouchesEnded(NSSet touches, UIEvent evt) |
|
||||
{ |
|
||||
var touch = touches.AnyObject as UITouch; |
|
||||
if (touch != null) |
|
||||
{ |
|
||||
var location = touch.LocationInView(this).ToAvalonia(); |
|
||||
|
|
||||
Input?.Invoke(new RawMouseEventArgs( |
|
||||
iOSPlatform.MouseDevice, |
|
||||
(uint)touch.Timestamp, |
|
||||
_inputRoot, |
|
||||
RawMouseEventType.LeftButtonUp, |
|
||||
location, |
|
||||
InputModifiers.None)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
Point _touchLastPoint; |
|
||||
public override void TouchesBegan(NSSet touches, UIEvent evt) |
|
||||
{ |
|
||||
var touch = touches.AnyObject as UITouch; |
|
||||
if (touch != null) |
|
||||
{ |
|
||||
var location = touch.LocationInView(this).ToAvalonia(); |
|
||||
_touchLastPoint = location; |
|
||||
Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot, |
|
||||
RawMouseEventType.Move, location, InputModifiers.None)); |
|
||||
|
|
||||
Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot, |
|
||||
RawMouseEventType.LeftButtonDown, location, InputModifiers.None)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public override void TouchesMoved(NSSet touches, UIEvent evt) |
|
||||
{ |
|
||||
var touch = touches.AnyObject as UITouch; |
|
||||
if (touch != null) |
|
||||
{ |
|
||||
var location = touch.LocationInView(this).ToAvalonia(); |
|
||||
if (iOSPlatform.MouseDevice.Captured != null) |
|
||||
Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot, |
|
||||
RawMouseEventType.Move, location, InputModifiers.LeftMouseButton)); |
|
||||
else |
|
||||
{ |
|
||||
//magic number based on test - correction of 0.02 is working perfect
|
|
||||
double correction = 0.02; |
|
||||
|
|
||||
Input?.Invoke(new RawMouseWheelEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, |
|
||||
_inputRoot, location, (location - _touchLastPoint) * correction, InputModifiers.LeftMouseButton)); |
|
||||
} |
|
||||
_touchLastPoint = location; |
|
||||
} |
|
||||
} |
} |
||||
|
|
||||
public void SetIcon(IWindowIconImpl icon) |
public override void LayoutSubviews() |
||||
{ |
{ |
||||
|
_impl.Frame = new CGRect(Padding.Left, Padding.Top, |
||||
|
Frame.Width - Padding.Left - Padding.Right, |
||||
|
Frame.Height - Padding.Top - Padding.Bottom); |
||||
} |
} |
||||
} |
|
||||
|
|
||||
class AvaloniaViewController : UIViewController |
|
||||
{ |
|
||||
public AvaloniaView AvaloniaView { get; } |
|
||||
|
|
||||
public AvaloniaViewController(UIWindow window) |
|
||||
{ |
|
||||
AvaloniaView = new AvaloniaView(window, this); |
|
||||
} |
|
||||
|
|
||||
public override void LoadView() |
public object Content |
||||
{ |
{ |
||||
View = AvaloniaView; |
get { return _root.Content; } |
||||
|
set { _root.Content = value; } |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,31 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using Avalonia.Media; |
||||
|
using Foundation; |
||||
|
using UIKit; |
||||
|
|
||||
|
namespace Avalonia.iOS |
||||
|
{ |
||||
|
public sealed class AvaloniaWindow : UIWindow |
||||
|
{ |
||||
|
readonly AvaloniaRootViewController _controller = new AvaloniaRootViewController(); |
||||
|
public object Content |
||||
|
{ |
||||
|
get { return _controller.Content; } |
||||
|
set { _controller.Content = value; } |
||||
|
} |
||||
|
|
||||
|
public AvaloniaWindow() : base(UIScreen.MainScreen.Bounds) |
||||
|
{ |
||||
|
RootViewController = _controller; |
||||
|
} |
||||
|
|
||||
|
public Color StatusBarColor |
||||
|
{ |
||||
|
get { return _controller.StatusBarColor; } |
||||
|
set { _controller.StatusBarColor = value; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using Avalonia.Rendering; |
||||
|
using CoreAnimation; |
||||
|
using Foundation; |
||||
|
using UIKit; |
||||
|
|
||||
|
namespace Avalonia.iOS |
||||
|
{ |
||||
|
class DisplayLinkRenderLoop : IRenderLoop |
||||
|
{ |
||||
|
public event EventHandler<EventArgs> Tick; |
||||
|
private CADisplayLink _link; |
||||
|
public DisplayLinkRenderLoop() |
||||
|
{ |
||||
|
|
||||
|
_link = CADisplayLink.Create(OnFrame); |
||||
|
_link.AddToRunLoop(NSRunLoop.Main, NSRunLoop.NSDefaultRunLoopMode); |
||||
|
} |
||||
|
|
||||
|
private void OnFrame() |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
Tick?.Invoke(this, new EventArgs()); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
//TODO: log
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Reactive.Disposables; |
||||
|
using System.Text; |
||||
|
using Avalonia.Platform; |
||||
|
using UIKit; |
||||
|
|
||||
|
namespace Avalonia.iOS |
||||
|
{ |
||||
|
class EmbeddableImpl : TopLevelImpl, IEmbeddableWindowImpl |
||||
|
{ |
||||
|
public void SetTitle(string title) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public IDisposable ShowDialog() |
||||
|
{ |
||||
|
return Disposable.Empty; |
||||
|
} |
||||
|
|
||||
|
public void SetSystemDecorations(bool enabled) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public event Action LostFocus; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using System.Text; |
||||
|
using Avalonia.Controls.Platform.Surfaces; |
||||
|
using CoreGraphics; |
||||
|
using UIKit; |
||||
|
|
||||
|
namespace Avalonia.iOS |
||||
|
{ |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// This is a bit weird, but CG doesn't provide proper bitmap
|
||||
|
/// with lockable bits, but can create one from data pointer
|
||||
|
/// So we are using our own buffer here.
|
||||
|
/// </summary>
|
||||
|
class EmulatedFramebuffer : ILockedFramebuffer |
||||
|
{ |
||||
|
|
||||
|
public EmulatedFramebuffer(UIView view) |
||||
|
{ |
||||
|
var factor = (int) UIScreen.MainScreen.Scale; |
||||
|
var frame = view.Frame; |
||||
|
Width = (int) frame.Width * factor; |
||||
|
Height = (int) frame.Height * factor; |
||||
|
RowBytes = Width * 4; |
||||
|
Dpi = new Size(96, 96) * factor; |
||||
|
Format = PixelFormat.Rgba8888; |
||||
|
Address = Marshal.AllocHGlobal(Height * RowBytes); |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
if (Address == IntPtr.Zero) |
||||
|
return; |
||||
|
var nfo = (int) CGBitmapFlags.ByteOrder32Big | (int) CGImageAlphaInfo.PremultipliedLast; |
||||
|
using (var colorSpace = CGColorSpace.CreateDeviceRGB()) |
||||
|
using (var bContext = new CGBitmapContext(Address, Width, Height, 8, Width * 4, |
||||
|
colorSpace, (CGImageAlphaInfo) nfo)) |
||||
|
using (var image = bContext.ToImage()) |
||||
|
using (var context = UIGraphics.GetCurrentContext()) |
||||
|
{ |
||||
|
// flip the image for CGContext.DrawImage
|
||||
|
context.TranslateCTM(0, Height); |
||||
|
context.ScaleCTM(1, -1); |
||||
|
context.DrawImage(new CGRect(0, 0, Width, Height), image); |
||||
|
} |
||||
|
Marshal.FreeHGlobal(Address); |
||||
|
Address = IntPtr.Zero; |
||||
|
} |
||||
|
|
||||
|
public IntPtr Address { get; private set; } |
||||
|
public int Width { get; } |
||||
|
public int Height { get; } |
||||
|
public int RowBytes { get; } |
||||
|
public Size Dpi { get; } |
||||
|
public PixelFormat Format { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,192 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Diagnostics; |
||||
|
using System.Linq; |
||||
|
using System.Reactive.Disposables; |
||||
|
using System.Text; |
||||
|
using CoreAnimation; |
||||
|
using CoreGraphics; |
||||
|
using Foundation; |
||||
|
using Avalonia.Controls.Platform; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Input.Raw; |
||||
|
using Avalonia.Media; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.Skia.iOS; |
||||
|
using UIKit; |
||||
|
using Avalonia.iOS.Specific; |
||||
|
using ObjCRuntime; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Controls.Platform.Surfaces; |
||||
|
|
||||
|
namespace Avalonia.iOS |
||||
|
{ |
||||
|
[Adopts("UIKeyInput")] |
||||
|
class TopLevelImpl : UIView, ITopLevelImpl, IFramebufferPlatformSurface |
||||
|
{ |
||||
|
private IInputRoot _inputRoot; |
||||
|
private readonly KeyboardEventsHelper<TopLevelImpl> _keyboardHelper; |
||||
|
private Point _position; |
||||
|
|
||||
|
public TopLevelImpl() |
||||
|
{ |
||||
|
_keyboardHelper = new KeyboardEventsHelper<TopLevelImpl>(this); |
||||
|
AutoresizingMask = UIViewAutoresizing.All; |
||||
|
} |
||||
|
|
||||
|
[Export("hasText")] |
||||
|
public bool HasText => _keyboardHelper.HasText(); |
||||
|
|
||||
|
[Export("insertText:")] |
||||
|
public void InsertText(string text) => _keyboardHelper.InsertText(text); |
||||
|
|
||||
|
[Export("deleteBackward")] |
||||
|
public void DeleteBackward() => _keyboardHelper.DeleteBackward(); |
||||
|
|
||||
|
public override bool CanBecomeFirstResponder => _keyboardHelper.CanBecomeFirstResponder(); |
||||
|
|
||||
|
public Action Activated { get; set; } |
||||
|
public Action Closed { get; set; } |
||||
|
public Action Deactivated { get; set; } |
||||
|
public Action<RawInputEventArgs> Input { get; set; } |
||||
|
public Action<Rect> Paint { get; set; } |
||||
|
public Action<Size> Resized { get; set; } |
||||
|
public Action<double> ScalingChanged { get; set; } |
||||
|
public Action<Point> PositionChanged { get; set; } |
||||
|
|
||||
|
public IPlatformHandle Handle => null; |
||||
|
|
||||
|
public double Scaling => UIScreen.MainScreen.Scale; |
||||
|
|
||||
|
public WindowState WindowState |
||||
|
{ |
||||
|
get { return WindowState.Normal; } |
||||
|
set { } |
||||
|
} |
||||
|
|
||||
|
public override void LayoutSubviews() => Resized?.Invoke(ClientSize); |
||||
|
|
||||
|
public Size ClientSize |
||||
|
{ |
||||
|
get { return Bounds.Size.ToAvalonia(); } |
||||
|
set { InvokeOnMainThread(() => Resized?.Invoke(ClientSize)); } |
||||
|
} |
||||
|
|
||||
|
public void Activate() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public override void Draw(CGRect rect) |
||||
|
{ |
||||
|
Paint?.Invoke(new Rect(rect.X, rect.Y, rect.Width, rect.Height)); |
||||
|
} |
||||
|
|
||||
|
public void Invalidate(Rect rect) => SetNeedsDisplay(); |
||||
|
|
||||
|
public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot; |
||||
|
|
||||
|
public Point PointToClient(Point point) => point; |
||||
|
|
||||
|
public Point PointToScreen(Point point) => point; |
||||
|
|
||||
|
public void SetCursor(IPlatformHandle cursor) |
||||
|
{ |
||||
|
//Not supported
|
||||
|
} |
||||
|
|
||||
|
public void Show() |
||||
|
{ |
||||
|
_keyboardHelper.ActivateAutoShowKeybord(); |
||||
|
} |
||||
|
|
||||
|
public void BeginMoveDrag() |
||||
|
{ |
||||
|
//Not supported
|
||||
|
} |
||||
|
|
||||
|
public void BeginResizeDrag(WindowEdge edge) |
||||
|
{ |
||||
|
//Not supported
|
||||
|
} |
||||
|
|
||||
|
public Point Position |
||||
|
{ |
||||
|
get { return _position; } |
||||
|
set |
||||
|
{ |
||||
|
_position = value; |
||||
|
PositionChanged?.Invoke(_position); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Size MaxClientSize => Bounds.Size.ToAvalonia(); |
||||
|
|
||||
|
public IEnumerable<object> Surfaces => new object[] { this }; |
||||
|
|
||||
|
|
||||
|
public void Hide() |
||||
|
{ |
||||
|
//Not supported
|
||||
|
} |
||||
|
|
||||
|
public override void TouchesEnded(NSSet touches, UIEvent evt) |
||||
|
{ |
||||
|
var touch = touches.AnyObject as UITouch; |
||||
|
if (touch != null) |
||||
|
{ |
||||
|
var location = touch.LocationInView(this).ToAvalonia(); |
||||
|
|
||||
|
Input?.Invoke(new RawMouseEventArgs( |
||||
|
iOSPlatform.MouseDevice, |
||||
|
(uint)touch.Timestamp, |
||||
|
_inputRoot, |
||||
|
RawMouseEventType.LeftButtonUp, |
||||
|
location, |
||||
|
InputModifiers.None)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Point _touchLastPoint; |
||||
|
public override void TouchesBegan(NSSet touches, UIEvent evt) |
||||
|
{ |
||||
|
var touch = touches.AnyObject as UITouch; |
||||
|
if (touch != null) |
||||
|
{ |
||||
|
var location = touch.LocationInView(this).ToAvalonia(); |
||||
|
_touchLastPoint = location; |
||||
|
Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot, |
||||
|
RawMouseEventType.Move, location, InputModifiers.None)); |
||||
|
|
||||
|
Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot, |
||||
|
RawMouseEventType.LeftButtonDown, location, InputModifiers.None)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void TouchesMoved(NSSet touches, UIEvent evt) |
||||
|
{ |
||||
|
var touch = touches.AnyObject as UITouch; |
||||
|
if (touch != null) |
||||
|
{ |
||||
|
var location = touch.LocationInView(this).ToAvalonia(); |
||||
|
if (iOSPlatform.MouseDevice.Captured != null) |
||||
|
Input?.Invoke(new RawMouseEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, _inputRoot, |
||||
|
RawMouseEventType.Move, location, InputModifiers.LeftMouseButton)); |
||||
|
else |
||||
|
{ |
||||
|
//magic number based on test - correction of 0.02 is working perfect
|
||||
|
double correction = 0.02; |
||||
|
|
||||
|
Input?.Invoke(new RawMouseWheelEventArgs(iOSPlatform.MouseDevice, (uint)touch.Timestamp, |
||||
|
_inputRoot, location, (location - _touchLastPoint) * correction, InputModifiers.LeftMouseButton)); |
||||
|
} |
||||
|
_touchLastPoint = location; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void SetIcon(IWindowIconImpl icon) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public ILockedFramebuffer Lock() => new EmulatedFramebuffer(this); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
<Application xmlns="https://github.com/avaloniaui"> |
||||
|
<Application.Styles> |
||||
|
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/> |
||||
|
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/> |
||||
|
</Application.Styles> |
||||
|
</Application> |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using Avalonia.Markup.Xaml; |
||||
|
using Foundation; |
||||
|
using UIKit; |
||||
|
|
||||
|
namespace Avalonia.iOSTestApplication |
||||
|
{ |
||||
|
public class SimpleApp : Avalonia.Application |
||||
|
{ |
||||
|
public override void Initialize() |
||||
|
{ |
||||
|
//Enforce load
|
||||
|
new Avalonia.Themes.Default.DefaultTheme(); |
||||
|
AvaloniaXamlLoader.Load(this); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Media; |
||||
|
|
||||
|
namespace Avalonia.iOSTestApplication |
||||
|
{ |
||||
|
class SimpleControl : ContentControl |
||||
|
{ |
||||
|
public SimpleControl() |
||||
|
{ |
||||
|
Content = new Button() {Content = "WAT"}; |
||||
|
MinWidth = 100; |
||||
|
MinHeight = 200; |
||||
|
Background = Brushes.CadetBlue; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue