CocoaVLayout.m

Go to the documentation of this file.
00001 //
00002 //  CocoaVLayout.m
00003 //  
00004 //
00005 //  Created by Samuel Strupp on 10.08.10.
00006 //  Copyright 2010 Synium Software GmbH. All rights reserved.
00007 //
00008 
00009 #ifdef HAVE_CONFIG_H
00010 # include <config.h>
00011 #endif
00012 
00013 
00014 
00015 #import "CocoaVLayout.h"
00016 #import "CocoaGwenGUIProtocol.h"
00017 
00018 
00019 @implementation CocoaVLayout
00020 
00021 @synthesize fillX;
00022 @synthesize fillY;
00023 
00024 - (id)initWithFrame:(NSRect)frame {
00025     self = [super initWithFrame:frame];
00026     if (self) {
00027         fillX = NO;
00028                 fillY = NO;
00029                 subviewsInOrder = [[NSMutableArray alloc] init];
00030                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(layoutSubviews) name:NSViewFrameDidChangeNotification object:self];
00031     }
00032     return self;
00033 }
00034 
00035 -(void) dealloc {
00036         [[NSNotificationCenter defaultCenter] removeObserver:self];
00037         [subviewsInOrder release];
00038         [super dealloc];
00039 }
00040 
00041 /*- (void)drawRect:(NSRect)dirtyRect {
00042         //debug colors
00043     [[NSColor redColor] set];
00044         NSRectFill(dirtyRect);
00045 }*/
00046 
00047 #define borderDistance 8.0
00048 #define cellDistance 4.0
00049 
00050 -(void) layoutSubviews {
00051         NSRect bounds = [self bounds];
00052         
00053         NSUInteger numOfSubViews = [subviewsInOrder count];
00054         
00055         if (numOfSubViews > 0) {
00056                 //Prepass to compute the sizes
00057                 
00058                 CGFloat sizesHeight[numOfSubViews];
00059                 CGFloat sizesWidth[numOfSubViews];
00060                 CGFloat exclusiveHeight = 0.0;
00061                 NSUInteger exclusiveChilds = 0;
00062                 
00063                 NSUInteger i;
00064                 for (i=0; i<numOfSubViews; i++) {
00065                         NSView* subview = [subviewsInOrder objectAtIndex:i];
00066                         if ([subview conformsToProtocol:@protocol(CocoaGwenGUIProtocol)]) {
00067                                 if ([(<CocoaGwenGUIProtocol>)subview fillX]) sizesWidth[i] = -1.0;
00068                                 else {
00069                                         CGFloat neededWidth = [(<CocoaGwenGUIProtocol>)subview minSize].width;
00070                                         sizesWidth[i] = neededWidth;
00071                                 }
00072                                 if ([(<CocoaGwenGUIProtocol>)subview fillY]) sizesHeight[i] = -1.0;
00073                                 else {
00074                                         CGFloat neededHeight = [(<CocoaGwenGUIProtocol>)subview minSize].height;
00075                                         sizesHeight[i] = neededHeight;
00076                                         exclusiveHeight += neededHeight;
00077                                         exclusiveChilds++;
00078                                 }
00079                         }
00080                         else {
00081                                 sizesWidth[i] = -1.0;
00082                                 sizesHeight[i] = -1.0;
00083                         }
00084                 }
00085                 
00086                 
00087                 //Compute standard Sizes for Subviews
00088 
00089                 CGFloat stdHeight = 0.0;
00090                 if (numOfSubViews > exclusiveChilds) {
00091                         CGFloat fillHeight = bounds.size.height-exclusiveHeight;
00092                         stdHeight = (fillHeight-(borderDistance+borderDistance)-((numOfSubViews-1)*cellDistance))/(numOfSubViews-exclusiveChilds);
00093                 }
00094                 else {
00095                         CGFloat fillHeight = bounds.size.height;
00096                         stdHeight = (fillHeight-(borderDistance+borderDistance)-((numOfSubViews-1)*cellDistance))/(numOfSubViews);
00097                 }
00098                 
00099                 CGFloat stdWidth = bounds.size.width-(borderDistance+borderDistance);
00100                 
00101                 //if (numOfSubViews>=4) NSLog(@"view.height = %f", bounds.size.height);
00102                 
00103                 
00104                 //change Subviews Frame
00105                 NSRect actualFrame = bounds;
00106                 actualFrame.origin.x = borderDistance;
00107                 actualFrame.origin.y += bounds.size.height-borderDistance;
00108                 for (i=0; i<numOfSubViews; i++) {
00109                         
00110                         CGFloat usedHeight = sizesHeight[i];
00111                         if (usedHeight < 0.0) usedHeight = stdHeight;
00112                         actualFrame.origin.y -= usedHeight;
00113                         actualFrame.size.height = usedHeight;
00114                         
00115                         //if (numOfSubViews>=4) NSLog(@"subview %i height = %f", i, usedHeight);
00116                         
00117                         CGFloat usedWidth = sizesWidth[i];
00118                         if (usedWidth < 0.0) usedWidth = stdWidth;
00119                         NSView* subview = [subviewsInOrder objectAtIndex:i];
00120                         actualFrame.size.width = usedWidth;
00121                         
00122                         [subview setFrame:actualFrame];
00123                         actualFrame.origin.y -= cellDistance;
00124                 }
00125         }
00126         
00127 }
00128 
00129 -(void) addLayoutSubview:(NSView*)new_subview {
00130         [subviewsInOrder addObject:new_subview];
00131         [self addSubview:new_subview];
00132         [self layoutSubviews];
00133 }
00134 
00135 #pragma mark Protocoll Methods
00136 
00137 - (NSSize) minSize {
00138         NSUInteger numOfSubViews = [subviewsInOrder count];
00139         CGFloat borderWidth = borderDistance+borderDistance;
00140         NSSize size = NSMakeSize(borderWidth, borderWidth);
00141         if (numOfSubViews > 0) {
00142                 NSUInteger i;
00143                 for (i=0; i<numOfSubViews; i++) {
00144                         NSView* subview = [subviewsInOrder objectAtIndex:i];
00145                         if ([subview conformsToProtocol:@protocol(CocoaGwenGUIProtocol)]) {
00146                                 NSSize subViewMinSize = [(<CocoaGwenGUIProtocol>)subview minSize];
00147                                 if (subViewMinSize.width+borderWidth > size.width) {
00148                                         size.width = subViewMinSize.width+borderWidth;
00149                                 }
00150                                 size.height += subViewMinSize.height;
00151                                 if (i>0) size.height += cellDistance;
00152                         }
00153                 }
00154         }
00155         return size;
00156 }
00157 
00158 - (void)setFrame:(NSRect)frameRect {
00159         NSSize minSize = [self minSize];
00160         if (frameRect.size.height < minSize.height) {
00161                 frameRect.size.height = minSize.height;
00162         }
00163         if (frameRect.size.width < minSize.width) {
00164                 frameRect.size.width = minSize.width;
00165         }
00166         [super setFrame:frameRect];
00167 }
00168 
00169 @end