UNPKG

blossom

Version:

Modern, Cross-Platform Application Framework

208 lines (168 loc) 7.21 kB
// ========================================================================== // Project: Blossom - Modern, Cross-Platform Application Framework // Copyright: ©2012 Fohr Motion Picture Studios. All rights reserved. // License: Licensed under the GPLv3 license (see BLOSSOM-LICENSE). // ========================================================================== /*globals sc_assert */ sc_require('surfaces/composite'); SC.ENTER_LEFT = 'enter-left'; SC.SLIDE_FLIP_LEFT = 'slide-flip-left'; SC.EXIT_RIGHT = 'exit-right'; /** @class `SC.ContainerSurface` implements a swappable surface container. You can set the container's `contentSurface` property to a surface, and the surface will be sized and positioned according to the container's size and position. In addition, the surface will be animated into place using one of three hardware-accellerated 3D transitions: - order in (defaults to SC.ENTER_LEFT) - replace (defaults to SC.SLIDE_FLIP_LEFT) - order out (defaults to SC.EXIT_RIGHT) You can change the transition to use, or set them to `null` to use no transition at all. @extends SC.CompositeSurface @since Blossom 1.0 */ SC.ContainerSurface = SC.CompositeSurface.extend({ // orderInTransition: null, // replaceTransition: null, // orderOutTransition: null, orderInTransition: SC.ENTER_LEFT, replaceTransition: SC.SLIDE_FLIP_LEFT, orderOutTransition: SC.EXIT_RIGHT, /** @property The surface displayed by this container. The surface's parent layout is relative to the container, and sized based on its bounds. Animated, hardware-accelerated 3D transitions are available when changing the surface. There are three possible transitions: - order in (defaults to SC.ENTER_LEFT) - replace (defaults to SC.SLIDE_FLIP_LEFT) - order out (defaults to SC.EXIT_RIGHT) You can change the type of transition for each of these situations, and that transition will be used whenever the `surface` property is changed. @type SC.Surface or null */ contentSurface: null, _sc_contentSurface: null, // Required, we're strict about null checking. _sc_contentSurfaceDidChange: function() { // console.log('SC.ContainerSurface#_sc_contentSurfaceDidChange()'); var old = this._sc_contentSurface, cur = this.get('contentSurface'), transition, frame = this.get('frame'); // element = this.__sc_element__, // container, style; sc_assert(old === null || old.kindOf(SC.Surface), "Blossom internal error: SC.Application^_sc_surface is invalid."); sc_assert(cur === null || cur.kindOf(SC.Surface), "SC.ContainerSurface@surface must either be null or an SC.Surface instance."); if (old === cur) return; // Nothing to do. // HACK: Work around a WebKit bug where the screen is black on first load. if (SC.isExecutingMain) { setTimeout(function() { document.body.insertBefore(document.createElement('div'), null); }, 0); } this._sc_contentSurface = cur; if (cur) { // cur.set('container', this); cur.set('frame', frame); cur.setIfChanged('isPresentInViewport', this.get('isPresentInViewport')); cur.setIfChanged('applicationHasFocus', this.get('applicationHasFocus')); } if (!old && cur) transition = this.get('orderInTransition'); else if (old && cur) transition = this.get('replaceTransition'); else if (old && !cur) transition = this.get('orderOutTransition'); else sc_assert(false); // transition = null; // force no transition if (old) transition = null; if (transition) { // order in if (!old && cur) { this.get('subsurfaces').pushObject(cur); cur.set('opacity', 1); var transform = SC.MakeIdentityTransform3D(); transform = SC.Transform3DRotateY(transform, Math.PI); SC.AnimationTransaction.begin({ duration: 0 }); cur.set('transform', transform); var transformOrigin = cur.get('transformOrigin'); transformOrigin.x = 1.0; transformOrigin.y = 0.5; this.set('transformOrigin', transformOrigin); this.set('opacity', 0.0); SC.AnimationTransaction.end(); // HACK: Fix me, use a statechart! this.isWaitingToTransition = true; var that = this; setTimeout(function() { that.isWaitingToTransition = false; SC.RunLoop.begin(); var transform = SC.MakeIdentityTransform3D(); transform = SC.Transform3DTranslateX(transform, frame.width); transform = SC.Transform3DRotateY(transform, -Math.PI); SC.AnimationTransaction.begin({ duration: 2000 }); that.set('transform', transform); SC.AnimationTransaction.end(); SC.AnimationTransaction.begin({ duration: 1000, delay: 1000 }); that.set('opacity', 1.0); SC.AnimationTransaction.end(); SC.RunLoop.end(); }, 0); } // Update the UI without any 3D transition. } else { // Force a sane transform. SC.AnimationTransaction.begin({ duration: 0 }); this.set('transform', SC.MakeIdentityTransform3D()); if (cur) cur.set('transform', SC.MakeIdentityTransform3D()); SC.AnimationTransaction.end(); // order in if (!old && cur) { this.get('subsurfaces').pushObject(cur); // replace } else if (old && cur) { var subsurfaces = this.get('subsurfaces'); subsurfaces.removeObject(old); subsurfaces.pushObject(cur); // order out } else if (old && !cur) { this.get('subsurfaces').removeObject(old); } } this.triggerLayoutAndRendering(); this._sc_containerFrameDidChange(); }.observes('contentSurface'), computeContentSurfaceFrame: function() { var frame = SC.MakeRect(this.get('frame')); frame.x = 0; frame.y = 0; return frame; }, _sc_containerFrameDidChange: function() { // console.log('SC.ContainerSurface#_sc_containerFrameDidChange()'); var frame = this.get('frame'), contentSurface = this.get('contentSurface'); if (!this.isWaitingToTransition) { var transform = SC.MakeIdentityTransform3D(); transform = SC.Transform3DTranslateX(transform, frame.width); transform = SC.Transform3DRotateY(transform, -Math.PI); this.set('transform', transform); } if (contentSurface) { frame = this.computeContentSurfaceFrame(); contentSurface.set('frame', frame); if (contentSurface.__useContentSize__) { contentSurface.__contentWidth__ = frame.width; contentSurface.__contentHeight__ = frame.height; contentSurface.triggerContentSizeUpdate(); } } }.observes('frame'), updateLayout: function() { // console.log('SC.ContainerSurface#updateLayout()'); var contentSurface = this.get('contentSurface'); if (contentSurface) contentSurface.updateLayout(); }, updateDisplay: function() { // console.log('SC.ContainerSurface#updateDisplay()'); var contentSurface = this.get('contentSurface'); if (contentSurface) contentSurface.updateDisplay(); } });