+/* Pinch with 2 fingers: zoom in around the center of the fingers.
+ */
+- (void) handlePinch:(UIPinchGestureRecognizer *)sender
+{
+ if (!xsft->event_cb || !xwindow) return;
+
+ [self showCloseButton];
+
+ if (sender.state == UIGestureRecognizerStateBegan)
+ pinch_transform = self.transform; // Save the base transform
+
+ switch (sender.state) {
+ case UIGestureRecognizerStateBegan:
+ case UIGestureRecognizerStateChanged:
+ {
+ double scale = sender.scale;
+
+ if (scale < 1)
+ return;
+
+ self.transform = CGAffineTransformScale (pinch_transform, scale, scale);
+
+ CGPoint p = [sender locationInView: self];
+ p.x /= self.layer.bounds.size.width;
+ p.y /= self.layer.bounds.size.height;
+
+ CGPoint np = CGPointMake (self.bounds.size.width * p.x,
+ self.bounds.size.height * p.y);
+ CGPoint op = CGPointMake (self.bounds.size.width *
+ self.layer.anchorPoint.x,
+ self.bounds.size.height *
+ self.layer.anchorPoint.y);
+ np = CGPointApplyAffineTransform (np, self.transform);
+ op = CGPointApplyAffineTransform (op, self.transform);
+
+ CGPoint pos = self.layer.position;
+ pos.x -= op.x;
+ pos.x += np.x;
+ pos.y -= op.y;
+ pos.y += np.y;
+ self.layer.position = pos;
+ self.layer.anchorPoint = p;
+ }
+ break;
+
+ case UIGestureRecognizerStateEnded:
+ {
+ // When released, snap back to the default zoom (but animate it).
+
+ CABasicAnimation *a1 = [CABasicAnimation
+ animationWithKeyPath:@"position.x"];
+ a1.fromValue = [NSNumber numberWithFloat: self.layer.position.x];
+ a1.toValue = [NSNumber numberWithFloat: self.bounds.size.width / 2];
+
+ CABasicAnimation *a2 = [CABasicAnimation
+ animationWithKeyPath:@"position.y"];
+ a2.fromValue = [NSNumber numberWithFloat: self.layer.position.y];
+ a2.toValue = [NSNumber numberWithFloat: self.bounds.size.height / 2];
+
+ CABasicAnimation *a3 = [CABasicAnimation
+ animationWithKeyPath:@"anchorPoint.x"];
+ a3.fromValue = [NSNumber numberWithFloat: self.layer.anchorPoint.x];
+ a3.toValue = [NSNumber numberWithFloat: 0.5];
+
+ CABasicAnimation *a4 = [CABasicAnimation
+ animationWithKeyPath:@"anchorPoint.y"];
+ a4.fromValue = [NSNumber numberWithFloat: self.layer.anchorPoint.y];
+ a4.toValue = [NSNumber numberWithFloat: 0.5];
+
+ CABasicAnimation *a5 = [CABasicAnimation
+ animationWithKeyPath:@"transform.scale"];
+ a5.fromValue = [NSNumber numberWithFloat: sender.scale];
+ a5.toValue = [NSNumber numberWithFloat: 1.0];
+
+ CAAnimationGroup *group = [CAAnimationGroup animation];
+ group.duration = 0.3;
+ group.repeatCount = 1;
+ group.autoreverses = NO;
+ group.animations = @[ a1, a2, a3, a4, a5 ];
+ group.timingFunction = [CAMediaTimingFunction
+ functionWithName:
+ kCAMediaTimingFunctionEaseIn];
+ [self.layer addAnimation:group forKey:@"unpinch"];
+
+ self.transform = pinch_transform;
+ self.layer.anchorPoint = CGPointMake (0.5, 0.5);
+ self.layer.position = CGPointMake (self.bounds.size.width / 2,
+ self.bounds.size.height / 2);
+ }
+ break;
+ default:
+ abort();
+ }
+}
+
+