API  1.0.0
CPView.j
Go to the documentation of this file.
1 /*
2  * CPView.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 
26 @global appkit_tag_dom_elements
27 
28 @typedef _CPViewFullScreenModeState
29 
30 #if PLATFORM(DOM)
31 
32 if (typeof(appkit_tag_dom_elements) !== "undefined" && appkit_tag_dom_elements)
33 {
34  AppKitTagDOMElement = function(owner, element)
35  {
36  element.setAttribute("data-cappuccino-view", [owner className]);
37  element.setAttribute("data-cappuccino-uid", [owner UID]);
38  }
39 }
40 else
41 {
42  AppKitTagDOMElement = function(owner, element)
43  {
44  // By default, do nothing.
45  }
46 }
47 
48 #endif
49 
50 /*
51  @global
52  @group CPViewAutoresizingMasks
53  The default resizingMask, the view will not resize or reposition itself.
54 */
56 /*
57  @global
58  @group CPViewAutoresizingMasks
59  Allow for flexible space on the left hand side of the view.
60 */
62 /*
63  @global
64  @group CPViewAutoresizingMasks
65  The view should grow and shrink horizontally with its parent view.
66 */
68 /*
69  @global
70  @group CPViewAutoresizingMasks
71  Allow for flexible space to the right hand side of the view.
72 */
74 /*
75  @global
76  @group CPViewAutoresizingMasks
77  Allow for flexible space above the view.
78 */
80 /*
81  @global
82  @group CPViewAutoresizingMasks
83  The view should grow and shrink vertically with its parent view.
84 */
86 /*
87  @global
88  @group CPViewAutoresizingMasks
89  Allow for flexible space below the view.
90 */
92 
93 _CPViewWillAppearNotification = @"CPViewWillAppearNotification";
94 _CPViewDidAppearNotification = @"CPViewDidAppearNotification";
95 _CPViewWillDisappearNotification = @"CPViewWillDisappearNotification";
96 _CPViewDidDisappearNotification = @"CPViewDidDisappearNotification";
97 
98 CPViewBoundsDidChangeNotification = @"CPViewBoundsDidChangeNotification";
99 CPViewFrameDidChangeNotification = @"CPViewFrameDidChangeNotification";
100 
102 
103 #if PLATFORM(DOM)
104 var DOMElementPrototype = nil,
105 
106  BackgroundTrivialColor = 0,
107  BackgroundVerticalThreePartImage = 1,
108  BackgroundHorizontalThreePartImage = 2,
109  BackgroundNinePartImage = 3,
110  BackgroundTransparentColor = 4,
111  BackgroundCSSStyling = 5;
112 #endif
113 
114 var CPViewFlags = { },
118 
120 
137 @implementation CPView : CPResponder <CPTheme>
138 {
139  CPWindow _window;
140 
141  CPView _superview;
142  CPArray _subviews;
143 
144  CPGraphicsContext _graphicsContext;
145 
146  int _tag;
147  CPString _identifier;
148 
149  CGRect _frame;
150  CGRect _bounds;
151  CGAffineTransform _boundsTransform;
152  CGAffineTransform _inverseBoundsTransform;
153 
154  CPSet _registeredDraggedTypes;
155  CPArray _registeredDraggedTypesArray;
156 
157  BOOL _isHidden;
158  BOOL _isHiddenOrHasHiddenAncestor;
159  BOOL _hitTests;
160  BOOL _clipsToBounds;
161 
162  BOOL _postsFrameChangedNotifications;
163  BOOL _postsBoundsChangedNotifications;
164  BOOL _inhibitFrameAndBoundsChangedNotifications;
165  BOOL _inLiveResize;
166  BOOL _isSuperviewAClipView;
167 
168 #if PLATFORM(DOM)
169  DOMElement _DOMElement;
170  DOMElement _DOMContentsElement;
171 
172  CPArray _DOMImageParts;
173  CPArray _DOMImageSizes;
174 
175  unsigned _backgroundType;
176 
177  // CSS styling
178  CPArray _cssStylePreviousState;
179  DOMElement _cssStyleNode;
180 #endif
181 
182  CGRect _dirtyRect;
183 
184  float _opacity;
185  CPColor _backgroundColor;
186 
187  BOOL _autoresizesSubviews;
188  unsigned _autoresizingMask;
189 
190  CALayer _layer;
191  BOOL _wantsLayer;
192 
193  // Full Screen State
194  BOOL _isInFullScreenMode;
195 
196  _CPViewFullScreenModeState _fullScreenModeState;
197 
198  // Zoom Support
199  BOOL _isScaled;
200  CGSize _hierarchyScaleSize;
201  CGSize _scaleSize;
202 
203  // Drawing high DPI
204  BOOL _needToSetTransformMatrix;
205  float _highDPIRatio;
206 
207  // Layout Support
208  BOOL _needsLayout;
209  JSObject _ephemeralSubviews;
210 
211  JSObject _ephemeralSubviewsForNames;
212  CPSet _ephereralSubviews;
213 
214  // Key View Support
215  CPView _nextKeyView;
216  CPView _previousKeyView;
217 
218  unsigned _viewClassFlags;
219 
220  // ToolTips
221  CPString _toolTip;
222  Function _toolTipFunctionIn;
223  Function _toolTipFunctionOut;
224  BOOL _toolTipInstalled;
225 
226  BOOL _isObserving;
227 
228  BOOL _allowsVibrancy;
229  CPAppearance _appearance;
230  CPAppearance _effectiveAppearance;
231 
232  CPMutableArray _trackingAreas;
233  BOOL _inhibitUpdateTrackingAreas;
234 
235  id _animator;
236  CPDictionary _animationsDictionary;
237  BOOL _inhibitDOMUpdates;
238  BOOL _forceUpdates;
239 }
240 
241 /*
242  Private method for Objective-J.
243  @ignore
244 */
245 + (void)initialize
246 {
247  if (self !== [CPView class])
248  return;
249 
250 #if PLATFORM(DOM)
251  DOMElementPrototype = document.createElement("div");
252 
253  var style = DOMElementPrototype.style;
254 
255  style.overflow = "hidden";
256  style.position = "absolute";
257  style.visibility = "visible";
258  style.zIndex = 0;
259 #endif
260 
262 }
263 
264 + (Class)_binderClassForBinding:(CPString)aBinding
265 {
266  if ([aBinding hasPrefix:CPHiddenBinding])
267  return [CPMultipleValueOrBinding class];
268 
269  return [super _binderClassForBinding:aBinding];
270 }
271 
276 + (void)setHighDPIDrawingEnabled:(BOOL)isEnabled
277 {
278  CPViewHighDPIDrawingEnabled = isEnabled;
279 }
280 
285 + (BOOL)isHighDPIDrawingEnabled
286 {
288 }
289 
290 + (CPSet)keyPathsForValuesAffectingFrame
291 {
292  return [CPSet setWithObjects:@"frameOrigin", @"frameSize"];
293 }
294 
295 + (CPSet)keyPathsForValuesAffectingBounds
296 {
297  return [CPSet setWithObjects:@"boundsOrigin", @"boundsSize"];
298 }
299 
300 + (CPMenu)defaultMenu
301 {
302  return nil;
303 }
304 
305 + (CPString)defaultThemeClass
306 {
307  return @"view";
308 }
309 
310 + (CPDictionary)themeAttributes
311 {
312  return @{
313  @"css-based": NO
314  };
315 }
316 
317 - (void)_setupViewFlags
318 {
319  var theClass = [self class],
320  classUID = [theClass UID];
321 
322  if (CPViewFlags[classUID] === undefined)
323  {
324  var flags = 0;
325 
326  if ([theClass instanceMethodForSelector:@selector(drawRect:)] !== [CPView instanceMethodForSelector:@selector(drawRect:)]
327  || [theClass instanceMethodForSelector:@selector(viewWillDraw)] !== [CPView instanceMethodForSelector:@selector(viewWillDraw)])
328  flags |= CPViewHasCustomDrawRect;
329 
330  if ([theClass instanceMethodForSelector:@selector(viewWillLayout)] !== [CPView instanceMethodForSelector:@selector(viewWillLayout)])
332 
333  if ([theClass instanceMethodForSelector:@selector(layoutSubviews)] !== [CPView instanceMethodForSelector:@selector(layoutSubviews)])
335 
336  CPViewFlags[classUID] = flags;
337  }
338 
339  _viewClassFlags = CPViewFlags[classUID];
340 }
341 
342 - (id)init
343 {
344  return [self initWithFrame:CGRectMakeZero()];
345 }
346 
351 - (id)initWithFrame:(CGRect)aFrame
352 {
353  self = [super init];
354 
355  if (self)
356  {
357  var width = CGRectGetWidth(aFrame),
358  height = CGRectGetHeight(aFrame);
359 
360  _subviews = [];
361  _registeredDraggedTypes = [CPSet set];
362  _registeredDraggedTypesArray = [];
363 
364  _trackingAreas = [];
365 
366  _tag = -1;
367 
368  _frame = CGRectMakeCopy(aFrame);
369  _bounds = CGRectMake(0.0, 0.0, width, height);
370 
371  _autoresizingMask = CPViewNotSizable;
372  _autoresizesSubviews = YES;
373  _clipsToBounds = YES;
374 
375  _opacity = 1.0;
376  _isHidden = NO;
377  _isHiddenOrHasHiddenAncestor = NO;
378  _hitTests = YES;
379 
380  _hierarchyScaleSize = CGSizeMake(1.0 , 1.0);
381  _scaleSize = CGSizeMake(1.0, 1.0);
382  _isScaled = NO;
383 
384  _theme = [CPTheme defaultTheme];
385  _themeState = CPThemeStateNormal;
386 
387 #if PLATFORM(DOM)
388  _DOMElement = DOMElementPrototype.cloneNode(false);
389  AppKitTagDOMElement(self, _DOMElement);
390 
391  CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(aFrame), CGRectGetMinY(aFrame));
392  CPDOMDisplayServerSetStyleSize(_DOMElement, width, height);
393 
394  _DOMImageParts = [];
395  _DOMImageSizes = [];
396 
397  _cssStylePreviousState = @[];
398 #endif
399 
400  _animator = nil;
401  _animationsDictionary = @{};
402 
403  [self _setupViewFlags];
404  [self _loadThemeAttributes];
405 
406  _inhibitDOMUpdates = NO;
407  _forceUpdates = NO;
408 
409  // We force here an updateTrackingAreas in order to let the view install its own tracking areas
410  // in the case where an externally owned tracking area is installed on this view before putting
411  // it in the view hierarchy.
412  [self updateTrackingAreas];
413 }
414 
415  return self;
416 }
417 
423 - (void)setToolTip:(CPString)aToolTip
424 {
425  if (_toolTip === aToolTip)
426  return;
427 
428  if (aToolTip && ![aToolTip isKindOfClass:CPString])
429  aToolTip = [aToolTip description];
430 
431  _toolTip = aToolTip;
432 
433  [self _manageToolTipInstallation];
434 }
435 
436 - (void)_manageToolTipInstallation
437 {
438  if ([self window] && _toolTip)
439  [self _installToolTipEventHandlers];
440  else
441  [self _uninstallToolTipEventHandlers];
442 }
447 - (void)_installToolTipEventHandlers
448 {
449  if (_toolTipInstalled)
450  return;
451 
452  if (!_toolTipFunctionIn)
453  _toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; };
454 
455  if (!_toolTipFunctionOut)
456  _toolTipFunctionOut = function(e) { [_CPToolTip invalidateCurrentToolTipIfNeeded]; };
457 
458 #if PLATFORM(DOM)
459  if (_DOMElement.addEventListener)
460  {
461  _DOMElement.addEventListener("mouseover", _toolTipFunctionIn, YES);
462  _DOMElement.addEventListener("keypress", _toolTipFunctionOut, YES);
463  _DOMElement.addEventListener("mouseout", _toolTipFunctionOut, YES);
464  }
465  else if (_DOMElement.attachEvent)
466  {
467  _DOMElement.attachEvent("onmouseover", _toolTipFunctionIn);
468  _DOMElement.attachEvent("onkeypress", _toolTipFunctionOut);
469  _DOMElement.attachEvent("onmouseout", _toolTipFunctionOut);
470  }
471 #endif
472 
473  _toolTipInstalled = YES;
474 }
475 
480 - (void)_uninstallToolTipEventHandlers
481 {
482  if (!_toolTipInstalled)
483  return;
484 
485 #if PLATFORM(DOM)
486  if (_DOMElement.removeEventListener)
487  {
488  _DOMElement.removeEventListener("mouseover", _toolTipFunctionIn, YES);
489  _DOMElement.removeEventListener("keypress", _toolTipFunctionOut, YES);
490  _DOMElement.removeEventListener("mouseout", _toolTipFunctionOut, YES);
491  }
492  else if (_DOMElement.detachEvent)
493  {
494  _DOMElement.detachEvent("onmouseover", _toolTipFunctionIn);
495  _DOMElement.detachEvent("onkeypress", _toolTipFunctionOut);
496  _DOMElement.detachEvent("onmouseout", _toolTipFunctionOut);
497  }
498 #endif
499 
500  _toolTipFunctionIn = nil;
501  _toolTipFunctionOut = nil;
502 
503  _toolTipInstalled = NO;
504 }
505 
510 - (CPView)superview
511 {
512  return _superview;
513 }
514 
519 - (CPArray)subviews
520 {
521  return [_subviews copy];
522 }
523 
527 - (CPWindow)window
528 {
529  return _window;
530 }
531 
536 - (void)addSubview:(CPView)aSubview
537 {
538  [self _insertSubview:aSubview atIndex:CPNotFound];
539 }
540 
547 - (void)addSubview:(CPView)aSubview positioned:(CPWindowOrderingMode)anOrderingMode relativeTo:(CPView)anotherView
548 {
549  var index = anotherView ? [_subviews indexOfObjectIdenticalTo:anotherView] : CPNotFound;
550 
551  // In other words, if no view, then either all the way at the bottom or all the way at the top.
552  if (index === CPNotFound)
553  index = (anOrderingMode === CPWindowAbove) ? [_subviews count] : 0;
554 
555  // else, if we have a view, above if above.
556  else if (anOrderingMode === CPWindowAbove)
557  ++index;
558 
559  [self _insertSubview:aSubview atIndex:index];
560 }
561 
562 /* @ignore */
563 - (void)_insertSubview:(CPView)aSubview atIndex:(int)anIndex
564 {
565  if (aSubview === self)
566  [CPException raise:CPInvalidArgumentException reason:"can't add a view as a subview of itself"];
567 #if DEBUG
568  if (!aSubview._superview && _subviews.indexOf(aSubview) !== CPNotFound)
569  [CPException raise:CPInvalidArgumentException reason:"can't insert a subview in duplicate (probably partially decoded)"];
570 #endif
571 
572  // Notify the subview that it will be moving.
573  [aSubview viewWillMoveToSuperview:self];
574 
575  // We will have to adjust the z-index of all views starting at this index.
576  var count = _subviews.length,
577  lastWindow;
578 
579  // Dirty the key view loop, in case the window wants to auto recalculate it
580  [[self window] _dirtyKeyViewLoop];
581 
582  // If this is already one of our subviews, remove it.
583  if (aSubview._superview === self)
584  {
585  var index = [_subviews indexOfObjectIdenticalTo:aSubview];
586 
587  // FIXME: should this be anIndex >= count? (last one)
588  if (index === anIndex || index === count - 1 && anIndex === count)
589  return;
590 
591  [_subviews removeObjectAtIndex:index];
592 
593 #if PLATFORM(DOM)
594  CPDOMDisplayServerRemoveChild(_DOMElement, aSubview._DOMElement);
595 #endif
596 
597  if (anIndex > index)
598  --anIndex;
599 
600  //We've effectively made the subviews array shorter, so represent that.
601  --count;
602  }
603  else
604  {
605  var superview = aSubview._superview;
606 
607  lastWindow = [superview window];
608 
609  // Remove the view from its previous superview.
610  [aSubview _removeFromSuperview];
611 
612  [aSubview _postViewWillAppearNotification];
613  // Set ourselves as the superview.
614  [aSubview _setSuperview:self];
615  }
616 
617  if (anIndex === CPNotFound || anIndex >= count)
618  {
619  _subviews.push(aSubview);
620 
621 #if PLATFORM(DOM)
622  // Attach the actual node.
623  CPDOMDisplayServerAppendChild(_DOMElement, aSubview._DOMElement);
624 #endif
625  }
626  else
627  {
628  _subviews.splice(anIndex, 0, aSubview);
629 
630 #if PLATFORM(DOM)
631  // Attach the actual node.
632  CPDOMDisplayServerInsertBefore(_DOMElement, aSubview._DOMElement, _subviews[anIndex + 1]._DOMElement);
633 #endif
634  }
635 
636  [aSubview setNextResponder:self];
637  [aSubview _scaleSizeUnitSquareToSize:[self _hierarchyScaleSize]];
638 
639  [aSubview viewDidMoveToSuperview];
640 
641  // Set the subview's window to our own.
642  if (_window)
643  [aSubview _setWindow:_window];
644 
645  if (!_window && lastWindow)
646  [aSubview _setWindow:nil];
647 
648  // This method might be called before we are fully unarchived, in which case the theme state isn't set up yet
649  // and none of the below matters anyhow.
650  if (_themeState)
651  {
652  if ([self hasThemeState:CPThemeStateFirstResponder])
653  [aSubview _notifyViewDidBecomeFirstResponder];
654  else
655  [aSubview _notifyViewDidResignFirstResponder];
656 
657  if ([self hasThemeState:CPThemeStateKeyWindow])
658  [aSubview _notifyWindowDidBecomeKey];
659  else
660  [aSubview _notifyWindowDidResignKey];
661  }
662 
663  [self didAddSubview:aSubview];
664 }
665 
670 - (void)didAddSubview:(CPView)aSubview
671 {
672 }
673 
678 - (void)removeFromSuperview
679 {
680  var superview = _superview;
681 
682  [self viewWillMoveToSuperview:nil];
683  [self _removeFromSuperview];
684  [self viewDidMoveToSuperview];
685 
686  if (superview)
687  [self _setWindow:nil];
688 }
689 
690 - (void)_removeFromSuperview
691 {
692  if (!_superview)
693  return;
694 
695  // Dirty the key view loop, in case the window wants to auto recalculate it
696  [[self window] _dirtyKeyViewLoop];
697 
698  [_superview willRemoveSubview:self];
699  [self _postViewWillDisappearNotification];
700 
701  [_superview._subviews removeObjectIdenticalTo:self];
702 
703 #if PLATFORM(DOM)
704  CPDOMDisplayServerRemoveChild(_superview._DOMElement, _DOMElement);
705 #endif
706 
707  // If the view is not hidden and one of its ancestors is hidden,
708  // notify the view that it is now unhidden.
709  [self _setSuperview:nil];
710 
711  [self _notifyWindowDidResignKey];
712  [self _notifyViewDidResignFirstResponder];
713 }
714 
720 - (void)replaceSubview:(CPView)aSubview with:(CPView)aView
721 {
722  if (aSubview._superview !== self || aSubview === aView)
723  return;
724 
725  var index = [_subviews indexOfObjectIdenticalTo:aSubview];
726 
727  [self _insertSubview:aView atIndex:index];
728 
729  [aSubview removeFromSuperview];
730 }
731 
732 - (void)setSubviews:(CPArray)newSubviews
733 {
734  if (!newSubviews)
735  [CPException raise:CPInvalidArgumentException reason:"newSubviews cannot be nil in -[CPView setSubviews:]"];
736 
737  // Trivial Case 0: Same array somehow
738  if ([_subviews isEqual:newSubviews])
739  return;
740 
741  // Trivial Case 1: No current subviews, simply add all new subviews.
742  if ([_subviews count] === 0)
743  {
744  var index = 0,
745  count = [newSubviews count];
746 
747  for (; index < count; ++index)
748  [self addSubview:newSubviews[index]];
749 
750  return;
751  }
752 
753  // Trivial Case 2: No new subviews, simply remove all current subviews.
754  if ([newSubviews count] === 0)
755  {
756  var count = [_subviews count];
757 
758  while (count--)
759  [_subviews[count] removeFromSuperview];
760 
761  return;
762  }
763 
764  // Find out the views that were removed.
765  var removedSubviews = [CPMutableSet setWithArray:_subviews];
766 
767  [removedSubviews removeObjectsInArray:newSubviews];
768  [removedSubviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
769 
770  // Find out which views need to be added.
771  var addedSubviews = [CPMutableSet setWithArray:newSubviews];
772 
773  [addedSubviews removeObjectsInArray:_subviews];
774 
775  var addedSubview = nil,
776  addedSubviewEnumerator = [addedSubviews objectEnumerator];
777 
778  while ((addedSubview = [addedSubviewEnumerator nextObject]) !== nil)
779  [self addSubview:addedSubview];
780 
781  // If the order is fine, no need to reorder.
782  if ([_subviews isEqual:newSubviews])
783  return;
784 
785  _subviews = [newSubviews copy];
786 
787 #if PLATFORM(DOM)
788  var index = 0,
789  count = [_subviews count];
790 
791  for (; index < count; ++index)
792  {
793  var subview = _subviews[index];
794 
795  CPDOMDisplayServerRemoveChild(_DOMElement, subview._DOMElement);
796  CPDOMDisplayServerAppendChild(_DOMElement, subview._DOMElement);
797  }
798 #endif
799 }
800 
801 /* @ignore */
802 - (void)_setWindow:(CPWindow)aWindow
803 {
804  [[self window] _dirtyKeyViewLoop];
805 
806  // Clear out first responder if we're the first responder and leaving.
807  if ([_window firstResponder] === self && _window != aWindow)
808  [_window makeFirstResponder:nil];
809 
810  // Notify the view and its subviews
811  [self viewWillMoveToWindow:aWindow];
812 
813  // Unregister the drag events from the current window and register
814  // them in the new window.
815  if (_registeredDraggedTypes)
816  {
817  [_window _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
818  [aWindow _noteRegisteredDraggedTypes:_registeredDraggedTypes];
819  }
820 
821  // View must be removed from the current window viewsWithTrackingAreas
822  if (_window && (_trackingAreas.length > 0))
823  [_window _removeTrackingAreaView:self];
824 
825  _window = aWindow;
826 
827  if (_window)
828  {
829  var owners;
830 
831  if (_trackingAreas.length > 0)
832  {
833  // View must be added to the new window viewsWithTrackingAreas
834  [_window _addTrackingAreaView:self];
835  owners = [self _calcTrackingAreaOwners];
836  }
837  else
838  owners = [self];
839 
840  // Notify that view tracking areas should be updated
841  // Cocoa doesn't notify on leaving a window
842  [self _updateTrackingAreasForOwners:owners];
843  }
844 
845  var count = [_subviews count];
846 
847  while (count--)
848  [_subviews[count] _setWindow:aWindow];
849 
850  if ([_window isKeyWindow])
851  [self setThemeState:CPThemeStateKeyWindow];
852  else
853  [self unsetThemeState:CPThemeStateKeyWindow];
854 
855  [self viewDidMoveToWindow];
856 
857  [self _manageToolTipInstallation];
858 
859  [[self window] _dirtyKeyViewLoop];
860 }
861 
866 - (BOOL)isDescendantOf:(CPView)aView
867 {
868  var view = self;
869 
870  do
871  {
872  if (view === aView)
873  return YES;
874  } while(view = [view superview])
875 
876  return NO;
877 }
878 
882 - (void)viewDidMoveToSuperview
883 {
884  [self setNeedsLayout:YES];
885  [self setNeedsDisplay:YES];
886 }
887 
891 - (void)viewDidMoveToWindow
892 {
893 }
894 
899 - (void)viewWillMoveToSuperview:(CPView)aView
900 {
901  _isSuperviewAClipView = [aView isKindOfClass:[CPClipView class]];
902 
903  [self _removeObservers];
904 
905  if (aView)
906  [self _addObservers];
907 }
908 
913 - (void)viewWillMoveToWindow:(CPWindow)aWindow
914 {
915 }
916 
921 - (void)willRemoveSubview:(CPView)aView
922 {
923 }
924 
925 - (void)_removeObservers
926 {
927  if (!_isObserving)
928  return;
929 
930  var count = [_subviews count];
931 
932  while (count--)
933  [_subviews[count] _removeObservers];
934 
935  _isObserving = NO;
936 }
937 
938 - (void)_addObservers
939 {
940  if (_isObserving)
941  return;
942 
943  var count = [_subviews count];
944 
945  while (count--)
946  [_subviews[count] _addObservers];
947 
948  _isObserving = YES;
949 }
950 
955 - (CPMenuItem)enclosingMenuItem
956 {
957  var view = self;
958 
959  while (view && ![view isKindOfClass:[_CPMenuItemView class]])
960  view = [view superview];
961 
962  if (view)
963  return view._menuItem;
964 
965  return nil;
966 /* var view = self,
967  enclosingMenuItem = _enclosingMenuItem;
968 
969  while (!enclosingMenuItem && (view = view._enclosingMenuItem))
970  view = [view superview];
971 
972  return enclosingMenuItem;*/
973 }
974 
975 - (void)setTag:(CPInteger)aTag
976 {
977  _tag = aTag;
978 }
979 
980 - (CPInteger)tag
981 {
982  return _tag;
983 }
984 
985 - (CPView)viewWithTag:(CPInteger)aTag
986 {
987  if ([self tag] === aTag)
988  return self;
989 
990  var index = 0,
991  count = _subviews.length;
992 
993  for (; index < count; ++index)
994  {
995  var view = [_subviews[index] viewWithTag:aTag];
996 
997  if (view)
998  return view;
999  }
1000 
1001  return nil;
1002 }
1003 
1008 - (BOOL)isFlipped
1009 {
1010  return YES;
1011 }
1012 
1020 - (void)setFrame:(CGRect)aFrame
1021 {
1022  if (CGRectEqualToRect(_frame, aFrame) && !_forceUpdates)
1023  return;
1024 
1025  _inhibitFrameAndBoundsChangedNotifications = YES;
1026 
1027  [self setFrameOrigin:aFrame.origin];
1028  [self setFrameSize:aFrame.size];
1029 
1030  _inhibitFrameAndBoundsChangedNotifications = NO;
1031 
1032  if (_postsFrameChangedNotifications)
1033  [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
1034 
1035  if (_isSuperviewAClipView)
1036  [[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
1037 
1038  if (!_inhibitUpdateTrackingAreas)
1039  [self _updateTrackingAreasWithRecursion:YES];
1040 }
1041 
1046 - (CGRect)frame
1047 {
1048  return CGRectMakeCopy(_frame);
1049 }
1050 
1051 - (CGPoint)frameOrigin
1052 {
1053  return CGPointMakeCopy(_frame.origin);
1054 }
1055 
1056 - (CGSize)frameSize
1057 {
1058  return CGSizeMakeCopy(_frame.size);
1059 }
1060 
1068 - (void)setCenter:(CGPoint)aPoint
1069 {
1070  [self setFrameOrigin:CGPointMake(aPoint.x - _frame.size.width / 2.0, aPoint.y - _frame.size.height / 2.0)];
1071 }
1072 
1077 - (CGPoint)center
1078 {
1079  return CGPointMake(_frame.size.width / 2.0 + _frame.origin.x, _frame.size.height / 2.0 + _frame.origin.y);
1080 }
1081 
1089 - (void)setFrameOrigin:(CGPoint)aPoint
1090 {
1091  var origin = _frame.origin;
1092 
1093  if (!aPoint || (CGPointEqualToPoint(origin, aPoint) && !_forceUpdates))
1094  return;
1095 
1096  origin.x = aPoint.x;
1097  origin.y = aPoint.y;
1098 
1099  if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
1100  [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
1101 
1102  if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
1103  [[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
1104 
1105 #if PLATFORM(DOM)
1106  if (!_inhibitDOMUpdates)
1107  {
1108  var transform = _superview ? _superview._boundsTransform : NULL;
1109 
1110  CPDOMDisplayServerSetStyleLeftTop(_DOMElement, transform, origin.x, origin.y);
1111  }
1112 #endif
1113 
1114  if (!_inhibitUpdateTrackingAreas && !_inhibitFrameAndBoundsChangedNotifications)
1115  [self _updateTrackingAreasWithRecursion:YES];
1116 }
1117 
1124 - (void)setFrameSize:(CGSize)aSize
1125 {
1126  var size = _frame.size;
1127 
1128  if (!aSize || (CGSizeEqualToSize(size, aSize) && !_forceUpdates))
1129  return;
1130 
1131  var oldSize = CGSizeMakeCopy(size);
1132 
1133  size.width = aSize.width;
1134  size.height = aSize.height;
1135 
1136  if (YES)
1137  {
1138  _bounds.size.width = aSize.width * 1 / _scaleSize.width;
1139  _bounds.size.height = aSize.height * 1 / _scaleSize.height;
1140  }
1141 
1142  if (_layer)
1143  [_layer _owningViewBoundsChanged];
1144 
1145  if (_autoresizesSubviews)
1146  [self resizeSubviewsWithOldSize:oldSize];
1147 
1148  [self setNeedsLayout];
1149  [self setNeedsDisplay:YES];
1150 
1151 #if PLATFORM(DOM)
1152  [self _setDisplayServerSetStyleSize:size];
1153 
1154  if (_backgroundType !== BackgroundTrivialColor)
1155  {
1156  if (_backgroundType === BackgroundTransparentColor)
1157  {
1158  CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, size.height);
1159  }
1160  else
1161  {
1162  var images = [[_backgroundColor patternImage] imageSlices],
1163  partIndex = 0,
1164  frameSize = aSize;
1165 
1166  if (_backgroundType === BackgroundVerticalThreePartImage)
1167  {
1168  var top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
1169  bottom = _DOMImageSizes[2] ? _DOMImageSizes[2].height : 0;
1170 
1171  // Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
1172  if (top)
1173  {
1174  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", top + "px");
1175  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, top);
1176  partIndex++;
1177  }
1178  if (_DOMImageSizes[1])
1179  {
1180  var height = frameSize.height - top - bottom;
1181 
1182  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", height + "px");
1183  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, size.height - top - bottom);
1184  partIndex++;
1185  }
1186  if (bottom)
1187  {
1188  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", bottom + "px");
1189  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, bottom);
1190  }
1191  }
1192  else if (_backgroundType === BackgroundHorizontalThreePartImage)
1193  {
1194  var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
1195  right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0;
1196 
1197  // Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
1198  if (left)
1199  {
1200  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], left + "px", frameSize.height + "px");
1201  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], left, size.height);
1202  partIndex++;
1203  }
1204  if (_DOMImageSizes[1])
1205  {
1206  var width = (frameSize.width - left - right);
1207 
1208  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], width + "px", frameSize.height + "px");
1209  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width - left - right, size.height);
1210  partIndex++;
1211  }
1212  if (right)
1213  {
1214  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], right + "px", frameSize.height + "px");
1215  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], right, size.height);
1216  }
1217  }
1218  else if (_backgroundType === BackgroundNinePartImage)
1219  {
1220  var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
1221  right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0,
1222  top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
1223  bottom = _DOMImageSizes[6] ? _DOMImageSizes[6].height : 0,
1224  width = size.width - left - right,
1225  height = size.height - top - bottom;
1226 
1227  if (_DOMImageSizes[0])
1228  partIndex++;
1229  if (_DOMImageSizes[1])
1230  {
1231  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, top);
1232  partIndex++;
1233  }
1234  if (_DOMImageSizes[2])
1235  partIndex++;
1236  if (_DOMImageSizes[3])
1237  {
1238  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[3].width, height);
1239  partIndex++;
1240  }
1241  if (_DOMImageSizes[4])
1242  {
1243  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, height);
1244  partIndex++;
1245  }
1246  if (_DOMImageSizes[5])
1247  {
1248  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[5].width, height);
1249  partIndex++;
1250  }
1251  if (_DOMImageSizes[6])
1252  partIndex++;
1253  if (_DOMImageSizes[7])
1254  {
1255  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, _DOMImageSizes[7].height);
1256  }
1257  }
1258  }
1259  }
1260 #endif
1261 
1262  if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
1263  [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
1264 
1265  if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
1266  [[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
1267 
1268  if (!_inhibitUpdateTrackingAreas && !_inhibitFrameAndBoundsChangedNotifications)
1269  [self _updateTrackingAreasWithRecursion:!_autoresizesSubviews];
1270 }
1271 
1277 - (void)_setDisplayServerSetStyleSize:(CGSize)aSize
1278 {
1279 #if PLATFORM(DOM)
1280  var scale = [self scaleSize];
1281 
1282  if (!_inhibitDOMUpdates)
1283  CPDOMDisplayServerSetStyleSize(_DOMElement, aSize.width * 1 / scale.width, aSize.height * 1 / scale.height);
1284 
1285  if (_DOMContentsElement)
1286  {
1287  CPDOMDisplayServerSetSize(_DOMContentsElement, aSize.width * _highDPIRatio * 1 / scale.width, aSize.height * _highDPIRatio * 1 / scale.height);
1288  CPDOMDisplayServerSetStyleSize(_DOMContentsElement, aSize.width * 1 / scale.width, aSize.height * 1 / scale.height);
1289 
1290  _needToSetTransformMatrix = YES;
1291  }
1292 #endif
1293 }
1294 
1300 - (void)setBounds:(CGRect)bounds
1301 {
1302  if (CGRectEqualToRect(_bounds, bounds))
1303  return;
1304 
1305  _inhibitFrameAndBoundsChangedNotifications = YES;
1306 
1307  [self setBoundsOrigin:bounds.origin];
1308  [self setBoundsSize:bounds.size];
1309 
1310  _inhibitFrameAndBoundsChangedNotifications = NO;
1311 
1312  if (_postsBoundsChangedNotifications)
1313  [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
1314 
1315  if (_isSuperviewAClipView)
1316  [[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
1317 
1318  if (!_inhibitUpdateTrackingAreas)
1319  [self _updateTrackingAreasWithRecursion:YES];
1320 }
1321 
1326 - (CGRect)bounds
1327 {
1328  return CGRectMakeCopy(_bounds);
1329 }
1330 
1331 - (CGPoint)boundsOrigin
1332 {
1333  return CGPointMakeCopy(_bounds.origin);
1334 }
1335 
1336 - (CGSize)boundsSize
1337 {
1338  return CGSizeMakeCopy(_bounds.size);
1339 }
1340 
1347 - (void)setBoundsOrigin:(CGPoint)aPoint
1348 {
1349  var origin = _bounds.origin;
1350 
1351  if (CGPointEqualToPoint(origin, aPoint))
1352  return;
1353 
1354  origin.x = aPoint.x;
1355  origin.y = aPoint.y;
1356 
1357  if (origin.x != 0 || origin.y != 0)
1358  {
1359  _boundsTransform = CGAffineTransformMakeTranslation(-origin.x, -origin.y);
1360  _inverseBoundsTransform = CGAffineTransformInvert(_boundsTransform);
1361  }
1362  else
1363  {
1364  _boundsTransform = nil;
1365  _inverseBoundsTransform = nil;
1366  }
1367 
1368 #if PLATFORM(DOM)
1369  var index = _subviews.length;
1370 
1371  while (index--)
1372  {
1373  var view = _subviews[index],
1374  origin = view._frame.origin;
1375 
1376  CPDOMDisplayServerSetStyleLeftTop(view._DOMElement, _boundsTransform, origin.x, origin.y);
1377  }
1378 #endif
1379 
1380  if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
1381  [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
1382 
1383  if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
1384  [[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
1385 
1386  if (!_inhibitUpdateTrackingAreas && !_inhibitFrameAndBoundsChangedNotifications)
1387  [self _updateTrackingAreasWithRecursion:YES];
1388 }
1389 
1396 - (void)setBoundsSize:(CGSize)aSize
1397 {
1398  var size = _bounds.size;
1399 
1400  if (CGSizeEqualToSize(size, aSize))
1401  return;
1402 
1403  var frameSize = _frame.size;
1404 
1405  if (!CGSizeEqualToSize(size, frameSize))
1406  {
1407  var origin = _bounds.origin;
1408 
1409  origin.x /= size.width / frameSize.width;
1410  origin.y /= size.height / frameSize.height;
1411  }
1412 
1413  size.width = aSize.width;
1414  size.height = aSize.height;
1415 
1416  if (!CGSizeEqualToSize(size, frameSize))
1417  {
1418  var origin = _bounds.origin;
1419 
1420  origin.x *= size.width / frameSize.width;
1421  origin.y *= size.height / frameSize.height;
1422  }
1423 
1424  if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
1425  [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
1426 
1427  if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
1428  [[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
1429 
1430  if (!_inhibitUpdateTrackingAreas && !_inhibitFrameAndBoundsChangedNotifications)
1431  [self _updateTrackingAreasWithRecursion:YES];
1432 }
1433 
1434 
1439 - (void)resizeWithOldSuperviewSize:(CGSize)aSize
1440 {
1441  var mask = [self autoresizingMask];
1442 
1443  if (mask === CPViewNotSizable)
1444  return;
1445 
1446  var frame = _superview._frame,
1447  newFrame = CGRectMakeCopy(_frame),
1448  dX = frame.size.width - aSize.width,
1449  dY = frame.size.height - aSize.height,
1450  evenFractionX = 1.0 / ((mask & CPViewMinXMargin ? 1 : 0) + (mask & CPViewWidthSizable ? 1 : 0) + (mask & CPViewMaxXMargin ? 1 : 0)),
1451  evenFractionY = 1.0 / ((mask & CPViewMinYMargin ? 1 : 0) + (mask & CPViewHeightSizable ? 1 : 0) + (mask & CPViewMaxYMargin ? 1 : 0)),
1452  baseX = (mask & CPViewMinXMargin ? _frame.origin.x : 0) +
1453  (mask & CPViewWidthSizable ? _frame.size.width : 0) +
1454  (mask & CPViewMaxXMargin ? aSize.width - _frame.size.width - _frame.origin.x : 0),
1455  baseY = (mask & CPViewMinYMargin ? _frame.origin.y : 0) +
1456  (mask & CPViewHeightSizable ? _frame.size.height : 0) +
1457  (mask & CPViewMaxYMargin ? aSize.height - _frame.size.height - _frame.origin.y : 0);
1458 
1459  if (mask & CPViewMinXMargin)
1460  newFrame.origin.x += dX * (baseX > 0 ? _frame.origin.x / baseX : evenFractionX);
1461 
1462  if (mask & CPViewWidthSizable)
1463  newFrame.size.width += dX * (baseX > 0 ? _frame.size.width / baseX : evenFractionX);
1464 
1465  if (mask & CPViewMinYMargin)
1466  newFrame.origin.y += dY * (baseY > 0 ? _frame.origin.y / baseY : evenFractionY);
1467 
1468  if (mask & CPViewHeightSizable)
1469  newFrame.size.height += dY * (baseY > 0 ? _frame.size.height / baseY : evenFractionY);
1470 
1471  [self setFrame:newFrame];
1472 }
1473 
1478 - (void)resizeSubviewsWithOldSize:(CGSize)aSize
1479 {
1480  var count = _subviews.length;
1481 
1482  while (count--)
1483  [_subviews[count] resizeWithOldSuperviewSize:aSize];
1484 }
1485 
1493 - (void)setAutoresizesSubviews:(BOOL)aFlag
1494 {
1495  _autoresizesSubviews = !!aFlag;
1496 }
1497 
1502 - (BOOL)autoresizesSubviews
1503 {
1504  return _autoresizesSubviews;
1505 }
1506 
1511 - (void)setAutoresizingMask:(unsigned)aMask
1512 {
1513  _autoresizingMask = aMask;
1514 }
1515 
1519 - (unsigned)autoresizingMask
1520 {
1521  return _autoresizingMask;
1522 }
1523 
1524 // Fullscreen Mode
1525 
1529 - (BOOL)enterFullScreenMode
1530 {
1531  return [self enterFullScreenMode:nil withOptions:nil];
1532 }
1533 
1539 - (BOOL)enterFullScreenMode:(CPScreen)aScreen withOptions:(CPDictionary)options
1540 {
1541  _fullScreenModeState = _CPViewFullScreenModeStateMake(self);
1542 
1543  var fullScreenWindow = [[CPWindow alloc] initWithContentRect:[[CPPlatformWindow primaryPlatformWindow] contentBounds] styleMask:CPBorderlessWindowMask];
1544 
1545  [fullScreenWindow setLevel:CPScreenSaverWindowLevel];
1546  [fullScreenWindow setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
1547 
1548  var contentView = [fullScreenWindow contentView];
1549 
1550  [contentView setBackgroundColor:[CPColor blackColor]];
1551  [contentView addSubview:self];
1552 
1553  [self setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
1554  [self setFrame:CGRectMakeCopy([contentView bounds])];
1555 
1556  [fullScreenWindow makeKeyAndOrderFront:self];
1557 
1558  [fullScreenWindow makeFirstResponder:self];
1559 
1560  _isInFullScreenMode = YES;
1561 
1562  return YES;
1563 }
1564 
1568 - (void)exitFullScreenMode
1569 {
1570  [self exitFullScreenModeWithOptions:nil];
1571 }
1572 
1577 - (void)exitFullScreenModeWithOptions:(CPDictionary)options
1578 {
1579  if (!_isInFullScreenMode)
1580  return;
1581 
1582  _isInFullScreenMode = NO;
1583 
1584  [self setFrame:_fullScreenModeState.frame];
1585  [self setAutoresizingMask:_fullScreenModeState.autoresizingMask];
1586  [_fullScreenModeState.superview _insertSubview:self atIndex:_fullScreenModeState.index];
1587 
1588  [[self window] orderOut:self];
1589 }
1590 
1594 - (BOOL)isInFullScreenMode
1595 {
1596  return _isInFullScreenMode;
1597 }
1598 
1603 - (void)setHidden:(BOOL)aFlag
1604 {
1605  aFlag = !!aFlag;
1606 
1607  if (_isHidden === aFlag)
1608  return;
1609 
1610 // FIXME: Should we return to visibility? This breaks in FireFox, Opera, and IE.
1611 // _DOMElement.style.visibility = (_isHidden = aFlag) ? "hidden" : "visible";
1612 #if PLATFORM(DOM)
1613  _DOMElement.style.display = aFlag ? "none" : "block";
1614 #endif
1615 
1616  if (aFlag)
1617  {
1618  var view = [_window firstResponder];
1619 
1620  if ([view isKindOfClass:[CPView class]])
1621  {
1622  do
1623  {
1624  if (self === view)
1625  {
1626  [_window makeFirstResponder:[self nextValidKeyView]];
1627  break;
1628  }
1629  }
1630  while (view = [view superview]);
1631  }
1632 
1633  [self _postViewWillDisappearNotification];
1634  [self _recursiveGainedHiddenAncestor];
1635  }
1636  else
1637  {
1638  [self setNeedsDisplay:YES];
1639 
1640  [self _postViewWillAppearNotification];
1641  [self _recursiveLostHiddenAncestor];
1642  }
1643 
1644  _isHidden = aFlag;
1645 }
1646 
1647 - (void)_postViewWillAppearNotification
1648 {
1649  [[CPNotificationCenter defaultCenter] postNotificationName:_CPViewWillAppearNotification object:self userInfo:nil];
1650 }
1651 
1652 - (void)_postViewDidAppearNotification
1653 {
1654  [[CPNotificationCenter defaultCenter] postNotificationName:_CPViewDidAppearNotification object:self userInfo:nil];
1655 }
1656 
1657 - (void)_postViewWillDisappearNotification
1658 {
1659  [[CPNotificationCenter defaultCenter] postNotificationName:_CPViewWillDisappearNotification object:self userInfo:nil];
1660 }
1661 
1662 - (void)_postViewDidDisappearNotification
1663 {
1664  [[CPNotificationCenter defaultCenter] postNotificationName:_CPViewDidDisappearNotification object:self userInfo:nil];
1665 }
1666 
1667 - (void)_setSuperview:(CPView)aSuperview
1668 {
1669  var hasOldSuperview = (_superview !== nil),
1670  hasNewSuperview = (aSuperview !== nil),
1671  oldSuperviewIsHidden = hasOldSuperview && [_superview isHiddenOrHasHiddenAncestor],
1672  newSuperviewIsHidden = hasNewSuperview && [aSuperview isHiddenOrHasHiddenAncestor];
1673 
1674  if (!newSuperviewIsHidden && oldSuperviewIsHidden)
1675  [self _recursiveLostHiddenAncestor];
1676 
1677  if (newSuperviewIsHidden && !oldSuperviewIsHidden)
1678  [self _recursiveGainedHiddenAncestor];
1679 
1680  _superview = aSuperview;
1681 
1682  if (hasOldSuperview)
1683  [self _postViewDidDisappearNotification];
1684 
1685  if (hasNewSuperview)
1686  [self _postViewDidAppearNotification];
1687 }
1688 
1689 - (void)_recursiveLostHiddenAncestor
1690 {
1691  if (_isHiddenOrHasHiddenAncestor)
1692  {
1693  _isHiddenOrHasHiddenAncestor = NO;
1694  [self viewDidUnhide];
1695  }
1696 
1697  [_subviews enumerateObjectsUsingBlock:function(view, idx, stop)
1698  {
1699  [view _recursiveLostHiddenAncestor];
1700  }];
1701 }
1702 
1703 - (void)_recursiveGainedHiddenAncestor
1704 {
1705  if (!_isHidden)
1706  {
1707  [self viewDidHide];
1708  }
1709 
1710  _isHiddenOrHasHiddenAncestor = YES;
1711 
1712  [_subviews enumerateObjectsUsingBlock:function(view, idx, stop)
1713  {
1714  [view _recursiveGainedHiddenAncestor];
1715  }];
1716 }
1717 
1721 - (BOOL)isHidden
1722 {
1723  return _isHidden;
1724 }
1725 
1726 - (void)setClipsToBounds:(BOOL)shouldClip
1727 {
1728  if (_clipsToBounds === shouldClip)
1729  return;
1730 
1731  _clipsToBounds = shouldClip;
1732 
1733 #if PLATFORM(DOM)
1734  _DOMElement.style.overflow = _clipsToBounds ? "hidden" : "visible";
1735 #endif
1736 }
1737 
1738 - (BOOL)clipsToBounds
1739 {
1740  return _clipsToBounds;
1741 }
1742 
1748 - (void)setAlphaValue:(float)anAlphaValue
1749 {
1750  if (_opacity === anAlphaValue)
1751  return;
1752 
1753  _opacity = anAlphaValue;
1754 
1755 #if PLATFORM(DOM)
1756 
1758  {
1759  if (anAlphaValue === 1.0)
1760  try { _DOMElement.style.removeAttribute("filter") } catch (anException) { }
1761  else
1762  _DOMElement.style.filter = "alpha(opacity=" + anAlphaValue * 100 + ")";
1763  }
1764  else
1765  _DOMElement.style.opacity = anAlphaValue;
1766 
1767 #endif
1768 }
1769 
1774 - (float)alphaValue
1775 {
1776  return _opacity;
1777 }
1778 
1783 - (BOOL)isHiddenOrHasHiddenAncestor
1784 {
1785  return _isHiddenOrHasHiddenAncestor;
1786 }
1787 
1791 - (BOOL)_isVisible
1792 {
1793  return ![self isHiddenOrHasHiddenAncestor] && [[self window] isVisible];
1794 }
1795 
1805 - (void)viewDidHide
1806 {
1807 
1808 }
1809 
1819 - (void)viewDidUnhide
1820 {
1821 
1822 }
1823 
1829 - (BOOL)acceptsFirstMouse:(CPEvent)anEvent
1830 {
1831  return NO;
1832 }
1833 
1838 - (BOOL)hitTests
1839 {
1840  return _hitTests;
1841 }
1842 
1847 - (void)setHitTests:(BOOL)shouldHitTest
1848 {
1849  _hitTests = !!shouldHitTest;
1850 }
1851 
1857 - (CPView)hitTest:(CGPoint)aPoint
1858 {
1859  if (_isHidden || !_hitTests)
1860  return nil;
1861 
1862  var frame = _frame,
1863  sizeScale = [self _hierarchyScaleSize];
1864 
1865  if (_isScaled)
1866  frame = CGRectApplyAffineTransform(_frame, CGAffineTransformMakeScale([_superview _hierarchyScaleSize].width, [_superview _hierarchyScaleSize].height));
1867  else
1868  frame = CGRectApplyAffineTransform(_frame, CGAffineTransformMakeScale(sizeScale.width, sizeScale.height));
1869 
1870  if (!CGRectContainsPoint(frame, aPoint))
1871  return nil;
1872 
1873  var view = nil,
1874  i = _subviews.length,
1875  adjustedPoint = CGPointMake(aPoint.x - CGRectGetMinX(frame), aPoint.y - CGRectGetMinY(frame));
1876 
1877  if (_inverseBoundsTransform)
1878  {
1879  var affineTransform = CGAffineTransformMakeCopy(_inverseBoundsTransform);
1880 
1881  if (_isScaled)
1882  {
1883  affineTransform.tx *= [_superview _hierarchyScaleSize].width;
1884  affineTransform.ty *= [_superview _hierarchyScaleSize].height;
1885  }
1886  else
1887  {
1888  affineTransform.tx *= sizeScale.width;
1889  affineTransform.ty *= sizeScale.height;
1890  }
1891 
1892  adjustedPoint = CGPointApplyAffineTransform(adjustedPoint, affineTransform);
1893  }
1894 
1895 
1896  while (i--)
1897  if (view = [_subviews[i] hitTest:adjustedPoint])
1898  return view;
1899 
1900  return self;
1901 }
1902 
1906 - (BOOL)needsPanelToBecomeKey
1907 {
1908  return NO;
1909 }
1910 
1915 - (BOOL)mouseDownCanMoveWindow
1916 {
1917  return ![self isOpaque];
1918 }
1919 
1920 - (void)mouseDown:(CPEvent)anEvent
1921 {
1922  if ([self mouseDownCanMoveWindow])
1923  [super mouseDown:anEvent];
1924 }
1925 
1926 - (void)rightMouseDown:(CPEvent)anEvent
1927 {
1928  var menu = [self menuForEvent:anEvent];
1929 
1930  if (menu)
1931  [CPMenu popUpContextMenu:menu withEvent:anEvent forView:self];
1932  else if ([[self nextResponder] isKindOfClass:CPView])
1933  [super rightMouseDown:anEvent];
1934  else
1935  [[[anEvent window] platformWindow] _propagateContextMenuDOMEvent:NO];
1936 }
1937 
1938 - (CPMenu)menuForEvent:(CPEvent)anEvent
1939 {
1940  return [self menu] || [[self class] defaultMenu];
1941 }
1942 
1947 - (void)setBackgroundColor:(CPColor)aColor
1948 {
1949  if (_backgroundColor === aColor)
1950  return;
1951 
1952  if (aColor === [CPNull null])
1953  aColor = nil;
1954 
1955  _backgroundColor = aColor;
1956 
1957 #if PLATFORM(DOM)
1958  if (_backgroundType === BackgroundCSSStyling)
1959  [_backgroundColor restorePreviousCSSState:@ref(_cssStylePreviousState) forDOMElement:_DOMElement];
1960 
1961  var patternImage = [_backgroundColor patternImage],
1962  colorExists = _backgroundColor && ([_backgroundColor patternImage] || [_backgroundColor alphaComponent] > 0.0),
1963  colorHasAlpha = colorExists && [_backgroundColor alphaComponent] < 1.0,
1964  supportsRGBA = CPFeatureIsCompatible(CPCSSRGBAFeature),
1965  colorNeedsDOMElement = colorHasAlpha && !supportsRGBA,
1966  amount = 0,
1967  slices,
1968  // For CSS theming
1969  isCSSBasedColor = [_backgroundColor isCSSBased];
1970 
1971  if (isCSSBasedColor)
1972  {
1973  _backgroundType = BackgroundCSSStyling;
1974  amount = -_DOMImageParts.length;
1975  }
1976  else if ([patternImage isThreePartImage])
1977  {
1978  _backgroundType = [patternImage isVertical] ? BackgroundVerticalThreePartImage : BackgroundHorizontalThreePartImage;
1979  amount = 3;
1980  }
1981  else if ([patternImage isNinePartImage])
1982  {
1983  _backgroundType = BackgroundNinePartImage;
1984  amount = 9;
1985  }
1986  else
1987  {
1988  _backgroundType = colorNeedsDOMElement ? BackgroundTransparentColor : BackgroundTrivialColor;
1989  amount = (colorNeedsDOMElement ? 1 : 0) - _DOMImageParts.length;
1990  }
1991 
1992  // Prepare multipart image data and reduce number of required DOM parts by number of empty slices in the multipart image to save needless DOM elements.
1993  if (_backgroundType === BackgroundVerticalThreePartImage || _backgroundType === BackgroundHorizontalThreePartImage || _backgroundType === BackgroundNinePartImage)
1994  {
1995  slices = [patternImage imageSlices];
1996 
1997  // We won't need more divs than there are slices.
1998  amount = MIN(amount, slices.length);
1999 
2000  for (var i = 0, count = slices.length; i < count; i++)
2001  {
2002  var image = slices[i],
2003  size = [image size];
2004 
2005  if (!size || (size.width === 0 && size.height === 0))
2006  size = nil;
2007 
2008  _DOMImageSizes[i] = size;
2009 
2010  // If there's a nil slice or a slice with no size, it won't need a div.
2011  if (!size)
2012  amount--;
2013  }
2014 
2015  // Now that we know how many divs we really need, compare that to number we actually have.
2016  amount -= _DOMImageParts.length;
2017  }
2018 
2019  // Make sure the number of divs we have match our needs.
2020  if (amount > 0)
2021  {
2022  while (amount--)
2023  {
2024  var DOMElement = DOMElementPrototype.cloneNode(false);
2025 
2026  DOMElement.style.zIndex = -1000;
2027 
2028  _DOMImageParts.push(DOMElement);
2029  _DOMElement.appendChild(DOMElement);
2030  }
2031  }
2032  else
2033  {
2034  amount = -amount;
2035  while (amount--)
2036  _DOMElement.removeChild(_DOMImageParts.pop());
2037  }
2038 
2039  if (_backgroundType === BackgroundCSSStyling)
2040  {
2041  _cssStyleNode = [_backgroundColor applyCSSColorForView:self
2042  onDOMElement:_DOMElement
2043  styleNode:_cssStyleNode
2044  previousState:@ref(_cssStylePreviousState)];
2045  }
2046  else if (_backgroundType === BackgroundTrivialColor || _backgroundType === BackgroundTransparentColor)
2047  {
2048  var colorCSS = colorExists ? [_backgroundColor cssString] : "";
2049 
2050  if (colorNeedsDOMElement)
2051  {
2052  _DOMElement.style.background = "";
2053  _DOMImageParts[0].style.background = [_backgroundColor cssString];
2054 
2055  if (patternImage)
2056  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[0], [patternImage size].width + "px", [patternImage size].height + "px");
2057 
2059  _DOMImageParts[0].style.filter = "alpha(opacity=" + [_backgroundColor alphaComponent] * 100 + ")";
2060  else
2061  _DOMImageParts[0].style.opacity = [_backgroundColor alphaComponent];
2062 
2063  var size = [self bounds].size;
2064  CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, size.height);
2065  }
2066  else
2067  {
2068  _DOMElement.style.background = colorCSS;
2069 
2070  if (patternImage)
2071  CPDOMDisplayServerSetStyleBackgroundSize(_DOMElement, [patternImage size].width + "px", [patternImage size].height + "px");
2072  }
2073  }
2074  else
2075  {
2076  var frameSize = _frame.size,
2077  partIndex = 0;
2078 
2079  for (var i = 0; i < slices.length; i++)
2080  {
2081  var size = _DOMImageSizes[i];
2082 
2083  if (!size)
2084  continue;
2085 
2086  var image = slices[i];
2087 
2088  // // If image was nil, size should have been nil too.
2089  // assert(image != nil);
2090 
2091  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, size.height);
2092 
2093  _DOMImageParts[partIndex].style.background = "url(\"" + [image filename] + "\")";
2094 
2095  if (!supportsRGBA)
2096  {
2098  try { _DOMImageParts[partIndex].style.removeAttribute("filter") } catch (anException) { }
2099  else
2100  _DOMImageParts[partIndex].style.opacity = 1.0;
2101  }
2102 
2103  partIndex++;
2104  }
2105 
2106  if (_backgroundType === BackgroundNinePartImage)
2107  {
2108  var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
2109  right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0,
2110  top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
2111  bottom = _DOMImageSizes[6] ? _DOMImageSizes[6].height : 0,
2112  width = frameSize.width - left - right,
2113  height = frameSize.height - top - bottom;
2114 
2115  partIndex = 0;
2116 
2117  if (_DOMImageSizes[0])
2118  {
2119  CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
2120  partIndex++;
2121  }
2122  if (_DOMImageSizes[1])
2123  {
2124  CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, 0.0);
2125  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, _DOMImageSizes[1].height);
2126  partIndex++;
2127  }
2128  if (_DOMImageSizes[2])
2129  {
2130  CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
2131  partIndex++;
2132  }
2133  if (_DOMImageSizes[3])
2134  {
2135  CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, top);
2136  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[3].width, height);
2137  partIndex++;
2138  }
2139  if (_DOMImageSizes[4])
2140  {
2141  CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, top);
2142  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, height);
2143  partIndex++;
2144  }
2145  if (_DOMImageSizes[5])
2146  {
2147  CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, top);
2148  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[5].width, height);
2149  partIndex++;
2150  }
2151  if (_DOMImageSizes[6])
2152  {
2153  CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
2154  partIndex++;
2155  }
2156  if (_DOMImageSizes[7])
2157  {
2158  CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, left, 0.0);
2159  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, _DOMImageSizes[7].height);
2160  partIndex++;
2161  }
2162  if (_DOMImageSizes[8])
2163  {
2164  CPDOMDisplayServerSetStyleRightBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
2165  }
2166  }
2167  else if (_backgroundType === BackgroundVerticalThreePartImage)
2168  {
2169  var top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
2170  bottom = _DOMImageSizes[2] ? _DOMImageSizes[2].height : 0;
2171 
2172  partIndex = 0;
2173 
2174  // Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
2175  if (top)
2176  {
2177  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", top + "px");
2178  CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
2179  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, top);
2180  partIndex++;
2181  }
2182  if (_DOMImageSizes[1])
2183  {
2184  var height = frameSize.height - top - bottom;
2185 
2186  //_DOMImageParts[partIndex].style.backgroundSize = frameSize.width + "px " + height + "px";
2187  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", height + "px");
2188  CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, top);
2189  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, height);
2190  partIndex++;
2191  }
2192  if (bottom)
2193  {
2194  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", bottom + "px");
2195  CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
2196  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, bottom);
2197  }
2198  }
2199  else if (_backgroundType === BackgroundHorizontalThreePartImage)
2200  {
2201  var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
2202  right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0;
2203 
2204  partIndex = 0;
2205 
2206  // Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
2207  if (left)
2208  {
2209  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], left + "px", frameSize.height + "px");
2210  CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
2211  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], left, frameSize.height);
2212  partIndex++;
2213  }
2214  if (_DOMImageSizes[1])
2215  {
2216  var width = (frameSize.width - left - right);
2217 
2218  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], width + "px", frameSize.height + "px");
2219  CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, 0.0);
2220  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, frameSize.height);
2221  partIndex++;
2222  }
2223  if (right)
2224  {
2225  CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], right + "px", frameSize.height + "px");
2226  CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
2227  CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], right, frameSize.height);
2228  }
2229  }
2230  }
2231 #endif
2232 }
2233 
2238 {
2239  return _backgroundColor;
2240 }
2241 
2242 // Converting Coordinates
2249 - (CGPoint)convertPoint:(CGPoint)aPoint fromView:(CPView)aView
2250 {
2251  if (aView === self)
2252  return aPoint;
2253 
2254  return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(aView, self));
2255 }
2256 
2262 - (CGPoint)convertPointFromBase:(CGPoint)aPoint
2263 {
2264  return [self convertPoint:aPoint fromView:nil];
2265 }
2266 
2273 - (CGPoint)convertPoint:(CGPoint)aPoint toView:(CPView)aView
2274 {
2275  if (aView === self)
2276  return aPoint;
2277 
2278  return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(self, aView));
2279 }
2280 
2281 
2287 - (CGPoint)convertPointToBase:(CGPoint)aPoint
2288 {
2289  return [self convertPoint:aPoint toView:nil];
2290 }
2291 
2298 - (CGSize)convertSize:(CGSize)aSize fromView:(CPView)aView
2299 {
2300  if (aView === self)
2301  return aSize;
2302 
2303  return CGSizeApplyAffineTransform(aSize, _CPViewGetTransform(aView, self));
2304 }
2305 
2312 - (CGSize)convertSize:(CGSize)aSize toView:(CPView)aView
2313 {
2314  if (aView === self)
2315  return aSize;
2316 
2317  return CGSizeApplyAffineTransform(aSize, _CPViewGetTransform(self, aView));
2318 }
2319 
2326 - (CGRect)convertRect:(CGRect)aRect fromView:(CPView)aView
2327 {
2328  if (self === aView)
2329  return aRect;
2330 
2331  return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(aView, self));
2332 }
2333 
2339 - (CGRect)convertRectFromBase:(CGRect)aRect
2340 {
2341  return [self convertRect:aRect fromView:nil];
2342 }
2343 
2350 - (CGRect)convertRect:(CGRect)aRect toView:(CPView)aView
2351 {
2352  if (self === aView)
2353  return aRect;
2354 
2355  return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(self, aView));
2356 }
2357 
2363 - (CGRect)convertRectToBase:(CGRect)aRect
2364 {
2365  return [self convertRect:aRect toView:nil];
2366 }
2367 
2380 - (void)setPostsFrameChangedNotifications:(BOOL)shouldPostFrameChangedNotifications
2381 {
2382  shouldPostFrameChangedNotifications = !!shouldPostFrameChangedNotifications;
2383 
2384  if (_postsFrameChangedNotifications === shouldPostFrameChangedNotifications)
2385  return;
2386 
2387  _postsFrameChangedNotifications = shouldPostFrameChangedNotifications;
2388 }
2389 
2393 - (BOOL)postsFrameChangedNotifications
2394 {
2395  return _postsFrameChangedNotifications;
2396 }
2397 
2410 - (void)setPostsBoundsChangedNotifications:(BOOL)shouldPostBoundsChangedNotifications
2411 {
2412  shouldPostBoundsChangedNotifications = !!shouldPostBoundsChangedNotifications;
2413 
2414  if (_postsBoundsChangedNotifications === shouldPostBoundsChangedNotifications)
2415  return;
2416 
2417  _postsBoundsChangedNotifications = shouldPostBoundsChangedNotifications;
2418 }
2419 
2425 - (BOOL)postsBoundsChangedNotifications
2426 {
2427  return _postsBoundsChangedNotifications;
2428 }
2429 
2440 - (void)dragImage:(CPImage)anImage at:(CGPoint)aLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
2441 {
2442  [_window dragImage:anImage at:[self convertPoint:aLocation toView:nil] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
2443 }
2444 
2455 - (void)dragView:(CPView)aView at:(CGPoint)aLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
2456 {
2457  [_window dragView:aView at:[self convertPoint:aLocation toView:nil] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
2458 }
2459 
2464 - (void)registerForDraggedTypes:(CPArray)pasteboardTypes
2465 {
2466  if (!pasteboardTypes || ![pasteboardTypes count])
2467  return;
2468 
2469  var theWindow = [self window];
2470 
2471  [theWindow _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
2472  [_registeredDraggedTypes addObjectsFromArray:pasteboardTypes];
2473  [theWindow _noteRegisteredDraggedTypes:_registeredDraggedTypes];
2474 
2475  _registeredDraggedTypesArray = nil;
2476 }
2477 
2482 - (CPArray)registeredDraggedTypes
2483 {
2484  if (!_registeredDraggedTypesArray)
2485  _registeredDraggedTypesArray = [_registeredDraggedTypes allObjects];
2486 
2487  return _registeredDraggedTypesArray;
2488 }
2489 
2493 - (void)unregisterDraggedTypes
2494 {
2495  [[self window] _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
2496 
2497  _registeredDraggedTypes = [CPSet set];
2498  _registeredDraggedTypesArray = [];
2499 }
2500 
2505 - (void)drawRect:(CGRect)aRect
2506 {
2507 
2508 }
2509 
2510 // Scaling
2511 
2518 - (void)scaleUnitSquareToSize:(CGSize)aSize
2519 {
2520  if (!aSize)
2521  return;
2522 
2523  // Reset the bounds
2524  var bounds = CGRectMakeCopy([self bounds]);
2525  bounds.size.width *= _scaleSize.width;
2526  bounds.size.height *= _scaleSize.height;
2527 
2528  [self willChangeValueForKey:@"scaleSize"];
2529  _scaleSize = CGSizeMakeCopy([self scaleSize]);
2530  _scaleSize.height *= aSize.height;
2531  _scaleSize.width *= aSize.width;
2532  [self didChangeValueForKey:@"scaleSize"];
2533  _isScaled = YES;
2534 
2535  _hierarchyScaleSize = CGSizeMakeCopy([self _hierarchyScaleSize]);
2536  _hierarchyScaleSize.height *= aSize.height;
2537  _hierarchyScaleSize.width *= aSize.width;
2538 
2539  var scaleAffine = CGAffineTransformMakeScale(1.0 / _scaleSize.width, 1.0 / _scaleSize.height),
2540  newBounds = CGRectApplyAffineTransform(CGRectMakeCopy(bounds), scaleAffine);
2541 
2542  [self setBounds:newBounds];
2543 
2544  [_subviews makeObjectsPerformSelector:@selector(_scaleSizeUnitSquareToSize:) withObject:aSize];
2545 }
2546 
2551 - (void)_scaleSizeUnitSquareToSize:(CGSize)aSize
2552 {
2553  _hierarchyScaleSize = CGSizeMakeCopy([_superview _hierarchyScaleSize]);
2554 
2555  if (_isScaled)
2556  {
2557  _hierarchyScaleSize.width *= _scaleSize.width;
2558  _hierarchyScaleSize.height *= _scaleSize.height;
2559  }
2560 
2561  [_subviews makeObjectsPerformSelector:@selector(_scaleSizeUnitSquareToSize:) withObject:aSize];
2562 }
2563 
2567 - (CGSize)_hierarchyScaleSize
2568 {
2569  return _hierarchyScaleSize || CGSizeMake(1.0, 1.0);
2570 }
2571 
2575 - (void)_applyCSSScalingTranformations
2576 {
2577 #if PLATFORM(DOM)
2578  if (_isScaled)
2579  {
2580  var scale = [self scaleSize],
2581  browserPropertyTransform = CPBrowserStyleProperty(@"transform"),
2582  browserPropertyTransformOrigin = CPBrowserStyleProperty(@"transformOrigin");
2583 
2584  self._DOMElement.style[browserPropertyTransform] = 'scale(' + scale.width + ', ' + scale.height + ')';
2585  self._DOMElement.style[browserPropertyTransformOrigin] = '0 0';
2586 
2587  [self _setDisplayServerSetStyleSize:[self frameSize]];
2588  }
2589 #endif
2590 }
2591 
2592 // Displaying
2593 
2597 - (void)setNeedsDisplay:(BOOL)aFlag
2598 {
2599  if (aFlag)
2600  {
2601  [self _applyCSSScalingTranformations];
2602  [self setNeedsDisplayInRect:[self bounds]];
2603  }
2604 }
2605 
2610 - (void)setNeedsDisplayInRect:(CGRect)aRect
2611 {
2612  if (!(_viewClassFlags & CPViewHasCustomDrawRect))
2613  return;
2614 
2615  if (CGRectIsEmpty(aRect))
2616  return;
2617 
2618  if (_dirtyRect && !CGRectIsEmpty(_dirtyRect))
2619  _dirtyRect = CGRectUnion(aRect, _dirtyRect);
2620  else
2621  _dirtyRect = CGRectMakeCopy(aRect);
2622 
2623  _CPDisplayServerAddDisplayObject(self);
2624 }
2625 
2626 - (BOOL)needsDisplay
2627 {
2628  return _dirtyRect && !CGRectIsEmpty(_dirtyRect);
2629 }
2630 
2634 - (void)displayIfNeeded
2635 {
2636  if ([self needsDisplay])
2637  [self displayRect:_dirtyRect];
2638 }
2639 
2643 - (void)display
2644 {
2645  [self displayRect:[self visibleRect]];
2646 }
2647 
2648 - (void)displayIfNeededInRect:(CGRect)aRect
2649 {
2650  if ([self needsDisplay])
2651  [self displayRect:aRect];
2652 }
2653 
2658 - (void)displayRect:(CGRect)aRect
2659 {
2660  [self viewWillDraw];
2661 
2662  [self displayRectIgnoringOpacity:aRect inContext:nil];
2663 
2664  _dirtyRect = NULL;
2665 }
2666 
2667 - (void)displayRectIgnoringOpacity:(CGRect)aRect inContext:(CPGraphicsContext)aGraphicsContext
2668 {
2669  if ([self isHidden])
2670  return;
2671 
2672 #if PLATFORM(DOM)
2673  [self lockFocus];
2674 
2675  CGContextClearRect([[CPGraphicsContext currentContext] graphicsPort], aRect);
2676 
2677  [self drawRect:aRect];
2678  [self unlockFocus];
2679 #endif
2680 }
2681 
2682 - (void)viewWillDraw
2683 {
2684 }
2685 
2689 - (void)lockFocus
2690 {
2691  if (!_graphicsContext)
2692  {
2693  var graphicsPort = CGBitmapGraphicsContextCreate();
2694 
2695 #if PLATFORM(DOM)
2696  var width = CGRectGetWidth(_frame),
2697  height = CGRectGetHeight(_frame),
2698  devicePixelRatio = window.devicePixelRatio || 1,
2699  backingStoreRatio = CPBrowserBackingStorePixelRatio(graphicsPort);
2700 
2701  _highDPIRatio = CPViewHighDPIDrawingEnabled ? (devicePixelRatio / backingStoreRatio) : 1;
2702 
2703  _DOMContentsElement = graphicsPort.DOMElement;
2704 
2705  _DOMContentsElement.style.zIndex = -100;
2706 
2707  _DOMContentsElement.style.overflow = "hidden";
2708  _DOMContentsElement.style.position = "absolute";
2709  _DOMContentsElement.style.visibility = "visible";
2710 
2711  CPDOMDisplayServerSetSize(_DOMContentsElement, width * _highDPIRatio, height * _highDPIRatio);
2712 
2713  CPDOMDisplayServerSetStyleLeftTop(_DOMContentsElement, NULL, 0.0, 0.0);
2714  CPDOMDisplayServerSetStyleSize(_DOMContentsElement, width, height);
2715 
2716  // The performance implications of this aren't clear, but without this subviews might not be redrawn when this
2717  // view moves.
2719  _DOMElement.style.webkitTransform = 'translateX(0)';
2720 
2721  CPDOMDisplayServerAppendChild(_DOMElement, _DOMContentsElement);
2722 #endif
2723  _graphicsContext = [CPGraphicsContext graphicsContextWithGraphicsPort:graphicsPort flipped:YES];
2724  _needToSetTransformMatrix = YES;
2725  }
2726 
2727 #if PLATFORM(DOM)
2728  if (_needToSetTransformMatrix && _highDPIRatio !== 1)
2729  [_graphicsContext graphicsPort].setTransform(_highDPIRatio, 0, 0 , _highDPIRatio, 0, 0);
2730 #endif
2731 
2732  _needToSetTransformMatrix = NO;
2733  [CPGraphicsContext setCurrentContext:_graphicsContext];
2734 
2735  CGContextSaveGState([_graphicsContext graphicsPort]);
2736 }
2737 
2741 - (void)unlockFocus
2742 {
2743  CGContextRestoreGState([_graphicsContext graphicsPort]);
2744 
2746 }
2747 
2748 - (void)setNeedsLayout
2749 {
2750  [self setNeedsLayout:YES];
2751 }
2752 
2753 - (void)setNeedsLayout:(BOOL)needLayout
2754 {
2755  if (!needLayout)
2756  {
2757  _needsLayout = NO;
2758  return;
2759  }
2760 
2761  _needsLayout = YES;
2762 
2763  _CPDisplayServerAddLayoutObject(self);
2764 }
2765 
2766 - (BOOL)needsLayout
2767 {
2768  return _needsLayout;
2769 }
2770 
2771 - (void)layout
2772 {
2773  _needsLayout = NO;
2774 
2775  if (_viewClassFlags & CPViewHasCustomViewWillLayout)
2776  [self viewWillLayout];
2777 
2778  if (_viewClassFlags & CPViewHasCustomLayoutSubviews)
2779  [self layoutSubviews];
2780 
2781  [self viewDidLayout];
2782 }
2783 
2784 - (void)layoutIfNeeded
2785 {
2786  if (_needsLayout)
2787  [self layout];
2788 }
2789 
2793 - (void)viewWillLayout
2794 {
2795 
2796 }
2797 
2801 - (void)viewDidLayout
2802 {
2803  [self _recomputeAppearance];
2804 }
2805 
2806 - (void)layoutSubviews
2807 {
2808 
2809 }
2810 
2814 - (BOOL)isOpaque
2815 {
2816  return NO;
2817 }
2818 
2822 - (CGRect)visibleRect
2823 {
2824  if (!_superview)
2825  return _bounds;
2826 
2827  return CGRectIntersection([self convertRect:[_superview visibleRect] fromView:_superview], _bounds);
2828 }
2829 
2830 // Scrolling
2831 /* @ignore */
2832 - (CPScrollView)_enclosingClipView
2833 {
2834  var superview = _superview,
2835  clipViewClass = [CPClipView class];
2836 
2837  while (superview && ![superview isKindOfClass:clipViewClass])
2838  superview = superview._superview;
2839 
2840  return superview;
2841 }
2842 
2847 - (void)scrollPoint:(CGPoint)aPoint
2848 {
2849  var clipView = [self _enclosingClipView];
2850 
2851  if (!clipView)
2852  return;
2853 
2854  [clipView scrollToPoint:[self convertPoint:aPoint toView:clipView]];
2855 }
2856 
2862 - (BOOL)scrollRectToVisible:(CGRect)aRect
2863 {
2864  // Make sure we have a rect that exists.
2865  aRect = CGRectIntersection(aRect, _bounds);
2866 
2867  // If aRect is empty no scrolling required.
2868  if (CGRectIsEmpty(aRect))
2869  return NO;
2870 
2871  var enclosingClipView = [self _enclosingClipView];
2872 
2873  // If we're not in a clip view, then there isn't much we can do.
2874  if (!enclosingClipView)
2875  return NO;
2876 
2877  var documentView = [enclosingClipView documentView];
2878 
2879  // If the clip view doesn't have a document view, then there isn't much we can do.
2880  if (!documentView)
2881  return NO;
2882 
2883  // Get the document view visible rect and convert aRect to the document view's coordinate system
2884  var documentViewVisibleRect = [documentView visibleRect],
2885  rectInDocumentView = [self convertRect:aRect toView:documentView];
2886 
2887  // If already visible then no scrolling required.
2888  if (CGRectContainsRect(documentViewVisibleRect, rectInDocumentView))
2889  return NO;
2890 
2891  var currentScrollPoint = documentViewVisibleRect.origin,
2892  scrollPoint = CGPointMakeCopy(currentScrollPoint),
2893  rectInDocumentViewMinX = CGRectGetMinX(rectInDocumentView),
2894  documentViewVisibleRectMinX = CGRectGetMinX(documentViewVisibleRect),
2895  doesItFitForWidth = documentViewVisibleRect.size.width >= rectInDocumentView.size.width;
2896 
2897  // One of the following has to be true since our current visible rect didn't contain aRect.
2898  if (rectInDocumentViewMinX < documentViewVisibleRectMinX && doesItFitForWidth)
2899  // Scroll to left edge of aRect as it is to the left of the visible rect and it fit inside
2900  scrollPoint.x = rectInDocumentViewMinX;
2901  else if (CGRectGetMaxX(rectInDocumentView) > CGRectGetMaxX(documentViewVisibleRect) && doesItFitForWidth)
2902  // Scroll to right edge of aRect as it is to the right of the visible rect and it fit inside
2903  scrollPoint.x = CGRectGetMaxX(rectInDocumentView) - documentViewVisibleRect.size.width;
2904  else if (rectInDocumentViewMinX > documentViewVisibleRectMinX)
2905  // Scroll to left edge of aRect as it is to the right of the visible rect and it doesn't fit inside
2906  scrollPoint.x = rectInDocumentViewMinX;
2907  else if (CGRectGetMaxX(rectInDocumentView) < CGRectGetMaxX(documentViewVisibleRect))
2908  // Scroll to right edge of aRect as it is to the left of the visible rect and it doesn't fit inside
2909  scrollPoint.x = CGRectGetMaxX(rectInDocumentView) - documentViewVisibleRect.size.width;
2910 
2911  var rectInDocumentViewMinY = CGRectGetMinY(rectInDocumentView),
2912  documentViewVisibleRectMinY = CGRectGetMinY(documentViewVisibleRect),
2913  doesItFitForHeight = documentViewVisibleRect.size.height >= rectInDocumentView.size.height;
2914 
2915  if (rectInDocumentViewMinY < documentViewVisibleRectMinY && doesItFitForHeight)
2916  // Scroll to top edge of aRect as it is above the visible rect and it fit inside
2917  scrollPoint.y = rectInDocumentViewMinY;
2918  else if (CGRectGetMaxY(rectInDocumentView) > CGRectGetMaxY(documentViewVisibleRect) && doesItFitForHeight)
2919  // Scroll to bottom edge of aRect as it is below the visible rect and it fit inside
2920  scrollPoint.y = CGRectGetMaxY(rectInDocumentView) - documentViewVisibleRect.size.height;
2921  else if (rectInDocumentViewMinY > documentViewVisibleRectMinY)
2922  // Scroll to top edge of aRect as it is below the visible rect and it doesn't fit inside
2923  scrollPoint.y = rectInDocumentViewMinY;
2924  else if (CGRectGetMaxY(rectInDocumentView) < CGRectGetMaxY(documentViewVisibleRect))
2925  // Scroll to bottom edge of aRect as it is above the visible rect and it doesn't fit inside
2926  scrollPoint.y = CGRectGetMaxY(rectInDocumentView) - documentViewVisibleRect.size.height;
2927 
2928  // Don't scroll if aRect contains the whole visible rect as it is already as visible as possible.
2929  // We check this by comparing to new scrollPoint to the current.
2930  if (CGPointEqualToPoint(scrollPoint, currentScrollPoint))
2931  return NO;
2932 
2933  [enclosingClipView scrollToPoint:scrollPoint];
2934 
2935  return YES;
2936 }
2937 
2941 - (BOOL)autoscroll:(CPEvent)anEvent
2942 {
2943  return [[self superview] autoscroll:anEvent];
2944 }
2945 
2952 - (CGRect)adjustScroll:(CGRect)proposedVisibleRect
2953 {
2954  return proposedVisibleRect;
2955 }
2956 
2960 - (void)scrollRect:(CGRect)aRect by:(float)anAmount
2961 {
2962 
2963 }
2964 
2969 - (CPScrollView)enclosingScrollView
2970 {
2971  var superview = _superview,
2972  scrollViewClass = [CPScrollView class];
2973 
2974  while (superview && ![superview isKindOfClass:scrollViewClass])
2975  superview = superview._superview;
2976 
2977  return superview;
2978 }
2979 
2985 - (void)scrollClipView:(CPClipView)aClipView toPoint:(CGPoint)aPoint
2986 {
2987  [aClipView scrollToPoint:aPoint];
2988 }
2989 
2995 - (void)reflectScrolledClipView:(CPClipView)aClipView
2996 {
2997 }
2998 
3002 - (BOOL)inLiveResize
3003 {
3004  return [self window] && [[self window] _inLiveResize];
3005 }
3006 
3016 - (void)viewWillStartLiveResize
3017 {
3018  _inLiveResize = YES;
3019 }
3020 
3031 - (void)viewDidEndLiveResize
3032 {
3033  _inLiveResize = NO;
3034 }
3035 
3036 @end
3037 
3038 @implementation CPView (KeyView)
3039 
3054 - (BOOL)performKeyEquivalent:(CPEvent)anEvent
3055 {
3056  var count = [_subviews count];
3057 
3058  // Is reverse iteration correct here? It matches the other (correct) code like hit testing.
3059  while (count--)
3060  if ([_subviews[count] performKeyEquivalent:anEvent])
3061  return YES;
3062 
3063  return NO;
3064 }
3065 
3066 - (BOOL)canBecomeKeyView
3067 {
3068  return [self acceptsFirstResponder] && ![self isHiddenOrHasHiddenAncestor];
3069 }
3070 
3071 - (CPView)nextKeyView
3072 {
3073  return _nextKeyView;
3074 }
3075 
3076 - (CPView)nextValidKeyView
3077 {
3078  var result = [self nextKeyView],
3079  resultUID = [result UID],
3080  unsuitableResults = {};
3081 
3082  while (result && ![result canBecomeKeyView])
3083  {
3084  unsuitableResults[resultUID] = 1;
3085  result = [result nextKeyView];
3086 
3087  resultUID = [result UID];
3088 
3089  // Did we get back to a key view we already ruled out due to ![result canBecomeKeyView]?
3090  if (unsuitableResults[resultUID])
3091  return nil;
3092  }
3093 
3094  return result;
3095 }
3096 
3097 - (CPView)previousKeyView
3098 {
3099  return _previousKeyView;
3100 }
3101 
3102 - (CPView)previousValidKeyView
3103 {
3104  var result = [self previousKeyView],
3105  firstResult = result;
3106 
3107  while (result && ![result canBecomeKeyView])
3108  {
3109  result = [result previousKeyView];
3110 
3111  // Cycled.
3112  if (result === firstResult)
3113  return nil;
3114  }
3115 
3116  return result;
3117 }
3118 
3119 - (void)_setPreviousKeyView:(CPView)previous
3120 {
3121  if (![previous isEqual:self])
3122  {
3123  var previousWindow = [previous window];
3124 
3125  if (!previousWindow || previousWindow === _window)
3126  {
3127  _previousKeyView = previous;
3128  return;
3129  }
3130  }
3131 
3132  _previousKeyView = nil;
3133 }
3134 
3135 - (void)setNextKeyView:(CPView)next
3136 {
3137  if (![next isEqual:self])
3138  {
3139  var nextWindow = [next window];
3140 
3141  if (!nextWindow || nextWindow === _window)
3142  {
3143  _nextKeyView = next;
3144  [_nextKeyView _setPreviousKeyView:self];
3145  return;
3146  }
3147  }
3148 
3149  _nextKeyView = nil;
3150 }
3151 
3152 @end
3153 
3155 
3159 - (void)setLayer:(CALayer)aLayer
3160 {
3161  if (_layer === aLayer)
3162  return;
3163 
3164  if (_layer)
3165  {
3166  _layer._owningView = nil;
3167 #if PLATFORM(DOM)
3168  _DOMElement.removeChild(_layer._DOMElement);
3169 #endif
3170  }
3171 
3172  _layer = aLayer;
3173 
3174  if (_layer)
3175  {
3176  var bounds = CGRectMakeCopy([self bounds]);
3177 
3178  [_layer _setOwningView:self];
3179 
3180 #if PLATFORM(DOM)
3181  _layer._DOMElement.style.zIndex = 100;
3182 
3183  _DOMElement.appendChild(_layer._DOMElement);
3184 #endif
3185  }
3186 }
3187 
3192 {
3193  return _layer;
3194 }
3195 
3200 - (void)setWantsLayer:(BOOL)aFlag
3201 {
3202  _wantsLayer = !!aFlag;
3203 }
3204 
3209 - (BOOL)wantsLayer
3210 {
3211  return _wantsLayer;
3212 }
3213 
3214 @end
3215 
3216 
3217 @implementation CPView (Scaling)
3218 
3224 - (void)setScaleSize:(CGSize)aSize
3225 {
3226  if (CGSizeEqualToSize(_scaleSize, aSize))
3227  return;
3228 
3229  var size = CGSizeMakeZero(),
3230  scale = CGSizeMakeCopy([self scaleSize]);
3231 
3232  size.height = aSize.height / scale.height;
3233  size.width = aSize.width / scale.width;
3234 
3235  [self scaleUnitSquareToSize:size];
3236  [self setNeedsDisplay:YES];
3237 }
3238 
3239 
3243 - (CGSize)scaleSize
3244 {
3245  return _scaleSize || CGSizeMake(1.0, 1.0);
3246 }
3247 
3248 @end
3249 
3250 
3251 @implementation CPView (Theming)
3252 
3253 #pragma mark Override
3254 
3255 - (BOOL)setThemeState:(ThemeState)aState
3256 {
3257  var shouldLayout = [super setThemeState:aState];
3258 
3259  if (!shouldLayout)
3260  return NO;
3261 
3262  [self setNeedsLayout:YES];
3263  [self setNeedsDisplay:YES];
3264 
3265  return YES;
3266 }
3267 
3268 - (BOOL)unsetThemeState:(ThemeState)aState
3269 {
3270  var shouldLayout = [super unsetThemeState:aState];
3271 
3272  if (!shouldLayout)
3273  return NO;
3274 
3275  [self setNeedsLayout:YES];
3276  [self setNeedsDisplay:YES];
3277 
3278  return YES;
3279 }
3280 
3281 - (void)setThemeClass:(CPString)theClass
3282 {
3283  [super setThemeClass:theClass];
3284 
3285  [self setNeedsLayout];
3286  [self setNeedsDisplay:YES];
3287 }
3288 
3289 
3290 #pragma mark First responder
3291 
3292 - (BOOL)becomeFirstResponder
3293 {
3294  var r = [super becomeFirstResponder];
3295 
3296  if (r)
3297  [self _notifyViewDidBecomeFirstResponder];
3298 
3299  return r;
3300 }
3301 
3302 - (void)_notifyViewDidBecomeFirstResponder
3303 {
3304  [self setThemeState:CPThemeStateFirstResponder];
3305 
3306  var count = [_subviews count];
3307 
3308  while (count--)
3309  [_subviews[count] _notifyViewDidBecomeFirstResponder];
3310 }
3311 
3312 - (BOOL)resignFirstResponder
3313 {
3314  var r = [super resignFirstResponder];
3315 
3316  if (r)
3317  [self _notifyViewDidResignFirstResponder];
3318 
3319  return r;
3320 }
3321 
3322 - (void)_notifyViewDidResignFirstResponder
3323 {
3324  [self unsetThemeState:CPThemeStateFirstResponder];
3325 
3326  var count = [_subviews count];
3327 
3328  while (count--)
3329  [_subviews[count] _notifyViewDidResignFirstResponder];
3330 }
3331 
3332 - (void)_notifyWindowDidBecomeKey
3333 {
3334  [self setThemeState:CPThemeStateKeyWindow];
3335 
3336  var count = [_subviews count];
3337 
3338  while (count--)
3339  [_subviews[count] _notifyWindowDidBecomeKey];
3340 }
3341 
3342 - (void)_notifyWindowDidResignKey
3343 {
3344  [self unsetThemeState:CPThemeStateKeyWindow];
3345 
3346  var count = [_subviews count];
3347 
3348  while (count--)
3349  [_subviews[count] _notifyWindowDidResignKey];
3350 }
3351 
3352 #pragma mark Theme Attributes
3353 
3354 - (void)_setThemeIncludingDescendants:(CPTheme)aTheme
3355 {
3356  [self setTheme:aTheme];
3357  [[self subviews] makeObjectsPerformSelector:@selector(_setThemeIncludingDescendants:) withObject:aTheme];
3358 }
3359 
3360 - (void)objectDidChangeTheme
3361 {
3362  if (!_themeAttributes)
3363  return;
3364 
3365  [super objectDidChangeTheme];
3366 
3367  [self setNeedsLayout];
3368  [self setNeedsDisplay:YES];
3369 }
3370 
3371 - (void)setValue:(id)aValue forThemeAttribute:(CPString)aName inState:(ThemeState)aState
3372 {
3373  var currentValue = [self currentValueForThemeAttribute:aName];
3374 
3375  [super setValue:aValue forThemeAttribute:aName inState:aState];
3376 
3377  if ([self currentValueForThemeAttribute:aName] === currentValue)
3378  return;
3379 
3380  [self setNeedsDisplay:YES];
3381  [self setNeedsLayout];
3382 }
3383 
3384 - (void)setValue:(id)aValue forThemeAttribute:(CPString)aName
3385 {
3386  var currentValue = [self currentValueForThemeAttribute:aName];
3387 
3388  [super setValue:aValue forThemeAttribute:aName ];
3389 
3390  if ([self currentValueForThemeAttribute:aName] === currentValue)
3391  return;
3392 
3393  [self setNeedsDisplay:YES];
3394  [self setNeedsLayout];
3395 }
3396 
3397 - (CPView)createEphemeralSubviewNamed:(CPString)aViewName
3398 {
3399  return nil;
3400 }
3401 
3402 - (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
3403 {
3404  return CGRectMakeZero();
3405 }
3406 
3407 - (CPView)layoutEphemeralSubviewNamed:(CPString)aViewName
3408  positioned:(CPWindowOrderingMode)anOrderingMode
3409  relativeToEphemeralSubviewNamed:(CPString)relativeToViewName
3410 {
3411  if (!_ephemeralSubviewsForNames)
3412  {
3413  _ephemeralSubviewsForNames = {};
3414  _ephemeralSubviews = [CPSet set];
3415  }
3416 
3417  var frame = [self rectForEphemeralSubviewNamed:aViewName];
3418 
3419  if (frame)
3420  {
3421  if (!_ephemeralSubviewsForNames[aViewName])
3422  {
3423  _ephemeralSubviewsForNames[aViewName] = [self createEphemeralSubviewNamed:aViewName];
3424 
3425  [_ephemeralSubviews addObject:_ephemeralSubviewsForNames[aViewName]];
3426 
3427  if (_ephemeralSubviewsForNames[aViewName])
3428  [self addSubview:_ephemeralSubviewsForNames[aViewName] positioned:anOrderingMode relativeTo:_ephemeralSubviewsForNames[relativeToViewName]];
3429  }
3430 
3431  if (_ephemeralSubviewsForNames[aViewName])
3432  [_ephemeralSubviewsForNames[aViewName] setFrame:frame];
3433  }
3434  else if (_ephemeralSubviewsForNames[aViewName])
3435  {
3436  [_ephemeralSubviewsForNames[aViewName] removeFromSuperview];
3437 
3438  [_ephemeralSubviews removeObject:_ephemeralSubviewsForNames[aViewName]];
3439  delete _ephemeralSubviewsForNames[aViewName];
3440  }
3441 
3442  return _ephemeralSubviewsForNames[aViewName];
3443 }
3444 
3445 - (CPView)ephemeralSubviewNamed:(CPString)aViewName
3446 {
3447  if (!_ephemeralSubviewsForNames)
3448  return nil;
3449 
3450  return (_ephemeralSubviewsForNames[aViewName] || nil);
3451 }
3452 
3453 @end
3454 
3455 @implementation CPView (CSSTheming)
3456 
3457 - (void)setDOMClassName:(CPString)aClassName
3458 {
3459 #if PLATFORM(DOM)
3460  _DOMElement.className = aClassName;
3461 #endif
3462 }
3463 
3464 @end
3465 
3466 
3467 @implementation CPView (Appearance)
3468 
3471 - (CPAppearance)effectiveAppearance
3472 {
3473  if (_appearance)
3474  return _appearance;
3475 
3476  return [_superview effectiveAppearance];
3477 }
3478 
3479 - (void)setAppearance:(CPAppearance)anAppearance
3480 {
3481  if ([_appearance isEqual:anAppearance])
3482  return;
3483 
3484  [self willChangeValueForKey:@"appearance"];
3485  _appearance = anAppearance;
3486  [self didChangeValueForKey:@"appearance"];
3487 
3488  [self setNeedsLayout:YES];
3489 }
3490 
3493 - (void)_recomputeAppearance
3494 {
3495  var effectiveAppearance = [self effectiveAppearance];
3496 
3497  if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameAqua]])
3498  {
3499  [self setThemeState:CPThemeStateAppearanceAqua];
3500  [self unsetThemeState:CPThemeStateAppearanceLightContent];
3501  [self unsetThemeState:CPThemeStateAppearanceVibrantLight];
3502  [self unsetThemeState:CPThemeStateAppearanceVibrantDark];
3503  }
3504  else if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameLightContent]])
3505  {
3506  [self unsetThemeState:CPThemeStateAppearanceAqua];
3507  [self setThemeState:CPThemeStateAppearanceLightContent];
3508  [self unsetThemeState:CPThemeStateAppearanceVibrantLight];
3509  [self unsetThemeState:CPThemeStateAppearanceVibrantDark];
3510  }
3511  else if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]])
3512  {
3513  [self unsetThemeState:CPThemeStateAppearanceAqua];
3514  [self unsetThemeState:CPThemeStateAppearanceLightContent];
3515  [self setThemeState:CPThemeStateAppearanceVibrantLight];
3516  [self unsetThemeState:CPThemeStateAppearanceVibrantDark];
3517  }
3518  else if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]])
3519  {
3520  [self unsetThemeState:CPThemeStateAppearanceAqua];
3521  [self unsetThemeState:CPThemeStateAppearanceLightContent];
3522  [self unsetThemeState:CPThemeStateAppearanceVibrantLight];
3523  [self setThemeState:CPThemeStateAppearanceVibrantDark];
3524  }
3525  else
3526  {
3527  [self unsetThemeState:CPThemeStateAppearanceAqua];
3528  [self unsetThemeState:CPThemeStateAppearanceLightContent];
3529  [self unsetThemeState:CPThemeStateAppearanceVibrantLight];
3530  [self unsetThemeState:CPThemeStateAppearanceVibrantDark];
3531  }
3532 
3533 // var start = [CPDate new];
3534 
3535  for (var i = 0, size = [_subviews count]; i < size; i++)
3536  {
3537  [[_subviews objectAtIndex:i] _recomputeAppearance];
3538  }
3539 // [_subviews makeObjectsPerformSelector:@selector(_recomputeAppearance)];
3540 
3541 /* var now = [CPDate new];
3542  var elapsedSeconds = [now timeIntervalSinceReferenceDate] - [start timeIntervalSinceReferenceDate];
3543 
3544  CPLog.trace(@"_recomputeAppearance " + [_subviews count] + " subviews in " + elapsedSeconds + @" seconds");
3545 */}
3546 
3547 
3548 @end
3549 
3551 
3552 - (void)addTrackingArea:(CPTrackingArea)trackingArea
3553 {
3554  // Consistency check
3555  if (!trackingArea || [_trackingAreas containsObjectIdenticalTo:trackingArea])
3556  return;
3557 
3558  if ([trackingArea view])
3559  [CPException raise:CPInternalInconsistencyException reason:"Tracking area has already been added to another view."];
3560 
3561  [_trackingAreas addObject:trackingArea];
3562  [trackingArea setView:self];
3563 
3564  if (_window)
3565  [_window _addTrackingArea:trackingArea];
3566 
3567  [trackingArea _updateWindowRect];
3568 }
3569 
3570 - (void)removeTrackingArea:(CPTrackingArea)trackingArea
3571 {
3572  // Consistency check
3573  if (!trackingArea)
3574  return;
3575 
3576  if (![_trackingAreas containsObjectIdenticalTo:trackingArea])
3577  [CPException raise:CPInternalInconsistencyException reason:"Trying to remove unreferenced trackingArea"];
3578 
3579  [self _removeTrackingArea:trackingArea];
3580 }
3581 
3599 - (void)updateTrackingAreas
3600 {
3601 
3602 }
3603 
3604 // Internal methods
3605 
3606 - (void)_removeTrackingArea:(CPTrackingArea)trackingArea
3607 {
3608  if (_window)
3609  [_window _removeTrackingArea:trackingArea];
3610 
3611  [trackingArea setView:nil];
3612  [_trackingAreas removeObjectIdenticalTo:trackingArea];
3613 }
3614 
3615 - (void)_updateTrackingAreasWithRecursion:(BOOL)shouldCallRecursively
3616 {
3617  _inhibitUpdateTrackingAreas = YES;
3618 
3619  [self _updateTrackingAreasForOwners:[self _calcTrackingAreaOwners]];
3620 
3621  if (shouldCallRecursively)
3622  {
3623  // Now, call _updateTrackingAreasWithRecursion on subviews
3624 
3625  for (var i = 0; i < _subviews.length; i++)
3626  [_subviews[i] _updateTrackingAreasWithRecursion:YES];
3627  }
3628 
3629  _inhibitUpdateTrackingAreas = NO;
3630 }
3631 
3632 - (CPArray)_calcTrackingAreaOwners
3633 {
3634  // First search all owners that must be notified
3635  // Remark: 99.99% of time, the only owner will be the view itself
3636  // In the same time, update the rects of InVisibleRect tracking areas
3637 
3638  var owners = [];
3639 
3640  for (var i = 0; i < _trackingAreas.length; i++)
3641  {
3642  var trackingArea = _trackingAreas[i];
3643 
3644  if ([trackingArea options] & CPTrackingInVisibleRect)
3645  [trackingArea _updateWindowRect];
3646 
3647  else
3648  {
3649  var owner = [trackingArea owner];
3650 
3651  if (![owners containsObjectIdenticalTo:owner])
3652  [owners addObject:owner];
3653  }
3654  }
3655 
3656  return owners;
3657 }
3658 
3659 - (void)_updateTrackingAreasForOwners:(CPArray)owners
3660 {
3661  for (var i = 0; i < owners.length; i++)
3662  [owners[i] updateTrackingAreas];
3663 }
3664 
3665 @end
3666 
3667 var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
3668  CPViewAutoresizesSubviewsKey = @"CPViewAutoresizesSubviews",
3669  CPViewBackgroundColorKey = @"CPViewBackgroundColor",
3670  CPViewBoundsKey = @"CPViewBoundsKey",
3671  CPViewFrameKey = @"CPViewFrameKey",
3672  CPViewHitTestsKey = @"CPViewHitTestsKey",
3673  CPViewToolTipKey = @"CPViewToolTipKey",
3674  CPViewIsHiddenKey = @"CPViewIsHiddenKey",
3675  CPViewOpacityKey = @"CPViewOpacityKey",
3676  CPViewSubviewsKey = @"CPViewSubviewsKey",
3677  CPViewSuperviewKey = @"CPViewSuperviewKey",
3678  CPViewTagKey = @"CPViewTagKey",
3679  CPViewWindowKey = @"CPViewWindowKey",
3680  CPViewNextKeyViewKey = @"CPViewNextKeyViewKey",
3681  CPViewPreviousKeyViewKey = @"CPViewPreviousKeyViewKey",
3682  CPReuseIdentifierKey = @"CPReuseIdentifierKey",
3683  CPViewScaleKey = @"CPViewScaleKey",
3684  CPViewSizeScaleKey = @"CPViewSizeScaleKey",
3685  CPViewIsScaledKey = @"CPViewIsScaledKey",
3686  CPViewAppearanceKey = @"CPViewAppearanceKey",
3687  CPViewTrackingAreasKey = @"CPViewTrackingAreasKey";
3688 
3689 @implementation CPView (CPCoding)
3690 
3696 - (id)initWithCoder:(CPCoder)aCoder
3697 {
3698  // We create the DOMElement "early" because there is a chance that we
3699  // will decode our superview before we are done decoding, at which point
3700  // we have to have an element to place in the tree. Perhaps there is
3701  // a more "elegant" way to do this...?
3702 #if PLATFORM(DOM)
3703  _DOMElement = DOMElementPrototype.cloneNode(false);
3704  AppKitTagDOMElement(self, _DOMElement);
3705 #endif
3706 
3707  // Also decode these "early".
3708  _frame = [aCoder decodeRectForKey:CPViewFrameKey];
3709  _bounds = [aCoder decodeRectForKey:CPViewBoundsKey];
3710 
3711  self = [super initWithCoder:aCoder];
3712 
3713  if (self)
3714  {
3715  _trackingAreas = [aCoder decodeObjectForKey:CPViewTrackingAreasKey];
3716 
3717  if (!_trackingAreas)
3718  _trackingAreas = [];
3719 
3720  // We have to manually check because it may be 0, so we can't use ||
3721  _tag = [aCoder containsValueForKey:CPViewTagKey] ? [aCoder decodeIntForKey:CPViewTagKey] : -1;
3722  _identifier = [aCoder decodeObjectForKey:CPReuseIdentifierKey];
3723 
3724  _window = [aCoder decodeObjectForKey:CPViewWindowKey];
3725  _superview = [aCoder decodeObjectForKey:CPViewSuperviewKey];
3726  // We have to manually add the subviews so that they will receive
3727  // viewWillMoveToSuperview: and viewDidMoveToSuperview:
3728  _subviews = [];
3729 
3730  var subviews = [aCoder decodeObjectForKey:CPViewSubviewsKey] || [];
3731 
3732  for (var i = 0, count = [subviews count]; i < count; ++i)
3733  {
3734  // addSubview won't do anything if the superview is already self, so clear it
3735  subviews[i]._superview = nil;
3736  [self addSubview:subviews[i]];
3737  }
3738 
3739  // FIXME: Should we encode/decode this?
3740  _registeredDraggedTypes = [CPSet set];
3741  _registeredDraggedTypesArray = [];
3742 
3743  // Other views (CPBox) might set an autoresizes mask on their subviews before it is actually decoded.
3744  // We make sure we don't override the value by checking if it was already set.
3745  if (_autoresizingMask === nil)
3746  _autoresizingMask = [aCoder decodeIntForKey:CPViewAutoresizingMaskKey] || CPViewNotSizable;
3747 
3748  _autoresizesSubviews = ![aCoder containsValueForKey:CPViewAutoresizesSubviewsKey] || [aCoder decodeBoolForKey:CPViewAutoresizesSubviewsKey];
3749 
3750  _hitTests = ![aCoder containsValueForKey:CPViewHitTestsKey] || [aCoder decodeBoolForKey:CPViewHitTestsKey];
3751 
3752  _toolTip = [aCoder decodeObjectForKey:CPViewToolTipKey];
3753 
3754  if (_toolTip)
3755  [self _installToolTipEventHandlers];
3756 
3757  _scaleSize = [aCoder containsValueForKey:CPViewScaleKey] ? [aCoder decodeSizeForKey:CPViewScaleKey] : CGSizeMake(1.0, 1.0);
3758  _hierarchyScaleSize = [aCoder containsValueForKey:CPViewSizeScaleKey] ? [aCoder decodeSizeForKey:CPViewSizeScaleKey] : CGSizeMake(1.0, 1.0);
3759  _isScaled = [aCoder containsValueForKey:CPViewIsScaledKey] ? [aCoder decodeBoolForKey:CPViewIsScaledKey] : NO;
3760 
3761  // DOM SETUP
3762 #if PLATFORM(DOM)
3763  _cssStylePreviousState = @[];
3764 
3765  _DOMImageParts = [];
3766  _DOMImageSizes = [];
3767 
3768  CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(_frame), CGRectGetMinY(_frame));
3769  [self _setDisplayServerSetStyleSize:_frame.size];
3770 
3771  var index = 0,
3772  count = _subviews.length;
3773 
3774  for (; index < count; ++index)
3775  {
3776  CPDOMDisplayServerAppendChild(_DOMElement, _subviews[index]._DOMElement);
3777  //_subviews[index]._superview = self;
3778  }
3779 #endif
3780 
3781  [self setHidden:[aCoder decodeBoolForKey:CPViewIsHiddenKey]];
3782  _isHiddenOrHasHiddenAncestor = NO;
3783 
3784  if ([aCoder containsValueForKey:CPViewOpacityKey])
3785  [self setAlphaValue:[aCoder decodeIntForKey:CPViewOpacityKey]];
3786  else
3787  _opacity = 1.0;
3788 
3789  [self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]];
3790  [self _setupViewFlags];
3791  [self _decodeThemeObjectsWithCoder:aCoder];
3792 
3793  [self setAppearance:[aCoder decodeObjectForKey:CPViewAppearanceKey]];
3794 
3795  [self setNeedsDisplay:YES];
3796  [self setNeedsLayout];
3797  }
3798 
3799  return self;
3800 }
3801 
3806 - (void)encodeWithCoder:(CPCoder)aCoder
3807 {
3808  [super encodeWithCoder:aCoder];
3809 
3810  if (_tag !== -1)
3811  [aCoder encodeInt:_tag forKey:CPViewTagKey];
3812 
3813  [aCoder encodeRect:_frame forKey:CPViewFrameKey];
3814  [aCoder encodeRect:_bounds forKey:CPViewBoundsKey];
3815 
3816  // This will come out nil on the other side with decodeObjectForKey:
3817  if (_window !== nil)
3818  [aCoder encodeConditionalObject:_window forKey:CPViewWindowKey];
3819 
3820  var count = [_subviews count],
3821  encodedSubviews = _subviews;
3822 
3823  if (count > 0 && [_ephemeralSubviews count] > 0)
3824  {
3825  encodedSubviews = [encodedSubviews copy];
3826 
3827  while (count--)
3828  if ([_ephemeralSubviews containsObject:encodedSubviews[count]])
3829  encodedSubviews.splice(count, 1);
3830  }
3831 
3832  if (encodedSubviews.length > 0)
3833  [aCoder encodeObject:encodedSubviews forKey:CPViewSubviewsKey];
3834 
3835  // This will come out nil on the other side with decodeObjectForKey:
3836  if (_superview !== nil)
3837  [aCoder encodeConditionalObject:_superview forKey:CPViewSuperviewKey];
3838 
3839  if (_autoresizingMask !== CPViewNotSizable)
3840  [aCoder encodeInt:_autoresizingMask forKey:CPViewAutoresizingMaskKey];
3841 
3842  if (!_autoresizesSubviews)
3843  [aCoder encodeBool:_autoresizesSubviews forKey:CPViewAutoresizesSubviewsKey];
3844 
3845  if (_backgroundColor !== nil)
3846  [aCoder encodeObject:_backgroundColor forKey:CPViewBackgroundColorKey];
3847 
3848  if (_hitTests !== YES)
3849  [aCoder encodeBool:_hitTests forKey:CPViewHitTestsKey];
3850 
3851  if (_opacity !== 1.0)
3852  [aCoder encodeFloat:_opacity forKey:CPViewOpacityKey];
3853 
3854  if (_isHidden)
3855  [aCoder encodeBool:_isHidden forKey:CPViewIsHiddenKey];
3856 
3857  if (_toolTip)
3858  [aCoder encodeObject:_toolTip forKey:CPViewToolTipKey];
3859 
3860  var nextKeyView = [self nextKeyView];
3861 
3862  if (nextKeyView !== nil && ![nextKeyView isEqual:self])
3863  [aCoder encodeConditionalObject:nextKeyView forKey:CPViewNextKeyViewKey];
3864 
3865  var previousKeyView = [self previousKeyView];
3866 
3867  if (previousKeyView !== nil && ![previousKeyView isEqual:self])
3868  [aCoder encodeConditionalObject:previousKeyView forKey:CPViewPreviousKeyViewKey];
3869 
3870  [self _encodeThemeObjectsWithCoder:aCoder];
3871 
3872  if (_identifier)
3873  [aCoder encodeObject:_identifier forKey:CPReuseIdentifierKey];
3874 
3875  [aCoder encodeSize:[self scaleSize] forKey:CPViewScaleKey];
3876  [aCoder encodeSize:[self _hierarchyScaleSize] forKey:CPViewSizeScaleKey];
3877  [aCoder encodeBool:_isScaled forKey:CPViewIsScaledKey];
3878  [aCoder encodeObject:_appearance forKey:CPViewAppearanceKey];
3879  [aCoder encodeObject:_trackingAreas forKey:CPViewTrackingAreasKey];
3880 }
3881 
3882 @end
3883 
3884 var _CPViewFullScreenModeStateMake = function(aView)
3885 {
3886  var superview = aView._superview;
3887 
3888  return { autoresizingMask:aView._autoresizingMask, frame:CGRectMakeCopy(aView._frame), index:(superview ? [superview._subviews indexOfObjectIdenticalTo:aView] : 0), superview:superview };
3889 };
3890 
3891 var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView)
3892 {
3893  var transform = CGAffineTransformMakeIdentity(),
3894  sameWindow = YES,
3895  fromWindow = nil,
3896  toWindow = nil;
3897 
3898  if (fromView)
3899  {
3900  var view = fromView;
3901 
3902  // FIXME: This doesn't handle the case when the outside views are equal.
3903  // If we have a fromView, "climb up" the view tree until
3904  // we hit the root node or we hit the toLayer.
3905  while (view && view != toView)
3906  {
3907  var frame = view._frame;
3908 
3909  if (view._isScaled)
3910  {
3911  var affineZoom = CGAffineTransformMakeScale(view._scaleSize.width, view._scaleSize.height);
3912  CGAffineTransformConcatTo(transform, affineZoom, transform);
3913  }
3914 
3915  transform.tx += CGRectGetMinX(frame);
3916  transform.ty += CGRectGetMinY(frame);
3917 
3918  if (view._boundsTransform)
3919  {
3920  var inverseBoundsTransform = CGAffineTransformMakeCopy(view._boundsTransform);
3921 
3922  if (view._isScaled)
3923  {
3924  var affineZoom = CGAffineTransformMakeScale(view._scaleSize.width, view._scaleSize.height);
3925  CGAffineTransformConcatTo(inverseBoundsTransform, affineZoom, inverseBoundsTransform);
3926  }
3927 
3928  CGAffineTransformConcatTo(transform, inverseBoundsTransform, transform);
3929  }
3930 
3931  view = view._superview;
3932  }
3933 
3934  // If we hit toView, then we're done.
3935  if (view === toView)
3936  {
3937  return transform;
3938  }
3939  else if (fromView && toView)
3940  {
3941  fromWindow = [fromView window];
3942  toWindow = [toView window];
3943 
3944  if (fromWindow && toWindow && fromWindow !== toWindow)
3945  sameWindow = NO;
3946  }
3947  }
3948 
3949  // FIXME: For now we can do things this way, but eventually we need to do them the "hard" way.
3950  var view = toView,
3951  transform2 = CGAffineTransformMakeIdentity();
3952 
3953  while (view && view != fromView)
3954  {
3955  var frame = CGRectMakeCopy(view._frame);
3956 
3957  // FIXME : For now we don't care about rotate transform and so on
3958  if (view._isScaled)
3959  {
3960  transform2.a *= 1 / view._scaleSize.width;
3961  transform2.d *= 1 / view._scaleSize.height;
3962  }
3963 
3964  transform2.tx += CGRectGetMinX(frame) * transform2.a;
3965  transform2.ty += CGRectGetMinY(frame) * transform2.d;
3966 
3967  if (view._boundsTransform)
3968  {
3969  var inverseBoundsTransform = CGAffineTransformMakeIdentity();
3970  inverseBoundsTransform.tx -= view._inverseBoundsTransform.tx * transform2.a;
3971  inverseBoundsTransform.ty -= view._inverseBoundsTransform.ty * transform2.d;
3972 
3973  CGAffineTransformConcatTo(transform2, inverseBoundsTransform, transform2);
3974  }
3975 
3976  view = view._superview;
3977  }
3978 
3979  transform2.tx = -transform2.tx;
3980  transform2.ty = -transform2.ty;
3981 
3982  if (view === fromView)
3983  {
3984  // toView is inside of fromView
3985  return transform2;
3986  }
3987 
3988  CGAffineTransformConcatTo(transform, transform2, transform);
3989 
3990  return transform;
3991 
3992 
3993 
3994 /* var views = [],
3995  view = toView;
3996 
3997  while (view)
3998  {
3999  views.push(view);
4000  view = view._superview;
4001  }
4002 
4003  var index = views.length;
4004 
4005  while (index--)
4006  {
4007  var frame = views[index]._frame;
4008 
4009  transform.tx -= CGRectGetMinX(frame);
4010  transform.ty -= CGRectGetMinY(frame);
4011  }*/
4012 
4013  return transform;
4014 };
id initWithFrame:(CGRect aFrame)
Definition: CPView.j:351
Used to implement exception handling (creating & raising).
Definition: CPException.h:2
void viewDidMoveToSuperview()
Definition: CPView.j:882
void lockFocus()
Definition: CPView.j:2689
void viewWillLayout()
Definition: CPView.j:2793
Definition: CPMenu.h:2
BOOL isHidden()
Definition: CALayer.j:597
void addSubview:(CPView aSubview)
Definition: CPView.j:536
void drawRect:(CGRect aRect)
Definition: CPView.j:2505
void layoutSubviews()
Definition: CPView.j:2806
void setAppearance:(CPAppearance anAppearance)
Definition: CPView.j:3479
id init()
Definition: CALayer.j:126
CGRect frame
CPCSSRGBAFeature
function CGAffineTransformMakeIdentity()
var isEqual
void postNotificationName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
void scrollToPoint:(CGPoint aPoint)
Definition: CPClipView.j:102
An object representation of nil.
Definition: CPNull.h:2
var CPReuseIdentifierKey
Definition: CPView.j:3682
CPViewWidthSizable
Definition: CPView.j:67
void layout()
Definition: CPView.j:2771
function CGAffineTransformMakeScale(sx, sy)
CPViewMaxYMargin
Definition: CPView.j:91
var CPViewIsHiddenKey
Definition: CPView.j:3674
CPString className()
Definition: CPObject.j:527
var CPViewSubviewsKey
Definition: CPView.j:3676
CPView previousKeyView()
Definition: CPView.j:3097
void setView:(CPView aValue)
BOOL autoscroll:(CPEvent anEvent)
Definition: CPView.j:2941
function CPBrowserBackingStorePixelRatio(context)
var CPViewHasCustomLayoutSubviews
Definition: CPView.j:116
var CPViewPreviousKeyViewKey
Definition: CPView.j:3681
void setFrame:(CGRect aFrame)
Definition: CPView.j:1020
function CGContextRestoreGState(aContext)
Definition: CGContext.j:156
function CGAffineTransformMakeCopy(anAffineTransform)
var CPViewFrameKey
Definition: CPView.j:3671
var CPViewBoundsKey
Definition: CPView.j:3670
void setCurrentContext:(CPGraphicsContext aGraphicsContext)
void viewWillDraw()
Definition: CPView.j:2682
int width
CGRect bounds()
Definition: CPView.j:1326
void raise:reason:(CPString aName, [reason] CPString aReason)
Definition: CPException.j:66
void removeFromSuperview()
Definition: CPView.j:678
var CPViewOpacityKey
Definition: CPView.j:3675
Definition: CALayer.h:2
BOOL enterFullScreenMode:withOptions:(CPScreen aScreen, [withOptions] CPDictionary options)
Definition: CPView.j:1539
var CPViewHasCustomDrawRect
Definition: CPView.j:115
void viewDidLayout()
Definition: CPView.j:2801
void setNeedsDisplayInRect:(CGRect aRect)
Definition: CPView.j:2610
var CPViewTagKey
Definition: CPView.j:3678
var CPViewAppearanceKey
Definition: CPView.j:3686
CPNotificationCenter defaultCenter()
CPInvalidArgumentException
Definition: CPException.j:25
A mutable key-value pair collection.
Definition: CPDictionary.h:2
var CPViewSizeScaleKey
Definition: CPView.j:3684
function ThemeState(stateNames)
Definition: CPTheme.j:379
void setNeedsDisplay()
Definition: CALayer.j:830
void displayRectIgnoringOpacity:inContext:(CGRect aRect, [inContext] CPGraphicsContext aGraphicsContext)
Definition: CPView.j:2667
void setBoundsOrigin:(CGPoint aPoint)
Definition: CPView.j:1347
void displayRect:(CGRect aRect)
Definition: CPView.j:2658
var CPViewWindowKey
Definition: CPView.j:3679
CGRect bounds()
Definition: CALayer.j:203
void display()
Definition: CALayer.j:488
CALayer layer()
Definition: CALayer.j:118
CPWindow window()
Definition: CPView.j:527
void setNeedsLayout:(BOOL needLayout)
Definition: CPView.j:2753
CPColor blackColor()
Definition: CPColor.j:284
id initWithContentRect:styleMask:(CGRect aContentRect, [styleMask] unsigned aStyleMask)
Definition: CPWindow.j:265
void viewWillMoveToSuperview:(CPView aView)
Definition: CPView.j:899
var CPViewAutoresizingMaskKey
Definition: CPView.j:3667
CPView createEphemeralSubviewNamed:(CPString aViewName)
Definition: CPView.j:3397
id initWithName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
var CPViewTrackingAreasKey
Definition: CPView.j:3687
An immutable string (collection of characters).
Definition: CPString.h:2
CGPoint convertPoint:fromView:(CGPoint aPoint, [fromView] CPView aView)
Definition: CPView.j:2249
var CPViewBackgroundColorKey
Definition: CPView.j:3669
var CPViewIsScaledKey
Definition: CPView.j:3685
Definition: CPImage.h:2
void addSubview:positioned:relativeTo:(CPView aSubview, [positioned] CPWindowOrderingMode anOrderingMode, [relativeTo] CPView anotherView)
Definition: CPView.j:547
function CPFeatureIsCompatible(aFeature)
var CachedNotificationCenter
Definition: CPView.j:101
CGRect convertRect:toView:(CGRect aRect, [toView] CPView aView)
Definition: CPView.j:2350
CPViewMinXMargin
Definition: CPView.j:61
CPView nextValidKeyView()
Definition: CPView.j:3076
void setHidden:(BOOL aFlag)
Definition: CPView.j:1603
void setAutoresizingMask:(unsigned aMask)
Definition: CPView.j:1511
BOOL isOpaque()
Definition: CPView.j:2814
void setNeedsDisplay:(BOOL aFlag)
Definition: CPView.j:2597
CPGraphicsContext graphicsContextWithGraphicsPort:flipped:(CGContext aContext, [flipped] BOOL aFlag)
CPMenu menuForEvent:(CPEvent anEvent)
Definition: CPView.j:1938
CPAppearanceNameAqua
Definition: CPAppearance.j:24
CGPoint convertPoint:toView:(CGPoint aPoint, [toView] CPView aView)
Definition: CPView.j:2273
CPViewBoundsDidChangeNotification
Definition: CPView.j:98
int tag
CPWindow window()
Definition: CPEvent.j:341
function CGAffineTransformMakeTranslation(tx, ty)
var CPViewSuperviewKey
Definition: CPView.j:3677
var CPViewScaleKey
Definition: CPView.j:3683
function CGContextClearRect(aContext, aRect)
Definition: CGContextVML.j:51
CPColor backgroundColor()
Definition: CALayer.j:629
var CPViewToolTipKey
Definition: CPView.j:3673
A notification that can be posted to a CPNotificationCenter.
Definition: CPNotification.h:2
var CPViewHitTestsKey
Definition: CPView.j:3672
function CGAffineTransformConcatTo(lhs, rhs, to)
CPTheme defaultTheme()
Definition: CPTheme.j:44
CPInternalInconsistencyException
Definition: CPException.j:28
void setAlphaValue:(float anAlphaValue)
Definition: CPView.j:1748
void orderOut:(id aSender)
Definition: CPWindow.j:1020
void setNeedsLayout()
Definition: CPView.j:2748
CGRect convertRect:fromView:(CGRect aRect, [fromView] CPView aView)
Definition: CPView.j:2326
void scaleUnitSquareToSize:(CGSize aSize)
Definition: CPView.j:2518
function CGSizeApplyAffineTransform(aSize, aTransform)
CPViewMaxXMargin
Definition: CPView.j:73
CPAppearanceNameLightContent
Definition: CPAppearance.j:25
CPAppearanceNameVibrantDark
Definition: CPAppearance.j:26
global appkit_tag_dom_elements typedef _CPViewFullScreenModeState CPViewNotSizable
Definition: CPView.j:55
var CPViewFlags
Definition: CPView.j:114
function CPBrowserStyleProperty(aProperty)
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
CPNotFound
Definition: CPObjJRuntime.j:62
void updateTrackingAreas()
Definition: CPView.j:3599
var CPViewHighDPIDrawingEnabled
Definition: CPView.j:119
CPThemeStateFirstResponder
Definition: CPTheme.j:625
function CGContextSaveGState(aContext)
Definition: CGContext.j:146
Sends messages (CPNotification) between objects.
CPViewHeightSizable
Definition: CPView.j:85
Definition: CPTheme.h:2
CGSize scaleSize()
Definition: CPView.j:3243
CPView nextKeyView()
Definition: CPView.j:3071
void setBounds:(CGRect bounds)
Definition: CPView.j:1300
CPString description()
Definition: CPString.j:178
CGAffineTransform affineTransform()
Definition: CALayer.j:293
var CPViewNextKeyViewKey
Definition: CPView.j:3680
void setBackgroundColor:(CPColor aColor)
Definition: CPView.j:1947
void setBoundsSize:(CGSize aSize)
Definition: CPView.j:1396
CPViewMinYMargin
Definition: CPView.j:79
var CPViewAutoresizesSubviewsKey
Definition: CPView.j:3668
void setFrameSize:(CGSize aSize)
Definition: CPView.j:1124
CPOpacityRequiresFilterFeature
Definition: CPEvent.h:2
void unlockFocus()
Definition: CPView.j:2741
CPView superview()
Definition: CPView.j:510
CPAppearanceNameVibrantLight
Definition: CPAppearance.j:27
var CPViewHasCustomViewWillLayout
Definition: CPView.j:117
unsigned autoresizingMask()
Definition: CPView.j:1519
CPPlatformWindow platformWindow()
Definition: CPWindow.j:389
function CGPointApplyAffineTransform(aPoint, aTransform)
function CPPlatformHasBug(aBug)
void exitFullScreenModeWithOptions:(CPDictionary options)
Definition: CPView.j:1577
function CGBitmapGraphicsContextCreate()
Definition: CGContext.j:136
CPWindowOrderingMode CPWindowAbove
CGRect visibleRect()
Definition: CPView.j:2822
void setFrameOrigin:(CGPoint aPoint)
Definition: CPView.j:1089
CPTrackingInVisibleRect
void resizeSubviewsWithOldSize:(CGSize aSize)
Definition: CPView.j:1478
void popUpContextMenu:withEvent:forView:(CPMenu aMenu, [withEvent] CPEvent anEvent, [forView] CPView aView)
Definition: CPMenu.j:857
CPPlatformWindow primaryPlatformWindow()
CPMenu menu
id alloc()
Definition: CPObject.j:130
CPViewFrameDidChangeNotification
Definition: CPView.j:99
CGRect rectForEphemeralSubviewNamed:(CPString aViewName)
Definition: CPView.j:3402
Definition: CPView.j:137
CPThemeStateKeyWindow
Definition: CPTheme.j:627
BOOL isHiddenOrHasHiddenAncestor()
Definition: CPView.j:1783
CPCanvasParentDrawErrorsOnMovementBug