New split view, other fixes.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@2869 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
fedor 1998-07-28 17:51:55 +00:00
parent 430b72325a
commit bbdc19e7be
3 changed files with 565 additions and 94 deletions

View file

@ -1,16 +1,26 @@
Tue Jul 28 13:02:43 1998 Adam Fedor <fedor@ultra.doc.com>
* Source/NSSplitView.m: Implemention from Robert Vasvari
<vrobi@ddrummer.com>.
* Headers/gnustep/gui/NSSplitView.h: Likewise.
Tues July 28 1998 Felipe A. Rodriguez <far@ix.netcom.com> Tues July 28 1998 Felipe A. Rodriguez <far@ix.netcom.com>
* NSScroller.m in trackScrollButtons method added code to highlight cell * NSScroller.m in trackScrollButtons method added code to
prior to calling trackMouse. In keeping with new behaviour of NSCell. highlight cell prior to calling trackMouse. In keeping with new
behaviour of NSCell.
Sat July 25 1998 Felipe A. Rodriguez <far@ix.netcom.com> Sat July 25 1998 Felipe A. Rodriguez <far@ix.netcom.com>
* NSCell.m removed highlight/unhighlight behaviour from trackMouse method * NSCell.m removed highlight/unhighlight behaviour from trackMouse
per OS spec. Behaviour is now as described for this method in method per OS spec. Behaviour is now as described for this method
NSControl, NSMatrix and NSCell. in NSControl, NSMatrix and NSCell.
* NSMatrix.m: rewrote mouseDown to more closely follow the OS spec. There
are still some very subtle differences. * NSMatrix.m: rewrote mouseDown to more closely follow the OS
* NSButton.m: now highlights it's cell before invoking Cell's trackMouse. spec. There are still some very subtle differences.
* NSButton.m: now highlights it's cell before invoking Cell's
trackMouse.
Mon Jul 20 10:37:22 1998 Adam Fedor <fedor@ultra.doc.com> Mon Jul 20 10:37:22 1998 Adam Fedor <fedor@ultra.doc.com>

View file

@ -5,8 +5,8 @@
Copyright (C) 1996 Free Software Foundation, Inc. Copyright (C) 1996 Free Software Foundation, Inc.
Author: Scott Christley <scottc@net-community.com> Author: Robert Vasvari <vrobi@ddrummer.com>
Date: 1996 Date: Jul 1998
This file is part of the GNUstep GUI Library. This file is part of the GNUstep GUI Library.
@ -29,50 +29,54 @@
#ifndef _GNUstep_H_NSSplitView #ifndef _GNUstep_H_NSSplitView
#define _GNUstep_H_NSSplitView #define _GNUstep_H_NSSplitView
#include <AppKit/NSView.h> #import <AppKit/NSView.h>
@class NSString; @class NSImage, NSColor, NSNotification;
@class NSNotification;
@interface NSSplitView : NSView <NSCoding> @interface NSSplitView : NSView
{ {
// Attributes id delegate;
int dividerWidth, draggedBarWidth;
id splitCursor;
BOOL isVertical;
NSImage *dimpleImage;
NSColor *backgroundColor, *dividerColor;
} }
// - (void) setDelegate: (id)anObject;
// Managing Component Views - (id) delegate;
// - (void) adjustSubviews;
- (void)adjustSubviews; - (void) drawDividerInRect: (NSRect)aRect;
- (float)dividerThickness;
- (void)drawDividerInRect:(NSRect)aRect;
// - (void) setVertical: (BOOL)flag; /* Vertical splitview has a vertical split bar */
// Assigning a Delegate - (BOOL) isVertical;
//
- (id)delegate;
- (void)setDelegate:(id)anObject;
// /* extra methods to make it more usable */
// Implemented by the Delegate - (float) dividerThickness; //defaults to 8
// - (void) setDividerThickNess: (float)newWidth;
- (void)splitView:(NSSplitView *)splitView - (float) draggedBarWidth;
constrainMinCoordinate:(float *)min - (void) setDraggedBarWidth: (float)newWidth;
maxCoordinate:(float *)max /* if flag is yes, dividerThickness is reset to the height/width of the dimple
ofSubviewAt:(int)offset; image + 1;
- (void)splitView:(NSSplitView *)sender */
resizeSubviewsWithOldSize:(NSSize)oldSize; - (void) setDimpleImage: (NSImage *)anImage resetDividerThickness: (BOOL)flag;
- (void)splitViewDidResizeSubviews:(NSNotification *)notification; - (NSImage *) dimpleImage;
- (void)splitViewWillResizeSubviews:(NSNotification *)notification; - (NSColor *) backgroundColor;
- (void) setBackgroundColor: (NSColor *)aColor;
// - (NSColor *) dividerColor;
// NSCoding protocol - (void) seDividerColor: (NSColor *)aColor;
//
- (void)encodeWithCoder:aCoder;
- initWithCoder:aDecoder;
@end @end
@interface NSObject(NSSplitViewDelegate)
- (void) splitView: (RBSplitView *)sender resizeSubviewsWithOldSize: (NSSize)oldSize;
- (void) splitView: (RBSplitView *)sender constrainMinCoordinate: (float *)min maxCoordinate: (float *)max ofSubviewAt: (int)offset;
- (void) splitViewWillResizeSubviews: (NSNotification *)notification;
- (void) splitViewDidResizeSubviews: (NSNotification *)notification;
@end
/* Notifications */
extern NSString *NSSplitViewDidResizeSubviewsNotification; extern NSString *NSSplitViewDidResizeSubviewsNotification;
extern NSString *NSSplitViewWillResizeSubviewsNotification; extern NSString *NSSplitViewWillResizeSubviewsNotification;
#endif // _GNUstep_H_NSSplitView #endif

View file

@ -1,12 +1,12 @@
/* /*
NSSplitView.m NSSplitView.h
Description... Allows multiple views to share a region in a window
Copyright (C) 1996 Free Software Foundation, Inc. Copyright (C) 1996 Free Software Foundation, Inc.
Author: Scott Christley <scottc@net-community.com> Author: Robert Vasvari <vrobi@ddrummer.com>
Date: 1996 Date: Jul 1998
This file is part of the GNUstep GUI Library. This file is part of the GNUstep GUI Library.
@ -26,83 +26,540 @@
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include <gnustep/gui/config.h> #import <Foundation/Foundation.h>
#include <AppKit/NSSplitView.h> #import <Foundation/NSRunLoop.h>
#import <AppKit/AppKit.h>
#include <string.h>
#include <math.h>
/* Backend protocol - methods that must be implemented by the backend to
complete the class */
@protocol NSSplitViewBackend
- (void) _fillRect: (NSRect)rect;
@end
@implementation NSSplitView @implementation NSSplitView
// /* API Methods */
// Class methods
// - (void)mouseDown:(NSEvent *)theEvent
+ (void)initialize
{ {
if (self == [NSSplitView class]) static NSRect oldRect; //only one can be dragged at a time
{ NSPoint p;
// Initial version NSEvent *e;
[self setVersion:1]; NSRect r, r1, bigRect, vis;
id v, prev=nil;
float minCoord,maxCoord;
NSArray *subs=[self subviews];
int offset=0,i,count=[subs count];
float divVertical, divHorizontal, div=[self dividerThickness];
NSColor *divColor=[self dividerColor];
NSDate *farAway=[NSDate distantFuture];
unsigned int eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask
| NSLeftMouseDraggedMask | NSMouseMovedMask
| NSPeriodicMask;
/* if there are less the two subviews, there is nothing
to do
*/
if(count<2) return;
[[self window] setAcceptsMouseMovedEvents:YES];
vis = [self visibleRect];
/* find out which divider it is */
p=[theEvent locationInWindow];
p = [self convertPoint:p fromView:nil];
for(i=0;i<count;i++)
{
v=[subs objectAtIndex:i];
r=[v frame];
/* if the click is inside of a subview, return.
this should never happen */
if([self isVertical])
{
if((p.y>NSMinY(r)) && (p.y<NSMaxY(r)))
goto RETURN_LABEL;
if(NSMaxY(r)>p.y)
{
offset=i;
/* get the enclosing rect for the two views */
if(prev) r=[prev frame];
else r = NSZeroRect;
if(v) r1=[v frame];
bigRect=r;
bigRect=NSUnionRect(r1 , bigRect);
break;
}
prev=v;
}
else
{
if((p.x>NSMinX(r)) && (p.x<NSMaxX(r)))
goto RETURN_LABEL;
if((NSMinX(r)+NSWidth(r))>p.x)
{
offset=i;
/* get the enclosing rect for the two views */
if(prev) r=[prev frame];
else r = NSZeroRect;
if(v) r1=[v frame];
bigRect=r;
bigRect=NSUnionRect(r1 , bigRect);
break;
}
prev=v;
}
} }
if([self isVertical])
{
divVertical=div;
divHorizontal=NSWidth([self frame]);
/* set the default limits on the dragging */
minCoord=NSMinY(bigRect)+divVertical;
maxCoord=NSHeight(bigRect)+NSMinY(bigRect)-divVertical;
}
else
{
divHorizontal=div;
divVertical=NSHeight([self frame]);
/* set the default limits on the dragging */
minCoord=NSMinX(bigRect)+divHorizontal;
maxCoord=NSWidth(bigRect)+NSMinX(bigRect)-divHorizontal;
}
/* find out what the dragging limit is */
if(delegate && [delegate respondsToSelector:@selector
(splitView:constrainMinCoordinate:maxCoordinate:ofSubviewAt:)])
{
if([self isVertical])
{
float delMinY=minCoord, delMaxY=maxCoord;
[delegate splitView:self
constrainMinCoordinate:&delMinY
maxCoordinate:&delMaxY
ofSubviewAt:offset];
/* we are still constrained by the original bounds */
if(delMinY>minCoord) minCoord=delMinY;
if(delMaxY<maxCoord) maxCoord=delMaxY;
}
else
{
float delMinX=minCoord, delMaxX=maxCoord;
[delegate splitView:self
constrainMinCoordinate:&delMinX
maxCoordinate:&delMaxX
ofSubviewAt:offset];
/* we are still constrained by the original bounds */
if(delMinX>minCoord) minCoord=delMinX;
if(delMaxX<maxCoord) maxCoord=delMaxX;
}
}
oldRect = NSZeroRect;
[self lockFocus];
/* FIXME: Are these really needed? */
[NSEvent startPeriodicEventsAfterDelay:0.1 withPeriod:0.1];
[[NSRunLoop currentRunLoop] limitDateForMode:NSEventTrackingRunLoopMode];
[divColor set];
r.size.width = divHorizontal;
r.size.height = divVertical;
e=[[NSApplication sharedApplication]
nextEventMatchingMask:eventMask
untilDate:farAway inMode:NSEventTrackingRunLoopMode dequeue:YES];
while([e type] != NSLeftMouseUp)
{
[self displayRect:oldRect];
if ([e type] != NSPeriodic)
{
p=[e locationInWindow];
p = [self convertPoint:p fromView:nil];
}
if([self isVertical])
{
if(p.y<minCoord) p.y=minCoord;
if(p.y>maxCoord) p.y=maxCoord;
r.origin.y = p.y-(divVertical/2.);
r.origin.x = NSMinX(vis);
}
else
{
if(p.x<minCoord) p.x=minCoord;
if(p.x>maxCoord) p.x=maxCoord;
r.origin.x = p.x-(divHorizontal/2.);
r.origin.y = NSMinY(vis);
}
NSDebugLog(@"drawing divider at x:%d, y:%d, w:%d, h:%d\n",
(int)NSMinX(r),(int)NSMinY(r),(int)NSWidth(r),
(int)NSHeight(r));
[self _fillRect: r];
[[NSDPSContext currentContext] flush];
oldRect=r;
e=[[NSApplication sharedApplication]
nextEventMatchingMask:eventMask
untilDate:farAway inMode:NSEventTrackingRunLoopMode dequeue:YES];
}
[self unlockFocus];
[NSEvent stopPeriodicEvents];
/* resize the subviews accordingly */
r = [prev frame];
if([self isVertical])
{
r.size.height=p.y-NSMinY(bigRect)-(divVertical/2.);
if(NSHeight(r) < 1.) r.size.height=1.;
}
else
{
r.size.width=p.x-NSMinX(bigRect)-(divHorizontal/2.);
if(NSWidth(r) < 1.) r.size.width=1.;
}
[prev setFrame:r];
NSDebugLog(@"drawing PREV at x:%d, y:%d, w:%d, h:%d\n",
(int)NSMinX(r),(int)NSMinY(r),(int)NSWidth(r),(int)NSHeight(r));
r1 = [v frame];
if([self isVertical])
{
r1.origin.y=p.y+(divVertical/2.);
if(NSMinY(r1) < 0.) r1.origin.y=0.;
r1.size.height=NSHeight(bigRect)-NSHeight(r)-divVertical;
if(NSHeight(r) < 1.) r.size.height=1.;
}
else
{
r1.origin.x=p.x+(divHorizontal/2.);
if(NSMinX(r1) < 0.) r1.origin.x=0.;
r1.size.width=NSWidth(bigRect)-NSWidth(r)-divHorizontal;
if(NSWidth(r1) < 1.) r1.size.width=1.;
}
[v setFrame:r1];
NSDebugLog(@"drawing LAST at x:%d, y:%d, w:%d, h:%d\n",
(int)NSMinX(r1),(int)NSMinY(r1),(int)NSWidth(r1),
(int)NSHeight(r1));
[[self window] invalidateCursorRectsForView:self];
RETURN_LABEL:
[[self window] setAcceptsMouseMovedEvents:NO];
[self setNeedsDisplay:YES];
} }
//
// Instance methods
//
//
// Managing Component Views
//
- (void)adjustSubviews - (void)adjustSubviews
{}
- (float)dividerThickness
{ {
return 0.0; NSRect fr=[self frame];
NSSize newSize;
NSPoint newPoint;
float total=0.;
if(delegate && [delegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)])
{
[delegate splitView:self resizeSubviewsWithOldSize:fr.size];
}
else
{ /* split the area up evenly */
NSArray *subs=[self subviews];
int i, div, count=[subs count];
id v;
int w,h;
NSRect r, bd=[self bounds];
div=(int)([self dividerThickness]*(count-1));
w=(int)ceil((NSWidth(bd)-div)/count);
h=(int)ceil((NSHeight(bd)-div)/count);
for(i=0;i<count;i++)
{
v=[subs objectAtIndex:i];
r = [v frame];
/* bounds check */
if([self isVertical])
{
newSize=NSMakeSize(NSWidth(bd), h);
/* make sure nothing spills over */
while((total+newSize.height)>(NSHeight(bd)-div))
{
newSize.height-=1.;
}
total+=newSize.height;
newPoint=NSMakePoint(0,(float)ceil(i ?
(i*([self dividerThickness]+h)) : 0));
if(newSize.height<1) newSize.height=1.;
if(newPoint.y<1) newPoint.y=1.;
}
else
{
newSize=NSMakeSize(w, NSHeight(bd));
/* make sure nothing spills over */
while((total+newSize.width)>(NSWidth(bd)-div))
{
newSize.width-=1.;
}
total+=newSize.width;
newPoint=NSMakePoint((float)ceil(i ?
(i*([self dividerThickness]+w)) : 0), 0);
if(newSize.width<1) newSize.width=1.;
if(newPoint.x<1) newPoint.x=1.;
}
[v setFrameSize: newSize];
[v setFrameOrigin: newPoint];
}
}
[[NSNotificationCenter defaultCenter]
postNotificationName:NSSplitViewDidResizeSubviewsNotification object:self];
}
- (void)addSubview:(NSView *)aView
positioned:(NSWindowOrderingMode)place
relativeTo:(NSView *)otherView
{
[super addSubview:aView positioned:place relativeTo:otherView];
/* register the subviews up for notification */
//[[NSNotificationCenter defaultCenter] addObserver:aView
// selector:@selector(splitViewDidResizeSubviews:)
// name:NSSplitViewDidResizeSubviewsNotification object:self];
[self adjustSubviews];
}
- (void)addSubview:aView
{
[super addSubview:aView];
[self adjustSubviews];
}
- (float)dividerThickness //defaults to 8
{
return dividerWidth;
}
- (void)setDividerThickNess:(float)newWidth
{
dividerWidth=newWidth;
}
- (float)draggedBarWidth //defaults to 8
{
return draggedBarWidth;
}
- (void)setDraggedBarWidth:(float)newWidth
{
draggedBarWidth=newWidth;
}
NSPoint centerSizeInRect(NSSize innerSize, NSRect outerRect)
{
NSPoint p;
p.x=MAX(NSMidX(outerRect)-(innerSize.width/2.),0.);
p.y=MAX(NSMidY(outerRect)-(innerSize.height/2.),0.);
return p;
}
NSPoint centerRectInRect(NSRect innerRect, NSRect outerRect)
{
return centerSizeInRect(innerRect.size,outerRect);
} }
- (void)drawDividerInRect:(NSRect)aRect - (void)drawDividerInRect:(NSRect)aRect
{}
//
// Assigning a Delegate
//
- (id)delegate
{ {
return nil; NSPoint dimpleOrigin;
NSSize dimpleSize;
/* focus is already on self */
if(!dimpleImage) return;
dimpleSize=[dimpleImage size];
/* composite into the center of the given rect. Since NSImages
are always flipped, we adjust for it here */
dimpleOrigin=centerSizeInRect(dimpleSize,aRect);
if([self isFlipped]) dimpleOrigin.y+=dimpleSize.height;
[dimpleImage compositeToPoint:dimpleOrigin operation:NSCompositeSourceOver];
} }
- (void)setDelegate:(id)anObject - (void)setVertical:(BOOL)flag /* Vertical splitview has a vertical split bar */
{} {
isVertical=flag;
}
// - (BOOL)isVertical
// Implemented by the Delegate {
// return isVertical;
- (void)splitView:(NSSplitView *)splitView }
constrainMinCoordinate:(float *)min
maxCoordinate:(float *)max
ofSubviewAt:(int)offset
{}
- (void)splitView:(NSSplitView *)sender - (void)setDimpleImage:(NSImage *)anImage resetDividerThickness:(BOOL)flag
resizeSubviewsWithOldSize:(NSSize)oldSize {
{} if(dimpleImage==anImage) return;
[dimpleImage release];
dimpleImage=[anImage retain];
- (void)splitViewDidResizeSubviews:(NSNotification *)notification if(flag)
{} {
NSSize s={8.,8.};
if(dimpleImage) s=[dimpleImage size];
[self setDividerThickNess: isVertical ? s.height : s.width];
}
}
- (void)splitViewWillResizeSubviews:(NSNotification *)notification - (void)drawRect:(NSRect)r
{} {
NSArray *subs=[self subviews];
int i, count=[subs count];
id v;
NSRect divRect;
if([self isOpaque])
{
[[self backgroundColor] set];
[self _fillRect: [self bounds]];
}
/* draw the dimples */
{
for(i=0;i<(count-1);i++)
{
v=[subs objectAtIndex:i];
divRect=[v frame];
if([self isVertical])
{
divRect.origin.y=NSMaxY(divRect);
divRect.size.height=[self dividerThickness];
}
else
{
divRect.origin.x=NSMaxX(divRect);
divRect.size.width=[self dividerThickness];
}
[self drawDividerInRect:divRect];
}
}
}
- (NSImage *)dimpleImage
{
return dimpleImage;
}
/* Overridden Methods */
- (BOOL)isFlipped
{
return NO;
}
- (BOOL)isOpaque
{
return YES;
}
- initWithFrame:(NSRect)frameRect
{
if((self=[super initWithFrame:frameRect])!=nil)
{
dividerWidth=8;
draggedBarWidth=8;
isVertical=NO;
[self seDividerColor:[NSColor darkGrayColor]];
[self setBackgroundColor:[NSColor whiteColor]];
[self setDimpleImage:
[NSImage imageNamed:@"splitButton.tiff"] resetDividerThickness:YES];
}
return self;
}
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize
{
[super resizeWithOldSuperviewSize:oldSize];
[self adjustSubviews];
[[self window] invalidateCursorRectsForView:self];
}
- delegate
{
return delegate;
}
- (void)setDelegate:anObject
{
if(delegate==anObject) return;
[delegate release];
delegate=[anObject retain];
}
- (NSColor *)dividerColor
{
return dividerColor;
}
- (void)seDividerColor:(NSColor *)aColor
{
if(dividerColor==aColor) return;
[dividerColor release];
dividerColor=[aColor retain];
}
- (NSColor *)backgroundColor
{
return backgroundColor;
}
- (void)setBackgroundColor:(NSColor *)aColor
{
if(backgroundColor==aColor) return;
[backgroundColor release];
backgroundColor=[aColor retain];
}
// //
// NSCoding protocol // NSCoding protocol
// //
- (void)encodeWithCoder:aCoder - (void)encodeWithCoder:aCoder
{ {
// NSDebugLog(@"NSSplitView: start encoding\n");
[super encodeWithCoder:aCoder]; [super encodeWithCoder:aCoder];
[aCoder encodeObject:delegate];
[aCoder encodeObject:splitCursor];
[aCoder encodeObject:dimpleImage];
[aCoder encodeObject:backgroundColor];
[aCoder encodeObject:dividerColor];
[aCoder encodeValueOfObjCType:@encode(int) at: &dividerWidth];
[aCoder encodeValueOfObjCType:@encode(int) at: &draggedBarWidth];
[aCoder encodeValueOfObjCType:@encode(BOOL) at: &isVertical];
// NSDebugLog(@"NSView: finish encoding\n");
} }
- initWithCoder:aDecoder - initWithCoder:aDecoder
{ {
[super initWithCoder:aDecoder]; self=[super initWithCoder:aDecoder];
// NSDebugLog(@"NSSplitView: start decoding\n");
delegate=[aDecoder decodeObject];
splitCursor=[aDecoder decodeObject];
dimpleImage=[aDecoder decodeObject];
backgroundColor=[aDecoder decodeObject];
dividerColor=[aDecoder decodeObject];
[aDecoder decodeValueOfObjCType:@encode(int) at: &dividerWidth];
[aDecoder decodeValueOfObjCType:@encode(int) at: &draggedBarWidth];
[aDecoder decodeValueOfObjCType:@encode(BOOL) at: &isVertical];
// NSDebugLog(@"NSView: finish decoding\n");
return self; return self;
} }
- (void)dealloc
{
[backgroundColor release];
[dividerColor release];
[dimpleImage release];
[super dealloc];
}
@end @end