//Title: BlipApplet
//Version:
//Copyright: Copyright (c) 1998
//Author: Matt Jensen
//Company: OQ.org
//Description:A simple Java applet to receive OQ messages while logged in as a "guest".
package org.openqueue.applet1;
import java.awt.*;
import java.applet.*;
import java.util.Vector;
import java.net.URL;
import OQAppletMessage;
public class OQApplet extends Applet implements SimpleOQAwareness {
protected OQConversationThread bcThread;
boolean isStandalone = false;
protected Vector messages; // OQAppletMessages.
private Color myBackColor;
private Color myTextColor;
private Color myClickColor;
private Font myFont;
private FontMetrics myFontMetrics;
private Image buffered_image = null;
private Dimension oldDim;
private String defaultStatusMessage;
private boolean CurrentlyReceiving = false;
int vautoTopic;
int vport;
int vitemHeight;
int vtextSize;
String vusername;
String vpassword;
String vserver;
String vbackColor;
String vtextColor;
String vclickColor;
String vfontName;
String vtargetFrame;
int vscrollDelay;
BorderLayout borderLayout1 = new BorderLayout();
Label StatusLabel = new Label();
int currentItemSpace = -1; // which item the mouse is currently over
int itemSpaceClicked = -1; // set on mouse down, check on mouse up to make sure we had a valid click in an item.
//Get a parameter value
public String getParameter(String key, String def) {
return isStandalone ? System.getProperty(key, def) :
(getParameter(key) != null ? getParameter(key) : def);
}
//Construct the applet
public OQApplet () {
messages = new Vector(10);
bcThread = null;
}
//Initialize the applet
public void init() {
try {
URL u = getCodeBase();
if (u != null) {
vserver = u.getHost();
} else {
vserver = "127.0.0.1";
}
} catch (Exception ex) {
// we know getCodeBase fails when we run standalone. ex.printStackTrace();
vserver = "127.0.0.1";
}
try { vautoTopic = Integer.parseInt(this.getParameter("autoTopic", "101")); } catch (Exception e) { e.printStackTrace(); }
try { vport = Integer.parseInt(this.getParameter("port", "8764")); } catch (Exception e) { e.printStackTrace(); }
try { vitemHeight = Integer.parseInt(this.getParameter("itemHeight", "22")); } catch (Exception e) { e.printStackTrace(); }
try { vtextSize = Integer.parseInt(this.getParameter("textSize", "9")); } catch (Exception e) { e.printStackTrace(); }
try { vscrollDelay = Integer.parseInt(this.getParameter("scrollDelay", "0")); } catch (Exception e) { e.printStackTrace(); }
try { vserver = this.getParameter("server", vserver); } catch (Exception e) { e.printStackTrace(); }
try { vbackColor = this.getParameter("backColor", "#FFFFFF"); } catch (Exception e) { e.printStackTrace(); }
try { vtextColor = this.getParameter("textColor", "#000000"); } catch (Exception e) { e.printStackTrace(); }
try { vclickColor = this.getParameter("clickColor", "#FF0000"); } catch (Exception e) { e.printStackTrace(); }
try { vfontName = this.getParameter("fontName", "Helvetica"); } catch (Exception e) { e.printStackTrace(); }
try { vtargetFrame = this.getParameter("targetFrame", ""); } catch (Exception e) { e.printStackTrace(); }
try { vusername = this.getParameter("username", "guest"); } catch (Exception e) { e.printStackTrace(); }
try { vpassword = this.getParameter("password", "guest"); } catch (Exception e) { e.printStackTrace(); }
try { jbInit(); } catch (Exception e) { e.printStackTrace(); }
}
//Component initialization
public void jbInit() throws Exception{
//JDK1.1 - this.setSize(new Dimension(138, 134));
try {
if (vtextColor.startsWith("#")) {
vtextColor = vtextColor.substring(1);
}
myTextColor = new Color (
Integer.parseInt(vtextColor, 16));
if (vclickColor.startsWith("#")) {
vclickColor = vclickColor.substring(1);
}
myClickColor = new Color (
Integer.parseInt(vclickColor, 16));
if (vbackColor.startsWith("#")) {
vbackColor = vbackColor.substring(1);
}
myBackColor = new Color (
Integer.parseInt(vbackColor, 16));
setBackground(myBackColor);
myFont = new Font(vfontName, Font.PLAIN, vtextSize);
//myFontMetrics = new FontMetrics(myFont); // currently unused
} catch (Exception ex) {
// the color specification is wrong.
}
StatusLabel.setBackground(Color.blue);
StatusLabel.setForeground(Color.white);
setStatusLabelText("(Offline)");
//StatusLabel.hide();
this.setLayout(borderLayout1);
this.add("South", StatusLabel);
oldDim = size();
if ((oldDim.width > 0) && (oldDim.height > 0)) {
buffered_image = createImage(oldDim.width, oldDim.height);
}
paint(getGraphics());
// we want SOME valid image so we can scroll in new messages.
}
public void setStatusLabelText(String s){
StatusLabel.setText(s);
}
//Start the applet
public void start() {
bcThread = new OQConversationThread((SimpleOQAwareness)this, vserver, vport, vusername, vpassword, vautoTopic);
messages.removeAllElements();
bcThread.start();
}
//Stop the applet
public void stop() {
if (bcThread != null) {
try {
bcThread.ourSocket.close();
} catch (Exception ex) {
}
bcThread.bSessionShouldContinue = false;
bcThread.stop();
}
}
//Destroy the applet
public void destroy() {
}
//Get Applet information
public String getAppletInfo() {
return "Applet Information";
}
//Get parameter info
public String[][] getParameterInfo() {
String pinfo[][] =
{
{"autoTopic", "int", "ID for a Topic to automatically subscribe to when logging in. -1 for no subscription."},
{"username", "String", "Name for login. Default is guest."},
{"password", "String", "Password for login. Default is password."},
};
return pinfo;
}
//Main method
static public void main(String[] args) {
OQApplet applet = new OQApplet ();
applet.isStandalone = true;
Frame frame = new Frame();
frame.setTitle("Applet Frame");
frame.add("Center", applet);
//applet.resize(300,300);
applet.init();
//applet.resize(300,300);
//JDK1.1 - applet.setSize(300,300);
applet.start();
frame.pack();
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
//JDK1.1 - frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
//JDK1.1 - frame.setVisible(true);
frame.show();
}
public String getAppletVersionString(){
return "0.65.0003";
}
public int itemSpaceFromEvent(Event e) {
Dimension d = size();
if ( ((e.y < 1) || (e.y > d.height)) || ((e.x < 1) || (e.x > d.width)) ) {
return -1;
} else {
// don't select last item if we're way past it but still in the applet space.
if (e.y == 0 ) {
if (messages.size() > 0) {
return 0; // yes, we're at the first pixel of the first item.
} else {
return -1;// no hit
}
} else {
if ((e.y-1) >= (vitemHeight * messages.size()) ) {
return -1;
} else {
return ((e.y-1) / vitemHeight);
}
}
}
}
public boolean handleEvent (Event e) {
while (CurrentlyReceiving) {
try {
Thread.currentThread().sleep(15);
} catch (InterruptedException ex) {
}
}
if (e.id == Event.WINDOW_MOVED) {
Dimension d = size();
if ((d.width > 0) && (d.height > 0)) {
buffered_image = createImage(d.width, d.height);
}
}
if (e.id == Event.MOUSE_EXIT) {
currentItemSpace = -1;
paint(getGraphics());
if (messages.size() > 0) { setDefaultStatusLabel();}
}
if (e.id == Event.MOUSE_MOVE) {
int newItemSpace = itemSpaceFromEvent(e);
if (currentItemSpace != newItemSpace) {
currentItemSpace = newItemSpace;
if (currentItemSpace != -1) {
// add anything special?
OQAppletMessage m = (OQAppletMessage) messages.elementAt(messages.size()-(newItemSpace+1));
if (m != null) { // should always be real, but just in case
String iu = m.getItemURL();
if (iu.equals("")) {
setStatusLabelText("(No link for this item)");
} else {
setStatusLabelText(iu);
}
}
} else {
// add anything special?
if (messages.size() > 0) { setDefaultStatusLabel();}
}
paint(getGraphics());
}
} else {
if (e.id == Event.MOUSE_DOWN) {
int newItemSpace = itemSpaceFromEvent(e);
if (newItemSpace != -1) {
// see if there is an ItemURL header,
// then try to open a browser window to it.
OQAppletMessage m = (OQAppletMessage) messages.elementAt(messages.size()-(newItemSpace+1));
String s = m.getItemURL();
if (s.equals("") == false) {
setStatusLabelText("Full Story at: " + s);
} else {
setStatusLabelText("No associated story.");
}
itemSpaceClicked = newItemSpace;
// highlight the item space now.
highlightItemSpace(itemSpaceClicked);
}
} else {
if (e.id == Event.MOUSE_UP) {
// XXX check against itemSpaceClicked to be sure it's the same.
int newItemSpace = itemSpaceFromEvent(e);
if ((newItemSpace != -1) && (newItemSpace == itemSpaceClicked)) {
// a valid selection has been seen.
ItemSpaceSelected(itemSpaceClicked);
}
itemSpaceClicked = -1;
Graphics g = getGraphics();
paint (g);
g.dispose();
}
}
}
return super.handleEvent(e);
}
public void ItemSpaceSelected(int i){
OQAppletMessage m = (OQAppletMessage) messages.elementAt(messages.size() - (i+1));
if (m != null) {
// by default, try to launch ItemURL.
String s = m.getItemURL();
if (s.equals("")) {
} else {
try {
URL u = new URL(s);
setStatusLabelText("Jumping to " + s);
if (vtargetFrame.equals("")) {
getAppletContext().showDocument(u);
} else {
getAppletContext().showDocument(u, vtargetFrame);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
public void setDefaultStatusLabel(){
if (defaultStatusMessage == null) {
if (bcThread != null) {
int theState = bcThread.state;
if (theState > 1 ) { setStatusLabelText("(Online)");}
if (theState == OQConversationThread.OQState_Offline) { setStatusLabelText("(Offline)");}
if (theState == OQConversationThread.OQState_Connected) { setStatusLabelText("(Connected)"); }
} else {
setStatusLabelText("(Offline)");
}
} else {
setStatusLabelText(defaultStatusMessage);
}
}
public synchronized void fireOQConnectionStateChange(int newState, int oldState) {
setDefaultStatusLabel();
// paint(getGraphics());
}
public synchronized void fireOQError(String e) {
defaultStatusMessage = e;
setStatusLabelText(e);
StatusLabel.show();
}
public synchronized void fireOQMessageReceived(int aTopicID, int aMessageID, String subject, String completeMessage) {
CurrentlyReceiving = true;
if (subject != null) {
OQAppletMessage m = new OQAppletMessage(aTopicID, aMessageID, subject, completeMessage);
messages.addElement(m);
Graphics g = getGraphics();
if (vscrollDelay > 0) {
if ((buffered_image != null) && (messages.size() > 1)) {
for (int i=1; i <= vitemHeight; i++){
g.drawImage(buffered_image, 0,i, null);
try {
Thread.currentThread().sleep(vscrollDelay);
} catch (InterruptedException ex) {
}
}
}
}
paint(g);
g.dispose();
} else {
System.err.println("fireMessageReceived was sent a null subject!");
}
CurrentlyReceiving = false;
}
public void update (Graphics g) {
paint(g);
}
private void highlightItemSpace(int i) {
Dimension d = size();
if ((d.width > 0) && (d.height > 0)) {
Graphics g = getGraphics();
g.setColor(myClickColor);
int CurrentItemTop = i * vitemHeight;
g.drawRect (0, CurrentItemTop+1, d.width-1, vitemHeight-1);
g.drawRect (1, CurrentItemTop+2, d.width-3, vitemHeight-3);
g.dispose();
}
}
public void paint(Graphics g) {
if ((g != null) ) {
synchronized (messages) {
try {
Dimension d = size();
if ((d.width > 0) && (d.height > 0)) {
if ((buffered_image == null) || ((d.width != oldDim.width) || (d.height != oldDim.height)) ) {
buffered_image = createImage(d.width, d.height);
oldDim.height = d.height;
oldDim.width = d.width;
}
Graphics bg = buffered_image.getGraphics();
bg.clearRect(0, 0, d.width, d.height);
bg.setFont(myFont);
myFontMetrics = bg.getFontMetrics();
// compute equal space above and below the text, then position us to draw text there.
int theFontAscent = myFontMetrics.getAscent();
int TextOffsetFromItemTop = vitemHeight - ( (vitemHeight - theFontAscent) / 2);
int bulletTopOffset = TextOffsetFromItemTop - ((theFontAscent / 3)+3); // go up one third of ascent (estimate).
int CurrentItemTop = 0;
int messageCount = messages.size();
if (messageCount > 0) {
int i=1;
while (i <= messageCount) {
OQAppletMessage m = (OQAppletMessage) messages.elementAt(messageCount - i);
if (m != null) {
bg.setColor(myTextColor);
bg.drawString(m.subject, 20, CurrentItemTop + TextOffsetFromItemTop);
bg.fillRect (10, CurrentItemTop + bulletTopOffset, 6,6);
if (currentItemSpace == i-1) {
bg.drawRect(0,CurrentItemTop+1, d.width-1, vitemHeight-1);
}
}
i++;
CurrentItemTop = CurrentItemTop + vitemHeight;
}
} else { // messagecount > 0
// zero messages
if ( bcThread.state < 2) {
bg.drawString( "(Currently offline)", 5, CurrentItemTop + TextOffsetFromItemTop);
}
}
// done drawing
bg.dispose();
g.drawImage(buffered_image, 0,0, null);
} else { // zero height or width, so don't draw.
}
} catch (Exception ex){
System.err.println("error in paint()..." );
ex.printStackTrace();
}
} // synchronized
} // g not null and buffered image not null
}
}