// Copyright 1997-1999 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "NSView-OAExtensions.h"

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>

#import "OAWrapUsage.h"
#import "NSFont-OAExtensions.h"

RCS_ID("$Header: /Network/Developer/Source/CVS/OmniGroup/OmniAppKit/OpenStepExtensions.subproj/NSView-OAExtensions.m,v 1.7 1999/03/30 21:26:03 kc Exp $")

@implementation NSView (OAExtensions)

// Drawing

- (void)drawRoundedRect:(NSRect)rect cornerRadius:(float)radius
   color:(NSColor *)color;
{
    [color set];
    PSnewpath();
    PSmoveto(NSMinX(rect), NSMinY(rect) + radius);
    PSlineto(NSMinX(rect), NSMaxY(rect) - radius);
    PSarct(NSMinX(rect), NSMaxY(rect),
           NSMinX(rect) + radius, NSMaxY(rect), radius);
    PSlineto(NSMaxX(rect) - radius, NSMaxY(rect));
    PSarct(NSMaxX(rect), NSMaxY(rect),
           NSMaxX(rect), NSMaxY(rect) - radius, radius);
    PSlineto(NSMaxX(rect), NSMinY(rect) + radius);
    PSarct(NSMaxX(rect), NSMinY(rect),
           NSMaxX(rect) - radius, NSMinY(rect), radius);
    PSlineto(NSMinX(rect) + radius, NSMinY(rect));
    PSarct(NSMinX(rect), NSMinY(rect),
           NSMinX(rect), NSMinY(rect) + radius, radius);
    PSclosepath();
    PSfill();
}

- (void)drawHorizontalSelectionInRect:(NSRect)rect;
{
    double height;
    
    [[NSColor selectedControlColor] set];
    NSRectFill(rect);

    [[NSColor controlShadowColor] set];
    height = NSHeight(rect);
    rect.size.height = 1.0;
    NSRectFill(rect);
    rect.origin.y += height;
    NSRectFill(rect);
}


// Scrolling

- (void)scrollDownByPercentage:(float)percentage;
{
    NSRect visibleRect;
    NSClipView *clipView;
    NSRect oldClipBounds, newClipBounds;

    if (![[self superview] respondsToSelector:@selector(documentVisibleRect)])
	return;

    clipView = (NSClipView *)[self superview];
    visibleRect = [self visibleRect];
    (&visibleRect)->origin.y += percentage * NSHeight(visibleRect);
    oldClipBounds = [clipView bounds];
    [self scrollPoint:visibleRect.origin];
    newClipBounds = [clipView bounds];
    if (NSMinY(oldClipBounds) == NSMinY(newClipBounds) &&
	NSMinX(oldClipBounds) == NSMinX(newClipBounds))
	return;
    if (![self canDraw])
	[[clipView superview] setNeedsDisplay: YES];
}

- (float)fraction;
{
    NSRect visibleRect;
    float fraction;

    visibleRect = [self visibleRect];
    
    if (NSHeight(visibleRect) >= NSHeight([self bounds]))
        return 0.0;

    fraction = NSMinY(visibleRect) /
      (NSHeight([self bounds]) - NSHeight(visibleRect));

    if (fraction <= 0.0)
        return 0.0;
    else if (fraction >= 1.0)
        return 1.0;
    else
        return fraction;
}

- (void)setFraction:(float)newFract;
{
    NSRect desiredRect;
    NSClipView *clipView;
    NSRect oldClipBounds, newClipBounds;

    if (![[self superview] respondsToSelector:@selector(documentVisibleRect)])
	return;

    desiredRect = [self visibleRect];

    if (NSHeight(desiredRect) >= NSHeight([self bounds]))
	return;			/* we're entirely visible */

    (&desiredRect)->origin.y = newFract *
      (NSHeight([self bounds]) - NSHeight(desiredRect));

    if (NSMinY(desiredRect) < 0.0)
	(&desiredRect)->origin.y = 0.0;
    else if (NSMaxY(desiredRect) > NSHeight([self bounds]))
	(&desiredRect)->origin.y = NSHeight([self bounds]) - NSHeight(desiredRect);

    clipView = (NSClipView *)[self superview];
    oldClipBounds = [clipView bounds];
    [self scrollPoint:desiredRect.origin];
    newClipBounds = [clipView bounds];
    if (NSMinY(oldClipBounds) == NSMinY(newClipBounds) &&
	NSMinX(oldClipBounds) == NSMinX(newClipBounds))
	return;
    if (![self canDraw])
	[[clipView superview] setNeedsDisplay: YES];
}


// Dragging

- (BOOL)shouldStartDragFromMouseDownEvent:(NSEvent *)event dragSlop:(float)dragSlop finalEvent:(NSEvent **)finalEventPointer;
{
    NSPoint eventLocation;
    NSRect slopRect;
    NSDate *distantFuture;

    OBPRECONDITION([event type] == NSLeftMouseDown);

    eventLocation = [event locationInWindow];
    slopRect = NSInsetRect(NSMakeRect(eventLocation.x, eventLocation.y, 0.0, 0.0), -dragSlop, -dragSlop);

    distantFuture = [NSDate distantFuture];
    while (1) {
        NSEvent *nextEvent;

        nextEvent = [NSApp nextEventMatchingMask:NSLeftMouseDraggedMask|NSLeftMouseUpMask untilDate:distantFuture inMode:NSEventTrackingRunLoopMode dequeue:YES];
        if (finalEventPointer)
            *finalEventPointer = nextEvent;

        if ([nextEvent type] == NSLeftMouseUp) {
	    return NO;
	    break;
	} else if (!NSMouseInRect([nextEvent locationInWindow], slopRect, NO)) {
            return YES;
	    break;
	}
    }
}


// Debugging

unsigned int NSViewMaxDebugDepth = 10;

- (NSMutableDictionary *)debugDictionary;
{
    NSMutableDictionary *debugDictionary;

    debugDictionary = [NSMutableDictionary dictionary];
    [debugDictionary setObject:OBShortObjectDescription(self) forKey:@"__self__"];
    [debugDictionary setObject:NSStringFromRect([self frame]) forKey:@"01_frame"];
    if (!NSEqualSizes([self bounds].size, [self frame].size) || !NSEqualPoints([self bounds].origin, NSZeroPoint))
        [debugDictionary setObject:NSStringFromRect([self bounds]) forKey:@"02_bounds"];
    if ([[self subviews] count] > 0)
        [debugDictionary setObject:[self subviews] forKey:@"subviews"];
    return debugDictionary;
}

- (NSString *)descriptionWithLocale:(NSDictionary *)locale indent:(unsigned int)level;
{
    if (level < NSViewMaxDebugDepth)
        return [[self debugDictionary] descriptionWithLocale:locale indent:level];
    else
        return [self shortDescription];
}

- (NSString *)description;
{
    return [self descriptionWithLocale:nil indent:0];
}

- (NSString *)shortDescription;
{
    return [super description];
}

@end
