Skip to content

Instantly share code, notes, and snippets.

@VitalJeevanjot
Last active November 8, 2023 03:17
Show Gist options
  • Save VitalJeevanjot/cedd3f640aa670945d601d84a68b2ee4 to your computer and use it in GitHub Desktop.
Save VitalJeevanjot/cedd3f640aa670945d601d84a68b2ee4 to your computer and use it in GitHub Desktop.
Moving object with Bounds
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