"Fossies" - the Fresh Open Source Software Archive

Member "jitsi-meet-7563/ios/sdk/src/picture-in-picture/DragGestureController.swift" (2 Oct 2023, 4350 Bytes) of package /linux/misc/jitsi-meet-7563.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Swift source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Copyright @ 2017-present Atlassian Pty Ltd
    3  *
    4  * Licensed under the Apache License, Version 2.0 (the "License");
    5  * you may not use this file except in compliance with the License.
    6  * You may obtain a copy of the License at
    7  *
    8  *     http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 import UIKit
   18 
   19 final class DragGestureController {
   20     var insets: UIEdgeInsets = UIEdgeInsets.zero
   21     var currentPosition: PiPViewCoordinator.Position? = nil
   22 
   23     private var frameBeforeDragging: CGRect = CGRect.zero
   24     private weak var view: UIView?
   25     private lazy var panGesture: UIPanGestureRecognizer = {
   26         UIPanGestureRecognizer(target: self,
   27                                action: #selector(handlePan(gesture:)))
   28     }()
   29 
   30     func startDragListener(inView view: UIView) {
   31         self.view = view
   32         view.addGestureRecognizer(panGesture)
   33         panGesture.isEnabled = true
   34     }
   35 
   36     func stopDragListener() {
   37         panGesture.isEnabled = false
   38         view?.removeGestureRecognizer(panGesture)
   39         view = nil
   40     }
   41 
   42     @objc private func handlePan(gesture: UIPanGestureRecognizer) {
   43         guard let view = view else { return }
   44 
   45         let translation = gesture.translation(in: view.superview)
   46         let velocity = gesture.velocity(in: view.superview)
   47         var frame = frameBeforeDragging
   48 
   49         switch gesture.state {
   50         case .began:
   51             frameBeforeDragging = view.frame
   52 
   53         case .changed:
   54             frame.origin.x = floor(frame.origin.x + translation.x)
   55             frame.origin.y = floor(frame.origin.y + translation.y)
   56             view.frame = frame
   57 
   58         case .ended:
   59             let currentPos = view.frame.origin
   60             let finalPos = calculateFinalPosition()
   61 
   62             let distance = CGPoint(x: currentPos.x - finalPos.x,
   63                                    y: currentPos.y - finalPos.y)
   64             let distanceMagnitude = magnitude(vector: distance)
   65             let velocityMagnitude = magnitude(vector: velocity)
   66             let animationDuration = 0.5
   67             let initialSpringVelocity =
   68                     velocityMagnitude / distanceMagnitude / CGFloat(animationDuration)
   69 
   70             frame.origin = CGPoint(x: finalPos.x, y: finalPos.y)
   71 
   72             UIView.animate(withDuration: animationDuration,
   73                            delay: 0,
   74                            usingSpringWithDamping: 0.9,
   75                            initialSpringVelocity: initialSpringVelocity,
   76                            options: .curveLinear,
   77                            animations: {
   78                 view.frame = frame })
   79 
   80         default:
   81             break
   82         }
   83     }
   84 
   85     private func calculateFinalPosition() -> CGPoint {
   86         guard
   87             let view = view,
   88             let bounds = view.superview?.frame
   89         else {
   90             return CGPoint.zero
   91         }
   92 
   93         let currentSize = view.frame.size
   94         let adjustedBounds = bounds.inset(by: insets)
   95         let threshold: CGFloat = 20.0
   96         let velocity = panGesture.velocity(in: view.superview)
   97         let location = panGesture.location(in: view.superview)
   98 
   99         let goLeft: Bool
  100         if abs(velocity.x) > threshold {
  101             goLeft = velocity.x < -threshold
  102         } else {
  103             goLeft = location.x < bounds.midX
  104         }
  105 
  106         let goUp: Bool
  107         if abs(velocity.y) > threshold {
  108             goUp = velocity.y < -threshold
  109         } else {
  110             goUp = location.y < bounds.midY
  111         }
  112 
  113         if (goLeft && goUp) {
  114             currentPosition = .upperLeftCorner
  115         }
  116 
  117         if (!goLeft && goUp) {
  118             currentPosition = .upperRightCorner
  119         }
  120 
  121         if (!goLeft && !goUp) {
  122             currentPosition = .lowerRightCorner
  123         }
  124 
  125         if (goLeft && !goUp) {
  126             currentPosition = .lowerLeftCorner
  127         }
  128         
  129         return currentPosition!.getOriginIn(bounds: adjustedBounds, size: currentSize)
  130     }
  131 
  132     private func magnitude(vector: CGPoint) -> CGFloat {
  133         sqrt(pow(vector.x, 2) + pow(vector.y, 2))
  134     }
  135 }