API  0.9.10
CPTheme.j
Go to the documentation of this file.
1 /*
2  * CPTheme.j
3  * AppKit
4  *
5  * Created by Francisco Tolmasky.
6  * Copyright 2009, 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 var CPThemesByName = { },
28 
29 
33 @implementation CPTheme : CPObject
34 {
35  CPString _name;
36  CPDictionary _attributes;
37 }
38 
39 + (void)setDefaultTheme:(CPTheme)aTheme
40 {
41  CPThemeDefaultTheme = aTheme;
42 }
43 
45 {
46  return CPThemeDefaultTheme;
47 }
48 
53 + (void)setDefaultHudTheme:(CPTheme)aTheme
54 {
55  CPThemeDefaultHudTheme = aTheme;
56 }
57 
64 {
68 }
69 
70 + (CPTheme)themeNamed:(CPString)aName
71 {
72  return CPThemesByName[aName];
73 }
74 
75 - (id)initWithName:(CPString)aName
76 {
77  self = [super init];
78 
79  if (self)
80  {
81  _name = aName;
82  _attributes = @{};
83 
84  CPThemesByName[_name] = self;
85  }
86 
87  return self;
88 }
89 
91 {
92  return _name;
93 }
94 
103 - (CPArray)classNames
104 {
105  return [_attributes allKeys];
106 }
107 
118 - (CPDictionary)attributesForClass:(id)aClass
119 {
120  if (!aClass)
121  return nil;
122 
123  var className = nil;
124 
125  if ([aClass isKindOfClass:[CPString class]])
126  {
127  // See if it is a class name
128  var theClass = CPClassFromString(aClass);
129 
130  if (theClass)
131  aClass = theClass;
132  else
133  className = aClass;
134  }
135 
136  if (!className)
137  {
138  if ([aClass respondsToSelector:@selector(defaultThemeClass)])
139  {
140  className = [aClass defaultThemeClass];
141  }
142  else if ([aClass respondsToSelector:@selector(themeClass)])
143  {
144  CPLog.warn(@"%@ themeClass is deprecated in favor of defaultThemeClass", CPStringFromClass(aClass));
145  className = [aClass themeClass];
146  }
147  else
148  {
149  return nil;
150  }
151  }
152 
153  return [_attributes objectForKey:className];
154 }
155 
172 - (CPDictionary)attributeNamesForClass:(id)aClass
173 {
174  var attributes = [self attributesForClass:aClass];
175 
176  if (attributes)
177  return [attributes allKeys];
178  else
179  return [CPArray array];
180 }
181 
195 - (_CPThemeAttribute)attributeWithName:(CPString)aName forClass:(id)aClass
196 {
197  var attributes = [self attributesForClass:aClass];
198 
199  if (!attributes)
200  return nil;
201 
202  return [attributes objectForKey:aName];
203 }
204 
218 - (id)valueForAttributeWithName:(CPString)aName forClass:(id)aClass
219 {
220  return [self valueForAttributeWithName:aName inState:CPThemeStateNormal forClass:aClass];
221 }
222 
236 - (id)valueForAttributeWithName:(CPString)aName inState:(ThemeState)aState forClass:(id)aClass
237 {
238  var attribute = [self attributeWithName:aName forClass:aClass];
239 
240  if (!attribute)
241  return nil;
242 
243  return [attribute valueForState:aState];
244 }
245 
246 - (void)takeThemeFromObject:(id)anObject
247 {
248  var attributes = [anObject _themeAttributeDictionary],
249  attributeName = nil,
250  attributeNames = [attributes keyEnumerator],
251  objectThemeClass = [anObject themeClass];
252 
253  while ((attributeName = [attributeNames nextObject]) !== nil)
254  [self _recordAttribute:[attributes objectForKey:attributeName] forClass:objectThemeClass];
255 }
256 
257 - (void)_recordAttribute:(_CPThemeAttribute)anAttribute forClass:(CPString)aClass
258 {
259  if (![anAttribute hasValues])
260  return;
261 
262  var attributes = [_attributes objectForKey:aClass];
263 
264  if (!attributes)
265  {
266  attributes = @{};
267 
268  [_attributes setObject:attributes forKey:aClass];
269  }
270 
271  var name = [anAttribute name],
272  existingAttribute = [attributes objectForKey:name];
273 
274  if (existingAttribute)
275  [attributes setObject:[existingAttribute attributeMergedWithAttribute:anAttribute] forKey:name];
276  else
277  [attributes setObject:anAttribute forKey:name];
278 }
279 
280 @end
281 
282 var CPThemeNameKey = @"CPThemeNameKey",
283  CPThemeAttributesKey = @"CPThemeAttributesKey";
284 
285 @implementation CPTheme (CPCoding)
286 
287 - (id)initWithCoder:(CPCoder)aCoder
288 {
289  self = [super init];
290 
291  if (self)
292  {
293  _name = [aCoder decodeObjectForKey:CPThemeNameKey];
294  _attributes = [aCoder decodeObjectForKey:CPThemeAttributesKey];
295 
296  CPThemesByName[_name] = self;
297  }
298 
299  return self;
300 }
301 
302 - (void)encodeWithCoder:(CPCoder)aCoder
303 {
304  [aCoder encodeObject:_name forKey:CPThemeNameKey];
305  [aCoder encodeObject:_attributes forKey:CPThemeAttributesKey];
306 }
307 
308 @end
309 
314 function ThemeState(stateNames)
315 {
316  var stateNameKeys = [];
317  this._stateNames = {};
318 
319  for (var key in stateNames)
320  {
321  if (!stateNames.hasOwnProperty(key))
322  continue;
323 
324  if (key !== 'normal')
325  {
326  this._stateNames[key] = true;
327  stateNameKeys.push(key);
328  }
329  }
330 
331  if (stateNameKeys.length === 0)
332  {
333  stateNameKeys.push('normal');
334  this._stateNames['normal'] = true;
335  }
336 
337  stateNameKeys.sort();
338  this._stateNameString = stateNameKeys[0];
339 
340  var stateNameLength = stateNameKeys.length;
341 
342  for (var stateIndex = 1; stateIndex < stateNameLength; stateIndex++)
343  this._stateNameString = this._stateNameString + "+" + stateNameKeys[stateIndex];
344 
345  this._stateNameCount = stateNameLength;
346 }
347 
348 ThemeState.prototype.toString = function()
349 {
350  return this._stateNameString;
351 }
352 
353 ThemeState.prototype.hasThemeState = function(aState)
354 {
355  if (!aState || !aState._stateNames)
356  return false;
357 
358  // We can do this in O(n) because both states have their stateNames already sorted.
359  for (var stateName in aState._stateNames)
360  {
361  if (!aState._stateNames.hasOwnProperty(stateName))
362  continue;
363 
364  if (!this._stateNames[stateName])
365  return false;
366  }
367  return true;
368 }
369 
370 ThemeState.prototype.isSubsetOf = function(aState)
371 {
372  if (aState._stateNameCount < this._stateNameCount)
373  return false;
374 
375  for (var key in this._stateNames)
376  {
377  if (!this._stateNames.hasOwnProperty(key))
378  continue;
379 
380  if (!aState._stateNames[key])
381  return false;
382  }
383  return true;
384 }
385 
386 ThemeState.prototype.without = function(aState)
387 {
388  if (!aState || aState === [CPNull null])
389  return this;
390 
391  var firstTransform = CPThemeWithoutTransform[this._stateNameString],
392  result;
393 
394  if (firstTransform)
395  {
396  result = firstTransform[aState._stateNameString];
397 
398  if (result)
399  return result;
400  }
401 
402  var newStates = {};
403 
404  for (var stateName in this._stateNames)
405  {
406  if (!this._stateNames.hasOwnProperty(stateName))
407  continue;
408 
409  if (!aState._stateNames[stateName])
410  newStates[stateName] = true;
411  }
412 
413  result = ThemeState._cacheThemeState(new ThemeState(newStates));
414 
415  if (!firstTransform)
416  firstTransform = CPThemeWithoutTransform[this._stateNameString] = {};
417 
418  firstTransform[aState._stateNameString] = result;
419 
420  return result;
421 }
422 
423 ThemeState.prototype.and = function(aState)
424 {
425  var firstTransform = CPThemeAndTransform[this._stateNameString],
426  result;
427 
428  if (firstTransform)
429  {
430  result = firstTransform[aState._stateNameString];
431 
432  if (result)
433  return result;
434  }
435 
436  result = CPThemeState(this, aState);
437 
438  if (!firstTransform)
439  firstTransform = CPThemeAndTransform[this._stateNameString] = {};
440 
441  firstTransform[aState._stateNameString] = result;
442 
443  return result;
444 }
445 
446 var CPThemeStates = {},
449 
450 ThemeState._cacheThemeState = function(aState)
451 {
452  // We do this caching so themeState equality works. Basically, doing CPThemeState('foo+bar') === CPThemeState('bar', 'foo') will return true.
453  var themeState = CPThemeStates[String(aState)];
454 
455  if (themeState === undefined)
456  {
457  themeState = aState;
458  CPThemeStates[String(themeState)] = themeState;
459  }
460 
461  return themeState;
462 }
463 
472 function CPThemeState()
473 {
474  if (arguments.length < 1)
475  throw "CPThemeState() must be called with at least one string argument";
476 
477  var themeState;
478 
479  if (arguments.length === 1 && typeof arguments[0] === 'string')
480  {
481  themeState = CPThemeStates[arguments[0]];
482 
483  if (themeState !== undefined)
484  return themeState;
485  }
486 
487  var stateNames = {};
488 
489  for (var argIndex = 0; argIndex < arguments.length; argIndex++)
490  {
491  if (arguments[argIndex] === [CPNull null] || !arguments[argIndex])
492  continue;
493 
494  if (typeof arguments[argIndex] === 'object')
495  {
496  for (var stateName in arguments[argIndex]._stateNames)
497  {
498  if (!arguments[argIndex]._stateNames.hasOwnProperty(stateName))
499  continue;
500 
501  stateNames[stateName] = true;
502  }
503  }
504  else
505  {
506  var allNames = arguments[argIndex].split('+');
507 
508  for (var nameIndex = 0; nameIndex < allNames.length; nameIndex++)
509  stateNames[allNames[nameIndex]] = true;
510  }
511  }
512 
513  themeState = ThemeState._cacheThemeState(new ThemeState(stateNames));
514  return themeState;
515 }
516 
517 @implementation _CPThemeKeyedUnarchiver : CPKeyedUnarchiver
518 {
519  CPBundle _bundle;
520 }
521 
522 - (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle
523 {
524  self = [super initForReadingWithData:data];
525 
526  if (self)
527  _bundle = aBundle;
528 
529  return self;
530 }
531 
532 - (CPBundle)bundle
533 {
534  return _bundle;
535 }
536 
537 - (BOOL)awakenCustomResources
538 {
539  return YES;
540 }
541 
542 @end
543 
544 CPThemeStateNormal = CPThemeState("normal");
545 CPThemeStateDisabled = CPThemeState("disabled");
546 CPThemeStateHovered = CPThemeState("hovered");
547 CPThemeStateHighlighted = CPThemeState("highlighted");
548 CPThemeStateSelected = CPThemeState("selected");
549 CPThemeStateTableDataView = CPThemeState("tableDataView");
550 CPThemeStateSelectedDataView = CPThemeState("selectedTableDataView");
551 CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
552 CPThemeStateBezeled = CPThemeState("bezeled");
553 CPThemeStateBordered = CPThemeState("bordered");
554 CPThemeStateEditable = CPThemeState("editable");
555 CPThemeStateEditing = CPThemeState("editing");
556 CPThemeStateVertical = CPThemeState("vertical");
557 CPThemeStateDefault = CPThemeState("default");
558 CPThemeStateCircular = CPThemeState("circular");
559 CPThemeStateAutocompleting = CPThemeState("autocompleting");
560 CPThemeStateFirstResponder = CPThemeState("firstResponder");
561 CPThemeStateMainWindow = CPThemeState("mainWindow");
562 CPThemeStateKeyWindow = CPThemeState("keyWindow");
563 CPThemeStateControlSizeRegular = CPThemeState("controlSizeRegular");
564 CPThemeStateControlSizeSmall = CPThemeState("controlSizeSmall");
565 CPThemeStateControlSizeMini = CPThemeState("controlSizeMini");
566 
567 CPThemeStateNormalString = String(CPThemeStateNormal);
568 
569 
570 @implementation _CPThemeAttribute : CPObject
571 {
572  CPString _name;
573  id _defaultValue;
574  CPDictionary _values;
575 
576  JSObject _cache;
577  _CPThemeAttribute _themeDefaultAttribute;
578 }
579 
580 - (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue defaultAttribute:(_CPThemeAttribute)aDefaultAttribute
581 {
582  self = [super init];
583 
584  if (self)
585  {
586  _cache = { };
587  _name = aName;
588  _defaultValue = aDefaultValue;
589 
590  if (aDefaultAttribute)
591  _themeDefaultAttribute = aDefaultAttribute;
592  }
593 
594  return self;
595 }
596 
597 - (CPString)name
598 {
599  return _name;
600 }
601 
602 - (id)defaultValue
603 {
604  return _defaultValue;
605 }
606 
607 - (BOOL)hasValues
608 {
609  return [_values count] > 0;
610 }
611 
612 - (_CPThemeAttribute)attributeBySettingValue:(id)aValue
613 {
614  var attribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue defaultAttribute:_themeDefaultAttribute];
615 
616  if (aValue !== undefined && aValue !== nil)
617  attribute._values = @{ CPThemeStateNormalString: aValue };
618 
619  return attribute;
620 }
621 
622 - (_CPThemeAttribute)attributeBySettingValue:(id)aValue forState:(ThemeState)aState
623 {
624  var shouldRemoveValue = aValue === undefined || aValue === nil,
625  attribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue defaultAttribute:_themeDefaultAttribute],
626  values = _values;
627 
628  if (values != null)
629  {
630  values = [values copy];
631 
632  if (shouldRemoveValue)
633  [values removeObjectForKey:String(aState)];
634  else
635  [values setObject:aValue forKey:String(aState)];
636 
637  attribute._values = values;
638  }
639  else if (!shouldRemoveValue)
640  {
641  values = [[CPDictionary alloc] init];
642  [values setObject:aValue forKey:String(aState)];
643  attribute._values = values;
644  }
645 
646  return attribute;
647 }
648 
649 - (id)value
650 {
651  return [self valueForState:CPThemeStateNormal];
652 }
653 
654 - (id)valueForState:(ThemeState)aState
655 {
656  var stateName = String(aState),
657  value = _cache[stateName];
658 
659  // This can be nil.
660  if (value !== undefined)
661  return value;
662 
663  value = [_values objectForKey:stateName];
664 
665  if (value === undefined || value === nil)
666  {
667  // If this is a composite state, find the closest partial subset match.
668  if (aState._stateNameCount > 1)
669  {
670  var states = [_values allKeys],
671  count = states ? states.length : 0,
672  largestThemeState = 0;
673 
674  while (count--)
675  {
676  var stateObject = CPThemeState(states[count]);
677 
678  if (stateObject.isSubsetOf(aState) && stateObject._stateNameCount > largestThemeState)
679  {
680  value = [_values objectForKey:states[count]];
681  largestThemeState = stateObject._stateNameCount;
682  }
683  }
684  }
685 
686  // Still don't have a value? OK, let's use the normal value.
687  if (value === undefined || value === nil)
688  value = [_values objectForKey:String(CPThemeStateNormal)];
689  }
690 
691  if (value === undefined || value === nil)
692  value = [_themeDefaultAttribute valueForState:aState];
693 
694  if (value === undefined || value === nil)
695  {
696  value = _defaultValue;
697 
698  // Class theme attributes cannot use nil because it's a dictionary.
699  // So transform CPNull into nil.
700  if (value === [CPNull null])
701  value = nil;
702  }
703 
704  _cache[stateName] = value;
705 
706  return value;
707 }
708 
709 - (_CPThemeAttribute)attributeBySettingParentAttribute:(_CPThemeAttribute)anAttribute
710 {
711  if (_themeDefaultAttribute === anAttribute)
712  return self;
713 
714  var attribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue defaultAttribute:anAttribute];
715 
716  attribute._values = [_values copy];
717 
718  return attribute;
719 }
720 
721 - (_CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
722 {
723  var mergedAttribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue defaultAttribute:_themeDefaultAttribute];
724 
725  mergedAttribute._values = [_values copy];
726 
727  if (anAttribute._values)
728  mergedAttribute._values ? [mergedAttribute._values addEntriesFromDictionary:anAttribute._values] : [anAttribute._values copy];
729 
730  return mergedAttribute;
731 }
732 
734 {
735  return [super description] + @" Name: " + _name + @", defaultAttribute: " + _themeDefaultAttribute + @", defaultValue: " + _defaultValue + @", values: " + _values;
736 }
737 
738 @end
739 
740 
741 // This is used to pass 'parrentAttribute' to the coder
743 
744 @implementation _CPThemeAttribute (CPCoding)
745 
746 - (id)initWithCoder:(CPCoder)aCoder
747 {
748  self = [super init];
749 
750  if (self)
751  {
752  _cache = {};
753 
754  _name = [aCoder decodeObjectForKey:@"name"];
755  _defaultValue = [aCoder decodeObjectForKey:@"defaultValue"];
756  _values = @{};
757  _themeDefaultAttribute = ParentAttributeForCoder;
758 
759  if ([aCoder containsValueForKey:@"value"])
760  {
761  var state;
762 
763  if ([aCoder containsValueForKey:@"state"])
764  state = [aCoder decodeObjectForKey:@"state"];
765  else
767 
768  [_values setObject:[aCoder decodeObjectForKey:"value"] forKey:state];
769  }
770  else
771  {
772  var encodedValues = [aCoder decodeObjectForKey:@"values"],
773  keys = [encodedValues allKeys],
774  count = keys.length;
775 
776  while (count--)
777  {
778  var key = keys[count];
779 
780  [_values setObject:[encodedValues objectForKey:key] forKey:key];
781  }
782  }
783  }
784 
785  return self;
786 }
787 
788 - (void)encodeWithCoder:(CPCoder)aCoder
789 {
790  [aCoder encodeObject:_name forKey:@"name"];
791  [aCoder encodeObject:_defaultValue forKey:@"defaultValue"];
792 
793  var keys = [_values allKeys],
794  count = keys ? keys.length : 0;
795 
796  if (count === 1)
797  {
798  var onlyKey = keys[0];
799 
800  if (onlyKey !== String(CPThemeStateNormal))
801  [aCoder encodeObject:onlyKey forKey:@"state"];
802 
803  [aCoder encodeObject:[_values objectForKey:onlyKey] forKey:@"value"];
804  }
805  else
806  {
807  var encodedValues = @{};
808 
809  while (count--)
810  {
811  var key = keys[count];
812 
813  [encodedValues setObject:[_values objectForKey:key] forKey:key];
814  }
815 
816  [aCoder encodeObject:encodedValues forKey:@"values"];
817  }
818 }
819 
820 @end
821 
822 function CPThemeAttributeEncode(aCoder, aThemeAttribute)
823 {
824  var values = aThemeAttribute._values,
825  count = [values count],
826  key = "$a" + [aThemeAttribute name];
827 
828  if (count === 1)
829  {
830  var state = [values allKeys][0];
831 
832  if (state === CPThemeStateNormalString)
833  {
834  [aCoder encodeObject:[values objectForKey:state] forKey:key];
835 
836  return YES;
837  }
838  }
839 
840  if (count >= 1)
841  {
842  [aCoder encodeObject:aThemeAttribute forKey:key];
843 
844  return YES;
845  }
846 
847  return NO;
848 }
849 
850 function CPThemeAttributeDecode(aCoder, attribute)
851 {
852  var key = "$a" + attribute._name;
853 
854  if ([aCoder containsValueForKey:key])
855  {
856  ParentAttributeForCoder = attribute._themeDefaultAttribute;
857 
858  var decodedAttribute = [aCoder decodeObjectForKey:key];
859 
861 
862  if (!decodedAttribute || !decodedAttribute.isa || ![decodedAttribute isKindOfClass:[_CPThemeAttribute class]])
863  attribute = [attribute attributeBySettingValue:decodedAttribute];
864  else
865  attribute = decodedAttribute;
866  }
867 
868  return attribute;
869 }
870 
871 /* TO AUTO CREATE THESE:
872 function bit_count(bits)
873  {
874  var count = 0;
875 
876  while (bits)
877  {
878  ++count;
879  bits &= (bits - 1);
880  }
881 
882  return count ;
883  }
884 
885 zeros = "000000000";
886 
887 function pad(string, digits)
888 {
889  return zeros.substr(0, digits - string.length) + string;
890 }
891 
892 var str = ""
893 str += '[';
894 for (i = 0;i < Math.pow(2,6);++i)
895 {
896  str += bit_count(i) + " /*" + pad(i.toString(2),6) + "*" + "/, ";
897 }
898 print(str+']');
899 
900 */
CPThemeStateEditing
Definition: CPTheme.j:555
CPThemeStateHovered
Definition: CPTheme.j:546
CPThemeStateSelected
Definition: CPTheme.j:548
CPTheme defaultHudTheme()
Definition: CPTheme.j:63
function CPStringFromClass(aClass)
Definition: CPObjJRuntime.j:38
CPThemeStateControlSizeMini
Definition: CPTheme.j:565
An object representation of nil.
Definition: CPNull.h:2
ThemeState prototype CPThemeWithoutTransform
Definition: CPTheme.j:447
id valueForAttributeWithName:inState:forClass:(CPString aName, [inState] ThemeState aState, [forClass] id aClass)
Definition: CPTheme.j:236
CPThemeStateDefault
Definition: CPTheme.j:557
CPString className()
Definition: CPObject.j:527
CPArray classNames()
Definition: CPTheme.j:103
CPThemeStateNormalString
Definition: CPTheme.j:567
CPThemeStateAutocompleting
Definition: CPTheme.j:559
CPThemeStateEditable
Definition: CPTheme.j:554
A Cappuccino wrapper for any data type.
Definition: CPData.h:2
Unarchives objects created using CPKeyedArchiver.
CPString name()
Definition: CPTheme.j:90
CPString description()
Definition: CPObject.j:358
A mutable key-value pair collection.
Definition: CPDictionary.h:2
function ThemeState(stateNames)
Definition: CPTheme.j:314
var CPThemeDefaultHudTheme
Definition: CPTheme.j:27
var CPThemeNameKey
Definition: CPTheme.j:282
CPThemeStateMainWindow
Definition: CPTheme.j:561
CPThemeStateTableDataView
Definition: CPTheme.j:549
CPThemeStateDisabled
Definition: CPTheme.j:545
CPThemeStateBezeled
Definition: CPTheme.j:552
An immutable string (collection of characters).
Definition: CPString.h:2
CPThemeStateCircular
Definition: CPTheme.j:558
function CPThemeAttributeDecode(aCoder, attribute)
Definition: CPTheme.j:850
_CPThemeAttribute attributeWithName:forClass:(CPString aName, [forClass] id aClass)
Definition: CPTheme.j:195
CPThemeStateBordered
Definition: CPTheme.j:553
CPThemeStateSelectedDataView
Definition: CPTheme.j:550
CPTheme defaultTheme()
Definition: CPTheme.j:44
function CPThemeAttributeEncode(aCoder, aThemeAttribute)
Definition: CPTheme.j:822
CPDictionary attributesForClass:(id aClass)
Definition: CPTheme.j:118
CPThemeStateVertical
Definition: CPTheme.j:556
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
CPThemeStateHighlighted
Definition: CPTheme.j:547
CPThemeStateFirstResponder
Definition: CPTheme.j:560
id init()
Definition: CPObject.j:145
Definition: CPTheme.h:2
CPTheme themeNamed:(CPString aName)
Definition: CPTheme.j:70
var ParentAttributeForCoder
Definition: CPTheme.j:742
CPThemeStateControlSizeSmall
Definition: CPTheme.j:564
CPThemeStateControlSizeRegular
Definition: CPTheme.j:563
ThemeState prototype CPThemeAndTransform
Definition: CPTheme.j:448
var CPThemeAttributesKey
Definition: CPTheme.j:283
var CPThemesByName
Definition: CPTheme.j:25
CPThemeStateGroupRow
Definition: CPTheme.j:551
function CPClassFromString(aClassName)
Definition: CPObjJRuntime.j:33
var CPThemeDefaultTheme
Definition: CPTheme.j:26
CPThemeStateKeyWindow
Definition: CPTheme.j:562