From 25c753ed0fcf70acddf3ad1ff937fc1438d883f3 Mon Sep 17 00:00:00 2001 From: Quentin Mathe Date: Fri, 28 May 2004 23:49:16 +0000 Subject: [PATCH] Fixed the toolbar validation support side effects git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@19411 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 9 ++ Source/GSToolbar.m | 212 +++++++++++++++++++++++++++++++-------------- Source/NSControl.m | 7 +- 3 files changed, 158 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index 98ca8a294..5f9b27461 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2004-05-29 Quentin Mathe + + * Source/NSControl.m: Reverted to the previous version (1.61) because + the 2004/05/23 changes changed the way an event can be caught by one + responder definitively through the responder chain. + * Source/GSToolbar.m: New way to catch mouse events with the validation + system (Uses NSWindowDidUpdateNotification instead of events interception + at the view level) and other minor changes. + 2004-05-27 01:39 Alexander Malmberg * Source/NSImage.m (-size): Don't try to get the size if rep is nil. diff --git a/Source/GSToolbar.m b/Source/GSToolbar.m index c3fe3165e..280e91bec 100644 --- a/Source/GSToolbar.m +++ b/Source/GSToolbar.m @@ -92,10 +92,6 @@ static id validationCenter; // Validation support -@interface NSView (ToolbarValidation) -- (void) mouseDown: (NSEvent *)event; -@end - @interface GSValidationObject : NSObject { NSMutableArray *_observers; @@ -150,17 +146,6 @@ static id validationCenter; // Validation mechanism -@implementation NSView (ToolbarValidation) - -- (void) mouseDown: (NSEvent *)event -{ - GSValidationManager *validationManager = - [[GSValidationCenter sharedValidationCenter] _validationManagerWithWindow: [self window]]; - - [validationManager performSelector: @selector(validate) withObject: nil afterDelay: 0.1]; -} -@end - @implementation GSValidationObject - (id) initWithView: (NSView *)view @@ -223,14 +208,14 @@ static id validationCenter; NSView *vw = [window _windowView]; ASSIGN(_window, window); + [nc addObserver: self selector: @selector(windowDidUpdate:) + name: NSWindowDidUpdateNotification object: _window]; [nc addObserver: self selector: @selector(windowWillClose:) name: NSWindowWillCloseNotification object: _window]; ASSIGN(_trackingRectView, vw); - _trackingRect = [_trackingRectView addTrackingRect: [_trackingRectView bounds] - owner: self - userData: nil - assumeInside: NO]; + _trackingRect = [_trackingRectView addTrackingRect: + [_trackingRectView bounds] owner: self userData: nil assumeInside: NO]; } return self; @@ -238,7 +223,9 @@ static id validationCenter; - (void) invalidate { - [_trackingRectView removeTrackingRect: _trackingRect]; // tracking rect retains us, that is normal ? + [_trackingRectView removeTrackingRect: _trackingRect]; + // tracking rect retains us, that is normal ? + [_validationTimer invalidate]; // timer idem } @@ -275,7 +262,8 @@ static id validationCenter; selector: @selector(validate) userInfo: nil repeats: YES]; - [[NSRunLoop currentRunLoop] addTimer: _validationTimer forMode: NSDefaultRunLoopMode]; + [[NSRunLoop currentRunLoop] addTimer: _validationTimer + forMode: NSDefaultRunLoopMode]; [self validate]; } } @@ -289,8 +277,22 @@ static id validationCenter; - (void) validate { - [[[GSValidationCenter sharedValidationCenter] - _validationObjectsWithWindow: _window] makeObjectsPerformSelector: @selector(validate)]; + [[[GSValidationCenter sharedValidationCenter] + _validationObjectsWithWindow: _window] + makeObjectsPerformSelector: @selector(validate)]; +} + + +- (void) windowDidUpdate: (NSNotification *)notification +{ + if ([[NSApp currentEvent] type] == NSLeftMouseUp) + { + GSValidationManager *validationManager = + [[GSValidationCenter sharedValidationCenter] + _validationManagerWithWindow: [notification object]]; + + [validationManager performSelector: @selector(validate) withObject: nil]; + } } @end @@ -312,8 +314,14 @@ static id validationCenter; _validationManagers = [[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]; + [nc addObserver: self + selector: @selector(viewWillMove:) + name: @"GSViewWillMoveToWindow" + object: nil]; + [nc addObserver: self + selector: @selector(viewDidMove:) + name: @"GSViewDidMoveToWindow" + object: nil]; } return self; @@ -328,9 +336,11 @@ static id validationCenter; - (void) viewDidMove: (NSNotification *)notification { NSWindow *window = [[notification object] window]; - GSValidationManager *validationManager = [self _validationManagerWithWindow : _prevWindow]; + GSValidationManager *validationManager = + [self _validationManagerWithWindow : _prevWindow]; - if (validationManager != nil && [[self _validationObjectsWithWindow: _prevWindow] count] == 0) + if (validationManager != nil + && [[self _validationObjectsWithWindow: _prevWindow] count] == 0) { [validationManager invalidate]; [_validationManagers removeObject: validationManager]; @@ -352,14 +362,16 @@ static id validationCenter; /* validationObjectWithView: opposite method * 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. + * 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; - if ((index = [_validationObjects indexOfObject: validationObject]) != NSNotFound) + if ((index = [_validationObjects indexOfObject: validationObject]) + != NSNotFound) { NSWindow *window = [[validationObject view] window]; @@ -367,7 +379,8 @@ static id validationCenter; if ([[self _validationObjectsWithWindow: window] count] == 0) { - GSValidationManager *validationManager = [self _validationManagerWithWindow: window]; + GSValidationManager *validationManager = + [self _validationManagerWithWindow: window]; [validationManager invalidate]; [_validationManagers removeObject: validationManager]; } @@ -375,8 +388,9 @@ static id validationCenter; } /* Return the validation object associated with the parameter view. - * 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 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 @@ -387,11 +401,13 @@ static id validationCenter; if (view == nil) { - NSLog(@"Validation object cannot be created because the view is nil"); + NSDebugLog(@"Validation object cannot be created because the view is \ + nil"); return nil; } - validationObject = [[_validationObjects objectsWithValue: view forKey: @"_view"] objectAtIndex: 0]; + validationObject = [[_validationObjects objectsWithValue: view + forKey: @"_view"] objectAtIndex: 0]; if (validationObject == nil) { validationObject = [[GSValidationObject alloc] initWithView: view]; @@ -403,7 +419,8 @@ static id validationCenter; validationManager = [self _validationManagerWithWindow: window]; if (validationManager == nil) { - validationManager = [[GSValidationManager alloc] initWithWindow: window]; + validationManager = + [[GSValidationManager alloc] initWithWindow: window]; [_validationManagers addObject: validationManager]; RELEASE(validationManager); } @@ -417,7 +434,8 @@ static id validationCenter; - (GSValidationManager *) _validationManagerWithWindow: (NSWindow *)window { GSValidationManager *validationManager = - [[_validationManagers objectsWithValue: window forKey: @"_window"] objectAtIndex: 0]; + [[_validationManagers objectsWithValue: window forKey: @"_window"] + objectAtIndex: 0]; return validationManager; } @@ -489,9 +507,10 @@ static id validationCenter; // Accessors - (NSArray *) _visibleBackViews; +- (BOOL) _usesStandardBackgroundColor; - (BOOL) _willBeVisible; -- (void) _setWillBeVisible: (BOOL)willBeVisible; - (void) _setUsesStandardBackgroundColor: (BOOL)standard; +- (void) _setWillBeVisible: (BOOL)willBeVisible; @end // --- @@ -723,28 +742,57 @@ static id validationCenter; NSArray *itemsToSelect; NSEnumerator *e; NSToolbarItem *item; - NSArray *selectableIdentifiers; + NSArray *selectableIdentifiers = nil; + BOOL updated = NO; // First, we have to deselect the previous selected toolbar items selectedItems = [[self items] objectsWithValue: [self selectedItemIdentifier] - forKey: @"_itemIdentifier"]; + forKey: @"_itemIdentifier"]; e = [selectedItems objectEnumerator]; while ((item = [e nextObject]) != nil) { [item _setSelected: NO]; - } - - ASSIGN(_selectedItemIdentifier, itemIdentifier); + } - if ([_delegate respondsToSelector: @selector(toolbarSelectableItemIdentifiers:)]) - selectableIdentifiers = [_delegate toolbarSelectableItemIdentifiers: self]; + if ([_delegate respondsToSelector: + @selector(toolbarSelectableItemIdentifiers:)]) + { + selectableIdentifiers = + [_delegate toolbarSelectableItemIdentifiers: self]; + } + else + { + NSLog(@"toolbar delegate does not respond to %@", + @selector(toolbarSelectableItemIdentifiers:)); + return; + } - itemsToSelect = [_items objectsWithValue: _selectedItemIdentifier forKey: @"_itemIdentifier"]; + if (selectableIdentifiers == nil) + { + NSLog(@"toolbar delegate returns no such selectable item identifiers"); + return; + } + + itemsToSelect = [_items objectsWithValue: itemIdentifier + forKey: @"_itemIdentifier"]; e = [itemsToSelect objectEnumerator]; while ((item = [e nextObject]) != nil) { - if ([selectableIdentifiers containsObject: [item itemIdentifier]] && ![item _selected]) - [item _setSelected: YES]; + if ([selectableIdentifiers containsObject: [item itemIdentifier]]) + { + if (![item _selected]) + [item _setSelected: YES]; + updated = YES; + } + } + + if (updated) + { + ASSIGN(_selectedItemIdentifier, itemIdentifier); + } + else + { + NSLog(@"toolbar delegate returns no such selectable item identifiers"); } } @@ -753,6 +801,11 @@ static id validationCenter; return _sizeMode; } +- (BOOL) usesStandardBackgroundColor +{ + return [_toolbarView _usesStandardBackgroundColor]; +} + - (void) setUsesStandardBackgroundColor: (BOOL)standard { [_toolbarView _setUsesStandardBackgroundColor: standard]; @@ -867,11 +920,13 @@ static id validationCenter; * * The methods below handles the toolbar edition and broacasts each associated * event to the other toolbars with identical identifiers. - * Warning : broadcast process only happens between instances based on the same class. + * Warning : broadcast process only happens between instances based on the same + * class. */ #define TRANSMIT(signature) \ - NSEnumerator *e = [[toolbars objectsWithValue: _identifier forKey: @"_identifier"] objectEnumerator]; \ + NSEnumerator *e = [[toolbars objectsWithValue: _identifier forKey: \ + @"_identifier"] objectEnumerator]; \ GSToolbar *toolbar; \ \ while ((toolbar = [e nextObject]) != nil) \ @@ -890,7 +945,7 @@ static id validationCenter; if([allowedItems containsObject: itemIdentifier]) { item = [self _toolbarItemForIdentifier: itemIdentifier]; - if(item == nil) + if (item == nil) { item = [_delegate toolbar: self itemForItemIdentifier: itemIdentifier @@ -901,9 +956,11 @@ static id validationCenter; { NSArray *selectableItems; - if ([_delegate respondsToSelector: @selector(toolbarSelectableItemIdentifiers:)]) + if ([_delegate respondsToSelector: + @selector(toolbarSelectableItemIdentifiers:)]) { - selectableItems = [_delegate toolbarSelectableItemIdentifiers: self]; + selectableItems = + [_delegate toolbarSelectableItemIdentifiers: self]; if ([selectableItems containsObject: itemIdentifier]) [item _setSelectable: YES]; } @@ -982,11 +1039,12 @@ static id validationCenter; if (_delegate == delegate || (broadcast == NO && [_delegate isMemberOfClass: [delegate class]])) return; - // We don't reload instances which received this message and already have a - // delegate based on a class identical to the parameter delegate, it permits - // to use only one nib owner class as a toolbar delegate even if a new instance - // of the nib owner are created with each new window (see MiniController.m in - // the toolbar example application). + /* We don't reload instances which received this message and already have a + * delegate based on a class identical to the parameter delegate, it permits + * to use only one nib owner class as a toolbar delegate even if a new + * instance of the nib owner are created with each new window (see + * MiniController.m in the toolbar example application). + */ #define CHECK_REQUIRED_METHOD(selector_name) \ @@ -994,7 +1052,8 @@ static id validationCenter; [NSException raise: NSInternalInconsistencyException \ format: @"delegate does not respond to %@",@#selector_name] - CHECK_REQUIRED_METHOD(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:); + CHECK_REQUIRED_METHOD(toolbar:itemForItemIdentifier: + willBeInsertedIntoToolbar:); CHECK_REQUIRED_METHOD(toolbarAllowedItemIdentifiers:); CHECK_REQUIRED_METHOD(toolbarDefaultItemIdentifiers:); @@ -1032,20 +1091,39 @@ static id validationCenter; GSValidationCenter *vc = [GSValidationCenter sharedValidationCenter]; GSToolbar *toolbarModel = [self _toolbarModel]; - validationObject = [vc validationObjectWithView: _toolbarView]; - if (validationObject != nil) + if (_toolbarView != nil) { - [validationObject removeObserver: self]; - if ([[validationObject observers] count] == 0) - [vc unregisterValidationObject: validationObject]; + validationObject = [vc validationObjectWithView: _toolbarView]; + if (validationObject != nil) + { + [validationObject removeObserver: self]; + if ([[validationObject observers] count] == 0) + [vc unregisterValidationObject: validationObject]; + } } - + ASSIGN(_toolbarView, toolbarView); - + + if (_toolbarView == nil) + 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. + * Why ? + * We don't set it before when the toolbar is inited, to do only one toolbar + * content load. + * ... + * 1 toolbar = [[GSToolbar alloc] initWithIdentifier: @"blabla"]; + * 2 [toolbar setDelegate: myDelegate]; + * In case such method like 1 sets a default delegate for the identifier by + * requesting a toolbar model, a toolbar content load would occur. + * With a method like 2 which follows immediatly : + * Another toolbar load content would occur related to a probably different + * delegate. + */ if (_delegate == nil) [self _setDelegate: [toolbarModel delegate] broadcast: NO]; } diff --git a/Source/NSControl.m b/Source/NSControl.m index 9e50bad3d..a083db7c5 100644 --- a/Source/NSControl.m +++ b/Source/NSControl.m @@ -552,10 +552,11 @@ static Class actionCellClass; if (![self isEnabled]) return; - [super mouseDown: theEvent]; - if (_ignoresMultiClick && ([theEvent clickCount] > 1)) - return; + { + [super mouseDown: theEvent]; + return; + } if ([_cell isContinuous]) {