views:

414

answers:

2

I have a custom NSView which contains a subview—for the purposes of solving this issue, the top level view is simply acting as a container and automatically resizes to fit within the window. Its subview draws a rectangle 10 pixels inset from the edge of the window, except for the bottom, which should get clipped by the window until it's resized to show the entire rectangle. It does not, however, behave as I intend, and instead shrinks the height of the rectangle when its superview has a smaller height than it does. How do I avoid this and have it stay at its proper height and instead get clipped when the superview is smaller?

The parent view's implementation code is:

- (id)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        subView = [[SubView alloc] initWithFrame:frameRect];
    }
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    [[NSColor grayColor] set];
    [subView setFrame:NSMakeRect(10, 10, dirtyRect.size.width - 20, 500)];
    [self addSubview:subView];
}

- (BOOL)isFlipped {
    return YES;
}

And the subview is just:

- (void)drawRect:(NSRect)dirtyRect {
    [[NSColor blackColor] set];
    [NSBezierPath strokeRect:dirtyRect];
}

- (BOOL)isFlipped {
    return YES;
}
+1  A: 

Most likely your subview has an autoresizing mask. You can clear this by calling -setAutoresizingMask: with NSViewNotSizable.

If the superview should not be resizing any of it's subviews, you could consider using -setAutoresizesSubviews:

ericgorr
I have, alas, tried both -setAutoresizingMask: with NSViewNotSizeable on both the superview and the subview, and -setAutoresizesSubviews on the superview, to no avail. It behaves the same way with all the combinations of those that I've tried.
Jonathan Patt
+1  A: 

As ericgorr pointed out, the autoResizingMask should take care of the resizing issue.

However, I notice that you are adding your subview in drawRect, which is not the right place to do it. drawRect is called many times during the lifetime of your program, but addSubview: only needs to be (and only should be) called once, like so:

- (id)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        subView = [[SubView alloc] initWithFrame:frameRect];
        [self addSubview:subView]; // this view now owns subView ...
        [subView release];         // ... so we can release our copy
    }
    return self; 
} 

- (void)drawRect:(NSRect)dirtyRect { 
    [[NSColor grayColor] set]; 
    [subView setFrame:NSMakeRect(10, 10, [self bounds].size.width - 20, 500)];
} 

Note also the use of [self bounds] instead of dirtyRect. dirtyRect is a rectangle describing the region which needs to be redrawn. This will not always be the entire bounding rectangle of your view. [self bounds], on the other hand, will always represent the entire bounds of your view, regardless of which portion is being redrawn.

e.James
As noted in my response to ericgorr's answer, I was unable to get it working with autoResizingMask. Regarding the placement of `addSubview:` and using `[self bounds]`, however, thanks for letting me know! That makes sense.
Jonathan Patt
And now that I've implemented the use of `[self bounds]` instead of `dirtyRect` in the subview, it works, which makes sense in light of your explanation about `dirtyRect` describing the region to be redrawn. So, thanks!
Jonathan Patt
You're welcome! Glad to hear it worked.
e.James