PageRenderTime 82ms CodeModel.GetById 23ms app.highlight 54ms RepoModel.GetById 1ms 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
  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
 24package org.gjt.sp.jedit.textarea;
 25
 26//{{{ Imports
 27import java.awt.*;
 28import java.awt.event.*;
 29import javax.swing.*;
 30import javax.swing.event.*;
 31import org.gjt.sp.jedit.GUIUtilities;
 32import org.gjt.sp.jedit.OperatingSystem;
 33import org.gjt.sp.jedit.Registers;
 34import org.gjt.sp.jedit.TextUtilities;
 35import org.gjt.sp.util.StandardUtilities;
 36//}}}
 37
 38class MouseHandler extends MouseInputAdapter
 39{
 40	//{{{ MouseHandler constructor
 41	MouseHandler(JEditTextArea textArea)
 42	{
 43		this.textArea = textArea;
 44	} //}}}
 45	
 46	//{{{ mousePressed() method
 47	public void mousePressed(MouseEvent evt)
 48	{
 49		showCursor();
 50
 51		control = (OperatingSystem.isMacOS() && evt.isMetaDown())
 52			|| (!OperatingSystem.isMacOS() && evt.isControlDown());
 53
 54		// so that Home <mouse click> Home is not the same
 55		// as pressing Home twice in a row
 56		textArea.getInputHandler().resetLastActionCount();
 57
 58		quickCopyDrag = (textArea.isQuickCopyEnabled() &&
 59			GUIUtilities.isMiddleButton(evt.getModifiers()));
 60
 61		if(!quickCopyDrag)
 62		{
 63			textArea.requestFocus();
 64			JEditTextArea.focusedComponent = textArea;
 65		}
 66
 67		if(textArea.getBuffer().isLoading())
 68			return;
 69
 70		int x = evt.getX();
 71		int y = evt.getY();
 72
 73		dragStart = textArea.xyToOffset(x,y,
 74			!(textArea.getPainter().isBlockCaretEnabled()
 75			|| textArea.isOverwriteEnabled()));
 76		dragStartLine = textArea.getLineOfOffset(dragStart);
 77		dragStartOffset = dragStart - textArea.getLineStartOffset(
 78			dragStartLine);
 79
 80		if(GUIUtilities.isPopupTrigger(evt)
 81			&& textArea.getRightClickPopup() != null)
 82		{
 83			if(textArea.isRightClickPopupEnabled())
 84				textArea.handlePopupTrigger(evt);
 85			return;
 86		}
 87
 88		dragged = false;
 89
 90		textArea.blink = true;
 91		textArea.invalidateLine(textArea.getCaretLine());
 92
 93		clickCount = evt.getClickCount();
 94
 95		if(textArea.isDragEnabled()
 96			&& textArea.selectionManager.insideSelection(x,y)
 97			&& clickCount == 1 && !evt.isShiftDown())
 98		{
 99			maybeDragAndDrop = true;
100			textArea.moveCaretPosition(dragStart,false);
101			return;
102		}
103		else
104			maybeDragAndDrop = false;
105
106		if(quickCopyDrag)
107		{
108			// ignore double clicks of middle button
109			doSingleClick(evt);
110		}
111		else
112		{
113			switch(clickCount)
114			{
115			case 1:
116				doSingleClick(evt);
117				break;
118			case 2:
119				doDoubleClick();
120				break;
121			default: //case 3:
122				doTripleClick();
123				break;
124			}
125		}
126	} //}}}
127
128	//{{{ doSingleClick() method
129	private void doSingleClick(MouseEvent evt)
130	{
131		int x = evt.getX();
132
133		int extraEndVirt = 0;
134		if(textArea.chunkCache.getLineInfo(
135			textArea.getLastScreenLine()).lastSubregion)
136		{
137			float dragStartLineWidth = textArea.offsetToXY(
138				dragStartLine,
139				textArea.getLineLength(dragStartLine)).x;
140			if(x > dragStartLineWidth)
141			{
142				extraEndVirt = (int)(
143					(x - dragStartLineWidth)
144					/ textArea.charWidth);
145				if(!textArea.getPainter().isBlockCaretEnabled()
146					&& !textArea.isOverwriteEnabled()
147					&& (x - textArea.getHorizontalOffset())
148					% textArea.charWidth > textArea.charWidth / 2)
149				{
150					extraEndVirt++;
151				}
152			}
153		}
154
155		if((control || textArea.isRectangularSelectionEnabled())
156			&& textArea.isEditable())
157		{
158			int screenLine = (evt.getY() / textArea.getPainter()
159				.getFontMetrics().getHeight());
160			if(screenLine > textArea.getLastScreenLine())
161				screenLine = textArea.getLastScreenLine();
162			ChunkCache.LineInfo info = textArea.chunkCache.getLineInfo(screenLine);
163			if(info.lastSubregion && extraEndVirt != 0)
164			{
165				// control-click in virtual space inserts
166				// whitespace and moves caret
167				String whitespace = StandardUtilities
168					.createWhiteSpace(extraEndVirt,0);
169				textArea.getBuffer().insert(dragStart,whitespace);
170
171				dragStart += whitespace.length();
172			}
173		}
174
175		if(evt.isShiftDown())
176		{
177			// XXX: getMarkPosition() deprecated!
178			textArea.resizeSelection(
179				textArea.getMarkPosition(),dragStart,extraEndVirt,
180				textArea.isRectangularSelectionEnabled()
181				|| control);
182
183			if(!quickCopyDrag)
184				textArea.moveCaretPosition(dragStart,false);
185
186			// so that shift-click-drag works
187			dragStartLine = textArea.getMarkLine();
188			dragStart = textArea.getMarkPosition();
189			dragStartOffset = dragStart
190				- textArea.getLineStartOffset(dragStartLine);
191
192			// so that quick copy works
193			dragged = true;
194
195			return;
196		}
197
198		if(!quickCopyDrag)
199			textArea.moveCaretPosition(dragStart,false);
200
201		if(!(textArea.isMultipleSelectionEnabled()
202			|| quickCopyDrag))
203			textArea.selectNone();
204	} //}}}
205
206	//{{{ doDoubleClick() method
207	private void doDoubleClick()
208	{
209		// Ignore empty lines
210		if(textArea.getLineLength(dragStartLine) == 0)
211			return;
212
213		String lineText = textArea.getLineText(dragStartLine);
214		String noWordSep = textArea.getBuffer()
215			.getStringProperty("noWordSep");
216		if(dragStartOffset == textArea.getLineLength(dragStartLine))
217			dragStartOffset--;
218
219		boolean joinNonWordChars = textArea.getJoinNonWordChars();
220		int wordStart = TextUtilities.findWordStart(lineText,dragStartOffset,
221			noWordSep,textArea.getJoinNonWordChars());
222		int wordEnd = TextUtilities.findWordEnd(lineText,
223			dragStartOffset+1,noWordSep,
224			textArea.getJoinNonWordChars());
225
226		int lineStart = textArea.getLineStartOffset(dragStartLine);
227		Selection sel = new Selection.Range(
228			lineStart + wordStart,
229			lineStart + wordEnd);
230		if(textArea.isMultipleSelectionEnabled())
231			textArea.addToSelection(sel);
232		else
233			textArea.setSelection(sel);
234
235		if(quickCopyDrag)
236			quickCopyDrag = false;
237
238		textArea.moveCaretPosition(lineStart + wordEnd,false);
239
240		dragged = true;
241	} //}}}
242
243	//{{{ doTripleClick() method
244	private void doTripleClick()
245	{
246		int newCaret = textArea.getLineEndOffset(dragStartLine);
247		if(dragStartLine == textArea.getLineCount() - 1)
248			newCaret--;
249
250		Selection sel = new Selection.Range(
251			textArea.getLineStartOffset(dragStartLine),
252			newCaret);
253		if(textArea.isMultipleSelectionEnabled())
254			textArea.addToSelection(sel);
255		else
256			textArea.setSelection(sel);
257
258		if(quickCopyDrag)
259			quickCopyDrag = false;
260
261		textArea.moveCaretPosition(newCaret,false);
262
263		dragged = true;
264	} //}}}
265
266	//{{{ mouseMoved() method
267	public void mouseMoved(MouseEvent evt)
268	{
269		showCursor();
270	} //}}}
271
272	//{{{ mouseDragged() method
273	public void mouseDragged(MouseEvent evt)
274	{
275		if(maybeDragAndDrop)
276		{
277			textArea.startDragAndDrop(evt,control);
278			return;
279		}
280
281		if(textArea.isDragInProgress())
282			return;
283
284		JPopupMenu popup = textArea.getRightClickPopup();
285		if(GUIUtilities.isPopupTrigger(evt)
286			|| (popup != null && popup.isVisible()))
287			return;
288
289		if(textArea.getBuffer().isLoading())
290			return;
291
292		TextAreaPainter painter = textArea.getPainter();
293		if(evt.getY() < 0)
294		{
295			int delta = Math.min(-1,evt.getY()
296				/ painter.getFontMetrics()
297				.getHeight());
298			textArea.setFirstLine(textArea.getFirstLine() + delta);
299		}
300		else if(evt.getY() >= painter.getHeight())
301		{
302			int delta = Math.max(1,(evt.getY()
303				- painter.getHeight()) /
304				painter.getFontMetrics()
305				.getHeight());
306			if(textArea.lastLinePartial)
307				delta--;
308			textArea.setFirstLine(textArea.getFirstLine() + delta);
309		}
310
311		switch(clickCount)
312		{
313		case 1:
314			doSingleDrag(evt);
315			break;
316		case 2:
317			doDoubleDrag(evt);
318			break;
319		default: //case 3:
320			doTripleDrag(evt);
321			break;
322		}
323	} //}}}
324
325	//{{{ doSingleDrag() method
326	private void doSingleDrag(MouseEvent evt)
327	{
328		dragged = true;
329
330		TextAreaPainter painter = textArea.getPainter();
331
332		int x = evt.getX();
333		int y = evt.getY();
334		if(y < 0)
335			y = 0;
336		else if(y >= painter.getHeight())
337			y = painter.getHeight() - 1;
338
339		int dot = textArea.xyToOffset(x,y,
340			(!painter.isBlockCaretEnabled()
341			&& !textArea.isOverwriteEnabled())
342			|| quickCopyDrag);
343		int dotLine = textArea.getLineOfOffset(dot);
344		int extraEndVirt = 0;
345
346		if(textArea.chunkCache.getLineInfo(
347			textArea.getLastScreenLine())
348			.lastSubregion)
349		{
350			float dotLineWidth = textArea.offsetToXY(
351				dotLine,textArea.getLineLength(dotLine)).x;
352			if(x > dotLineWidth)
353			{
354				extraEndVirt = (int)((x - dotLineWidth) / textArea.charWidth);
355				if(!painter.isBlockCaretEnabled()
356					&& !textArea.isOverwriteEnabled()
357					&& (x - textArea.getHorizontalOffset()) % textArea.charWidth > textArea.charWidth / 2)
358					extraEndVirt++;
359			}
360		}
361
362		textArea.resizeSelection(dragStart,dot,extraEndVirt,
363			textArea.isRectangularSelectionEnabled()
364			|| control);
365
366		if(quickCopyDrag)
367		{
368			// just scroll to the dragged location
369			textArea.scrollTo(dotLine,dot - textArea.getLineStartOffset(dotLine),false);
370		}
371		else
372		{
373			if(dot != textArea.getCaretPosition())
374				textArea.moveCaretPosition(dot,false);
375			if(textArea.isRectangularSelectionEnabled()
376				&& extraEndVirt != 0)
377			{
378				textArea.scrollTo(dotLine,dot - textArea.getLineStartOffset(dotLine)
379					+ extraEndVirt,false);
380			}
381		}
382	} //}}}
383
384	//{{{ doDoubleDrag() method
385	private void doDoubleDrag(MouseEvent evt)
386	{
387		int markLineStart = textArea.getLineStartOffset(dragStartLine);
388		int markLineLength = textArea.getLineLength(dragStartLine);
389		int mark = dragStartOffset;
390
391		TextAreaPainter painter = textArea.getPainter();
392
393		int pos = textArea.xyToOffset(evt.getX(),
394			Math.max(0,Math.min(painter.getHeight(),evt.getY())),
395			!(painter.isBlockCaretEnabled()
396			|| textArea.isOverwriteEnabled()));
397		int line = textArea.getLineOfOffset(pos);
398		int lineStart = textArea.getLineStartOffset(line);
399		int lineLength = textArea.getLineLength(line);
400		int offset = pos - lineStart;
401
402		String lineText = textArea.getLineText(line);
403		String markLineText = textArea.getLineText(dragStartLine);
404		String noWordSep = textArea.getBuffer()
405			.getStringProperty("noWordSep");
406		boolean joinNonWordChars = textArea.getJoinNonWordChars();
407
408		if(markLineStart + dragStartOffset > lineStart + offset)
409		{
410			if(offset != 0 && offset != lineLength)
411			{
412				offset = TextUtilities.findWordStart(
413					lineText,offset,noWordSep,
414					joinNonWordChars);
415			}
416
417			if(markLineLength != 0)
418			{
419				mark = TextUtilities.findWordEnd(
420					markLineText,mark,noWordSep,
421					joinNonWordChars);
422			}
423		}
424		else
425		{
426			if(offset != 0 && lineLength != 0)
427			{
428				offset = TextUtilities.findWordEnd(
429					lineText,offset,noWordSep,
430					joinNonWordChars);
431			}
432
433			if(mark != 0 && mark != markLineLength)
434			{
435				mark = TextUtilities.findWordStart(
436					markLineText,mark,noWordSep,
437					joinNonWordChars);
438			}
439		}
440
441		if(lineStart + offset == textArea.getCaretPosition())
442			return;
443
444		textArea.resizeSelection(markLineStart + mark,
445			lineStart + offset,0,false);
446		textArea.moveCaretPosition(lineStart + offset,false);
447
448		dragged = true;
449	} //}}}
450
451	//{{{ doTripleDrag() method
452	private void doTripleDrag(MouseEvent evt)
453	{
454		TextAreaPainter painter = textArea.getPainter();
455		
456		int offset = textArea.xyToOffset(evt.getX(),
457			Math.max(0,Math.min(painter.getHeight(),evt.getY())),
458			false);
459		int mouseLine = textArea.getLineOfOffset(offset);
460		int mark;
461		int mouse;
462		if(dragStartLine > mouseLine)
463		{
464			mark = textArea.getLineEndOffset(dragStartLine) - 1;
465			if(offset == textArea.getLineEndOffset(mouseLine) - 1)
466				mouse = offset;
467			else
468				mouse = textArea.getLineStartOffset(mouseLine);
469		}
470		else
471		{
472			mark = textArea.getLineStartOffset(dragStartLine);
473			if(offset == textArea.getLineStartOffset(mouseLine))
474				mouse = offset;
475			else if(offset == textArea.getLineEndOffset(mouseLine) - 1
476				&& mouseLine != textArea.getLineCount() - 1)
477				mouse = textArea.getLineEndOffset(mouseLine);
478			else
479				mouse = textArea.getLineEndOffset(mouseLine) - 1;
480		}
481
482		mouse = Math.min(textArea.getBuffer().getLength(),mouse);
483
484		if(mouse == textArea.getCaretPosition())
485			return;
486
487		textArea.resizeSelection(mark,mouse,0,false);
488		textArea.moveCaretPosition(mouse,false);
489
490		dragged = true;
491	} //}}}
492
493	//{{{ mouseReleased() method
494	public void mouseReleased(MouseEvent evt)
495	{
496		// middle mouse button drag inserts selection
497		// at caret position
498		Selection sel = textArea.getSelectionAtOffset(dragStart);
499		if(dragged && sel != null)
500		{
501			Registers.setRegister('%',textArea.getSelectedText(sel));
502			if(quickCopyDrag)
503			{
504				textArea.removeFromSelection(sel);
505				Registers.paste(JEditTextArea.focusedComponent,
506					'%',sel instanceof Selection.Rect);
507
508				JEditTextArea.focusedComponent.requestFocus();
509			}
510		}
511		else if(!dragged && textArea.isQuickCopyEnabled() &&
512			GUIUtilities.isMiddleButton(evt.getModifiers()))
513		{
514			textArea.requestFocus();
515			JEditTextArea.focusedComponent = textArea;
516
517			textArea.setCaretPosition(dragStart,false);
518			if(!textArea.isEditable())
519				textArea.getToolkit().beep();
520			else
521				Registers.paste(textArea,'%',control);
522		}
523		else if(maybeDragAndDrop
524			&& !textArea.isMultipleSelectionEnabled())
525		{
526			textArea.selectNone();
527		}
528
529		dragged = false;
530	} //}}}
531
532	//{{{ Private members
533	private JEditTextArea textArea;
534	private int dragStartLine;
535	private int dragStartOffset;
536	private int dragStart;
537	private int clickCount;
538	private boolean dragged;
539	private boolean quickCopyDrag;
540	private boolean control;
541	/* with drag and drop on, a mouse down in a selection does not
542	immediately deselect */
543	private boolean maybeDragAndDrop;
544	
545	//{{{ showCursor() method
546	private void showCursor()
547	{
548		textArea.getPainter().setCursor(
549			Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
550	} //}}}
551
552	//}}}
553}