StoryPaneController.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. 'use strict';
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: Storytelling
  5. * (C) Copyright IBM Corp. 2014, 2019
  6. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  7. */
  8. define(['baglass/core-client/js/core-client/ui/core/Events', 'underscore', 'baglass/core-client/js/core-client/utils/ClassFactory'], function (Events, _, ClassFactory) {
  9. var Controller = Events.extend({
  10. authoring: false,
  11. currentSceneIndex: 0,
  12. timelineController: null,
  13. sceneCount: 0,
  14. fullscreen: false,
  15. // Map 'layout type' to 'listing' values
  16. layoutToListing: {
  17. slideshow: 'slideShow',
  18. panAndZoom1: 'panAndZoom1',
  19. panAndZoom2: 'panAndZoom2',
  20. panAndZoom3: 'panAndZoom3',
  21. panAndZoom4: 'panAndZoom4',
  22. panAndZoom5: 'panAndZoom5',
  23. panAndZoom6: 'panAndZoom6'
  24. },
  25. init: function init(options) {
  26. Controller.inherited('init', this, arguments);
  27. this.eventRouter = options.eventRouter;
  28. this.model = options.model; // dashboard-core.BoardModel
  29. this.timelineController = options.timelineController;
  30. this.authoring = options.authoring;
  31. this.dashboardApi = options.dashboardApi;
  32. // Listen for events.
  33. this.eventRouter.on('layoutType:changed', this._onLayoutTypeChanged, this);
  34. this.eventRouter.on('mode:change', this.onModeChanged, this);
  35. this.eventRouter.on('navigation:started', this.onNavigationStarted, this);
  36. this.eventRouter.on('navigation:complete', this.onNavigationComplete, this);
  37. this.eventRouter.on('playback:prev', this.previousScene, this);
  38. this.eventRouter.on('playback:next', this.nextScene, this);
  39. this.eventRouter.on('playback:togglePlayPause', this.togglePlayPause, this);
  40. this.eventRouter.on('timeline:end', this.playThrough, this);
  41. this.model.layout.on('change:showOverviews', this.onShowOverviewsChanged, this);
  42. this.model.layout.on('change:pageSize', this.onPageSizeChange, this);
  43. this.timelineController.on('time:update', this.onTimeUpdated, this);
  44. this.timelineController.on('playState:change', this.onTimeStateChanged, this);
  45. this.timelineController.on('navigateMarkers:change', this.onNavigateMarkersChange, this);
  46. this.timelineController.on('kioskMode:change', this.onKioskModeChange, this);
  47. // Start listening for layouts being added.
  48. this.model.on('addLayouts', this.onAddLayouts, this);
  49. this.model.on('removeLayouts', this.onRemoveLayout, this);
  50. // Keep track of the scene count.
  51. this.sceneCount = this.getSceneCount();
  52. this.playThroughTimer = null;
  53. this.overviewPauseLength = 5000; // ms
  54. this.startOverviewIndex = -1;
  55. this.endOverviewIndex = -2;
  56. // we want to display scene 0 in authoring mode even if we have overviews
  57. this.currentSceneIndex = this.showStartOverview() && !this.isAuthoring() ? this.startOverviewIndex : 0;
  58. // the start/end overview id relate to the 'id' property from the consumeView PanAndZoomLayout._overviews array
  59. this.startOverviewId = 'start';
  60. this.endOverviewId = 'end';
  61. this.currentSceneId = this.showStartOverview() && !this.isAuthoring() ? this.startOverviewId : this.model.layout.items[0].id;
  62. // track sharing
  63. this.shareState = null;
  64. },
  65. onStoryLayoutReady: function onStoryLayoutReady(sceneId, sceneTime) {
  66. // set the current index to match the id from the shareable URL
  67. if (sceneId) {
  68. // the indices -1 and -2 are used as scene IDs for start overview and end overview
  69. var idx = parseInt(sceneId, 10);
  70. this.currentSceneIndex = idx < 0 ? idx : this.getSceneIndex(sceneId);
  71. }
  72. // Update the time queue with the current scene.
  73. this._updateSelectedScene();
  74. // Make the state of the story match
  75. this.timelineController.maxPreviousScenes(this.currentSceneIndex);
  76. this.timelineController.zeroFutureScenes(this.currentSceneIndex);
  77. // set the current time to match the time from the shareable URL
  78. if (sceneTime >= 0) {
  79. this.setCurrentTime(sceneTime);
  80. }
  81. },
  82. destroy: function destroy() {
  83. this.eventRouter.off('layoutType:changed', this._onLayoutTypeChanged, this);
  84. this.eventRouter.off('mode:change', this.onModeChanged, this);
  85. this.eventRouter.off('navigation:started', this.onNavigationStarted, this);
  86. this.eventRouter.off('navigation:complete', this.onNavigationComplete, this);
  87. this.eventRouter.off('playback:prev', this.previousScene, this);
  88. this.eventRouter.off('playback:next', this.nextScene, this);
  89. this.eventRouter.off('playback:togglePlayPause', this.togglePlayPause, this);
  90. this.eventRouter.off('timeline:end', this.playThrough, this);
  91. this.model.layout.off('change:showOverviews', this.onShowOverviewsChanged, this);
  92. this.model.layout.off('change:pageSize', this.onPageSizeChange, this);
  93. this.timelineController.off('time:update', this.onTimeUpdated, this);
  94. this.timelineController.off('playState:change', this.onTimeStateChanged, this);
  95. this.timelineController.off('navigateMarkers:change', this.onNavigateMarkersChange, this);
  96. this.timelineController.off('kioskMode:change', this.onKioskModeChange, this);
  97. // Stop listening for layouts being added.
  98. this.model.off('addLayouts', this.onAddLayouts, this);
  99. this.model.off('removeLayouts', this.onRemoveLayout, this);
  100. },
  101. /**
  102. * Callback when share panel shows.
  103. * @param slideout {Object} The share panel slideout
  104. */
  105. enterShareState: function enterShareState(slideout) {
  106. if (!this.shareState) {
  107. var playing = this.isPlaying();
  108. if (playing) {
  109. this.pause();
  110. }
  111. this.shareState = { wasPlaying: playing, slideout: slideout };
  112. }
  113. },
  114. /**
  115. * Callback when share panel hides.
  116. */
  117. leaveShareState: function leaveShareState() {
  118. if (this.shareState) {
  119. if (this.shareState.wasPlaying && !this.isPlaying()) {
  120. this.play();
  121. }
  122. this.shareState = null;
  123. }
  124. },
  125. enterPrintMode: function enterPrintMode() {
  126. return this.timelineController.maxPreviousScenes(-2);
  127. },
  128. leavePrintMode: function leavePrintMode(sceneTime) {
  129. var _this = this;
  130. return this.timelineController.zeroFutureScenes(-1).then(function () {
  131. if (sceneTime >= 0) {
  132. _this.setCurrentTime(sceneTime);
  133. }
  134. });
  135. },
  136. getTimelineController: function getTimelineController() {
  137. return this.timelineController;
  138. },
  139. pause: function pause() {
  140. this.cancelPlaythroughTimer();
  141. this.timelineController.pause();
  142. },
  143. cancelPlaythroughTimer: function cancelPlaythroughTimer() {
  144. if (this.playThroughTimer) {
  145. clearTimeout(this.playThroughTimer);
  146. this.playThroughTimer = null;
  147. }
  148. },
  149. selectNextSceneAfterPause: function selectNextSceneAfterPause(options) {
  150. if (!this.playThroughTimer) {
  151. this.playThroughTimer = setTimeout(function () {
  152. if (!this.isAuthoring()) {
  153. this.nextScene(options);
  154. }
  155. }.bind(this), this.overviewPauseLength);
  156. }
  157. },
  158. playThrough: function playThrough(event) {
  159. if (this.isPlayThrough() && !this.isAuthoring() && !this.isPlaying() && event) {
  160. if (event.play !== false) {
  161. if (this.isOverview()) {
  162. this.selectNextSceneAfterPause({ play: true });
  163. } else {
  164. this.nextScene({ play: event.endState === 'playing' });
  165. }
  166. }
  167. }
  168. },
  169. play: function play() {
  170. this.cancelPlaythroughTimer();
  171. if (this.isStartOverview()) {
  172. this.selectScene({
  173. index: 0,
  174. play: true
  175. });
  176. } else {
  177. this.timelineController.play();
  178. }
  179. },
  180. stop: function stop() {
  181. this.cancelPlaythroughTimer();
  182. this.timelineController.stop();
  183. },
  184. isScenePopulated: function isScenePopulated(sceneId) {
  185. return this.model.layout.listWidgets([sceneId]).length > 0;
  186. },
  187. isPlaying: function isPlaying() {
  188. return this.timelineController.isPlaying();
  189. },
  190. togglePlayThrough: function togglePlayThrough() {
  191. this.cancelPlaythroughTimer();
  192. this.timelineController.togglePlayThrough();
  193. },
  194. toggleKioskMode: function toggleKioskMode() {
  195. this.timelineController.toggleKioskMode();
  196. // update Next/Prev scene labels
  197. this.trigger('kioskMode:change', { isKioskMode: this.isKioskMode() });
  198. },
  199. toggleNavigateMarkers: function toggleNavigateMarkers() {
  200. this.timelineController.toggleNavigateMarkers();
  201. },
  202. toggleRefreshData: function toggleRefreshData() {
  203. this.timelineController.toggleRefreshData();
  204. },
  205. togglePlayPause: function togglePlayPause() {
  206. if (this.isPlaying()) {
  207. this.pause();
  208. } else {
  209. this.play();
  210. }
  211. },
  212. getCurrentTime: function getCurrentTime() {
  213. return this.timelineController.getCurrentTime();
  214. },
  215. setCurrentTime: function setCurrentTime(time) {
  216. return this.timelineController.setCurrentTime(time);
  217. },
  218. getDuration: function getDuration() {
  219. return this.timelineController.getDuration();
  220. },
  221. widgetAtStartOfCurrentScene: function widgetAtStartOfCurrentScene(widgetId) {
  222. var episode = this.timelineController.getTimelineEpisodeById(widgetId);
  223. if (episode) {
  224. return episode.touchesStart();
  225. }
  226. return false;
  227. },
  228. nextScene: function nextScene(options) {
  229. if (this.isNavigateMarkers() && !this.timelineController.isAtEndOfScene()) {
  230. return this._nextMarker();
  231. } else {
  232. return this._nextScene(options);
  233. }
  234. },
  235. _nextScene: function _nextScene(options) {
  236. this.dashboardApi.deselectAllWidgets();
  237. // Trigger dashboard.
  238. if (this.isKioskMode() && this.isOnLastScene()) {
  239. var refreshData = this.isRefreshData() && !this.isAuthoring();
  240. if (this.getSceneCount() > 1) {
  241. return this._invokeLifeCycleHandlers('scene:next', _.extend({}, options, { to: this.getFirstSceneIndex(), refreshData: refreshData }));
  242. } else {
  243. return this.selectScene({
  244. index: this.getFirstSceneIndex(),
  245. forceSelect: true,
  246. refreshData: refreshData
  247. });
  248. }
  249. } else if (!this.isOnLastScene()) {
  250. return this._invokeLifeCycleHandlers('scene:next', options);
  251. }
  252. },
  253. _nextMarker: function _nextMarker() {
  254. return this.timelineController.jumpToNextMarker();
  255. },
  256. previousScene: function previousScene() {
  257. if (this.isNavigateMarkers() && !this.timelineController.isAtStartOfScene()) {
  258. return this._previousMarker();
  259. } else {
  260. return this._previousScene();
  261. }
  262. },
  263. _previousScene: function _previousScene() {
  264. this.dashboardApi.deselectAllWidgets();
  265. // Trigger dashboard.
  266. if (this.isKioskMode() && this.isOnFirstScene()) {
  267. if (this.getSceneCount() > 1) {
  268. return this._invokeLifeCycleHandlers('scene:previous', { to: this.getLastSceneIndex() });
  269. } else {
  270. return this.selectScene({
  271. index: this.getLastSceneIndex(),
  272. forceSelect: true
  273. });
  274. }
  275. } else if (!this.isOnFirstScene()) {
  276. var refreshData = this.isOnSecondScene() && this.isRefreshData() && !this.isAuthoring();
  277. return this._invokeLifeCycleHandlers('scene:previous', { refreshData: refreshData });
  278. }
  279. },
  280. _previousMarker: function _previousMarker() {
  281. return this.timelineController.jumpToPreviousMarker();
  282. },
  283. _invokeLifeCycleHandlers: function _invokeLifeCycleHandlers(name, payload) {
  284. return this.dashboardApi.getDashboardCoreSvc('.LifeCycleManager').invokeLifeCycleHandlers(name, payload);
  285. },
  286. getStoryDurationLabel: function getStoryDurationLabel() {
  287. // TODO: calculate total story duration and return either story duration or scene duration depending on selection.
  288. return this.timelineController.getTimeLabel(this.timelineController.getDuration(), true);
  289. },
  290. getStoryCurrentTimeLabel: function getStoryCurrentTimeLabel() {
  291. // TODO: calculate total story duration and return either story current time or scene current time depending on selection.
  292. return this.timelineController.getTimeLabel(this.timelineController.getCurrentTime(), true);
  293. },
  294. getSelectedSceneIndex: function getSelectedSceneIndex() {
  295. return this.currentSceneIndex;
  296. },
  297. getFirstSceneIndex: function getFirstSceneIndex() {
  298. return this.showAuthoringOverview() ? this.startOverviewIndex : 0;
  299. },
  300. getLastSceneIndex: function getLastSceneIndex() {
  301. return this.showEndOverview() ? this.endOverviewIndex : this.model.layout.items.length - 1;
  302. },
  303. getSceneCount: function getSceneCount() {
  304. return this.model.layout.items.length;
  305. },
  306. getScenes: function getScenes() {
  307. return this.model.layout.items;
  308. },
  309. getScene: function getScene(index) {
  310. return this.model.layout.items[index];
  311. },
  312. getSceneById: function getSceneById(id) {
  313. return this.model.layout.findModel(id);
  314. },
  315. getSceneId: function getSceneId(index) {
  316. return this.model.layout.items[index].id;
  317. },
  318. getSceneIndex: function getSceneIndex(id) {
  319. var items = this.model.layout.items || [];
  320. for (var i = 0; i < items.length; i++) {
  321. if (items[i].id === id) {
  322. return i;
  323. }
  324. }
  325. return -1;
  326. },
  327. // FIXME: SceneLayout.js (and the two authoring classes SlideShow.js and PanAndZoomLayout.js)
  328. // is the only place we should be doing the conversion of our scene model IDs to index values.
  329. // The start and end overview's IDs are now "start" and "end" (for the most part)
  330. // but because StoryPaneController also does sceneId to model item index value it still works.
  331. getCurrentSceneInfo: function getCurrentSceneInfo() {
  332. var info = {};
  333. // the indices -1 and -2 are used as scene IDs for start overview and end overview
  334. if (this.currentSceneIndex < 0) {
  335. info.id = this.currentSceneIndex.toString();
  336. } else {
  337. var scene = this.getScene(this.currentSceneIndex);
  338. info.id = scene.id;
  339. info.title = scene.title;
  340. }
  341. return info;
  342. },
  343. addScene: function addScene() {
  344. var _this2 = this;
  345. var sceneType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'SceneLayout1';
  346. var title = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  347. this.stop();
  348. this.dashboardApi.deselectAllWidgets();
  349. return ClassFactory.loadModule('storytelling/layouts/' + sceneType).then(function (sceneLayout) {
  350. var sceneSpec = sceneLayout.get();
  351. sceneSpec.layout.title = title;
  352. var options = {
  353. addLayoutArray: [{
  354. model: sceneSpec.layout,
  355. parentId: _this2.model.layout.id,
  356. modelIdsValid: true
  357. }],
  358. widgetSpecMap: sceneSpec.widgets
  359. };
  360. return _this2.model.addLayouts(options);
  361. });
  362. },
  363. /**
  364. * Updates the 'currentSceneIndex' and triggers a global "scene:select" event
  365. * @param {Object} options
  366. * @param {Number} options.index a value that represents what scene will become selected
  367. * @param {String} options.modelId the model Id of the scene to be selected
  368. */
  369. selectScene: function selectScene(options) {
  370. this.dashboardApi.deselectAllWidgets();
  371. if (this.currentSceneIndex !== options.index || options.forceSelect) {
  372. var refreshData = options.refreshData || options.index === this.getFirstSceneIndex() && this.isRefreshData() && !this.isAuthoring();
  373. this.currentSceneIndex = options.index;
  374. // Send event to dashboard (and this controller).
  375. return this._invokeLifeCycleHandlers('scene:select', _.extend({}, options, { refreshData: refreshData }));
  376. }
  377. return Promise.resolve();
  378. },
  379. getNavModel: function getNavModel() {
  380. return this.layoutToListing[this.model.layout.type] || '';
  381. },
  382. changeNavModel: function changeNavModel(navModel) {
  383. this.eventRouter.trigger('navigation:change', { type: navModel });
  384. },
  385. deleteScene: function deleteScene(id) {
  386. this.model.removeLayouts(id);
  387. },
  388. duplicateScene: function duplicateScene(id) {
  389. this.model.duplicateLayout(id);
  390. },
  391. renameScene: function renameScene(id, title) {
  392. var pageModel = this.model.layout.findModel(id);
  393. var options = this.model.getLanguageModelOptions();
  394. options.silent = false;
  395. if (pageModel) {
  396. pageModel.set({ title: title }, options);
  397. }
  398. },
  399. moveViewBefore: function moveViewBefore(pageModel, beforeId) {
  400. if (pageModel.id !== beforeId && pageModel.getNextSiblingId() !== beforeId) {
  401. pageModel.updateModel({
  402. updateArray: [{
  403. id: pageModel.id,
  404. parentId: pageModel.getParent().id,
  405. insertBefore: beforeId
  406. }]
  407. });
  408. }
  409. },
  410. moveSceneLeft: function moveSceneLeft(id) {
  411. var sceneModel = this.model.layout.findModel(id);
  412. var prevId = sceneModel.getPreviousSiblingId();
  413. if (prevId) {
  414. this.moveViewBefore(sceneModel, prevId);
  415. }
  416. },
  417. moveSceneRight: function moveSceneRight(id) {
  418. var sceneModel = this.model.layout.findModel(id);
  419. var nextModel = this.model.layout.findModel(sceneModel.getNextSiblingId());
  420. if (nextModel) {
  421. this.moveViewBefore(sceneModel, nextModel.getNextSiblingId());
  422. }
  423. },
  424. isPlayThrough: function isPlayThrough() {
  425. return this.timelineController.isPlayThrough();
  426. },
  427. isKioskMode: function isKioskMode() {
  428. return this.timelineController.isKioskMode();
  429. },
  430. isNavigateMarkers: function isNavigateMarkers() {
  431. return this.timelineController.isNavigateMarkers();
  432. },
  433. isRefreshData: function isRefreshData() {
  434. return this.timelineController.isRefreshData();
  435. },
  436. isOnFirstScene: function isOnFirstScene() {
  437. return this.currentSceneIndex === this.getFirstSceneIndex();
  438. },
  439. isOnSecondScene: function isOnSecondScene() {
  440. return this.currentSceneIndex === this.getFirstSceneIndex() + 1;
  441. },
  442. isOnLastScene: function isOnLastScene() {
  443. return this.currentSceneIndex === this.getLastSceneIndex();
  444. },
  445. isOverview: function isOverview() {
  446. return this.currentSceneIndex < 0;
  447. },
  448. isStartOverview: function isStartOverview() {
  449. return this.currentSceneIndex === this.startOverviewIndex;
  450. },
  451. isEndOverview: function isEndOverview() {
  452. return this.currentSceneIndex === this.endOverviewIndex;
  453. },
  454. isAuthoring: function isAuthoring() {
  455. return this.authoring;
  456. },
  457. isAtEndOfScene: function isAtEndOfScene() {
  458. return this.timelineController.isAtEndOfScene();
  459. },
  460. isAtStartOfScene: function isAtStartOfScene() {
  461. return this.timelineController.isAtStartOfScene();
  462. },
  463. isFullscreen: function isFullscreen() {
  464. return this.fullscreen;
  465. },
  466. expandScene: function expandScene() {
  467. var options = {
  468. index: this.currentSceneIndex
  469. };
  470. this.trigger('scene:expand', options);
  471. },
  472. collapseScene: function collapseScene() {
  473. this.trigger('scene:collapse', { index: this.currentSceneIndex });
  474. },
  475. onShowOverviewsChanged: function onShowOverviewsChanged() {
  476. if (!this.showEndOverview() && this.currentSceneIndex === this.endOverviewIndex) {
  477. this.selectScene({
  478. index: this.getLastSceneIndex()
  479. });
  480. }
  481. this.trigger('change:showOverviews');
  482. },
  483. hasOverview: function hasOverview() {
  484. return this.model.layout.hasOverview;
  485. },
  486. /** Returns true if the start overview frame should be shown, false otherwise. */
  487. showStartOverview: function showStartOverview() {
  488. return this.model.layout.hasOverview && this.model.layout.showOverviews.showStart;
  489. },
  490. /** Returns true if the start overview frame should be shown, false otherwise.
  491. * This one is used when we're in authoring mode and show the overview for editing
  492. * purposes but it may not be shown in consumption mode.
  493. */
  494. showAuthoringOverview: function showAuthoringOverview() {
  495. return this.model.layout.hasOverview && (this.model.layout.showOverviews.showStart || this.authoring);
  496. },
  497. /** Returns true if the end overview frame should be shown, false otherwise. */
  498. showEndOverview: function showEndOverview() {
  499. return this.model.layout.hasOverview && this.model.layout.showOverviews.showEnd;
  500. },
  501. didEnterFullScreen: function didEnterFullScreen() {
  502. this.fullscreen = true;
  503. },
  504. didExitFullScreen: function didExitFullScreen() {
  505. this.fullscreen = false;
  506. },
  507. /*
  508. * Event handlers.
  509. */
  510. onModeChanged: function onModeChanged(event) {
  511. this.authoring = event.authoring;
  512. if (!this.showAuthoringOverview() && this.currentSceneIndex === this.startOverviewIndex) {
  513. this.selectScene({
  514. index: 0,
  515. play: false
  516. });
  517. }
  518. if (!this.authoring && this.isRefreshData()) {
  519. this.selectScene({
  520. index: this.currentSceneIndex,
  521. play: false,
  522. forceSelect: true,
  523. refreshData: true
  524. });
  525. }
  526. this.trigger('mode:change', { authoring: this.authoring });
  527. },
  528. onAddLayouts: function onAddLayouts(event) {
  529. var addLayoutArray = event.value.parameter.addLayoutArray;
  530. _.each(addLayoutArray, this.onAddLayout.bind(this));
  531. },
  532. onAddLayout: function onAddLayout(addLayout) {
  533. var layoutModel = this.model.layout.findModel(addLayout.model.id);
  534. var sceneCount = this.getSceneCount();
  535. if (this.sceneCount !== sceneCount) {
  536. this.sceneCount = sceneCount;
  537. var insertBefore = addLayout.insertBefore ? addLayout.insertBefore : null;
  538. var sceneIndex = this.getSceneIndex(layoutModel.id);
  539. this.trigger('scene:add', {
  540. scene: layoutModel,
  541. index: sceneIndex,
  542. insertBefore: insertBefore
  543. });
  544. }
  545. },
  546. onRemoveLayout: function onRemoveLayout(event) {
  547. var sceneCount = this.getSceneCount();
  548. if (this.sceneCount !== sceneCount) {
  549. this.sceneCount = sceneCount;
  550. _.each(event.value.parameter, function (sceneId) {
  551. this.trigger('scene:remove', {
  552. id: sceneId
  553. });
  554. }.bind(this));
  555. this.timelineController.onRemoveLayout(event);
  556. // When removing a scene the currentSceneIndex value will point to the removed scene's sibling.
  557. // If there is no n+1 sibling (meaning the last scene was removed) choose the value for the previous sibling
  558. var selectedIndex = this.currentSceneIndex;
  559. if (selectedIndex >= sceneCount) {
  560. selectedIndex = sceneCount - 1;
  561. }
  562. this.selectScene({
  563. index: selectedIndex
  564. });
  565. }
  566. },
  567. onPageSizeChange: function onPageSizeChange(payload) {
  568. this.trigger('change:pageSize', payload.value);
  569. },
  570. onTimeUpdated: function onTimeUpdated(evt) {
  571. this._triggerTimeUpdated(evt.currentTime, evt.sceneId);
  572. },
  573. _hideSharePanel: function _hideSharePanel() {
  574. if (this.shareState) {
  575. if (this.shareState.slideout) {
  576. this.shareState.slideout.hide({ hideOnly: true });
  577. }
  578. this.shareState = null;
  579. }
  580. },
  581. onTimeStateChanged: function onTimeStateChanged(evt) {
  582. this._hideSharePanel();
  583. this._triggerPlayStateUpdated(evt);
  584. },
  585. onNavigateMarkersChange: function onNavigateMarkersChange(evt) {
  586. this.trigger('navigateMarkers:change', evt);
  587. },
  588. onKioskModeChange: function onKioskModeChange(evt) {
  589. this.trigger('kioskMode:change', evt);
  590. },
  591. onNavigationStarted: function onNavigationStarted(evt) {
  592. this.cancelPlaythroughTimer();
  593. this.currentSceneIndex = evt.index;
  594. this.currentSceneId = evt.scene.id;
  595. this._updateSelectedScene();
  596. this._triggerSceneChanged();
  597. this.trigger('scene:select', evt);
  598. // hide share panel whenever a scene is about to play
  599. this._hideSharePanel();
  600. // hide the filter dock if navigating to an overview scene
  601. // also trigger playthrough since overviews have no duration
  602. if (evt.overview || evt.index < 0) {
  603. this.playThrough(evt);
  604. this.eventRouter.trigger('filterDock:disable');
  605. } else if (!this.isFullscreen() && evt.scene) {
  606. this.eventRouter.trigger('filterDock:enable');
  607. }
  608. },
  609. onNavigationComplete: function onNavigationComplete(evt) {
  610. this.trigger('navigation:complete', evt);
  611. },
  612. _onLayoutTypeChanged: function _onLayoutTypeChanged(evt) {
  613. this.eventRouter.trigger('properties:refreshPane', {});
  614. this.trigger('layoutType:changed', evt);
  615. },
  616. /*
  617. * Helpers.
  618. */
  619. _updateSelectedScene: function _updateSelectedScene() {
  620. var scene = this.getScene(this.currentSceneIndex);
  621. this.timelineController.setScene(scene);
  622. },
  623. _triggerTimeUpdated: function _triggerTimeUpdated(time, sceneId) {
  624. var timeLabel = this.timelineController.getTimeLabel(time, true);
  625. this.trigger('time:update', { time: time, label: timeLabel, sceneId: sceneId });
  626. },
  627. _triggerPlayStateUpdated: function _triggerPlayStateUpdated(event) {
  628. this.trigger('playState:change', event);
  629. },
  630. _triggerSceneChanged: function _triggerSceneChanged() {
  631. if (this.currentSceneIndex >= 0) {
  632. var modelId = this.getScene(this.currentSceneIndex).id;
  633. this.eventRouter.trigger('tab:tabChanged', { modelId: modelId });
  634. }
  635. },
  636. getTimelineAPI: function getTimelineAPI() {
  637. return this.timelineController.getAPI();
  638. }
  639. });
  640. return Controller;
  641. });
  642. //# sourceMappingURL=StoryPaneController.js.map