Difference between revisions of "Mobile App Dev 2022W: Assignment 2"

From Soma-notes
Jump to navigation Jump to search
Line 2: Line 2:


==Questions==
==Questions==
When explaining what code does, be sure to explain both the mechanics of what the code does and how that code fits into the overall functionality of the program.


# [1] Explain how to add [https://upload.wikimedia.org/wikipedia/commons/6/6f/Male_fawn_Boxer_undocked.jpg this image from Wikipedia] to the image list under the name "Boxer".
# [1] Explain how to add [https://upload.wikimedia.org/wikipedia/commons/6/6f/Male_fawn_Boxer_undocked.jpg this image from Wikipedia] to the image list under the name "Boxer".
Line 8: Line 10:
# [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?
# [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?
# [2] Why does the program have both currentAmount and finalAmount for implementing the magnification gesture?  Specifically, how does the program behave if we use finalAmount in the onChanged handler and do nothing in the onEnded handler of magnifying?
# [2] Why does the program have both currentAmount and finalAmount for implementing the magnification gesture?  Specifically, how does the program behave if we use finalAmount in the onChanged handler and do nothing in the onEnded handler of magnifying?
# [2] What do each line do in lines 50-53? These implement the action function of the "Remember Image" menu option.


==[https://homeostasis.scs.carleton.ca/~soma/mad-2022w/code/remotePicViewer2/ContentView.swift Code: remotePicViewer2 ContentView.swift]==
==[https://homeostasis.scs.carleton.ca/~soma/mad-2022w/code/remotePicViewer2/ContentView.swift Code: remotePicViewer2 ContentView.swift]==

Revision as of 23:20, 10 February 2022

This assignment is still being developed.

Questions

When explaining what code does, be sure to explain both the mechanics of what the code does and how that code fits into the overall functionality of the program.

  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?
  5. [2] Why does the program have both currentAmount and finalAmount for implementing the magnification gesture? Specifically, how does the program behave if we use finalAmount in the onChanged handler and do nothing in the onEnded handler of magnifying?
  6. [2] What do each line do in lines 50-53? These implement the action function of the "Remember Image" menu option.

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()
    }
}