From f74fed5ee03c33d0aec810d4336efc47b500c6c1 Mon Sep 17 00:00:00 2001 From: Martin Carlberg Date: Wed, 16 Dec 2020 11:29:11 +0100 Subject: [PATCH] Fixed: CPTextView now handles more options from Interface Builder The new options are: 1. Resizable Horizontally 2. Resizable Vertically 3. Max Size Also two options from the Text Container is recognized: 1. Tracks text view width 2. Tracks text view height The last two are needed to allow the text view to recalculate the size of its content if the frame size is changed. --- AppKit/CPTextView/CPTextContainer.j | 25 ++++++++- AppKit/CPTextView/CPTextView.j | 81 +++++++++++++++++------------ Tools/nib2cib/NSTextContainer.j | 4 ++ Tools/nib2cib/NSTextView.j | 8 +++ 4 files changed, 82 insertions(+), 36 deletions(-) diff --git a/AppKit/CPTextView/CPTextContainer.j b/AppKit/CPTextView/CPTextContainer.j index 7797cd526..48490579e 100644 --- a/AppKit/CPTextView/CPTextContainer.j +++ b/AppKit/CPTextView/CPTextContainer.j @@ -84,6 +84,8 @@ CPLineMovesUp = 4; CPLayoutManager _layoutManager @accessors(property=layoutManager); CPTextView _textView @accessors(property=textView); BOOL _inResizing; + BOOL _widthTracksTextView; + BOOL _heightTracksTextView; } @@ -139,11 +141,17 @@ CPLineMovesUp = 4; } // Controls whether the receiver adjusts the width of its bounding rectangle when its text view is resized. +- (BOOL)widthTracksTextView +{ + return _widthTracksTextView; +} + - (void)setWidthTracksTextView:(BOOL)flag { + _widthTracksTextView = flag; [_textView setPostsFrameChangedNotifications:flag]; - if (flag) + if (flag && _textView) { [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewFrameChanged:) @@ -168,12 +176,18 @@ CPLineMovesUp = 4; - (void)setTextView:(CPTextView)aTextView { if (_textView) + { + [self setWidthTracksTextView:NO]; // We only support width [_textView setTextContainer:nil]; + } _textView = aTextView; if (_textView) + { + [self setWidthTracksTextView:_widthTracksTextView]; // We only support width [_textView setTextContainer:self]; + } [_layoutManager textContainerChangedTextView:self]; } @@ -222,7 +236,9 @@ CPLineMovesUp = 4; var CPTextContainerSizeKey = @"CPTextContainerSizeKey", - CPTextContainerLayoutManagerKey = @"CPTextContainerLayoutManagerKey"; + CPTextContainerLayoutManagerKey = @"CPTextContainerLayoutManagerKey", + CPTextContainerWidthTracksTextViewKey = @"CPTextContainerWidthTracksTextViewKey", + CPTextContainerHeightTracksTextViewKey = @"CPTextContainerHeightTracksTextViewKey"; @implementation CPTextContainer (CPCoding) @@ -238,6 +254,9 @@ var CPTextContainerSizeKey = @"CPTextContainerSizeKey", _layoutManager = [aCoder decodeObjectForKey:CPTextContainerLayoutManagerKey]; [_layoutManager addTextContainer:self]; + + _widthTracksTextView = [aCoder decodeBoolForKey:CPTextContainerWidthTracksTextViewKey]; + _heightTracksTextView = [aCoder decodeBoolForKey:CPTextContainerHeightTracksTextViewKey]; } return self; @@ -247,6 +266,8 @@ var CPTextContainerSizeKey = @"CPTextContainerSizeKey", { [aCoder encodeSize:_size forKey:CPTextContainerSizeKey]; [aCoder encodeObject:_layoutManager forKey:CPTextContainerLayoutManagerKey]; + [aCoder encodeBool:_widthTracksTextView forKey:CPTextContainerWidthTracksTextViewKey]; + [aCoder encodeBool:_heightTracksTextView forKey:CPTextContainerHeightTracksTextViewKey]; } @end diff --git a/AppKit/CPTextView/CPTextView.j b/AppKit/CPTextView/CPTextView.j index 118630bd3..b811db0b3 100644 --- a/AppKit/CPTextView/CPTextView.j +++ b/AppKit/CPTextView/CPTextView.j @@ -1978,43 +1978,45 @@ Sets the selection to a range of characters in response to user action. - (void)setFrameSize:(CGSize)aSize { - var minSize = [self minSize], - maxSize = [self maxSize], - desiredSize = CGSizeCreateCopy(aSize), - rect = CGRectUnion([_layoutManager boundingRectForGlyphRange:CPMakeRange(0, 1) inTextContainer:_textContainer], - [_layoutManager boundingRectForGlyphRange:CPMakeRange(MAX(0, [_layoutManager numberOfCharacters] - 2), 1) inTextContainer:_textContainer]), - myClipviewSize = nil; + var desiredSize = CGSizeCreateCopy(aSize); + + if (_isHorizontallyResizable || _isVerticallyResizable) + { + var minSize = [self minSize], + maxSize = [self maxSize], + rect = CGRectUnion([_layoutManager boundingRectForGlyphRange:CPMakeRange(0, 1) inTextContainer:_textContainer], + [_layoutManager boundingRectForGlyphRange:CPMakeRange(MAX(0, [_layoutManager numberOfCharacters] - 2), 1) inTextContainer:_textContainer]); + + if ([_layoutManager extraLineFragmentTextContainer] === _textContainer) + rect = CGRectUnion(rect, [_layoutManager extraLineFragmentRect]); + + if (_isHorizontallyResizable) + { + rect = [_layoutManager boundingRectForGlyphRange:CPMakeRange(0, MAX(0, [_layoutManager numberOfCharacters] - 1)) inTextContainer:_textContainer]; // needs expensive "deep" recalculation + + desiredSize.width = rect.size.width + 2 * _textContainerInset.width; + + if (desiredSize.width < minSize.width) + desiredSize.width = minSize.width; + else if (desiredSize.width > maxSize.width) + desiredSize.width = maxSize.width; + } + + if (_isVerticallyResizable) + { + desiredSize.height = rect.size.height + 2 * _textContainerInset.height; + + if (desiredSize.height < minSize.height) + desiredSize.height = minSize.height; + else if (desiredSize.height > maxSize.height) + desiredSize.height = maxSize.height; + } + } if ([[self superview] isKindOfClass:[CPClipView class]]) - myClipviewSize = [[self superview] frame].size; - - if ([_layoutManager extraLineFragmentTextContainer] === _textContainer) - rect = CGRectUnion(rect, [_layoutManager extraLineFragmentRect]); - - if (_isHorizontallyResizable) { - rect = [_layoutManager boundingRectForGlyphRange:CPMakeRange(0, MAX(0, [_layoutManager numberOfCharacters] - 1)) inTextContainer:_textContainer]; // needs expensive "deep" recalculation + var myClipviewSize = [[self superview] frame].size; - desiredSize.width = rect.size.width + 2 * _textContainerInset.width; - - if (desiredSize.width < minSize.width) - desiredSize.width = minSize.width; - else if (desiredSize.width > maxSize.width) - desiredSize.width = maxSize.width; - } - - if (_isVerticallyResizable) - { - desiredSize.height = rect.size.height + 2 * _textContainerInset.height; - - if (desiredSize.height < minSize.height) - desiredSize.height = minSize.height; - else if (desiredSize.height > maxSize.height) - desiredSize.height = maxSize.height; - } - - if (myClipviewSize) - { if (desiredSize.width < myClipviewSize.width) desiredSize.width = myClipviewSize.width; if (desiredSize.height < myClipviewSize.height) @@ -2382,7 +2384,11 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey", CPTextViewTextStorageKey = @"CPTextViewTextStorageKey", CPTextViewInsertionPointColorKey = @"CPTextViewInsertionPointColorKey", CPTextViewSelectedTextAttributesKey = @"CPTextViewSelectedTextAttributesKey", - CPTextViewDelegateKey = @"CPTextViewDelegateKey"; + CPTextViewDelegateKey = @"CPTextViewDelegateKey", + CPTextViewHorizontallyResizableKey = @"CPTextViewHorizontallyResizableKey", + CPTextViewVerticallyResizableKey = @"CPTextViewVerticallyResizableKey", + CPMaxSize = @"CPMaxSize"; + @implementation CPTextView (CPCoding) @@ -2423,6 +2429,10 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey", [self setFont:[_typingAttributes valueForKey:CPFontAttributeName]]; [self setString:[_textStorage string]]; + + [self setMaxSize:[aCoder decodeSizeForKey:CPMaxSize]]; + [self setHorizontallyResizable:[aCoder decodeBoolForKey:CPTextViewHorizontallyResizableKey]]; + [self setVerticallyResizable:[aCoder decodeBoolForKey:CPTextViewVerticallyResizableKey]] } return self; @@ -2438,6 +2448,9 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey", [aCoder encodeObject:_selectedTextAttributes forKey:CPTextViewSelectedTextAttributesKey]; [aCoder encodeBool:_allowsUndo forKey:CPTextViewAllowsUndoKey]; [aCoder encodeBool:_usesFontPanel forKey:CPTextViewUsesFontPanelKey]; + [aCoder encodeBool:_isHorizontallyResizable forKey:CPTextViewHorizontallyResizableKey]; + [aCoder encodeBool:_isVerticallyResizable forKey:CPTextViewVerticallyResizableKey]; + [aCoder encodeSize:_maxSize forKey:CPMaxSize]; } @end diff --git a/Tools/nib2cib/NSTextContainer.j b/Tools/nib2cib/NSTextContainer.j index eb21910a0..b713f0db3 100644 --- a/Tools/nib2cib/NSTextContainer.j +++ b/Tools/nib2cib/NSTextContainer.j @@ -35,6 +35,10 @@ _layoutManager = [aCoder decodeObjectForKey:@"NSLayoutManager"]; [_layoutManager addTextContainer:self]; + var tcFlags = [aCoder decodeIntForKey: @"NSTCFlags"]; + _widthTracksTextView = (tcFlags & 0x00000001) ? YES : NO; + _heightTracksTextView = (tcFlags & 0x00000002) ? YES : NO; + return self; } diff --git a/Tools/nib2cib/NSTextView.j b/Tools/nib2cib/NSTextView.j index 2c7492ead..c70f6b5ec 100644 --- a/Tools/nib2cib/NSTextView.j +++ b/Tools/nib2cib/NSTextView.j @@ -44,6 +44,14 @@ [self setInsertionPointColor:[aTextViewSharedData insertionColor]]; [self setSelectedTextAttributes:[aTextViewSharedData selectedTextAttributes]]; [[self textContainer] setWidthTracksTextView:YES]; + + if ([aCoder containsValueForKey:@"NSMaxSize"]) + _maxSize = [aCoder decodeSizeForKey:@"NSMaxSize"]; + + var tvFlags = [aCoder decodeIntForKey:@"NSTVFlags"]; + + _isHorizontallyResizable = (tvFlags & 0x00000001) ? YES : NO; + _isVerticallyResizable = (tvFlags & 0x00000002) ? YES : NO; } return self;