PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/textarea/MouseHandler.java

#
Java | 553 lines | 424 code | 77 blank | 52 comment | 113 complexity | bd136b413a4ac4969bc909d8d1d9016e MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * JEditTextArea.java - jEdit's text component
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 2005 Slava Pestov
  7. * Portions copyright (C) 2000 Ollie Rutherfurd
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. */
  23. package org.gjt.sp.jedit.textarea;
  24. //{{{ Imports
  25. import java.awt.*;
  26. import java.awt.event.*;
  27. import javax.swing.*;
  28. import javax.swing.event.*;
  29. import org.gjt.sp.jedit.GUIUtilities;
  30. import org.gjt.sp.jedit.OperatingSystem;
  31. import org.gjt.sp.jedit.Registers;
  32. import org.gjt.sp.jedit.TextUtilities;
  33. import org.gjt.sp.util.StandardUtilities;
  34. //}}}
  35. class MouseHandler extends MouseInputAdapter
  36. {
  37. //{{{ MouseHandler constructor
  38. MouseHandler(JEditTextArea textArea)
  39. {
  40. this.textArea = textArea;
  41. } //}}}
  42. //{{{ mousePressed() method
  43. public void mousePressed(MouseEvent evt)
  44. {
  45. showCursor();
  46. control = (OperatingSystem.isMacOS() && evt.isMetaDown())
  47. || (!OperatingSystem.isMacOS() && evt.isControlDown());
  48. // so that Home <mouse click> Home is not the same
  49. // as pressing Home twice in a row
  50. textArea.getInputHandler().resetLastActionCount();
  51. quickCopyDrag = (textArea.isQuickCopyEnabled() &&
  52. GUIUtilities.isMiddleButton(evt.getModifiers()));
  53. if(!quickCopyDrag)
  54. {
  55. textArea.requestFocus();
  56. JEditTextArea.focusedComponent = textArea;
  57. }
  58. if(textArea.getBuffer().isLoading())
  59. return;
  60. int x = evt.getX();
  61. int y = evt.getY();
  62. dragStart = textArea.xyToOffset(x,y,
  63. !(textArea.getPainter().isBlockCaretEnabled()
  64. || textArea.isOverwriteEnabled()));
  65. dragStartLine = textArea.getLineOfOffset(dragStart);
  66. dragStartOffset = dragStart - textArea.getLineStartOffset(
  67. dragStartLine);
  68. if(GUIUtilities.isPopupTrigger(evt)
  69. && textArea.getRightClickPopup() != null)
  70. {
  71. if(textArea.isRightClickPopupEnabled())
  72. textArea.handlePopupTrigger(evt);
  73. return;
  74. }
  75. dragged = false;
  76. textArea.blink = true;
  77. textArea.invalidateLine(textArea.getCaretLine());
  78. clickCount = evt.getClickCount();
  79. if(textArea.isDragEnabled()
  80. && textArea.selectionManager.insideSelection(x,y)
  81. && clickCount == 1 && !evt.isShiftDown())
  82. {
  83. maybeDragAndDrop = true;
  84. textArea.moveCaretPosition(dragStart,false);
  85. return;
  86. }
  87. else
  88. maybeDragAndDrop = false;
  89. if(quickCopyDrag)
  90. {
  91. // ignore double clicks of middle button
  92. doSingleClick(evt);
  93. }
  94. else
  95. {
  96. switch(clickCount)
  97. {
  98. case 1:
  99. doSingleClick(evt);
  100. break;
  101. case 2:
  102. doDoubleClick();
  103. break;
  104. default: //case 3:
  105. doTripleClick();
  106. break;
  107. }
  108. }
  109. } //}}}
  110. //{{{ doSingleClick() method
  111. private void doSingleClick(MouseEvent evt)
  112. {
  113. int x = evt.getX();
  114. int extraEndVirt = 0;
  115. if(textArea.chunkCache.getLineInfo(
  116. textArea.getLastScreenLine()).lastSubregion)
  117. {
  118. float dragStartLineWidth = textArea.offsetToXY(
  119. dragStartLine,
  120. textArea.getLineLength(dragStartLine)).x;
  121. if(x > dragStartLineWidth)
  122. {
  123. extraEndVirt = (int)(
  124. (x - dragStartLineWidth)
  125. / textArea.charWidth);
  126. if(!textArea.getPainter().isBlockCaretEnabled()
  127. && !textArea.isOverwriteEnabled()
  128. && (x - textArea.getHorizontalOffset())
  129. % textArea.charWidth > textArea.charWidth / 2)
  130. {
  131. extraEndVirt++;
  132. }
  133. }
  134. }
  135. if((control || textArea.isRectangularSelectionEnabled())
  136. && textArea.isEditable())
  137. {
  138. int screenLine = (evt.getY() / textArea.getPainter()
  139. .getFontMetrics().getHeight());
  140. if(screenLine > textArea.getLastScreenLine())
  141. screenLine = textArea.getLastScreenLine();
  142. ChunkCache.LineInfo info = textArea.chunkCache.getLineInfo(screenLine);
  143. if(info.lastSubregion && extraEndVirt != 0)
  144. {
  145. // control-click in virtual space inserts
  146. // whitespace and moves caret
  147. String whitespace = StandardUtilities
  148. .createWhiteSpace(extraEndVirt,0);
  149. textArea.getBuffer().insert(dragStart,whitespace);
  150. dragStart += whitespace.length();
  151. }
  152. }
  153. if(evt.isShiftDown())
  154. {
  155. // XXX: getMarkPosition() deprecated!
  156. textArea.resizeSelection(
  157. textArea.getMarkPosition(),dragStart,extraEndVirt,
  158. textArea.isRectangularSelectionEnabled()
  159. || control);
  160. if(!quickCopyDrag)
  161. textArea.moveCaretPosition(dragStart,false);
  162. // so that shift-click-drag works
  163. dragStartLine = textArea.getMarkLine();
  164. dragStart = textArea.getMarkPosition();
  165. dragStartOffset = dragStart
  166. - textArea.getLineStartOffset(dragStartLine);
  167. // so that quick copy works
  168. dragged = true;
  169. return;
  170. }
  171. if(!quickCopyDrag)
  172. textArea.moveCaretPosition(dragStart,false);
  173. if(!(textArea.isMultipleSelectionEnabled()
  174. || quickCopyDrag))
  175. textArea.selectNone();
  176. } //}}}
  177. //{{{ doDoubleClick() method
  178. private void doDoubleClick()
  179. {
  180. // Ignore empty lines
  181. if(textArea.getLineLength(dragStartLine) == 0)
  182. return;
  183. String lineText = textArea.getLineText(dragStartLine);
  184. String noWordSep = textArea.getBuffer()
  185. .getStringProperty("noWordSep");
  186. if(dragStartOffset == textArea.getLineLength(dragStartLine))
  187. dragStartOffset--;
  188. boolean joinNonWordChars = textArea.getJoinNonWordChars();
  189. int wordStart = TextUtilities.findWordStart(lineText,dragStartOffset,
  190. noWordSep,textArea.getJoinNonWordChars());
  191. int wordEnd = TextUtilities.findWordEnd(lineText,
  192. dragStartOffset+1,noWordSep,
  193. textArea.getJoinNonWordChars());
  194. int lineStart = textArea.getLineStartOffset(dragStartLine);
  195. Selection sel = new Selection.Range(
  196. lineStart + wordStart,
  197. lineStart + wordEnd);
  198. if(textArea.isMultipleSelectionEnabled())
  199. textArea.addToSelection(sel);
  200. else
  201. textArea.setSelection(sel);
  202. if(quickCopyDrag)
  203. quickCopyDrag = false;
  204. textArea.moveCaretPosition(lineStart + wordEnd,false);
  205. dragged = true;
  206. } //}}}
  207. //{{{ doTripleClick() method
  208. private void doTripleClick()
  209. {
  210. int newCaret = textArea.getLineEndOffset(dragStartLine);
  211. if(dragStartLine == textArea.getLineCount() - 1)
  212. newCaret--;
  213. Selection sel = new Selection.Range(
  214. textArea.getLineStartOffset(dragStartLine),
  215. newCaret);
  216. if(textArea.isMultipleSelectionEnabled())
  217. textArea.addToSelection(sel);
  218. else
  219. textArea.setSelection(sel);
  220. if(quickCopyDrag)
  221. quickCopyDrag = false;
  222. textArea.moveCaretPosition(newCaret,false);
  223. dragged = true;
  224. } //}}}
  225. //{{{ mouseMoved() method
  226. public void mouseMoved(MouseEvent evt)
  227. {
  228. showCursor();
  229. } //}}}
  230. //{{{ mouseDragged() method
  231. public void mouseDragged(MouseEvent evt)
  232. {
  233. if(maybeDragAndDrop)
  234. {
  235. textArea.startDragAndDrop(evt,control);
  236. return;
  237. }
  238. if(textArea.isDragInProgress())
  239. return;
  240. JPopupMenu popup = textArea.getRightClickPopup();
  241. if(GUIUtilities.isPopupTrigger(evt)
  242. || (popup != null && popup.isVisible()))
  243. return;
  244. if(textArea.getBuffer().isLoading())
  245. return;
  246. TextAreaPainter painter = textArea.getPainter();
  247. if(evt.getY() < 0)
  248. {
  249. int delta = Math.min(-1,evt.getY()
  250. / painter.getFontMetrics()
  251. .getHeight());
  252. textArea.setFirstLine(textArea.getFirstLine() + delta);
  253. }
  254. else if(evt.getY() >= painter.getHeight())
  255. {
  256. int delta = Math.max(1,(evt.getY()
  257. - painter.getHeight()) /
  258. painter.getFontMetrics()
  259. .getHeight());
  260. if(textArea.lastLinePartial)
  261. delta--;
  262. textArea.setFirstLine(textArea.getFirstLine() + delta);
  263. }
  264. switch(clickCount)
  265. {
  266. case 1:
  267. doSingleDrag(evt);
  268. break;
  269. case 2:
  270. doDoubleDrag(evt);
  271. break;
  272. default: //case 3:
  273. doTripleDrag(evt);
  274. break;
  275. }
  276. } //}}}
  277. //{{{ doSingleDrag() method
  278. private void doSingleDrag(MouseEvent evt)
  279. {
  280. dragged = true;
  281. TextAreaPainter painter = textArea.getPainter();
  282. int x = evt.getX();
  283. int y = evt.getY();
  284. if(y < 0)
  285. y = 0;
  286. else if(y >= painter.getHeight())
  287. y = painter.getHeight() - 1;
  288. int dot = textArea.xyToOffset(x,y,
  289. (!painter.isBlockCaretEnabled()
  290. && !textArea.isOverwriteEnabled())
  291. || quickCopyDrag);
  292. int dotLine = textArea.getLineOfOffset(dot);
  293. int extraEndVirt = 0;
  294. if(textArea.chunkCache.getLineInfo(
  295. textArea.getLastScreenLine())
  296. .lastSubregion)
  297. {
  298. float dotLineWidth = textArea.offsetToXY(
  299. dotLine,textArea.getLineLength(dotLine)).x;
  300. if(x > dotLineWidth)
  301. {
  302. extraEndVirt = (int)((x - dotLineWidth) / textArea.charWidth);
  303. if(!painter.isBlockCaretEnabled()
  304. && !textArea.isOverwriteEnabled()
  305. && (x - textArea.getHorizontalOffset()) % textArea.charWidth > textArea.charWidth / 2)
  306. extraEndVirt++;
  307. }
  308. }
  309. textArea.resizeSelection(dragStart,dot,extraEndVirt,
  310. textArea.isRectangularSelectionEnabled()
  311. || control);
  312. if(quickCopyDrag)
  313. {
  314. // just scroll to the dragged location
  315. textArea.scrollTo(dotLine,dot - textArea.getLineStartOffset(dotLine),false);
  316. }
  317. else
  318. {
  319. if(dot != textArea.getCaretPosition())
  320. textArea.moveCaretPosition(dot,false);
  321. if(textArea.isRectangularSelectionEnabled()
  322. && extraEndVirt != 0)
  323. {
  324. textArea.scrollTo(dotLine,dot - textArea.getLineStartOffset(dotLine)
  325. + extraEndVirt,false);
  326. }
  327. }
  328. } //}}}
  329. //{{{ doDoubleDrag() method
  330. private void doDoubleDrag(MouseEvent evt)
  331. {
  332. int markLineStart = textArea.getLineStartOffset(dragStartLine);
  333. int markLineLength = textArea.getLineLength(dragStartLine);
  334. int mark = dragStartOffset;
  335. TextAreaPainter painter = textArea.getPainter();
  336. int pos = textArea.xyToOffset(evt.getX(),
  337. Math.max(0,Math.min(painter.getHeight(),evt.getY())),
  338. !(painter.isBlockCaretEnabled()
  339. || textArea.isOverwriteEnabled()));
  340. int line = textArea.getLineOfOffset(pos);
  341. int lineStart = textArea.getLineStartOffset(line);
  342. int lineLength = textArea.getLineLength(line);
  343. int offset = pos - lineStart;
  344. String lineText = textArea.getLineText(line);
  345. String markLineText = textArea.getLineText(dragStartLine);
  346. String noWordSep = textArea.getBuffer()
  347. .getStringProperty("noWordSep");
  348. boolean joinNonWordChars = textArea.getJoinNonWordChars();
  349. if(markLineStart + dragStartOffset > lineStart + offset)
  350. {
  351. if(offset != 0 && offset != lineLength)
  352. {
  353. offset = TextUtilities.findWordStart(
  354. lineText,offset,noWordSep,
  355. joinNonWordChars);
  356. }
  357. if(markLineLength != 0)
  358. {
  359. mark = TextUtilities.findWordEnd(
  360. markLineText,mark,noWordSep,
  361. joinNonWordChars);
  362. }
  363. }
  364. else
  365. {
  366. if(offset != 0 && lineLength != 0)
  367. {
  368. offset = TextUtilities.findWordEnd(
  369. lineText,offset,noWordSep,
  370. joinNonWordChars);
  371. }
  372. if(mark != 0 && mark != markLineLength)
  373. {
  374. mark = TextUtilities.findWordStart(
  375. markLineText,mark,noWordSep,
  376. joinNonWordChars);
  377. }
  378. }
  379. if(lineStart + offset == textArea.getCaretPosition())
  380. return;
  381. textArea.resizeSelection(markLineStart + mark,
  382. lineStart + offset,0,false);
  383. textArea.moveCaretPosition(lineStart + offset,false);
  384. dragged = true;
  385. } //}}}
  386. //{{{ doTripleDrag() method
  387. private void doTripleDrag(MouseEvent evt)
  388. {
  389. TextAreaPainter painter = textArea.getPainter();
  390. int offset = textArea.xyToOffset(evt.getX(),
  391. Math.max(0,Math.min(painter.getHeight(),evt.getY())),
  392. false);
  393. int mouseLine = textArea.getLineOfOffset(offset);
  394. int mark;
  395. int mouse;
  396. if(dragStartLine > mouseLine)
  397. {
  398. mark = textArea.getLineEndOffset(dragStartLine) - 1;
  399. if(offset == textArea.getLineEndOffset(mouseLine) - 1)
  400. mouse = offset;
  401. else
  402. mouse = textArea.getLineStartOffset(mouseLine);
  403. }
  404. else
  405. {
  406. mark = textArea.getLineStartOffset(dragStartLine);
  407. if(offset == textArea.getLineStartOffset(mouseLine))
  408. mouse = offset;
  409. else if(offset == textArea.getLineEndOffset(mouseLine) - 1
  410. && mouseLine != textArea.getLineCount() - 1)
  411. mouse = textArea.getLineEndOffset(mouseLine);
  412. else
  413. mouse = textArea.getLineEndOffset(mouseLine) - 1;
  414. }
  415. mouse = Math.min(textArea.getBuffer().getLength(),mouse);
  416. if(mouse == textArea.getCaretPosition())
  417. return;
  418. textArea.resizeSelection(mark,mouse,0,false);
  419. textArea.moveCaretPosition(mouse,false);
  420. dragged = true;
  421. } //}}}
  422. //{{{ mouseReleased() method
  423. public void mouseReleased(MouseEvent evt)
  424. {
  425. // middle mouse button drag inserts selection
  426. // at caret position
  427. Selection sel = textArea.getSelectionAtOffset(dragStart);
  428. if(dragged && sel != null)
  429. {
  430. Registers.setRegister('%',textArea.getSelectedText(sel));
  431. if(quickCopyDrag)
  432. {
  433. textArea.removeFromSelection(sel);
  434. Registers.paste(JEditTextArea.focusedComponent,
  435. '%',sel instanceof Selection.Rect);
  436. JEditTextArea.focusedComponent.requestFocus();
  437. }
  438. }
  439. else if(!dragged && textArea.isQuickCopyEnabled() &&
  440. GUIUtilities.isMiddleButton(evt.getModifiers()))
  441. {
  442. textArea.requestFocus();
  443. JEditTextArea.focusedComponent = textArea;
  444. textArea.setCaretPosition(dragStart,false);
  445. if(!textArea.isEditable())
  446. textArea.getToolkit().beep();
  447. else
  448. Registers.paste(textArea,'%',control);
  449. }
  450. else if(maybeDragAndDrop
  451. && !textArea.isMultipleSelectionEnabled())
  452. {
  453. textArea.selectNone();
  454. }
  455. dragged = false;
  456. } //}}}
  457. //{{{ Private members
  458. private JEditTextArea textArea;
  459. private int dragStartLine;
  460. private int dragStartOffset;
  461. private int dragStart;
  462. private int clickCount;
  463. private boolean dragged;
  464. private boolean quickCopyDrag;
  465. private boolean control;
  466. /* with drag and drop on, a mouse down in a selection does not
  467. immediately deselect */
  468. private boolean maybeDragAndDrop;
  469. //{{{ showCursor() method
  470. private void showCursor()
  471. {
  472. textArea.getPainter().setCursor(
  473. Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
  474. } //}}}
  475. //}}}
  476. }