/*****************************************************************************
* jmenu *
* by Matthew L Wilson mlavwilson@hotmail.com, mewilson@bluemoon.net *
* http://www.bluemoon.net/~mewilson *
* COPYRIGHT NOTICE *
* Copyright 1999 Matthew L. Wilson All Rights Reserved. *
* Jmenu may be used and modified free of charge by anyone so long *
* this copyright notice and the comments above remain intact. By using this *
* code you agree to indemnify Matthew L. Wilson from any liability that *
* might arise from it's use. *
* *
* Selling the code for this program without prior written consent is *
* expressly forbidden. In other words, please ask first before you try and *
* make money off of my program. *
* *
* Obtain permission before redistributing this software over the Internet or *
* in any other medium. In all cases copyright and header must remain intact.*
******************************************************************************/
import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.net.*;
import java.util.StringTokenizer;
public class jmenu extends Applet implements Runnable {
//PARAMETERS: name param name
Color TEXT_HILIGHT, // "color-highlight"
TEXT_NORMAL, // "color-text"
BACK_GROUND, // "color-background"
CONNECTORS, // "color-connectors"
UNDER_LINE; // "color-under-line"
Font NAME_FONT; // "font-name-size"
int SPACING = 16; // "spacing"
int Num_Entries=500,
BufferX, BufferY, // Used for scrolling up and down.
MaxLevel, oldItem, // Last entry the mouse was over.
AppletY, AppletX; // Size of th eapplet.
String string; // Used for parameters.
Graphics b;
Image buffer = null;
Image[] Icon; // All the icons
entry Item[] = new entry[ Num_Entries ]; //Stores all entries.
int I[] = new int[ Num_Entries ]; //Stores entries visable to the user.
URL url; // The URl to open a page.
Thread thread; // Monitors the icons while they are downloaded
MediaTracker tracker; // Monitors the icons while they are downloaded
public void start()
{ thread = new Thread(this);
thread.start();
}
public void stop()
{ thread.stop();
thread = null;
}
// Load all the icons, then call createTree().
public void run()
{
try {
tracker.waitForID(0);
}
catch (InterruptedException e) {return;}
createTree();
}
/*1) Init the Media Tracker
2) Init the double buffer
3) Get all parameters
4) Start the download of all the icons
5) Call addFolder(-1,"") which is a recursive function
6) Call initConnectors()
7) Check to see if there is a "start-page"
8) Call createTree(), which draws the tree on the buffer */
public void init()
{
tracker = new MediaTracker(this);
AppletX = size().width;
AppletY = size().height;
try {
buffer = createImage(AppletX,1000); b = buffer.getGraphics();
}catch (Exception e) { getAppletContext().showDocument( getDocumentBase(),"_self" ); }
TEXT_NORMAL = setParmColor( getParameter("color-text" ), Color.black);
BACK_GROUND = setParmColor( getParameter("color-background"), Color.white);
CONNECTORS = setParmColor( getParameter("color-connectors"), BACK_GROUND);
TEXT_HILIGHT = setParmColor( getParameter("color-highlight" ), TEXT_NORMAL);
UNDER_LINE = setParmColor( getParameter("color-under-line"), BACK_GROUND);
SPACING = (getParameter("spacing") == null ? SPACING : Integer.parseInt(getParameter("spacing")));
String font = getParameter("font-name-size");
if (font != null)
{ StringTokenizer to = new StringTokenizer(font, ",");
String name = to.nextToken();
int size = Integer.parseInt(to.nextToken());
NAME_FONT = new Font(name, 0, size);
b.setFont(NAME_FONT);
}
for (Num_Entries = 0; ;Num_Entries++) if (null == getParameter("icon"+Num_Entries) ) break;
Icon = new Image[Num_Entries];
Num_Entries = 0;
while(1==1)
{ string = getParameter("icon"+Num_Entries);
if (string == null) break;
Icon[Num_Entries] = getImage(getDocumentBase(),string);
showStatus("Loading icons");
tracker.addImage(Icon[Num_Entries], 0);
Num_Entries++;
}
Num_Entries = 0;
addFolder(-1,""); initConnectors();
for (int i = 1; i<500; i++) I[i] = -1; I[0] = 0;
String Starter = getParameter("start-page");
for (int i = Num_Entries-1; i>0; i--) if (( Starter.equals("?"+Item[i].Location) )&&(Item[i].Location != ""))
{
int folder = 0;
showDocument(Item[i].Location, Item[i].Target);
folder = Item[i].Folder-1;
for (int j = i; j>=0; j--) if ( (Item[j].Folder == folder) && (Item[j].Icon < 2) )
{
Item[j].Icon = 1;
folder = Item[j].Folder-1;
}
break;
}
createTree();
}
// This recursive function gets the parameter and loads the item into Item[].
public void addFolder(int Level, String Folder)
{
String parameter, Status, icon, Location, Target, Name;
int Num = 1;
while(1==1)
{ string = getParameter(""+Folder+"/"+Num);
if (string == null) return;
StringTokenizer to = new StringTokenizer(string, ",");
icon = to.nextToken();
Name = to.nextToken();
if (to.hasMoreTokens()) Location = to.nextToken();
else Location = "";
if (to.hasMoreTokens()) Target = to.nextToken();
else Target = "";
if (to.hasMoreTokens()) Status = to.nextToken();
else Status = "";
Item[Num_Entries] = new entry(""+Level, icon, Location, Target, Name, Status);
Num_Entries++;
Num++;
if (Integer.parseInt(icon) < 2) addFolder(Level+1,""+Folder+"/"+Name);
}
}
//Draws the lines between the items.
public void initConnectors()
{
int lastConnector;
for (int i = Num_Entries-1; i>0; i--)
{
try { lastConnector = Item[i+1].Connector[Item[i].Folder];}
catch(Exception e) {lastConnector=0;}
if ( lastConnector == 0) Item[i].Connector[Item[i].Folder] = 3;
else Item[i].Connector[Item[i].Folder] = 2;
for (int j = i-1; j>0; j--)
if (Item[i].Folder <= Item[j].Folder) Item[j].Connector[Item[i].Folder] = 1;
else break;
}
}
//Moves the visible items from Item[] to I[].
public void createTree()
{
int i = 1,
level = 0,
Cur_Folder = 0;
while( i < Num_Entries)
{
if (Item[0].Icon == 0) break;
level++;
I[level] = i;
if (Item[i].Icon == 0)
{
Cur_Folder = i++;
while ( (Item[i].Folder > Item[ Cur_Folder ].Folder) ){ if (++i >= Num_Entries ) break; }
}
else i++;
}
MaxLevel=level;
for (i = level+1; i<= Num_Entries; i++) I[i]=-1;
paintTree();
}
//Draws the tree menu on the buffer.
public void paintTree()
{
b.setColor(BACK_GROUND);
b.fillRect(0,0,AppletX,AppletY);
if ( Icon[ Item[0].Icon ] != null) b.drawImage( Icon[ Item[0].Icon ], BufferX,BufferY,null);
if (Item[0].Icon == 1)
{
for (int i=1; I[i] != -1; i++)
{
b.setColor(CONNECTORS);
for (int j=0; j<=Item[I[i]].Folder; j++)
{
switch(Item[I[i]].Connector[j])
{
case 1: b.drawLine( j*SPACING+((int)SPACING/2)+BufferX, SPACING*i+BufferY,j*SPACING+((int)SPACING/2)+BufferX, SPACING*i+SPACING+BufferY);
break;
case 2: b.drawLine( j*SPACING+((int)SPACING/2)+BufferX, SPACING*i+BufferY,j*SPACING+((int)SPACING/2)+BufferX, SPACING*i+SPACING+BufferY);
b.drawLine( j*SPACING+((int)SPACING/2)+BufferX, SPACING*i+((int)SPACING/2)+BufferY,j*SPACING+SPACING+BufferX, SPACING*i+((int)SPACING/2)+BufferY);
break;
case 3: b.drawLine( j*SPACING+((int)SPACING/2)+BufferX, SPACING*i+BufferY,j*SPACING+((int)SPACING/2)+BufferX, SPACING*i+((int)SPACING/2)+BufferY);
b.drawLine( j*SPACING+((int)SPACING/2)+BufferX, SPACING*i+((int)SPACING/2)+BufferY,j*SPACING+SPACING+BufferX, SPACING*i+((int)SPACING/2)+BufferY);
break;
}
}
if (Icon[ Item[I[i]].Icon ] != null)b.drawImage( Icon[ Item[I[i]].Icon ], Item[I[i]].Folder*SPACING+SPACING+BufferX,SPACING*i+BufferY, this);
if (oldItem == i)
{ if (Item[ I[oldItem]].Location != ""){b.setColor(UNDER_LINE); b.drawLine(Item[I[oldItem]].Folder*SPACING+SPACING+20+BufferX, SPACING*oldItem+14+BufferY,Item[I[oldItem]].Folder*SPACING+SPACING+20+BufferX+( b.getFontMetrics().stringWidth(Item[ I[oldItem] ].Name) ), SPACING*oldItem+14+BufferY);}
b.setColor(TEXT_HILIGHT);
}else b.setColor(TEXT_NORMAL);
b.drawString( Item[ I[i] ].Name, Item[I[i]].Folder*SPACING+SPACING+20+BufferX, SPACING*i+13+BufferY);
}
}
else
{
b.setColor(TEXT_NORMAL);b.drawString("Code by: Matthew Wilson",5,AppletY-25);
b.setColor(TEXT_HILIGHT);b.drawString("mlavwilson@hotmail.com",5,AppletY-10);
}
repaint();
}
//if the entry has a url, this function points the browser to it.
public boolean mouseUp(Event evt, int x, int y)
{
y = y-BufferY;
if ((Item[0].Icon == 0) && (y > 350)) showDocument("mailto:mlavwilson@hotmail.com","main");
if (y/SPACING > Num_Entries) return true;
if ( (I[y/SPACING] != -1) || ( (y/SPACING) == 0) )
{
if (Item[ I[y/SPACING] ].Icon < 2)
{
if( (x/SPACING) == Item[I[y/SPACING]].Folder+1 )
{
if (Item[I[y/SPACING]].Icon == 1) Item[I[y/SPACING]].Icon = 0;
else Item[I[y/SPACING]].Icon = 1;
}
else if (Item[I[y/SPACING]].Location != "") showDocument(Item[I[y/SPACING]].Location, Item[I[y/SPACING]].Target);
else if (Item[I[y/SPACING]].Icon == 1) Item[I[y/SPACING]].Icon = 0;else Item[I[y/SPACING]].Icon = 1;
createTree();
}
else showDocument(Item[I[y/SPACING]].Location, Item[I[y/SPACING]].Target);
}
return true;
}
//If the item has a url the name is underlined, and the status bar is populated.
public boolean mouseMove(Event e, int x, int y)
{
if ( (I[(y-BufferY)/SPACING] != -1) )
{
if ((y-BufferY)/SPACING != oldItem)
{
if(oldItem != 0)
{
b.setColor(BACK_GROUND); b.drawLine(Item[I[oldItem]].Folder*SPACING+SPACING+20+BufferX, SPACING*oldItem+14+BufferY,Item[I[oldItem]].Folder*SPACING+SPACING+20+BufferX+( b.getFontMetrics().stringWidth(Item[ I[oldItem] ].Name) ), SPACING*oldItem+14+BufferY);
b.setColor(TEXT_NORMAL); b.drawString( Item[ I[oldItem] ].Name, Item[I[oldItem]].Folder*SPACING+SPACING+20+BufferX, SPACING*oldItem+13+BufferY);
}
oldItem = (y-BufferY)/SPACING;
if (oldItem != 0)
{
if (Item[ I[oldItem]].Location != ""){b.setColor(UNDER_LINE); b.drawLine(Item[I[oldItem]].Folder*SPACING+SPACING+20+BufferX, SPACING*oldItem+14+BufferY,Item[I[oldItem]].Folder*SPACING+SPACING+20+BufferX+( b.getFontMetrics().stringWidth(Item[ I[oldItem] ].Name) ), SPACING*oldItem+14+BufferY);}
b.setColor(TEXT_HILIGHT); b.drawString( Item[ I[oldItem] ].Name, Item[I[oldItem]].Folder*SPACING+SPACING+20+BufferX, SPACING*oldItem+13+BufferY);
}
repaint(); showStatus(Item[I[(y-BufferY)/SPACING]].Status);
}
}
if (Item[0].Icon == 1)
{
if ( (y>(AppletY-SPACING)) && ( BufferY > -((SPACING*MaxLevel) - (AppletY-SPACING)) ) )
{ BufferY = BufferY-SPACING;
paintTree();
repaint();
}
if ( (y< 10) && (BufferY < 0) )
{ BufferY = BufferY+SPACING;
paintTree();
repaint();
}
}
else
{
if(y > AppletY-20) showStatus("Contact the author of this menu applet: mlavwilson@hotmail.com");
}
return true;
}
//converts hex to java Color.
public Color setParmColor(String s, Color c) // Convert hexadecimal RGB parameter to color
{
int[] hex = new int[6];
String h ="0123456789abcdef";
if ((s!=null)&&(s.length()==6))
{ for (int i=0;i<6;i++) for (int j=0;j<16;j++)
if (Character.toLowerCase(s.charAt(i))==h.charAt(j)) hex[i]=j;
c=new Color(hex[0]*16+hex[1], hex[2]*16+hex[3], hex[4]*16+hex[5]);
}
return c;
}
public String[][] getParameterInfo()
{
String[][] info = {
{"color-highlight" , "COLOR" , "#123456" },
{"color-text" , "COLOR" , "#123456" },
{"color-background" , "COLOR" , "#123456" },
{"color-connectors" , "COLOR" , "#123456" },
{"color-under-line" , "COLOR" , "#123456" },
{"!font-name-size" , "FONT " , "Helvetica,12"},
{"spacing" , "int " , "18" },
{"icon[0-?]" , "IMAGE" , "icons/me.gif"},
{"[folder name]/[1-?]" , "Item in menu", "Icon,Name,URL,Target,Status bar"}
};
return info;
}
//Functions the javascript can acess.
public void setTEXT_NORMAL(String string) {TEXT_NORMAL = setParmColor( string, TEXT_NORMAL ); paintTree(); }
public void setBACK_GROUND(String string) {BACK_GROUND = setParmColor( string, BACK_GROUND ); paintTree(); }
public void setCONNECTORS(String string) {CONNECTORS = setParmColor( string, CONNECTORS ); paintTree(); }
public void setTEXT_HILIGHT(String string){TEXT_HILIGHT = setParmColor( string, TEXT_HILIGHT); paintTree(); }
public void setUNDER_LINE(String string) {UNDER_LINE = setParmColor( string, UNDER_LINE ); }
public void setSPACING(String string) {try{SPACING = Integer.parseInt(string); BufferX=BufferY=0; paintTree();} catch(Exception e) {}}
public void setFONT_SIZE(String string) {int size = (string == null ? 14 : Integer.parseInt(string)); NAME_FONT = new Font("Helvetica", 0, size); b.setFont(NAME_FONT); paintTree(); }
public void update(Graphics g){paint(g);}//eliminate flicker.
public void debug(String string){ System.out.println(string); }//used for debuging.
public String getAppletInfo() {return "\t applet menu v1.5\nby Matthew Wilson: mlavwilson@hotmail.com";}
//if the window was resized, createTree() is called.
public void paint(Graphics g)
{
if(AppletY != size().height)
{
AppletY = size().height;
createTree();
}
g.drawImage(buffer,0,0,null);
}
//Points the browser to the URL L and Target T.
public void showDocument(String L, String T)
{
String Path;
if ( (L.startsWith("http")) || (L.startsWith("mail") ) ) Path ="";
else Path =""+getCodeBase();
try{ url = new URL( Path+L ); } catch (MalformedURLException e) { showStatus("Malformed URL"); }
getAppletContext().showDocument( url, T );
}
}