1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#import "ui/app_list/cocoa/item_drag_controller.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#import "ui/app_list/cocoa/apps_grid_view_item.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/cocoa/window_size_constants.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Scale to transform the grid cell when a drag starts. Note that 1.5 ensures
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// that integers are used for the layer bounds when the grid cell dimensions
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// are even.
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const CGFloat kDraggingIconScale = 1.5;
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const NSTimeInterval kAnimationDuration = 0.2;
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)@interface ItemDragController ()
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)animateTransformFrom:(CATransform3D)fromValue
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 useDelegate:(BOOL)useDelegate;
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)clearAnimations;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)@end
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)@implementation ItemDragController
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (id)initWithGridCellSize:(NSSize)size {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if ((self = [super init])) {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    NSRect frameRect = NSMakeRect(0,
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  0,
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  size.width * kDraggingIconScale,
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  size.height * kDraggingIconScale);
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::scoped_nsobject<NSView> dragView(
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        [[NSView alloc] initWithFrame:frameRect]);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    [dragView setWantsLayer:YES];
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    [dragView setHidden:YES];
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dragLayer_.reset([[CALayer layer] retain]);
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    [dragLayer_ setFrame:NSRectToCGRect(frameRect)];
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    [[dragView layer] addSublayer:dragLayer_];
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    [self setView:dragView];
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return self;
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)initiate:(AppsGridViewItem*)item
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mouseDownLocation:(NSPoint)mouseDownLocation
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      currentLocation:(NSPoint)currentLocation
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            timestamp:(NSTimeInterval)eventTimestamp {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [self clearAnimations];
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NSView* itemView = [item view];
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NSPoint pointInGridCell = [itemView convertPoint:mouseDownLocation
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          fromView:nil];
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mouseOffset_ = NSMakePoint(pointInGridCell.x - NSMidX([itemView bounds]),
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             NSMidY([itemView bounds]) - pointInGridCell.y);
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NSBitmapImageRep* imageRep = [item dragRepresentationForRestore:NO];
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [dragLayer_ setContents:reinterpret_cast<id>([imageRep CGImage])];
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [dragLayer_ setTransform:CATransform3DIdentity];
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add a grow animation to the layer.
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CATransform3D growFrom = CATransform3DScale(CATransform3DIdentity,
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              1.0 / kDraggingIconScale,
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              1.0 / kDraggingIconScale,
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              1.0);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [self animateTransformFrom:growFrom
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 useDelegate:NO];
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  growStart_ = eventTimestamp;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [[self view] setHidden:NO];
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)update:(NSPoint)currentLocation
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     timestamp:(NSTimeInterval)eventTimestamp {
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NSPoint pointInSuperview = [[[self view] superview]
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      convertPoint:currentLocation
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          fromView:nil];
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NSRect rect = [[self view] bounds];
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NSPoint anchor = NSMakePoint(NSMidX(rect), NSMidY(rect));
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If the grow animation is still in progress, make the point of the image
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // that was clicked appear stuck to the mouse cursor.
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CGFloat progress = (eventTimestamp - growStart_) / kAnimationDuration;
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CGFloat currentIconScale = progress < 1.0 ?
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      1.0 + (kDraggingIconScale - 1.0) * progress :
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kDraggingIconScale;
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pointInSuperview.x -= (mouseOffset_.x * currentIconScale + anchor.x);
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pointInSuperview.y -= (mouseOffset_.y * currentIconScale + anchor.y);
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [[self view] setFrameOrigin:pointInSuperview];
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)complete:(AppsGridViewItem*)item
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    targetOrigin:(NSPoint)targetOrigin {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [self clearAnimations];
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NSView* itemView = [item view];
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NSBitmapImageRep* imageRep = [item dragRepresentationForRestore:YES];
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [dragLayer_ setContents:reinterpret_cast<id>([imageRep CGImage])];
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [dragLayer_ setTransform:CATransform3DScale(CATransform3DIdentity,
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              1.0 / kDraggingIconScale,
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              1.0 / kDraggingIconScale,
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              1.0)];
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Retain the button so it can be unhidden when the animation completes. Note
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // that the |item| and corresponding button can differ from the |item| passed
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to initiate(), if it moved to a new page during the drag. At this point the
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // destination page is known, so retain the button.
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  buttonToRestore_.reset([[item button] retain]);
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add the shrink animation for the layer.
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [self animateTransformFrom:CATransform3DIdentity
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 useDelegate:YES];
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  shrinking_ = YES;
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Also animate the translation, on the view.
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(tapted): This should be merged into the scale transform, instead of
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // using a separate NSViewAnimation.
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NSRect startRect = [[self view] frame];
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The final position needs to be adjusted since it shrinks from each side.
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NSRect targetRect = NSMakeRect(
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      targetOrigin.x - NSMidX([itemView bounds]) * (kDraggingIconScale - 1),
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      targetOrigin.y - NSMidY([itemView bounds]) * (kDraggingIconScale - 1),
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      startRect.size.width,
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      startRect.size.height);
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NSDictionary* animationDict = @{
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NSViewAnimationTargetKey:     [self view],
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NSViewAnimationStartFrameKey: [NSValue valueWithRect:startRect],
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NSViewAnimationEndFrameKey:   [NSValue valueWithRect:targetRect]
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::scoped_nsobject<NSViewAnimation> translate([[NSViewAnimation alloc]
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      initWithViewAnimations:[NSArray arrayWithObject:animationDict]]);
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [translate setDuration:kAnimationDuration];
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [translate startAnimation];
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)animateTransformFrom:(CATransform3D)fromValue
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 useDelegate:(BOOL)useDelegate {
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CABasicAnimation* animation =
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      [CABasicAnimation animationWithKeyPath:@"transform"];
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [animation setFromValue:[NSValue valueWithCATransform3D:fromValue]];
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (useDelegate)
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    [animation setDelegate:self];
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [animation setDuration:kAnimationDuration];
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [CATransaction begin];
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [CATransaction setValue:[NSNumber numberWithFloat:kAnimationDuration]
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   forKey:kCATransactionAnimationDuration];
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [dragLayer_ addAnimation:animation
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    forKey:@"transform"];
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [CATransaction commit];
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)clearAnimations {
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [dragLayer_ removeAllAnimations];
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!shrinking_)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(buttonToRestore_);
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [buttonToRestore_ setHidden:NO];
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  buttonToRestore_.reset();
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  shrinking_ = NO;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)animationDidStop:(CAAnimation*)anim
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                finished:(BOOL)finished {
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!finished)
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(shrinking_);
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [self clearAnimations];
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [dragLayer_ setContents:nil];
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [[self view] setHidden:YES];
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)@end
185