📄 richbox.java
字号:
caretLine = content.getLineAtOffset(caretOffset);
if (caretLine < lineCount - 1) {
GC gc = getGC();
int verticalMaximum = contentHelper.getHeightOfLines(gc, 0, lineCount);
int pageSize = clientAreaHeight - topMargin - bottomMargin;
int scrollLines = Math.min(lineCount - caretLine - 1, getFullVisibleLineCount());
scrollLines = Math.max(1, scrollLines);
caretLine += scrollLines;
caretOffset = contentHelper.getOffsetAtX(gc, caretLine, columnX);
if(pageSize > verticalMaximum)
showCaret();
else
setVerticalScrollOffset(contentHelper.getHeightOfLines(gc, 0, caretLine), true);
releaseGC();
}
// 显示光标
showCaret(caretLine);
columnX = oldColumnX;
}
/**
* 上翻一页,保持光标X位置不变。上翻页将光标减掉view中的全部可见行数。
*/
private void doPageUp() {
int oldColumnX = columnX;
int caretLine = content.getLineAtOffset(caretOffset);
// 如果当前光标所在的行大于0,上翻一页
if (caretLine > 0) {
GC gc = getGC();
int scrollLines = Math.max(1, Math.min(caretLine, getFullVisibleLineCount()));
int scrollOffset;
caretLine -= scrollLines;
caretOffset = contentHelper.getOffsetAtX(gc, caretLine, columnX);
setVerticalScrollOffset(contentHelper.getHeightOfLines(gc, 0, caretLine), true);
releaseGC();
}
// 显示光标
showCaret(caretLine);
columnX = oldColumnX;
}
/**
* @return
* 返回窗口中完全可见行的行数
*/
private int getFullVisibleLineCount() {
GC gc = getGC();
int fullVisibleBottomLine = getFullVisibleBottomLine(gc);
int fullVisibleTopLine = topLine;
if(contentHelper.getHeightOfLines(gc, 0, fullVisibleTopLine) - verticalScrollOffset < 0)
fullVisibleTopLine++;
releaseGC();
int lineCount = fullVisibleBottomLine - fullVisibleTopLine + 1;
if(lineCount < 0)
return 0;
else
return lineCount;
}
/**
* 光标置于最后
*/
private void doTextEnd() {
if(caretOffset < content.getCharCount()) {
caretOffset = content.getCharCount();
showCaret();
}
}
/**
* 光标置于最开头
*/
private void doTextStart() {
if(caretOffset != 0) {
caretOffset = 0;
showCaret();
}
}
/**
* 将光标置于行结尾
*/
private void doLineEnd() {
int caretLine = content.getLineAtOffset(caretOffset);
int lineOffset = content.getLineStartOffset(caretLine);
int lineLength = content.getLine(caretLine).length();
int lineEndOffset = lineOffset + lineLength;
if (caretOffset < lineEndOffset) {
caretOffset = lineEndOffset;
showCaret();
}
}
/**
* 将光标置于行开始
*/
private void doLineStart() {
int caretLine = content.getLineAtOffset(caretOffset);
int lineOffset = content.getLineStartOffset(caretLine);
if (caretOffset > lineOffset) {
caretOffset = lineOffset;
showCaret(caretLine);
}
}
/**
*如果存在被选择区,则把光标放置到被选择区结束,否则简单移动
* <p>
*
* @see #doSimpleCaretRigth
*/
private void doCaretRight() {
if (selectionEnd > selectionStart) {
int caretLine;
caretOffset = selectionEnd;
caretLine = content.getLineAtOffset(caretOffset);
showCaret(caretLine);
} else {
doSimpleCaretRigth();
}
}
/**
* 往后移动光标一格,如果光标在一行的末尾,则要置光标到下一行的开头,如果后面是个图片,
* 要注意移动两个位置
*/
private void doSimpleCaretRigth() {
int caretLine = content.getLineAtOffset(caretOffset);
int lineOffset = content.getLineStartOffset(caretLine);
int offsetInLine = caretOffset - lineOffset;
if (offsetInLine < content.getLine(caretLine).length()) {
if(content.isImageTag(caretOffset))
caretOffset++;
caretOffset++;
showCaret();
} else if (caretLine < content.getLineCount() - 1) {
caretLine++;
caretOffset = content.getLineStartOffset(caretLine);
showCaret(caretLine);
}
}
/**
* 如果存在被选择区,则把光标放置到被选择区开始,否则简单移动
* <p>
*
* @see #doSimpleCaretLeft
*/
private void doCaretLeft() {
if (selectionEnd > selectionStart) {
int caretLine;
caretOffset = selectionStart;
caretLine = content.getLineAtOffset(caretOffset);
showCaret(caretLine);
} else {
doSimpleCaretLeft();
}
}
/**
* 往前移动光标一格,如果光标在一行的开头,则要置光标到上一行的末尾,如果前面是个图片,
* 要注意移动两个位置
*/
private void doSimpleCaretLeft() {
int caretLine = content.getLineAtOffset(caretOffset);
int lineOffset = content.getLineStartOffset(caretLine);
int offsetInLine = caretOffset - lineOffset;
if (offsetInLine > 0) {
caretOffset--;
if(content.isImageTag(caretOffset - 1))
caretOffset--;
showCaret(caretLine);
} else if (caretLine > 0) {
caretLine--;
lineOffset = content.getLineStartOffset(caretLine);
int newCaretOffset = lineOffset + content.getLine(caretLine).length();
if(newCaretOffset == caretOffset)
caretOffset--;
else
caretOffset = newCaretOffset;
if(content.isImageTag(caretOffset - 1))
caretOffset--;
showCaret();
}
}
/**
* 删除一个用户自定义按键绑定
*
* @param key
* a key code defined in SWT.java or a character. Optionally ORd
* with a state mask. Preferred state masks are one or more of
* SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for
* modifier platform differences. However, there may be cases
* where using the specific state masks (i.e., SWT.CTRL,
* SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
*/
public void removeUserKeyAction(int key) {
setUserKeyAction(key, null);
}
/**
* 添加一个用户自定义按键事件
*
* @param key
* @param action
*/
public void setUserKeyAction(int key, Runnable action) {
if(action == null)
setKeyBinding(key, SWT.NULL);
else
setKeyBinding(key, CUSTOM_ACTION);
int keyValue = key & SWT.KEY_MASK;
int modifierValue = key & SWT.MODIFIER_MASK;
char keyChar = (char)keyValue;
if (Character.isLetter(keyChar)) {
// 添加key的大写形式
char ch = Character.toUpperCase(keyChar);
int newKey = ch | modifierValue;
if (action == null)
userActionMap.remove(new Integer(newKey));
else
userActionMap.put(new Integer(newKey), action);
// 添加key的小写形式
ch = Character.toLowerCase(keyChar);
newKey = ch | modifierValue;
if (action == null)
userActionMap.remove(new Integer(newKey));
else
userActionMap.put(new Integer(newKey), action);
} else {
// 不是字符形式的按键则直接添加
if (action == null)
userActionMap.remove(new Integer(key));
else
userActionMap.put(new Integer(key), action);
}
}
/**
* 得到用户自定义动作对象
*
* @param key
* 按键值
* @return
* Runnable对象
*/
public Runnable getUserKeyAction(int key) {
return (Runnable)userActionMap.get(new Integer(key));
}
/**
* 查找和相关按键绑定的动作id
* <p>
*
* @param key
* a key code defined in SWT.java or a character. Optionally ORd
* with a state mask. Preferred state masks are one or more of
* SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for
* modifier platform differences. However, there may be cases
* where using the specific state masks (i.e., SWT.CTRL,
* SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
* @return
* 动作ID,SWT.NULL表示没有动作
* @exception SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been
* disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public int getKeyBinding(int key) {
checkWidget();
Integer action = (Integer) keyActionMap.get(new Integer(key));
if (action == null)
return SWT.NULL;
else
return action.intValue();
}
/**
* 添加一个按键绑定
* <p>
*
* @param key
* a key code defined in SWT.java or a character. Optionally ORd
* with a state mask. Preferred state masks are one or more of
* SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for
* modifier platform differences. However, there may be cases
* where using the specific state masks (i.e., SWT.CTRL,
* SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
* @param action
* 动作ID
* @exception SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been
* disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setKeyBinding(int key, int action) {
checkWidget();
int keyValue = key & SWT.KEY_MASK;
int modifierValue = key & SWT.MODIFIER_MASK;
char keyChar = (char)keyValue;
if (Character.isLetter(keyChar)) {
// 添加key的大写形式
char ch = Character.toUpperCase(keyChar);
int newKey = ch | modifierValue;
if (action == SWT.NULL)
keyActionMap.remove(new Integer(newKey));
else
keyActionMap.put(new Integer(newKey), new Integer(action));
// 添加key的小写形式
ch = Character.toLowerCase(keyChar);
newKey = ch | modifierValue;
if (action == SWT.NULL)
keyActionMap.remove(new Integer(newKey));
else
keyActionMap.put(new Integer(newKey), new Integer(action));
} else {
// 不是字符形式的按键则直接添加
if (action == SWT.NULL)
keyActionMap.remove(new Integer(key));
else
keyActionMap.put(new Integer(key), new Integer(action));
}
}
/**
* 删除一个按键绑定
*
* @param key
*/
public void removeKeyBinding(int key) {
setKeyBinding(key, SWT.NULL);
}
/**
* 添加缺省按键绑定
*/
private void createKeyBindings() {
// 导航按键绑定
setKeyBinding(SWT.HOME, LINE_START);
setKeyBinding(SWT.END, LINE_END);
setKeyBinding(SWT.PAGE_UP, PAGE_UP);
setKeyBinding(SWT.PAGE_DOWN, PAGE_DOWN);
setKeyBinding(SWT.HOME | SWT.MOD1, TEXT_START);
setKeyBinding(SWT.END | SWT.MOD1, TEXT_END);
setKeyBinding(SWT.PAGE_UP | SWT.MOD1, TEXT_START);
setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, TEXT_END);
setKeyBinding(SWT.ARROW_LEFT, COLUMN_LEFT);
setKeyBinding(SWT.ARROW_RIGHT, COLUMN_RIGHT);
setKeyBinding(SWT.ARROW_UP, LINE_UP);
setKeyBinding(SWT.ARROW_DOWN, LINE_DOWN);
// Selection
setKeyBinding(SWT.ARROW_UP | SWT.MOD2, SELECT_LINE_UP);
setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, SELECT_LINE_DOWN);
setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, SELECT_COLUMN_LEFT);
setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, SELECT_COLUMN_RIGHT);
setKeyBinding('A' | SWT.MOD1, SELECT_ALL);
// Modification
setKeyBinding('X' | SWT.MOD1, CUT);
setKeyBinding('C' | SWT.MOD1, COPY);
setKeyBinding('V' | SWT.MOD1, PASTE);
setKeyBinding(SWT.BS, DELETE_PREVIOUS);
setKeyBinding(SWT.DEL, DELETE_NEXT);
setKeyBinding(SWT.CR, NEW_LINE);
}
/**
* @param event
*/
protected void handleDispose(Event event) {
removeListener(SWT.Dispose, listener);
notifyListeners(SWT.Dispose, event);
event.type = SWT.None;
if (caret != null) {
caret.dispose();
caret = null;
}
if(backXorColor != null)
backXorColor.dispose();
clipboard.dispose();
beamCursor = null;
}
/**
* @param event
*/
protected void handlePaint(Event event) {
// Check if there is work to do
if (event.height == 0)
return;
// adjust y position for pixel based scrolling and top margin
int startLine = contentHelper.getLineAtY(event.gc, verticalScrollOffset);
int paintYFromTopLine = contentHelper.getHeightOfLines(event.gc, topLine, startLine);
int topLineOffset = contentHelper.getYOfLine(event.gc, topLine) - verticalScrollOffset;
int startY = paintYFromTopLine + topLineOffset + topMargin;
int renderHeight = event.y + event.height - startY;
performPaint(event.gc, startLine, startY, renderHeight);
}
/**
* 调整光标的位置和大小
*
* @param gc
* @param y
*/
private void adjustCaret(GC gc, int y) {
int delta = topMargin - y;
if(delta < 0)
delta = 0;
caret.setLocation(caret.getLocation().x, y + delta);
caret.setSize(1, contentHelper.getLineHeight(gc, topLine) - delta);
}
/**
* @param gc
* @param startLine
* @param startY
* @param renderHeight
*/
private void performPaint(GC gc, int startLine, int startY, int renderHeight) {
Rectangle clientArea = getClientArea();
Color background = getBackground();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -