Index: trunk/extensions/VisualEditor/modules/es/views/es.SurfaceView.js |
— | — | @@ -43,10 +43,7 @@ |
44 | 44 | alt: false |
45 | 45 | } |
46 | 46 | }; |
47 | | - this.selection = { |
48 | | - from: 0, |
49 | | - to: 0 |
50 | | - }; |
| 47 | + this.selection = new es.Range(); |
51 | 48 | |
52 | 49 | // References for use in closures |
53 | 50 | var surfaceView = this, |
— | — | @@ -113,18 +110,25 @@ |
114 | 111 | } ); |
115 | 112 | }; |
116 | 113 | |
| 114 | +es.SurfaceView.prototype.hasSelection = function() { |
| 115 | + return !!this.selection.getLength(); |
| 116 | +} |
| 117 | + |
117 | 118 | es.SurfaceView.prototype.onMouseDown = function( e ) { |
118 | 119 | if ( e.button === 0 /* left mouse button */ ) { |
119 | | - var position = es.Position.newFromEventPagePosition( e ), |
120 | | - offset = this.documentView.getOffsetFromEvent( e ), |
121 | | - nodeView = this.documentView.getNodeFromOffset( offset, false ); |
122 | | - this.showCursor( offset, position.left > nodeView.$.offset().left ); |
123 | 120 | this.mouse.selecting = true; |
124 | | - if ( !this.keyboard.keys.shift ) { |
125 | | - this.selection.from = offset; |
| 121 | + this.selection.to = this.documentView.getOffsetFromEvent( e ); |
| 122 | + |
| 123 | + if ( this.keyboard.keys.shift ) { |
| 124 | + this.drawSelection(); |
| 125 | + this.hideCursor(); |
| 126 | + } else { |
| 127 | + this.documentView.clearSelection(); |
| 128 | + this.selection.from = this.selection.to; |
| 129 | + var position = es.Position.newFromEventPagePosition( e ), |
| 130 | + nodeView = this.documentView.getNodeFromOffset( this.selection.to, false ); |
| 131 | + this.showCursor( this.selection.to, position.left > nodeView.$.offset().left ); |
126 | 132 | } |
127 | | - this.selection.to = offset; |
128 | | - this.drawSelection(); |
129 | 133 | } |
130 | 134 | if ( !this.$input.is( ':focus' ) ) { |
131 | 135 | this.$input.focus().select(); |
— | — | @@ -135,21 +139,18 @@ |
136 | 140 | |
137 | 141 | es.SurfaceView.prototype.onMouseMove = function( e ) { |
138 | 142 | if ( e.button === 0 /* left mouse button */ && this.mouse.selecting ) { |
139 | | - this.hideCursor(); |
140 | 143 | this.selection.to = this.documentView.getOffsetFromEvent( e ); |
141 | | - if ( !this.drawSelection() ) { |
142 | | - this.showCursor(); |
| 144 | + this.drawSelection(); |
| 145 | + if ( this.selection.getLength() ) { |
| 146 | + this.hideCursor(); |
143 | 147 | } |
144 | 148 | } |
145 | 149 | }; |
146 | 150 | |
147 | 151 | es.SurfaceView.prototype.onMouseUp = function( e ) { |
148 | | - if ( e.button === 0 /* left mouse button */ && this.selection.to ) { |
149 | | - if ( this.drawSelection() ) { |
150 | | - this.hideCursor(); |
151 | | - } |
| 152 | + if ( e.button === 0 /* left mouse button */ ) { |
| 153 | + this.mouse.selecting = false; |
152 | 154 | } |
153 | | - this.mouse.selecting = false; |
154 | 155 | }; |
155 | 156 | |
156 | 157 | es.SurfaceView.prototype.drawSelection = function() { |
— | — | @@ -161,6 +162,7 @@ |
162 | 163 | switch ( e.keyCode ) { |
163 | 164 | case 16: // Shift |
164 | 165 | this.keyboard.keys.shift = true; |
| 166 | + this.keyboard.selecting = true; |
165 | 167 | break; |
166 | 168 | case 17: // Control |
167 | 169 | this.keyboard.keys.control = true; |
— | — | @@ -231,30 +233,60 @@ |
232 | 234 | }; |
233 | 235 | |
234 | 236 | es.SurfaceView.prototype.moveCursor = function( instruction ) { |
| 237 | + this.selection.normalize(); |
235 | 238 | if ( instruction === 'left') { |
236 | | - this.showCursor( |
237 | | - this.documentView.getModel().getRelativeContentOffset( this.cursor.offset, -1 ) |
238 | | - ); |
| 239 | + if ( this.keyboard.keys.shift ) { |
| 240 | + this.showCursor( |
| 241 | + this.documentView.getModel().getRelativeContentOffset( this.selection.to, -1 ) |
| 242 | + ); |
| 243 | + this.drawSelection(); |
| 244 | + this.hideCursor(); |
| 245 | + } else { |
| 246 | + this.showCursor( |
| 247 | + this.documentView.getModel().getRelativeContentOffset( this.selection.start, -1 ) |
| 248 | + ); |
| 249 | + this.selection.from = this.selection.to; |
| 250 | + this.documentView.clearSelection(); |
| 251 | + } |
239 | 252 | } else if ( instruction === 'right' ) { |
240 | | - this.showCursor( |
241 | | - this.documentView.getModel().getRelativeContentOffset( this.cursor.offset, 1 ) |
242 | | - ); |
| 253 | + |
| 254 | + if ( this.keyboard.keys.shift ) { |
| 255 | + this.showCursor( |
| 256 | + this.documentView.getModel().getRelativeContentOffset( this.selection.to, 1 ) |
| 257 | + ); |
| 258 | + this.drawSelection(); |
| 259 | + this.hideCursor(); |
| 260 | + } else { |
| 261 | + this.showCursor( |
| 262 | + this.documentView.getModel().getRelativeContentOffset( this.selection.end, 1 ) |
| 263 | + ); |
| 264 | + this.selection.from = this.selection.to; |
| 265 | + this.documentView.clearSelection(); |
| 266 | + } |
243 | 267 | } else if ( instruction === 'up' || instruction === 'down' ) { |
244 | 268 | // ... |
245 | 269 | } else if ( instruction === 'home' || instruction === 'end' ) { |
246 | 270 | var offset; |
247 | 271 | if ( this.cursor.initialBias ) { |
248 | 272 | offset = this.documentView.getModel().getRelativeContentOffset( |
249 | | - this.cursor.offset, -1 ); |
| 273 | + this.selection.to, -1 ); |
250 | 274 | } else { |
251 | | - offset = this.cursor.offset; |
| 275 | + offset = this.selection.to; |
252 | 276 | } |
| 277 | + |
| 278 | + |
| 279 | + |
253 | 280 | if ( instruction === 'home' ) { |
254 | 281 | this.showCursor( |
255 | 282 | this.documentView.getRenderedLineRangeFromOffset( offset ).start, false ); |
256 | 283 | } else { // end |
257 | 284 | this.showCursor( this.documentView.getRenderedLineRangeFromOffset( offset ).end, true ); |
258 | 285 | } |
| 286 | + if ( this.keyboard.keys.shift ) { |
| 287 | + this.drawSelection(); |
| 288 | + this.hideCursor(); |
| 289 | + } |
| 290 | + |
259 | 291 | } |
260 | 292 | }; |
261 | 293 | |
— | — | @@ -267,9 +299,9 @@ |
268 | 300 | es.SurfaceView.prototype.showCursor = function( offset, leftBias ) { |
269 | 301 | if ( typeof offset !== 'undefined' ) { |
270 | 302 | this.cursor.initialBias = leftBias ? true : false; |
271 | | - this.cursor.offset = offset; |
| 303 | + this.selection.to = offset; |
272 | 304 | var position = this.documentView.getRenderedPositionFromOffset( |
273 | | - this.cursor.offset, leftBias |
| 305 | + this.selection.to, leftBias |
274 | 306 | ); |
275 | 307 | this.cursor.$.css( { |
276 | 308 | 'left': position.left, |