/** * BlueCove - Java library for Bluetooth * Copyright (C) 2006-2009 Vlad Skarzhevskyy * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * @author vlads * @version $Id$ */ package org.bluecove.tester.me; import java.util.Vector; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; import org.bluecove.tester.log.Logger; import org.bluecove.tester.log.LoggerAppender; import org.bluecove.tester.util.TimeUtils; public class LoggerCanvas extends Canvas implements LoggerAppender { protected boolean showLogDebug = true; public static boolean logTimeStamp = false; public static boolean logTimeStampMillisecond = true; private int line; private int lineOffsetY; private int lineOffsetX; private Vector logMessages = new Vector(); private int errorCount = 0; private int logLine = 0; private int logScrollX; private int logVisibleLines = 0; private int logMessagesSownSize = 0; private boolean movingCursor = false; private boolean logLastEvenVisible = true; protected int backgroundColor = 255; protected int fontColor = 0; private long nextMemroyUpdate = 0; private int nextMemroyStatusLen = 0; public LoggerCanvas() { Logger.addAppender(this); } protected String getCanvasTitleText() { return null; } protected String getCanvasStatusText() { return null; } protected void paintBackground(Graphics g, int width, int height) { } protected void paintMemoryStatus(Graphics g, int y, int width, int height) { long now = System.currentTimeMillis(); if (nextMemroyUpdate < now) { // Next Update in 5 secons nextMemroyUpdate = now + 1000 * 5; Runtime r = Runtime.getRuntime(); long total = r.totalMemory(); long used = total - r.freeMemory(); nextMemroyStatusLen = (int) ((used * width) / total); } g.drawLine(0, y, nextMemroyStatusLen, y); } public int writeln(Graphics g, String s) { int h = (g.getFont().getHeight() + 1); int y = lineOffsetY + h * line; g.drawString(s, lineOffsetX, y, Graphics.LEFT | Graphics.TOP); line++; return y + h; } protected void paint(Graphics g) { lineOffsetY = 0; lineOffsetX = 0; line = 0; int width = getWidth(); int height = getHeight(); g.setGrayScale(backgroundColor); g.fillRect(0, 0, width, height); paintBackground(g, width, height); g.setColor(fontColor); int lastY = 0; String title = getCanvasTitleText(); if (title != null) { lastY = writeln(g, title); } paintMemoryStatus(g, lastY, width, height); line = 0; lineOffsetY = lastY + 2; Font font = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL); g.setFont(font); String status = getCanvasStatusText(); if (status != null) { lastY = writeln(g, status); } int lineHeight = g.getFont().getHeight() + 1; logVisibleLines = (height - lastY) / lineHeight; lineOffsetX = logScrollX; if (!movingCursor && logLastEvenVisible) { if (((logLine + logVisibleLines) < logMessages.size())) { setLogEndLine(); } } movingCursor = false; logMessagesSownSize = logMessages.size(); int logIndex = logLine; while (((lastY) < height) && (logIndex < logMessagesSownSize)) { try { String message = (String) logMessages.elementAt(logIndex); lastY = writeln(g, message); logIndex++; } catch (ArrayIndexOutOfBoundsException e) { logLastEvenVisible = true; return; } } logLastEvenVisible = (logIndex == logMessagesSownSize); } protected void logScrollBottom() { logScrollX = 0; setLogEndLine(); } protected void logLinesMove(int action) { switch (action) { case UP: if (logLine > 0) { logLine--; movingCursor = true; } break; case DOWN: if ((logLine + logVisibleLines - 1) < logMessages.size()) { logLine++; } break; case RIGHT: if (logScrollX > -500) { logScrollX -= 20; } break; case LEFT: if (logScrollX < 0) { logScrollX += 20; } break; default: return; } } public void appendLog(int level, String message, Throwable throwable) { if (!showLogDebug && (level == Logger.DEBUG)) { return; } StringBuffer buf = new StringBuffer(); if (logTimeStamp) { TimeUtils.appendTimeStampNow(buf, logTimeStampMillisecond).append(' '); } switch (level) { case Logger.ERROR: errorCount++; buf.append("e."); break; case Logger.WARN: buf.append("w."); break; case Logger.INFO: buf.append("i."); break; } buf.append(message); if (throwable != null) { buf.append(' '); String className = throwable.getClass().getName(); buf.append(className.substring(1 + className.lastIndexOf('.'))); buf.append(':'); buf.append(throwable.getMessage()); } String m = buf.toString().replace('\t', ' '); int cr = m.indexOf("\n"); while (cr != -1) { logMessages.addElement(m.substring(0, cr)); m = m.substring(cr + 1); cr = m.indexOf("\n"); } logMessages.addElement(m); int logMax = 500; if (logMessages.size() >= logMax) { Vector newLogMessages = new Vector(); for (int i = logMax - 5; i < logMax; i++) { newLogMessages.addElement(logMessages.elementAt(i)); } Vector prevLogMessages = logMessages; logMessages = newLogMessages; // GC helper prevLogMessages.removeAllElements(); logLine = 0; } if (logLastEvenVisible) { // BlueCoveTestMIDlet.display.flashBacklight(0); repaint(); } } private void setLogEndLine() { logLine = logMessages.size() - logVisibleLines; if (logLine < 0) { logLine = 0; } } protected void clearLog() { logMessages.removeAllElements(); errorCount = 0; logLine = 0; logScrollX = 0; } }