📄 historycanvas.java
字号:
int start, end; for (start = 0; start < s.length(); start = end) { int visWidth = scrollbar.getX() - rightOffset - leftOffset - firstOffset; firstOffset = 0; for (end = start; end <= s.length(); end++) { String substr = s.substring(start, end); if (font.stringWidth(substr) > visWidth) { splitLines.addElement(s.substring(start, --end)); break; } else if (end == s.length()) { splitLines.addElement(s.substring(start, end)); } } } return splitLines; } /** * Appends a string to the history lines list. First checks whether the * string fits on a line. If not, splits it to multiple strings, each * fitting on a line of its own. At last, appends these lines to the history * lines list. * * @param s * Message string to append to history lines list. * @param systemMessage * if <code>true</code> then the message is a system message * and is not added to {@link #messages} list. */ // TODO Optimize the splitting process. public void append(Message msg) { if (msg.body == null || msg.body.length() == 0) { msg.bodyLines = new Vector(); msg.senderLines = new Vector(); return; } int senderWidth = 0; if (msg.isSystemMessage()) { msg.senderLines = new Vector(); } else { msg.senderLines = splitLines(msg.sender + ": ", 0); senderWidth = font.stringWidth((String) msg.senderLines .lastElement()); } msg.bodyLines = splitLines(msg.body, senderWidth); messages.addElement(msg); repaint(); } /** * Returns the color assigned to particular message sender. If given sender * does not yet have a color assigned, take the following one from the * senderColors. * * @param sender * Name of sender. * @return Color assigned to given sender name. TODO Multiple senders with * identical name get assigned with identical color. */ private int getSenderColor(String sender) { int result; Integer i; if ((i = (Integer) colorHash.get(sender)) == null) { result = senderColors[colorHash.size()]; colorHash.put(sender, new Integer(result)); } else result = i.intValue(); return result; } /** * Paints the currently visible lines. Repaints the canvas using the default * color and draw history lines at current position, drawing only that much * lines, that would fit on a device screen. While the list of lines is * empty and a splash drawer has been provided when creating canvas, the * splash screen is painted instead. * * @param g * Graphics provided by the canvas for painting the canvas * content. TODO Optimize the repainting process. */ protected void paint(Graphics g) { g.setColor(backgroundColor); g.fillRect(0, 0, getWidth(), getHeight()); curPos = normalizeCurPos(atEnd ? scrollNotifier.getActualLength() : curPos); int count; if (scrollNotifier.getActualLength() > getLinesPerScreen()) count = getLinesPerScreen(); else count = scrollNotifier.getActualLength(); int topOffset = (getHeight() % font.getHeight()) / 2; g.setFont(font); int curLine = 0; for (int msgIndex = 0; msgIndex < messages.size(); msgIndex++) { int senderWidth = 0; Message msg = (Message) messages.elementAt(msgIndex); for (int i = 0; i < msg.senderLines.size(); i++) { if (curLine >= curPos && curLine < curPos + count) { g.setColor(getSenderColor(msg.sender)); String senderLine = (String) msg.senderLines.elementAt(i); g.drawString(senderLine, leftOffset, topOffset + (curLine - curPos) * font.getHeight(), Graphics.TOP | Graphics.LEFT); if (i == msg.senderLines.size() - 1) senderWidth = font.stringWidth(senderLine); } if (i != msg.senderLines.size() - 1) curLine++; } for (int i = 0; i < msg.bodyLines.size(); i++) { if (curLine >= curPos && curLine < curPos + count) { if (msg.isSystemMessage()) g.setColor(systemMessageColor); else g.setColor(messageBodyColor); String bodyLine = (String) msg.bodyLines.elementAt(i); g.drawString(bodyLine, leftOffset + senderWidth, topOffset + (curLine - curPos) * font.getHeight(), Graphics.TOP | Graphics.LEFT); senderWidth = 0; } curLine++; } } g.setColor(0x000000); scrollbar.paint(g); } /** * TODO Handles user actions throughout the application. Entities the commands * are handled for are {@link #history}, {@link #inputBox} and * {@link #exitAler}. * * @param c * Command user has sent. * @param d * Displayable the command has come from. */ public void commandAction(Command c, Displayable d) { Display display = Display.getDisplay(ibtu); if (d == this) { // TODO Make historyCanvas switch to inputBox on any key event. if (c == commandNew) display.setCurrent(inputBox); else if (c == commandExit) { setHistoryCommandsExit(); } else if (c == commandExitCancel) { setHistoryCommandsNormal(); } else if (c == commandExitSure) { ibtu.disconnect(); display.setCurrent(ibtu.getConForm()); messages.removeAllElements(); setHistoryCommandsNormal(); } } else if (d == inputBox) { if (c == inputBoxCommandSend) { String s = inputBox.getString(); if (s.trim().length() > 0) { /* send message and append to history */ ibtu.sendMessage(s); String deviceName = Peer.getDeviceName(); append(new Message(deviceName, s)); display.setCurrent(this); inputBox.setString(""); } } else if (c == inputBoxCommandCancel) { display.setCurrent(this); inputBox.setString(""); } } } /** * Handles the device keypad actions. Provide user with ability to scroll * the history canvas by means of pressing {@link Canvas#UP} and * {@link Canvas#DOWN} keys and change current position within a history * lines list. * * @param keyCode * Code of a key pressed. */ public void keyPressed(int keyCode) { int action = getGameAction(keyCode); int savPos = curPos = normalizeCurPos(curPos); int savSize = scrollNotifier.getActualLength(); switch (action) { case UP: curPos--; break; case DOWN: curPos++; break; default: // any other command Display.getDisplay(ibtu).setCurrent(inputBox); return; } curPos = normalizeCurPos(curPos); if ((savPos != curPos) || (savSize != scrollNotifier.getActualLength())) { atEnd = (curPos >= (scrollNotifier.getActualLength() - getLinesPerScreen())); repaint(); } } /** * Handles repeated events from the device keypad. Simply call * {@link HistoryCanvas#keyPressed(int)} passing it a keyCode. * * @param keyCode * Code of a key held down. */ public void keyRepeated(int keyCode) { keyPressed(keyCode); } /** * ScrollNotifer implementation for HistoryCanvas. Returns current * properties of canvas for the need of scrollbar to represent actual state * of history being displayed. * * @author Jan Tomka */ private class HistoryCanvasScrollNotifier implements IScrollNotifier { /** * Calculates the number of items currently in the history lines list. * * @return Number of lines in history. TODO Get rid of calls to this * method in historyCanvas. */ public int getActualLength() { return Message.countLines(messages); } /** * Calculates the number of items displayable at the same time. Simply * calls {@link HisotryCanvas#getLinesPerScreen()}. * * @return Number of lines that fit on a device screen. */ public int getVisibleLength() { return getLinesPerScreen(); } /** * Calculates the index of a line currently displayed on top of canvas. * * @return Number of currently topmost line. */ public int getCurrentPosition() { return normalizeCurPos(curPos); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -