Mobile App Dev 2022W: Assignment 2

From Soma-notes
Revision as of 03:09, 11 February 2022 by Soma (talk | contribs) (→‎Questions)

This assignment is still being developed.

Questions

  1. [1] Explain how to add this image from Wikipedia to the image list under the name "Boxer".
  2. [2] What name is added to the menu if we manually enter a URL and select "Remember Image"? Why? Explain with an example.
  3. [2] There is an image URL on line 67. When is this image displayed during normal program operation? Why?
  4. [2] If you delete line 28 and instead replace line 20 with "var imageNames = [String] (images.keys)", the program will compile and run. Will it function any differently? Why?

Code: remotePicViewer2 ContentView.swift

// remotePicViewer2
//
// code for Assignment 2
// COMP 1601 2022W, Carleton University
//
// Anil Somayaji, February 10, 2022
// Code is licenced under the FSF GPLv3 or newer
//
// Note this code is for teaching purposes only.  In particular
// it is not robust and does not handle error conditions properly.
//

import SwiftUI

var images: [String: String] = [
    "Kittens": "https://homeostasis.scs.carleton.ca/~soma/mad-2022w/images/kittens.jpeg",
    "Sad Dog":
        "https://homeostasis.scs.carleton.ca/~soma/mad-2022w/images/roshi.jpeg",
]

@available(macOS 12.0, *)
struct ContentView: View {
    @State private var imageName = "Kittens"
    @State private var theImage = getImage("Kittens")
    @State private var moved = false
    @State private var finalAmount: CGFloat = 1
    @State private var angle = Angle(degrees: 0.0)
    @State private var imageNames = [String] (images.keys)
    
    func resetState() {
        moved = false
        finalAmount = 1
        angle = Angle(degrees: 0.0)
    }
    
    var body: some View {
        VStack {
            Text("Image Viewer")
                .font(.title)
            TextField("Enter an image URL", text: $theImage)
            Menu("Known Images") {
                ForEach(imageNames, id: \.self) {s in
                    Button(s, action: {
                        theImage = getImage(s)
                        resetState()
                    })
                }
                Divider()
                Button("Remember Image", action: {
                    let urlParts = theImage.split(separator: "/")
                    let newName = String(urlParts[urlParts.count - 1])
                    imageNames.append(newName)
                    images[newName] = theImage
                })
            }
            Divider().background(Color.black)
            ActiveImage(theImage: $theImage, imageName: $imageName, moved: $moved, finalAmount: $finalAmount, angle: $angle)
        }
    }
}

func getImage(_ imageName: String) -> String {
    return images[imageName] ?? "https://homeostasis.scs.carleton.ca/~soma/year.jpg"
}

@available(macOS 12.0, *)
struct ActiveImage: View {
    @State private var position = CGPoint(x: 0, y: 0)
    @State private var currentAmount: CGFloat = 0

    @Binding var theImage: String
    @Binding var imageName: String
    @Binding var moved: Bool
    @Binding var finalAmount: CGFloat
    @Binding var angle: Angle
    
    var body: some View {
        GeometryReader {g in
            AsyncImage(url: URL(string: theImage), content: {image in
                image
                    .resizable()
                    .scaledToFit()
                    .position(moved ? position :
                                CGPoint(x: g.size.width / 2,
                                        y: g.size.height / 2))
                    .scaleEffect(finalAmount + currentAmount)
                    .gesture(dragging)
                    .gesture(magnifying)
                    .rotationEffect(self.angle)
                    .onLongPressGesture(perform: tapReset)
                    .onTapGesture(count: 2, perform: zoom)
                    .onTapGesture(count: 1, perform: rotateImage)
            }, placeholder: {
                ProgressView()
                    .position(moved ? position :
                                CGPoint(x: g.size.width / 2,
                                        y: g.size.height / 2))
            })
        }
    }
    
    func zoom() {
        self.finalAmount = self.finalAmount * 2
    }

    func tapReset() {
        self.finalAmount = 1
        self.moved = false
        self.angle = Angle(degrees: 0.0)
    }
    
    func rotateImage() {
        let oldDegrees = self.angle.degrees
        self.angle = Angle(degrees: oldDegrees + 45)
    }

    var magnifying: some Gesture {
        MagnificationGesture().onChanged { amount in
            self.currentAmount = amount - 1
        }
        .onEnded { amount in
            self.finalAmount += self.currentAmount
            self.currentAmount = 0
        }
    }
    
    var dragging: some Gesture {
        DragGesture()
            .onChanged {s in
                self.moved = true
                self.position = s.location
            }
            .onEnded {s in
                self.moved = true
                self.position = s.location
            }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}