|
2d29c36d
»
|
gabriel |
2008-08-07 |
importing |
1 |
// |
| |
2 |
// GHViewAnimation.m |
|
13e87165
»
|
gabriel |
2008-08-12 |
where did this originally c... |
3 |
// |
|
2d29c36d
»
|
gabriel |
2008-08-07 |
importing |
4 |
// From ViewAnimationTest project. (TODO: Find source) |
|
13e87165
»
|
gabriel |
2008-08-12 |
where did this originally c... |
5 |
// Not sure where this is from originally, and I refactored it a bunch. |
| |
6 |
// If anyone recognizes this code, let me know. |
|
2d29c36d
»
|
gabriel |
2008-08-07 |
importing |
7 |
// |
| |
8 |
|
| |
9 |
#import "GHViewAnimation.h" |
| |
10 |
|
| |
11 |
|
| |
12 |
@implementation GHViewAnimation |
| |
13 |
|
| |
14 |
- (id)initWithContainer:(NSView *)container view:(NSView *)view1 view:(NSView *)view2 { |
| |
15 |
self = [super init]; |
| |
16 |
if (self) { |
| |
17 |
container_ = container; |
| |
18 |
|
| |
19 |
view1_ = [self wrapView:view1 container:container_ hide:NO]; |
| |
20 |
view2_ = [self wrapView:view2 container:container_ hide:YES]; |
| |
21 |
|
| |
22 |
toView_ = view2_; |
| |
23 |
fromView_ = view1_; |
| |
24 |
|
| |
25 |
} |
| |
26 |
return self; |
| |
27 |
} |
| |
28 |
|
| |
29 |
- (NSView *)wrapView:(NSView *)view container:(NSView *)container hide:(BOOL)hide { |
| |
30 |
NSRect rect = [container bounds]; |
| |
31 |
NSView *tempView = [[NSView alloc] initWithFrame:rect]; |
| |
32 |
[tempView addSubview:view]; |
| |
33 |
[tempView setAutoresizingMask:[container autoresizingMask]]; |
| |
34 |
[container addSubview:tempView]; |
| |
35 |
rect = [tempView bounds]; |
| |
36 |
[tempView setHidden:hide]; |
| |
37 |
[view setFrame:rect]; |
|
698fda67
»
|
gabriel |
2009-09-18 |
Fixing leak |
38 |
return [tempView autorelease]; |
|
2d29c36d
»
|
gabriel |
2008-08-07 |
importing |
39 |
} |
| |
40 |
|
| |
41 |
- (void)prepareSubviewOfView:(NSView *)view { |
| |
42 |
NSView *subview = [[view subviews] objectAtIndex:0]; |
| |
43 |
[subview setFrameOrigin:NSZeroPoint]; |
| |
44 |
// Reset the mask and let each animation turn on whatever resizing options it needs |
| |
45 |
[subview setAutoresizingMask:NSViewNotSizable]; |
| |
46 |
} |
| |
47 |
|
| |
48 |
- (void)resetSubviewOfView:(NSView *)view { |
| |
49 |
NSView *subview = [[view subviews] objectAtIndex:0]; |
| |
50 |
[subview setFrameOrigin:NSZeroPoint]; |
| |
51 |
// Allow the views to resize properly now that the animation is done. |
| |
52 |
[subview setAutoresizingMask:[container_ autoresizingMask]]; |
| |
53 |
} |
| |
54 |
|
| |
55 |
- (NSViewAnimation *)dissolve { |
| |
56 |
[toView_ setFrame:[container_ bounds]]; |
| |
57 |
// Note: view does not need to be unhidden manually as in the other cases. This is because the fade in |
| |
58 |
// effect will do it for you. |
| |
59 |
|
| |
60 |
NSViewAnimation *animation = [[[NSViewAnimation alloc] initWithViewAnimations: |
| |
61 |
[NSArray arrayWithObjects: |
| |
62 |
// Old view is set to fade out |
| |
63 |
[NSDictionary dictionaryWithObjectsAndKeys:fromView_, NSViewAnimationTargetKey, NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey, nil], |
| |
64 |
// New view is set to fade in |
| |
65 |
[NSDictionary dictionaryWithObjectsAndKeys:toView_, NSViewAnimationTargetKey, NSViewAnimationFadeInEffect, NSViewAnimationEffectKey, nil], |
| |
66 |
nil] |
| |
67 |
] autorelease]; |
| |
68 |
return animation; |
| |
69 |
} |
| |
70 |
|
| |
71 |
- (NSViewAnimation *)moveIn { |
| |
72 |
NSRect rect = [container_ bounds]; |
| |
73 |
// Set the old view to be resizable on the right side. It will appear as if it's sitting still |
| |
74 |
[[[fromView_ subviews] objectAtIndex:0] setAutoresizingMask:NSViewMaxXMargin]; |
| |
75 |
|
| |
76 |
// Set the new view to be out of bounds on the right side, ready to be animated in |
| |
77 |
[toView_ setFrame:NSMakeRect(NSMaxX(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect))]; |
| |
78 |
// If a previous animation resulted in a zero frame, it set it to hidden. We have to unhide it manually. |
| |
79 |
[toView_ setHidden:NO]; |
| |
80 |
|
| |
81 |
NSViewAnimation *animation = [[[NSViewAnimation alloc] initWithViewAnimations: |
| |
82 |
[NSArray arrayWithObjects: |
| |
83 |
// The left "viewport" shrinks to zero-width on the left side |
| |
84 |
[NSDictionary dictionaryWithObjectsAndKeys:fromView_, NSViewAnimationTargetKey, [NSValue valueWithRect:NSMakeRect(NSMinX(rect), NSMinY(rect), 0.0, NSHeight(rect))], NSViewAnimationEndFrameKey, nil], |
| |
85 |
// New view frame is just the viewable area. Since it is currently out of bounds, it will appear to slide |
| |
86 |
// in bounds. |
| |
87 |
[NSDictionary dictionaryWithObjectsAndKeys:toView_, NSViewAnimationTargetKey, [NSValue valueWithRect:rect], NSViewAnimationEndFrameKey, nil], |
| |
88 |
nil] |
| |
89 |
] autorelease]; |
| |
90 |
return animation; |
| |
91 |
} |
| |
92 |
|
| |
93 |
- (NSViewAnimation *)push { |
| |
94 |
NSRect rect = [container_ bounds]; |
| |
95 |
// Set old view to be resizable on the left side. It will appear to move to the left since the right margin is |
| |
96 |
// fixed. |
| |
97 |
[[[fromView_ subviews] objectAtIndex:0] setAutoresizingMask:NSViewMinXMargin]; |
| |
98 |
|
| |
99 |
// Set the new view to be out of bounds on the right side, ready to be animated in |
| |
100 |
[toView_ setFrame:NSMakeRect(NSMaxX(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect))]; |
| |
101 |
// If a previous animation resulted in a zero frame, it set it to hidden. We have to unhide it manually. |
| |
102 |
[toView_ setHidden:NO]; |
| |
103 |
|
| |
104 |
NSViewAnimation *animation = [[[NSViewAnimation alloc] initWithViewAnimations: |
| |
105 |
[NSArray arrayWithObjects: |
| |
106 |
// Old view frame gets moved to the left, out of bounds. |
| |
107 |
[NSDictionary dictionaryWithObjectsAndKeys:fromView_, NSViewAnimationTargetKey, [NSValue valueWithRect:NSMakeRect(NSMinX(rect) - NSWidth(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect))], NSViewAnimationEndFrameKey, nil], |
| |
108 |
// New view frame is just the viewable area. Since it is currently out of bounds, it will appear to slide |
| |
109 |
// in bounds. Note, this is the same as in the "Move In" case. |
| |
110 |
[NSDictionary dictionaryWithObjectsAndKeys:toView_, NSViewAnimationTargetKey, [NSValue valueWithRect:rect], NSViewAnimationEndFrameKey, nil], |
| |
111 |
nil] |
| |
112 |
] autorelease]; |
| |
113 |
return animation; |
| |
114 |
} |
| |
115 |
|
| |
116 |
- (NSViewAnimation *)reveal { |
| |
117 |
NSRect rect = [container_ bounds]; |
| |
118 |
// Set old view to be resizable on the left side. It will appear to move to the left since the right margin is |
| |
119 |
// fixed. |
| |
120 |
[[[fromView_ subviews] objectAtIndex:0] setAutoresizingMask:NSViewMinXMargin]; |
| |
121 |
|
| |
122 |
// Set new view to be resizable on the right side. It will appear to sit still. |
| |
123 |
[[[toView_ subviews] objectAtIndex:0] setAutoresizingMask:NSViewMinXMargin]; |
| |
124 |
|
| |
125 |
// Make the right viewport zero-width view on the right side. It will reveal the view as it expands to the left. |
| |
126 |
[toView_ setFrame:NSMakeRect(NSMaxX(rect), NSMinY(rect), 0.0, NSHeight(rect))]; |
| |
127 |
[toView_ setHidden:NO]; |
| |
128 |
|
| |
129 |
// Make the subview such that it's right edge is flush with its superview/viewport. |
| |
130 |
[[[toView_ subviews] objectAtIndex:0] setFrame:NSMakeRect(NSMinX(rect) - NSWidth(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect))]; |
| |
131 |
|
| |
132 |
NSViewAnimation *animation = [[[NSViewAnimation alloc] initWithViewAnimations: |
| |
133 |
[NSArray arrayWithObjects: |
| |
134 |
// The left "viewport" shrinks to zero-width |
| |
135 |
[NSDictionary dictionaryWithObjectsAndKeys:fromView_, NSViewAnimationTargetKey, [NSValue valueWithRect:NSMakeRect(NSMinX(rect), NSMinY(rect), 0.0, NSHeight(rect))], NSViewAnimationEndFrameKey, nil], |
| |
136 |
// The right view port expands to encompass the full bounds. |
| |
137 |
[NSDictionary dictionaryWithObjectsAndKeys:toView_, NSViewAnimationTargetKey, [NSValue valueWithRect:rect], NSViewAnimationEndFrameKey, nil], |
| |
138 |
nil] |
| |
139 |
] autorelease]; |
| |
140 |
return animation; |
| |
141 |
} |
| |
142 |
|
| |
143 |
- (NSViewAnimation *)wipe { |
| |
144 |
NSRect rect = [container_ bounds]; |
| |
145 |
// Set the old view to be resizable on the right side. It will appear as if it's sitting still |
| |
146 |
[[[fromView_ subviews] objectAtIndex:0] setAutoresizingMask:NSViewMaxXMargin]; |
| |
147 |
|
| |
148 |
// Set new view to be resizable on the right side. It will appear to sit still. |
| |
149 |
[[[toView_ subviews] objectAtIndex:0] setAutoresizingMask:NSViewMinXMargin]; |
| |
150 |
|
| |
151 |
// Make the right viewport zero-wdith |
| |
152 |
[toView_ setFrame:NSMakeRect(NSMaxX(rect), NSMinY(rect), 0.0, NSHeight(rect))]; |
| |
153 |
[toView_ setHidden:NO]; |
| |
154 |
|
| |
155 |
// Make the subview such that it's right edge is flush with its superview/viewport. |
| |
156 |
[[[toView_ subviews] objectAtIndex:0] setFrame:NSMakeRect(NSMinX(rect) - NSWidth(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect))]; |
| |
157 |
|
| |
158 |
NSViewAnimation *animation = [[[NSViewAnimation alloc] initWithViewAnimations: |
| |
159 |
[NSArray arrayWithObjects: |
| |
160 |
// The left "viewport" shrinks to zero-width |
| |
161 |
[NSDictionary dictionaryWithObjectsAndKeys:fromView_, NSViewAnimationTargetKey, [NSValue valueWithRect:NSMakeRect(NSMinX(rect), NSMinY(rect), 0.0, NSHeight(rect))], NSViewAnimationEndFrameKey, nil], |
| |
162 |
// The right view port expands to encompass the full bounds. |
| |
163 |
[NSDictionary dictionaryWithObjectsAndKeys:toView_, NSViewAnimationTargetKey, [NSValue valueWithRect:rect], NSViewAnimationEndFrameKey, nil], |
| |
164 |
nil] |
| |
165 |
] autorelease]; |
| |
166 |
return animation; |
| |
167 |
} |
| |
168 |
|
| |
169 |
|
| |
170 |
- (void)animate:(GHViewAnimationType)animationType { |
| |
171 |
|
| |
172 |
if ([view1_ isHidden]) { |
| |
173 |
toView_ = view1_; |
| |
174 |
fromView_ = view2_; |
| |
175 |
} else { |
| |
176 |
toView_ = view2_; |
| |
177 |
fromView_ = view1_; |
| |
178 |
} |
| |
179 |
|
| |
180 |
// Unset the first responder. Can cause drawing artifacts since the blue glow extends beyond the view's bounds. |
| |
181 |
//[[container_ window] makeFirstResponder:nil]; |
| |
182 |
|
| |
183 |
// Turn off all autoresizing for now. Will be twiddling these for different effects. |
| |
184 |
[self prepareSubviewOfView:toView_]; |
| |
185 |
[self prepareSubviewOfView:fromView_]; |
| |
186 |
|
| |
187 |
NSViewAnimation *animation = nil; |
| |
188 |
switch (animationType) { |
| |
189 |
case GHViewAnimationDissolve: animation = [self dissolve]; break; |
| |
190 |
case GHViewAnimationMoveIn: animation = [self moveIn]; break; |
| |
191 |
case GHViewAnimationPush: animation = [self push]; break; |
| |
192 |
case GHViewAnimationReveal: animation = [self reveal]; break; |
| |
193 |
case GHViewAnimationWipe: animation = [self wipe]; break; |
| |
194 |
default: |
| |
195 |
NSAssert(false, @"Invalid animation type"); |
| |
196 |
} |
| |
197 |
|
| |
198 |
|
| |
199 |
[animation setAnimationBlockingMode:NSAnimationBlocking]; |
| |
200 |
[animation startAnimation]; |
| |
201 |
|
| |
202 |
// Not all the animations above result in the old view being hidden so do it here |
| |
203 |
[fromView_ setHidden:YES]; |
| |
204 |
|
| |
205 |
[self resetSubviewOfView:fromView_]; |
| |
206 |
[self resetSubviewOfView:toView_]; |
| |
207 |
} |
| |
208 |
|
| |
209 |
@end |