From 951c165938be899ad5925d7605e6487ce90d2bea Mon Sep 17 00:00:00 2001 From: richard Date: Wed, 3 Feb 1999 21:53:29 +0000 Subject: [PATCH] General tidyup - make updates work properly etc. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@3647 72102866-910b-0410-8b05-ffd578937521 --- Source/NSApplication.m | 26 +- Source/NSClipView.m | 201 ++++-- Source/NSScrollView.m | 945 ++++++++++++++------------- Source/NSScroller.m | 1401 ++++++++++++++++++++-------------------- Source/NSWindow.m | 8 +- 5 files changed, 1402 insertions(+), 1179 deletions(-) diff --git a/Source/NSApplication.m b/Source/NSApplication.m index dda288ba3..a8987c5a0 100644 --- a/Source/NSApplication.m +++ b/Source/NSApplication.m @@ -1220,23 +1220,25 @@ BOOL done = NO; windows_need_update = flag; } -- (void)updateWindows // send an update message +- (void) updateWindows // send an update message { // to all visible windows -int i, count; -NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + int i, count; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; NSArray *window_list = [self windows]; + + windows_need_update = NO; // notify that an update is // imminent - [nc postNotificationName:NSApplicationWillUpdateNotification object:self]; + [nc postNotificationName:NSApplicationWillUpdateNotification object: self]; - for (i = 0, count = [window_list count]; i < count; i++) - { - NSWindow *win = [window_list objectAtIndex:i]; - if ([win isVisible]) // send update only if the - [win update]; // window is visible - } - // notify update did occur - [nc postNotificationName:NSApplicationDidUpdateNotification object:self]; + for (i = 0, count = [window_list count]; i < count; i++) + { + NSWindow *win = [window_list objectAtIndex: i]; + if ([win isVisible]) // send update only if the + [win update]; // window is visible + } + // notify update did occur + [nc postNotificationName:NSApplicationDidUpdateNotification object:self]; } - (NSArray*) windows diff --git a/Source/NSClipView.m b/Source/NSClipView.m index eca648668..7d4a00c8f 100644 --- a/Source/NSClipView.m +++ b/Source/NSClipView.m @@ -5,14 +5,14 @@ Author: Ovidiu Predescu Date: July 1997 - + This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -42,7 +42,7 @@ return self; } -- (void)setDocumentView:(NSView*)aView +- (void) setDocumentView: (NSView*)aView { if (_documentView == aView) return; @@ -81,11 +81,11 @@ [[self superview] reflectScrolledClipView:self]; } -- (void)resetCursorRects +- (void) resetCursorRects { [self addCursorRect:[self bounds] cursor:_cursor]; } - + - (void) resizeSubviewsWithOldSize: (NSSize)old_size { [super resizeSubviewsWithOldSize: old_size]; @@ -95,8 +95,11 @@ } } -- (void)scrollToPoint:(NSPoint)point +- (void) scrollToPoint: (NSPoint)point { + NSRect originalBounds = [self bounds]; + NSRect newBounds = originalBounds; + NSRect intersection; #ifdef DEBUGLOG NSPoint currentPoint = [self bounds].origin; @@ -105,26 +108,101 @@ point.x, point.y); #endif - point = [self constrainScrollPoint: point]; - [self setBoundsOrigin: NSMakePoint(point.x, point.y)]; + newBounds.origin = [self constrainScrollPoint: point]; + + if (NSEqualPoints(originalBounds.origin, newBounds.origin)) + return; + +// [self setBoundsOrigin: newBounds.origin]; - [self setNeedsDisplay: YES]; if (_copiesOnScroll) - /* TODO: move the visible portion of the document */ - [_documentView displayRect: bounds]; + { + // copy the portion of the view that is common before and after scrolling. + // then tell docview to draw the exposed parts. + // intersection is the common rectangle + intersection = NSIntersectionRect(originalBounds, newBounds); + if (NSEqualRects(intersection, NSZeroRect)) + { + // no intersection -- docview should draw everyting + [self setBoundsOrigin: newBounds.origin]; + [_documentView setNeedsDisplayInRect: newBounds]; + } + else + { + NSPoint destPoint = intersection.origin; + float dx = newBounds.origin.x - originalBounds.origin.x; + float dy = newBounds.origin.y - originalBounds.origin.y; + destPoint.x -= dx; + destPoint.y -= dy; + [self lockFocus]; + NSCopyBits(0, intersection, destPoint); + [self unlockFocus]; + + [self setBoundsOrigin: newBounds.origin]; + if (dx != 0) + { + // moved in x -- redraw a full-height rectangle at + // side of intersection + NSRect redrawRect; + + redrawRect.origin.y = newBounds.origin.y; + redrawRect.size.height = newBounds.size.height; + redrawRect.size.width = newBounds.size.width + - intersection.size.width; + if (dx < 0) + { + // moved to the left -- redraw at left of intersection + redrawRect.origin.x = newBounds.origin.x; + } + else + { + // moved to the right -- redraw at right of intersection + redrawRect.origin.x = newBounds.origin.x + + intersection.size.width; + } + [_documentView setNeedsDisplayInRect: redrawRect]; + } + + if (dy != 0) + { + // moved in y + // -- redraw rectangle with intersection's width over or under it + NSRect redrawRect; + + redrawRect.origin.x = intersection.origin.x; + redrawRect.size.width = intersection.size.width; + redrawRect.size.height = newBounds.size.height + - intersection.size.height; + if (dy < 0) + { + // moved down -- redraw under intersection + redrawRect.origin.y = newBounds.origin.y; + } + else + { + // moved up -- redraw over intersection + redrawRect.origin.y = newBounds.origin.y + + intersection.size.height; + } + [_documentView setNeedsDisplayInRect: redrawRect]; + } + } + } else - [_documentView setNeedsDisplayInRect: bounds]; -// [_documentView setNeedsDisplay: YES]; -[self display]; + { + // dont copy anything -- docview draws it all + [self setBoundsOrigin: newBounds.origin]; + [_documentView setNeedsDisplayInRect: newBounds]; + } } -- (NSPoint)constrainScrollPoint:(NSPoint)proposedNewOrigin +- (NSPoint) constrainScrollPoint: (NSPoint)proposedNewOrigin { NSRect documentFrame = [_documentView frame]; NSPoint new = proposedNewOrigin; if (documentFrame.size.width <= bounds.size.width) - new.x = 0.0; + new.x = documentFrame.origin.x; else if (proposedNewOrigin.x <= documentFrame.origin.x) new.x = documentFrame.origin.x; else if (proposedNewOrigin.x @@ -145,7 +223,7 @@ else { if (documentFrame.size.height <= bounds.size.height) - new.y = 0.0; + new.y = documentFrame.origin.y; else if (proposedNewOrigin.y <= documentFrame.origin.y) new.y = documentFrame.origin.y; else if (proposedNewOrigin.y @@ -156,7 +234,7 @@ return new; } -- (NSRect)documentRect +- (NSRect) documentRect { NSRect documentFrame = [_documentView frame]; NSRect clipViewBounds = bounds; @@ -169,7 +247,7 @@ return rect; } -- (NSRect)documentVisibleRect +- (NSRect) documentVisibleRect { NSRect documentBounds = [_documentView bounds]; NSRect clipViewBounds = bounds; @@ -183,97 +261,132 @@ return rect; } -- (void) drawRect:(NSRect)rect +- (void) drawRect: (NSRect)rect { [[self backgroundColor] set]; NSRectFill(rect); } -- (BOOL)autoscroll:(NSEvent*)theEvent +- (BOOL) autoscroll: (NSEvent*)theEvent { return 0; } -- (void)viewBoundsChanged:(NSNotification*)aNotification +- (void) viewBoundsChanged: (NSNotification*)aNotification { [super_view reflectScrolledClipView:self]; } -- (void)viewFrameChanged:(NSNotification*)aNotification +- (void) viewFrameChanged: (NSNotification*)aNotification { [self setBoundsOrigin: [self constrainScrollPoint: bounds.origin]]; [super_view reflectScrolledClipView:self]; } -- (void)scaleUnitSquareToSize:(NSSize)newUnitSize +- (void) scaleUnitSquareToSize: (NSSize)newUnitSize { [super scaleUnitSquareToSize:newUnitSize]; [super_view reflectScrolledClipView:self]; } -- (void)setBoundsOrigin:(NSPoint)aPoint +- (void) setBoundsOrigin: (NSPoint)aPoint { [super setBoundsOrigin:aPoint]; [super_view reflectScrolledClipView:self]; } -- (void)setBoundsSize:(NSSize)aSize +- (void) setBoundsSize: (NSSize)aSize { [super setBoundsSize:aSize]; [super_view reflectScrolledClipView:self]; } -- (void)setFrameSize:(NSSize)aSize +- (void) setFrameSize: (NSSize)aSize { [super setFrameSize:aSize]; [super_view reflectScrolledClipView:self]; } -- (void)setFrameOrigin:(NSPoint)aPoint +- (void) setFrameOrigin: (NSPoint)aPoint { [super setFrameOrigin:aPoint]; [super_view reflectScrolledClipView:self]; } -- (void)setFrame:(NSRect)rect +- (void) setFrame: (NSRect)rect { [super setFrame:rect]; [super_view reflectScrolledClipView:self]; } -- (void)translateOriginToPoint:(NSPoint)aPoint +- (void) translateOriginToPoint: (NSPoint)aPoint { [super translateOriginToPoint:aPoint]; [super_view reflectScrolledClipView:self]; } -- (BOOL)isOpaque { return YES; } -- (id)documentView { return _documentView; } -- (void)setCopiesOnScroll:(BOOL)flag { _copiesOnScroll = flag; } -- (BOOL)copiesOnScroll { return _copiesOnScroll; } -- (void)setDocumentCursor:(NSCursor*)aCursor { ASSIGN(_cursor, aCursor); } -- (NSCursor*)documentCursor { return _cursor; } -- (NSColor*)backgroundColor { return _backgroundColor; } -- (BOOL)isFlipped { return [_documentView isFlipped]; } -- (BOOL)acceptsFirstResponder { return _documentView != nil; } +- (BOOL) isOpaque +{ + return YES; +} -- (void)setBackgroundColor:(NSColor*)aColor +- (id) documentView +{ + return _documentView; +} + +- (void) setCopiesOnScroll: (BOOL)flag +{ + _copiesOnScroll = flag; +} + +- (BOOL) copiesOnScroll +{ + return _copiesOnScroll; +} + +- (void) setDocumentCursor: (NSCursor*)aCursor +{ + ASSIGN(_cursor, aCursor); +} + +- (NSCursor*) documentCursor +{ + return _cursor; +} + +- (NSColor*) backgroundColor +{ + return _backgroundColor; +} + +- (BOOL) isFlipped +{ + return [_documentView isFlipped]; +} + +- (BOOL) acceptsFirstResponder +{ + return _documentView != nil; +} + +- (void) setBackgroundColor: (NSColor*)aColor { ASSIGN(_backgroundColor, aColor); } /* Disable rotation of clip view */ -- (void)rotateByAngle:(float)angle +- (void) rotateByAngle: (float)angle {} -- (void)setBoundsRotation:(float)angle +- (void) setBoundsRotation: (float)angle {} -- (void)setFrameRotation:(float)angle +- (void) setFrameRotation: (float)angle {} /* Managing responder chain */ -- (BOOL)becomeFirstResponder +- (BOOL) becomeFirstResponder { return [_documentView becomeFirstResponder]; } diff --git a/Source/NSScrollView.m b/Source/NSScrollView.m index 0e9c4ea47..77541bae1 100644 --- a/Source/NSScrollView.m +++ b/Source/NSScrollView.m @@ -7,14 +7,14 @@ Date: July 1997 Author: Felipe A. Rodriguez Date: October 1998 - + This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -36,11 +36,11 @@ // // Postscript functions to be defined and implemented by the backend // -extern void PSsetlinewidth(float width); -extern void PSsetgray(float num); +extern void PSsetlinewidth(float width); +extern void PSsetgray(float num); extern void PSmoveto(float x, float y); extern void PSrlineto(float x, float y); -extern void PSstroke(void); +extern void PSstroke(void); extern void PSgrestore(void); extern void PSgsave(void); @@ -57,125 +57,138 @@ static Class rulerViewClass = nil; // // Class methods // -+ (void)initialize ++ (void) initialize { - if (self == [NSScrollView class]) - { - NSDebugLog(@"Initialize NSScrollView class\n"); - [self setVersion:1]; - } + if (self == [NSScrollView class]) + { + NSDebugLog(@"Initialize NSScrollView class\n"); + [self setVersion: 1]; + } } -+ (void)setRulerViewClass:(Class)aClass { rulerViewClass = aClass; } -+ (Class)rulerViewClass { return rulerViewClass; } - -+ (NSSize)contentSizeForFrameSize:(NSSize)frameSize // calc content size by - hasHorizontalScroller:(BOOL)hFlag // taking into account - hasVerticalScroller:(BOOL)vFlag // the border type - borderType:(NSBorderType)borderType ++ (void) setRulerViewClass: (Class)aClass { -NSSize size = frameSize; - // Substract 1 from the width and height of - if (hFlag) // the line that separates the horizontal - { // and vertical scroller from the clip view - size.height -= [NSScroller scrollerWidth]; - size.height -= 1; - } - if (vFlag) - { - size.width -= [NSScroller scrollerWidth]; - size.width -= 1; - } - - switch (borderType) - { - case NSNoBorder: - break; - - case NSLineBorder: - size.width -= 2; - size.height -= 2; - break; - - case NSBezelBorder: - case NSGrooveBorder: - size.width -= 4; - size.height -= 4; - break; - } - - return size; + rulerViewClass = aClass; } -+ (NSSize)frameSizeForContentSize:(NSSize)contentSize - hasHorizontalScroller:(BOOL)hFlag - hasVerticalScroller:(BOOL)vFlag - borderType:(NSBorderType)borderType ++ (Class) rulerViewClass { -NSSize size = contentSize; - // Add 1 to the width and height for the - if (hFlag) // line that separates the horizontal and - { // vertical scroller from the clip view. - size.height += [NSScroller scrollerWidth]; - size.height += 1; - } - if (vFlag) - { - size.width += [NSScroller scrollerWidth]; - size.width += 1; - } + return rulerViewClass; +} - switch (borderType) - { - case NSNoBorder: - break; - - case NSLineBorder: - size.width += 2; - size.height += 2; - break; - - case NSBezelBorder: - case NSGrooveBorder: - size.width += 4; - size.height += 4; - break; - } ++ (NSSize) contentSizeForFrameSize: (NSSize)frameSize + hasHorizontalScroller: (BOOL)hFlag + hasVerticalScroller: (BOOL)vFlag + borderType: (NSBorderType)borderType +{ + NSSize size = frameSize; - return size; + // Substract 1 from the width and height of + // the line that separates the horizontal + // and vertical scroller from the clip view + if (hFlag) + { + size.height -= [NSScroller scrollerWidth]; + size.height -= 1; + } + if (vFlag) + { + size.width -= [NSScroller scrollerWidth]; + size.width -= 1; + } + + switch (borderType) + { + case NSNoBorder: + break; + + case NSLineBorder: + size.width -= 2; + size.height -= 2; + break; + + case NSBezelBorder: + case NSGrooveBorder: + size.width -= 4; + size.height -= 4; + break; + } + + return size; +} + ++ (NSSize) frameSizeForContentSize: (NSSize)contentSize + hasHorizontalScroller: (BOOL)hFlag + hasVerticalScroller: (BOOL)vFlag + borderType: (NSBorderType)borderType +{ + NSSize size = contentSize; + + // Add 1 to the width and height for the + // line that separates the horizontal and + // vertical scroller from the clip view. + if (hFlag) + { + size.height += [NSScroller scrollerWidth]; + size.height += 1; + } + if (vFlag) + { + size.width += [NSScroller scrollerWidth]; + size.width += 1; + } + + switch (borderType) + { + case NSNoBorder: + break; + + case NSLineBorder: + size.width += 2; + size.height += 2; + break; + + case NSBezelBorder: + case NSGrooveBorder: + size.width += 4; + size.height += 4; + break; + } + + return size; } // // Instance methods // -- initWithFrame:(NSRect)rect +- initWithFrame: (NSRect)rect { - [super initWithFrame:rect]; - [self setContentView:[[NSClipView new] autorelease]]; - _lineScroll = 10; - _pageScroll = 10; - _borderType = NSBezelBorder; - _scrollsDynamically = YES; - [self tile]; - - return self; + [super initWithFrame: rect]; + [self setContentView: [[NSClipView new] autorelease]]; + _lineScroll = 10; + _pageScroll = 10; + _borderType = NSBezelBorder; + _scrollsDynamically = YES; + [self tile]; + + return self; } - init { - return [self initWithFrame:NSZeroRect]; + return [self initWithFrame: NSZeroRect]; } -- (void)dealloc +- (void) dealloc { - [_contentView release]; - - [_horizScroller release]; - [_vertScroller release]; - [_horizRuler release]; - [_vertRuler release]; - - [super dealloc]; + [_contentView release]; + + [_horizScroller release]; + [_vertScroller release]; + [_horizRuler release]; + [_vertRuler release]; + + [super dealloc]; } - (void) setContentView: (NSView*)aView @@ -190,448 +203,510 @@ NSSize size = contentSize; { [_horizScroller removeFromSuperview]; - // Do not add the scroller view to the subviews array yet; + // Do not add the scroller view to the subviews array yet; // -setHasHorizontalScroller must be invoked first ASSIGN(_horizScroller, aScroller); - if (_horizScroller) + if (_horizScroller) { [_horizScroller setAutoresizingMask: NSViewWidthSizable]; - [_horizScroller setTarget:self]; - [_horizScroller setAction:@selector(_doScroll:)]; + [_horizScroller setTarget: self]; + [_horizScroller setAction: @selector(_doScroll:)]; } } -- (void)setHasHorizontalScroller:(BOOL)flag +- (void) setHasHorizontalScroller: (BOOL)flag { - if (_hasHorizScroller == flag) - return; + if (_hasHorizScroller == flag) + return; - _hasHorizScroller = flag; + _hasHorizScroller = flag; - if (_hasHorizScroller) - { - if (!_horizScroller) - [self setHorizontalScroller:[[NSScroller new] autorelease]]; - [self addSubview:_horizScroller]; - } - else - [_horizScroller removeFromSuperview]; + if (_hasHorizScroller) + { + if (!_horizScroller) + [self setHorizontalScroller: [[NSScroller new] autorelease]]; + [self addSubview: _horizScroller]; + } + else + [_horizScroller removeFromSuperview]; - [self tile]; + [self tile]; } - (void) setVerticalScroller: (NSScroller*)aScroller { [_vertScroller removeFromSuperview]; - // Do not add the scroller view to the subviews array yet; + // Do not add the scroller view to the subviews array yet; // -setHasVerticalScroller must be invoked first ASSIGN(_vertScroller, aScroller); - if (_vertScroller) + if (_vertScroller) { [_vertScroller setAutoresizingMask: NSViewHeightSizable]; - [_vertScroller setTarget:self]; - [_vertScroller setAction:@selector(_doScroll:)]; + [_vertScroller setTarget: self]; + [_vertScroller setAction: @selector(_doScroll:)]; } } -- (void)setHasVerticalScroller:(BOOL)flag +- (void) setHasVerticalScroller: (BOOL)flag { - if (_hasVertScroller == flag) - return; + if (_hasVertScroller == flag) + return; - _hasVertScroller = flag; + _hasVertScroller = flag; - if (_hasVertScroller) - { - if (!_vertScroller) - { - [self setVerticalScroller:[[NSScroller new] autorelease]]; - if (_contentView && ![_contentView isFlipped]) - [_vertScroller setFloatValue:1]; - } - [self addSubview:_vertScroller]; - } - else - [_vertScroller removeFromSuperview]; + if (_hasVertScroller) + { + if (!_vertScroller) + { + [self setVerticalScroller: [[NSScroller new] autorelease]]; + if (_contentView && ![_contentView isFlipped]) + [_vertScroller setFloatValue: 1]; + } + [self addSubview: _vertScroller]; + } + else + [_vertScroller removeFromSuperview]; - [self tile]; + [self tile]; } -- (void)_doScroll:(NSScroller*)scroller +- (void)_doScroll: (NSScroller*)scroller { -float floatValue = [scroller floatValue]; -NSRect clipViewBounds = [_contentView bounds]; -NSScrollerPart hitPart = [scroller hitPart]; -NSRect documentRect = [_contentView documentRect]; -float amount = 0; -NSPoint point; + float floatValue = [scroller floatValue]; + NSRect clipViewBounds = [_contentView bounds]; + NSScrollerPart hitPart = [scroller hitPart]; + NSRect documentRect = [_contentView documentRect]; + float amount = 0; + NSPoint point = clipViewBounds.origin; - NSDebugLog (@"_doScroll: float value = %f", floatValue); + NSDebugLog (@"_doScroll: float value = %f", floatValue); - _knobMoved = NO; + // do nothing if scroller is unknown + if (scroller != _horizScroller && scroller != _vertScroller) + return; - if(hitPart == NSScrollerKnob) - _knobMoved = YES; - else - { - if (hitPart == NSScrollerIncrementLine) - amount = _lineScroll; - else if (hitPart == NSScrollerIncrementPage) - amount = _pageScroll; - else if (hitPart == NSScrollerDecrementLine) - amount = -_lineScroll; - else if (hitPart == NSScrollerDecrementPage) - amount = -_pageScroll; - else - _knobMoved = YES; - } + _knobMoved = NO; - if (!_knobMoved) // button scrolling - { - if (scroller == _horizScroller) - { - point.x = clipViewBounds.origin.x + amount; - point.y = clipViewBounds.origin.y; - } - else - { - if (scroller == _vertScroller) - { - point.x = clipViewBounds.origin.x; - // If view is flipped - if ([_contentView isFlipped]) // reverse the scroll - amount = -amount; // direction - NSDebugLog (@"increment/decrement: amount = %f, flipped = %d", - amount, [_contentView isFlipped]); - point.y = clipViewBounds.origin.y + amount; - point.y = point.y < 0 ? 0 : point.y; // FIX ME s/b in - } // clipview - else - return; // do nothing - } - } - else // knob scolling - { - if (scroller == _horizScroller) - { - point.x = floatValue * (documentRect.size.width + if (hitPart == NSScrollerKnob || hitPart == NSScrollerKnobSlot) + _knobMoved = YES; + else + { + //FIXME in a page scroll, amount should be the portion of the view that + // stays visible, not the one that disapears + if (hitPart == NSScrollerIncrementLine) + amount = _lineScroll; + else if (hitPart == NSScrollerIncrementPage) + amount = _pageScroll; + else if (hitPart == NSScrollerDecrementLine) + amount = -_lineScroll; + else if (hitPart == NSScrollerDecrementPage) + amount = -_pageScroll; + else + return; + } + + if (!_knobMoved) // button scrolling + { + if (scroller == _horizScroller) + { + point.x = clipViewBounds.origin.x + amount; + } + else + { + if ([_contentView isFlipped]) + { + // If view is flipped + // reverse the scroll direction + amount = -amount; + } + NSDebugLog (@"increment/decrement: amount = %f, flipped = %d", + amount, [_contentView isFlipped]); + point.y = clipViewBounds.origin.y + amount; + } + } + else // knob scolling + { + if (scroller == _horizScroller) + { + point.x = floatValue * (documentRect.size.width - clipViewBounds.size.width); - point.y = clipViewBounds.origin.y; - } - else - { - if (scroller == _vertScroller) - { - point.x = clipViewBounds.origin.x; - if (![_contentView isFlipped]) - floatValue = 1 - floatValue; - point.y = floatValue * (documentRect.size.height - - clipViewBounds.size.height); - } - else - return; // do nothing - } - } + } + else + { + if (![_contentView isFlipped]) + floatValue = 1 - floatValue; + point.y = floatValue * (documentRect.size.height + - clipViewBounds.size.height); + } + } - [_contentView scrollToPoint:point]; // scroll clipview - if (!_knobMoved) - { // if scrolling via - [self reflectScrolledClipView:_contentView]; // buttons update -// if (scroller == _vertScroller) // scroller pos to -// [_vertScroller displayIfNeeded]; // reflect clipview -// else -// [_horizScroller displayIfNeeded]; -// [window flushWindow]; - } + [_contentView scrollToPoint: point]; + // scroll clipview + // reflectScrolledClipView has been called by the clipView. + + //FIXME: should this be here? + // NSWindow's doc says update is called for each event + [window update]; } -- (void)reflectScrolledClipView:(NSClipView*)aClipView +- (void) reflectScrolledClipView: (NSClipView*)aClipView { -NSRect documentFrame = NSZeroRect; -NSRect clipViewBounds = NSZeroRect; -float floatValue; -float knobProportion; -id documentView; - // do nothing if - if(aClipView != _contentView) // aClipView is not - return; // our content view + NSRect documentFrame = NSZeroRect; + NSRect clipViewBounds = NSZeroRect; + float floatValue; + float knobProportion; + id documentView; -// if (_knobMoved) // is this really needed? -// return; // FAR FIX ME ? + if (aClipView != _contentView) + return; - NSDebugLog (@"reflectScrolledClipView:"); + NSDebugLog (@"reflectScrolledClipView:"); - clipViewBounds = [_contentView bounds]; - if ((documentView = [_contentView documentView])) - documentFrame = [documentView frame]; + clipViewBounds = [_contentView bounds]; + if ((documentView = [_contentView documentView])) + documentFrame = [documentView frame]; - if (_hasVertScroller) - { - if (documentFrame.size.height <= clipViewBounds.size.height) - [_vertScroller setEnabled:NO]; - else - { - [_vertScroller setEnabled:YES]; - knobProportion = clipViewBounds.size.height / - documentFrame.size.height; - floatValue = clipViewBounds.origin.y / (documentFrame.size.height - - clipViewBounds.size.height); - if (![_contentView isFlipped]) - floatValue = 1 - floatValue; - [_vertScroller setFloatValue:floatValue - knobProportion:knobProportion]; - [_vertScroller displayIfNeededIgnoringOpacity]; - } - } + if (_hasVertScroller) + { + if (documentFrame.size.height <= clipViewBounds.size.height) + [_vertScroller setEnabled: NO]; + else + { + [_vertScroller setEnabled: YES]; + knobProportion = clipViewBounds.size.height / + documentFrame.size.height; + floatValue = clipViewBounds.origin.y / (documentFrame.size.height + - clipViewBounds.size.height); + if (![_contentView isFlipped]) + floatValue = 1 - floatValue; + [_vertScroller setFloatValue: floatValue + knobProportion: knobProportion]; + } + } - if (_hasHorizScroller) - { - if (documentFrame.size.width <= clipViewBounds.size.width) - [_horizScroller setEnabled:NO]; - else - { - [_horizScroller setEnabled:YES]; - knobProportion = clipViewBounds.size.width / - documentFrame.size.width; - floatValue = clipViewBounds.origin.x / (documentFrame.size.width - - clipViewBounds.size.width); - [_horizScroller setFloatValue:floatValue - knobProportion:knobProportion]; - [_horizScroller displayIfNeededIgnoringOpacity]; - } - } - - [window flushWindow]; + if (_hasHorizScroller) + { + if (documentFrame.size.width <= clipViewBounds.size.width) + [_horizScroller setEnabled: NO]; + else + { + [_horizScroller setEnabled: YES]; + knobProportion = clipViewBounds.size.width / + documentFrame.size.width; + floatValue = clipViewBounds.origin.x / (documentFrame.size.width - + clipViewBounds.size.width); + [_horizScroller setFloatValue: floatValue + knobProportion: knobProportion]; + } + } } -- (void)setHorizontalRulerView:(NSRulerView*)aRulerView // FIX ME +- (void) setHorizontalRulerView: (NSRulerView*)aRulerView // FIX ME { - ASSIGN(_horizRuler, aRulerView); + ASSIGN(_horizRuler, aRulerView); } -- (void)setHasHorizontalRuler:(BOOL)flag // FIX ME +- (void) setHasHorizontalRuler: (BOOL)flag // FIX ME { - if (_hasHorizRuler == flag) - return; + if (_hasHorizRuler == flag) + return; - _hasHorizRuler = flag; + _hasHorizRuler = flag; } -- (void)setVerticalRulerView:(NSRulerView*)ruler // FIX ME +- (void) setVerticalRulerView: (NSRulerView*)ruler // FIX ME { - ASSIGN(_vertRuler, ruler); + ASSIGN(_vertRuler, ruler); } -- (void)setHasVerticalRuler:(BOOL)flag // FIX ME +- (void) setHasVerticalRuler: (BOOL)flag // FIX ME { - if (_hasVertRuler == flag) - return; + if (_hasVertRuler == flag) + return; - _hasVertRuler = flag; + _hasVertRuler = flag; } -- (void)setRulersVisible:(BOOL)flag +- (void) setRulersVisible: (BOOL)flag { } -- (void)setFrame:(NSRect)rect +- (void) setFrame: (NSRect)rect { - [super setFrame:rect]; - [self tile]; + [super setFrame: rect]; + [self tile]; } -- (void)setFrameSize:(NSSize)size +- (void) setFrameSize: (NSSize)size { - [super setFrameSize:size]; - [self tile]; + [super setFrameSize: size]; + [self tile]; } -- (void)tile +- (void) tile { -NSRect boundsRect = [self bounds]; -NSSize contentSize = [isa contentSizeForFrameSize:boundsRect.size - hasHorizontalScroller:_hasHorizScroller - hasVerticalScroller:_hasVertScroller - borderType:_borderType]; -float scrollerWidth = [NSScroller scrollerWidth]; -NSRect contentRect = { NSZeroPoint, contentSize }; -NSRect vertScrollerRect = NSZeroRect; -NSRect horizScrollerRect = NSZeroRect; -float borderThickness = 0; + NSRect boundsRect = [self bounds]; + NSSize contentSize = [isa contentSizeForFrameSize: boundsRect.size + hasHorizontalScroller: _hasHorizScroller + hasVerticalScroller: _hasVertScroller + borderType: _borderType]; + float scrollerWidth = [NSScroller scrollerWidth]; + NSRect contentRect = { NSZeroPoint, contentSize }; + NSRect vertScrollerRect = NSZeroRect; + NSRect horizScrollerRect = NSZeroRect; + float borderThickness = 0; - switch ([self borderType]) - { - case NSNoBorder: - break; - - case NSLineBorder: - borderThickness = 1; - break; - - case NSBezelBorder: - case NSGrooveBorder: - borderThickness = 2; - break; - } + switch ([self borderType]) + { + case NSNoBorder: + break; - contentRect.origin.x = borderThickness; - contentRect.origin.y = borderThickness; + case NSLineBorder: + borderThickness = 1; + break; - if (_hasVertScroller) - { - vertScrollerRect.origin.x = boundsRect.origin.x + borderThickness; - vertScrollerRect.origin.y = boundsRect.origin.y + borderThickness; - vertScrollerRect.size.width = scrollerWidth; - vertScrollerRect.size.height =bounds.size.height - 2 * borderThickness; - - contentRect.origin.x += scrollerWidth + 1; - } + case NSBezelBorder: + case NSGrooveBorder: + borderThickness = 2; + break; + } - if (_hasHorizScroller) - { - horizScrollerRect.origin.x = contentRect.origin.x; - horizScrollerRect.origin.y = boundsRect.origin.y + borderThickness; - horizScrollerRect.size.width = contentRect.size.width; - horizScrollerRect.size.height = scrollerWidth; + contentRect.origin.x = borderThickness; + contentRect.origin.y = borderThickness; - contentRect.origin.y += scrollerWidth + 1; - } + if (_hasVertScroller) + { + vertScrollerRect.origin.x = boundsRect.origin.x + borderThickness; + vertScrollerRect.origin.y = boundsRect.origin.y + borderThickness; + vertScrollerRect.size.width = scrollerWidth; + vertScrollerRect.size.height =bounds.size.height - 2 * borderThickness; - // If the document view is not - if (![_contentView isFlipped]) // flipped reverse the meaning - [_vertScroller setFloatValue:1]; // of the vertical scroller's - [_horizScroller setFrame:horizScrollerRect]; - [_vertScroller setFrame:vertScrollerRect]; - [_contentView setFrame:contentRect]; + contentRect.origin.x += scrollerWidth + 1; + } + + if (_hasHorizScroller) + { + horizScrollerRect.origin.x = contentRect.origin.x; + horizScrollerRect.origin.y = boundsRect.origin.y + borderThickness; + horizScrollerRect.size.width = contentRect.size.width; + horizScrollerRect.size.height = scrollerWidth; + + contentRect.origin.y += scrollerWidth + 1; + } + + // If the document view is not flipped reverse the meaning + // of the vertical scroller's + if (![_contentView isFlipped]) + [_vertScroller setFloatValue: 1]; + [_horizScroller setFrame: horizScrollerRect]; + [_vertScroller setFrame: vertScrollerRect]; + [_contentView setFrame: contentRect]; } -- (void)drawRect:(NSRect)rect +- (void) drawRect: (NSRect)rect { -float scrollerWidth = [NSScroller scrollerWidth]; -float horizLinePosition, horizLineLength = [self bounds].size.width; -float borderThickness = 0; + float scrollerWidth = [NSScroller scrollerWidth]; + float horizLinePosition, horizLineLength = [self bounds].size.width; + float borderThickness = 0; - fprintf (stderr, - "NSScrollView drawRect: origin (%1.2f, %1.2f), size (%1.2f, %1.2f)\n", - rect.origin.x, rect.origin.y, + fprintf (stderr, + "NSScrollView drawRect: origin (%1.2f, %1.2f), size (%1.2f, %1.2f)\n", + rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); - PSgsave (); - switch ([self borderType]) - { - case NSNoBorder: - break; - - case NSLineBorder: - borderThickness = 1; - NSFrameRect (rect); - break; - - case NSBezelBorder: - borderThickness = 2; - NSDrawGrayBezel (rect, rect); - break; - - case NSGrooveBorder: - borderThickness = 2; - NSDrawGroove (rect, rect); - break; - } + PSgsave (); + switch ([self borderType]) + { + case NSNoBorder: + break; - horizLinePosition = borderThickness; + case NSLineBorder: + borderThickness = 1; + NSFrameRect (rect); + break; - PSsetlinewidth (1); - PSsetgray (0); - if (_hasVertScroller) - { - horizLinePosition = scrollerWidth + borderThickness; - horizLineLength -= scrollerWidth + 2 * borderThickness; - PSmoveto (horizLinePosition, borderThickness + 1); - PSrlineto (0, [self bounds].size.height - 2 * borderThickness); - PSstroke (); - } + case NSBezelBorder: + borderThickness = 2; + NSDrawGrayBezel (rect, rect); + break; - if (_hasHorizScroller) - { - PSmoveto (horizLinePosition, scrollerWidth + borderThickness + 1); - PSrlineto (horizLineLength - 1, 0); - PSstroke (); - } + case NSGrooveBorder: + borderThickness = 2; + NSDrawGroove (rect, rect); + break; + } - PSgrestore (); + horizLinePosition = borderThickness; + + PSsetlinewidth (1); + PSsetgray (0); + if (_hasVertScroller) + { + horizLinePosition = scrollerWidth + borderThickness; + horizLineLength -= scrollerWidth + 2 * borderThickness; + PSmoveto (horizLinePosition, borderThickness + 1); + PSrlineto (0, [self bounds].size.height - 2 * borderThickness); + PSstroke (); + } + + if (_hasHorizScroller) + { + PSmoveto (horizLinePosition, scrollerWidth + borderThickness + 1); + PSrlineto (horizLineLength - 1, 0); + PSstroke (); + } + + PSgrestore (); } -- (NSRect)documentVisibleRect +- (NSRect) documentVisibleRect { - return [_contentView documentVisibleRect]; + return [_contentView documentVisibleRect]; } -- (void)setBackgroundColor:(NSColor*)aColor +- (void) setBackgroundColor: (NSColor*)aColor { - [_contentView setBackgroundColor:aColor]; + [_contentView setBackgroundColor: aColor]; } -- (NSColor*)backgroundColor -{ - return [_contentView backgroundColor]; -} - -- (void)setBorderType:(NSBorderType)borderType -{ - _borderType = borderType; -} - -- (void)setDocumentView:(NSView*)aView +- (NSColor*) backgroundColor { - [_contentView setDocumentView:aView]; - if (_contentView && ![_contentView isFlipped]) - [_vertScroller setFloatValue:1]; - [self tile]; + return [_contentView backgroundColor]; +} + +- (void) setBorderType: (NSBorderType)borderType +{ + _borderType = borderType; +} + +- (void) setDocumentView: (NSView*)aView +{ + [_contentView setDocumentView: aView]; + if (_contentView && ![_contentView isFlipped]) + [_vertScroller setFloatValue: 1]; + [self tile]; #if 0 /* Redundant stuff - done in -tile */ - [_contentView viewFrameChanged:nil]; - // update scroller - [self reflectScrolledClipView:(NSClipView*)_contentView]; + [_contentView viewFrameChanged: nil]; + // update scroller + [self reflectScrolledClipView: (NSClipView*)_contentView]; #endif } #if 0 /* Don't need to override if we can trust the default autoresizing */ -- (void)resizeSubviewsWithOldSize:(NSSize)oldSize +- (void) resizeSubviewsWithOldSize: (NSSize)oldSize { - fprintf (stderr, "NSScrollView resizeSubviewsWithOldSize \n"); - [super resizeSubviewsWithOldSize:oldSize]; - [self tile]; + fprintf (stderr, "NSScrollView resizeSubviewsWithOldSize \n"); + [super resizeSubviewsWithOldSize: oldSize]; + [self tile]; } #endif -- (id)documentView { return [_contentView documentView]; } -- (NSCursor*)documentCursor { return [_contentView documentCursor]; } - -- (void)setDocumentCursor:(NSCursor*)aCursor +- (id) documentView { - [_contentView setDocumentCursor:aCursor]; + return [_contentView documentView]; } -- (BOOL)isOpaque { return YES; } -- (NSBorderType)borderType { return _borderType; } -- (NSScroller*)verticalScroller { return _vertScroller; } -- (BOOL)hasVerticalScroller { return _hasVertScroller; } -- (BOOL)hasHorizontalRuler { return _hasHorizRuler; } -- (NSSize)contentSize { return [_contentView bounds].size; } -- (NSView*)contentView { return _contentView; } -- (NSRulerView*)horizontalRulerView { return _horizRuler; } -- (BOOL)hasVerticalRuler { return _hasVertRuler; } -- (NSRulerView*)verticalRulerView { return _vertRuler; } -- (BOOL)rulersVisible { return _rulersVisible; } -- (void)setLineScroll:(float)aFloat { _lineScroll = aFloat; } -- (float)lineScroll { return _lineScroll; } -- (void)setPageScroll:(float)aFloat { _pageScroll = aFloat; } -- (float)pageScroll { return _pageScroll; } -- (void)setScrollsDynamically:(BOOL)flag { _scrollsDynamically = flag; } -- (BOOL)scrollsDynamically { return _scrollsDynamically; } -- (NSScroller*)horizontalScroller { return _horizScroller; } -- (BOOL)hasHorizontalScroller { return _hasHorizScroller; } +- (NSCursor*) documentCursor +{ + return [_contentView documentCursor]; +} + +- (void) setDocumentCursor: (NSCursor*)aCursor +{ + [_contentView setDocumentCursor: aCursor]; +} + +- (BOOL) isOpaque +{ + return YES; +} + +- (NSBorderType) borderType +{ + return _borderType; +} + +- (BOOL) hasVerticalScroller +{ + return _hasVertScroller; +} + +- (BOOL) hasHorizontalRuler +{ + return _hasHorizRuler; +} + +- (NSSize) contentSize +{ + return [_contentView bounds].size; +} + +- (NSView*) contentView +{ + return _contentView; +} + +- (NSRulerView*) horizontalRulerView +{ + return _horizRuler; +} + +- (BOOL) hasVerticalRuler +{ + return _hasVertRuler; +} + +- (NSRulerView*) verticalRulerView +{ + return _vertRuler; +} + +- (BOOL) rulersVisible +{ + return _rulersVisible; +} + +- (void) setLineScroll: (float)aFloat +{ + _lineScroll = aFloat; +} + +- (float) lineScroll +{ + return _lineScroll; +} + +- (void) setPageScroll: (float)aFloat +{ + _pageScroll = aFloat; +} + +- (float) pageScroll +{ + return _pageScroll; +} + +- (void) setScrollsDynamically: (BOOL)flag +{ + _scrollsDynamically = flag; +} + +- (BOOL) scrollsDynamically +{ + return _scrollsDynamically; +} + +- (NSScroller*) horizontalScroller +{ + return _horizScroller; +} + +- (BOOL) hasHorizontalScroller +{ + return _hasHorizScroller; +} @end diff --git a/Source/NSScroller.m b/Source/NSScroller.m index 0cf31d812..b6778d9c4 100644 --- a/Source/NSScroller.m +++ b/Source/NSScroller.m @@ -8,14 +8,14 @@ Date: July 1997 Author: Felipe A. Rodriguez Date: August 1998 - + This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -45,11 +45,11 @@ @implementation NSScroller // -// Class variables +// Class variables // -static NSButtonCell* upCell = nil; // button cells used by +static NSButtonCell* upCell = nil; // button cells used by static NSButtonCell* downCell = nil; // scroller instances -static NSButtonCell* leftCell = nil; // to draw scroller +static NSButtonCell* leftCell = nil; // to draw scroller static NSButtonCell* rightCell = nil; // buttons and knob. static NSButtonCell* knobCell = nil; @@ -57,7 +57,7 @@ static const float scrollerWidth = 17; static const float buttonsWidth = 16; static const float buttonsDistance = 1; -static float halfKnobRectHeight; +static float halfKnobRectHeight; static float slotOriginPlusKnobHeight; static float slotOriginPlusSlotHeightMinusKnobHeight; static float slotHeightMinusKnobHeight; @@ -69,774 +69,801 @@ static NSRect slotRect = {{0,0},{0,0}}; static BOOL preCalcValues = NO; // -// Class methods +// Class methods // -+ (void)initialize ++ (void) initialize { - if (self == [NSScroller class]) - [self setVersion:1]; + if (self == [NSScroller class]) + [self setVersion: 1]; } -+ (float)scrollerWidth { return scrollerWidth; } -- (NSScrollArrowPosition)arrowsPosition { return _arrowsPosition; } -- (NSUsableScrollerParts)usableParts { return _usableParts; } -- (float)knobProportion { return _knobProportion; } -- (NSScrollerPart)hitPart { return _hitPart; } -- (float)floatValue { return _floatValue; } -- (void)setAction:(SEL)action { _action = action; } -- (SEL)action { return _action; } -- (void)setTarget:(id)target { ASSIGN(_target, target); } -- (id)target { return _target; } -- (void)encodeWithCoder:aCoder { } -- initWithCoder:aDecoder { return self; } -- (BOOL)isOpaque { return YES; } - -- initWithFrame:(NSRect)frameRect ++ (float) scrollerWidth { - if (frameRect.size.width > frameRect.size.height) // determine the - { // orientation of - _isHorizontal = YES; // the scroller and - frameRect.size.height = [isa scrollerWidth]; // adjust it's size - } // accordingly - else - { - _isHorizontal = NO; - frameRect.size.width = [isa scrollerWidth]; - } - - [super initWithFrame:frameRect]; - - if (_isHorizontal) - _arrowsPosition = NSScrollerArrowsMinEnd; - else - _arrowsPosition = NSScrollerArrowsMaxEnd; - - _hitPart = NSScrollerNoPart; - [self drawParts]; - [self setEnabled:NO]; - [self checkSpaceForParts]; - - return self; + return scrollerWidth; } -- init +- (NSScrollArrowPosition) arrowsPosition { - return [self initWithFrame:NSZeroRect]; + return _arrowsPosition; } -- (void)drawParts -{ // Create the class variable - if (knobCell) // button cells if they do not - return; // yet exist. - - upCell = [NSButtonCell new]; - [upCell setHighlightsBy:NSChangeBackgroundCellMask|NSContentsCellMask]; - [upCell setImage:[NSImage imageNamed:@"common_ArrowUp"]]; - [upCell setAlternateImage:[NSImage imageNamed:@"common_ArrowUpH"]]; - [upCell setImagePosition:NSImageOnly]; - [upCell setContinuous:YES]; - [upCell setPeriodicDelay:0.05 interval:0.05]; - - downCell = [NSButtonCell new]; - [downCell setHighlightsBy:NSChangeBackgroundCellMask|NSContentsCellMask]; - [downCell setImage:[NSImage imageNamed:@"common_ArrowDown"]]; - [downCell setAlternateImage:[NSImage imageNamed:@"common_ArrowDownH"]]; - [downCell setImagePosition:NSImageOnly]; - [downCell setContinuous:YES]; - [downCell setPeriodicDelay:0.05 interval:0.05]; - - leftCell = [NSButtonCell new]; - [leftCell setHighlightsBy:NSChangeBackgroundCellMask|NSContentsCellMask]; - [leftCell setImage:[NSImage imageNamed:@"common_ArrowLeft"]]; - [leftCell setAlternateImage:[NSImage imageNamed:@"common_ArrowLeftH"]]; - [leftCell setImagePosition:NSImageOnly]; - [leftCell setContinuous:YES]; - [leftCell setPeriodicDelay:0.05 interval:0.05]; - - rightCell = [NSButtonCell new]; - [rightCell setHighlightsBy:NSChangeBackgroundCellMask|NSContentsCellMask]; - [rightCell setImage:[NSImage imageNamed:@"common_ArrowRight"]]; - [rightCell setAlternateImage:[NSImage imageNamed:@"common_ArrowRightH"]]; - [rightCell setImagePosition:NSImageOnly]; - [rightCell setContinuous:YES]; - [rightCell setPeriodicDelay:0.05 interval:0.05]; - - knobCell = [NSButtonCell new]; - [knobCell setButtonType:NSMomentaryChangeButton]; - [knobCell setImage:[NSImage imageNamed:@"common_Dimple"]]; - [knobCell setImagePosition:NSImageOnly]; -} - -- (void)_setTargetAndActionToCells +- (NSUsableScrollerParts) usableParts { - [upCell setTarget:_target]; - [upCell setAction:_action]; - - [downCell setTarget:_target]; - [downCell setAction:_action]; - - [leftCell setTarget:_target]; - [leftCell setAction:_action]; - - [rightCell setTarget:_target]; - [rightCell setAction:_action]; - - [knobCell setTarget:_target]; - [knobCell setAction:_action]; + return _usableParts; } -- (void)checkSpaceForParts +- (float) knobProportion { -NSSize frameSize = [self frame].size; -float size = (_isHorizontal ? frameSize.width : frameSize.height); -float scrollerWidth = [isa scrollerWidth]; - - if (size > 3 * scrollerWidth + 2) - _usableParts = NSAllScrollerParts; - else - if (size > 2 * scrollerWidth + 1) - _usableParts = NSOnlyScrollerArrows; - else - if (size > scrollerWidth) - _usableParts = NSNoScrollerParts; + return _knobProportion; } -- (void)setEnabled:(BOOL)flag +- (NSScrollerPart) hitPart { - if (_isEnabled == flag) - return; - - _isEnabled = flag; - [self setNeedsDisplay:YES]; + return _hitPart; } -- (void)setArrowsPosition:(NSScrollArrowPosition)where +- (float) floatValue { - if (_arrowsPosition == where) - return; - - _arrowsPosition = where; - [self setNeedsDisplay:YES]; + return _floatValue; } -- (void)setFloatValue:(float)aFloat +- (void) setAction: (SEL)action { - if (aFloat < 0) - _floatValue = 0; - else - if (aFloat > 1) - _floatValue = 1; - else - _floatValue = aFloat; - - [self setNeedsDisplayInRect:[self rectForPart:NSScrollerKnobSlot]]; + _action = action; } -- (void)setFloatValue:(float)aFloat knobProportion:(float)ratio +- (SEL) action { - if (ratio < 0) - _knobProportion = 0; - else - if (ratio > 1) - _knobProportion = 1; - else - _knobProportion = ratio; - - [self setFloatValue:aFloat]; + return _action; } -- (void)setFrame:(NSRect)frameRect +- (void) setTarget: (id)target { - if (frameRect.size.width > frameRect.size.height) // determine the - { // orientation of - _isHorizontal = YES; // the scroller and - frameRect.size.height = [isa scrollerWidth]; // adjust it's size - } // accordingly - else - { - _isHorizontal = NO; - frameRect.size.width = [isa scrollerWidth]; - } - - [super setFrame:frameRect]; - - if (_isHorizontal) - _arrowsPosition = NSScrollerArrowsMinEnd; - else - _arrowsPosition = NSScrollerArrowsMaxEnd; - - _hitPart = NSScrollerNoPart; - [self checkSpaceForParts]; + ASSIGN(_target, target); } -- (void)setFrameSize:(NSSize)size +- (id) target { - [super setFrameSize:size]; - [self checkSpaceForParts]; - [self setNeedsDisplay:YES]; + return _target; } -- (NSScrollerPart)testPart:(NSPoint)thePoint // return what part -{ // of the scroller -NSRect rect; // the mouse hit - - if (thePoint.x < 0 || thePoint.x > frame.size.width - || thePoint.y < 0 || thePoint.y > frame.size.height) - return NSScrollerNoPart; - - rect = [self rectForPart:NSScrollerDecrementLine]; - if ([self mouse:thePoint inRect:rect]) - return NSScrollerDecrementLine; - - rect = [self rectForPart:NSScrollerIncrementLine]; - if ([self mouse:thePoint inRect:rect]) - return NSScrollerIncrementLine; - - rect = [self rectForPart:NSScrollerKnob]; - if ([self mouse:thePoint inRect:rect]) - return NSScrollerKnob; - - rect = [self rectForPart:NSScrollerKnobSlot]; - if ([self mouse:thePoint inRect:rect]) - return NSScrollerKnobSlot; - - rect = [self rectForPart:NSScrollerDecrementPage]; - if ([self mouse:thePoint inRect:rect]) - return NSScrollerDecrementPage; - - rect = [self rectForPart:NSScrollerIncrementPage]; - if ([self mouse:thePoint inRect:rect]) - return NSScrollerIncrementPage; - - return NSScrollerNoPart; -} - -- (float)_floatValueForMousePoint:(NSPoint)point +- (void) encodeWithCoder: (NSCoder*)aCoder { -NSRect knobRect = [self rectForPart:NSScrollerKnob]; -NSRect slotRect = [self rectForPart:NSScrollerKnobSlot]; -float floatValue = 0; -float position; +} - if (_isHorizontal) // Adjust point to lie - { // within the knob slot - float halfKnobRectWidth = knobRect.size.width / 2; +- (id) initWithCoder: (NSCoder*)aDecoder +{ + return self; +} - if (point.x < slotRect.origin.x + halfKnobRectWidth) - position = slotRect.origin.x + halfKnobRectWidth; - else - { - if (point.x > slotRect.origin.x + slotRect.size.width - +- (BOOL) isOpaque +{ + return YES; +} + +- (id) initWithFrame: (NSRect)frameRect +{ + // determine the orientation of the scroller and adjust it's size accordingly + if (frameRect.size.width > frameRect.size.height) + { + _isHorizontal = YES; + frameRect.size.height = [isa scrollerWidth]; + } + else + { + _isHorizontal = NO; + frameRect.size.width = [isa scrollerWidth]; + } + + [super initWithFrame: frameRect]; + + if (_isHorizontal) + _arrowsPosition = NSScrollerArrowsMinEnd; + else + _arrowsPosition = NSScrollerArrowsMaxEnd; + + _hitPart = NSScrollerNoPart; + [self drawParts]; + [self setEnabled: NO]; + [self checkSpaceForParts]; + + return self; +} + +- (id) init +{ + return [self initWithFrame: NSZeroRect]; +} + +- (void) drawParts +{ + // Create the class variable button cells if they do not yet exist. + if (knobCell) + return; + + upCell = [NSButtonCell new]; + [upCell setHighlightsBy: NSChangeBackgroundCellMask|NSContentsCellMask]; + [upCell setImage: [NSImage imageNamed: @"common_ArrowUp"]]; + [upCell setAlternateImage: [NSImage imageNamed: @"common_ArrowUpH"]]; + [upCell setImagePosition: NSImageOnly]; + [upCell setContinuous: YES]; + [upCell setPeriodicDelay: 0.05 interval: 0.05]; + + downCell = [NSButtonCell new]; + [downCell setHighlightsBy: NSChangeBackgroundCellMask|NSContentsCellMask]; + [downCell setImage: [NSImage imageNamed: @"common_ArrowDown"]]; + [downCell setAlternateImage: [NSImage imageNamed: @"common_ArrowDownH"]]; + [downCell setImagePosition: NSImageOnly]; + [downCell setContinuous: YES]; + [downCell setPeriodicDelay: 0.05 interval: 0.05]; + + leftCell = [NSButtonCell new]; + [leftCell setHighlightsBy: NSChangeBackgroundCellMask|NSContentsCellMask]; + [leftCell setImage: [NSImage imageNamed: @"common_ArrowLeft"]]; + [leftCell setAlternateImage: [NSImage imageNamed: @"common_ArrowLeftH"]]; + [leftCell setImagePosition: NSImageOnly]; + [leftCell setContinuous: YES]; + [leftCell setPeriodicDelay: 0.05 interval: 0.05]; + + rightCell = [NSButtonCell new]; + [rightCell setHighlightsBy: NSChangeBackgroundCellMask|NSContentsCellMask]; + [rightCell setImage: [NSImage imageNamed: @"common_ArrowRight"]]; + [rightCell setAlternateImage: [NSImage imageNamed: @"common_ArrowRightH"]]; + [rightCell setImagePosition: NSImageOnly]; + [rightCell setContinuous: YES]; + [rightCell setPeriodicDelay: 0.05 interval: 0.05]; + + knobCell = [NSButtonCell new]; + [knobCell setButtonType: NSMomentaryChangeButton]; + [knobCell setImage: [NSImage imageNamed: @"common_Dimple"]]; + [knobCell setImagePosition: NSImageOnly]; +} + +- (void) _setTargetAndActionToCells +{ + [upCell setTarget: _target]; + [upCell setAction: _action]; + + [downCell setTarget: _target]; + [downCell setAction: _action]; + + [leftCell setTarget: _target]; + [leftCell setAction: _action]; + + [rightCell setTarget: _target]; + [rightCell setAction: _action]; + + [knobCell setTarget: _target]; + [knobCell setAction: _action]; +} + +- (void) checkSpaceForParts +{ + NSSize frameSize = [self frame].size; + float size = (_isHorizontal ? frameSize.width : frameSize.height); + float scrollerWidth = [isa scrollerWidth]; + + if (size > 3 * scrollerWidth + 2) + _usableParts = NSAllScrollerParts; + else if (size > 2 * scrollerWidth + 1) + _usableParts = NSOnlyScrollerArrows; + else + _usableParts = NSNoScrollerParts; +} + +- (void) setEnabled: (BOOL)flag +{ + if (_isEnabled == flag) + return; + + _isEnabled = flag; + [self setNeedsDisplay: YES]; +} + +- (void) setArrowsPosition: (NSScrollArrowPosition)where +{ + if (_arrowsPosition == where) + return; + + _arrowsPosition = where; + [self setNeedsDisplay: YES]; +} + +- (void) setFloatValue: (float)aFloat +{ + if (aFloat == _floatValue) + return; + + if (aFloat < 0) + _floatValue = 0; + else if (aFloat > 1) + _floatValue = 1; + else + _floatValue = aFloat; + + [self setNeedsDisplayInRect: [self rectForPart: NSScrollerKnobSlot]]; +} + +- (void) setFloatValue: (float)aFloat knobProportion: (float)ratio +{ + if (ratio < 0) + _knobProportion = 0; + else if (ratio > 1) + _knobProportion = 1; + else + _knobProportion = ratio; + + [self setFloatValue: aFloat]; +} + +- (void) setFrame: (NSRect)frameRect +{ + // determine the orientation of the scroller and adjust it's size accordingly + if (frameRect.size.width > frameRect.size.height) + { + _isHorizontal = YES; + frameRect.size.height = [isa scrollerWidth]; + } + else + { + _isHorizontal = NO; + frameRect.size.width = [isa scrollerWidth]; + } + + [super setFrame: frameRect]; + + if (_isHorizontal) + _arrowsPosition = NSScrollerArrowsMinEnd; + else + _arrowsPosition = NSScrollerArrowsMaxEnd; + + _hitPart = NSScrollerNoPart; + [self checkSpaceForParts]; +} + +- (void) setFrameSize: (NSSize)size +{ + [super setFrameSize: size]; + [self checkSpaceForParts]; + [self setNeedsDisplay: YES]; +} + +- (NSScrollerPart)testPart: (NSPoint)thePoint +{ + // return what part of the scroller the mouse hit + NSRect rect; + + if (thePoint.x < 0 || thePoint.x > frame.size.width + || thePoint.y < 0 || thePoint.y > frame.size.height) + return NSScrollerNoPart; + + rect = [self rectForPart: NSScrollerDecrementLine]; + if ([self mouse: thePoint inRect: rect]) + return NSScrollerDecrementLine; + + rect = [self rectForPart: NSScrollerIncrementLine]; + if ([self mouse: thePoint inRect: rect]) + return NSScrollerIncrementLine; + + rect = [self rectForPart: NSScrollerKnob]; + if ([self mouse: thePoint inRect: rect]) + return NSScrollerKnob; + + rect = [self rectForPart: NSScrollerKnobSlot]; + if ([self mouse: thePoint inRect: rect]) + return NSScrollerKnobSlot; + + rect = [self rectForPart: NSScrollerDecrementPage]; + if ([self mouse: thePoint inRect: rect]) + return NSScrollerDecrementPage; + + rect = [self rectForPart: NSScrollerIncrementPage]; + if ([self mouse: thePoint inRect: rect]) + return NSScrollerIncrementPage; + + return NSScrollerNoPart; +} + +- (float) _floatValueForMousePoint: (NSPoint)point +{ + NSRect knobRect = [self rectForPart: NSScrollerKnob]; + NSRect slotRect = [self rectForPart: NSScrollerKnobSlot]; + float floatValue = 0; + float position; + + // Adjust point to lie within the knob slot + if (_isHorizontal) + { + float halfKnobRectWidth = knobRect.size.width / 2; + + if (point.x < slotRect.origin.x + halfKnobRectWidth) + position = slotRect.origin.x + halfKnobRectWidth; + else + { + if (point.x > slotRect.origin.x + slotRect.size.width - halfKnobRectWidth) - position = slotRect.origin.x + slotRect.size.width - + position = slotRect.origin.x + slotRect.size.width - halfKnobRectWidth; - else - position = point.x; - } // Compute float value - // given the knob size - floatValue = (position - (slotRect.origin.x + halfKnobRectWidth)) - / (slotRect.size.width - knobRect.size.width); - } - else // Adjust point to lie - { // within the knob slot - float halfKnobRectHeight = knobRect.size.height / 2; + else + position = point.x; + } + // Compute float value given the knob size + floatValue = (position - (slotRect.origin.x + halfKnobRectWidth)) + / (slotRect.size.width - knobRect.size.width); + } + else + { + float halfKnobRectHeight = knobRect.size.height / 2; - if (point.y < slotRect.origin.y + halfKnobRectHeight) - position = slotRect.origin.y + halfKnobRectHeight; - else - { - if (point.y > slotRect.origin.y + slotRect.size.height - - halfKnobRectHeight) - position = slotRect.origin.y + slotRect.size.height - - halfKnobRectHeight; - else - position = point.y; - } - // Compute float value - floatValue = (position - (slotRect.origin.y + halfKnobRectHeight)) / - (slotRect.size.height - knobRect.size.height); - floatValue = 1 - floatValue; - } + if (point.y < slotRect.origin.y + halfKnobRectHeight) + position = slotRect.origin.y + halfKnobRectHeight; + else + { + if (point.y > slotRect.origin.y + slotRect.size.height - + halfKnobRectHeight) + position = slotRect.origin.y + slotRect.size.height - + halfKnobRectHeight; + else + position = point.y; + } + // Compute float value given the knob size + floatValue = (position - (slotRect.origin.y + halfKnobRectHeight)) / + (slotRect.size.height - knobRect.size.height); + floatValue = 1 - floatValue; + } - return floatValue; + return floatValue; } -- (void)_preCalcParts // pre calculate -{ // values to lessen -NSRect knobRect = [self rectForPart:NSScrollerKnob]; // the burden while - // scrolling - slotRect = [self rectForPart:NSScrollerKnobSlot]; - - halfKnobRectWidth = knobRect.size.width / 2; - slotOriginPlusKnobWidth = slotRect.origin.x + halfKnobRectWidth; - slotOriginPlusSlotWidthMinusHalfKnobWidth = slotRect.origin.x + - slotRect.size.width - halfKnobRectWidth; - slotWidthMinusKnobWidth = slotRect.size.width - knobRect.size.width; - - halfKnobRectHeight = knobRect.size.height / 2; - slotOriginPlusKnobHeight = slotRect.origin.y + halfKnobRectHeight; - slotOriginPlusSlotHeightMinusKnobHeight = slotRect.origin.y + - slotRect.size.height - halfKnobRectHeight; - slotHeightMinusKnobHeight = slotRect.size.height - knobRect.size.height; -} - -- (float)_floatValueForMousePointFromPreCalc:(NSPoint)point -{ -float floatValue = 0; -float position; - - if (_isHorizontal) // Adjust point to lie - { // within the knob slot - if (point.x < slotOriginPlusKnobWidth) - position = slotOriginPlusKnobWidth; - else - { - if (point.x > slotOriginPlusSlotWidthMinusHalfKnobWidth) - position = slotOriginPlusSlotWidthMinusHalfKnobWidth; - else - position = point.x; - } // Compute float value - // given the knob size - floatValue = (position - slotOriginPlusKnobWidth) / - slotWidthMinusKnobWidth; - } - else // Adjust point to lie - { // within the knob slot - if (point.y < slotOriginPlusKnobHeight) - position = slotOriginPlusKnobHeight; - else - { - if (point.y > slotOriginPlusSlotHeightMinusKnobHeight) - position = slotOriginPlusSlotHeightMinusKnobHeight; - else - position = point.y; - } - // Compute float value - floatValue = (position - slotOriginPlusKnobHeight) / - slotHeightMinusKnobHeight; - floatValue = 1 - floatValue; - } - - return floatValue; -} - -- (void)mouseDown:(NSEvent*)theEvent +- (void) _preCalcParts { -NSPoint location = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; + NSRect knobRect = [self rectForPart: NSScrollerKnob]; - [self lockFocus]; - _hitPart = [self testPart:location]; - [self _setTargetAndActionToCells]; - - switch (_hitPart) + slotRect = [self rectForPart: NSScrollerKnobSlot]; + halfKnobRectWidth = knobRect.size.width / 2; + slotOriginPlusKnobWidth = slotRect.origin.x + halfKnobRectWidth; + slotOriginPlusSlotWidthMinusHalfKnobWidth = slotRect.origin.x + + slotRect.size.width - halfKnobRectWidth; + slotWidthMinusKnobWidth = slotRect.size.width - knobRect.size.width; + + halfKnobRectHeight = knobRect.size.height / 2; + slotOriginPlusKnobHeight = slotRect.origin.y + halfKnobRectHeight; + slotOriginPlusSlotHeightMinusKnobHeight = slotRect.origin.y + + slotRect.size.height - halfKnobRectHeight; + slotHeightMinusKnobHeight = slotRect.size.height - knobRect.size.height; +} + +- (float) _floatValueForMousePointFromPreCalc: (NSPoint)point +{ + float floatValue = 0; + float position; + + if (_isHorizontal) + { + if (point.x < slotOriginPlusKnobWidth) + position = slotOriginPlusKnobWidth; + else + { + if (point.x > slotOriginPlusSlotWidthMinusHalfKnobWidth) + position = slotOriginPlusSlotWidthMinusHalfKnobWidth; + else + position = point.x; + } + floatValue = (position - slotOriginPlusKnobWidth) / + slotWidthMinusKnobWidth; + } + else + { + if (point.y < slotOriginPlusKnobHeight) + position = slotOriginPlusKnobHeight; + else + { + if (point.y > slotOriginPlusSlotHeightMinusKnobHeight) + position = slotOriginPlusSlotHeightMinusKnobHeight; + else + position = point.y; + } + + floatValue = (position - slotOriginPlusKnobHeight) / + slotHeightMinusKnobHeight; + floatValue = 1 - floatValue; + } + + return floatValue; +} + +- (void) mouseDown: (NSEvent*)theEvent +{ + NSPoint location = [self convertPoint: [theEvent locationInWindow] + fromView: nil]; + + _hitPart = [self testPart: location]; + [self _setTargetAndActionToCells]; + + switch (_hitPart) + { + case NSScrollerIncrementLine: + case NSScrollerDecrementLine: + case NSScrollerIncrementPage: + case NSScrollerDecrementPage: + [self trackScrollButtons: theEvent]; + break; + + case NSScrollerKnob: + [self trackKnob: theEvent]; + break; + + case NSScrollerKnobSlot: + { + float floatValue = [self _floatValueForMousePoint: location]; + + [self setFloatValue: floatValue]; + [self sendAction: _action to: _target]; + [self trackKnob: theEvent]; + break; + } + + case NSScrollerNoPart: + break; + } + + _hitPart = NSScrollerNoPart; +} + +- (void)trackKnob: (NSEvent*)theEvent +{ + unsigned int eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask + | NSLeftMouseDraggedMask | NSMouseMovedMask + | NSPeriodicMask; + NSApplication *app = [NSApplication sharedApplication]; + NSPoint point, apoint; + float oldFloatValue = _floatValue; + float floatValue; + NSDate *theDistantFuture = [NSDate distantFuture]; + PSMatrix* matrix; + NSEventType eventType; + NSRect knobRect = {{0,0},{0,0}}; + int periodCount = 0; // allows a forced update + NSMutableArray* path = [self _pathBetweenSubview: self + toSuperview: [window contentView]]; + + [path addObject: [window contentView]]; + matrix = [self _concatenateMatricesInReverseOrderFromPath: path]; + [matrix inverse]; + + //fprintf(stderr, " trackKnob \n"); + + [self _preCalcParts]; // pre calc scroller parts + preCalcValues = YES; + + _hitPart = NSScrollerKnob; + // set periodic events rate to achieve max of ~30fps + [NSEvent startPeriodicEventsAfterDelay: 0.02 withPeriod: 0.03]; + [[NSRunLoop currentRunLoop] limitDateForMode: NSEventTrackingRunLoopMode]; + + while ((eventType = [theEvent type]) != NSLeftMouseUp) + { + if (eventType != NSPeriodic) + { + apoint = [theEvent locationInWindow]; + // zero the periodic count whenever a real position event is recieved + periodCount = 0; + } + else + { + // if 6x periods have gone by w/o movement + // check mouse and update if necessary + if (periodCount == 6) + apoint = [window mouseLocationOutsideOfEventStream]; + + point = [matrix pointInMatrixSpace: apoint]; + + if (point.x != knobRect.origin.x || point.y != knobRect.origin.y) + { + floatValue = [self _floatValueForMousePointFromPreCalc: point]; + + if (floatValue != oldFloatValue) { - case NSScrollerIncrementLine: - case NSScrollerDecrementLine: - case NSScrollerIncrementPage: - case NSScrollerDecrementPage: - [self trackScrollButtons:theEvent]; - break; - - case NSScrollerKnob: - [self trackKnob:theEvent]; - break; - - case NSScrollerKnobSlot: - { - float floatValue = [self _floatValueForMousePoint:location]; - - [self setFloatValue:floatValue]; - [self sendAction:_action to:_target]; - [self drawKnobSlot]; - [self drawKnob]; - [window flushWindow]; - [self trackKnob:theEvent]; - break; - } - - case NSScrollerNoPart: - break; + [self setFloatValue: floatValue]; + [self sendAction: _action to: _target]; + + oldFloatValue = floatValue; + [window update]; } - - _hitPart = NSScrollerNoPart; - [self unlockFocus]; + knobRect.origin = point; + } + // avoid timing related scrolling hesitation by counting number of + // periodic events since scroll pos was updated, when this reaches + // 6x periodic rate an update is forced on next periodic event + periodCount++; + } + + theEvent = [app nextEventMatchingMask: eventMask + untilDate: theDistantFuture + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; + } + [NSEvent stopPeriodicEvents]; + + preCalcValues = NO; } -- (void)trackKnob:(NSEvent*)theEvent +- (void) trackScrollButtons: (NSEvent*)theEvent { -unsigned int eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask - | NSLeftMouseDraggedMask | NSMouseMovedMask - | NSPeriodicMask; -NSApplication *app = [NSApplication sharedApplication]; -NSPoint point, apoint; -float oldFloatValue = _floatValue; -float floatValue; -NSDate *theDistantFuture = [NSDate distantFuture]; -PSMatrix* matrix; -NSEventType eventType; -NSRect knobRect = {{0,0},{0,0}}; -int periodCount = 0; // allows a forced update -NSMutableArray* path = [self _pathBetweenSubview:self - toSuperview:[window contentView]]; + NSApplication *theApp = [NSApplication sharedApplication]; + unsigned int eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask | + NSLeftMouseDraggedMask | NSMouseMovedMask; + NSPoint location; + BOOL shouldReturn = NO; + id theCell = nil; + NSRect rect; - [path addObject: [window contentView]]; - matrix = [self _concatenateMatricesInReverseOrderFromPath:path]; - [matrix inverse]; + NSDebugLog (@"trackScrollButtons"); + do + { + location = [self convertPoint: [theEvent locationInWindow]fromView: nil]; + _hitPart = [self testPart: location]; + rect = [self rectForPart: _hitPart]; -//fprintf(stderr, " trackKnob \n"); + switch (_hitPart) + { + case NSScrollerIncrementLine: + case NSScrollerIncrementPage: + theCell = (_isHorizontal ? rightCell : upCell); + break; - [self _preCalcParts]; // pre calc scroller parts - preCalcValues = YES; + case NSScrollerDecrementLine: + case NSScrollerDecrementPage: + theCell = (_isHorizontal ? leftCell : downCell); + break; - _hitPart = NSScrollerKnob; // set periodic events rate - // to achieve max of ~30fps - [NSEvent startPeriodicEventsAfterDelay:0.02 withPeriod:0.03]; - [[NSRunLoop currentRunLoop] limitDateForMode:NSEventTrackingRunLoopMode]; + default: + theCell = nil; + break; + } - while ((eventType = [theEvent type]) != NSLeftMouseUp) - { // user is moving scroller - if (eventType != NSPeriodic) // loop until left mouse up - { - apoint = [theEvent locationInWindow]; // zero the periodic count - periodCount = 0; // whenever a real position - } // event is recieved - else - { // if 6x periods have gone by w/o movement - if(periodCount == 6) // check mouse and update if necessary - apoint = [window mouseLocationOutsideOfEventStream]; + if (theCell) + { + [self lockFocus]; + [theCell highlight: YES withFrame: rect inView: self]; + [self unlockFocus]; + [window flushWindow]; - point = [matrix pointInMatrixSpace:apoint]; + NSLog (@"tracking cell %x", theCell); - if (point.x != knobRect.origin.x || point.y != knobRect.origin.y) - { - floatValue = [self _floatValueForMousePointFromPreCalc:point]; + shouldReturn = [theCell trackMouse: theEvent + inRect: rect + ofView: self + untilMouseUp: YES]; - if (floatValue != oldFloatValue) - { - if (floatValue < 0) - _floatValue = 0; - else - { - if (floatValue > 1) - _floatValue = 1; - else - _floatValue = floatValue; - } + [self lockFocus]; + [theCell highlight: NO withFrame: rect inView: self]; + [self unlockFocus]; + [window flushWindow]; + } - [self drawKnobSlot]; // draw the scroller slot - [self drawKnob]; // draw the scroller knob - [_target performSelector:_action withObject:self]; - [window flushWindow]; + if (shouldReturn) + break; - oldFloatValue = floatValue; - } // avoid timing related scrolling - // hesitation by counting number of - knobRect.origin = point; // periodic events since scroll pos - } // was updated, when this reaches - periodCount++; // 6x periodic rate an update is - } // forced on next periodic event - theEvent = [app nextEventMatchingMask:eventMask - untilDate:theDistantFuture - inMode:NSEventTrackingRunLoopMode - dequeue:YES]; - } - [NSEvent stopPeriodicEvents]; + theEvent = [theApp nextEventMatchingMask: eventMask + untilDate: [NSDate distantFuture] + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; + } + while ([theEvent type] != NSLeftMouseUp); - if([_target isKindOf:[NSScrollView class]]) // hack for XRAW FIX ME - { - NSObject *targetCV = (NSObject *)[_target contentView]; - - if([targetCV respondsToSelector:@selector(_freeMatrix)]) - [targetCV _freeMatrix]; - } - - preCalcValues = NO; + NSDebugLog (@"return from trackScrollButtons"); } -- (void)trackScrollButtons:(NSEvent*)theEvent -{ -NSApplication *theApp = [NSApplication sharedApplication]; -unsigned int eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask | - NSLeftMouseDraggedMask | NSMouseMovedMask; -NSPoint location; -BOOL shouldReturn = NO; -id theCell = nil; -NSRect rect; - - NSDebugLog (@"trackScrollButtons"); - do { - location = [self convertPoint:[theEvent locationInWindow]fromView:nil]; - _hitPart = [self testPart:location]; - rect = [self rectForPart:_hitPart]; - - switch (_hitPart) // determine which - { // cell was hit - case NSScrollerIncrementLine: - case NSScrollerIncrementPage: - theCell = (_isHorizontal ? rightCell : upCell); - break; - - case NSScrollerDecrementLine: - case NSScrollerDecrementPage: - theCell = (_isHorizontal ? leftCell : downCell); - break; - - default: - theCell = nil; - break; - } - - if (theCell) - { - [theCell highlight:YES withFrame:rect inView:self]; - [window flushWindow]; - - NSLog (@"tracking cell %x", theCell); - - shouldReturn = [theCell trackMouse:theEvent // Track the mouse - inRect:rect // until left mouse - ofView:self // goes up - untilMouseUp:YES]; - - if([_target isKindOf:[NSScrollView class]]) // a hack for XRAW - { // FIX ME - NSObject *targetCV = (NSObject *)[_target contentView]; - - if([targetCV respondsToSelector:@selector(_freeMatrix)]) - [targetCV _freeMatrix]; - } - - [theCell highlight:NO withFrame:rect inView:self]; - [window flushWindow]; - } - - if (shouldReturn) - break; - - theEvent = [theApp nextEventMatchingMask:eventMask - untilDate:[NSDate distantFuture] - inMode:NSEventTrackingRunLoopMode - dequeue:YES]; - } - while ([theEvent type] != NSLeftMouseUp); - - NSDebugLog (@"return from trackScrollButtons"); -} - -- (BOOL)sendActionO:(SEL)theAction to:(id)theTarget -{ // send action to -BOOL ret = [super sendAction:theAction to:theTarget]; // the target on - // behalf of cell - [self drawKnobSlot]; // lockFocus set in mouseDown method is - [self drawKnob]; // active so we simply redraw the knob and - [window flushWindow]; // slot to reflect the hit scroll button - - return ret; -} - // // draw the scroller // -- (void)drawRect:(NSRect)rect +- (void) drawRect: (NSRect)rect { - NSDebugLog (@"NSScroller drawRect: ((%f, %f), (%f, %f))", - rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); - - [self drawArrow:NSScrollerDecrementArrow highlight:NO]; - [self drawArrow:NSScrollerIncrementArrow highlight:NO]; - - [self drawKnobSlot]; - [self drawKnob]; + NSDebugLog (@"NSScroller drawRect: ((%f, %f), (%f, %f))", + rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); + + [self drawArrow: NSScrollerDecrementArrow highlight: NO]; + [self drawArrow: NSScrollerIncrementArrow highlight: NO]; + + [self drawKnobSlot]; + [self drawKnob]; } -- (void)drawArrow:(NSScrollerArrow)whichButton highlight:(BOOL)flag +- (void) drawArrow: (NSScrollerArrow)whichButton highlight: (BOOL)flag { -NSRect rect = [self rectForPart:(whichButton == NSScrollerIncrementArrow - ? NSScrollerIncrementLine : NSScrollerDecrementLine)]; -id theCell = nil; + NSRect rect = [self rectForPart: (whichButton == NSScrollerIncrementArrow + ? NSScrollerIncrementLine : NSScrollerDecrementLine)]; + id theCell = nil; - NSDebugLog (@"position of %s cell is (%f, %f)", - (whichButton == NSScrollerIncrementArrow ? "increment" : "decrement"), - rect.origin.x, rect.origin.y); - - switch (whichButton) - { - case NSScrollerDecrementArrow: - theCell = (_isHorizontal ? leftCell : downCell); - break; - case NSScrollerIncrementArrow: - theCell = (_isHorizontal ? rightCell : upCell); - break; - } - - [theCell drawWithFrame:rect inView:self]; + NSDebugLog (@"position of %s cell is (%f, %f)", + (whichButton == NSScrollerIncrementArrow ? "increment" : "decrement"), + rect.origin.x, rect.origin.y); + + switch (whichButton) + { + case NSScrollerDecrementArrow: + theCell = (_isHorizontal ? leftCell : downCell); + break; + case NSScrollerIncrementArrow: + theCell = (_isHorizontal ? rightCell : upCell); + break; + } + + [theCell drawWithFrame: rect inView: self]; } -- (void)drawKnob +- (void) drawKnob { - [knobCell drawWithFrame:[self rectForPart:NSScrollerKnob] inView:self]; + [knobCell drawWithFrame: [self rectForPart: NSScrollerKnob] inView: self]; } -- (void)drawKnobSlot +- (void) drawKnobSlot { -NSRect rect; + NSRect rect; - if(preCalcValues) // in a modal loop we - rect = slotRect; // have already pre - else // calc'd our parts - rect = [self rectForPart:NSScrollerKnobSlot]; + // in a modal loop we have already pre calc'd our parts + if (preCalcValues) + rect = slotRect; + else + rect = [self rectForPart: NSScrollerKnobSlot]; - [[NSColor darkGrayColor] set]; - NSRectFill(rect); // draw the bar slot + [[NSColor darkGrayColor] set]; + NSRectFill(rect); } -- (NSRect)rectForPart:(NSScrollerPart)partCode +- (NSRect)rectForPart: (NSScrollerPart)partCode { -NSRect scrollerFrame = frame; -float x = 1, y = 1, width = 0, height = 0, floatValue; -NSScrollArrowPosition arrowsPosition; -NSUsableScrollerParts usableParts; - // If the scroller is disabled then - if (!_isEnabled) // the scroller buttons and the - usableParts = NSNoScrollerParts; // knob are not displayed at all. + NSRect scrollerFrame = frame; + float x = 1, y = 1, width = 0, height = 0, floatValue; + NSScrollArrowPosition arrowsPosition; + NSUsableScrollerParts usableParts; + // If the scroller is disabled then the scroller buttons and the + // knob are not displayed at all. + if (!_isEnabled) + usableParts = NSNoScrollerParts; + else + usableParts = _usableParts; + + // Since we haven't yet flipped views we have + // to swap the meaning of the arrows position + // if the scroller's orientation is vertical. + if (!_isHorizontal) + { + if (_arrowsPosition == NSScrollerArrowsMaxEnd) + arrowsPosition = NSScrollerArrowsMinEnd; + else + { + if (_arrowsPosition == NSScrollerArrowsMinEnd) + arrowsPosition = NSScrollerArrowsMaxEnd; + else + arrowsPosition = NSScrollerArrowsNone; + } + } + else + arrowsPosition = _arrowsPosition; + + // Assign to `width' and `height' values describing + // the width and height of the scroller regardless + // of its orientation. Also compute the `floatValue' + // which is essentially the same width as _floatValue + // but keeps track of the scroller's orientation. + if (_isHorizontal) + { + width = scrollerFrame.size.height; + height = scrollerFrame.size.width; + floatValue = _floatValue; + } + else + { + width = scrollerFrame.size.width; + height = scrollerFrame.size.height; + floatValue = 1 - _floatValue; + } + // The x, y, width and height values are computed below for the vertical + // scroller. The height of the scroll buttons is assumed to be equal to + // the width. + switch (partCode) + { + case NSScrollerKnob: + { + float knobHeight, knobPosition, slotHeight; + // If the scroller does not have parts or a knob return a zero rect. + if (usableParts == NSNoScrollerParts || + usableParts == NSOnlyScrollerArrows) + return NSZeroRect; + // calc the slot Height + slotHeight = height - (arrowsPosition == NSScrollerArrowsNone ? + 0 : 2 * (buttonsWidth + buttonsDistance)); + if (_isHorizontal) + slotHeight -= 2; + knobHeight = _knobProportion * slotHeight; + if (knobHeight < buttonsWidth) + knobHeight = buttonsWidth; + // calc knob's position + knobPosition = floatValue * (slotHeight - knobHeight); + knobPosition = (float)floor(knobPosition); // avoid rounding error + // calc actual position + y = knobPosition + (arrowsPosition == NSScrollerArrowsMaxEnd + || arrowsPosition == NSScrollerArrowsNone ? + 0 : 2 * (buttonsWidth + buttonsDistance)); + height = knobHeight; + width = buttonsWidth; + if (_isHorizontal) // keeps horiz knob off of the buttons + y++; + break; + } + + case NSScrollerKnobSlot: + // if the scroller does not have buttons the slot completely + // fills the scroller. + x = 0; + width = scrollerWidth; + if (usableParts == NSNoScrollerParts) + { + y = 0; // `height' unchanged + break; + } + if (arrowsPosition == NSScrollerArrowsMaxEnd) + { + y = 0; + height -= 2 * (buttonsWidth + buttonsDistance) + 1; + } else - usableParts = _usableParts; + { + if (arrowsPosition == NSScrollerArrowsMinEnd) + { + y = 2 * (buttonsWidth + buttonsDistance) + 1; + height -= y; + } + else + y = 0; // `height' unchanged + } + break; - // Since we haven't yet flipped views we have - if (!_isHorizontal) // to swap the meaning of the arrows position - { // if the scroller's orientation is vertical. - if (_arrowsPosition == NSScrollerArrowsMaxEnd) - arrowsPosition = NSScrollerArrowsMinEnd; - else - { - if (_arrowsPosition == NSScrollerArrowsMinEnd) - arrowsPosition = NSScrollerArrowsMaxEnd; - else - arrowsPosition = NSScrollerArrowsNone; - } - } + case NSScrollerDecrementLine: + case NSScrollerDecrementPage: + // if scroller has no parts or knob then return a zero rect + if (usableParts == NSNoScrollerParts) + return NSZeroRect; + width = buttonsWidth; + if (arrowsPosition == NSScrollerArrowsMaxEnd) + y = height - 2 * (buttonsWidth + buttonsDistance); else - arrowsPosition = _arrowsPosition; + { + if (arrowsPosition == NSScrollerArrowsMinEnd) + y = 1; + else + return NSZeroRect; + } + height = buttonsWidth; + break; - // Assign to `width' and `height' values describing - // the width and height of the scroller regardless - // of its orientation. Also compute the `floatValue' - if (_isHorizontal) // which is essentially the same width as _floatValue - { // but keeps track of the scroller's orientation. - width = scrollerFrame.size.height; - height = scrollerFrame.size.width; - floatValue = _floatValue; - } - else - { - width = scrollerFrame.size.width; - height = scrollerFrame.size.height; - floatValue = 1 - _floatValue; - } // The x, y, width and height values - // are computed below for the vertical - switch (partCode) // scroller. The height of the scroll - { // buttons is assumed to be equal to - case NSScrollerKnob: // the width. - { - float knobHeight, knobPosition, slotHeight; - // If the scroller does not have parts - // or a knob return a zero rect. - if (usableParts == NSNoScrollerParts || - usableParts == NSOnlyScrollerArrows) - return NSZeroRect; - // calc the slot Height - slotHeight = height - (arrowsPosition == NSScrollerArrowsNone ? - 0 : 2 * (buttonsWidth + buttonsDistance)); - if (_isHorizontal) - slotHeight -= 2; - knobHeight = _knobProportion * slotHeight; - if (knobHeight < buttonsWidth) - knobHeight = buttonsWidth; - // calc knob's position - knobPosition = floatValue * (slotHeight - knobHeight); - knobPosition = (float)floor(knobPosition); // avoid rounding error - // calc actual position - y = knobPosition + (arrowsPosition == NSScrollerArrowsMaxEnd - || arrowsPosition == NSScrollerArrowsNone ? - 0 : 2 * (buttonsWidth + buttonsDistance)); - height = knobHeight; - width = buttonsWidth; - if (_isHorizontal) // keeps horiz knob off - y++; // of the buttons - break; - } - - case NSScrollerKnobSlot: - x = 0; // if the scroller does - width = scrollerWidth; // not have buttons the - // slot completely - if (usableParts == NSNoScrollerParts) // fills the scroller. - { - y = 0; // `height' unchanged - break; - } - if (arrowsPosition == NSScrollerArrowsMaxEnd) - { - y = 0; - height -= 2 * (buttonsWidth + buttonsDistance) + 1; - } - else - { - if (arrowsPosition == NSScrollerArrowsMinEnd) - { - y = 2 * (buttonsWidth + buttonsDistance) + 1; - height -= y; - } - else - y = 0; // `height' unchanged - } - break; - - case NSScrollerDecrementLine: - case NSScrollerDecrementPage: - if (usableParts == NSNoScrollerParts) // if scroller has no - return NSZeroRect; // parts or knob then - // return a zero rect - width = buttonsWidth; - if (arrowsPosition == NSScrollerArrowsMaxEnd) - y = height - 2 * (buttonsWidth + buttonsDistance); - else - { - if (arrowsPosition == NSScrollerArrowsMinEnd) - y = 1; - else - return NSZeroRect; - } - height = buttonsWidth; - break; - - case NSScrollerIncrementLine: - case NSScrollerIncrementPage: - if (usableParts == NSNoScrollerParts) // if scroller has no - return NSZeroRect; // parts or knob then - // return a zero rect - width = buttonsWidth; - if (arrowsPosition == NSScrollerArrowsMaxEnd) - y = height - (buttonsWidth + buttonsDistance); - else - { - if (arrowsPosition == NSScrollerArrowsMinEnd) - y = buttonsWidth + buttonsDistance + 1; - else - return NSZeroRect; - } - height = buttonsWidth; - break; - - case NSScrollerNoPart: - return NSZeroRect; - } - - if (_isHorizontal) - return NSMakeRect (y, x, height, width); + case NSScrollerIncrementLine: + case NSScrollerIncrementPage: + if (usableParts == NSNoScrollerParts) + return NSZeroRect; + width = buttonsWidth; + if (arrowsPosition == NSScrollerArrowsMaxEnd) + y = height - (buttonsWidth + buttonsDistance); else - return NSMakeRect (x, y, width, height); + { + if (arrowsPosition == NSScrollerArrowsMinEnd) + y = buttonsWidth + buttonsDistance + 1; + else + return NSZeroRect; + } + height = buttonsWidth; + break; + + case NSScrollerNoPart: + return NSZeroRect; + } + + if (_isHorizontal) + return NSMakeRect (y, x, height, width); + else + return NSMakeRect (x, y, width, height); } @end diff --git a/Source/NSWindow.m b/Source/NSWindow.m index 6f51f813f..d9027220d 100644 --- a/Source/NSWindow.m +++ b/Source/NSWindow.m @@ -561,7 +561,13 @@ NSPoint basePoint; - (BOOL)isAutodisplay { return is_autodisplay; } - (BOOL)isFlushWindowDisabled { return disable_flush_window; } - (void)setAutodisplay:(BOOL)flag { is_autodisplay = flag; } -- (void)setViewsNeedDisplay:(BOOL)flag { needs_display = flag; } + +- (void) setViewsNeedDisplay: (BOOL)flag +{ + needs_display = flag; + [[NSApplication sharedApplication] setWindowsNeedUpdate: YES]; +} + - (BOOL)viewsNeedDisplay { return needs_display; } - (void)useOptimizedDrawing:(BOOL)flag { optimize_drawing = flag; }