Fixed a crash when Core Image was available.
[ITKit.git] / ITSpinWindowEffect.m
1 #import "ITSpinWindowEffect.h"
2 #import "ITCoreGraphicsHacks.h"
3 #import "ITTransientStatusWindow.h"
4
5
6 @interface ITSpinWindowEffect (Private)
7 - (void)performAppearFromProgress:(float)progress effectTime:(float)time;
8 - (void)appearStep;
9 - (void)appearFinish;
10 - (void)performVanishFromProgress:(float)progress effectTime:(float)time;
11 - (void)vanishStep;
12 - (void)vanishFinish;
13 - (void)setSpin:(float)progress;
14 @end
15
16
17 @implementation ITSpinWindowEffect
18
19
20 + (NSString *)effectName
21 {
22     return @"Spin";
23 }
24
25 + (NSDictionary *)supportedPositions
26 {
27     return [NSDictionary dictionaryWithObjectsAndKeys:
28         [NSDictionary dictionaryWithObjectsAndKeys:
29             [NSNumber numberWithBool:YES], @"Left",
30             [NSNumber numberWithBool:YES], @"Center",
31             [NSNumber numberWithBool:YES], @"Right", nil] , @"Top" ,
32         [NSDictionary dictionaryWithObjectsAndKeys:
33             [NSNumber numberWithBool:YES], @"Left",
34             [NSNumber numberWithBool:YES], @"Center",
35             [NSNumber numberWithBool:YES], @"Right", nil] , @"Middle" ,
36         [NSDictionary dictionaryWithObjectsAndKeys:
37             [NSNumber numberWithBool:YES], @"Left",
38             [NSNumber numberWithBool:YES], @"Center",
39             [NSNumber numberWithBool:YES], @"Right", nil] , @"Bottom" , nil];
40 }
41
42
43 + (unsigned int)listOrder
44 {
45     return 700;
46 }
47
48
49 /*************************************************************************/
50 #pragma mark -
51 #pragma mark APPEAR METHODS
52 /*************************************************************************/
53
54 - (void)performAppear
55 {
56     __idle = NO;
57     
58     [self setWindowVisibility:ITWindowAppearingState];
59     [self performAppearFromProgress:0.0 effectTime:_effectTime];
60 }
61
62 - (void)performAppearFromProgress:(float)progress effectTime:(float)time
63 {
64     [_window setEffectProgress:progress];
65     _effectSpeed = (1.0 / (EFFECT_FPS * time));
66     
67     if ( progress == 0.0 ) {
68         [self setSpin:0.0];
69         [_window setAlphaValue:0.0];
70     }
71     
72     [_window orderFront:self];
73     _effectTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / EFFECT_FPS)
74                                                     target:self
75                                                   selector:@selector(appearStep)
76                                                   userInfo:nil
77                                                    repeats:YES];
78 }
79
80 - (void)appearStep
81 {
82     float interSpin = 0.0;
83     [_window setEffectProgress:([_window effectProgress] + _effectSpeed)];
84     [_window setEffectProgress:( ([_window effectProgress] < 1.0) ? [_window effectProgress] : 1.0)];
85     interSpin = (( sin(([_window effectProgress] * pi) - (pi / 2)) + 1 ) / 2);
86     [self setSpin:-interSpin];
87     [_window setAlphaValue:interSpin];
88
89     if ( [_window effectProgress] >= 1.0 ) {
90         [self appearFinish];
91     }
92 }
93
94 - (void)appearFinish
95 {
96     [_effectTimer invalidate];
97     _effectTimer = nil;
98     [self setWindowVisibility:ITWindowVisibleState];
99     
100     __idle = YES;
101     
102     if ( __shouldReleaseWhenIdle ) {
103         [self release];
104     }
105 }
106
107 - (void)cancelAppear
108 {
109     [self setWindowVisibility:ITWindowVanishingState];
110     
111     [_effectTimer invalidate];
112     _effectTimer = nil;
113     
114     [self performVanishFromProgress:[_window effectProgress] effectTime:(_effectTime / 3.5)];
115 }
116
117
118 /*************************************************************************/
119 #pragma mark -
120 #pragma mark VANISH METHODS
121 /*************************************************************************/
122
123 - (void)performVanish
124 {
125     __idle = NO;
126     
127     [self setWindowVisibility:ITWindowVanishingState];
128     [self performVanishFromProgress:1.0 effectTime:_effectTime];
129 }
130
131 - (void)performVanishFromProgress:(float)progress effectTime:(float)time
132 {
133     [_window setEffectProgress:progress];
134     _effectSpeed = (1.0 / (EFFECT_FPS * time));
135     if ( progress == 1.0 ) {
136         [self setSpin:0.0];
137         [_window setAlphaValue:1.0];
138     }
139
140     [_window orderFront:self];
141     _effectTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / EFFECT_FPS)
142                                                     target:self
143                                                   selector:@selector(vanishStep)
144                                                   userInfo:nil
145                                                    repeats:YES];
146 }
147
148 - (void)vanishStep
149 {
150     float interSpin = 1.0;
151     [_window setEffectProgress:([_window effectProgress] - _effectSpeed)];
152     [_window setEffectProgress:( ([_window effectProgress] > 0.0) ? [_window effectProgress] : 0.0)];
153     interSpin = (( sin(([_window effectProgress] * pi) - (pi / 2)) + 1 ) / 2);
154     [self setSpin:interSpin];
155     [_window setAlphaValue:interSpin];
156
157     if ( [_window effectProgress] <= 0.0 ) {
158         [self vanishFinish];
159     }
160 }
161
162 - (void)vanishFinish
163 {
164     [_effectTimer invalidate];
165     _effectTimer = nil;
166     [_window orderOut:self];
167     [_window setAlphaValue:1.0];
168     [self setSpin:0.0];
169     [self setWindowVisibility:ITWindowHiddenState];
170     
171     __idle = YES;
172     
173     if ( __shouldReleaseWhenIdle ) {
174         [self release];
175     }
176 }
177
178 - (void)cancelVanish
179 {
180     [self setWindowVisibility:ITWindowAppearingState];
181     
182     [_effectTimer invalidate];
183     _effectTimer = nil;
184     
185     [self performAppearFromProgress:[_window effectProgress] effectTime:(_effectTime / 3.5)];
186 }
187
188
189 /*************************************************************************/
190 #pragma mark -
191 #pragma mark PRIVATE METHOD IMPLEMENTATIONS
192 /*************************************************************************/
193
194 - (void)setSpin:(float)progress
195 {
196     float radAngle = (progress * 4 * pi);
197     CGAffineTransform transform;
198     NSPoint translation;
199     NSRect winFrame = [_window frame];
200     
201     translation.x = (winFrame.size.width / 2.0);
202     translation.y = (winFrame.size.height / 2.0);
203     transform = CGAffineTransformMakeTranslation(translation.x, translation.y);
204     transform = CGAffineTransformRotate(transform, radAngle);
205     transform = CGAffineTransformTranslate(transform, -translation.x, -translation.y);
206     
207     translation.x = -winFrame.origin.x;
208     translation.y = winFrame.origin.y + winFrame.size.height - [[NSScreen mainScreen] frame].size.height;
209     
210     transform = CGAffineTransformTranslate(transform, translation.x, translation.y);
211     CGSSetWindowTransform([NSApp contextID],
212                           (CGSWindowID)[_window windowNumber],
213                           transform);
214 }
215
216 @end