API  1.0.0
CPControl.j
Go to the documentation of this file.
1 /*
2  * CPControl.j
3  * AppKit
4  *
5  * Created by Francisco Tolmasky.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 
25 @global CPApp
26 
27 @protocol CPControlTextEditingDelegate <CPObject>
28 
29 @optional
30 - (void)controlTextDidBeginEditing:(CPNotification)aNotification;
31 - (void)controlTextDidChange:(CPNotification)aNotification;
32 - (void)controlTextDidEndEditing:(CPNotification)aNotification;
33 - (void)controlTextDidFocus:(CPNotification)aNotification;
34 - (void)controlTextDidBlur:(CPNotification)aNotification;
35 - (BOOL)control:(CPControl)control didFailToFormatString:(CPString)string errorDescription:(CPString)error;
36 
37 @end
38 
39 @typedef CPControlSize
43 
44 @typedef CPLineBreakMode
51 
52 @typedef CPVerticalTextAlignment
56 
57 // Deprecated for use with images, use the CPImageScale constants
58 @typedef CPImageScaling
62 
67 
68 @typedef CPCellImagePosition
76 
80 
81 CPControlNormalBackgroundColor = "CPControlNormalBackgroundColor";
82 CPControlSelectedBackgroundColor = "CPControlSelectedBackgroundColor";
83 CPControlHighlightedBackgroundColor = "CPControlHighlightedBackgroundColor";
84 CPControlDisabledBackgroundColor = "CPControlDisabledBackgroundColor";
85 
86 CPControlTextDidBeginEditingNotification = "CPControlTextDidBeginEditingNotification";
87 CPControlTextDidChangeNotification = "CPControlTextDidChangeNotification";
88 CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotification";
89 
91 
97 @implementation CPControl : CPView
98 {
99  id _value;
100  CPFormatter _formatter;
101 
102  // Target-Action Support
103  id _target;
104  SEL _action;
105  int _sendActionOn;
106  BOOL _sendsActionOnEndEditing;
107 
108  // Mouse Tracking Support
109  BOOL _continuousTracking;
110  BOOL _trackingWasWithinFrame;
111  unsigned _trackingMouseDownFlags;
112  CGPoint _previousTrackingLocation;
113 
114  CPControlSize _controlSize;
115 
116  CPWritingDirection _baseWritingDirection;
117 }
118 
119 + (CPDictionary)themeAttributes
120 {
121  return @{
122  @"alignment": CPLeftTextAlignment,
123  @"vertical-alignment": CPTopVerticalTextAlignment,
124  @"line-break-mode": CPLineBreakByClipping,
125  @"text-color": [CPColor blackColor],
126  @"font": [CPFont systemFontOfSize:CPFontCurrentSystemSize],
127  @"text-shadow-color": [CPNull null],
128  @"text-shadow-offset": CGSizeMakeZero(),
129  @"image-position": CPImageLeft,
130  @"image-scaling": CPScaleToFit,
131  @"min-size": CGSizeMakeZero(),
132  @"max-size": CGSizeMake(-1.0, -1.0),
133  @"nib2cib-adjustment-frame": CGRectMakeZero()
134  };
135 }
136 
137 + (void)initialize
138 {
139  if (self !== [CPControl class])
140  return;
141 
142  [self exposeBinding:@"value"];
143  [self exposeBinding:@"objectValue"];
144  [self exposeBinding:@"stringValue"];
145  [self exposeBinding:@"integerValue"];
146  [self exposeBinding:@"intValue"];
147  [self exposeBinding:@"doubleValue"];
148  [self exposeBinding:@"floatValue"];
149 
150  [self exposeBinding:@"enabled"];
151 }
152 
153 + (Class)_binderClassForBinding:(CPString)aBinding
154 {
155  if (aBinding === CPValueBinding)
156  return [_CPValueBinder class];
157  else if ([aBinding hasPrefix:CPEnabledBinding])
158  return [CPMultipleValueAndBinding class];
159 
160  return [super _binderClassForBinding:aBinding];
161 }
162 
166 - (void)_continuouslyReverseSetBinding
167 {
168  var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
169  theBinding = [binderClass getBinding:CPValueBinding forObject:self];
170 
171  if ([theBinding continuouslyUpdatesValue])
172  [theBinding reverseSetValueFor:@"objectValue"];
173 }
174 
175 - (void)_reverseSetBinding
176 {
177  var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
178  theBinding = [binderClass getBinding:CPValueBinding forObject:self];
179 
180  [theBinding reverseSetValueFor:@"objectValue"];
181 }
182 
183 - (id)initWithFrame:(CGRect)aFrame
184 {
185  self = [super initWithFrame:aFrame];
186 
187  if (self)
188  {
189  _sendActionOn = CPLeftMouseUpMask;
190  _trackingMouseDownFlags = 0;
191  }
192 
193  return self;
194 }
195 
196 #pragma mark -
197 #pragma mark Control Size
198 
202 - (CPControlSize)controlSize
203 {
204  return _controlSize;
205 }
206 
211 - (void)setControlSize:(CPControlSize)aControlSize
212 {
213  if (_controlSize === aControlSize)
214  return;
215 
216  [self unsetThemeState:[self _controlSizeThemeState]];
217  _controlSize = aControlSize;
218  [self setThemeState:[self _controlSizeThemeState]];
219 
220  [self setNeedsLayout];
221  [self setNeedsDisplay:YES];
222 }
223 
228 - (ThemeState)_controlSizeThemeState
229 {
230  switch (_controlSize)
231  {
232  case CPSmallControlSize:
234 
235  case CPMiniControlSize:
237 
239  default:
241  }
242 }
243 
249 - (void)_sizeToControlSize
250 {
251  var frameSize = [self frameSize],
252  minSize = [self currentValueForThemeAttribute:@"min-size"],
253  maxSize = [self currentValueForThemeAttribute:@"max-size"];
254 
255  if (minSize.width > 0)
256  {
257  frameSize.width = MAX(minSize.width, frameSize.width);
258 
259  if (maxSize.width > 0)
260  frameSize.width = MIN(maxSize.width, frameSize.width);
261  }
262 
263  if (minSize.height > 0)
264  {
265  frameSize.height = MAX(minSize.height, frameSize.height);
266 
267  if (maxSize.height > 0)
268  frameSize.height = MIN(maxSize.height, frameSize.height);
269  }
270 
271  [self setFrameSize:frameSize];
272 }
273 
274 
275 #pragma mark -
276 
282 - (void)setAction:(SEL)anAction
283 {
284  _action = anAction;
285 }
286 
290 - (SEL)action
291 {
292  return _action;
293 }
294 
300 - (void)setTarget:(id)aTarget
301 {
302  _target = aTarget;
303 }
304 
308 - (id)target
309 {
310  return _target;
311 }
312 
319 - (BOOL)sendAction:(SEL)anAction to:(id)anObject
320 {
321  [self _reverseSetBinding];
322 
323  var binding = [CPBinder getBinding:CPTargetBinding forObject:self];
324  [binding invokeAction];
325 
326  return [CPApp sendAction:anAction to:anObject from:self];
327 }
328 
329 - (int)sendActionOn:(int)mask
330 {
331  var previousMask = _sendActionOn;
332 
333  _sendActionOn = mask;
334 
335  return previousMask;
336 }
337 
341 - (BOOL)isContinuous
342 {
343  // Some subclasses should redefine this with CPLeftMouseDraggedMask
344  return (_sendActionOn & CPPeriodicMask) !== 0;
345 }
346 
350 - (void)setContinuous:(BOOL)flag
351 {
352  // Some subclasses should redefine this with CPLeftMouseDraggedMask
353  if (flag)
354  _sendActionOn |= CPPeriodicMask;
355  else
356  _sendActionOn &= ~CPPeriodicMask;
357 }
358 
362 - (BOOL)tracksMouseOutsideOfFrame
363 {
364  return NO;
365 }
366 
367 - (void)trackMouse:(CPEvent)anEvent
368 {
369  var type = [anEvent type],
370  currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
371  isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
372 
373  if (type === CPLeftMouseUp)
374  {
375  [self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:YES];
376 
377  _trackingMouseDownFlags = 0;
378 
379  if (isWithinFrame)
380  [self setThemeState:CPThemeStateHovered];
381  }
382  else
383  {
384  [self unsetThemeState:CPThemeStateHovered];
385 
386  if (type === CPLeftMouseDown)
387  {
388  _trackingMouseDownFlags = [anEvent modifierFlags];
389  _continuousTracking = [self startTrackingAt:currentLocation];
390  }
391  else if (type === CPLeftMouseDragged)
392  {
393  if (isWithinFrame)
394  {
395  if (!_trackingWasWithinFrame)
396  _continuousTracking = [self startTrackingAt:currentLocation];
397 
398  else if (_continuousTracking)
399  _continuousTracking = [self continueTracking:_previousTrackingLocation at:currentLocation];
400  }
401  else
402  [self stopTracking:_previousTrackingLocation at:currentLocation mouseIsUp:NO];
403  }
404 
405  [CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
406  }
407 
408  if ((_sendActionOn & (1 << type)) && isWithinFrame)
409  [self sendAction:_action to:_target];
410 
411  _trackingWasWithinFrame = isWithinFrame;
412  _previousTrackingLocation = currentLocation;
413 }
414 
415 - (void)setState:(CPInteger)state
416 {
417 }
418 
419 - (CPInteger)nextState
420 {
421  return 0;
422 }
423 
429 - (void)performClick:(id)sender
430 {
431  if (![self isEnabled])
432  return;
433 
434  [self highlight:YES];
435  [self setState:[self nextState]];
436 
437  try
438  {
439  [self sendAction:[self action] to:[self target]];
440  }
441  catch (e)
442  {
443  throw e;
444  }
445  finally
446  {
448  }
449 }
450 
455 - (void)unhighlightButtonTimerDidFinish:(id)sender
456 {
457  [self highlight:NO];
458 }
459 
463 - (unsigned)mouseDownFlags
464 {
465  return _trackingMouseDownFlags;
466 }
467 
468 - (BOOL)startTrackingAt:(CGPoint)aPoint
469 {
470  [self highlight:YES];
471 
472  return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
473 }
474 
475 - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
476 {
477  return (_sendActionOn & CPPeriodicMask) || (_sendActionOn & CPLeftMouseDraggedMask);
478 }
479 
480 - (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
481 {
482  if (mouseIsUp)
483  [self highlight:NO];
484  else
485  [self highlight:YES];
486 }
487 
491 - (BOOL)acceptsFirstMouse:(CPEvent)anEvent
492 {
493  return [self isEnabled];
494 }
495 
496 - (void)mouseDown:(CPEvent)anEvent
497 {
498  if (![self isEnabled])
499  return;
500 
501  [self trackMouse:anEvent];
502 }
503 
504 - (void)mouseEntered:(CPEvent)anEvent
505 {
506  if (![self isEnabled])
507  return;
508 
509  [self setThemeState:CPThemeStateHovered];
510 }
511 
512 - (void)mouseExited:(CPEvent)anEvent
513 {
514  var currentLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
515  isWithinFrame = [self tracksMouseOutsideOfFrame] || CGRectContainsPoint([self bounds], currentLocation);
516 
517  // Make sure we're not still in the frame because Cappuccino will sent mouseExited events
518  // for all of the (ephemeral) subviews of a view as well.
519  if (!isWithinFrame)
520  [self unsetThemeState:CPThemeStateHovered];
521 }
522 
526 - (id)objectValue
527 {
528  return _value;
529 }
530 
534 - (void)setObjectValue:(id)anObject
535 {
536  _value = anObject;
537 
538  [self setNeedsLayout];
539  [self setNeedsDisplay:YES];
540 }
541 
545 - (float)floatValue
546 {
547  var floatValue = parseFloat(_value, 10);
548  return isNaN(floatValue) ? 0.0 : floatValue;
549 }
550 
554 - (void)setFloatValue:(float)aValue
555 {
556  [self setObjectValue:aValue];
557 }
558 
562 - (double)doubleValue
563 {
564  var doubleValue = parseFloat(_value, 10);
565  return isNaN(doubleValue) ? 0.0 : doubleValue;
566 }
567 
571 - (void)setDoubleValue:(double)anObject
572 {
573  [self setObjectValue:anObject];
574 }
575 
579 - (int)intValue
580 {
581  var intValue = parseInt(_value, 10);
582  return isNaN(intValue) ? 0.0 : intValue;
583 }
584 
588 - (void)setIntValue:(int)anObject
589 {
590  [self setObjectValue:anObject];
591 }
592 
596 - (int)integerValue
597 {
598  var intValue = parseInt(_value, 10);
599  return isNaN(intValue) ? 0.0 : intValue;
600 }
601 
605 - (void)setIntegerValue:(int)anObject
606 {
607  [self setObjectValue:anObject];
608 }
609 
613 - (CPString)stringValue
614 {
615  if (_formatter && _value !== undefined)
616  {
617  var formattedValue = [self hasThemeState:CPThemeStateEditing] ? [_formatter editingStringForObjectValue:_value] : [_formatter stringForObjectValue:_value];
618 
619  if (formattedValue !== nil && formattedValue !== undefined)
620  return formattedValue;
621  }
622 
623  return (_value === undefined || _value === nil) ? @"" : String(_value);
624 }
625 
629 - (void)setStringValue:(CPString)aString
630 {
631  // Cocoa raises an invalid parameter assertion and returns if you pass nil.
632  if (aString === nil || aString === undefined)
633  {
634  CPLog.warn("nil or undefined sent to CPControl -setStringValue");
635  return;
636  }
637 
638  var value;
639 
640  if (_formatter)
641  {
642  value = nil;
643 
644  if ([_formatter getObjectValue:@ref(value) forString:aString errorDescription:nil] === NO)
645  {
646  // If the given string is non-empty and doesn't work, Cocoa tries an empty string.
647  if (!aString || [_formatter getObjectValue:@ref(value) forString:@"" errorDescription:nil] === NO)
648  value = undefined; // Means the value is invalid
649  }
650  }
651  else
652  value = aString;
653 
654  [self setObjectValue:value];
655 }
656 
657 - (void)takeDoubleValueFrom:(id)sender
658 {
659  if ([sender respondsToSelector:@selector(doubleValue)])
660  [self setDoubleValue:[sender doubleValue]];
661 }
662 
663 
664 - (void)takeFloatValueFrom:(id)sender
665 {
666  if ([sender respondsToSelector:@selector(floatValue)])
667  [self setFloatValue:[sender floatValue]];
668 }
669 
670 - (void)takeIntegerValueFrom:(id)sender
671 {
672  if ([sender respondsToSelector:@selector(integerValue)])
673  [self setIntegerValue:[sender integerValue]];
674 }
675 
676 - (void)takeIntValueFrom:(id)sender
677 {
678  if ([sender respondsToSelector:@selector(intValue)])
679  [self setIntValue:[sender intValue]];
680 }
681 
682 - (void)takeObjectValueFrom:(id)sender
683 {
684  if ([sender respondsToSelector:@selector(objectValue)])
685  [self setObjectValue:[sender objectValue]];
686 }
687 
688 - (void)takeStringValueFrom:(id)sender
689 {
690  if ([sender respondsToSelector:@selector(stringValue)])
691  [self setStringValue:[sender stringValue]];
692 }
693 
694 - (void)textDidBeginEditing:(CPNotification)note
695 {
696  //this looks to prevent false propagation of notifications for other objects
697  if ([note object] != self)
698  return;
699 
700  [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}];
701 }
702 
703 - (void)textDidChange:(CPNotification)note
704 {
705  //this looks to prevent false propagation of notifications for other objects
706  if ([note object] != self)
707  return;
708 
709  [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:@{"CPFieldEditor": [note object]}];
710 }
711 
712 - (void)textDidEndEditing:(CPNotification)note
713 {
714  //this looks to prevent false propagation of notifications for other objects
715  if ([note object] != self)
716  return;
717 
718  [self _reverseSetBinding];
719 
720  [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[note userInfo]];
721 }
722 
728 - (unsigned)_currentTextMovement
729 {
730  var currentEvent = [CPApp currentEvent],
731  keyCode = [currentEvent keyCode],
732  modifierFlags = [currentEvent modifierFlags];
733 
734  switch (keyCode)
735  {
736  case CPEscapeKeyCode:
737  return CPCancelTextMovement;
738 
739  case CPLeftArrowKeyCode:
740  return CPLeftTextMovement;
741 
742  case CPRightArrowKeyCode:
743  return CPRightTextMovement;
744 
745  case CPUpArrowKeyCode:
746  return CPUpTextMovement;
747 
748  case CPDownArrowKeyCode:
749  return CPDownTextMovement;
750 
751  case CPReturnKeyCode:
752  return CPReturnTextMovement;
753 
754  case CPTabKeyCode:
755  if (modifierFlags & CPShiftKeyMask)
756  return CPBacktabTextMovement;
757 
758  return CPTabTextMovement;
759 
760  default:
761  return CPOtherTextMovement;
762  }
763 }
764 
776 - (void)setAlignment:(CPTextAlignment)alignment
777 {
778  [self setValue:alignment forThemeAttribute:@"alignment"];
779 }
780 
784 - (CPTextAlignment)alignment
785 {
786  return [self valueForThemeAttribute:@"alignment"];
787 }
788 
798 - (void)setVerticalAlignment:(CPTextVerticalAlignment)alignment
799 {
800  [self setValue:alignment forThemeAttribute:@"vertical-alignment"];
801 }
802 
806 - (CPTextVerticalAlignment)verticalAlignment
807 {
808  return [self valueForThemeAttribute:@"vertical-alignment"];
809 }
810 
823 - (void)setLineBreakMode:(CPLineBreakMode)mode
824 {
825  [self setValue:mode forThemeAttribute:@"line-break-mode"];
826 }
827 
831 - (CPLineBreakMode)lineBreakMode
832 {
833  return [self valueForThemeAttribute:@"line-break-mode"];
834 }
835 
841 - (void)setTextColor:(CPColor)aColor
842 {
843  [self setValue:aColor forThemeAttribute:@"text-color"];
844 }
845 
849 - (CPColor)textColor
850 {
851  return [self valueForThemeAttribute:@"text-color"];
852 }
853 
857 - (void)setTextShadowColor:(CPColor)aColor
858 {
859  [self setValue:aColor forThemeAttribute:@"text-shadow-color"];
860 }
861 
865 - (CPColor)textShadowColor
866 {
867  return [self valueForThemeAttribute:@"text-shadow-color"];
868 }
869 
875 - (void)setTextShadowOffset:(CGSize)offset
876 {
877  [self setValue:offset forThemeAttribute:@"text-shadow-offset"];
878 }
879 
883 - (CGSize)textShadowOffset
884 {
885  return [self valueForThemeAttribute:@"text-shadow-offset"];
886 }
887 
891 - (void)setFont:(CPFont)aFont
892 {
893  [self setValue:aFont forThemeAttribute:@"font"];
894 }
895 
899 - (CPFont)font
900 {
901  return [self valueForThemeAttribute:@"font"];
902 }
903 
917 - (void)setImagePosition:(CPCellImagePosition)position
918 {
919  [self setValue:position forThemeAttribute:@"image-position"];
920 }
921 
925 - (CPCellImagePosition)imagePosition
926 {
927  return [self valueForThemeAttribute:@"image-position"];
928 }
929 
940 - (void)setImageScaling:(CPImageScaling)scaling
941 {
942  [self setValue:scaling forThemeAttribute:@"image-scaling"];
943 }
944 
948 - (CPUInteger)imageScaling
949 {
950  return [self valueForThemeAttribute:@"image-scaling"];
951 }
952 
959 - (void)setEnabled:(BOOL)isEnabled
960 {
961  if (isEnabled)
962  [self unsetThemeState:CPThemeStateDisabled];
963  else
964  [self setThemeState:CPThemeStateDisabled];
965 }
966 
970 - (BOOL)isEnabled
971 {
972  return ![self hasThemeState:CPThemeStateDisabled];
973 }
974 
980 - (void)highlight:(BOOL)shouldHighlight
981 {
982  [self setHighlighted:shouldHighlight];
983 }
984 
990 - (void)setHighlighted:(BOOL)isHighlighted
991 {
992  if (isHighlighted)
993  [self setThemeState:CPThemeStateHighlighted];
994  else
995  [self unsetThemeState:CPThemeStateHighlighted];
996 }
997 
1001 - (BOOL)isHighlighted
1002 {
1003  return [self hasThemeState:CPThemeStateHighlighted];
1004 }
1005 
1006 
1007 #pragma mark -
1008 #pragma mark Base writing direction
1009 
1014 - (void)setBaseWritingDirection:(CPWritingDirection)writingDirection
1015 {
1016  if (writingDirection == _baseWritingDirection)
1017  return;
1018 
1019  [self willChangeValueForKey:@"baseWritingDirection"];
1020  _baseWritingDirection = writingDirection;
1021  [self didChangeValueForKey:@"baseWritingDirection"];
1022 
1023 #if PLATFORM(DOM)
1024 
1025  var style;
1026 
1027  switch (_baseWritingDirection)
1028  {
1030  style = "initial";
1031  break;
1032 
1034  style = "ltr";
1035  break;
1036 
1038  style = "rtl";
1039  break;
1040 
1041  default:
1042  style = "initial";
1043  }
1044 
1045  _DOMElement.style.direction = style;
1046 #endif
1047 }
1048 
1049 @end
1050 
1052 {
1053  CPTrackingArea _controlTrackingArea;
1054 }
1055 
1056 - (void)updateTrackingAreas
1057 {
1058  if (_controlTrackingArea)
1059  [self removeTrackingArea:_controlTrackingArea];
1060 
1061  _controlTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
1062  options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
1063  owner:self
1064  userInfo:nil];
1065  [self addTrackingArea:_controlTrackingArea];
1066  [super updateTrackingAreas];
1067 }
1068 
1069 @end
1070 
1071 var CPControlActionKey = @"CPControlActionKey",
1072  CPControlControlSizeKey = @"CPControlControlSizeKey",
1073  CPControlControlStateKey = @"CPControlControlStateKey",
1074  CPControlFormatterKey = @"CPControlFormatterKey",
1075  CPControlIsEnabledKey = @"CPControlIsEnabledKey",
1076  CPControlSendActionOnKey = @"CPControlSendActionOnKey",
1077  CPControlSendsActionOnEndEditingKey = @"CPControlSendsActionOnEndEditingKey",
1078  CPControlTargetKey = @"CPControlTargetKey",
1079  CPControlValueKey = @"CPControlValueKey",
1080  CPControlBaseWrittingDirectionKey = @"CPControlBaseWrittingDirectionKey";
1081 
1082  __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
1083 
1084 @implementation CPControl (CPCoding)
1085 
1086 /*
1087  Initializes the control by unarchiving it from a coder.
1088 
1089  @param aCoder the coder from which to unarchive the control
1090  @return the initialized control
1091 */
1092 - (id)initWithCoder:(CPCoder)aCoder
1093 {
1094  self = [super initWithCoder:aCoder];
1095 
1096  if (self)
1097  {
1098  [self setObjectValue:[aCoder decodeObjectForKey:CPControlValueKey]];
1099 
1100  [self setTarget:[aCoder decodeObjectForKey:CPControlTargetKey]];
1101  [self setAction:[aCoder decodeObjectForKey:CPControlActionKey]];
1102 
1103  [self sendActionOn:[aCoder decodeIntForKey:CPControlSendActionOnKey]];
1104  [self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
1105 
1106  [self setFormatter:[aCoder decodeObjectForKey:CPControlFormatterKey]];
1107 
1108  [self setControlSize:[aCoder decodeIntForKey:CPControlControlSizeKey]];
1109 
1110  [self setBaseWritingDirection:[aCoder decodeIntForKey:CPControlBaseWrittingDirectionKey]];
1111  }
1112 
1113  return self;
1114 }
1115 
1116 /*
1117  Archives the control to the provided coder.
1118 
1119  @param aCoder the coder to which the control will be archived.
1120 */
1121 - (void)encodeWithCoder:(CPCoder)aCoder
1122 {
1123  [super encodeWithCoder:aCoder];
1124 
1125  if (_sendsActionOnEndEditing)
1126  [aCoder encodeBool:_sendsActionOnEndEditing forKey:CPControlSendsActionOnEndEditingKey];
1127 
1128  var objectValue = [self objectValue];
1129 
1130  if (objectValue !== nil)
1131  [aCoder encodeObject:objectValue forKey:CPControlValueKey];
1132 
1133  if (_target !== nil)
1134  [aCoder encodeConditionalObject:_target forKey:CPControlTargetKey];
1135 
1136  if (_action !== nil)
1137  [aCoder encodeObject:_action forKey:CPControlActionKey];
1138 
1139  [aCoder encodeInt:_sendActionOn forKey:CPControlSendActionOnKey];
1140 
1141  if (_formatter !== nil)
1142  [aCoder encodeObject:_formatter forKey:CPControlFormatterKey];
1143 
1144  [aCoder encodeInt:_controlSize forKey:CPControlControlSizeKey];
1145 
1146  [aCoder encodeInt:_baseWritingDirection forKey:CPControlBaseWrittingDirectionKey];
1147 
1148 }
1149 
1150 @end
1151 
1152 var _CPControlSizeIdentifiers = [],
1153  _CPControlCachedColorWithPatternImages = {},
1154  _CPControlCachedThreePartImagePattern = {};
1155 
1156 _CPControlSizeIdentifiers[CPRegularControlSize] = "Regular";
1157 _CPControlSizeIdentifiers[CPSmallControlSize] = "Small";
1158 _CPControlSizeIdentifiers[CPMiniControlSize] = "Mini";
1159 
1160 function _CPControlIdentifierForControlSize(aControlSize)
1161 {
1162  return _CPControlSizeIdentifiers[aControlSize];
1163 }
1164 
1165 function _CPControlColorWithPatternImage(sizes, aClassName)
1166 {
1167  var index = 1,
1168  count = arguments.length,
1169  identifier = "";
1170 
1171  for (; index < count; ++index)
1172  identifier += arguments[index];
1173 
1174  var color = _CPControlCachedColorWithPatternImages[identifier];
1175 
1176  if (!color)
1177  {
1178  var bundle = [CPBundle bundleForClass:[CPControl class]];
1179 
1180  color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + ".png"] size:sizes[identifier]]];
1181 
1182  _CPControlCachedColorWithPatternImages[identifier] = color;
1183  }
1184 
1185  return color;
1186 }
1187 
1188 function _CPControlThreePartImagePattern(isVertical, sizes, aClassName)
1189 {
1190  var index = 2,
1191  count = arguments.length,
1192  identifier = "";
1193 
1194  for (; index < count; ++index)
1195  identifier += arguments[index];
1196 
1197  var color = _CPControlCachedThreePartImagePattern[identifier];
1198 
1199  if (!color)
1200  {
1201  var bundle = [CPBundle bundleForClass:[CPControl class]],
1202  path = aClassName + "/" + identifier;
1203 
1204  sizes = sizes[identifier];
1205 
1207  [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "0.png"] size:sizes[0]],
1208  [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "1.png"] size:sizes[1]],
1209  [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + "2.png"] size:sizes[2]]
1210  ] isVertical:isVertical]];
1211 
1212  _CPControlCachedThreePartImagePattern[identifier] = color;
1213  }
1214 
1215  return color;
1216 }
1217 
1219 
1223 - (CPFormatter)formatter
1224 {
1225  return _formatter;
1226 }
1227 
1231 - (void)setFormatter:(CPFormatter)aValue
1232 {
1233  _formatter = aValue;
1234 }
1235 
1239 - (BOOL)sendsActionOnEndEditing
1240 {
1241  return _sendsActionOnEndEditing;
1242 }
1243 
1247 - (void)setSendsActionOnEndEditing:(BOOL)aValue
1248 {
1249  _sendsActionOnEndEditing = aValue;
1250 }
1251 
1255 - (CPWritingDirection)baseWritingDirection
1256 {
1257  return _baseWritingDirection;
1258 }
1259 
1263 - (void)setBaseWritingDirection:(CPWritingDirection)aValue
1264 {
1265  _baseWritingDirection = aValue;
1266 }
1267 
1268 @end
id initWithFrame:(CGRect aFrame)
Definition: CPView.j:351
Definition: CPFont.h:2
CPControlSelectedBackgroundColor
Definition: CPControl.j:82
CPControlHighlightedBackgroundColor
Definition: CPControl.j:83
CPPeriodicMask
BOOL tracksMouseOutsideOfFrame()
Definition: CPControl.j:362
CPUpTextMovement
Definition: CPText.j:66
id initWithImageSlices:isVertical:(CPArray imageSlices, [isVertical] BOOL isVertical)
Definition: CPImage.j:750
void setAction:(SEL anAction)
Definition: CPControl.j:282
BOOL isEnabled()
Definition: CPControl.j:970
BOOL setThemeState:(ThemeState aState)
Definition: CPView.j:3255
FrameUpdater prototype identifier
CPThemeStateControlSizeMini
Definition: CPTheme.j:630
void trackMouse:(CPEvent anEvent)
Definition: CPControl.j:367
void postNotificationName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
An object representation of nil.
Definition: CPNull.h:2
id initWithCoder:(CPCoder aCoder)
Definition: CPView.j:3696
CPImageAbove
Definition: CPControl.j:74
CPScaleToFit
Definition: CPControl.j:60
CPFont systemFontOfSize:(CGSize aSize)
Definition: CPFont.j:282
void setTarget:(id aTarget)
Definition: CPControl.j:300
CPColor colorWithPatternImage:(CPImage anImage)
Definition: CPColor.j:482
CPEscapeKeyCode
Definition: CPResponder.j:29
BOOL startTrackingAt:(CGPoint aPoint)
Definition: CPControl.j:468
CPScaleNone
Definition: CPControl.j:61
CPLineBreakByTruncatingHead
Definition: CPControl.j:48
CPWritingDirectionRightToLeft
Definition: CPText.j:73
void setBaseWritingDirection:(CPWritingDirection writingDirection)
Definition: CPControl.j:1014
CPTabTextMovement
Definition: CPText.j:62
CPMiniControlSize
Definition: CPControl.j:42
CPInteger nextState()
Definition: CPControl.j:419
CGPoint locationInWindow()
Definition: CPEvent.j:290
CPReturnTextMovement
Definition: CPText.j:61
CPLineBreakByCharWrapping
Definition: CPControl.j:46
CPSmallControlSize
Definition: CPControl.j:41
void setIntValue:(int anObject)
Definition: CPControl.j:588
CPLeftMouseUpMask
CPLeftTextMovement
Definition: CPText.j:64
void setControlSize:(CPControlSize aControlSize)
Definition: CPControl.j:211
CPEventType type()
Definition: CPEvent.j:325
int sendActionOn:(int mask)
Definition: CPControl.j:329
unsigned modifierFlags()
Definition: CPEvent.j:309
CPImageScaleProportionallyDown
Definition: CPControl.j:63
void setValue:forThemeAttribute:(id aValue, [forThemeAttribute] CPString aName)
Definition: CPView.j:3384
CPNotificationCenter defaultCenter()
void setFormatter:(CPFormatter aValue)
Definition: CPControl.j:1231
A mutable key-value pair collection.
Definition: CPDictionary.h:2
function ThemeState(stateNames)
Definition: CPTheme.j:379
CPImageScaleAxesIndependently
Definition: CPControl.j:64
CPImageScaleNone
Definition: CPControl.j:65
CGRect bounds()
Definition: CALayer.j:203
CPLineBreakByTruncatingMiddle
Definition: CPControl.j:50
CPImageLeft
Definition: CPControl.j:71
CPControlTextDidChangeNotification
Definition: CPControl.j:87
CPColor blackColor()
Definition: CPColor.j:284
CPDownTextMovement
Definition: CPText.j:67
CPReturnKeyCode
Definition: CPResponder.j:28
CPMixedState
Definition: CPControl.j:79
An immutable string (collection of characters).
Definition: CPString.h:2
CPNull null()
Definition: CPNull.j:51
CGPoint convertPoint:fromView:(CGPoint aPoint, [fromView] CPView aView)
Definition: CPView.j:2249
CPCellImagePosition CPNoImage
Definition: CPControl.j:69
Definition: CPImage.h:2
var CPControlControlStateKey
Definition: CPControl.j:1073
BOOL sendAction:to:(SEL anAction, [to] id anObject)
Definition: CPControl.j:319
SEL action()
Definition: CPControl.j:290
CPLineBreakByClipping
Definition: CPControl.j:47
void setFloatValue:(float aValue)
Definition: CPControl.j:554
CPImageOnly
Definition: CPControl.j:70
var CPControlBlackColor
Definition: CPControl.j:90
id initWithContentsOfFile:size:(CPString aFilename, [size] CGSize aSize)
Definition: CPImage.j:176
var CPControlTargetKey
Definition: CPControl.j:1078
CPFormatter is an abstract class that declares an interface for objects that create, interpret, and validate the textual representation of cell contents. The Foundation framework provides two concrete subclasses of CPFormatter to generate these objects: CPNumberFormatter and CPDateFormatter.
Definition: CPFormatter.h:2
CPControlDisabledBackgroundColor
Definition: CPControl.j:84
CPBinder getBinding:forObject:(CPString aBinding, [forObject] id anObject)
void setNeedsDisplay:(BOOL aFlag)
Definition: CPView.j:2597
CPLeftArrowKeyCode
Definition: CPResponder.j:33
void setObjectValue:(id anObject)
Definition: CPControl.j:534
CPRightArrowKeyCode
Definition: CPResponder.j:35
void encodeWithCoder:(CPCoder aCoder)
Definition: CPView.j:3806
CPUpArrowKeyCode
Definition: CPResponder.j:34
CPDownArrowKeyCode
Definition: CPResponder.j:36
CPLeftMouseUp
CPShiftKeyMask
CPVerticalTextAlignment CPTopVerticalTextAlignment
Definition: CPControl.j:53
void setStringValue:(CPString aString)
Definition: CPControl.j:629
A notification that can be posted to a CPNotificationCenter.
Definition: CPNotification.h:2
void setHighlighted:(BOOL isHighlighted)
Definition: CPControl.j:990
CPTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:(CPTimeInterval seconds, [target] id aTarget, [selector] SEL aSelector, [userInfo] id userInfo, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:58
CPLineBreakByTruncatingTail
Definition: CPControl.j:49
CPRightTextMovement
Definition: CPText.j:65
BOOL continueTracking:at:(CGPoint lastPoint, [at] CGPoint aPoint)
Definition: CPControl.j:475
void setNeedsLayout()
Definition: CPView.j:2748
CPImageScaling CPScaleProportionally
Definition: CPControl.j:59
id target()
Definition: CPControl.j:308
CPWritingDirectionLeftToRight
Definition: CPText.j:72
var CPControlValueKey
Definition: CPControl.j:1079
void highlight:(BOOL shouldHighlight)
Definition: CPControl.j:980
CPOtherTextMovement
Definition: CPText.j:60
CPBottomVerticalTextAlignment
Definition: CPControl.j:55
CPImageOverlaps
Definition: CPControl.j:75
var CPControlSendsActionOnEndEditingKey
Definition: CPControl.j:1077
void setSendsActionOnEndEditing:(BOOL aValue)
Definition: CPControl.j:1247
CPControlNormalBackgroundColor
Definition: CPControl.j:81
A timer object that can send a message after the given time interval.
Definition: CPTimer.h:2
CPLeftMouseDragged
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
void updateTrackingAreas()
Definition: CPView.j:3599
CPLeftMouseDraggedMask
CPDictionary userInfo()
CPControlSize CPRegularControlSize
Definition: CPControl.j:40
BOOL unsetThemeState:(ThemeState aState)
Definition: CPView.j:3268
Sends messages (CPNotification) between objects.
var CPControlSendActionOnKey
Definition: CPControl.j:1076
void addTrackingArea:(CPTrackingArea trackingArea)
Definition: CPView.j:3552
CPImageRight
Definition: CPControl.j:72
var CPControlFormatterKey
Definition: CPControl.j:1074
CPControlTextDidEndEditingNotification
Definition: CPControl.j:88
var CPControlActionKey
Definition: CPControl.j:1071
CPTextAlignment CPLeftTextAlignment
Definition: CPText.j:76
CPLeftMouseDown
CPControlTextDidBeginEditingNotification
Definition: CPControl.j:86
CPBundle bundleForClass:(Class aClass)
Definition: CPBundle.j:77
CPLineBreakMode CPLineBreakByWordWrapping
Definition: CPControl.j:45
CPCancelTextMovement
Definition: CPText.j:68
var CPControlBaseWrittingDirectionKey
Definition: CPControl.j:1080
Definition: CPEvent.h:2
CPThemeStateControlSizeSmall
Definition: CPTheme.j:629
CPThemeStateControlSizeRegular
Definition: CPTheme.j:628
CPImageBelow
Definition: CPControl.j:73
void setDoubleValue:(double anObject)
Definition: CPControl.j:571
CPTrackingArea initWithRect:options:owner:userInfo:(CGRect aRect, [options] CPTrackingAreaOptions options, [owner] id owner, [userInfo] CPDictionary userInfo)
void setIntegerValue:(int anObject)
Definition: CPControl.j:605
CPOffState
Definition: CPControl.j:78
CPTabKeyCode
Definition: CPResponder.j:27
var CPControlIsEnabledKey
Definition: CPControl.j:1075
CPOnState
Definition: CPControl.j:77
void setState:(CPInteger state)
Definition: CPControl.j:415
CPWritingDirection CPWritingDirectionNatural
Definition: CPText.j:71
var CPControlControlSizeKey
Definition: CPControl.j:1072
CPImageScaleProportionallyUpOrDown
Definition: CPControl.j:66
id objectValue()
Definition: CPControl.j:526
void removeTrackingArea:(CPTrackingArea trackingArea)
Definition: CPView.j:3570
void stopTracking:at:mouseIsUp:(CGPoint lastPoint, [at] CGPoint aPoint, [mouseIsUp] BOOL mouseIsUp)
Definition: CPControl.j:480
CPCenterVerticalTextAlignment
Definition: CPControl.j:54
id alloc()
Definition: CPObject.j:130
CPBacktabTextMovement
Definition: CPText.j:63
Definition: CPView.j:137