Text field updates.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@4014 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 1999-04-01 20:21:05 +00:00
parent 01a589ed94
commit 6935a9df0a
6 changed files with 437 additions and 73 deletions

View file

@ -1,3 +1,10 @@
Thu Apr 1 20:45:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSTextField.m: init with same default values as OPENSTEP
* Source/NSPanel.m: Tidied.
* Source/NSStringDrawing.m: First go at support for paragraph styles,
tabs, and kerning.
Thu Apr 1 10:00:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Model/GMAppKit.m: Added patch supplied by Jonathan Gapen

View file

@ -384,7 +384,7 @@ static GSAlertPanel *gmodelAlertPanel = nil;
NSViewWidthSizable | NSViewHeightSizable | NSViewMaxYMargin];
[messageField setEditable: NO];
[messageField setSelectable: NO];
[messageField setBordered: NO];
[messageField setBezeled: NO];
[messageField setDrawsBackground: NO];
[messageField setAlignment: NSCenterTextAlignment];
[messageField setStringValue: @""];
@ -398,7 +398,7 @@ static GSAlertPanel *gmodelAlertPanel = nil;
[titleField setAutoresizingMask: NSViewWidthSizable | NSViewMinYMargin];
[titleField setEditable: NO];
[titleField setSelectable: NO];
[titleField setBordered: NO];
[titleField setBezeled: NO];
[titleField setDrawsBackground: NO];
[titleField setStringValue: @""];
[titleField setFont: [NSFont systemFontOfSize: 18.0]];
@ -684,6 +684,7 @@ NSRunAlertPanel(NSString *title,
standardAlertPanel = panel;
}
[panel center];
result = [panel runModal];
NSReleaseAlertPanel(panel);
return result;
@ -705,6 +706,7 @@ NSRunCriticalAlertPanel(NSString *title,
defaultButton, alternateButton, otherButton, ap);
va_end (ap);
[panel center];
result = [panel runModal];
NSReleaseAlertPanel(panel);
return result;
@ -726,6 +728,7 @@ NSRunInformationalAlertPanel(NSString *title,
defaultButton, alternateButton, otherButton, ap);
va_end (ap);
[panel center];
result = [panel runModal];
NSReleaseAlertPanel(panel);
return result;
@ -788,6 +791,7 @@ NSRunLocalizedAlertPanel(NSString *table,
standardAlertPanel = panel;
}
[panel center];
result = [panel runModal];
NSReleaseAlertPanel(panel);
return result;

View file

@ -1,13 +1,11 @@
/*
NSStringDrawing.m
Categories which add measure capabilities to NSAttributedString
Categories which add drawing capabilities to NSAttributedString
and NSString.
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1999 Free Software Foundation, Inc.
Author: Felipe A. Rodriguez <far@ix.netcom.com>
Date: Aug 1998
Author: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Date: Mar 1999 - rewrite from scratch
@ -76,7 +74,213 @@
@implementation NSAttributedString (NSStringDrawing)
static NSCharacterSet *nlset = nil;
static NSCharacterSet *nlset;
static NSFont *defFont;
static NSParagraphStyle *defStyle;
static NSColor *defFgCol;
static NSColor *defBgCol;
/*
* Thne 'checkInit()' function is called to ensure that any static
* variables required by the string drawing code are initialised.
*/
static void
checkInit()
{
static BOOL beenHere = NO;
if (beenHere == NO)
{
NSCharacterSet *not_ws;
NSMutableCharacterSet *new_set;
/*
* Build a character set containing only newline characters.
*/
not_ws = [[NSCharacterSet whitespaceCharacterSet] invertedSet];
new_set = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy];
[new_set formIntersectionWithCharacterSet: not_ws];
nlset = [new_set copy];
[new_set release];
defStyle = [NSParagraphStyle defaultParagraphStyle];
[defStyle retain];
defBgCol = nil;
beenHere = YES;
}
/*
* These defaults could change during the running of the program if the
* user defaults are changed.
*/
defFont = [NSFont userFontOfSize: 12];
defFgCol = [NSColor textColor];
}
/*
* The 'sizeLine()' function is called to determine the size of a single
* line of text (specified by the 'range' argument) that may be part of
* a larger attributed string.
* If will also return the position of the baseline of the text within
* the bounding rectangle as an offset from the bottom of the rectangle.
*/
static NSSize
sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
{
unsigned pos = line.location;
unsigned end = NSMaxRange(line);
NSSize size = NSMakeSize(0, 0);
float baseline = 0;
while (pos < end)
{
NSFont *font;
NSParagraphStyle *style;
int superscript;
int ligature;
float base;
float kern;
NSNumber *num;
NSRange maxRange;
NSRange range;
float below;
float above;
// Maximum range is up to end of line.
maxRange = NSMakeRange(pos, end - pos);
// Get font and range over which it applies.
font = (NSFont*)[str attribute: NSFontAttributeName
atIndex: pos
effectiveRange: &range];
if (font == nil)
font = defFont;
maxRange = NSIntersectionRange(maxRange, range);
// Get style and range over which it applies.
style = (NSParagraphStyle*)[str attribute: NSParagraphStyleAttributeName
atIndex: pos
effectiveRange: &range];
if (style == nil)
style = defStyle;
maxRange = NSIntersectionRange(maxRange, range);
/*
* Perform initial horizontal positioning
*/
if (pos == line.location)
{
if (first)
size.width = [style firstLineHeadIndent];
else
size.width = [style headIndent];
}
// Get baseline offset and range over which it applies.
num = (NSNumber*)[str attribute: NSBaselineOffsetAttributeName
atIndex: pos
effectiveRange: &range];
if (num == nil)
base = 0.0;
else
base = [num floatValue];
maxRange = NSIntersectionRange(maxRange, range);
// Get kern attribute and range over which it applies.
num = (NSNumber*)[str attribute: NSKernAttributeName
atIndex: pos
effectiveRange: &range];
if (num == nil)
kern = 0.0;
else
kern = [num floatValue];
maxRange = NSIntersectionRange(maxRange, range);
// Get superscript and range over which it applies.
num = (NSNumber*)[str attribute: NSSuperscriptAttributeName
atIndex: pos
effectiveRange: &range];
if (num == nil)
superscript = 0;
else
superscript = [num intValue];
maxRange = NSIntersectionRange(maxRange, range);
// Get ligature attribute and range over which it applies.
num = (NSNumber*)[str attribute: NSLigatureAttributeName
atIndex: pos
effectiveRange: &range];
if (num == nil)
ligature = 1;
else
ligature = [num intValue];
maxRange = NSIntersectionRange(maxRange, range);
/*
* See if the height of the bounding rectangle needs to grow to fit
* the font for this text.
*/
// FIXME - superscript should have some effect on height.
below = [font descender];
above = [font pointSize] - below;
if (base > 0)
above += base; // Character is above baseline.
else if (base < 0)
below -= base; // Character is below baseline.
if (below > baseline)
baseline = below;
if (size.height < baseline + above)
size.height = baseline + above;
/*
* Now we add the widths of the characters.
*/
// FIXME - ligature should have some effect on width.
range = maxRange;
pos = NSMaxRange(range); // Next position in string.
if (range.length > 0)
{
unichar chars[range.length];
NSArray *tabStops = [style tabStops];
unsigned numTabs = [tabStops count];
unsigned nextTab = 0;
unsigned i;
[[str string] getCharacters: chars range: range];
for (i = 0; i < range.length; i++)
{
if (chars[i] == '\t')
{
NSTextTab *tab;
/*
* Either advance to next tabstop or by a space if
* there are no more tabstops.
*/
while (nextTab < numTabs)
{
tab = [tabStops objectAtIndex: nextTab];
if ([tab location] > size.width)
break;
nextTab++;
}
if (nextTab < numTabs)
size.width = [tab location];
else
size.width += [font advancementForGlyph: ' '].width;
}
else
{
size.width += [font advancementForGlyph: chars[i]].width;
size.width += kern;
}
}
}
}
if (baseptr)
*baseptr = baseline;
return size;
}
/* FIXME completely ignores paragraph style attachments and other layout info */
- (void) drawAtPoint: (NSPoint)point
@ -85,27 +289,11 @@ static NSCharacterSet *nlset = nil;
NSString *allText = [self string];
unsigned length = [allText length];
unsigned linePos = 0;
NSFont *defFont = [NSFont userFontOfSize: 12];
NSParagraphStyle *defStyle = [NSParagraphStyle defaultParagraphStyle];
NSColor *defFgCol = [NSColor textColor];
NSColor *defBgCol = nil;
BOOL isFlipped = [[ctxt focusView] isFlipped];
NSPoint start = point;
NSParagraphStyle *style = nil;
BOOL first = YES;
/*
* Build a character set containing only newline characters if necessary.
*/
if (nlset == nil)
{
NSCharacterSet *not_ws;
NSMutableCharacterSet *new_set;
not_ws = [[NSCharacterSet whitespaceCharacterSet] invertedSet];
new_set = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy];
[new_set formIntersectionWithCharacterSet: not_ws];
nlset = [new_set copy];
[new_set release];
}
checkInit();
/*
* Now produce output on a per-line basis.
@ -114,8 +302,10 @@ static NSCharacterSet *nlset = nil;
{
NSRange line; // Range of current line.
NSRange eol; // Rnage of newline character.
float lineHeight; // Height of text in this line.
unsigned position; // Position in NSString.
NSSize lineSize;
float baseline;
float xpos = 0;
/*
* Determine the range of the next line of text (in 'line') and set
@ -133,13 +323,72 @@ static NSCharacterSet *nlset = nil;
linePos = NSMaxRange(eol);
position = line.location;
if (first == NO)
{
NSParagraphStyle *newStyle;
NSColor *bg;
float leading;
/*
* Check to see if the new line begins with the same paragraph style
* that the old ended in. This information is used to handle what
* happens between lines and whether the new line is also a new
* paragraph.
*/
newStyle = (NSParagraphStyle*)[self
attribute: NSParagraphStyleAttributeName
atIndex: position
effectiveRange: 0];
if ([style isEqual: newStyle])
{
leading = [style lineSpacing];
}
else
{
leading = [style paragraphSpacing];
first = YES;
}
if (isFlipped)
point.y -= leading;
else
point.y += leading;
/*
* Fill the inter-line/interparagraph space with the background
* color in use at the end of the last paragraph.
*/
bg = (NSColor*)[self attribute: NSBackgroundColorAttributeName
atIndex: position - 1
effectiveRange: 0];
if (bg == nil)
bg = defBgCol;
if (bg != nil)
{
NSRect fillrect;
fillrect.origin = point;
fillrect.size.width = lineSize.width;
fillrect.size.height = leading;
[bg set];
if (isFlipped == NO)
fillrect.origin.y -= fillrect.size.height;
NSRectFill(fillrect);
}
}
/*
* Calculate sizing information for the entire line.
*/
lineSize = sizeLine(self, line, first, &baseline);
while (position < eol.location)
{
NSAttributedString *subAttr;
NSString *subString;
NSSize size;
NSFont *font;
NSParagraphStyle *style;
NSColor *bg;
NSColor *fg;
int underline;
@ -164,13 +413,14 @@ static NSCharacterSet *nlset = nil;
maxRange = NSIntersectionRange(maxRange, range);
// Get style and range over which it applies.
style = (NSParagraphStyle*)[self attribute: NSParagraphStyleAttributeName
style = (NSParagraphStyle*)[self
attribute: NSParagraphStyleAttributeName
atIndex: position
effectiveRange: &range];
if (style == nil)
style = defStyle;
maxRange = NSIntersectionRange(maxRange, range);
// Get background color and range over which it applies.
bg = (NSColor*)[self attribute: NSBackgroundColorAttributeName
atIndex: position
@ -237,6 +487,31 @@ static NSCharacterSet *nlset = nil;
ligature = [num intValue];
maxRange = NSIntersectionRange(maxRange, range);
/*
* If this is a new line - adjust for indentation.
*/
if (position == line.location)
{
NSRect fillrect;
fillrect.origin = point;
fillrect.size = lineSize;
if (first)
xpos = [style firstLineHeadIndent];
else
xpos += [style headIndent];
fillrect.size.width = xpos;
if (bg != nil && fillrect.size.width > 0)
{
[bg set];
if (isFlipped == NO)
fillrect.origin.y -= fillrect.size.height;
NSRectFill(fillrect);
}
}
/*
* Now, at last we have all the required text drawing attributes and
* we have a range over which ALL of them apply. We update our
@ -250,52 +525,132 @@ static NSCharacterSet *nlset = nil;
size.width = [font widthOfString: subString];
size.height = [font pointSize];
lineHeight = size.height;
/*
* If we have a background color set - we fill in the
* region occupied by this substring.
*/
if (bg)
if (range.length > 0)
{
NSRect rect;
unichar chars[range.length];
NSArray *tabStops = [style tabStops];
unsigned numTabs = [tabStops count];
unsigned nextTab = 0;
unsigned i;
rect.origin = point;
rect.size = size;
if (isFlipped == NO)
rect.origin.y -= size.height;
[[self string] getCharacters: chars range: range];
[bg set];
NSRectFill(rect);
/*
* If we have a background color set - we fill in the
* region occupied by this substring.
*/
if (bg)
{
float oldx = xpos;
NSRect rect;
for (i = 0; i < range.length; i++)
{
if (chars[i] == '\t')
{
NSTextTab *tab;
/*
* Either advance to next tabstop or by a space
* if there are no more tabstops.
*/
while (nextTab < numTabs)
{
tab = [tabStops objectAtIndex: nextTab];
if ([tab location] > xpos)
break;
nextTab++;
}
if (nextTab < numTabs)
xpos = [tab location];
else
xpos += [font advancementForGlyph: ' '].width;
}
else
{
xpos += [font advancementForGlyph: chars[i]].width;
xpos += kern;
}
}
rect.origin.x = point.x + oldx;
rect.origin.y = point.y;
rect.size.height = lineSize.height;
rect.size.width = xpos - oldx;
xpos = oldx;
if (isFlipped == NO)
rect.origin.y -= lineSize.height;
[bg set];
NSRectFill(rect);
}
/*
* Set font and color, then draw the substring.
* NB. Our origin is top-left of the string so we need to
* calculate a vertical coordinate for the baseline of the
* text produced by psshow.
*/
[fg set];
[font set];
if (isFlipped)
ypos = point.y + lineSize.height - baseline - base;
else
ypos = point.y - lineSize.height + baseline + base;
for (i = 0; i < range.length; i++)
{
if (chars[i] == '\t')
{
NSTextTab *tab;
/*
* Either advance to next tabstop or by a space
* if there are no more tabstops.
*/
while (nextTab < numTabs)
{
tab = [tabStops objectAtIndex: nextTab];
if ([tab location] > xpos)
break;
nextTab++;
}
if (nextTab < numTabs)
xpos = [tab location];
else
xpos += [font advancementForGlyph: ' '].width;
}
else
{
char buf[2];
xpos += kern;
DPSmoveto(ctxt, point.x + xpos, ypos);
/*
* FIXME Eugh - we simply assume that the unichar string
* actually contains ascii characters and render them
* using dpsshow
*/
buf[0] = chars[i];
buf[1] = '\0';
DPSshow(ctxt, buf);
xpos += [font advancementForGlyph: chars[i]].width;
}
}
}
/*
* Set font and color, then draw the substring.
* NB. Our origin is top-left of the string so we need to
* calculate a vertical coordinate for the baseline of the
* text produced by psshow.
*/
if (isFlipped)
ypos = point.y + size.height - [font descender];
else
ypos = point.y - size.height + [font descender];
[fg set];
[font set];
DPSmoveto(ctxt, point.x, ypos);
DPSshow(ctxt, [subString cString]);
if (underline == NSSingleUnderlineStyle)
{
DPSmoveto(ctxt, point.x, ypos);
DPSlineto(ctxt, point.x + size.width - 1, ypos);
DPSlineto(ctxt, point.x + xpos - 1, ypos);
}
point.x += size.width; // Next point to draw from.
}
point.x = start.x;
if (isFlipped)
point.y += lineHeight;
point.y += lineSize.height;
else
point.y -= lineHeight;
point.y -= lineSize.height;
first = NO;
}
}

View file

@ -89,6 +89,9 @@ id _nsTextfieldCellClass = nil;
[self setCell: c];
[c release];
[cell setState: 1];
[cell setBezeled: YES];
[cell setSelectable: YES];
[cell setEditable: YES];
[cell setDrawsBackground: YES];
text_cursor = [[NSCursor IBeamCursor] retain];
@ -115,7 +118,7 @@ id _nsTextfieldCellClass = nil;
{
id c;
c = [super copyWithZone: zone];
c = [(id)super copyWithZone: zone];
[c setTextCursor: [NSCursor IBeamCursor]];
return c;

View file

@ -71,13 +71,7 @@
{
[super initTextCell: aString];
[self setEnabled: YES];
[self setBordered: YES];
[self setBezeled: YES];
[self setScrollable: YES];
[self setEditable: YES];
[self setAlignment: NSLeftTextAlignment];
[self setBackgroundColor: [NSColor textBackgroundColor]];
[self setTextColor: [NSColor textColor]];
[self setFont: [NSFont systemFontOfSize: 0]];

View file

@ -532,8 +532,9 @@
- (void) center
{
NSSize screenSize = [[NSScreen mainScreen] frame].size;
NSPoint origin = frame.origin; // center the window
// within it's screen
NSPoint origin = frame.origin;
// center the window within it's screen
origin.x = (screenSize.width - frame.size.width) / 2;
origin.y = (screenSize.height - frame.size.height) / 2;
[self setFrameOrigin: origin];