Source/Grid.m
author Jens Alfke <jens@mooseyard.com>
Mon Mar 10 17:32:04 2008 -0700 (2008-03-10)
changeset 2 7b0441db81e5
parent 0 e9f7ba4718e1
child 3 40d225cf9c43
permissions -rw-r--r--
Oops, needed to fix an #include
jens@0
     1
/*  This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
jens@0
     2
    http://developer.apple.com/samplecode/GeekGameBoard/
jens@0
     3
    Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
jens@0
     4
jens@0
     5
    Redistribution and use in source and binary forms, with or without modification, are permitted
jens@0
     6
    provided that the following conditions are met:
jens@0
     7
jens@0
     8
    * Redistributions of source code must retain the above copyright notice, this list of conditions
jens@0
     9
      and the following disclaimer.
jens@0
    10
    * Redistributions in binary form must reproduce the above copyright notice, this list of
jens@0
    11
      conditions and the following disclaimer in the documentation and/or other materials provided
jens@0
    12
      with the distribution.
jens@0
    13
jens@0
    14
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
jens@0
    15
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
jens@0
    16
    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
jens@0
    17
    BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
jens@0
    18
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
jens@0
    19
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
jens@0
    20
    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
jens@0
    21
    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@0
    22
*/
jens@0
    23
#import "Grid.h"
jens@0
    24
#import "Bit.h"
jens@0
    25
#import "Game.h"
jens@0
    26
#import "QuartzUtils.h"
jens@0
    27
jens@0
    28
jens@0
    29
@implementation Grid
jens@0
    30
jens@0
    31
jens@0
    32
- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
jens@0
    33
            spacing: (CGSize)spacing
jens@0
    34
           position: (CGPoint)pos
jens@0
    35
{
jens@0
    36
    NSParameterAssert(nRows>0 && nColumns>0);
jens@0
    37
    self = [super init];
jens@0
    38
    if( self ) {
jens@0
    39
        _nRows = nRows;
jens@0
    40
        _nColumns = nColumns;
jens@0
    41
        _spacing = spacing;
jens@0
    42
        _cellClass = [GridCell class];
jens@1
    43
        self.lineColor = kBlackColor;
jens@0
    44
        _allowsMoves = YES;
jens@0
    45
        _usesDiagonals = YES;
jens@0
    46
jens@0
    47
        self.bounds = CGRectMake(-1, -1, nColumns*spacing.width+2, nRows*spacing.height+2);
jens@0
    48
        self.position = pos;
jens@0
    49
        self.anchorPoint = CGPointMake(0,0);
jens@0
    50
        self.zPosition = kBoardZ;
jens@0
    51
        self.needsDisplayOnBoundsChange = YES;
jens@0
    52
        
jens@0
    53
        unsigned n = nRows*nColumns;
jens@0
    54
        _cells = [[NSMutableArray alloc] initWithCapacity: n];
jens@0
    55
        id null = [NSNull null];
jens@0
    56
        while( n-- > 0 )
jens@0
    57
            [_cells addObject: null];
jens@0
    58
jens@0
    59
        [self setNeedsDisplay];
jens@0
    60
    }
jens@0
    61
    return self;
jens@0
    62
}
jens@0
    63
jens@0
    64
jens@0
    65
- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
jens@0
    66
              frame: (CGRect)frame
jens@0
    67
{
jens@0
    68
    CGFloat spacing = floor(MIN( (frame.size.width -2)/(CGFloat)nColumns,
jens@0
    69
                               (frame.size.height-2)/(CGFloat)nRows) );
jens@0
    70
    return [self initWithRows: nRows columns: nColumns
jens@0
    71
                      spacing: CGSizeMake(spacing,spacing)
jens@0
    72
                     position: frame.origin];
jens@0
    73
}
jens@0
    74
jens@0
    75
jens@0
    76
- (void) dealloc
jens@0
    77
{
jens@0
    78
    CGColorRelease(_cellColor);
jens@0
    79
    CGColorRelease(_lineColor);
jens@0
    80
    [_cells release];
jens@0
    81
    [super dealloc];
jens@0
    82
}
jens@0
    83
jens@0
    84
jens@0
    85
static void setcolor( CGColorRef *var, CGColorRef color )
jens@0
    86
{
jens@0
    87
    if( color != *var ) {
jens@0
    88
        CGColorRelease(*var);
jens@0
    89
        *var = CGColorRetain(color);
jens@0
    90
    }
jens@0
    91
}
jens@0
    92
jens@0
    93
- (CGColorRef) cellColor                        {return _cellColor;}
jens@0
    94
- (void) setCellColor: (CGColorRef)cellColor    {setcolor(&_cellColor,cellColor);}
jens@0
    95
jens@0
    96
- (CGColorRef) lineColor                        {return _lineColor;}
jens@0
    97
- (void) setLineColor: (CGColorRef)lineColor    {setcolor(&_lineColor,lineColor);}
jens@0
    98
jens@0
    99
@synthesize cellClass=_cellClass, rows=_nRows, columns=_nColumns, spacing=_spacing,
jens@0
   100
            usesDiagonals=_usesDiagonals, allowsMoves=_allowsMoves, allowsCaptures=_allowsCaptures;
jens@0
   101
jens@0
   102
jens@0
   103
#pragma mark -
jens@0
   104
#pragma mark GEOMETRY:
jens@0
   105
jens@0
   106
jens@0
   107
- (GridCell*) cellAtRow: (unsigned)row column: (unsigned)col
jens@0
   108
{
jens@0
   109
    if( row < _nRows && col < _nColumns ) {
jens@0
   110
        id cell = [_cells objectAtIndex: row*_nColumns+col];
jens@0
   111
        if( cell != [NSNull null] )
jens@0
   112
            return cell;
jens@0
   113
    }
jens@0
   114
    return nil;
jens@0
   115
}
jens@0
   116
jens@0
   117
jens@0
   118
/** Subclasses can override this, to change the cell's class or frame. */
jens@0
   119
- (GridCell*) createCellAtRow: (unsigned)row column: (unsigned)col 
jens@0
   120
               suggestedFrame: (CGRect)frame
jens@0
   121
{
jens@0
   122
    return [[[_cellClass alloc] initWithGrid: self 
jens@0
   123
                                        row: row column: col
jens@0
   124
                                      frame: frame]
jens@0
   125
                    autorelease];
jens@0
   126
}
jens@0
   127
jens@0
   128
jens@0
   129
- (GridCell*) addCellAtRow: (unsigned)row column: (unsigned)col
jens@0
   130
{
jens@0
   131
    NSParameterAssert(row<_nRows);
jens@0
   132
    NSParameterAssert(col<_nColumns);
jens@0
   133
    unsigned index = row*_nColumns+col;
jens@0
   134
    GridCell *cell = [_cells objectAtIndex: index];
jens@0
   135
    if( (id)cell == [NSNull null] ) {
jens@0
   136
        CGRect frame = CGRectMake(col*_spacing.width, row*_spacing.height,
jens@0
   137
                                  _spacing.width,_spacing.height);
jens@0
   138
        cell = [self createCellAtRow: row column: col suggestedFrame: frame];
jens@0
   139
        if( cell ) {
jens@0
   140
            [_cells replaceObjectAtIndex: index withObject: cell];
jens@0
   141
            [self addSublayer: cell];
jens@0
   142
            [self setNeedsDisplay];
jens@0
   143
        }
jens@0
   144
    }
jens@0
   145
    return cell;
jens@0
   146
}
jens@0
   147
jens@0
   148
jens@0
   149
- (void) addAllCells
jens@0
   150
{
jens@0
   151
    for( int row=_nRows-1; row>=0; row-- )                // makes 'upper' cells be in 'back'
jens@0
   152
        for( int col=0; col<_nColumns; col++ ) 
jens@0
   153
            [self addCellAtRow: row column: col];
jens@0
   154
}
jens@0
   155
jens@0
   156
jens@0
   157
- (void) removeCellAtRow: (unsigned)row column: (unsigned)col
jens@0
   158
{
jens@0
   159
    NSParameterAssert(row<_nRows);
jens@0
   160
    NSParameterAssert(col<_nColumns);
jens@0
   161
    unsigned index = row*_nColumns+col;
jens@0
   162
    id cell = [_cells objectAtIndex: index];
jens@0
   163
    if( cell != [NSNull null] )
jens@0
   164
        [cell removeFromSuperlayer];
jens@0
   165
    [_cells replaceObjectAtIndex: index withObject: [NSNull null]];
jens@0
   166
    [self setNeedsDisplay];
jens@0
   167
}
jens@0
   168
jens@0
   169
jens@0
   170
#pragma mark -
jens@0
   171
#pragma mark DRAWING:
jens@0
   172
jens@0
   173
jens@0
   174
- (void) drawCellsInContext: (CGContextRef)ctx fill: (BOOL)fill
jens@0
   175
{
jens@0
   176
    // Subroutine of -drawInContext:. Draws all the cells, with or without a fill.
jens@0
   177
    for( unsigned row=0; row<_nRows; row++ )
jens@0
   178
        for( unsigned col=0; col<_nColumns; col++ ) {
jens@0
   179
            GridCell *cell = [self cellAtRow: row column: col];
jens@0
   180
            if( cell )
jens@0
   181
                [cell drawInParentContext: ctx fill: fill];
jens@0
   182
        }
jens@0
   183
}
jens@0
   184
jens@0
   185
jens@0
   186
- (void)drawInContext:(CGContextRef)ctx
jens@0
   187
{
jens@0
   188
    // Custom CALayer drawing implementation. Delegates to the cells to draw themselves
jens@0
   189
    // in me; this is more efficient than having each cell have its own drawing.
jens@0
   190
    if( _cellColor ) {
jens@0
   191
        CGContextSetFillColorWithColor(ctx, _cellColor);
jens@0
   192
        [self drawCellsInContext: ctx fill: YES];
jens@0
   193
    }
jens@0
   194
    if( _lineColor ) {
jens@0
   195
        CGContextSetStrokeColorWithColor(ctx,_lineColor);
jens@0
   196
        [self drawCellsInContext:ctx fill: NO];
jens@0
   197
    }
jens@0
   198
}
jens@0
   199
jens@0
   200
jens@0
   201
@end
jens@0
   202
jens@0
   203
jens@0
   204
jens@0
   205
#pragma mark -
jens@0
   206
jens@0
   207
@implementation GridCell
jens@0
   208
jens@0
   209
jens@0
   210
- (id) initWithGrid: (Grid*)grid 
jens@0
   211
                row: (unsigned)row column: (unsigned)col
jens@0
   212
              frame: (CGRect)frame
jens@0
   213
{
jens@0
   214
    self = [super init];
jens@0
   215
    if (self != nil) {
jens@0
   216
        _grid = grid;
jens@0
   217
        _row = row;
jens@0
   218
        _column = col;
jens@0
   219
        self.position = frame.origin;
jens@0
   220
        CGRect bounds = frame;
jens@0
   221
        bounds.origin.x -= floor(bounds.origin.x);  // make sure my coords fall on pixel boundaries
jens@0
   222
        bounds.origin.y -= floor(bounds.origin.y);
jens@0
   223
        self.bounds = bounds;
jens@0
   224
        self.anchorPoint = CGPointMake(0,0);
jens@0
   225
        self.borderColor = kHighlightColor;         // Used when highlighting (see -setHighlighted:)
jens@0
   226
    }
jens@0
   227
    return self;
jens@0
   228
}
jens@0
   229
jens@0
   230
- (NSString*) description
jens@0
   231
{
jens@0
   232
    return [NSString stringWithFormat: @"%@(%u,%u)", [self class],_column,_row];
jens@0
   233
}
jens@0
   234
jens@0
   235
@synthesize grid=_grid, row=_row, column=_column;
jens@0
   236
jens@0
   237
jens@0
   238
- (void) drawInParentContext: (CGContextRef)ctx fill: (BOOL)fill
jens@0
   239
{
jens@0
   240
    // Default implementation just fills or outlines the cell.
jens@0
   241
    CGRect frame = self.frame;
jens@0
   242
    if( fill )
jens@0
   243
        CGContextFillRect(ctx,frame);
jens@0
   244
    else
jens@0
   245
        CGContextStrokeRect(ctx, frame);
jens@0
   246
}
jens@0
   247
jens@0
   248
jens@0
   249
- (void) setBit: (Bit*)bit
jens@0
   250
{
jens@0
   251
    if( bit != self.bit ) {
jens@0
   252
        [super setBit: bit];
jens@0
   253
        if( bit ) {
jens@0
   254
            // Center it:
jens@0
   255
            CGSize size = self.bounds.size;
jens@0
   256
            bit.position = CGPointMake(floor(size.width/2.0),
jens@0
   257
                                       floor(size.height/2.0));
jens@0
   258
        }
jens@0
   259
    }
jens@0
   260
}
jens@0
   261
jens@0
   262
- (Bit*) canDragBit: (Bit*)bit
jens@0
   263
{
jens@0
   264
    if( _grid.allowsMoves && bit==self.bit )
jens@0
   265
        return [super canDragBit: bit];
jens@0
   266
    else
jens@0
   267
        return nil;
jens@0
   268
}
jens@0
   269
jens@0
   270
- (BOOL) canDropBit: (Bit*)bit atPoint: (CGPoint)point
jens@0
   271
{
jens@0
   272
    return self.bit == nil || _grid.allowsCaptures;
jens@0
   273
}
jens@0
   274
jens@0
   275
jens@0
   276
- (BOOL) fwdIsN 
jens@0
   277
{
jens@0
   278
    return self.game.currentPlayer.index == 0;
jens@0
   279
}
jens@0
   280
jens@0
   281
jens@0
   282
- (NSArray*) neighbors
jens@0
   283
{
jens@0
   284
    BOOL orthogonal = ! _grid.usesDiagonals;
jens@0
   285
    NSMutableArray *neighbors = [NSMutableArray arrayWithCapacity: 8];
jens@0
   286
    for( int dy=-1; dy<=1; dy++ )
jens@0
   287
        for( int dx=-1; dx<=1; dx++ )
jens@0
   288
            if( (dx || dy) && !(orthogonal && dx && dy) ) {
jens@0
   289
                GridCell *cell = [_grid cellAtRow: _row+dy column: _column+dx];
jens@0
   290
                if( cell )
jens@0
   291
                    [neighbors addObject: cell];
jens@0
   292
            }
jens@0
   293
    return neighbors;
jens@0
   294
}
jens@0
   295
jens@0
   296
jens@0
   297
// Recursive subroutine used by getGroup:.
jens@0
   298
- (void) x_addToGroup: (NSMutableSet*)group liberties: (NSMutableSet*)liberties owner: (Player*)owner
jens@0
   299
{
jens@0
   300
    Bit *bit = self.bit;
jens@0
   301
    if( bit == nil ) {
jens@0
   302
        if( [liberties containsObject: self] )
jens@0
   303
            return; // already traversed
jens@0
   304
        [liberties addObject: self];
jens@0
   305
    } else if( bit.owner==owner ) {
jens@0
   306
        if( [group containsObject: self] )
jens@0
   307
            return; // already traversed
jens@0
   308
        [group addObject: self];
jens@0
   309
        for( GridCell *c in self.neighbors )
jens@0
   310
            [c x_addToGroup: group liberties: liberties owner: owner];
jens@0
   311
    }
jens@0
   312
}
jens@0
   313
jens@0
   314
jens@0
   315
- (NSSet*) getGroup: (int*)outLiberties
jens@0
   316
{
jens@0
   317
    NSMutableSet *group=[NSMutableSet set], *liberties=nil;
jens@0
   318
    if( outLiberties )
jens@0
   319
        liberties = [NSMutableSet set];
jens@0
   320
    [self x_addToGroup: group liberties: liberties owner: self.bit.owner];
jens@0
   321
    if( outLiberties )
jens@0
   322
        *outLiberties = liberties.count;
jens@0
   323
    return group;
jens@0
   324
}
jens@0
   325
jens@0
   326
jens@0
   327
#pragma mark -
jens@0
   328
#pragma mark DRAG-AND-DROP:
jens@0
   329
jens@0
   330
jens@1
   331
#if ! TARGET_OS_ASPEN
jens@1
   332
jens@0
   333
// An image from another app can be dragged onto a Dispenser to change the Piece's appearance.
jens@0
   334
jens@0
   335
jens@0
   336
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
jens@0
   337
{
jens@0
   338
    NSPasteboard *pb = [sender draggingPasteboard];
jens@0
   339
    if( [NSImage canInitWithPasteboard: pb] )
jens@0
   340
        return NSDragOperationCopy;
jens@0
   341
    else
jens@0
   342
        return NSDragOperationNone;
jens@0
   343
}
jens@0
   344
jens@0
   345
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
jens@0
   346
{
jens@0
   347
    CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
jens@0
   348
    if( image ) {
jens@0
   349
        CGColorRef pattern = CreatePatternColor(image);
jens@0
   350
        _grid.cellColor = pattern;
jens@0
   351
        CGColorRelease(pattern);
jens@0
   352
        [_grid setNeedsDisplay];
jens@0
   353
        return YES;
jens@0
   354
    } else
jens@0
   355
        return NO;
jens@0
   356
}
jens@0
   357
jens@1
   358
#endif
jens@0
   359
jens@0
   360
@end
jens@0
   361
jens@0
   362
jens@0
   363
jens@0
   364
jens@0
   365
#pragma mark -
jens@0
   366
jens@0
   367
@implementation RectGrid
jens@0
   368
jens@0
   369
jens@0
   370
- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
jens@0
   371
            spacing: (CGSize)spacing
jens@0
   372
           position: (CGPoint)pos
jens@0
   373
{
jens@0
   374
    self = [super initWithRows: nRows columns: nColumns spacing: spacing position: pos];
jens@0
   375
    if( self ) {
jens@0
   376
        _cellClass = [Square class];
jens@0
   377
    }
jens@0
   378
    return self;
jens@0
   379
}
jens@0
   380
jens@0
   381
jens@0
   382
- (CGColorRef) altCellColor                         {return _altCellColor;}
jens@0
   383
- (void) setAltCellColor: (CGColorRef)altCellColor  {setcolor(&_altCellColor,altCellColor);}
jens@0
   384
jens@0
   385
jens@0
   386
@end
jens@0
   387
jens@0
   388
jens@0
   389
jens@0
   390
#pragma mark -
jens@0
   391
jens@0
   392
@implementation Square
jens@0
   393
jens@0
   394
jens@0
   395
- (void) drawInParentContext: (CGContextRef)ctx fill: (BOOL)fill
jens@0
   396
{
jens@0
   397
    if( fill ) {
jens@0
   398
        CGColorRef c = ((RectGrid*)_grid).altCellColor;
jens@0
   399
        if( c ) {
jens@0
   400
            if( ! ((_row+_column) & 1) )
jens@0
   401
                c = _grid.cellColor;
jens@0
   402
            CGContextSetFillColorWithColor(ctx, c);
jens@0
   403
        }
jens@0
   404
    }
jens@0
   405
    [super drawInParentContext: ctx fill: fill];
jens@0
   406
}
jens@0
   407
jens@0
   408
jens@0
   409
- (void) setHighlighted: (BOOL)highlighted
jens@0
   410
{
jens@0
   411
    [super setHighlighted: highlighted];
jens@0
   412
    self.borderWidth = (highlighted ?6 :0);
jens@0
   413
}
jens@0
   414
jens@0
   415
jens@0
   416
- (Square*) nw     {return (Square*)[_grid cellAtRow: _row+1 column: _column-1];}
jens@0
   417
- (Square*) n      {return (Square*)[_grid cellAtRow: _row+1 column: _column  ];}
jens@0
   418
- (Square*) ne     {return (Square*)[_grid cellAtRow: _row+1 column: _column+1];}
jens@0
   419
- (Square*) e      {return (Square*)[_grid cellAtRow: _row   column: _column+1];}
jens@0
   420
- (Square*) se     {return (Square*)[_grid cellAtRow: _row-1 column: _column+1];}
jens@0
   421
- (Square*) s      {return (Square*)[_grid cellAtRow: _row-1 column: _column  ];}
jens@0
   422
- (Square*) sw     {return (Square*)[_grid cellAtRow: _row-1 column: _column-1];}
jens@0
   423
- (Square*) w      {return (Square*)[_grid cellAtRow: _row   column: _column-1];}
jens@0
   424
jens@0
   425
// Directions relative to the current player:
jens@0
   426
- (Square*) fl     {return self.fwdIsN ?self.nw :self.se;}
jens@0
   427
- (Square*) f      {return self.fwdIsN ?self.n  :self.s;}
jens@0
   428
- (Square*) fr     {return self.fwdIsN ?self.ne :self.sw;}
jens@0
   429
- (Square*) r      {return self.fwdIsN ?self.e  :self.w;}
jens@0
   430
- (Square*) br     {return self.fwdIsN ?self.se :self.nw;}
jens@0
   431
- (Square*) b      {return self.fwdIsN ?self.s  :self.n;}
jens@0
   432
- (Square*) bl     {return self.fwdIsN ?self.sw :self.ne;}
jens@0
   433
- (Square*) l      {return self.fwdIsN ?self.w  :self.e;}
jens@0
   434
jens@0
   435
jens@1
   436
#if ! TARGET_OS_ASPEN
jens@1
   437
jens@0
   438
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
jens@0
   439
{
jens@0
   440
    CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
jens@0
   441
    if( image ) {
jens@0
   442
        CGColorRef color = CreatePatternColor(image);
jens@0
   443
        RectGrid *rectGrid = (RectGrid*)_grid;
jens@0
   444
        if( rectGrid.altCellColor && ((_row+_column) & 1) )
jens@0
   445
            rectGrid.altCellColor = color;
jens@0
   446
        else
jens@0
   447
            rectGrid.cellColor = color;
jens@0
   448
        CGColorRelease(color);
jens@0
   449
        [rectGrid setNeedsDisplay];
jens@0
   450
        return YES;
jens@0
   451
    } else
jens@0
   452
        return NO;
jens@0
   453
}
jens@0
   454
jens@1
   455
#endif
jens@1
   456
jens@0
   457
@end
jens@0
   458
jens@0
   459
jens@0
   460
jens@0
   461
#pragma mark -
jens@0
   462
jens@0
   463
@implementation GoSquare
jens@0
   464
jens@0
   465
@synthesize dotted=_dotted;
jens@0
   466
jens@0
   467
- (void) drawInParentContext: (CGContextRef)ctx fill: (BOOL)fill
jens@0
   468
{
jens@0
   469
    if( fill )
jens@0
   470
        [super drawInParentContext: ctx fill: fill];
jens@0
   471
    else {
jens@0
   472
        CGRect frame = self.frame;
jens@0
   473
        const CGFloat midx=floor(CGRectGetMidX(frame))+0.5, 
jens@0
   474
                    midy=floor(CGRectGetMidY(frame))+0.5;
jens@0
   475
        CGPoint p[4] = {{CGRectGetMinX(frame),midy},
jens@0
   476
                        {CGRectGetMaxX(frame),midy},
jens@0
   477
                        {midx,CGRectGetMinY(frame)},
jens@0
   478
                        {midx,CGRectGetMaxY(frame)}};
jens@0
   479
        if( ! self.s )  p[2].y = midy;
jens@0
   480
        if( ! self.n )  p[3].y = midy;
jens@0
   481
        if( ! self.w )  p[0].x = midx;
jens@0
   482
        if( ! self.e )  p[1].x = midx;
jens@0
   483
        CGContextStrokeLineSegments(ctx, p, 4);
jens@0
   484
        
jens@0
   485
        if( _dotted ) {
jens@0
   486
            CGContextSetFillColorWithColor(ctx,_grid.lineColor);
jens@0
   487
            CGRect dot = CGRectMake(midx-2.5, midy-2.5, 5, 5);
jens@0
   488
            CGContextFillEllipseInRect(ctx, dot);
jens@0
   489
        }
jens@0
   490
    }
jens@0
   491
}
jens@0
   492
jens@1
   493
jens@0
   494
@end