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 (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com