Set the text container to max size, when the text view is resizable.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@25863 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2008-01-04 21:02:29 +00:00
parent 341653bcb0
commit 3dc7f6d74c
5 changed files with 329 additions and 209 deletions

View file

@ -1,3 +1,17 @@
2008-01-04 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSTextContainer.m: Replace tabs with spaces.
* Source/GSHorizontalTypesetter.m
(-_getProposedRectFor:withLineHeight:) Extract proposed rect
generation into separate method.
* Source/GSLayoutManager.m (-_doLayoutToGlyph:,
_doLayoutToContainer:): Implement based on code from _doLayout.
* Source/GSLayoutManager.m (-_doLayout): Implement via
_doLayoutToContainer:.
* Source/NSTextView.m (-setHorizontallyResizable:,
-setVerticallyResizable:): Set the width/height of the text
container to max size, when resizable.
2008-01-03 Fred Kiefer <FredKiefer@gmx.de>
* Headers/AppKit/NSStringDrawing.h: Include GSVersionMacros.h

View file

@ -425,6 +425,32 @@ typedef struct GSHorizontalTypesetter_line_frag_s
return YES;
}
- (NSRect)_getProposedRectFor: (BOOL)newParagraph
withLineHeight: (float) line_height
{
float hindent;
float tindent = [curParagraphStyle tailIndent];
if (newParagraph)
hindent = [curParagraphStyle firstLineHeadIndent];
else
hindent = [curParagraphStyle headIndent];
if (tindent <= 0.0)
{
NSSize size;
size = [curTextContainer containerSize];
tindent = size.width + tindent;
}
return NSMakeRect(hindent,
curPoint.y,
tindent - hindent,
line_height + [curParagraphStyle lineSpacing]);
}
/*
Return values 0, 1, 2 are mostly the same as from
-layoutGlyphsInLayoutManager:.... Additions:
@ -475,7 +501,7 @@ Return values 0, 1, 2 are mostly the same as from
[curLayoutManager _softInvalidateFirstGlyphInTextContainer: curTextContainer] == curGlyph)
{
if ([self _reuseSoftInvalidatedLayout])
return 4;
return 4;
}
@ -490,12 +516,11 @@ Return values 0, 1, 2 are mostly the same as from
will be properly positioned after a trailing newline in the text.
*/
NSRect r, r2, remain;
float hindent, tindent;
if (!newParagraph || !curGlyph)
{
return 2;
}
{
return 2;
}
/*
We aren't actually interested in the glyph data, but we want the
@ -504,30 +529,23 @@ Return values 0, 1, 2 are mostly the same as from
*/
[self _cacheMoveTo: curGlyph - 1];
hindent = [curParagraphStyle firstLineHeadIndent];
tindent = [curParagraphStyle tailIndent];
if (tindent <= 0.0)
tindent = [curTextContainer containerSize].width + tindent;
line_height = [curFont defaultLineHeightForFont];
r = NSMakeRect(hindent,
curPoint.y,
tindent - hindent,
line_height + [curParagraphStyle lineSpacing]);
r = [self _getProposedRectFor: newParagraph
withLineHeight: line_height];
r = [curTextContainer lineFragmentRectForProposedRect: r
sweepDirection: NSLineSweepRight
movementDirection: NSLineMoveDown
remainingRect: &remain];
sweepDirection: NSLineSweepRight
movementDirection: NSLineMoveDown
remainingRect: &remain];
if (!NSIsEmptyRect(r))
{
r2 = r;
r2.size.width = 1;
[curLayoutManager setExtraLineFragmentRect: r
usedRect: r2
textContainer: curTextContainer];
}
{
r2 = r;
r2.size.width = 1;
[curLayoutManager setExtraLineFragmentRect: r
usedRect: r2
textContainer: curTextContainer];
}
return 2;
}
@ -583,22 +601,8 @@ Return values 0, 1, 2 are mostly the same as from
restart: ;
{
float hindent, tindent = [curParagraphStyle tailIndent];
if (newParagraph)
hindent = [curParagraphStyle firstLineHeadIndent];
else
hindent = [curParagraphStyle headIndent];
if (tindent <= 0.0)
tindent = [curTextContainer containerSize].width + tindent;
remain = NSMakeRect(hindent,
curPoint.y,
tindent - hindent,
line_height + [curParagraphStyle lineSpacing]);
}
remain = [self _getProposedRectFor: newParagraph
withLineHeight: line_height];
/*
Build a list of all line frag rects for this line.
@ -616,7 +620,7 @@ restart: ;
movementDirection: line_frags_num?NSLineDoesntMove:NSLineMoveDown
remainingRect: &remain];
if (NSEqualRects(rect, NSZeroRect))
break;
break;
line_frags_num++;
if (line_frags_num > line_frags_size)

View file

@ -1573,6 +1573,11 @@ places where we switch.
-(void) _doLayout
{
[self _doLayoutToContainer: num_textcontainers - 1];
}
-(void) _doLayoutToGlyph: (unsigned int)glyphIndex
{
int i, j;
textcontainer_t *tc;
@ -1587,79 +1592,155 @@ places where we switch.
for (i = 0, tc = textcontainers; i < num_textcontainers; i++, tc++)
{
if (tc->complete)
continue;
continue;
while (1)
{
if (tc->num_linefrags)
prev = tc->linefrags[tc->num_linefrags - 1].rect;
else
prev = NSZeroRect;
j = [typesetter layoutGlyphsInLayoutManager: self
inTextContainer: tc->textContainer
startingAtGlyphIndex: next
previousLineFragmentRect: prev
nextGlyphIndex: &next
numberOfLineFragments: 0];
if (j)
break;
}
{
if (tc->num_linefrags)
prev = tc->linefrags[tc->num_linefrags - 1].rect;
else
prev = NSZeroRect;
j = [typesetter layoutGlyphsInLayoutManager: self
inTextContainer: tc->textContainer
startingAtGlyphIndex: next
previousLineFragmentRect: prev
nextGlyphIndex: &next
numberOfLineFragments: 0];
if (j)
break;
if (next > glyphIndex)
{
// If all the requested work is done just leave
return;
}
}
tc->complete = YES;
tc->usedRectValid = NO;
if (tc->num_soft)
{
/*
If there is any soft invalidated layout information left, remove
it.
*/
int k;
linefrag_t *lf;
for (k = tc->num_linefrags, lf = tc->linefrags + k; k < tc->num_linefrags + tc->num_soft; k++, lf++)
{
if (lf->points)
{
free(lf->points);
lf->points = NULL;
}
if (lf->attachments)
{
free(lf->attachments);
lf->attachments = NULL;
}
}
tc->num_soft = 0;
}
{
/*
If there is any soft invalidated layout information left, remove
it.
*/
int k;
linefrag_t *lf;
for (k = tc->num_linefrags, lf = tc->linefrags + k;
k < tc->num_linefrags + tc->num_soft; k++, lf++)
{
if (lf->points)
{
free(lf->points);
lf->points = NULL;
}
if (lf->attachments)
{
free(lf->attachments);
lf->attachments = NULL;
}
}
tc->num_soft = 0;
}
if (delegate_responds)
{
[_delegate layoutManager: self
didCompleteLayoutForTextContainer: tc->textContainer
atEnd: j == 2];
/* The call might have resulted in more text containers being
added, so 'textcontainers' might have moved. */
tc = textcontainers + i;
}
{
[_delegate layoutManager: self
didCompleteLayoutForTextContainer: tc->textContainer
atEnd: j == 2];
/* The call might have resulted in more text containers being
added, so 'textcontainers' might have moved. */
tc = textcontainers + i;
}
if (j == 2)
{
break;
}
{
break;
}
if (i == num_textcontainers && delegate_responds)
{
[_delegate layoutManager: self
didCompleteLayoutForTextContainer: nil
atEnd: NO];
}
{
[_delegate layoutManager: self
didCompleteLayoutForTextContainer: nil
atEnd: NO];
}
}
}
-(void) _doLayoutToGlyph: (unsigned int)glyphIndex
{
[self _doLayout];
}
-(void) _doLayoutToContainer: (int)cindex
{
[self _doLayout];
int i, j;
textcontainer_t *tc;
unsigned int next;
NSRect prev;
BOOL delegate_responds;
delegate_responds = [_delegate respondsToSelector:
@selector(layoutManager:didCompleteLayoutForTextContainer:atEnd:)];
next = layout_glyph;
for (i = 0, tc = textcontainers; i <= cindex; i++, tc++)
{
if (tc->complete)
continue;
while (1)
{
if (tc->num_linefrags)
prev = tc->linefrags[tc->num_linefrags - 1].rect;
else
prev = NSZeroRect;
j = [typesetter layoutGlyphsInLayoutManager: self
inTextContainer: tc->textContainer
startingAtGlyphIndex: next
previousLineFragmentRect: prev
nextGlyphIndex: &next
numberOfLineFragments: 0];
if (j)
break;
}
tc->complete = YES;
tc->usedRectValid = NO;
if (tc->num_soft)
{
/*
If there is any soft invalidated layout information left, remove
it.
*/
int k;
linefrag_t *lf;
for (k = tc->num_linefrags, lf = tc->linefrags + k;
k < tc->num_linefrags + tc->num_soft; k++, lf++)
{
if (lf->points)
{
free(lf->points);
lf->points = NULL;
}
if (lf->attachments)
{
free(lf->attachments);
lf->attachments = NULL;
}
}
tc->num_soft = 0;
}
if (delegate_responds)
{
[_delegate layoutManager: self
didCompleteLayoutForTextContainer: tc->textContainer
atEnd: j == 2];
/* The call might have resulted in more text containers being
added, so 'textcontainers' might have moved. */
tc = textcontainers + i;
}
if (j == 2)
{
break;
}
if (i == num_textcontainers && delegate_responds)
{
[_delegate layoutManager: self
didCompleteLayoutForTextContainer: nil
atEnd: NO];
}
}
}

View file

@ -17,7 +17,7 @@
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
@ -49,31 +49,31 @@ use bounds rectangle instead of frame? */
{
if (_observingFrameChanges)
{
id textView;
NSSize newTextViewSize;
NSSize size;
NSSize inset;
id textView;
NSSize newTextViewSize;
NSSize size;
NSSize inset;
textView = [aNotification object];
if (textView != _textView)
{
NSDebugLog(@"NSTextContainer got notification for wrong View %@",
textView);
return;
}
NSDebugLog(@"NSTextContainer got notification for wrong View %@",
textView);
return;
}
newTextViewSize = [textView frame].size;
size = _containerRect.size;
inset = [textView textContainerInset];
if (_widthTracksTextView)
{
size.width = MAX(newTextViewSize.width - (inset.width * 2.0), 0.0);
}
{
size.width = MAX(newTextViewSize.width - (inset.width * 2.0), 0.0);
}
if (_heightTracksTextView)
{
size.height = MAX(newTextViewSize.height - (inset.height * 2.0),
0.0);
}
{
size.height = MAX(newTextViewSize.height - (inset.height * 2.0),
0.0);
}
[self setContainerSize: size];
}
@ -111,8 +111,8 @@ use bounds rectangle instead of frame? */
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver: self
name: NSViewFrameDidChangeNotification
object: _textView];
name: NSViewFrameDidChangeNotification
object: _textView];
[_textView setTextContainer: nil];
RELEASE(_textView);
@ -155,22 +155,22 @@ framework intact.
[textStorage addLayoutManager: aLayoutManager];
for (i = 0; i < count; i++)
{
NSTextContainer *container;
{
NSTextContainer *container;
container = RETAIN([textContainers objectAtIndex: i]);
[oldLayoutManager removeTextContainerAtIndex: i];
/* One of these calls will result in our _layoutManager being
changed. */
[aLayoutManager addTextContainer: container];
container = RETAIN([textContainers objectAtIndex: i]);
[oldLayoutManager removeTextContainerAtIndex: i];
/* One of these calls will result in our _layoutManager being
changed. */
[aLayoutManager addTextContainer: container];
/* The textview is caching the layout manager; refresh the
* cache with this do-nothing call. */
/* TODO: probably unnecessary; the call in -setLayoutManager:
should be enough */
[[container textView] setTextContainer: container];
RELEASE(container);
}
/* The textview is caching the layout manager; refresh the
* cache with this do-nothing call. */
/* TODO: probably unnecessary; the call in -setLayoutManager:
should be enough */
[[container textView] setTextContainer: container];
RELEASE(container);
}
RELEASE(oldLayoutManager);
}
}
@ -180,15 +180,15 @@ framework intact.
NSNotificationCenter *nc;
nc = [NSNotificationCenter defaultCenter];
if (_textView)
{
[_textView setTextContainer: nil];
[nc removeObserver: self name: NSViewFrameDidChangeNotification
object: _textView];
object: _textView];
/* NB: We do not set posts frame change notifications for the
text view to NO because there could be other observers for
the frame change notifications. */
text view to NO because there could be other observers for
the frame change notifications. */
}
ASSIGN(_textView, aTextView);
@ -197,13 +197,13 @@ framework intact.
{
[_textView setTextContainer: self];
if (_observingFrameChanges)
{
[_textView setPostsFrameChangedNotifications: YES];
[nc addObserver: self
selector: @selector(_textViewFrameChanged:)
name: NSViewFrameDidChangeNotification
object: _textView];
}
{
[_textView setPostsFrameChangedNotifications: YES];
[nc addObserver: self
selector: @selector(_textViewFrameChanged:)
name: NSViewFrameDidChangeNotification
object: _textView];
}
}
/* If someone's trying to set a NSTextView for us, the layout manager we
@ -256,14 +256,14 @@ framework intact.
{
[_textView setPostsFrameChangedNotifications: YES];
[nc addObserver: self
selector: @selector(_textViewFrameChanged:)
name: NSViewFrameDidChangeNotification
object: _textView];
selector: @selector(_textViewFrameChanged:)
name: NSViewFrameDidChangeNotification
object: _textView];
}
else
{
[nc removeObserver: self name: NSViewFrameDidChangeNotification
object: _textView];
object: _textView];
}
}
@ -291,14 +291,14 @@ framework intact.
{
[_textView setPostsFrameChangedNotifications: YES];
[nc addObserver: self
selector: @selector(_textViewFrameChanged:)
name: NSViewFrameDidChangeNotification
object: _textView];
selector: @selector(_textViewFrameChanged:)
name: NSViewFrameDidChangeNotification
object: _textView];
}
else
{
[nc removeObserver: self name: NSViewFrameDidChangeNotification
object: _textView];
object: _textView];
}
}
@ -321,9 +321,9 @@ framework intact.
}
- (NSRect) lineFragmentRectForProposedRect: (NSRect)proposedRect
sweepDirection: (NSLineSweepDirection)sweepDir
movementDirection: (NSLineMovementDirection)moveDir
remainingRect: (NSRect *)remainingRect
sweepDirection: (NSLineSweepDirection)sweepDir
movementDirection: (NSLineMovementDirection)moveDir
remainingRect: (NSRect *)remainingRect
{
float minx, maxx, miny, maxy;
float cminx, cmaxx, cminy, cmaxy;
@ -348,66 +348,66 @@ framework intact.
switch (moveDir)
{
case NSLineMoveLeft:
if (maxx < cminx)
return NSZeroRect;
if (maxx > cmaxx)
{
minx -= maxx-cmaxx;
maxx = cmaxx;
}
break;
if (maxx < cminx)
return NSZeroRect;
if (maxx > cmaxx)
{
minx -= maxx-cmaxx;
maxx = cmaxx;
}
break;
case NSLineMoveRight:
if (minx > cmaxx)
return NSZeroRect;
if (minx < cminx)
{
maxx += cminx-minx;
minx = cminx;
}
break;
if (minx > cmaxx)
return NSZeroRect;
if (minx < cminx)
{
maxx += cminx-minx;
minx = cminx;
}
break;
case NSLineMoveDown:
if (miny > cmaxy)
return NSZeroRect;
if (miny < cminy)
{
maxy += cminy - miny;
miny = cminy;
}
break;
if (miny > cmaxy)
return NSZeroRect;
if (miny < cminy)
{
maxy += cminy - miny;
miny = cminy;
}
break;
case NSLineMoveUp:
if (maxy < cminy)
return NSZeroRect;
if (maxy > cmaxy)
{
miny -= maxy - cmaxy;
maxy = cmaxy;
}
break;
if (maxy < cminy)
return NSZeroRect;
if (maxy > cmaxy)
{
miny -= maxy - cmaxy;
maxy = cmaxy;
}
break;
case NSLineDoesntMove:
break;
break;
}
switch (sweepDir)
{
case NSLineSweepLeft:
case NSLineSweepRight:
if (minx < cminx)
minx = cminx;
if (maxx > cmaxx)
maxx = cmaxx;
break;
if (minx < cminx)
minx = cminx;
if (maxx > cmaxx)
maxx = cmaxx;
break;
case NSLineSweepDown:
case NSLineSweepUp:
if (miny < cminy)
miny = cminy;
if (maxy > cmaxy)
maxy = cmaxy;
break;
if (miny < cminy)
miny = cminy;
if (maxy > cmaxy)
maxy = cmaxy;
break;
}
if (minx < cminx || maxx > cmaxx ||
@ -439,18 +439,18 @@ framework intact.
if ([aDecoder containsValueForKey: @"NSWidth"])
{
size.width = [aDecoder decodeFloatForKey: @"NSWidth"];
}
size.width = [aDecoder decodeFloatForKey: @"NSWidth"];
}
self = [self initWithContainerSize: size];
if ([aDecoder containsValueForKey: @"NSTCFlags"])
{
int flags = [aDecoder decodeIntForKey: @"NSTCFlags"];
// decode the flags.
_widthTracksTextView = flags & 1;
_heightTracksTextView = flags & 2;
_observingFrameChanges = flags & 4;
}
int flags = [aDecoder decodeIntForKey: @"NSTCFlags"];
// decode the flags.
_widthTracksTextView = flags & 1;
_heightTracksTextView = flags & 2;
_observingFrameChanges = flags & 4;
}
// decoding the manager adds this text container automatically...
[aDecoder decodeObjectForKey: @"NSLayoutManager"];
@ -469,8 +469,8 @@ framework intact.
{
NSSize size = _containerRect.size;
int flags = ((_widthTracksTextView)?1:0) |
((_heightTracksTextView)?2:0) |
((_observingFrameChanges)?4:0);
((_heightTracksTextView)?2:0) |
((_observingFrameChanges)?4:0);
[coder encodeObject: _textView forKey: @"NSTextView"];
[coder encodeFloat: size.width forKey: @"NSWidth"];

View file

@ -1612,13 +1612,34 @@ incorrectly. */
{
/* Safety call */
[_textContainer setWidthTracksTextView: !flag];
if (flag)
{
NSSize size;
NSSize inset;
inset = [self textContainerInset];
size = [_textContainer containerSize];
size.width = MAX(_maxSize.width - (inset.width * 2.0), 0.0);
[_textContainer setContainerSize: size];
}
_tf.is_horizontally_resizable = flag;
}
- (void) setVerticallyResizable: (BOOL)flag
{
/* Safety call */
[_textContainer setHeightTracksTextView: !flag];
if (flag)
{
NSSize size;
NSSize inset;
inset = [self textContainerInset];
size = [_textContainer containerSize];
size.height = MAX(_maxSize.height - (inset.height * 2.0), 0.0);
[_textContainer setContainerSize: size];
}
_tf.is_vertically_resizable = flag;
}