![]() |
API 0.9.5
|
00001 /* 00002 * CPPopover.j 00003 * AppKit 00004 * 00005 * Created by Antoine Mercadal. 00006 * Copyright 2011 Antoine Mercadal. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 00024 00025 00026 CPPopoverBehaviorApplicationDefined = 0; 00027 CPPopoverBehaviorTransient = 1; 00028 CPPopoverBehaviorSemitransient = 2; 00029 00030 00031 var CPPopoverDelegate_popover_willShow_ = 1 << 0, 00032 CPPopoverDelegate_popover_didShow_ = 1 << 1, 00033 CPPopoverDelegate_popover_shouldClose_ = 1 << 2, 00034 CPPopoverDelegate_popover_willClose_ = 1 << 3, 00035 CPPopoverDelegate_popover_didClose_ = 1 << 4; 00036 00037 00051 @implementation CPPopover : CPResponder 00052 { 00053 @outlet CPViewController _contentViewController; 00054 @outlet id _delegate; 00055 00056 BOOL _animates; 00057 BOOL _shown; 00058 int _appearance; 00059 int _behavior; 00060 00061 BOOL _needsCompute; 00062 _CPAttachedWindow _attachedWindow; 00063 int _implementedDelegateMethods; 00064 } 00065 00066 00067 #pragma mark - 00068 #pragma mark Initialization 00069 00075 - (CPPopover)init 00076 { 00077 if (self = [super init]) 00078 { 00079 _animates = YES; 00080 _appearance = CPPopoverAppearanceMinimal; 00081 _behavior = CPPopoverBehaviorApplicationDefined; 00082 _needsCompute = YES; 00083 _shown = NO; 00084 } 00085 00086 return self; 00087 } 00088 00089 00090 #pragma mark - 00091 #pragma mark Getters / Setters 00092 00098 - (CPRect)positioningRect 00099 { 00100 if (!_attachedWindow || ![_attachedWindow isVisible]) 00101 return nil; 00102 return [_attachedWindow frame]; 00103 } 00104 00108 - (void)setPositioningRect:(CPRect)aRect 00109 { 00110 if (!_attachedWindow || ![_attachedWindow isVisible]) 00111 return; 00112 [_attachedWindow setFrame:aRect]; 00113 } 00114 00120 - (CPRect)contentSize 00121 { 00122 if (!_attachedWindow || ![_attachedWindow isVisible]) 00123 return nil; 00124 return [[_contentViewController view] frameSize]; 00125 } 00126 00132 - (void)setContentSize:(CPSize)aSize 00133 { 00134 [[_contentViewController view] setFrameSize:aSize]; 00135 } 00136 00142 - (BOOL)shown 00143 { 00144 if (!_attachedWindow) 00145 return NO; 00146 return [_attachedWindow isVisible]; 00147 } 00148 00156 - (void)setBehaviour:(int)aBehaviour 00157 { 00158 if (_behavior == aBehaviour) 00159 return; 00160 00161 _behavior = aBehaviour; 00162 _needsCompute = YES; 00163 } 00164 00165 00166 - (void)setDelegate:(id)aDelegate 00167 { 00168 if (_delegate === aDelegate) 00169 return; 00170 00171 _delegate = aDelegate; 00172 _implementedDelegateMethods = 0; 00173 00174 if ([_delegate respondsToSelector:@selector(popoverWillShow:)]) 00175 _implementedDelegateMethods |= CPPopoverDelegate_popover_willShow_; 00176 00177 if ([_delegate respondsToSelector:@selector(popoverDidShow:)]) 00178 _implementedDelegateMethods |= CPPopoverDelegate_popover_didShow_; 00179 00180 if ([_delegate respondsToSelector:@selector(popoverShouldClose:)]) 00181 _implementedDelegateMethods |= CPPopoverDelegate_popover_shouldClose_; 00182 00183 if ([_delegate respondsToSelector:@selector(popoverWillClose:)]) 00184 _implementedDelegateMethods |= CPPopoverDelegate_popover_willClose_; 00185 00186 if ([_delegate respondsToSelector:@selector(popoverDidClose:)]) 00187 _implementedDelegateMethods |= CPPopoverDelegate_popover_didClose_; 00188 } 00189 00190 #pragma mark - 00191 #pragma mark Positioning 00192 00200 - (void)showRelativeToRect:(CPRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge 00201 { 00202 if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_) 00203 [_delegate popoverWillShow:self]; 00204 00205 if (!_contentViewController) 00206 [CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"]; 00207 00208 if (_needsCompute || !_attachedWindow) 00209 { 00210 var styleMask = (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : nil; 00211 _attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:styleMask]; 00212 } 00213 00214 [_attachedWindow setAppearance:_appearance]; 00215 [_attachedWindow setAnimates:_animates]; 00216 [_attachedWindow setDelegate:self]; 00217 [_attachedWindow setMovableByWindowBackground:NO]; 00218 [_attachedWindow setFrame:[_attachedWindow frameRectForContentRect:[[_contentViewController view] frame]]]; 00219 [_attachedWindow setContentView:[_contentViewController view]]; 00220 00221 if (positioningRect) 00222 [_attachedWindow positionRelativeToRect:positioningRect preferredEdge:preferredEdge]; 00223 else if (positioningView) 00224 [_attachedWindow positionRelativeToView:positioningView preferredEdge:preferredEdge]; 00225 else 00226 [CPException raise:CPInvalidArgumentException reason:@"a value must be passed for positioningRect or positioningView"]; 00227 00228 if (_implementedDelegateMethods & CPPopoverDelegate_popover_didShow_) 00229 [_delegate popoverDidShow:self]; 00230 } 00231 00235 - (void)close 00236 { 00237 if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_) 00238 if (![_delegate popoverShouldClose:self]) 00239 return; 00240 00241 if (_implementedDelegateMethods & CPPopoverDelegate_popover_willClose_) 00242 [_delegate popoverWillClose:self]; 00243 00244 [_attachedWindow close]; 00245 00246 if (_implementedDelegateMethods & CPPopoverDelegate_popover_didClose_) 00247 [_delegate popoverDidClose:self]; 00248 } 00249 00250 00251 #pragma mark - 00252 #pragma mark Action 00253 00259 - (IBAction)performClose:(id)aSender 00260 { 00261 [self close]; 00262 } 00263 00264 00265 #pragma mark - 00266 #pragma mark Delegates 00267 00269 - (BOOL)attachedWindowShouldClose:(_CPAttachedWindow)anAttachedWindow 00270 { 00271 [self close]; 00272 00273 // we return NO, because we want the CPPopover to compute 00274 // if the attached can be close in order to send delegate messages 00275 return NO; 00276 } 00277 00278 @end 00279 00280 var CPPopoverNeedsComputeKey = @"CPPopoverNeedsComputeKey", 00281 CPPopoverAppearanceKey = @"CPPopoverAppearanceKey", 00282 CPPopoverAnimatesKey = @"CPPopoverAnimatesKey", 00283 CPPopoverContentViewControllerKey = @"CPPopoverContentViewControllerKey", 00284 CPPopoverDelegateKey = @"CPPopoverDelegateKey", 00285 CPPopoverBehaviorKey = @"CPPopoverBehaviorKey"; 00286 00287 @implementation CPPopover (CPCoding) 00288 00289 - (id)initWithCoder:(CPCoder)aCoder 00290 { 00291 self = [super initWithCoder:aCoder]; 00292 00293 if (self) 00294 { 00295 _needsCompute = [aCoder decodeIntForKey:CPPopoverNeedsComputeKey]; 00296 _appearance = [aCoder decodeIntForKey:CPPopoverAppearanceKey]; 00297 _animates = [aCoder decodeBoolForKey:CPPopoverAnimatesKey]; 00298 _contentViewController = [aCoder decodeObjectForKey:CPPopoverContentViewControllerKey]; 00299 [self setDelegate:[aCoder decodeObjectForKey:CPPopoverDelegateKey]]; 00300 [self setBehaviour:[aCoder decodeIntForKey:CPPopoverBehaviorKey]]; 00301 } 00302 return self; 00303 } 00304 00305 - (void)encodeWithCoder:(CPCoder)aCoder 00306 { 00307 [super encodeWithCoder:aCoder]; 00308 00309 [aCoder encodeBool:_needsCompute forKey:CPPopoverNeedsComputeKey]; 00310 [aCoder encodeInt:_appearance forKey:CPPopoverAppearanceKey]; 00311 [aCoder encodeObject:_animates forKey:CPPopoverAnimatesKey]; 00312 [aCoder encodeObject:_contentViewController forKey:CPPopoverContentViewControllerKey]; 00313 [aCoder encodeObject:_delegate forKey:CPPopoverDelegateKey]; 00314 [aCoder encodeInt:_behavior forKey:CPPopoverBehaviorKey]; 00315 } 00316 00317 @end 00318 00319 @implementation CPPopover (CPSynthesizedAccessors) 00320 00324 - (CPViewController)contentViewController 00325 { 00326 return _contentViewController; 00327 } 00328 00332 - (void)setContentViewController:(CPViewController)aValue 00333 { 00334 _contentViewController = aValue; 00335 } 00336 00340 - (id)delegate 00341 { 00342 return _delegate; 00343 } 00344 00348 - (BOOL)animates 00349 { 00350 return _animates; 00351 } 00352 00356 - (void)setAnimates:(BOOL)aValue 00357 { 00358 _animates = aValue; 00359 } 00360 00364 - (BOOL)shown 00365 { 00366 return _shown; 00367 } 00368 00372 - (int)appearance 00373 { 00374 return _appearance; 00375 } 00376 00380 - (void)setAppearance:(int)aValue 00381 { 00382 _appearance = aValue; 00383 } 00384 00388 - (int)behavior 00389 { 00390 return _behavior; 00391 } 00392 00393 @end