/* * cognet chat app * * Copyright 2003, Brian Swetland * See LICENSE for redistribution terms * * Derived from: * * @(#)ChatHistory.java 1.0 01/03/23 * * Copyright 2000 by Danger Research, Inc. * 165 University Avenue, Palo Alto, CA 94301 * All rights reserved. * See SAMPLE_CODE_LICENSE for redistribution terms. * */ package org.twodot.cognet; import danger.ui.*; import danger.util.LineBreaker; import java.util.Enumeration; public class ChatHistory extends View { public ChatHistory(int inSizeLimit, Engine e) { Rect r; mPlainFont = Font.findSystemFont(); mBoldFont = Font.findSystemFont(); mAscent = mBoldFont.getAscent() + mBoldFont.getDescent(); mLineHeight = mAscent + kLeading - 2; mLimit = inSizeLimit; setSize(20, 10); engine = e; tag_bitmap = engine.app.bm_tag; tag_width = tag_bitmap.getWidth(); tag_height = tag_bitmap.getHeight(); tag_font = Font.findFont("Bort7"); } Bitmap tag_bitmap; int tag_width, tag_height; Font tag_font; public void paint(Pen inPen) { Rect r = getBounds(); int i, x, y; ChatLine index = mBottomDisplayLine; //* Clear the area if(mCurrentSelection != 0){ inPen.setColor(Color.GRAY10); } else { inPen.setColor(Color.WHITE); } inPen.fillRect(r); inPen.setColor(Color.BLACK); x = r.left; y = mLineHeight * (mNumDisplayLines - 1); y += mAscent; y += r.top; SmileyEngine smiley = new SmileyEngine(mPlainFont); inPen.setFont(mPlainFont); //* Draw the individual lines while ((y > r.top) && (null != index)) { // if (engine.app.doSmileys) smiley.drawString(x,y,index.mText, inPen); // else // inPen.drawText(x, y, index.mText); y -= mLineHeight; index = index.mPrev; } y = 0; x = r.right - tag_width; inPen.setColor(Color.BLACK); Enumeration enum = engine.alerts.keys(); while (enum.hasMoreElements()) { inPen.setFont(tag_font); inPen.drawBitmap(x, y, tag_bitmap); inPen.drawText(x + 3, y + 9, ((Character) enum.nextElement()).toString()); y += tag_height; } } public void setSize(int inWidth, int inHeight) { Rect r; super.setSize(inWidth, inHeight); mPlainLineBreaker = new LineBreaker("", mPlainFont, inWidth - 8, 0); mBoldLineBreaker = new LineBreaker("", mBoldFont, inWidth - 8, 0); r = getBounds(); r.inset(kBorder); mNumDisplayLines = r.getHeight() / mLineHeight; } public void AddChannel(String inText) { AddLines(inText, 0); } public void AddSent(String inText) { AddLines(inText, 3); } public void AddPrivate(String inText) { AddLines(inText, 1); } public void AddServer(String inText) { AddLines(inText, 2); } void AddLines(String inText, int glyph) { if (engine.app.doSmileys) AddLinesIcon(inText, glyph); else AddLinesPlain(inText, glyph); } private void AddLinesPlain(String inText, int glyph) { int firstChar = 0, lastChar = 0; boolean firstLine = true; LineBreaker lineBreaker; //* If we're scrolled up then we need to mark this line as the first //* incoming line that we missed; if (0 == mCurrentSelection) mFirstMissed = false; //* Pick the right line breaker depending on the font lineBreaker = mPlainLineBreaker; lineBreaker.setText(inText); while (lastChar < inText.length()) { String s; ChatLine line; lastChar = lineBreaker.nextLineBreak(firstChar); s = inText.substring(firstChar, lastChar); line = new ChatLine(s, glyph, firstLine, mFirstMissed); AddLine(line, glyph); firstLine = false; mFirstMissed = false; firstChar = lastChar; } TrimForLength(); } private void AddLinesIcon(String inText, int glyph) { int firstChar = 0, lastChar = 0; boolean firstLine = true; //LineBreaker lineBreaker; SmileyEngine smileyEngine; //* If we're scrolled up then we need to mark this line as the first //* incoming line that we missed; if (0 == mCurrentSelection) mFirstMissed = false; //* Pick the right line breaker depending on the font //lineBreaker = mPlainLineBreaker; //lineBreaker.setText(inText); if (inText.startsWith("<::::>")) { // server flag inText = SmileyEngine.ICON_FLAG + inText.substring(6); } if (inText.startsWith("<*>")) { // cognet++ message inText = SmileyEngine.ICON_COG + inText.substring(3); } if (inText.startsWith("* ")) { // action flag inText = SmileyEngine.ICON_BULLET + inText.substring(1); } if (inText.startsWith("<-> ")) { // info flag inText = SmileyEngine.ICON_INFO + inText.substring(3); } smileyEngine = new SmileyEngine(mPlainFont, inText); String strLine; while ((strLine = smileyEngine.getNext(getWidth() - 8)) != null) { String s; ChatLine line; line = new ChatLine(strLine, glyph, firstLine, mFirstMissed); AddLine(line, glyph); firstLine = false; mFirstMissed = false; } TrimForLength(); } public void AddLine(ChatLine inLine, int glyph) { Rect r = getBounds(); int numLines; ChatLine line; boolean atBottom = false; if (mBottomDisplayLine == mTail) atBottom = true; mNumLines++; mTextSize += inLine.mText.length(); r.inset(kBorder); numLines = r.getHeight() / mLineHeight; if (null == mHead) { mHead = inLine; mBottomDisplayLine = inLine; mTail = inLine; return; } mTail.mNext = inLine; inLine.mPrev = mTail; mTail = inLine; if (atBottom /* || output */) { mCurrentSelection = 0; mBottomDisplayLine = mTail; } else { mCurrentSelection++; } } void TrimForLength() { while (mTextSize > mLimit) { if (mNumDisplayLines >= (mNumLines - mCurrentSelection)) { mCurrentSelection--; mBottomDisplayLine = mBottomDisplayLine.mNext; } mTextSize -= mHead.mText.length(); mHead.mNext.mPrev = null; mHead = mHead.mNext; mNumLines--; } } void ScrollUp() { if ((mNumLines - mCurrentSelection) <= mNumDisplayLines) return; mCurrentSelection++; mBottomDisplayLine = mBottomDisplayLine.mPrev; mFirstMissed = true; } void ScrollDown() { if (mCurrentSelection == 0) return; mCurrentSelection--; mBottomDisplayLine = mBottomDisplayLine.mNext; if (0 == mCurrentSelection) mFirstMissed = false; } public void Clear() { mTextSize = 0; mNumLines = 0; mCurrentSelection = 0; mHead = null; mTail = null; mBottomDisplayLine = null; mFirstMissed = false; } void setPlainFont(Font f) { Clear(); mPlainFont = f; mAscent = mPlainFont.getAscent() + mPlainFont.getDescent(); mLineHeight = mAscent + kLeading - 2; mNumDisplayLines = getHeight() / mLineHeight; } void setEmoticons(boolean onOff) { Clear(); engine.app.doSmileys = onOff; } private int mLimit; private int mTextSize; private int mNumDisplayLines; private int mNumLines; private int mCurrentSelection; private int mAscent; private int mLineHeight; private ChatLine mHead; private ChatLine mBottomDisplayLine; private ChatLine mTail; private Font mPlainFont; private Font mBoldFont; private LineBreaker mPlainLineBreaker; private LineBreaker mBoldLineBreaker; private boolean mFirstMissed; static final int kBorder = 2; static final int kLeading = 2; Engine engine; } class ChatLine { public ChatLine(String inText, int glyph, boolean inFirstLine, boolean inFirstMissed) { mText = inText; mGlyph = glyph; mFirstLine = inFirstLine; mFirstMissed = inFirstMissed; } String mText; int mGlyph; boolean mFirstLine; boolean mFirstMissed; ChatLine mPrev; ChatLine mNext; }