• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Table of TextViews
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


  • Follow-Ups:
    • Re: Table of TextViews
      • From: Ken Thomases <email@hidden>
    • Re: Table of TextViews
      • From: Charles Jenkins <email@hidden>
References: 
 >Table of TextViews (From: Charles Jenkins <email@hidden>)
 >Re: Table of TextViews (From: Ken Thomases <email@hidden>)
 >Re: Table of TextViews (From: Charles Jenkins <email@hidden>)
 >Re: Table of TextViews (From: Keary Suska <email@hidden>)
 >Re: Table of TextViews (From: Charles Jenkins <email@hidden>)
 >Re: Table of TextViews (From: Ken Thomases <email@hidden>)

  • Prev by Date: Swift - Basic query regarding managedObjectContext method invocation from app delegate
  • Next by Date: Re: Table of TextViews
  • Previous by thread: Re: Table of TextViews
  • Next by thread: Re: Table of TextViews
  • Index(es):
    • Date
    • Thread