From: Matthew Judy Date: Sun, 13 Apr 2003 15:19:26 +0000 (+0000) Subject: Fairly large ITTSW checkin. X-Git-Tag: v0.1~47 X-Git-Url: http://git.ithinksw.org/ITKit.git/commitdiff_plain/7c89200521dd8c6cb8fc8a17c633ac80d4b18bd2 Fairly large ITTSW checkin. - Created ITCutWindowEffect for simple appear and vanish without a transition. Better than using nil in the ITTSW. - Moved the concept of effect progress out of the effects and into the window itself, as a method in the ITWindowMobility protocol (formerly known as ITWindowPositioning). - Moved the logic to start the vanish timer into ITTSW's setVisibility callback method. If an effect sets the window's visibility to the "Visible" state (having completely appeared, or completely canceled vanishing), the timer will begin. - Cleaned up a lot of code, and improved performance a bit. Looks even better than before on my old dual 450... who knows, it might be good on a G3 :) Stuff that's left in the Kit side of MT's statuswindows: - Implement vanish timer. - Finalize ITSlide*allyWindowEffect - ( Warning... long. ) Cancelling a window appearing should always use a reverse of the entry effect. But sometimes, a different effect may be desired for cancelling a vanishing window than the reverse of the exit effect. For example, a window "Cuts" in, and begins to "Dissolve" out. As of now, cancelling the dissolve out will cause a very fast dissolve back in, however, to match Apple's style, a simple "cut" back in would be desired. It's not as simple as always using an inverse of the entry effect to cancel vanish. Some effects are too radically different (consider trying to cancel a "Pivot" exit with the inverse of a "SlideHorizontally". It just wouldn't work. Personally, i think it's actually better to keep the heuristic as it is, and in the case of "Cut" in / "Dissolve" out, fuck the way Apple does it... Ours looks better. However, a third effect object could be instantiated to handle the cancel vanish effect, which would be used for that purpose if present. This is a big maybe, and is definitely not a showstopper for MT FCS. --- diff --git a/ITCutWindowEffect.h b/ITCutWindowEffect.h new file mode 100755 index 0000000..4826001 --- /dev/null +++ b/ITCutWindowEffect.h @@ -0,0 +1,23 @@ +/* + * ITKit + * ITCutWindowEffect + * Effect subclass which performs a simple cut in or out, with no transition. + * + * Original Author : Matt Judy + * Responsibility : Matt Judy + * + * Copyright (c) 2002 - 2003 iThink Software. + * All Rights Reserved + * + */ + + +#import +#import "ITWindowEffect.h" + + +@interface ITCutWindowEffect : ITWindowEffect { + +} + +@end diff --git a/ITCutWindowEffect.m b/ITCutWindowEffect.m new file mode 100755 index 0000000..a42fcc8 --- /dev/null +++ b/ITCutWindowEffect.m @@ -0,0 +1,42 @@ +#import "ITCutWindowEffect.h" +#import "ITTransientStatusWindow.h" + + +@implementation ITCutWindowEffect + + +/*************************************************************************/ +#pragma mark - +#pragma mark APPEAR METHODS +/*************************************************************************/ + +- (void)performAppear +{ + [_window orderFront:self]; + [self setWindowVisibility:ITTransientStatusWindowVisibleState]; +} + +- (void)cancelAppear +{ + [self performVanish]; +} + + +/*************************************************************************/ +#pragma mark - +#pragma mark VANISH METHODS +/*************************************************************************/ + +- (void)performVanish +{ + [_window orderOut:self]; + [self setWindowVisibility:ITTransientStatusWindowHiddenState]; +} + +- (void)cancelVanish +{ + [self performAppear]; +} + + +@end diff --git a/ITDissolveWindowEffect.m b/ITDissolveWindowEffect.m index 31aed00..fc2bd38 100755 --- a/ITDissolveWindowEffect.m +++ b/ITDissolveWindowEffect.m @@ -1,27 +1,136 @@ #import "ITDissolveWindowEffect.h" +#import "ITTransientStatusWindow.h" + + +@interface ITDissolveWindowEffect (Private) +- (void)performAppearFromProgress:(float)progress effectTime:(float)time; +- (void)appearStep; +- (void)appearFinish; +- (void)performVanishFromProgress:(float)progress effectTime:(float)time; +- (void)vanishStep; +- (void)vanishFinish; +@end @implementation ITDissolveWindowEffect +/*************************************************************************/ +#pragma mark - +#pragma mark APPEAR METHODS +/*************************************************************************/ + - (void)performAppear { - NSLog(@"ITDissolveWindowEffect does not implement performAppear."); + [self setWindowVisibility:ITTransientStatusWindowAppearingState]; + [self performAppearFromProgress:0.0 effectTime:_effectTime]; } -- (void)performVanish +- (void)performAppearFromProgress:(float)progress effectTime:(float)time +{ + [_window setEffectProgress:progress]; + _effectSpeed = (1.0 / (EFFECT_FPS * time)); + + if ( progress == 0.0 ) { + [_window setAlphaValue:0.0]; + } + + [_window orderFront:self]; + _effectTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / EFFECT_FPS) + target:self + selector:@selector(appearStep) + userInfo:nil + repeats:YES]; +} + +- (void)appearStep +{ + float interFade = 0.0; + [_window setEffectProgress:([_window effectProgress] + _effectSpeed)]; + [_window setEffectProgress:( ([_window effectProgress] < 1.0) ? [_window effectProgress] : 1.0)]; + interFade = (( sin(([_window effectProgress] * pi) - (pi / 2)) + 1 ) / 2); + [_window setAlphaValue:interFade]; + + if ( [_window effectProgress] >= 1.0 ) { + [self appearFinish]; + } +} + +- (void)appearFinish { - NSLog(@"ITDissolveWindowEffect does not implement performVanish."); + [_effectTimer invalidate]; + _effectTimer = nil; + [self setWindowVisibility:ITTransientStatusWindowVisibleState]; } - (void)cancelAppear { - NSLog(@"ITWindowEffect does not implement cancelAppear."); + [self setWindowVisibility:ITTransientStatusWindowVanishingState]; + + [_effectTimer invalidate]; + _effectTimer = nil; + + [self performVanishFromProgress:[_window effectProgress] effectTime:(_effectTime / 3.5)]; +} + + +/*************************************************************************/ +#pragma mark - +#pragma mark VANISH METHODS +/*************************************************************************/ + +- (void)performVanish +{ + [self setWindowVisibility:ITTransientStatusWindowVanishingState]; + [self performVanishFromProgress:1.0 effectTime:_effectTime]; +} + +- (void)performVanishFromProgress:(float)progress effectTime:(float)time +{ + [_window setEffectProgress:progress]; + _effectSpeed = (1.0 / (EFFECT_FPS * time)); + if ( progress == 1.0 ) { + [_window setAlphaValue:1.0]; + } + + [_window orderFront:self]; + _effectTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / EFFECT_FPS) + target:self + selector:@selector(vanishStep) + userInfo:nil + repeats:YES]; +} + +- (void)vanishStep +{ + float interFade = 1.0; + [_window setEffectProgress:([_window effectProgress] - _effectSpeed)]; + [_window setEffectProgress:( ([_window effectProgress] > 0.0) ? [_window effectProgress] : 0.0)]; + interFade = (( sin(([_window effectProgress] * pi) - (pi / 2)) + 1 ) / 2); + [_window setAlphaValue:interFade]; + + if ( [_window effectProgress] <= 0.0 ) { + [self vanishFinish]; + } +} + +- (void)vanishFinish +{ + [_effectTimer invalidate]; + _effectTimer = nil; + [_window orderOut:self]; + [_window setAlphaValue:1.0]; + [self setWindowVisibility:ITTransientStatusWindowHiddenState]; } - (void)cancelVanish { - NSLog(@"ITDissolveWindowEffect does not implement cancelVanish."); + [self setWindowVisibility:ITTransientStatusWindowVanishingState]; + + [_effectTimer invalidate]; + _effectTimer = nil; + + [self performAppearFromProgress:[_window effectProgress] effectTime:(_effectTime / 3.5)]; } diff --git a/ITPivotWindowEffect.m b/ITPivotWindowEffect.m index 2c87f68..95c1040 100755 --- a/ITPivotWindowEffect.m +++ b/ITPivotWindowEffect.m @@ -6,14 +6,22 @@ @interface ITPivotWindowEffect (Private) - (void)setPivot:(float)angle; - (void)performAppearFromProgress:(float)progress effectTime:(float)time; -- (void)performVanishFromProgress:(float)progress effectTime:(float)time; +- (void)appearStep; - (void)appearFinish; +- (void)performVanishFromProgress:(float)progress effectTime:(float)time; +- (void)vanishStep; - (void)vanishFinish; @end @implementation ITPivotWindowEffect + +/*************************************************************************/ +#pragma mark - +#pragma mark APPEAR METHODS +/*************************************************************************/ + - (void)performAppear { [self setWindowVisibility:ITTransientStatusWindowAppearingState]; @@ -22,7 +30,7 @@ - (void)performAppearFromProgress:(float)progress effectTime:(float)time { - _effectProgress = progress; + [_window setEffectProgress:progress]; _effectSpeed = (1.0 / (EFFECT_FPS * time)); if ( progress == 0.0 ) { @@ -38,91 +46,105 @@ repeats:YES]; } -- (void)performVanish +- (void)appearStep { - [self setWindowVisibility:ITTransientStatusWindowVanishingState]; - [self performVanishFromProgress:1.0 effectTime:_effectTime]; -} + float interPivot = 0.0; + [_window setEffectProgress:([_window effectProgress] + _effectSpeed)]; + [_window setEffectProgress:( ([_window effectProgress] < 1.0) ? [_window effectProgress] : 1.0)]; + interPivot = (( sin(([_window effectProgress] * pi) - (pi / 2)) + 1 ) / 2); + [self setPivot:((interPivot * 45) + 315)]; + [_window setAlphaValue:interPivot]; -- (void)performVanishFromProgress:(float)progress effectTime:(float)time -{ - _effectProgress = progress; - _effectSpeed = (1.0 / (EFFECT_FPS * time)); - if ( progress == 1.0 ) { - [self setPivot:0.0]; - [_window setAlphaValue:1.0]; + if ( [_window effectProgress] >= 1.0 ) { + [self appearFinish]; } - - [_window orderFront:self]; - _effectTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / EFFECT_FPS) - target:self - selector:@selector(vanishStep) - userInfo:nil - repeats:YES]; } -- (void)cancelAppear +- (void)appearFinish { - [self setWindowVisibility:ITTransientStatusWindowVanishingState]; - [_effectTimer invalidate]; _effectTimer = nil; - - [self performVanishFromProgress:_effectProgress effectTime:(_effectTime / 3.5)]; + [self setWindowVisibility:ITTransientStatusWindowVisibleState]; } -- (void)cancelVanish +- (void)cancelAppear { - [self setWindowVisibility:ITTransientStatusWindowAppearingState]; + [self setWindowVisibility:ITTransientStatusWindowVanishingState]; [_effectTimer invalidate]; _effectTimer = nil; - [self performAppearFromProgress:_effectProgress effectTime:(_effectTime / 3.5)]; + [self performVanishFromProgress:[_window effectProgress] effectTime:(_effectTime / 3.5)]; } -- (void)appearStep + +/*************************************************************************/ +#pragma mark - +#pragma mark VANISH METHODS +/*************************************************************************/ + +- (void)performVanish { - float interPivot = 0.0; - _effectProgress += _effectSpeed; - _effectProgress = (_effectProgress < 1.0 ? _effectProgress : 1.0); - interPivot = (( sin((_effectProgress * pi) - (pi / 2)) + 1 ) / 2); - [self setPivot:((interPivot * 45) + 315)]; - [_window setAlphaValue:interPivot]; + [self setWindowVisibility:ITTransientStatusWindowVanishingState]; + [self performVanishFromProgress:1.0 effectTime:_effectTime]; +} - if ( _effectProgress >= 1.0 ) { - [self appearFinish]; +- (void)performVanishFromProgress:(float)progress effectTime:(float)time +{ + [_window setEffectProgress:progress]; + _effectSpeed = (1.0 / (EFFECT_FPS * time)); + if ( progress == 1.0 ) { + [self setPivot:0.0]; + [_window setAlphaValue:1.0]; } + + [_window orderFront:self]; + _effectTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / EFFECT_FPS) + target:self + selector:@selector(vanishStep) + userInfo:nil + repeats:YES]; } - (void)vanishStep { float interPivot = 1.0; - _effectProgress -= _effectSpeed; - _effectProgress = (_effectProgress > 0.0 ? _effectProgress : 0.0); - interPivot = (( sin((_effectProgress * pi) - (pi / 2)) + 1 ) / 2); + [_window setEffectProgress:([_window effectProgress] - _effectSpeed)]; + [_window setEffectProgress:( ([_window effectProgress] > 0.0) ? [_window effectProgress] : 0.0)]; + interPivot = (( sin(([_window effectProgress] * pi) - (pi / 2)) + 1 ) / 2); [self setPivot:((interPivot * 45) + 315)]; [_window setAlphaValue:interPivot]; - if ( _effectProgress <= 0.0 ) { + if ( [_window effectProgress] <= 0.0 ) { [self vanishFinish]; } } -- (void)appearFinish +- (void)vanishFinish { [_effectTimer invalidate]; _effectTimer = nil; - [self setWindowVisibility:ITTransientStatusWindowVisibleState]; + [_window orderOut:self]; + [_window setAlphaValue:1.0]; + [self setWindowVisibility:ITTransientStatusWindowHiddenState]; } -- (void)vanishFinish +- (void)cancelVanish { + [self setWindowVisibility:ITTransientStatusWindowAppearingState]; + [_effectTimer invalidate]; _effectTimer = nil; - [self setWindowVisibility:ITTransientStatusWindowHiddenState]; + + [self performAppearFromProgress:[_window effectProgress] effectTime:(_effectTime / 3.5)]; } + +/*************************************************************************/ +#pragma mark - +#pragma mark PRIVATE METHOD IMPLEMENTATIONS +/*************************************************************************/ + - (void)setPivot:(float)angle { float degAngle = (angle * (pi / 180)); diff --git a/ITTransientStatusWindow.h b/ITTransientStatusWindow.h index 90d74c6..dcbe360 100755 --- a/ITTransientStatusWindow.h +++ b/ITTransientStatusWindow.h @@ -43,7 +43,7 @@ typedef enum { } ITTransientStatusWindowBackgroundType; -@interface ITTransientStatusWindow : NSWindow { +@interface ITTransientStatusWindow : NSWindow { ITWindowVisibilityState _visibilityState; ITTransientStatusWindowExitMode _exitMode; @@ -51,6 +51,7 @@ typedef enum { ITTransientStatusWindowBackgroundType _backgroundType; ITWindowEffect *_entryEffect; ITWindowEffect *_exitEffect; + double _effectProgress; ITVerticalWindowPosition _verticalPosition; ITHorizontalWindowPosition _horizontalPosition; float _screenPadding; @@ -90,6 +91,9 @@ typedef enum { - (ITHorizontalWindowPosition)horizontalPosition; - (void)setHorizontalPosition:(ITHorizontalWindowPosition)newPosition; +- (float)effectProgress; +- (void)setEffectProgress:(float)newProgress; + - (ITWindowEffect *)entryEffect; - (void)setEntryEffect:(ITWindowEffect *)newEffect; diff --git a/ITTransientStatusWindow.m b/ITTransientStatusWindow.m index b06fb3a..6cb33a3 100755 --- a/ITTransientStatusWindow.m +++ b/ITTransientStatusWindow.m @@ -156,13 +156,7 @@ static ITTransientStatusWindow *staticWindow = nil; { if ( _visibilityState == ITTransientStatusWindowHiddenState ) { // Window is hidden. Appear as normal, and start the timer. - if ( _entryEffect == nil ) { - [self orderFront:self]; - _visibilityState = ITTransientStatusWindowVisibleState; - } else { - [_entryEffect performAppear]; - } - [self startVanishTimer]; + [_entryEffect performAppear]; } else if ( _visibilityState == ITTransientStatusWindowVisibleState ) { // Window is completely visible. Simply reset the timer. [self startVanishTimer]; @@ -170,13 +164,7 @@ static ITTransientStatusWindow *staticWindow = nil; // Window is on its way in. Do nothing. } else if ( _visibilityState == ITTransientStatusWindowVanishingState ) { // Window is on its way out. Cancel the vanish. - if ( _exitEffect == nil ) { - [self orderFront:self]; - _visibilityState = ITTransientStatusWindowVisibleState; - } else { - [_exitEffect cancelVanish]; - } - [self startVanishTimer]; + [_exitEffect cancelVanish]; } } @@ -184,13 +172,7 @@ static ITTransientStatusWindow *staticWindow = nil; { if ( _visibilityState == ITTransientStatusWindowVisibleState ) { // Window is totally visible. Perform exit effect. - if ( _exitEffect == nil ) { - [self orderOut:self]; - _visibilityState = ITTransientStatusWindowHiddenState; - } else { - [_exitEffect performVanish]; - } - [self startVanishTimer]; + [_exitEffect performVanish]; } else if ( _visibilityState == ITTransientStatusWindowHiddenState ) { // Window is hidden. Do nothing. } else if ( _visibilityState == ITTransientStatusWindowAppearingState ) { @@ -209,6 +191,10 @@ static ITTransientStatusWindow *staticWindow = nil; - (void)setVisibilityState:(ITWindowVisibilityState)newState { _visibilityState = newState; + + if ( _visibilityState == ITTransientStatusWindowVisibleState ) { + [self startVanishTimer]; + } } - (ITTransientStatusWindowExitMode)exitMode @@ -264,6 +250,16 @@ static ITTransientStatusWindow *staticWindow = nil; _horizontalPosition = newPosition; } +- (float)effectProgress +{ + return _effectProgress; +} + +- (void)setEffectProgress:(float)newProgress +{ + _effectProgress = newProgress; +} + - (float)screenPadding { return _screenPadding; @@ -332,7 +328,8 @@ static ITTransientStatusWindow *staticWindow = nil; - (void)startVanishTimer { - + // start timer, if appropriate + // if timer already exists, restart it. } @end diff --git a/ITWindowEffect.h b/ITWindowEffect.h index 2cc6c45..71852e2 100755 --- a/ITWindowEffect.h +++ b/ITWindowEffect.h @@ -15,6 +15,7 @@ #import #import "ITWindowPositioning.h" +@class ITTransientStatusWindow; #define EFFECT_FPS 30.0 #define DEFAULT_EFFECT_TIME 0.75 @@ -36,18 +37,19 @@ typedef enum { @end -@protocol ITWindowVisibility +@protocol ITWindowMotility - (ITWindowVisibilityState)visibilityState; - (void)setVisibilityState:(ITWindowVisibilityState)newState; +- (float)effectProgress; +- (void)setEffectProgress:(float)newProgress; @end @interface ITWindowEffect : NSObject { - NSWindow *_window; + ITTransientStatusWindow *_window; float _effectTime; float _effectSpeed; - double _effectProgress; ITVerticalWindowPosition _verticalPosition; ITHorizontalWindowPosition _horizontalPosition; NSTimer *_effectTimer; diff --git a/ITWindowEffect.m b/ITWindowEffect.m index d485df5..752742b 100755 --- a/ITWindowEffect.m +++ b/ITWindowEffect.m @@ -11,7 +11,6 @@ _window = [window retain]; _effectTime = DEFAULT_EFFECT_TIME; - _effectProgress = 0.00; _effectTimer = nil; if ( [window conformsToProtocol:@protocol(ITWindowPositioning)] ) { @@ -40,7 +39,7 @@ - (void)setWindowVisibility:(ITWindowVisibilityState)visibilityState { - if ( [_window conformsToProtocol:@protocol(ITWindowVisibility)] ) { + if ( [_window conformsToProtocol:@protocol(ITWindowMotility)] ) { // Cast so the compiler won't gripe [(ITTransientStatusWindow *)_window setVisibilityState:visibilityState]; } else { diff --git a/Showcase/Controller.m b/Showcase/Controller.m index 16b5c0b..f2680bd 100755 --- a/Showcase/Controller.m +++ b/Showcase/Controller.m @@ -2,6 +2,8 @@ #import "ITTransientStatusWindow.h" #import "ITTextField.h" #import "ITPivotWindowEffect.h" +#import "ITDissolveWindowEffect.h" +#import "ITCutWindowEffect.h" #define SW_PAD 24.0 #define SW_SPACE 24.0 @@ -200,8 +202,10 @@ [[statusWindow contentView] setNeedsDisplay:YES]; - [statusWindow setEntryEffect:[[ITPivotWindowEffect alloc] initWithWindow:statusWindow]]; - [statusWindow setExitEffect:[[ITPivotWindowEffect alloc] initWithWindow:statusWindow]]; +// [statusWindow setEntryEffect:[[ITPivotWindowEffect alloc] initWithWindow:statusWindow]]; +// [statusWindow setExitEffect:[[ITPivotWindowEffect alloc] initWithWindow:statusWindow]]; + [statusWindow setEntryEffect:[[ITCutWindowEffect alloc] initWithWindow:statusWindow]]; + [statusWindow setExitEffect: [[ITDissolveWindowEffect alloc] initWithWindow:statusWindow]]; } - (IBAction)toggleStatusWindow:(id)sender