📄 jedittextarea.java
字号:
boolean newBias;
if(start <= end)
{
newStart = start;
newEnd = end;
newBias = false;
}
else
{
newStart = end;
newEnd = start;
newBias = true;
}
if(newStart < 0 || newEnd > getDocumentLength())
{
throw new IllegalArgumentException("Bounds out of"
+ " range: " + newStart + "," +
newEnd);
}
// If the new position is the same as the old, we don't
// do all this crap, however we still do the stuff at
// the end (clearing magic position, scrolling)
if(newStart != selectionStart || newEnd != selectionEnd
|| newBias != biasLeft)
{
int newStartLine = getLineOfOffset(newStart);
int newEndLine = getLineOfOffset(newEnd);
if(painter.isBracketHighlightEnabled())
{
if(bracketLine != -1)
painter.invalidateLine(bracketLine);
updateBracketHighlight(end);
if(bracketLine != -1)
painter.invalidateLine(bracketLine);
}
painter.invalidateLineRange(selectionStartLine,selectionEndLine);
painter.invalidateLineRange(newStartLine,newEndLine);
document.addUndoableEdit(new CaretUndo(
selectionStart,selectionEnd));
selectionStart = newStart;
selectionEnd = newEnd;
selectionStartLine = newStartLine;
selectionEndLine = newEndLine;
biasLeft = newBias;
fireCaretEvent();
}
// When the user is typing, etc, we don't want the caret
// to blink
blink = true;
caretTimer.restart();
// Disable rectangle select if selection start = selection end
if(selectionStart == selectionEnd)
rectSelect = false;
// Clear the `magic' caret position used by up/down
magicCaret = -1;
scrollToCaret();
}
/**
* Returns the selected text, or null if no selection is active.
*/
public final String getSelectedText()
{
if(selectionStart == selectionEnd)
return null;
if(rectSelect)
{
// Return each row of the selection on a new line
Element map = document.getDefaultRootElement();
int start = selectionStart - map.getElement(selectionStartLine)
.getStartOffset();
int end = selectionEnd - map.getElement(selectionEndLine)
.getStartOffset();
// Certain rectangles satisfy this condition...
if(end < start)
{
int tmp = end;
end = start;
start = tmp;
}
StringBuffer buf = new StringBuffer();
Segment seg = new Segment();
for(int i = selectionStartLine; i <= selectionEndLine; i++)
{
Element lineElement = map.getElement(i);
int lineStart = lineElement.getStartOffset();
int lineEnd = lineElement.getEndOffset() - 1;
int lineLen = lineEnd - lineStart;
lineStart = Math.min(lineStart + start,lineEnd);
lineLen = Math.min(end - start,lineEnd - lineStart);
getText(lineStart,lineLen,seg);
buf.append(seg.array,seg.offset,seg.count);
if(i != selectionEndLine)
buf.append('\n');
}
return buf.toString();
}
else
{
return getText(selectionStart,
selectionEnd - selectionStart);
}
}
/**
* Replaces the selection with the specified text.
* @param selectedText The replacement text for the selection
*/
public void setSelectedText(String selectedText)
{
if(!editable)
{
throw new InternalError("Text component"
+ " read only");
}
document.beginCompoundEdit();
try
{
if(rectSelect)
{
Element map = document.getDefaultRootElement();
int start = selectionStart - map.getElement(selectionStartLine)
.getStartOffset();
int end = selectionEnd - map.getElement(selectionEndLine)
.getStartOffset();
// Certain rectangles satisfy this condition...
if(end < start)
{
int tmp = end;
end = start;
start = tmp;
}
int lastNewline = 0;
int currNewline = 0;
for(int i = selectionStartLine; i <= selectionEndLine; i++)
{
Element lineElement = map.getElement(i);
int lineStart = lineElement.getStartOffset();
int lineEnd = lineElement.getEndOffset() - 1;
int rectStart = Math.min(lineEnd,lineStart + start);
document.remove(rectStart,Math.min(lineEnd - rectStart,
end - start));
if(selectedText == null)
continue;
currNewline = selectedText.indexOf('\n',lastNewline);
if(currNewline == -1)
currNewline = selectedText.length();
document.insertString(rectStart,selectedText
.substring(lastNewline,currNewline),null);
lastNewline = Math.min(selectedText.length(),
currNewline + 1);
}
if(selectedText != null &&
currNewline != selectedText.length())
{
int offset = map.getElement(selectionEndLine)
.getEndOffset() - 1;
document.insertString(offset,"\n",null);
document.insertString(offset + 1,selectedText
.substring(currNewline + 1),null);
}
}
else
{
document.remove(selectionStart,
selectionEnd - selectionStart);
if(selectedText != null)
{
document.insertString(selectionStart,
selectedText,null);
}
}
}
catch(BadLocationException bl)
{
bl.printStackTrace();
throw new InternalError("Cannot replace"
+ " selection");
}
// No matter what happends... stops us from leaving document
// in a bad state
finally
{
document.endCompoundEdit();
}
setCaretPosition(selectionEnd);
}
/**
* Returns true if this text area is editable, false otherwise.
*/
public final boolean isEditable()
{
return editable;
}
/**
* Sets if this component is editable.
* @param editable True if this text area should be editable,
* false otherwise
*/
public final void setEditable(boolean editable)
{
this.editable = editable;
}
/**
* Returns the right click popup menu.
*/
public final JPopupMenu getRightClickPopup()
{
return popup;
}
/**
* Sets the right click popup menu.
* @param popup The popup
*/
public final void setRightClickPopup(JPopupMenu popup)
{
this.popup = popup;
}
/**
* Returns the `magic' caret position. This can be used to preserve
* the column position when moving up and down lines.
*/
public final int getMagicCaretPosition()
{
return magicCaret;
}
/**
* Sets the `magic' caret position. This can be used to preserve
* the column position when moving up and down lines.
* @param magicCaret The magic caret position
*/
public final void setMagicCaretPosition(int magicCaret)
{
this.magicCaret = magicCaret;
}
/**
* Similar to <code>setSelectedText()</code>, but overstrikes the
* appropriate number of characters if overwrite mode is enabled.
* @param str The string
* @see #setSelectedText(String)
* @see #isOverwriteEnabled()
*/
public void overwriteSetSelectedText(String str)
{
// Don't overstrike if there is a selection
if(!overwrite || selectionStart != selectionEnd)
{
setSelectedText(str);
return;
}
// Don't overstrike if we're on the end of
// the line
int caret = getCaretPosition();
int caretLineEnd = getLineEndOffset(getCaretLine());
if(caretLineEnd - caret <= str.length())
{
setSelectedText(str);
return;
}
document.beginCompoundEdit();
try
{
document.remove(caret,str.length());
document.insertString(caret,str,null);
}
catch(BadLocationException bl)
{
bl.printStackTrace();
}
finally
{
document.endCompoundEdit();
}
}
/**
* Returns true if overwrite mode is enabled, false otherwise.
*/
public final boolean isOverwriteEnabled()
{
return overwrite;
}
/**
* Sets if overwrite mode should be enabled.
* @param overwrite True if overwrite mode should be enabled,
* false otherwise.
*/
public final void setOverwriteEnabled(boolean overwrite)
{
this.overwrite = overwrite;
painter.invalidateSelectedLines();
}
/**
* Returns true if the selection is rectangular, false otherwise.
*/
public final boolean isSelectionRectangular()
{
return rectSelect;
}
/**
* Sets if the selection should be rectangular.
* @param overwrite True if the selection should be rectangular,
* false otherwise.
*/
public final void setSelectionRectangular(boolean rectSelect)
{
this.rectSelect = rectSelect;
painter.invalidateSelectedLines();
}
/**
* Returns the position of the highlighted bracket (the bracket
* matching the one before the caret)
*/
public final int getBracketPosition()
{
return bracketPosition;
}
/**
* Returns the line of the highlighted bracket (the bracket
* matching the one before the caret)
*/
public final int getBracketLine()
{
return bracketLine;
}
/**
* Adds a caret change listener to this text area.
* @param listener The listener
*/
public final void addCaretListener(CaretListener listener)
{
listenerList.add(CaretListener.class,listener);
}
/**
* Removes a caret change listener from this text area.
* @param listener The listener
*/
public final void removeCaretListener(CaretListener listener)
{
listenerList.remove(CaretListener.class,listener);
}
/**
* Deletes the selected text from the text area and places it
* into the clipboard.
*/
public void cut()
{
if(editable)
{
copy();
setSelectedText("");
}
}
/**
* Places the selected text into the clipboard.
*/
public void copy()
{
if(selectionStart != selectionEnd)
{
Clipboard clipboard = getToolkit().getSystemClipboard();
String selection = getSelectedText();
int repeatCount = inputHandler.getRepeatCount();
StringBuffer buf = new StringBuffer();
for(int i = 0; i < repeatCount; i++)
buf.append(selection);
clipboard.setContents(new StringSelection(buf.toString()),null);
}
}
/**
* Inserts the clipboard contents into the text.
*/
public void paste()
{
if(editable)
{
Clipboard clipboard = getToolkit().getSystemClipboard();
try
{
// The MacOS MRJ doesn't convert \r to \n,
// so do it here
String selection = ((String)clipboard
.getContents(this).getTransferData(
DataFlavor.stringFlavor))
.replace('\r','\n');
int repeatCount = inputHandler.getRepeatCount();
StringBuffer buf = new StringBuffer();
for(int i = 0; i < repeatCount; i++)
buf.append(selection);
selection = buf.toString();
setSelectedText(selection);
}
catch(Exception e)
{
getToolkit().beep();
//System.err.println("Clipboard does not" + " contain a string");
}
}
}
/**
* Called by the AWT when this component is removed from it's parent.
* This stops clears the currently focused component.
*/
public void removeNotify()
{
super.removeNotify();
if(focusedComponent == this)
focusedComponent = null;
}
/**
* Forwards key events directly to the input handler.
* This is slightly faster than using a KeyListener
* because some Swing overhead is avoided.
*/
public void processKeyEvent(KeyEvent evt)
{
if(inputHandler == null)
return;
switch(evt.getID())
{
case KeyEvent.KEY_TYPED:
inputHandler.keyTyped(evt);
break;
case KeyEvent.KEY_PRESSED:
inputHandler.keyPressed(evt);
break;
case KeyEvent.KEY_RELEASED:
inputHandler.keyReleased(evt);
break;
}
}
// protected members
protected static String CENTER = "center";
protected static String RIGHT = "right";
protected static String BOTTOM = "bottom";
public static JEditTextArea focusedComponent;
protected static Timer caretTimer;
protected TextAreaPainter painter;
protected JPopupMenu popup;
protected EventListenerList listenerList;
protected MutableCaretEvent caretEvent;
protected boolean caretBlinks;
protected boolean caretVisible;
protected boolean blink;
protected boolean editable;
protected int firstLine;
protected int visibleLines;
protected int electricScroll;
protected int horizontalOffset;
protected JScrollBar vertical;
protected JScrollBar horizontal;
protected boolean scrollBarsInitialized;
protected InputHandler inputHandler;
protected SyntaxDocument document;
protected DocumentHandler documentHandler;
protected Segment lineSegment;
protected int selectionStart;
protected int selectionStartLine;
protected int selectionEnd;
protected int selectionEndLine;
protected boolean biasLeft;
protected int bracketPosition;
protected int bracketLine;
protected int magicCaret;
protected boolean overwrite;
protected boolean rectSelect;
protected void fireCaretEvent()
{
Object[] listeners = listenerList.getListenerList();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -