Last active
November 8, 2023 03:17
-
-
Save VitalJeevanjot/cedd3f640aa670945d601d84a68b2ee4 to your computer and use it in GitHub Desktop.
Moving object with Bounds
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace FabulousCanvasImageMove | |
open System | |
open Avalonia | |
open Avalonia.Layout | |
open Avalonia.Controls | |
open Avalonia.Controls.Shapes | |
open Fabulous | |
open Fabulous.Avalonia | |
open type Fabulous.Avalonia.View | |
open Avalonia.Platform.Storage | |
open Avalonia.Media | |
module ImageOpener = | |
type Model = { Files: IStorageFile list} | |
type Msg = | |
| FileSelection of IStorageFile list | |
| OpenPicker | |
let init () = { Files = [] } | |
let getStorageProvider () = FabApplication.Current.StorageProvider | |
let openPicker (model: Model) = | |
task { | |
let! wellKnownFolder = | |
getStorageProvider().TryGetWellKnownFolderAsync(WellKnownFolder.Pictures) | |
|> Async.AwaitTask | |
let options = FilePickerOpenOptions() | |
options.Title <- "Select an Image" | |
options.AllowMultiple <- false | |
options.FileTypeFilter <- [ FilePickerFileTypes.ImageAll ] | |
options.SuggestedStartLocation <- wellKnownFolder | |
let! res = getStorageProvider().OpenFilePickerAsync(options) |> Async.AwaitTask | |
//if Seq.length(model.Files) > 0 then | |
// printfn "Path below ---------------------------" | |
// printfn "Stopped inside" | |
// let list = Seq.toList model.Files | |
// printfn $"{list}" | |
//else | |
// printfn "nothing..." | |
let mutableList = List.ofSeq res | |
return FileSelection mutableList | |
} | |
let update msg model = | |
match msg with | |
| OpenPicker -> model, Cmd.ofTaskMsg(openPicker(model)) | |
| FileSelection file -> | |
let latestFiles = (model.Files, file) ||> List.append | |
latestFiles |> List.iter (fun elem -> printfn "%A " elem.Path) | |
{ model with | |
Files = latestFiles }, Cmd.none | |
let view model = | |
(HStack(5.) { | |
Button("Add Image", OpenPicker) | |
.size(100, 30) | |
.horizontalAlignment(HorizontalAlignment.Center) | |
.horizontalContentAlignment(HorizontalAlignment.Center) | |
.background(Brushes.RoyalBlue) | |
.cornerRadius(8.0) | |
}) | |
.margin(0., 6.) | |
.horizontalAlignment(HorizontalAlignment.Center) | |
.gridRow(1) | |
module DrawCanvas = | |
type Model = | |
{ IsPressed: bool | |
IsMoving: bool | |
OutOfBound: bool | |
LastPoint: Point option | |
RectPoint: Point option | |
OldRectPoint: Point option | |
OldLastPoint: Point option | |
ImageManager: ImageOpener.Model | |
} | |
type Msg = | |
| DoNothing | |
| PointerPressed of Input.PointerPressedEventArgs | |
| PointerReleased of Input.PointerReleasedEventArgs | |
| PointerMoved of Input.PointerEventArgs | |
| PointerPressedRect of Input.PointerPressedEventArgs | |
| PointerMovedRect of Input.PointerEventArgs | |
| ImageManagerMsg of ImageOpener.Msg | |
let init () = | |
{ IsPressed = false | |
IsMoving = false | |
OutOfBound = false | |
LastPoint = Some(Point(0., 0.)) | |
RectPoint = Some(Point(0., 0.)) | |
OldRectPoint = Some(Point(0., 0.)) | |
OldLastPoint = Some(Point(0., 0.)) | |
ImageManager = ImageOpener.init() | |
} | |
let canvasRef = ViewRef<Canvas>() | |
let rectangleRef = ViewRef<Rectangle>() | |
let imagesRef = ViewRef<Image seq>() | |
let update msg model = | |
match msg with | |
| DoNothing -> model | |
| ImageManagerMsg msg -> | |
let (imageManager, cmd) = ImageOpener.update msg model.ImageManager | |
{ model with | |
ImageManager = imageManager } | |
| PointerPressed args -> | |
printfn $"paths files {model.ImageManager.Files}" | |
let _point = args.GetPosition(canvasRef.Value) | |
{ model with LastPoint = Some _point } | |
| PointerReleased args -> | |
let _point = args.GetPosition(canvasRef.Value) | |
{ model with | |
LastPoint = model.OldLastPoint; | |
IsMoving = false; | |
IsPressed = false } | |
| PointerMoved args -> | |
let _point = args.GetPosition(canvasRef.Value) | |
let rectPoint = args.GetPosition(rectangleRef.Value) | |
if model.IsPressed && not model.OutOfBound then | |
{ model with | |
LastPoint = Some _point | |
OldLastPoint = Some _point | |
OldRectPoint = | |
Some(Point(_point.X - rectPoint.X, _point.Y - rectPoint.Y)) | |
IsMoving = true } | |
elif model.IsPressed && model.OutOfBound then | |
//printfn $"Was Out of bounds {DateTime.Now}" | |
{model with LastPoint = model.OldLastPoint; OutOfBound = false} | |
else | |
model | |
| PointerPressedRect args -> | |
//printfn $"{ImageOpener.init().Files}" | |
match args.Source with | |
| :? Rectangle as rect -> | |
let position = args.GetPosition(rect) | |
{ model with | |
RectPoint = Some position | |
IsPressed = true } | |
| _ -> model | |
| PointerMovedRect args -> | |
match args.Source with | |
| :? Rectangle as rect -> | |
let rectPositionByCanvas = args.GetPosition(canvasRef.Value) | |
let rectPosition = args.GetPosition(rect) | |
if model.IsMoving then | |
let boundX = (rectPositionByCanvas.X - rectPosition.X) + rect.Width | |
let boundY = (rectPositionByCanvas.Y - rectPosition.Y) + rect.Height | |
if boundX > canvasRef.Value.Bounds.Width || boundX < rect.Width | |
then | |
{model with OutOfBound = true} | |
elif boundY > canvasRef.Value.Bounds.Height || boundY < rect.Height | |
then | |
{model with OutOfBound = true} | |
else | |
{model with OutOfBound = false} | |
else | |
model | |
| _ -> model | |
let view model = | |
(Canvas() { | |
Rectangle(10., 10.) | |
.size(100., 100.) | |
.fill(Brushes.Black) | |
.renderTransform( | |
if model.IsMoving then | |
TranslateTransform( | |
model.LastPoint.Value.X - model.RectPoint.Value.X, | |
model.LastPoint.Value.Y - model.RectPoint.Value.Y | |
) | |
else | |
TranslateTransform(model.OldRectPoint.Value.X, model.OldRectPoint.Value.Y) | |
) | |
.reference(rectangleRef) | |
.onPointerPressed(PointerPressedRect) | |
.onPointerMoved(PointerMovedRect) | |
//Image("file:///C:/Users/jeevan/Documents/bcyeg.png", Stretch.Uniform) | |
// .size(100, 100) | |
// .renderTransform(TranslateTransform( | |
// 200, | |
// 200 | |
// )) | |
for file in model.ImageManager.Files do | |
Image(file.Path.ToString(), Stretch.Uniform) | |
.size(100, 100) | |
.renderTransform(TranslateTransform( | |
200, | |
200 | |
)) | |
}) | |
.reference(canvasRef) | |
.clipToBounds(true) | |
.gridRow(0) | |
.background(Brushes.White) | |
.onPointerPressed(PointerPressed) | |
.onPointerReleased(PointerReleased) | |
.onPointerMoved (PointerMoved) | |
module App = | |
type Model = | |
{ DrawingCanvas: DrawCanvas.Model | |
FilePicker: ImageOpener.Model } | |
type Msg = | |
| DrawingCanvasMsg of DrawCanvas.Msg | |
| FilePickerMsg of ImageOpener.Msg | |
let initModel = | |
{ DrawingCanvas = DrawCanvas.init () | |
FilePicker = ImageOpener.init () } | |
let init () = initModel, Cmd.none | |
let update msg model = | |
match msg with | |
| DrawingCanvasMsg msg -> | |
let drawingCanvas = DrawCanvas.update msg model.DrawingCanvas | |
{ model with | |
DrawingCanvas = drawingCanvas }, | |
Cmd.none | |
| FilePickerMsg msg -> | |
let filePicker, cmd = ImageOpener.update msg model.FilePicker | |
{ model with FilePicker = filePicker }, Cmd.map FilePickerMsg cmd | |
let view model = | |
Grid(coldefs = [], rowdefs = [Star; Auto]) { | |
View.map DrawingCanvasMsg (DrawCanvas.view(model.DrawingCanvas)) | |
View.map FilePickerMsg (ImageOpener.view(model.FilePicker)) | |
} | |
#if MOBILE | |
let app model = SingleViewApplication(view model) | |
#else | |
let app model = DesktopApplication(Window(view model)) | |
#endif | |
let program = Program.statefulWithCmd init update app |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment