Re: Table of TextViews
Re: Table of TextViews
- Subject: Re: Table of TextViews
- From: Charles Jenkins <email@hidden>
- Date: Tue, 14 Oct 2014 08:49:15 -0400
Can I ask you folks to look over and comment on this code? I think I’ve set up the text view and text container correctly to track the size of the text they contain, and I can notify my table view delegate when their size changes. The problem I’m having is that the table view delegate can note and log the size change and everything works well--as long as I don’t really do anything with the information. But if the table view delegate notifies the table that the corresponding row size changed, everything goes crazy.
I’m going to take this step by step. Would you comment on my NSTextView subclass and tell me if something is wrong in the way I’ve set it up to size itself, notify itself, or pass along size-change notifications?
The code below is from three separate source files, but I’m sure you can tell which is which.
@protocol SizeWatcher <NSObject>
// Notify of actual size change, along with variables to
// answer the most common questions receiver will want to
// ask:
// Did width grow? Shrink? Remain the same?
// Did height grow? Shrink? Remain the same?
// What is the view's new frame/bounds?
-(void)sizeChangedForView:(NSView*)view
widthChange:(CGFloat)wc
heightChange:(CGFloat)hc;
@end
#import "SizeWatcher.h"
@interface CJAutosizingTextView : NSTextView
-(void)addSizeWatcher:(id)obj;
-(void)removeSizeWatcher:(id)obj;
-(void)removeAllSizeWatchers;
-(void)setLayoutManager:(NSLayoutManager*)lm;
@end
#import "CJAutosizingTextView.h"
@interface CJAutosizingTextView ()
@property NSRect oldFrame;
@property NSMutableArray* sizeWatchers;
@end
@implementation CJAutosizingTextView
@synthesize oldFrame;
@synthesize sizeWatchers;
-(instancetype)initWithFrame:(NSRect)frameRect
andLayoutManager:(NSLayoutManager*)lm
{
self = [super initWithFrame:frameRect];
if ( self != nil ) {
sizeWatchers = nil;
oldFrame = frameRect;
NSTextContainer* tc = [[NSTextContainer alloc] init];
self.textContainer = tc;
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(frameChanged:)
name:NSViewFrameDidChangeNotification
object:self];
self.layoutManager = lm;
// Make text container and text view automatically
// size themselves vertically to fit the text
tc.widthTracksTextView = YES;
tc.heightTracksTextView = NO;
self.horizontallyResizable = NO;
self.verticallyResizable = YES;
// Allow superview to resize text view's width
self.autoresizingMask = NSViewWidthSizable;
}
return self;
}
-(instancetype)initWithFrame:(NSRect)frameRect
{
return [self initWithFrame:frameRect andLayoutManager:nil];
}
-(void)dealloc
{
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self
name:NSViewFrameDidChangeNotification
object:self];
}
// NSTextView already has a layoutManager: selector to read the
// text container's layout manager. Here we add a convenient
// setter companion
-(void)setLayoutManager:(NSLayoutManager*)lm
{
self.textContainer.layoutManager = lm;
}
// Maintain the array of size watchers
-(void)addSizeWatcher:(id)obj
{
if ( [obj conformsToProtocol:@protocol(SizeWatcher)] ) {
if ( sizeWatchers == nil ) {
sizeWatchers = [[NSMutableArray alloc] initWithCapacity:1];
}
[self.sizeWatchers addObject:obj];
}
}
-(void)removeSizeWatcher:(id)obj
{
if ( sizeWatchers != nil ) {
[sizeWatchers removeObject:obj];
}
}
-(void)removeAllSizeWatchers
{
if ( sizeWatchers != nil ) {
[sizeWatchers removeAllObjects];
}
}
// When I'm notified that my frame changes, see if the new frame's
// size change and, if so, notify all size watchers
-(void)frameChanged:(NSNotification*)note
{
// Begin with test that's probably unnecessary, but just to be sure...
if ( [note object] == self ) {
NSRect newFrame = self.frame;
CGFloat wd = newFrame.size.width - oldFrame.size.width;
CGFloat hd = newFrame.size.width - oldFrame.size.width;
oldFrame = newFrame;
if ( wd != 0.0 || hd != 0.0 ) {
// Notify watchers of actual size change
for ( NSObject<SizeWatcher>* obj in sizeWatchers ) {
[obj sizeChangedForView:self widthChange:wd heightChange:hd];
}
}
}
}
@end
--
Charles
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden