mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-22 13:10:59 +00:00
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:
parent
1fc4e353c9
commit
a73d9b885a
12 changed files with 1035 additions and 49 deletions
24
ChangeLog
24
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ****************************/
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <Foundation/Foundation.h>
|
||||
#include <AppKit/NSControl.h>
|
||||
|
||||
@class NSColor;
|
||||
@class NSTableColumn;
|
||||
@class NSTableHeaderView;
|
||||
@class NSView;
|
||||
|
|
|
@ -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
|
||||
|
|
178
Source/NSMenu.m
178
Source/NSMenu.m
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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];
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue