| File: | Source/NSCell.m |
| Location: | line 2833, column 3 |
| Description: | Incorrect decrement of the reference count of an object that is not owned at this point by the caller |
| Code is compiled to use reference counts |
| 1 | /** <title>NSCell</title> | ||||
| 2 | |||||
| 3 | <abstract>The abstract cell class</abstract> | ||||
| 4 | |||||
| 5 | Copyright (C) 1996-2012 Free Software Foundation, Inc. | ||||
| 6 | |||||
| 7 | Author: Scott Christley <scottc@net-community.com> | ||||
| 8 | Date: 1996 | ||||
| 9 | Modifications: Felipe A. Rodriguez <far@ix.netcom.com> | ||||
| 10 | Date: August 1998 | ||||
| 11 | Rewrite: Multiple authors | ||||
| 12 | Date: 1999 | ||||
| 13 | Editing, formatters: Nicola Pero <nicola@brainstorm.co.uk> | ||||
| 14 | Date: 2000 | ||||
| 15 | |||||
| 16 | This file is part of the GNUstep GUI Library. | ||||
| 17 | |||||
| 18 | This library is free software; you can redistribute it and/or | ||||
| 19 | modify it under the terms of the GNU Lesser General Public | ||||
| 20 | License as published by the Free Software Foundation; either | ||||
| 21 | version 2 of the License, or (at your option) any later version. | ||||
| 22 | |||||
| 23 | This library is distributed in the hope that it will be useful, | ||||
| 24 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| 25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
| 26 | Lesser General Public License for more details. | ||||
| 27 | |||||
| 28 | You should have received a copy of the GNU Lesser General Public | ||||
| 29 | License along with this library; see the file COPYING.LIB. | ||||
| 30 | If not, see <http://www.gnu.org/licenses/> or write to the | ||||
| 31 | Free Software Foundation, 51 Franklin Street, Fifth Floor, | ||||
| 32 | Boston, MA 02110-1301, USA. | ||||
| 33 | */ | ||||
| 34 | |||||
| 35 | #import "config.h" | ||||
| 36 | #import <Foundation/NSCoder.h> | ||||
| 37 | #import <Foundation/NSDebug.h> | ||||
| 38 | #import <Foundation/NSException.h> | ||||
| 39 | #import <Foundation/NSFormatter.h> | ||||
| 40 | #import <Foundation/NSValue.h> | ||||
| 41 | #import <Foundation/NSNotification.h> | ||||
| 42 | #import <Foundation/NSNumberFormatter.h> | ||||
| 43 | #import <Foundation/NSRunLoop.h> | ||||
| 44 | #import <Foundation/NSString.h> | ||||
| 45 | #import <Foundation/NSGeometry.h> | ||||
| 46 | |||||
| 47 | #import "AppKit/AppKitExceptions.h" | ||||
| 48 | #import "AppKit/NSAttributedString.h" | ||||
| 49 | #import "AppKit/NSApplication.h" | ||||
| 50 | #import "AppKit/NSControl.h" | ||||
| 51 | #import "AppKit/NSCell.h" | ||||
| 52 | #import "AppKit/NSClipView.h" | ||||
| 53 | #import "AppKit/NSColor.h" | ||||
| 54 | #import "AppKit/NSCursor.h" | ||||
| 55 | #import "AppKit/NSEvent.h" | ||||
| 56 | #import "AppKit/NSFont.h" | ||||
| 57 | #import "AppKit/NSGraphics.h" | ||||
| 58 | #import "AppKit/NSImage.h" | ||||
| 59 | #import "AppKit/NSMenu.h" | ||||
| 60 | #import "AppKit/NSParagraphStyle.h" | ||||
| 61 | #import "AppKit/NSStringDrawing.h" | ||||
| 62 | #import "AppKit/NSTextView.h" | ||||
| 63 | #import "AppKit/NSTextContainer.h" | ||||
| 64 | #import "AppKit/NSView.h" | ||||
| 65 | #import "AppKit/NSWindow.h" | ||||
| 66 | #import "GNUstepGUI/GSTheme.h" | ||||
| 67 | #import "GSGuiPrivate.h" | ||||
| 68 | |||||
| 69 | static Class colorClass; | ||||
| 70 | static Class cellClass; | ||||
| 71 | static Class fontClass; | ||||
| 72 | static Class imageClass; | ||||
| 73 | |||||
| 74 | static NSColor *txtCol; | ||||
| 75 | static NSColor *dtxtCol; | ||||
| 76 | |||||
| 77 | @interface NSCell (PrivateColor) | ||||
| 78 | + (void) _systemColorsChanged: (NSNotification*)n; | ||||
| 79 | @end | ||||
| 80 | |||||
| 81 | |||||
| 82 | @implementation NSCell (PrivateColor) | ||||
| 83 | + (void) _systemColorsChanged: (NSNotification*)n | ||||
| 84 | { | ||||
| 85 | ASSIGN (txtCol, [colorClass controlTextColor])({ id __object = txtCol; txtCol = [([colorClass controlTextColor ]) retain]; [__object release]; }); | ||||
| 86 | ASSIGN (dtxtCol, [colorClass disabledControlTextColor])({ id __object = dtxtCol; dtxtCol = [([colorClass disabledControlTextColor ]) retain]; [__object release]; }); | ||||
| 87 | } | ||||
| 88 | @end | ||||
| 89 | |||||
| 90 | |||||
| 91 | /** | ||||
| 92 | *<p> TODO Desctiption</p> | ||||
| 93 | */ | ||||
| 94 | |||||
| 95 | @implementation NSCell | ||||
| 96 | |||||
| 97 | /* | ||||
| 98 | * Class methods | ||||
| 99 | */ | ||||
| 100 | + (void) initialize | ||||
| 101 | { | ||||
| 102 | if (self == [NSCell class]) | ||||
| 103 | { | ||||
| 104 | [self setVersion: 3]; | ||||
| 105 | colorClass = [NSColor class]; | ||||
| 106 | cellClass = [NSCell class]; | ||||
| 107 | fontClass = [NSFont class]; | ||||
| 108 | imageClass = [NSImage class]; | ||||
| 109 | /* | ||||
| 110 | * Watch for changes to system colors, and simulate an initial change | ||||
| 111 | * in order to set up our defaults. | ||||
| 112 | */ | ||||
| 113 | [[NSNotificationCenter defaultCenter] | ||||
| 114 | addObserver: self | ||||
| 115 | selector: @selector(_systemColorsChanged:) | ||||
| 116 | name: NSSystemColorsDidChangeNotification | ||||
| 117 | object: nil((id)((void*)0))]; | ||||
| 118 | [self _systemColorsChanged: nil((id)((void*)0))]; | ||||
| 119 | } | ||||
| 120 | } | ||||
| 121 | |||||
| 122 | + (NSMenu*) defaultMenu | ||||
| 123 | { | ||||
| 124 | return nil((id)((void*)0)); | ||||
| 125 | } | ||||
| 126 | |||||
| 127 | + (NSFocusRingType) defaultFocusRingType | ||||
| 128 | { | ||||
| 129 | return NSFocusRingTypeDefault; | ||||
| 130 | } | ||||
| 131 | |||||
| 132 | /**<p>This class method returns NO. This method should be overrided by | ||||
| 133 | subclasses.</p> | ||||
| 134 | */ | ||||
| 135 | + (BOOL) prefersTrackingUntilMouseUp | ||||
| 136 | { | ||||
| 137 | return NO((BOOL)0); | ||||
| 138 | } | ||||
| 139 | |||||
| 140 | /* | ||||
| 141 | * Instance methods | ||||
| 142 | */ | ||||
| 143 | - (id) init | ||||
| 144 | { | ||||
| 145 | return [self initTextCell: @""]; | ||||
| 146 | } | ||||
| 147 | |||||
| 148 | /**<p>Initializes and returns a new NSCell with a NSImage <var>anImage</var>. | ||||
| 149 | This method sets the image position to <ref type="type" | ||||
| 150 | id="NSCellImagePosition">NSImageOnly</ref> and the cell's type to | ||||
| 151 | <ref type="type" id="NSCellType">NSImageCellType</ref>.</p> | ||||
| 152 | <p>See Also: -initTextCell: </p> | ||||
| 153 | */ | ||||
| 154 | - (id) initImageCell: (NSImage*)anImage | ||||
| 155 | { | ||||
| 156 | _cell.type = NSImageCellType; | ||||
| 157 | _cell_image = RETAIN (anImage)[(anImage) retain]; | ||||
| 158 | _cell.image_position = NSImageOnly; | ||||
| 159 | _font = RETAIN ([fontClass systemFontOfSize: 0])[([fontClass systemFontOfSize: 0]) retain]; | ||||
| 160 | |||||
| 161 | // Implicitly set by allocation: | ||||
| 162 | // | ||||
| 163 | //_font = nil; | ||||
| 164 | //_cell.contents_is_attributed_string = NO; | ||||
| 165 | //_cell.is_highlighted = NO; | ||||
| 166 | //_cell.is_disabled = NO; | ||||
| 167 | //_cell.is_editable = NO; | ||||
| 168 | //_cell.is_rich_text = NO; | ||||
| 169 | //_cell.imports_graphics = NO; | ||||
| 170 | //_cell.shows_first_responder = NO; | ||||
| 171 | //_cell.refuses_first_responder = NO; | ||||
| 172 | //_cell.sends_action_on_end_editing = NO; | ||||
| 173 | //_cell.is_bordered = NO; | ||||
| 174 | //_cell.is_bezeled = NO; | ||||
| 175 | //_cell.is_scrollable = NO; | ||||
| 176 | //_cell.is_selectable = NO; | ||||
| 177 | //_cell.state = 0; | ||||
| 178 | //_cell.line_break_mode = NSLineBreakByWordWrapping; | ||||
| 179 | _action_mask = NSLeftMouseUpMask; | ||||
| 180 | _menu = [object_getClass(self) defaultMenu]; | ||||
| 181 | [self setFocusRingType: [object_getClass(self) defaultFocusRingType]]; | ||||
| 182 | |||||
| 183 | return self; | ||||
| 184 | } | ||||
| 185 | /**<p>Initializes and returns a new NSCell with a NSString aString. | ||||
| 186 | This method sets the cell's type to <ref type="type" id="NSCellType"> | ||||
| 187 | NSTextCellType</ref>.</p> | ||||
| 188 | <p>See Also: -initImageCell: </p> | ||||
| 189 | */ | ||||
| 190 | - (id) initTextCell: (NSString*)aString | ||||
| 191 | { | ||||
| 192 | _cell.type = NSTextCellType; | ||||
| 193 | _contents = RETAIN (aString)[(aString) retain]; | ||||
| 194 | _font = RETAIN ([fontClass systemFontOfSize: 0])[([fontClass systemFontOfSize: 0]) retain]; | ||||
| 195 | |||||
| 196 | // Implicitly set by allocation: | ||||
| 197 | // | ||||
| 198 | //_cell.contents_is_attributed_string = NO; | ||||
| 199 | //_cell_image = nil; | ||||
| 200 | //_cell.image_position = NSNoImage; | ||||
| 201 | //_cell.is_disabled = NO; | ||||
| 202 | //_cell.state = 0; | ||||
| 203 | //_cell.is_highlighted = NO; | ||||
| 204 | //_cell.is_editable = NO; | ||||
| 205 | //_cell.is_bordered = NO; | ||||
| 206 | //_cell.is_bezeled = NO; | ||||
| 207 | //_cell.is_scrollable = NO; | ||||
| 208 | //_cell.is_selectable = NO; | ||||
| 209 | //_cell.line_break_mode = NSLineBreakByWordWrapping; | ||||
| 210 | _action_mask = NSLeftMouseUpMask; | ||||
| 211 | _menu = [object_getClass(self) defaultMenu]; | ||||
| 212 | [self setFocusRingType: [object_getClass(self) defaultFocusRingType]]; | ||||
| 213 | |||||
| 214 | return self; | ||||
| 215 | } | ||||
| 216 | |||||
| 217 | - (void) dealloc | ||||
| 218 | { | ||||
| 219 | TEST_RELEASE (_contents)({id __object = (_contents); if (__object != ((id)((void*)0)) ) [__object release]; }); | ||||
| 220 | TEST_RELEASE (_cell_image)({id __object = (_cell_image); if (__object != ((id)((void*)0 ))) [__object release]; }); | ||||
| 221 | TEST_RELEASE (_font)({id __object = (_font); if (__object != ((id)((void*)0))) [__object release]; }); | ||||
| 222 | TEST_RELEASE (_represented_object)({id __object = (_represented_object); if (__object != ((id)( (void*)0))) [__object release]; }); | ||||
| 223 | TEST_RELEASE (_object_value)({id __object = (_object_value); if (__object != ((id)((void* )0))) [__object release]; }); | ||||
| 224 | TEST_RELEASE (_formatter)({id __object = (_formatter); if (__object != ((id)((void*)0) )) [__object release]; }); | ||||
| 225 | TEST_RELEASE (_menu)({id __object = (_menu); if (__object != ((id)((void*)0))) [__object release]; }); | ||||
| 226 | |||||
| 227 | [super dealloc]; | ||||
| 228 | } | ||||
| 229 | |||||
| 230 | /* | ||||
| 231 | * Setting the NSCell's Value | ||||
| 232 | */ | ||||
| 233 | - (id) objectValue | ||||
| 234 | { | ||||
| 235 | if (_cell.has_valid_object_value) | ||||
| 236 | { | ||||
| 237 | return _object_value; | ||||
| 238 | } | ||||
| 239 | else | ||||
| 240 | { | ||||
| 241 | return nil((id)((void*)0)); | ||||
| 242 | } | ||||
| 243 | } | ||||
| 244 | |||||
| 245 | - (BOOL) hasValidObjectValue | ||||
| 246 | { | ||||
| 247 | return _cell.has_valid_object_value; | ||||
| 248 | } | ||||
| 249 | |||||
| 250 | /**<p>Returns the NSCell's value as a double. </p> | ||||
| 251 | *<p>See Also: -setDoubleValue: </p> | ||||
| 252 | */ | ||||
| 253 | - (double) doubleValue | ||||
| 254 | { | ||||
| 255 | if ((_cell.has_valid_object_value == YES((BOOL)1)) && | ||||
| 256 | ([_object_value respondsToSelector: @selector(doubleValue)])) | ||||
| 257 | { | ||||
| 258 | return [_object_value doubleValue]; | ||||
| 259 | } | ||||
| 260 | else | ||||
| 261 | { | ||||
| 262 | return [[self stringValue] doubleValue]; | ||||
| 263 | } | ||||
| 264 | } | ||||
| 265 | |||||
| 266 | /**<p>Returns the cell's value as a float. </p> | ||||
| 267 | *<p>See Also: -setFloatValue: </p> | ||||
| 268 | */ | ||||
| 269 | - (float) floatValue | ||||
| 270 | { | ||||
| 271 | if ((_cell.has_valid_object_value == YES((BOOL)1)) && | ||||
| 272 | ([_object_value respondsToSelector: @selector(floatValue)])) | ||||
| 273 | { | ||||
| 274 | return [_object_value floatValue]; | ||||
| 275 | } | ||||
| 276 | else | ||||
| 277 | { | ||||
| 278 | return [[self stringValue] floatValue]; | ||||
| 279 | } | ||||
| 280 | } | ||||
| 281 | |||||
| 282 | /**<p>Returns the cell's value as an int. </p> | ||||
| 283 | *<p>See Also: -setIntValue:</p> | ||||
| 284 | */ | ||||
| 285 | - (int) intValue | ||||
| 286 | { | ||||
| 287 | if ((_cell.has_valid_object_value == YES((BOOL)1)) && | ||||
| 288 | ([_object_value respondsToSelector: @selector(intValue)])) | ||||
| 289 | { | ||||
| 290 | return [_object_value intValue]; | ||||
| 291 | } | ||||
| 292 | else | ||||
| 293 | { | ||||
| 294 | return [[self stringValue] intValue]; | ||||
| 295 | } | ||||
| 296 | } | ||||
| 297 | |||||
| 298 | /**<p>Returns the cell's value as an NSInteger. </p> | ||||
| 299 | *<p>See Also: -setIntegerValue:</p> | ||||
| 300 | */ | ||||
| 301 | - (NSInteger) integerValue | ||||
| 302 | { | ||||
| 303 | if ((_cell.has_valid_object_value == YES((BOOL)1)) && | ||||
| 304 | ([_object_value respondsToSelector: @selector(integerValue)])) | ||||
| 305 | { | ||||
| 306 | return [_object_value integerValue]; | ||||
| 307 | } | ||||
| 308 | else | ||||
| 309 | { | ||||
| 310 | return [[self stringValue] integerValue]; | ||||
| 311 | } | ||||
| 312 | } | ||||
| 313 | |||||
| 314 | /**<p>Returns the cell's value as a NSString.</p> | ||||
| 315 | *<p>See Also: -setStringValue: </p> | ||||
| 316 | */ | ||||
| 317 | - (NSString*) stringValue | ||||
| 318 | { | ||||
| 319 | if (nil((id)((void*)0)) == _contents) | ||||
| 320 | { | ||||
| 321 | return @""; | ||||
| 322 | } | ||||
| 323 | |||||
| 324 | if (_cell.contents_is_attributed_string == NO((BOOL)0)) | ||||
| 325 | { | ||||
| 326 | // If we have a formatter this is also the string of the _object_value | ||||
| 327 | return (NSString *)_contents; | ||||
| 328 | } | ||||
| 329 | else | ||||
| 330 | { | ||||
| 331 | return [(NSAttributedString *)_contents string]; | ||||
| 332 | } | ||||
| 333 | } | ||||
| 334 | |||||
| 335 | - (void) setObjectValue: (id)object | ||||
| 336 | { | ||||
| 337 | id newContents; | ||||
| 338 | |||||
| 339 | ASSIGN (_object_value, object)({ id __object = _object_value; _object_value = [(object) retain ]; [__object release]; }); | ||||
| 340 | |||||
| 341 | if (_formatter == nil((id)((void*)0))) | ||||
| 342 | { | ||||
| 343 | if (object == nil((id)((void*)0)) || [object isKindOfClass: [NSString class]] == YES((BOOL)1)) | ||||
| 344 | { | ||||
| 345 | newContents = object; | ||||
| 346 | _cell.contents_is_attributed_string = NO((BOOL)0); | ||||
| 347 | _cell.has_valid_object_value = YES((BOOL)1); | ||||
| 348 | } | ||||
| 349 | else if ([object isKindOfClass: [NSAttributedString class]] == YES((BOOL)1)) | ||||
| 350 | { | ||||
| 351 | newContents = object; | ||||
| 352 | _cell.contents_is_attributed_string = YES((BOOL)1); | ||||
| 353 | _cell.has_valid_object_value = YES((BOOL)1); | ||||
| 354 | } | ||||
| 355 | else if ([_object_value respondsToSelector: @selector(attributedStringValue)]) | ||||
| 356 | { | ||||
| 357 | newContents = [_object_value attributedStringValue]; | ||||
| 358 | _cell.contents_is_attributed_string = YES((BOOL)1); | ||||
| 359 | _cell.has_valid_object_value = YES((BOOL)1); | ||||
| 360 | } | ||||
| 361 | else if ([_object_value respondsToSelector: @selector(stringValue)]) | ||||
| 362 | { | ||||
| 363 | // If the thing that was assigned is not a string, but | ||||
| 364 | // responds to stringValue then get that. | ||||
| 365 | newContents = [_object_value stringValue]; | ||||
| 366 | _cell.contents_is_attributed_string = NO((BOOL)0); | ||||
| 367 | _cell.has_valid_object_value = YES((BOOL)1); | ||||
| 368 | } | ||||
| 369 | else | ||||
| 370 | { | ||||
| 371 | newContents = [_object_value description]; | ||||
| 372 | _cell.contents_is_attributed_string = NO((BOOL)0); | ||||
| 373 | _cell.has_valid_object_value = YES((BOOL)1); | ||||
| 374 | } | ||||
| 375 | } | ||||
| 376 | else | ||||
| 377 | { | ||||
| 378 | newContents = [_formatter stringForObjectValue: _object_value]; | ||||
| 379 | _cell.contents_is_attributed_string = NO((BOOL)0); | ||||
| 380 | if (newContents != nil((id)((void*)0))) | ||||
| 381 | { | ||||
| 382 | _cell.has_valid_object_value = YES((BOOL)1); | ||||
| 383 | } | ||||
| 384 | else | ||||
| 385 | { | ||||
| 386 | _cell.has_valid_object_value = NO((BOOL)0); | ||||
| 387 | } | ||||
| 388 | } | ||||
| 389 | |||||
| 390 | ASSIGNCOPY(_contents, newContents)({ id __object = _contents; _contents = [(newContents) copy]; [__object release]; }); | ||||
| 391 | } | ||||
| 392 | |||||
| 393 | |||||
| 394 | /**<p>Sets the NSCell's value to aDouble.</p> | ||||
| 395 | *<p>See Also: -doubleValue</p> | ||||
| 396 | */ | ||||
| 397 | - (void) setDoubleValue: (double)aDouble | ||||
| 398 | { | ||||
| 399 | NSNumber *number; | ||||
| 400 | |||||
| 401 | // NB: GNUstep can set a double value for an image cell | ||||
| 402 | |||||
| 403 | number = [NSNumber numberWithDouble: aDouble]; | ||||
| 404 | [self setObjectValue: number]; | ||||
| 405 | } | ||||
| 406 | |||||
| 407 | /** | ||||
| 408 | *<p>Sets the NSCell's value to a aFloat. This used for example in | ||||
| 409 | NSSliderCell</p> | ||||
| 410 | *<p>See Also: -floatValue</p> | ||||
| 411 | */ | ||||
| 412 | - (void) setFloatValue: (float)aFloat | ||||
| 413 | { | ||||
| 414 | NSNumber *number; | ||||
| 415 | |||||
| 416 | // NB: GNUstep can set a float value for an image cell. | ||||
| 417 | // NSSliderCell is an example of it! | ||||
| 418 | |||||
| 419 | number = [NSNumber numberWithFloat: aFloat]; | ||||
| 420 | [self setObjectValue: number]; | ||||
| 421 | } | ||||
| 422 | |||||
| 423 | |||||
| 424 | /** | ||||
| 425 | *<p>Sets the NSCell's value to anInt.</p> | ||||
| 426 | *<p>See Also: -intValue</p> | ||||
| 427 | */ | ||||
| 428 | - (void) setIntValue: (int)anInt | ||||
| 429 | { | ||||
| 430 | NSNumber *number; | ||||
| 431 | |||||
| 432 | // NB: GNUstep can set an int value for an image cell. | ||||
| 433 | |||||
| 434 | number = [NSNumber numberWithInt: anInt]; | ||||
| 435 | [self setObjectValue: number]; | ||||
| 436 | } | ||||
| 437 | |||||
| 438 | /** | ||||
| 439 | *<p>Sets the NSCell's value to anInt.</p> | ||||
| 440 | *<p>See Also: -integerValue</p> | ||||
| 441 | */ | ||||
| 442 | - (void) setIntegerValue: (NSInteger)anInt | ||||
| 443 | { | ||||
| 444 | NSNumber *number; | ||||
| 445 | |||||
| 446 | // NB: GNUstep can set an int value for an image cell. | ||||
| 447 | |||||
| 448 | number = [NSNumber numberWithInteger: anInt]; | ||||
| 449 | [self setObjectValue: number]; | ||||
| 450 | } | ||||
| 451 | |||||
| 452 | /**<p>Sets the cell's value to a NSString. | ||||
| 453 | The NSCell's type is set to NSTextCellType if needed</p> | ||||
| 454 | <p>See Also: -stringValue</p> | ||||
| 455 | */ | ||||
| 456 | - (void) setStringValue: (NSString*)aString | ||||
| 457 | { | ||||
| 458 | /* We warn about nil for compatibiliy with MacOS X, which refuses | ||||
| 459 | nil. */ | ||||
| 460 | if (aString == nil((id)((void*)0))) | ||||
| 461 | { | ||||
| 462 | NSDebugMLLog (@"MacOSXCompatibility",do { if (GSDebugSet(@"MacOSXCompatibility") == ((BOOL)1)) { NSString *s = GSDebugFunctionMsg( __PRETTY_FUNCTION__, "NSCell.m", 463 , [NSString stringWithFormat: @"Attempt to use nil as string value" ]); NSLog(@"%@", s); }} while (0) | ||||
| 463 | @"Attempt to use nil as string value")do { if (GSDebugSet(@"MacOSXCompatibility") == ((BOOL)1)) { NSString *s = GSDebugFunctionMsg( __PRETTY_FUNCTION__, "NSCell.m", 463 , [NSString stringWithFormat: @"Attempt to use nil as string value" ]); NSLog(@"%@", s); }} while (0); | ||||
| 464 | } | ||||
| 465 | |||||
| 466 | if (_cell.type != NSTextCellType) | ||||
| 467 | { | ||||
| 468 | [self setType: NSTextCellType]; | ||||
| 469 | } | ||||
| 470 | |||||
| 471 | if (_formatter == nil((id)((void*)0))) | ||||
| 472 | { | ||||
| 473 | [self setObjectValue: aString]; | ||||
| 474 | } | ||||
| 475 | else | ||||
| 476 | { | ||||
| 477 | id newObjectValue; | ||||
| 478 | |||||
| 479 | if ([_formatter getObjectValue: &newObjectValue | ||||
| 480 | forString: aString | ||||
| 481 | errorDescription: NULL((void *)0)]) | ||||
| 482 | { | ||||
| 483 | [self setObjectValue: newObjectValue]; | ||||
| 484 | } | ||||
| 485 | else | ||||
| 486 | { | ||||
| 487 | ASSIGNCOPY(_contents, aString)({ id __object = _contents; _contents = [(aString) copy]; [__object release]; }); | ||||
| 488 | _cell.contents_is_attributed_string = NO((BOOL)0); | ||||
| 489 | _cell.has_valid_object_value = NO((BOOL)0); | ||||
| 490 | } | ||||
| 491 | } | ||||
| 492 | } | ||||
| 493 | |||||
| 494 | /**<p>Returns some NSCell's attributes for the specified <ref type="type" | ||||
| 495 | id="NSCellAttribute">NSCellAttribute</ref></p> | ||||
| 496 | <p>See Also: -setCellAttribute:to:</p> | ||||
| 497 | */ | ||||
| 498 | - (int) cellAttribute: (NSCellAttribute)aParameter | ||||
| 499 | { | ||||
| 500 | switch (aParameter) | ||||
| 501 | { | ||||
| 502 | case NSCellDisabled: return _cell.is_disabled; | ||||
| 503 | case NSCellState: return _cell.state; | ||||
| 504 | case NSCellEditable: return _cell.is_editable; | ||||
| 505 | case NSCellHighlighted: return _cell.is_highlighted; | ||||
| 506 | case NSCellIsBordered: return _cell.is_bordered; | ||||
| 507 | case NSCellAllowsMixedState: return _cell.allows_mixed_state; | ||||
| 508 | |||||
| 509 | /* | ||||
| 510 | case NSPushInCell: return 0; | ||||
| 511 | case NSChangeGrayCell: return 0; | ||||
| 512 | case NSCellLightsByContents: return 0; | ||||
| 513 | case NSCellLightsByGray: return 0; | ||||
| 514 | case NSChangeBackgroundCell: return 0; | ||||
| 515 | case NSCellLightsByBackground: return 0; | ||||
| 516 | case NSCellChangesContents: return 0; | ||||
| 517 | case NSCellIsInsetButton: return 0; | ||||
| 518 | */ | ||||
| 519 | case NSCellHasOverlappingImage: | ||||
| 520 | { | ||||
| 521 | return _cell.image_position == NSImageOverlaps; | ||||
| 522 | } | ||||
| 523 | case NSCellHasImageHorizontal: | ||||
| 524 | { | ||||
| 525 | return (_cell.image_position == NSImageRight) | ||||
| 526 | || (_cell.image_position == NSImageLeft); | ||||
| 527 | } | ||||
| 528 | case NSCellHasImageOnLeftOrBottom: | ||||
| 529 | { | ||||
| 530 | return (_cell.image_position == NSImageBelow) | ||||
| 531 | || (_cell.image_position == NSImageLeft); | ||||
| 532 | } | ||||
| 533 | default: | ||||
| 534 | { | ||||
| 535 | NSWarnLog (@"cell attribute %d not supported", aParameter)do { if (GSDebugSet(@"NoWarn") == ((BOOL)0)) { NSLog(@"cell attribute %d not supported" , aParameter); }} while (0); | ||||
| 536 | break; | ||||
| 537 | } | ||||
| 538 | } | ||||
| 539 | |||||
| 540 | return 0; | ||||
| 541 | } | ||||
| 542 | |||||
| 543 | |||||
| 544 | /**<p>TODO</p> | ||||
| 545 | *<p>See Also: -cellAttribute:</p> | ||||
| 546 | */ | ||||
| 547 | - (void) setCellAttribute: (NSCellAttribute)aParameter to: (int)value | ||||
| 548 | { | ||||
| 549 | switch (aParameter) | ||||
| 550 | { | ||||
| 551 | case NSCellDisabled: | ||||
| 552 | { | ||||
| 553 | _cell.is_disabled = value; | ||||
| 554 | break; | ||||
| 555 | } | ||||
| 556 | case NSCellState: | ||||
| 557 | { | ||||
| 558 | _cell.state = value; | ||||
| 559 | break; | ||||
| 560 | } | ||||
| 561 | case NSCellEditable: | ||||
| 562 | { | ||||
| 563 | _cell.is_editable = value; | ||||
| 564 | break; | ||||
| 565 | } | ||||
| 566 | case NSCellHighlighted: | ||||
| 567 | { | ||||
| 568 | _cell.is_highlighted = value; | ||||
| 569 | break; | ||||
| 570 | } | ||||
| 571 | case NSCellHasOverlappingImage: | ||||
| 572 | { | ||||
| 573 | if (value) | ||||
| 574 | { | ||||
| 575 | _cell.image_position = NSImageOverlaps; | ||||
| 576 | } | ||||
| 577 | else | ||||
| 578 | { | ||||
| 579 | if (_cell.image_position == NSImageOverlaps) | ||||
| 580 | { | ||||
| 581 | _cell.image_position = NSImageLeft; | ||||
| 582 | } | ||||
| 583 | } | ||||
| 584 | break; | ||||
| 585 | } | ||||
| 586 | case NSCellHasImageHorizontal: | ||||
| 587 | { | ||||
| 588 | if (value) | ||||
| 589 | { | ||||
| 590 | if (_cell.image_position != NSImageLeft | ||||
| 591 | && _cell.image_position != NSImageRight) | ||||
| 592 | { | ||||
| 593 | _cell.image_position = NSImageLeft; | ||||
| 594 | } | ||||
| 595 | } | ||||
| 596 | else | ||||
| 597 | { | ||||
| 598 | if (_cell.image_position == NSImageLeft) | ||||
| 599 | { | ||||
| 600 | _cell.image_position = NSImageAbove; | ||||
| 601 | } | ||||
| 602 | else if (_cell.image_position == NSImageRight) | ||||
| 603 | { | ||||
| 604 | _cell.image_position = NSImageBelow; | ||||
| 605 | } | ||||
| 606 | } | ||||
| 607 | break; | ||||
| 608 | } | ||||
| 609 | case NSCellHasImageOnLeftOrBottom: | ||||
| 610 | { | ||||
| 611 | if (value) | ||||
| 612 | { | ||||
| 613 | if (_cell.image_position == NSImageAbove) | ||||
| 614 | { | ||||
| 615 | _cell.image_position = NSImageBelow; | ||||
| 616 | } | ||||
| 617 | else | ||||
| 618 | { | ||||
| 619 | _cell.image_position = NSImageLeft; | ||||
| 620 | } | ||||
| 621 | } | ||||
| 622 | else | ||||
| 623 | { | ||||
| 624 | if (_cell.image_position == NSImageBelow) | ||||
| 625 | { | ||||
| 626 | _cell.image_position = NSImageAbove; | ||||
| 627 | } | ||||
| 628 | else | ||||
| 629 | { | ||||
| 630 | _cell.image_position = NSImageRight; | ||||
| 631 | } | ||||
| 632 | } | ||||
| 633 | break; | ||||
| 634 | } | ||||
| 635 | /* | ||||
| 636 | case NSCellChangesContents: | ||||
| 637 | _cell. = value; | ||||
| 638 | break; | ||||
| 639 | case NSCellIsInsetButton: | ||||
| 640 | _cell. = value; | ||||
| 641 | break; | ||||
| 642 | */ | ||||
| 643 | case NSCellIsBordered: | ||||
| 644 | { | ||||
| 645 | _cell.is_bordered = value; | ||||
| 646 | break; | ||||
| 647 | } | ||||
| 648 | case NSCellAllowsMixedState: | ||||
| 649 | { | ||||
| 650 | _cell.allows_mixed_state = value; | ||||
| 651 | break; | ||||
| 652 | } | ||||
| 653 | default: | ||||
| 654 | { | ||||
| 655 | NSWarnLog (@"cell attribute %d not supported", aParameter)do { if (GSDebugSet(@"NoWarn") == ((BOOL)0)) { NSLog(@"cell attribute %d not supported" , aParameter); }} while (0); | ||||
| 656 | break; | ||||
| 657 | } | ||||
| 658 | } | ||||
| 659 | } | ||||
| 660 | |||||
| 661 | /**<p>Sets the NSCell's type. See <ref type="type" id="NSCellType">NSCellType | ||||
| 662 | </ref>.If the cell is set to NSTextCellType, the cell is given | ||||
| 663 | a default title and is reset to the default system font.</p> | ||||
| 664 | <p>See Also: -type</p> | ||||
| 665 | */ | ||||
| 666 | - (void) setType: (NSCellType)aType | ||||
| 667 | { | ||||
| 668 | if (_cell.type == aType) | ||||
| 669 | { | ||||
| 670 | return; | ||||
| 671 | } | ||||
| 672 | |||||
| 673 | _cell.type = aType; | ||||
| 674 | switch (_cell.type) | ||||
| 675 | { | ||||
| 676 | case NSTextCellType: | ||||
| 677 | { | ||||
| 678 | ASSIGN (_contents, @"title")({ id __object = _contents; _contents = [(@"title") retain]; [ __object release]; }); | ||||
| 679 | _cell.contents_is_attributed_string = NO((BOOL)0); | ||||
| 680 | /* Doc says we have to reset the font too. */ | ||||
| 681 | ASSIGN (_font, [fontClass systemFontOfSize: 0])({ id __object = _font; _font = [([fontClass systemFontOfSize : 0]) retain]; [__object release]; }); | ||||
| 682 | break; | ||||
| 683 | } | ||||
| 684 | case NSImageCellType: | ||||
| 685 | { | ||||
| 686 | TEST_RELEASE (_cell_image)({id __object = (_cell_image); if (__object != ((id)((void*)0 ))) [__object release]; }); | ||||
| 687 | _cell_image = nil((id)((void*)0)); | ||||
| 688 | break; | ||||
| 689 | } | ||||
| 690 | } | ||||
| 691 | } | ||||
| 692 | |||||
| 693 | /**<p>Returns the cell's type. Returns NSNullCellType if the | ||||
| 694 | cell's type flag is set to NSImageCellType and if the cell's image | ||||
| 695 | is nil. See <ref type="type" id="NSCellType">NSCellType</ref> for more | ||||
| 696 | information.</p><p>See Also -setType:</p> | ||||
| 697 | */ | ||||
| 698 | - (NSCellType) type | ||||
| 699 | { | ||||
| 700 | if (_cell.type == NSImageCellType && _cell_image == nil((id)((void*)0))) | ||||
| 701 | return NSNullCellType; | ||||
| 702 | |||||
| 703 | return _cell.type; | ||||
| 704 | } | ||||
| 705 | |||||
| 706 | |||||
| 707 | /**<p>Returns whether the NSCell can respond to mouse events.</p> | ||||
| 708 | *<p>See Also: -setEnabled:</p> | ||||
| 709 | */ | ||||
| 710 | - (BOOL) isEnabled | ||||
| 711 | { | ||||
| 712 | return !_cell.is_disabled; | ||||
| 713 | } | ||||
| 714 | |||||
| 715 | /**<p>Sets whether the NSCell can respond to mouse events</p> | ||||
| 716 | <p>See Also: -isEnabled</p> | ||||
| 717 | */ | ||||
| 718 | - (void) setEnabled: (BOOL)flag | ||||
| 719 | { | ||||
| 720 | _cell.is_disabled = !flag; | ||||
| 721 | } | ||||
| 722 | |||||
| 723 | /**<p>Returns whether the NSCell has a bezeled border. By default a NSCell | ||||
| 724 | has no bezeled border</p><p>See Also: -setBezeled:</p> | ||||
| 725 | */ | ||||
| 726 | - (BOOL) isBezeled | ||||
| 727 | { | ||||
| 728 | return _cell.is_bezeled; | ||||
| 729 | } | ||||
| 730 | |||||
| 731 | /**<p>Returns whether the NSCell has a border. By default a NSCell has | ||||
| 732 | border</p><p>See Also: -setBordered: -setBezeled: -isBezeled</p> | ||||
| 733 | */ | ||||
| 734 | - (BOOL) isBordered | ||||
| 735 | { | ||||
| 736 | return _cell.is_bordered; | ||||
| 737 | } | ||||
| 738 | |||||
| 739 | /**<p>Returns whether the cell is opaque. Return NO by default</p> | ||||
| 740 | */ | ||||
| 741 | - (BOOL) isOpaque | ||||
| 742 | { | ||||
| 743 | return NO((BOOL)0); | ||||
| 744 | } | ||||
| 745 | |||||
| 746 | /**<p>Sets whether the cell has a bezeled border. | ||||
| 747 | If this method is called, the bordered flag is turn off. | ||||
| 748 | By default a NSCell has no bezeled border</p> | ||||
| 749 | <p>See Also: -isBezeled -setBordered: -isBordered</p> | ||||
| 750 | */ | ||||
| 751 | - (void) setBezeled: (BOOL)flag | ||||
| 752 | { | ||||
| 753 | _cell.is_bezeled = flag; | ||||
| 754 | _cell.is_bordered = NO((BOOL)0); | ||||
| 755 | } | ||||
| 756 | |||||
| 757 | /**<p>Sets whether the cell has a border. If this method is called, | ||||
| 758 | the bezeled flag is turn off. By default a NSCell has no border</p> | ||||
| 759 | <p>See Also: -isBordered -setBezeled: -isBezeled</p> | ||||
| 760 | */ | ||||
| 761 | - (void) setBordered: (BOOL)flag | ||||
| 762 | { | ||||
| 763 | _cell.is_bordered = flag; | ||||
| 764 | _cell.is_bezeled = NO((BOOL)0); | ||||
| 765 | } | ||||
| 766 | |||||
| 767 | - (NSFocusRingType) focusRingType | ||||
| 768 | { | ||||
| 769 | return _cell.focus_ring_type; | ||||
| 770 | } | ||||
| 771 | |||||
| 772 | - (void) setFocusRingType: (NSFocusRingType)type | ||||
| 773 | { | ||||
| 774 | _cell.focus_ring_type = type; | ||||
| 775 | } | ||||
| 776 | |||||
| 777 | /**<p>Sets the NSCell's state. Please use always symbolic constants when | ||||
| 778 | calling this method. The integer values could be changed in the this | ||||
| 779 | implementation. (Currently they match the Cocoa values but they are | ||||
| 780 | quite strange)</p> <p>See Also: -state</p> | ||||
| 781 | */ | ||||
| 782 | - (void) setState: (NSInteger)value | ||||
| 783 | { | ||||
| 784 | /* We do exactly as in macosx when value is not NSOnState, | ||||
| 785 | * NSOffState, NSMixedState, even if their behaviour (value < 0 ==> | ||||
| 786 | * NSMixedState) is a bit strange. We could decide to do | ||||
| 787 | * differently in the future, so please use always symbolic | ||||
| 788 | * constants when calling this method, this way your code won't be | ||||
| 789 | * broken by changes. */ | ||||
| 790 | if (value > 0 || (value < 0 && _cell.allows_mixed_state == NO((BOOL)0))) | ||||
| 791 | { | ||||
| 792 | _cell.state = NSOnState; | ||||
| 793 | } | ||||
| 794 | else if (value == 0) | ||||
| 795 | { | ||||
| 796 | _cell.state = NSOffState; | ||||
| 797 | } | ||||
| 798 | else | ||||
| 799 | { | ||||
| 800 | _cell.state = NSMixedState; | ||||
| 801 | } | ||||
| 802 | } | ||||
| 803 | |||||
| 804 | /**<p>Returns the NSCell's state</p> | ||||
| 805 | <p>See Also: -setState: </p> | ||||
| 806 | */ | ||||
| 807 | - (NSInteger) state | ||||
| 808 | { | ||||
| 809 | return _cell.state; | ||||
| 810 | } | ||||
| 811 | |||||
| 812 | - (BOOL) allowsMixedState | ||||
| 813 | { | ||||
| 814 | return _cell.allows_mixed_state; | ||||
| 815 | } | ||||
| 816 | |||||
| 817 | - (void) setAllowsMixedState: (BOOL)flag | ||||
| 818 | { | ||||
| 819 | _cell.allows_mixed_state = flag; | ||||
| 820 | if (!flag && _cell.state == NSMixedState) | ||||
| 821 | { | ||||
| 822 | [self setNextState]; | ||||
| 823 | } | ||||
| 824 | } | ||||
| 825 | |||||
| 826 | - (NSInteger) nextState | ||||
| 827 | { | ||||
| 828 | switch (_cell.state) | ||||
| 829 | { | ||||
| 830 | case NSOnState: | ||||
| 831 | { | ||||
| 832 | return NSOffState; | ||||
| 833 | } | ||||
| 834 | case NSOffState: | ||||
| 835 | { | ||||
| 836 | if (_cell.allows_mixed_state) | ||||
| 837 | { | ||||
| 838 | return NSMixedState; | ||||
| 839 | } | ||||
| 840 | else | ||||
| 841 | { | ||||
| 842 | return NSOnState; | ||||
| 843 | } | ||||
| 844 | } | ||||
| 845 | case NSMixedState: | ||||
| 846 | default: | ||||
| 847 | { | ||||
| 848 | return NSOnState; | ||||
| 849 | } | ||||
| 850 | } | ||||
| 851 | } | ||||
| 852 | |||||
| 853 | - (void) setNextState | ||||
| 854 | { | ||||
| 855 | [self setState: [self nextState]]; | ||||
| 856 | } | ||||
| 857 | |||||
| 858 | /**<p>Returns the alignment of the text used in the NSCell. See | ||||
| 859 | <ref type="type" id="NSTextAlignment">NSTextAlignment</ref> for more | ||||
| 860 | informations. By default the text alignment is <ref type="type" | ||||
| 861 | id="NSTextAlignment">NSJustifiedTextAlignment</ref></p> | ||||
| 862 | <p>See Also: -setAlignment:</p> | ||||
| 863 | */ | ||||
| 864 | - (NSTextAlignment) alignment | ||||
| 865 | { | ||||
| 866 | return _cell.text_align; | ||||
| 867 | } | ||||
| 868 | |||||
| 869 | /** <p>Returns the font of the text used in the NSCell</p> | ||||
| 870 | <p>See Also: -setFont:</p> | ||||
| 871 | */ | ||||
| 872 | - (NSFont*) font | ||||
| 873 | { | ||||
| 874 | return _font; | ||||
| 875 | } | ||||
| 876 | |||||
| 877 | /**<p>Returns whether the cell is editable.By default a NSCell is not editable. | ||||
| 878 | </p><p>See Also: -setEditable:</p> | ||||
| 879 | */ | ||||
| 880 | - (BOOL) isEditable | ||||
| 881 | { | ||||
| 882 | return _cell.is_editable; | ||||
| 883 | } | ||||
| 884 | |||||
| 885 | /**<p>Returns whether the cell is selectable. This method returns YES if | ||||
| 886 | the cell is selectable or editable. NO otherwise</p> | ||||
| 887 | <p>See Also: -setSelectable: -isEditable -setEditable: </p> | ||||
| 888 | */ | ||||
| 889 | - (BOOL) isSelectable | ||||
| 890 | { | ||||
| 891 | return _cell.is_selectable || _cell.is_editable; | ||||
| 892 | } | ||||
| 893 | |||||
| 894 | /**<p>Returns whether the NSCell is scrollable. By default a NSCell is not | ||||
| 895 | scrollable</p><p>See Also: -setScrollable:</p> | ||||
| 896 | */ | ||||
| 897 | - (BOOL) isScrollable | ||||
| 898 | { | ||||
| 899 | return _cell.is_scrollable; | ||||
| 900 | } | ||||
| 901 | |||||
| 902 | /**<p>Sets the alignment of the text. See <ref type="type" | ||||
| 903 | id="NSTextAlignment">NSTextAlignment</ref>.</p><p>See Also: -alignment </p> | ||||
| 904 | */ | ||||
| 905 | - (void) setAlignment: (NSTextAlignment)mode | ||||
| 906 | { | ||||
| 907 | // This does not have any influence on attributed strings | ||||
| 908 | _cell.text_align = mode; | ||||
| 909 | } | ||||
| 910 | |||||
| 911 | /**<p>Sets whether the NSCell's text is editable.</p> | ||||
| 912 | <p>See Also: -isEditable -setSelectable: -isSelectable</p> | ||||
| 913 | */ | ||||
| 914 | - (void) setEditable: (BOOL)flag | ||||
| 915 | { | ||||
| 916 | /* | ||||
| 917 | * The cell_editable flag is also checked to see if the cell is | ||||
| 918 | * selectable so turning edit on also turns selectability on (until | ||||
| 919 | * edit is turned off again). | ||||
| 920 | */ | ||||
| 921 | _cell.is_editable = flag; | ||||
| 922 | } | ||||
| 923 | |||||
| 924 | /**<p>Sets the text font. The NSCell's type is set to NSTextCellType if needed | ||||
| 925 | </p><p>See Also: -font -setType: -type</p> | ||||
| 926 | */ | ||||
| 927 | - (void) setFont: (NSFont*)fontObject | ||||
| 928 | { | ||||
| 929 | if (_cell.type != NSTextCellType) | ||||
| 930 | { | ||||
| 931 | [self setType: NSTextCellType]; | ||||
| 932 | } | ||||
| 933 | |||||
| 934 | // This does not have any influence on attributed strings | ||||
| 935 | ASSIGN (_font, fontObject)({ id __object = _font; _font = [(fontObject) retain]; [__object release]; }); | ||||
| 936 | } | ||||
| 937 | |||||
| 938 | /**<p>Sets whether the cell selectable. Making a cell unselectable also | ||||
| 939 | * makes it uneditable until a -setEditable: re-enables it.</p> | ||||
| 940 | *<p>See Also: -isSelectable -setEditable: -isEditable</p> | ||||
| 941 | */ | ||||
| 942 | - (void) setSelectable: (BOOL)flag | ||||
| 943 | { | ||||
| 944 | _cell.is_selectable = flag; | ||||
| 945 | |||||
| 946 | if (!flag) | ||||
| 947 | _cell.is_editable = NO((BOOL)0); | ||||
| 948 | } | ||||
| 949 | |||||
| 950 | /**<p>Sets whether the NCell is scrollable. By default a NSCell is not | ||||
| 951 | scrollable</p><p>See Also: -isSelectable</p> | ||||
| 952 | */ | ||||
| 953 | - (void) setScrollable: (BOOL)flag | ||||
| 954 | { | ||||
| 955 | _cell.is_scrollable = flag; | ||||
| 956 | if (flag) | ||||
| 957 | { | ||||
| 958 | [self setWraps: NO((BOOL)0)]; | ||||
| 959 | } | ||||
| 960 | } | ||||
| 961 | |||||
| 962 | - (void) setWraps: (BOOL)flag | ||||
| 963 | { | ||||
| 964 | if (flag) | ||||
| 965 | { | ||||
| 966 | if (![self wraps]) | ||||
| 967 | [self setLineBreakMode: NSLineBreakByWordWrapping]; | ||||
| 968 | } | ||||
| 969 | else | ||||
| 970 | { | ||||
| 971 | if ([self wraps]) | ||||
| 972 | [self setLineBreakMode: NSLineBreakByClipping]; | ||||
| 973 | } | ||||
| 974 | } | ||||
| 975 | |||||
| 976 | - (BOOL) wraps | ||||
| 977 | { | ||||
| 978 | return _cell.line_break_mode == NSLineBreakByWordWrapping | ||||
| 979 | || _cell.line_break_mode == NSLineBreakByCharWrapping; | ||||
| 980 | } | ||||
| 981 | |||||
| 982 | - (void) setAttributedStringValue: (NSAttributedString*)attribStr | ||||
| 983 | { | ||||
| 984 | /* Hmm. FIXME. Not sure what to do here. */ | ||||
| 985 | if (_formatter != nil((id)((void*)0))) | ||||
| 986 | { | ||||
| 987 | id newObjectValue; | ||||
| 988 | |||||
| 989 | if ([_formatter getObjectValue: &newObjectValue | ||||
| 990 | forString: [attribStr string] | ||||
| 991 | errorDescription: NULL((void *)0)] == YES((BOOL)1)) | ||||
| 992 | { | ||||
| 993 | [self setObjectValue: newObjectValue]; | ||||
| 994 | /* What about the attributed string ? We are loosing it. */ | ||||
| 995 | return; | ||||
| 996 | } | ||||
| 997 | _cell.has_valid_object_value = NO((BOOL)0); | ||||
| 998 | } | ||||
| 999 | else | ||||
| 1000 | { | ||||
| 1001 | _cell.has_valid_object_value = YES((BOOL)1); | ||||
| 1002 | ASSIGN (_object_value, attribStr)({ id __object = _object_value; _object_value = [(attribStr) retain ]; [__object release]; }); | ||||
| 1003 | } | ||||
| 1004 | |||||
| 1005 | ASSIGN (_contents, attribStr)({ id __object = _contents; _contents = [(attribStr) retain]; [__object release]; }); | ||||
| 1006 | _cell.contents_is_attributed_string = YES((BOOL)1); | ||||
| 1007 | } | ||||
| 1008 | |||||
| 1009 | - (NSAttributedString*) attributedStringValue | ||||
| 1010 | { | ||||
| 1011 | if (_formatter != nil((id)((void*)0))) | ||||
| 1012 | { | ||||
| 1013 | NSDictionary *attributes; | ||||
| 1014 | NSAttributedString *attrStr; | ||||
| 1015 | |||||
| 1016 | attributes = [self _nonAutoreleasedTypingAttributes]; | ||||
| 1017 | attrStr = [_formatter attributedStringForObjectValue: _object_value | ||||
| 1018 | withDefaultAttributes: attributes]; | ||||
| 1019 | RELEASE(attributes)[(attributes) release]; | ||||
| 1020 | if (attrStr != nil((id)((void*)0))) | ||||
| 1021 | { | ||||
| 1022 | return attrStr; | ||||
| 1023 | } | ||||
| 1024 | } | ||||
| 1025 | |||||
| 1026 | /* In all other cases */ | ||||
| 1027 | if (_cell.contents_is_attributed_string && | ||||
| 1028 | nil((id)((void*)0)) != _contents) | ||||
| 1029 | { | ||||
| 1030 | return (NSAttributedString *)_contents; | ||||
| 1031 | } | ||||
| 1032 | else | ||||
| 1033 | { | ||||
| 1034 | NSDictionary *dict; | ||||
| 1035 | NSAttributedString *attrStr; | ||||
| 1036 | |||||
| 1037 | dict = [self _nonAutoreleasedTypingAttributes]; | ||||
| 1038 | attrStr = [[NSAttributedString alloc] initWithString: [self stringValue] | ||||
| 1039 | attributes: dict]; | ||||
| 1040 | RELEASE(dict)[(dict) release]; | ||||
| 1041 | return AUTORELEASE(attrStr)[(attrStr) autorelease]; | ||||
| 1042 | } | ||||
| 1043 | } | ||||
| 1044 | |||||
| 1045 | - (void) setAllowsEditingTextAttributes: (BOOL)flag | ||||
| 1046 | { | ||||
| 1047 | _cell.is_rich_text = flag; | ||||
| 1048 | if (!flag) | ||||
| 1049 | _cell.imports_graphics = NO((BOOL)0); | ||||
| 1050 | } | ||||
| 1051 | |||||
| 1052 | - (BOOL) allowsEditingTextAttributes | ||||
| 1053 | { | ||||
| 1054 | return _cell.is_rich_text; | ||||
| 1055 | } | ||||
| 1056 | |||||
| 1057 | - (void) setImportsGraphics: (BOOL)flag | ||||
| 1058 | { | ||||
| 1059 | _cell.imports_graphics = flag; | ||||
| 1060 | if (flag) | ||||
| 1061 | _cell.is_rich_text = YES((BOOL)1); | ||||
| 1062 | } | ||||
| 1063 | |||||
| 1064 | - (BOOL) importsGraphics | ||||
| 1065 | { | ||||
| 1066 | return _cell.imports_graphics; | ||||
| 1067 | } | ||||
| 1068 | |||||
| 1069 | - (NSString*) title | ||||
| 1070 | { | ||||
| 1071 | return [self stringValue]; | ||||
| 1072 | } | ||||
| 1073 | |||||
| 1074 | - (void) setTitle: (NSString*)aString | ||||
| 1075 | { | ||||
| 1076 | [self setStringValue: aString]; | ||||
| 1077 | } | ||||
| 1078 | |||||
| 1079 | - (NSLineBreakMode) lineBreakMode | ||||
| 1080 | { | ||||
| 1081 | return _cell.line_break_mode; | ||||
| 1082 | } | ||||
| 1083 | |||||
| 1084 | - (void) setLineBreakMode: (NSLineBreakMode)mode | ||||
| 1085 | { | ||||
| 1086 | if (mode == NSLineBreakByCharWrapping || mode == NSLineBreakByWordWrapping) | ||||
| 1087 | { | ||||
| 1088 | _cell.is_scrollable = NO((BOOL)0); | ||||
| 1089 | } | ||||
| 1090 | _cell.line_break_mode = mode; | ||||
| 1091 | } | ||||
| 1092 | |||||
| 1093 | - (NSWritingDirection) baseWritingDirection | ||||
| 1094 | { | ||||
| 1095 | return _cell.base_writing_direction; | ||||
| 1096 | } | ||||
| 1097 | |||||
| 1098 | - (void) setBaseWritingDirection: (NSWritingDirection)direction | ||||
| 1099 | { | ||||
| 1100 | _cell.base_writing_direction = direction; | ||||
| 1101 | } | ||||
| 1102 | |||||
| 1103 | /**<p>Implemented by subclasses to return the action method. | ||||
| 1104 | The NSCell implementaiton returns NULL.</p> | ||||
| 1105 | <p>See Also: -setAction: -setTarget: -target</p> | ||||
| 1106 | */ | ||||
| 1107 | - (SEL) action | ||||
| 1108 | { | ||||
| 1109 | return NULL((void *)0); | ||||
| 1110 | } | ||||
| 1111 | |||||
| 1112 | /** <p>Implemented by subclasses to set the action method. | ||||
| 1113 | The NSCell implementation raises a NSInternalInconsistencyException</p> | ||||
| 1114 | <p>See Also: -action -setTarget: -target</p> | ||||
| 1115 | */ | ||||
| 1116 | - (void) setAction: (SEL)aSelector | ||||
| 1117 | { | ||||
| 1118 | [NSException raise: NSInternalInconsistencyException | ||||
| 1119 | format: @"attempt to set an action in an NSCell"]; | ||||
| 1120 | } | ||||
| 1121 | |||||
| 1122 | /**<p>Implemented by subclasses to set the target object. | ||||
| 1123 | The NSCell implementation raises a NSInternalInconsistencyException</p> | ||||
| 1124 | <p>See Also: -target -setAction: -action</p> | ||||
| 1125 | */ | ||||
| 1126 | - (void) setTarget: (id)anObject | ||||
| 1127 | { | ||||
| 1128 | [NSException raise: NSInternalInconsistencyException | ||||
| 1129 | format: @"attempt to set a target in an NSCell"]; | ||||
| 1130 | } | ||||
| 1131 | |||||
| 1132 | /**<p>Implemented by subclass to return the target object. | ||||
| 1133 | The NSCell implementation returns nil</p> | ||||
| 1134 | <p>See Also: -setTarget: -setAction: -action</p> | ||||
| 1135 | */ | ||||
| 1136 | - (id) target | ||||
| 1137 | { | ||||
| 1138 | return nil((id)((void*)0)); | ||||
| 1139 | } | ||||
| 1140 | |||||
| 1141 | /**<p>Returns whether the cell can continuously send its action messages.</p> | ||||
| 1142 | <p>See Also: -setContinuous:</p> | ||||
| 1143 | */ | ||||
| 1144 | - (BOOL) isContinuous | ||||
| 1145 | { | ||||
| 1146 | // Some subclasses should redefine this with NSLeftMouseDraggedMask | ||||
| 1147 | return (_action_mask & NSPeriodicMask) != 0; | ||||
| 1148 | } | ||||
| 1149 | |||||
| 1150 | /**<p>Sets whether the cell can continuously send its action messages.</p> | ||||
| 1151 | *<p>See Also: -isContinuous</p> | ||||
| 1152 | */ | ||||
| 1153 | - (void) setContinuous: (BOOL)flag | ||||
| 1154 | { | ||||
| 1155 | // Some subclasses should redefine this with NSLeftMouseDraggedMask | ||||
| 1156 | if (flag) | ||||
| 1157 | { | ||||
| 1158 | _action_mask |= NSPeriodicMask; | ||||
| 1159 | } | ||||
| 1160 | else | ||||
| 1161 | { | ||||
| 1162 | _action_mask &= ~NSPeriodicMask; | ||||
| 1163 | } | ||||
| 1164 | } | ||||
| 1165 | |||||
| 1166 | /**<p>TODO Explain</p> | ||||
| 1167 | */ | ||||
| 1168 | - (int) sendActionOn: (int)mask | ||||
| 1169 | { | ||||
| 1170 | unsigned int previousMask = _action_mask; | ||||
| 1171 | |||||
| 1172 | _action_mask = mask; | ||||
| 1173 | |||||
| 1174 | return previousMask; | ||||
| 1175 | } | ||||
| 1176 | |||||
| 1177 | /**<p>Returns the NSCell's image if the NSCell's type is <ref type="type" | ||||
| 1178 | id="NSCellType">NSImageCellType</ref>, | ||||
| 1179 | returns nil otherwise.</p> | ||||
| 1180 | <p>See Also: -setImage: -setType: -type</p> | ||||
| 1181 | */ | ||||
| 1182 | - (NSImage*) image | ||||
| 1183 | { | ||||
| 1184 | if (_cell.type == NSImageCellType) | ||||
| 1185 | { | ||||
| 1186 | return _cell_image; | ||||
| 1187 | } | ||||
| 1188 | else | ||||
| 1189 | return nil((id)((void*)0)); | ||||
| 1190 | } | ||||
| 1191 | |||||
| 1192 | /**<p>Sets the NSCell's image to anImage. This method sets the cell's type | ||||
| 1193 | to NSImageCellType if needed. Raises an NSInvalidArgumentException if | ||||
| 1194 | the anImage is not an NSImage (sub)class. The new image is retained and the | ||||
| 1195 | old one is released</p><p>See Also: -image</p> | ||||
| 1196 | */ | ||||
| 1197 | - (void) setImage: (NSImage*)anImage | ||||
| 1198 | { | ||||
| 1199 | if (anImage) | ||||
| 1200 | { | ||||
| 1201 | NSAssert ([anImage isKindOfClass: imageClass],do { if (!(([anImage isKindOfClass: imageClass]))) { [[NSAssertionHandler currentHandler] handleFailureInMethod: _cmd object: self file : [NSString stringWithUTF8String: "NSCell.m"] lineNumber: 1202 description: ((NSInvalidArgumentException))]; } } while(0) | ||||
| 1202 | NSInvalidArgumentException)do { if (!(([anImage isKindOfClass: imageClass]))) { [[NSAssertionHandler currentHandler] handleFailureInMethod: _cmd object: self file : [NSString stringWithUTF8String: "NSCell.m"] lineNumber: 1202 description: ((NSInvalidArgumentException))]; } } while(0); | ||||
| 1203 | } | ||||
| 1204 | |||||
| 1205 | if (_cell.type != NSImageCellType) | ||||
| 1206 | { | ||||
| 1207 | [self setType: NSImageCellType]; | ||||
| 1208 | } | ||||
| 1209 | |||||
| 1210 | ASSIGN (_cell_image, anImage)({ id __object = _cell_image; _cell_image = [(anImage) retain ]; [__object release]; }); | ||||
| 1211 | } | ||||
| 1212 | |||||
| 1213 | /**<p>Implemented by sublclasses to assigns the tag <var>anInt</var>. | ||||
| 1214 | The NSCell implementation raises an NSInvalidArgumentException.</p> | ||||
| 1215 | <p>See Also: -tag</p> | ||||
| 1216 | */ | ||||
| 1217 | - (void) setTag: (NSInteger)anInt | ||||
| 1218 | { | ||||
| 1219 | [NSException raise: NSInternalInconsistencyException | ||||
| 1220 | format: @"attempt to set a tag in an NSCell"]; | ||||
| 1221 | } | ||||
| 1222 | |||||
| 1223 | /**<p>Implemented by subclasses to Return the tag. | ||||
| 1224 | The NSCell implementation returns -1 </p><p>See Also: -setTag:</p> | ||||
| 1225 | */ | ||||
| 1226 | - (NSInteger) tag | ||||
| 1227 | { | ||||
| 1228 | return -1; | ||||
| 1229 | } | ||||
| 1230 | |||||
| 1231 | /* | ||||
| 1232 | * Formatting Data | ||||
| 1233 | */ | ||||
| 1234 | - (void) setFloatingPointFormat: (BOOL)autoRange | ||||
| 1235 | left: (unsigned int)leftDigits | ||||
| 1236 | right: (unsigned int)rightDigits | ||||
| 1237 | { | ||||
| 1238 | NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; | ||||
| 1239 | NSMutableString *format = [[NSMutableString alloc] init]; | ||||
| 1240 | |||||
| 1241 | if (autoRange) | ||||
| 1242 | { | ||||
| 1243 | unsigned fieldWidth = leftDigits + rightDigits + 1; | ||||
| 1244 | |||||
| 1245 | // FIXME: this does not fully match the documentation. | ||||
| 1246 | while (fieldWidth--) | ||||
| 1247 | { | ||||
| 1248 | [format appendString: @"#"]; | ||||
| 1249 | } | ||||
| 1250 | } | ||||
| 1251 | else | ||||
| 1252 | { | ||||
| 1253 | while (leftDigits--) | ||||
| 1254 | { | ||||
| 1255 | [format appendString: @"#"]; | ||||
| 1256 | } | ||||
| 1257 | [format appendString: @"."]; | ||||
| 1258 | while (rightDigits--) | ||||
| 1259 | { | ||||
| 1260 | [format appendString: @"0"]; | ||||
| 1261 | } | ||||
| 1262 | } | ||||
| 1263 | |||||
| 1264 | [formatter setFormat: format]; | ||||
| 1265 | RELEASE(format)[(format) release]; | ||||
| 1266 | [self setFormatter: formatter]; | ||||
| 1267 | RELEASE(formatter)[(formatter) release]; | ||||
| 1268 | } | ||||
| 1269 | |||||
| 1270 | - (void) setFormatter: (NSFormatter*)newFormatter | ||||
| 1271 | { | ||||
| 1272 | ASSIGN(_formatter, newFormatter)({ id __object = _formatter; _formatter = [(newFormatter) retain ]; [__object release]; }); | ||||
| 1273 | } | ||||
| 1274 | |||||
| 1275 | - (id) formatter | ||||
| 1276 | { | ||||
| 1277 | return _formatter; | ||||
| 1278 | } | ||||
| 1279 | |||||
| 1280 | /**<p> TODO</p> | ||||
| 1281 | */ | ||||
| 1282 | - (int) entryType | ||||
| 1283 | { | ||||
| 1284 | return _cell.entry_type; | ||||
| 1285 | } | ||||
| 1286 | |||||
| 1287 | /** <p>TODO</p> | ||||
| 1288 | */ | ||||
| 1289 | - (void) setEntryType: (int)aType | ||||
| 1290 | { | ||||
| 1291 | [self setType: NSTextCellType]; | ||||
| 1292 | // TODO: This should select a suitable formatter | ||||
| 1293 | _cell.entry_type = aType; | ||||
| 1294 | } | ||||
| 1295 | |||||
| 1296 | - (BOOL) isEntryAcceptable: (NSString*)aString | ||||
| 1297 | { | ||||
| 1298 | if ((_formatter != nil((id)((void*)0))) && ![aString isEqualToString: @""]) | ||||
| 1299 | { | ||||
| 1300 | id newObjectValue; | ||||
| 1301 | |||||
| 1302 | return [_formatter getObjectValue: &newObjectValue | ||||
| 1303 | forString: aString | ||||
| 1304 | errorDescription: NULL((void *)0)]; | ||||
| 1305 | } | ||||
| 1306 | else | ||||
| 1307 | { | ||||
| 1308 | return YES((BOOL)1); | ||||
| 1309 | } | ||||
| 1310 | } | ||||
| 1311 | |||||
| 1312 | /* | ||||
| 1313 | * Menu | ||||
| 1314 | */ | ||||
| 1315 | - (void) setMenu: (NSMenu*)aMenu | ||||
| 1316 | { | ||||
| 1317 | ASSIGN (_menu, aMenu)({ id __object = _menu; _menu = [(aMenu) retain]; [__object release ]; }); | ||||
| 1318 | } | ||||
| 1319 | |||||
| 1320 | - (NSMenu*) menu | ||||
| 1321 | { | ||||
| 1322 | return _menu; | ||||
| 1323 | } | ||||
| 1324 | |||||
| 1325 | - (NSMenu*) menuForEvent: (NSEvent*)anEvent | ||||
| 1326 | inRect: (NSRect)cellFrame | ||||
| 1327 | ofView: (NSView*)aView | ||||
| 1328 | { | ||||
| 1329 | return [self menu]; | ||||
| 1330 | } | ||||
| 1331 | |||||
| 1332 | /** | ||||
| 1333 | * Compares the reciever to another to another NSCell. | ||||
| 1334 | * The argument must be an NSCell sublclass and have | ||||
| 1335 | * the NSCellType NSTextCellType. Returns the result | ||||
| 1336 | * of the comparison of each cell's stringValue. | ||||
| 1337 | */ | ||||
| 1338 | - (NSComparisonResult) compare: (id)otherCell | ||||
| 1339 | { | ||||
| 1340 | if ([otherCell isKindOfClass: cellClass] == NO((BOOL)0)) | ||||
| 1341 | { | ||||
| 1342 | [NSException raise: NSBadComparisonException | ||||
| 1343 | format: @"NSCell comparison with non-NSCell"]; | ||||
| 1344 | } | ||||
| 1345 | if (_cell.type != NSTextCellType | ||||
| 1346 | || ((NSCell*)otherCell)->_cell.type != NSTextCellType) | ||||
| 1347 | { | ||||
| 1348 | [NSException raise: NSBadComparisonException | ||||
| 1349 | format: @"Comparison between non-text cells"]; | ||||
| 1350 | } | ||||
| 1351 | /* We shouldn't access instance variables directly as subclasses | ||||
| 1352 | may override stringValue to retrieve the value from somewhere else. */ | ||||
| 1353 | return [[self stringValue] compare: [(NSCell*)otherCell stringValue]]; | ||||
| 1354 | } | ||||
| 1355 | |||||
| 1356 | /* | ||||
| 1357 | * Should this cell respond to keyboard input? | ||||
| 1358 | */ | ||||
| 1359 | - (BOOL) acceptsFirstResponder | ||||
| 1360 | { | ||||
| 1361 | return _cell.is_disabled == NO((BOOL)0) && _cell.refuses_first_responder == NO((BOOL)0); | ||||
| 1362 | } | ||||
| 1363 | |||||
| 1364 | - (void) setShowsFirstResponder: (BOOL)flag | ||||
| 1365 | { | ||||
| 1366 | _cell.shows_first_responder = flag; | ||||
| 1367 | } | ||||
| 1368 | |||||
| 1369 | - (BOOL) showsFirstResponder | ||||
| 1370 | { | ||||
| 1371 | return _cell.shows_first_responder; | ||||
| 1372 | } | ||||
| 1373 | |||||
| 1374 | - (void) setTitleWithMnemonic: (NSString*)aString | ||||
| 1375 | { | ||||
| 1376 | NSRange r = [aString rangeOfString: @"&"]; | ||||
| 1377 | |||||
| 1378 | if (r.length > 0) | ||||
| 1379 | { | ||||
| 1380 | unsigned int location = r.location; | ||||
| 1381 | |||||
| 1382 | |||||
| 1383 | [self setTitle: [[aString substringToIndex: location] | ||||
| 1384 | stringByAppendingString: | ||||
| 1385 | [aString substringFromIndex: NSMaxRange(r)]]]; | ||||
| 1386 | // TODO: We should underline this character | ||||
| 1387 | [self setMnemonicLocation: location]; | ||||
| 1388 | } | ||||
| 1389 | } | ||||
| 1390 | |||||
| 1391 | - (NSString*) mnemonic | ||||
| 1392 | { | ||||
| 1393 | NSUInteger location = [self mnemonicLocation]; | ||||
| 1394 | NSString *c = [self title]; | ||||
| 1395 | |||||
| 1396 | if ((location == NSNotFound) || location >= [c length]) | ||||
| 1397 | return @""; | ||||
| 1398 | |||||
| 1399 | return [c substringWithRange: NSMakeRange (location, 1)]; | ||||
| 1400 | } | ||||
| 1401 | |||||
| 1402 | - (void) setMnemonicLocation: (NSUInteger)location | ||||
| 1403 | { | ||||
| 1404 | _cell.mnemonic_location = location; | ||||
| 1405 | } | ||||
| 1406 | |||||
| 1407 | - (NSUInteger) mnemonicLocation | ||||
| 1408 | { | ||||
| 1409 | return _cell.mnemonic_location; | ||||
| 1410 | } | ||||
| 1411 | |||||
| 1412 | - (BOOL) refusesFirstResponder | ||||
| 1413 | { | ||||
| 1414 | return _cell.refuses_first_responder; | ||||
| 1415 | } | ||||
| 1416 | |||||
| 1417 | - (void) setRefusesFirstResponder: (BOOL)flag | ||||
| 1418 | { | ||||
| 1419 | _cell.refuses_first_responder = flag; | ||||
| 1420 | } | ||||
| 1421 | |||||
| 1422 | /** | ||||
| 1423 | * Simulates a single click in the cell (only works with controls which have | ||||
| 1424 | * no more than one cell). This method is deprecated, | ||||
| 1425 | * performClickWithFrame:inView: is the right method to use now. | ||||
| 1426 | */ | ||||
| 1427 | - (void) performClick: (id)sender | ||||
| 1428 | { | ||||
| 1429 | NSView *cv = [self controlView]; | ||||
| 1430 | |||||
| 1431 | if (cv != nil((id)((void*)0))) | ||||
| 1432 | [self performClickWithFrame: [cv bounds] inView: cv]; | ||||
| 1433 | } | ||||
| 1434 | |||||
| 1435 | /* | ||||
| 1436 | * Helper method used to send actions. Sender normally is [self controlView]. | ||||
| 1437 | */ | ||||
| 1438 | - (BOOL) _sendActionFrom: (id)sender | ||||
| 1439 | { | ||||
| 1440 | SEL action = [self action]; | ||||
| 1441 | |||||
| 1442 | if ([sender respondsToSelector: @selector(sendAction:to:)]) | ||||
| 1443 | { | ||||
| 1444 | return [sender sendAction: action to: [self target]]; | ||||
| 1445 | } | ||||
| 1446 | else | ||||
| 1447 | { | ||||
| 1448 | if (sender == nil((id)((void*)0))) | ||||
| 1449 | sender = self; | ||||
| 1450 | |||||
| 1451 | if (action) | ||||
| 1452 | { | ||||
| 1453 | return [NSApp sendAction: action to: [self target] from: sender]; | ||||
| 1454 | } | ||||
| 1455 | } | ||||
| 1456 | |||||
| 1457 | return NO((BOOL)0); | ||||
| 1458 | } | ||||
| 1459 | |||||
| 1460 | /** | ||||
| 1461 | * Simulates a single click in the cell. | ||||
| 1462 | * The display of the cell with this event | ||||
| 1463 | * occurs in the area delimited by <var>cellFrame</var> within | ||||
| 1464 | * <var>controlView</var>. | ||||
| 1465 | */ | ||||
| 1466 | - (void) performClickWithFrame: (NSRect)cellFrame inView: (NSView *)controlView | ||||
| 1467 | { | ||||
| 1468 | if (_cell.is_disabled == YES((BOOL)1)) | ||||
| 1469 | { | ||||
| 1470 | return; | ||||
| 1471 | } | ||||
| 1472 | |||||
| 1473 | [self setNextState]; | ||||
| 1474 | |||||
| 1475 | if (controlView != nil((id)((void*)0))) | ||||
| 1476 | { | ||||
| 1477 | NSWindow *cvWin = [controlView window]; | ||||
| 1478 | NSDate *limit = [NSDate dateWithTimeIntervalSinceNow: 0.1]; | ||||
| 1479 | |||||
| 1480 | [controlView lockFocus]; | ||||
| 1481 | [self highlight: YES((BOOL)1) withFrame: cellFrame inView: controlView]; | ||||
| 1482 | [cvWin flushWindow]; | ||||
| 1483 | |||||
| 1484 | // Wait approx 1/10 seconds | ||||
| 1485 | [[NSRunLoop currentRunLoop] runUntilDate: limit]; | ||||
| 1486 | |||||
| 1487 | [self highlight: NO((BOOL)0) withFrame: cellFrame inView: controlView]; | ||||
| 1488 | [cvWin flushWindow]; | ||||
| 1489 | [controlView unlockFocus]; | ||||
| 1490 | } | ||||
| 1491 | |||||
| 1492 | [self _sendActionFrom: controlView]; | ||||
| 1493 | } | ||||
| 1494 | |||||
| 1495 | /* | ||||
| 1496 | * Deriving values from other objects (not necessarily cells) | ||||
| 1497 | */ | ||||
| 1498 | - (void) takeObjectValueFrom: (id)sender | ||||
| 1499 | { | ||||
| 1500 | [self setObjectValue: [sender objectValue]]; | ||||
| 1501 | } | ||||
| 1502 | |||||
| 1503 | /** <p>Sets the NSCell's double value to sender's double value</p> | ||||
| 1504 | <p>See Also: -setDoubleValue:</p> | ||||
| 1505 | */ | ||||
| 1506 | - (void) takeDoubleValueFrom: (id)sender | ||||
| 1507 | { | ||||
| 1508 | [self setDoubleValue: [sender doubleValue]]; | ||||
| 1509 | } | ||||
| 1510 | |||||
| 1511 | /** <p>Sets the NSCell's float value to sender's float value</p> | ||||
| 1512 | <p>See Also: -setFloatValue:</p> | ||||
| 1513 | */ | ||||
| 1514 | - (void) takeFloatValueFrom: (id)sender | ||||
| 1515 | { | ||||
| 1516 | [self setFloatValue: [sender floatValue]]; | ||||
| 1517 | } | ||||
| 1518 | |||||
| 1519 | /** <p>Sets the NSCell's int value to sender's int value</p> | ||||
| 1520 | <p>See Also: -setIntValue:</p> | ||||
| 1521 | */ | ||||
| 1522 | - (void) takeIntValueFrom: (id)sender | ||||
| 1523 | { | ||||
| 1524 | [self setIntValue: [sender intValue]]; | ||||
| 1525 | } | ||||
| 1526 | |||||
| 1527 | /** <p>Sets the NSCell's NSInteger value to sender's NSInteger value</p> | ||||
| 1528 | <p>See Also: -setIntegerValue:</p> | ||||
| 1529 | */ | ||||
| 1530 | - (void) takeIntegerValueFrom: (id)sender | ||||
| 1531 | { | ||||
| 1532 | [self setIntegerValue: [sender integerValue]]; | ||||
| 1533 | } | ||||
| 1534 | |||||
| 1535 | /** <p>Sets the NSCell's NSString value to sender's NSSting value</p> | ||||
| 1536 | <p>See Also: -setStringValue:</p> | ||||
| 1537 | */ | ||||
| 1538 | - (void) takeStringValueFrom: (id)sender | ||||
| 1539 | { | ||||
| 1540 | [self setStringValue: [sender stringValue]]; | ||||
| 1541 | } | ||||
| 1542 | |||||
| 1543 | /** <p>Returns the NSCell's represented object</p> | ||||
| 1544 | <p>See Also: -setRepresentedObject:</p> | ||||
| 1545 | */ | ||||
| 1546 | - (id) representedObject | ||||
| 1547 | { | ||||
| 1548 | return _represented_object; | ||||
| 1549 | } | ||||
| 1550 | |||||
| 1551 | /** <p>Sets the NSCell's represented object to <var>anObject</var>. | ||||
| 1552 | anObject will be retain.</p><p>See Also: -representedObject</p> | ||||
| 1553 | */ | ||||
| 1554 | - (void) setRepresentedObject: (id)anObject | ||||
| 1555 | { | ||||
| 1556 | /* Ahm - not nice - the RETAIN here could cause retain cycles - anyway. */ | ||||
| 1557 | ASSIGN (_represented_object, anObject)({ id __object = _represented_object; _represented_object = [ (anObject) retain]; [__object release]; }); | ||||
| 1558 | } | ||||
| 1559 | |||||
| 1560 | /** <p>Returns YES. Subclasses should overrided this method if you want | ||||
| 1561 | stop tracking the mouse. This method is call in the | ||||
| 1562 | -trackMouse:inRect:ofView:untilMouseUp: main loop.</p> | ||||
| 1563 | <p>See Also: -trackMouse:inRect:ofView:untilMouseUp:</p> | ||||
| 1564 | */ | ||||
| 1565 | - (BOOL) continueTracking: (NSPoint)lastPoint | ||||
| 1566 | at: (NSPoint)currentPoint | ||||
| 1567 | inView: (NSView*)controlView | ||||
| 1568 | { | ||||
| 1569 | return YES((BOOL)1); | ||||
| 1570 | } | ||||
| 1571 | |||||
| 1572 | /**<p>Returns the mouse flags. This flags are usally sets in | ||||
| 1573 | the -trackMouse:inRect:ofView:untilMouseUp: method</p> | ||||
| 1574 | */ | ||||
| 1575 | - (int) mouseDownFlags | ||||
| 1576 | { | ||||
| 1577 | return _mouse_down_flags; | ||||
| 1578 | } | ||||
| 1579 | |||||
| 1580 | /**<p>Gets the NSCell's <var>delay</var> and the <var>interval</var> | ||||
| 1581 | parameters used when NSCell sends continouly action messages. | ||||
| 1582 | The NSCell implementation sets both <var>delay</var> and <var>interval</var> | ||||
| 1583 | to 0.1.</p> | ||||
| 1584 | <p>See Also: -trackMouse:inRect:ofView:untilMouseUp:</p> | ||||
| 1585 | */ | ||||
| 1586 | - (void) getPeriodicDelay: (float*)delay interval: (float*)interval | ||||
| 1587 | { | ||||
| 1588 | *delay = 0.1; | ||||
| 1589 | *interval = 0.1; | ||||
| 1590 | } | ||||
| 1591 | |||||
| 1592 | /**<p>Returns whether tracking starts. The NSCell implementation | ||||
| 1593 | returns YES when the <var>startPoint</var> is into the control view | ||||
| 1594 | retangle, NO otherwise. This method is call at the early stage of | ||||
| 1595 | -trackMouse:inRect:ofView:untilMouseUp:</p><p>See Also: | ||||
| 1596 | [NSView-mouse:inRect:] -trackMouse:inRect:ofView:untilMouseUp: | ||||
| 1597 | </p> | ||||
| 1598 | */ | ||||
| 1599 | - (BOOL) startTrackingAt: (NSPoint)startPoint inView: (NSView*)controlView | ||||
| 1600 | { | ||||
| 1601 | // If the point is in the view then yes start tracking | ||||
| 1602 | if ([controlView mouse: startPoint inRect: [controlView bounds]]) | ||||
| 1603 | return YES((BOOL)1); | ||||
| 1604 | else | ||||
| 1605 | return NO((BOOL)0); | ||||
| 1606 | } | ||||
| 1607 | |||||
| 1608 | /**<p>Default implementation of this method in NSCell does nothing.</p> | ||||
| 1609 | */ | ||||
| 1610 | - (void) stopTracking: (NSPoint)lastPoint | ||||
| 1611 | at: (NSPoint)stopPoint | ||||
| 1612 | inView: (NSView*)controlView | ||||
| 1613 | mouseIsUp: (BOOL)flag | ||||
| 1614 | { | ||||
| 1615 | } | ||||
| 1616 | |||||
| 1617 | - (BOOL) trackMouse: (NSEvent*)theEvent | ||||
| 1618 | inRect: (NSRect)cellFrame | ||||
| 1619 | ofView: (NSView*)controlView | ||||
| 1620 | untilMouseUp: (BOOL)flag | ||||
| 1621 | { | ||||
| 1622 | NSApplication *theApp = [NSApplication sharedApplication]; | ||||
| 1623 | unsigned event_mask = NSLeftMouseDownMask | NSLeftMouseUpMask | ||||
| 1624 | | NSMouseMovedMask | NSLeftMouseDraggedMask | NSOtherMouseDraggedMask | ||||
| 1625 | | NSRightMouseDraggedMask; | ||||
| 1626 | NSPoint location = [theEvent locationInWindow]; | ||||
| 1627 | NSPoint point = [controlView convertPoint: location fromView: nil((id)((void*)0))]; | ||||
| 1628 | float delay; | ||||
| 1629 | float interval; | ||||
| 1630 | NSPoint last_point = point; | ||||
| 1631 | BOOL done; | ||||
| 1632 | BOOL mouseWentUp; | ||||
| 1633 | unsigned periodCount = 0; | ||||
| 1634 | |||||
| 1635 | NSDebugLLog(@"NSCell", @"cell start tracking in rect %@ initial point %f %f",do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell start tracking in rect %@ initial point %f %f" , NSStringFromRect(cellFrame), point.x, point.y); } while (0 ) | ||||
| 1636 | NSStringFromRect(cellFrame), point.x, point.y)do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell start tracking in rect %@ initial point %f %f" , NSStringFromRect(cellFrame), point.x, point.y); } while (0 ); | ||||
| 1637 | |||||
| 1638 | _mouse_down_flags = [theEvent modifierFlags]; | ||||
| 1639 | if (![self startTrackingAt: point inView: controlView]) | ||||
| 1640 | return NO((BOOL)0); | ||||
| 1641 | |||||
| 1642 | if (![controlView mouse: point inRect: cellFrame]) | ||||
| 1643 | return NO((BOOL)0); // point is not in cell | ||||
| 1644 | |||||
| 1645 | if ((_action_mask & NSLeftMouseDownMask) | ||||
| 1646 | && [theEvent type] == NSLeftMouseDown) | ||||
| 1647 | [self _sendActionFrom: controlView]; | ||||
| 1648 | |||||
| 1649 | if (_action_mask & NSPeriodicMask) | ||||
| 1650 | { | ||||
| 1651 | [self getPeriodicDelay: &delay interval: &interval]; | ||||
| 1652 | [NSEvent startPeriodicEventsAfterDelay: delay withPeriod: interval]; | ||||
| 1653 | event_mask |= NSPeriodicMask; | ||||
| 1654 | } | ||||
| 1655 | |||||
| 1656 | NSDebugLLog(@"NSCell", @"cell get mouse events\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell get mouse events\n" ); } while (0); | ||||
| 1657 | mouseWentUp = NO((BOOL)0); | ||||
| 1658 | done = NO((BOOL)0); | ||||
| 1659 | if (theEvent != [NSApp currentEvent]) | ||||
| 1660 | theEvent = [NSApp currentEvent]; | ||||
| 1661 | else | ||||
| 1662 | theEvent = [theApp nextEventMatchingMask: event_mask | ||||
| 1663 | untilDate: [NSDate distantFuture] | ||||
| 1664 | inMode: NSEventTrackingRunLoopMode | ||||
| 1665 | dequeue: YES((BOOL)1)]; | ||||
| 1666 | |||||
| 1667 | while (!done) | ||||
| 1668 | { | ||||
| 1669 | NSEventType eventType; | ||||
| 1670 | BOOL pointIsInCell; | ||||
| 1671 | |||||
| 1672 | eventType = [theEvent type]; | ||||
| 1673 | |||||
| 1674 | if (eventType != NSPeriodic || periodCount == 4) | ||||
| 1675 | { | ||||
| 1676 | last_point = point; | ||||
| 1677 | if (eventType == NSPeriodic) | ||||
| 1678 | { | ||||
| 1679 | NSWindow *w = [controlView window]; | ||||
| 1680 | |||||
| 1681 | /* | ||||
| 1682 | * Too many periodic events in succession - | ||||
| 1683 | * update the mouse location and reset the counter. | ||||
| 1684 | */ | ||||
| 1685 | location = [w mouseLocationOutsideOfEventStream]; | ||||
| 1686 | periodCount = 0; | ||||
| 1687 | } | ||||
| 1688 | else | ||||
| 1689 | { | ||||
| 1690 | location = [theEvent locationInWindow]; | ||||
| 1691 | } | ||||
| 1692 | point = [controlView convertPoint: location fromView: nil((id)((void*)0))]; | ||||
| 1693 | NSDebugLLog(@"NSCell", @"location %f %f\n", location.x, location.y)do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"location %f %f\n" , location.x, location.y); } while (0); | ||||
| 1694 | NSDebugLLog(@"NSCell", @"point %f %f\n", point.x, point.y)do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"point %f %f\n" , point.x, point.y); } while (0); | ||||
| 1695 | } | ||||
| 1696 | else | ||||
| 1697 | { | ||||
| 1698 | periodCount++; | ||||
| 1699 | NSDebugLLog (@"NSCell", @"cell got a periodic event")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell got a periodic event" ); } while (0); | ||||
| 1700 | } | ||||
| 1701 | |||||
| 1702 | if (![controlView mouse: point inRect: cellFrame]) | ||||
| 1703 | { | ||||
| 1704 | NSDebugLLog(@"NSCell", @"point not in cell frame\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"point not in cell frame\n" ); } while (0); | ||||
| 1705 | |||||
| 1706 | pointIsInCell = NO((BOOL)0); | ||||
| 1707 | if (flag == NO((BOOL)0)) | ||||
| 1708 | { | ||||
| 1709 | NSDebugLLog(@"NSCell", @"cell return immediately\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell return immediately\n" ); } while (0); | ||||
| 1710 | done = YES((BOOL)1); | ||||
| 1711 | } | ||||
| 1712 | } | ||||
| 1713 | else | ||||
| 1714 | { | ||||
| 1715 | pointIsInCell = YES((BOOL)1); | ||||
| 1716 | } | ||||
| 1717 | |||||
| 1718 | if (!done && ![self continueTracking: last_point // should continue | ||||
| 1719 | at: point // tracking? | ||||
| 1720 | inView: controlView]) | ||||
| 1721 | { | ||||
| 1722 | NSDebugLLog(@"NSCell", @"cell stop tracking\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell stop tracking\n" ); } while (0); | ||||
| 1723 | done = YES((BOOL)1); | ||||
| 1724 | } | ||||
| 1725 | |||||
| 1726 | // Did the mouse go up? | ||||
| 1727 | if (eventType == NSLeftMouseUp) | ||||
| 1728 | { | ||||
| 1729 | NSDebugLLog(@"NSCell", @"cell mouse went up\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell mouse went up\n" ); } while (0); | ||||
| 1730 | mouseWentUp = YES((BOOL)1); | ||||
| 1731 | done = YES((BOOL)1); | ||||
| 1732 | } | ||||
| 1733 | else | ||||
| 1734 | { | ||||
| 1735 | if (pointIsInCell && ((eventType == NSLeftMouseDragged | ||||
| 1736 | && (_action_mask & NSLeftMouseDraggedMask)) | ||||
| 1737 | || ((eventType == NSPeriodic) | ||||
| 1738 | && (_action_mask & NSPeriodicMask)))) | ||||
| 1739 | [self _sendActionFrom: controlView]; | ||||
| 1740 | } | ||||
| 1741 | |||||
| 1742 | if (!done) | ||||
| 1743 | theEvent = [theApp nextEventMatchingMask: event_mask | ||||
| 1744 | untilDate: [NSDate distantFuture] | ||||
| 1745 | inMode: NSEventTrackingRunLoopMode | ||||
| 1746 | dequeue: YES((BOOL)1)]; | ||||
| 1747 | } | ||||
| 1748 | |||||
| 1749 | // Hook called when stop tracking | ||||
| 1750 | [self stopTracking: last_point | ||||
| 1751 | at: point | ||||
| 1752 | inView: controlView | ||||
| 1753 | mouseIsUp: mouseWentUp]; | ||||
| 1754 | |||||
| 1755 | if (_action_mask & NSPeriodicMask) | ||||
| 1756 | [NSEvent stopPeriodicEvents]; | ||||
| 1757 | |||||
| 1758 | if (mouseWentUp) | ||||
| 1759 | { | ||||
| 1760 | [self setNextState]; | ||||
| 1761 | if ((_action_mask & NSLeftMouseUpMask)) | ||||
| 1762 | [self _sendActionFrom: controlView]; | ||||
| 1763 | } | ||||
| 1764 | |||||
| 1765 | // Return YES only if the mouse went up within the cell | ||||
| 1766 | if (mouseWentUp && (flag || [controlView mouse: point inRect: cellFrame])) | ||||
| 1767 | { | ||||
| 1768 | NSDebugLLog(@"NSCell", @"mouse went up in cell\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"mouse went up in cell\n" ); } while (0); | ||||
| 1769 | return YES((BOOL)1); | ||||
| 1770 | } | ||||
| 1771 | |||||
| 1772 | NSDebugLLog(@"NSCell", @"mouse did not go up in cell\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"mouse did not go up in cell\n" ); } while (0); | ||||
| 1773 | return NO((BOOL)0); // Otherwise return NO | ||||
| 1774 | } | ||||
| 1775 | |||||
| 1776 | /** <p>TODO</p> | ||||
| 1777 | */ | ||||
| 1778 | - (void) resetCursorRect: (NSRect)cellFrame inView: (NSView*)controlView | ||||
| 1779 | { | ||||
| 1780 | if (_cell.type == NSTextCellType && _cell.is_disabled == NO((BOOL)0) | ||||
| 1781 | && (_cell.is_selectable == YES((BOOL)1) || _cell.is_editable == YES((BOOL)1))) | ||||
| 1782 | { | ||||
| 1783 | static NSCursor *cursor = nil((id)((void*)0)); | ||||
| 1784 | NSRect rect; | ||||
| 1785 | |||||
| 1786 | if (cursor== nil((id)((void*)0))) | ||||
| 1787 | { | ||||
| 1788 | cursor = RETAIN([NSCursor IBeamCursor])[([NSCursor IBeamCursor]) retain]; | ||||
| 1789 | } | ||||
| 1790 | rect = NSIntersectionRect(cellFrame, [controlView visibleRect]); | ||||
| 1791 | /* | ||||
| 1792 | * Here we depend on an undocumented feature of NSCursor which may or | ||||
| 1793 | * may not exist in OPENSTEP or MacOS-X ... | ||||
| 1794 | * If we add a cursor rect to a view and don't set it to be set on | ||||
| 1795 | * either entry to or exit from the view, we push it on entry and | ||||
| 1796 | * pop it from the cursor stack on exit. | ||||
| 1797 | */ | ||||
| 1798 | [controlView addCursorRect: rect cursor: cursor]; | ||||
| 1799 | } | ||||
| 1800 | } | ||||
| 1801 | |||||
| 1802 | /**<p>Implemented by subclasses to returns the key equivalent. | ||||
| 1803 | The NSCell implementation returns an empty NSString. </p> | ||||
| 1804 | */ | ||||
| 1805 | - (NSString*) keyEquivalent | ||||
| 1806 | { | ||||
| 1807 | return @""; | ||||
| 1808 | } | ||||
| 1809 | |||||
| 1810 | /**<p>Does nothing. This method is used by subclasses to recalculate sizes</p> | ||||
| 1811 | <p>It is usally called from a NSControl object</p> | ||||
| 1812 | <p>See Also: [NSControl-calcSize]</p> | ||||
| 1813 | */ | ||||
| 1814 | - (void) calcDrawInfo: (NSRect)aRect | ||||
| 1815 | { | ||||
| 1816 | } | ||||
| 1817 | |||||
| 1818 | /**Returns the minimun size needed to display the NSCell. | ||||
| 1819 | This size is calculate by adding : | ||||
| 1820 | <list> | ||||
| 1821 | <item> the borders (plain or bezeled) size</item> | ||||
| 1822 | <item> the spacing between the border and inside the cell</item> | ||||
| 1823 | <item> the TODO ... if the cell is type of NSTextCellType | ||||
| 1824 | or the image size if the cell has a NSImageCellType type.</item> | ||||
| 1825 | </list> | ||||
| 1826 | <p>This method returns NSZeroSize if the cell has a NSNullCellType type | ||||
| 1827 | (Cocoa returns a very big size instead). | ||||
| 1828 | </p> | ||||
| 1829 | */ | ||||
| 1830 | - (NSSize) cellSize | ||||
| 1831 | { | ||||
| 1832 | NSSize borderSize, s; | ||||
| 1833 | NSBorderType aType; | ||||
| 1834 | |||||
| 1835 | // Get border size | ||||
| 1836 | if (_cell.is_bordered) | ||||
| 1837 | aType = NSLineBorder; | ||||
| 1838 | else if (_cell.is_bezeled) | ||||
| 1839 | aType = NSBezelBorder; | ||||
| 1840 | else | ||||
| 1841 | aType = NSNoBorder; | ||||
| 1842 | |||||
| 1843 | borderSize = [[GSTheme theme] sizeForBorderType: aType]; | ||||
| 1844 | |||||
| 1845 | // Add spacing between border and inside | ||||
| 1846 | if (_cell.is_bordered || _cell.is_bezeled) | ||||
| 1847 | { | ||||
| 1848 | borderSize.height += 1; | ||||
| 1849 | borderSize.width += 3; | ||||
| 1850 | } | ||||
| 1851 | |||||
| 1852 | // Get Content Size | ||||
| 1853 | switch (_cell.type) | ||||
| 1854 | { | ||||
| 1855 | case NSTextCellType: | ||||
| 1856 | { | ||||
| 1857 | NSAttributedString *attrStr; | ||||
| 1858 | |||||
| 1859 | attrStr = [self attributedStringValue]; | ||||
| 1860 | if ([attrStr length] != 0) | ||||
| 1861 | { | ||||
| 1862 | s = [attrStr size]; | ||||
| 1863 | } | ||||
| 1864 | else | ||||
| 1865 | { | ||||
| 1866 | s = [self _sizeText: @"A"]; | ||||
| 1867 | } | ||||
| 1868 | } | ||||
| 1869 | break; | ||||
| 1870 | |||||
| 1871 | case NSImageCellType: | ||||
| 1872 | if (_cell_image == nil((id)((void*)0))) | ||||
| 1873 | { | ||||
| 1874 | s = NSZeroSize; | ||||
| 1875 | } | ||||
| 1876 | else | ||||
| 1877 | { | ||||
| 1878 | s = [_cell_image size]; | ||||
| 1879 | } | ||||
| 1880 | break; | ||||
| 1881 | |||||
| 1882 | default: | ||||
| 1883 | case NSNullCellType: | ||||
| 1884 | // macosx instead returns a 'very big size' here; we return NSZeroSize | ||||
| 1885 | s = NSZeroSize; | ||||
| 1886 | break; | ||||
| 1887 | } | ||||
| 1888 | |||||
| 1889 | // Add in border size | ||||
| 1890 | s.width += 2 * borderSize.width; | ||||
| 1891 | s.height += 2 * borderSize.height; | ||||
| 1892 | |||||
| 1893 | return s; | ||||
| 1894 | } | ||||
| 1895 | |||||
| 1896 | /**<p>TODO. Currently the GNUstep implementation returns -cellSize</p> | ||||
| 1897 | <p>See Also: -cellSize</p> | ||||
| 1898 | */ | ||||
| 1899 | - (NSSize) cellSizeForBounds: (NSRect)aRect | ||||
| 1900 | { | ||||
| 1901 | if (_cell.type == NSTextCellType) | ||||
| 1902 | { | ||||
| 1903 | // TODO: Resize the text to fit | ||||
| 1904 | } | ||||
| 1905 | |||||
| 1906 | return [self cellSize]; | ||||
| 1907 | } | ||||
| 1908 | |||||
| 1909 | /**<p>TODO</p> | ||||
| 1910 | */ | ||||
| 1911 | - (NSRect) drawingRectForBounds: (NSRect)theRect | ||||
| 1912 | { | ||||
| 1913 | NSSize borderSize; | ||||
| 1914 | NSBorderType aType; | ||||
| 1915 | |||||
| 1916 | // Get border size | ||||
| 1917 | if (_cell.is_bordered) | ||||
| 1918 | aType = NSLineBorder; | ||||
| 1919 | else if (_cell.is_bezeled) | ||||
| 1920 | aType = NSBezelBorder; | ||||
| 1921 | else | ||||
| 1922 | aType = NSNoBorder; | ||||
| 1923 | |||||
| 1924 | borderSize = [[GSTheme theme] sizeForBorderType: aType]; | ||||
| 1925 | return NSInsetRect(theRect, borderSize.width, borderSize.height); | ||||
| 1926 | } | ||||
| 1927 | |||||
| 1928 | /**<p>The GNUstep implementation returns -drawingRectForBounds:</p> | ||||
| 1929 | */ | ||||
| 1930 | - (NSRect) imageRectForBounds: (NSRect)theRect | ||||
| 1931 | { | ||||
| 1932 | return [self drawingRectForBounds: theRect]; | ||||
| 1933 | } | ||||
| 1934 | |||||
| 1935 | /** <p>TODO</p> | ||||
| 1936 | */ | ||||
| 1937 | - (NSRect) titleRectForBounds: (NSRect)theRect | ||||
| 1938 | { | ||||
| 1939 | if (_cell.type == NSTextCellType) | ||||
| 1940 | { | ||||
| 1941 | NSRect frame = [self drawingRectForBounds: theRect]; | ||||
| 1942 | |||||
| 1943 | // Add spacing between border and inside | ||||
| 1944 | if (_cell.is_bordered || _cell.is_bezeled) | ||||
| 1945 | { | ||||
| 1946 | frame.origin.x += 3; | ||||
| 1947 | frame.size.width -= 6; | ||||
| 1948 | frame.origin.y += 1; | ||||
| 1949 | frame.size.height -= 2; | ||||
| 1950 | } | ||||
| 1951 | return frame; | ||||
| 1952 | } | ||||
| 1953 | else | ||||
| 1954 | { | ||||
| 1955 | return theRect; | ||||
| 1956 | } | ||||
| 1957 | } | ||||
| 1958 | |||||
| 1959 | - (void) setControlSize: (NSControlSize)controlSize | ||||
| 1960 | { | ||||
| 1961 | _cell.control_size = controlSize; | ||||
| 1962 | } | ||||
| 1963 | |||||
| 1964 | - (NSControlSize) controlSize | ||||
| 1965 | { | ||||
| 1966 | return _cell.control_size; | ||||
| 1967 | } | ||||
| 1968 | |||||
| 1969 | - (void) setControlTint: (NSControlTint)controlTint | ||||
| 1970 | { | ||||
| 1971 | _cell.control_tint = controlTint; | ||||
| 1972 | } | ||||
| 1973 | |||||
| 1974 | - (NSControlTint) controlTint | ||||
| 1975 | { | ||||
| 1976 | return _cell.control_tint; | ||||
| 1977 | } | ||||
| 1978 | |||||
| 1979 | /**<p>This method is used by subclasses to get the control view. | ||||
| 1980 | This method returns nil.</p> | ||||
| 1981 | */ | ||||
| 1982 | - (NSView*) controlView | ||||
| 1983 | { | ||||
| 1984 | return nil((id)((void*)0)); | ||||
| 1985 | } | ||||
| 1986 | |||||
| 1987 | /**<p>This method is used by subclasses to specify the control view.</p> | ||||
| 1988 | */ | ||||
| 1989 | - (void) setControlView: (NSView*)view | ||||
| 1990 | { | ||||
| 1991 | // Do nothing | ||||
| 1992 | } | ||||
| 1993 | |||||
| 1994 | /** <p>This drawing is minimal and with no background, | ||||
| 1995 | * to make it easier for subclass to customize drawing. </p> | ||||
| 1996 | */ | ||||
| 1997 | - (void) drawInteriorWithFrame: (NSRect)cellFrame inView: (NSView*)controlView | ||||
| 1998 | { | ||||
| 1999 | NSRect drawingRect = [self drawingRectForBounds: cellFrame]; | ||||
| 2000 | |||||
| 2001 | //FIXME: Check if this is also neccessary for images, | ||||
| 2002 | // Add spacing between border and inside | ||||
| 2003 | if (_cell.is_bordered || _cell.is_bezeled) | ||||
| 2004 | { | ||||
| 2005 | drawingRect.origin.x += 3; | ||||
| 2006 | drawingRect.size.width -= 6; | ||||
| 2007 | drawingRect.origin.y += 1; | ||||
| 2008 | drawingRect.size.height -= 2; | ||||
| 2009 | } | ||||
| 2010 | |||||
| 2011 | switch (_cell.type) | ||||
| 2012 | { | ||||
| 2013 | case NSTextCellType: | ||||
| 2014 | if (_cell.in_editing) | ||||
| 2015 | [self _drawEditorWithFrame: cellFrame inView: controlView]; | ||||
| 2016 | else | ||||
| 2017 | [self _drawAttributedText: [self _drawAttributedString] | ||||
| 2018 | inFrame: drawingRect]; | ||||
| 2019 | break; | ||||
| 2020 | |||||
| 2021 | case NSImageCellType: | ||||
| 2022 | if (_cell_image) | ||||
| 2023 | { | ||||
| 2024 | NSSize size; | ||||
| 2025 | NSPoint position; | ||||
| 2026 | |||||
| 2027 | size = [_cell_image size]; | ||||
| 2028 | position.x = MAX(NSMidX(drawingRect) - (size.width/2.),0.)(((NSMidX(drawingRect) - (size.width/2.))>(0.))?(NSMidX(drawingRect ) - (size.width/2.)):(0.)); | ||||
| 2029 | position.y = MAX(NSMidY(drawingRect) - (size.height/2.),0.)(((NSMidY(drawingRect) - (size.height/2.))>(0.))?(NSMidY(drawingRect ) - (size.height/2.)):(0.)); | ||||
| 2030 | |||||
| 2031 | [_cell_image drawInRect: NSMakeRect(position.x, position.y, size.width, size.height) | ||||
| 2032 | fromRect: NSZeroRect | ||||
| 2033 | operation: NSCompositeSourceOver | ||||
| 2034 | fraction: 1.0 | ||||
| 2035 | respectFlipped: YES((BOOL)1) | ||||
| 2036 | hints: nil((id)((void*)0))]; | ||||
| 2037 | } | ||||
| 2038 | break; | ||||
| 2039 | |||||
| 2040 | case NSNullCellType: | ||||
| 2041 | break; | ||||
| 2042 | } | ||||
| 2043 | |||||
| 2044 | // NB: We don't do any highlighting to make it easier for subclasses | ||||
| 2045 | // to reuse this code while doing their own custom highlighting and | ||||
| 2046 | // prettyfying | ||||
| 2047 | } | ||||
| 2048 | |||||
| 2049 | /**<p>Draws the cell in <var>controlView</var></p> | ||||
| 2050 | */ | ||||
| 2051 | - (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView | ||||
| 2052 | { | ||||
| 2053 | // do nothing if cell's frame rect is zero | ||||
| 2054 | if (NSIsEmptyRect(cellFrame)) | ||||
| 2055 | return; | ||||
| 2056 | |||||
| 2057 | // draw the border if needed | ||||
| 2058 | [self _drawBorderAndBackgroundWithFrame: cellFrame inView: controlView]; | ||||
| 2059 | // draw interior | ||||
| 2060 | [self drawInteriorWithFrame: cellFrame inView: controlView]; | ||||
| 2061 | // Draw first responder | ||||
| 2062 | [self _drawFocusRingWithFrame: cellFrame inView: controlView]; | ||||
| 2063 | } | ||||
| 2064 | |||||
| 2065 | /**<p>Sets whether the NSCell is highlighted.</p> | ||||
| 2066 | <p>See Also: -isHighlighted</p> | ||||
| 2067 | */ | ||||
| 2068 | - (void) setHighlighted: (BOOL) flag | ||||
| 2069 | { | ||||
| 2070 | _cell.is_highlighted = flag; | ||||
| 2071 | } | ||||
| 2072 | |||||
| 2073 | /**<p>Returns whether the cell is highlighted. By default NO</p> | ||||
| 2074 | <p>See Also: -setHighlighted:</p> | ||||
| 2075 | */ | ||||
| 2076 | - (BOOL) isHighlighted | ||||
| 2077 | { | ||||
| 2078 | return _cell.is_highlighted; | ||||
| 2079 | } | ||||
| 2080 | |||||
| 2081 | /** | ||||
| 2082 | *<p>TODO explain</p> | ||||
| 2083 | */ | ||||
| 2084 | |||||
| 2085 | - (void) highlight: (BOOL)lit | ||||
| 2086 | withFrame: (NSRect)cellFrame | ||||
| 2087 | inView: (NSView*)controlView | ||||
| 2088 | { | ||||
| 2089 | if (_cell.is_highlighted != lit) | ||||
| 2090 | { | ||||
| 2091 | _cell.is_highlighted = lit; | ||||
| 2092 | /* | ||||
| 2093 | * NB: This has a visible effect only if subclasses override | ||||
| 2094 | * drawWithFrame:inView: to draw something special when the | ||||
| 2095 | * cell is highlighted. | ||||
| 2096 | * NSCell simply draws border+text/image and makes no highlighting, | ||||
| 2097 | * for easier subclassing. | ||||
| 2098 | */ | ||||
| 2099 | if ([self isOpaque] == NO((BOOL)0)) | ||||
| 2100 | { | ||||
| 2101 | /* FIXME - This looks like potentially generating an | ||||
| 2102 | * infinite loop! The control asking the cell to draw | ||||
| 2103 | * itself in the rect, the cell asking the control to draw | ||||
| 2104 | * the rect, the control asking the cell to draw itself in | ||||
| 2105 | * the rect, the cell ... | ||||
| 2106 | * | ||||
| 2107 | * I think we should remove it. The control is responsible | ||||
| 2108 | * for using the cell to draw, not vice versa. | ||||
| 2109 | */ | ||||
| 2110 | [controlView displayRect: cellFrame]; | ||||
| 2111 | } | ||||
| 2112 | [self drawWithFrame: cellFrame inView: controlView]; | ||||
| 2113 | } | ||||
| 2114 | } | ||||
| 2115 | |||||
| 2116 | - (NSColor*) highlightColorWithFrame: (NSRect)cellFrame | ||||
| 2117 | inView: (NSView *)controlView | ||||
| 2118 | { | ||||
| 2119 | return [NSColor selectedControlColor]; | ||||
| 2120 | } | ||||
| 2121 | |||||
| 2122 | - (NSText*) setUpFieldEditorAttributes: (NSText*)textObject | ||||
| 2123 | { | ||||
| 2124 | NSDictionary *attr; | ||||
| 2125 | |||||
| 2126 | // Reset the string to have a well defined state. The real string gets set later on. | ||||
| 2127 | [textObject setString: @""]; | ||||
| 2128 | |||||
| 2129 | [textObject setTextColor: [self textColor]]; | ||||
| 2130 | if ([self isBezeled]) | ||||
| 2131 | { | ||||
| 2132 | [textObject setBackgroundColor: [NSColor textBackgroundColor]]; | ||||
| 2133 | [textObject setDrawsBackground: YES((BOOL)1)]; | ||||
| 2134 | } | ||||
| 2135 | else | ||||
| 2136 | { | ||||
| 2137 | [textObject setDrawsBackground: NO((BOOL)0)]; | ||||
| 2138 | } | ||||
| 2139 | [textObject setFont: [self font]]; | ||||
| 2140 | [textObject setAlignment: [self alignment]]; | ||||
| 2141 | // FIXME: Add base writing direction | ||||
| 2142 | |||||
| 2143 | [textObject setEditable: [self isEditable]]; | ||||
| 2144 | [textObject setSelectable: [self isSelectable]]; | ||||
| 2145 | [textObject setRichText: [self allowsEditingTextAttributes]]; | ||||
| 2146 | [textObject setImportsGraphics: [self importsGraphics]]; | ||||
| 2147 | [(NSTextView*)textObject setAllowsUndo: [self allowsUndo]]; | ||||
| 2148 | attr = [self _nonAutoreleasedTypingAttributes]; | ||||
| 2149 | [(NSTextView*)textObject setTypingAttributes: attr]; | ||||
| 2150 | RELEASE(attr)[(attr) release]; | ||||
| 2151 | |||||
| 2152 | return textObject; | ||||
| 2153 | } | ||||
| 2154 | |||||
| 2155 | - (void) _setupTextWithFrame: (NSRect)aRect | ||||
| 2156 | inView: (NSView*)controlView | ||||
| 2157 | editor: (NSText*)textObject | ||||
| 2158 | delegate: (id)anObject | ||||
| 2159 | range: (NSRange)selection | ||||
| 2160 | { | ||||
| 2161 | BOOL needsClipView; | ||||
| 2162 | BOOL wraps = [self wraps]; | ||||
| 2163 | NSTextContainer *ct; | ||||
| 2164 | NSSize maxSize; | ||||
| 2165 | NSRect titleRect = [self titleRectForBounds: aRect]; | ||||
| 2166 | |||||
| 2167 | /* We always add a clip view if the cell is editable so that the user | ||||
| 2168 | can edit the whole contents even if the cell's contents normally is | ||||
| 2169 | clipped. */ | ||||
| 2170 | needsClipView = [self isScrollable] || [self isEditable]; | ||||
| 2171 | if (needsClipView) | ||||
| 2172 | { | ||||
| 2173 | NSClipView *cv; | ||||
| 2174 | |||||
| 2175 | cv = [[NSClipView alloc] initWithFrame: titleRect]; | ||||
| 2176 | [cv setDocumentView: textObject]; | ||||
| 2177 | [controlView addSubview: cv]; | ||||
| 2178 | RELEASE(cv)[(cv) release]; | ||||
| 2179 | } | ||||
| 2180 | else | ||||
| 2181 | [controlView addSubview: textObject]; | ||||
| 2182 | |||||
| 2183 | /* Note: The order of statements matters here. We must set the text object's | ||||
| 2184 | horizontallyResizable and verticallyResizable attributes before setting | ||||
| 2185 | its frame size. Otherwise, the text object's width and/or height might | ||||
| 2186 | incorrectly be reduced to zero (since the text object has no contents at | ||||
| 2187 | this point) if the text object was resizable by its text container before. | ||||
| 2188 | Of course we could also have set the text object's minimum size to the | ||||
| 2189 | intended frame size, but then we must update the minimum size whenever | ||||
| 2190 | the field editor's frame is changed in -_drawEditorWithFrame:inView:. | ||||
| 2191 | Note that the minimum size is not relevant when a clip view is used. */ | ||||
| 2192 | [textObject setMinSize: NSZeroSize]; | ||||
| 2193 | [textObject setMaxSize: NSMakeSize(1e6, 1e6)]; | ||||
| 2194 | [textObject setHorizontallyResizable: needsClipView && !wraps]; | ||||
| 2195 | [textObject setVerticallyResizable: needsClipView]; | ||||
| 2196 | [textObject setFrame: titleRect]; | ||||
| 2197 | if (needsClipView) | ||||
| 2198 | [textObject setAutoresizingMask: NSViewWidthSizable + NSViewHeightSizable]; | ||||
| 2199 | else | ||||
| 2200 | [textObject setAutoresizingMask: NSViewNotSizable]; | ||||
| 2201 | |||||
| 2202 | /* Note: Order of statements matters again. The heightTracksTextView | ||||
| 2203 | and widthTracksTextView container attributes must be set after setting | ||||
| 2204 | the horizontallyResizable and verticallyResizable text view attributes | ||||
| 2205 | because NSTextView's setter methods include "safety code", which | ||||
| 2206 | always updates the container attributes along with the text view | ||||
| 2207 | attributes. | ||||
| 2208 | FIXME Fix NSTextView to only reset the text container attributes, but | ||||
| 2209 | never set them. However note that this may break some sloppily written | ||||
| 2210 | code which forgets to set the text container attributes. */ | ||||
| 2211 | /* See comments in NSStringDrawing.m about the choice of maximum size. */ | ||||
| 2212 | ct = [(NSTextView*)textObject textContainer]; | ||||
| 2213 | if (wraps) | ||||
| 2214 | maxSize = NSMakeSize(NSWidth(titleRect), 1e6); | ||||
| 2215 | else | ||||
| 2216 | maxSize = NSMakeSize(1e6, 1e6); | ||||
| 2217 | [ct setContainerSize: maxSize]; | ||||
| 2218 | [ct setWidthTracksTextView: wraps]; | ||||
| 2219 | [ct setHeightTracksTextView: NO((BOOL)0)]; | ||||
| 2220 | |||||
| 2221 | [self _updateFieldEditor: textObject]; | ||||
| 2222 | |||||
| 2223 | [textObject setSelectedRange: selection]; | ||||
| 2224 | [textObject scrollRangeToVisible: selection]; | ||||
| 2225 | |||||
| 2226 | [textObject setDelegate: anObject]; | ||||
| 2227 | [[controlView window] makeFirstResponder: textObject]; | ||||
| 2228 | _cell.in_editing = YES((BOOL)1); | ||||
| 2229 | } | ||||
| 2230 | |||||
| 2231 | /**<p>Ends any text editing. This method sets the text object's delegate | ||||
| 2232 | to nil, and remove the NSClipView and the text object used for editing</p> | ||||
| 2233 | <p>See Also: -editWithFrame:inView:editor:delegate:event:</p> | ||||
| 2234 | */ | ||||
| 2235 | - (void) endEditing: (NSText*)textObject | ||||
| 2236 | { | ||||
| 2237 | NSClipView *clipView; | ||||
| 2238 | |||||
| 2239 | _cell.in_editing = NO((BOOL)0); | ||||
| 2240 | [textObject setString: @""]; | ||||
| 2241 | [textObject setDelegate: nil((id)((void*)0))]; | ||||
| 2242 | |||||
| 2243 | clipView = (NSClipView*)[textObject superview]; | ||||
| 2244 | if ([clipView isKindOfClass: [NSClipView class]]) | ||||
| 2245 | { | ||||
| 2246 | [clipView setDocumentView: nil((id)((void*)0))]; | ||||
| 2247 | [clipView removeFromSuperview]; | ||||
| 2248 | } | ||||
| 2249 | else | ||||
| 2250 | [textObject removeFromSuperview]; | ||||
| 2251 | } | ||||
| 2252 | |||||
| 2253 | /* | ||||
| 2254 | * Editing Text | ||||
| 2255 | */ | ||||
| 2256 | /** <p>.This method does nothing if a the <var>controlView</var> is nil, | ||||
| 2257 | if text object does not exist or if the cell's type is not <ref type="type" | ||||
| 2258 | id="NSCellType">NSTextCellType</ref></p> | ||||
| 2259 | */ | ||||
| 2260 | - (void) editWithFrame: (NSRect)aRect | ||||
| 2261 | inView: (NSView*)controlView | ||||
| 2262 | editor: (NSText*)textObject | ||||
| 2263 | delegate: (id)anObject | ||||
| 2264 | event: (NSEvent*)theEvent | ||||
| 2265 | { | ||||
| 2266 | if (!controlView || !textObject || (_cell.type != NSTextCellType)) | ||||
| 2267 | return; | ||||
| 2268 | |||||
| 2269 | [self _setupTextWithFrame: aRect | ||||
| 2270 | inView: controlView | ||||
| 2271 | editor: textObject | ||||
| 2272 | delegate: anObject | ||||
| 2273 | range: NSMakeRange(0, 0)]; | ||||
| 2274 | |||||
| 2275 | if ([theEvent type] == NSLeftMouseDown) | ||||
| 2276 | { | ||||
| 2277 | [textObject mouseDown: theEvent]; | ||||
| 2278 | } | ||||
| 2279 | } | ||||
| 2280 | |||||
| 2281 | /** <p> This method does nothing if the <var>controlView</var> is nil, | ||||
| 2282 | if text object does not exist or if the cell's type is not <ref type="type" | ||||
| 2283 | id="NSCellType">NSTextCellType</ref> </p> | ||||
| 2284 | */ | ||||
| 2285 | - (void) selectWithFrame: (NSRect)aRect | ||||
| 2286 | inView: (NSView*)controlView | ||||
| 2287 | editor: (NSText*)textObject | ||||
| 2288 | delegate: (id)anObject | ||||
| 2289 | start: (int)selStart | ||||
| 2290 | length: (int)selLength | ||||
| 2291 | { | ||||
| 2292 | if (!controlView || !textObject || (_cell.type != NSTextCellType)) | ||||
| 2293 | return; | ||||
| 2294 | |||||
| 2295 | [self _setupTextWithFrame: aRect | ||||
| 2296 | inView: controlView | ||||
| 2297 | editor: textObject | ||||
| 2298 | delegate: anObject | ||||
| 2299 | range: NSMakeRange(selStart, selLength)]; | ||||
| 2300 | } | ||||
| 2301 | |||||
| 2302 | - (BOOL) sendsActionOnEndEditing | ||||
| 2303 | { | ||||
| 2304 | return _cell.sends_action_on_end_editing; | ||||
| 2305 | } | ||||
| 2306 | |||||
| 2307 | - (void) setSendsActionOnEndEditing: (BOOL)flag | ||||
| 2308 | { | ||||
| 2309 | _cell.sends_action_on_end_editing = flag; | ||||
| 2310 | } | ||||
| 2311 | |||||
| 2312 | - (BOOL) allowsUndo | ||||
| 2313 | { | ||||
| 2314 | return _cell.allows_undo; | ||||
| 2315 | } | ||||
| 2316 | |||||
| 2317 | - (void) setAllowsUndo: (BOOL)flag | ||||
| 2318 | { | ||||
| 2319 | _cell.allows_undo = flag; | ||||
| 2320 | } | ||||
| 2321 | |||||
| 2322 | /* | ||||
| 2323 | * Copying | ||||
| 2324 | */ | ||||
| 2325 | - (id) copyWithZone: (NSZone*)zone | ||||
| 2326 | { | ||||
| 2327 | NSCell *c = (NSCell*)NSCopyObject (self, 0, zone); | ||||
| 2328 | |||||
| 2329 | /* Hmmm. */ | ||||
| 2330 | c->_contents = [_contents copyWithZone: zone]; | ||||
| 2331 | /* Because of performance issues (and because so the doc says) only | ||||
| 2332 | pointers to the objects are copied. We need to RETAIN them all | ||||
| 2333 | though. */ | ||||
| 2334 | _font = TEST_RETAIN (_font)({id __object = (_font); (__object != ((id)((void*)0))) ? [__object retain] : ((id)((void*)0)); }); | ||||
| 2335 | _object_value = TEST_RETAIN (_object_value)({id __object = (_object_value); (__object != ((id)((void*)0) )) ? [__object retain] : ((id)((void*)0)); }); | ||||
| 2336 | _menu = TEST_RETAIN (_menu)({id __object = (_menu); (__object != ((id)((void*)0))) ? [__object retain] : ((id)((void*)0)); }); | ||||
| 2337 | _cell_image = TEST_RETAIN (_cell_image)({id __object = (_cell_image); (__object != ((id)((void*)0))) ? [__object retain] : ((id)((void*)0)); }); | ||||
| 2338 | _formatter = TEST_RETAIN (_formatter)({id __object = (_formatter); (__object != ((id)((void*)0))) ? [__object retain] : ((id)((void*)0)); }); | ||||
| 2339 | _formatter = TEST_RETAIN (_represented_object)({id __object = (_represented_object); (__object != ((id)((void *)0))) ? [__object retain] : ((id)((void*)0)); }); | ||||
| 2340 | |||||
| 2341 | return c; | ||||
| 2342 | } | ||||
| 2343 | |||||
| 2344 | /* | ||||
| 2345 | * NSCoding protocol | ||||
| 2346 | */ | ||||
| 2347 | - (void) encodeWithCoder: (NSCoder*)aCoder | ||||
| 2348 | { | ||||
| 2349 | if ([aCoder allowsKeyedCoding]) | ||||
| 2350 | { | ||||
| 2351 | unsigned long cFlags = 0; | ||||
| 2352 | unsigned int cFlags2 = 0; | ||||
| 2353 | id contents; | ||||
| 2354 | |||||
| 2355 | // encode contents | ||||
| 2356 | if (_cell.type == NSTextCellType) | ||||
| 2357 | { | ||||
| 2358 | contents = _contents; | ||||
| 2359 | } | ||||
| 2360 | else if (_cell.type == NSImageCellType) | ||||
| 2361 | { | ||||
| 2362 | contents = _cell_image; | ||||
| 2363 | } | ||||
| 2364 | else | ||||
| 2365 | { | ||||
| 2366 | contents = [self objectValue]; | ||||
| 2367 | } | ||||
| 2368 | [aCoder encodeObject: contents forKey: @"NSContents"]; | ||||
| 2369 | |||||
| 2370 | // flags | ||||
| 2371 | cFlags |= [self focusRingType]; | ||||
| 2372 | cFlags |= [self showsFirstResponder] ? 0x4 : 0; | ||||
| 2373 | cFlags |= (_action_mask & NSLeftMouseUpMask) ? 0 : 0x20; | ||||
| 2374 | cFlags |= [self wraps] ? 0x40 : 0; | ||||
| 2375 | cFlags |= (_action_mask & NSLeftMouseDraggedMask) ? 0x100 : 0; | ||||
| 2376 | cFlags |= (_action_mask & NSLeftMouseDownMask) ? 0x40000 : 0; | ||||
| 2377 | cFlags |= [self isContinuous] ? 0x80000 : 0; | ||||
| 2378 | cFlags |= [self isScrollable] ? 0x100000 : 0; | ||||
| 2379 | cFlags |= [self isSelectable] ? 0x200000 : 0; | ||||
| 2380 | cFlags |= [self isBezeled] ? 0x400000 : 0; | ||||
| 2381 | cFlags |= [self isBordered] ? 0x800000 : 0; | ||||
| 2382 | cFlags |= ([self type] << 26); | ||||
| 2383 | cFlags |= [self isEditable] ? 0x10000000 : 0; | ||||
| 2384 | cFlags |= ([self isEnabled] == NO((BOOL)0)) ? 0x20000000 : 0; | ||||
| 2385 | cFlags |= [self isHighlighted] ? 0x40000000 : 0; | ||||
| 2386 | cFlags |= ([self state] == NSOnState) ? 0x80000000 : 0; | ||||
| 2387 | [aCoder encodeInt: cFlags forKey: @"NSCellFlags"]; | ||||
| 2388 | |||||
| 2389 | // flags part 2 | ||||
| 2390 | cFlags2 |= ([self controlTint] << 5); | ||||
| 2391 | cFlags2 |= ([self lineBreakMode] << 9); | ||||
| 2392 | cFlags2 |= ([self controlSize] << 17); | ||||
| 2393 | cFlags2 |= [self sendsActionOnEndEditing] ? 0x400000 : 0; | ||||
| 2394 | cFlags2 |= [self allowsMixedState] ? 0x1000000 : 0; | ||||
| 2395 | cFlags2 |= [self refusesFirstResponder] ? 0x2000000 : 0; | ||||
| 2396 | cFlags2 |= ([self alignment] << 26); | ||||
| 2397 | cFlags2 |= [self importsGraphics] ? 0x20000000 : 0; | ||||
| 2398 | cFlags2 |= [self allowsEditingTextAttributes] ? 0x40000000 : 0; | ||||
| 2399 | [aCoder encodeInt: cFlags2 forKey: @"NSCellFlags2"]; | ||||
| 2400 | |||||
| 2401 | if (_cell.type == NSTextCellType) | ||||
| 2402 | { | ||||
| 2403 | // font and formatter. | ||||
| 2404 | if ([self font]) | ||||
| 2405 | { | ||||
| 2406 | [aCoder encodeObject: [self font] forKey: @"NSSupport"]; | ||||
| 2407 | } | ||||
| 2408 | |||||
| 2409 | if ([self formatter]) | ||||
| 2410 | { | ||||
| 2411 | [aCoder encodeObject: [self formatter] forKey: @"NSFormatter"]; | ||||
| 2412 | } | ||||
| 2413 | } | ||||
| 2414 | else if ([self image]) | ||||
| 2415 | { | ||||
| 2416 | [aCoder encodeObject: [self image] forKey: @"NSSupport"]; | ||||
| 2417 | } | ||||
| 2418 | } | ||||
| 2419 | else | ||||
| 2420 | { | ||||
| 2421 | BOOL flag; | ||||
| 2422 | unsigned int tmp_int; | ||||
| 2423 | |||||
| 2424 | [aCoder encodeObject: _contents]; | ||||
| 2425 | [aCoder encodeObject: _cell_image]; | ||||
| 2426 | [aCoder encodeObject: _font]; | ||||
| 2427 | [aCoder encodeObject: _object_value]; | ||||
| 2428 | flag = _cell.contents_is_attributed_string; | ||||
| 2429 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2430 | flag = _cell.is_highlighted; | ||||
| 2431 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2432 | flag = _cell.is_disabled; | ||||
| 2433 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2434 | flag = _cell.is_editable; | ||||
| 2435 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2436 | flag = _cell.is_rich_text; | ||||
| 2437 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2438 | flag = _cell.imports_graphics; | ||||
| 2439 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2440 | flag = _cell.shows_first_responder; | ||||
| 2441 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2442 | flag = _cell.refuses_first_responder; | ||||
| 2443 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2444 | flag = _cell.sends_action_on_end_editing; | ||||
| 2445 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2446 | flag = _cell.is_bordered; | ||||
| 2447 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2448 | flag = _cell.is_bezeled; | ||||
| 2449 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2450 | flag = _cell.is_scrollable; | ||||
| 2451 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2452 | flag = _cell.is_selectable; | ||||
| 2453 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2454 | // This used to be is_continuous, which has been replaced. | ||||
| 2455 | /* Ayers 20.03.2003: But we must continue to encode it for backward | ||||
| 2456 | compatibility or current releases will have undefined behavior when | ||||
| 2457 | decoding archives (i.e. .gorm files) encoded by this version. */ | ||||
| 2458 | flag = [self isContinuous]; | ||||
| 2459 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2460 | flag = _cell.allows_mixed_state; | ||||
| 2461 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2462 | flag = [self wraps]; | ||||
| 2463 | [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2464 | tmp_int = _cell.text_align; | ||||
| 2465 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2466 | tmp_int = _cell.type; | ||||
| 2467 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2468 | tmp_int = _cell.image_position; | ||||
| 2469 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2470 | tmp_int = _cell.entry_type; | ||||
| 2471 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2472 | // FIXME: State may be -1, why do we encode it as unsigned? | ||||
| 2473 | tmp_int = _cell.state; | ||||
| 2474 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2475 | tmp_int = _cell.mnemonic_location; | ||||
| 2476 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2477 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &_mouse_down_flags]; | ||||
| 2478 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &_action_mask]; | ||||
| 2479 | [aCoder encodeValueOfObjCType: @encode(id) at: &_formatter]; | ||||
| 2480 | [aCoder encodeValueOfObjCType: @encode(id) at: &_menu]; | ||||
| 2481 | [aCoder encodeValueOfObjCType: @encode(id) at: &_represented_object]; | ||||
| 2482 | |||||
| 2483 | tmp_int = _cell.allows_undo; | ||||
| 2484 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2485 | tmp_int = _cell.line_break_mode; | ||||
| 2486 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2487 | tmp_int = _cell.control_tint; | ||||
| 2488 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2489 | tmp_int = _cell.control_size; | ||||
| 2490 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2491 | tmp_int = _cell.focus_ring_type; | ||||
| 2492 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2493 | tmp_int = _cell.base_writing_direction; | ||||
| 2494 | [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2495 | } | ||||
| 2496 | } | ||||
| 2497 | |||||
| 2498 | - (id) initWithCoder: (NSCoder*)aDecoder | ||||
| 2499 | { | ||||
| 2500 | if ([aDecoder allowsKeyedCoding]) | ||||
| 2501 | { | ||||
| 2502 | id contents = [aDecoder decodeObjectForKey: @"NSContents"]; | ||||
| 2503 | |||||
| 2504 | // initialize based on content... | ||||
| 2505 | if ([contents isKindOfClass: [NSString class]]) | ||||
| 2506 | { | ||||
| 2507 | self = [self initTextCell: contents]; | ||||
| 2508 | } | ||||
| 2509 | else if ([contents isKindOfClass: [NSImage class]]) | ||||
| 2510 | { | ||||
| 2511 | self = [self initImageCell: contents]; | ||||
| 2512 | } | ||||
| 2513 | else | ||||
| 2514 | { | ||||
| 2515 | self = [self init]; | ||||
| 2516 | [self setObjectValue: contents]; | ||||
| 2517 | } | ||||
| 2518 | |||||
| 2519 | if ([aDecoder containsValueForKey: @"NSCellFlags"]) | ||||
| 2520 | { | ||||
| 2521 | unsigned long cFlags; | ||||
| 2522 | unsigned long mask = 0; | ||||
| 2523 | cFlags = [aDecoder decodeIntForKey: @"NSCellFlags"]; | ||||
| 2524 | |||||
| 2525 | [self setFocusRingType: (cFlags & 0x3)]; | ||||
| 2526 | [self setShowsFirstResponder: ((cFlags & 0x4) == 0x4)]; | ||||
| 2527 | // This bit flag is the other way around! | ||||
| 2528 | if ((cFlags & 0x20) != 0x20) | ||||
| 2529 | mask |= NSLeftMouseUpMask; | ||||
| 2530 | // This bit flag is the other way around! | ||||
| 2531 | [self setWraps: ((cFlags & 0x40) != 0x40)]; | ||||
| 2532 | if ((cFlags & 0x100) == 0x100) | ||||
| 2533 | mask |= NSLeftMouseDraggedMask; | ||||
| 2534 | if ((cFlags & 0x40000) == 0x40000) | ||||
| 2535 | mask |= NSLeftMouseDownMask; | ||||
| 2536 | if ((cFlags & 0x80000) == 0x80000) | ||||
| 2537 | mask |= NSPeriodicMask; | ||||
| 2538 | [self sendActionOn: mask]; | ||||
| 2539 | [self setScrollable: ((cFlags & 0x100000) == 0x100000)]; | ||||
| 2540 | [self setSelectable: ((cFlags & 0x200000) == 0x200000)]; | ||||
| 2541 | [self setBezeled: ((cFlags & 0x400000) == 0x400000)]; | ||||
| 2542 | [self setBordered: ((cFlags & 0x800000) == 0x800000)]; | ||||
| 2543 | [self setType: ((cFlags & 0xC000000) >> 26)]; | ||||
| 2544 | [self setEditable: ((cFlags & 0x10000000) == 0x10000000)]; | ||||
| 2545 | // This bit flag is the other way around! | ||||
| 2546 | [self setEnabled: ((cFlags & 0x20000000) != 0x20000000)]; | ||||
| 2547 | [self setHighlighted: ((cFlags & 0x40000000) == 0x40000000)]; | ||||
| 2548 | [self setState: ((cFlags & 0x80000000) == 0x80000000) ? NSOnState : NSOffState]; | ||||
| 2549 | } | ||||
| 2550 | if ([aDecoder containsValueForKey: @"NSCellFlags2"]) | ||||
| 2551 | { | ||||
| 2552 | int cFlags2; | ||||
| 2553 | |||||
| 2554 | cFlags2 = [aDecoder decodeIntForKey: @"NSCellFlags2"]; | ||||
| 2555 | [self setControlTint: ((cFlags2 & 0xE0) >> 5)]; | ||||
| 2556 | [self setLineBreakMode: ((cFlags2 & 0xE00) >> 9)]; | ||||
| 2557 | [self setControlSize: ((cFlags2 & 0xE0000) >> 17)]; | ||||
| 2558 | [self setSendsActionOnEndEditing: ((cFlags2 & 0x400000) == 0x400000)]; | ||||
| 2559 | [self setAllowsMixedState: ((cFlags2 & 0x1000000) == 0x1000000)]; | ||||
| 2560 | [self setRefusesFirstResponder: ((cFlags2 & 0x2000000) == 0x2000000)]; | ||||
| 2561 | [self setAlignment: ((cFlags2 & 0x1C000000) >> 26)]; | ||||
| 2562 | [self setImportsGraphics: ((cFlags2 & 0x20000000) == 0x20000000)]; | ||||
| 2563 | [self setAllowsEditingTextAttributes: ((cFlags2 & 0x40000000) == 0x40000000)]; | ||||
| 2564 | } | ||||
| 2565 | if ([aDecoder containsValueForKey: @"NSSupport"]) | ||||
| 2566 | { | ||||
| 2567 | id support = [aDecoder decodeObjectForKey: @"NSSupport"]; | ||||
| 2568 | |||||
| 2569 | if ([support isKindOfClass: [NSFont class]]) | ||||
| 2570 | { | ||||
| 2571 | [self setFont: support]; | ||||
| 2572 | } | ||||
| 2573 | else if ([support isKindOfClass: [NSImage class]]) | ||||
| 2574 | { | ||||
| 2575 | [self setImage: support]; | ||||
| 2576 | } | ||||
| 2577 | } | ||||
| 2578 | if ([aDecoder containsValueForKey: @"NSFormatter"]) | ||||
| 2579 | { | ||||
| 2580 | NSFormatter *formatter = [aDecoder decodeObjectForKey: @"NSFormatter"]; | ||||
| 2581 | |||||
| 2582 | [self setFormatter: formatter]; | ||||
| 2583 | } | ||||
| 2584 | } | ||||
| 2585 | else | ||||
| 2586 | { | ||||
| 2587 | BOOL flag, wraps; | ||||
| 2588 | unsigned int tmp_int; | ||||
| 2589 | id formatter, menu; | ||||
| 2590 | int version = [aDecoder versionForClassName: @"NSCell"]; | ||||
| 2591 | |||||
| 2592 | [aDecoder decodeValueOfObjCType: @encode(id) at: &_contents]; | ||||
| 2593 | [aDecoder decodeValueOfObjCType: @encode(id) at: &_cell_image]; | ||||
| 2594 | [aDecoder decodeValueOfObjCType: @encode(id) at: &_font]; | ||||
| 2595 | [aDecoder decodeValueOfObjCType: @encode(id) at: &_object_value]; | ||||
| 2596 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2597 | _cell.contents_is_attributed_string = flag; | ||||
| 2598 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2599 | _cell.is_highlighted = flag; | ||||
| 2600 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2601 | _cell.is_disabled = flag; | ||||
| 2602 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2603 | _cell.is_editable = flag; | ||||
| 2604 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2605 | _cell.is_rich_text = flag; | ||||
| 2606 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2607 | _cell.imports_graphics = flag; | ||||
| 2608 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2609 | _cell.shows_first_responder = flag; | ||||
| 2610 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2611 | _cell.refuses_first_responder = flag; | ||||
| 2612 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2613 | _cell.sends_action_on_end_editing = flag; | ||||
| 2614 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2615 | _cell.is_bordered = flag; | ||||
| 2616 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2617 | _cell.is_bezeled = flag; | ||||
| 2618 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2619 | _cell.is_scrollable = flag; | ||||
| 2620 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2621 | _cell.is_selectable = flag; | ||||
| 2622 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2623 | // This used to be is_continuous, which has been replaced. | ||||
| 2624 | //_cell.is_continuous = flag; | ||||
| 2625 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2626 | _cell.allows_mixed_state = flag; | ||||
| 2627 | [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag]; | ||||
| 2628 | /* The wraps attribute has been superseded by lineBreakMode. However, | ||||
| 2629 | we may need it to set lineBreakMode when reading old archives. */ | ||||
| 2630 | wraps = flag; | ||||
| 2631 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2632 | _cell.text_align = tmp_int; | ||||
| 2633 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2634 | _cell.type = tmp_int; | ||||
| 2635 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2636 | _cell.image_position = tmp_int; | ||||
| 2637 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2638 | _cell.entry_type = tmp_int; | ||||
| 2639 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2640 | _cell.state = tmp_int; | ||||
| 2641 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2642 | _cell.mnemonic_location = tmp_int; | ||||
| 2643 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) | ||||
| 2644 | at: &_mouse_down_flags]; | ||||
| 2645 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &_action_mask]; | ||||
| 2646 | if (version < 3) | ||||
| 2647 | { | ||||
| 2648 | unsigned int mask = 0; | ||||
| 2649 | |||||
| 2650 | // Convert old GNUstep mask value to Cocoa values | ||||
| 2651 | if ((_action_mask & 0x1) == 0x1) | ||||
| 2652 | { | ||||
| 2653 | mask |= NSLeftMouseDownMask; | ||||
| 2654 | } | ||||
| 2655 | if ((_action_mask & 0x2) == 0x2) | ||||
| 2656 | { | ||||
| 2657 | mask |= NSLeftMouseUpMask; | ||||
| 2658 | } | ||||
| 2659 | if ((_action_mask & 0x4) == 0x4) | ||||
| 2660 | { | ||||
| 2661 | mask |= NSOtherMouseDownMask; | ||||
| 2662 | } | ||||
| 2663 | if ((_action_mask & 0x8) == 0x8) | ||||
| 2664 | { | ||||
| 2665 | mask |= NSOtherMouseUpMask; | ||||
| 2666 | } | ||||
| 2667 | if ((_action_mask & 0x10) == 0x10) | ||||
| 2668 | { | ||||
| 2669 | mask |= NSRightMouseDownMask; | ||||
| 2670 | } | ||||
| 2671 | if ((_action_mask & 0x20) == 0x20) | ||||
| 2672 | { | ||||
| 2673 | mask |= NSRightMouseUpMask; | ||||
| 2674 | } | ||||
| 2675 | if ((_action_mask & 0x40) == 0x40) | ||||
| 2676 | { | ||||
| 2677 | mask |= NSMouseMovedMask; | ||||
| 2678 | } | ||||
| 2679 | if ((_action_mask & 0x80) == 0x80) | ||||
| 2680 | { | ||||
| 2681 | mask |= NSLeftMouseDraggedMask; | ||||
| 2682 | } | ||||
| 2683 | if ((_action_mask & 0x100) == 0x100) | ||||
| 2684 | { | ||||
| 2685 | mask |= NSOtherMouseDraggedMask; | ||||
| 2686 | } | ||||
| 2687 | if ((_action_mask & 0x200) == 0x200) | ||||
| 2688 | { | ||||
| 2689 | mask |= NSRightMouseDraggedMask; | ||||
| 2690 | } | ||||
| 2691 | if ((_action_mask & 0x400) == 0x400) | ||||
| 2692 | { | ||||
| 2693 | mask |= NSMouseEnteredMask; | ||||
| 2694 | } | ||||
| 2695 | if ((_action_mask & 0x800) == 0x800) | ||||
| 2696 | { | ||||
| 2697 | mask |= NSMouseExitedMask; | ||||
| 2698 | } | ||||
| 2699 | if ((_action_mask & 0x1000) == 0x1000) | ||||
| 2700 | { | ||||
| 2701 | mask |= NSKeyDownMask; | ||||
| 2702 | } | ||||
| 2703 | if ((_action_mask & 0x2000) == 0x2000) | ||||
| 2704 | { | ||||
| 2705 | mask |= NSKeyUpMask; | ||||
| 2706 | } | ||||
| 2707 | if ((_action_mask & 0x4000) == 0x4000) | ||||
| 2708 | { | ||||
| 2709 | mask |= NSFlagsChangedMask; | ||||
| 2710 | } | ||||
| 2711 | if ((_action_mask & 0x8000) == 0x8000) | ||||
| 2712 | { | ||||
| 2713 | mask |= NSAppKitDefinedMask; | ||||
| 2714 | } | ||||
| 2715 | if ((_action_mask & 0x10000) == 0x10000) | ||||
| 2716 | { | ||||
| 2717 | mask |= NSSystemDefinedMask; | ||||
| 2718 | } | ||||
| 2719 | if ((_action_mask & 0x20000) == 0x20000) | ||||
| 2720 | { | ||||
| 2721 | mask |= NSApplicationDefinedMask; | ||||
| 2722 | } | ||||
| 2723 | if ((_action_mask & 0x40000) == 0x40000) | ||||
| 2724 | { | ||||
| 2725 | mask |= NSPeriodicMask; | ||||
| 2726 | } | ||||
| 2727 | if ((_action_mask & 0x80000) == 0x80000) | ||||
| 2728 | { | ||||
| 2729 | mask |= NSCursorUpdateMask; | ||||
| 2730 | } | ||||
| 2731 | if ((_action_mask & 0x100000) == 0x100000) | ||||
| 2732 | { | ||||
| 2733 | mask |= NSScrollWheelMask; | ||||
| 2734 | } | ||||
| 2735 | _action_mask = mask; | ||||
| 2736 | } | ||||
| 2737 | _action_mask |= NSLeftMouseUpMask; | ||||
| 2738 | [aDecoder decodeValueOfObjCType: @encode(id) at: &formatter]; | ||||
| 2739 | [self setFormatter: formatter]; | ||||
| 2740 | [aDecoder decodeValueOfObjCType: @encode(id) at: &menu]; | ||||
| 2741 | [self setMenu: menu]; | ||||
| 2742 | [aDecoder decodeValueOfObjCType: @encode(id) at: &_represented_object]; | ||||
| 2743 | |||||
| 2744 | if (_formatter != nil((id)((void*)0))) | ||||
| 2745 | { | ||||
| 2746 | NSString *contents; | ||||
| 2747 | |||||
| 2748 | contents = [_formatter stringForObjectValue: _object_value]; | ||||
| 2749 | if (contents != nil((id)((void*)0))) | ||||
| 2750 | { | ||||
| 2751 | _cell.has_valid_object_value = YES((BOOL)1); | ||||
| 2752 | ASSIGN (_contents, contents)({ id __object = _contents; _contents = [(contents) retain]; [ __object release]; }); | ||||
| 2753 | _cell.contents_is_attributed_string = NO((BOOL)0); | ||||
| 2754 | } | ||||
| 2755 | } | ||||
| 2756 | |||||
| 2757 | if (version >= 2) | ||||
| 2758 | { | ||||
| 2759 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2760 | _cell.allows_undo = tmp_int; | ||||
| 2761 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2762 | _cell.line_break_mode = tmp_int; | ||||
| 2763 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2764 | _cell.control_tint = tmp_int; | ||||
| 2765 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2766 | _cell.control_size = tmp_int; | ||||
| 2767 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2768 | _cell.focus_ring_type = tmp_int; | ||||
| 2769 | [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int]; | ||||
| 2770 | _cell.base_writing_direction = tmp_int; | ||||
| 2771 | } | ||||
| 2772 | else | ||||
| 2773 | { | ||||
| 2774 | /* Backward compatibility: Derive lineBreakMode from the superseded | ||||
| 2775 | wraps attribute. */ | ||||
| 2776 | [self setWraps: wraps]; | ||||
| 2777 | } | ||||
| 2778 | } | ||||
| 2779 | return self; | ||||
| 2780 | } | ||||
| 2781 | @end | ||||
| 2782 | |||||
| 2783 | @implementation NSCell (PrivateMethods) | ||||
| 2784 | |||||
| 2785 | - (NSColor*) textColor | ||||
| 2786 | { | ||||
| 2787 | if (_cell.is_disabled) | ||||
| 2788 | return dtxtCol; | ||||
| 2789 | else | ||||
| 2790 | return txtCol; | ||||
| 2791 | } | ||||
| 2792 | |||||
| 2793 | /* This method is an exception and returns a non-autoreleased | ||||
| 2794 | dictionary, so that calling methods can deallocate it immediately | ||||
| 2795 | using release. Otherwise if many cells are drawn/their size | ||||
| 2796 | computed, we pile up hundreds or thousands of these objects before they | ||||
| 2797 | are deallocated at the end of the run loop. */ | ||||
| 2798 | - (NSDictionary*) _nonAutoreleasedTypingAttributes | ||||
| 2799 | { | ||||
| 2800 | NSDictionary *attr; | ||||
| 2801 | NSColor *color; | ||||
| 2802 | NSMutableParagraphStyle *paragraphStyle; | ||||
| 2803 | |||||
| 2804 | color = [self textColor]; | ||||
| 2805 | /* Note: There are only a few possible paragraph styles for cells. | ||||
| 2806 | TODO: Cache them and reuse them for the whole app lifetime. */ | ||||
| 2807 | paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; | ||||
| 2808 | [paragraphStyle setLineBreakMode: [self lineBreakMode]]; | ||||
| 2809 | [paragraphStyle setBaseWritingDirection: [self baseWritingDirection]]; | ||||
| 2810 | [paragraphStyle setAlignment: [self alignment]]; | ||||
| 2811 | |||||
| 2812 | attr = [[NSDictionary alloc] initWithObjectsAndKeys: | ||||
| 2813 | _font, NSFontAttributeName, | ||||
| 2814 | color, NSForegroundColorAttributeName, | ||||
| 2815 | paragraphStyle, NSParagraphStyleAttributeName, | ||||
| 2816 | nil((id)((void*)0))]; | ||||
| 2817 | RELEASE (paragraphStyle)[(paragraphStyle) release]; | ||||
| 2818 | return attr; | ||||
| 2819 | } | ||||
| 2820 | |||||
| 2821 | - (NSSize) _sizeText: (NSString*)title | ||||
| 2822 | { | ||||
| 2823 | NSSize size; | ||||
| 2824 | NSDictionary *dict; | ||||
| 2825 | |||||
| 2826 | if (title == nil((id)((void*)0))) | ||||
| |||||
| |||||
| 2827 | { | ||||
| 2828 | return NSMakeSize (0,0); | ||||
| 2829 | } | ||||
| 2830 | |||||
| 2831 | dict = [self _nonAutoreleasedTypingAttributes]; | ||||
| |||||
| 2832 | size = [title sizeWithAttributes: dict]; | ||||
| 2833 | RELEASE (dict)[(dict) release]; | ||||
| |||||
| 2834 | return size; | ||||
| 2835 | } | ||||
| 2836 | |||||
| 2837 | /** | ||||
| 2838 | * Private internal method, returns an attributed string to display. | ||||
| 2839 | */ | ||||
| 2840 | - (NSAttributedString*) _drawAttributedString | ||||
| 2841 | { | ||||
| 2842 | if (!_cell.is_disabled) | ||||
| 2843 | { | ||||
| 2844 | return [self attributedStringValue]; | ||||
| 2845 | } | ||||
| 2846 | else | ||||
| 2847 | { | ||||
| 2848 | NSAttributedString *attrStr = [self attributedStringValue]; | ||||
| 2849 | NSDictionary *attribs; | ||||
| 2850 | NSMutableDictionary *newAttribs; | ||||
| 2851 | |||||
| 2852 | attribs = [attrStr attributesAtIndex: 0 | ||||
| 2853 | effectiveRange: NULL((void *)0)]; | ||||
| 2854 | newAttribs = [NSMutableDictionary dictionaryWithDictionary: attribs]; | ||||
| 2855 | [newAttribs setObject: [NSColor disabledControlTextColor] | ||||
| 2856 | forKey: NSForegroundColorAttributeName]; | ||||
| 2857 | |||||
| 2858 | return AUTORELEASE([[NSAttributedString alloc][([[NSAttributedString alloc] initWithString: [attrStr string ] attributes: newAttribs]) autorelease] | ||||
| 2859 | initWithString: [attrStr string][([[NSAttributedString alloc] initWithString: [attrStr string ] attributes: newAttribs]) autorelease] | ||||
| 2860 | attributes: newAttribs])[([[NSAttributedString alloc] initWithString: [attrStr string ] attributes: newAttribs]) autorelease]; | ||||
| 2861 | } | ||||
| 2862 | } | ||||
| 2863 | |||||
| 2864 | /** | ||||
| 2865 | * Private internal method to display an attributed string. | ||||
| 2866 | */ | ||||
| 2867 | - (void) _drawAttributedText: (NSAttributedString*)aString | ||||
| 2868 | inFrame: (NSRect)aRect | ||||
| 2869 | { | ||||
| 2870 | NSSize titleSize; | ||||
| 2871 | |||||
| 2872 | if (aString == nil((id)((void*)0))) | ||||
| 2873 | return; | ||||
| 2874 | |||||
| 2875 | titleSize = [aString size]; | ||||
| 2876 | |||||
| 2877 | /** Important: text should always be vertically centered without | ||||
| 2878 | * considering descender [as if descender did not exist]. | ||||
| 2879 | * This is particularly important for single line texts. | ||||
| 2880 | * Please make sure the output remains always correct. | ||||
| 2881 | */ | ||||
| 2882 | aRect.origin.y = NSMidY (aRect) - titleSize.height/2; | ||||
| 2883 | aRect.size.height = titleSize.height; | ||||
| 2884 | |||||
| 2885 | [aString drawInRect: aRect]; | ||||
| 2886 | } | ||||
| 2887 | |||||
| 2888 | - (void) _drawText: (NSString*)aString inFrame: (NSRect)cellFrame | ||||
| 2889 | { | ||||
| 2890 | NSSize titleSize; | ||||
| 2891 | NSDictionary *attributes; | ||||
| 2892 | |||||
| 2893 | if (aString == nil((id)((void*)0))) | ||||
| 2894 | return; | ||||
| 2895 | |||||
| 2896 | attributes = [self _nonAutoreleasedTypingAttributes]; | ||||
| 2897 | titleSize = [aString sizeWithAttributes: attributes]; | ||||
| 2898 | |||||
| 2899 | /** Important: text should always be vertically centered without | ||||
| 2900 | * considering descender [as if descender did not exist]. | ||||
| 2901 | * This is particularly important for single line texts. | ||||
| 2902 | * Please make sure the output remains always correct. | ||||
| 2903 | */ | ||||
| 2904 | cellFrame.origin.y = NSMidY (cellFrame) - titleSize.height/2; | ||||
| 2905 | cellFrame.size.height = titleSize.height; | ||||
| 2906 | |||||
| 2907 | [aString drawInRect: cellFrame withAttributes: attributes]; | ||||
| 2908 | RELEASE (attributes)[(attributes) release]; | ||||
| 2909 | } | ||||
| 2910 | |||||
| 2911 | // Private helper method overridden in subclasses | ||||
| 2912 | - (void) _drawBorderAndBackgroundWithFrame: (NSRect)cellFrame | ||||
| 2913 | inView: (NSView*)controlView | ||||
| 2914 | { | ||||
| 2915 | NSBorderType aType; | ||||
| 2916 | |||||
| 2917 | // Get border size | ||||
| 2918 | if (_cell.is_bordered) | ||||
| 2919 | aType = NSLineBorder; | ||||
| 2920 | else if (_cell.is_bezeled) | ||||
| 2921 | aType = NSBezelBorder; | ||||
| 2922 | else | ||||
| 2923 | aType = NSNoBorder; | ||||
| 2924 | |||||
| 2925 | [[GSTheme theme] drawBorderType: aType frame: cellFrame view: controlView]; | ||||
| 2926 | } | ||||
| 2927 | |||||
| 2928 | // Private helper method | ||||
| 2929 | - (void) _drawFocusRingWithFrame: (NSRect)cellFrame inView: (NSView*)controlView | ||||
| 2930 | { | ||||
| 2931 | if (_cell.shows_first_responder | ||||
| 2932 | && [[controlView window] firstResponder] == controlView) | ||||
| 2933 | { | ||||
| 2934 | switch (_cell.focus_ring_type) | ||||
| 2935 | { | ||||
| 2936 | case NSFocusRingTypeDefault: | ||||
| 2937 | [[GSTheme theme] drawFocusFrame: [self drawingRectForBounds: | ||||
| 2938 | cellFrame] | ||||
| 2939 | view: controlView]; | ||||
| 2940 | break; | ||||
| 2941 | case NSFocusRingTypeExterior: | ||||
| 2942 | [[GSTheme theme] drawFocusFrame: cellFrame | ||||
| 2943 | view: controlView]; | ||||
| 2944 | break; | ||||
| 2945 | case NSFocusRingTypeNone: | ||||
| 2946 | default: | ||||
| 2947 | break; | ||||
| 2948 | } | ||||
| 2949 | } | ||||
| 2950 | } | ||||
| 2951 | |||||
| 2952 | - (void) _drawEditorWithFrame: (NSRect)cellFrame | ||||
| 2953 | inView: (NSView *)controlView | ||||
| 2954 | { | ||||
| 2955 | /* Look Ma', no drawing here... */ | ||||
| 2956 | |||||
| 2957 | if ([controlView isKindOfClass: [NSControl class]]) | ||||
| 2958 | { | ||||
| 2959 | /* Adjust the text editor's frame to match cell's frame (w/o border) */ | ||||
| 2960 | NSRect titleRect = [self titleRectForBounds: cellFrame]; | ||||
| 2961 | NSText *textObject = [(NSControl*)controlView currentEditor]; | ||||
| 2962 | NSView *clipView = [textObject superview]; | ||||
| 2963 | |||||
| 2964 | if ([clipView isKindOfClass: [NSClipView class]]) | ||||
| 2965 | { | ||||
| 2966 | [clipView setFrame: titleRect]; | ||||
| 2967 | } | ||||
| 2968 | else | ||||
| 2969 | { | ||||
| 2970 | [textObject setFrame: titleRect]; | ||||
| 2971 | } | ||||
| 2972 | } | ||||
| 2973 | } | ||||
| 2974 | |||||
| 2975 | - (BOOL) _sendsActionOn:(int)eventTypeMask | ||||
| 2976 | { | ||||
| 2977 | return (_action_mask & eventTypeMask); | ||||
| 2978 | } | ||||
| 2979 | |||||
| 2980 | - (void) _setInEditing: (BOOL)flag | ||||
| 2981 | { | ||||
| 2982 | _cell.in_editing = flag; | ||||
| 2983 | } | ||||
| 2984 | |||||
| 2985 | - (void) _updateFieldEditor: (NSText*)textObject | ||||
| 2986 | { | ||||
| 2987 | if (_formatter != nil((id)((void*)0))) | ||||
| 2988 | { | ||||
| 2989 | NSString *contents; | ||||
| 2990 | |||||
| 2991 | contents = [_formatter editingStringForObjectValue: _object_value]; | ||||
| 2992 | if (contents == nil((id)((void*)0))) | ||||
| 2993 | { | ||||
| 2994 | // We cannot call the stringValue method as this will call | ||||
| 2995 | // validateEditing in NSActionCell subclasses | ||||
| 2996 | if (nil((id)((void*)0)) == _contents) | ||||
| 2997 | { | ||||
| 2998 | contents = @""; | ||||
| 2999 | } | ||||
| 3000 | else | ||||
| 3001 | { | ||||
| 3002 | if (_cell.contents_is_attributed_string == NO((BOOL)0)) | ||||
| 3003 | { | ||||
| 3004 | contents = (NSString *)_contents; | ||||
| 3005 | } | ||||
| 3006 | else | ||||
| 3007 | { | ||||
| 3008 | contents = [(NSAttributedString *)_contents string]; | ||||
| 3009 | } | ||||
| 3010 | } | ||||
| 3011 | } | ||||
| 3012 | if (![contents isEqualToString: [textObject string]]) | ||||
| 3013 | [textObject setText: contents]; | ||||
| 3014 | } | ||||
| 3015 | else | ||||
| 3016 | { | ||||
| 3017 | NSString *contents; | ||||
| 3018 | |||||
| 3019 | if (nil((id)((void*)0)) == _contents) | ||||
| 3020 | { | ||||
| 3021 | contents = @""; | ||||
| 3022 | } | ||||
| 3023 | else | ||||
| 3024 | { | ||||
| 3025 | if (_cell.contents_is_attributed_string == NO((BOOL)0)) | ||||
| 3026 | { | ||||
| 3027 | contents = (NSString *)_contents; | ||||
| 3028 | } | ||||
| 3029 | else | ||||
| 3030 | { | ||||
| 3031 | contents = [(NSAttributedString *)_contents string]; | ||||
| 3032 | } | ||||
| 3033 | } | ||||
| 3034 | if (![contents isEqualToString: [textObject string]]) | ||||
| 3035 | { | ||||
| 3036 | if (_cell.contents_is_attributed_string == NO((BOOL)0)) | ||||
| 3037 | { | ||||
| 3038 | [textObject setText: contents]; | ||||
| 3039 | } | ||||
| 3040 | else | ||||
| 3041 | { | ||||
| 3042 | // FIXME what about attribute changes? | ||||
| 3043 | NSRange range = NSMakeRange(0, [[textObject string] length]); | ||||
| 3044 | [textObject replaceCharactersInRange: range | ||||
| 3045 | withAttributedString: (NSAttributedString *)_contents]; | ||||
| 3046 | } | ||||
| 3047 | } | ||||
| 3048 | } | ||||
| 3049 | } | ||||
| 3050 | |||||
| 3051 | /** | ||||
| 3052 | * Private method used by NSImageCell and NSButtonCell for calculating | ||||
| 3053 | * scaled image size | ||||
| 3054 | */ | ||||
| 3055 | |||||
| 3056 | static inline NSSize | ||||
| 3057 | scaleProportionally(NSSize imageSize, NSSize canvasSize, BOOL scaleUpOrDown) | ||||
| 3058 | { | ||||
| 3059 | CGFloat ratio; | ||||
| 3060 | |||||
| 3061 | if (imageSize.width <= 0 | ||||
| 3062 | || imageSize.height <= 0) | ||||
| 3063 | { | ||||
| 3064 | return NSMakeSize(0, 0); | ||||
| 3065 | } | ||||
| 3066 | |||||
| 3067 | /* Get the smaller ratio and scale the image size by it. */ | ||||
| 3068 | ratio = MIN(canvasSize.width / imageSize.width,(((canvasSize.width / imageSize.width)<(canvasSize.height / imageSize.height))?(canvasSize.width / imageSize.width):(canvasSize .height / imageSize.height)) | ||||
| 3069 | canvasSize.height / imageSize.height)(((canvasSize.width / imageSize.width)<(canvasSize.height / imageSize.height))?(canvasSize.width / imageSize.width):(canvasSize .height / imageSize.height)); | ||||
| 3070 | |||||
| 3071 | /* Only scale down, unless scaleUpOrDown is YES */ | ||||
| 3072 | if (ratio < 1.0 || scaleUpOrDown) | ||||
| 3073 | { | ||||
| 3074 | imageSize.width *= ratio; | ||||
| 3075 | imageSize.height *= ratio; | ||||
| 3076 | } | ||||
| 3077 | |||||
| 3078 | return imageSize; | ||||
| 3079 | } | ||||
| 3080 | |||||
| 3081 | - (NSSize) _scaleImageWithSize: (NSSize)imageSize | ||||
| 3082 | toFitInSize: (NSSize)canvasSize | ||||
| 3083 | scalingType: (NSImageScaling)scalingType | ||||
| 3084 | { | ||||
| 3085 | NSSize result; | ||||
| 3086 | switch (scalingType) | ||||
| 3087 | { | ||||
| 3088 | case NSImageScaleProportionallyDown: // == NSScaleProportionally | ||||
| 3089 | { | ||||
| 3090 | result = scaleProportionally (imageSize, canvasSize, NO((BOOL)0)); | ||||
| 3091 | break; | ||||
| 3092 | } | ||||
| 3093 | case NSImageScaleAxesIndependently: // == NSScaleToFit | ||||
| 3094 | { | ||||
| 3095 | result = canvasSize; | ||||
| 3096 | break; | ||||
| 3097 | } | ||||
| 3098 | default: | ||||
| 3099 | case NSImageScaleNone: // == NSScaleNone | ||||
| 3100 | { | ||||
| 3101 | result = imageSize; | ||||
| 3102 | break; | ||||
| 3103 | } | ||||
| 3104 | case NSImageScaleProportionallyUpOrDown: | ||||
| 3105 | { | ||||
| 3106 | result = scaleProportionally (imageSize, canvasSize, YES((BOOL)1)); | ||||
| 3107 | break; | ||||
| 3108 | } | ||||
| 3109 | } | ||||
| 3110 | return result; | ||||
| 3111 | } | ||||
| 3112 | |||||
| 3113 | @end |