Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifdef HAVE_CONFIG_H
00010 # include <config.h>
00011 #endif
00012
00013 #import "CocoaGridLayout.h"
00014 #import "CocoaGwenGUIProtocol.h"
00015
00016
00017 @implementation CocoaGridLayout
00018
00019 @synthesize fillX;
00020 @synthesize fillY;
00021
00022 @synthesize columns;
00023 @synthesize rows;
00024
00025 - (id)initWithFrame:(NSRect)frame {
00026 self = [super initWithFrame:frame];
00027 if (self) {
00028 fillX = NO;
00029 fillY = NO;
00030 subviewsInOrder = [[NSMutableArray alloc] init];
00031 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(layoutSubviews) name:NSViewFrameDidChangeNotification object:self];
00032 }
00033 return self;
00034 }
00035
00036 -(void) dealloc {
00037 [[NSNotificationCenter defaultCenter] removeObserver:self];
00038 [subviewsInOrder release];
00039 [super dealloc];
00040 }
00041
00042
00043
00044
00045
00046
00047
00048 #define borderDistance 8.0
00049 #define cellDistance 4.0
00050
00051 -(void) layoutSubviews {
00052 NSRect bounds = [self bounds];
00053
00054 NSUInteger numOfSubViews = [subviewsInOrder count];
00055
00056 if (numOfSubViews > 0) {
00057
00058 BOOL columnMode = (columns > 0);
00059
00060 NSInteger neededColumns, neededRows;
00061
00062 if (columnMode) {
00063 neededColumns = columns;
00064 neededRows = numOfSubViews/columns + numOfSubViews%columns;
00065 }
00066 else {
00067 if (rows > 0) {
00068 neededColumns = numOfSubViews/rows + numOfSubViews%rows;
00069 neededRows = rows;
00070 }
00071 else {
00072
00073 neededColumns = 1;
00074 neededRows = numOfSubViews;
00075 }
00076 }
00077
00078
00079 CGFloat minWidthNeededForColumn[neededColumns];
00080 CGFloat minHeightNeededForRow[neededRows];
00081 char fillXFlags[neededColumns];
00082 char fillYFlags[neededRows];
00083
00084 NSUInteger i;
00085 for (i=0; i<neededColumns; i++) {
00086 minWidthNeededForColumn[i] = 0.0;
00087 fillXFlags[i] = 0;
00088 }
00089 for (i=0; i<neededRows; i++) {
00090 minHeightNeededForRow[i] = 0.0;
00091 fillYFlags[i] = 0;
00092 }
00093
00094 NSInteger actualRow, actualColumn;
00095
00096 for (i=0; i<numOfSubViews; i++) {
00097 if (columnMode) {
00098 actualRow = i/neededColumns;
00099 actualColumn = i%neededColumns;
00100 }
00101 else {
00102 actualRow = i%neededRows;
00103 actualColumn = i/neededRows;
00104 }
00105
00106 NSView* subview = [subviewsInOrder objectAtIndex:i];
00107 if ([subview conformsToProtocol:@protocol(CocoaGwenGUIProtocol)]) {
00108 NSSize minSize = [(<CocoaGwenGUIProtocol>)subview minSize];
00109
00110 if (minWidthNeededForColumn[actualColumn] < minSize.width)
00111 minWidthNeededForColumn[actualColumn] = minSize.width;
00112
00113 if (minHeightNeededForRow[actualRow] < minSize.height)
00114 minHeightNeededForRow[actualRow] = minSize.height;
00115
00116 if ([(<CocoaGwenGUIProtocol>)subview fillX]) fillXFlags[actualColumn] = 1;
00117 if ([(<CocoaGwenGUIProtocol>)subview fillY]) fillYFlags[actualRow] = 1;
00118
00119 }
00120 }
00121
00122
00123
00124 CGFloat maxWidth = bounds.size.width-borderDistance-borderDistance-(neededColumns-1)*cellDistance;
00125 NSInteger flexibleCells = 0;
00126 for(i=0; i<neededColumns; i++) {
00127 if (fillXFlags[i] == 1) flexibleCells++;
00128 else maxWidth -= minWidthNeededForColumn[i];
00129 }
00130 if (maxWidth > 0.0 && flexibleCells > 0) {
00131 CGFloat flexibleStdWidth = maxWidth/flexibleCells;
00132 for (i=0; i<neededColumns; i++) {
00133 if (fillXFlags[i] == 1) minWidthNeededForColumn[i] = flexibleStdWidth;
00134 }
00135 }
00136
00137 CGFloat maxHeight = bounds.size.height-borderDistance-borderDistance-(neededRows-1)*cellDistance;
00138 flexibleCells = 0;
00139 for(i=0; i<neededRows; i++) {
00140 if (fillYFlags[i] == 1) flexibleCells++;
00141 else maxHeight -= minHeightNeededForRow[i];
00142 }
00143 if (maxHeight > 0.0 && flexibleCells > 0) {
00144 CGFloat flexibleStdHeight = maxHeight/flexibleCells;
00145 for (i=0; i<neededRows; i++) {
00146 if (fillYFlags[i] == 1) minHeightNeededForRow[i] = flexibleStdHeight;
00147 }
00148 }
00149
00150
00151
00152
00153
00154 NSRect actualFrame = bounds;
00155 actualFrame.origin.x = borderDistance;
00156 actualFrame.origin.y += bounds.size.height-borderDistance;
00157
00158
00159 NSInteger oldIndex = -1;
00160
00161 for (i=0; i<numOfSubViews; i++) {
00162 if (columnMode) {
00163 actualRow = i/neededColumns;
00164 actualColumn = i%neededColumns;
00165
00166 if (oldIndex != actualRow) {
00167 actualFrame.origin.x = borderDistance;
00168 actualFrame.origin.y -= minHeightNeededForRow[actualRow]+cellDistance;
00169 oldIndex = actualRow;
00170 }
00171 }
00172 else {
00173 actualRow = i%neededRows;
00174 actualColumn = i/neededRows;
00175
00176 if (oldIndex != actualColumn) {
00177 if (oldIndex >= 0) actualFrame.origin.x += minWidthNeededForColumn[oldIndex]+cellDistance;
00178 actualFrame.origin.y = bounds.origin.y+bounds.size.height-borderDistance-minHeightNeededForRow[actualRow];
00179 oldIndex = actualColumn;
00180 }
00181 }
00182
00183 NSView* subview = [subviewsInOrder objectAtIndex:i];
00184
00185 actualFrame.size.height = minHeightNeededForRow[actualRow];
00186 actualFrame.size.width = minWidthNeededForColumn[actualColumn];
00187 NSRect realFrame = actualFrame;
00188 if ([subview conformsToProtocol:@protocol(CocoaGwenGUIProtocol)]) {
00189 BOOL flexWidth = [(<CocoaGwenGUIProtocol>)subview fillX];
00190 BOOL flexHeight = [(<CocoaGwenGUIProtocol>)subview fillY];
00191 if (!flexWidth || !flexHeight) {
00192 NSSize minSize = [(<CocoaGwenGUIProtocol>)subview minSize];
00193 if (!flexWidth && minSize.width < realFrame.size.width) realFrame.size.width = minSize.width;
00194 if (!flexHeight && minSize.height < realFrame.size.height) {
00195 realFrame.origin.y += realFrame.size.height-minSize.height;
00196 realFrame.size.height = minSize.height;
00197 }
00198 }
00199 }
00200 [subview setFrame:realFrame];
00201
00202
00203 if (columnMode) actualFrame.origin.x += actualFrame.size.width+cellDistance;
00204 else if (actualRow+1 < neededRows) actualFrame.origin.y -= minHeightNeededForRow[actualRow+1]+cellDistance;
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 }
00271
00272 }
00273
00274 -(void) addLayoutSubview:(NSView*)new_subview {
00275 [subviewsInOrder addObject:new_subview];
00276 [self addSubview:new_subview];
00277 [self layoutSubviews];
00278 }
00279
00280 #pragma mark Protocoll Methods
00281
00282 - (NSSize) minSize {
00283 NSUInteger numOfSubViews = [subviewsInOrder count];
00284
00285 if (numOfSubViews > 0) {
00286
00287 NSInteger neededColumns, neededRows;
00288 BOOL columnMode = (columns > 0);
00289 if (columnMode) {
00290 neededColumns = columns;
00291 neededRows = numOfSubViews/columns + numOfSubViews%columns;
00292 }
00293 else {
00294 if (rows > 0) {
00295 neededColumns = numOfSubViews/rows + numOfSubViews%rows;
00296 neededRows = rows;
00297 }
00298 else {
00299
00300 neededColumns = 1;
00301 neededRows = numOfSubViews;
00302 }
00303 }
00304
00305
00306 CGFloat minWidthNeededForColumn[neededColumns];
00307 CGFloat minHeightNeededForRow[neededRows];
00308
00309 NSUInteger i;
00310 for (i=0; i<neededColumns; i++) {
00311 minWidthNeededForColumn[i] = 0.0;
00312 }
00313 for (i=0; i<neededRows; i++) {
00314 minHeightNeededForRow[i] = 0.0;
00315 }
00316
00317 NSInteger actualRow, actualColumn;
00318
00319 for (i=0; i<numOfSubViews; i++) {
00320 if (columnMode) {
00321 actualRow = i/neededColumns;
00322 actualColumn = i%neededColumns;
00323 }
00324 else {
00325 actualRow = i%neededRows;
00326 actualColumn = i/neededRows;
00327 }
00328
00329 NSView* subview = [subviewsInOrder objectAtIndex:i];
00330 if ([subview conformsToProtocol:@protocol(CocoaGwenGUIProtocol)]) {
00331 NSSize minSize = [(<CocoaGwenGUIProtocol>)subview minSize];
00332
00333 if (minWidthNeededForColumn[actualColumn] < minSize.width)
00334 minWidthNeededForColumn[actualColumn] = minSize.width;
00335
00336 if (minHeightNeededForRow[actualRow] < minSize.height)
00337 minHeightNeededForRow[actualRow] = minSize.height;
00338 }
00339 }
00340 CGFloat minNeededWidth = borderDistance+borderDistance+(neededColumns-1)*cellDistance;
00341 for (i=0; i<neededColumns; i++) {
00342 minNeededWidth += minWidthNeededForColumn[i];
00343 }
00344 CGFloat minNeededHeight = borderDistance+borderDistance+(neededRows-1)*cellDistance;
00345 for (i=0; i<neededRows; i++) {
00346 minNeededHeight += minHeightNeededForRow[i];
00347 }
00348 return NSMakeSize(minNeededWidth, minNeededHeight);
00349 }
00350 return NSZeroSize;
00351 }
00352
00353 - (void)setFrame:(NSRect)frameRect {
00354 NSSize minSize = [self minSize];
00355 if (frameRect.size.height < minSize.height) {
00356 frameRect.size.height = minSize.height;
00357 }
00358 if (frameRect.size.width < minSize.width) {
00359 frameRect.size.width = minSize.width;
00360 }
00361 [super setFrame:frameRect];
00362 }
00363
00364 @end