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
This commit is contained in:
Quentin Mathe 2004-05-28 23:49:16 +00:00
parent 181eac6eeb
commit 25c753ed0f
3 changed files with 158 additions and 70 deletions

View file

@ -1,3 +1,12 @@
2004-05-29 Quentin Mathe <qmathe@lub-internet.fr>
* 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 <alexander@malmberg.org> 2004-05-27 01:39 Alexander Malmberg <alexander@malmberg.org>
* Source/NSImage.m (-size): Don't try to get the size if rep is nil. * Source/NSImage.m (-size): Don't try to get the size if rep is nil.

View file

@ -92,10 +92,6 @@ static id validationCenter;
// Validation support // Validation support
@interface NSView (ToolbarValidation)
- (void) mouseDown: (NSEvent *)event;
@end
@interface GSValidationObject : NSObject @interface GSValidationObject : NSObject
{ {
NSMutableArray *_observers; NSMutableArray *_observers;
@ -150,17 +146,6 @@ static id validationCenter;
// Validation mechanism // 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 @implementation GSValidationObject
- (id) initWithView: (NSView *)view - (id) initWithView: (NSView *)view
@ -223,14 +208,14 @@ static id validationCenter;
NSView *vw = [window _windowView]; NSView *vw = [window _windowView];
ASSIGN(_window, window); ASSIGN(_window, window);
[nc addObserver: self selector: @selector(windowDidUpdate:)
name: NSWindowDidUpdateNotification object: _window];
[nc addObserver: self selector: @selector(windowWillClose:) [nc addObserver: self selector: @selector(windowWillClose:)
name: NSWindowWillCloseNotification object: _window]; name: NSWindowWillCloseNotification object: _window];
ASSIGN(_trackingRectView, vw); ASSIGN(_trackingRectView, vw);
_trackingRect = [_trackingRectView addTrackingRect: [_trackingRectView bounds] _trackingRect = [_trackingRectView addTrackingRect:
owner: self [_trackingRectView bounds] owner: self userData: nil assumeInside: NO];
userData: nil
assumeInside: NO];
} }
return self; return self;
@ -238,7 +223,9 @@ static id validationCenter;
- (void) invalidate - (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 [_validationTimer invalidate]; // timer idem
} }
@ -275,7 +262,8 @@ static id validationCenter;
selector: @selector(validate) selector: @selector(validate)
userInfo: nil userInfo: nil
repeats: YES]; repeats: YES];
[[NSRunLoop currentRunLoop] addTimer: _validationTimer forMode: NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] addTimer: _validationTimer
forMode: NSDefaultRunLoopMode];
[self validate]; [self validate];
} }
} }
@ -289,8 +277,22 @@ static id validationCenter;
- (void) validate - (void) validate
{ {
[[[GSValidationCenter sharedValidationCenter] [[[GSValidationCenter sharedValidationCenter]
_validationObjectsWithWindow: _window] makeObjectsPerformSelector: @selector(validate)]; _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 @end
@ -312,8 +314,14 @@ static id validationCenter;
_validationManagers = [[NSMutableArray alloc] init]; _validationManagers = [[NSMutableArray alloc] init];
_validationObjects = [[NSMutableArray alloc] init]; _validationObjects = [[NSMutableArray alloc] init];
[nc addObserver: self selector: @selector(viewWillMove:) name: @"GSViewWillMoveToWindow" object: nil]; [nc addObserver: self
[nc addObserver: self selector: @selector(viewDidMove:) name: @"GSViewDidMoveToWindow" object: nil]; selector: @selector(viewWillMove:)
name: @"GSViewWillMoveToWindow"
object: nil];
[nc addObserver: self
selector: @selector(viewDidMove:)
name: @"GSViewDidMoveToWindow"
object: nil];
} }
return self; return self;
@ -328,9 +336,11 @@ static id validationCenter;
- (void) viewDidMove: (NSNotification *)notification - (void) viewDidMove: (NSNotification *)notification
{ {
NSWindow *window = [[notification object] window]; 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]; [validationManager invalidate];
[_validationManagers removeObject: validationManager]; [_validationManagers removeObject: validationManager];
@ -352,14 +362,16 @@ static id validationCenter;
/* validationObjectWithView: opposite method /* validationObjectWithView: opposite method
* Remove the object in the validation objects list. * Remove the object in the validation objects list.
* Release the validation manager associated to the window (related to the validation object and its * Release the validation manager associated to the window (related to the
* view) in the case there are no other validation objects related to this window. * validation object and its view) in the case there are no other validation
* objects related to this window.
*/ */
- (void) unregisterValidationObject: (GSValidationObject *)validationObject - (void) unregisterValidationObject: (GSValidationObject *)validationObject
{ {
int index; int index;
if ((index = [_validationObjects indexOfObject: validationObject]) != NSNotFound) if ((index = [_validationObjects indexOfObject: validationObject])
!= NSNotFound)
{ {
NSWindow *window = [[validationObject view] window]; NSWindow *window = [[validationObject view] window];
@ -367,7 +379,8 @@ static id validationCenter;
if ([[self _validationObjectsWithWindow: window] count] == 0) if ([[self _validationObjectsWithWindow: window] count] == 0)
{ {
GSValidationManager *validationManager = [self _validationManagerWithWindow: window]; GSValidationManager *validationManager =
[self _validationManagerWithWindow: window];
[validationManager invalidate]; [validationManager invalidate];
[_validationManagers removeObject: validationManager]; [_validationManagers removeObject: validationManager];
} }
@ -375,8 +388,9 @@ static id validationCenter;
} }
/* Return the validation object associated with the parameter view. /* 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 * If there is no such validation object, create it by using view and then check
* validation manager (bound to the window which the view depends on) exists. * that an associated validation manager (bound to the window which the view
* depends on) exists.
* If there is no such validation manager, create it. * If there is no such validation manager, create it.
*/ */
- (GSValidationObject *) validationObjectWithView: (NSView *)view - (GSValidationObject *) validationObjectWithView: (NSView *)view
@ -387,11 +401,13 @@ static id validationCenter;
if (view == nil) 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; return nil;
} }
validationObject = [[_validationObjects objectsWithValue: view forKey: @"_view"] objectAtIndex: 0]; validationObject = [[_validationObjects objectsWithValue: view
forKey: @"_view"] objectAtIndex: 0];
if (validationObject == nil) if (validationObject == nil)
{ {
validationObject = [[GSValidationObject alloc] initWithView: view]; validationObject = [[GSValidationObject alloc] initWithView: view];
@ -403,7 +419,8 @@ static id validationCenter;
validationManager = [self _validationManagerWithWindow: window]; validationManager = [self _validationManagerWithWindow: window];
if (validationManager == nil) if (validationManager == nil)
{ {
validationManager = [[GSValidationManager alloc] initWithWindow: window]; validationManager =
[[GSValidationManager alloc] initWithWindow: window];
[_validationManagers addObject: validationManager]; [_validationManagers addObject: validationManager];
RELEASE(validationManager); RELEASE(validationManager);
} }
@ -417,7 +434,8 @@ static id validationCenter;
- (GSValidationManager *) _validationManagerWithWindow: (NSWindow *)window - (GSValidationManager *) _validationManagerWithWindow: (NSWindow *)window
{ {
GSValidationManager *validationManager = GSValidationManager *validationManager =
[[_validationManagers objectsWithValue: window forKey: @"_window"] objectAtIndex: 0]; [[_validationManagers objectsWithValue: window forKey: @"_window"]
objectAtIndex: 0];
return validationManager; return validationManager;
} }
@ -489,9 +507,10 @@ static id validationCenter;
// Accessors // Accessors
- (NSArray *) _visibleBackViews; - (NSArray *) _visibleBackViews;
- (BOOL) _usesStandardBackgroundColor;
- (BOOL) _willBeVisible; - (BOOL) _willBeVisible;
- (void) _setWillBeVisible: (BOOL)willBeVisible;
- (void) _setUsesStandardBackgroundColor: (BOOL)standard; - (void) _setUsesStandardBackgroundColor: (BOOL)standard;
- (void) _setWillBeVisible: (BOOL)willBeVisible;
@end @end
// --- // ---
@ -723,28 +742,57 @@ static id validationCenter;
NSArray *itemsToSelect; NSArray *itemsToSelect;
NSEnumerator *e; NSEnumerator *e;
NSToolbarItem *item; NSToolbarItem *item;
NSArray *selectableIdentifiers; NSArray *selectableIdentifiers = nil;
BOOL updated = NO;
// First, we have to deselect the previous selected toolbar items // First, we have to deselect the previous selected toolbar items
selectedItems = [[self items] objectsWithValue: [self selectedItemIdentifier] selectedItems = [[self items] objectsWithValue: [self selectedItemIdentifier]
forKey: @"_itemIdentifier"]; forKey: @"_itemIdentifier"];
e = [selectedItems objectEnumerator]; e = [selectedItems objectEnumerator];
while ((item = [e nextObject]) != nil) while ((item = [e nextObject]) != nil)
{ {
[item _setSelected: NO]; [item _setSelected: NO];
} }
ASSIGN(_selectedItemIdentifier, itemIdentifier);
if ([_delegate respondsToSelector: @selector(toolbarSelectableItemIdentifiers:)]) if ([_delegate respondsToSelector:
selectableIdentifiers = [_delegate toolbarSelectableItemIdentifiers: self]; @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]; e = [itemsToSelect objectEnumerator];
while ((item = [e nextObject]) != nil) while ((item = [e nextObject]) != nil)
{ {
if ([selectableIdentifiers containsObject: [item itemIdentifier]] && ![item _selected]) if ([selectableIdentifiers containsObject: [item itemIdentifier]])
[item _setSelected: YES]; {
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; return _sizeMode;
} }
- (BOOL) usesStandardBackgroundColor
{
return [_toolbarView _usesStandardBackgroundColor];
}
- (void) setUsesStandardBackgroundColor: (BOOL)standard - (void) setUsesStandardBackgroundColor: (BOOL)standard
{ {
[_toolbarView _setUsesStandardBackgroundColor: standard]; [_toolbarView _setUsesStandardBackgroundColor: standard];
@ -867,11 +920,13 @@ static id validationCenter;
* *
* The methods below handles the toolbar edition and broacasts each associated * The methods below handles the toolbar edition and broacasts each associated
* event to the other toolbars with identical identifiers. * 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) \ #define TRANSMIT(signature) \
NSEnumerator *e = [[toolbars objectsWithValue: _identifier forKey: @"_identifier"] objectEnumerator]; \ NSEnumerator *e = [[toolbars objectsWithValue: _identifier forKey: \
@"_identifier"] objectEnumerator]; \
GSToolbar *toolbar; \ GSToolbar *toolbar; \
\ \
while ((toolbar = [e nextObject]) != nil) \ while ((toolbar = [e nextObject]) != nil) \
@ -890,7 +945,7 @@ static id validationCenter;
if([allowedItems containsObject: itemIdentifier]) if([allowedItems containsObject: itemIdentifier])
{ {
item = [self _toolbarItemForIdentifier: itemIdentifier]; item = [self _toolbarItemForIdentifier: itemIdentifier];
if(item == nil) if (item == nil)
{ {
item = item =
[_delegate toolbar: self itemForItemIdentifier: itemIdentifier [_delegate toolbar: self itemForItemIdentifier: itemIdentifier
@ -901,9 +956,11 @@ static id validationCenter;
{ {
NSArray *selectableItems; NSArray *selectableItems;
if ([_delegate respondsToSelector: @selector(toolbarSelectableItemIdentifiers:)]) if ([_delegate respondsToSelector:
@selector(toolbarSelectableItemIdentifiers:)])
{ {
selectableItems = [_delegate toolbarSelectableItemIdentifiers: self]; selectableItems =
[_delegate toolbarSelectableItemIdentifiers: self];
if ([selectableItems containsObject: itemIdentifier]) if ([selectableItems containsObject: itemIdentifier])
[item _setSelectable: YES]; [item _setSelectable: YES];
} }
@ -982,11 +1039,12 @@ static id validationCenter;
if (_delegate == delegate if (_delegate == delegate
|| (broadcast == NO && [_delegate isMemberOfClass: [delegate class]])) || (broadcast == NO && [_delegate isMemberOfClass: [delegate class]]))
return; return;
// We don't reload instances which received this message and already have a /* 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 * 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 * to use only one nib owner class as a toolbar delegate even if a new
// of the nib owner are created with each new window (see MiniController.m in * instance of the nib owner are created with each new window (see
// the toolbar example application). * MiniController.m in the toolbar example application).
*/
#define CHECK_REQUIRED_METHOD(selector_name) \ #define CHECK_REQUIRED_METHOD(selector_name) \
@ -994,7 +1052,8 @@ static id validationCenter;
[NSException raise: NSInternalInconsistencyException \ [NSException raise: NSInternalInconsistencyException \
format: @"delegate does not respond to %@",@#selector_name] 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(toolbarAllowedItemIdentifiers:);
CHECK_REQUIRED_METHOD(toolbarDefaultItemIdentifiers:); CHECK_REQUIRED_METHOD(toolbarDefaultItemIdentifiers:);
@ -1032,20 +1091,39 @@ static id validationCenter;
GSValidationCenter *vc = [GSValidationCenter sharedValidationCenter]; GSValidationCenter *vc = [GSValidationCenter sharedValidationCenter];
GSToolbar *toolbarModel = [self _toolbarModel]; GSToolbar *toolbarModel = [self _toolbarModel];
validationObject = [vc validationObjectWithView: _toolbarView]; if (_toolbarView != nil)
if (validationObject != nil)
{ {
[validationObject removeObserver: self]; validationObject = [vc validationObjectWithView: _toolbarView];
if ([[validationObject observers] count] == 0) if (validationObject != nil)
[vc unregisterValidationObject: validationObject]; {
[validationObject removeObserver: self];
if ([[validationObject observers] count] == 0)
[vc unregisterValidationObject: validationObject];
}
} }
ASSIGN(_toolbarView, toolbarView); ASSIGN(_toolbarView, toolbarView);
if (_toolbarView == nil)
return;
validationObject = [vc validationObjectWithView: _toolbarView]; validationObject = [vc validationObjectWithView: _toolbarView];
if (validationObject != nil) if (validationObject != nil)
[validationObject addObserver: self]; [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) if (_delegate == nil)
[self _setDelegate: [toolbarModel delegate] broadcast: NO]; [self _setDelegate: [toolbarModel delegate] broadcast: NO];
} }

View file

@ -552,10 +552,11 @@ static Class actionCellClass;
if (![self isEnabled]) if (![self isEnabled])
return; return;
[super mouseDown: theEvent];
if (_ignoresMultiClick && ([theEvent clickCount] > 1)) if (_ignoresMultiClick && ([theEvent clickCount] > 1))
return; {
[super mouseDown: theEvent];
return;
}
if ([_cell isContinuous]) if ([_cell isContinuous])
{ {