QIOSTextInputOverlay: fade-out handles upon focus transfer

Small adjustment to a76d709. Instead of removing the selection
handles immediately when an object loses focus, we choose to
animate them out the same way we do when we lose selection.

We do this by setting the handle visibility to false, which will
trigger the fade-out animation. Then we wait a for the animation
to finish before we remove and delete them fully.

Change-Id: Iaa93969af086000d9e1cf8a39bd12c6a8b70c89e
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
This commit is contained in:
Richard Moe Gustavsen 2016-05-04 14:45:58 +02:00
parent 459933708a
commit 8c42837689

View File

@ -45,6 +45,7 @@
#include "qiostextinputoverlay.h" #include "qiostextinputoverlay.h"
typedef QPair<int, int> SelectionPair; typedef QPair<int, int> SelectionPair;
typedef void (^Block)(void);
static const CGFloat kKnobWidth = 10; static const CGFloat kKnobWidth = 10;
@ -68,7 +69,7 @@ static bool hasSelection()
return selection.first != selection.second; return selection.first != selection.second;
} }
static void executeBlockWithoutAnimation(void (^block)(void)) static void executeBlockWithoutAnimation(Block block)
{ {
[CATransaction begin]; [CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
@ -306,6 +307,7 @@ static void executeBlockWithoutAnimation(void (^block)(void))
@property (nonatomic, assign) CGRect cursorRectangle; @property (nonatomic, assign) CGRect cursorRectangle;
@property (nonatomic, assign) CGFloat handleScale; @property (nonatomic, assign) CGFloat handleScale;
@property (nonatomic, assign) BOOL visible; @property (nonatomic, assign) BOOL visible;
@property (nonatomic, copy) Block onAnimationDidStop;
@end @end
@implementation QIOSHandleLayer @implementation QIOSHandleLayer
@ -359,7 +361,8 @@ static void executeBlockWithoutAnimation(void (^block)(void))
[NSNumber numberWithFloat:1], nil]; [NSNumber numberWithFloat:1], nil];
return animation; return animation;
} else { } else {
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:key]; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key];
[animation setDelegate:self];
animation.fromValue = [self valueForKey:key]; animation.fromValue = [self valueForKey:key];
[animation setDuration:0.2]; [animation setDuration:0.2];
return animation; return animation;
@ -368,6 +371,14 @@ static void executeBlockWithoutAnimation(void (^block)(void))
return [super actionForKey:key]; return [super actionForKey:key];
} }
- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
{
Q_UNUSED(animation);
Q_UNUSED(flag);
if (self.onAnimationDidStop)
self.onAnimationDidStop();
}
- (void)setVisible:(BOOL)visible - (void)setVisible:(BOOL)visible
{ {
if (visible == _visible) if (visible == _visible)
@ -679,7 +690,7 @@ static void executeBlockWithoutAnimation(void (^block)(void))
if (enabled) { if (enabled) {
// Create a layer that clips the handles inside the input field // Create a layer that clips the handles inside the input field
_clipRectLayer = [[CALayer new] autorelease]; _clipRectLayer = [CALayer new];
_clipRectLayer.masksToBounds = YES; _clipRectLayer.masksToBounds = YES;
[self.focusView.layer addSublayer:_clipRectLayer]; [self.focusView.layer addSublayer:_clipRectLayer];
@ -705,7 +716,26 @@ static void executeBlockWithoutAnimation(void (^block)(void))
[self updateSelection]; [self updateSelection];
} else { } else {
[_clipRectLayer removeFromSuperlayer]; // Fade out the handles by setting visible to NO, and wait for the animations
// to finish before removing the clip rect layer, including the handles.
// Create a local variable to hold the clipRectLayer while the animation is
// ongoing to ensure that any subsequent calls to setEnabled does not interfere.
// Also, declare it as __block to stop it from being automatically retained, which
// would cause a cyclic dependency between clipRectLayer and the block.
__block CALayer *clipRectLayer = _clipRectLayer;
__block int handleCount = 2;
Block block = ^{
if (--handleCount == 0) {
[clipRectLayer removeFromSuperlayer];
[clipRectLayer release];
}
};
_cursorLayer.onAnimationDidStop = block;
_anchorLayer.onAnimationDidStop = block;
_cursorLayer.visible = NO;
_anchorLayer.visible = NO;
_clipRectLayer = 0; _clipRectLayer = 0;
_cursorLayer = 0; _cursorLayer = 0;
_anchorLayer = 0; _anchorLayer = 0;