diff --git a/ChangeLog b/ChangeLog index e10ecc8b4..4ae108c81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,13 +1,108 @@ -2006-10-26 Richard Frith-Macdonald +2006-11-02 Richard Frith-Macdonald - * Source/GSTheme.m: implement use of tiling for NSButton + * Source/GSTheme.m: + * Source/GSInfoPanel.m: + Merge in changes from theme branch... + Support tiling when drawing button cells. + Make theme panel link visible, as someone suggested that having + it totally hidden was not so good. Perhaps make it more explicit + in future? +2006-11-01 Matt Rice + + * Source/NSTableView.m: + (-editColumn:row:withEvent:select:): Raise when passed an unselected + row. + (-textDidEndEditing:): Handle NSReturnTextMovement. + (_editNextCellAfterRow:inColumn:): New private method. + + +2006-11-01 Matt Rice + + * Source/NSTableView.m: Add new private methods. + (-mouseDown:): Reorganize and don't track cells until dragging + has been ruled out. + * Source/NSCell.m (trackMouse:inRect:ofView:untilMouseUp:): + Handle events no longer in the queue. + * Source/GSDragView.m: Change NSLog to NSDebugLLog. + +2006-10-31 Matt Rice + + * Tools/gopen.m + * Source/NSView.m + * Source/GSPDFPrintOperation.m + * Source/NSHelpManager.m + * Source/GSHelpManagerPanel.m: Add missing includes. + +2006-10-31 Richard Frith-Macdonald + + * Source/NSWorkspace.m: add missing include + +2006-10-30 Matt Rice + + * Source/NSComboBoxCell.m (validateSelection): Test for invalid row. + +2006-10-28 Adam Fedor + + * Source/NSApplication.m (initialize_gnustep_backend): Use + GSBackend class directly when backend is compiled as a library. + (Partial fix for Bug #16453, see also gnustep-back). + +2006-10-27 Matt Rice + + * Source/NSAlert.m: Add GSRunExceptionPanel function + and GSExceptionPanel class. + * Headers/AppKit/NSPanel.h: Declare GSRunExceptionPanel. + * Source/NSApplication.m (_NSAppKitUncaughtExceptionHandler): + Use GSRunExceptionPanel. + +2006-10-27 Matt Rice + + * Source/NSTableView.m (-setFrame:,-setFrameSize:): Use + documentVisibleRect. Shrink if table is larger than needed height. + fixes bug #18117. + (-drawBackgroundInClipRect:): Draw the background. + * Source/NSClipView.m (-documentVisibleRect:): Return the clip views + visible rect converted to the document views coordinate system. + +2006-10-24 Matt Rice + + * Source/NSApplication.m (NSAppIcon -mouseDown:): Call unhide: + regardless of whether we're hidden or not. + +2006-10-22 Matt Rice + + * Source/NSTableView.m (-mouseDown:): Check for empty selection. + when adding to the current selection. Fixes bug #15261. + +2006-10-21 Matt Rice + + * Headers/AppKit/NSGraphics.h: Add GSOrderedWindows function. + * Source/NSApplication.m (NSAppIconView -mouseDown:): Use + GSOrderedWindows. + (NSApplication -deactivate): Ditto. + (-hide:): Ditto. + (-unhideWithoutActivation:): Ditto. + (-makeWindowsPerform:inOrder): Ditto. + (-orderedWindows:): Ditto. + (-windowWillClose:): Ditto. + * Source/GSDisplayServer.m: Implement -windowlist. + * Source/NSWindow.m (NSCountWindowList,NSWindowList): Use -windowlist. + (GSOrderedWindows): Initial implementation. + +2006-10-21 11:30-EDT Matt Rice + + * Source/NSTableView.m: If the tableview is smaller than + it's clipview, then resize it so that it fits. + Corrects bug#9608 and bug#18073. + Patch committed by: Gregory Casamento + 2006-10-19 21:17-EDT Gregory John Casamento * Source/NSMenuItemCell.m: Correct menu highlighting issue found by applying changes suggested by Jeff Teunissen. This change causes the menu to use the correct text color when - highlighted. + highlighted. (minor change) 2006-10-19 Richard Frith-Macdonald @@ -25,7 +120,7 @@ * Source/NSFont.m: Apply slightly modified version of patch from Jeff Teunissen deek@d2dc.net to setNSFont(). Setting - a font should set its size. + a font should set its size. (minor change) * Source/NSImage.m: Set the alpha on the background when printing. 2006-10-15 11:23-EDT Mark Tracy diff --git a/Headers/AppKit/NSGraphics.h b/Headers/AppKit/NSGraphics.h index 70a3ad3ff..a98bf2f57 100644 --- a/Headers/AppKit/NSGraphics.h +++ b/Headers/AppKit/NSGraphics.h @@ -215,6 +215,7 @@ GSWViewIsFlipped(NSGraphicsContext *ctxt) @class NSArray; @class NSWindow; +APPKIT_EXPORT NSArray* GSOrderedWindows(void); APPKIT_EXPORT NSArray* GSAllWindows(void); APPKIT_EXPORT NSWindow* GSWindowWithNumber(int num); #endif diff --git a/Headers/AppKit/NSPanel.h b/Headers/AppKit/NSPanel.h index dc729d6a7..03137e463 100644 --- a/Headers/AppKit/NSPanel.h +++ b/Headers/AppKit/NSPanel.h @@ -174,6 +174,12 @@ APPKIT_EXPORT void NSBeginInformationalAlertSheet(NSString *title, void *contextInfo, NSString *msg, ...); +APPKIT_EXPORT int GSRunExceptionPanel(NSString *title, + NSException *exception, + NSString *defaultButton, + NSString *alternateButton, + NSString *otherButton); + #endif // diff --git a/Source/GSDisplayServer.m b/Source/GSDisplayServer.m index 84a452316..e9ec01c3b 100644 --- a/Source/GSDisplayServer.m +++ b/Source/GSDisplayServer.m @@ -33,6 +33,7 @@ #include #include +#include "AppKit/NSApplication.h" #include "AppKit/NSEvent.h" #include "AppKit/NSImage.h" #include "AppKit/NSWindow.h" @@ -664,11 +665,25 @@ GSCurrentServer(void) return 0; } -/** Returns the list of windows that the server controls */ +/** Backends can override this method to return an array of window numbers + ordered front to back. The front most window being the first object + in the array. + The default implementation returns the visible windows in an + unspecified order. + */ - (NSArray *) windowlist { - [self subclassResponsibility: _cmd]; - return nil; + NSMutableArray *list = [NSMutableArray arrayWithArray:[NSApp windows]]; + int c = [list count]; + + while (c-- > 0) + { + if (![[list objectAtIndex:c] isVisible]) + { + [list removeObjectAtIndex:c]; + } + } + return [list valueForKey:@"windowNumber"]; } /** Returns the depth of the window */ diff --git a/Source/GSDragView.m b/Source/GSDragView.m index 0de433eee..a0cb6c3a6 100644 --- a/Source/GSDragView.m +++ b/Source/GSDragView.m @@ -756,7 +756,7 @@ static GSDragView *sharedDragView = nil; break; default: - NSLog(@"Internal: dropped NSAppKitDefined (%d) event", sub); + NSDebugLLog(@"NSDragging", @"dropped NSAppKitDefined (%d) event", sub); break; } } diff --git a/Source/GSHelpManagerPanel.m b/Source/GSHelpManagerPanel.m index 7701c2944..546d588eb 100644 --- a/Source/GSHelpManagerPanel.m +++ b/Source/GSHelpManagerPanel.m @@ -29,6 +29,7 @@ #include "AppKit/NSAttributedString.h" #include "AppKit/NSTextView.h" #include "AppKit/NSTextContainer.h" +#include "AppKit/NSTextStorage.h" #include "AppKit/NSScrollView.h" #include "AppKit/NSButton.h" #include "AppKit/NSClipView.h" diff --git a/Source/GSPDFPrintOperation.m b/Source/GSPDFPrintOperation.m index e2262f32a..7f78c4415 100644 --- a/Source/GSPDFPrintOperation.m +++ b/Source/GSPDFPrintOperation.m @@ -35,6 +35,7 @@ #include #include #include +#include #include "AppKit/NSView.h" #include "GNUstepGUI/GSPDFPrintOperation.h" diff --git a/Source/NSAlert.m b/Source/NSAlert.m index 04eb64498..96c0a7d1e 100644 --- a/Source/NSAlert.m +++ b/Source/NSAlert.m @@ -1468,3 +1468,236 @@ void NSBeginInformationalAlertSheet(NSString *title, } @end + +@interface GSExceptionPanel : GSAlertPanel +{ + NSBrowser *_browser; + NSDictionary *_userInfo; + NSPanel *_userInfoPanel; +} +- (void) setUserInfo:(NSDictionary *)userInfo; +- (NSPanel *)userInfoPanel; +@end + +int GSRunExceptionPanel( + NSString *title, + NSException *exception, + NSString *defaultButton, + NSString *alternateButton, + NSString *otherButton) +{ + NSString *message; + GSExceptionPanel *panel; + int result; + + message = [NSString stringWithFormat:@"%@: %@", + [exception name], + [exception reason]]; + if (defaultButton == nil) + { + defaultButton = @"OK"; + } + + panel = [[GSExceptionPanel alloc] init]; + + if (title == nil) + { + title = @"Exception"; + } + + [panel setTitle: title + message: message + def: defaultButton + alt: alternateButton + other: otherButton]; + [panel setUserInfo: [exception userInfo]]; + result = [panel runModal]; + [[panel userInfoPanel] orderOut:nil]; + [panel setUserInfo: nil]; + + RELEASE(panel); + return result; +} + +@implementation GSExceptionPanel +- (void) dealloc +{ + RELEASE(_userInfo); + RELEASE(_browser); + RELEASE(_userInfoPanel); + [super dealloc]; +} +- (id) init +{ + if ((self = [super init])) + { + [icoButton setEnabled:YES]; + [icoButton setTarget:self]; + [icoButton setAction:@selector(_icoAction:)]; + } + + return self; +} +- (NSPanel *) userInfoPanel +{ + return _userInfoPanel; +} + +- (void) setUserInfo:(NSDictionary *)userInfo; +{ + ASSIGN(_userInfo, userInfo); + [_browser reloadColumn:0]; +} + +- (void) _icoAction:(id)sender +{ + NSRect fr; + + if (_userInfoPanel) + { + [_browser reloadColumn:0]; + return; + } + + fr = NSMakeRect(_frame.origin.x, _frame.origin.y + _frame.size.height + 15, + _frame.size.width, 108); + _userInfoPanel = [[NSPanel alloc] initWithContentRect:fr + styleMask:NSTitledWindowMask + | NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + [_userInfoPanel setTitle:@"User Info Inspector"]; + [_userInfoPanel setWorksWhenModal:YES]; + + fr = NSMakeRect(8, 8, _frame.size.width - 16, 100); + _browser = [[NSBrowser alloc] initWithFrame:fr]; + [_browser setMaxVisibleColumns:2]; + [_browser setDelegate:self]; + [_browser setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [_browser reloadColumn:0]; + [[_userInfoPanel contentView] addSubview:_browser]; + [_userInfoPanel makeKeyAndOrderFront:self]; +} + +- (int) browser:(id)browser +numberOfRowsInColumn:(int)col +{ + if (col == 0) + return [[_userInfo allKeys] count]; + else + { + id val = [[(NSCell *)[browser selectedCellInColumn:col - 1] representedObject] description]; + volatile id foo = nil; + NS_DURING + foo = [val propertyList]; + val = foo; + NS_HANDLER + NS_ENDHANDLER + + if ([val isKindOfClass:[NSArray class]]) + return [val count]; + else if ([val isKindOfClass:[NSDictionary class]]) + return [[val allKeys] count]; + else return val != nil; + } + return 0; +} + +- (void) browser:(NSBrowser *)browser willDisplayCell:(NSBrowserCell *)cell atRow:(int)row +column:(int)column +{ + if (column == 0) + { + id key = [[_userInfo allKeys] objectAtIndex:row]; + id val = [_userInfo objectForKey:key]; + + [cell setLeaf:NO]; + [cell setStringValue:[key description]]; + [cell setRepresentedObject: val]; + } + else + { + volatile id val = [(NSCell *)[browser selectedCellInColumn:column - 1] representedObject]; + BOOL flag; + + if (!([val isKindOfClass:[NSArray class]] || [val isKindOfClass:[NSArray class]])) + { + volatile id foo = nil; + val = [val description]; + NS_DURING + foo = [val propertyList]; + val = foo; + NS_HANDLER + NS_ENDHANDLER + } + flag = (!([val isKindOfClass:[NSArray class]] + || [val isKindOfClass:[NSDictionary class]])); + + + + [cell setLeaf:flag]; + + if ([val isKindOfClass:[NSArray class]]) + { + volatile id obj = [val objectAtIndex:row]; + if (!([obj isKindOfClass:[NSArray class]] || [obj isKindOfClass:[NSArray class]])) + { + volatile id foo; + obj = [[obj description] propertyList]; + NS_DURING + foo = [obj propertyList]; + obj = foo; + NS_HANDLER + NS_ENDHANDLER + } + + if ([obj isKindOfClass:[NSArray class]]) + { + [cell setRepresentedObject:obj]; + [cell setLeaf:NO]; + [cell setStringValue:[NSString stringWithFormat:@"%@ %p", [obj class], obj]]; + } + else if ([obj isKindOfClass:[NSDictionary class]]) + { + [cell setRepresentedObject:obj]; + [cell setLeaf:NO]; + [cell setStringValue:[NSString stringWithFormat:@"%@ %p", [obj class], obj]]; + } + else + { + [cell setLeaf:YES]; + [cell setStringValue:[obj description]]; + [cell setRepresentedObject:nil]; + } + } + else if ([val isKindOfClass:[NSDictionary class]]) + { + id key = [[val allKeys] objectAtIndex:row]; + volatile id it = [(NSDictionary *)val objectForKey: key]; + volatile id foo; + foo = [it description]; + NS_DURING + foo = [it propertyList]; + it = foo; + NS_HANDLER + NS_ENDHANDLER + [cell setStringValue:[key description]]; + [cell setRepresentedObject:it]; + } + else + { + [cell setLeaf:YES]; + [cell setStringValue:[val description]]; + } + + } +} +- (id) browser:(NSBrowser *)browser titleOfColumn:(int)column +{ + if (column == 0) return @"userInfo"; + id val = [(NSCell *)[browser selectedCellInColumn:column - 1] representedObject]; + NSString *title = [NSString stringWithFormat:@"%@ %p", [val class], val]; + return title; +} +@end + diff --git a/Source/NSApplication.m b/Source/NSApplication.m index 6d9bd665f..0156aea4e 100644 --- a/Source/NSApplication.m +++ b/Source/NSApplication.m @@ -113,19 +113,17 @@ _NSAppKitUncaughtExceptionHandler (NSException *exception) [exception raise]; } - retVal = NSRunCriticalAlertPanel + retVal = GSRunExceptionPanel ([NSString stringWithFormat: _(@"Critical Error in %@"), [[NSProcessInfo processInfo] processName]], - @"%@: %@", + exception, _(@"Abort"), nil, #ifdef DEBUG - _(@"Debug"), + _(@"Debug")); #else - nil, + nil); #endif - [exception name], - [exception reason]); /* The user wants to abort */ if (retVal == NSAlertDefault) @@ -298,11 +296,10 @@ initialize_gnustep_backend(void) } #else - /* GSBackend will be in a separate library, so use the runtime - to find the class and avoid an unresolved reference problem */ - backend = [[NSBundle gnustepBundle] classNamed: @"GSBackend"]; - NSCAssert (backend, _(@"Can't find backend context")); - [backend initializeBackend]; + /* GSBackend will be in a separate library linked in with the app. + This would be cleaner with ...classNamed: @"GSBackend", but that + doesn't work in some cases (Mac OS X for instance). */ + [GSBackend initializeBackend]; #endif } return YES; @@ -504,30 +501,15 @@ static NSSize scaledIconSizeForSize(NSSize imageSize) { if ([theEvent clickCount] >= 2) { - /* If the app is not hidden we need to order front any visible and - possibly obscured windows. If we are active we need to order front - the key or main window again, otherwise unhide: will unhide and - activate us. Do this all in a way which will not change the stacking - order. - - There are 3 possibilities: - 1. app is active and has no obscured windows - 2. app is active and has obscured windows - 3. app is inactive. - I don't know of any way to tell 1 from 2 and do nothing. - - This should ideally set aWin NSWindowBelow the key or main window - but with most windowmanagers. It doesn't seem to place the receiving - window immediately below like it should. - */ + /* if not hidden raise windows which are possibly obscured. */ if ([NSApp isHidden] == NO) { - int i; - NSArray *windows = RETAIN([NSApp windows]); - - for (i = 0; i < [windows count]; i++) + NSArray *windows = RETAIN(GSOrderedWindows()); + NSWindow *aWin; + NSEnumerator *iter = [windows reverseObjectEnumerator]; + + while ((aWin = [iter nextObject])) { - NSWindow *aWin = [windows objectAtIndex:i]; if ([aWin isVisible] == YES && [aWin isMiniaturized] == NO && aWin != [NSApp keyWindow] && aWin != [NSApp mainWindow] @@ -562,7 +544,7 @@ static NSSize scaledIconSizeForSize(NSSize imageSize) RELEASE(windows); } - [NSApp unhide: self]; + [NSApp unhide: self]; // or activate or do nothing. } else { @@ -1167,6 +1149,12 @@ static NSSize scaledIconSizeForSize(NSSize imageSize) [[_inactive objectAtIndex: i] orderFrontRegardless]; } [_inactive removeAllObjects]; + + if (_unhide_on_activation) + { + [self unhide: nil]; + } + if ([self keyWindow] == nil && _hidden_key != nil && [[self windows] indexOfObjectIdenticalTo: _hidden_key] != NSNotFound) { @@ -1174,11 +1162,6 @@ static NSSize scaledIconSizeForSize(NSSize imageSize) _hidden_key = nil; } - if (_unhide_on_activation) - { - [self unhide: nil]; - } - if ([self keyWindow] != nil) { [[self keyWindow] orderFront: self]; @@ -1216,13 +1199,14 @@ static NSSize scaledIconSizeForSize(NSSize imageSize) { if (_app_is_active == YES) { - NSArray *windows_list = [self windows]; - unsigned count = [windows_list count]; - unsigned i; + NSArray *windows_list; NSDictionary *info; + NSWindow *win; + NSEnumerator *iter; [nc postNotificationName: NSApplicationWillResignActiveNotification object: self]; + _app_is_active = NO; @@ -1235,11 +1219,14 @@ static NSSize scaledIconSizeForSize(NSSize imageSize) // This is not a problem if it is also key, and I'm not sure if it // is a problem at all. May be annoying in the case of workspace switch. [[self mainWindow] resignMainWindow]; - for (i = 0; i < count; i++) + + windows_list = GSOrderedWindows(); + iter = [windows_list reverseObjectEnumerator]; + + while ((win = [iter nextObject])) { NSModalSession theSession; - NSWindow *win = [windows_list objectAtIndex: i]; - + if ([win isVisible] == NO) { continue; /* Already invisible */ @@ -2205,10 +2192,10 @@ image.

See Also: -applicationIconImage

{ if (_app_is_hidden == NO) { - NSArray *windows_list = [self windows]; - unsigned count = [windows_list count]; + NSArray *windows_list; NSDictionary *info; - unsigned i; + NSWindow *win; + NSEnumerator *iter; [nc postNotificationName: NSApplicationWillHideNotification object: self]; @@ -2218,10 +2205,12 @@ image.

See Also: -applicationIconImage

_hidden_key = [self keyWindow]; [_hidden_key resignKeyWindow]; } - for (i = 0; i < count; i++) - { - NSWindow *win = [windows_list objectAtIndex: i]; + + windows_list = GSOrderedWindows(); + iter = [windows_list reverseObjectEnumerator]; + while ((win = [iter nextObject])) + { if ([win isVisible] == NO) { continue; /* Already invisible */ @@ -2314,12 +2303,6 @@ image.

See Also: -applicationIconImage

[[_hidden objectAtIndex: i] orderFrontRegardless]; } [_hidden removeAllObjects]; - if (_hidden_key != nil - && [[self windows] indexOfObjectIdenticalTo: _hidden_key] != NSNotFound) - { - [_hidden_key makeKeyAndOrderFront: self]; - _hidden_key = nil; - } [[_app_icon_window contentView] setNeedsDisplay: YES]; info = [self _notificationUserInfo]; @@ -2393,12 +2376,20 @@ image.

See Also: -applicationIconImage

*/ - (NSWindow*) makeWindowsPerform: (SEL)aSelector inOrder: (BOOL)flag { - NSArray *window_list = [self windows]; - unsigned i; + NSArray *window_list; + unsigned i, c; - // FIXME flag ignored - i = [window_list count]; - while (i-- > 0) + // so i suppose when flag is YES it only runs on visible windows + if (flag) + { + window_list = GSOrderedWindows(); + } + else + { + window_list = [self windows]; + } + + for (i = 0, c = [window_list count]; i < c; i++) { NSWindow *window = [window_list objectAtIndex: i]; @@ -3251,14 +3242,24 @@ image.

See Also: -applicationIconImage

} /** - * OS X scripting method to return windows in front-to-back on-screen order. - * The GNUstep implementation returns all the windows in an arbitrary - * order. + * OS X scripting method to return windows in front-to-back on-screen order + * for scriptable windows. + * The GNUstep implementation returns all the windows excluding NSPanels. + * some backends may return an array in an unspecified order. */ - (NSArray *) orderedWindows { - // FIXME - return [self windows]; + NSArray *arr = GSOrderedWindows(); + NSMutableArray *ret = [[NSArray alloc] initWithCapacity:[arr count]]; + NSEnumerator *iter = [arr objectEnumerator]; + id win; + while ((win = [iter nextObject])) + { + if (![win isKindOfClass:[NSPanel class]]) + [ret addObject:win]; + } + + return AUTORELEASE(ret); } /* @@ -3478,17 +3479,17 @@ image.

See Also: -applicationIconImage

- (void) _windowWillClose: (NSNotification*) notification { NSWindow *win = [notification object]; - NSArray *windows_list = [self windows]; + NSArray *windows_list = GSOrderedWindows(); unsigned count = [windows_list count]; unsigned i; NSMutableArray *list = [NSMutableArray arrayWithCapacity: count]; BOOL wasKey = [win isKeyWindow]; BOOL wasMain = [win isMainWindow]; + NSEnumerator *iter = [windows_list objectEnumerator]; + NSWindow *tmp; - for (i = 0; i < count; i++) + while ((tmp = [iter nextObject])) { - NSWindow *tmp = [windows_list objectAtIndex: i]; - if ([tmp canBecomeMainWindow] == YES && [tmp isVisible] == YES) { [list addObject: tmp]; diff --git a/Source/NSCell.m b/Source/NSCell.m index 157721b5c..e2db02262 100644 --- a/Source/NSCell.m +++ b/Source/NSCell.m @@ -1548,15 +1548,19 @@ static NSColor *shadowCol; NSDebugLLog(@"NSCell", @"cell get mouse events\n"); mouseWentUp = NO; done = NO; + if (theEvent != [NSApp currentEvent]) + theEvent = [NSApp currentEvent]; + else + theEvent = [theApp nextEventMatchingMask: event_mask + untilDate: nil + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; + while (!done) { NSEventType eventType; BOOL pointIsInCell; - theEvent = [theApp nextEventMatchingMask: event_mask - untilDate: nil - inMode: NSEventTrackingRunLoopMode - dequeue: YES]; eventType = [theEvent type]; if (eventType != NSPeriodic || periodCount == 4) @@ -1626,6 +1630,12 @@ static NSColor *shadowCol; && (_action_mask & NSPeriodicMask)))) [(NSControl*)controlView sendAction: action to: target]; } + + if (!done) + theEvent = [theApp nextEventMatchingMask: event_mask + untilDate: nil + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; } // Hook called when stop tracking diff --git a/Source/NSClipView.m b/Source/NSClipView.m index 58d4c1f53..79fc10132 100644 --- a/Source/NSClipView.m +++ b/Source/NSClipView.m @@ -462,26 +462,17 @@ static inline NSRect integralRect (NSRect rect, NSView *view) return rect; } -/**

Returns the document visible rectangle. Returns NSZeroRect if the - document view does not exists.

+/**

Returns the document visible rectangle in the document views coordinate + * system.

See Also: -documentRect [NSView-convertRect:toView:]

*/ - (NSRect) documentVisibleRect { - NSRect documentBounds; - NSRect clipViewBounds; - NSRect rect; - - if (_documentView == nil) - { - return NSZeroRect; - } - - documentBounds = [_documentView bounds]; - clipViewBounds = [self convertRect: _bounds toView: _documentView]; - rect = NSIntersectionRect (documentBounds, clipViewBounds); - - return rect; + NSRect visRect; + + visRect = [self visibleRect]; + visRect = [self convertRect:visRect toView:_documentView]; + return visRect; } - (void) drawRect: (NSRect)rect diff --git a/Source/NSComboBoxCell.m b/Source/NSComboBoxCell.m index 4b3d1f3b0..60a94dd4b 100644 --- a/Source/NSComboBoxCell.m +++ b/Source/NSComboBoxCell.m @@ -697,21 +697,25 @@ static GSComboWindow *gsWindow = nil; { NSText *textObject = nil; id cv = [_cell controlView]; + int index = [_cell indexOfSelectedItem]; if ([cv isKindOfClass: [NSControl class]]) { textObject = [(NSControl *)cv currentEditor]; } - [_cell setStringValue: [_cell _stringValueAtIndex: - [_cell indexOfSelectedItem]]]; - // Will update the editor when needed + if (index != -1) + { + [_cell setStringValue: [_cell _stringValueAtIndex: + [_cell indexOfSelectedItem]]]; + // Will update the editor when needed - // FIXME: Because NSCell doesn't behave correctly the line just over has - // no effect, to correct this fact, the code below is needed. - [textObject setString: [_cell _stringValueAtIndex: - [_cell indexOfSelectedItem]]]; - // End of the code to remove + // FIXME: Because NSCell doesn't behave correctly the line just over has + // no effect, to correct this fact, the code below is needed. + [textObject setString: [_cell _stringValueAtIndex: + [_cell indexOfSelectedItem]]]; + // End of the code to remove + } if (textObject != nil) { diff --git a/Source/NSHelpManager.m b/Source/NSHelpManager.m index 193d59082..ee558db60 100644 --- a/Source/NSHelpManager.m +++ b/Source/NSHelpManager.m @@ -36,6 +36,7 @@ #include "AppKit/NSAttributedString.h" #include "AppKit/NSApplication.h" #include "AppKit/NSWorkspace.h" +#include "AppKit/NSFileWrapper.h" #include "AppKit/NSHelpManager.h" #include "AppKit/NSHelpPanel.h" #include "AppKit/NSHelpPanel.h" @@ -44,6 +45,7 @@ #include "AppKit/NSGraphics.h" #include "AppKit/NSScrollView.h" #include "AppKit/NSTextView.h" +#include "AppKit/NSTextStorage.h" #include "GNUstepGUI/GSHelpManagerPanel.h" diff --git a/Source/NSTableView.m b/Source/NSTableView.m index 7df8d6510..c8932a766 100644 --- a/Source/NSTableView.m +++ b/Source/NSTableView.m @@ -146,7 +146,10 @@ typedef struct _tableViewFlags - (void) _unselectAllColumns; @end - +@interface NSTableView (EventLoopHelper) +- (void) _trackCellAtColumn:(int)column row:(int)row withEvent:(NSEvent *)ev; +- (BOOL) _startDragOperationWithEvent:(NSEvent *)theEvent; +@end /* * A specific struct and its associated quick sort function @@ -1941,6 +1944,7 @@ static void computeNewSelection column: (int)column; - (BOOL) _editPreviousEditableCellBeforeRow: (int)row column: (int)column; +- (void) _editNextCellAfterRow:(int)row inColumn:(int)column; - (void) _autosaveTableColumns; - (void) _autoloadTableColumns; @end @@ -3210,6 +3214,12 @@ byExtendingSelection: (BOOL)flag [self scrollRowToVisible: rowIndex]; [self scrollColumnToVisible: columnIndex]; + if (rowIndex != _selectedRow) + { + [NSException raise:NSInvalidArgumentException + format:@"Attempted to edit unselected row"]; + } + if (rowIndex < 0 || rowIndex >= _numberOfRows || columnIndex < 0 || columnIndex >= _numberOfColumns) { @@ -3341,25 +3351,121 @@ static inline float computePeriod(NSPoint mouseLocationWin, return 0.01; } +- (void) _trackCellAtColumn:(int)columnIndex + row:(int)rowIndex + withEvent:(NSEvent *)theEvent +{ + NSTableColumn *tb; + NSCell *cell; + NSRect cellFrame; + id originalValue; + + if (rowIndex == -1 || columnIndex == -1) + { + return; + } + + tb = [_tableColumns objectAtIndex: columnIndex]; + /* we should copy the cell here, as we do on editing. + otherwise validation on a cell being edited could + cause the cell we are selecting to get it's objectValue */ + cell = [[tb dataCellForRow: rowIndex] copy]; + originalValue = RETAIN([self _objectValueForTableColumn:tb + row:rowIndex]); + [cell setObjectValue: originalValue]; + cellFrame = [self frameOfCellAtColumn: columnIndex + row: rowIndex]; + [cell setHighlighted: YES]; + [self setNeedsDisplayInRect: cellFrame]; + /* give delegate a chance to i.e set target */ + [self _willDisplayCell: cell + forTableColumn: tb + row: rowIndex]; + + if ([cell trackMouse: theEvent + inRect: cellFrame + ofView: self + untilMouseUp:[[cell class] + prefersTrackingUntilMouseUp]]) + { + id newValue = [cell objectValue]; + + if ([tb isEditable] + && originalValue != newValue + && ![originalValue isEqual: newValue]) + { + [self _setObjectValue: newValue + forTableColumn: tb + row: rowIndex]; + } + } + RELEASE(originalValue); + [cell setHighlighted: NO]; + [self setNeedsDisplayInRect: cellFrame]; + RELEASE(cell); +} + +- (BOOL) _startDragOperationWithEvent:(NSEvent *)theEvent +{ + NSPasteboard *pboard; + NSArray *rows; + + rows = [self _selectedRowArray]; + pboard = [NSPasteboard pasteboardWithName: NSDragPboard]; + if ([self _writeRows: rows + toPasteboard: pboard] == YES) + { + NSPoint p = NSZeroPoint; + NSImage *dragImage; + NSSize s; + + dragImage = [self dragImageForRows: rows + event: theEvent + dragImageOffset: &p]; + /* + * Store image offset in s ... the returned + * value is the position of the center of + * the image, so we adjust to the bottom left + * corner. + */ + s = [dragImage size]; + s.width = p.x - s.width/2; + s.height = p.y + s.height/2; // View is flipped + + /* + * Find the current mouse location and adjust + * it to determine the location of the bottom + * left corner of the image in this view's + * coordinate system. + */ + p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; + p.x += s.width; + p.y += s.height; + + + [self dragImage: dragImage + at: p + offset: NSMakeSize(0, 0) + event: theEvent + pasteboard: pboard + source: self + slideBack: YES]; + return YES; + } + return NO; +} + - (void) mouseDown: (NSEvent *)theEvent { NSPoint initialLocation = [theEvent locationInWindow]; NSPoint location; - int clickCount; // Pathological case -- ignore mouse down if ((_numberOfRows == 0) || (_numberOfColumns == 0)) { - [super mouseDown: theEvent]; return; } - clickCount = [theEvent clickCount]; - if (clickCount > 2) - { - return; - } - /* Stop editing if any */ if (_textObject != nil) { @@ -3371,8 +3477,9 @@ static inline float computePeriod(NSPoint mouseLocationWin, location = [self convertPoint: initialLocation fromView: nil]; _clickedRow = [self rowAtPoint: location]; _clickedColumn = [self columnAtPoint: location]; - - if (clickCount == 2) + + if ([theEvent type] == NSLeftMouseDown + && [theEvent clickCount] > 1) { // Double-click event @@ -3384,13 +3491,19 @@ static inline float computePeriod(NSPoint mouseLocationWin, if (![self _isCellEditableColumn: _clickedColumn row: _clickedRow ]) { // Send double-action but don't edit - [self sendAction: _doubleAction to: _target]; + [self _trackCellAtColumn:_clickedColumn + row:_clickedRow + withEvent:theEvent]; + if (_clickedRow != -1) + [self sendAction: _doubleAction to: _target]; } else { // It is OK to edit column. Go on, do it. - [self editColumn: _clickedColumn row: _clickedRow - withEvent: theEvent select: YES]; + [self editColumn: _clickedColumn + row: _clickedRow + withEvent: theEvent + select: YES]; } } else @@ -3401,7 +3514,7 @@ static inline float computePeriod(NSPoint mouseLocationWin, | NSLeftMouseDownMask | NSLeftMouseDraggedMask | NSPeriodicMask); - unsigned selectionMode; + unsigned selectionMode = 0; NSPoint mouseLocationWin; NSPoint mouseLocationView; NSDate *distantFuture = [NSDate distantFuture]; @@ -3420,8 +3533,8 @@ static inline float computePeriod(NSPoint mouseLocationWin, int originalRow = _clickedRow; int oldRow = -1; int currentRow = -1; - - selectionMode = 0; + BOOL getNextEvent = YES; + if (_allowsMultipleSelection == YES) { selectionMode |= ALLOWS_MULTIPLE; @@ -3445,7 +3558,7 @@ static inline float computePeriod(NSPoint mouseLocationWin, if (modifiers & NSControlKeyMask) { selectionMode |= CONTROL_DOWN; - if (_allowsMultipleSelection == YES) + if (_allowsMultipleSelection == YES && _selectedRow != -1) { originalRow = _selectedRow; selectionMode |= SHIFT_DOWN; @@ -3464,78 +3577,25 @@ static inline float computePeriod(NSPoint mouseLocationWin, // let's sort the _selectedRows oldSelectedRows = [_selectedRows copy]; - mouseLocationView = location; lastEvent = theEvent; - - if ([self mouse: mouseLocationView inRect: _bounds]) - { - NSTableColumn *tb; - NSCell *cell; - NSRect cellFrame; - id originalValue; - - // Prepare the cell - tb = [_tableColumns objectAtIndex: _clickedColumn]; - /* we should copy the cell here, as we do on editing. - otherwise validation on a cell being edited could - cause the cell we are selecting to get it's objectValue */ - cell = [[tb dataCellForRow: _clickedRow] copy]; - originalValue = RETAIN([self _objectValueForTableColumn:tb row:_clickedRow]); - [cell setObjectValue: originalValue]; - cellFrame = [self frameOfCellAtColumn: _clickedColumn - row: _clickedRow]; - [cell setHighlighted: YES]; - [self setNeedsDisplayInRect: cellFrame]; - /* give delegate a chance to i.e set target */ - [self _willDisplayCell: cell - forTableColumn: tb - row: _clickedRow]; - if ([cell trackMouse: lastEvent - inRect: cellFrame - ofView: self - untilMouseUp: [[cell class] prefersTrackingUntilMouseUp]]) - { - id newValue = [cell objectValue]; - - if ([tb isEditable] && originalValue != newValue - && ![originalValue isEqual: newValue]) - { - [self _setObjectValue: newValue - forTableColumn: tb - row: _clickedRow]; - } - done = YES; - currentRow = _clickedRow; - computeNewSelection(self, - oldSelectedRows, - _selectedRows, - originalRow, - oldRow, - currentRow, - &_selectedRow, - selectionMode); - } - RELEASE(originalValue); - [cell setHighlighted: NO]; - RELEASE(cell); - [self setNeedsDisplayInRect: cellFrame]; - lastEvent = [NSApp currentEvent]; - } while (done != YES) { /* - Wrap each iteration in an autorelease pool. Otherwise, we end - up allocating huge amounts of objects if the button is held - down for a long time. + Wrap each iteration in an autorelease pool. Otherwise, we end + up allocating huge amounts of objects if the button is held + down for a long time. */ CREATE_AUTORELEASE_POOL(arp); BOOL shouldComputeNewSelection = NO; - + + mouseLocationWin = [lastEvent locationInWindow]; + mouseLocationView = [self convertPoint: mouseLocationWin + fromView: nil]; + switch ([lastEvent type]) { case NSLeftMouseUp: - mouseLocationWin = [lastEvent locationInWindow]; if ((mouseLocationWin.y > minYVisible) && (mouseLocationWin.y < maxYVisible)) { @@ -3545,15 +3605,21 @@ static inline float computePeriod(NSPoint mouseLocationWin, [NSEvent stopPeriodicEvents]; startedPeriodicEvents = NO; } - mouseLocationView = [self convertPoint: mouseLocationWin - fromView: nil]; mouseLocationView.x = _bounds.origin.x; oldRow = currentRow; currentRow = [self rowAtPoint: mouseLocationView]; + if (oldRow != currentRow) { shouldComputeNewSelection = YES; } + + if (draggingPossible == YES) + { + [self _trackCellAtColumn:_clickedColumn + row:_clickedRow + withEvent:theEvent]; + } } else { @@ -3565,10 +3631,6 @@ static inline float computePeriod(NSPoint mouseLocationWin, case NSLeftMouseDown: case NSLeftMouseDragged: - mouseLocationWin = [lastEvent locationInWindow]; - mouseLocationView = [self convertPoint: mouseLocationWin - fromView: nil]; - if (fabs(mouseLocationWin.x - initialLocation.x) > 1 || fabs(mouseLocationWin.y - initialLocation.y) > 1) { @@ -3584,12 +3646,10 @@ static inline float computePeriod(NSPoint mouseLocationWin, } else if (fabs(mouseLocationWin.x - initialLocation.x) >= 4) { - NSPasteboard *pboard; - NSArray *rows; - mouseLocationView.x = _bounds.origin.x; oldRow = currentRow; currentRow = [self rowAtPoint: mouseLocationView]; + if (![_selectedRows containsIndex: currentRow]) { /* Mouse drag in a row that wasn't selected. @@ -3604,46 +3664,8 @@ static inline float computePeriod(NSPoint mouseLocationWin, selectionMode); } - rows = [self _selectedRowArray]; - pboard = [NSPasteboard pasteboardWithName: NSDragPboard]; - if ([self _writeRows: rows - toPasteboard: pboard] == YES) + if ([self _startDragOperationWithEvent:theEvent]) { - NSPoint p = NSZeroPoint; - NSImage *dragImage; - NSSize s; - - dragImage = [self dragImageForRows: rows - event: theEvent - dragImageOffset: &p]; - /* - * Store image offset in s ... the returned - * value is the position of the center of - * the image, so we adjust to the bottom left - * corner. - */ - s = [dragImage size]; - s.width = p.x - s.width/2; - s.height = p.y + s.height/2; // View is flipped - - /* - * Find the current mouse location and adjust - * it to determine the location of the bottom - * left corner of the image in this view's - * coordinate system. - */ - p = [self convertPoint: - [theEvent locationInWindow] fromView: nil]; - p.x += s.width; - p.y += s.height; - - [self dragImage: dragImage - at: p - offset: NSMakeSize(0, 0) - event: theEvent - pasteboard: pboard - source: self - slideBack: YES]; return; } else @@ -3662,8 +3684,6 @@ static inline float computePeriod(NSPoint mouseLocationWin, startedPeriodicEvents = NO; } - mouseLocationView = [self convertPoint: mouseLocationWin - fromView: nil]; mouseLocationView.x = _bounds.origin.x; oldRow = currentRow; currentRow = [self rowAtPoint: mouseLocationView]; @@ -3671,6 +3691,11 @@ static inline float computePeriod(NSPoint mouseLocationWin, { shouldComputeNewSelection = YES; } + + [self _trackCellAtColumn:_clickedColumn + row:_clickedRow + withEvent:theEvent]; + getNextEvent = (lastEvent == [NSApp currentEvent]); } else { @@ -3731,6 +3756,15 @@ static inline float computePeriod(NSPoint mouseLocationWin, if (shouldComputeNewSelection == YES) { + if (originalRow == -1) + { + originalRow = currentRow; + } + + if (currentRow == -1) + { + currentRow = _numberOfRows - 1; + } computeNewSelection(self, oldSelectedRows, _selectedRows, @@ -3741,12 +3775,25 @@ static inline float computePeriod(NSPoint mouseLocationWin, selectionMode); [self displayIfNeeded]; } + if (done == NO) { - lastEvent = [NSApp nextEventMatchingMask: eventMask + /* in certain cases we are working with events that have already + * occured and been dequeued by NSCell classes, in these cases + * we set getNextEvent to NO, and get the current event. + */ + if (getNextEvent == YES) + { + lastEvent = [NSApp nextEventMatchingMask: eventMask untilDate: distantFuture inMode: NSEventTrackingRunLoopMode dequeue: YES]; + } + else + { + lastEvent = [NSApp currentEvent]; + getNextEvent = YES; + } } DESTROY(arp); } @@ -3769,7 +3816,8 @@ static inline float computePeriod(NSPoint mouseLocationWin, TODO: should we ask the data source/column for the cell for this row/column and check whether it has its own action/target? */ - [self sendAction: _action to: _target]; + if (_clickedRow != -1) + [self sendAction: _action to: _target]; } return; } @@ -4002,7 +4050,52 @@ static inline float computePeriod(NSPoint mouseLocationWin, - (void) setFrame: (NSRect)frameRect { - [super setFrame: frameRect]; + NSRect tmpRect = frameRect; + if ([_super_view respondsToSelector:@selector(documentVisibleRect)]) + { + float rowsHeight = ((_numberOfRows * _rowHeight) + 1); + NSRect docRect = [(NSClipView *)_super_view documentVisibleRect]; + + if (rowsHeight < docRect.size.height) + { + tmpRect.size.height = docRect.size.height; + } + else + { + tmpRect.size.height = rowsHeight; + } + // TODO width? + } + [super setFrame: tmpRect]; +} + +- (void) setFrameSize: (NSSize)frameSize +{ + NSSize tmpSize = frameSize; + + if ([_super_view respondsToSelector:@selector(documentVisibleRect)]) + { + float rowsHeight = ((_numberOfRows * _rowHeight) + 1); + NSRect docRect = [(NSClipView *)_super_view documentVisibleRect]; + + if (rowsHeight < docRect.size.height) + { + tmpSize.height = docRect.size.height; + } + else + { + tmpSize.height = rowsHeight; + } + // TODO width? + } + [super setFrameSize: tmpSize]; +} + +- (void) viewWillMoveToSuperview:(NSView *)newSuper +{ + [super viewWillMoveToSuperview:newSuper]; + /* need to potentially enlarge to fill the documentRect of the clip view */ + [self setFrame:_frame]; } - (void) sizeToFit @@ -4639,11 +4732,8 @@ static inline float computePeriod(NSPoint mouseLocationWin, - (void) drawBackgroundInClipRect: (NSRect)clipRect { - // FIXME - /* [_backgroundColor set]; NSRectFill (clipRect); - */ } - (void) drawRect: (NSRect)aRect @@ -4867,6 +4957,7 @@ static inline float computePeriod(NSPoint mouseLocationWin, switch ([(NSNumber *)textMovement intValue]) { case NSReturnTextMovement: + [self _editNextCellAfterRow:row inColumn:column]; // Send action ? break; case NSTabTextMovement: @@ -5466,6 +5557,23 @@ static inline float computePeriod(NSPoint mouseLocationWin, } } +- (void) _editNextCellAfterRow:(int)row inColumn:(int)column +{ + if (++row >= _numberOfColumns) + row = 0; + + if ([self _shouldSelectRow:row]) + { + [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] + byExtendingSelection:NO]; + + if ([self _isCellEditableColumn:column row:row]) + { + [self editColumn:column row:row withEvent:nil select:YES]; + } + } +} + -(BOOL) _editNextEditableCellAfterRow: (int)row column: (int)column { @@ -5697,6 +5805,7 @@ static inline float computePeriod(NSPoint mouseLocationWin, } _superview_width = visible_width; } + [self setFrame:_frame]; } @@ -5802,8 +5911,15 @@ static inline float computePeriod(NSPoint mouseLocationWin, [self displayIfNeeded]; [[NSColor darkGrayColor] set]; - - if (currentDropOperation == NSTableViewDropAbove) + + if (currentDropRow > _numberOfRows) + { + newRect = [self bounds]; + NSFrameRectWithWidth(newRect, 2.0); + oldDraggingRect = newRect; + currentDropRow = _numberOfRows; + } + else if (currentDropOperation == NSTableViewDropAbove) { if (currentDropRow == 0) { diff --git a/Source/NSView.m b/Source/NSView.m index 134b0799d..627893f3e 100644 --- a/Source/NSView.m +++ b/Source/NSView.m @@ -52,6 +52,7 @@ #include "AppKit/NSAffineTransform.h" #include "AppKit/NSApplication.h" +#include "AppKit/NSCursor.h" #include "AppKit/NSDocumentController.h" #include "AppKit/NSDocument.h" #include "AppKit/NSClipView.h" diff --git a/Source/NSWindow.m b/Source/NSWindow.m index 13f88c743..4a145375e 100644 --- a/Source/NSWindow.m +++ b/Source/NSWindow.m @@ -4613,23 +4613,37 @@ BOOL GSViewAcceptsDrag(NSView *v, id dragInfo) void NSCountWindows(int *count) { - *count = (int)NSCountMapTable(windowmaps); + *count = (int)[[GSCurrentServer() windowlist] count]; } void NSWindowList(int size, int list[]) { - NSMapEnumerator me = NSEnumerateMapTable(windowmaps); - void *key; - id win; - int i = 0; - - while (i < size && NSNextMapEnumeratorPair(&me, &key, (void*)&win)) + NSArray *windowList = [GSCurrentServer() windowlist]; + unsigned i, c; + for (i = 0, c = [windowList count]; i < size && i < c; i++) { - list[i++] = (intptr_t)key; + list[i] = [[windowList objectAtIndex:i] intValue]; } -/* FIXME - the list produced should be in window stacking order */ } +NSArray *GSOrderedWindows(void) +{ + NSArray *window_list = [GSCurrentServer() windowlist]; + NSMutableArray *ret = [NSMutableArray array]; + int i, c; + + for (i = 0, c = [window_list count]; i < c; i++) + { + int windowNumber = [[window_list objectAtIndex:i] intValue]; + NSWindow *win = GSWindowWithNumber(windowNumber); + + [ret addObject:win]; + } + + return ret; +} + + NSArray* GSAllWindows(void) { if (windowmaps) diff --git a/Source/NSWorkspace.m b/Source/NSWorkspace.m index 5449901cc..52198bc70 100644 --- a/Source/NSWorkspace.m +++ b/Source/NSWorkspace.m @@ -42,6 +42,7 @@ #endif #include +#include #include #include #include diff --git a/Tools/gopen.m b/Tools/gopen.m index 1d283badf..ba6486466 100644 --- a/Tools/gopen.m +++ b/Tools/gopen.m @@ -21,6 +21,7 @@ */ #include +#include #include #include #include