multi_select_handler.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Distributed under the BSD license:
  3. *
  4. * Copyright (c) 2010, Ajax.org B.V.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of Ajax.org B.V. nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * ***** END LICENSE BLOCK ***** */
  30. define(function(require, exports, module) {
  31. var event = require("../lib/event");
  32. var useragent = require("../lib/useragent");
  33. // mouse
  34. function isSamePoint(p1, p2) {
  35. return p1.row == p2.row && p1.column == p2.column;
  36. }
  37. function onMouseDown(e) {
  38. var ev = e.domEvent;
  39. var alt = ev.altKey;
  40. var shift = ev.shiftKey;
  41. var ctrl = ev.ctrlKey;
  42. var accel = e.getAccelKey();
  43. var button = e.getButton();
  44. if (ctrl && useragent.isMac)
  45. button = ev.button;
  46. if (e.editor.inMultiSelectMode && button == 2) {
  47. e.editor.textInput.onContextMenu(e.domEvent);
  48. return;
  49. }
  50. if (!ctrl && !alt && !accel) {
  51. if (button === 0 && e.editor.inMultiSelectMode)
  52. e.editor.exitMultiSelectMode();
  53. return;
  54. }
  55. if (button !== 0)
  56. return;
  57. var editor = e.editor;
  58. var selection = editor.selection;
  59. var isMultiSelect = editor.inMultiSelectMode;
  60. var pos = e.getDocumentPosition();
  61. var cursor = selection.getCursor();
  62. var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));
  63. var mouseX = e.x, mouseY = e.y;
  64. var onMouseSelection = function(e) {
  65. mouseX = e.clientX;
  66. mouseY = e.clientY;
  67. };
  68. var session = editor.session;
  69. var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
  70. var screenCursor = screenAnchor;
  71. var selectionMode;
  72. if (editor.$mouseHandler.$enableJumpToDef) {
  73. if (ctrl && alt || accel && alt)
  74. selectionMode = shift ? "block" : "add";
  75. else if (alt && editor.$blockSelectEnabled)
  76. selectionMode = "block";
  77. } else {
  78. if (accel && !alt) {
  79. selectionMode = "add";
  80. if (!isMultiSelect && shift)
  81. return;
  82. } else if (alt && editor.$blockSelectEnabled) {
  83. selectionMode = "block";
  84. }
  85. }
  86. if (selectionMode && useragent.isMac && ev.ctrlKey) {
  87. editor.$mouseHandler.cancelContextMenu();
  88. }
  89. if (selectionMode == "add") {
  90. if (!isMultiSelect && inSelection)
  91. return; // dragging
  92. if (!isMultiSelect) {
  93. var range = selection.toOrientedRange();
  94. editor.addSelectionMarker(range);
  95. }
  96. var oldRange = selection.rangeList.rangeAtPoint(pos);
  97. editor.$blockScrolling++;
  98. editor.inVirtualSelectionMode = true;
  99. if (shift) {
  100. oldRange = null;
  101. range = selection.ranges[0] || range;
  102. editor.removeSelectionMarker(range);
  103. }
  104. editor.once("mouseup", function() {
  105. var tmpSel = selection.toOrientedRange();
  106. if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor))
  107. selection.substractPoint(tmpSel.cursor);
  108. else {
  109. if (shift) {
  110. selection.substractPoint(range.cursor);
  111. } else if (range) {
  112. editor.removeSelectionMarker(range);
  113. selection.addRange(range);
  114. }
  115. selection.addRange(tmpSel);
  116. }
  117. editor.$blockScrolling--;
  118. editor.inVirtualSelectionMode = false;
  119. });
  120. } else if (selectionMode == "block") {
  121. e.stop();
  122. editor.inVirtualSelectionMode = true;
  123. var initialRange;
  124. var rectSel = [];
  125. var blockSelect = function() {
  126. var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
  127. var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column);
  128. if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead))
  129. return;
  130. screenCursor = newCursor;
  131. editor.$blockScrolling++;
  132. editor.selection.moveToPosition(cursor);
  133. editor.renderer.scrollCursorIntoView();
  134. editor.removeSelectionMarkers(rectSel);
  135. rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);
  136. if (editor.$mouseHandler.$clickSelection && rectSel.length == 1 && rectSel[0].isEmpty())
  137. rectSel[0] = editor.$mouseHandler.$clickSelection.clone();
  138. rectSel.forEach(editor.addSelectionMarker, editor);
  139. editor.updateSelectionMarkers();
  140. editor.$blockScrolling--;
  141. };
  142. editor.$blockScrolling++;
  143. if (isMultiSelect && !accel) {
  144. selection.toSingleRange();
  145. } else if (!isMultiSelect && accel) {
  146. initialRange = selection.toOrientedRange();
  147. editor.addSelectionMarker(initialRange);
  148. }
  149. if (shift)
  150. screenAnchor = session.documentToScreenPosition(selection.lead);
  151. else
  152. selection.moveToPosition(pos);
  153. editor.$blockScrolling--;
  154. screenCursor = {row: -1, column: -1};
  155. var onMouseSelectionEnd = function(e) {
  156. clearInterval(timerId);
  157. editor.removeSelectionMarkers(rectSel);
  158. if (!rectSel.length)
  159. rectSel = [selection.toOrientedRange()];
  160. editor.$blockScrolling++;
  161. if (initialRange) {
  162. editor.removeSelectionMarker(initialRange);
  163. selection.toSingleRange(initialRange);
  164. }
  165. for (var i = 0; i < rectSel.length; i++)
  166. selection.addRange(rectSel[i]);
  167. editor.inVirtualSelectionMode = false;
  168. editor.$mouseHandler.$clickSelection = null;
  169. editor.$blockScrolling--;
  170. };
  171. var onSelectionInterval = blockSelect;
  172. event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
  173. var timerId = setInterval(function() {onSelectionInterval();}, 20);
  174. return e.preventDefault();
  175. }
  176. }
  177. exports.onMouseDown = onMouseDown;
  178. });