OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 'use strict'; | 5 'use strict'; |
6 | 6 |
7 /** | 7 /** |
8 * Slide mode displays a single image and has a set of controls to navigate | 8 * Slide mode displays a single image and has a set of controls to navigate |
9 * between the images and to edit an image. | 9 * between the images and to edit an image. |
10 * | 10 * |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 * @return {string} Mode name. | 84 * @return {string} Mode name. |
85 */ | 85 */ |
86 SlideMode.prototype.getName = function() { return 'slide'; }; | 86 SlideMode.prototype.getName = function() { return 'slide'; }; |
87 | 87 |
88 /** | 88 /** |
89 * @return {string} Mode title. | 89 * @return {string} Mode title. |
90 */ | 90 */ |
91 SlideMode.prototype.getTitle = function() { return 'GALLERY_SLIDE'; }; | 91 SlideMode.prototype.getTitle = function() { return 'GALLERY_SLIDE'; }; |
92 | 92 |
93 /** | 93 /** |
| 94 * @return {Viewport} Viewport. |
| 95 */ |
| 96 SlideMode.prototype.getViewport = function() { return this.viewport_; }; |
| 97 |
| 98 /** |
94 * Initialize the listeners. | 99 * Initialize the listeners. |
95 * @private | 100 * @private |
96 */ | 101 */ |
97 SlideMode.prototype.initListeners_ = function() { | 102 SlideMode.prototype.initListeners_ = function() { |
98 window.addEventListener('resize', this.onResize_.bind(this)); | 103 window.addEventListener('resize', this.onResize_.bind(this)); |
99 }; | 104 }; |
100 | 105 |
101 /** | 106 /** |
102 * Initialize the UI. | 107 * Initialize the UI. |
103 * @private | 108 * @private |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 { | 230 { |
226 root: this.container_, | 231 root: this.container_, |
227 image: this.imageContainer_, | 232 image: this.imageContainer_, |
228 toolbar: this.editBarMain_, | 233 toolbar: this.editBarMain_, |
229 mode: this.editBarModeWrapper_ | 234 mode: this.editBarModeWrapper_ |
230 }, | 235 }, |
231 SlideMode.EDITOR_MODES, | 236 SlideMode.EDITOR_MODES, |
232 this.displayStringFunction_, | 237 this.displayStringFunction_, |
233 this.onToolsVisibilityChanged_.bind(this)); | 238 this.onToolsVisibilityChanged_.bind(this)); |
234 | 239 |
235 this.editor_.getBuffer().addOverlay( | 240 this.touchHandlers_ = new TouchHandler(this.imageContainer_, this); |
236 new SwipeOverlay(this.advanceManually.bind(this))); | |
237 }; | 241 }; |
238 | 242 |
239 /** | 243 /** |
240 * Load items, display the selected item. | 244 * Load items, display the selected item. |
241 * @param {Rect} zoomFromRect Rectangle for zoom effect. | 245 * @param {Rect} zoomFromRect Rectangle for zoom effect. |
242 * @param {function} displayCallback Called when the image is displayed. | 246 * @param {function} displayCallback Called when the image is displayed. |
243 * @param {function} loadCallback Called when the image is displayed. | 247 * @param {function} loadCallback Called when the image is displayed. |
244 */ | 248 */ |
245 SlideMode.prototype.enter = function( | 249 SlideMode.prototype.enter = function( |
246 zoomFromRect, displayCallback, loadCallback) { | 250 zoomFromRect, displayCallback, loadCallback) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 }.bind(this)).then(function(delay) { | 308 }.bind(this)).then(function(delay) { |
305 // Turn the mode active. | 309 // Turn the mode active. |
306 this.active_ = true; | 310 this.active_ = true; |
307 ImageUtil.setAttribute(this.arrowBox_, 'active', this.getItemCount_() > 1); | 311 ImageUtil.setAttribute(this.arrowBox_, 'active', this.getItemCount_() > 1); |
308 this.ribbon_.enable(); | 312 this.ribbon_.enable(); |
309 | 313 |
310 // Register handlers. | 314 // Register handlers. |
311 this.selectionModel_.addEventListener('change', this.onSelectionBound_); | 315 this.selectionModel_.addEventListener('change', this.onSelectionBound_); |
312 this.dataModel_.addEventListener('splice', this.onSpliceBound_); | 316 this.dataModel_.addEventListener('splice', this.onSpliceBound_); |
313 this.dataModel_.addEventListener('content', this.onContentBound_); | 317 this.dataModel_.addEventListener('content', this.onContentBound_); |
| 318 this.touchHandlers_.enabled = true; |
314 | 319 |
315 // Wait 1000ms after the animation is done, then prefetch the next image. | 320 // Wait 1000ms after the animation is done, then prefetch the next image. |
316 this.requestPrefetch(1, delay + 1000); | 321 this.requestPrefetch(1, delay + 1000); |
317 | 322 |
318 // Call load callback. | 323 // Call load callback. |
319 if (loadCallback) | 324 if (loadCallback) |
320 loadCallback(); | 325 loadCallback(); |
321 }.bind(this)).catch(function(error) { | 326 }.bind(this)).catch(function(error) { |
322 console.error(error.stack, error); | 327 console.error(error.stack, error); |
323 }); | 328 }); |
(...skipping 26 matching lines...) Expand all Loading... |
350 if (this.getItemCount_() === 0) { | 355 if (this.getItemCount_() === 0) { |
351 this.showErrorBanner_(false); | 356 this.showErrorBanner_(false); |
352 commitDone(); | 357 commitDone(); |
353 } else { | 358 } else { |
354 this.commitItem_(commitDone); | 359 this.commitItem_(commitDone); |
355 } | 360 } |
356 | 361 |
357 // Disable the slide-mode only buttons when leaving. | 362 // Disable the slide-mode only buttons when leaving. |
358 this.editButton_.setAttribute('disabled', ''); | 363 this.editButton_.setAttribute('disabled', ''); |
359 this.printButton_.setAttribute('disabled', ''); | 364 this.printButton_.setAttribute('disabled', ''); |
| 365 |
| 366 // Disable touch operation. |
| 367 this.touchHandlers_.enabled = false; |
360 }; | 368 }; |
361 | 369 |
362 | 370 |
363 /** | 371 /** |
364 * Execute an action when the editor is not busy. | 372 * Execute an action when the editor is not busy. |
365 * | 373 * |
366 * @param {function} action Function to execute. | 374 * @param {function} action Function to execute. |
367 */ | 375 */ |
368 SlideMode.prototype.executeWhenReady = function(action) { | 376 SlideMode.prototype.executeWhenReady = function(action) { |
369 this.editor_.executeWhenReady(action); | 377 this.editor_.executeWhenReady(action); |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 break; | 861 break; |
854 | 862 |
855 case 'U+0045': // 'e' toggles the editor. | 863 case 'U+0045': // 'e' toggles the editor. |
856 if (!this.editButton_.hasAttribute('disabled')) | 864 if (!this.editButton_.hasAttribute('disabled')) |
857 this.toggleEditor(event); | 865 this.toggleEditor(event); |
858 break; | 866 break; |
859 | 867 |
860 case 'U+001B': // Escape | 868 case 'U+001B': // Escape |
861 if (this.isEditing()) { | 869 if (this.isEditing()) { |
862 this.toggleEditor(event); | 870 this.toggleEditor(event); |
863 } else if (this.viewport_.getZoomIndex() !== 0) { | 871 } else if (this.viewport_.isZoomed()) { |
864 this.viewport_.resetView(); | 872 this.viewport_.resetView(); |
| 873 this.touchHandlers_.stopOperation(); |
865 this.imageView_.applyViewportChange(); | 874 this.imageView_.applyViewportChange(); |
866 } else { | 875 } else { |
867 return false; // Not handled. | 876 return false; // Not handled. |
868 } | 877 } |
869 break; | 878 break; |
870 | 879 |
871 case 'Home': | 880 case 'Home': |
872 this.selectFirst(); | 881 this.selectFirst(); |
873 break; | 882 break; |
874 case 'End': | 883 case 'End': |
875 this.selectLast(); | 884 this.selectLast(); |
876 break; | 885 break; |
877 case 'Up': | 886 case 'Up': |
878 case 'Down': | 887 case 'Down': |
879 case 'Left': | 888 case 'Left': |
880 case 'Right': | 889 case 'Right': |
881 if (!this.isEditing() && this.viewport_.getZoomIndex() !== 0) { | 890 if (!this.isEditing() && this.viewport_.isZoomed()) { |
882 var delta = SlideMode.KEY_OFFSET_MAP[keyID]; | 891 var delta = SlideMode.KEY_OFFSET_MAP[keyID]; |
883 this.viewport_.setOffset( | 892 this.viewport_.setOffset( |
884 ~~(this.viewport_.getOffsetX() + | 893 ~~(this.viewport_.getOffsetX() + |
885 delta[0] * this.viewport_.getZoom()), | 894 delta[0] * this.viewport_.getZoom()), |
886 ~~(this.viewport_.getOffsetY() + | 895 ~~(this.viewport_.getOffsetY() + |
887 delta[1] * this.viewport_.getZoom()), | 896 delta[1] * this.viewport_.getZoom())); |
888 true); | 897 this.touchHandlers_.stopOperation(); |
889 this.imageView_.applyViewportChange(); | 898 this.imageView_.applyViewportChange(); |
890 } else { | 899 } else { |
891 this.advanceWithKeyboard(keyID); | 900 this.advanceWithKeyboard(keyID); |
892 } | 901 } |
893 break; | 902 break; |
894 case 'MediaNextTrack': | 903 case 'MediaNextTrack': |
895 case 'MediaPreviousTrack': | 904 case 'MediaPreviousTrack': |
896 this.advanceWithKeyboard(keyID); | 905 this.advanceWithKeyboard(keyID); |
897 break; | 906 break; |
898 | 907 |
899 case 'Ctrl-U+00BB': // Ctrl+'=' zoom in. | 908 case 'Ctrl-U+00BB': // Ctrl+'=' zoom in. |
900 if (!this.isEditing()) { | 909 if (!this.isEditing()) { |
901 this.viewport_.setZoomIndex(this.viewport_.getZoomIndex() + 1); | 910 this.viewport_.zoomIn(); |
| 911 this.touchHandlers_.stopOperation(); |
902 this.imageView_.applyViewportChange(); | 912 this.imageView_.applyViewportChange(); |
903 } | 913 } |
904 break; | 914 break; |
905 | 915 |
906 case 'Ctrl-U+00BD': // Ctrl+'-' zoom out. | 916 case 'Ctrl-U+00BD': // Ctrl+'-' zoom out. |
907 if (!this.isEditing()) { | 917 if (!this.isEditing()) { |
908 this.viewport_.setZoomIndex(this.viewport_.getZoomIndex() - 1); | 918 this.viewport_.zoomOut(); |
| 919 this.touchHandlers_.stopOperation(); |
909 this.imageView_.applyViewportChange(); | 920 this.imageView_.applyViewportChange(); |
910 } | 921 } |
911 break; | 922 break; |
912 | 923 |
913 case 'Ctrl-U+0030': // Ctrl+'0' zoom reset. | 924 case 'Ctrl-U+0030': // Ctrl+'0' zoom reset. |
914 if (!this.isEditing()) { | 925 if (!this.isEditing()) { |
915 this.viewport_.resetView(); | 926 this.viewport_.setZoom(1.0); |
| 927 this.touchHandlers_.stopOperation(); |
916 this.imageView_.applyViewportChange(); | 928 this.imageView_.applyViewportChange(); |
917 } | 929 } |
918 break; | 930 break; |
919 } | 931 } |
920 | 932 |
921 return true; | 933 return true; |
922 }; | 934 }; |
923 | 935 |
924 /** | 936 /** |
925 * Resize handler. | 937 * Resize handler. |
926 * @private | 938 * @private |
927 */ | 939 */ |
928 SlideMode.prototype.onResize_ = function() { | 940 SlideMode.prototype.onResize_ = function() { |
929 this.viewport_.setScreenSize( | 941 this.viewport_.setScreenSize( |
930 this.container_.clientWidth, this.container_.clientHeight); | 942 this.container_.clientWidth, this.container_.clientHeight); |
| 943 this.touchHandlers_.stopOperation(); |
931 this.editor_.getBuffer().draw(); | 944 this.editor_.getBuffer().draw(); |
932 }; | 945 }; |
933 | 946 |
934 /** | 947 /** |
935 * Update thumbnails. | 948 * Update thumbnails. |
936 */ | 949 */ |
937 SlideMode.prototype.updateThumbnails = function() { | 950 SlideMode.prototype.updateThumbnails = function() { |
938 this.ribbon_.reset(); | 951 this.ribbon_.reset(); |
939 if (this.active_) | 952 if (this.active_) |
940 this.ribbon_.redraw(); | 953 this.ribbon_.redraw(); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 | 1083 |
1071 /** | 1084 /** |
1072 * @return {boolean} True if the slideshow is on. | 1085 * @return {boolean} True if the slideshow is on. |
1073 * @private | 1086 * @private |
1074 */ | 1087 */ |
1075 SlideMode.prototype.isSlideshowOn_ = function() { | 1088 SlideMode.prototype.isSlideshowOn_ = function() { |
1076 return this.container_.hasAttribute('slideshow'); | 1089 return this.container_.hasAttribute('slideshow'); |
1077 }; | 1090 }; |
1078 | 1091 |
1079 /** | 1092 /** |
1080 * Start the slideshow. | 1093 * Starts the slideshow. |
1081 * @param {number=} opt_interval First interval in ms. | 1094 * @param {number=} opt_interval First interval in ms. |
1082 * @param {Event=} opt_event Event. | 1095 * @param {Event=} opt_event Event. |
1083 */ | 1096 */ |
1084 SlideMode.prototype.startSlideshow = function(opt_interval, opt_event) { | 1097 SlideMode.prototype.startSlideshow = function(opt_interval, opt_event) { |
1085 // Reset zoom. | 1098 // Reset zoom. |
1086 this.viewport_.resetView(); | 1099 this.viewport_.resetView(); |
1087 this.imageView_.applyViewportChange(); | 1100 this.imageView_.applyViewportChange(); |
1088 | 1101 |
| 1102 // Disable touch operation. |
| 1103 this.touchHandlers_.enabled = false; |
| 1104 |
1089 // Set the attribute early to prevent the toolbar from flashing when | 1105 // Set the attribute early to prevent the toolbar from flashing when |
1090 // the slideshow is being started from the mosaic view. | 1106 // the slideshow is being started from the mosaic view. |
1091 this.container_.setAttribute('slideshow', 'playing'); | 1107 this.container_.setAttribute('slideshow', 'playing'); |
1092 | 1108 |
1093 if (this.active_) { | 1109 if (this.active_) { |
1094 this.stopEditing_(); | 1110 this.stopEditing_(); |
1095 } else { | 1111 } else { |
1096 // We are in the Mosaic mode. Toggle the mode but remember to return. | 1112 // We are in the Mosaic mode. Toggle the mode but remember to return. |
1097 this.leaveAfterSlideshow_ = true; | 1113 this.leaveAfterSlideshow_ = true; |
1098 this.toggleMode_(this.startSlideshow.bind( | 1114 this.toggleMode_(this.startSlideshow.bind( |
(...skipping 10 matching lines...) Expand all Loading... |
1109 setTimeout(this.toggleFullScreen_.bind(this), | 1125 setTimeout(this.toggleFullScreen_.bind(this), |
1110 ImageView.ZOOM_ANIMATION_DURATION); | 1126 ImageView.ZOOM_ANIMATION_DURATION); |
1111 opt_interval = (opt_interval || SlideMode.SLIDESHOW_INTERVAL) + | 1127 opt_interval = (opt_interval || SlideMode.SLIDESHOW_INTERVAL) + |
1112 SlideMode.FULLSCREEN_TOGGLE_DELAY; | 1128 SlideMode.FULLSCREEN_TOGGLE_DELAY; |
1113 } | 1129 } |
1114 | 1130 |
1115 this.resumeSlideshow_(opt_interval); | 1131 this.resumeSlideshow_(opt_interval); |
1116 }; | 1132 }; |
1117 | 1133 |
1118 /** | 1134 /** |
1119 * Stop the slideshow. | 1135 * Stops the slideshow. |
1120 * @param {Event=} opt_event Event. | 1136 * @param {Event=} opt_event Event. |
1121 * @private | 1137 * @private |
1122 */ | 1138 */ |
1123 SlideMode.prototype.stopSlideshow_ = function(opt_event) { | 1139 SlideMode.prototype.stopSlideshow_ = function(opt_event) { |
1124 if (!this.isSlideshowOn_()) | 1140 if (!this.isSlideshowOn_()) |
1125 return; | 1141 return; |
1126 | 1142 |
1127 if (opt_event) // Caused by user action, notify the Gallery. | 1143 if (opt_event) // Caused by user action, notify the Gallery. |
1128 cr.dispatchSimpleEvent(this, 'useraction'); | 1144 cr.dispatchSimpleEvent(this, 'useraction'); |
1129 | 1145 |
1130 this.pauseSlideshow_(); | 1146 this.pauseSlideshow_(); |
1131 this.container_.removeAttribute('slideshow'); | 1147 this.container_.removeAttribute('slideshow'); |
1132 | 1148 |
1133 // Do not restore fullscreen if we exited fullscreen while in slideshow. | 1149 // Do not restore fullscreen if we exited fullscreen while in slideshow. |
1134 var fullscreen = util.isFullScreen(this.context_.appWindow); | 1150 var fullscreen = util.isFullScreen(this.context_.appWindow); |
1135 var toggleModeDelay = 0; | 1151 var toggleModeDelay = 0; |
1136 if (!this.fullscreenBeforeSlideshow_ && fullscreen) { | 1152 if (!this.fullscreenBeforeSlideshow_ && fullscreen) { |
1137 this.toggleFullScreen_(); | 1153 this.toggleFullScreen_(); |
1138 toggleModeDelay = SlideMode.FULLSCREEN_TOGGLE_DELAY; | 1154 toggleModeDelay = SlideMode.FULLSCREEN_TOGGLE_DELAY; |
1139 } | 1155 } |
1140 if (this.leaveAfterSlideshow_) { | 1156 if (this.leaveAfterSlideshow_) { |
1141 this.leaveAfterSlideshow_ = false; | 1157 this.leaveAfterSlideshow_ = false; |
1142 setTimeout(this.toggleMode_.bind(this), toggleModeDelay); | 1158 setTimeout(this.toggleMode_.bind(this), toggleModeDelay); |
1143 } | 1159 } |
| 1160 |
| 1161 // Re-enable touch operation. |
| 1162 this.touchHandlers_.enabled = true; |
1144 }; | 1163 }; |
1145 | 1164 |
1146 /** | 1165 /** |
1147 * @return {boolean} True if the slideshow is playing (not paused). | 1166 * @return {boolean} True if the slideshow is playing (not paused). |
1148 * @private | 1167 * @private |
1149 */ | 1168 */ |
1150 SlideMode.prototype.isSlideshowPlaying_ = function() { | 1169 SlideMode.prototype.isSlideshowPlaying_ = function() { |
1151 return this.container_.getAttribute('slideshow') === 'playing'; | 1170 return this.container_.getAttribute('slideshow') === 'playing'; |
1152 }; | 1171 }; |
1153 | 1172 |
1154 /** | 1173 /** |
1155 * Pause/resume the slideshow. | 1174 * Pauses/resumes the slideshow. |
1156 * @private | 1175 * @private |
1157 */ | 1176 */ |
1158 SlideMode.prototype.toggleSlideshowPause_ = function() { | 1177 SlideMode.prototype.toggleSlideshowPause_ = function() { |
1159 cr.dispatchSimpleEvent(this, 'useraction'); // Show the tools. | 1178 cr.dispatchSimpleEvent(this, 'useraction'); // Show the tools. |
1160 if (this.isSlideshowPlaying_()) { | 1179 if (this.isSlideshowPlaying_()) { |
1161 this.pauseSlideshow_(); | 1180 this.pauseSlideshow_(); |
1162 } else { | 1181 } else { |
1163 this.resumeSlideshow_(SlideMode.SLIDESHOW_INTERVAL_FIRST); | 1182 this.resumeSlideshow_(SlideMode.SLIDESHOW_INTERVAL_FIRST); |
1164 } | 1183 } |
1165 }; | 1184 }; |
1166 | 1185 |
1167 /** | 1186 /** |
1168 * @param {number=} opt_interval Slideshow interval in ms. | 1187 * @param {number=} opt_interval Slideshow interval in ms. |
1169 * @private | 1188 * @private |
1170 */ | 1189 */ |
1171 SlideMode.prototype.scheduleNextSlide_ = function(opt_interval) { | 1190 SlideMode.prototype.scheduleNextSlide_ = function(opt_interval) { |
1172 console.assert(this.isSlideshowPlaying_(), 'Inconsistent slideshow state'); | 1191 console.assert(this.isSlideshowPlaying_(), 'Inconsistent slideshow state'); |
1173 | 1192 |
1174 if (this.slideShowTimeout_) | 1193 if (this.slideShowTimeout_) |
1175 clearTimeout(this.slideShowTimeout_); | 1194 clearTimeout(this.slideShowTimeout_); |
1176 | 1195 |
1177 this.slideShowTimeout_ = setTimeout(function() { | 1196 this.slideShowTimeout_ = setTimeout(function() { |
1178 this.slideShowTimeout_ = null; | 1197 this.slideShowTimeout_ = null; |
1179 this.selectNext(1); | 1198 this.selectNext(1); |
1180 }.bind(this), | 1199 }.bind(this), |
1181 opt_interval || SlideMode.SLIDESHOW_INTERVAL); | 1200 opt_interval || SlideMode.SLIDESHOW_INTERVAL); |
1182 }; | 1201 }; |
1183 | 1202 |
1184 /** | 1203 /** |
1185 * Resume the slideshow. | 1204 * Resumes the slideshow. |
1186 * @param {number=} opt_interval Slideshow interval in ms. | 1205 * @param {number=} opt_interval Slideshow interval in ms. |
1187 * @private | 1206 * @private |
1188 */ | 1207 */ |
1189 SlideMode.prototype.resumeSlideshow_ = function(opt_interval) { | 1208 SlideMode.prototype.resumeSlideshow_ = function(opt_interval) { |
1190 this.container_.setAttribute('slideshow', 'playing'); | 1209 this.container_.setAttribute('slideshow', 'playing'); |
1191 this.scheduleNextSlide_(opt_interval); | 1210 this.scheduleNextSlide_(opt_interval); |
1192 }; | 1211 }; |
1193 | 1212 |
1194 /** | 1213 /** |
1195 * Pause the slideshow. | 1214 * Pauses the slideshow. |
1196 * @private | 1215 * @private |
1197 */ | 1216 */ |
1198 SlideMode.prototype.pauseSlideshow_ = function() { | 1217 SlideMode.prototype.pauseSlideshow_ = function() { |
1199 this.container_.setAttribute('slideshow', 'paused'); | 1218 this.container_.setAttribute('slideshow', 'paused'); |
1200 if (this.slideShowTimeout_) { | 1219 if (this.slideShowTimeout_) { |
1201 clearTimeout(this.slideShowTimeout_); | 1220 clearTimeout(this.slideShowTimeout_); |
1202 this.slideShowTimeout_ = null; | 1221 this.slideShowTimeout_ = null; |
1203 } | 1222 } |
1204 }; | 1223 }; |
1205 | 1224 |
1206 /** | 1225 /** |
1207 * @return {boolean} True if the editor is active. | 1226 * @return {boolean} True if the editor is active. |
1208 */ | 1227 */ |
1209 SlideMode.prototype.isEditing = function() { | 1228 SlideMode.prototype.isEditing = function() { |
1210 return this.container_.hasAttribute('editing'); | 1229 return this.container_.hasAttribute('editing'); |
1211 }; | 1230 }; |
1212 | 1231 |
1213 /** | 1232 /** |
1214 * Stop editing. | 1233 * Stops editing. |
1215 * @private | 1234 * @private |
1216 */ | 1235 */ |
1217 SlideMode.prototype.stopEditing_ = function() { | 1236 SlideMode.prototype.stopEditing_ = function() { |
1218 if (this.isEditing()) | 1237 if (this.isEditing()) |
1219 this.toggleEditor(); | 1238 this.toggleEditor(); |
1220 }; | 1239 }; |
1221 | 1240 |
1222 /** | 1241 /** |
1223 * Activate/deactivate editor. | 1242 * Activate/deactivate editor. |
1224 * @param {Event=} opt_event Event. | 1243 * @param {Event=} opt_event Event. |
(...skipping 12 matching lines...) Expand all Loading... |
1237 ImageUtil.setAttribute(this.container_, 'editing', !this.isEditing()); | 1256 ImageUtil.setAttribute(this.container_, 'editing', !this.isEditing()); |
1238 | 1257 |
1239 if (this.isEditing()) { // isEditing has just been flipped to a new value. | 1258 if (this.isEditing()) { // isEditing has just been flipped to a new value. |
1240 // Reset zoom. | 1259 // Reset zoom. |
1241 this.viewport_.resetView(); | 1260 this.viewport_.resetView(); |
1242 this.imageView_.applyViewportChange(); | 1261 this.imageView_.applyViewportChange(); |
1243 if (this.context_.readonlyDirName) { | 1262 if (this.context_.readonlyDirName) { |
1244 this.editor_.getPrompt().showAt( | 1263 this.editor_.getPrompt().showAt( |
1245 'top', 'GALLERY_READONLY_WARNING', 0, this.context_.readonlyDirName); | 1264 'top', 'GALLERY_READONLY_WARNING', 0, this.context_.readonlyDirName); |
1246 } | 1265 } |
| 1266 this.touchHandlers_.enabled = false; |
1247 } else { | 1267 } else { |
1248 this.editor_.getPrompt().hide(); | 1268 this.editor_.getPrompt().hide(); |
1249 this.editor_.leaveModeGently(); | 1269 this.editor_.leaveModeGently(); |
| 1270 this.touchHandlers_.enabled = true; |
1250 } | 1271 } |
1251 }; | 1272 }; |
1252 | 1273 |
1253 /** | 1274 /** |
1254 * Prints the current item. | 1275 * Prints the current item. |
1255 * @private | 1276 * @private |
1256 */ | 1277 */ |
1257 SlideMode.prototype.print_ = function() { | 1278 SlideMode.prototype.print_ = function() { |
1258 cr.dispatchSimpleEvent(this, 'useraction'); | 1279 cr.dispatchSimpleEvent(this, 'useraction'); |
1259 window.print(); | 1280 window.print(); |
1260 }; | 1281 }; |
1261 | 1282 |
1262 /** | 1283 /** |
1263 * Display the error banner. | 1284 * Displays the error banner. |
1264 * @param {string} message Message. | 1285 * @param {string} message Message. |
1265 * @private | 1286 * @private |
1266 */ | 1287 */ |
1267 SlideMode.prototype.showErrorBanner_ = function(message) { | 1288 SlideMode.prototype.showErrorBanner_ = function(message) { |
1268 if (message) { | 1289 if (message) { |
1269 this.errorBanner_.textContent = this.displayStringFunction_(message); | 1290 this.errorBanner_.textContent = this.displayStringFunction_(message); |
1270 } | 1291 } |
1271 ImageUtil.setAttribute(this.container_, 'error', !!message); | 1292 ImageUtil.setAttribute(this.container_, 'error', !!message); |
1272 }; | 1293 }; |
1273 | 1294 |
1274 /** | 1295 /** |
1275 * Show/hide the busy spinner. | 1296 * Shows/hides the busy spinner. |
1276 * | 1297 * |
1277 * @param {boolean} on True if show, false if hide. | 1298 * @param {boolean} on True if show, false if hide. |
1278 * @private | 1299 * @private |
1279 */ | 1300 */ |
1280 SlideMode.prototype.showSpinner_ = function(on) { | 1301 SlideMode.prototype.showSpinner_ = function(on) { |
1281 if (this.spinnerTimer_) { | 1302 if (this.spinnerTimer_) { |
1282 clearTimeout(this.spinnerTimer_); | 1303 clearTimeout(this.spinnerTimer_); |
1283 this.spinnerTimer_ = null; | 1304 this.spinnerTimer_ = null; |
1284 } | 1305 } |
1285 | 1306 |
1286 if (on) { | 1307 if (on) { |
1287 this.spinnerTimer_ = setTimeout(function() { | 1308 this.spinnerTimer_ = setTimeout(function() { |
1288 this.spinnerTimer_ = null; | 1309 this.spinnerTimer_ = null; |
1289 ImageUtil.setAttribute(this.container_, 'spinner', true); | 1310 ImageUtil.setAttribute(this.container_, 'spinner', true); |
1290 }.bind(this), 1000); | 1311 }.bind(this), 1000); |
1291 } else { | 1312 } else { |
1292 ImageUtil.setAttribute(this.container_, 'spinner', false); | 1313 ImageUtil.setAttribute(this.container_, 'spinner', false); |
1293 } | 1314 } |
1294 }; | 1315 }; |
1295 | 1316 |
1296 /** | 1317 /** |
1297 * Overlay that handles swipe gestures. Changes to the next or previous file. | 1318 * Apply the change of viewport. |
1298 * @param {function(number)} callback A callback accepting the swipe direction | 1319 */ |
1299 * (1 means left, -1 right). | 1320 SlideMode.prototype.applyViewportChange = function() { |
| 1321 this.imageView_.applyViewportChange(); |
| 1322 }; |
| 1323 |
| 1324 /** |
| 1325 * Touch handlers of the slide mode. |
| 1326 * @param {DOMElement} targetElement Event source. |
| 1327 * @param {SlideMode} slideMode Slide mode to be operated by the handler. |
1300 * @constructor | 1328 * @constructor |
1301 * @implements {ImageBuffer.Overlay} | 1329 */ |
1302 */ | 1330 function TouchHandler(targetElement, slideMode) { |
1303 function SwipeOverlay(callback) { | 1331 /** |
1304 this.callback_ = callback; | 1332 * Event source. |
| 1333 * @type {DOMElement} |
| 1334 */ |
| 1335 this.targetElement_ = targetElement; |
| 1336 |
| 1337 /** |
| 1338 * Target of touch operations. |
| 1339 * @type {SlideMode} |
| 1340 * @private |
| 1341 */ |
| 1342 this.slideMode_ = slideMode; |
| 1343 |
| 1344 /** |
| 1345 * Flag to enable/disable touch operation. |
| 1346 * @type {boolean} |
| 1347 */ |
| 1348 this.enabled_ = true; |
| 1349 |
| 1350 /** |
| 1351 * Whether it is in a touch operation that is started from targetElement or |
| 1352 * not. |
| 1353 * @type {boolean} |
| 1354 * @private |
| 1355 */ |
| 1356 this.touchStarted_ = false; |
| 1357 |
| 1358 /** |
| 1359 * The swipe action that should happen only once in an operation is already |
| 1360 * done or not. |
| 1361 * @type {boolean} |
| 1362 * @private |
| 1363 */ |
| 1364 this.done_ = false; |
| 1365 |
| 1366 /** |
| 1367 * Event on beginning of the current gesture. |
| 1368 * The variable is updated when the number of touch finger changed. |
| 1369 * @type {TouchEvent} |
| 1370 * @private |
| 1371 */ |
| 1372 this.gestureStartEvent_ = null; |
| 1373 |
| 1374 /** |
| 1375 * Last touch event. |
| 1376 * @type {TouchEvent} |
| 1377 * @private |
| 1378 */ |
| 1379 this.lastEvent_ = null; |
| 1380 |
| 1381 /** |
| 1382 * Zoom value just after last touch event. |
| 1383 * @type {number} |
| 1384 * @private |
| 1385 */ |
| 1386 this.lastZoom_ = 1.0; |
| 1387 |
| 1388 targetElement.addEventListener('touchstart', this.onTouchStart_.bind(this)); |
| 1389 var onTouchEventBound = this.onTouchEvent_.bind(this); |
| 1390 targetElement.ownerDocument.addEventListener('touchmove', onTouchEventBound); |
| 1391 targetElement.ownerDocument.addEventListener('touchend', onTouchEventBound); |
1305 } | 1392 } |
1306 | 1393 |
1307 /** | 1394 /** |
1308 * Inherit ImageBuffer.Overlay. | |
1309 */ | |
1310 SwipeOverlay.prototype.__proto__ = ImageBuffer.Overlay.prototype; | |
1311 | |
1312 /** | |
1313 * @param {number} x X pointer position. | |
1314 * @param {number} y Y pointer position. | |
1315 * @param {boolean} touch True if dragging caused by touch. | |
1316 * @return {function} The closure to call on drag. | |
1317 */ | |
1318 SwipeOverlay.prototype.getDragHandler = function(x, y, touch) { | |
1319 if (!touch) | |
1320 return null; | |
1321 var origin = x; | |
1322 var done = false; | |
1323 return function(x, y) { | |
1324 if (!done && origin - x > SwipeOverlay.SWIPE_THRESHOLD) { | |
1325 this.callback_(1); | |
1326 done = true; | |
1327 } else if (!done && x - origin > SwipeOverlay.SWIPE_THRESHOLD) { | |
1328 this.callback_(-1); | |
1329 done = true; | |
1330 } | |
1331 }.bind(this); | |
1332 }; | |
1333 | |
1334 /** | |
1335 * If the user touched the image and moved the finger more than SWIPE_THRESHOLD | 1395 * If the user touched the image and moved the finger more than SWIPE_THRESHOLD |
1336 * horizontally it's considered as a swipe gesture (change the current image). | 1396 * horizontally it's considered as a swipe gesture (change the current image). |
1337 */ | 1397 * @type {number} |
1338 SwipeOverlay.SWIPE_THRESHOLD = 100; | 1398 * @const |
| 1399 */ |
| 1400 TouchHandler.SWIPE_THRESHOLD = 100; |
| 1401 |
| 1402 /** |
| 1403 * Obtains distance between fingers. |
| 1404 * @param {TouchEvent} event Touch event. It should include more than two |
| 1405 * touches. |
| 1406 * @return {boolean} Distance between touch[0] and touch[1]. |
| 1407 */ |
| 1408 TouchHandler.getDistance = function(event) { |
| 1409 var touch1 = event.touches[0]; |
| 1410 var touch2 = event.touches[1]; |
| 1411 var dx = touch1.clientX - touch2.clientX; |
| 1412 var dy = touch1.clientY - touch2.clientY; |
| 1413 return Math.sqrt(dx * dx + dy * dy); |
| 1414 }; |
| 1415 |
| 1416 TouchHandler.prototype = { |
| 1417 /** |
| 1418 * @param {boolean} flag New value. |
| 1419 */ |
| 1420 set enabled(flag) { |
| 1421 this.enabled_ = flag; |
| 1422 if (!this.enabled_) |
| 1423 this.stopOperation(); |
| 1424 } |
| 1425 }; |
| 1426 |
| 1427 /** |
| 1428 * Stops the current touch operation. |
| 1429 */ |
| 1430 TouchHandler.prototype.stopOperation = function() { |
| 1431 this.touchStarted_ = false; |
| 1432 this.done_ = false; |
| 1433 this.gestureStartEvent_ = null; |
| 1434 this.lastEvent_ = null; |
| 1435 this.lastZoom_ = 1.0; |
| 1436 }; |
| 1437 |
| 1438 TouchHandler.prototype.onTouchStart_ = function(event) { |
| 1439 if (this.enabled_ && event.touches.length === 1) |
| 1440 this.touchStarted_ = true; |
| 1441 }; |
| 1442 |
| 1443 /** |
| 1444 * @param {event} event Touch event. |
| 1445 */ |
| 1446 TouchHandler.prototype.onTouchEvent_ = function(event) { |
| 1447 // Check if the current touch operation started from the target element or |
| 1448 // not. |
| 1449 if (!this.touchStarted_) |
| 1450 return; |
| 1451 |
| 1452 // Check if the current touch operation ends with the event. |
| 1453 if (event.touches.length === 0) { |
| 1454 this.stopOperation(); |
| 1455 return; |
| 1456 } |
| 1457 |
| 1458 // Check if a new gesture started or not. |
| 1459 if (!this.lastEvent_ || |
| 1460 this.lastEvent_.touches.length !== event.touches.length) { |
| 1461 if (event.touches.length === 2 || |
| 1462 event.touches.length === 1) { |
| 1463 this.gestureStartEvent_ = event; |
| 1464 this.lastEvent_ = event; |
| 1465 this.lastZoom_ = this.slideMode_.getViewport().getZoom(); |
| 1466 } else { |
| 1467 this.gestureStartEvent_ = null; |
| 1468 this.lastEvent_ = null; |
| 1469 this.lastZoom_ = 1.0; |
| 1470 } |
| 1471 return; |
| 1472 } |
| 1473 |
| 1474 // Handle the gesture movement. |
| 1475 var viewport = this.slideMode_.getViewport(); |
| 1476 switch (event.touches.length) { |
| 1477 case 1: |
| 1478 if (viewport.isZoomed()) { |
| 1479 // Scrolling an image by swipe. |
| 1480 var dx = event.touches[0].screenX - this.lastEvent_.touches[0].screenX; |
| 1481 var dy = event.touches[0].screenY - this.lastEvent_.touches[0].screenY; |
| 1482 viewport.setOffset( |
| 1483 viewport.getOffsetX() + dx, viewport.getOffsetY() + dy); |
| 1484 this.slideMode_.applyViewportChange(); |
| 1485 } else { |
| 1486 // Traversing images by swipe. |
| 1487 if (this.done_) |
| 1488 break; |
| 1489 var dx = |
| 1490 event.touches[0].clientX - |
| 1491 this.gestureStartEvent_.touches[0].clientX; |
| 1492 if (dx > TouchHandler.SWIPE_THRESHOLD) { |
| 1493 this.slideMode_.advanceManually(-1); |
| 1494 this.done_ = true; |
| 1495 } else if (dx < -TouchHandler.SWIPE_THRESHOLD) { |
| 1496 this.slideMode_.advanceManually(1); |
| 1497 this.done_ = true; |
| 1498 } |
| 1499 } |
| 1500 break; |
| 1501 |
| 1502 case 2: |
| 1503 // Pinch zoom. |
| 1504 var distance1 = TouchHandler.getDistance(this.lastEvent_); |
| 1505 var distance2 = TouchHandler.getDistance(event); |
| 1506 if (distance1 === 0) |
| 1507 break; |
| 1508 var zoom = distance2 / distance1 * this.lastZoom_; |
| 1509 viewport.setZoom(zoom); |
| 1510 this.slideMode_.applyViewportChange(); |
| 1511 break; |
| 1512 } |
| 1513 |
| 1514 // Update the last event. |
| 1515 this.lastEvent_ = event; |
| 1516 this.lastZoom_ = viewport.getZoom(); |
| 1517 }; |
OLD | NEW |