Hi,

I want a generic animated split view. So I had a rummage online, and couldn't 
find anyone who had prepared the wheel for me. Consequently I set out to create 
my own.  I soon found that overriding setPosition:ofDividerAtIndex: and make it 
work correctly for split views with more than two views was not as simple as I 
expected it to be. Then I had a Bright Idea™ in realising that Apple have 
already done all the heavy lifting for me, and that I could use that to my 
advantage:

I created a category on NSSplitView which adds exactly two methods:

@interface NSSplitView (NSSplitView_Animation)

- (CGFloat)catPositionOfDividerAtIndex:(NSInteger)index;
- (void)catAnimateDividerAtIndex:(NSInteger)index 
toPosition:(CGFloat)newPosition;

@end

@implementation NSSplitView (NSSplitView_Animation)

- (CGFloat)catPositionOfDividerAtIndex:(NSInteger)index
{
        NSRect frame = [[self.subviews objectAtIndex:index] frame];
        return self.isVertical ? NSMaxX(frame) : NSMaxY(frame);
}

- (void)catAnimateDividerAtIndex:(NSInteger)index 
toPosition:(CGFloat)newPosition
{
        CGFloat currentPosition = [self catPositionOfDividerAtIndex:index];
        NSUInteger numberOfSubviews = self.subviews.count;
        NSRect newRect[numberOfSubviews];
        
        [self setPosition:newPosition ofDividerAtIndex:index];
        
        for (NSUInteger i = 0; i < numberOfSubviews; i++) {
                newRect[i] = [[self.subviews objectAtIndex:i] frame];
        }
        
        [self setPosition:currentPosition ofDividerAtIndex:index];
        
        [NSAnimationContext beginGrouping]; {
                [[NSAnimationContext currentContext] setDuration:0.2];
                for (NSUInteger i = 0; i < numberOfSubviews; i++) {
                        [[[self.subviews objectAtIndex:i] animator] 
setFrame:newRect[i]];
                }               
        } [NSAnimationContext endGrouping];
}

@end

So, what am I doing:
1. Get the current divider position.
2. Set the new divider position.
3. Get the frames of all the splitview's subviews, which are now adjusted to 
their new values.
4. Reset the divider position to the original, to restore the original frame 
values of the subviews.
5. Animate the frames of all subviews to their new values.

Why I am doing all this:
I initially thought I would only need to change the values of the frames for 
the two views on either side of the affected divider. But it turns out that, 
when doing that, other views also magically resize. I don't know why. It is 
possible I made a mistake somewhere, but, having taken a thorough look at my 
own code, I don't think so. That's when the idea occurred to leverage what 
Apple have already provided, rather then possibly spending hours wrestling to 
get it right, maybe only to find later that there are subtleties that I had 
overlooked. As far as I know, changing the divider position initially without 
animation, and changing it back without animation, to obtain correct new values 
for all subview frames before performing the actual animation, should have no 
side effects, and be fairly efficient, making this a cheap and code-economic 
technique.

I'm posting this for two reasons:
1. I want to ask if anyone thinks the technique used above has caveats or if 
anyone thinks the technique is inefficient and can think of a more efficient or 
better way to implement animation for NSSplitView.
2. It appears to work quite nicely for splitviews in either orientation, with 
any number of subviews, including sub-splitviews. If there is no solid reason 
to avoid this technique, it may be useful to others who are trying to do 
similar things with NSSplitView.

Any comments appreciated.

Oh, one last thing: anyone in favour of subclassing, rather than being 
categorical?

Cheers,
António

-----------------------------------------------------------
And could you keep your heart in wonder
at the daily miracles of your life,
your pain would not seem less wondrous
than your joy.

--Kahlil Gibran
-----------------------------------------------------------



_______________________________________________

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to