📄 rtextarea.java
字号:
* from the caret position. If a match is found, it is selected in this
* text area.
*
* @param text The string literal or regular expression to search for.
* @param forward Whether to search forward from the caret position or
* backward from it.
* @param matchCase Whether the search should be case-sensitive.
* @param wholeWord Whether there should be spaces or tabs on either side
* of the match.
* @param regex Whether <code>text</code> is a Java regular expression to
* search for.
* @return Whether a match was found (and thus selected).
*/
public boolean find(String text, boolean forward, boolean matchCase,
boolean wholeWord, boolean regex) {
// Be smart about what position we're "starting" at. For example,
// if they are searching backwards and there is a selection such that
// the dot is past the mark, and the selection is the text for which
// you're searching, this search will find and return the current
// selection. So, in that case we start at the beginning of the
// selection.
Caret c = getCaret();
int caretPosition = c.getDot();
int start = (!forward && (c.getDot() != c.getMark())) ?
getSelectionStart() : caretPosition;
// Be smart about the text we grab to search in. We grab more than
// a single line because our searches can return multiline results.
// We copy only the chars that will be searched through.
String findIn = null;
if (forward) {
try {
findIn = getText(start, getDocument().getLength() - start);
}
catch (BadLocationException ble) {
ble.printStackTrace();
return false;
}
start = 0;
}
else { // backward
try {
findIn = getText(0, start + 1);
}
catch (BadLocationException ble) {
ble.printStackTrace();
return false;
}
}
// Find the next location of the text we're searching for. If we're
// looking for a regular expression, the returned match has a
// possibly varying width, so we return its start and end positions
// in a Point.
int pos = -1;
java.awt.Point regExPos = null;
if (regex == false) {
pos = FindDialog.getNextMatchPos(text, findIn, start,
forward, matchCase, wholeWord);
}
else {
regExPos = FindDialog.getNextMatchPosRegEx(text, findIn, start,
forward, matchCase, wholeWord);
}
findIn = null; // May help garbage collecting.
// If a match was found, select it and return!
if (pos != -1) {
// Without this, if JTextArea isn't in focus, selection won't
// appear selected.
c.setSelectionVisible(true);
pos = forward ? caretPosition + pos : pos;
c.setDot(pos);
c.moveDot(pos + text.length());
return true;
}
else if (regExPos != null) {
// Without this, if JTextArea isn't in focus, selection won't
// appear selected.
c.setSelectionVisible(true);
if (forward) {
regExPos.translate(caretPosition, caretPosition);
}
c.setDot(regExPos.x);
c.moveDot(regExPos.y);
return true;
}
// No match.
return false;
}
/*****************************************************************************/
/**
* Notifies all listeners that a caret change has occured.
*
* @param e The caret event.
*/
protected void fireCaretUpdate(CaretEvent e) {
// Decide whether we need to repaint the current line background.
possiblyUpdateCurrentLineHighlightLocation();
// Now, if there is a highlighted region of text, allow them to cut
// and copy.
if (e != null && e.getDot() != e.getMark()) { // && !cutAction.isEnabled()) {
cutAction.setEnabled(true);
copyAction.setEnabled(true);
}
// Otherwise, if there is no highlighted region, don't let them cut
// or copy. The condition here should speed things up, because this
// way, we will only enable the actions the first time the selection
// becomes nothing.
else if (cutAction.isEnabled() == true) {
cutAction.setEnabled(false);
copyAction.setEnabled(false);
}
super.fireCaretUpdate(e);
}
/*****************************************************************************/
/**
* Removes the "Ctrl+H <=> Backspace" behavior that Java shows, for some
* odd reason...
*/
private void fixCtrlH() {
InputMap inputMap = getInputMap();
KeyStroke char010 = KeyStroke.getKeyStroke("typed \010");
InputMap parent = inputMap;
while (parent != null) {
parent.remove(char010);
parent = parent.getParent();
}
KeyStroke backspace = KeyStroke.getKeyStroke("BACK_SPACE");
inputMap.put(backspace, DefaultEditorKit.deletePrevCharAction);
}
/*****************************************************************************/
/**
* Provides a way to gain access to the editor actions on the right-click
* popup menu. This way you can make toolbar/menu bar items use the actual
* actions used by all <code>RTextArea</code>s, so that icons stay
* synchronized and you don't have to worry about enabling/disabling them
* yourself.<p>
* Keep in mind that these actions are shared across all instances of
* <code>RTextArea</code>, so a change to any action returned by this
* method is global across all <code>RTextArea</code> editors in your
* application.
*
* @param action The action to retrieve, such as <code>CUT_ACTION</code>.
* If the action name is invalid, <code>null</code> is
* returned.
* @return The action, or <code>null</code> if an invalid action is
* requested.
*/
public static RecordableTextAction getAction(int action) {
if (action < MIN_ACTION_CONSTANT || action > MAX_ACTION_CONSTANT) {
return null;
}
switch (action) {
case CUT_ACTION:
return cutAction;
case COPY_ACTION:
return copyAction;
case PASTE_ACTION:
return pasteAction;
case DELETE_ACTION:
return deleteAction;
case UNDO_ACTION:
return undoAction;
case REDO_ACTION:
return redoAction;
case SELECT_ALL_ACTION:
return selectAllAction;
}
return null;
}
/*****************************************************************************/
/**
* Returns the macro currently stored in this <code>RTextArea</code>.
* Since macros are shared, all <code>RTextArea</code>s in the currently-
* running application are using this macro.
*
* @return The current macro, or <code>null</code> if no macro has been
* recorded/loaded.
* @see #loadMacro
*/
public static synchronized Macro getCurrentMacro() {
return currentMacro;
}
/*****************************************************************************/
/**
* Returns the default color used for "mark all."
*
* @return The color.
* @see #getMarkAllHighlightColor
* @see #setMarkAllHighlightColor
*/
public static final Color getDefaultMarkAllHighlightColor() {
return DEFAULT_MARK_ALL_COLOR;
}
/*****************************************************************************/
/**
* Returns the icon group being used for the actions of this text area.
*
* @return The icon group.
* @see #setIconGroup
*/
public static IconGroup getIconGroup() {
return iconGroup;
}
/*****************************************************************************/
/**
* Returns the color used in "mark all."
*
* @return The color.
* @see #setMarkAllHighlightColor
*/
public Color getMarkAllHighlightColor() {
return (Color) markAllHighlightPainter.getPaint();
}
/*****************************************************************************/
/**
* Returns the maximum ascent of all fonts used in this text area. In
* the case of a standard <code>RTextArea</code>, this is simply the
* ascent of the current font.<p>
*
* This value could be useful, for example, to implement a line-numbering
* scheme.
*
* @return The ascent of the current font.
*/
public int getMaxAscent() {
return getFontMetrics(getFont()).getAscent();
}
/*****************************************************************************/
/**
* Returns the text mode this editor pane is currently in.
*
* @return Either <code>RTextArea.INSERT_MODE</code> or
* <code>RTextArea.OVERWRITE_MODE</code>.
*/
public final int getTextMode() {
return textMode;
}
/*****************************************************************************/
/**
* Does the actual dirtywork of replacing the selected text in this
* text area (i.e., in its document). This method provides a hook for
* subclasses to handle this in a different way.
*
* @param content The content to add.
*/
protected void handleReplaceSelection(String content) {
Document doc = getDocument();
if (doc != null) {
try {
Caret c = getCaret();
int dot = c.getDot();
int mark = c.getMark();
int p0 = Math.min(dot, mark);
int p1 = Math.max(dot, mark);
( (RTextAreaDocument) doc).replace(p0, p1 - p0,
content, null);
}
catch (BadLocationException e) {
UIManager.getLookAndFeel().
provideErrorFeedback(RTextArea.this);
}
}
}
/*****************************************************************************/
private static boolean first = false;
/**
* Creates and localizes our shared actions.
*
* @param ta The text area being created.
*/
private static final synchronized void initActions(RTextArea ta) {
// We only need to initialize the actions for the first created
// text area, since they're shared among all text areas.
if (!first) {
first = true;
ResourceBundle bundle = ResourceBundle.getBundle(RESOURCE_BUNDLE);
cantUndoText = bundle.getString("CantUndo");
cantRedoText = bundle.getString("CantRedo");
// Create actions for right-click popup menu.
// 1.5.2004/pwy: Replaced the CTRL_MASK with the cross-platform version...
int defaultModifier = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
String name = bundle.getString("CutActionName");
char mnemonic = bundle.getString("CutActionMnemonic").charAt(0);
cutAction = new RTextAreaEditorKit.CutAction(name, null, name,
new Integer(mnemonic),
KeyStroke.getKeyStroke(KeyEvent.VK_X, defaultModifier));
name = bundle.getString("CopyActionName");
mnemonic = bundle.getString("CopyActionMnemonic").charAt(0);
copyAction = new RTextAreaEditorKit.CopyAction(name, null, name,
new Integer(mnemonic),
KeyStroke.getKeyStroke(KeyEvent.VK_C, defaultModifier));
name = bundle.getString("PasteActionName");
mnemonic = bundle.getString("PasteActionMnemonic").charAt(0);
pasteAction = new RTextAreaEditorKit.PasteAction(name, null, name,
new Integer(mnemonic),
KeyStroke.getKeyStroke(KeyEvent.VK_V, defaultModifier));
name = bundle.getString("DeleteActionName");
mnemonic = bundle.getString("DeleteActionMnemonic").charAt(0);
deleteAction = new RTextAreaEditorKit.DeleteNextCharAction(name, null,
name,
new Integer(mnemonic), KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
undoAction = new RTextAreaEditorKit.UndoAction(cantUndoText, null, "Undo",
new Integer(KeyEvent.VK_Z),
KeyStroke.getKeyStroke(KeyEvent.VK_Z, defaultModifier));
redoAction = new RTextAreaEditorKit.RedoAction(cantRedoText, null, "Redo",
new Integer(KeyEvent.VK_Y),
KeyStroke.getKeyStroke(KeyEvent.VK_Y, defaultModifier));
name = bundle.getString("SAActionName");
mnemonic = bundle.getString("SAActionMnemonic").charAt(0);
selectAllAction = new RTextAreaEditorKit.SelectAllAction(name, null, name,
new Integer(mnemonic),
KeyStroke.getKeyStroke(KeyEvent.VK_A, defaultModifier));
bundle = null;
} // End of if (!first).
}
/*****************************************************************************/
/**
* Returns whether or not RText is in the middle of an undo or redo
* operation. This method is package-private so that
* <code>ConfigurableCaret</code> can know whether an insert or
* removal is part of an undo or redo. This method is also a giant HACK
* to get around the fact that there is no way for a Caret to know that
* an event is coming from an undo/redo unless the DocumentEvent passed
* to it says so. In J2SE5.0, DefaultCaret knows because the event is of
* type UndoRedoDocumentEvent, but that class is (of course) package-
* private, so we can't get to it. So we work around it by having the
* caret poll the text area directly.
*
*@return Whether the text area is currently doing an undo or redo.
*/
boolean inUndoRedo() {
return inUndoRedo;
}
/*****************************************************************************/
/**
* Returns whether or not a macro is being recorded.
*
* @return Whether or not a macro is being recorded.
* @see #beginRecordingMacro
* @see #endRecordingMacro
*/
public static synchronized boolean isRecordingMacro() {
return recordingMacro;
}
/*****************************************************************************/
/**
* Loads a macro to be used by all <code>RTextArea</code>s in the current
* application.
*
* @param macro The macro to load.
* @see #getCurrentMacro
*/
public static synchronized void loadMacro(Macro macro) {
currentMacro = macro;
}
/*****************************************************************************/
/**
* Marks all instances of the specified text in this text area.
*
* @param toMark The text to mark.
* @param matchCase Whether the match should be case-sensitive.
* @param wholeWord Whether the matches should be surrounded by spaces or
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -