1 | /*
|
---|
2 | * cognet chat app
|
---|
3 | *
|
---|
4 | * Copyright 2003, Brian Swetland <swetland@frotz.net>
|
---|
5 | * See LICENSE for redistribution terms
|
---|
6 | *
|
---|
7 | * Derived from:
|
---|
8 | *
|
---|
9 | * @(#)ChatHistory.java 1.0 01/03/23
|
---|
10 | *
|
---|
11 | * Copyright 2000 by Danger Research, Inc.
|
---|
12 | * 165 University Avenue, Palo Alto, CA 94301
|
---|
13 | * All rights reserved.
|
---|
14 | * See SAMPLE_CODE_LICENSE for redistribution terms.
|
---|
15 | *
|
---|
16 | */
|
---|
17 |
|
---|
18 | package org.twodot.cognet;
|
---|
19 |
|
---|
20 | import danger.ui.*;
|
---|
21 | import danger.util.LineBreaker;
|
---|
22 | import java.util.Enumeration;
|
---|
23 |
|
---|
24 | public class ChatHistory extends View
|
---|
25 | {
|
---|
26 | public
|
---|
27 | ChatHistory(int inSizeLimit, Engine e)
|
---|
28 | {
|
---|
29 | Rect r;
|
---|
30 |
|
---|
31 | mPlainFont = Font.findSystemFont();
|
---|
32 | mBoldFont = Font.findSystemFont();
|
---|
33 |
|
---|
34 | mAscent = mBoldFont.getAscent() + mBoldFont.getDescent();
|
---|
35 | mLineHeight = mAscent + kLeading - 2;
|
---|
36 |
|
---|
37 | mLimit = inSizeLimit;
|
---|
38 |
|
---|
39 | setSize(20, 10);
|
---|
40 | engine = e;
|
---|
41 |
|
---|
42 | tag_bitmap = engine.app.bm_tag;
|
---|
43 | tag_width = tag_bitmap.getWidth();
|
---|
44 | tag_height = tag_bitmap.getHeight();
|
---|
45 | tag_font = Font.findFont("Bort7");
|
---|
46 | }
|
---|
47 |
|
---|
48 | Bitmap tag_bitmap;
|
---|
49 | int tag_width, tag_height;
|
---|
50 | Font tag_font;
|
---|
51 |
|
---|
52 |
|
---|
53 | public void
|
---|
54 | paint(Pen inPen)
|
---|
55 | {
|
---|
56 |
|
---|
57 | Rect r = getBounds();
|
---|
58 | int i, x, y;
|
---|
59 | ChatLine index = mBottomDisplayLine;
|
---|
60 |
|
---|
61 | //* Clear the area
|
---|
62 | if(mCurrentSelection != 0){
|
---|
63 | inPen.setColor(Color.GRAY10);
|
---|
64 | } else {
|
---|
65 | inPen.setColor(Color.WHITE);
|
---|
66 | }
|
---|
67 | inPen.fillRect(r);
|
---|
68 |
|
---|
69 | inPen.setColor(Color.BLACK);
|
---|
70 |
|
---|
71 | x = r.left;
|
---|
72 | y = mLineHeight * (mNumDisplayLines - 1);
|
---|
73 | y += mAscent;
|
---|
74 | y += r.top;
|
---|
75 |
|
---|
76 | SmileyEngine smiley = new SmileyEngine(mPlainFont);
|
---|
77 | inPen.setFont(mPlainFont);
|
---|
78 | //* Draw the individual lines
|
---|
79 | while ((y > r.top) && (null != index)) {
|
---|
80 | // if (engine.app.doSmileys)
|
---|
81 | smiley.drawString(x,y,index.mText, inPen);
|
---|
82 | // else
|
---|
83 | // inPen.drawText(x, y, index.mText);
|
---|
84 |
|
---|
85 | y -= mLineHeight;
|
---|
86 | index = index.mPrev;
|
---|
87 | }
|
---|
88 |
|
---|
89 | y = 0;
|
---|
90 | x = r.right - tag_width;
|
---|
91 |
|
---|
92 |
|
---|
93 | inPen.setColor(Color.BLACK);
|
---|
94 |
|
---|
95 | Enumeration enum = engine.alerts.keys();
|
---|
96 | while (enum.hasMoreElements()) {
|
---|
97 | inPen.setFont(tag_font);
|
---|
98 | inPen.drawBitmap(x, y, tag_bitmap);
|
---|
99 | inPen.drawText(x + 3, y + 9, ((Character) enum.nextElement()).toString());
|
---|
100 | y += tag_height;
|
---|
101 | }
|
---|
102 | }
|
---|
103 |
|
---|
104 | public void
|
---|
105 | setSize(int inWidth, int inHeight)
|
---|
106 | {
|
---|
107 | Rect r;
|
---|
108 |
|
---|
109 | super.setSize(inWidth, inHeight);
|
---|
110 |
|
---|
111 | mPlainLineBreaker = new LineBreaker("", mPlainFont, inWidth - 8, 0);
|
---|
112 | mBoldLineBreaker = new LineBreaker("", mBoldFont, inWidth - 8, 0);
|
---|
113 |
|
---|
114 | r = getBounds();
|
---|
115 | r.inset(kBorder);
|
---|
116 |
|
---|
117 | mNumDisplayLines = r.getHeight() / mLineHeight;
|
---|
118 | }
|
---|
119 |
|
---|
120 | public void
|
---|
121 | AddChannel(String inText) {
|
---|
122 | AddLines(inText, 0);
|
---|
123 | }
|
---|
124 |
|
---|
125 | public void
|
---|
126 | AddSent(String inText) {
|
---|
127 | AddLines(inText, 3);
|
---|
128 | }
|
---|
129 |
|
---|
130 | public void
|
---|
131 | AddPrivate(String inText) {
|
---|
132 | AddLines(inText, 1);
|
---|
133 | }
|
---|
134 |
|
---|
135 | public void
|
---|
136 | AddServer(String inText) {
|
---|
137 | AddLines(inText, 2);
|
---|
138 | }
|
---|
139 |
|
---|
140 |
|
---|
141 | void AddLines(String inText, int glyph) {
|
---|
142 | if (engine.app.doSmileys)
|
---|
143 | AddLinesIcon(inText, glyph);
|
---|
144 | else
|
---|
145 | AddLinesPlain(inText, glyph);
|
---|
146 | }
|
---|
147 |
|
---|
148 | private void AddLinesPlain(String inText, int glyph)
|
---|
149 | {
|
---|
150 | int firstChar = 0, lastChar = 0;
|
---|
151 | boolean firstLine = true;
|
---|
152 | LineBreaker lineBreaker;
|
---|
153 |
|
---|
154 | //* If we're scrolled up then we need to mark this line as the first
|
---|
155 | //* incoming line that we missed;
|
---|
156 | if (0 == mCurrentSelection)
|
---|
157 | mFirstMissed = false;
|
---|
158 |
|
---|
159 | //* Pick the right line breaker depending on the font
|
---|
160 | lineBreaker = mPlainLineBreaker;
|
---|
161 |
|
---|
162 | lineBreaker.setText(inText);
|
---|
163 |
|
---|
164 | while (lastChar < inText.length())
|
---|
165 | {
|
---|
166 | String s;
|
---|
167 | ChatLine line;
|
---|
168 |
|
---|
169 | lastChar = lineBreaker.nextLineBreak(firstChar);
|
---|
170 |
|
---|
171 | s = inText.substring(firstChar, lastChar);
|
---|
172 | line = new ChatLine(s, glyph, firstLine, mFirstMissed);
|
---|
173 | AddLine(line, glyph);
|
---|
174 |
|
---|
175 | firstLine = false;
|
---|
176 | mFirstMissed = false;
|
---|
177 |
|
---|
178 | firstChar = lastChar;
|
---|
179 | }
|
---|
180 |
|
---|
181 | TrimForLength();
|
---|
182 | }
|
---|
183 |
|
---|
184 |
|
---|
185 | private void AddLinesIcon(String inText, int glyph)
|
---|
186 | {
|
---|
187 | int firstChar = 0, lastChar = 0;
|
---|
188 | boolean firstLine = true;
|
---|
189 | //LineBreaker lineBreaker;
|
---|
190 | SmileyEngine smileyEngine;
|
---|
191 |
|
---|
192 | //* If we're scrolled up then we need to mark this line as the first
|
---|
193 | //* incoming line that we missed;
|
---|
194 | if (0 == mCurrentSelection)
|
---|
195 | mFirstMissed = false;
|
---|
196 |
|
---|
197 | //* Pick the right line breaker depending on the font
|
---|
198 | //lineBreaker = mPlainLineBreaker;
|
---|
199 |
|
---|
200 | //lineBreaker.setText(inText);
|
---|
201 | if (inText.startsWith("<::::>")) {
|
---|
202 | // server flag
|
---|
203 | inText = SmileyEngine.ICON_FLAG + inText.substring(6);
|
---|
204 | }
|
---|
205 | if (inText.startsWith("<*>")) {
|
---|
206 | // cognet++ message
|
---|
207 | inText = SmileyEngine.ICON_COG + inText.substring(3);
|
---|
208 | }
|
---|
209 | if (inText.startsWith("* ")) {
|
---|
210 | // action flag
|
---|
211 | inText = SmileyEngine.ICON_BULLET + inText.substring(1);
|
---|
212 | }
|
---|
213 | if (inText.startsWith("<-> ")) {
|
---|
214 | // info flag
|
---|
215 | inText = SmileyEngine.ICON_INFO + inText.substring(3);
|
---|
216 | }
|
---|
217 |
|
---|
218 | smileyEngine = new SmileyEngine(mPlainFont, inText);
|
---|
219 | String strLine;
|
---|
220 |
|
---|
221 |
|
---|
222 | while ((strLine = smileyEngine.getNext(getWidth() - 8)) != null)
|
---|
223 | {
|
---|
224 | String s;
|
---|
225 | ChatLine line;
|
---|
226 |
|
---|
227 | line = new ChatLine(strLine, glyph, firstLine, mFirstMissed);
|
---|
228 | AddLine(line, glyph);
|
---|
229 |
|
---|
230 | firstLine = false;
|
---|
231 | mFirstMissed = false;
|
---|
232 |
|
---|
233 | }
|
---|
234 |
|
---|
235 | TrimForLength();
|
---|
236 | }
|
---|
237 |
|
---|
238 | public void
|
---|
239 | AddLine(ChatLine inLine, int glyph)
|
---|
240 | {
|
---|
241 | Rect r = getBounds();
|
---|
242 | int numLines;
|
---|
243 | ChatLine line;
|
---|
244 | boolean atBottom = false;
|
---|
245 |
|
---|
246 | if (mBottomDisplayLine == mTail)
|
---|
247 | atBottom = true;
|
---|
248 |
|
---|
249 | mNumLines++;
|
---|
250 | mTextSize += inLine.mText.length();
|
---|
251 |
|
---|
252 | r.inset(kBorder);
|
---|
253 | numLines = r.getHeight() / mLineHeight;
|
---|
254 |
|
---|
255 | if (null == mHead)
|
---|
256 | {
|
---|
257 | mHead = inLine;
|
---|
258 | mBottomDisplayLine = inLine;
|
---|
259 | mTail = inLine;
|
---|
260 |
|
---|
261 | return;
|
---|
262 | }
|
---|
263 |
|
---|
264 | mTail.mNext = inLine;
|
---|
265 | inLine.mPrev = mTail;
|
---|
266 | mTail = inLine;
|
---|
267 |
|
---|
268 | if (atBottom /* || output */)
|
---|
269 | {
|
---|
270 | mCurrentSelection = 0;
|
---|
271 | mBottomDisplayLine = mTail;
|
---|
272 | }
|
---|
273 | else
|
---|
274 | {
|
---|
275 | mCurrentSelection++;
|
---|
276 | }
|
---|
277 | }
|
---|
278 |
|
---|
279 | void
|
---|
280 | TrimForLength()
|
---|
281 | {
|
---|
282 | while (mTextSize > mLimit)
|
---|
283 | {
|
---|
284 | if (mNumDisplayLines >= (mNumLines - mCurrentSelection))
|
---|
285 | {
|
---|
286 | mCurrentSelection--;
|
---|
287 | mBottomDisplayLine = mBottomDisplayLine.mNext;
|
---|
288 | }
|
---|
289 |
|
---|
290 | mTextSize -= mHead.mText.length();
|
---|
291 |
|
---|
292 | mHead.mNext.mPrev = null;
|
---|
293 | mHead = mHead.mNext;
|
---|
294 |
|
---|
295 | mNumLines--;
|
---|
296 | }
|
---|
297 | }
|
---|
298 |
|
---|
299 | void
|
---|
300 | ScrollUp()
|
---|
301 | {
|
---|
302 | if ((mNumLines - mCurrentSelection) <= mNumDisplayLines)
|
---|
303 | return;
|
---|
304 |
|
---|
305 | mCurrentSelection++;
|
---|
306 | mBottomDisplayLine = mBottomDisplayLine.mPrev;
|
---|
307 |
|
---|
308 | mFirstMissed = true;
|
---|
309 | }
|
---|
310 |
|
---|
311 | void
|
---|
312 | ScrollDown()
|
---|
313 | {
|
---|
314 | if (mCurrentSelection == 0)
|
---|
315 | return;
|
---|
316 |
|
---|
317 | mCurrentSelection--;
|
---|
318 | mBottomDisplayLine = mBottomDisplayLine.mNext;
|
---|
319 |
|
---|
320 | if (0 == mCurrentSelection)
|
---|
321 | mFirstMissed = false;
|
---|
322 | }
|
---|
323 |
|
---|
324 | public void
|
---|
325 | Clear() {
|
---|
326 | mTextSize = 0;
|
---|
327 | mNumLines = 0;
|
---|
328 | mCurrentSelection = 0;
|
---|
329 | mHead = null;
|
---|
330 | mTail = null;
|
---|
331 | mBottomDisplayLine = null;
|
---|
332 | mFirstMissed = false;
|
---|
333 | }
|
---|
334 |
|
---|
335 | void setPlainFont(Font f) {
|
---|
336 | Clear();
|
---|
337 | mPlainFont = f;
|
---|
338 | mAscent = mPlainFont.getAscent() + mPlainFont.getDescent();
|
---|
339 | mLineHeight = mAscent + kLeading - 2;
|
---|
340 | mNumDisplayLines = getHeight() / mLineHeight;
|
---|
341 | }
|
---|
342 |
|
---|
343 | void setEmoticons(boolean onOff) {
|
---|
344 | Clear();
|
---|
345 | engine.app.doSmileys = onOff;
|
---|
346 | }
|
---|
347 |
|
---|
348 | private int mLimit;
|
---|
349 | private int mTextSize;
|
---|
350 | private int mNumDisplayLines;
|
---|
351 |
|
---|
352 | private int mNumLines;
|
---|
353 | private int mCurrentSelection;
|
---|
354 |
|
---|
355 | private int mAscent;
|
---|
356 | private int mLineHeight;
|
---|
357 |
|
---|
358 | private ChatLine mHead;
|
---|
359 | private ChatLine mBottomDisplayLine;
|
---|
360 | private ChatLine mTail;
|
---|
361 |
|
---|
362 | private Font mPlainFont;
|
---|
363 | private Font mBoldFont;
|
---|
364 |
|
---|
365 | private LineBreaker mPlainLineBreaker;
|
---|
366 | private LineBreaker mBoldLineBreaker;
|
---|
367 |
|
---|
368 | private boolean mFirstMissed;
|
---|
369 |
|
---|
370 | static final int kBorder = 2;
|
---|
371 | static final int kLeading = 2;
|
---|
372 | Engine engine;
|
---|
373 | }
|
---|
374 |
|
---|
375 | class ChatLine
|
---|
376 | {
|
---|
377 | public
|
---|
378 | ChatLine(String inText, int glyph, boolean inFirstLine, boolean inFirstMissed)
|
---|
379 | {
|
---|
380 | mText = inText;
|
---|
381 | mGlyph = glyph;
|
---|
382 | mFirstLine = inFirstLine;
|
---|
383 | mFirstMissed = inFirstMissed;
|
---|
384 | }
|
---|
385 |
|
---|
386 | String mText;
|
---|
387 | int mGlyph;
|
---|
388 | boolean mFirstLine;
|
---|
389 | boolean mFirstMissed;
|
---|
390 |
|
---|
391 | ChatLine mPrev;
|
---|
392 | ChatLine mNext;
|
---|
393 | }
|
---|