TextComponents: triple-click-and-drag now extends selection by whole lines

triple-click-and-drag does not work in theme editor because drag is enabled, anyway a triple-click now selects the whole line before dragging starts
This commit is contained in:
Karl Tauber
2021-10-22 13:14:01 +02:00
parent e13fb25f14
commit 8fa1eae352
5 changed files with 165 additions and 70 deletions

View File

@@ -18,12 +18,16 @@ package com.formdev.flatlaf.themeeditor;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.JTextComponent;
import javax.swing.text.Utilities;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaUI;
@@ -70,59 +74,83 @@ class FlatRSyntaxTextAreaUI
extends ConfigurableCaret
{
private boolean isWordSelection;
private int beginInitialWord;
private int endInitialWord;
private boolean isLineSelection;
private int dragSelectionStart;
private int dragSelectionEnd;
@Override
public void mousePressed( MouseEvent e ) {
super.mousePressed( e );
JTextComponent c = getComponent();
// left double-click starts word selection
isWordSelection = e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) && !e.isConsumed();
if( isWordSelection ) {
beginInitialWord = getMark();
endInitialWord = getDot();
// left triple-click starts line selection
isLineSelection = e.getClickCount() == 3 && SwingUtilities.isLeftMouseButton( e ) && (!e.isConsumed() || c.getDragEnabled());
// select line
// (this is also done in DefaultCaret.mouseClicked(), but this event is
// sent when the mouse is released, which is too late for triple-click-and-drag)
if( isLineSelection ) {
ActionMap actionMap = c.getActionMap();
Action selectLineAction = (actionMap != null)
? actionMap.get( DefaultEditorKit.selectLineAction )
: null;
if( selectLineAction != null ) {
selectLineAction.actionPerformed( new ActionEvent( c,
ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers() ) );
}
}
// remember selection where word/line selection starts to keep it always selected while dragging
if( isWordSelection || isLineSelection ) {
int mark = getMark();
int dot = getDot();
dragSelectionStart = Math.min( dot, mark );
dragSelectionEnd = Math.max( dot, mark );
}
}
@Override
public void mouseReleased( MouseEvent e ) {
isWordSelection = false;
isLineSelection = false;
super.mouseReleased( e );
}
@Override
public void mouseDragged( MouseEvent e ) {
if( isWordSelection && !e.isConsumed() && SwingUtilities.isLeftMouseButton( e ) ) {
// fix Swing's double-click-and-drag behavior so that dragging after
// a double-click extends selection by whole words
if( (isWordSelection || isLineSelection) &&
!e.isConsumed() && SwingUtilities.isLeftMouseButton( e ) )
{
// fix Swing's double/triple-click-and-drag behavior so that dragging after
// a double/triple-click extends selection by whole words/lines
JTextComponent c = getComponent();
int pos = c.viewToModel( e.getPoint() );
if( pos < 0 )
return;
try {
int mark;
int dot;
if( pos > endInitialWord ) {
mark = beginInitialWord;
dot = Utilities.getWordEnd( c, pos );
} else if( pos < beginInitialWord ) {
mark = endInitialWord;
dot = Utilities.getWordStart( c, pos );
} else {
mark = beginInitialWord;
dot = endInitialWord;
}
if( mark != getMark() )
setDot( mark );
if( dot != getDot() )
moveDot( dot );
if( pos > dragSelectionEnd )
select( dragSelectionStart, isWordSelection ? Utilities.getWordEnd( c, pos ) : Utilities.getRowEnd( c, pos ) );
else if( pos < dragSelectionStart )
select( dragSelectionEnd, isWordSelection ? Utilities.getWordStart( c, pos ) : Utilities.getRowStart( c, pos ) );
else
select( dragSelectionStart, dragSelectionEnd );
} catch( BadLocationException ex ) {
UIManager.getLookAndFeel().provideErrorFeedback( c );
}
} else
super.mouseDragged( e );
}
private void select( int mark, int dot ) {
if( mark != getMark() )
setDot( mark );
if( dot != getDot() )
moveDot( dot );
}
}
}