A load of changes.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@4724 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Michael Silva 1999-08-19 23:18:25 +00:00
parent 1fc4e353c9
commit a73d9b885a
12 changed files with 1035 additions and 49 deletions

View file

@ -1,3 +1,27 @@
1999-08-19 Michael Hanni <mhanni@sprintmail.com>
* Headers/NSAttributedString.h
NSLayoutManager.h
NSTableView.h: modifications, mostly added ivars.
* Source/NSLayoutManager.m: implemented much code for layout and
display.
* Source/NSMenu.m: fixed some nagging problems. tearoffs should
work almost universally. Positions are saved and restored. If you
previous position exists for the main menu it goes to the upper
left corner.
* Source/NSMenuView.m: a few attempts to fix the "move to submenu"
bugs.
* Source/NSPopUpButton.m: many bug fixes and new implementations.
Too many to list here.
* Source/NSTableView.m: more code implemented, though I wouldn't
recommend trying to use this class. :-)
* Source/NSText.m: debugging code to help pinpoint which methods
can be used in NSTextView and which have to be overridden.
* Source/NSTextStorage.m: properly assigns itself to its
layoutManager.
* Source/NSTextView.m: more code additions to coincide with the
new NSLayoutManager.
1999-08-03 Michael Hanni <mhanni@sprintmail.com>
* Source/NSMenu.m: commented out code which did multiple menu

View file

@ -56,6 +56,13 @@ enum
NSSingleUnderlineStyle = 1
};
@interface NSAttributedString(DrawingAddition)
-(NSSize) sizeRange:(NSRange) aRange;
-(void) drawRange:(NSRange) aRange atPoint:(NSPoint) aPoint;
-(void) drawRange:(NSRange) aRange inRect:(NSRect) aRect;
-(BOOL) areMultipleFontsInRange:(NSRange) aRange;
@end
@interface NSAttributedString (AppKit)
- (BOOL) containsAttachments;
- (NSDictionary*) fontAttributesInRange: (NSRange)range;

View file

@ -58,8 +58,8 @@
@class NSView;
@class NSEvent;
// Michael's botch list. :-)
@class GSRunStorage;
// These glyph attributes are used only inside the glyph generation machinery, but must be shared between componenets.
enum _NSGlyphAttribute {
@ -87,6 +87,12 @@ typedef enum {
NSStorage *_containerUsedRects;
NSStorage *_glyphs;
// GS data storage.
GSRunStorage *containerRuns;
GSRunStorage *fragmentRuns;
GSRunStorage *locationRuns;
NSRunStorage *_containerRuns;
NSRunStorage *_fragmentRuns;
NSRunStorage *_glyphLocations;
@ -149,6 +155,7 @@ typedef enum {
BOOL _showsControlChars;
float _hyphenationFactor;
BOOL _usesScreenFonts;
BOOL finished;
}
/**************************** Initialization ****************************/

View file

@ -4,7 +4,6 @@
#include <Foundation/Foundation.h>
#include <AppKit/NSControl.h>
@class NSColor;
@class NSTableColumn;
@class NSTableHeaderView;
@class NSView;

View file

@ -7,6 +7,8 @@
Author: Jonathan Gapen <jagapen@smithlab.chem.wisc.edu>
Date: July 1999
Author: Michael Hanni <mhanni@sprintmail.com>
Date: August 1999
This file is part of the GNUstep GUI Library.
@ -27,14 +29,271 @@
*/
#include <AppKit/NSLayoutManager.h>
// _GSRunSearchKey is an internal class which serves as the foundation for
// all our searching. This may not be an elegant way to go about this, so
// if someone wants to optimize this out, please do.
@interface _GSRunSearchKey : NSObject
{
@public
NSRange glyphRange;
}
@end
@implementation _GSRunSearchKey
- (id)init
{
return [super init];
}
- (void) dealloc
{
[super dealloc];
}
@end
@interface GSGlyphLocation : _GSRunSearchKey
{
@public
NSPoint point;
}
@end
@implementation GSGlyphLocation
- (id)init
{
return [super init];
}
- (void) dealloc
{
[super dealloc];
}
@end
@interface GSLineLayoutInfo : _GSRunSearchKey
{
@public
NSRect lineFragmentRect;
NSRect usedRect;
}
@end
@implementation GSLineLayoutInfo
- (id)init
{
return [super init];
}
- (void) dealloc
{
[super dealloc];
}
@end
@interface GSTextContainerLayoutInfo : _GSRunSearchKey
{
@public
NSTextContainer *textContainer;
NSString *testString;
}
@end
@implementation GSTextContainerLayoutInfo
- (id)init
{
return [super init];
}
- (void) dealloc
{
[super dealloc];
}
@end
#define GSI_ARRAY_TYPES GSUNION_OBJ
#ifdef GSIArray
#undef GSIArray
#endif
#include <base/GSIArray.h>
static NSComparisonResult aSort(GSIArrayItem i0, GSIArrayItem i1)
{
if (((_GSRunSearchKey *)(i0.obj))->glyphRange.location
< ((_GSRunSearchKey *)(i1.obj))->glyphRange.location)
return NSOrderedAscending;
else if (((_GSRunSearchKey *)(i0.obj))->glyphRange.location
>= NSMaxRange(((_GSRunSearchKey *)(i1.obj))->glyphRange))
return NSOrderedDescending;
else
return NSOrderedSame;
}
@interface GSRunStorage : NSObject
{
unsigned int _count;
void *_runs;
}
- (void)insertObject:(id)anObject;
- (void)insertObject:(id)anObject atIndex:(unsigned)theIndex;
- (id)objectAtIndex:(unsigned)theIndex;
- (unsigned)indexOfObject:(id)anObject;
- (unsigned)indexOfObjectContainingLocation:(unsigned)aLocation;
- (id)objectContainingLocation:(unsigned)aLocation;
- (int)count;
@end
@implementation GSRunStorage
- (id)init
{
NSZone *z;
[super init];
z = [self zone];
_runs = NSZoneMalloc(z, sizeof(GSIArray_t));
GSIArrayInitWithZoneAndCapacity((GSIArray)_runs, z, 8);
return self;
}
- (void)insertObject:(id)anObject
{
_GSRunSearchKey *aKey = [_GSRunSearchKey new];
_GSRunSearchKey *aObject = (_GSRunSearchKey *)anObject;
int position;
aKey->glyphRange.location = aObject->glyphRange.location;
position = GSIArrayInsertionPosition(_runs, (GSIArrayItem)aKey, aSort);
NSLog(@"key: %d aObject: %d position: %d", aKey->glyphRange.location,
aObject->glyphRange.location, position);
if (position > 0)
{
_GSRunSearchKey *anKey = GSIArrayItemAtIndex(_runs, (unsigned)position - 1).obj;
if (anKey->glyphRange.location == aObject->glyphRange.location)
{
// GSIArrayInsertSorted(_runs, (GSIArrayItem)anObject, aSort);
NSLog(@"=========> duplicated item.");
GSIArraySetItemAtIndex(_runs, (GSIArrayItem)anObject, position-1);
}
else
{
NSLog(@"=========> not duplicated item.");
GSIArrayInsertItem(_runs, (GSIArrayItem)anObject, position);
}
}
else if (position == 0)
{
NSLog(@"=========> first item (zero index).");
GSIArrayInsertItem(_runs, (GSIArrayItem)anObject, position);
// GSIArrayInsertSorted(_runs, (GSIArrayItem)anObject, aSort);
// [self insertObject:anObject atIndex:position];
}
else
NSLog(@"dead. VERY DEAD DEAD DEAD DEAD.");
NSLog(@"==> %d item(s)", GSIArrayCount(_runs));
}
- (void)insertObject:(id)anObject
atIndex:(unsigned)theIndex
{
NSLog(@"insertObject:atIndex: called. %d item(s)", GSIArrayCount(_runs));
GSIArrayInsertSorted(_runs, (GSIArrayItem)anObject, aSort);
// GSIArrayInsertItem(_runs, (GSIArrayItem)anObject, theIndex);
NSLog(@"insertObject:atIndex: ended. %d item(s)", GSIArrayCount(_runs));
}
- (void)removeObjectAtIndex:(int)theIndex
{
GSIArrayRemoveItemAtIndex(_runs, theIndex);
}
- (id)objectAtIndex:(unsigned)theIndex
{
return GSIArrayItemAtIndex(_runs, (unsigned)theIndex).obj;
}
- (unsigned)indexOfObject:(id)anObject
{
return NSNotFound;
}
- (unsigned)indexOfObjectContainingLocation:(unsigned)aLocation
{
_GSRunSearchKey *aKey = [_GSRunSearchKey new];
int position;
aKey->glyphRange.location = aLocation;
position = GSIArrayInsertionPosition(_runs, (GSIArrayItem)aKey, aSort);
if (position >= 0 && position - 1 >= 0)
{
aKey = GSIArrayItemAtIndex(_runs, (unsigned)position - 1).obj;
if (NSLocationInRange(aLocation, aKey->glyphRange))
{
return (position - 1);
}
}
return -1;
}
- (id)objectContainingLocation:(unsigned)aLocation
{
_GSRunSearchKey *aKey = [_GSRunSearchKey new];
int position;
aKey->glyphRange.location = aLocation;
position = GSIArrayInsertionPosition(_runs, (GSIArrayItem)aKey, aSort);
if (position >= 0 && position - 1 >= 0)
{
aKey = GSIArrayItemAtIndex(_runs, (unsigned)position - 1).obj;
if (NSLocationInRange(aLocation, aKey->glyphRange))
{
return aKey;
}
}
return nil;
}
- (id)lastObject
{
return GSIArrayItemAtIndex(_runs, GSIArrayCount(_runs) - 1).obj;
}
- (int)count
{
return GSIArrayCount(_runs);
}
@end
@implementation NSLayoutManager
- (id) init
{
[super init];
_backgroundLayout = YES;
_delegate = nil;
_textContainers = [[NSMutableArray alloc] initWithCapacity: 2];
containerRuns = [GSRunStorage new];
fragmentRuns = [GSRunStorage new];
locationRuns = [GSRunStorage new];
return self;
}
@ -135,6 +394,23 @@
{
NSLog(@"NSLayoutManager was just notified that a change in the text
storage occured.");
/*
if (mask == NSTextStorageEditedCharacters)
{
aLayoutHole = [[NSLayoutHole alloc]
initWithCharacterRange:invalidatedRange isSoft:NO];
}
else if (mask == NSTextStorageEditedAttributes)
{
}
else if (mask == NSTextStorageEditedCharacters | NSTextStorageEditedAttributes)
{
}
*/
// invalidation should occure here.
[self _doLayout];
}
//
@ -220,6 +496,9 @@ storage occured.");
//
// Setting glyph attributes
//
// Each NSGlyph has an attribute field, yes?
- (void)setIntAttribute: (int)attribute
value: (int)anInt
forGlyphAtIndex: (unsigned)glyphIndex
@ -238,26 +517,55 @@ storage occured.");
- (void)setTextContainer: (NSTextContainer *)aTextContainer
forGlyphRange: (NSRange)glyphRange
{
GSTextContainerLayoutInfo *theLine = [GSTextContainerLayoutInfo new];
theLine->glyphRange = glyphRange;
ASSIGN(theLine->textContainer, aTextContainer);
[containerRuns insertObject:theLine];
}
- (NSRange)glyphRangeForTextContainer: (NSTextContainer *)aTextContainer
{
NSSize tcSize = [aTextContainer containerSize];
int i;
NSLog(@"glyphRangeForTextContainer: called. There are %d
textContainer(s) in containerRuns.", [containerRuns count]);
return NSMakeRange(0, 0);
for (i=0;i<[containerRuns count];i++)
{
GSTextContainerLayoutInfo *aNewLine = [containerRuns objectAtIndex:i];
NSLog(@"glyphRangeForTextContainer: (%d, %d)",
aNewLine->glyphRange.location,
aNewLine->glyphRange.length);
if ([aNewLine->textContainer isEqual:aTextContainer])
{
NSLog(@"glyphRangeForWantedTextContainer: (%d, %d)",
aNewLine->glyphRange.location,
aNewLine->glyphRange.length);
return aNewLine->glyphRange;
}
}
return NSMakeRange(NSNotFound, 0);
}
- (NSTextContainer *)textContainerForGlyphAtIndex: (unsigned)glyphIndex
effectiveRange: (NSRange *)effectiveRange
{
return nil;
}
GSTextContainerLayoutInfo *theLine = [containerRuns objectContainingLocation:glyphIndex];
- (NSRect)usedRectForTextContainer: (NSTextContainer *)aTextContainer
{
return NSZeroRect;
if(theLine)
{
(NSRange *)effectiveRange = &theLine->glyphRange;
return theLine->textContainer;
}
(NSRange *)effectiveRange = NULL;
return nil;
}
//
@ -267,17 +575,42 @@ storage occured.");
forGlyphRange: (NSRange)glyphRange
usedRect: (NSRect)usedRect
{
GSLineLayoutInfo *aNewLine = [GSLineLayoutInfo new];
aNewLine->glyphRange = glyphRange;
aNewLine->lineFragmentRect = fragmentRect;
aNewLine->usedRect = usedRect;
[fragmentRuns insertObject:aNewLine];
}
- (NSRect)lineFragmentRectForGlyphAtIndex: (unsigned)glyphIndex
effectiveRange: (NSRange *)lineFragmentRange
{
GSLineLayoutInfo *theLine = [fragmentRuns objectContainingLocation:glyphIndex];
if (theLine)
{
(NSRange *)lineFragmentRange = &theLine->glyphRange;
return theLine->lineFragmentRect;
}
(NSRange *)lineFragmentRange = NULL;
return NSZeroRect;
}
- (NSRect)lineFragmentUsedRectForGlyphAtIndex: (unsigned)glyphIndex
effectiveRange: (NSRange *)lineFragmentRange
{
GSLineLayoutInfo *theLine = [fragmentRuns objectContainingLocation:glyphIndex];
if (theLine)
{
(NSRange *)lineFragmentRange = &theLine->glyphRange;
return theLine->usedRect;
}
(NSRange *)lineFragmentRange = NULL;
return NSZeroRect;
}
@ -315,9 +648,16 @@ storage occured.");
//
// Layout of glyphs
//
- (void)setLocation: (NSPoint)aPoint
forStartOfGlyphRange: (NSRange)glyphRange
{
GSGlyphLocation *aNewLine = [GSGlyphLocation new];
aNewLine->glyphRange = glyphRange;
aNewLine->point = aPoint;
[locationRuns insertObject:aNewLine];
}
- (NSPoint)locationForGlyphAtIndex: (unsigned)glyphIndex
@ -327,7 +667,14 @@ storage occured.");
- (NSRange)rangeOfNominallySpacedGlyphsContainingIndex: (unsigned)glyphIndex
{
return NSMakeRange(0, 0);
GSLineLayoutInfo *theLine = [locationRuns objectContainingLocation:glyphIndex];
if (theLine)
{
return theLine->glyphRange;
}
return NSMakeRange(NSNotFound, 0);
}
- (NSRect *)rectArrayForCharacterRange: (NSRange)charRange
@ -335,7 +682,43 @@ storage occured.");
inTextContainer: (NSTextContainer *)aTextContainer
rectCount: (unsigned *)rectCount
{
return NULL;
/*
GSLineLayoutInfo *theLine = [GSLineLayoutInfo new];
int position, lastPosition;
int i, j = 0;
theLine->glyphRange.location = charRange.location;
position = GSIArrayInsertionPosition(lineFragments, (GSIArrayItem)theLine, aSort);
if (position < 0)
{
return NULL;
}
theLine->glyphRange.location = charRange.location + charRange.length;
lastPosition = GSIArrayInsertionPosition(lineFragments, (GSIArrayItem)theLine, aSort);
if (lastPosition > 0)
{
_cachedRectArray = NSZoneRealloc([self zone], _cachedRectArray,
(lastPosition - position) * sizeof(NSRect));
_cachedRectArrayCapacity = lastPosition - position;
for (i = position - 1; i < lastPosition - 1; i++)
{
GSLineLayoutInfo *aLine = GSIArrayItemAtIndex(lineFragments, i).obj;
_cachedRectArray[j] = aLine->lineFragmentRect;
j++;
}
}
(*rectCount) = (position - 1 + lastPosition - 1);
return _cachedRectArray;
*/
}
- (NSRect *)rectArrayForGlyphRange: (NSRange)glyphRange
@ -343,12 +726,41 @@ storage occured.");
inTextContainer: (NSTextContainer *)aTextContainer
rectCount: (unsigned *)rectCount
{
return NULL;
return _cachedRectArray;
}
- (NSRect)boundingRectForGlyphRange: (NSRange)glyphRange
inTextContainer: (NSTextContainer *)aTextContainer
{
/* Returns a single bounding rectangle enclosing all glyphs and other
marks drawn in aTextContainer for glyphRange, including glyphs that draw
outside their line fragment rectangles and text attributes such as
underlining. This method is useful for determining the area that needs to
be redrawn when a range of glyphs changes. */
/*
unsigned rectCount;
NSRect *rects = [self rectArrayForCharacterRange: [self glyphRangeForTextContainer:aTextContainer]
withinSelectedCharacterRange: NSMakeRange(0,0)
inTextContainer: aTextContainer
rectCount: &rectCount];
// NSPoint aOrigin = [aTextContainer originPoint];
NSRect rRect = NSZeroRect;
int i;
for (i=0;i<rectCount;i++)
{
NSRect aRect = rects[i];
if (aRect.origin.y == rRect.size.height)
rRect.size.height += aRect.size.width;
if (rRect.size.width == aRect.origin.x)
rRect.size.width += aRect.size.width;
}
return rRect;
*/
return NSZeroRect;
}
@ -425,6 +837,11 @@ fractionOfDistanceThroughGlyph: (float *)partialFraction
{
}
- (unsigned int)firstUnlaidCharacterIndex
{
return 0;
}
//
// Using screen fonts
//
@ -490,6 +907,54 @@ fractionOfDistanceThroughGlyph: (float *)partialFraction
- (void)drawGlyphsForGlyphRange: (NSRange)glyphRange
atPoint: (NSPoint)containerOrigin
{
int firstPosition, lastPosition, i;
for (i=0;i<[fragmentRuns count];i++)
{
GSLineLayoutInfo *info = [fragmentRuns objectAtIndex:i];
/*
NSLog(@"i: %d glyphRange: (%d, %d) lineFragmentRect: (%f, %f) (%f, %f)",
i,
info->glyphRange.location,
info->glyphRange.length,
info->lineFragmentRect.origin.x,
info->lineFragmentRect.origin.y,
info->lineFragmentRect.size.width,
info->lineFragmentRect.size.height);
*/
}
firstPosition = [fragmentRuns indexOfObjectContainingLocation:glyphRange.location];
lastPosition = [fragmentRuns
indexOfObjectContainingLocation:(glyphRange.location+glyphRange.length-2)];
NSLog(@"glyphRange: (%d, %d) position1: %d position2: %d",
glyphRange.location, glyphRange.length, firstPosition, lastPosition);
if (firstPosition >= 0)
{
if (lastPosition == -1)
{
lastPosition = [fragmentRuns count]; // FIXME
NSLog(@"fixed lastPosition: %d", lastPosition);
}
for (i = firstPosition; i < lastPosition; i++)
{
GSLineLayoutInfo *aLine = [fragmentRuns objectAtIndex:i];
/*
NSLog(@"drawRange: (%d, %d) inRect (%f, %f) (%f, %f)",
aLine->glyphRange.location,
aLine->glyphRange.length,
aLine->lineFragmentRect.origin.x,
aLine->lineFragmentRect.origin.y,
aLine->lineFragmentRect.size.width,
aLine->lineFragmentRect.size.height);
*/
[_textStorage drawRange:aLine->glyphRange inRect:aLine->lineFragmentRect];
}
}
}
- (void)drawUnderlineForGlyphRange: (NSRange)glyphRange
@ -523,3 +988,238 @@ fractionOfDistanceThroughGlyph: (float *)partialFraction
}
@end /* NSLayoutManager */
/* Thew methods laid out here are not correct, however the code they
contain for the most part is. Therefore, my country and a handsome gift of
Ghiradelli chocolate to he who puts all the pieces together :) */
@interface _GNUTextScanner:NSObject
{ NSString *string;
NSCharacterSet *set,*iSet;
unsigned stringLength;
NSRange activeRange;
}
+(_GNUTextScanner*) scannerWithString:(NSString*) aStr set:(NSCharacterSet*) aSet invertedSet:(NSCharacterSet*) anInvSet;
-(void) setString:(NSString*) aString set:(NSCharacterSet*) aSet invertedSet:(NSCharacterSet*) anInvSet;
-(NSRange) _scanCharactersInverted:(BOOL) inverted;
-(NSRange) scanSetCharacters;
-(NSRange) scanNonSetCharacters;
-(BOOL) isAtEnd;
-(unsigned) scanLocation;
-(void) setScanLocation:(unsigned) aLoc;
@end
@implementation NSLayoutManager (Private)
- (int)_rebuildLayoutForTextContainer:(NSTextContainer *)aContainer
startingAtGlyphIndex:(int)glyphIndex
{
NSSize cSize = [aContainer containerSize];
float i = 0.0;
NSMutableArray *lines = [NSMutableArray new];
int indexToAdd;
_GNUTextScanner *lineScanner;
_GNUTextScanner *paragraphScanner;
BOOL lastLineForContainerReached = NO;
NSString *aString;
int previousScanLocation;
int endScanLocation;
int startIndex;
NSRect firstProposedRect;
NSRect secondProposedRect;
NSFont *default_font = [NSFont systemFontOfSize: 12.0];
int widthOfString;
NSSize rSize;
NSCharacterSet *selectionParagraphGranularitySet = [NSCharacterSet characterSetWithCharactersInString:@"\n"];
NSCharacterSet *selectionWordGranularitySet = [NSCharacterSet characterSetWithCharactersInString:@" "];
NSCharacterSet *invSelectionWordGranularitySet = [selectionWordGranularitySet invertedSet];
NSCharacterSet *invSelectionParagraphGranularitySet = [selectionParagraphGranularitySet invertedSet];
NSRange paragraphRange;
NSRange leadingSpacesRange;
NSRange currentStringRange;
NSRange trailingSpacesRange;
NSRange leadingNlRange;
NSSize lSize;
float lineWidth = 0.0;
float ourLines = 0.0;
NSLog(@"rebuilding Layout at index: %d.\n", glyphIndex);
// 1.) figure out how many glyphs we can fit in our container by
// breaking up glyphs from the first unlaid out glyph and breaking it
// into lines.
//
// 2.)
// a.) set the range for the container
// b.) for each line in step 1 we need to set a lineFragmentRect and
// an origin point.
// Here we go at part 1.
startIndex = glyphIndex;
// lineScanner = [NSScanner scannerWithString:[_textStorage string]];
paragraphScanner = [_GNUTextScanner scannerWithString:[_textStorage string]
set:selectionParagraphGranularitySet invertedSet:invSelectionParagraphGranularitySet];
[paragraphScanner setScanLocation:startIndex];
NSLog(@"length of textStorage: %d", [[_textStorage string] length]);
// NSLog(@"buffer: %@", [_textStorage string]);
// This scanner eats one word at a time, we should have it imbeded in
// another scanner that snacks on paragraphs (i.e. lines that end with
// \n). Look in NSText.
while (![paragraphScanner isAtEnd])
{
// leadingNlRange=[paragraphScanner scanSetCharacters];
paragraphRange = [paragraphScanner scanNonSetCharacters];
leadingNlRange=[paragraphScanner scanSetCharacters];
if (leadingNlRange.length)
currentStringRange = NSUnionRange (leadingNlRange,paragraphRange);
NSLog(@"paragraphRange: (%d, %d)", paragraphRange.location, paragraphRange.length);
NSLog(@"======> begin paragraph");
lineScanner = [_GNUTextScanner scannerWithString:[[_textStorage string] substringWithRange:paragraphRange]
set:selectionWordGranularitySet invertedSet:invSelectionWordGranularitySet];
while(![lineScanner isAtEnd])
{
previousScanLocation = [lineScanner scanLocation];
// snack next word
leadingSpacesRange = [lineScanner scanSetCharacters]; // leading spaces: only first time
currentStringRange = [lineScanner scanNonSetCharacters];
trailingSpacesRange= [lineScanner scanSetCharacters];
if (leadingSpacesRange.length)
currentStringRange = NSUnionRange (leadingSpacesRange,currentStringRange);
if (trailingSpacesRange.length)
currentStringRange = NSUnionRange (trailingSpacesRange,currentStringRange);
lSize = [_textStorage sizeRange:currentStringRange];
if (lineWidth + lSize.width < cSize.width)
{
if ([lineScanner isAtEnd])
{
NSLog(@"we are at end before finishing a line: %d.\n", [lineScanner scanLocation]);
[lines addObject:[NSNumber numberWithInt:(int)[lineScanner scanLocation] + paragraphRange.location]];
}
lineWidth += lSize.width;
NSLog(@"lineWidth: %f", lineWidth);
}
else
{
if (ourLines > cSize.height)
{
lastLineForContainerReached = YES;
break;
}
[lineScanner setScanLocation:previousScanLocation];
indexToAdd = previousScanLocation + paragraphRange.location;
ourLines += 14.0;
lineWidth = 0;
NSLog(@"indexToAdd: %d\tourLines: %f", indexToAdd, ourLines);
[lines addObject:[NSNumber numberWithInt:indexToAdd]];
}
}
if (lastLineForContainerReached)
break;
}
endScanLocation = [lineScanner scanLocation] + paragraphRange.location;
NSLog(@"endScanLocation: %d", endScanLocation);
// set this container for that glyphrange
[self setTextContainer:aContainer
forGlyphRange:NSMakeRange(startIndex, endScanLocation - startIndex)];
NSLog(@"ok, move on to step 2.");
// step 2. break the lines up and assign rects to them.
for (i=0;i<[lines count];i++)
{
NSRect aRect, *bRect;
float padding = [aContainer lineFragmentPadding];
NSRange ourRange;
NSLog(@"\t\t===> %d", [[lines objectAtIndex:i] intValue]);
if (i == 0)
{
ourRange = NSMakeRange (startIndex,
[[lines objectAtIndex:i] intValue] - startIndex);
}
else
{
ourRange = NSMakeRange ([[lines objectAtIndex:i-1] intValue],
[[lines objectAtIndex:i] intValue] - [[lines objectAtIndex:i-1]
intValue]);
}
firstProposedRect = NSMakeRect (0, i * 14, cSize.width, 14);
// ask our textContainer to fix our lineFragment.
secondProposedRect = [aContainer lineFragmentRectForProposedRect:firstProposedRect
sweepDirection: NULL
movementDirection: NULL
remainingRect: &bRect];
// set the line fragmentRect for this range.
[self setLineFragmentRect: secondProposedRect
forGlyphRange: ourRange
usedRect: aRect];
// set the location for this string to be 'show'ed.
[self setLocation:NSMakePoint(secondProposedRect.origin.x + padding,
secondProposedRect.origin.y + padding)
forStartOfGlyphRange: ourRange];
}
// bloody hack.
// if (moreText)
// [delegate layoutManager:self
// didCompleteLayoutForTextContainer:[textContainers objectAtIndex:i]
// atEnd:NO];
// else
// [delegate layoutManager:self
// didCompleteLayoutForTextContainer:[textContainers objectAtIndex:i]
// atEnd:YES];
[lines release];
return endScanLocation;
}
- (void)_doLayout
{
int i;
BOOL moreText;
int gIndex = 0;
NSLog(@"doLayout called.\n");
for (i=0;i<[_textContainers count];i++)
{
gIndex = [self _rebuildLayoutForTextContainer:[_textContainers objectAtIndex:i]
startingAtGlyphIndex:gIndex];
}
}
@end

View file

@ -50,9 +50,12 @@
#include <AppKit/NSMenuItemCell.h>
#include <AppKit/NSPopUpButton.h>
#include <AppKit/NSPopUpButtonCell.h>
#include <AppKit/NSScreen.h>
static NSZone *menuZone = NULL;
static NSString* NSMenuLocationsKey = @"NSMenuLocations";
@implementation NSMenu
// Class Methods
@ -174,12 +177,10 @@ static NSZone *menuZone = NULL;
[[aWindow contentView] addSubview:titleView];
[titleView setMenu: self];
/*
[defaultCenter addObserver: self
selector: @selector(_showTornOffMenuIfAny:)
name: NSApplicationWillFinishLaunchingNotification
object: theApp];
*/
[defaultCenter addObserver: self
selector: @selector(_deactivate:)
name: NSApplicationWillResignActiveNotification
@ -383,7 +384,7 @@ static NSZone *menuZone = NULL;
- (int) indexOfItem: (id <NSMenuItem>)anObject
{
if (![(NSMenuItemCell *)anObject isKindOfClass: [NSMenuItemCell class]]
|| [(id)anObject isKindOfClass: [NSPopUpButtonCell class]])
|| ![(id)anObject isKindOfClass: [NSPopUpButtonCell class]])
{
NSLog(@"You must use an NSMenuItemCell, or a derivative thereof.\n");
return -1;
@ -429,11 +430,23 @@ static NSZone *menuZone = NULL;
return i;
}
}
return -1;
}
- (int) indexOfItemWithSubmenu: (NSMenu *)anObject
{
int i;
for (i=0;i<[menu_items count];i++)
{
if ([[[menu_items objectAtIndex:i] title]
isEqual:[anObject title]])
{
return i;
}
}
return -1;
}
@ -586,6 +599,9 @@ static NSZone *menuZone = NULL;
if (shouldBeEnabled != wasEnabled)
{
[cell setEnabled: shouldBeEnabled];
[[self window] flushWindow];
// [menu_view setNeedsDisplay:YES];
// [menu_view setNeedsDisplayInRect:[menu_view rectOfItemAtIndex:i]];
// FIXME
// [menuCells setNeedsDisplayInRect: [menuCells cellFrameAtRow: i]];
}
@ -703,10 +719,38 @@ static NSZone *menuZone = NULL;
[titleView setFrameOrigin: NSMakePoint(0, mFrame.size.height)];
[titleView setFrameSize: NSMakeSize (mFrame.size.width,21)];
size.height = mFrame.size.height+21;
[bWindow setFrame: NSMakeRect(300,300,size.width,size.height)
display: NO];
[aWindow setFrame: NSMakeRect(300,300,size.width,size.height)
display: YES];
[aWindow setContentSize: size];
[bWindow setContentSize: size];
/*
if (menu_supermenu)
{
frame.origin = [supermenu locationForSubmenu: self];
}
else
{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSDictionary* menuLocations = [defaults
objectForKey: NSMenuLocationsKey];
NSString* key;
NSArray* array;
if ([[NSApplication sharedApplication] mainMenu] == self)
key = @"Main menu";
else
key = [self title];
if (key)
{
array = [menuLocations objectForKey: key];
if (array && [array isKindOfClass: [NSArray class]])
{
frame.origin.x = [[array objectAtIndex: 0] floatValue];
frame.origin.y = [[array objectAtIndex: 1] floatValue];
}
}
}
*/
}
else
{
@ -754,6 +798,30 @@ static NSZone *menuZone = NULL;
[aWindow orderOut:nil];
}
- (void)_showTornOffMenuIfAny: (NSNotification*)notification
{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSDictionary* menuLocations = [defaults objectForKey: NSMenuLocationsKey];
NSString* key;
NSArray* array;
if ([[NSApplication sharedApplication] mainMenu] == self)
key = nil; // Ignore the main menu
else
key = [self title];
if (key)
{
array = [menuLocations objectForKey: key];
if (array && [array isKindOfClass: [NSArray class]])
{
[titleView windowBecomeTornOff];
[self _setTornOff:YES];
[self display];
}
}
}
- (BOOL) isFollowTransient
{
return menu_follow_transient;
@ -762,27 +830,90 @@ static NSZone *menuZone = NULL;
- (void) _setTornOff:(BOOL)flag
{
menu_is_tornoff = flag;
[[[self supermenu] menuView] setHighlightedItemIndex:-1];
/*
if (flag)
{
if (menu_supermenu)
{
menu_supermenu->menu_attached_menu = nil;
menu_supermenu = nil;
}
}
*/
}
- (void) _performMenuClose:(id)sender
{
NSUserDefaults* defaults;
NSMutableDictionary* menuLocations;
NSString* key;
[self _setTornOff:NO];
[self close];
[titleView _releaseCloseButton];
defaults = [NSUserDefaults standardUserDefaults];
menuLocations = [[[defaults objectForKey: NSMenuLocationsKey]
mutableCopy] autorelease];
key = [self title]; // Remove window's position$
if (key) // info from defaults db
{
[menuLocations removeObjectForKey: key];
[defaults setObject: menuLocations forKey: NSMenuLocationsKey];
[defaults synchronize];
}
}
- (void) display
{
if (menu_changed)
[self sizeToFit];
if (menu_supermenu) // query super menu for
{ // position
if (menu_supermenu && ![self isTornOff]) // query super menu for
{ // position
NSPoint location = [menu_supermenu locationForSubmenu: self];
[aWindow setFrameOrigin: location];
menu_supermenu->menu_attached_menu = self;
}
}
else
{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSDictionary* menuLocations = [defaults
objectForKey: NSMenuLocationsKey];
NSString* key;
NSArray* array;
NSPoint origin;
if ([[NSApplication sharedApplication] mainMenu] == self)
key = @"Main menu";
else
key = [self title];
if (key)
{
array = [menuLocations objectForKey: key];
if (array && [array isKindOfClass: [NSArray class]])
{
origin.x = [[array objectAtIndex: 0] floatValue];
origin.y = [[array objectAtIndex: 1] floatValue];
[aWindow setFrameOrigin: origin];
}
else
{
float aPoint = [[NSScreen mainScreen] frame].size.height - [aWindow frame].size.height;
[aWindow setFrameOrigin:NSMakePoint(0,aPoint)];
[bWindow setFrameOrigin:NSMakePoint(0,aPoint)];
}
}
}
[self submenuAction: nil];
menu_is_visible = YES;
[aWindow orderFront:nil];
@ -883,6 +1014,13 @@ static NSZone *menuZone = NULL;
- (void) mouseDown: (NSEvent*)theEvent
{
NSUserDefaults *defaults;
NSMutableDictionary *menuLocations;
NSMenu *appMainMenu;
NSPoint origin;
NSArray* array;
NSString* key;
NSPoint lastLocation;
NSPoint location;
unsigned eventMask = NSLeftMouseUpMask | NSLeftMouseDownMask
@ -958,7 +1096,27 @@ static NSZone *menuZone = NULL;
}
}
[NSEvent stopPeriodicEvents];
// save position code goes here. FIXME.
appMainMenu = [NSApp mainMenu];
defaults = [NSUserDefaults standardUserDefaults];
menuLocations = [[[defaults objectForKey: NSMenuLocationsKey] mutableCopy] autorelease];
if (!menuLocations)
menuLocations = [NSMutableDictionary dictionaryWithCapacity: 2];
origin = [[menu window] frame].origin;
array = [NSArray arrayWithObjects:
[[NSNumber numberWithInt: origin.x] stringValue],
[[NSNumber numberWithInt: origin.y] stringValue], nil];
if (menu == appMainMenu)
key = @"Main menu";
else
key = [menu title]; // Save menu window pos
[menuLocations setObject: array forKey: key]; // in defaults databa
[defaults setObject: menuLocations forKey: NSMenuLocationsKey];
[defaults synchronize];
}
- (void) windowBecomeTornOff

View file

@ -595,10 +595,18 @@ static float GSMenuBarHeight = 25.0; // a guess.
}
else
{
[self setHighlightedItemIndex: -1];
lastIndex = index;
weWereOut = YES;
[window flushWindow];
if (![[menuv_items_link objectAtIndex: lastIndex] hasSubmenu])
{
[self setHighlightedItemIndex: -1];
lastIndex = index;
weWereOut = YES;
[window flushWindow];
}
else
{
weLeftMenu = YES;
done = YES;
}
}
}

View file

@ -158,10 +158,14 @@
{
int i;
[[popb_menu itemArray] removeAllObjects];
/*
for (i=0;i<[self numberOfItems];i++)
{
[popb_menu removeItemAtIndex:i];
}
*/
[self synchronizeTitleAndSelectedItem];
}
@ -196,7 +200,9 @@
- (int)indexOfSelectedItem
{
// FIXME
if (popb_selectedItem >= 0)
return popb_selectedItem;
return -1;
}
@ -304,8 +310,25 @@
return -1;
}
- (int)setTitle:(NSString *)aString
- (void)setTitle:(NSString *)aString
{
if (!popb_pullsDown)
{
int aIndex = [self indexOfItemWithTitle:aString];
if (aIndex >= 0)
popb_selectedItem = aIndex;
else
{
[self addItemWithTitle:aString];
popb_selectedItem = [self indexOfItemWithTitle:aString];
[self setNeedsDisplay:YES];
}
}
else
{
[self setNeedsDisplay:YES];
}
}
- (SEL)action
@ -330,25 +353,33 @@
- (void)_buttonPressed:(id)sender
{
if (!popb_pullsDown)
popb_selectedItem = [self indexOfItemWithRepresentedObject:[sender representedObject]];
else
popb_selectedItem = 0;
popb_selectedItem = [self indexOfItemWithRepresentedObject:[sender representedObject]];
[self synchronizeTitleAndSelectedItem];
[self lockFocus];
[self drawRect:[self frame]];
[self unlockFocus];
[self setNeedsDisplay:YES];
if (pub_target && pub_action)
[pub_target performSelector:pub_action withObject:self];
if (popb_pullsDown)
popb_selectedItem = 0;
}
- (void)synchronizeTitleAndSelectedItem
{
// urph
if (popb_selectedItem > [self numberOfItems] - 1)
{
popb_selectedItem = 0;
}
[self sizeToFit];
}
- (void)sizeToFit
{
[[popb_menu menuView] sizeToFit];
}
- (void)_popup:(NSNotification*)notification

View file

@ -6,6 +6,14 @@
#include <AppKit/NSText.h>
@implementation NSTableView
+ (void) initialize
{
if (self == [NSTableView class])
{
[self setVersion: 1];
}
}
- (id)initWithFrame:(NSRect)frameRect
{
self = [super initWithFrame:frameRect];

View file

@ -252,12 +252,14 @@ static NSRange MakeRangeFromAbs(int a1,int a2)
// end: _GNUTextScanner implementation--------------------------------------
/*
@interface NSAttributedString(DrawingAddition)
-(NSSize) sizeRange:(NSRange) aRange;
-(void) drawRange:(NSRange) aRange atPoint:(NSPoint) aPoint;
-(void) drawRange:(NSRange) aRange inRect:(NSRect) aRect;
-(BOOL) areMultipleFontsInRange:(NSRange) aRange;
@end
*/
@implementation NSAttributedString(DrawingAddition)
-(NSSize) sizeRange:(NSRange) lineRange
@ -291,6 +293,16 @@ static NSRange MakeRangeFromAbs(int a1,int a2)
}
}
-(void) drawRange:(NSRange) aRange inRect:(NSRect) aRect;
{
NSString *substring=[[self string] substringWithRange:aRange];
[substring drawInRect:aRect withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[NSFont systemFontOfSize:12.0],NSFontAttributeName,
[NSColor blueColor],NSForegroundColorAttributeName,
nil]];
}
-(BOOL) areMultipleFontsInRange:(NSRange) aRange
{ NSRange longestRange;
[self attribute:NSFontAttributeName atIndex:aRange.location longestEffectiveRange:&longestRange inRange:aRange];
@ -431,10 +443,15 @@ static NSRange MakeRangeFromAbs(int a1,int a2)
[self setSelectedRange:NSMakeRange(0,0)];
return self;
}
-(NSDictionary*) defaultTypingAttributes
{ return [NSDictionary dictionaryWithObjectsAndKeys: default_font,NSFontAttributeName,
text_color,NSForegroundColorAttributeName,
nil];
{
return [NSDictionary dictionaryWithObjectsAndKeys:
default_font,NSFontAttributeName,
text_color,NSForegroundColorAttributeName,
nil];
}
/*

View file

@ -97,7 +97,10 @@ changeInLength: [attributedString length] - aRange.length];
- (void) addLayoutManager: (NSLayoutManager*)obj
{
if ([layoutManagers indexOfObjectIdenticalTo: obj] == NSNotFound)
[layoutManagers addObject: obj];
{
[layoutManagers addObject: obj];
[obj setTextStorage:self];
}
}
- (void) removeLayoutManager: (NSLayoutManager*)obj

View file

@ -58,6 +58,7 @@
textStorage = [[NSTextStorage alloc] init];
layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
[layoutManager release];
@ -141,7 +142,15 @@
- (void)setNeedsDisplayInRect:(NSRect)aRect
avoidAdditionalLayout:(BOOL)flag
{
// FIXME.
/*
NSRange glyphsToDraw = [layoutManager
glyphRangeForTextContainer:textContainer];
[self lockFocus];
[layoutManager drawGlyphsForGlyphRange:glyphsToDraw
atPoint:[self frame].origin];
[self unlockFocus];
*/
}
/* We override NSView's setNeedsDisplayInRect: */
@ -284,7 +293,7 @@ aRect.size.height);
- (void)setSelectedRange:(NSRange)charRange
{
NSLog(@"setSelectedRange");
NSLog(@"setSelectedRange (%d, %d)", charRange.location, charRange.length);
/*
[[NSNotificationCenter defaultCenter]
postNotificationName:NSTextViewDidChangeSelectionNotification
@ -906,7 +915,15 @@ container, returning the modified location. */
initWithString: string
attributes: [self typingAttributes]] autorelease];
[textStorage insertAttributedString:aString atIndex:0];
// [textStorage replaceRange:NSMakeRange(0, [string length])
// withString:aString];
[textStorage setAttributedString: aString];
//replaceCharactersInRange:NSMakeRange(0, [string length])
// withAttributedString: aString];
// [textStorage insertAttributedString:aString atIndex:0];
}
-(void) setText:(NSString *)string {[self setString:string];}
@ -916,8 +933,8 @@ container, returning the modified location. */
NSLog(@"%@", aString);
if (![aString isKindOfClass:[NSAttributedString class]])
aString = [[[NSAttributedString alloc] initWithString:aString
attributes:[self typingAttributes]] autorelease];
aString = [[NSAttributedString alloc] initWithString:aString
attributes:[self typingAttributes]];
[textStorage replaceCharactersInRange:[self selectedRange]
withAttributedString:(NSAttributedString *)aString];
@ -930,7 +947,14 @@ container, returning the modified location. */
- (void)drawRect:(NSRect)aRect
{
[textStorage drawRange:[self selectedRange] atPoint:aRect.origin.x];
if(tv_backGroundColor)
{
[tv_backGroundColor set];
NSRectFill (aRect);
}
[layoutManager drawGlyphsForGlyphRange:[layoutManager glyphRangeForTextContainer: textContainer]
atPoint: [self frame].origin];
}
/*