mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-31 19:20:48 +00:00
Toolbar improvements... Fixed several major and minor bugs, rewritten the validation support, lot of memory leaks eliminated and other changes
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@19689 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
572ce7130e
commit
dce085aaf0
8 changed files with 492 additions and 378 deletions
31
ChangeLog
31
ChangeLog
|
@ -1,3 +1,34 @@
|
||||||
|
2004-07-07 Quentin Mathe <qmathe@club-internet.fr>
|
||||||
|
|
||||||
|
* Source/GSToolbar.m: Fixed several segmentation faults which could
|
||||||
|
occur when windows with a toolbar have been closed and new similar
|
||||||
|
windows are initialized (bug #9535), rewritten validation support to
|
||||||
|
be more clearer and efficient, and the toolbar notifications now
|
||||||
|
correctly bundles the toolbar items in the notification dictionary
|
||||||
|
(Patch by Ludovic Marcotte).
|
||||||
|
* Source/GSToolbarView:
|
||||||
|
* Source/NSToolbar.m:
|
||||||
|
* Source/NSWindow+Toolbar.m:
|
||||||
|
Related changes and lot of memory leaks fixed permitting to have now
|
||||||
|
the toolbar system properly deallocated when the toolbar is not anymore
|
||||||
|
retained by the user and the toolbar view.
|
||||||
|
Note: In order to observe the toolbar system being deallocated when you close
|
||||||
|
a window, you need to have the option "Window released when closed"
|
||||||
|
checked.
|
||||||
|
Actual retain logic is strictly :
|
||||||
|
- Superview in the view hierachy retains toolbar view
|
||||||
|
- Toolbar view retains toolbar
|
||||||
|
- Toolbar view retains toolbar items view
|
||||||
|
- Toolbar retains toolbar items
|
||||||
|
And when a toolbar is based on NSToolbar class :
|
||||||
|
- Windows retains toolbar view.
|
||||||
|
* Source/NSView.m: Added a missing method call -viewWillMoveToSuperview:
|
||||||
|
in -removeSubview: method (this missing method is used by the toolbar
|
||||||
|
view).
|
||||||
|
* Headers/Additions/GNUstepGUI/GSToolbar.h:
|
||||||
|
* Headers/AppKit/NSToolbar.h:
|
||||||
|
Moved the _window ivar from GSToolbar class to NSToolbar class.
|
||||||
|
|
||||||
2004-07-07 01:23 Alexander Malmberg <alexander@malmberg.org>
|
2004-07-07 01:23 Alexander Malmberg <alexander@malmberg.org>
|
||||||
|
|
||||||
* Source/NSWindow+Toolbar.m: Properly convert window frames to
|
* Source/NSWindow+Toolbar.m: Properly convert window frames to
|
||||||
|
|
|
@ -79,7 +79,6 @@ APPKIT_EXPORT NSString *NSToolbarWillAddItemNotification;
|
||||||
NSString *_selectedItemIdentifier;
|
NSString *_selectedItemIdentifier;
|
||||||
NSMutableArray *_items;
|
NSMutableArray *_items;
|
||||||
GSToolbarView *_toolbarView;
|
GSToolbarView *_toolbarView;
|
||||||
NSWindow *_window;
|
|
||||||
BOOL _build;
|
BOOL _build;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
@interface NSToolbar : GSToolbar
|
@interface NSToolbar : GSToolbar
|
||||||
{
|
{
|
||||||
|
NSWindow *_window;
|
||||||
BOOL _visible;
|
BOOL _visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,15 +56,16 @@ static const int current_version = 1;
|
||||||
static NSMutableArray *toolbars;
|
static NSMutableArray *toolbars;
|
||||||
|
|
||||||
// Validation stuff
|
// Validation stuff
|
||||||
static const unsigned int ValidationInterval = 10;
|
static const unsigned int ValidationInterval = 4;
|
||||||
static id validationCenter;
|
@class GSValidationCenter; // Mandatory because the interface is declared later
|
||||||
|
static GSValidationCenter *vc;
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
@implementation NSArray (ObjectsWithValueForKey)
|
@implementation NSArray (ObjectsWithValueForKey)
|
||||||
|
|
||||||
- (NSArray *) objectsWithValue: (id)value forKey: (NSString *)key
|
- (NSArray *) objectsWithValue: (id)value forKey: (NSString *)key
|
||||||
{
|
{
|
||||||
NSMutableArray *result = [[NSMutableArray alloc] init];
|
NSMutableArray *result = [NSMutableArray array];
|
||||||
NSArray *keys = [self valueForKey: key];
|
NSArray *keys = [self valueForKey: key];
|
||||||
int i, n = 0;
|
int i, n = 0;
|
||||||
|
|
||||||
|
@ -84,381 +85,377 @@ static id validationCenter;
|
||||||
if ([result count] == 0)
|
if ([result count] == 0)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
AUTORELEASE(result);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
// Validation support
|
/*
|
||||||
|
* Validation support
|
||||||
|
*
|
||||||
|
* Validation support is architectured around a shared validation center, which
|
||||||
|
* is our public interface to handle the validation, behind the scene each
|
||||||
|
* window has an associated validation object created when an observer is added
|
||||||
|
* to the validation center.
|
||||||
|
* A validation object calls the _validate: method on the observer when the
|
||||||
|
* mouse is inside the observed window and only in the case this window is
|
||||||
|
* updated or in the case the mouse stays inside more than four seconds, then
|
||||||
|
* the action will be reiterated every four seconds until the mouse exits.
|
||||||
|
* A validation object owns a window to observe, a tracking rect attached to
|
||||||
|
* the window root view to know when the mouse is inside, a timer to be able to
|
||||||
|
* send the _validate: message periodically, and one ore more observers, then it
|
||||||
|
* is necessary to supply with each registered observer an associated window to
|
||||||
|
* observe.
|
||||||
|
* In the case, an object would observe several windows, the _validate: has a
|
||||||
|
* parameter observedWindow to let us know where the message is coming from.
|
||||||
|
* Because we cannot know surely when a validation object is deallocated, a
|
||||||
|
* method named clean has been added which permits to invalidate a validation
|
||||||
|
* object which must not be used anymore, not calling it would let segmentation
|
||||||
|
* faults occurs.
|
||||||
|
*/
|
||||||
|
|
||||||
@interface GSValidationObject : NSObject
|
@interface GSValidationObject : NSObject
|
||||||
{
|
|
||||||
NSMutableArray *_observers;
|
|
||||||
NSView *_view;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) initWithView: (NSView *)view;
|
|
||||||
- (NSArray *) observers;
|
|
||||||
- (void) addObserver: (id)observer;
|
|
||||||
- (void) removeObserver: (id)observer;
|
|
||||||
- (void) validate;
|
|
||||||
- (NSView *) view;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface GSValidationManager : NSObject
|
|
||||||
{
|
{
|
||||||
NSWindow *_window;
|
NSWindow *_window;
|
||||||
NSView *_trackingRectView;
|
NSView *_trackingRectView;
|
||||||
NSTrackingRectTag _trackingRect;
|
NSTrackingRectTag _trackingRect;
|
||||||
|
NSMutableArray *_observers;
|
||||||
NSTimer *_validationTimer;
|
NSTimer *_validationTimer;
|
||||||
BOOL _inside;
|
BOOL _inside;
|
||||||
|
BOOL _validating;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initWithWindow: (NSWindow *)window;
|
- (NSMutableArray *) observers;
|
||||||
|
- (void) setObservers: (NSMutableArray *)observers;
|
||||||
|
- (NSWindow *) window;
|
||||||
|
- (void) setWindow: (NSWindow *)window;
|
||||||
- (void) validate;
|
- (void) validate;
|
||||||
|
- (void) scheduledValidate;
|
||||||
|
- (void) clean;
|
||||||
|
|
||||||
- (void) invalidate;
|
|
||||||
|
|
||||||
// Tracking rect methods
|
|
||||||
- (void) mouseEntered: (NSEvent *)event;
|
|
||||||
- (void) mouseExited: (NSEvent *)event;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface GSValidationCenter : NSObject
|
@interface GSValidationCenter : NSObject
|
||||||
{
|
{
|
||||||
NSMutableArray *_validationManagers;
|
NSMutableArray *_vobjs;
|
||||||
NSMutableArray *_validationObjects;
|
|
||||||
NSWindow *_prevWindow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (GSValidationCenter *) sharedValidationCenter;
|
+ (id) sharedValidationCenter;
|
||||||
- (id) init;
|
|
||||||
- (void) viewWillMove: (NSNotification *)notification;
|
- (NSArray *) observersWindow: (NSWindow *)window;
|
||||||
- (void) viewDidMove: (NSNotification *)notification;
|
- (void) addObserver: (id)observer window: (NSWindow *)window;
|
||||||
- (void) unregisterValidationObject: (GSValidationObject *)validationObject;
|
- (void) removeObserver: (id)observer window: (NSWindow *)window;
|
||||||
- (GSValidationObject *) validationObjectWithView: (NSView *)view;
|
|
||||||
|
|
||||||
// Private methods
|
|
||||||
- (GSValidationManager *) _validationManagerWithWindow: (NSWindow *)window;
|
|
||||||
- (NSArray *) _validationObjectsWithWindow: (NSWindow *)window;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
// Validation mechanism
|
// Validation mechanism
|
||||||
|
|
||||||
@implementation GSValidationObject
|
|
||||||
|
|
||||||
- (id) initWithView: (NSView *)view
|
|
||||||
{
|
|
||||||
if ((self = [super init]) != nil)
|
|
||||||
{
|
|
||||||
ASSIGN(_view, view);
|
|
||||||
_observers = [[NSMutableArray alloc] init];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) dealloc
|
|
||||||
{
|
|
||||||
RELEASE(_view);
|
|
||||||
RELEASE(_observers);
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *) observers
|
|
||||||
{
|
|
||||||
return _observers;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) addObserver: (id)observer
|
|
||||||
{
|
|
||||||
[_observers addObject: observer];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) removeObserver: (id)observer
|
|
||||||
{
|
|
||||||
if ([_observers containsObject: observer])
|
|
||||||
[_observers removeObject: observer];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) validate
|
|
||||||
{
|
|
||||||
if ([_view superview] != nil)
|
|
||||||
{
|
|
||||||
[_observers makeObjectsPerformSelector: @selector(_validate)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSView *) view
|
|
||||||
{
|
|
||||||
return _view;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface NSWindow (GNUstepPrivate)
|
@interface NSWindow (GNUstepPrivate)
|
||||||
- (NSView *) _windowView;
|
- (NSView *) _windowView;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GSValidationManager
|
@implementation GSValidationObject
|
||||||
|
|
||||||
- (id) initWithWindow: (NSWindow *)window
|
- (id) initWithWindow: (NSWindow *)window
|
||||||
{
|
{
|
||||||
if ((self = [super init]) != nil)
|
if ((self = [super init]) != nil)
|
||||||
{
|
{
|
||||||
NSView *vw;
|
_observers = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
vw = [window _windowView];
|
|
||||||
|
|
||||||
ASSIGN(_window, window);
|
|
||||||
[nc addObserver: self selector: @selector(windowDidUpdate:)
|
[nc addObserver: self selector: @selector(windowDidUpdate:)
|
||||||
name: NSWindowDidUpdateNotification object: _window];
|
name: NSWindowDidUpdateNotification
|
||||||
[nc addObserver: self selector: @selector(windowWillClose:)
|
object: window];
|
||||||
name: NSWindowWillCloseNotification object: _window];
|
[nc addObserver: vc
|
||||||
|
selector: @selector(windowWillClose:)
|
||||||
|
name: NSWindowWillCloseNotification
|
||||||
|
object: window];
|
||||||
|
|
||||||
ASSIGN(_trackingRectView, vw);
|
_trackingRectView = [window _windowView];
|
||||||
_trackingRect
|
_trackingRect
|
||||||
= [_trackingRectView addTrackingRect: [_trackingRectView bounds]
|
= [_trackingRectView addTrackingRect: [_trackingRectView bounds]
|
||||||
owner: self
|
owner: self
|
||||||
userData: nil
|
userData: nil
|
||||||
assumeInside: NO];
|
assumeInside: NO];
|
||||||
|
_window = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) invalidate
|
|
||||||
{
|
|
||||||
[_trackingRectView removeTrackingRect: _trackingRect];
|
|
||||||
// tracking rect retains us, that is normal ?
|
|
||||||
|
|
||||||
[_validationTimer invalidate]; // timer idem
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
RELEASE(_trackingRectView);
|
// NSLog(@"vobj dealloc");
|
||||||
RELEASE(_window);
|
|
||||||
|
// [_trackingRectView removeTrackingRect: _trackingRect];
|
||||||
|
// Not here because the tracking rect retains us, then when the tracking rect
|
||||||
|
// would be deallocated that would create a loop and a segmentation fault.
|
||||||
|
// See next method.
|
||||||
|
|
||||||
|
RELEASE(_observers);
|
||||||
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) windowWillClose: (NSNotification *)notification
|
- (void) clean
|
||||||
{
|
{
|
||||||
GSValidationCenter *vc = [GSValidationCenter sharedValidationCenter];
|
if ([_validationTimer isValid])
|
||||||
NSEnumerator *e;
|
|
||||||
id vo;
|
|
||||||
|
|
||||||
[nc removeObserver: self];
|
|
||||||
|
|
||||||
e = [[vc _validationObjectsWithWindow: _window] objectEnumerator];
|
|
||||||
while ((vo = [e nextObject]) != nil)
|
|
||||||
{
|
{
|
||||||
[vc unregisterValidationObject: vo];
|
[_validationTimer invalidate];
|
||||||
|
_validationTimer = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[nc removeObserver: vc
|
||||||
|
name: NSWindowWillCloseNotification
|
||||||
|
object: _window];
|
||||||
|
[nc removeObserver: self
|
||||||
|
name: NSWindowDidUpdateNotification
|
||||||
|
object: _window];
|
||||||
|
|
||||||
|
[self setWindow: nil];
|
||||||
|
// Needed because the validation timer can retain us and by this way retain also the toolbar which is
|
||||||
|
// currently observing.
|
||||||
|
|
||||||
|
[self setObservers: nil]; // To release observers
|
||||||
|
|
||||||
|
[_trackingRectView removeTrackingRect: _trackingRect];
|
||||||
|
// We can safely remove the tracking rect here, because it will never call
|
||||||
|
// this method unlike dealloc.
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: Replace the deprecated method which follows by this one when -base
|
||||||
|
* NSObject will implement it.
|
||||||
|
*
|
||||||
|
- (id) valueForUndefinedKey: (NSString *)key
|
||||||
|
{
|
||||||
|
if ([key isEqualToString: @"window"] || [key isEqualToString: @"_window"])
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
return [super valueForUndefinedKey: key];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
- (id) handleQueryWithUnboundKey: (NSString *)key
|
||||||
|
{
|
||||||
|
if ([key isEqualToString: @"window"] || [key isEqualToString: @"_window"])
|
||||||
|
return [NSNull null];
|
||||||
|
|
||||||
|
return [super handleQueryWithUnboundKey: key];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableArray *) observers
|
||||||
|
{
|
||||||
|
return _observers;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setObservers: (NSMutableArray *)observers
|
||||||
|
{
|
||||||
|
ASSIGN(_observers, observers);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSWindow *) window
|
||||||
|
{
|
||||||
|
return _window;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setWindow: (NSWindow *)window
|
||||||
|
{
|
||||||
|
_window = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) validate
|
||||||
|
{
|
||||||
|
_validating = YES;
|
||||||
|
|
||||||
|
// NSLog(@"vobj validate");
|
||||||
|
|
||||||
|
[_observers makeObjectsPerformSelector: @selector(_validate:)
|
||||||
|
withObject: _window];
|
||||||
|
|
||||||
|
_validating = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) mouseEntered: (NSEvent *)event
|
- (void) mouseEntered: (NSEvent *)event
|
||||||
{
|
{
|
||||||
_inside = YES;
|
_inside = YES;
|
||||||
if (_validationTimer == nil || ![_validationTimer isValid])
|
[self scheduledValidate];
|
||||||
{
|
|
||||||
_validationTimer = [NSTimer timerWithTimeInterval: ValidationInterval
|
|
||||||
target: self
|
|
||||||
selector: @selector(validate)
|
|
||||||
userInfo: nil
|
|
||||||
repeats: YES];
|
|
||||||
[[NSRunLoop currentRunLoop] addTimer: _validationTimer
|
|
||||||
forMode: NSDefaultRunLoopMode];
|
|
||||||
[self validate];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) mouseExited: (NSEvent *)event
|
- (void) mouseExited: (NSEvent *)event
|
||||||
{
|
{
|
||||||
_inside = NO;
|
_inside = NO;
|
||||||
[_validationTimer invalidate];
|
if ([_validationTimer isValid])
|
||||||
_validationTimer = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) validate
|
|
||||||
{
|
|
||||||
[[[GSValidationCenter sharedValidationCenter]
|
|
||||||
_validationObjectsWithWindow: _window]
|
|
||||||
makeObjectsPerformSelector: @selector(validate)];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (void) windowDidUpdate: (NSNotification *)notification
|
|
||||||
{
|
|
||||||
if ([[NSApp currentEvent] type] == NSLeftMouseUp)
|
|
||||||
{
|
{
|
||||||
GSValidationManager *validationManager =
|
[_validationTimer invalidate];
|
||||||
[[GSValidationCenter sharedValidationCenter]
|
_validationTimer = nil;
|
||||||
_validationManagerWithWindow: [notification object]];
|
|
||||||
|
|
||||||
[validationManager performSelector: @selector(validate) withObject: nil];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) windowDidUpdate: (NSNotification *)notification
|
||||||
|
{
|
||||||
|
// NSLog(@"Window update %d", [[NSApp currentEvent] type]);
|
||||||
|
|
||||||
|
if (!_inside || _validating || [[NSApp currentEvent] type] == NSMouseMoved)
|
||||||
|
return;
|
||||||
|
// _validating permits in the case the UI/window is refreshed by a validation to
|
||||||
|
// avoid have windowDidUpdate called, which would cause a loop like that :
|
||||||
|
// validate -> view update -> windowDidUpdate -> validate etc.
|
||||||
|
|
||||||
|
[self validate];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) scheduledValidate
|
||||||
|
{
|
||||||
|
if (!_inside)
|
||||||
|
return;
|
||||||
|
|
||||||
|
[self validate];
|
||||||
|
|
||||||
|
_validationTimer =
|
||||||
|
[NSTimer timerWithTimeInterval: ValidationInterval
|
||||||
|
target: self
|
||||||
|
selector: @selector(scheduledValidate)
|
||||||
|
userInfo: nil
|
||||||
|
repeats: NO];
|
||||||
|
[[NSRunLoop currentRunLoop] addTimer: _validationTimer
|
||||||
|
forMode: NSDefaultRunLoopMode];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@implementation GSValidationCenter
|
@implementation GSValidationCenter
|
||||||
|
|
||||||
+ (GSValidationCenter *) sharedValidationCenter
|
+ (GSValidationCenter *) sharedValidationCenter
|
||||||
{
|
{
|
||||||
if (validationCenter == nil)
|
if (vc == nil)
|
||||||
validationCenter = [[GSValidationCenter alloc] init];
|
{
|
||||||
|
if ((vc = [[GSValidationCenter alloc] init]) != nil)
|
||||||
|
{
|
||||||
|
// Nothing special
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return validationCenter;
|
return vc;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) init
|
- (id) init
|
||||||
{
|
{
|
||||||
if ((self = [super init]) != nil)
|
if ((self = [super init]) != nil)
|
||||||
{
|
{
|
||||||
_validationManagers = [[NSMutableArray alloc] init];
|
_vobjs = [[NSMutableArray alloc] init];
|
||||||
_validationObjects = [[NSMutableArray alloc] init];
|
|
||||||
|
|
||||||
[nc addObserver: self
|
|
||||||
selector: @selector(viewWillMove:)
|
|
||||||
name: @"GSViewWillMoveToWindow"
|
|
||||||
object: nil];
|
|
||||||
[nc addObserver: self
|
|
||||||
selector: @selector(viewDidMove:)
|
|
||||||
name: @"GSViewDidMoveToWindow"
|
|
||||||
object: nil];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) viewWillMove: (NSNotification *)notification
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
_prevWindow = [[notification object] window];
|
[nc removeObserver: self];
|
||||||
RETAIN(_prevWindow);
|
|
||||||
|
RELEASE(_vobjs);
|
||||||
|
|
||||||
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) viewDidMove: (NSNotification *)notification
|
- (NSArray *) observersWindow: (NSWindow *)window
|
||||||
{
|
{
|
||||||
NSWindow *window = [[notification object] window];
|
int i;
|
||||||
GSValidationManager *validationManager =
|
NSArray *observersArray;
|
||||||
[self _validationManagerWithWindow : _prevWindow];
|
NSMutableArray *result;
|
||||||
|
|
||||||
if (validationManager != nil
|
if (window == nil)
|
||||||
&& [[self _validationObjectsWithWindow: _prevWindow] count] == 0)
|
|
||||||
{
|
{
|
||||||
[validationManager invalidate];
|
result = [NSMutableArray array];
|
||||||
[_validationManagers removeObject: validationManager];
|
observersArray = [_vobjs valueForKey: @"_observers"];
|
||||||
|
for (i = 0; i < [observersArray count]; i++)
|
||||||
|
{
|
||||||
|
[result addObjectsFromArray: [observersArray objectAtIndex: i]];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = [[[_vobjs objectsWithValue: window forKey: @"_window"]
|
||||||
|
objectAtIndex: 0] observers];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) addObserver: (id)observer window: (NSWindow *)window
|
||||||
|
{
|
||||||
|
GSValidationObject *vobj =
|
||||||
|
[[_vobjs objectsWithValue: window forKey: @"_window"] objectAtIndex: 0];
|
||||||
|
NSMutableArray *observersWindow = nil;
|
||||||
|
|
||||||
if (window == nil)
|
if (window == nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
validationManager = [self _validationManagerWithWindow: window];
|
if (vobj != nil)
|
||||||
if (validationManager == nil)
|
|
||||||
{
|
{
|
||||||
validationManager = [[GSValidationManager alloc] initWithWindow: window];
|
observersWindow = [vobj observers];
|
||||||
[_validationManagers addObject: validationManager];
|
|
||||||
RELEASE(validationManager);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
RELEASE(_prevWindow);
|
{
|
||||||
|
vobj = [[GSValidationObject alloc] initWithWindow: window];
|
||||||
|
[_vobjs addObject: vobj];
|
||||||
|
RELEASE(vobj);
|
||||||
|
|
||||||
|
observersWindow = [NSMutableArray array];
|
||||||
|
[vobj setObservers: observersWindow];
|
||||||
|
}
|
||||||
|
|
||||||
|
[observersWindow addObject: observer];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* validationObjectWithView: opposite method
|
- (void) removeObserver: (id)observer window: (NSWindow *)window
|
||||||
* Remove the object in the validation objects list.
|
|
||||||
* Release the validation manager associated to the window (related to the
|
|
||||||
* validation object and its view) in the case there are no other validation
|
|
||||||
* objects related to this window.
|
|
||||||
*/
|
|
||||||
- (void) unregisterValidationObject: (GSValidationObject *)validationObject
|
|
||||||
{
|
{
|
||||||
int index;
|
GSValidationObject *vobj;
|
||||||
|
NSMutableArray *observersWindow;
|
||||||
if ((index = [_validationObjects indexOfObject: validationObject])
|
NSMutableArray *windows;
|
||||||
!= NSNotFound)
|
NSEnumerator *e;
|
||||||
{
|
NSWindow *w;
|
||||||
NSWindow *window = [[validationObject view] window];
|
|
||||||
|
|
||||||
[_validationObjects removeObjectAtIndex: index];
|
|
||||||
|
|
||||||
if ([[self _validationObjectsWithWindow: window] count] == 0)
|
|
||||||
{
|
|
||||||
GSValidationManager *validationManager =
|
|
||||||
[self _validationManagerWithWindow: window];
|
|
||||||
[validationManager invalidate];
|
|
||||||
[_validationManagers removeObject: validationManager];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the validation object associated with the parameter view.
|
if (window == nil)
|
||||||
* If there is no such validation object, create it by using view and then check
|
|
||||||
* that an associated validation manager (bound to the window which the view
|
|
||||||
* depends on) exists.
|
|
||||||
* If there is no such validation manager, create it.
|
|
||||||
*/
|
|
||||||
- (GSValidationObject *) validationObjectWithView: (NSView *)view
|
|
||||||
{
|
|
||||||
GSValidationObject *validationObject;
|
|
||||||
GSValidationManager *validationManager;
|
|
||||||
NSWindow *window = [view window];
|
|
||||||
|
|
||||||
if (view == nil)
|
|
||||||
{
|
{
|
||||||
NSDebugLog(@"Validation object cannot be created because the view is \
|
windows = [_vobjs valueForKey: @"_window"];
|
||||||
nil");
|
}
|
||||||
return nil;
|
else
|
||||||
|
{
|
||||||
|
windows = [NSArray arrayWithObject: window];
|
||||||
}
|
}
|
||||||
|
|
||||||
validationObject = [[_validationObjects objectsWithValue: view
|
e = [windows objectEnumerator];
|
||||||
forKey: @"_view"] objectAtIndex: 0];
|
|
||||||
if (validationObject == nil)
|
while ((w = [e nextObject]) != nil)
|
||||||
{
|
{
|
||||||
validationObject = [[GSValidationObject alloc] initWithView: view];
|
vobj = [[_vobjs objectsWithValue: w forKey: @"_window"] objectAtIndex: 0];
|
||||||
[_validationObjects addObject: validationObject];
|
observersWindow = [vobj observers];
|
||||||
|
|
||||||
if (window == nil)
|
if (observersWindow != nil && [observersWindow containsObject: observer])
|
||||||
return nil;
|
|
||||||
|
|
||||||
validationManager = [self _validationManagerWithWindow: window];
|
|
||||||
if (validationManager == nil)
|
|
||||||
{
|
{
|
||||||
validationManager =
|
[observersWindow removeObject: observer];
|
||||||
[[GSValidationManager alloc] initWithWindow: window];
|
if ([observersWindow count] == 0)
|
||||||
[_validationManagers addObject: validationManager];
|
{
|
||||||
RELEASE(validationManager);
|
[vobj clean];
|
||||||
|
[_vobjs removeObjectIdenticalTo: vobj];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validationObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private methods
|
- (void) windowWillClose: (NSNotification *)notification
|
||||||
|
|
||||||
- (GSValidationManager *) _validationManagerWithWindow: (NSWindow *)window
|
|
||||||
{
|
{
|
||||||
GSValidationManager *validationManager =
|
GSValidationObject *vobj;
|
||||||
[[_validationManagers objectsWithValue: window forKey: @"_window"]
|
|
||||||
objectAtIndex: 0];
|
// NSLog(@"Window will close");
|
||||||
|
|
||||||
return validationManager;
|
vobj = [[_vobjs objectsWithValue: [notification object] forKey: @"_window"]
|
||||||
}
|
objectAtIndex: 0];
|
||||||
|
if (vobj != nil)
|
||||||
- (NSArray *) _validationObjectsWithWindow: (NSWindow *)window
|
|
||||||
{
|
|
||||||
NSEnumerator *e = [_validationObjects objectEnumerator];
|
|
||||||
id validationObject;
|
|
||||||
NSMutableArray *array = [NSMutableArray array];
|
|
||||||
|
|
||||||
while ((validationObject = [e nextObject]) != nil)
|
|
||||||
{
|
{
|
||||||
if ([[validationObject view] window] == window)
|
[vobj clean];
|
||||||
[array addObject: validationObject];
|
[_vobjs removeObjectIdenticalTo: vobj];
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -491,7 +488,8 @@ static id validationCenter;
|
||||||
- (void) _loadConfig;
|
- (void) _loadConfig;
|
||||||
- (NSToolbarItem *) _toolbarItemForIdentifier: (NSString *)itemIdent;
|
- (NSToolbarItem *) _toolbarItemForIdentifier: (NSString *)itemIdent;
|
||||||
- (GSToolbar *) _toolbarModel;
|
- (GSToolbar *) _toolbarModel;
|
||||||
- (void) _validate;
|
- (void) _validate: (NSWindow *)observedWindow;
|
||||||
|
- (void) _toolbarViewWillMoveToSuperview: (NSView *)newSuperview;
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
- (void) _setToolbarView: (GSToolbarView *)toolbarView;
|
- (void) _setToolbarView: (GSToolbarView *)toolbarView;
|
||||||
|
@ -532,6 +530,7 @@ static id validationCenter;
|
||||||
{
|
{
|
||||||
[self setVersion: current_version];
|
[self setVersion: current_version];
|
||||||
nc = [NSNotificationCenter defaultCenter];
|
nc = [NSNotificationCenter defaultCenter];
|
||||||
|
vc = [GSValidationCenter sharedValidationCenter];
|
||||||
toolbars = [[NSMutableArray alloc] init];
|
toolbars = [[NSMutableArray alloc] init];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -579,10 +578,10 @@ static id validationCenter;
|
||||||
if ([toolbarModel displayMode] != displayMode
|
if ([toolbarModel displayMode] != displayMode
|
||||||
&& [toolbarModel sizeMode] != sizeMode)
|
&& [toolbarModel sizeMode] != sizeMode)
|
||||||
{
|
{
|
||||||
// raise an exception.
|
// Raise an exception.
|
||||||
}
|
}
|
||||||
|
|
||||||
//[self _loadConfig];
|
// [self _loadConfig];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -591,7 +590,7 @@ static id validationCenter;
|
||||||
_autosavesConfiguration = NO;
|
_autosavesConfiguration = NO;
|
||||||
_configurationDictionary = nil;
|
_configurationDictionary = nil;
|
||||||
|
|
||||||
//[self _loadConfig];
|
// [self _loadConfig];
|
||||||
|
|
||||||
_delegate = nil;
|
_delegate = nil;
|
||||||
}
|
}
|
||||||
|
@ -605,8 +604,12 @@ static id validationCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
// use DESTROY ?
|
NSLog(@"Toolbar dealloc %@", self);
|
||||||
|
|
||||||
|
[vc removeObserver: self window: nil];
|
||||||
|
|
||||||
|
// Use DESTROY ?
|
||||||
RELEASE(_identifier);
|
RELEASE(_identifier);
|
||||||
RELEASE(_selectedItemIdentifier);
|
RELEASE(_selectedItemIdentifier);
|
||||||
RELEASE(_configurationDictionary);
|
RELEASE(_configurationDictionary);
|
||||||
|
@ -621,6 +624,40 @@ static id validationCenter;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) release
|
||||||
|
{
|
||||||
|
// We currently only worry about when our toolbar view is deallocated.
|
||||||
|
// Views which belongs to a window which is deallocated, are released.
|
||||||
|
// In such case, it's necessary to remove the toolbar which belongs to this
|
||||||
|
// view from the master list when nobody else still retains us, so that it
|
||||||
|
// doesn't cause a memory leak.
|
||||||
|
if ([self retainCount] == 2)
|
||||||
|
[toolbars removeObjectIdenticalTo: self];
|
||||||
|
|
||||||
|
[super release];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: Replace the deprecated method which follows by this one when -base
|
||||||
|
* NSObject will implement it.
|
||||||
|
*
|
||||||
|
- (id) valueForUndefinedKey: (NSString *)key
|
||||||
|
{
|
||||||
|
if ([key isEqualToString: @"window"] || [key isEqualToString: @"_window"])
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
return [super valueForUndefinedKey: key];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
- (id) handleQueryWithUnboundKey: (NSString *)key
|
||||||
|
{
|
||||||
|
if ([key isEqualToString: @"window"] || [key isEqualToString: @"_window"])
|
||||||
|
return [NSNull null];
|
||||||
|
|
||||||
|
return [super handleQueryWithUnboundKey: key];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) insertItemWithItemIdentifier: (NSString *)itemIdentifier
|
- (void) insertItemWithItemIdentifier: (NSString *)itemIdentifier
|
||||||
atIndex: (int)index
|
atIndex: (int)index
|
||||||
{
|
{
|
||||||
|
@ -768,14 +805,14 @@ static id validationCenter;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSLog(@"toolbar delegate does not respond to %@",
|
NSLog(@"Toolbar delegate does not respond to %@",
|
||||||
@selector(toolbarSelectableItemIdentifiers:));
|
@selector(toolbarSelectableItemIdentifiers:));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectableIdentifiers == nil)
|
if (selectableIdentifiers == nil)
|
||||||
{
|
{
|
||||||
NSLog(@"toolbar delegate returns no such selectable item identifiers");
|
NSLog(@"Toolbar delegate returns no such selectable item identifiers");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -798,7 +835,7 @@ static id validationCenter;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSLog(@"toolbar delegate returns no such selectable item identifiers");
|
NSLog(@"Toolbar delegate returns no such selectable item identifiers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,7 +859,7 @@ static id validationCenter;
|
||||||
- (void) _build
|
- (void) _build
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* toolbar build :
|
* Toolbar build :
|
||||||
* will use the delegate when there is no toolbar model
|
* will use the delegate when there is no toolbar model
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -886,7 +923,7 @@ static id validationCenter;
|
||||||
{
|
{
|
||||||
NSArray *linked;
|
NSArray *linked;
|
||||||
id toolbar;
|
id toolbar;
|
||||||
|
|
||||||
linked = [toolbars objectsWithValue: [self identifier]
|
linked = [toolbars objectsWithValue: [self identifier]
|
||||||
forKey: @"_identifier"];
|
forKey: @"_identifier"];
|
||||||
|
|
||||||
|
@ -894,10 +931,12 @@ static id validationCenter;
|
||||||
{
|
{
|
||||||
toolbar = [linked objectAtIndex: 0];
|
toolbar = [linked objectAtIndex: 0];
|
||||||
|
|
||||||
// toolbar model class must be identical to self class :
|
// Toolbar model class must be identical to self class :
|
||||||
// an NSToolbar instance cannot use a GSToolbar instance as a model
|
// an NSToolbar instance cannot use a GSToolbar instance as a model
|
||||||
if ([toolbar isMemberOfClass: [self class]] && toolbar != self)
|
if ([toolbar isMemberOfClass: [self class]] && toolbar != self)
|
||||||
return toolbar;
|
return toolbar;
|
||||||
|
else
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -939,7 +978,7 @@ static id validationCenter;
|
||||||
{ \
|
{ \
|
||||||
if (toolbar != self && [toolbar isMemberOfClass: [self class]]) \
|
if (toolbar != self && [toolbar isMemberOfClass: [self class]]) \
|
||||||
[toolbar signature]; \
|
[toolbar signature]; \
|
||||||
}
|
} \
|
||||||
|
|
||||||
- (void) _insertItemWithItemIdentifier: (NSString *)itemIdentifier
|
- (void) _insertItemWithItemIdentifier: (NSString *)itemIdentifier
|
||||||
atIndex: (int)index
|
atIndex: (int)index
|
||||||
|
@ -972,7 +1011,8 @@ static id validationCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
[nc postNotificationName: NSToolbarWillAddItemNotification
|
[nc postNotificationName: NSToolbarWillAddItemNotification
|
||||||
object: self];
|
object: self
|
||||||
|
userInfo: [NSDictionary dictionaryWithObject: item forKey: @"item"]];
|
||||||
[item _setToolbar: self];
|
[item _setToolbar: self];
|
||||||
[_items insertObject: item atIndex: index];
|
[_items insertObject: item atIndex: index];
|
||||||
|
|
||||||
|
@ -994,10 +1034,15 @@ static id validationCenter;
|
||||||
|
|
||||||
- (void) _removeItemAtIndex: (int)index broadcast: (BOOL)broadcast
|
- (void) _removeItemAtIndex: (int)index broadcast: (BOOL)broadcast
|
||||||
{
|
{
|
||||||
|
id item;
|
||||||
|
|
||||||
|
item = RETAIN([_items objectAtIndex: index]);
|
||||||
[_items removeObjectAtIndex: index];
|
[_items removeObjectAtIndex: index];
|
||||||
[_toolbarView _reload];
|
[_toolbarView _reload];
|
||||||
[nc postNotificationName: NSToolbarDidRemoveItemNotification object: self];
|
[nc postNotificationName: NSToolbarDidRemoveItemNotification
|
||||||
|
object: self
|
||||||
|
userInfo: [NSDictionary dictionaryWithObject: item forKey: @"item"]];
|
||||||
|
RELEASE(item);
|
||||||
|
|
||||||
if (broadcast)
|
if (broadcast)
|
||||||
{
|
{
|
||||||
|
@ -1041,8 +1086,8 @@ static id validationCenter;
|
||||||
|
|
||||||
- (void) _setDelegate: (id)delegate broadcast: (BOOL)broadcast
|
- (void) _setDelegate: (id)delegate broadcast: (BOOL)broadcast
|
||||||
{
|
{
|
||||||
if(_delegate)
|
//if(_delegate)
|
||||||
[nc removeObserver: _delegate name: nil object: self];
|
// [nc removeObserver: _delegate name: nil object: self];
|
||||||
|
|
||||||
if (_delegate == delegate
|
if (_delegate == delegate
|
||||||
|| (broadcast == NO && [_delegate isMemberOfClass: [delegate class]]))
|
|| (broadcast == NO && [_delegate isMemberOfClass: [delegate class]]))
|
||||||
|
@ -1053,7 +1098,9 @@ static id validationCenter;
|
||||||
* instance of the nib owner are created with each new window (see
|
* instance of the nib owner are created with each new window (see
|
||||||
* MiniController.m in the toolbar example application).
|
* MiniController.m in the toolbar example application).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if(_delegate)
|
||||||
|
[nc removeObserver: _delegate name: nil object: self];
|
||||||
|
|
||||||
#define CHECK_REQUIRED_METHOD(selector_name) \
|
#define CHECK_REQUIRED_METHOD(selector_name) \
|
||||||
if (![delegate respondsToSelector: @selector(selector_name)]) \
|
if (![delegate respondsToSelector: @selector(selector_name)]) \
|
||||||
|
@ -1065,7 +1112,7 @@ static id validationCenter;
|
||||||
CHECK_REQUIRED_METHOD(toolbarAllowedItemIdentifiers:);
|
CHECK_REQUIRED_METHOD(toolbarAllowedItemIdentifiers:);
|
||||||
CHECK_REQUIRED_METHOD(toolbarDefaultItemIdentifiers:);
|
CHECK_REQUIRED_METHOD(toolbarDefaultItemIdentifiers:);
|
||||||
|
|
||||||
// assign the delegate...
|
// Assign the delegate...
|
||||||
_delegate = delegate;
|
_delegate = delegate;
|
||||||
|
|
||||||
#define SET_DELEGATE_NOTIFICATION(notif_name) \
|
#define SET_DELEGATE_NOTIFICATION(notif_name) \
|
||||||
|
@ -1081,7 +1128,7 @@ static id validationCenter;
|
||||||
if (_toolbarView != nil)
|
if (_toolbarView != nil)
|
||||||
[_toolbarView _reload];
|
[_toolbarView _reload];
|
||||||
|
|
||||||
// broadcast now...
|
// Broadcast now...
|
||||||
|
|
||||||
if (broadcast)
|
if (broadcast)
|
||||||
{
|
{
|
||||||
|
@ -1093,34 +1140,28 @@ static id validationCenter;
|
||||||
|
|
||||||
- (void) _setToolbarView: (GSToolbarView *)toolbarView
|
- (void) _setToolbarView: (GSToolbarView *)toolbarView
|
||||||
{
|
{
|
||||||
GSValidationObject *validationObject = nil;
|
|
||||||
GSValidationCenter *vc = [GSValidationCenter sharedValidationCenter];
|
|
||||||
GSToolbar *toolbarModel = [self _toolbarModel];
|
GSToolbar *toolbarModel = [self _toolbarModel];
|
||||||
|
|
||||||
if (_toolbarView != nil)
|
if (_toolbarView != nil)
|
||||||
{
|
{
|
||||||
validationObject = [vc validationObjectWithView: _toolbarView];
|
[vc removeObserver: self window: nil];
|
||||||
if (validationObject != nil)
|
}
|
||||||
{
|
if (toolbarView != nil)
|
||||||
[validationObject removeObserver: self];
|
{
|
||||||
if ([[validationObject observers] count] == 0)
|
[vc addObserver: self window: [toolbarView window]];
|
||||||
[vc unregisterValidationObject: validationObject];
|
// In the case the window parameter is a nil value, nothing happens.
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSIGN(_toolbarView, toolbarView);
|
// Don't do an ASSIGN here, the toolbar itself retains us.
|
||||||
|
_toolbarView = toolbarView;
|
||||||
|
|
||||||
if (_toolbarView == nil)
|
if (_toolbarView == nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
validationObject = [vc validationObjectWithView: _toolbarView];
|
|
||||||
if (validationObject != nil)
|
|
||||||
[validationObject addObserver: self];
|
|
||||||
|
|
||||||
/* In the case, the user hasn't set a delegate until now, we set it.
|
/* In the case, the user hasn't set a delegate until now, we set it.
|
||||||
* Why ?
|
* Why ?
|
||||||
* We don't set it before when the toolbar is inited, to do only one toolbar
|
* We don't set it before when the toolbar is initialized, to do only one
|
||||||
* content load.
|
* toolbar content load.
|
||||||
* ...
|
* ...
|
||||||
* 1 toolbar = [[GSToolbar alloc] initWithIdentifier: @"blabla"];
|
* 1 toolbar = [[GSToolbar alloc] initWithIdentifier: @"blabla"];
|
||||||
* 2 [toolbar setDelegate: myDelegate];
|
* 2 [toolbar setDelegate: myDelegate];
|
||||||
|
@ -1139,8 +1180,24 @@ static id validationCenter;
|
||||||
return _toolbarView;
|
return _toolbarView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _validate
|
- (void) _toolbarViewWillMoveToSuperview: (NSView *)newSuperview
|
||||||
{
|
{
|
||||||
|
// Must synchronize the validation system
|
||||||
|
// _toolbarView should never be nil here
|
||||||
|
// We don't handle synchronization when the toolbar view is added to a superview not
|
||||||
|
// binded to a window, such superview being later moved to a window. (FIX ME ?)
|
||||||
|
|
||||||
|
// NSLog(@"Moving to window %@", [newSuperview window]);
|
||||||
|
|
||||||
|
[vc removeObserver: self window: nil];
|
||||||
|
if (newSuperview != nil)
|
||||||
|
[vc addObserver: self window: [newSuperview window]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) _validate: (NSWindow *)observedWindow
|
||||||
|
{
|
||||||
|
// We observe only one window, then we ignore observedWindow.
|
||||||
|
|
||||||
[self validateVisibleItems];
|
[self validateVisibleItems];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,7 @@ static void initSystemExtensionsColors(void)
|
||||||
*/
|
*/
|
||||||
@interface GSToolbar (GNUstepPrivate)
|
@interface GSToolbar (GNUstepPrivate)
|
||||||
- (void) _build;
|
- (void) _build;
|
||||||
|
- (void) _toolbarViewWillMoveToSuperview: (NSView *)newSuperview;
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
- (void) _setToolbarView: (GSToolbarView *)toolbarView;
|
- (void) _setToolbarView: (GSToolbarView *)toolbarView;
|
||||||
|
@ -158,6 +159,8 @@ static void initSystemExtensionsColors(void)
|
||||||
- (NSArray *) _visibleBackViews;
|
- (NSArray *) _visibleBackViews;
|
||||||
- (void) _setSizeMode: (NSToolbarSizeMode)sizeMode;
|
- (void) _setSizeMode: (NSToolbarSizeMode)sizeMode;
|
||||||
- (NSToolbarSizeMode) _sizeMode;
|
- (NSToolbarSizeMode) _sizeMode;
|
||||||
|
- (BOOL) _usesStandardBackgroundColor;
|
||||||
|
- (void) _setUsesStandardBackgroundColor: (BOOL)standard;
|
||||||
- (void) _setWillBeVisible: (BOOL)willBeVisible;
|
- (void) _setWillBeVisible: (BOOL)willBeVisible;
|
||||||
- (BOOL) _willBeVisible;
|
- (BOOL) _willBeVisible;
|
||||||
@end
|
@end
|
||||||
|
@ -172,8 +175,8 @@ static void initSystemExtensionsColors(void)
|
||||||
// Accessors
|
// Accessors
|
||||||
- (NSMenu *) returnMenu;
|
- (NSMenu *) returnMenu;
|
||||||
|
|
||||||
// this method cannot be called "menu" otherwise it would override NSResponder
|
// This method cannot be called "menu" otherwise it would override NSResponder
|
||||||
// method with the same name
|
// method with the same name.
|
||||||
|
|
||||||
- (void) layout;
|
- (void) layout;
|
||||||
- (void) setToolbar: (GSToolbar *)toolbar;
|
- (void) setToolbar: (GSToolbar *)toolbar;
|
||||||
|
@ -185,7 +188,7 @@ static void initSystemExtensionsColors(void)
|
||||||
NSImage *image = [NSImage imageNamed: @"common_ToolbarClippedItemsMark"];
|
NSImage *image = [NSImage imageNamed: @"common_ToolbarClippedItemsMark"];
|
||||||
|
|
||||||
if ((self = [super initWithFrame: NSMakeRect(0, 0, _ClippedItemsViewWidth,
|
if ((self = [super initWithFrame: NSMakeRect(0, 0, _ClippedItemsViewWidth,
|
||||||
100)]) != nil) // the correct height will be set by the layout method
|
100)]) != nil) // The correct height will be set by the layout method
|
||||||
{
|
{
|
||||||
[self setBordered: NO];
|
[self setBordered: NO];
|
||||||
[[self cell] setHighlightsBy: NSChangeGrayCellMask
|
[[self cell] setHighlightsBy: NSChangeGrayCellMask
|
||||||
|
@ -193,19 +196,13 @@ static void initSystemExtensionsColors(void)
|
||||||
[self setAutoresizingMask: NSViewNotSizable];
|
[self setAutoresizingMask: NSViewNotSizable];
|
||||||
[self setImagePosition: NSImageOnly];
|
[self setImagePosition: NSImageOnly];
|
||||||
[image setScalesWhenResized: YES];
|
[image setScalesWhenResized: YES];
|
||||||
//[image setSize: NSMakeSize(20, 20)];
|
// [image setSize: NSMakeSize(20, 20)];
|
||||||
[self setImage: image];
|
[self setImage: image];
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
|
||||||
{
|
|
||||||
RELEASE(_toolbar);
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) layout {
|
- (void) layout {
|
||||||
[self setFrameSize: NSMakeSize([self frame].size.width,
|
[self setFrameSize: NSMakeSize([self frame].size.width,
|
||||||
[[_toolbar _toolbarView] _heightFromLayout])];
|
[[_toolbar _toolbarView] _heightFromLayout])];
|
||||||
|
@ -235,7 +232,7 @@ static void initSystemExtensionsColors(void)
|
||||||
|
|
||||||
- (NSMenu *) returnMenu
|
- (NSMenu *) returnMenu
|
||||||
{
|
{
|
||||||
// this method cannot be called "menu" otherwise it would
|
// This method cannot be called "menu" otherwise it would
|
||||||
// override NSResponder method with the same name
|
// override NSResponder method with the same name
|
||||||
NSMenu *menu = [[NSMenu alloc] initWithTitle: @""];
|
NSMenu *menu = [[NSMenu alloc] initWithTitle: @""];
|
||||||
NSEnumerator *e;
|
NSEnumerator *e;
|
||||||
|
@ -269,7 +266,8 @@ static void initSystemExtensionsColors(void)
|
||||||
|
|
||||||
- (void) setToolbar: (GSToolbar *)toolbar
|
- (void) setToolbar: (GSToolbar *)toolbar
|
||||||
{
|
{
|
||||||
ASSIGN(_toolbar, toolbar);
|
// Don't do an ASSIGN here, the toolbar view retains us.
|
||||||
|
_toolbar = toolbar;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -318,7 +316,7 @@ static void initSystemExtensionsColors(void)
|
||||||
toolbarViewHeight = _ToolbarViewSmallHeight;
|
toolbarViewHeight = _ToolbarViewSmallHeight;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// raise exception
|
// Raise exception
|
||||||
toolbarViewHeight = 0;
|
toolbarViewHeight = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,8 +354,17 @@ static void initSystemExtensionsColors(void)
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id) retain
|
||||||
|
{
|
||||||
|
return [super retain];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
|
NSLog(@"Toolbar view dealloc");
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
||||||
|
|
||||||
RELEASE(_toolbar);
|
RELEASE(_toolbar);
|
||||||
RELEASE(_clippedItemsMark);
|
RELEASE(_clippedItemsMark);
|
||||||
RELEASE(_clipView);
|
RELEASE(_clipView);
|
||||||
|
@ -427,6 +434,14 @@ static void initSystemExtensionsColors(void)
|
||||||
[self _reload];
|
[self _reload];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) viewWillMoveToSuperview: (NSView *)newSuperview
|
||||||
|
{
|
||||||
|
[super viewWillMoveToSuperview: newSuperview];
|
||||||
|
|
||||||
|
[_toolbar _toolbarViewWillMoveToSuperview: newSuperview];
|
||||||
|
// Allow to update the validation system which is window specific
|
||||||
|
}
|
||||||
|
|
||||||
- (void) viewDidMoveToWindow
|
- (void) viewDidMoveToWindow
|
||||||
{
|
{
|
||||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||||
|
@ -437,18 +452,8 @@ static void initSystemExtensionsColors(void)
|
||||||
|
|
||||||
[nc removeObserver: self name: NSWindowDidResizeNotification object: nil];
|
[nc removeObserver: self name: NSWindowDidResizeNotification object: nil];
|
||||||
[nc addObserver: self selector: @selector(windowDidResize:)
|
[nc addObserver: self selector: @selector(windowDidResize:)
|
||||||
name: NSWindowDidResizeNotification object: _window];
|
name: NSWindowDidResizeNotification
|
||||||
|
object: _window];
|
||||||
[nc postNotificationName: @"GSViewDidMoveToWindow" object: self];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) viewWillMoveToWindow: (NSWindow *)newWindow
|
|
||||||
{
|
|
||||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
|
||||||
|
|
||||||
[super viewWillMoveToWindow: newWindow];
|
|
||||||
|
|
||||||
[nc postNotificationName: @"GSViewWillMoveToWindow" object: self];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// More methods... Accessors
|
// More methods... Accessors
|
||||||
|
@ -484,7 +489,7 @@ static void initSystemExtensionsColors(void)
|
||||||
rect.size.height = _ToolbarViewSmallHeight;
|
rect.size.height = _ToolbarViewSmallHeight;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
; // invalid
|
; // Invalid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take in account the border
|
// Take in account the border
|
||||||
|
@ -611,7 +616,7 @@ static void initSystemExtensionsColors(void)
|
||||||
// We add each backView associated with an added toolbar item
|
// We add each backView associated with an added toolbar item
|
||||||
|
|
||||||
e = [backViews objectEnumerator];
|
e = [backViews objectEnumerator];
|
||||||
subviews = [_clipView subviews];
|
subviews = [_clipView subviews];
|
||||||
|
|
||||||
while ((backView = [e nextObject]) != nil)
|
while ((backView = [e nextObject]) != nil)
|
||||||
{
|
{
|
||||||
|
@ -679,7 +684,7 @@ static void initSystemExtensionsColors(void)
|
||||||
- (void) _setToolbar: (GSToolbar *)toolbar
|
- (void) _setToolbar: (GSToolbar *)toolbar
|
||||||
{
|
{
|
||||||
if ([toolbar sizeMode] != _sizeMode)
|
if ([toolbar sizeMode] != _sizeMode)
|
||||||
; // FIXME : raise exception here
|
; // FIXME: Raise exception here
|
||||||
|
|
||||||
[toolbar _setToolbarView: self]; // We set the toolbar view on the new toolbar
|
[toolbar _setToolbarView: self]; // We set the toolbar view on the new toolbar
|
||||||
[_toolbar _setToolbarView: nil]; // We unset the toolbar view from the previous toolbar
|
[_toolbar _setToolbarView: nil]; // We unset the toolbar view from the previous toolbar
|
||||||
|
@ -763,8 +768,9 @@ static void initSystemExtensionsColors(void)
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Will return the visible (not clipped) back views in the toolbar view even when the toolbar is not visible
|
// Will return the visible (not clipped) back views in the toolbar view even
|
||||||
// May be should be renamed _notClippedBackViews method
|
// when the toolbar is not visible .
|
||||||
|
// May be should be renamed _notClippedBackViews method.
|
||||||
- (NSArray *) _visibleBackViews
|
- (NSArray *) _visibleBackViews
|
||||||
{
|
{
|
||||||
NSArray *items = [_toolbar items];
|
NSArray *items = [_toolbar items];
|
||||||
|
@ -814,6 +820,11 @@ static void initSystemExtensionsColors(void)
|
||||||
_willBeVisible = willBeVisible;
|
_willBeVisible = willBeVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) _usesStandardBackgroundColor
|
||||||
|
{
|
||||||
|
return [BackgroundColor isEqual: [self standardBackgroundColor]];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) _setUsesStandardBackgroundColor: (BOOL)standard
|
- (void) _setUsesStandardBackgroundColor: (BOOL)standard
|
||||||
{
|
{
|
||||||
if (standard)
|
if (standard)
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include <Foundation/NSObject.h>
|
#include <Foundation/NSObject.h>
|
||||||
#include <Foundation/NSArray.h>
|
#include <Foundation/NSArray.h>
|
||||||
|
#include <Foundation/NSAutoreleasePool.h>
|
||||||
#include <Foundation/NSDictionary.h>
|
#include <Foundation/NSDictionary.h>
|
||||||
#include <Foundation/NSException.h>
|
#include <Foundation/NSException.h>
|
||||||
#include <Foundation/NSNotification.h>
|
#include <Foundation/NSNotification.h>
|
||||||
|
@ -137,7 +138,8 @@ static const int current_version = 1;
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
|
// NSLog(@"Dummy NSToolbar dealloc");
|
||||||
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +190,7 @@ static const int current_version = 1;
|
||||||
{ \
|
{ \
|
||||||
if (toolbar != self && [self isMemberOfClass: [self class]]) \
|
if (toolbar != self && [self isMemberOfClass: [self class]]) \
|
||||||
[toolbar signature]; \
|
[toolbar signature]; \
|
||||||
}
|
} \
|
||||||
|
|
||||||
- (void) _setDisplayMode: (NSToolbarDisplayMode)displayMode
|
- (void) _setDisplayMode: (NSToolbarDisplayMode)displayMode
|
||||||
broadcast: (BOOL)broadcast
|
broadcast: (BOOL)broadcast
|
||||||
|
@ -247,40 +249,43 @@ static const int current_version = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle notifications
|
// Notifications
|
||||||
|
|
||||||
- (void) handleNotification: (NSNotification *)notification
|
- (void) handleNotification: (NSNotification *)notification
|
||||||
{
|
{
|
||||||
NSMutableArray *toolbars = [GSToolbar _toolbars];
|
|
||||||
|
|
||||||
// We currently only worry about when our window closes.
|
// We currently only worry about when our window closes.
|
||||||
// It's necessary to remove the toolbar which belongs to this
|
// It's necessary to set the _window ivar in master list to nil when it is
|
||||||
// window from the master list, so that it doesn't cause a
|
// closed, so that it doesn't cause a segmentation fault when we looks at
|
||||||
// memory leak.
|
// _window ivar with KVC in -[NSWindow(Toolbar) toolbar].
|
||||||
[toolbars removeObjectIdenticalTo: self];
|
[self _setWindow: nil];
|
||||||
|
|
||||||
|
if ([_toolbarView superview] == nil)
|
||||||
|
RELEASE(_toolbarView);
|
||||||
|
// We release the toolbar view in such case because NSWindow(Toolbar) retains
|
||||||
|
// it when its superview value is nil.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private Accessors
|
// Private Accessors
|
||||||
|
|
||||||
- (void)_setWindow: (NSWindow *)window
|
- (void) _setWindow: (NSWindow *)window
|
||||||
{
|
{
|
||||||
if(_window != window)
|
if (_window != window)
|
||||||
{
|
{
|
||||||
if(_window)
|
if (_window)
|
||||||
{
|
{
|
||||||
[nc removeObserver: _window];
|
[nc removeObserver: self];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(window)
|
if (window)
|
||||||
{
|
{
|
||||||
// watch for this window closing....
|
// Watch for this window closing....
|
||||||
[nc addObserver: self
|
[nc addObserver: self
|
||||||
selector: @selector(handleNotification:)
|
selector: @selector(handleNotification:)
|
||||||
name: NSWindowWillCloseNotification
|
name: NSWindowWillCloseNotification
|
||||||
object: window];
|
object: window];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't do an ASSIGN because the toolbar view retains us.
|
// We don't do an ASSIGN because the toolbar view retains us.
|
||||||
// call [NSWindow(Toolbar) setToolbar:] to set the toolbar window
|
// call [NSWindow(Toolbar) setToolbar:] to set the toolbar window
|
||||||
_window = window;
|
_window = window;
|
||||||
|
|
|
@ -620,6 +620,7 @@ GSSetDragTypes(NSView* obj, NSArray *types)
|
||||||
[self willRemoveSubview: aView];
|
[self willRemoveSubview: aView];
|
||||||
aView->_super_view = nil;
|
aView->_super_view = nil;
|
||||||
[aView viewWillMoveToWindow: nil];
|
[aView viewWillMoveToWindow: nil];
|
||||||
|
[aView viewWillMoveToSuperview: nil];
|
||||||
[aView setNextResponder: nil];
|
[aView setNextResponder: nil];
|
||||||
RETAIN(aView);
|
RETAIN(aView);
|
||||||
[_sub_views removeObjectIdenticalTo: aView];
|
[_sub_views removeObjectIdenticalTo: aView];
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include <Foundation/NSDebug.h>
|
#include <Foundation/NSDebug.h>
|
||||||
#include <Foundation/NSException.h>
|
#include <Foundation/NSException.h>
|
||||||
|
#include <Foundation/NSAutoreleasePool.h>
|
||||||
#include "AppKit/NSWindow+Toolbar.h"
|
#include "AppKit/NSWindow+Toolbar.h"
|
||||||
#include "AppKit/NSView.h"
|
#include "AppKit/NSView.h"
|
||||||
#include "AppKit/NSToolbar.h"
|
#include "AppKit/NSToolbar.h"
|
||||||
|
@ -98,7 +98,11 @@
|
||||||
|
|
||||||
if (toolbar != nil && [toolbar isVisible])
|
if (toolbar != nil && [toolbar isVisible])
|
||||||
{
|
{
|
||||||
NSArray *subviews = [_contentView subviews];
|
NSArray *subviews = [_contentView subviews];
|
||||||
|
// Take in account this method call returns an array which is an
|
||||||
|
// autoreleased copy.
|
||||||
|
// By side effect, this increments the toolbar view retain count until the
|
||||||
|
// autorelease pool is cleared.
|
||||||
NSView *subview;
|
NSView *subview;
|
||||||
int i, n = [subviews count];
|
int i, n = [subviews count];
|
||||||
GSToolbarView *toolbarView = [toolbar _toolbarView];
|
GSToolbarView *toolbarView = [toolbar _toolbarView];
|
||||||
|
@ -140,7 +144,7 @@
|
||||||
return (index == NSNotFound) ? nil : [toolbars objectAtIndex: index];
|
return (index == NSNotFound) ? nil : [toolbars objectAtIndex: index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// user oriented method
|
// User oriented method
|
||||||
- (void) setContentViewWithoutToolbar: (NSView *)contentViewWithoutToolbar
|
- (void) setContentViewWithoutToolbar: (NSView *)contentViewWithoutToolbar
|
||||||
{
|
{
|
||||||
NSToolbar *toolbar = [self toolbar];
|
NSToolbar *toolbar = [self toolbar];
|
||||||
|
@ -160,7 +164,13 @@
|
||||||
- (void) setToolbar: (NSToolbar*)toolbar
|
- (void) setToolbar: (NSToolbar*)toolbar
|
||||||
{
|
{
|
||||||
NSToolbar *lastToolbar = [self toolbar];
|
NSToolbar *lastToolbar = [self toolbar];
|
||||||
GSToolbarView *toolbarView = nil;
|
GSToolbarView *toolbarView = [toolbar _toolbarView];
|
||||||
|
|
||||||
|
if (toolbarView != nil)
|
||||||
|
{
|
||||||
|
NSLog(@"Error: the new toolbar is still owned by a toolbar view");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (lastToolbar != nil)
|
if (lastToolbar != nil)
|
||||||
{
|
{
|
||||||
|
@ -178,18 +188,16 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
/*
|
||||||
// ELSE
|
* Else we do
|
||||||
// -----
|
*/
|
||||||
|
|
||||||
// The window want to know which toolbar is binded
|
// The window want to know which toolbar is binded
|
||||||
|
|
||||||
[toolbar _setWindow : self];
|
[toolbar _setWindow : self];
|
||||||
|
|
||||||
// Instantiate or retrieve the toolbar view (we create this view when the toolbar hasn't such
|
// Instantiate the toolbar view
|
||||||
// view)...
|
|
||||||
|
|
||||||
toolbarView = [toolbar _toolbarView];
|
|
||||||
if (toolbarView == nil)
|
if (toolbarView == nil)
|
||||||
{
|
{
|
||||||
toolbarView = [[GSToolbarView alloc] initWithFrame: NSMakeRect(0, 0,
|
toolbarView = [[GSToolbarView alloc] initWithFrame: NSMakeRect(0, 0,
|
||||||
|
@ -274,10 +282,10 @@
|
||||||
contentViewWithoutToolbar = _contentView;
|
contentViewWithoutToolbar = _contentView;
|
||||||
|
|
||||||
// Switch the content view
|
// Switch the content view
|
||||||
|
|
||||||
RETAIN(contentViewWithoutToolbar);
|
RETAIN(contentViewWithoutToolbar);
|
||||||
[self setContentView:
|
[self setContentView:
|
||||||
[[NSView alloc] initWithFrame: [_contentView frame]]];
|
AUTORELEASE([[NSView alloc] initWithFrame: [_contentView frame]])];
|
||||||
|
|
||||||
// Resize the window
|
// Resize the window
|
||||||
|
|
||||||
|
@ -298,9 +306,9 @@
|
||||||
contentViewWithoutToolbarFrame.size.height,
|
contentViewWithoutToolbarFrame.size.height,
|
||||||
contentViewWithoutToolbarFrame.size.width,
|
contentViewWithoutToolbarFrame.size.width,
|
||||||
newToolbarViewHeight)];
|
newToolbarViewHeight)];
|
||||||
|
|
||||||
[_contentView addSubview: toolbarView];
|
[_contentView addSubview: toolbarView];
|
||||||
|
RELEASE(toolbarView);
|
||||||
|
|
||||||
// Insert the previous content view
|
// Insert the previous content view
|
||||||
|
|
||||||
/* We want contentViewWithoutToolbarFrame at the origin of our new
|
/* We want contentViewWithoutToolbarFrame at the origin of our new
|
||||||
|
@ -319,7 +327,7 @@
|
||||||
contentViewWithoutToolbar = [self contentViewWithoutToolbar];
|
contentViewWithoutToolbar = [self contentViewWithoutToolbar];
|
||||||
|
|
||||||
// Unplug the toolbar view
|
// Unplug the toolbar view
|
||||||
|
RETAIN(toolbarView);
|
||||||
[toolbarView removeFromSuperview];
|
[toolbarView removeFromSuperview];
|
||||||
|
|
||||||
// Resize the window
|
// Resize the window
|
||||||
|
@ -339,9 +347,10 @@
|
||||||
// Switch the content view
|
// Switch the content view
|
||||||
|
|
||||||
RETAIN(contentViewWithoutToolbar);
|
RETAIN(contentViewWithoutToolbar);
|
||||||
// because setContentView: will release the parent view (aka _contentView) and
|
// Because setContentView: will release the parent view (aka _contentView) and
|
||||||
// their subviews and actually contentViewWithoutToolbar is a subview of _contentView
|
// their subviews and actually contentViewWithoutToolbar is a subview of _contentView
|
||||||
|
|
||||||
|
[contentViewWithoutToolbar removeFromSuperviewWithoutNeedingDisplay];
|
||||||
[self setContentView: contentViewWithoutToolbar];
|
[self setContentView: contentViewWithoutToolbar];
|
||||||
|
|
||||||
RELEASE(contentViewWithoutToolbar);
|
RELEASE(contentViewWithoutToolbar);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue