📄 richbox.java
字号:
y = topMargin;
} else if(y < clientAreaHeight - bottomMargin && y + h > clientAreaHeight - bottomMargin) {
h = clientAreaHeight - bottomMargin - y;
} else if(y < topMargin || y >= clientAreaHeight - bottomMargin && clientAreaHeight != 0) {
caret.setVisible(false);
return;
}
caret.setVisible(true);
caret.setLocation(newCaretX + leftMargin , y);
caret.setSize(1, h);
columnX = newCaretX;
}
/**
* 计算最顶行索引
*/
void calculateTopLine() {
topLine = contentHelper.getLineAtY(getGC(), verticalScrollOffset);
releaseGC();
}
/**
* @param event
*/
protected void handleTraverse(Event event) {
switch (event.detail) {
case SWT.TRAVERSE_ESCAPE:
case SWT.TRAVERSE_PAGE_NEXT:
case SWT.TRAVERSE_PAGE_PREVIOUS:
event.doit = true;
break;
case SWT.TRAVERSE_RETURN:
case SWT.TRAVERSE_TAB_NEXT:
case SWT.TRAVERSE_TAB_PREVIOUS:
if (readonly || (event.stateMask & SWT.MODIFIER_MASK) != 0) {
event.doit = true;
}
break;
}
}
/**
* @return
* 被选择的内容
*/
public String getSelection() {
return content.getText(selectionStart, selectionEnd);
}
/**
* @return
* true表示有选择的区域
*/
public boolean hasSelection() {
return selectionEnd != selectionStart;
}
/**
* @param event
*/
protected void handleResize(Event event) {
int oldHeight = clientAreaHeight;
int oldWidth = clientAreaWidth;
Rectangle clientArea = getClientArea();
clientAreaHeight = clientArea.height;
clientAreaWidth = clientArea.width;
// rewrap and redraw
if(oldWidth != clientAreaWidth) {
content.wrap(clientAreaWidth - leftMargin - rightMargin);
redraw();
}
// refresh scroll bar
setScrollBars();
// reset caret
if (oldHeight != clientAreaHeight)
calculateTopLine();
if(clientAreaHeight > 0 && clientAreaWidth - leftMargin - rightMargin > 0)
showCaret();
}
/**
* @param event
*/
protected void handleMouseMove(Event event) {
if ((event.stateMask & SWT.BUTTON1) == 0)
return;
event.y -= topMargin;
event.x -= leftMargin;
doMouseLocationChange(event.x, event.y, true);
doAutoScroll(event);
}
/**
* 如果鼠标出了客户区,自动滚动
*/
private void doAutoScroll(Event event) {
Rectangle area = getClientArea();
if (event.y > area.height)
doAutoScroll(SWT.DOWN);
else if (event.y < 0)
doAutoScroll(SWT.UP);
else
endAutoScroll();
}
/**
* 结束自动滚动
*/
private void endAutoScroll() {
autoScrollDirection = SWT.NULL;
}
/**
* 开始自动滚动
* <p>
*
* @param direction
* SWT.UP, SWT.DOWN
*/
private void doAutoScroll(int direction) {
// 方向相同则不用管
if (autoScrollDirection == direction)
return;
// 方向不合法则返回
if (direction != SWT.UP && direction != SWT.DOWN)
return;
// 开始滚动
autoScrollDirection = direction;
getDisplay().timerExec(AUTO_SCROLL_INTERVAL, autoScrollTimer);
}
/**
* 往上选择一行
*/
private void doLineUp() {
int oldColumnX;
int caretLine = content.getLineAtOffset(caretOffset);
int lineStartOffset = content.getLineStartOffset(caretLine);
// 保存当前光标X偏移
oldColumnX = columnX;
if (caretLine > 0)
caretLine = doSimpleLineUp();
// 显示光标
showCaret(caretLine);
// save the original horizontal caret position
columnX = oldColumnX;
}
/**
* 显示光标,这个方法会修改光标X位置
*/
private void showCaret() {
int caretLine = content.getLineAtOffset(caretOffset);
showCaret(caretLine);
}
/**
* 把光标置于caretLine行,并且让光标可见,也就是要让caretLine行可见
* 这个方法会修改光标X位置
*/
private void showCaret(int caretLine) {
boolean scrolled = showLine(caretLine);
if (scrolled == false)
setCaretLocation();
}
/**
* 光标所在行减1,保持光标水平位置基本不变
*
* @return
* 光标所在行号
*/
private int doSimpleLineUp() {
int caretLine = content.getLineAtOffset(caretOffset);
if (caretLine > 0) {
caretLine--;
caretOffset = contentHelper.getOffsetAtX(getGC(), caretLine, columnX);
releaseGC();
}
return caretLine;
}
/**
* 使指定的行处于view中,如果这一行当前不在view中,则需要滚动
* <p>
*
* @param line
* 需要显示的行的行号
* @return
* true表示经过了滚动,false表示没有
*/
private boolean showLine(int line) {
boolean scrolled = false;
GC gc = getGC();
if (line <= topLine) {
scrolled = setVerticalScrollOffset(contentHelper.getHeightOfLines(gc, 0, line), true);
} else if (line > getFullVisibleBottomLine(gc)) {
scrolled = setVerticalScrollOffset(contentHelper.getHeightOfLines(gc, 0, line + 1) - clientAreaHeight + topMargin + bottomMargin, true);
}
releaseGC();
return scrolled;
}
/**
* @return
* 得到view中的最后一个全部可见行的行号
*/
private int getFullVisibleBottomLine(GC gc) {
int y = clientAreaHeight - topMargin - bottomMargin + verticalScrollOffset;
int line = contentHelper.getLineAtY(gc, y);
if(contentHelper.getHeightOfLines(gc, 0, line + 1) > y)
line--;
return line;
}
/**
* @param gc
* GC
* @return
* 得到view中可见的最后一行的行号,不需要全部可见
*/
private int getBottomLine(GC gc) {
int y = clientAreaHeight - topMargin - bottomMargin + verticalScrollOffset;
return contentHelper.getLineAtY(gc, y);
}
/**
* 往下选择一行
*/
private void doLineDown() {
int oldColumnX;
int caretLine;
int lineStartOffset;
caretLine = content.getLineAtOffset(caretOffset);
lineStartOffset = content.getLineStartOffset(caretLine);
// 保存光标X参照点以便移动后恢复
oldColumnX = columnX;
if (caretLine < content.getLineCount() - 1)
caretLine = doSimpleLineDown();
// 显示光标
showCaret(caretLine);
// save the original horizontal caret position
columnX = oldColumnX;
}
/**
* 光标所在行加1,保持光标水平位置基本不变
*
* @return index of the new line relative to the first line in the document
*/
private int doSimpleLineDown() {
int caretLine = content.getLineAtOffset(caretOffset);
if (caretLine < content.getLineCount() - 1) {
caretLine++;
caretOffset = contentHelper.getOffsetAtX(getGC(), caretLine, columnX);
releaseGC();
}
return caretLine;
}
/**
* @param event
*/
protected void handleMouseDoubleClick(Event event) {
if (event.button != 1 || doubleClickEnabled == false)
return;
// 得到应该被选择的区域
int caretLine = content.getLineAtOffset(caretOffset);
int lineStartOffset = content.getLineStartOffset(caretLine);
int nextLineStartOffset = content.getLineStartOffset(caretLine + 1);
// 重置选择区
resetSelection(lineStartOffset, nextLineStartOffset);
// 重置光标
caretOffset = lineStartOffset;
setCaretLocation();
}
/**
* 将被选择区域置为指定的值,我们需要重画旧的选择区,再画新的选择区
*
* @param start
* @param end
*/
private void resetSelection(int start, int end) {
int oldStart = selectionStart;
int oldEnd = selectionEnd;
resetSelection();
redrawRange(oldStart, oldEnd);
// 画新的选择区
selectionStart = start;
selectionEnd = end;
redrawRange(selectionStart, selectionEnd);
if(!IS_WIN32 && selectionEnd != selectionStart)
setClipboardContent(selectionStart, selectionEnd - selectionStart);
}
/**
* 重画start和end之间的字符,不包括end
*
* @param start
* @param end
*/
private void redrawRange(int start, int end) {
if(end <= start)
return;
GC gc = getGC();
int startLine = content.getLineAtOffset(start);
int endLine = content.getLineAtOffset(end - 1);
int bottomLine = getBottomLine(gc);
if(endLine < topLine || startLine > bottomLine)
return;
// 让开始行和结束行出现在view中
while(startLine < topLine)
startLine++;
while(endLine > bottomLine)
endLine--;
int y = contentHelper.getHeightOfLines(gc, 0, startLine) - verticalScrollOffset + topMargin;
int h = contentHelper.getHeightOfLines(gc, startLine, endLine + 1);
releaseGC();
redraw(leftMargin, y, clientAreaWidth - leftMargin - rightMargin, h, true);
}
/**
* Resets the selection.
*/
private void resetSelection() {
selectionStart = selectionEnd = caretOffset;
}
/**
* @param event
*/
protected void handleMouseUp(Event event) {
endAutoScroll();
if ((event.stateMask & SWT.BUTTON3) != 0 && enableContextMenu) {
contextMenu.setLocation(toDisplay(event.x, event.y));
contextMenu.setVisible(true);
}
}
/**
* @param event
*/
protected void handleMouseDown(Event event) {
if(!IS_WIN32 && event.button == 2) {
paste();
return;
}
if ((event.button != 1)
|| (IS_CARBON && (event.stateMask & SWT.MOD4) != 0)) {
return;
}
event.x -= leftMargin;
event.y -= topMargin;
if(event.x < 0 || event.y < 0)
return;
doMouseLocationChange(event.x, event.y, false);
}
/**
* 清除选择区
*/
private void clearSelection() {
int oldStart = selectionStart;
int oldEnd = selectionEnd;
resetSelection();
redrawRange(oldStart, oldEnd);
}
/**
* @param x
* @param y
* @param move
* true表示鼠标在移动中
*/
private void doMouseLocationChange(int x, int y, boolean move) {
GC gc = getGC();
int lineIndex = contentHelper.getLineAtY(gc, y + verticalScrollOffset);
caretOffset = contentHelper.getOffsetAtX(gc, lineIndex, x);
setCaretLocation();
releaseGC();
if(move) {
// 判断谁先谁后,谁应该是start,谁是end
if(caretOffset >= selectionAnchor)
resetSelection(selectionAnchor, caretOffset);
else
resetSelection(caretOffset, selectionAnchor);
} else {
selectionAnchor = caretOffset;
clearSelection();
}
}
/**
* @param event
*/
protected void handleKeyDown(Event event) {
Event verifyEvent = new Event();
verifyEvent.character = event.character;
verifyEvent.keyCode = event.keyCode;
verifyEvent.stateMask = event.stateMask;
verifyEvent.doit = true;
notifyListeners(VerifyKey, verifyEvent);
if (verifyEvent.doit == true) {
handleKey(event);
}
}
/**
* @param event
*/
protected void handleKey(Event event) {
int action;
int key;
if (event.keyCode != 0) {
// special key pressed (e.g., F1)
key = event.keyCode | event.stateMask;
action = getKeyBinding(key);
} else {
// character key pressed
key = event.character | event.stateMask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -