?? postcardcanvas.java
字號:
// Copyright 2002 Nokia Corporation.
//
// THIS SOURCE CODE IS PROVIDED 'AS IS', WITH NO WARRANTIES WHATSOEVER,
// EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, FITNESS
// FOR ANY PARTICULAR PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE
// OR TRADE PRACTICE, RELATING TO THE SOURCE CODE OR ANY WARRANTY OTHERWISE
// ARISING OUT OF ANY PROPOSAL, SPECIFICATION, OR SAMPLE AND WITH NO
// OBLIGATION OF NOKIA TO PROVIDE THE LICENSEE WITH ANY MAINTENANCE OR
// SUPPORT. FURTHERMORE, NOKIA MAKES NO WARRANTY THAT EXERCISE OF THE
// RIGHTS GRANTED HEREUNDER DOES NOT INFRINGE OR MAY NOT CAUSE INFRINGEMENT
// OF ANY PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OWNED OR CONTROLLED
// BY THIRD PARTIES
//
// Furthermore, information provided in this source code is preliminary,
// and may be changed substantially prior to final release. Nokia Corporation
// retains the right to make changes to this source code at
// any time, without notice. This source code is provided for informational
// purposes only.
//
// Nokia and Nokia Connecting People are registered trademarks of Nokia
// Corporation.
// Java and all Java-based marks are trademarks or registered trademarks of
// Sun Microsystems, Inc.
// Other product and company names mentioned herein may be trademarks or
// trade names of their respective owners.
//
// A non-exclusive, non-transferable, worldwide, limited license is hereby
// granted to the Licensee to download, print, reproduce and modify the
// source code. The licensee has the right to market, sell, distribute and
// make available the source code in original or modified form only when
// incorporated into the programs developed by the Licensee. No other
// license, express or implied, by estoppel or otherwise, to any other
// intellectual property rights is granted herein.
package example.postcard;
import javax.microedition.lcdui.*;
import java.util.Random;
import java.util.Vector;
// The main canvas of the MIDlet. It contains text and a floating
// animation, and plays a tune (Smart Messaging Ringing Tone format).
class PostcardCanvas
extends Canvas
implements CommandListener, Runnable
{
private static final int BORDER = 2;
private static final int SLIDER_WIDTH = 4;
private static final Font FONT = Font.getFont(Font.FACE_MONOSPACE,
Font.STYLE_PLAIN, Font.SIZE_SMALL);
private final PostcardMIDlet midlet;
private final Command exitCommand;
private final Command silentCommand;
private final Command playCommand;
private final ContinuousTunePlayer player;
private final int lineHeight, lineWidth, maxLines;
private final Vector textLines = new Vector();
private int topLine = 0;
private volatile Thread animationThread = null;
private Animation animation = null;
private boolean isUpPressed = false;
private boolean isDownPressed = false;
private boolean firstPlayRequest = true;
private volatile boolean isPlaying = false;
// The constructor for the PostcardCanvas:
// 'midlet' is the parent MIDlet, used for callbacks such as exit requests.
// 'message' is the text message to be displayed.
// 'tune' is a hexadecimal representation of the tune to be played.
// The bytes are in Smart Messaging Ringing Tone format.
// 'animationSequence' is the sequence of animation images.
// It may be null. In that case, no animation is
// performed and just the text and tune are used.
PostcardCanvas(PostcardMIDlet midlet, String message, String tune,
AnimationSequence animationSequence)
{
this.midlet = midlet;
lineWidth = getWidth() - (2 * BORDER) - SLIDER_WIDTH;
lineHeight = FONT.getHeight();
maxLines = (getHeight() - (2 * BORDER)) / lineHeight;
// Split the message into multiple lines of text.
// The approach used isn't very smart. It doesn't do word
// splitting or word wrapping, to keep this example simple.
if (FONT.stringWidth(message) < lineWidth)
{
// the message fits in a single line of text
textLines.addElement(message);
}
else
{
// multiple lines of text are needed
int offset = 0;
int len = 1;
while((offset + len) <= message.length())
{
while(((offset + len) <= message.length()) &&
(FONT.substringWidth(message, offset, len) <= lineWidth))
{
len++;
}
textLines.addElement(message.substring(offset,
offset + len - 1));
offset += (len - 1);
len = 1;
}
}
// create the animation sequence
if (animationSequence != null)
{
try
{
animation = new Animation(animationSequence, BORDER, BORDER,
(getWidth() - SLIDER_WIDTH - BORDER),
(getHeight() - BORDER));
}
catch(Exception e)
{
// By default, animation is null.
}
}
// create the tune player
player = makeContinuousTunePlayer();
if (tune != null)
{
try
{
player.setTune(tune);
}
catch(Exception e)
{
// There is some problem with the setting (e.g. invalid
// hexadecimal data, invalide tune data) or playing the tune.
// A tune will not be played in this case.
}
}
// add the screen's commands
exitCommand = new Command("Exit", Command.EXIT, 1);
addCommand(exitCommand);
if (player.hasSoundSupport())
{
playCommand = new Command("Play", Command.SCREEN, 2);
silentCommand = new Command("Silent", Command.SCREEN, 2);
addCommand(playCommand);
}
else
{
playCommand = null;
silentCommand = null;
}
setCommandListener(this);
}
synchronized void start()
{
animationThread = new Thread(this);
animationThread.start();
player.restart();
}
synchronized void stop()
{
animationThread = null;
player.stop();
}
public void run()
{
int millisPerTick = 100;
Thread currentThread = Thread.currentThread();
try
{
// This ends when animationThread is set to null, or when
// it is subsequently set to a new thread; either way, the
// current thread should terminate
while (currentThread == animationThread)
{
long startTime = System.currentTimeMillis();
// No animation progress if we are hidden by a system screen.
if (isShown())
{
tick();
repaint(0, 0, getWidth(), getHeight());
serviceRepaints();
}
long timeTaken = System.currentTimeMillis() - startTime;
if (timeTaken < millisPerTick)
{
synchronized (this)
{
wait(millisPerTick - timeTaken);
}
}
else
{
currentThread.yield();
}
}
}
catch (InterruptedException e)
{
}
}
private void tick()
{
if (isUpPressed)
{
if ((topLine - 1) < 0)
{
topLine = 0;
}
else
{
topLine--;
}
}
else if (isDownPressed)
{
if (textLines.size() > 0)
{
if ((topLine + maxLines) < textLines.size())
{
topLine++;
}
}
}
if (animation != null)
{
animation.tick();
}
}
public void paint(Graphics g)
{
// wipe the entire canavas clean
g.setColor(0xffffff); // WHITE
g.fillRect(0, 0, getWidth(), getHeight());
// draw the animation
g.setColor(0x000000); // BLACK
g.setFont(FONT);
int ix=0;
for (ix=0; ((ix < maxLines) && ((topLine + ix) < textLines.size()));
ix++)
{
g.drawString((String)textLines.elementAt(topLine + ix),
BORDER, (BORDER + (lineHeight * ix)),
(Graphics.TOP | Graphics.LEFT));
}
// Add a 'slider' in case the number of text lines
// is longer than fits on one display.
if (textLines.size() > maxLines)
{
drawSlider(g, topLine, textLines.size());
}
animation.draw(g);
}
public void keyPressed(int keyCode)
{
int action = getGameAction(keyCode);
if (action == UP)
{
isUpPressed = true;
isDownPressed = false;
if (topLine > 0)
{
topLine--;
}
}
else if (action == DOWN)
{
isDownPressed = true;
isUpPressed = false;
if((topLine + maxLines) < textLines.size())
{
topLine++;
}
}
}
public void keyReleased(int keyCode)
{
int action = getGameAction(keyCode);
if (action == UP)
{
isUpPressed = false;
}
else if (action == DOWN)
{
isDownPressed = false;
}
}
// If the number of text lines exceeds the amount that can
// be displayed in one screen, then a text slider is drawn
// to indicate the position of the displayed text within
// the entire text message.
private void drawSlider(Graphics g, int index, int length)
{
int x = getWidth() - SLIDER_WIDTH;
int y = 0;
// The text slider is drawn in the area from
// {x, y} = {x, 0} to {x + SLIDER_WIDTH, getHeight()}
int sy = 2; // initial slider y-position
int sh = 6; // slider height in pixels
// Leave a 2 pixel offset at the top and bottom, for the slider's rail
// to protrude past the slider. The rail's length = full canvas height.
int syMax = getHeight() - sh - 2 - 2;
if ((index == 0) || (length == 0))
{
sy = 2;
}
else
{
sy = 2 + ((syMax * index) / length);
}
// (x+0 is empty space)
g.setColor(0x000000); // BLACK
g.drawLine(x+1, sy, x+1, sy+sh); // slider
g.drawLine(x+2, 0, x+2, getHeight()); // rail
g.drawLine(x+3, sy, x+3, sy+sh); // slider
g.setColor(0xffffff); // WHITE
g.drawLine(x+2, sy, x+2, sy+sh); // slider
}
public void commandAction(Command c, Displayable d)
{
if (c == exitCommand)
{
stop();
midlet.exitRequested();
}
else if (player.hasSoundSupport() && (c == silentCommand))
{
setIsPlaying(false);
player.stop();
removeCommand(silentCommand);
addCommand(playCommand);
}
else if (player.hasSoundSupport() && (c == playCommand))
{
setIsPlaying(true);
if (firstPlayRequest)
{
firstPlayRequest = false;
player.playContinuously();
}
else
{
player.restart();
}
removeCommand(playCommand);
addCommand(silentCommand);
}
}
private synchronized void setIsPlaying(boolean isPlaying)
{
this.isPlaying = isPlaying;
}
public void hideNotify()
{
setIsPlaying(false);
player.stop();
// We aren't sure which commands are currently available;
// we remove both to be safe and add the play command so
// it's available when the MIDlet is visible again.
// Rather than using 'showNotify' to resume playing, allow
// a manually requested resume using the 'Play' command.
removeCommand(playCommand);
removeCommand(silentCommand);
addCommand(playCommand);
}
private static ContinuousTunePlayer makeContinuousTunePlayer()
{
// Other types of ContinuousTunePlayers could be
// added here in the future if needed.
ContinuousTunePlayer player;
try
{
// Throw an exception if no Nokia UI API available.
Class.forName("com.nokia.mid.sound.Sound");
Class clas = Class.forName(
"example.postcard.NokiaContinuousTunePlayer");
player = (ContinuousTunePlayer)(clas.newInstance());
}
catch (Exception e)
{
player = new ContinuousTunePlayer();
}
return player;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -