├── .gitattributes ├── .gitignore ├── FluidSharp.Maui.sln ├── FluidSharp.Video.Recorder ├── FluidSharp.Video.Recorder.csproj └── VideoRecorderLayoutSurface.cs ├── FluidSharp.Views.Forms ├── FluidSharp.Views.Forms.Android │ ├── FluidSharp.Views.Forms.Android.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Resources │ │ └── Resource.designer.cs │ └── TouchEffect.cs ├── FluidSharp.Views.Forms.UWP │ ├── FluidSharp.Views.Forms.UWP.csproj │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── SkiaSharp.FlowUI.Views.Forms.UWP.rd.xml │ └── TouchEffect.cs └── FluidSharp.Views.Forms.iOS │ ├── FluidSharp.Views.Forms.iOS.csproj │ ├── Properties │ └── AssemblyInfo.cs │ ├── TouchEffect.cs │ └── TouchRecognizer.cs ├── FluidSharp.Views ├── FluidSharp.Views.Android │ ├── AndroidFluidWidgetView.cs │ ├── FluidSharp.Views.Android.csproj │ ├── FluidSharp.Views.Android.nuspec │ ├── FluidUIActivity.cs │ ├── FluidWidgetCanvasView.cs │ ├── FluidWidgetGLView.cs │ ├── License.txt │ ├── NativeViewManager.cs │ ├── NativeViews │ │ ├── FontExtensions.cs │ │ ├── KeyboardExtensions.cs │ │ ├── NativeTextboxImpl.cs │ │ └── NativeViewExtensions.cs │ ├── Resources │ │ ├── AboutResources.txt │ │ ├── Resource.designer.cs │ │ └── values │ │ │ └── strings.xml │ ├── SkiaView.cs │ ├── SkiaViews.cs │ └── nuget instructions.txt ├── FluidSharp.Views.Forms.UWP │ ├── FluidSharp.Views.Forms.UWP.csproj │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── SkiaSharp.FlowUI.Views.Forms.UWP.rd.xml │ └── TouchEffect.cs ├── FluidSharp.Views.Forms.iOS │ ├── FluidSharp.Views.Forms.iOS.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── TouchEffect.cs │ └── TouchRecognizer.cs ├── FluidSharp.Views.Forms │ ├── FluidSharp.Views.Forms.csproj │ ├── FluidWidgetView2.cs │ ├── NativeViewManager.cs │ ├── NativeViews │ │ └── NativeTextboxImpl.cs │ ├── SkiaView.cs │ └── XamarinExtensions.cs ├── FluidSharp.Views.Maui │ ├── FluidSharp.Views.Maui.csproj │ ├── License.txt │ └── Platforms │ │ ├── Android │ │ ├── AndroidFluidWidgetView.cs │ │ ├── FluidSharp.Views.Android.nuspec │ │ ├── FluidUIActivity.cs │ │ ├── FluidWidgetCanvasView.cs │ │ ├── FluidWidgetGLView.cs │ │ ├── License.txt │ │ ├── NativeViewManager.cs │ │ ├── NativeViews │ │ │ ├── FontExtensions.cs │ │ │ ├── KeyboardExtensions.cs │ │ │ ├── NativeTextboxImpl.cs │ │ │ └── NativeViewExtensions.cs │ │ ├── Resources │ │ │ └── values │ │ │ │ └── strings.xml │ │ ├── SkiaView.cs │ │ ├── SkiaViews.cs │ │ └── nuget instructions.txt │ │ └── iOS │ │ ├── FluidSharp.Views.iOS.nuspec │ │ ├── FluidUICanvasViewController.cs │ │ ├── FluidUIGLViewController.cs │ │ ├── FluidWidgetCanvasView.cs │ │ ├── FluidWidgetGLView.cs │ │ ├── License.txt │ │ ├── NativeViewManager.cs │ │ ├── NativeViews │ │ ├── INativeTextboxImpl.cs │ │ ├── NativeMultiLineTextboxImpl.cs │ │ ├── NativeSingleLineTextboxImpl.cs │ │ └── NativeViewExtensions.cs │ │ ├── Services │ │ └── KeyboardTracker.cs │ │ ├── SkiaView.cs │ │ ├── SkiaViews.cs │ │ ├── TouchRecognizer.cs │ │ └── nuget instructions.txt ├── FluidSharp.Views.Shared │ └── FluidWidgetView.cs ├── FluidSharp.Views.WindowsForms.Core │ ├── FluidSharp.Views.WindowsForms.Core.csproj │ ├── FluidWidgetView.resx │ ├── License.txt │ ├── NativeViews │ │ ├── NativeTextboxImpl.cs │ │ └── NativeViewExtensions.cs │ └── SkiaView.resx ├── FluidSharp.Views.WindowsForms │ ├── FluidSharp.Views.WindowsForms.csproj │ ├── NativeViewManager.cs │ ├── NativeViews │ │ └── NativeTextboxImpl.cs │ ├── OpenTK.dll.config │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SkiaView.cs │ ├── SkiaView.resx │ ├── app.config │ └── packages.config ├── FluidSharp.Views.iOS │ ├── FluidSharp.Views.iOS.csproj │ ├── FluidSharp.Views.iOS.nuspec │ ├── FluidUICanvasViewController.cs │ ├── FluidUIGLViewController.cs │ ├── FluidWidgetCanvasView.cs │ ├── FluidWidgetGLView.cs │ ├── License.txt │ ├── NativeViewManager.cs │ ├── NativeViews │ │ ├── INativeTextboxImpl.cs │ │ ├── NativeMultiLineTextboxImpl.cs │ │ ├── NativeSingleLineTextboxImpl.cs │ │ └── NativeViewExtensions.cs │ ├── Services │ │ └── KeyboardTracker.cs │ ├── SkiaView.cs │ ├── SkiaViews.cs │ ├── TouchRecognizer.cs │ └── nuget instructions.txt ├── Ref │ └── SkiaSharp.Views.Android.dll └── SkiaSharp.Views.Forms │ ├── SkiaSharp.Views.Forms.Android │ ├── SKCanvasViewRenderer.cs │ ├── SKGLViewRenderer.cs │ ├── SKImageSourceHandler.cs │ ├── SKTouchHandler.cs │ └── SkiaSharp.Views.Forms.Android.csproj │ ├── SkiaSharp.Views.Forms.Native.Shared │ ├── Registrar.cs │ ├── SKCanvasViewRendererBase.cs │ └── SKGLViewRendererBase.cs │ ├── SkiaSharp.Views.Forms.Shared │ ├── Extensions.cs │ ├── RendererTypes.cs │ ├── SKCanvasView.cs │ ├── SKGLView.cs │ ├── SKImageSource.cs │ ├── SKPaintGLSurfaceEventArgs.cs │ ├── SKPaintSurfaceEventArgs.cs │ └── SKTouchEventArgs.cs │ ├── SkiaSharp.Views.Forms.iOS │ ├── SKCanvasViewRenderer.cs │ ├── SKGLViewRenderer.cs │ ├── SKImageSourceHandler.cs │ ├── SKTouchHandler.cs │ └── SkiaSharp.Views.Forms.iOS.csproj │ ├── SkiaSharp.Views.Forms.sln │ └── SkiaSharp.Views.Forms │ ├── SKCanvasViewRenderer.cs │ ├── SKGLViewRenderer.cs │ ├── SkiaSharp.Views.Forms.csproj │ └── nuget │ └── build │ └── net462 │ └── SkiaSharp.Views.Forms.targets ├── FluidSharp.sln ├── FluidSharp ├── Animations │ ├── AlignAnimation.cs │ ├── Animation.cs │ ├── DynamicAnimatedWidget.cs │ ├── DynamicAnimation.cs │ ├── DynamicFrame.cs │ ├── Easing.cs │ ├── Frame.cs │ ├── IAnimation.cs │ ├── OptionalAnimatedWidget.cs │ ├── StandardAnimation.cs │ ├── State.cs │ └── StateAnimation.cs ├── Engine │ ├── EngineException.cs │ ├── FluidWidgetViewImplementation.cs │ ├── MakeWidgetException.cs │ ├── MeasureException.cs │ ├── PaintException.cs │ ├── PerformanceTracker.cs │ └── TapHandlerException.cs ├── FluidSharp.csproj ├── Interfaces │ ├── IBackgroundColorSource.cs │ ├── IFluidWidgetView.cs │ ├── ISkiaView.cs │ └── IWidgetSource.cs ├── Interop │ ├── INativeView.cs │ ├── INativeViewManager.cs │ ├── NativeViewManagerBase.cs │ └── ScaledNativeViewManager.cs ├── Layouts │ ├── Device.cs │ ├── LayoutSize.cs │ ├── LayoutSurface.cs │ ├── Margins.cs │ ├── MeasureCache.cs │ ├── PlatformStyle.cs │ └── SKRectExtensions.cs ├── License.txt ├── Navigation │ ├── HeroPageTransition.cs │ ├── IPage.cs │ ├── IPageTransition.cs │ ├── NavigationContainer.cs │ ├── NavigationTop.cs │ ├── NavigationTransitionState.cs │ ├── OverlayPageTransition.cs │ ├── PopupPageTransition.cs │ └── PushPageTransition.cs ├── Paint │ ├── FluidSharpStyle.cs │ ├── Images │ │ ├── FileImageSource.cs │ │ ├── ImageCache.cs │ │ ├── ImageSource.cs │ │ ├── ResourceImageSource.cs │ │ └── ResourcePictureSource.cs │ ├── PaintCache.cs │ ├── PaintSurfaceEventArgs.cs │ ├── SKPaintExtensions.cs │ └── ScreenshotLayoutSurface.cs ├── SkiaSharp.FlowUI.sln ├── State │ ├── CarouselState.cs │ ├── LastTapped.cs │ ├── OptionBarState.cs │ ├── ScrollState.cs │ ├── SlideOverState.cs │ ├── SliderState.cs │ ├── SlidingCellState.cs │ ├── SwitchState.cs │ ├── TransitionState.cs │ ├── TypedContext.cs │ └── VisualState.cs ├── Touch │ ├── EditTarget.cs │ ├── GestureArena.cs │ ├── HitTestHit.cs │ ├── HitTestLayoutSurface.cs │ ├── HitTestStop.cs │ ├── TouchActionEventArgs.cs │ ├── TouchActionType.cs │ └── TouchTarget.cs └── Widgets │ ├── Align.cs │ ├── Animations │ ├── AnimatedRectangle.cs │ ├── AnimatedWidgets.cs │ ├── FadeInElement.cs │ ├── FadeInPicture.cs │ ├── HeightTransition.cs │ ├── IncrementalAnimationContainer.cs │ ├── OriginTranslationWidget.cs │ ├── SlideInAnimation.cs │ └── SlideUpAnimation.cs │ ├── AutoCacheWidget.cs │ ├── Blur.cs │ ├── Caching │ ├── CachedWidget.cs │ └── WidgetCache.cs │ ├── Carousel.cs │ ├── Center.cs │ ├── CenterHorizontal.cs │ ├── CenterRotate.cs │ ├── Checkbox.cs │ ├── Circle.cs │ ├── Column.cs │ ├── ColumnPool.cs │ ├── Container.cs │ ├── CrossPlatform │ ├── Button.cs │ ├── CrossButton.cs │ ├── DeletableCell.cs │ ├── SelectableButtonWidget.cs │ └── ShortList.cs │ ├── Cupertino │ └── CupertinoApp.cs │ ├── Debugging │ ├── FrameCounter.cs │ └── PerformanceChart.cs │ ├── Field.cs │ ├── FlatButton.cs │ ├── Flow.cs │ ├── GestureDetector.cs │ ├── Hero.cs │ ├── HeroTransition.cs │ ├── HorizontalAlignment.cs │ ├── HorizontalGradient.cs │ ├── Image.cs │ ├── Layout.cs │ ├── LayoutCell.cs │ ├── LongList.cs │ ├── LongListContents.cs │ ├── Material │ └── InkWell.cs │ ├── Members │ └── FixableList.cs │ ├── Native │ ├── INativeViewImpl.cs │ ├── Keyboard.cs │ ├── NativeTextboxWidget.cs │ ├── NativeViewWidget.cs │ ├── ReturnType.cs │ └── ReturnTypeInfo.cs │ ├── Navigation │ └── SlideBackNavigation.cs │ ├── NearAndFar.cs │ ├── NearAndFarWithMargin.cs │ ├── Opacity.cs │ ├── OptionBar.cs │ ├── OptionalWidget.cs │ ├── OverscrollBehavior.cs │ ├── Picture.cs │ ├── ProgressIndicator.cs │ ├── Rectangle.cs │ ├── RelativeMargin.cs │ ├── RichText.cs │ ├── RichText │ ├── CircleSpan.cs │ └── PictureSpan.cs │ ├── RoundedRectangle.cs │ ├── Row.cs │ ├── Scale.cs │ ├── ScaleMode.cs │ ├── Scrollable.cs │ ├── Shape.cs │ ├── ShapeAsFontGlyph.cs │ ├── ShapeBidirectional.cs │ ├── Slidable.cs │ ├── SlideOverContainer.cs │ ├── SlideTransition.cs │ ├── Slider.cs │ ├── SlidingCell.cs │ ├── Spacing.cs │ ├── SplitContainerBottom.cs │ ├── SplitContainerFar.cs │ ├── SplitContainerNear.cs │ ├── Stateful │ └── TwoStateWidget.cs │ ├── StatefulSlideTransition.cs │ ├── Text.cs │ ├── Translate.cs │ ├── VerticalAlignment.cs │ ├── VerticalGradient.cs │ └── Widget.cs ├── README.md └── Samples ├── FluidSharp.Samples.All ├── Basic │ ├── HelloWorld.cs │ └── Rectangle.cs ├── FluidSharp.Samples.All.csproj ├── LayoutSamples │ ├── AlignSample.cs │ ├── FlowSample.cs │ ├── LayoutSample.cs │ └── ShapesSample.cs ├── Sample.cs └── SampleApp.cs ├── FluidSharp.Samples.Screenshots ├── FluidSharp.Samples.Screenshots.csproj └── Program.cs ├── FluidSharp.Samples.WindowsFormsCore ├── FluidSharp.Samples.WindowsFormsCore.csproj ├── Form1.Designer.cs ├── Form1.cs ├── Form1.resx └── Program.cs ├── FluidSharp.Samples.iOS ├── AppDelegate.cs ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon1024.png │ │ ├── Icon120.png │ │ ├── Icon152.png │ │ ├── Icon167.png │ │ ├── Icon180.png │ │ ├── Icon20.png │ │ ├── Icon29.png │ │ ├── Icon40.png │ │ ├── Icon58.png │ │ ├── Icon60.png │ │ ├── Icon76.png │ │ ├── Icon80.png │ │ └── Icon87.png ├── Entitlements.plist ├── FluidSharp.Samples.iOS.csproj ├── Info.plist ├── LaunchScreen.storyboard ├── Main.cs ├── Properties │ └── AssemblyInfo.cs ├── Resources │ └── LaunchScreen.xib └── SceneDelegate.cs ├── FluidSharp.Samples.sln └── Screenshots ├── Align.png ├── Background Color.png ├── Flow.png ├── Hello world.png ├── Layout.png └── Shapes.png /FluidSharp.Video.Recorder/FluidSharp.Video.Recorder.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | 6 | 7 | 8 | true 9 | 10 | 11 | 12 | true 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /FluidSharp.Views.Forms/FluidSharp.Views.Forms.Android/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using Android.App; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("FluidSharp.Views.Forms.Android")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("FluidSharp.Views.Forms.Android")] 14 | [assembly: AssemblyCopyright("Copyright © 2018")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: ComVisible(false)] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Build and Revision Numbers 27 | // by using the '*' as shown below: 28 | // [assembly: AssemblyVersion("1.0.*")] 29 | [assembly: AssemblyVersion("1.0.0.0")] 30 | [assembly: AssemblyFileVersion("1.0.0.0")] 31 | -------------------------------------------------------------------------------- /FluidSharp.Views.Forms/FluidSharp.Views.Forms.UWP/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FluidSharp.Views.Forms.UWP")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FluidSharp.Views.Forms.UWP")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /FluidSharp.Views.Forms/FluidSharp.Views.Forms.UWP/Properties/SkiaSharp.FlowUI.Views.Forms.UWP.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /FluidSharp.Views.Forms/FluidSharp.Views.Forms.iOS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FluidSharp.Views.Forms.iOS")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FluidSharp.Views.Forms.iOS")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("50c7b8c9-e664-45af-b88e-0c9b8b9c1be1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FluidSharp.Views.Forms/FluidSharp.Views.Forms.iOS/TouchEffect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | using Xamarin.Forms; 5 | using Xamarin.Forms.Platform.iOS; 6 | 7 | using UIKit; 8 | using TouchTracking = FluidSharp.Views.Forms; 9 | 10 | 11 | [assembly: ResolutionGroupName("FluidSharp")] 12 | [assembly: ExportEffect(typeof(FluidSharp.iOS.TouchEffect), "TouchEffect")] 13 | namespace FluidSharp.iOS 14 | { 15 | public class TouchEffect : PlatformEffect 16 | { 17 | UIView view; 18 | TouchRecognizer touchRecognizer; 19 | 20 | protected override void OnAttached() 21 | { 22 | // Get the iOS UIView corresponding to the Element that the effect is attached to 23 | view = Control == null ? Container : Control; 24 | 25 | // Get access to the TouchEffect class in the .NET Standard library 26 | TouchTracking.TouchEffect effect = (TouchTracking.TouchEffect)Element.Effects.FirstOrDefault(e => e is TouchTracking.TouchEffect); 27 | 28 | if (effect != null && view != null) 29 | { 30 | // Create a TouchRecognizer for this UIView 31 | touchRecognizer = new TouchRecognizer(Element, view, effect); 32 | view.AddGestureRecognizer(touchRecognizer); 33 | } 34 | } 35 | 36 | protected override void OnDetached() 37 | { 38 | if (touchRecognizer != null) 39 | { 40 | // Clean up the TouchRecognizer object 41 | touchRecognizer.Detach(); 42 | 43 | // Remove the TouchRecognizer from the UIView 44 | view.RemoveGestureRecognizer(touchRecognizer); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Android/AndroidFluidWidgetView.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content; 3 | using Android.OS; 4 | using Android.Runtime; 5 | using Android.Views; 6 | using Android.Widget; 7 | using FluidSharp.State; 8 | using SkiaSharp; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | 14 | namespace FluidSharp.Views.Android 15 | { 16 | public abstract class AndroidFluidWidgetView : RelativeLayout 17 | { 18 | 19 | public abstract SKSize PlatformScale { get; } 20 | public abstract VisualState VisualState { get; } 21 | 22 | protected AndroidFluidWidgetView(Context context) : base(context) 23 | { 24 | } 25 | 26 | public void AddOnMainThread(View childview) 27 | { 28 | 29 | ((Activity)Context).RunOnUiThread(() => 30 | { 31 | if (childview.Parent != null) 32 | ((ViewGroup)childview.Parent).RemoveView(childview); 33 | AddView(childview); 34 | }); 35 | 36 | } 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Android/FluidSharp.Views.Android.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | FluidSharp.Views.Android 5 | 1.3.5-alpha 6 | $title$ 7 | Wouter Steenbergen 8 | My Daily Bits LLC 9 | true 10 | License.txt 11 | FluidSharp is a high performance mobile first multi-platform UI layout framework based on Skia. 12 | Initial release 13 | 2022-2023 Wouter Steenbergen 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Android/License.txt: -------------------------------------------------------------------------------- 1 |  Copyright 2022-2024 Wouter Steenbergen 2 | 3 | Licensed for evaluation ("internal development") only. 4 | Not licenced to be distributed as part of a commercially available product. 5 | 6 | You may not use this file except in compliance with the License. 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Android/NativeViews/NativeViewExtensions.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using SkiaSharp.TextBlocks; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using AColor = Android.Graphics.Color; 8 | 9 | namespace FluidSharp.Views.Android.NativeViews 10 | { 11 | public static class NativeViewExtensions 12 | { 13 | 14 | 15 | public static AColor ToAndroid(this SKColor self) 16 | { 17 | return new AColor(self.Red, self.Green, self.Blue, self.Alpha); 18 | } 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Android/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.xml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable/ 12 | icon.png 13 | 14 | layout/ 15 | main.xml 16 | 17 | values/ 18 | strings.xml 19 | 20 | In order to get the build system to recognize Android resources, set the build action to 21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 22 | instead operate on resource IDs. When you compile an Android application that uses resources, 23 | the build system will package the resources for distribution and generate a class called "R" 24 | (this is an Android convention) that contains the tokens for each one of the resources 25 | included. For example, for the above Resources layout, this is what the R class would expose: 26 | 27 | public class R { 28 | public class drawable { 29 | public const int icon = 0x123; 30 | } 31 | 32 | public class layout { 33 | public const int main = 0x456; 34 | } 35 | 36 | public class strings { 37 | public const int first_string = 0xabc; 38 | public const int second_string = 0xbcd; 39 | } 40 | } 41 | 42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main 43 | to reference the layout/main.xml file, or R.strings.first_string to reference the first 44 | string in the dictionary file values/strings.xml. -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Android/Resources/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Hello World, Click Me! 3 | FluidSharp.Views.Android 4 | 5 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Android/nuget instructions.txt: -------------------------------------------------------------------------------- 1 |  2 | cd C:\wouterst79\FluidSharp\source\FluidSharp.Views\FluidSharp.Views.Android 3 | c:\wouterst79\nuget.exe pack FluidSharp.Views.Android.nuspec 4 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Forms.UWP/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FluidSharp.Views.Forms.UWP")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FluidSharp.Views.Forms.UWP")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Forms.UWP/Properties/SkiaSharp.FlowUI.Views.Forms.UWP.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Forms.iOS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FluidSharp.Views.Forms.iOS")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FluidSharp.Views.Forms.iOS")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("50c7b8c9-e664-45af-b88e-0c9b8b9c1be1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Forms.iOS/TouchEffect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | using Xamarin.Forms; 5 | using Xamarin.Forms.Platform.iOS; 6 | 7 | using UIKit; 8 | using TouchTracking = FluidSharp.Views.Forms; 9 | 10 | 11 | [assembly: ResolutionGroupName("FluidSharp")] 12 | [assembly: ExportEffect(typeof(FluidSharp.iOS.TouchEffect), "TouchEffect")] 13 | namespace FluidSharp.iOS 14 | { 15 | public class TouchEffect : PlatformEffect 16 | { 17 | UIView view; 18 | TouchRecognizer touchRecognizer; 19 | 20 | protected override void OnAttached() 21 | { 22 | // Get the iOS UIView corresponding to the Element that the effect is attached to 23 | view = Control == null ? Container : Control; 24 | 25 | // Get access to the TouchEffect class in the .NET Standard library 26 | TouchTracking.TouchEffect effect = (TouchTracking.TouchEffect)Element.Effects.FirstOrDefault(e => e is TouchTracking.TouchEffect); 27 | 28 | if (effect != null && view != null) 29 | { 30 | // Create a TouchRecognizer for this UIView 31 | touchRecognizer = new TouchRecognizer(Element, view, effect); 32 | view.AddGestureRecognizer(touchRecognizer); 33 | } 34 | } 35 | 36 | protected override void OnDetached() 37 | { 38 | if (touchRecognizer != null) 39 | { 40 | // Clean up the TouchRecognizer object 41 | touchRecognizer.Detach(); 42 | 43 | // Remove the TouchRecognizer from the UIView 44 | view.RemoveGestureRecognizer(touchRecognizer); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Forms/FluidSharp.Views.Forms.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0-android;net7.0-ios 5 | 6 | true 7 | Wouter Steenbergen 8 | 1.4.0-alpha 9 | My Daily Bits LLC 10 | Xamarin Forms Views for FluidSharp (all platforms) 11 | 2022-2023 Wouter Steenbergen 12 | MIT 13 | 14 | 15 | 16 | TRACE;__FORMS__ 17 | 18 | 19 | 20 | TRACE;__FORMS__ 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Component 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Forms/NativeViewManager.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Interop; 2 | using FluidSharp.Widgets.Native; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Xamarin.Forms; 10 | 11 | namespace FluidSharp.Views.Forms 12 | { 13 | 14 | public class NativeViewManager : NativeViewManagerBase 15 | { 16 | 17 | public SkiaView View; 18 | 19 | public NativeViewManager(SkiaView view) 20 | { 21 | View = view; 22 | } 23 | 24 | public override IEnumerable GetChildren() => View.GetViews(); 25 | 26 | public override SKSize GetControlSize(View control) => new SKSize((float)control.Bounds.Width, (float)control.Bounds.Height); 27 | 28 | public override void RegisterNewControl(View newControl) => View.Children.Add(newControl); 29 | 30 | public override void SetControlVisible(View control, bool visible) 31 | { 32 | if (control.IsVisible != visible) control.IsVisible = visible; 33 | } 34 | 35 | public override void UpdateControl(View control, NativeViewWidget nativeViewWidget, SKRect rect, SKRect original) 36 | { 37 | var bounds = new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height); 38 | if (control.Bounds != bounds) 39 | { 40 | AbsoluteLayout.SetLayoutBounds(control, bounds); 41 | System.Diagnostics.Debug.WriteLine("setting bounds"); 42 | } 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Forms/NativeViews/NativeTextboxImpl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Xamarin.Forms; 7 | 8 | namespace FluidSharp.Views.Forms.NativeViews 9 | { 10 | public class NativeTextboxImpl : Entry 11 | { 12 | 13 | public object Context; 14 | 15 | private Func RequestRedraw; 16 | 17 | public NativeTextboxImpl(Func requestRedraw) 18 | { 19 | RequestRedraw = requestRedraw; 20 | // BackColor = Color.Red; 21 | // Height = 100; 22 | // this.Click += NativeAdViewImpl_Click; 23 | } 24 | 25 | //private void NativeAdViewImpl_Click(object sender, EventArgs e) 26 | //{ 27 | // this.Height = Height == 100 ? 150 : 100; 28 | // Task.Run(RequestRedraw); 29 | //} 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Forms/XamarinExtensions.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using SkiaSharp.Views.Forms; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using Xamarin.Forms; 7 | 8 | namespace FluidSharp.Views.Forms 9 | { 10 | public static class XamarinExtensions 11 | { 12 | 13 | public static SKColor SKColor(this ResourceDictionary resourceDictionary, string ResourceName) 14 | { 15 | var c = resourceDictionary[ResourceName]; 16 | Color color; 17 | if (c is OnPlatform opc) 18 | color = opc; 19 | else 20 | color = (Color)c; 21 | return color.ToSKColor(); 22 | } 23 | 24 | public static SKColor ColorFromResources(string ResourceName) => Application.Current.Resources.SKColor(ResourceName); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/License.txt: -------------------------------------------------------------------------------- 1 |  Copyright 2022-2024 Wouter Steenbergen 2 | 3 | Licensed for evaluation ("internal development") only. 4 | Not licenced to be distributed as part of a commercially available product. 5 | 6 | You may not use this file except in compliance with the License. 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/Android/AndroidFluidWidgetView.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content; 3 | using Android.OS; 4 | using Android.Runtime; 5 | using Android.Views; 6 | using Android.Widget; 7 | using FluidSharp.State; 8 | using SkiaSharp; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Text; 13 | 14 | namespace FluidSharp.Views.Android 15 | { 16 | public abstract class AndroidFluidWidgetView : RelativeLayout 17 | { 18 | 19 | public abstract SKSize PlatformScale { get; } 20 | public abstract VisualState VisualState { get; } 21 | 22 | protected AndroidFluidWidgetView(Context context) : base(context) 23 | { 24 | } 25 | 26 | public void AddOnMainThread(View childview) 27 | { 28 | 29 | ((Activity)Context).RunOnUiThread(() => 30 | { 31 | if (childview.Parent == this) return; 32 | if (childview.Parent != null) 33 | ((ViewGroup)childview.Parent).RemoveView(childview); 34 | AddView(childview); 35 | }); 36 | 37 | } 38 | 39 | } 40 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/Android/FluidSharp.Views.Android.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | FluidSharp.Views.Android 5 | 1.3.5-alpha 6 | $title$ 7 | Wouter Steenbergen 8 | My Daily Bits LLC 9 | true 10 | License.txt 11 | FluidSharp is a high performance mobile first multi-platform UI layout framework based on Skia. 12 | Initial release 13 | 2022-2023 Wouter Steenbergen 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/Android/License.txt: -------------------------------------------------------------------------------- 1 |  Copyright 2022 - 2024 - Wouter Steenbergen 2 | 3 | Licensed for evaluation ("internal development") only. 4 | Not licenced to be distributed as part of a commercially available product. 5 | 6 | You may not use this file except in compliance with the License. 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/Android/NativeViews/NativeViewExtensions.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using SkiaSharp.TextBlocks; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using AColor = Android.Graphics.Color; 8 | 9 | namespace FluidSharp.Views.Android.NativeViews 10 | { 11 | public static class NativeViewExtensions 12 | { 13 | 14 | 15 | public static AColor ToAndroid(this SKColor self) 16 | { 17 | return new AColor(self.Red, self.Green, self.Blue, self.Alpha); 18 | } 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/Android/Resources/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Hello World, Click Me! 3 | FluidSharp.Views.Android 4 | 5 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/Android/nuget instructions.txt: -------------------------------------------------------------------------------- 1 |  2 | cd C:\wouterst79\FluidSharp\source\FluidSharp.Views\FluidSharp.Views.Android 3 | c:\wouterst79\nuget.exe pack FluidSharp.Views.Android.nuspec 4 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/iOS/FluidSharp.Views.iOS.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | FluidSharp.Views.iOS 5 | 1.3.3-alpha 6 | $title$ 7 | Wouter Steenbergen 8 | My Daily Bits LLC 9 | true 10 | License.txt 11 | FluidSharp is a high performance mobile first multi-platform UI layout framework based on Skia. 12 | Initial release 13 | 2022-2023 Wouter Steenbergen 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/iOS/License.txt: -------------------------------------------------------------------------------- 1 |  Copyright 2022 - Wouter Steenbergen 2 | 3 | Licensed for evaluation ("internal development") only. 4 | Not licenced to be distributed as part of a commercially available product. 5 | 6 | You may not use this file except in compliance with the License. 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/iOS/NativeViews/INativeTextboxImpl.cs: -------------------------------------------------------------------------------- 1 | #if DEBUG 2 | #define PRINTEVENTS 3 | #endif 4 | 5 | namespace FluidSharp.Views.iOS.NativeViews 6 | { 7 | public interface INativeTextboxImpl 8 | { 9 | object Context { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/iOS/NativeViews/NativeViewExtensions.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Widgets.Native; 2 | using Foundation; 3 | using SkiaSharp; 4 | using SkiaSharp.TextBlocks; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using UIKit; 10 | 11 | namespace FluidSharp.Views.iOS.NativeViews 12 | { 13 | public static class NativeViewExtensions 14 | { 15 | 16 | public static UIFont ToUIFont(this Font font) 17 | { 18 | UIFont result; 19 | if (font.FontStyle.Weight == 600)//SKFontStyleWeight.SemiBold) 20 | { 21 | result = UIFont.FromName(font.Name + " Semibold", font.TextSize); 22 | if (result != null) return result; 23 | } 24 | result = UIFont.FromName(font.Name, font.TextSize); 25 | return result; 26 | } 27 | 28 | public static UIColor ToUIColor(this SKColor color) 29 | { 30 | return new UIColor(color.Red / 255f, color.Green / 255f, color.Blue / 255f, color.Alpha / 255f); 31 | } 32 | 33 | internal static UIReturnKeyType ToUIReturnKeyType(this ReturnType returnType) 34 | { 35 | switch (returnType) 36 | { 37 | case ReturnType.Go: 38 | return UIReturnKeyType.Go; 39 | case ReturnType.Next: 40 | return UIReturnKeyType.Next; 41 | case ReturnType.Send: 42 | return UIReturnKeyType.Send; 43 | case ReturnType.Search: 44 | return UIReturnKeyType.Search; 45 | case ReturnType.Done: 46 | return UIReturnKeyType.Done; 47 | case ReturnType.Default: 48 | return UIReturnKeyType.Default; 49 | default: 50 | throw new System.NotImplementedException($"ReturnType {returnType} not supported"); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.Maui/Platforms/iOS/nuget instructions.txt: -------------------------------------------------------------------------------- 1 |  2 | cd C:\wouterst79\FluidSharp\source\FluidSharp.Views\FluidSharp.Views.iOS 3 | c:\wouterst79\nuget.exe pack FluidSharp.Views.iOS.nuspec 4 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.WindowsForms.Core/FluidSharp.Views.WindowsForms.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0-windows 5 | true 6 | 7 | true 8 | Wouter Steenbergen 9 | My Daily Bits LLC 10 | WindowdForms Views for FluidSharp (net9.0) 11 | 2020-2025 Wouter Steenbergen 12 | 13 | 3.0.0-alpha 14 | enable 15 | true 16 | License.txt 17 | 18 | 19 | 20 | 21 | TRACE;__WINDOWSFORMS__ 22 | 23 | 24 | 25 | TRACE;__WINDOWSFORMS__ 26 | 27 | 28 | 29 | 30 | 31 | True 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Component 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.WindowsForms.Core/License.txt: -------------------------------------------------------------------------------- 1 |  Copyright 2022-2024 Wouter Steenbergen 2 | 3 | Licensed for evaluation ("internal development") only. 4 | Not licenced to be distributed as part of a commercially available product. 5 | 6 | You may not use this file except in compliance with the License. 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.WindowsForms.Core/NativeViews/NativeViewExtensions.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using SkiaSharp.TextBlocks; 3 | using UWPFont = System.Drawing.Font; 4 | using UWPColor = System.Drawing.Color; 5 | 6 | namespace FluidSharp.Views.WindowsForms.Core.NativeViews 7 | { 8 | public static class NativeViewExtensions 9 | { 10 | 11 | public static UWPFont ToUWPFont(this Font font) 12 | { 13 | return new UWPFont(font.Name, font.TextSize / 2); 14 | } 15 | 16 | public static UWPColor ToUWPColor(this SKColor color) 17 | { 18 | return UWPColor.FromArgb(color.Alpha, color.Red, color.Green, color.Blue); 19 | } 20 | 21 | } 22 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.WindowsForms/NativeViews/NativeTextboxImpl.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Widgets.Native; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | 9 | namespace FluidSharp.Views.WindowsForms.NativeViews 10 | { 11 | public class NativeTextboxImpl : TextBox, INativeViewImpl 12 | { 13 | 14 | public object Context; 15 | 16 | private Func RequestRedraw; 17 | private Func SetText; 18 | 19 | public NativeTextboxImpl(Func requestRedraw) 20 | { 21 | RequestRedraw = requestRedraw; 22 | // BackColor = Color.Red; 23 | // Height = 100; 24 | // this.Click += NativeAdViewImpl_Click; 25 | } 26 | 27 | public void UpdateControl(NativeViewWidget nativeViewWidget) 28 | { 29 | var widget = (NativeTextboxWidget)nativeViewWidget; 30 | if (Text != widget.Text) 31 | { 32 | Text = widget.Text; 33 | } 34 | SetText = widget.SetText; 35 | } 36 | 37 | //private void NativeAdViewImpl_Click(object sender, EventArgs e) 38 | //{ 39 | // this.Height = Height == 100 ? 150 : 100; 40 | // Task.Run(RequestRedraw); 41 | //} 42 | 43 | protected override void OnTextChanged(EventArgs e) 44 | { 45 | base.OnTextChanged(e); 46 | Task.Run(() => SetText(Text)); 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.WindowsForms/OpenTK.dll.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.WindowsForms/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FluidSharp.WindowsForms.NetFramework")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FluidSharp.WindowsForms.NetFramework")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("72b7f87e-5f47-4064-bec3-ac411c08e308")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.WindowsForms/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.WindowsForms/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.iOS/FluidSharp.Views.iOS.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | FluidSharp.Views.iOS 5 | 1.3.3-alpha 6 | $title$ 7 | Wouter Steenbergen 8 | My Daily Bits LLC 9 | true 10 | License.txt 11 | FluidSharp is a high performance mobile first multi-platform UI layout framework based on Skia. 12 | Initial release 13 | 2022-2023 Wouter Steenbergen 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.iOS/License.txt: -------------------------------------------------------------------------------- 1 |  Copyright 2022-2024 Wouter Steenbergen 2 | 3 | Licensed for evaluation ("internal development") only. 4 | Not licenced to be distributed as part of a commercially available product. 5 | 6 | You may not use this file except in compliance with the License. 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.iOS/NativeViews/INativeTextboxImpl.cs: -------------------------------------------------------------------------------- 1 | #if DEBUG 2 | #define PRINTEVENTS 3 | #endif 4 | 5 | namespace FluidSharp.Views.iOS.NativeViews 6 | { 7 | public interface INativeTextboxImpl 8 | { 9 | object Context { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.iOS/NativeViews/NativeViewExtensions.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Widgets.Native; 2 | using Foundation; 3 | using SkiaSharp; 4 | using SkiaSharp.TextBlocks; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using UIKit; 10 | 11 | namespace FluidSharp.Views.iOS.NativeViews 12 | { 13 | public static class NativeViewExtensions 14 | { 15 | 16 | public static UIFont ToUIFont(this Font font) 17 | { 18 | UIFont result; 19 | if (font.FontStyle.Weight == 600)//SKFontStyleWeight.SemiBold) 20 | { 21 | result = UIFont.FromName(font.Name + " Semibold", font.TextSize); 22 | if (result != null) return result; 23 | } 24 | result = UIFont.FromName(font.Name, font.TextSize); 25 | return result; 26 | } 27 | 28 | public static UIColor ToUIColor(this SKColor color) 29 | { 30 | return new UIColor(color.Red / 255f, color.Green / 255f, color.Blue / 255f, color.Alpha / 255f); 31 | } 32 | 33 | internal static UIReturnKeyType ToUIReturnKeyType(this ReturnType returnType) 34 | { 35 | switch (returnType) 36 | { 37 | case ReturnType.Go: 38 | return UIReturnKeyType.Go; 39 | case ReturnType.Next: 40 | return UIReturnKeyType.Next; 41 | case ReturnType.Send: 42 | return UIReturnKeyType.Send; 43 | case ReturnType.Search: 44 | return UIReturnKeyType.Search; 45 | case ReturnType.Done: 46 | return UIReturnKeyType.Done; 47 | case ReturnType.Default: 48 | return UIReturnKeyType.Default; 49 | default: 50 | throw new System.NotImplementedException($"ReturnType {returnType} not supported"); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.iOS/Services/KeyboardTracker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using Foundation; 7 | using UIKit; 8 | 9 | namespace FluidSharp.Views.iOS.Services 10 | { 11 | 12 | 13 | // https://developer.apple.com/library/archive/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html 14 | 15 | // https://docs.microsoft.com/en-us/dotnet/api/uikit.uikeyboard.notifications.observedidshow?view=xamarin-ios-sdk-12 16 | 17 | public class KeyboardTracker 18 | { 19 | 20 | NSObject _keyboardShowObserver; 21 | NSObject _keyboardHideObserver; 22 | NSObject _keyboardChangeObserver; 23 | 24 | Action OnKeyboardHeightChanged; 25 | 26 | public KeyboardTracker(Action onKeyboardHeightChanged) 27 | { 28 | OnKeyboardHeightChanged = onKeyboardHeightChanged; 29 | } 30 | 31 | public void RegisterForKeyboardNotifications() 32 | { 33 | _keyboardShowObserver = UIKeyboard.Notifications.ObserveWillShow((s, e) => OnKeyboardShow(e)); 34 | _keyboardChangeObserver = UIKeyboard.Notifications.ObserveWillChangeFrame((s, e) => OnKeyboardShow(e)); 35 | _keyboardHideObserver = UIKeyboard.Notifications.ObserveWillHide((s, e) => OnKeyboardHide(e)); 36 | } 37 | 38 | public void UnregisterForKeyboardNotifications() 39 | { 40 | if (_keyboardShowObserver != null) 41 | { 42 | _keyboardShowObserver.Dispose(); 43 | _keyboardShowObserver = null; 44 | } 45 | 46 | if (_keyboardChangeObserver != null) 47 | { 48 | _keyboardChangeObserver.Dispose(); 49 | _keyboardChangeObserver = null; 50 | } 51 | 52 | if (_keyboardHideObserver != null) 53 | { 54 | _keyboardHideObserver.Dispose(); 55 | _keyboardHideObserver = null; 56 | } 57 | 58 | } 59 | 60 | protected virtual void OnKeyboardShow(UIKeyboardEventArgs notification) 61 | { 62 | OnKeyboardHeightChanged(notification.FrameEnd.Height); 63 | } 64 | 65 | private void OnKeyboardHide(UIKeyboardEventArgs notification) 66 | { 67 | OnKeyboardHeightChanged(0); 68 | } 69 | 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /FluidSharp.Views/FluidSharp.Views.iOS/nuget instructions.txt: -------------------------------------------------------------------------------- 1 |  2 | cd C:\wouterst79\FluidSharp\source\FluidSharp.Views\FluidSharp.Views.iOS 3 | c:\wouterst79\nuget.exe pack FluidSharp.Views.iOS.nuspec 4 | -------------------------------------------------------------------------------- /FluidSharp.Views/Ref/SkiaSharp.Views.Android.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/FluidSharp.Views/Ref/SkiaSharp.Views.Android.dll -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Android/SKCanvasViewRenderer.cs: -------------------------------------------------------------------------------- 1 | using Android.Content; 2 | 3 | #if __MAUI__ 4 | using SKFormsView = SkiaSharp.Views.Maui.Controls.SKCanvasView; 5 | using SKNativeView = SkiaSharp.Views.Android.SKCanvasView; 6 | #else 7 | using Xamarin.Forms; 8 | 9 | using SKFormsView = SkiaSharp.Views.Forms.SKCanvasView; 10 | using SKNativeView = SkiaSharp.Views.Android.SKCanvasView; 11 | 12 | [assembly: ExportRenderer(typeof(SKFormsView), typeof(SkiaSharp.Views.Forms.SKCanvasViewRenderer))] 13 | #endif 14 | 15 | #if __MAUI__ 16 | namespace SkiaSharp.Views.Maui.Controls.Compatibility 17 | #else 18 | namespace SkiaSharp.Views.Forms 19 | #endif 20 | { 21 | public class SKCanvasViewRenderer : SKCanvasViewRendererBase 22 | { 23 | public SKCanvasViewRenderer(Context context) 24 | : base(context) 25 | { 26 | } 27 | 28 | protected override SKNativeView CreateNativeControl() => 29 | GetType() == typeof(SKCanvasViewRenderer) 30 | ? new SKNativeView(Context) 31 | : base.CreateNativeControl(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Android/SKGLViewRenderer.cs: -------------------------------------------------------------------------------- 1 | using Android.Content; 2 | using Android.Opengl; 3 | 4 | #if __MAUI__ 5 | using SKFormsView = SkiaSharp.Views.Maui.Controls.SKGLView; 6 | using SKNativeView = SkiaSharp.Views.Android.SKGLTextureView; 7 | #else 8 | using Xamarin.Forms; 9 | 10 | using SKFormsView = SkiaSharp.Views.Forms.SKGLView; 11 | using SKNativeView = SkiaSharp.Views.Android.SKGLTextureView; 12 | 13 | [assembly: ExportRenderer(typeof(SKFormsView), typeof(SkiaSharp.Views.Forms.SKGLViewRenderer))] 14 | #endif 15 | 16 | #if __MAUI__ 17 | namespace SkiaSharp.Views.Maui.Controls.Compatibility 18 | #else 19 | namespace SkiaSharp.Views.Forms 20 | #endif 21 | { 22 | public class SKGLViewRenderer : SKGLViewRendererBase 23 | { 24 | public SKGLViewRenderer(Context context) 25 | : base(context) 26 | { 27 | } 28 | 29 | protected override void SetupRenderLoop(bool oneShot) 30 | { 31 | if (oneShot) 32 | { 33 | Control.RequestRender(); 34 | } 35 | 36 | Control.RenderMode = Element.HasRenderLoop 37 | ? Rendermode.Continuously 38 | : Rendermode.WhenDirty; 39 | } 40 | 41 | protected override SKNativeView CreateNativeControl() 42 | { 43 | var view = GetType() == typeof(SKGLViewRenderer) 44 | ? new SKNativeView(Context) 45 | : base.CreateNativeControl(); 46 | 47 | // Force the opacity to false for consistency with the other platforms 48 | view.SetOpaque(false); 49 | 50 | return view; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Android/SKImageSourceHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Android.Content; 4 | using Android.Graphics; 5 | 6 | using SkiaSharp.Views.Android; 7 | 8 | #if __MAUI__ 9 | using Microsoft.Maui.Controls; 10 | using Microsoft.Maui.Controls.Compatibility.Platform.Android; 11 | #else 12 | using Xamarin.Forms; 13 | using Xamarin.Forms.Platform.Android; 14 | 15 | [assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKImageImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))] 16 | [assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKBitmapImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))] 17 | [assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKPixmapImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))] 18 | [assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKPictureImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))] 19 | #endif 20 | 21 | #if __MAUI__ 22 | namespace SkiaSharp.Views.Maui.Controls.Compatibility 23 | #else 24 | namespace SkiaSharp.Views.Forms 25 | #endif 26 | { 27 | public sealed class SKImageSourceHandler : IImageSourceHandler 28 | { 29 | public Task LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default(CancellationToken)) 30 | { 31 | Bitmap bitmap = null; 32 | 33 | var imageImageSource = imagesource as SKImageImageSource; 34 | if (imageImageSource != null) 35 | { 36 | bitmap = imageImageSource.Image?.ToBitmap(); 37 | } 38 | 39 | var bitmapImageSource = imagesource as SKBitmapImageSource; 40 | if (bitmapImageSource != null) 41 | { 42 | bitmap = bitmapImageSource.Bitmap?.ToBitmap(); 43 | } 44 | 45 | var pixmapImageSource = imagesource as SKPixmapImageSource; 46 | if (pixmapImageSource != null) 47 | { 48 | bitmap = pixmapImageSource.Pixmap?.ToBitmap(); 49 | } 50 | 51 | var pictureImageSource = imagesource as SKPictureImageSource; 52 | if (pictureImageSource != null) 53 | { 54 | bitmap = pictureImageSource.Picture?.ToBitmap(pictureImageSource.Dimensions); 55 | } 56 | 57 | return Task.FromResult(bitmap); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Android/SkiaSharp.Views.Forms.Android.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0-android 5 | SkiaSharp.Views.Forms 6 | SkiaSharp.Views.Forms 7 | false 8 | SkiaSharp.Views.Forms 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Native.Shared/Registrar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SkiaSharp.Views.Forms 4 | { 5 | internal class Registrar 6 | { 7 | internal static void EnsureRegistered(Type type, Type handler) 8 | { 9 | var registered = Xamarin.Forms.Internals.Registrar.Registered; 10 | if (registered.GetHandlerType(type) != null) 11 | return; 12 | registered.Register(type, handler); 13 | } 14 | } 15 | 16 | public sealed partial class SKImageImageSource 17 | { 18 | static SKImageImageSource() => 19 | Registrar.EnsureRegistered(typeof(SKImageImageSource), typeof(SKImageSourceHandler)); 20 | } 21 | 22 | public sealed partial class SKBitmapImageSource 23 | { 24 | static SKBitmapImageSource() => 25 | Registrar.EnsureRegistered(typeof(SKBitmapImageSource), typeof(SKImageSourceHandler)); 26 | } 27 | 28 | public sealed partial class SKPixmapImageSource 29 | { 30 | static SKPixmapImageSource() => 31 | Registrar.EnsureRegistered(typeof(SKPixmapImageSource), typeof(SKImageSourceHandler)); 32 | } 33 | 34 | public sealed partial class SKPictureImageSource 35 | { 36 | static SKPictureImageSource() => 37 | Registrar.EnsureRegistered(typeof(SKPictureImageSource), typeof(SKImageSourceHandler)); 38 | } 39 | 40 | public partial class SKCanvasView 41 | { 42 | static SKCanvasView() => 43 | Registrar.EnsureRegistered(typeof(SKCanvasView), typeof(SKCanvasViewRenderer)); 44 | } 45 | 46 | public partial class SKGLView 47 | { 48 | static SKGLView() => 49 | Registrar.EnsureRegistered(typeof(SKGLView), typeof(SKGLViewRenderer)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/Extensions.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace SkiaSharp.Views.Forms 4 | { 5 | public static class Extensions 6 | { 7 | public static Point ToFormsPoint(this SKPointI point) 8 | { 9 | return new Point(point.X, point.Y); 10 | } 11 | 12 | public static Point ToFormsPoint(this SKPoint point) 13 | { 14 | return new Point(point.X, point.Y); 15 | } 16 | 17 | public static SKPoint ToSKPoint(this Point point) 18 | { 19 | return new SKPoint((float)point.X, (float)point.Y); 20 | } 21 | 22 | // Xamarin.Forms.Point 23 | 24 | public static Size ToFormsSize(this SKSizeI size) 25 | { 26 | return new Size(size.Width, size.Height); 27 | } 28 | 29 | public static Size ToFormsSize(this SKSize size) 30 | { 31 | return new Size(size.Width, size.Height); 32 | } 33 | 34 | public static SKSize ToSKSize(this Size size) 35 | { 36 | return new SKSize((float)size.Width, (float)size.Height); 37 | } 38 | 39 | // Xamarin.Forms.Size 40 | 41 | public static Rectangle ToFormsRect(this SKRectI rect) 42 | { 43 | return new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height); 44 | } 45 | 46 | public static Rectangle ToFormsRect(this SKRect rect) 47 | { 48 | return new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height); 49 | } 50 | 51 | public static SKRect ToSKRect(this Rectangle rect) 52 | { 53 | return new SKRect((float)rect.Left, (float)rect.Top, (float)rect.Right, (float)rect.Bottom); 54 | } 55 | 56 | // Xamarin.Forms.Color 57 | 58 | public static Color ToFormsColor(this SKColor color) => 59 | new Color(color.Red / 255.0, color.Green / 255.0, color.Blue / 255.0, color.Alpha / 255.0); 60 | 61 | public static Color ToFormsColor(this SKColorF color) => 62 | new Color(color.Red, color.Green, color.Blue, color.Alpha); 63 | 64 | public static SKColor ToSKColor(this Color color) => 65 | new SKColor((byte)(color.R * 255), (byte)(color.G * 255), (byte)(color.B * 255), (byte)(color.A * 255)); 66 | 67 | public static SKColorF ToSKColorF(this Color color) => 68 | new SKColorF((float)color.R, (float)color.G, (float)color.B, (float)color.A); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/RendererTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | #if __MAUI__ 4 | using Microsoft.Maui; 5 | using Microsoft.Maui.Controls; 6 | #else 7 | using Xamarin.Forms; 8 | #endif 9 | 10 | #if __MAUI__ 11 | namespace SkiaSharp.Views.Maui.Controls 12 | #else 13 | namespace SkiaSharp.Views.Forms 14 | #endif 15 | { 16 | public class GetPropertyValueEventArgs : EventArgs 17 | { 18 | public T Value { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/SKPaintSurfaceEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | #if __MAUI__ 4 | using Microsoft.Maui; 5 | #else 6 | using Xamarin.Forms; 7 | #endif 8 | 9 | #if __MAUI__ 10 | namespace SkiaSharp.Views.Maui 11 | #else 12 | namespace SkiaSharp.Views.Forms 13 | #endif 14 | { 15 | public class SKPaintSurfaceEventArgs : EventArgs 16 | { 17 | public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info) 18 | : this(surface, info, info) 19 | { 20 | } 21 | 22 | public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info, SKImageInfo rawInfo) 23 | { 24 | Surface = surface; 25 | Info = info; 26 | RawInfo = rawInfo; 27 | } 28 | 29 | public SKSurface Surface { get; } 30 | 31 | public SKImageInfo Info { get; } 32 | 33 | public SKImageInfo RawInfo { get; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.iOS/SKCanvasViewRenderer.cs: -------------------------------------------------------------------------------- 1 | #if __MAUI__ 2 | using SKFormsView = SkiaSharp.Views.Maui.Controls.SKCanvasView; 3 | using SKNativeView = SkiaSharp.Views.iOS.SKCanvasView; 4 | #else 5 | using Xamarin.Forms; 6 | 7 | using SKFormsView = SkiaSharp.Views.Forms.SKCanvasView; 8 | using SKNativeView = SkiaSharp.Views.iOS.SKCanvasView; 9 | 10 | [assembly: ExportRenderer(typeof(SKFormsView), typeof(SkiaSharp.Views.Forms.SKCanvasViewRenderer))] 11 | #endif 12 | 13 | #if __MAUI__ 14 | namespace SkiaSharp.Views.Maui.Controls.Compatibility 15 | #else 16 | namespace SkiaSharp.Views.Forms 17 | #endif 18 | { 19 | public class SKCanvasViewRenderer : SKCanvasViewRendererBase 20 | { 21 | public SKCanvasViewRenderer() 22 | { 23 | SetDisablesUserInteraction(true); 24 | } 25 | 26 | protected override SKNativeView CreateNativeControl() 27 | { 28 | var view = GetType() == typeof(SKCanvasViewRenderer) 29 | ? new SKNativeView() 30 | : base.CreateNativeControl(); 31 | 32 | // Force the opacity to false for consistency with the other platforms 33 | view.Opaque = false; 34 | 35 | return view; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.iOS/SKImageSourceHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using UIKit; 4 | 5 | using SkiaSharp.Views.iOS; 6 | 7 | #if __MAUI__ 8 | using Microsoft.Maui.Controls; 9 | using Microsoft.Maui.Controls.Compatibility.Platform.iOS; 10 | #else 11 | using Xamarin.Forms; 12 | using Xamarin.Forms.Platform.iOS; 13 | 14 | [assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKImageImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))] 15 | [assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKBitmapImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))] 16 | [assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKPixmapImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))] 17 | [assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKPictureImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))] 18 | #endif 19 | 20 | #if __MAUI__ 21 | namespace SkiaSharp.Views.Maui.Controls.Compatibility 22 | #else 23 | namespace SkiaSharp.Views.Forms 24 | #endif 25 | { 26 | public sealed class SKImageSourceHandler : IImageSourceHandler 27 | { 28 | public Task LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = default(CancellationToken), float scale = 1f) 29 | { 30 | UIImage image = null; 31 | 32 | var imageImageSource = imagesource as SKImageImageSource; 33 | if (imageImageSource != null) 34 | { 35 | image = imageImageSource.Image?.ToUIImage(); 36 | } 37 | 38 | var bitmapImageSource = imagesource as SKBitmapImageSource; 39 | if (bitmapImageSource != null) 40 | { 41 | image = bitmapImageSource.Bitmap?.ToUIImage(); 42 | } 43 | 44 | var pixmapImageSource = imagesource as SKPixmapImageSource; 45 | if (pixmapImageSource != null) 46 | { 47 | image = pixmapImageSource.Pixmap?.ToUIImage(); 48 | } 49 | 50 | var pictureImageSource = imagesource as SKPictureImageSource; 51 | if (pictureImageSource != null) 52 | { 53 | image = pictureImageSource.Picture?.ToUIImage(pictureImageSource.Dimensions); 54 | } 55 | 56 | return Task.FromResult(image); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.iOS/SkiaSharp.Views.Forms.iOS.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0-ios 5 | SkiaSharp.Views.Forms 6 | SkiaSharp.Views.Forms 7 | false 8 | SkiaSharp.Views.Forms 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33213.308 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.Forms", "SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.csproj", "{42595E7C-0F4A-4987-97C3-2D071E2B895E}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {42595E7C-0F4A-4987-97C3-2D071E2B895E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {42595E7C-0F4A-4987-97C3-2D071E2B895E}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {42595E7C-0F4A-4987-97C3-2D071E2B895E}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {42595E7C-0F4A-4987-97C3-2D071E2B895E}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {C15E64CB-EE77-48B1-A3BF-FB0BA24C0BE8} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms/SKCanvasViewRenderer.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Views.Forms 2 | { 3 | internal class SKCanvasViewRenderer 4 | { 5 | public SKCanvasViewRenderer() 6 | { 7 | throw new System.PlatformNotSupportedException("SKCanvasView is not yet supported on this platform."); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms/SKGLViewRenderer.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Views.Forms 2 | { 3 | internal class SKGLViewRenderer 4 | { 5 | public SKGLViewRenderer() 6 | { 7 | throw new System.PlatformNotSupportedException("SKGLView is not yet supported on this platform."); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0-ios;net7.0-android 5 | SkiaSharp.Views.Forms 6 | SkiaSharp.Views.Forms 7 | false 8 | SkiaSharp.Views.Forms 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /FluidSharp.Views/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms/nuget/build/net462/SkiaSharp.Views.Forms.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | True 7 | 8 | 9 | 10 | 11 | 12 | 13 | <_RequiredWPFReferences Include="@(ReferencePath)" Condition="'%(Filename)' == 'PresentationCore'" /> 14 | <_RequiredWPFReferences Include="@(ReferencePath)" Condition="'%(Filename)' == 'PresentationFramework'" /> 15 | <_RequiredWPFReferences Include="@(ReferencePath)" Condition="'%(Filename)' == 'WindowsBase'" /> 16 | 17 | 20 | 21 | 22 | 23 | <_RequiredGTKReferences Include="@(ReferencePath)" Condition="'%(Filename)' == 'gtk-sharp'" /> 24 | 25 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /FluidSharp/Animations/AlignAnimation.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using FluidSharp.Widgets; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Animations 9 | { 10 | public class AlignAnimation : Widget 11 | { 12 | 13 | public Align A; 14 | public Align B; 15 | 16 | public float Percentage; 17 | 18 | public AlignAnimation(Align a, Align b, float percentage) 19 | { 20 | A = a ?? throw new ArgumentNullException(nameof(a)); 21 | B = b ?? throw new ArgumentNullException(nameof(b)); 22 | Percentage = percentage; 23 | } 24 | 25 | public static Widget Make(Align a, Align b, float pct) 26 | { 27 | if (pct <= 0) return a; 28 | if (pct >= 1) return b; 29 | return new AlignAnimation(a, b, pct); 30 | } 31 | 32 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 33 | { 34 | if (A.Child == B.Child) return A.Measure(measureCache, boundaries); 35 | var sa = A.Measure(measureCache, boundaries); 36 | var sb = B.Measure(measureCache, boundaries); 37 | var pcta = (1 - Percentage); 38 | var pctb = Percentage; 39 | return new SKSize(sa.Width * pcta + sb.Width * pctb, sa.Height * pcta + sb.Height * pctb); 40 | } 41 | 42 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 43 | { 44 | var recta = A.GetChildRect(layoutsurface, rect); 45 | var rectb = B.GetChildRect(layoutsurface, rect); 46 | 47 | var pcta = (1 - Percentage); 48 | var pctb = Percentage; 49 | 50 | var childrect = new SKRect(recta.Left * pcta + rectb.Left * pctb, 51 | recta.Top * pcta + rectb.Top * pctb, 52 | recta.Right * pcta + rectb.Right * pctb, 53 | recta.Bottom * pcta + rectb.Bottom * pctb); 54 | 55 | layoutsurface.Paint(A.Child, childrect); 56 | 57 | return childrect; 58 | } 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /FluidSharp/Animations/DynamicAnimation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FluidSharp.Animations 6 | { 7 | public class DynamicAnimation : IAnimation 8 | { 9 | 10 | public Animation Animation; 11 | 12 | public DynamicAnimation(Animation animation) 13 | { 14 | Animation = animation; 15 | } 16 | 17 | public float GetValue() => Animation.GetValue(); 18 | public bool Completed => Animation.Completed; 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FluidSharp/Animations/DynamicFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FluidSharp.Animations 6 | { 7 | public class DynamicFrame : IAnimation 8 | { 9 | 10 | public Frame Frame; 11 | 12 | public DynamicFrame(Frame animation) 13 | { 14 | Frame = animation; 15 | } 16 | 17 | public float GetValue() => Frame.GetValue(); 18 | public bool Completed => Frame.Completed; 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FluidSharp/Animations/Frame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluidSharp.Animations 4 | { 5 | public class Frame : Animation 6 | { 7 | 8 | // Frame 9 | public string Name { get; set; } 10 | public TimeSpan FrameStart { get; set; } 11 | public TimeSpan FrameEnd => FrameStart + Duration; 12 | 13 | public TimeSpan GetDurationPct(float pct) => FrameStart + Duration * pct; 14 | 15 | public Frame(string name, float durationMS, Easing? easing = null) 16 | : this(Speed, name, TimeSpan.Zero, TimeSpan.FromMilliseconds(durationMS), easing) 17 | { } 18 | 19 | public Frame(string name, float startMS, float durationMS, Easing? easing = null) 20 | : this(Speed, name, TimeSpan.FromMilliseconds(startMS), TimeSpan.FromMilliseconds(durationMS), easing) 21 | { } 22 | 23 | public Frame(string name, TimeSpan start, TimeSpan duration, Easing? easing = null) 24 | : this(Speed, name, start, duration, easing) 25 | { 26 | } 27 | 28 | private Frame(float speed, string name, TimeSpan start, TimeSpan duration, Easing? easing = null) 29 | { 30 | Name = name ?? throw new ArgumentNullException(nameof(name)); 31 | FrameStart = start * speed; 32 | Duration = duration * speed; 33 | Easing = easing; 34 | } 35 | 36 | public Frame Reverse() 37 | { 38 | StartValue = 1; EndValue = 0; 39 | return this; 40 | } 41 | 42 | public Frame SetStartEnd(float start, float end) 43 | { 44 | StartValue = start; 45 | EndValue = end; 46 | return this; 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /FluidSharp/Animations/IAnimation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FluidSharp.Animations 6 | { 7 | public interface IAnimation 8 | { 9 | 10 | bool Completed { get; } 11 | 12 | public float GetValue(); 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /FluidSharp/Animations/OptionalAnimatedWidget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using FluidSharp.Widgets; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Animations 9 | { 10 | public class OptionalAnimatedWidget : Widget 11 | { 12 | 13 | public Func Animation; 14 | public Func MakeWidget; 15 | 16 | public OptionalAnimatedWidget(Func animation, Func makeWidget) 17 | { 18 | Animation = animation ?? throw new ArgumentNullException(nameof(animation)); 19 | MakeWidget = makeWidget ?? throw new ArgumentNullException(nameof(makeWidget)); 20 | } 21 | 22 | private Animation? LastAnimation; 23 | private Widget? Widget; 24 | 25 | private Widget? GetWidget() 26 | { 27 | var a = Animation(); 28 | if (LastAnimation != a) 29 | { 30 | Widget = MakeWidget(a); 31 | LastAnimation = a; 32 | } 33 | return Widget; 34 | } 35 | 36 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => GetWidget()?.Measure(measureCache, boundaries) ?? new SKSize(); 37 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 38 | { 39 | var widget = GetWidget(); 40 | if (widget != null) 41 | return layoutsurface.Paint(widget, rect); 42 | else 43 | return rect.WithHeight(0); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /FluidSharp/Animations/State.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluidSharp.Animations 4 | { 5 | public class State 6 | { 7 | 8 | public string Name { get; set; } 9 | 10 | public Animation.Coordinated Animation = new Animation.Coordinated(DateTime.UtcNow); 11 | 12 | public State(string name) => Name = name; 13 | 14 | public bool Started { get; set; } 15 | public bool Completed => Started && Animation.Completed; 16 | 17 | public Animation.Coordinated? AnimationIfStarted => Started ? Animation : null; 18 | 19 | public void Reset() 20 | { 21 | Started = false; 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /FluidSharp/Animations/StateAnimation.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace FluidSharp.Animations 4 | { 5 | public class StateAnimation : Animation 6 | { 7 | 8 | public List States { get; set; } = new List(); 9 | 10 | public State? CurrentState { get; private set; } 11 | 12 | public State Add(State state) 13 | { 14 | States.Add(state); 15 | return state; 16 | } 17 | 18 | public void StartState(State state) 19 | { 20 | state.Animation.Start(); 21 | CurrentState = state; 22 | state.Started = true; 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /FluidSharp/Engine/EngineException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FluidSharp.Engine 6 | { 7 | public class EngineException : Exception 8 | { 9 | public EngineException(string message) : base(message) 10 | { 11 | } 12 | public EngineException(string message, Exception innerException) : base(message, innerException) 13 | { 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /FluidSharp/Engine/MakeWidgetException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluidSharp.Engine 7 | { 8 | public class MakeWidgetException : Exception 9 | { 10 | 11 | private IDictionary Details; 12 | public override IDictionary Data => Details; 13 | 14 | public MakeWidgetException(string message, Exception innerException) : base(message, innerException) 15 | { 16 | Details = innerException?.Data; 17 | } 18 | 19 | public MakeWidgetException(string message, Exception innerException, Dictionary details) : base(message, innerException) 20 | { 21 | Details = details ?? innerException?.Data; 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /FluidSharp/Engine/MeasureException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluidSharp.Engine 7 | { 8 | public class MeasureException : Exception 9 | { 10 | 11 | private Dictionary Details; 12 | public override IDictionary Data => Details; 13 | 14 | public MeasureException(string message, Exception innerException, Dictionary details) : base(message, innerException) 15 | { 16 | Details = details; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /FluidSharp/Engine/PaintException.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Widgets; 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Engine 8 | { 9 | public class PaintException : Exception 10 | { 11 | 12 | 13 | public Widget Widget { get; set; } 14 | 15 | private IDictionary? Details; 16 | public override IDictionary Data => Details ?? new Dictionary(); 17 | 18 | public PaintException(string message, Widget widget, Exception innerException) : base(message, innerException) 19 | { 20 | Widget = widget; 21 | Details = innerException?.Data; 22 | } 23 | 24 | public PaintException(string message, Widget widget, Exception innerException, Dictionary? details) : base(message, innerException) 25 | { 26 | Widget = widget; 27 | Details = details ?? innerException?.Data; 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /FluidSharp/Engine/TapHandlerException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluidSharp.Engine 7 | { 8 | public class TapHandlerException : Exception 9 | { 10 | 11 | private IDictionary Details; 12 | public override IDictionary Data => Details; 13 | 14 | public TapHandlerException(string message, object context, Exception innerException) : base(message, innerException) 15 | { 16 | Details = innerException?.Data ?? new Dictionary(); 17 | Details["TapHandlerContext"] = $"{context}"; 18 | } 19 | 20 | public TapHandlerException(string message, object context, Exception innerException, Dictionary details) : base(message, innerException) 21 | { 22 | Details = details ?? innerException?.Data ?? new Dictionary(); 23 | Details["TapHandlerContext"] = $"{context}"; 24 | } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /FluidSharp/FluidSharp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | true 6 | Wouter Steenbergen 7 | My Daily Bits LLC 8 | FluidSharp is a high performance mobile first multi-platform UI layout framework based on Skia. 9 | 2020-2025 Wouter Steenbergen 10 | 11 | 3.0.1-alpha 12 | enable 13 | true 14 | License.txt 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | True 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /FluidSharp/Interfaces/IBackgroundColorSource.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp 9 | { 10 | 11 | /// 12 | /// Implementations of this interface produce Widgets to be rendered by FluidSharp 13 | /// 14 | public interface IBackgroundColorSource 15 | { 16 | SKColor BackgroundColor { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /FluidSharp/Interfaces/IFluidWidgetView.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Interop; 2 | using FluidSharp.State; 3 | using FluidSharp.Widgets; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp 9 | { 10 | 11 | public interface IFluidWidgetView : IWidgetSource, IBackgroundColorSource 12 | { 13 | 14 | bool AutoSizeHeight { get; } 15 | void SetHeight(float Height); 16 | 17 | INativeViewManager GetNativeViewManager(); 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /FluidSharp/Interfaces/ISkiaView.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Touch; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp 8 | { 9 | public interface ISkiaView 10 | { 11 | 12 | float Width { get; } 13 | float Height { get; } 14 | 15 | SKSize PlatformScale { get; } 16 | 17 | event EventHandler PaintViewSurface; 18 | event EventHandler Touch; 19 | 20 | void InvalidatePaint(); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /FluidSharp/Interfaces/IWidgetSource.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp 8 | { 9 | 10 | /// 11 | /// Implementations of this interface produce Widgets to be rendered by FluidSharp 12 | /// 13 | public interface IWidgetSource 14 | { 15 | Widget MakeWidget(VisualState visualState); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /FluidSharp/Interop/INativeView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FluidSharp.Interop 6 | { 7 | class INativeView 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /FluidSharp/Interop/INativeViewManager.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Widgets.Native; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Interop 8 | { 9 | public interface INativeViewManager 10 | { 11 | 12 | SKSize Measure(NativeViewWidget nativeViewWidget, SKSize boundaries); 13 | 14 | void PaintStarted(); 15 | void UpdateNativeView(NativeViewWidget nativeViewWidget, SKRect rect, SKRect original); 16 | void PaintCompleted(); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /FluidSharp/Interop/ScaledNativeViewManager.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Widgets.Native; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Interop 8 | { 9 | public class ScaledNativeViewManager : INativeViewManager 10 | { 11 | 12 | public SKPoint Factor; 13 | public INativeViewManager InnerManager; 14 | 15 | public ScaledNativeViewManager(SKPoint factor, INativeViewManager innerManager) 16 | { 17 | Factor = factor; 18 | InnerManager = innerManager; 19 | } 20 | 21 | public SKSize Measure(NativeViewWidget nativeViewWidget, SKSize boundaries) 22 | { 23 | var scaledboundaries = new SKSize(boundaries.Width * Factor.X, boundaries.Height * Factor.Y); 24 | var childsize = InnerManager.Measure(nativeViewWidget, scaledboundaries); 25 | return new SKSize(childsize.Width / Factor.X, childsize.Height / Factor.Y); 26 | } 27 | 28 | public void PaintStarted() => InnerManager.PaintStarted(); 29 | 30 | public void UpdateNativeView(NativeViewWidget nativeViewWidget, SKRect rect, SKRect original) 31 | { 32 | var scaled = new SKRect(rect.Left * Factor.X, rect.Top * Factor.Y, rect.Right * Factor.X, rect.Bottom * Factor.Y); 33 | InnerManager.UpdateNativeView(nativeViewWidget, scaled, original); 34 | } 35 | 36 | public void PaintCompleted() => InnerManager.PaintCompleted(); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /FluidSharp/Layouts/Device.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Paint; 2 | using SkiaSharp.TextBlocks.Enum; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp 8 | { 9 | 10 | public class Device 11 | { 12 | 13 | public FlowDirection FlowDirection = FlowDirection.LeftToRight; 14 | 15 | public float FontSizeScale = 1f; 16 | public float LineSpacing = 1f; 17 | public float DefaultScale = 1f; 18 | 19 | public bool PixelRounding = false; 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /FluidSharp/Layouts/MeasureCache.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Interop; 2 | using FluidSharp.Paint.Images; 3 | using SkiaSharp.TextBlocks; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Layouts 9 | { 10 | 11 | /// 12 | /// The Measure Context represents View level layout parameters 13 | /// 14 | public class MeasureCache : IDisposable 15 | { 16 | 17 | public TextShaper TextShaper; 18 | public ImageCache ImageCache; 19 | 20 | public INativeViewManager NativeViewManager; 21 | 22 | public MeasureCache(Device device, Action onDataAvailable, INativeViewManager nativeViewManager) 23 | { 24 | TextShaper = new TextShaper(true, device.FontSizeScale); 25 | ImageCache = new ImageCache(onDataAvailable); 26 | NativeViewManager = nativeViewManager; 27 | } 28 | 29 | public void Dispose() 30 | { 31 | TextShaper.Dispose(); 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /FluidSharp/License.txt: -------------------------------------------------------------------------------- 1 |  Copyright 2022-2025 Wouter Steenbergen 2 | 3 | Licensed for evaluation ("internal development") only. 4 | Not licenced to be distributed as part of a commercially available product. 5 | 6 | You may not use this file except in compliance with the License. 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | -------------------------------------------------------------------------------- /FluidSharp/Navigation/HeroPageTransition.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using FluidSharp.Animations; 3 | using FluidSharp.State; 4 | using FluidSharp.Widgets; 5 | using FluidSharp.Widgets.Animations; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace FluidSharp.Navigation 12 | { 13 | public class HeroPageTransition : IPageTransition 14 | { 15 | 16 | public NavigationTransitionState TransitionState; 17 | public Func OnTransitionCompleted; 18 | 19 | public Task Start() => TransitionState.SetTarget(true, null); 20 | public Task Reverse() => TransitionState.SetTarget(false, null); 21 | 22 | public HeroPageTransition(bool start, Func onTransitionCompleted) 23 | { 24 | OnTransitionCompleted = onTransitionCompleted; 25 | TransitionState = new NavigationTransitionState(start, OnTransitionCompleted); 26 | TransitionState.TransitionDuration = TimeSpan.FromSeconds(1); 27 | } 28 | 29 | public Widget MakeWidget(NavigationContext context, VisualState visualState, IWidgetSource from, IWidgetSource to, Func dismiss) 30 | { 31 | var frame = TransitionState.GetFrame(); 32 | 33 | var transition = HeroTransition.MakeWidget(visualState, frame, (vs, istarget) => !istarget ? from.MakeWidget(vs) : to.MakeWidget(vs)); 34 | //var transition = SlideTransition.MakeWidget(visualState, frame, 0.5f, (vs, istarget) => !istarget ? from.MakeWidget(vs) : to.MakeWidget(vs)); 35 | 36 | return transition; 37 | } 38 | 39 | 40 | } 41 | } 42 | #endif -------------------------------------------------------------------------------- /FluidSharp/Navigation/IPage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace FluidSharp.Navigation 7 | { 8 | public interface IPage : IWidgetSource 9 | { 10 | 11 | public bool CanSlideBack { get; } 12 | 13 | public IPageTransition? GetPageTransition(bool startingstate, Func onTransitionCompleted); 14 | 15 | public Func? PrepareForResurface(); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /FluidSharp/Navigation/IPageTransition.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace FluidSharp.Navigation 9 | { 10 | public interface IPageTransition 11 | { 12 | 13 | public Widget MakeWidget(NavigationContainer navigationContainer, VisualState visualState, IWidgetSource from, IWidgetSource to); 14 | 15 | public Task Start(); 16 | public Task Reverse(); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /FluidSharp/Navigation/NavigationTop.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluidSharp.Navigation 7 | { 8 | public class NavigationTop 9 | { 10 | 11 | private object Context; 12 | public DateTime Started; 13 | 14 | public NavigationTop() { } 15 | 16 | public NavigationTop(object context) 17 | { 18 | Context = context; 19 | Started = DateTime.UtcNow; 20 | } 21 | 22 | public bool IsContext(object context) 23 | { 24 | return TypedContext.ContextEqual(Context, context); 25 | } 26 | 27 | public bool IsContext(object context, bool includederived) 28 | { 29 | return TypedContext.ContextEqual(Context, context, includederived); 30 | } 31 | 32 | public bool IsContext(bool acceptnull) 33 | { 34 | return TypedContext.ContextEqual(Context, acceptnull); 35 | } 36 | 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /FluidSharp/Navigation/NavigationTransitionState.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets; 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | namespace FluidSharp.Navigation 7 | { 8 | public class NavigationTransitionState : TransitionState 9 | { 10 | public NavigationTransitionState(bool startingstate, Func? onTransitionCompleted) : base(startingstate) 11 | { 12 | CurrentDuration = PushPageTransition.DefaultDuration; 13 | _ = SetTarget(!startingstate, default); 14 | if (onTransitionCompleted != null) 15 | { 16 | OnCompleted = () => onTransitionCompleted(Current); 17 | } 18 | } 19 | 20 | public override int GetDirection(bool from, bool to) 21 | { 22 | if (from == to) return 0; 23 | return from ? -1 : 1; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /FluidSharp/Navigation/OverlayPageTransition.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using FluidSharp.Animations; 3 | using FluidSharp.Layouts; 4 | using FluidSharp.State; 5 | using FluidSharp.Touch; 6 | using FluidSharp.Widgets; 7 | using FluidSharp.Widgets.Material; 8 | using SkiaSharp; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | 14 | namespace FluidSharp.Navigation 15 | { 16 | public class OverlayPageTransition : IPageTransition 17 | { 18 | 19 | public SKColor MaskColor; 20 | 21 | public NavigationTransitionState TransitionState; 22 | private Func OnTransitionCompleted2; 23 | 24 | public Task Start() => TransitionState.SetTarget(true, null); 25 | public Task Reverse() => TransitionState.SetTarget(false, null); 26 | 27 | public OverlayPageTransition(bool startingstate, SKColor maskColor, Func onTransitionCompleted) 28 | { 29 | MaskColor = maskColor; 30 | OnTransitionCompleted2 = onTransitionCompleted; 31 | TransitionState = new NavigationTransitionState(startingstate, onTransitionCompleted); 32 | //TransitionState.TransitionDuration = TimeSpan.FromSeconds(2); 33 | } 34 | 35 | public Task OnTransitionCompleted(bool open) => !open ? OnTransitionCompleted2(open) : Task.CompletedTask; 36 | 37 | public Widget MakeWidget(NavigationContext context, VisualState visualState, IWidgetSource from, IWidgetSource to, Func dismiss) 38 | { 39 | 40 | var animation = TransitionState.GetAnimation(Easing.CubicOut); 41 | var popup = to.MakeWidget(visualState); 42 | popup = new HeightTransition(animation, popup, false); 43 | popup = new FadeInElement(animation, popup); 44 | 45 | return new Container(ContainerLayout.Expand, 46 | 47 | from.MakeWidget(visualState), 48 | new HitTestStop(), 49 | Rectangle.Fill(MaskColor.WithOpacity(animation.GetValue())), 50 | 51 | new SplitContainer( 52 | popup, 53 | GestureDetector.TapDetector(visualState, "overlay", dismiss, new Container(ContainerLayout.Expand)) 54 | ) 55 | 56 | ); 57 | 58 | } 59 | 60 | 61 | } 62 | } 63 | #endif -------------------------------------------------------------------------------- /FluidSharp/Navigation/PushPageTransition.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Animations; 2 | using FluidSharp.State; 3 | using FluidSharp.Widgets; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace FluidSharp.Navigation 10 | { 11 | public class PushPageTransition : IPageTransition 12 | { 13 | 14 | public const float PushOverlap = .5f; 15 | 16 | public NavigationTransitionState TransitionState; 17 | public Func OnTransitionCompleted; 18 | 19 | public static TimeSpan DefaultDuration = TimeSpan.FromMilliseconds(250); 20 | public static Easing? DefaultEasing = null; 21 | 22 | public Task Start() => TransitionState.SetTarget(true, null); 23 | public Task Reverse() => TransitionState.SetTarget(false, null); 24 | 25 | public PushPageTransition(bool start, Func onTransitionCompleted) 26 | { 27 | OnTransitionCompleted = onTransitionCompleted; 28 | TransitionState = new NavigationTransitionState(start, OnTransitionCompleted) { Easing = DefaultEasing }; 29 | } 30 | 31 | public Widget MakeWidget(NavigationContainer navigationContainer, VisualState visualState, IWidgetSource from, IWidgetSource to) 32 | { 33 | var frame = TransitionState.GetFrame(); 34 | return SlideTransition.MakeWidget(visualState, frame, PushOverlap, (vs, istarget) => 35 | { 36 | var widgetsource = (istarget ? to : from) ?? to ?? from; 37 | return widgetsource.MakeWidget(vs); 38 | }); 39 | } 40 | 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /FluidSharp/Paint/FluidSharpStyle.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluidSharp.Paint 7 | { 8 | public class FluidSharpStyle 9 | { 10 | public static SKColor TapStartBackgroundColor = SKColors.LightGray.WithAlpha(128); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /FluidSharp/Paint/Images/FileImageSource.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Runtime.CompilerServices; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace FluidSharp.Paint.Images 13 | { 14 | public class FileImageSource : ImageSource 15 | { 16 | 17 | public string Path; 18 | 19 | public FileImageSource(string name, string path) : base(name) 20 | { 21 | Path = path; 22 | } 23 | 24 | public override SKImage? GetImage() 25 | { 26 | if (File.Exists(Path)) 27 | { 28 | using (var stream = File.OpenRead(Path)) 29 | { 30 | if (stream.Length == 0) return null; 31 | var image = SKImage.FromBitmap(SKBitmap.Decode(stream)); 32 | return image; 33 | } 34 | } 35 | 36 | return null; 37 | 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /FluidSharp/Paint/Images/ImageSource.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | using System.Runtime.CompilerServices; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Paint.Images 9 | { 10 | 11 | public abstract class ImageSource 12 | { 13 | 14 | public readonly string Name; 15 | 16 | public abstract SKImage GetImage(); 17 | 18 | public ImageSource(string name) => Name = name; 19 | 20 | //public static ImageSource FromFile(string file); 21 | //public static ImageSource FromResource(string resource, Type resolvingType); 22 | //public static ImageSource FromResource(string resource, Assembly sourceAssembly = null); 23 | //public static ImageSource FromStream(Func stream); 24 | 25 | 26 | [MethodImpl(MethodImplOptions.NoInlining)] 27 | public static implicit operator ImageSource(string resource) => new ResourceImageSource(resource, Assembly.GetCallingAssembly()); 28 | 29 | //public static implicit operator ImageSource(string resource) => new FileImageSource(resource); 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /FluidSharp/Paint/Images/ResourceImageSource.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Runtime.CompilerServices; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace FluidSharp.Paint.Images 12 | { 13 | public class ResourceImageSource : ImageSource 14 | { 15 | 16 | private Assembly Assembly; 17 | 18 | [MethodImpl(MethodImplOptions.NoInlining)] 19 | public ResourceImageSource(string name) : base(name) 20 | { 21 | if (name == "-1932644951.553218622") 22 | throw new Exception(); 23 | Assembly = Assembly.GetCallingAssembly(); 24 | } 25 | 26 | public ResourceImageSource(string name, Assembly assembly) : base(name) 27 | { 28 | if (name == "-1932644951.553218622") 29 | throw new Exception(); 30 | Assembly = assembly; 31 | } 32 | 33 | public override SKImage GetImage() 34 | { 35 | 36 | var resourcenames = Assembly.GetManifestResourceNames(); 37 | var fullname = resourcenames.FirstOrDefault(f => f.EndsWith(Name)); 38 | 39 | if (fullname == null) 40 | throw new Exception($"Resource not found: {Name}"); 41 | 42 | using (var stream = Assembly.GetManifestResourceStream(fullname)) 43 | { 44 | var image = SKImage.FromBitmap(SKBitmap.Decode(stream)); 45 | return image; 46 | } 47 | 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /FluidSharp/Paint/Images/ResourcePictureSource.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using SkiaSharp; 3 | using Svg.Skia; 4 | using System; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Runtime.CompilerServices; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace FluidSharp.Paint.Images 14 | { 15 | public class ResourcePictureSource : ImageSource 16 | { 17 | 18 | private Assembly Assembly; 19 | 20 | [MethodImpl(MethodImplOptions.NoInlining)] 21 | public ResourceImageSource(string name) : base(name) 22 | { 23 | Assembly = Assembly.GetCallingAssembly(); 24 | } 25 | 26 | public ResourceImageSource(string name, Assembly assembly) : base(name) 27 | { 28 | Assembly = assembly; 29 | } 30 | 31 | public override SKImage GetImage() 32 | { 33 | 34 | var resourcenames = Assembly.GetManifestResourceNames(); 35 | var fullname = resourcenames.FirstOrDefault(f => f.EndsWith(Name)); 36 | 37 | if (fullname == null) 38 | throw new Exception($"Resource not found: {Name}"); 39 | 40 | using (var stream = Assembly.GetManifestResourceStream(fullname)) 41 | { 42 | if (fullname.EndsWith(".svg")) 43 | { 44 | var svg = new SKSvg(); 45 | var picture = svg.Load(stream); 46 | var rect = svg.Picture.CullRect; 47 | return SKImage.FromPicture(svg.Picture, rect.Size.ToSizeI()); 48 | } 49 | else 50 | { 51 | var image = SKImage.FromBitmap(SKBitmap.Decode(stream)); 52 | return image; 53 | } 54 | } 55 | 56 | } 57 | 58 | } 59 | } 60 | #endif -------------------------------------------------------------------------------- /FluidSharp/Paint/PaintSurfaceEventArgs.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluidSharp 7 | { 8 | public class PaintSurfaceEventArgs 9 | { 10 | public SKCanvas Canvas; 11 | public float Width; 12 | public float Height; 13 | public SKSurface Surface; 14 | public SKImageInfo Info; 15 | 16 | public PaintSurfaceEventArgs(SKCanvas canvas, float width, float height, SKSurface surface, SKImageInfo info) 17 | { 18 | Canvas = canvas; 19 | Width = width; 20 | Height = height; 21 | Surface = surface; 22 | Info = info; 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /FluidSharp/Paint/SKPaintExtensions.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluidSharp 7 | { 8 | 9 | //public class SKPaint 10 | //{ 11 | // private SKPaint() { } 12 | //} 13 | 14 | public static class SKPaintExtensions 15 | { 16 | 17 | public static SKColor MixColor(this SKColor color1, SKColor color2, float twopct) 18 | { 19 | if (twopct <= 0) return color1; 20 | if (twopct >= 1) return color2; 21 | var onepct = 1 - twopct; 22 | return new SKColor(Mix(color1.Red, color2.Red), Mix(color1.Green, color2.Green), Mix(color1.Blue, color2.Blue), Mix(color1.Alpha, color2.Alpha)); 23 | byte Mix(byte c1, byte c2) => (byte)(c1 * onepct + c2 * twopct); 24 | } 25 | 26 | public static SKColor WithOpacity(this SKColor color, float opacity) => opacity >= 1 ? color : color.WithAlpha((byte)(opacity * color.Alpha)); 27 | 28 | public static bool IsLight(this SKColor color) 29 | { 30 | color.ToHsl(out var h, out var s, out var l); 31 | return l > 60f; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /FluidSharp/SkiaSharp.FlowUI.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29806.167 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.FlowUI", "SkiaSharp.FlowUI.csproj", "{0E04262C-69B8-4D4F-B55E-071283B6A766}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.TextBlock", "..\..\..\SkiaSharp.TextBlock\source\SkiaSharp.TextBlock\SkiaSharp.TextBlock.csproj", "{2C25F2AA-A645-4315-9DCD-DE0C1E939F00}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0E04262C-69B8-4D4F-B55E-071283B6A766}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {0E04262C-69B8-4D4F-B55E-071283B6A766}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {0E04262C-69B8-4D4F-B55E-071283B6A766}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {0E04262C-69B8-4D4F-B55E-071283B6A766}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {2C25F2AA-A645-4315-9DCD-DE0C1E939F00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {2C25F2AA-A645-4315-9DCD-DE0C1E939F00}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {2C25F2AA-A645-4315-9DCD-DE0C1E939F00}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {2C25F2AA-A645-4315-9DCD-DE0C1E939F00}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {8D1D8DA7-CD11-414F-B03D-0A124AAFDCE8} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /FluidSharp/State/LastTapped.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FluidSharp.State 6 | { 7 | public class LastTapped 8 | { 9 | 10 | public object Context; 11 | public DateTime Tapped; 12 | 13 | private LastTapped(object context) 14 | { 15 | Context = context; 16 | Tapped = DateTime.UtcNow; 17 | } 18 | 19 | public static void SetContext(VisualState visualState, object context) 20 | { 21 | if (!(context is TapContext)) 22 | throw new ArgumentOutOfRangeException("LastTapped context must be of type TapContext"); 23 | visualState["lasttapped"] = new LastTapped(context); 24 | } 25 | 26 | public static DateTime? ForContext(VisualState visualState, object context) 27 | { 28 | var lasttapped = visualState.GetOrDefault("lasttapped"); 29 | //System.Diagnostics.Debug.WriteLine($"{lasttapped?.Context} - {context}"); 30 | if (lasttapped != null && TypedContext.ContextEqual(lasttapped.Context, context, false)) 31 | return lasttapped.Tapped; 32 | else 33 | return null; 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /FluidSharp/State/OptionBarState.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Animations; 2 | using FluidSharp.Engine; 3 | using FluidSharp.Widgets; 4 | using SkiaSharp; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using static FluidSharp.Widgets.Scrollable; 10 | 11 | namespace FluidSharp.State 12 | { 13 | public class OptionBarState 14 | { 15 | 16 | public int AtScrollStart; 17 | public int Current; 18 | public DateTime? ScrollStart; 19 | 20 | public TimeSpan ScrollDuration => TimeSpan.FromMilliseconds(350); 21 | 22 | public OptionBarState(int value) 23 | { 24 | Current = value; 25 | } 26 | 27 | public void SetCurrent(int value) 28 | { 29 | if (Current == value) return; 30 | AtScrollStart = Current; 31 | Current = value; 32 | ScrollStart = DateTime.UtcNow; 33 | } 34 | 35 | public (float scroll, bool isanimating) GetScroll() 36 | { 37 | 38 | if (ScrollStart.HasValue) 39 | { 40 | var d = (float)(DateTime.UtcNow.Subtract(ScrollStart.Value).TotalMilliseconds / ScrollDuration.TotalMilliseconds); 41 | 42 | if (d > 1) 43 | return (Current, false); 44 | 45 | d = Easing.CubicOut.Ease(d); 46 | var scroll = AtScrollStart + (Current - AtScrollStart) * d; 47 | 48 | return (scroll, true); 49 | } 50 | else 51 | { 52 | return (Current, false); 53 | } 54 | 55 | } 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /FluidSharp/State/SliderState.cs: -------------------------------------------------------------------------------- 1 | //using FluidSharp.Animations; 2 | //using FluidSharp.Touch; 3 | //using FluidSharp.Widgets; 4 | //using FluidSharp.Widgets.CrossPlatform; 5 | //using SkiaSharp; 6 | //using System; 7 | //using System.Collections.Generic; 8 | //using System.Text; 9 | //using System.Threading.Tasks; 10 | 11 | //namespace FluidSharp.State 12 | //{ 13 | // public class SliderState 14 | // { 15 | 16 | // private object Context; 17 | 18 | // public SKPoint Location; 19 | 20 | // public SliderState() { } 21 | 22 | // public bool IsContext(object context) 23 | // { 24 | // if (Context == null) return context == null; 25 | // return Context.Equals(context); 26 | // } 27 | 28 | // public async Task SetTouchPoint(object context, SKPoint location, VisualState visualState) 29 | // { 30 | 31 | // Context = context; 32 | // Location = location; 33 | 34 | // await visualState.RequestRedraw(); 35 | 36 | // } 37 | 38 | // } 39 | //} 40 | -------------------------------------------------------------------------------- /FluidSharp/State/SwitchState.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Animations; 2 | using FluidSharp.Engine; 3 | using FluidSharp.Widgets; 4 | using SkiaSharp; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using static FluidSharp.Widgets.Scrollable; 10 | 11 | namespace FluidSharp.State 12 | { 13 | public class SwitchState : TransitionState 14 | { 15 | 16 | public DateTime? LastSwitched; 17 | 18 | public SwitchState(bool startingstate, Func onSettingChanged) : base(startingstate) 19 | { 20 | TransitionDuration = TimeSpan.FromMilliseconds(125);// SlideTransition.DefaultDuration; 21 | OnCompleted = () => onSettingChanged(Current); 22 | } 23 | 24 | public override int GetDirection(bool from, bool to) 25 | { 26 | if (from == to) return 0; 27 | return from ? -1 : 1; 28 | } 29 | 30 | public override Animation GetAnimation(Easing easing) 31 | { 32 | 33 | var current = Current; 34 | var target = Target; 35 | 36 | var min = target ? 0 : 1; 37 | var delta = target ? 1 : -1; 38 | 39 | if (current == target) 40 | return new Animation(AnimationStart, CurrentDuration, min, min + delta, easing); 41 | else 42 | return new Animation(AnimationStart, CurrentDuration, min, min + delta, easing, () => Progress(GetFrame())); 43 | 44 | } 45 | 46 | public Task Toggle() => SetTarget(!Target, null); 47 | 48 | 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /FluidSharp/Touch/EditTarget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace FluidSharp.Touch 9 | { 10 | public class EditTarget 11 | { 12 | 13 | private object? Context; 14 | public Func> EndEdit; 15 | 16 | public EditTarget() { Context = null; EndEdit = (validate) => Task.FromResult(true); } 17 | public EditTarget(object context) { Context = context; EndEdit = (validate) => Task.FromResult(true); } 18 | public EditTarget(object context, Func> endEdit) 19 | { 20 | Context = context ?? throw new ArgumentNullException(nameof(context)); 21 | EndEdit = endEdit ?? throw new ArgumentNullException(nameof(endEdit)); 22 | } 23 | 24 | public bool IsContext(object context) 25 | { 26 | return TypedContext.ContextEqual(Context, context); 27 | } 28 | 29 | public bool IsContext(object context, bool includederived) 30 | { 31 | return TypedContext.ContextEqual(Context, context, includederived); 32 | } 33 | 34 | public bool IsContext(bool acceptnull) 35 | { 36 | return TypedContext.ContextEqual(Context, acceptnull); 37 | } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /FluidSharp/Touch/HitTestHit.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Widgets; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Touch 8 | { 9 | public class HitTestHit 10 | { 11 | 12 | public Device Device; 13 | public Widget Widget; 14 | public SKPoint LocationInWidget; 15 | public SKRect WidgetRect; 16 | public SKPoint Scale; 17 | 18 | public HitTestHit(Device device, Widget widget, SKPoint locationInWidget, SKRect widgetRect, SKPoint scale) 19 | { 20 | Device = device; 21 | Widget = widget; 22 | LocationInWidget = locationInWidget; 23 | WidgetRect = widgetRect; 24 | Scale = scale; 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /FluidSharp/Touch/HitTestStop.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using FluidSharp.Widgets; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Touch 9 | { 10 | public class HitTestStop : Widget 11 | { 12 | 13 | public Widget? Contents; 14 | 15 | public HitTestStop(Widget? contents = null) => Contents = contents; 16 | 17 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => Contents == null ? new SKSize(0, 0) : Contents.Measure(measureCache, boundaries); 18 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) => Contents == null ? rect.WithHeight(0) : layoutsurface.Paint(Contents, rect); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FluidSharp/Touch/TouchActionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | 7 | // all credit to https://github.com/xamarin/xamarin-forms-samples/tree/master/Effects/TouchTrackingEffect/TouchTrackingEffect/TouchTrackingEffect 8 | 9 | 10 | namespace FluidSharp.Touch 11 | { 12 | public class TouchActionEventArgs 13 | { 14 | 15 | public long PointerId; 16 | public TouchActionType Type; 17 | public SKPoint LocationOnDevice; 18 | public SKPoint LocationInView; 19 | public SKSize ViewSize; 20 | public bool IsInContact; 21 | 22 | public TouchActionEventArgs(long id, TouchActionType type, SKPoint locationOnDevice, SKPoint locationInView, SKSize viewSize, bool isInContact) 23 | { 24 | PointerId = id; 25 | Type = type; 26 | LocationOnDevice = locationOnDevice; 27 | LocationInView = locationInView; 28 | ViewSize = viewSize; 29 | IsInContact = isInContact; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /FluidSharp/Touch/TouchActionType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FluidSharp.Touch 6 | { 7 | public enum TouchActionType 8 | { 9 | Entered, 10 | Pressed, 11 | Moved, 12 | Released, 13 | Exited, 14 | Cancelled 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /FluidSharp/Touch/TouchTarget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Touch 8 | { 9 | public class TouchTarget 10 | { 11 | 12 | private object Context; 13 | public DateTime Started; 14 | public SKPoint LocationOnWidget; 15 | 16 | public TouchTarget() { } 17 | 18 | public TouchTarget(object context, SKPoint locationOnWidget) 19 | { 20 | Context = context; 21 | Started = DateTime.UtcNow; 22 | LocationOnWidget = locationOnWidget; 23 | } 24 | 25 | public bool IsContext(object context) 26 | { 27 | return TypedContext.ContextEqual(Context, context); 28 | } 29 | 30 | public bool IsContext(object context, bool includederived) 31 | { 32 | return TypedContext.ContextEqual(Context, context, includederived); 33 | } 34 | 35 | public bool IsContext(bool acceptnull) 36 | { 37 | return TypedContext.ContextEqual(Context, acceptnull); 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Animations/AnimatedRectangle.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Animations; 2 | using FluidSharp.Layouts; 3 | using FluidSharp.Paint; 4 | using SkiaSharp; 5 | using SkiaSharp.TextBlocks.Enum; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace FluidSharp.Widgets 11 | { 12 | 13 | public partial class Rectangle 14 | { 15 | 16 | public static Widget FillAnimated(IAnimation animation, Func getColor) 17 | { 18 | var value = animation.GetValue(); 19 | var rectangle = Rectangle.Fill(getColor(value)); 20 | return new AnimatedWidget(animation, rectangle, p => rectangle.BackgroundColor = getColor(p)); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Animations/AnimatedWidgets.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Animations; 2 | using FluidSharp.Layouts; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace FluidSharp.Widgets 10 | { 11 | public class AnimatedWidget : Widget 12 | { 13 | 14 | public IAnimation Animation; 15 | 16 | public Widget? Contents; 17 | 18 | public Action? UpdateContents; 19 | 20 | public AnimatedWidget(IAnimation animation, Widget? contents) 21 | { 22 | Animation = animation; 23 | Contents = contents; 24 | } 25 | 26 | public AnimatedWidget(IAnimation animation, Widget? contents, Action updateContents) 27 | { 28 | Animation = animation; 29 | Contents = contents; 30 | UpdateContents = updateContents; 31 | } 32 | 33 | 34 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => Contents?.Measure(measureCache, boundaries) ?? new SKSize(); 35 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 36 | { 37 | if (UpdateContents != null) 38 | { 39 | UpdateContents(Animation.GetValue()); 40 | } 41 | // don't do it here, because this class may be inherited 42 | //if (!Animation.Completed) layoutsurface.SetHasActiveAnimations(); 43 | return Contents == null ? rect : layoutsurface.Paint(Contents, rect); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Animations/FadeInPicture.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Animations; 2 | using FluidSharp.Layouts; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Widgets.Animations 9 | { 10 | public class FadeInPicture : Widget 11 | { 12 | 13 | public IAnimation Animation { get; set; } 14 | public Picture Picture { get; set; } 15 | 16 | public FadeInPicture(IAnimation animation, Picture picture) 17 | { 18 | Animation = animation; 19 | var startingOpacity = animation.GetValue(); 20 | Picture = picture.WithOpacity(startingOpacity); 21 | } 22 | 23 | 24 | 25 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => Picture.Measure(measureCache, boundaries); 26 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 27 | { 28 | Picture.Opacity = Animation.GetValue(); 29 | if (!Animation.Completed) 30 | layoutsurface.SetHasActiveAnimations(); 31 | return layoutsurface.Paint(Picture, rect); 32 | } 33 | 34 | } 35 | 36 | 37 | //public class FadeInElement2 : Widget 38 | //{ 39 | 40 | // public Widget Contents; 41 | 42 | // public Animation? Animation { get; set; } 43 | // public Action SetAnimation { get; set; } 44 | 45 | // public FadeInElement2(Widget contents, Action setAnimation) 46 | // { 47 | // Contents = contents; 48 | // SetAnimation = setAnimation; 49 | // } 50 | 51 | 52 | // public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => Contents.Measure(measureCache, boundaries); 53 | // public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 54 | // { 55 | // if (Animation != null) 56 | // { 57 | // Opacity.Factor = Animation.GetValue(); 58 | // if (!Animation.Completed) 59 | // layoutsurface.SetHasActiveAnimations(); 60 | // } 61 | // return layoutsurface.Paint(Opacity, rect); 62 | // } 63 | //} 64 | } 65 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Blur.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using FluidSharp.Layouts; 3 | using FluidSharp.Paint; 4 | using SkiaSharp; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace FluidSharp.Widgets 10 | { 11 | public class Blur : Widget 12 | { 13 | 14 | public float Sigma { get; set; } 15 | public Widget Contents { get; set; } 16 | 17 | public Blur(float sigma, Widget contents) 18 | { 19 | Sigma = sigma; 20 | Contents = contents ?? throw new ArgumentNullException(nameof(contents)); 21 | } 22 | 23 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => Contents.Measure(measureCache, boundaries); 24 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 25 | { 26 | 27 | if (layoutsurface.Canvas == null || Sigma == 0) 28 | return layoutsurface.Paint(Contents, rect); 29 | 30 | using (var recorder = new SKPictureRecorder()) 31 | { 32 | 33 | var originalcanvas = layoutsurface.Canvas; 34 | var recording = recorder.BeginRecording(rect); 35 | layoutsurface.SetCanvas(recording); 36 | 37 | var result = layoutsurface.Paint(Contents, rect); 38 | 39 | var recorded = recorder.EndRecordingAsDrawable().Snapshot(); 40 | 41 | layoutsurface.SetCanvas(originalcanvas); 42 | 43 | using (var filter = SKImageFilter.CreateBlur(Sigma, Sigma)) 44 | { 45 | var paint = PaintCache.GetBackgroundPaint(SKColors.Red, true, () => filter); 46 | originalcanvas.DrawPicture(recorded, paint); 47 | } 48 | 49 | return result; 50 | 51 | } 52 | 53 | } 54 | 55 | } 56 | } 57 | #endif -------------------------------------------------------------------------------- /FluidSharp/Widgets/Caching/CachedWidget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets.Caching 8 | { 9 | public class CachedWidget : Widget 10 | { 11 | 12 | private Func GetValue; 13 | private Func MakeWidget; 14 | 15 | private TValue LastValue; 16 | private Widget? Widget; 17 | 18 | private Widget GetWidget() 19 | { 20 | var value = GetValue(); 21 | #if DEBUG 22 | if (value == null) throw new ArgumentOutOfRangeException("value"); 23 | #endif 24 | if (Widget is null || !value.Equals(LastValue)) 25 | { 26 | Widget = MakeWidget(value); 27 | LastValue = value; 28 | } 29 | return Widget; 30 | } 31 | 32 | public CachedWidget(Func getValue, Func makeWidget) 33 | { 34 | GetValue = getValue ?? throw new ArgumentNullException(nameof(getValue)); 35 | MakeWidget = makeWidget ?? throw new ArgumentNullException(nameof(makeWidget)); 36 | LastValue = getValue(); 37 | Widget = MakeWidget(LastValue); 38 | } 39 | 40 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => GetWidget().Measure(measureCache, boundaries); 41 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) => layoutsurface.Paint(GetWidget(), rect); 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Carousel.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace FluidSharp.Widgets 8 | { 9 | public class Carousel 10 | { 11 | 12 | //public static Widget Make(VisualState visualState, CarouselState stateTransition, Func makevaluewidget) 13 | //{ 14 | // return GestureDetector.HorizontalPanDetector(visualState, stateTransition, 15 | // SlideTransition.MakeWidget(visualState, stateTransition.GetFrame(), makevaluewidget) 16 | // ); 17 | //} 18 | 19 | public static Widget Make(VisualState visualState, CarouselState stateTransition, TransitionFrame frame, float spacing, Widget separator, Func makevaluewidget) 20 | { 21 | return GestureDetector.HorizontalPanDetector(visualState, stateTransition, 22 | SlideTransition.MakeWidget(visualState, frame, spacing, 0, separator, makevaluewidget) 23 | ); 24 | } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Center.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets 8 | { 9 | 10 | public class Center : Widget 11 | { 12 | 13 | public Widget Child; 14 | 15 | public Center(Widget child) 16 | { 17 | Child = child ?? throw new ArgumentNullException(nameof(child)); 18 | } 19 | 20 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 21 | { 22 | return Child.Measure(measureCache, boundaries); 23 | } 24 | 25 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 26 | { 27 | 28 | var childsize = Child.Measure(layoutsurface.MeasureCache, new SKSize(rect.Width, rect.Height)); 29 | 30 | var xm = rect.Left + rect.Width / 2; 31 | var ym = rect.Top + rect.Height / 2; 32 | 33 | var childrect = new SKRect(xm - childsize.Width / 2, ym - childsize.Height / 2, xm + childsize.Width / 2, ym + childsize.Height / 2); 34 | layoutsurface.Paint(Child, childrect); 35 | 36 | return rect; 37 | } 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/CenterHorizontal.cs: -------------------------------------------------------------------------------- 1 | #define SHOWSPACING 2 | using FluidSharp.Layouts; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Widgets 9 | { 10 | 11 | public class CenterHorizontal : Widget 12 | { 13 | 14 | public Widget Child; 15 | public Margins Margin; 16 | 17 | public CenterHorizontal(Widget child) 18 | { 19 | Child = child ?? throw new ArgumentNullException(nameof(child)); 20 | } 21 | 22 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 23 | { 24 | var size = Child.Measure(measureCache, Margin.Shrink(boundaries)); 25 | return Margin.Grow(size); 26 | } 27 | 28 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 29 | { 30 | 31 | var childrect = Margin.Shrink(rect, layoutsurface.FlowDirection); 32 | 33 | var childsize = Child.Measure(layoutsurface.MeasureCache, new SKSize(childrect.Width, childrect.Height)); 34 | 35 | var xm = rect.MidX; 36 | 37 | childrect = new SKRect(xm - childsize.Width / 2, childrect.Top, xm + childsize.Width / 2, childrect.Top + childsize.Height); 38 | layoutsurface.Paint(Child, childrect); 39 | 40 | #if SHOWSPACING 41 | layoutsurface.DebugMargin(childrect, Margin, SKColors.YellowGreen); 42 | #endif 43 | return rect.WithHeight(childsize.Height + Margin.TotalY); 44 | } 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/CenterRotate.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets 8 | { 9 | public class CenterRotate : Widget 10 | { 11 | 12 | public float Degrees { get; set; } 13 | public Widget InnerWidget { get; set; } 14 | 15 | public CenterRotate(float degrees, Widget innerWidget) 16 | { 17 | Degrees = degrees; 18 | InnerWidget = innerWidget; 19 | } 20 | 21 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => InnerWidget.Measure(measureCache, boundaries); 22 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 23 | { 24 | var canvas = layoutsurface.Canvas; 25 | if (canvas != null) 26 | { 27 | canvas.Save(); 28 | canvas.RotateDegrees(Degrees, rect.MidX, rect.MidY); 29 | } 30 | 31 | var result = layoutsurface.Paint(InnerWidget, rect); 32 | 33 | if (canvas != null) 34 | canvas.Restore(); 35 | 36 | return result; 37 | 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/CrossPlatform/CrossButton.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets.Material; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace FluidSharp.Widgets.CrossPlatform 9 | { 10 | public class CrossButton 11 | { 12 | 13 | 14 | public static Widget Make(PlatformStyle platformStyle, VisualState visualState, object context, Func onTapped, bool enabled, Widget child) 15 | { 16 | if (!enabled) return child; 17 | return Make(platformStyle, visualState, context, onTapped, child); 18 | } 19 | 20 | public static Widget Make(PlatformStyle platformStyle, VisualState visualState, object context, Func onTapped, Widget child) 21 | { 22 | if (child == null) return null; 23 | 24 | if (platformStyle == PlatformStyle.Material) 25 | return new InkWell(ContainerLayout.FillHorizontal, visualState, context, platformStyle.InkWellColor, onTapped, child); 26 | 27 | //if (platformStyle == PlatformStyle.Cupertino) 28 | return FlatButton.FillHorizontal(visualState, context, platformStyle.FlatButtonSelectedBackgroundColor, onTapped, child); 29 | 30 | //if (platformStyle == PlatformStyle.UWP) 31 | //return FlatButton.FillHorizontal(visualState, context, platformStyle.FlatButtonSelectedBackgroundColor, onTapped, child); 32 | 33 | //throw new ArgumentOutOfRangeException(); 34 | } 35 | 36 | public static Widget MakeWithLongTapped(PlatformStyle platformStyle, VisualState visualState, object context, Func onTapped, Func? onLongTapped, Widget child) 37 | { 38 | if (child == null) return null; 39 | 40 | if (platformStyle == PlatformStyle.Material) 41 | return new InkWell(ContainerLayout.FillHorizontal, visualState, context, platformStyle.InkWellColor, onTapped, onLongTapped, child); 42 | 43 | return FlatButton.FillHorizontal(visualState, context, platformStyle.FlatButtonSelectedBackgroundColor, onTapped, child, onLongTapped); 44 | 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/CrossPlatform/SelectableButtonWidget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace FluidSharp.Widgets.CrossPlatform 9 | { 10 | public class SelectableButtonWidget 11 | { 12 | 13 | public static Widget Make(PlatformStyle platformStyle, VisualState visualState, object context, Widget contents, bool ischecked, SKColor selectedcolor, Func onTapped, ContainerLayout containerLayout = ContainerLayout.FillHorizontal) 14 | { 15 | 16 | var istouchtarget = visualState.TouchTarget.IsContext(context, false); 17 | var hasbackground = istouchtarget || ischecked; 18 | var backgroundcolor = hasbackground ? 19 | (istouchtarget ? platformStyle.FlatButtonSelectedBackgroundColor : selectedcolor) 20 | : default; 21 | 22 | var innerwidget = new Container(containerLayout) 23 | { 24 | MinimumSize = new SKSize(0, 10), 25 | Children = 26 | { 27 | hasbackground ? Rectangle.Fill(backgroundcolor) : null, 28 | Align.Center(contents) 29 | } 30 | }; 31 | 32 | return GestureDetector.TapDetector(visualState, context, onTapped, null, innerwidget); 33 | } 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/CrossPlatform/ShortList.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets.Members; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace FluidSharp.Widgets.CrossPlatform 11 | { 12 | public class ShortList 13 | { 14 | 15 | public static Widget Make(PlatformStyle platformStyle, VisualState visualState, object context, IEnumerable items, Func isItemSelected, SKColor selectedColor, Func onItemSelected, Func makeItemWidget) 16 | { 17 | return new Scrollable(visualState, context, platformStyle.DefaultOverscrollBehavior, 18 | new Column(0) 19 | { 20 | Separator = platformStyle.Separator, 21 | Children = items.Select( 22 | item => SelectableButtonWidget.Make(platformStyle, visualState, item, 23 | makeItemWidget(item), isItemSelected(item), selectedColor, () => onItemSelected(item)) 24 | ).ToFixableList() 25 | } 26 | ) 27 | { ClipContents = true }; 28 | } 29 | 30 | public static Widget Make(PlatformStyle platformStyle, VisualState visualState, object context, IEnumerable items, Func isItemSelected, SKColor selectedColor, Func onItemSelected, Func makeItemWidget, Widget? header, Widget? footer) 31 | { 32 | var column = 33 | new Column(0) 34 | { 35 | Separator = platformStyle.Separator, 36 | Children = items.Select( 37 | item => SelectableButtonWidget.Make(platformStyle, visualState, item, 38 | makeItemWidget(item), isItemSelected(item), selectedColor, () => onItemSelected(item)) 39 | ).ToFixableList() 40 | }; 41 | if (header != null) column.Children.Insert(0, header); 42 | if (footer != null) column.Children.Add(footer); 43 | return new Scrollable(visualState, context, platformStyle.DefaultOverscrollBehavior, column) 44 | { ClipContents = true }; 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Cupertino/CupertinoApp.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets.Cupertino 8 | { 9 | public class CupertinoApp : Widget 10 | { 11 | 12 | public Widget Child; 13 | 14 | public CupertinoApp(Widget contents) 15 | { 16 | Child = new Layout() 17 | { 18 | Rows = 19 | { 20 | LayoutSize.Absolute(30), 21 | LayoutSize.Remaining 22 | }, 23 | Cells = 24 | { 25 | new LayoutCell(0,1, contents) 26 | } 27 | }; 28 | } 29 | 30 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => Child.Measure(measureCache, boundaries); 31 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) => layoutsurface.Paint(Child, rect); 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Hero.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using FluidSharp.Layouts; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Widgets 9 | { 10 | public class Hero : Widget 11 | { 12 | 13 | public string Tag { get; set; } 14 | public Widget Child { get; set; } 15 | 16 | public Hero(string tag, Widget child) 17 | { 18 | Tag = tag ?? throw new ArgumentNullException(nameof(tag)); 19 | Child = child ?? throw new ArgumentNullException(nameof(child)); 20 | } 21 | 22 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => Child.Measure(measureCache, boundaries); 23 | 24 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 25 | { 26 | return layoutsurface.Paint(Child, rect); 27 | } 28 | 29 | } 30 | } 31 | #endif -------------------------------------------------------------------------------- /FluidSharp/Widgets/HorizontalAlignment.cs: -------------------------------------------------------------------------------- 1 | namespace FluidSharp.Widgets 2 | { 3 | public enum HorizontalAlignment 4 | { 5 | Near, 6 | Center, 7 | Far, 8 | Expand 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/LayoutCell.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets 8 | { 9 | public class LayoutCell : Widget 10 | { 11 | 12 | public bool Debug; 13 | 14 | public int Column; 15 | public int Row; 16 | 17 | public int ColumnSpan; 18 | public int RowSpan; 19 | 20 | public Widget? Child; 21 | 22 | public HorizontalAlignment HorizontalAlignment; 23 | 24 | public LayoutCell(int column, int row, Widget? child, HorizontalAlignment horizontalAlignment = HorizontalAlignment.Near) : this(column, row, 1, 1, child, horizontalAlignment) 25 | { 26 | } 27 | 28 | public LayoutCell(int column, int row, int columnSpan, int rowSpan, Widget? child, HorizontalAlignment horizontalAlignment = HorizontalAlignment.Near) 29 | { 30 | Column = column; 31 | Row = row; 32 | ColumnSpan = columnSpan; 33 | RowSpan = rowSpan; 34 | Child = child; 35 | HorizontalAlignment = horizontalAlignment; 36 | } 37 | 38 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => Child?.Measure(measureCache, boundaries) ?? new SKSize(); 39 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 40 | { 41 | if (Child == null) 42 | return new SKRect(rect.Left, rect.Top, rect.Right, rect.Top); 43 | 44 | if (HorizontalAlignment == HorizontalAlignment.Near) 45 | { 46 | // near, no measure needed 47 | var result = layoutsurface.Paint(Child, rect); 48 | if (Debug) 49 | layoutsurface.DebugRect(rect, SKColors.Red); 50 | return result; 51 | } 52 | else 53 | { 54 | // center or far 55 | var childsize = Child.Measure(layoutsurface.MeasureCache, rect.Size); 56 | var childrect = rect.HorizontalAlign(childsize, HorizontalAlignment, layoutsurface.Device.FlowDirection); 57 | 58 | var result = layoutsurface.Paint(Child, childrect); 59 | if (Debug) 60 | layoutsurface.DebugRect(childrect, SKColors.Red); 61 | return result; 62 | } 63 | 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/LongList.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets.CrossPlatform; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace FluidSharp.Widgets 9 | { 10 | 11 | /// 12 | /// A long list widget is similar to 13 | /// 14 | public class LongList 15 | { 16 | 17 | public static Widget Make(PlatformStyle platformStyle, VisualState visualState, object context, IList items, float itemHeight, Func onItemSelected, Func makeItemWidget, bool clipcontents) 18 | { 19 | 20 | Func makebutton = (item) => CrossButton.Make(platformStyle, visualState, item, () => onItemSelected(item), makeItemWidget(item)); 21 | 22 | return new Scrollable(visualState, context, platformStyle.DefaultOverscrollBehavior, 23 | new LongListContents(items, itemHeight, onItemSelected, makebutton) 24 | ) 25 | { ClipContents = clipcontents } ; 26 | 27 | } 28 | 29 | //public static Widget Make(VisualState visualState, IEnumerable items, Func getItemHeight, Func onItemSelected, Func makeItemWidget) 30 | //{ 31 | // public static Widget Make(PlatformStyle platformStyle, VisualState visualState, IEnumerable items, Func isItemSelected, SKColor selectedColor, Func onItemSelected, Func makeItemWidget) 32 | // { 33 | // return new Scrollable(visualState, items, platformStyle.DefaultOverscrollBehavior, 34 | // new Column() 35 | // { 36 | // Children = items.Select( 37 | // item => MakeSelectableButton(platformStyle, visualState, item, 38 | // makeItemWidget(item), isItemSelected(item), selectedColor, () => onItemSelected(item)) 39 | // ).ToList() 40 | // } 41 | // ); 42 | // } 43 | 44 | //} 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Members/FixableList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluidSharp.Widgets.Members 7 | { 8 | public class FixableList : IList 9 | { 10 | 11 | private readonly List _list; 12 | 13 | 14 | public FixableList() { _list = new List(); } 15 | public FixableList(IEnumerable values) { _list = new List(values); } 16 | 17 | 18 | public bool IsFixed; 19 | 20 | public int IndexOf(T item) => _list.IndexOf(item); 21 | 22 | // fixable API: 23 | public void Insert(int index, T item) { if (!IsFixed) _list.Insert(index, item); } 24 | public void RemoveAt(int index) { if (!IsFixed) _list.RemoveAt(index); } 25 | public T this[int index] { get => _list[index]; set { if (!IsFixed) _list[index] = value; } } 26 | public void Add(T item) { if (!IsFixed) _list.Add(item); } 27 | public void Clear() { if (!IsFixed) _list.Clear(); } 28 | 29 | public bool Remove(T item) 30 | { 31 | if (IsFixed) return false; 32 | else return _list.Remove(item); 33 | } 34 | 35 | // other List APIs (that are not IList) 36 | public void AddRange(IEnumerable range) { if (!IsFixed) _list.AddRange(range); } 37 | 38 | 39 | public bool Contains(T item) => _list.Contains(item); 40 | public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex); 41 | 42 | public int Count => _list.Count; 43 | 44 | public bool IsReadOnly => IsFixed; 45 | 46 | public IEnumerator GetEnumerator() => _list.GetEnumerator(); 47 | IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); 48 | 49 | } 50 | 51 | 52 | public static class FixableListExtensions 53 | { 54 | 55 | public static FixableList ToFixableList(this IEnumerable values) where T : class => new FixableList(values); 56 | public static FixableList ToFixableList2(this IEnumerable values) => new FixableList(values); 57 | 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Native/INativeViewImpl.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluidSharp.Widgets.Native 7 | { 8 | public interface INativeViewImpl 9 | { 10 | 11 | void SetVisible(bool visible); 12 | void SetBounds(SKRect nativebounds); 13 | 14 | void UpdateControl(NativeViewWidget nativeViewWidget, SKRect rect, SKRect original); 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Native/Keyboard.cs: -------------------------------------------------------------------------------- 1 | namespace FluidSharp 2 | { 3 | public enum Keyboard 4 | { 5 | Default, 6 | Name, 7 | Plain, 8 | Email, 9 | Numeric, 10 | Chat, 11 | Telephone, 12 | Text, 13 | Url, 14 | 15 | MultiLine 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Native/NativeTextboxWidget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using SkiaSharp.TextBlocks; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace FluidSharp.Widgets.Native 10 | { 11 | 12 | public class NativeTextboxWidget : NativeViewWidget 13 | { 14 | 15 | public object Context; 16 | 17 | public string Text; 18 | public Func SetText; 19 | private Func SetTextImpl; 20 | 21 | public Font Font; 22 | public SKColor TextColor; 23 | 24 | public bool HasFocus; 25 | public Keyboard Keyboard; 26 | 27 | public ReturnTypeInfo? ReturnTypeInfo; 28 | 29 | public Text? MeasureWidget; 30 | 31 | public NativeTextboxWidget(object context, string? text, Func settext, Font font, SKColor textcolor, bool hasFocus, Keyboard keyboard, bool sizebytext = false, ReturnTypeInfo? returnTypeInfo = null) 32 | { 33 | Context = context; 34 | Text = text ?? ""; 35 | SetTextImpl = settext; 36 | SetText = SetTextFunc; 37 | Font = font; 38 | TextColor = textcolor; 39 | HasFocus = hasFocus; 40 | Keyboard = keyboard; 41 | ReturnTypeInfo = returnTypeInfo; 42 | //if (sizebytext) 43 | MeasureWidget = new Text(font, default, Text + "W"); 44 | //else 45 | // ExpandHorizontal = true; 46 | } 47 | 48 | public Task SetTextFunc(string text) 49 | { 50 | Text = text; 51 | return SetTextImpl(text); 52 | } 53 | 54 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 55 | { 56 | if (MeasureWidget is null) return base.Measure(measureCache, boundaries); 57 | if (Text + "W" != MeasureWidget.TextBlock.Text) 58 | { 59 | var current = MeasureWidget.TextBlock; 60 | MeasureWidget.TextBlock = new TextBlock(current.Font, current.Color, Text + "W"); 61 | } 62 | return MeasureWidget.Measure(measureCache, boundaries); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Native/NativeViewWidget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets.Native 8 | { 9 | public abstract class NativeViewWidget : Widget 10 | { 11 | 12 | public bool ExpandHorizontal { get; set; } 13 | public bool ExpandVertical { get; set; } 14 | 15 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 16 | { 17 | if (measureCache.NativeViewManager == null) 18 | { 19 | Console.WriteLine($"Warning: NativeViewManager is null measuring NativeViewWidget {this.GetType().Name}"); 20 | return new SKSize(); 21 | } 22 | var childsize = measureCache.NativeViewManager.Measure(this, boundaries); 23 | if (ExpandHorizontal) childsize = new SKSize(boundaries.Width, childsize.Height); 24 | if (ExpandVertical) childsize = new SKSize(childsize.Width, boundaries.Height); 25 | return childsize; 26 | } 27 | 28 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 29 | { 30 | if (layoutsurface.Canvas != null) 31 | { 32 | if (layoutsurface.MeasureCache.NativeViewManager == null) 33 | { 34 | Console.WriteLine($"Warning: NativeViewManager is null updating NativeViewWidget {this.GetType().Name}"); 35 | } 36 | else 37 | { 38 | //if (!layoutsurface.HasActiveAnimations) 39 | layoutsurface.MeasureCache.NativeViewManager.UpdateNativeView(this, rect, rect); 40 | } 41 | } 42 | return rect; 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Native/ReturnType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FluidSharp.Widgets.Native 6 | { 7 | public enum ReturnType 8 | { 9 | Default, 10 | Done, 11 | Go, 12 | Next, 13 | Search, 14 | Send, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Native/ReturnTypeInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FluidSharp.Widgets.Native 6 | { 7 | public class ReturnTypeInfo 8 | { 9 | public ReturnType ReturnType { get; set; } 10 | public Action OnReturnPressed { get; set; } 11 | 12 | public ReturnTypeInfo(ReturnType returnType, Action onReturnPressed) 13 | { 14 | ReturnType = returnType; 15 | OnReturnPressed = onReturnPressed ?? throw new ArgumentNullException(nameof(onReturnPressed)); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Navigation/SlideBackNavigation.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using FluidSharp.Navigation; 3 | using FluidSharp.State; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace FluidSharp.Widgets 10 | { 11 | public class SlideBackNavigation 12 | { 13 | 14 | public static Widget Make(VisualState visualState, CarouselState stateTransition, TransitionFrame frame, float pandetectorwidth, float spacing, Widget? separator, Func makevaluewidget) 15 | { 16 | return GestureDetector.HorizontalPanDetector(visualState, stateTransition, pandetectorwidth, 17 | SlideTransition.MakeWidget(visualState, frame, spacing, PushPageTransition.PushOverlap, separator, makevaluewidget) 18 | ); 19 | } 20 | 21 | } 22 | } 23 | #endif -------------------------------------------------------------------------------- /FluidSharp/Widgets/OptionalWidget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using FluidSharp.State; 3 | using FluidSharp.Widgets.CrossPlatform; 4 | using SkiaSharp; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace FluidSharp.Widgets 11 | { 12 | public class OptionalWidget : Widget 13 | { 14 | 15 | private Func IsVisible; 16 | 17 | private Widget Contents; 18 | 19 | public OptionalWidget(Func isVisible, Widget contents) 20 | { 21 | IsVisible = isVisible ?? throw new ArgumentNullException(nameof(isVisible)); 22 | Contents = contents ?? throw new ArgumentNullException(nameof(contents)); 23 | } 24 | 25 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 26 | { 27 | return IsVisible() ? Contents.Measure(measureCache, boundaries) : new SKSize(); 28 | } 29 | 30 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 31 | { 32 | return IsVisible() ? layoutsurface.Paint(Contents, rect) : rect.WithHeight(0); 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/OverscrollBehavior.cs: -------------------------------------------------------------------------------- 1 | namespace FluidSharp.Widgets 2 | { 3 | public enum OverscrollBehavior 4 | { 5 | None, 6 | Stretch, 7 | Invert 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/RelativeMargin.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets 8 | { 9 | public class RelativeMargin : Widget 10 | { 11 | 12 | public float XFixed { get; set; } 13 | public float YFixed { get; set; } 14 | 15 | public float XMarginPercentage { get; set; } 16 | public float YMarginPercentage { get; set; } 17 | 18 | public Widget InnerWidget { get; set; } 19 | 20 | public RelativeMargin(float xFixed, float yFixed, float xMarginPercentage, float yMarginPercentage, Widget innerWidget) 21 | { 22 | XFixed = xFixed; 23 | YFixed = yFixed; 24 | XMarginPercentage = xMarginPercentage; 25 | YMarginPercentage = yMarginPercentage; 26 | InnerWidget = innerWidget; 27 | } 28 | 29 | private SKSize GetDxDy(SKSize available) 30 | { 31 | var availableX = (available.Width - XFixed); 32 | var availableY = (available.Height - YFixed); 33 | var dx = availableX * XMarginPercentage / 2; 34 | var dy = availableY * YMarginPercentage / 2; 35 | return new SKSize(dx, dy); 36 | } 37 | 38 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 39 | { 40 | var dxdy = GetDxDy(boundaries); 41 | var childsize = InnerWidget.Measure(measureCache, new SKSize(boundaries.Width - dxdy.Width * 2, boundaries.Height - dxdy.Height * 2)); 42 | return new SKSize(childsize.Width + dxdy.Width * 2, childsize.Height + dxdy.Height * 2); 43 | } 44 | 45 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 46 | { 47 | var dxdy = GetDxDy(rect.Size); 48 | var childrect = new SKRect(rect.Left + dxdy.Width, rect.Top + dxdy.Height, rect.Right - dxdy.Width, rect.Bottom - dxdy.Height); 49 | var result = layoutsurface.Paint(InnerWidget, childrect); 50 | return new SKRect(rect.Left - dxdy.Width, rect.Top - dxdy.Height, rect.Right + dxdy.Width, rect.Bottom + dxdy.Height); 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/RichText.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using SkiaSharp.TextBlocks; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.Linq; 8 | using System.Text; 9 | 10 | namespace FluidSharp.Widgets 11 | { 12 | public class RichText : Widget, ITextWidget 13 | { 14 | 15 | public float MarginY; 16 | public RichTextBlock RichTextBlock = new RichTextBlock(); 17 | public bool Any() => RichTextBlock.Spans.Count > 0; 18 | public int MaxLines { get => RichTextBlock.MaxLines; set => RichTextBlock.MaxLines = value; } 19 | 20 | public RichText() { } 21 | 22 | public RichText(params Text[] texts) 23 | { 24 | foreach (var text in texts) 25 | AddText(text); 26 | } 27 | 28 | public RichText(RichTextBlock richTextBlock) { RichTextBlock = richTextBlock; } 29 | 30 | public void AddText(Text text) 31 | { 32 | var my = text.GetMarginY(); 33 | if (MarginY < my) MarginY = my; 34 | RichTextBlock.Add(text.TextBlock); 35 | } 36 | 37 | public float GetMarginY() => MarginY; 38 | 39 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 40 | { 41 | return RichTextBlock.Measure(boundaries.Width, measureCache.TextShaper); 42 | } 43 | 44 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 45 | { 46 | var result = RichTextBlock.Paint(layoutsurface.Canvas, rect, layoutsurface.Device.FlowDirection, layoutsurface.MeasureCache.TextShaper); 47 | 48 | //#if DEBUG 49 | // var measured = Measure(layoutsurface.MeasureCache, rect.Size); 50 | // if (result.Height > measured.Height) 51 | // { 52 | // System.Diagnostics.Debug.WriteLine($"warning: Paint resulted in larger rect {result} than measured rect {measured}"); 53 | // } 54 | //#endif 55 | 56 | return result; 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/RichText/CircleSpan.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using FluidSharp.Paint; 3 | using SkiaSharp; 4 | using SkiaSharp.TextBlocks; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace FluidSharp.Widgets 10 | { 11 | public class CircleSpan : OwnerDrawnRichTextSpan 12 | { 13 | 14 | public float Size; 15 | public Margins Margins; 16 | public SKColor Color; 17 | 18 | private const bool Antialias = true; 19 | 20 | public CircleSpan(float size, Margins margins, SKColor color) 21 | { 22 | Size = size; 23 | Margins = margins; 24 | Color = color; 25 | } 26 | 27 | public override SKSize GetSize(TextShaper textShaper) => new SKSize(Margins.TotalX + Size, Margins.TotalY + Size); 28 | 29 | public override void DrawMeasuredSpan(SKCanvas canvas, float x, float y, float fontheight, float marginy, MeasuredSpan measuredSpan, bool isrtl) 30 | { 31 | 32 | var radius = Size / 2; 33 | 34 | x += isrtl ? Margins.Far : Margins.Near + radius; 35 | y -= (Margins.Bottom + radius); 36 | 37 | if (Color != null && Color.Alpha != 0) 38 | { 39 | canvas.DrawCircle(x, y, radius, PaintCache.GetBackgroundPaint(Color, Antialias)); 40 | } 41 | 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/RichText/PictureSpan.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using SkiaSharp.TextBlocks; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets 8 | { 9 | public class PictureSpan : OwnerDrawnRichTextSpan 10 | { 11 | 12 | public Picture Picture; 13 | public float Opacity = 1; 14 | public SKPoint Translate; 15 | 16 | public PictureSpan(Picture picture) 17 | { 18 | Picture = picture ?? throw new ArgumentNullException(nameof(picture)); 19 | } 20 | 21 | public override SKSize GetSize(TextShaper textShaper) => Picture.Size; 22 | 23 | public override void DrawMeasuredSpan(SKCanvas canvas, float x, float y, float fontheight, float marginy, MeasuredSpan measuredSpan, bool isrtl) 24 | { 25 | 26 | var size = Picture.Size; 27 | y -= (fontheight + size.Height) / 2;// align center of picture to center of font 28 | 29 | var rect = new SKRect(x, y, x + size.Width, y + size.Height); 30 | Picture.Paint(canvas, rect, isrtl); 31 | 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Scale.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Interop; 2 | using FluidSharp.Layouts; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Widgets 9 | { 10 | public class Scale : Widget 11 | { 12 | 13 | public SKPoint Factor; 14 | 15 | public Widget Child; 16 | 17 | public Scale(float factor, Widget child) 18 | { 19 | Factor = new SKPoint(factor, factor); 20 | Child = child; 21 | } 22 | 23 | public Scale(float scaleX, float scaleY, Widget child) 24 | { 25 | Factor = new SKPoint(scaleX, scaleY); 26 | Child = child; 27 | } 28 | 29 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 30 | { 31 | var scaledboundaries = new SKSize(boundaries.Width / Factor.X, boundaries.Height / Factor.Y); 32 | var childmeasure = Child.Measure(measureCache, scaledboundaries); 33 | return new SKSize(childmeasure.Width * Factor.X, childmeasure.Height * Factor.Y); 34 | } 35 | 36 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 37 | { 38 | var canvas = layoutsurface.Canvas; 39 | 40 | var prevmanager = layoutsurface.MeasureCache.NativeViewManager; 41 | if (prevmanager != null) 42 | layoutsurface.MeasureCache.NativeViewManager = new ScaledNativeViewManager(Factor, prevmanager); 43 | 44 | if (canvas != null) 45 | { 46 | canvas.Save(); 47 | canvas.Scale(Factor); 48 | } 49 | var drawrect = new SKRect(rect.Left / Factor.X, rect.Top / Factor.Y, rect.Right / Factor.X, rect.Bottom / Factor.Y); 50 | var childrect = layoutsurface.Paint(Child, drawrect); 51 | var result = new SKRect(childrect.Left * Factor.X, childrect.Top * Factor.Y, childrect.Right * Factor.X, childrect.Bottom * Factor.Y); 52 | 53 | layoutsurface.MeasureCache.NativeViewManager = prevmanager; 54 | if (canvas != null) 55 | { 56 | canvas.Restore(); 57 | } 58 | return result; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/ScaleMode.cs: -------------------------------------------------------------------------------- 1 | namespace FluidSharp.Widgets 2 | { 3 | public enum ScaleMode 4 | { 5 | Strech, 6 | Fit, 7 | Fill 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Shape.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using FluidSharp.Layouts; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Widgets 9 | { 10 | public class Shape : Widget 11 | { 12 | 13 | public SKPath Path; 14 | public SKColor BackgroundColor; 15 | public SKColor BorderColor; 16 | public float StrokeWidth = 1f; 17 | 18 | public Shape(SKPath path, SKColor backgroundColor, SKColor borderColor) 19 | { 20 | Path = path; 21 | BackgroundColor = backgroundColor; 22 | BorderColor = borderColor; 23 | } 24 | 25 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 26 | { 27 | return boundaries; 28 | } 29 | 30 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 31 | { 32 | 33 | var canvas = layoutsurface.Canvas; 34 | if (canvas != null) 35 | { 36 | 37 | var bounds = Path.Bounds; 38 | using (var drawpath = new SKPath(Path)) 39 | { 40 | 41 | drawpath.Transform(SKMatrix.MakeScale(rect.Width / bounds.Width, rect.Height / bounds.Height)); 42 | drawpath.Transform(SKMatrix.MakeTranslation(rect.Left, rect.Top)); 43 | 44 | if (BackgroundColor != null && BackgroundColor.Alpha != 0) 45 | using (var paint = new SKPaint() { Color = BackgroundColor, IsAntialias = true }) 46 | canvas.DrawPath(drawpath, paint); 47 | 48 | if (BorderColor != null && BorderColor.Alpha != 0) 49 | using (var paint = new SKPaint() { Color = BorderColor, IsStroke = true, IsAntialias = true, StrokeWidth = StrokeWidth }) 50 | canvas.DrawPath(drawpath, paint); 51 | 52 | } 53 | } 54 | 55 | return rect; 56 | } 57 | 58 | 59 | } 60 | } 61 | 62 | #endif -------------------------------------------------------------------------------- /FluidSharp/Widgets/ShapeAsFontGlyph.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using FluidSharp.Layouts; 3 | using FluidSharp.Paint; 4 | using SkiaSharp; 5 | using SkiaSharp.TextBlocks; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace FluidSharp.Widgets 11 | { 12 | public class ShapeAsFontGlyph : Widget 13 | { 14 | 15 | public Font Font; 16 | public Shape Shape; 17 | 18 | public ShapeAsFontGlyph(Font font, Shape shape) 19 | { 20 | Font = font; 21 | Shape = shape; 22 | } 23 | 24 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 25 | { 26 | var (charwidth, fontmetrics) = GetMetrics(measureCache); 27 | 28 | var FontHeight = fontmetrics.CapHeight; 29 | var LineHeight = -fontmetrics.Top; 30 | var MarginY = (LineHeight - FontHeight) / 2; 31 | 32 | return new SKSize(charwidth, LineHeight); 33 | } 34 | 35 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 36 | { 37 | 38 | var (charwidth, fontmetrics) = GetMetrics(layoutsurface.MeasureCache); 39 | 40 | var FontHeight = fontmetrics.CapHeight; 41 | var LineHeight = -fontmetrics.Top; 42 | var MarginY = (LineHeight - FontHeight) / 2; 43 | 44 | var paintrect = new SKRect(rect.Left, rect.Top + MarginY, rect.Left + charwidth, rect.Top + LineHeight - MarginY); 45 | 46 | layoutsurface.Paint(Shape, paintrect); 47 | 48 | return paintrect; 49 | 50 | } 51 | 52 | private (float width, SKFontMetrics fontmetrics) GetMetrics(MeasureCache measureCache) 53 | { 54 | var shape = measureCache.TextShaper.GetGlyphSpan(Font, "a"); 55 | return (shape.Measure(0, 0).width, shape.Paints[0].FontMetrics); 56 | } 57 | 58 | 59 | } 60 | } 61 | #endif -------------------------------------------------------------------------------- /FluidSharp/Widgets/ShapeBidirectional.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using SkiaSharp; 3 | using SkiaSharp.TextBlocks.Enum; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Widgets 9 | { 10 | public class ShapeBidirectional : Shape 11 | { 12 | 13 | public SKPath LtrPath; 14 | public SKPath RtlPath; 15 | 16 | public ShapeBidirectional(SKPath ltrpath, SKPath rtlpath, SKColor backgroundColor, SKColor borderColor) : base(ltrpath, backgroundColor, borderColor) 17 | { 18 | LtrPath = ltrpath; 19 | RtlPath = rtlpath; 20 | } 21 | 22 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 23 | { 24 | if (layoutsurface.Device.FlowDirection == FlowDirection.LeftToRight) 25 | Path = LtrPath; 26 | else 27 | Path = RtlPath; 28 | return base.PaintInternal(layoutsurface, rect); 29 | } 30 | } 31 | } 32 | #endif -------------------------------------------------------------------------------- /FluidSharp/Widgets/Spacing.cs: -------------------------------------------------------------------------------- 1 | #if DEBUG 2 | #define SHOWSPACING 3 | #endif 4 | using FluidSharp.Layouts; 5 | using SkiaSharp; 6 | using SkiaSharp.TextBlocks.Enum; 7 | using System; 8 | using System.Collections.Concurrent; 9 | using System.Collections.Generic; 10 | using System.Text; 11 | 12 | namespace FluidSharp.Widgets 13 | { 14 | public class Spacing : Widget 15 | { 16 | 17 | public SKSize Size; 18 | 19 | private static ConcurrentDictionary SquareCache = new ConcurrentDictionary(); 20 | private static ConcurrentDictionary<(float width, float height), Spacing> RectCache = new ConcurrentDictionary<(float width, float height), Spacing>(); 21 | 22 | private Spacing(float size) => Size = new SKSize(size, size); 23 | protected Spacing(float width, float height) => Size = new SKSize(width, height); 24 | 25 | public static Spacing Make(float size) 26 | { 27 | if (!SquareCache.TryGetValue(size, out var result)) SquareCache[size] = result = new Spacing(size); 28 | return result; 29 | } 30 | 31 | public static Spacing Make(float width, float height) 32 | { 33 | if (!RectCache.TryGetValue((width, height), out var result)) RectCache[(width, height)] = result = new Spacing(width, height); 34 | return result; 35 | } 36 | 37 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 38 | { 39 | return Size; 40 | } 41 | 42 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 43 | { 44 | 45 | var x = rect.Left; 46 | if (layoutsurface.Device.FlowDirection == FlowDirection.RightToLeft) 47 | x = rect.Right - Size.Width; 48 | 49 | var y = rect.Top; 50 | var dest = new SKRect(x, y, x + Size.Width, y + Size.Height); 51 | 52 | #if SHOWSPACING 53 | layoutsurface.DebugSpacing(dest, () => $"{Size.Width}x{Size.Height}", SKColors.Blue); 54 | #endif 55 | 56 | return dest; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/SplitContainerBottom.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets 8 | { 9 | 10 | public class SplitContainerBottom : Widget 11 | { 12 | 13 | public Widget MainContents { get; set; } 14 | public Widget RemainingContents { get; set; } 15 | 16 | public SplitContainerBottom(Widget mainContents, Widget remainingContents) 17 | { 18 | MainContents = mainContents ?? throw new ArgumentNullException(nameof(mainContents)); 19 | RemainingContents = remainingContents ?? throw new ArgumentNullException(nameof(remainingContents)); 20 | } 21 | 22 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => boundaries; 23 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 24 | { 25 | 26 | var mainsize = MainContents.Measure(layoutsurface.MeasureCache, rect.Size); 27 | 28 | // remaining 29 | var remainingrect = rect.WithHeight(rect.Height - mainsize.Height); 30 | if (remainingrect.Height > 0) 31 | layoutsurface.Paint(RemainingContents, remainingrect); 32 | 33 | // main 34 | var mainrect = rect.FromBottomHeight(mainsize.Height); 35 | layoutsurface.Paint(MainContents, mainrect); 36 | 37 | return rect; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/SplitContainerNear.cs: -------------------------------------------------------------------------------- 1 | #define SHOWSPACING 2 | using FluidSharp.Layouts; 3 | using SkiaSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Widgets 9 | { 10 | 11 | public class SplitContainerNear : Widget 12 | { 13 | 14 | public Widget Near { get; set; } 15 | public float Spacing { get; set; } 16 | public Widget? Far { get; set; } 17 | 18 | public float Height { get; set; } 19 | 20 | public Margins Margin; 21 | 22 | public SplitContainerNear(Widget near, float spacing, Widget? far, float height, Margins margin) 23 | { 24 | Near = near ?? throw new ArgumentNullException(nameof(near)); 25 | Spacing = spacing; 26 | Far = far; 27 | Height = height; 28 | Margin = margin; 29 | } 30 | 31 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => new SKSize(boundaries.Width, Height); 32 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 33 | { 34 | 35 | var childrect = Margin.Shrink(rect, layoutsurface.FlowDirection).WithHeight(Height - Margin.TotalY); 36 | var nearwidth = Near.Measure(layoutsurface.MeasureCache, childrect.Size).Width; 37 | 38 | // near 39 | var nearrect = childrect.HorizontalAlign(new SKSize(nearwidth, childrect.Height), HorizontalAlignment.Near, layoutsurface.FlowDirection); 40 | layoutsurface.Paint(Near, nearrect); 41 | 42 | // far 43 | var farwidth = childrect.Width - Spacing - nearwidth; 44 | if (farwidth > 0 && Far != null) 45 | { 46 | var farrect = childrect.HorizontalAlign(new SKSize(farwidth, childrect.Height), HorizontalAlignment.Far, layoutsurface.FlowDirection); 47 | layoutsurface.Paint(Far, farrect); 48 | } 49 | 50 | #if SHOWSPACING 51 | layoutsurface.DebugMargin(childrect, Margin, SKColors.YellowGreen); 52 | //layoutsurface.DebugRect(drawrect, SKColors.Blue.WithAlpha(128)); 53 | #endif 54 | 55 | return rect.WithHeight(Height); 56 | 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Stateful/TwoStateWidget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using FluidSharp.State; 3 | using FluidSharp.Widgets.CrossPlatform; 4 | using SkiaSharp; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace FluidSharp.Widgets.Stateful 11 | { 12 | public class TwoStateWidget : Widget 13 | { 14 | 15 | private Func IsSelected; 16 | private Func MakeWidget; 17 | 18 | private Widget? NotSelectedWidget; 19 | private Widget? SelectedWidget; 20 | 21 | private Widget GetWidget() 22 | { 23 | if (IsSelected()) 24 | { 25 | if (SelectedWidget is null) SelectedWidget = MakeWidget(true); 26 | return SelectedWidget; 27 | } 28 | else 29 | { 30 | if (NotSelectedWidget is null) NotSelectedWidget = MakeWidget(false); 31 | return NotSelectedWidget; 32 | } 33 | } 34 | 35 | public TwoStateWidget(Func isSelected, Func makeWidget) 36 | { 37 | IsSelected = isSelected; 38 | MakeWidget = makeWidget; 39 | } 40 | 41 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => GetWidget().Measure(measureCache, boundaries); 42 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) => layoutsurface.Paint(GetWidget(), rect); 43 | 44 | 45 | 46 | //public static Widget Make(PlatformStyle platformStyle, VisualState visualState, object context, Func onTapped, Widget contents) 47 | //{ 48 | // var id = context is string ? context : context.GetType().Name; 49 | // return new StatefulButton(visualState, platformStyle.FlatButtonSelectedBackgroundColor, context, onTapped, contents); 50 | //} 51 | 52 | //public static Widget MakeButton(PlatformStyle platformStyle, VisualState visualState, object context, Func onTapped, Func isSelected, Func makecontents) 53 | //{ 54 | // return Make(platformStyle, visualState, context, onTapped, new SelectableWidget(isSelected, makecontents)); 55 | //} 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/StatefulSlideTransition.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using FluidSharp.Navigation; 3 | using FluidSharp.Paint; 4 | using FluidSharp.State; 5 | using FluidSharp.Widgets.Caching; 6 | using SkiaSharp; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static FluidSharp.Widgets.GestureDetector; 12 | 13 | namespace FluidSharp.Widgets 14 | { 15 | public class StatefulSlideTransition : Widget 16 | { 17 | 18 | public static TimeSpan DefaultDuration = TimeSpan.FromMilliseconds(250); 19 | 20 | public CarouselState State; 21 | public float PanDetectorWidth; 22 | 23 | Func MakeValueWidget; 24 | private PanGestureDetector PanDetector; 25 | 26 | public StatefulSlideTransition(VisualState visualState, CarouselState state, float pandetectorwidth, Func makeValueWidget) 27 | { 28 | State = state ?? throw new ArgumentNullException(nameof(state)); 29 | PanDetectorWidth = pandetectorwidth; 30 | MakeValueWidget = makeValueWidget ?? throw new ArgumentNullException(nameof(makeValueWidget)); 31 | 32 | var contents = MakeWidget(visualState); 33 | PanDetector = HorizontalPanDetector(visualState, State, pandetectorwidth, contents); 34 | 35 | } 36 | 37 | //WidgetCache Transition = new WidgetCache(); 38 | private Widget MakeWidget(VisualState visualState) 39 | { 40 | var frame = State.GetFrame(); 41 | //return Transition.Get(frame.Ratio, () => 42 | //{ 43 | return SlideTransition.MakeWidget(visualState, frame, 0, PushPageTransition.PushOverlap, null, MakeValueWidget); 44 | //}); 45 | } 46 | 47 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => PanDetector.Child.Measure(measureCache, 48 | boundaries); 49 | 50 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 51 | { 52 | 53 | PanDetector.Child = MakeWidget(layoutsurface.VisualState); 54 | return layoutsurface.Paint(PanDetector, rect); 55 | 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Translate.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace FluidSharp.Widgets 8 | { 9 | public class Translate : Widget 10 | { 11 | 12 | public SKPoint Translation { get; set; } 13 | public Widget InnerWidget { get; set; } 14 | 15 | 16 | public Translate(float x, float y, Widget innerWidget) 17 | { 18 | Translation = new SKPoint(x, y); 19 | InnerWidget = innerWidget; 20 | } 21 | 22 | public Translate(SKPoint translation, Widget innerWidget) 23 | { 24 | Translation = translation; 25 | InnerWidget = innerWidget; 26 | } 27 | 28 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) => InnerWidget.Measure(measureCache, boundaries); 29 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 30 | { 31 | if (layoutsurface.IsRtl) 32 | { 33 | var translated = new SKRect(rect.Left - Translation.X, rect.Top + Translation.Y, rect.Right - Translation.X, rect.Bottom + Translation.Y); 34 | var location = layoutsurface.Paint(InnerWidget, translated); 35 | var inverse = new SKRect(location.Left + Translation.X, location.Top - Translation.Y, location.Right + Translation.X, location.Bottom - Translation.Y); 36 | return inverse; 37 | } 38 | else 39 | { 40 | var translated = new SKRect(rect.Left + Translation.X, rect.Top + Translation.Y, rect.Right + Translation.X, rect.Bottom + Translation.Y); 41 | var location = layoutsurface.Paint(InnerWidget, translated); 42 | var inverse = new SKRect(location.Left - Translation.X, location.Top - Translation.Y, location.Right - Translation.X, location.Bottom - Translation.Y); 43 | return inverse; 44 | } 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/VerticalAlignment.cs: -------------------------------------------------------------------------------- 1 | namespace FluidSharp.Widgets 2 | { 3 | public enum VerticalAlignment 4 | { 5 | Top, 6 | Center, 7 | Baseline, // Direct Text children only 8 | Bottom 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/VerticalGradient.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using FluidSharp.Paint; 3 | using SkiaSharp; 4 | using SkiaSharp.TextBlocks.Enum; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace FluidSharp.Widgets 10 | { 11 | 12 | public class VerticalGradient : Widget 13 | { 14 | 15 | 16 | public SKColor Color1; 17 | public SKColor Color2; 18 | public float Height; 19 | 20 | public VerticalGradient(SKColor color1, SKColor color2, float height) 21 | { 22 | Color1 = color1; 23 | Color2 = color2; 24 | Height = height; 25 | } 26 | 27 | public override SKSize Measure(MeasureCache measureCache, SKSize boundaries) 28 | { 29 | return boundaries; 30 | } 31 | 32 | public override SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect) 33 | { 34 | 35 | rect = rect.WithHeight(Height); 36 | if (layoutsurface.Canvas != null) 37 | { 38 | 39 | using ( 40 | var gradient = SKShader.CreateLinearGradient( 41 | new SKPoint(0, rect.Top), 42 | new SKPoint(0, rect.Bottom), 43 | new SKColor[] { Color1, Color2 }, 44 | new float[] { 0, 1 }, 45 | SKShaderTileMode.Clamp)) 46 | { 47 | layoutsurface.Canvas.DrawRect(rect, PaintCache.GetShaderPaint(gradient)); 48 | } 49 | 50 | } 51 | 52 | return rect; 53 | } 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /FluidSharp/Widgets/Widget.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using SkiaSharp; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Input; 8 | 9 | namespace FluidSharp.Widgets 10 | { 11 | public abstract class Widget 12 | { 13 | 14 | 15 | public static Action? WidgetAllocated; 16 | 17 | #if DEBUG 18 | public string? DebugTag; 19 | public bool IsNew = true; 20 | #endif 21 | 22 | public abstract SKSize Measure(MeasureCache measureCache, SKSize boundaries); 23 | 24 | public abstract SKRect PaintInternal(LayoutSurface layoutsurface, SKRect rect); 25 | 26 | 27 | public Widget() 28 | { 29 | WidgetAllocated?.Invoke(this); 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FluidSharp 2 | FluidSharp is a high performance mobile first multi-platform UI layout framework based on Skia. 3 | 4 | 5 | ## Using FluidSharp 6 | 7 | SkiaSharp.TextBlocks is available as a convenient NuGet package, to use install the package like this: 8 | 9 | ``` 10 | nuget install FluidSharp 11 | ``` 12 | 13 | 14 | ## Sample 15 | 16 | ``` 17 | public abstract class Sample : IWidgetSource 18 | { 19 | public abstract string Name { get; } 20 | public abstract Widget MakeWidget(VisualState visualState); 21 | } 22 | 23 | public class HelloWorld : Sample 24 | { 25 | public override string Name => "Hello world"; 26 | public override Widget MakeWidget(VisualState visualState) 27 | { 28 | return new Text(new Font(14), SKColors.Black, "Hello World!"); 29 | } 30 | } 31 | 32 | fluidWidgetView1.WidgetSource = new Sample(); 33 | 34 | ``` 35 | 36 | Result: 37 | ![Hello world.png](./Samples/Screenshots/Hello world.png) 38 | 39 | 40 | See the Samples folder for more code samples. 41 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.All/Basic/HelloWorld.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets; 3 | using FluidSharp.Widgets.CrossPlatform; 4 | using SkiaSharp; 5 | using SkiaSharp.TextBlocks; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | using Font = SkiaSharp.TextBlocks.Font; 10 | 11 | namespace FluidSharp.Samples.All.Basic 12 | { 13 | public class HelloWorld : Sample 14 | { 15 | 16 | public override string Name => "Hello world"; 17 | 18 | public override Widget MakeWidget(VisualState visualState) 19 | { 20 | return new Text(new Font(14), SKColors.Black, "Hello World!"); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.All/Basic/Rectangle.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets; 3 | using FluidSharp.Widgets.CrossPlatform; 4 | using SkiaSharp; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace FluidSharp.Samples.All.Basic 10 | { 11 | public class BackgroundColor : Sample 12 | { 13 | 14 | public override string Name => "Background Color"; 15 | 16 | public override Widget MakeWidget(VisualState visualState) 17 | { 18 | return Rectangle.Fill(SKColors.Red); 19 | } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.All/FluidSharp.Samples.All.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.All/LayoutSamples/AlignSample.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Layouts; 2 | using FluidSharp.State; 3 | using FluidSharp.Widgets; 4 | using FluidSharp.Widgets.CrossPlatform; 5 | using SkiaSharp; 6 | using SkiaSharp.TextBlocks; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | 12 | namespace FluidSharp.Samples.All.LayoutSamples 13 | { 14 | public class AlignSample : Sample 15 | { 16 | 17 | public override string Name => "Align"; 18 | 19 | public override Widget MakeWidget(VisualState visualState) 20 | { 21 | 22 | var layout = new Layout() { ColumnSpacing = 10, RowSpacing = 10, Margin = new Margins(5) }; 23 | 24 | foreach (var h in Enum.GetValues(typeof(HorizontalAlignment)).Cast()) 25 | { 26 | foreach (var v in Enum.GetValues(typeof(VerticalAlignment)).Cast()) 27 | { 28 | 29 | layout.Cells.Add(new LayoutCell((int)h, (int)v, new Layout() 30 | { 31 | 32 | Cells = 33 | { 34 | new LayoutCell(0,0, Rectangle.Stroke(SKColors.LightGray)), 35 | new LayoutCell(0,0, 36 | new Align(h, v, 37 | new Text(new Font(14), SKColors.Black, $"{h} - {v}") 38 | ) 39 | ) 40 | } 41 | 42 | })); 43 | 44 | } 45 | } 46 | 47 | return new Container(ContainerLayout.Fill) 48 | { 49 | Children = 50 | { 51 | new Container(ContainerLayout.Fill) {MinimumSize = new SKSize(200, 200)}, 52 | layout, 53 | } 54 | }; 55 | 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.All/Sample.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.State; 2 | using FluidSharp.Widgets; 3 | using FluidSharp.Widgets.CrossPlatform; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace FluidSharp.Samples.All 9 | { 10 | public abstract class Sample : IWidgetSource 11 | { 12 | 13 | public abstract string Name { get; } 14 | 15 | public abstract Widget MakeWidget(VisualState visualState); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.Screenshots/FluidSharp.Samples.Screenshots.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.WindowsFormsCore/FluidSharp.Samples.WindowsFormsCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | netcoreapp3.1 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.WindowsFormsCore/Form1.cs: -------------------------------------------------------------------------------- 1 | using FluidSharp.Samples.All; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace FluidSharp.Samples.WindowsFormsCore 13 | { 14 | public partial class Form1 : Form 15 | { 16 | public Form1() 17 | { 18 | InitializeComponent(); 19 | 20 | 21 | var sampleApp = new SampleApp(); 22 | 23 | fluidWidgetView1.WidgetSource = sampleApp; 24 | 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.WindowsFormsCore/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace FluidSharp.Samples.WindowsFormsCore 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 18 | Application.EnableVisualStyles(); 19 | Application.SetCompatibleTextRenderingDefault(false); 20 | Application.Run(new Form1()); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/FluidSharp.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Info.plist: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | CFBundleDisplayName 6 | FluidSharp.Samples.iOS 7 | CFBundleIdentifier 8 | com.companyname.FluidSharp.Samples.iOS 9 | CFBundleShortVersionString 10 | 1.0 11 | CFBundleVersion 12 | 1.0 13 | LSRequiresIPhoneOS 14 | 15 | MinimumOSVersion 16 | 14.5 17 | UIDeviceFamily 18 | 19 | 1 20 | 2 21 | 22 | UILaunchStoryboardName 23 | LaunchScreen 24 | UIRequiredDeviceCapabilities 25 | 26 | armv7 27 | 28 | UISupportedInterfaceOrientations 29 | 30 | UIInterfaceOrientationPortrait 31 | UIInterfaceOrientationLandscapeLeft 32 | UIInterfaceOrientationLandscapeRight 33 | 34 | UISupportedInterfaceOrientations~ipad 35 | 36 | UIInterfaceOrientationPortrait 37 | UIInterfaceOrientationPortraitUpsideDown 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | XSAppIconAssets 42 | Assets.xcassets/AppIcon.appiconset 43 | 44 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Main.cs: -------------------------------------------------------------------------------- 1 | using UIKit; 2 | 3 | namespace FluidSharp.Samples.iOS 4 | { 5 | public class Application 6 | { 7 | // This is the main entry point of the application. 8 | static void Main(string[] args) 9 | { 10 | // if you want to use a different Application Delegate class from "AppDelegate" 11 | // you can specify it here. 12 | UIApplication.Main(args, null, "AppDelegate"); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Samples/FluidSharp.Samples.iOS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FluidSharp.Samples.iOS")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FluidSharp.Samples.iOS")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("50c7b8c9-e664-45af-b88e-0c9b8b9c1be1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Samples/Screenshots/Align.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/Screenshots/Align.png -------------------------------------------------------------------------------- /Samples/Screenshots/Background Color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/Screenshots/Background Color.png -------------------------------------------------------------------------------- /Samples/Screenshots/Flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/Screenshots/Flow.png -------------------------------------------------------------------------------- /Samples/Screenshots/Hello world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/Screenshots/Hello world.png -------------------------------------------------------------------------------- /Samples/Screenshots/Layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/Screenshots/Layout.png -------------------------------------------------------------------------------- /Samples/Screenshots/Shapes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wouterst79/FluidSharp/3de7c73adf7e3b662b183a453d766cb7aaa2ff9a/Samples/Screenshots/Shapes.png --------------------------------------------------------------------------------