Merge pull request #10 from gunyarakun/fix-invalid-return
[cocotron.git] / AppKit / NSTextFieldCell.m
bloba992089bb2a30b602e4a686e233f61dfd1df10cb
1 /* Copyright (c) 2006-2007 Christopher J. W. Lloyd <cjwl@objc.net>
3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
9 #import <AppKit/NSTextFieldCell.h>
10 #import <AppKit/NSApplication.h>
11 #import <AppKit/NSAttributedString.h>
12 #import <AppKit/NSStringDrawing.h>
13 #import <AppKit/NSGraphicsContext.h>
14 #import <AppKit/NSGraphics.h>
15 #import <AppKit/NSGraphicsStyle.h>
16 #import <AppKit/NSFont.h>
17 #import <AppKit/NSColor.h>
18 #import <AppKit/NSParagraphStyle.h>
19 #import <AppKit/NSStringDrawer.h>
20 #import <Foundation/NSKeyedArchiver.h>
21 #import <AppKit/NSObject+BindingSupport.h>
22 #import <AppKit/NSRaise.h>
24 @implementation NSTextFieldCell
26 -(void)encodeWithCoder:(NSCoder *)coder {
27    NSUnimplementedMethod();
30 -initWithCoder:(NSCoder *)coder {
31    [super initWithCoder:coder];
33    if([coder allowsKeyedCoding]){
34     NSKeyedUnarchiver *keyed=(NSKeyedUnarchiver *)coder;
35     
36     _drawsBackground=[keyed decodeBoolForKey:@"NSDrawsBackground"];
37     _backgroundColor=[[keyed decodeObjectForKey:@"NSBackgroundColor"] retain];
38     _textColor=[[keyed decodeObjectForKey:@"NSTextColor"] retain];
39     _bezelStyle=[keyed decodeIntegerForKey:@"NSTextBezelStyle"];
40     _placeholder=[[keyed decodeObjectForKey:@"NSPlaceholderString"] retain];
41    }
42    else {
43     [NSException raise:NSInvalidArgumentException format:@"%@ can not initWithCoder:%@",isa,[coder class]];
44    }
46    return self;
49 -initTextCell:(NSString *)string {
50   [super initTextCell:string];
51   // default for _isBezeled=NO;
52   return self;
55 // Override NSCell behavior of creating an image/null type cell
56 -init {
57    return [self initTextCell:@""];
60 -(void)dealloc {
61    [_backgroundColor release];
62    [_textColor release];
63    [super dealloc];
66 -copyWithZone:(NSZone *)zone {
67     NSTextFieldCell *cell = [super copyWithZone:zone];
69     cell->_backgroundColor=[_backgroundColor copy];
70     cell->_textColor=[_textColor copy];
72     return cell;
75 -(NSCellType)type {
76    return NSTextCellType;
79 -(NSColor *)backgroundColor {
80    return _backgroundColor;
83 -(NSColor *)textColor {
84    return _textColor;
87 -(BOOL)drawsBackground {
88    return _drawsBackground;
91 -(NSTextFieldBezelStyle)bezelStyle {
92    return _bezelStyle;
95 -(NSString *)placeholderString {
96    if([_placeholder isKindOfClass:[NSString class]])
97     return _placeholder;
98     
99    return nil;
102 -(NSAttributedString *)placeholderAttributedString {
103    if([_placeholder isKindOfClass:[NSAttributedString class]])
104     return _placeholder;
105     
106    return nil;
109 -(void)setBackgroundColor:(NSColor *)color {
110    color=[color retain];
111    [_backgroundColor release];
112    _backgroundColor=color; 
115 -(void)setTextColor:(NSColor *)color {
116    color=[color retain];
117    [_textColor release];
118    _textColor=color; 
121 -(void)setDrawsBackground:(BOOL)flag {
122    _drawsBackground=flag;
125 -(void)setBezelStyle:(NSTextFieldBezelStyle)value {
126    _bezelStyle=value;
129 -(void)setPlaceholderString:(NSString *)value {
130    value=[value copy];
131    [_placeholder release];
132    _placeholder=value;
135 -(void)setPlaceholderAttributedString:(NSAttributedString *)value {
136    value=[value copy];
137    [_placeholder release];
138    _placeholder=value;
141 // titleRectForBounds is not used for generating the value rect in a text field
142 -(NSRect)_valueRectForBounds:(NSRect)rect {
143    if([self isBezeled]){
144    
145     switch([self bezelStyle]){
146      default:
147      case NSTextFieldSquareBezel:
148     rect=NSInsetRect(rect,3,3);
149       break;
151      case NSTextFieldRoundedBezel:;
152       CGFloat radius=rect.size.height/2;
153       rect=NSInsetRect(rect,radius,3);
154       break;
155     }
156    }
157    else if([self isBordered])
158     rect=NSInsetRect(rect,2,2);
159    else 
160     rect=NSInsetRect(rect,2,0); 
162    return rect;
165 -(NSRect)titleRectForBounds:(NSRect)rect {
166    return [self _valueRectForBounds:rect];
169 -(NSRect)drawingRectForBounds:(NSRect)rect {
170    return [self _valueRectForBounds:rect];
173 -(NSAttributedString *)attributedStringValue {
174    if([_objectValue isKindOfClass:[NSAttributedString class]]){
175     if(_textColor==nil)
176      return _objectValue;
177     else {
178      NSMutableAttributedString *result=[[_objectValue mutableCopy] autorelease];
180      [result addAttribute:NSForegroundColorAttributeName value:_textColor range:NSMakeRange(0,[result length])];
182      return result;
183     }
184    }
185    else {
186     NSMutableDictionary *attributes=[NSMutableDictionary dictionary];
187     NSMutableParagraphStyle *paraStyle=[[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
188     NSFont              *font=[self font];
190     if(font!=nil)
191      [attributes setObject:font forKey:NSFontAttributeName];
193     if([self isEnabled]){
194      if(_textColor!=nil)
195       [attributes setObject:_textColor
196                      forKey:NSForegroundColorAttributeName];
197     }
198     else {
199      [attributes setObject:[NSColor disabledControlTextColor]
200                      forKey:NSForegroundColorAttributeName];
201     }
203 #if 0
204     if([self drawsBackground]/* && ![self isBezeled]*/){
205      NSColor *color=(_backgroundColor==nil)?[NSColor controlColor]:_backgroundColor;
206      [attributes setObject:color
207                     forKey:NSBackgroundColorAttributeName];
208     }
209 #endif
211     [paraStyle setLineBreakMode:_lineBreakMode];
212     [paraStyle setAlignment:_textAlignment];
213     [attributes setObject:paraStyle forKey:NSParagraphStyleAttributeName];
215     return [[[NSAttributedString alloc] initWithString:[self stringValue] attributes:attributes] autorelease];
216    }
219 -(NSSize)cellSize 
221         NSSize size = [[self attributedStringValue] size];
222         
223         if([self isBezeled])
224         {
225                 size.width += 6;
226                 size.height += 6;
227         }
228         else if([self isBordered])
229         {
230                 size.width += 4;
231                 size.height += 4;
232         }
233         else
234         {
235                 size.width += 4;
236         }
237         return size;
240 -(void)editWithFrame:(NSRect)frame inView:(NSView *)view editor:(NSText *)editor delegate:(id)delegate event:(NSEvent *)event {
241    frame=[self titleRectForBounds:frame];
242    [super editWithFrame:frame inView:view editor:editor delegate:delegate event:event];
245 -(void)selectWithFrame:(NSRect)frame inView:(NSView *)view editor:(NSText *)editor delegate:(id)delegate start:(int)location length:(int)length {
246    frame=[self titleRectForBounds:frame];
247    [super selectWithFrame:frame inView:view editor:editor delegate:delegate start:location length:length];
250 -(void)drawInteriorWithFrame:(NSRect)frame inView:(NSView *)control {
251    NSRect titleRect=[self titleRectForBounds:frame];
253    NSAttributedString *drawValue=[self attributedStringValue];
254    
255    if([drawValue length]==0 && [_placeholder length]>0){
256     if([_placeholder isKindOfClass:[NSAttributedString class]])
257       drawValue=_placeholder;
258     else if([_placeholder isKindOfClass:[NSString class]]){
259      NSMutableAttributedString *placeString=[[drawValue mutableCopy] autorelease];
260      [[placeString mutableString] setString:_placeholder];
261      [placeString addAttribute:NSForegroundColorAttributeName value:[NSColor disabledControlTextColor] range:NSMakeRange(0,[placeString length])];
262      drawValue=placeString;
264    }
265         [drawValue _clipAndDrawInRect:titleRect truncatingTail: _lineBreakMode > NSLineBreakByClipping];
268 static void drawRoundedBezel(CGContextRef context,CGRect frame){
269    CGFloat radius=frame.size.height/2;
270    
271    CGContextBeginPath(context);
272    CGContextAddArc(context,CGRectGetMaxX(frame)-radius,CGRectGetMinY(frame)+radius,radius,M_PI_2,M_PI_2*3,YES);
273    CGContextAddArc(context,CGRectGetMinX(frame)+radius,CGRectGetMinY(frame)+radius,radius,M_PI_2*3,M_PI_2,YES);
274    CGContextClosePath(context);
275    CGContextFillPath(context);
278 -(void)drawWithFrame:(NSRect)frame inView:(NSView *)control {
279    NSRect backRect=[self drawingRectForBounds:frame];
281    _controlView=control;
283    if([self isBezeled]){
284     switch([self bezelStyle]){
285      default:
286      case NSTextFieldSquareBezel:
287     [[control graphicsStyle] drawTextFieldBorderInRect:frame bezeledNotLine:YES];
288     backRect=NSInsetRect(backRect,-1,-1);
289       break;
291      case NSTextFieldRoundedBezel:;
292       CGContextRef context=[[NSGraphicsContext currentContext] graphicsPort];
293       NSRect roundedFrame=frame;
294       
295       roundedFrame.size.height--;
296       [[NSColor darkGrayColor] setFill];
297       drawRoundedBezel(context,roundedFrame);
298       
299       roundedFrame.origin.y+=1;
300       [[NSColor lightGrayColor] setFill];
301       drawRoundedBezel(context,roundedFrame);
303       roundedFrame=NSInsetRect(roundedFrame,1,1);
304       [[NSColor whiteColor] setFill];
305       drawRoundedBezel(context,roundedFrame);
306       break;
307    }
308     
309    }
310    else {
311     if([self isBordered]){
312      [[control graphicsStyle] drawTextFieldBorderInRect:frame bezeledNotLine:NO];
313      backRect=NSInsetRect(backRect,-1,-1);
314     }
315    }
317    if([self drawsBackground]){
318     if(!([self isBezeled] && [self bezelStyle]==NSTextFieldRoundedBezel)){
319     NSColor *color=(_backgroundColor==nil)?[NSColor controlColor]:_backgroundColor;
321     [color setFill];
322     NSRectFill(backRect);
323    }
324    }
326    [self drawInteriorWithFrame:frame inView:control];
329 @end
331 @implementation NSTextFieldCell (Bindings)
333 - (CGFloat) _fontSize {
334     return [_font pointSize];
336 - (void) _setFontSize:(CGFloat)fontSize {
337     NSString *fontName = [_font fontName];
338     [self setFont:[NSFont fontWithName:fontName 
339                                   size:fontSize]];
341 - (NSString*) _fontFamilyName {
342     return [_font familyName];
344 - (void) _setFontFamilyName:(NSString*)familyName {
345     if (!familyName) {
346         return;
347     }
348     
349     NSLog(@"_setFontFamilyName: %@", familyName);
350     
351     CGFloat currentSize = [_font pointSize];
352     [self setFont:[NSFont fontWithName:familyName 
353                                    size:currentSize]];
356 -(id)_replacementKeyPathForBinding:(id)binding {
357     if([binding isEqual:@"value"])
358                 return @"stringValue";
359     return [super _replacementKeyPathForBinding:binding];
362 @end