API 0.9.5
AppKit/CPControl.j
Go to the documentation of this file.
00001 /*
00002  * CPControl.j
00003  * AppKit
00004  *
00005  * Created by Francisco Tolmasky.
00006  * Copyright 2008, 280 North, Inc.
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00023 #import "../Foundation/Ref.h"
00024 
00025 
00026 CPLeftTextAlignment             = 0;
00027 CPRightTextAlignment            = 1;
00028 CPCenterTextAlignment           = 2;
00029 CPJustifiedTextAlignment        = 3;
00030 CPNaturalTextAlignment          = 4;
00031 
00032 CPRegularControlSize            = 0;
00033 CPSmallControlSize              = 1;
00034 CPMiniControlSize               = 2;
00035 
00036 CPLineBreakByWordWrapping       = 0;
00037 CPLineBreakByCharWrapping       = 1;
00038 CPLineBreakByClipping           = 2;
00039 CPLineBreakByTruncatingHead     = 3;
00040 CPLineBreakByTruncatingTail     = 4;
00041 CPLineBreakByTruncatingMiddle   = 5;
00042 
00043 CPTopVerticalTextAlignment      = 1;
00044 CPCenterVerticalTextAlignment   = 2;
00045 CPBottomVerticalTextAlignment   = 3;
00046 
00047 CPScaleProportionally           = 0;
00048 CPScaleToFit                    = 1;
00049 CPScaleNone                     = 2;
00050 
00051 CPNoImage                       = 0;
00052 CPImageOnly                     = 1;
00053 CPImageLeft                     = 2;
00054 CPImageRight                    = 3;
00055 CPImageBelow                    = 4;
00056 CPImageAbove                    = 5;
00057 CPImageOverlaps                 = 6;
00058 
00059 CPOnState                       = 1;
00060 CPOffState                      = 0;
00061 CPMixedState                    = -1;
00062 
00063 CPControlNormalBackgroundColor      = "CPControlNormalBackgroundColor";
00064 CPControlSelectedBackgroundColor    = "CPControlSelectedBackgroundColor";
00065 CPControlHighlightedBackgroundColor = "CPControlHighlightedBackgroundColor";
00066 CPControlDisabledBackgroundColor    = "CPControlDisabledBackgroundColor";
00067 
00068 CPControlTextDidBeginEditingNotification    = "CPControlTextDidBeginEditingNotification";
00069 CPControlTextDidChangeNotification          = "CPControlTextDidChangeNotification";
00070 CPControlTextDidEndEditingNotification      = "CPControlTextDidEndEditingNotification";
00071 
00072 var CPControlBlackColor = [CPColor blackColor];
00073 
00080 @implementation CPControl : CPView
00081 {
00082     id                  _value;
00083     CPFormatter         _formatter;
00084 
00085     // Target-Action Support
00086     id                  _target;
00087     SEL                 _action;
00088     int                 _sendActionOn;
00089     BOOL                _sendsActionOnEndEditing;
00090 
00091     // Mouse Tracking Support
00092     BOOL                _continuousTracking;
00093     BOOL                _trackingWasWithinFrame;
00094     unsigned            _trackingMouseDownFlags;
00095     CGPoint             _previousTrackingLocation;
00096 }
00097 
00098 + (CPDictionary)themeAttributes
00099 {
00100     return [CPDictionary dictionaryWithObjects:[CPLeftTextAlignment,
00101                                                 CPTopVerticalTextAlignment,
00102                                                 CPLineBreakByClipping,
00103                                                 [CPColor blackColor],
00104                                                 [CPFont systemFontOfSize:12.0],
00105                                                 [CPNull null],
00106                                                 _CGSizeMakeZero(),
00107                                                 CPImageLeft,
00108                                                 CPScaleToFit,
00109                                                 _CGSizeMakeZero(),
00110                                                 _CGSizeMake(-1.0, -1.0)]
00111                                        forKeys:[@"alignment",
00112                                                 @"vertical-alignment",
00113                                                 @"line-break-mode",
00114                                                 @"text-color",
00115                                                 @"font",
00116                                                 @"text-shadow-color",
00117                                                 @"text-shadow-offset",
00118                                                 @"image-position",
00119                                                 @"image-scaling",
00120                                                 @"min-size",
00121                                                 @"max-size"]];
00122 }
00123 
00124 + (void)initialize
00125 {
00126     if (self === [CPControl class])
00127     {
00128         [self exposeBinding:@"value"];
00129         [self exposeBinding:@"objectValue"];
00130         [self exposeBinding:@"stringValue"];
00131         [self exposeBinding:@"integerValue"];
00132         [self exposeBinding:@"intValue"];
00133         [self exposeBinding:@"doubleValue"];
00134         [self exposeBinding:@"floatValue"];
00135 
00136         [self exposeBinding:@"enabled"];
00137     }
00138 }
00139 
00140 + (Class)_binderClassForBinding:(CPString)theBinding
00141 {
00142     if (theBinding === CPValueBinding)
00143         return [_CPValueBinder class];
00144 
00145     return [super _binderClassForBinding:theBinding];
00146 }
00147 
00151 - (void)_continuouslyReverseSetBinding
00152 {
00153     var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
00154         theBinding = [binderClass getBinding:CPValueBinding forObject:self];
00155 
00156     if ([theBinding continuouslyUpdatesValue])
00157         [theBinding reverseSetValueFor:@"objectValue"];
00158 }
00159 
00160 - (void)_reverseSetBinding
00161 {
00162     var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
00163         theBinding = [binderClass getBinding:CPValueBinding forObject:self];
00164 
00165     [theBinding reverseSetValueFor:@"objectValue"];
00166 }
00167 
00168 - (id)initWithFrame:(CGRect)aFrame
00169 {
00170     self = [super initWithFrame:aFrame];
00171 
00172     if (self)
00173     {
00174         _sendActionOn = CPLeftMouseUpMask;
00175         _trackingMouseDownFlags = 0;
00176     }
00177 
00178     return self;
00179 }
00180 
00186 - (void)setAction:(SEL)anAction
00187 {
00188     _action = anAction;
00189 }
00190 
00194 - (SEL)action
00195 {
00196     return _action;
00197 }
00198 
00204 - (void)setTarget:(id)aTarget
00205 {
00206     _target = aTarget;
00207 }
00208 
00212 - (id)target
00213 {
00214     return _target;
00215 }
00216 
00223 - (BOOL)sendAction:(SEL)anAction to:(id)anObject
00224 {
00225     [self _reverseSetBinding];
00226 
00227     return [CPApp sendAction:anAction to:anObject from:self];
00228 }
00229 
00230 - (int)sendActionOn:(int)mask
00231 {
00232     var previousMask = _sendActionOn;
00233 
00234     _sendActionOn = mask;
00235 
00236     return previousMask;
00237 }
00238 
00242 - (BOOL)isContinuous
00243 {
00244     // Some subclasses should redefine this with CPLeftMouseDraggedMask
00245     return (_sendActionOn & CPPeriodicMask) !== 0;
00246 }
00247 
00251 - (void)setContinuous:(BOOL)flag
00252 {
00253     // Some subclasses should redefine this with CPLeftMouseDraggedMask
00254     if (flag)
00255         _sendActionOn |= CPPeriodicMask;
00256     else
00257         _sendActionOn &= ~CPPeriodicMask;
00258 }
00259 
00263 - (BOOL)tracksMouseOutsideOfFrame
00264 {
00265     return NO;
00266 }
00267 
00268 - (void)trackMouse:(CPEvent)anEvent
00269 {
00270     var type = [anEvent type],
00271         currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
00272         isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
00273 
00274     if (type === CPLeftMouseUp)
00275     {
00276         [self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
00277 
00278         _trackingMouseDownFlags = 0;
00279 
00280         if (isWithinFrame)
00281             [self setThemeState:CPThemeStateHovered];
00282     }
00283     else
00284     {
00285         [self unsetThemeState:CPThemeStateHovered];
00286 
00287         if (type === CPLeftMouseDown)
00288         {
00289             _trackingMouseDownFlags = [anEvent modifierFlags];
00290             _continuousTracking = [self startTrackingAt:currentLocation];
00291         }
00292         else if (type === CPLeftMouseDragged)
00293         {
00294             if (isWithinFrame)
00295             {
00296                 if (!_trackingWasWithinFrame)
00297                     _continuousTracking = [self startTrackingAt:currentLocation];
00298 
00299                 else if (_continuousTracking)
00300                     _continuousTracking = [self continueTracking:_previousTrackingLocation at:currentLocation];
00301             }
00302             else
00303                 [self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:NO];
00304         }
00305 
00306         [CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
00307     }
00308 
00309     if ((_sendActionOn & (1 << type)) && isWithinFrame)
00310         [self sendAction:_action to:_target];
00311 
00312     _trackingWasWithinFrame = isWithinFrame;
00313     _previousTrackingLocation = currentLocation;
00314 }
00315 
00316 - (void)setState:(int)state
00317 {
00318 }
00319 
00320 - (int)nextState
00321 {
00322     return 0;
00323 }
00324 
00330 - (void)performClick:(id)sender
00331 {
00332     if (![self isEnabled])
00333         return;
00334 
00335     [self highlight:YES];
00336     [self setState:[self nextState]];
00337 
00338     try
00339     {
00340         [self sendAction:[self action] to:[self target]];
00341     }
00342     catch (e)
00343     {
00344         throw e;
00345     }
00346     finally
00347     {
00348         [CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unhighlightButtonTimerDidFinish:) userInfo:nil repeats:NO];
00349     }
00350 }
00351 
00356 - (void)unhighlightButtonTimerDidFinish:(id)sender
00357 {
00358     [self highlight:NO];
00359 }
00360 
00364 - (unsigned)mouseDownFlags
00365 {
00366     return _trackingMouseDownFlags;
00367 }
00368 
00369 - (BOOL)startTrackingAt:(CGPoint)aPoint
00370 {
00371     [self highlight:YES];
00372 
00373     return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
00374 }
00375 
00376 - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
00377 {
00378     return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
00379 }
00380 
00381 - (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
00382 {
00383     [self highlight:NO];
00384 }
00385 
00386 - (void)mouseDown:(CPEvent)anEvent
00387 {
00388     if (![self isEnabled])
00389         return;
00390 
00391     [self trackMouse:anEvent];
00392 }
00393 
00394 - (void)mouseEntered:(CPEvent)anEvent
00395 {
00396     if (![self isEnabled])
00397         return;
00398 
00399     [self setThemeState:CPThemeStateHovered];
00400 }
00401 
00402 - (void)mouseExited:(CPEvent)anEvent
00403 {
00404     var currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
00405         isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
00406 
00407     // Make sure we're not still in the frame because Cappuccino will sent mouseExited events
00408     // for all of the (ephemeral) subviews of a view as well.
00409     if (!isWithinFrame)
00410         [self unsetThemeState:CPThemeStateHovered];
00411 }
00412 
00416 - (id)objectValue
00417 {
00418     return _value;
00419 }
00420 
00424 - (void)setObjectValue:(id)anObject
00425 {
00426     _value = anObject;
00427 
00428     [self setNeedsLayout];
00429     [self setNeedsDisplay:YES];
00430 }
00431 
00435 - (float)floatValue
00436 {
00437     var floatValue = parseFloat(_value, 10);
00438     return isNaN(floatValue) ? 0.0 : floatValue;
00439 }
00440 
00444 - (void)setFloatValue:(float)aValue
00445 {
00446     [self setObjectValue:aValue];
00447 }
00448 
00452 - (double)doubleValue
00453 {
00454     var doubleValue = parseFloat(_value, 10);
00455     return isNaN(doubleValue) ? 0.0 : doubleValue;
00456 }
00457 
00461 - (void)setDoubleValue:(double)anObject
00462 {
00463     [self setObjectValue:anObject];
00464 }
00465 
00469 - (int)intValue
00470 {
00471     var intValue = parseInt(_value, 10);
00472     return isNaN(intValue) ? 0.0 : intValue;
00473 }
00474 
00478 - (void)setIntValue:(int)anObject
00479 {
00480     [self setObjectValue:anObject];
00481 }
00482 
00486 - (int)integerValue
00487 {
00488     var intValue = parseInt(_value, 10);
00489     return isNaN(intValue) ? 0.0 : intValue;
00490 }
00491 
00495 - (void)setIntegerValue:(int)anObject
00496 {
00497     [self setObjectValue:anObject];
00498 }
00499 
00503 - (CPString)stringValue
00504 {
00505     if (_formatter && _value !== undefined && _value !== nil)
00506     {
00507         var formattedValue = [self hasThemeState:CPThemeStateEditing] ? [_formatter editingStringForObjectValue:_value] : [_formatter stringForObjectValue:_value];
00508 
00509         if (formattedValue !== nil && formattedValue !== undefined)
00510             return formattedValue;
00511     }
00512 
00513     return (_value === undefined || _value === nil) ? "" : String(_value);
00514 }
00515 
00519 - (void)setStringValue:(CPString)aString
00520 {
00521     // Cocoa raises an invalid parameter assertion and returns if you pass nil.
00522     if (aString === nil || aString === undefined)
00523     {
00524         CPLog.warn("nil sent to CPControl -setStringValue");
00525         return;
00526     }
00527 
00528     var value;
00529 
00530     if (_formatter)
00531     {
00532         value = nil;
00533 
00534         if ([_formatter getObjectValue:AT_REF(value) forString:aString errorDescription:nil] === NO)
00535         {
00536             // If the given string is non-empty and doesn't work, Cocoa tries an empty string.
00537             if (!aString || [_formatter getObjectValue:AT_REF(value) forString:@"" errorDescription:nil] === NO)
00538                 value = undefined;  // Means the value is invalid
00539         }
00540     }
00541     else
00542         value = aString;
00543 
00544     [self setObjectValue:value];
00545 }
00546 
00547 - (void)takeDoubleValueFrom:(id)sender
00548 {
00549     if ([sender respondsToSelector:@selector(doubleValue)])
00550         [self setDoubleValue:[sender doubleValue]];
00551 }
00552 
00553 
00554 - (void)takeFloatValueFrom:(id)sender
00555 {
00556     if ([sender respondsToSelector:@selector(floatValue)])
00557         [self setFloatValue:[sender floatValue]];
00558 }
00559 
00560 - (void)takeIntegerValueFrom:(id)sender
00561 {
00562     if ([sender respondsToSelector:@selector(integerValue)])
00563         [self setIntegerValue:[sender integerValue]];
00564 }
00565 
00566 - (void)takeIntValueFrom:(id)sender
00567 {
00568     if ([sender respondsToSelector:@selector(intValue)])
00569         [self setIntValue:[sender intValue]];
00570 }
00571 
00572 - (void)takeObjectValueFrom:(id)sender
00573 {
00574     if ([sender respondsToSelector:@selector(objectValue)])
00575         [self setObjectValue:[sender objectValue]];
00576 }
00577 
00578 - (void)takeStringValueFrom:(id)sender
00579 {
00580     if ([sender respondsToSelector:@selector(stringValue)])
00581         [self setStringValue:[sender stringValue]];
00582 }
00583 
00584 - (void)textDidBeginEditing:(CPNotification)note
00585 {
00586     //this looks to prevent false propagation of notifications for other objects
00587     if ([note object] != self)
00588         return;
00589 
00590     [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
00591 }
00592 
00593 - (void)textDidChange:(CPNotification)note
00594 {
00595     //this looks to prevent false propagation of notifications for other objects
00596     if ([note object] != self)
00597         return;
00598 
00599     [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
00600 }
00601 
00602 - (void)textDidEndEditing:(CPNotification)note
00603 {
00604     //this looks to prevent false propagation of notifications for other objects
00605     if ([note object] != self)
00606         return;
00607 
00608     [self _reverseSetBinding];
00609 
00610     [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
00611 }
00612 
00624 - (void)setAlignment:(CPTextAlignment)alignment
00625 {
00626     [self setValue:alignment forThemeAttribute:@"alignment"];
00627 }
00628 
00632 - (CPTextAlignment)alignment
00633 {
00634     return [self valueForThemeAttribute:@"alignment"];
00635 }
00636 
00646 - (void)setVerticalAlignment:(CPTextVerticalAlignment)alignment
00647 {
00648     [self setValue:alignment forThemeAttribute:@"vertical-alignment"];
00649 }
00650 
00654 - (CPTextVerticalAlignment)verticalAlignment
00655 {
00656     return [self valueForThemeAttribute:@"vertical-alignment"];
00657 }
00658 
00671 - (void)setLineBreakMode:(CPLineBreakMode)mode
00672 {
00673     [self setValue:mode forThemeAttribute:@"line-break-mode"];
00674 }
00675 
00679 - (CPLineBreakMode)lineBreakMode
00680 {
00681     return [self valueForThemeAttribute:@"line-break-mode"];
00682 }
00683 
00689 - (void)setTextColor:(CPColor)aColor
00690 {
00691     [self setValue:aColor forThemeAttribute:@"text-color"];
00692 }
00693 
00697 - (CPColor)textColor
00698 {
00699     return [self valueForThemeAttribute:@"text-color"];
00700 }
00701 
00705 - (void)setTextShadowColor:(CPColor)aColor
00706 {
00707     [self setValue:aColor forThemeAttribute:@"text-shadow-color"];
00708 }
00709 
00713 - (CPColor)textShadowColor
00714 {
00715     return [self valueForThemeAttribute:@"text-shadow-color"];
00716 }
00717 
00723 - (void)setTextShadowOffset:(CGSize)offset
00724 {
00725     [self setValue:offset forThemeAttribute:@"text-shadow-offset"];
00726 }
00727 
00731 - (CGSize)textShadowOffset
00732 {
00733     return [self valueForThemeAttribute:@"text-shadow-offset"];
00734 }
00735 
00739 - (void)setFont:(CPFont)aFont
00740 {
00741     [self setValue:aFont forThemeAttribute:@"font"];
00742 }
00743 
00747 - (CPFont)font
00748 {
00749     return [self valueForThemeAttribute:@"font"];
00750 }
00751 
00765 - (void)setImagePosition:(CPCellImagePosition)position
00766 {
00767     [self setValue:position forThemeAttribute:@"image-position"];
00768 }
00769 
00773 - (CPCellImagePosition)imagePosition
00774 {
00775     return [self valueForThemeAttribute:@"image-position"];
00776 }
00777 
00787 - (void)setImageScaling:(CPImageScaling)scaling
00788 {
00789     [self setValue:scaling forThemeAttribute:@"image-scaling"];
00790 }
00791 
00795 - (CPImageScaling)imageScaling
00796 {
00797     return [self valueForThemeAttribute:@"image-scaling"];
00798 }
00799 
00806 - (void)setEnabled:(BOOL)isEnabled
00807 {
00808     if (isEnabled)
00809         [self unsetThemeState:CPThemeStateDisabled];
00810     else
00811         [self setThemeState:CPThemeStateDisabled];
00812 }
00813 
00817 - (BOOL)isEnabled
00818 {
00819     return ![self hasThemeState:CPThemeStateDisabled];
00820 }
00821 
00827 - (void)highlight:(BOOL)shouldHighlight
00828 {
00829     [self setHighlighted:shouldHighlight];
00830 }
00831 
00837 - (void)setHighlighted:(BOOL)isHighlighted
00838 {
00839     if (isHighlighted)
00840         [self setThemeState:CPThemeStateHighlighted];
00841     else
00842         [self unsetThemeState:CPThemeStateHighlighted];
00843 }
00844 
00848 - (BOOL)isHighlighted
00849 {
00850     return [self hasThemeState:CPThemeStateHighlighted];
00851 }
00852 
00853 @end
00854 
00855 var CPControlValueKey           = "CPControlValueKey",
00856     CPControlControlStateKey    = @"CPControlControlStateKey",
00857     CPControlIsEnabledKey       = "CPControlIsEnabledKey",
00858 
00859     CPControlTargetKey          = "CPControlTargetKey",
00860     CPControlActionKey          = "CPControlActionKey",
00861     CPControlSendActionOnKey    = "CPControlSendActionOnKey",
00862 
00863     CPControlSendsActionOnEndEditingKey = "CPControlSendsActionOnEndEditingKey";
00864 
00865 var __Deprecated__CPImageViewImageKey   = @"CPImageViewImageKey";
00866 
00867 @implementation CPControl (CPCoding)
00868 
00869 /*
00870     Initializes the control by unarchiving it from a coder.
00871 
00872     @param aCoder the coder from which to unarchive the control
00873     @return the initialized control
00874 */
00875 - (id)initWithCoder:(CPCoder)aCoder
00876 {
00877     self = [super initWithCoder:aCoder];
00878 
00879     if (self)
00880     {
00881         [self setObjectValue:[aCoder decodeObjectForKey:CPControlValueKey]];
00882 
00883         [self setTarget:[aCoder decodeObjectForKey:CPControlTargetKey]];
00884         [self setAction:[aCoder decodeObjectForKey:CPControlActionKey]];
00885 
00886         [self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
00887         [self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
00888     }
00889 
00890     return self;
00891 }
00892 
00893 /*
00894     Archives the control to the provided coder.
00895 
00896     @param aCoder the coder to which the control will be archived.
00897 */
00898 - (void)encodeWithCoder:(CPCoder)aCoder
00899 {
00900     [super encodeWithCoder:aCoder];
00901 
00902     if (_sendsActionOnEndEditing)
00903         [aCoder encodeBool:_sendsActionOnEndEditing forKey:CPControlSendsActionOnEndEditingKey];
00904 
00905     var objectValue = [self objectValue];
00906 
00907     if (objectValue !== nil)
00908         [aCoder encodeObject:objectValue forKey:CPControlValueKey];
00909 
00910     if (_target !== nil)
00911         [aCoder encodeConditionalObject:_target forKey:CPControlTargetKey];
00912 
00913     if (_action !== nil)
00914         [aCoder encodeObject:_action forKey:CPControlActionKey];
00915 
00916     [aCoder encodeInt:_sendActionOn forKey:CPControlSendActionOnKey];
00917 }
00918 
00919 @end
00920 
00921 var _CPControlSizeIdentifiers               = [],
00922     _CPControlCachedColorWithPatternImages  = {},
00923     _CPControlCachedThreePartImagePattern   = {};
00924 
00925 _CPControlSizeIdentifiers[CPRegularControlSize] = "Regular";
00926 _CPControlSizeIdentifiers[CPSmallControlSize]   = "Small";
00927 _CPControlSizeIdentifiers[CPMiniControlSize]    = "Mini";
00928 
00929 function _CPControlIdentifierForControlSize(aControlSize)
00930 {
00931     return _CPControlSizeIdentifiers[aControlSize];
00932 }
00933 
00934 function _CPControlColorWithPatternImage(sizes, aClassName)
00935 {
00936     var index = 1,
00937         count = arguments.length,
00938         identifier = "";
00939 
00940     for (; index < count; ++index)
00941         identifier += arguments[index];
00942 
00943     var color = _CPControlCachedColorWithPatternImages[identifier];
00944 
00945     if (!color)
00946     {
00947         var bundle = [CPBundle bundleForClass:[CPControl class]];
00948 
00949         color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + ".png"] size:sizes[identifier]]];
00950 
00951         _CPControlCachedColorWithPatternImages[identifier] = color;
00952     }
00953 
00954     return color;
00955 }
00956 
00957 function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
00958 {
00959     var index = 2,
00960         count = arguments.length,
00961         identifier = "";
00962 
00963     for (; index < count; ++index)
00964         identifier += arguments[index];
00965 
00966     var color = _CPControlCachedThreePartImagePattern[identifier];
00967 
00968     if (!color)
00969     {
00970         var bundle = [CPBundle bundleForClass:[CPControl class]],
00971             path = aClassName + "/" + identifier;
00972 
00973         sizes = sizes[identifier];
00974 
00975         color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:[
00976                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "0.png"] size:sizes[0]],
00977                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "1.png"] size:sizes[1]],
00978                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "2.png"] size:sizes[2]]
00979                 ] isVertical:isVertical]];
00980 
00981         _CPControlCachedThreePartImagePattern[identifier] = color;
00982     }
00983 
00984     return color;
00985 }
00986 
00987 @implementation CPControl (CPSynthesizedAccessors)
00988 
00992 - (CPFormatter)formatter
00993 {
00994     return _formatter;
00995 }
00996 
01000 - (void)setFormatter:(CPFormatter)aValue
01001 {
01002     _formatter = aValue;
01003 }
01004 
01008 - (BOOL)sendsActionOnEndEditing
01009 {
01010     return _sendsActionOnEndEditing;
01011 }
01012 
01016 - (void)setSendsActionOnEndEditing:(BOOL)aValue
01017 {
01018     _sendsActionOnEndEditing = aValue;
01019 }
01020 
01021 @end
 All Classes Files Functions Variables Defines