00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import "CPFont.j"
00024 @import "CPShadow.j"
00025 @import "CPView.j"
00026
00027 #include "CoreGraphics/CGGeometry.h"
00028 #include "Platform/Platform.h"
00029
00030 CPLeftTextAlignment = 0;
00031 CPRightTextAlignment = 1;
00032 CPCenterTextAlignment = 2;
00033 CPJustifiedTextAlignment = 3;
00034 CPNaturalTextAlignment = 4;
00035
00036 CPRegularControlSize = 0;
00037 CPSmallControlSize = 1;
00038 CPMiniControlSize = 2;
00039
00040 CPLineBreakByWordWrapping = 0;
00041 CPLineBreakByCharWrapping = 1;
00042 CPLineBreakByClipping = 2;
00043 CPLineBreakByTruncatingHead = 3;
00044 CPLineBreakByTruncatingTail = 4;
00045 CPLineBreakByTruncatingMiddle = 5;
00046
00047 CPTopVerticalTextAlignment = 1,
00048 CPCenterVerticalTextAlignment = 2,
00049 CPBottomVerticalTextAlignment = 3;
00050
00051 CPScaleProportionally = 0;
00052 CPScaleToFit = 1;
00053 CPScaleNone = 2;
00054
00055 CPNoImage = 0;
00056 CPImageOnly = 1;
00057 CPImageLeft = 2;
00058 CPImageRight = 3;
00059 CPImageBelow = 4;
00060 CPImageAbove = 5;
00061 CPImageOverlaps = 6;
00062
00063 CPOnState = 1;
00064 CPOffState = 0;
00065 CPMixedState = -1;
00066
00067 CPControlNormalBackgroundColor = "CPControlNormalBackgroundColor";
00068 CPControlSelectedBackgroundColor = "CPControlSelectedBackgroundColor";
00069 CPControlHighlightedBackgroundColor = "CPControlHighlightedBackgroundColor";
00070 CPControlDisabledBackgroundColor = "CPControlDisabledBackgroundColor";
00071
00072 CPControlTextDidBeginEditingNotification = "CPControlTextDidBeginEditingNotification";
00073 CPControlTextDidChangeNotification = "CPControlTextDidChangeNotification";
00074 CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotification";
00075
00076 var CPControlBlackColor = [CPColor blackColor];
00077
00084 @implementation CPControl : CPView
00085 {
00086 id _value;
00087
00088
00089 id _target;
00090 SEL _action;
00091 int _sendActionOn;
00092 BOOL _sendsActionOnEndEditing @accessors(property=sendsActionOnEndEditing);
00093
00094
00095 BOOL _continuousTracking;
00096 BOOL _trackingWasWithinFrame;
00097 unsigned _trackingMouseDownFlags;
00098 CGPoint _previousTrackingLocation;
00099
00100 CPString _toolTip;
00101 }
00102
00103 + (CPDictionary)themeAttributes
00104 {
00105 return [CPDictionary dictionaryWithObjects:[CPLeftTextAlignment,
00106 CPTopVerticalTextAlignment,
00107 CPLineBreakByClipping,
00108 [CPColor blackColor],
00109 [CPFont systemFontOfSize:12.0],
00110 [CPNull null],
00111 _CGSizeMakeZero(),
00112 CPImageLeft,
00113 CPScaleToFit,
00114 _CGSizeMakeZero(),
00115 _CGSizeMake(-1.0, -1.0)]
00116 forKeys:[@"alignment",
00117 @"vertical-alignment",
00118 @"line-break-mode",
00119 @"text-color",
00120 @"font",
00121 @"text-shadow-color",
00122 @"text-shadow-offset",
00123 @"image-position",
00124 @"image-scaling",
00125 @"min-size",
00126 @"max-size"]];
00127 }
00128
00129 - (id)initWithFrame:(CGRect)aFrame
00130 {
00131 self = [super initWithFrame:aFrame];
00132
00133 if (self)
00134 {
00135 _sendActionOn = CPLeftMouseUpMask;
00136 _trackingMouseDownFlags = 0;
00137 }
00138
00139 return self;
00140 }
00141
00146 - (void)setAction:(SEL)anAction
00147 {
00148 _action = anAction;
00149 }
00150
00154 - (SEL)action
00155 {
00156 return _action;
00157 }
00158
00163 - (void)setTarget:(id)aTarget
00164 {
00165 _target = aTarget;
00166 }
00167
00171 - (id)target
00172 {
00173 return _target;
00174 }
00175
00181 - (void)sendAction:(SEL)anAction to:(id)anObject
00182 {
00183 [CPApp sendAction:anAction to:anObject from:self];
00184 }
00185
00186 - (int)sendActionOn:(int)mask
00187 {
00188 var previousMask = _sendActionOn;
00189
00190 _sendActionOn = mask;
00191
00192 return previousMask;
00193 }
00194
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00215
00216
00217
00218
00219
00220
00221
00225 - (BOOL)isContinuous
00226 {
00227
00228 return (_sendActionOn & CPPeriodicMask) !== 0;
00229 }
00230
00234 - (void)setContinuous:(BOOL)flag
00235 {
00236
00237 if (flag)
00238 _sendActionOn |= CPPeriodicMask;
00239 else
00240 _sendActionOn &= ~CPPeriodicMask;
00241 }
00242
00243 - (BOOL)tracksMouseOutsideOfFrame
00244 {
00245 return NO;
00246 }
00247
00248 - (void)trackMouse:(CPEvent)anEvent
00249 {
00250 var type = [anEvent type],
00251 currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil];
00252 isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
00253
00254 if (type === CPLeftMouseUp)
00255 {
00256 [self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
00257
00258 _trackingMouseDownFlags = 0;
00259 }
00260
00261 else
00262 {
00263 if (type === CPLeftMouseDown)
00264 {
00265 _trackingMouseDownFlags = [anEvent modifierFlags];
00266 _continuousTracking = [self startTrackingAt:currentLocation];
00267 }
00268 else if (type === CPLeftMouseDragged)
00269 {
00270 if (isWithinFrame)
00271 {
00272 if (!_trackingWasWithinFrame)
00273 _continuousTracking = [self startTrackingAt:currentLocation];
00274
00275 else if (_continuousTracking)
00276 _continuousTracking = [self continueTracking:_previousTrackingLocation at:currentLocation];
00277 }
00278 else
00279 [self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:NO];
00280 }
00281
00282 [CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
00283 }
00284
00285 if ((_sendActionOn & (1 << type)) && isWithinFrame)
00286 [self sendAction:_action to:_target];
00287
00288 _trackingWasWithinFrame = isWithinFrame;
00289 _previousTrackingLocation = currentLocation;
00290 }
00291
00292 - (void)setState:(int)state
00293 {
00294 }
00295
00296 - (int)nextState
00297 {
00298 return 0;
00299 }
00300
00301 - (void)performClick:(id)sender
00302 {
00303 [self highlight:YES];
00304 [self setState:[self nextState]];
00305 [self sendAction:[self action] to:[self target]];
00306
00307 [CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unhighlightButtonTimerDidFinish:) userInfo:nil repeats:NO];
00308 }
00309
00310 - (void)unhighlightButtonTimerDidFinish:(id)sender
00311 {
00312 [self highlight:NO];
00313 }
00314
00315 - (unsigned)mouseDownFlags
00316 {
00317 return _trackingMouseDownFlags;
00318 }
00319
00320 - (BOOL)startTrackingAt:(CGPoint)aPoint
00321 {
00322 [self highlight:YES];
00323
00324 return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
00325 }
00326
00327 - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
00328 {
00329 return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
00330 }
00331
00332 - (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
00333 {
00334 [self highlight:NO];
00335 }
00336
00337 - (void)mouseDown:(CPEvent)anEvent
00338 {
00339 if (![self isEnabled])
00340 return;
00341
00342 [self trackMouse:anEvent];
00343 }
00344
00348 - (id)objectValue
00349 {
00350 return _value;
00351 }
00352
00356 - (void)setObjectValue:(id)anObject
00357 {
00358 _value = anObject;
00359
00360 [self setNeedsLayout];
00361 [self setNeedsDisplay:YES];
00362 }
00363
00367 - (float)floatValue
00368 {
00369 var floatValue = parseFloat(_value, 10);
00370 return isNaN(floatValue) ? 0.0 : floatValue;
00371 }
00372
00376 - (void)setFloatValue:(float)aValue
00377 {
00378 [self setObjectValue:aValue];
00379 }
00380
00384 - (double)doubleValue
00385 {
00386 var doubleValue = parseFloat(_value, 10);
00387 return isNaN(doubleValue) ? 0.0 : doubleValue;
00388 }
00389
00393 - (void)setDoubleValue:(double)anObject
00394 {
00395 [self setObjectValue:anObject];
00396 }
00397
00401 - (int)intValue
00402 {
00403 var intValue = parseInt(_value, 10);
00404 return isNaN(intValue) ? 0.0 : intValue;
00405 }
00406
00410 - (void)setIntValue:(int)anObject
00411 {
00412 [self setObjectValue:anObject];
00413 }
00414
00418 - (int)integerValue
00419 {
00420 var intValue = parseInt(_value, 10);
00421 return isNaN(intValue) ? 0.0 : intValue;
00422 }
00423
00427 - (void)setIntegerValue:(int)anObject
00428 {
00429 [self setObjectValue:anObject];
00430 }
00431
00435 - (CPString)stringValue
00436 {
00437 return (_value === undefined || _value === nil) ? "" : String(_value);
00438 }
00439
00443 - (void)setStringValue:(CPString)anObject
00444 {
00445 [self setObjectValue:anObject];
00446 }
00447
00448 - (void)takeDoubleValueFrom:(id)sender
00449 {
00450 if ([sender respondsToSelector:@selector(doubleValue)])
00451 [self setDoubleValue:[sender doubleValue]];
00452 }
00453
00454
00455 - (void)takeFloatValueFrom:(id)sender
00456 {
00457 if ([sender respondsToSelector:@selector(floatValue)])
00458 [self setFloatValue:[sender floatValue]];
00459 }
00460
00461
00462 - (void)takeIntegerValueFrom:(id)sender
00463 {
00464 if ([sender respondsToSelector:@selector(integerValue)])
00465 [self setIntegerValue:[sender integerValue]];
00466 }
00467
00468
00469 - (void)takeIntValueFrom:(id)sender
00470 {
00471 if ([sender respondsToSelector:@selector(intValue)])
00472 [self setIntValue:[sender intValue]];
00473 }
00474
00475
00476 - (void)takeObjectValueFrom:(id)sender
00477 {
00478 if ([sender respondsToSelector:@selector(objectValue)])
00479 [self setObjectValue:[sender objectValue]];
00480 }
00481
00482 - (void)takeStringValueFrom:(id)sender
00483 {
00484 if ([sender respondsToSelector:@selector(stringValue)])
00485 [self setStringValue:[sender stringValue]];
00486 }
00487
00488 - (void)textDidBeginEditing:(CPNotification)note
00489 {
00490
00491 if([note object] != self)
00492 return;
00493
00494 [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
00495 }
00496
00497 - (void)textDidChange:(CPNotification)note
00498 {
00499
00500 if([note object] != self)
00501 return;
00502
00503 [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
00504 }
00505
00506 - (void)textDidEndEditing:(CPNotification)note
00507 {
00508
00509 if([note object] != self)
00510 return;
00511
00512 [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
00513 }
00514
00515 #define BRIDGE(UPPERCASE, LOWERCASE, ATTRIBUTENAME) \
00516 \
00517 - (void)set##UPPERCASE:(id)aValue\
00518 {\
00519 [self setValue:aValue forThemeAttribute:ATTRIBUTENAME];\
00520 }\
00521 \
00522 - (id)LOWERCASE\
00523 {\
00524 return [self valueForThemeAttribute:ATTRIBUTENAME];\
00525 }
00526
00527 BRIDGE(Alignment, alignment, "alignment")
00528 BRIDGE(VerticalAlignment, verticalAlignment, "vertical-alignment")
00529 BRIDGE(LineBreakMode, lineBreakMode, "line-break-mode")
00530 BRIDGE(TextColor, textColor, "text-color")
00531 BRIDGE(Font, font, "font")
00532 BRIDGE(TextShadowColor, textShadowColor, "text-shadow-color")
00533 BRIDGE(TextShadowOffset, textShadowOffset, "text-shadow-offset")
00534 BRIDGE(ImagePosition, imagePosition, "image-position")
00535 BRIDGE(ImageScaling, imageScaling, "image-scaling")
00536
00537 - (void)setEnabled:(BOOL)isEnabled
00538 {
00539 if (isEnabled)
00540 [self unsetThemeState:CPThemeStateDisabled];
00541 else
00542 [self setThemeState:CPThemeStateDisabled];
00543 }
00544
00545 - (BOOL)isEnabled
00546 {
00547 return ![self hasThemeState:CPThemeStateDisabled];
00548 }
00549
00550 - (void)highlight:(BOOL)shouldHighlight
00551 {
00552 [self setHighlighted:shouldHighlight];
00553 }
00554
00555 - (void)setHighlighted:(BOOL)isHighlighted
00556 {
00557 if (isHighlighted)
00558 [self setThemeState:CPThemeStateHighlighted];
00559 else
00560 [self unsetThemeState:CPThemeStateHighlighted];
00561 }
00562
00563 - (BOOL)isHighlighted
00564 {
00565 return [self hasThemeState:CPThemeStateHighlighted];
00566 }
00567
00568 @end
00569
00570 var CPControlValueKey = "CPControlValueKey",
00571 CPControlControlStateKey = @"CPControlControlStateKey",
00572 CPControlIsEnabledKey = "CPControlIsEnabledKey",
00573
00574 CPControlTargetKey = "CPControlTargetKey",
00575 CPControlActionKey = "CPControlActionKey",
00576 CPControlSendActionOnKey = "CPControlSendActionOnKey",
00577
00578 CPControlSendsActionOnEndEditingKey = "CPControlSendsActionOnEndEditingKey";
00579
00580 var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
00581
00582 @implementation CPControl (CPCoding)
00583
00584
00585
00586
00587
00588
00589 - (id)initWithCoder:(CPCoder)aCoder
00590 {
00591 self = [super initWithCoder:aCoder];
00592
00593 if (self)
00594 {
00595 [self setObjectValue:[aCoder decodeObjectForKey:CPControlValueKey]];
00596
00597 [self setTarget:[aCoder decodeObjectForKey:CPControlTargetKey]];
00598 [self setAction:[aCoder decodeObjectForKey:CPControlActionKey]];
00599
00600 [self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
00601 [self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
00602 }
00603
00604 return self;
00605 }
00606
00607
00608
00609
00610
00611 - (void)encodeWithCoder:(CPCoder)aCoder
00612 {
00613 [super encodeWithCoder:aCoder];
00614
00615 if (_sendsActionOnEndEditing)
00616 [aCoder encodeBool:_sendsActionOnEndEditing forKey:CPControlSendsActionOnEndEditingKey];
00617
00618 if (_value !== nil)
00619 [aCoder encodeObject:_value forKey:CPControlValueKey];
00620
00621 if (_target !== nil)
00622 [aCoder encodeConditionalObject:_target forKey:CPControlTargetKey];
00623
00624 if (_action !== NULL)
00625 [aCoder encodeObject:_action forKey:CPControlActionKey];
00626
00627 [aCoder encodeInt:_sendActionOn forKey:CPControlSendActionOnKey];
00628 }
00629
00630 @end
00631
00632 var _CPControlSizeIdentifiers = [],
00633 _CPControlCachedColorWithPatternImages = {},
00634 _CPControlCachedThreePartImagePattern = {};
00635
00636 _CPControlSizeIdentifiers[CPRegularControlSize] = "Regular";
00637 _CPControlSizeIdentifiers[CPSmallControlSize] = "Small";
00638 _CPControlSizeIdentifiers[CPMiniControlSize] = "Mini";
00639
00640 function _CPControlIdentifierForControlSize(aControlSize)
00641 {
00642 return _CPControlSizeIdentifiers[aControlSize];
00643 }
00644
00645 function _CPControlColorWithPatternImage(sizes, aClassName)
00646 {
00647 var index = 1,
00648 count = arguments.length,
00649 identifier = "";
00650
00651 for (; index < count; ++index)
00652 identifier += arguments[index];
00653
00654 var color = _CPControlCachedColorWithPatternImages[identifier];
00655
00656 if (!color)
00657 {
00658 var bundle = [CPBundle bundleForClass:[CPControl class]];
00659
00660 color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + ".png"] size:sizes[identifier]]];
00661
00662 _CPControlCachedColorWithPatternImages[identifier] = color;
00663 }
00664
00665 return color;
00666 }
00667
00668 function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
00669 {
00670 var index = 2,
00671 count = arguments.length,
00672 identifier = "";
00673
00674 for (; index < count; ++index)
00675 identifier += arguments[index];
00676
00677 var color = _CPControlCachedThreePartImagePattern[identifier];
00678
00679 if (!color)
00680 {
00681 var bundle = [CPBundle bundleForClass:[CPControl class]],
00682 path = aClassName + "/" + identifier;
00683
00684 sizes = sizes[identifier];
00685
00686 color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:[
00687 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "0.png"] size:sizes[0]],
00688 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "1.png"] size:sizes[1]],
00689 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "2.png"] size:sizes[2]]
00690 ] isVertical:isVertical]];
00691
00692 _CPControlCachedThreePartImagePattern[identifier] = color;
00693 }
00694
00695 return color;
00696 }