Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(487)

Side by Side Diff: ui/file_manager/gallery/js/slide_mode.js

Issue 411853002: Gallery.app: Add touch handlers for the zoom/scroll feature. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698