1/* 2 Project: Cartotheque 3 4 Copyright (C) 2005 Stefan Urbanek 5 6 Author : Stefan Urbanek 7 Created: 2005-Feb 8 License: GNU LGPL 2.1 9*/ 10 11#import "CardMatrix.h" 12 13#import "Card.h" 14#import "Cartotheque.h" 15 16#import <Foundation/NSNotification.h> 17#import <AppKit/NSColor.h> 18#import <AppKit/NSGraphics.h> 19#import <AppKit/NSBezierPath.h> 20#import <AppKit/NSCell.h> 21#import <AppKit/NSMatrix.h> 22#import <AppKit/NSScrollView.h> 23#import <AppKit/NSStringDrawing.h> 24#import <AppKit/PSOperators.h> 25 26@interface CardCell:NSCell 27@end 28 29@implementation CardCell 30- initWithCard:(Card *)card 31{ 32 self = [super init]; 33 34 [self setRepresentedObject:card]; 35 36 return self; 37} 38- (void)drawInteriorWithFrame:(NSRect)cellFrame 39 inView:(NSView *)controlView 40{ 41 NSRect rect; 42 NSRect textRect; 43 44#define FACTOR 0.75 /* or whatever */ 45 PSgsave(); 46 PStranslate(cellFrame.origin.x,cellFrame.origin.y); 47 PSscale(FACTOR,FACTOR); 48 rect = NSMakeRect(0,0,cellFrame.size.width/FACTOR, 49 cellFrame.size.height/FACTOR); 50 51 rect = NSInsetRect(rect, 4,4); 52 53 [[NSColor whiteColor] set]; 54 [NSBezierPath fillRect:rect]; 55 [[NSColor blackColor] set]; 56 [NSBezierPath strokeRect:rect]; 57 58 textRect = NSInsetRect(rect, 4,4); 59 60 /* FIXME: this works only for NSString/NSAttributeString card contents */ 61 [[[self representedObject] contents] drawInRect: textRect]; 62 63 PSgrestore(); 64 65 if([self isHighlighted]) 66 { 67 NSColor *color; 68 color = [NSColor selectedControlColor]; 69 color = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; 70 color = [color colorWithAlphaComponent:0.5]; 71 72 [color set]; 73 [NSBezierPath fillRect:cellFrame]; 74 } 75} 76@end 77 78@interface CardMatrix(Private) 79- (void)_initSubviews; 80@end 81 82@implementation CardMatrix 83- initWithFrame:(NSRect)rect 84{ 85 self = [super initWithFrame:rect]; 86 87 [self _initSubviews]; 88 89 return self; 90} 91- (void)awakeFromNib 92{ 93 [self _initSubviews]; 94} 95- (void)_initSubviews 96{ 97 scrollView = [[NSScrollView alloc] initWithFrame:[self bounds]]; 98 matrix = [[NSMatrix alloc] initWithFrame:NSMakeRect(0,0,0,0)]; 99 100 [matrix setTarget:self]; 101 [matrix setAction:@selector(cardSelectionChanged:)]; 102 [matrix setDoubleAction:@selector(cardDoubleclicked:)]; 103 [matrix setMode:NSListModeMatrix]; 104 [matrix setAllowsEmptySelection:YES]; 105 106 [scrollView setBorderType:NSBezelBorder]; 107 [scrollView setDocumentView:matrix]; 108 [scrollView setAutoresizingMask:[self autoresizingMask]]; 109 [scrollView setHasVerticalScroller:YES]; 110 [scrollView setHasHorizontalScroller:NO]; 111 112 [self addSubview:scrollView]; 113 cardFrameSize = NSMakeSize(80.0, 60.0); 114 cardSpacing = NSMakeSize(4.0, 4.0); 115 116 [self setPostsFrameChangedNotifications:YES]; 117} 118- (void)dealloc 119{ 120 /* FIXME: release subviews */ 121 [[NSNotificationCenter defaultCenter] removeObserver:self]; 122 123 RELEASE(cartotheque); 124 RELEASE(delegate); 125 [super dealloc]; 126} 127- (void)setDelegate:(id)anObject 128{ 129 ASSIGN(delegate, anObject); 130} 131- (void)setCartotheque:(Cartotheque *)cards 132{ 133 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 134 135 ASSIGN(cartotheque, cards); 136 137 [nc removeObserver:self]; 138 139 [nc addObserver:self 140 selector:@selector(cartothequeCardsChanged:) 141 name:CardCreatedNotification 142 object:cartotheque]; 143 144 [nc addObserver:self 145 selector:@selector(frameDidChange:) 146 name:NSViewFrameDidChangeNotification 147 object:self]; 148 149 /* FIXME: use some other, probably private, method */ 150 [self reloadCards]; 151} 152- (void)cardSelectionChanged:(id)sender 153{ 154 Card *card; 155 156 card = [[matrix selectedCell] representedObject]; 157 158 /* FIXME: add array of selected objetcs */ 159 //[delegate cardMatrix:self didChangeSelection:nil]; 160} 161- (void)cardDoubleclicked:(id)sender 162{ 163 Card *card; 164 165 card = [[matrix selectedCell] representedObject]; 166 167 if([delegate respondsToSelector:@selector(cardMatrix:openCard:)]) 168 { 169 [delegate cardMatrix:self openCard:card]; 170 } 171} 172- (void)reloadCards 173{ 174 NSMutableArray *cells; 175 NSEnumerator *enumerator; 176 CardCell *cell; 177 NSSize size; 178 Card *card; 179 int i; 180 int columns; 181 182 /* remove all matrix cells */ 183 while([matrix numberOfRows] > 0) 184 { 185 [matrix removeRow:0]; 186 } 187 size = [scrollView contentSize]; 188 columns = size.width / (cardFrameSize.width + cardSpacing.width); 189 190 enumerator = [[cartotheque allCards] objectEnumerator]; 191 192 cells = [NSMutableArray array]; 193 194 i = 0; 195 196 while( (card = [enumerator nextObject]) ) 197 { 198 cell = [[CardCell alloc] initWithCard:card]; 199 [cells addObject:AUTORELEASE(cell)]; 200 201 i = i + 1; 202 if(i >= columns) 203 { 204 [matrix addRowWithCells:cells]; 205 [cells removeAllObjects]; 206 i = 0; 207 } 208 } 209 if([cells count] > 0) 210 { 211 [matrix addRowWithCells:cells]; 212 } 213 [matrix setCellSize:cardFrameSize]; 214 // [matrix setIntercellSpacing:cardSpacing]; 215 [matrix sizeToCells]; 216 217 /* FIXME: is this really needed? */ 218 [matrix setNeedsDisplay:YES]; 219 [scrollView setNeedsDisplay:YES]; 220 221 [self setNeedsDisplay:YES]; 222} 223- (NSArray *)selectedCards 224{ 225 NSMutableArray *array; 226 NSEnumerator *enumerator; 227 CardCell *cell; 228 Card *card; 229 230 array = [NSMutableArray array]; 231 enumerator = [[matrix selectedCells] objectEnumerator]; 232 233 while( (cell = [enumerator nextObject]) ) 234 { 235 card = [cell representedObject]; 236 [array addObject:card]; 237 } 238 239 return [NSArray arrayWithArray:array]; 240} 241 242- (void)setCardFrameSize:(NSSize)size 243{ 244 cardFrameSize = size; 245} 246- (void)cartothequeCardsChanged:(NSNotification *)notification 247{ 248 [self reloadCards]; 249 [self setNeedsDisplay:YES]; 250} 251- (void)frameDidChange:(NSNotification *)notification 252{ 253 [self reloadCards]; 254 [self setNeedsDisplay:YES]; 255} 256@end 257