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 TouchHandlers(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_.enable = 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_.enable = 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_.isZooming()) { |
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_.isZooming()) { |
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_.enable = 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_.enable = 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_.enable = 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_.enable = 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() { |
1300 * @constructor | 1321 this.imageView_.applyViewportChange(); |
1301 * @implements {ImageBuffer.Overlay} | 1322 }; |
1302 */ | 1323 |
1303 function SwipeOverlay(callback) { | 1324 /** |
mtomasz
2014/07/23 08:15:08
@param, @constructor missing
hirono
2014/07/23 09:27:23
Done.
| |
1304 this.callback_ = callback; | 1325 * Touch handlers of the slide mode. |
1326 */ | |
1327 function TouchHandlers(targetElement, slideMode) { | |
mtomasz
2014/07/23 08:15:08
I'm wondering if the plural naming is fine. How ab
hirono
2014/07/23 09:27:23
Done.
| |
1328 /** | |
1329 * Event source. | |
1330 * @type {DOMElement} | |
1331 */ | |
1332 this.targetElement_ = targetElement; | |
1333 | |
1334 /** | |
1335 * Target of touch operations. | |
1336 * @type {SlideMode} | |
1337 * @private | |
1338 */ | |
1339 this.slideMode_ = slideMode; | |
1340 | |
1341 /** | |
1342 * Flag to enable/disable touch operation. | |
1343 */ | |
1344 this.enable_ = true; | |
mtomasz
2014/07/23 08:15:08
nit: enabled?
hirono
2014/07/23 09:27:23
Done.
| |
1345 | |
1346 /** | |
1347 * Whether it is in a touch operation that is started from targetElement or | |
1348 * not. | |
1349 * @type {boolean} | |
1350 * @private | |
1351 */ | |
1352 this.inTouch_ = false; | |
mtomasz
2014/07/23 08:15:08
nit: How about simply touchStarted?
hirono
2014/07/23 09:27:23
Done.
| |
1353 | |
1354 /** | |
1355 * The swipe action that should happen only once in an operation is already | |
1356 * done or not. | |
1357 * @type {boolean} | |
1358 * @private | |
1359 */ | |
1360 this.done_ = false; | |
1361 | |
1362 /** | |
1363 * Event on beginning of the current gesture. | |
1364 * The variable is updated when the number of touch finger changed. | |
1365 * @type {TouchEvent} | |
1366 * @private | |
1367 */ | |
1368 this.gestureStartEvent_ = null; | |
1369 | |
1370 /** | |
1371 * Last touch event. | |
1372 * @type {TouchEvent} | |
1373 * @private | |
1374 */ | |
1375 this.lastEvent_ = null; | |
1376 | |
1377 /** | |
1378 * Zoom value just after last touch event. | |
1379 * @type {number} | |
1380 * @private | |
1381 */ | |
1382 this.lastZoom_ = 1.0; | |
1383 | |
1384 var onTouchEventBound = this.onTouchEvent_.bind(this); | |
1385 targetElement.addEventListener('touchstart', onTouchEventBound); | |
1386 targetElement.ownerDocument.addEventListener('touchmove', onTouchEventBound); | |
1387 targetElement.ownerDocument.addEventListener('touchend', onTouchEventBound); | |
1305 } | 1388 } |
1306 | 1389 |
1307 /** | 1390 /** |
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 | 1391 * 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). | 1392 * horizontally it's considered as a swipe gesture (change the current image). |
1337 */ | 1393 * @type {number} |
1338 SwipeOverlay.SWIPE_THRESHOLD = 100; | 1394 * @const |
1395 */ | |
1396 TouchHandlers.SWIPE_THRESHOLD = 100; | |
1397 | |
1398 /** | |
1399 * Obtains distance between fingers. | |
1400 * @param {TouchEvent} event Touch event. It should include more than two | |
1401 * touches. | |
1402 * @return {boolean} Distance between touch[0] and touch[1]. | |
1403 */ | |
1404 TouchHandlers.getDistance = function(event) { | |
1405 var touch1 = event.touches[0]; | |
1406 var touch2 = event.touches[1]; | |
1407 var dx = touch1.clientX - touch2.clientX; | |
1408 var dy = touch1.clientY - touch2.clientY; | |
1409 return Math.sqrt(dx * dx + dy * dy); | |
1410 }; | |
1411 | |
1412 TouchHandlers.prototype = { | |
1413 /** | |
1414 * @param {boolean} flag New value. | |
1415 */ | |
1416 set enable(flag) { | |
1417 this.enable_ = flag; | |
1418 if (!this.enable_) | |
1419 this.stopOperation(); | |
1420 } | |
1421 }; | |
1422 | |
1423 /** | |
1424 * Stops the current touch operation. | |
1425 */ | |
1426 TouchHandlers.prototype.stopOperation = function() { | |
1427 this.inTouch_ = false; | |
1428 this.done_ = false; | |
1429 this.gestureStartEvent_ = null; | |
1430 this.lastEvent_ = null; | |
1431 this.lastZoom_ = 1.0; | |
1432 }; | |
1433 | |
1434 /** | |
1435 * @param {event} event Touch event. | |
1436 */ | |
1437 TouchHandlers.prototype.onTouchEvent_ = function(event) { | |
1438 // Check if the current touch operation started from the target element or | |
1439 // not. | |
1440 if (!this.inTouch_) { | |
1441 // Check if a touch operation starts with the event. | |
1442 if (this.enable_ && | |
1443 event.type === 'touchstart' && | |
mtomasz
2014/07/23 08:15:08
nit: Why not splitting this to a separate method?
hirono
2014/07/23 09:27:23
Done.
| |
1444 event.touches.length === 1) { | |
1445 this.inTouch_ = true; | |
1446 } else { | |
1447 return; | |
1448 } | |
1449 } else { | |
1450 // Check if the current touch operaiton ends with the event. | |
mtomasz
2014/07/23 08:15:08
typo: operation
hirono
2014/07/23 09:27:23
Done.
| |
1451 if (event.touches.length === 0) { | |
1452 this.stopOperation(); | |
1453 return; | |
1454 } | |
1455 } | |
1456 | |
1457 // Check if a new gesture started or not. | |
1458 if (!this.lastEvent_ || | |
1459 this.lastEvent_.touches.length !== event.touches.length) { | |
1460 if (event.touches.length === 2 || | |
1461 event.touches.length === 1) { | |
1462 this.gestureStartEvent_ = event; | |
1463 this.lastEvent_ = event; | |
1464 this.lastZoom_ = this.slideMode_.getViewport().getZoom(); | |
1465 } else { | |
1466 this.gestureStartEvent_ = null; | |
1467 this.lastEvent_ = null; | |
1468 this.lastZoom_ = 1.0; | |
1469 } | |
1470 return; | |
1471 } | |
1472 | |
1473 // Handle the gesture movement. | |
1474 var viewport = this.slideMode_.getViewport(); | |
1475 switch (event.touches.length) { | |
1476 case 1: | |
1477 if (viewport.isZooming()) { | |
1478 // Scrolling an image by swipe. | |
1479 var dx = event.touches[0].screenX - this.lastEvent_.touches[0].screenX; | |
1480 var dy = event.touches[0].screenY - this.lastEvent_.touches[0].screenY; | |
1481 viewport.setOffset( | |
1482 viewport.getOffsetX() + dx, viewport.getOffsetY() + dy); | |
1483 this.slideMode_.applyViewportChange(); | |
1484 } else { | |
1485 // Traversing images by swipe. | |
1486 if (this.done_) | |
1487 break; | |
1488 var dx = | |
1489 event.touches[0].clientX - | |
1490 this.gestureStartEvent_.touches[0].clientX; | |
1491 if (dx > TouchHandlers.SWIPE_THRESHOLD) { | |
1492 this.slideMode_.advanceManually(-1); | |
1493 this.done_ = true; | |
1494 } else if (dx < -TouchHandlers.SWIPE_THRESHOLD) { | |
1495 this.slideMode_.advanceManually(1); | |
1496 this.done_ = true; | |
1497 } | |
1498 } | |
1499 break; | |
1500 | |
1501 case 2: | |
1502 // Pinch zoom. | |
1503 var distance1 = TouchHandlers.getDistance(this.lastEvent_); | |
1504 var distance2 = TouchHandlers.getDistance(event); | |
1505 if (distance1 == 0.0) | |
mtomasz
2014/07/23 08:15:08
nit: Simply === 0?
hirono
2014/07/23 09:27:23
Done.
| |
1506 break; | |
1507 var zoom = distance2 / distance1 * this.lastZoom_; | |
1508 viewport.setZoom(zoom); | |
1509 this.slideMode_.applyViewportChange(); | |
1510 break; | |
1511 } | |
1512 | |
1513 // Update the last event. | |
1514 this.lastEvent_ = event; | |
1515 this.lastZoom_ = viewport.getZoom(); | |
1516 }; | |
OLD | NEW |