📄 chatbox.java
字号:
lineCache.delete(caretChar, caretChar + 1);
else
nextLine.delete(0, 1);
}
// 删除他,他的字符追加到当前行
lineBufs.remove(caretLine + 1);
lineCache.append(nextLine.getChars());
lineCache.appendSmiley(nextLine.getSmiley());
// 得到下一行的hard属性
lineCache.hardLine = nextLine.hardLine;
// 调整行,注意我们要减1,因为我们上面删了一行
i = adjustLine(gc, lineCache) - 1;
lines += i;
// 调整视口
if(i < 0)
viewEndLine = getEndLine(viewBeginLine);
// 调整卷滚条
adjustVerticalBar();
gc.dispose();
}
setCaretLine(caretLine);
redraw();
}
// 处理下方向键
private void handleDownKey() {
if(caretLine == lines - 1) return;
else {
caretLine++;
if(caretLine > viewEndLine) {
viewEndLine++;
viewBeginLine = getBeginLine(viewEndLine);
adjustVerticalBar();
}
}
clearSelected();
GC gc = new GC(this);
int w = caret.getLocation().x - margin;
caretChar = ((LineCache)lineBufs.get(caretLine)).getBeginCharIndexLessThanWidth(gc, w);
gc.dispose();
redraw();
}
// 处理End按键
private void handleEndKey(KeyEvent e) {
// 如果按了CTRL,则回到最开头
if((e.stateMask & SWT.CTRL) != 0) {
viewEndLine = lines - 1;
viewBeginLine = getBeginLine(viewEndLine);
// 设置光标参数
setCaretLine(viewEndLine);
caretChar = ((LineCache)lineBufs.get(caretLine)).size();
// 调整卷滚条
adjustVerticalBar();
// 重画
redraw();
} else
caretChar = ((LineCache)lineBufs.get(caretLine)).size();
clearSelected();
redraw();
}
// 处理回车
private void handleEnterKey() {
LineCache line = (LineCache)lineBufs.get(caretLine);
// 如果有选择部分,则先删除选择部分
if(selected) {
handleDeleteKey();
}
GC gc = new GC(this);
// 得到当前行,删除enter发生的位置之后的所有字符,做为下一行
// 新行将具有和当前行一样的hard属性,同时当前行的hardline属性
// 被置为true
LineCache newLine = new LineCache();
newLine.append(line.delete(caretChar));
newLine.appendSmiley(line.exceedSmiley);
newLine.hardLine = line.hardLine;
line.hardLine = true;
// 添加新行
lineBufs.add(caretLine + 1, newLine);
// 如果是软分行,要接着调整后面的行,注意外面把i初始化为1,因为如果newline的hardline为
// false,那么if不会被执行,新行就是newLine
int i = 1;
if(newLine.size() > 0 && !newLine.hardLine) {
// 得到新行后面一行并删除
LineCache nextLine = (LineCache)lineBufs.get(caretLine + 2);
lineBufs.remove(caretLine + 2);
// 把删除的这行的内容添加到新行
newLine.append(nextLine.getChars());
newLine.appendSmiley(nextLine.getSmiley());
// 删除行的hard属性赋予新行
newLine.hardLine = nextLine.hardLine;
// 调整新行
i = adjustLine(gc, newLine);
}
// 调整总行数
lines += i;
// 改变光标位置
caretLine++;
caretChar = 0;
// 调整视口
if(caretLine > viewEndLine) {
viewEndLine++;
viewBeginLine = getBeginLine(viewEndLine);
} else if(i > 0)
viewEndLine = getEndLine(viewBeginLine);
// 调整垂直卷滚条
adjustVerticalBar();
gc.dispose();
redraw();
}
// 处理Home按键
private void handleHomeKey(KeyEvent e) {
// 如果按了CTRL,则回到最开头
if((e.stateMask & SWT.CTRL) != 0){
// 调整开始行和结束行
viewBeginLine = 0;
viewEndLine = getEndLine(viewBeginLine);
// 调整光标参数
caretChar = 0;
setCaretLine(0);
// 调整卷滚条
adjustVerticalBar();
// 重画
redraw();
} else
caretChar = 0;
clearSelected();
redraw();
}
// 处理左方向键
private void handleLeftKey() {
if(caretChar == 0) {
if(caretLine == 0) return;
else {
caretLine--;
caretChar = ((LineCache)lineBufs.get(caretLine)).size();
if(caretLine < viewBeginLine) {
viewBeginLine--;
viewEndLine = getEndLine(viewBeginLine);
adjustVerticalBar();
}
}
} else
caretChar--;
clearSelected();
redraw();
}
// 处理右方向键
private void handleRightKey() {
int size = ((LineCache)lineBufs.get(caretLine)).size();
if(caretChar >= size) {
if(caretLine == lines - 1) return;
else {
caretLine++;
caretChar = 0;
if(caretLine > viewEndLine) {
viewEndLine++;
viewBeginLine = getBeginLine(viewEndLine);
adjustVerticalBar();
}
}
} else
caretChar++;
clearSelected();
redraw();
}
// 处理上方向键
private void handleUpKey() {
if(caretLine == 0) return;
else{
caretLine--;
if(caretLine < viewBeginLine) {
viewBeginLine--;
viewEndLine = getEndLine(viewBeginLine);
adjustVerticalBar();
}
}
clearSelected();
GC gc = new GC(this);
int w = caret.getLocation().x - margin;
caretChar = ((LineCache)lineBufs.get(caretLine)).getBeginCharIndexLessThanWidth(gc, w);
gc.dispose();
redraw();
}
// 初始化工作
private void initVariable() {
display = getDisplay();
color = new Color(display, 0xF7, 0xF3, 0xF7);
// 设置光标
caret = new Caret(this, SWT.NONE);
setCaret(caret);
caret.setLocation(margin, margin);
GC gc = new GC(this);
fontMetrics = gc.getFontMetrics();
caret.setSize(1, fontMetrics.getHeight());
gc.dispose();
// 设置鼠标
beamCursor = new Cursor(display, SWT.CURSOR_IBEAM);
this.setCursor(beamCursor);
// 初始化变量
down = false;
enabled = true;
clipboard = new Clipboard(display);
useEnter = true;
// 初始化光标位置和缓冲区
caretLine = caretChar = 0;
maxChar = 400;
lineBufs = new ArrayList();
lineBufs.add(new LineCache());
// 设置视口坐标和当前行数
viewBeginLine = viewEndLine = 0;
lines = 1;
// 设置背景
setBackground(display.getSystemColor(SWT.COLOR_WHITE));
// 获得垂直卷滚条
vBar = this.getVerticalBar();
vBar.setMinimum(0);
vBar.setMaximum(lines);
vBar.setIncrement(1);
vBar.setVisible(false);
vBar.addSelectionListener(
new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleScroll();
}
}
);
// 添加监听器
addPaintListener(this);
addDisposeListener(this);
addMouseListener(this);
addKeyListener(this);
addTraverseListener(this);
addMouseMoveListener(this);
addControlListener(this);
}
// 处理滚动事件
private void handleScroll() {
viewBeginLine = vBar.getSelection();
viewEndLine = getEndLine(viewBeginLine);
caret.setVisible(false);
redraw();
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
*/
public void keyPressed(KeyEvent e) {
// 如果鼠标按下了,则暂时不响应任何键盘事件
if(down) {
e.doit = false;
return;
}
// 检查光标是否在视口之外,这可能是因为卷滚条的原因,需要把光标搞到视口来
if(caretLine < viewBeginLine || caretLine > viewEndLine) {
viewBeginLine = caretLine;
viewEndLine = getEndLine(viewBeginLine);
caret.setVisible(true);
adjustVerticalBar();
redraw();
}
if(e.keyCode == SWT.HOME)
handleHomeKey(e);
else if(e.keyCode == SWT.END)
handleEndKey(e);
else if(e.keyCode == SWT.ARROW_LEFT)
handleLeftKey();
else if(e.keyCode == SWT.ARROW_RIGHT)
handleRightKey();
else if(e.keyCode == SWT.ARROW_DOWN)
handleDownKey();
else if(e.keyCode == SWT.ARROW_UP)
handleUpKey();
else if(e.keyCode == SWT.CR && enabled) {
if(useEnter && (e.stateMask & SWT.CTRL) == 0)
handleEnterKey();
else if(!useEnter && (e.stateMask & SWT.CTRL) != 0)
handleEnterKey();
} else if(e.keyCode == SWT.BS && enabled)
handleBackSpaceKey();
else if(e.keyCode == SWT.DEL && enabled)
handleDeleteKey();
else if(e.character == 0x01) // Ctrl + A
handleCtrlA();
else if(e.character == 0x03) // Ctrl + C
handleCtrlC();
else if(e.character == 0x18 && enabled) // Ctrl + X
handleCtrlX();
else if(e.character == 0x16 && enabled) // Ctrl + V
handleCtrlV();
else if(e.character != 0 && enabled) {
// 检查是否有不允许的键按下,如果是,返回
if(!noLaithKey(e)) return;
handleCharacter(e.character, 0);
}
}
// 处理粘贴事件
private void handleCtrlV() {
String data = (String)clipboard.getContents(TextTransfer.getInstance());
if(data != null) paste(data);
}
// 粘贴,会处理data中的表情和换行符号
private void paste(String data) {
if(data == null) return;
List list = parseText(data);
int size = list.size();
for(int i = 0; i < size; i++) {
LineCache lineCache = (LineCache)lineBufs.get(caretLine);
handleCharacter(lineCache, (char)0, 0, (LineCache)list.get(i), false, false);
if(i < size - 1)
handleEnterKey();
}
}
// 处理剪切事件
private void handleCtrlX() {
if(selected) {
LineCache lineCache = (LineCache)lineBufs.get(caretLine);
handleCharacter(lineCache, (char)0, 0, null, true, true);
clipboard.setContents(new Object[] { regularCopy }, new Transfer[] { TextTransfer.getInstance()});
}
}
// 处理拷贝事件
private void handleCtrlC() {
if(selected) {
LineCache copyCache = copySelected();
regularCopy = copyCache.getString();
clipboard.setContents(new Object[] { regularCopy }, new Transfer[] { TextTransfer.getInstance()});
}
}
// 处理全选事件
private void handleCtrlA() {
for(int i = 0; i < lines; i++) {
LineCache lineCache = (LineCache)lineBufs.get(i);
lineCache.affected = true;
lineCache.affectedBegin = 0;
lineCache.affectedEnd = lineCache.size();
}
affectedBeginLine = 0;
affectedEndLine = lines - 1;
selected = true;
caretLine = caretChar = 0;
redraw();
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
*/
public void keyReleased(KeyEvent e) {
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
*/
public void mouseDoubleClick(MouseEvent e) {
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
*/
public void mouseDown(MouseEvent e) {
if(e.button == 3) { // 右键弹出菜单
if(enabled) {
enableMenu.setLocation(toDisplay(e.x, e.y));
enableMenu.setVisible(true);
} else {
disableMenu.setLocation(toDisplay(e.x, e.y));
disableMenu.setVisible(true);
}
} else if(e.button == 1) { // 左键设置光标
GC gc = new GC(this);
setCaretLine(calcCaretLine(e.y));
caretChar = calcCaretChar(gc, e.x, caretLine);
caret.setVisible(false);
gc.dispose();
clearSelected();
redraw();
setFocus();
affectedBeginLine = caretLine;
down = true;
downX = e.x;
downY = e.y;
setCapture(true);
} else if(e.button == 2) { // 中键执行粘贴任务
handleCtrlV();
}
}
// 清除所有被影响的标志,如果selected为true的话
private void clearSelected() {
if(selected) {
selected = false;
for(int i = affectedBeginLine; i <= affectedEndLine; i++)
((LineCache)lineBufs.get(i)).affected = false;
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
*/
public void mouseMove(MouseEvent e) {
if(down) {
// 得到当前鼠标所在的行和字符
GC gc = new GC(this);
int cl = calcCaretLine(e.y);
int cc = calcCaretChar(gc, e.x, cl);
gc.dispose();
if(cl == viewEndLine) {
vBar.setSelection(vBar.getSelection() + 1);
handleScroll();
} else if(cl == viewBeginLine){
vBar.setSelection(vBar.getSelection() - 1);
handleScroll();
}
for(int i = 0; i < lines; i++)
((LineCache)lineBufs.get(i)).affected = false;
// 如果字符数没变,直接返回
if(cl == caretLine && cc == caretChar) return;
// 设置受影响的行
if(cl == caretLine && cc != caretChar) {
LineCache lineCache = (LineCache)lineBufs.get(cl);
lineCache.affected = true;
lineCache.affectedBegin = Math.min(cc, caretChar);
lineCache.affectedEnd = Math.max(cc, caretChar);
selected = true;
affectedEndLine = caretLine;
} else if(cl > caretLine) {
setAffected(caretLine, caretChar, cl, cc);
selected = true;
affectedEndLine = cl;
} else {
setAffected(cl, cc, caretLine, caretChar);
selected = true;
affectedBeginLine = cl;
affectedEndLine = caretLine;
}
redraw();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -