API 0.9.5
AppKit/CPBox.j
Go to the documentation of this file.
00001 /*
00002  * CPBox.j
00003  * AppKit
00004  *
00005  * Created by Ross Boucher.
00006  * Copyright 2009, 280 North, Inc.
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00023 
00024 // CPBoxType
00025 CPBoxPrimary    = 0;
00026 CPBoxSecondary  = 1;
00027 CPBoxSeparator  = 2;
00028 CPBoxOldStyle   = 3;
00029 CPBoxCustom     = 4;
00030 
00031 // CPBorderType
00032 CPNoBorder      = 0;
00033 CPLineBorder    = 1;
00034 CPBezelBorder   = 2;
00035 CPGrooveBorder  = 3;
00036 
00043 @implementation CPBox : CPView
00044 {
00045     CPBoxType       _boxType;
00046     CPBorderType    _borderType;
00047 
00048     CPColor         _borderColor;
00049     CPColor         _fillColor;
00050 
00051     float           _cornerRadius;
00052     float           _borderWidth;
00053 
00054     CPSize          _contentMargin;
00055     CPView          _contentView;
00056 }
00057 
00058 + (id)boxEnclosingView:(CPView)aView
00059 {
00060     var box = [[self alloc] initWithFrame:CGRectMakeZero()],
00061         enclosingView = [aView superview];
00062 
00063         [box setAutoresizingMask:[aView autoresizingMask]];
00064     [box setFrameFromContentFrame:[aView frame]];
00065 
00066     [enclosingView replaceSubview:aView with:box];
00067 
00068     [box setContentView:aView];
00069 
00070     return box;
00071 }
00072 
00073 - (id)initWithFrame:(CPRect)frameRect
00074 {
00075     self = [super initWithFrame:frameRect];
00076 
00077     if (self)
00078     {
00079         _borderType = CPBezelBorder;
00080         _fillColor = [CPColor clearColor];
00081         _borderColor = [CPColor blackColor];
00082 
00083         _borderWidth = 1.0;
00084         _contentMargin = CGSizeMake(0.0, 0.0);
00085 
00086         _contentView = [[CPView alloc] initWithFrame:[self bounds]];
00087         [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
00088 
00089         [self setAutoresizesSubviews:YES];
00090         [self addSubview:_contentView];
00091     }
00092 
00093     return self;
00094 }
00095 
00096 // Configuring Boxes
00097 
00103 - (CPRect)borderRect
00104 {
00105     return [self bounds];
00106 }
00107 
00120 - (CPBorderType)borderType
00121 {
00122     return _borderType;
00123 }
00124 
00125 
00138 - (void)setBorderType:(CPBorderType)aBorderType
00139 {
00140     if (_borderType === aBorderType)
00141         return;
00142 
00143     _borderType = aBorderType;
00144     [self setNeedsDisplay:YES];
00145 }
00146 
00162 - (CPBoxType)boxType
00163 {
00164     return _boxType;
00165 }
00166 
00182 - (void)setBoxType:(CPBoxType)aBoxType
00183 {
00184     if (_boxType === aBoxType)
00185         return;
00186 
00187     _boxType = aBoxType;
00188     [self setNeedsDisplay:YES];
00189 }
00190 
00191 - (CPColor)borderColor
00192 {
00193     return _borderColor;
00194 }
00195 
00196 - (void)setBorderColor:(CPColor)color
00197 {
00198     if ([color isEqual:_borderColor])
00199         return;
00200 
00201     _borderColor = color;
00202     [self setNeedsDisplay:YES];
00203 }
00204 
00205 - (float)borderWidth
00206 {
00207     return _borderWidth;
00208 }
00209 
00210 - (void)setBorderWidth:(float)width
00211 {
00212     if (width === _borderWidth)
00213         return;
00214 
00215     _borderWidth = width;
00216     [self setNeedsDisplay:YES];
00217 }
00218 
00219 - (float)cornerRadius
00220 {
00221     return _cornerRadius;
00222 }
00223 
00224 - (void)setCornerRadius:(float)radius
00225 {
00226     if (radius === _cornerRadius)
00227         return;
00228 
00229     _cornerRadius = radius;
00230     [self setNeedsDisplay:YES];
00231 }
00232 
00233 - (CPColor)fillColor
00234 {
00235     return _fillColor;
00236 }
00237 
00238 - (void)setFillColor:(CPColor)color
00239 {
00240     if ([color isEqual:_fillColor])
00241         return;
00242 
00243     _fillColor = color;
00244     [self setNeedsDisplay:YES];
00245 }
00246 
00247 - (CPView)contentView
00248 {
00249     return _contentView;
00250 }
00251 
00252 - (void)setContentView:(CPView)aView
00253 {
00254     if (aView === _contentView)
00255         return;
00256 
00257     [aView setFrame:CGRectInset([self bounds], _contentMargin.width + _borderWidth, _contentMargin.height + _borderWidth)];
00258     [aView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
00259     [self replaceSubview:_contentView with:aView];
00260 
00261     _contentView = aView;
00262 }
00263 
00264 - (CPSize)contentViewMargins
00265 {
00266     return _contentMargin;
00267 }
00268 
00269 - (void)setContentViewMargins:(CPSize)size
00270 {
00271      if (size.width < 0 || size.height < 0)
00272          [CPException raise:CPGenericException reason:@"Margins must be positive"];
00273 
00274     _contentMargin = CGSizeMakeCopy(size);
00275     [self setNeedsDisplay:YES];
00276 }
00277 
00278 - (void)setFrameFromContentFrame:(CPRect)aRect
00279 {
00280     [self setFrame:CGRectInset(aRect, -(_contentMargin.width + _borderWidth), -(_contentMargin.height + _borderWidth))];
00281     [self setNeedsDisplay:YES];
00282 }
00283 
00284 - (void)sizeToFit
00285 {
00286     var contentFrame = [_contentView frame];
00287 
00288     [self setFrameSize:CGSizeMake(contentFrame.size.width + _contentMargin.width * 2,
00289                                   contentFrame.size.height + _contentMargin.height * 2)];
00290 
00291     [_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height)];
00292 }
00293 
00294 - (void)drawRect:(CPRect)rect
00295 {
00296     if (_borderType === CPNoBorder)
00297         return;
00298 
00299     var bounds = [self bounds];
00300 
00301     switch (_boxType)
00302     {
00303         case CPBoxSeparator:
00304             // NSBox does not include a horizontal flag for the separator type. We have to determine
00305             // the type of separator to draw by the width and height of the frame.
00306             if (CGRectGetWidth(bounds) === 5.0)
00307                 return [self _drawVerticalSeperatorInRect:bounds];
00308             else if (CGRectGetHeight(bounds) === 5.0)
00309                 return [self _drawHorizontalSeperatorInRect:bounds];
00310 
00311             break;
00312     }
00313 
00314     switch (_borderType)
00315     {
00316         case CPBezelBorder:
00317             [self _drawBezelBorderInRect:bounds];
00318             break;
00319 
00320         default:
00321         case CPLineBorder:
00322             [self _drawLineBorderInRect:bounds];
00323             break;
00324     }
00325 }
00326 
00327 - (void)_drawHorizontalSeperatorInRect:(CGRect)aRect
00328 {
00329     var context = [[CPGraphicsContext currentContext] graphicsPort];
00330 
00331     CGContextSetStrokeColor(context, [self borderColor]);
00332     CGContextSetLineWidth(context, 1.0);
00333 
00334     CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMinY(aRect) + 0.5);
00335     CGContextAddLineToPoint(context, CGRectGetWidth(aRect), CGRectGetMinY(aRect) + 0.5);
00336     CGContextStrokePath(context);
00337 }
00338 
00339 - (void)_drawVerticalSeperatorInRect:(CGRect)aRect
00340 {
00341     var context = [[CPGraphicsContext currentContext] graphicsPort];
00342 
00343     CGContextSetStrokeColor(context, [self borderColor]);
00344     CGContextSetLineWidth(context, 1.0);
00345 
00346     CGContextMoveToPoint(context, CGRectGetMinX(aRect) + 0.5, CGRectGetMinY(aRect));
00347     CGContextAddLineToPoint(context, CGRectGetMinX(aRect) + 0.5, CGRectGetHeight(aRect));
00348     CGContextStrokePath(context);
00349 }
00350 
00351 - (void)_drawBezelBorderInRect:(CGRect)aRect
00352 {
00353     var context = [[CPGraphicsContext currentContext] graphicsPort],
00354         sides = [CPMinYEdge, CPMaxXEdge, CPMaxYEdge, CPMinXEdge],
00355         sideGray = 190.0 / 255.0,
00356         grays = [142.0 / 255.0, sideGray, sideGray, sideGray],
00357         borderWidth = _borderWidth;
00358 
00359     while (borderWidth--)
00360         aRect = CPDrawTiledRects(aRect, aRect, sides, grays);
00361 
00362     CGContextSetFillColor(context, [self fillColor]);
00363     CGContextFillRect(context, aRect);
00364 }
00365 
00366 - (void)_drawLineBorderInRect:(CGRect)aRect
00367 {
00368     var context = [[CPGraphicsContext currentContext] graphicsPort];
00369 
00370     aRect = CGRectInset(aRect, _borderWidth / 2.0, _borderWidth / 2.0);
00371 
00372     CGContextSetFillColor(context, [self fillColor]);
00373     CGContextSetStrokeColor(context, [self borderColor]);
00374 
00375     CGContextSetLineWidth(context, _borderWidth);
00376     CGContextFillRoundedRectangleInRect(context, aRect, _cornerRadius, YES, YES, YES, YES);
00377     CGContextStrokeRoundedRectangleInRect(context, aRect, _cornerRadius, YES, YES, YES, YES);
00378 }
00379 
00380 @end
00381 
00382 var CPBoxTypeKey          = @"CPBoxTypeKey",
00383     CPBoxBorderTypeKey    = @"CPBoxBorderTypeKey",
00384     CPBoxBorderColorKey   = @"CPBoxBorderColorKey",
00385     CPBoxFillColorKey     = @"CPBoxFillColorKey",
00386     CPBoxCornerRadiusKey  = @"CPBoxCornerRadiusKey",
00387     CPBoxBorderWidthKey   = @"CPBoxBorderWidthKey",
00388     CPBoxContentMarginKey = @"CPBoxContentMarginKey";
00389 
00390 @implementation CPBox (CPCoding)
00391 
00392 - (id)initWithCoder:(CPCoder)aCoder
00393 {
00394     self = [super initWithCoder:aCoder];
00395 
00396     if (self)
00397     {
00398         _boxType       = [aCoder decodeIntForKey:CPBoxTypeKey];
00399         _borderType    = [aCoder decodeIntForKey:CPBoxBorderTypeKey];
00400 
00401         _borderColor   = [aCoder decodeObjectForKey:CPBoxBorderColorKey];
00402         _fillColor     = [aCoder decodeObjectForKey:CPBoxFillColorKey];
00403 
00404         _cornerRadius  = [aCoder decodeFloatForKey:CPBoxCornerRadiusKey];
00405         _borderWidth   = [aCoder decodeFloatForKey:CPBoxBorderWidthKey];
00406 
00407         _contentMargin = [aCoder decodeSizeForKey:CPBoxContentMarginKey];
00408 
00409         _contentView   = [self subviews][0];
00410 
00411         [self setAutoresizesSubviews:YES];
00412         [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
00413     }
00414 
00415     return self;
00416 }
00417 
00418 - (void)encodeWithCoder:(CPCoder)aCoder
00419 {
00420     [super encodeWithCoder:aCoder];
00421 
00422     [aCoder encodeInt:_boxType forKey:CPBoxTypeKey];
00423     [aCoder encodeInt:_borderType forKey:CPBoxBorderTypeKey];
00424 
00425     [aCoder encodeObject:_borderColor forKey:CPBoxBorderColorKey];
00426     [aCoder encodeObject:_fillColor forKey:CPBoxFillColorKey];
00427 
00428     [aCoder encodeFloat:_cornerRadius forKey:CPBoxCornerRadiusKey];
00429     [aCoder encodeFloat:_borderWidth forKey:CPBoxBorderWidthKey];
00430 
00431     [aCoder encodeSize:_contentMargin forKey:CPBoxContentMarginKey];
00432 }
00433 
00434 @end
 All Classes Files Functions Variables Defines