📄 popup.java
字号:
// For Sony Ericsson Mobile Communications
package bluegammon.gui.popup;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import bluegammon.Device;
import bluegammon.Resources;
/**
* <p>
* The <code>Popup</code> represents a popup with text and zero or many
* alternatives that user can select among. A popup can be shown for a
* specific amount of time or forever, the latter case requiring a user to close
* the popup. The choice of the alternatives can be reported by implementing
* a <code>PopupListener</code>
* </p><p>
* This class contains all functionality of a popup, i.e. interaction,
* graphics and callback.
* </p>
*/
public class Popup implements Runnable
{
/** Preset alternative containing OK */
public static final char[][] ALT_OK;
/** Preset alternative containing CANCEL */
public static final char[][] ALT_CANCEL;
/** Preset alternatives containing YES and NO */
public static final char[][] ALT_YES_NO;
/** Preset alternatives containing OK and CANCEL */
public static final char[][] ALT_OK_CANCEL;
/** Preset alternatives containing YES, NO, and CANCEL */
public static final char[][] ALT_YES_NO_CANCEL;
// Setup preset alternatives
static
{
ALT_OK = new char[1][];
ALT_OK[0] = Resources.getChars(Resources.TXT_OK);
ALT_CANCEL = new char[1][];
ALT_CANCEL[0] = Resources.getChars(Resources.TXT_CANCEL);
ALT_YES_NO = new char[2][];
ALT_YES_NO[0] = Resources.getChars(Resources.TXT_YES);
ALT_YES_NO[1] = Resources.getChars(Resources.TXT_NO);
ALT_OK_CANCEL = new char[2][];
ALT_OK_CANCEL[0] = ALT_OK[0];
ALT_OK_CANCEL[1] = ALT_CANCEL[0];
ALT_YES_NO_CANCEL = new char[3][];
ALT_YES_NO_CANCEL[0] = ALT_YES_NO[0];
ALT_YES_NO_CANCEL[1] = ALT_YES_NO[1];
ALT_YES_NO_CANCEL[2] = ALT_CANCEL[0];
}
/** The text to show in the popup */
protected char[] m_text;
/** Number of alternatives to select in popup */
protected byte m_alternatives;
/** Array of texts as chararrays in alternatives */
protected char[][] m_altTexts;
/** Time out in seconds */
protected byte m_timeOut;
/** Alternative reported back if timeout is reached */
protected byte m_timeOutAlt;
/** Current alternative index */
protected byte m_curAlt;
/** Listener to this popup */
protected PopupListener m_listener;
/** Flag indicating if popup is active */
protected volatile boolean m_active = true;
/** Width of popup */
protected int m_w;
/** Height of popup */
protected int m_h;
/**
* Indices indicating where to break the text organized as [line][0 = start
* char offset | 1 = char len]
*/
protected int[][] m_breakTextData;
/** Number of visible text lines in popup */
protected int m_visibleLines;
/** Current line offset */
protected int m_curLine;
/** Maximum line offset */
protected int m_maxLine;
/** Horizontal coordinate offset of text */
protected int m_yoffset;
/** The life time of this popup */
protected long m_endTime;
// Graphical data
protected Font m_font = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD,
Font.SIZE_SMALL);
protected int m_fontHeight = m_font.getHeight();
protected int m_borderColor = 0xdd0000;
protected int m_backgroundColor = 0xcc440000;
protected int m_textColor = 0xffffff;
protected int m_alternativeColor = 0xff2200;
protected int m_selectedAlternativeColor = 0xffffff;
protected static int[] m_rgbData;
/**
* Space between actual popup graphics and the rectangle reported in method
* <code>init</code>
*/
protected static final int OFFSET_POPUP = 8;
/** Space between popup edges and text content */
protected static final int OFFSET_TEXT = 2;
/** Space between alternative texts */
protected static final int OFFSET_ALT = 4;
/** Scrollbar width */
protected static final int SB_WIDTH = 5;
/** Textbreak constants */
protected static final char[] TEXTBREAKS =
{ ' ', '?', ';', ',', '.', '!',
':', '-', '=', '(', ')', '[', ']' };
/** New line constant */
protected static final char NEWLINE = '\n';
/**
* Creates an uninitialized popup. Call <code>init</code> to setup
* this popup instance. This constructor is used for instance cache
* functionality.
*/
public Popup() {}
/**
* Initializes this popup.
*
* @param text The text to show in popup.
* @param altTexts The alternatives to select among or null if no choices.
* @param timeOut Time out for this popup in seconds (0 means no timeout).
* @param defaultAlt Index of default alternative.
* @param timeOutAlt Alternative index reported on time out.
* @param listener The popuplistener being reported on selection or timeout or null
* if no listener.
* @param width Canvas width.
* @param height Canvas height.
*/
public void init(char[] text, char[][] altTexts, byte timeOut,
byte defaultAlt, byte timeOutAlt, PopupListener listener, int width,
int height)
{
// Set parameters
m_text = text;
m_altTexts = altTexts;
if (altTexts != null)
{
m_alternatives = (byte) altTexts.length;
}
else
{
m_alternatives = 0;
}
m_timeOut = timeOut;
m_timeOutAlt = timeOutAlt;
m_listener = listener;
m_curAlt = defaultAlt;
m_w = width - (OFFSET_POPUP << 1);
m_h = height - (OFFSET_POPUP << 1);
m_active = true;
if (m_timeOut > 0)
{
// Set timeout
m_endTime = System.currentTimeMillis() + (m_timeOut * 1000);
}
else if (m_alternatives > 0)
{
// No timeout
m_endTime = 0;
}
else
{
// This should never happen - a popup with no alternatives and no timeout
m_endTime = System.currentTimeMillis();
}
m_visibleLines =
Math.max(1, ((m_h - (OFFSET_TEXT << 1)) / m_fontHeight) - 1);
int w = m_w - (OFFSET_TEXT << 1) - (SB_WIDTH << 1);
m_curLine = 0;
m_breakTextData = breakString(text, w);
// Calculate height
m_yoffset = 0;
m_maxLine = m_breakTextData.length - m_visibleLines + 1;
if (m_breakTextData.length < m_visibleLines)
{
int newH = m_breakTextData.length * m_fontHeight;
if (m_alternatives > 0)
newH += m_fontHeight;
newH += OFFSET_TEXT + OFFSET_ALT;
m_yoffset = (m_h - newH) >> 1;
m_h = newH;
}
// Create transparent rgb buffer if needed (8 lines)
if (m_rgbData == null || m_rgbData.length != m_w * 8)
{
m_rgbData = new int[m_w * 8];
for (int i = 0; i < m_rgbData.length; i++)
{
m_rgbData[i] = m_backgroundColor;
}
}
// Start poll thread
new Thread(this, "PopupPoll").start();
}
/**
* Breaks specified character array and returns a break matrix by line,
* organized as [line][0 | 1] where 0 means starting offset in text for this
* line, 1 means number of characters of this line.
*
* @param text The string to break
* @param width Width in pixels to break on
* @return A break index table
*/
protected int[][] breakString(char[] text, int width)
{
// Count text lines
int offset = 0;
int lines = 0;
int newOffset;
while (offset < text.length)
{
newOffset =
findNextBreak(text, offset, text.length - offset, width, m_font);
offset = newOffset;
lines++;
}
int[][] indices = new int[lines][2];
// Setting offset data
lines = 0;
offset = 0;
while (offset < text.length)
{
newOffset =
findNextBreak(text, offset, text.length - offset, width, m_font);
indices[lines][0] = offset;
indices[lines][1] = newOffset - offset;
lines++;
offset = newOffset;
}
return indices;
}
/**
* Returns next break when breaking a string.
*
* @param text The chars to calculate on
* @param offset From what offset to read in chars
* @param len How many characters to read
* @param w Width
* @param f Font
* @return Offset of next break or length of text if no more breaks
*/
public int findNextBreak(char[] text, int offset, int len, int w, Font f)
{
int breakOffset = offset;
int textW = 0;
int niceB = -1;
char c;
charLoop: while (breakOffset <= offset + len && textW < w)
{
if (breakOffset == offset + len)
c = TEXTBREAKS[0]; // last character + 1, fake break char
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -