libs-gui/Source/NSScrollView.m
Felipe A. Rodriguez d093540668 gui changes
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@3260 72102866-910b-0410-8b05-ffd578937521
1998-11-20 02:14:22 +00:00

456 lines
11 KiB
Objective-C

/*
NSScrollView.m
Copyright (C) 1996 Free Software Foundation, Inc.
Author: Ovidiu Predescu <ovidiu@net-community.com>
Date: July 1997
Author: Felipe A. Rodriguez <far@ix.netcom.com>
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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gnustep/gui/config.h>
#include <math.h>
#include <AppKit/NSScroller.h>
#include <AppKit/NSClipView.h>
#include <AppKit/NSScrollView.h>
#include <AppKit/NSWindow.h>
@implementation NSScrollView
static Class rulerViewClass = nil;
+ (void)initialize
{
}
+ (void)setRulerViewClass:(Class)aClass
{
rulerViewClass = aClass;
}
+ (Class)rulerViewClass
{
return rulerViewClass;
}
/* Backends should rewrite the following 2 methods and adjust the frames
depending on the border type. */
+ (NSSize)contentSizeForFrameSize:(NSSize)frameSize
hasHorizontalScroller:(BOOL)hFlag
hasVerticalScroller:(BOOL)vFlag
borderType:(NSBorderType)borderType
{
NSSize size = frameSize;
if (hFlag)
size.height -= [NSScroller scrollerWidth];
if (vFlag)
size.width -= [NSScroller scrollerWidth];
return size;
}
+ (NSSize)frameSizeForContentSize:(NSSize)contentSize
hasHorizontalScroller:(BOOL)hFlag
hasVerticalScroller:(BOOL)vFlag
borderType:(NSBorderType)borderType
{
NSSize size = contentSize;
if (hFlag)
size.height += [NSScroller scrollerWidth];
if (vFlag)
size.width += [NSScroller scrollerWidth];
return size;
}
- initWithFrame:(NSRect)rect
{
[super initWithFrame:rect];
[self setContentView:[[NSClipView new] autorelease]];
_lineScroll = 10;
_pageScroll = 10;
_borderType = NSBezelBorder;
_scrollsDynamically = YES;
autoresizingMask = NSViewMaxYMargin;
[self tile];
return self;
}
- init
{
return [self initWithFrame:NSZeroRect];
}
- (void)dealloc
{
[_contentView release];
[_horizScroller release];
[_vertScroller release];
[_horizRuler release];
[_vertRuler release];
[super dealloc];
}
- (void)setContentView:(NSView*)aView
{
ASSIGN(_contentView, aView);
[self addSubview:_contentView];
[self tile];
}
- (void)setHorizontalScroller:(NSScroller*)aScroller
{
[_horizScroller removeFromSuperview];
/* Do not add the scroller view to the subviews array yet; the user has to
explicitly invoke -setHasHorizontalScroller:. */
ASSIGN(_horizScroller, aScroller);
if (_horizScroller) {
[_horizScroller setTarget:self];
[_horizScroller setAction:@selector(_doScroll:)];
}
}
- (void)setHasHorizontalScroller:(BOOL)flag
{
if (_hasHorizScroller == flag)
return;
_hasHorizScroller = flag;
if (_hasHorizScroller) {
if (!_horizScroller)
[self setHorizontalScroller:[[NSScroller new] autorelease]];
[self addSubview:_horizScroller];
}
else
[_horizScroller removeFromSuperview];
[self tile];
}
- (void)setVerticalScroller:(NSScroller*)aScroller
{
[_vertScroller removeFromSuperview];
/* Do not add the scroller view to the subviews array yet; the user has to
explicitly invoke -setHasVerticalScroller:. */
ASSIGN(_vertScroller, aScroller);
if (_vertScroller) {
[_vertScroller setTarget:self];
[_vertScroller setAction:@selector(_doScroll:)];
}
}
- (void)setHasVerticalScroller:(BOOL)flag
{
if (_hasVertScroller == flag)
return;
_hasVertScroller = flag;
if (_hasVertScroller) {
if (!_vertScroller) {
[self setVerticalScroller:[[NSScroller new] autorelease]];
if (_contentView && ![_contentView isFlipped])
[_vertScroller setFloatValue:1];
}
[self addSubview:_vertScroller];
}
else
[_vertScroller removeFromSuperview];
[self tile];
}
- (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;
NSDebugLog (@"_doScroll: float value = %f", floatValue);
_knobMoved = NO;
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;
}
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
- 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
}
}
[_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];
}
}
- (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
// if (_knobMoved) // is this really needed?
// return; // FAR FIX ME ?
NSDebugLog (@"reflectScrolledClipView:");
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 (_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];
}
}
// [self setNeedsDisplay:YES]; // not needed by XRAW causes flicker
[window flushWindow];
}
- (void)setHorizontalRulerView:(NSRulerView*)aRulerView
{
/* TODO */
ASSIGN(_horizRuler, aRulerView);
}
- (void)setHasHorizontalRuler:(BOOL)flag
{
/* TODO */
if (_hasHorizRuler == flag)
return;
_hasHorizRuler = flag;
}
- (void)setVerticalRulerView:(NSRulerView*)ruler
{
/* TODO */
ASSIGN(_vertRuler, ruler);
}
- (void)setHasVerticalRuler:(BOOL)flag
{
/* TODO */
if (_hasVertRuler == flag)
return;
_hasVertRuler = flag;
}
- (void)setRulersVisible:(BOOL)flag
{
/* TODO */
}
- (void)setFrame:(NSRect)rect
{
[super setFrame:rect];
[self tile];
}
- (void)setFrameSize:(NSSize)size
{
[super setFrameSize:size];
[self tile];
}
/* This method should be implemented in the backend to position the scroll
view's interface elements */
- (void)tile
{
}
- (NSRect)documentVisibleRect
{
return [_contentView documentVisibleRect];
}
- (void)setBackgroundColor:(NSColor*)aColor
{
[_contentView setBackgroundColor:aColor];
}
- (NSColor*)backgroundColor
{
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];
}
- (id)documentView
{
return [_contentView documentView];
}
- (void)setDocumentCursor:(NSCursor*)aCursor
{
[_contentView setDocumentCursor:aCursor];
}
- (NSCursor*)documentCursor
{
return [_contentView documentCursor];
}
- (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; }
@end