advertisement
javaboutique
Search Tips
Articles  |   Tutorials  |   Reviews  |   Tools  |   by Category  |   by Date  |   by Name  |   Submit  |   Source  |   Forums  |  
javaboutique
Browse DevX


Partners & Affiliates











advertisement

PopupNavigator


Java Source:

// PopupNavigator -  web-site navigation pop-up menu Java applet.
// Copyright © 1999-2000 Branko Dimitrijevic
// bepp@bepp.8m.com
// http://bepp.8m.com

package PopupNavigator;

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.StringTokenizer;
import java.net.URL;
import java.net.MalformedURLException;



// TODO: Support for settig predefined cursor or loading
// a cursor from URL.

// TODO: Support for foregraund color, background color,
// icons, foreground and background image.

// TODO: Merge PopupNavigatorMenu and PopupNavigatorMenuItem?

// TODO: Support for system colors.

// TODO: Support for configuration file.
//   1) For menu tree only.
//   2) For everything except menu tree.
//   3) For both 1) and 2).

// TODO: Test when there is too mutch sub-parameters.



class PopupNavigatorMenu extends Menu {

  // We don't use Font class because we need to know what values are
  // default (null) - after temporary change of font.
  public String fontName = null;
  public Integer fontStyle = null, fontSize = null;

  public PopupNavigatorMenu(String label) {
    super(label);
  }

}



// We need special class to store URLs.
class PopupNavigatorMenuItem extends MenuItem {

  public URL url = null;
  // Stores URLs that are in the different domain (to avoid premature DNS lookups).
  public String url_string = null;
  public String frame = null;

  // We don't use Font class becouse we need to know what values are
  // default (null) - after temporary change of font.
  public String fontName = null;
  public Integer fontStyle = null, fontSize = null;

  public PopupNavigatorMenuItem(String label) {
    super(label);
  }

} // PopupNavigatorMenuItem



public class PopupNavigatorApplet extends Applet {

  // True if mouse is inside applet.
  private boolean mouseIn = false;
  private boolean mouseDown = false;

  // Maximum number of semicolon-delimited tokens (sub-parameters)
  // within single applet parameter value.
  private static final short MaxSubParameters = 9;

  private static final short MaxMenuDepth = 10;

  private char delimiterChar = ';';
  private char escapeChar = '\\';
  private String URLBase = "CODEBASE";

  private String defaultFontName = "Dialog";
  private String defaultFontStyle = "PLAIN";
  private String defaultFontSize = "12";
  private String defaultForegroundColor = "BLACK";
  private String defaultBackgroundColor = "LIGHTGRAY";
  // We don't use "_self" as default because of posibility to improve
  // compatibility with non-frames browsers (HotJava?) by not caling
  // frame-enabled showDocumetn(). I don't know if this is effective.
  private String defaultFrame = null;

  // Selection method constants.
  private static final String smRecursive = "RECURSIVE";
  private static final String smItem = "ITEM";
  private static final String smNone = "NONE";

  private String selectionMode = smRecursive;
  private String selectionFontName = null;
  private String selectionFontStyle = "BOLD";
  private String selectionFontSize = null;

  private String menuActivation = "CLICK";
  private String statusText = null;

  private String menuPosition = "BOTTOM";
  private String missingURL = "ERROR";

  // Used in paint().
  private String labelText = null;
  private Font labelFont = null;
  private Color labelForeground = null;
  private Color labelBackground = null;

  private String mouseoverLabelText = null;
  private Font mouseoverLabelFont = null;
  private Color mouseoverLabelForeground = null;
  private Color mouseoverLabelBackground = null;

  private String clickLabelText = null;
  private Font clickLabelFont = null;
  private Color clickLabelForeground = null;
  private Color clickLabelBackground = null;

  // Button style constants.
  private static final String bsFlat = "FLAT";
  private static final String bsSemiflat = "SEMIFLAT";
  private static final String bsNormal = "NORMAL";

  // Button hover constants.
  private static final String bhHover = "HOVER";
  private static final String bhNohover = "NOHOVER";

  // ButtonStyle = style;hover.
  private String buttonStyle = bsNormal;
  private String buttonHover = bhHover; // Mouseover effect.

  private Image buttonImage = null;
  private Image mouseoverButtonImage = null;
  private Image clickButtonImage = null;

  private static final String bipAbsolute = "ABSOLUTE";
  private static final String bipCenter = "CENTER";
  private static final String bipLeft = "LEFT";
  private static final String bipRight = "RIGHT";
  private static final String bipTop = "TOP";
  private static final String bipBottom = "BOTTOM";

  private String buttonImagePosition = "ABSOLUTE";
  private String buttonImagePositionX = "0";
  private String buttonImagePositionY = "0";
  private String mouseoverButtonImagePosition = null;
  private String mouseoverButtonImagePositionX = null;
  private String mouseoverButtonImagePositionY = null;
  private String clickButtonImagePosition = null;
  private String clickButtonImagePositionX = null;
  private String clickButtonImagePositionY = null;

  // Last selected menu item. Used to improve compatibility
  // with frames. In IE5 this doesn't work.
  PopupNavigatorMenuItem oldSelection = null;

  // Used in loadMenu(). Not static because of multi-use of the same applet
  // in one web page.
  short[] paramCoord = new short[MaxMenuDepth];

  boolean isStandalone = false;
  GridLayout gridLayout1 = new GridLayout();
  PopupMenu popupMenu = new PopupMenu();

  // Get a parameter value. If parameter is not found, def is returned.
  public String getParameter(String key, String def) {
    String tmp;
    tmp = isStandalone ? System.getProperty(key, def) : getParameter(key);
    if (tmp == null)
      tmp = def;
    if (tmp != null)
      tmp = tmp.trim();
    return tmp;
  }

  private Image getImageFromParam(String paramName, Image def) {
    String paramValue;
    paramValue = getParameter(paramName,null);
    if (paramValue == null)
      return def;
    else if (paramValue.length() == 0)
      return null;
    else
      return getImage(encodeURL(paramValue));
  }

  // Returns true if url_string references current domain.
  // Important to avoid unneccessary DNS lookups.
  private boolean isCurrentDomain(final String url_string) {

    // url_string can not be local if it contains "://" or begins with "mailto:".

    String Url = url_string.trim();

    // Strts with "mailto:"?
    if (Url.startsWith("mailto:"))
      return false;


    //for (int i=0; i<Url.length(); ++i) {
    //  if (
    //    Url.charAt(i) == ':'
    //    && i+1 < Url.length()
    //    && Url.charAt(i+1) == '/'
    //    && i+2 < Url.length()
    //    && Url.charAt(i+2) == '/'
    //  ) {
    //} // for search for "://"

    //for (int i = 0; i+2 < Url.length(); ++i) {
    //  if (
    //    Url.charAt(i) == ':'
    //    && Url.charAt(i+1) == '/'
    //    && Url.charAt(i+2) == '/'
    //  ) {
    //} // for search for "://"

    // Contains "://"?
    int i = Url.indexOf("://");
    if (i >= 0) {
      // url_string is not local if its beginning is different then
      // local protocol + local host.
      URL base = getDocumentBase();
      String Protocol = base.getProtocol();
      if (Protocol.equalsIgnoreCase("mailto"))
        Protocol = "mailto:";
      else
        Protocol = Protocol + "://";
      String Host = base.getHost();
      return Url.toLowerCase().startsWith((Protocol + Host).toLowerCase());
    } // if found "://"

    return true;

  } // isCurrentDomain()

  // Returns URL depending on UrlStr parameter and the URLBase parameter.
  private URL encodeURL(String UrlStr) {
    URL base;
    try {
      if (URLBase.equalsIgnoreCase("CODEBASE"))
        base = this.getCodeBase();
      else if (URLBase.equalsIgnoreCase("DOCUMENT"))
        base = this.getDocumentBase();
      else
        base = new URL(URLBase);
      return new URL(base,UrlStr);
    }
    catch (MalformedURLException x) {
      return null;
    }

    /*
    catch (MalformedURLException x) {
      if (!hasErrors) {
        Tokens[0] = formatErrorLabel(
          null,"MALFORMED URL",paramKey.toString(),paramValue);
        hasErrors = true;
      }
    }
    */
  }

  // Decodes semicolon-delimited 'value' and returns array
  // of it's tokens (sub-parameters). StringTokenizer is not
  // used becouse we need support for escape character
  // (backslash). Named sub-parameters will be implemented
  // later. Skipped sub-parameters will be assigned 'Defaults'
  // members with same index. If 'Defaults' is null, then
  // nulls will be assigned to skipped tokens.

  private String[] decodeParamValue(String value, String[] Defaults) throws Exception {

    // TODO: Support for named parameters.

    String[] Tokens = new String[MaxSubParameters];
    int i,currentTokenIndex;

    if (Defaults!=null && Defaults.length>MaxSubParameters)
      throw(new Exception("PopupNavigatorApplet.decodeParamValue() Defaults out of range."));

    StringBuffer currentToken = new StringBuffer();

    for (i=0,currentTokenIndex=0; i<value.length(); ++i) {
      if (value.charAt(i) == escapeChar) {
        ++i;  // Skipping escape.
        if (i<value.length())
          currentToken.append(value.charAt(i)); // Adding character after escape.
      }
      else if (value.charAt(i) == delimiterChar) {
        if (currentToken.length() > 0) { // To leave default or null for skipped sub-parameters.
          Tokens[currentTokenIndex] = currentToken.toString();
          currentToken = new StringBuffer();
        }
        else if (Defaults!=null && currentTokenIndex<Defaults.length) {
          Tokens[currentTokenIndex] = Defaults[currentTokenIndex];
        }
        ++currentTokenIndex;
      }
      else
        currentToken.append(value.charAt(i));
    } // for (iterate through 'value')


    // Last token doesn't need to finish with ';'.
    if (currentToken.length() > 0)  // To leave default or null if last sub-parameter is skipped.
      Tokens[currentTokenIndex++] = currentToken.toString();
    else if (Defaults!=null && currentTokenIndex<Defaults.length) {
      Tokens[currentTokenIndex] = Defaults[currentTokenIndex];
      ++currentTokenIndex;
    }

    // Applying the rest of defaults.
    if (Defaults != null)
      while (currentTokenIndex < Defaults.length) {
        Tokens[currentTokenIndex] = Defaults[currentTokenIndex];
        ++currentTokenIndex;
      }

    return Tokens;

  } // decodeParamValue()



  // Converts string representation of font style to int (as defined
  // in Font class). On failure returns Font.PLAIN - because of
  // robustness.
  private int strToFontStyle(String style) {

    String stylestr = style.toUpperCase();

    //if (stylestr.equals("PLAIN"))
    //  return Font.PLAIN;
    //else
    if (stylestr.equals("BOLD"))
      return Font.BOLD;
    else if (stylestr.equals("ITALIC"))
      return Font.ITALIC;
    else if (stylestr.equals("BOLDITALIC") || stylestr.equals("ITALICBOLD"))
      return Font.BOLD + Font.ITALIC;
    else
      return Font.PLAIN;

  } // strToFontStyle



  private Color strToColor(String value) throws Exception {

    // TODO: Support for system color (CONTROL,...).

    Color result = null;

    // Named color.
    if (Character.isLetter(value.charAt(0))) {
      // We don't want to change 'value'.
      String tmp = value.trim().toUpperCase();  // trim: doesn't change this - returns new string.

      if (tmp.equals("BLACK"))
        result = Color.black;
      else if (tmp.equals("BLUE"))
        result = Color.blue;
      else if (tmp.equals("CYAN"))
        result = Color.cyan;
      else if (tmp.equals("DARKGRAY"))
        result = Color.darkGray;
      else if (tmp.equals("GRAY"))
        result = Color.gray;
      else if (tmp.equals("GREEN"))
        result = Color.green;
      else if (tmp.equals("LIGHTGRAY"))
        result = Color.lightGray;
      else if (tmp.equals("MAGENTA"))
        result = Color.magenta;
      else if (tmp.equals("ORANGE"))
        result = Color.orange;
      else if (tmp.equals("PINK"))
        result = Color.pink;
      else if (tmp.equals("RED"))
        result = Color.red;
      else if (tmp.equals("WHITE"))
        result = Color.white;
      else if (tmp.equals("YELLOW"))
        result = Color.yellow;

      // TODO: Support for system colors.

    } // if named color

    // One integer or space-delimited three-integer color.
    else {
      StringTokenizer st = new StringTokenizer(value," ",false);
      Integer r=null,g=null,b=null;

      if (st.hasMoreTokens()) {
        r = new Integer(st.nextToken());
        if (st.hasMoreTokens()) {
          g = new Integer(st.nextToken());
          if (st.hasMoreTokens())
            b = new Integer(st.nextToken());
        }
      }
      else
        throw new Exception("PopupNavigator.strToColor() Bad color formatting.");

      if (g == null)
        result = new Color(r.intValue()); // r contains whole RGB value.
      else {
        if (b == null)  // Error only b has no value.
          throw new Exception("PopupNavigator.strToColor() Bad color formatting - blue is missing.");
        else // All r, g and b have value.
          result = new Color(r.intValue(),g.intValue(),b.intValue());
      }
    } // else it's number

    return result;

  } // strToColor()

  private boolean strToBoolean(String value) {
    if (value.equalsIgnoreCase("TRUE"))
      return true;
    else
      return false;
  }



  //Construct the applet
  public PopupNavigatorApplet() {
  }



  // Returns Font constructed from begin-th Token (begin, begin+1 and
  // begin+2 contains name, style and size of the font).
  // If Tokens parameter is not sufficient, default values are used:
  // Dialog - PLAIN - 12.
  private Font constructFont(String[] Tokens, int begin) {
    String name = "Dialog";
    int style = Font.PLAIN, size = 12;

    if (Tokens != null) {
      if (Tokens[begin] != null)
        name = Tokens[begin];
      if (Tokens[begin+1] != null)
        style = strToFontStyle(Tokens[begin+1]);
      if (Tokens[begin+2] != null)
        size = new Integer(Tokens[begin+2]).intValue();
    }
    return new Font(name,style,size);
  }



  private String formatErrorLabel(String label, String msg, String paramKey, String paramValue) {
    return
    ((label == null || label.length()==0) ? "" : label + " ")
    + ((msg == null || msg.length()==0) ? "" : msg + " ")
    + "<PARAM NAME=\""
    + ((paramKey == null) ? "null" : paramKey)
    + "\" VALUE=\""
    + ((paramValue == null) ? "null" : paramValue)
    + "\">";
  }



  // Visually distinguishes 'item'. Uses applet-level variable
  // 'selectionMethod' to determine should it recursively
  // distinguish a super-menu.
  private void selectItem(MenuItem item, boolean recursive) {

    if (item instanceof PopupNavigatorMenuItem) {
      PopupNavigatorMenuItem tmpItem = (PopupNavigatorMenuItem)item;
      tmpItem.setFont(new Font(
        (selectionFontName != null) ? selectionFontName : tmpItem.fontName,
        (selectionFontStyle != null) ? strToFontStyle(selectionFontStyle) : tmpItem.fontStyle.intValue(),
        (selectionFontSize != null) ? new Integer(selectionFontSize).intValue() : tmpItem.fontSize.intValue()
      ));
    }
    else if (item instanceof PopupNavigatorMenu) {
      PopupNavigatorMenu tmpMenu = (PopupNavigatorMenu)item;
      tmpMenu.setFont(new Font(
        (selectionFontName != null) ? selectionFontName : tmpMenu.fontName,
        (selectionFontStyle != null) ? strToFontStyle(selectionFontStyle) : tmpMenu.fontStyle.intValue(),
        (selectionFontSize != null) ? new Integer(selectionFontSize).intValue() : tmpMenu.fontSize.intValue()
      ));
    }

    if (
      recursive
      && selectionMode.equalsIgnoreCase(smRecursive)
      && item.getParent() != null
      && item.getParent() instanceof PopupNavigatorMenu
    )
      selectItem((PopupNavigatorMenu)(item.getParent()),true);

  }


  // Uses 'selectionMethod' in the same way as selectItem() does.
  private void deselectItem(MenuItem item, boolean recursive) {

    if (item instanceof PopupNavigatorMenuItem) {
      PopupNavigatorMenuItem tmpItem = (PopupNavigatorMenuItem)item;
      tmpItem.setFont(new Font(
        tmpItem.fontName,
        tmpItem.fontStyle.intValue(),
        tmpItem.fontSize.intValue()
      ));
    }
    else if (item instanceof PopupNavigatorMenu) {
      PopupNavigatorMenu tmpMenu = (PopupNavigatorMenu)item;
      tmpMenu.setFont(new Font(
        tmpMenu.fontName,
        tmpMenu.fontStyle.intValue(),
        tmpMenu.fontSize.intValue()
      ));
    }

    if (
      recursive
      && selectionMode.equalsIgnoreCase(smRecursive)
      && item.getParent()!= null
      && item.getParent() instanceof PopupNavigatorMenu
    )
      deselectItem((PopupNavigatorMenu)(item.getParent()),true);

  }



  // Recursively loads menu-tree with first 'depth' coordinates
  // contained in 'paramCoord' and inserts it as submenu of
  // 'baseMenu'. 'depth' actually contains current level of
  // recursion.
  // Possible return values:
  //   0 - No submenu.
  //   1 - Submenu without selection.
  //   2 - Selected submenu => current item should be also selected.

  private int loadMenu(Menu baseMenu, int depth) {

    int result = 0;

    // Buld non-changing part of parameter key.

    StringBuffer paramKeyStart = new StringBuffer();

    // Current depth ('depth') is excluded.
    for (int i=0; i<depth; ++i) {
      paramKeyStart.append(paramCoord[i]);
      // Delimiter coordinates in non-changing part.
      if (i+1 < depth)
        paramKeyStart.append(delimiterChar);
    }

    // Delimit non-changing and changing part.
    if (paramKeyStart.length() > 0)
      paramKeyStart.append(delimiterChar);

    String paramValue; // Result from getParameter().

    // Iterates through 'depth' level.
    paramCoord[depth] = 0;

    do { // while (paramValue != null);

      // Creating parameter key as semicolon-delimited list of coordinates
      // of current menu item. For example: "1;5;0". We just need to append
      // current depth (contained in 'depth') to precreated non-changing
      // part of key.

      String paramKey = paramKeyStart.toString() + paramCoord[depth];

      // Getting value for current menu item.
      paramValue = getParameter(paramKey.toString(),null);

      if (paramValue != null) { // Item exists.

        if (result==0)
          result = 1; // Maybe will be changed to 2.
        String[] Tokens;

        // To error that occured first.
        boolean hasErrors = false;

        try {
          Tokens = decodeParamValue(paramValue,null);
        } // try
        catch(Exception x) {
          Tokens = new String[MaxSubParameters];
          Tokens[0] = x.toString();
          //Tokens[0] = formatErrorLabel
          //  (null,x.getMessage(),paramKey.toString(),paramValue);
          hasErrors = true;
        }

        // Check for submenus.

        PopupNavigatorMenu tmpMenu = new PopupNavigatorMenu(paramValue);
        int recursiveResult = loadMenu(tmpMenu, depth + 1);

        // Has sub-menus.
        if (recursiveResult > 0) {

          try {

            // 0     1        2         3
            // Label;FontName;FontStyle;FontSize

            // Set font. defaultFontName, defaultFontStyle and defaultFontSize
            // are guarantied not to be null.
            tmpMenu.fontName = (Tokens[1] != null) ? Tokens[1] : defaultFontName;
            tmpMenu.fontStyle = new Integer(strToFontStyle((Tokens[2] != null) ? Tokens[2] : defaultFontStyle));
            tmpMenu.fontSize = new Integer((Tokens[3] != null) ? Tokens[3] : defaultFontSize);

            // Should we select it?
            if (recursiveResult==2) {
              selectItem(tmpMenu,false); // 'false' means non-recursive.
              result = recursiveResult;
            }
            else
              deselectItem(tmpMenu,false);
          }
          catch (Exception x) {
            Tokens = new String[MaxSubParameters];
            //Tokens[0] = x.getMessage();
            Tokens[0] = x.toString();
            //Tokens[0] = formatErrorLabel
            //  (null,x.getMessage(),paramKey.toString(),paramValue);
          }

          // We don't disable it even if it has errors - in order to reach child items.
          tmpMenu.setLabel(Tokens[0]);

          baseMenu.add(tmpMenu);

        } // if has sub-menus

        else { // Menu leaf (hasn't sub-menus).

          // 0     1   2     3        4         5
          // Label;URL;Frame;FontName;FontStyle;FontSize

          // No submenus - we need MenuItem instead of Menu.
          PopupNavigatorMenuItem tmpMenuItem = new PopupNavigatorMenuItem(paramValue);

          try {

            // If it's not a separator (has no label or label is
            // different from "-"), we need url and frame.
            if (Tokens[0]==null || !Tokens[0].equals("-")) {

              // Is URL null?
              if (Tokens[1] == null) {
                if (!hasErrors) {
                  if (missingURL.equalsIgnoreCase("ERROR")) {
                    Tokens[0] = formatErrorLabel(
                      null,"MISSING URL",paramKey.toString(),paramValue);
                    hasErrors = true;
                  }
                  else if (missingURL.equalsIgnoreCase("DISABLE")) {
                    tmpMenuItem.setEnabled(false);
                  }
                }
              }
              else {
                // PREMATURE DNS lookups!
                /*
                URL base;
                try {
                  if (URLBase.equalsIgnoreCase("CODEBASE"))
                    base = this.getCodeBase();
                  else if (URLBase.equalsIgnoreCase("DOCUMENT"))
                    base = this.getDocumentBase();
                  else
                    base = new URL(URLBase);
                  tmpMenuItem.url = new URL(base,Tokens[1]);
                }
                catch (MalformedURLException x) {
                  if (!hasErrors) {
                    Tokens[0] = formatErrorLabel(
                      null,"MALFORMED URL",paramKey.toString(),paramValue);
                    hasErrors = true;
                  }
                }
                */

                if (isCurrentDomain(Tokens[1])) {
                  tmpMenuItem.url = encodeURL(Tokens[1]);
                  if (tmpMenuItem.url == null) {
                    if (!hasErrors) {
                      Tokens[0] = formatErrorLabel(
                        null,"MALFORMED URL",paramKey.toString(),paramValue);
                      hasErrors = true;
                    }
                  }
                }
                else
                  tmpMenuItem.url_string = Tokens[1];

                // Set target frame.
                if (Tokens[2]==null)
                  tmpMenuItem.frame = defaultFrame;
                else
                  tmpMenuItem.frame = Tokens[2];
              } // else url isn't null

              // If label is omitted, use URL as label. We don't need to check
              // for hasErrors because it is false (Tokens[0] wouldn't be null
              // otherwise).
              if ( /*!hasErrors ||*/ Tokens[0] == null)
                Tokens[0] = Tokens[1];

            } // if not separator

            // Set font. defaultFontName, defaultFontStyle and defaultFontSize
            // are guarantied not to be null.
            tmpMenuItem.fontName = (Tokens[3] != null) ? Tokens[3] : defaultFontName;
            tmpMenuItem.fontStyle = new Integer(strToFontStyle((Tokens[4] != null) ? Tokens[4] : defaultFontStyle));
            tmpMenuItem.fontSize = new Integer((Tokens[5] != null) ? Tokens[5] : defaultFontSize);

            // Should we select item?
            if (
              (selectionMode.equalsIgnoreCase(smRecursive) || selectionMode.equalsIgnoreCase(smItem))
              && tmpMenuItem.url != null
              && tmpMenuItem.url.equals(getDocumentBase())
              /*
              && tmpMenuItem.url_string != null
              && sameAsDocumentBase(tmpMenuItem.url_string)
              */
            ) {
              selectItem(tmpMenuItem,false);
              if (selectionMode.equalsIgnoreCase(smRecursive))
                result = 2;
            }
            else
              deselectItem(tmpMenuItem,false);

          }
          catch (Exception x) {
            Tokens = new String[MaxSubParameters];
            //Tokens[0] = x.getMessage();
            Tokens[0] = x.toString();
            //Tokens[0] = formatErrorLabel
            //  (null,x.getMessage(),paramKey.toString(),paramValue);
            hasErrors = true;
          }

          tmpMenuItem.setLabel(Tokens[0]);
          if (hasErrors)
            tmpMenuItem.setEnabled(false);

          baseMenu.add(tmpMenuItem);

        } // else add menu leaf

        ++paramCoord[depth];

      } // if (paramValue != null)

    } while (paramValue != null);

    return result;

  } // loadMenu()

  /*
  // Invalid due Java's stupid parameter passing.
  private void loadLabel(
    String ParamName,
    String[] Default,
    String T,
    Font F,
    Color Fg,
    Color Bg
  ) throws Exception {

    String[] Tokens = decodeParamValue(getParameter("Label", ""),Default);
    T = Tokens[0];
    F = constructFont(Tokens,1); // Font is constructed from tokens: 1 (name), 2 (style) and 3 (size).
    Fg = strToColor(Tokens[4]);
    Bg = strToColor(Tokens[5]);

  }
  */

  // Initialize the applet.
  public void init() {
    try {
      jbInit();

      delimiterChar = getParameter("DelimiterChar", "" + delimiterChar).charAt(0);
      escapeChar = getParameter("EscapeChar", "" + escapeChar).charAt(0);
      URLBase = getParameter("URLBase",URLBase);

      defaultFontName = getParameter("DefaultFontName", defaultFontName);
      defaultFontStyle = getParameter("DefaultFontStyle", defaultFontStyle);
      defaultFontSize = getParameter("DefaultFontSize", defaultFontSize);
      defaultForegroundColor = getParameter("DefaultForegroundColor", defaultForegroundColor);
      defaultFrame = getParameter("DefaultFrame");

      String[] Tokens;

      // Setup button appearance.
      Tokens = decodeParamValue(
        getParameter("Label", ""),
        new String[] {null,defaultFontName,defaultFontStyle,
          defaultFontSize,defaultForegroundColor,defaultBackgroundColor}
      );
      if (Tokens[0] == null) {
        if (getParameter("Label",null) == null)
          Tokens[0] = "Navigate";
        else
          Tokens[0] = "";
      }
      labelText = Tokens[0];
      labelFont = constructFont(Tokens,1); // Font is constructed from tokens: 1 (name), 2 (style) and 3 (size).
      labelForeground = strToColor(Tokens[4]);
      labelBackground = strToColor(Tokens[5]);

      Tokens = decodeParamValue(
        getParameter("MouseoverLabel", ""),
        Tokens
      );
      mouseoverLabelText = Tokens[0];
      mouseoverLabelFont = constructFont(Tokens,1); // Font is constructed from tokens: 1 (name), 2 (style) and 3 (size).
      mouseoverLabelForeground = strToColor(Tokens[4]);
      mouseoverLabelBackground = strToColor(Tokens[5]);

      Tokens = decodeParamValue(
        getParameter("ClickLabel", ""),
        Tokens
      );
      clickLabelText = Tokens[0];
      clickLabelFont = constructFont(Tokens,1); // Font is constructed from tokens: 1 (name), 2 (style) and 3 (size).
      clickLabelForeground = strToColor(Tokens[4]);
      clickLabelBackground = strToColor(Tokens[5]);

      // Mouseover (hover) effect.
      Tokens = decodeParamValue(
        getParameter("ButtonStyle", ""),
        new String[] {buttonStyle,buttonHover}
      );
      buttonStyle = Tokens[0];
      buttonHover = Tokens[1];

      // Selection distinguishing.
      Tokens = decodeParamValue(
        getParameter("Selection", ""),
        new String[] {selectionMode,selectionFontName,selectionFontStyle,selectionFontSize}
      );
      selectionMode = Tokens[0];
      selectionFontName = Tokens[1];
      selectionFontStyle = Tokens[2];
      selectionFontSize = Tokens[3];

      menuActivation = getParameter("MenuActivation",menuActivation);

      // TODO: Show URL in status-bar.
      statusText = getParameter("StatusText",statusText);

      menuPosition = getParameter("MenuPosition",menuPosition);
      missingURL = getParameter("MissingURL",missingURL);

      // Load button images.
      buttonImage = getImageFromParam("Image",null);
      mouseoverButtonImage = getImageFromParam("MouseoverImage",buttonImage);
      clickButtonImage = getImageFromParam("ClickImage",mouseoverButtonImage);

      // Load button image positions.
      Tokens = decodeParamValue(
        getParameter("ImagePosition", ""),
        new String[] {buttonImagePosition,buttonImagePositionX,buttonImagePositionY}
      );
      buttonImagePosition = Tokens[0];
      buttonImagePositionX = Tokens[1];
      buttonImagePositionY = Tokens[2];

      Tokens = decodeParamValue(
        getParameter("MouseoverImagePosition", ""),
        Tokens
      );
      mouseoverButtonImagePosition = Tokens[0];
      mouseoverButtonImagePositionX = Tokens[1];
      mouseoverButtonImagePositionY = Tokens[2];

      Tokens = decodeParamValue(
        getParameter("ClickImagePosition", ""),
        Tokens
      );
      clickButtonImagePosition = Tokens[0];
      clickButtonImagePositionX = Tokens[1];
      clickButtonImagePositionY = Tokens[2];

      //buttonImagePosition = getParameter("ImagePosition",buttonImagePosition);
      //mouseoverButtonImagePosition = getParameter("MouseoverImagePosition",mouseoverButtonImagePosition);
      //clickButtonImagePosition = getParameter("ClickImagePosition",clickButtonImagePosition);

      //buttonImage = getImageFromParam("ButtonImage");
      //buttonHoverImage = getImageFromParam("ButtonHoverImage");
      //buttonDownImage = getImageFromParam("ButtonDownImage");

      // Load menu.
      loadMenu(popupMenu,0);

      enableEvents(AWTEvent.MOUSE_EVENT_MASK);

    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }



  // Component initialization.
  private void jbInit() throws Exception {
    this.setLayout(gridLayout1);
    //menuButton.setLabel("MenuButton");
    /*
    menuButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        menuButton_actionPerformed(e);
      }
    });
    */
    //this.setSize(400,300);
    //this.setSize(MenuButton.getBounds().width+2,MenuButton.getBounds().height+2);
    //menuButton.requestFocus();
    //this.add(menuButton, null);
    this.add(popupMenu);
  }

  public void showPopupMenu() {
    int x,y;
    if (menuPosition.equalsIgnoreCase("RIGHT")) {
      //x = menuButton.getBounds().width;
      x = getBounds().width;
      y = 0;
    }
    else { //if menuPosition.equalsIgnoreCase("BOTTOM")
      x = 0;
      //y = menuButton.getBounds().height;
      y = getBounds().height;
    }
    //popupMenu.show(menuButton,x,y);
    popupMenu.show(this,x,y);
  }

  public boolean action(Event evt, Object arg) {

    //if (evt.target instanceof Button)
    //  showPopupMenu();
    //if (evt.target instanceof Applet)
    //  showPopupMenu();
    //else
    if (evt.target instanceof PopupNavigatorMenuItem) {
      PopupNavigatorMenuItem source = (PopupNavigatorMenuItem)(evt.target);
      switch(evt.id) {
        case Event.ACTION_EVENT:
          navigate(source);
          return true;
          //break;
        // PopupMenu currently doesn't support mouse events.
        //case Event.MOUSE_ENTER:
        //  showStatus(source.url.toString());
        //  break;
        default:
          return false;
      }
    }

    return false;

    // Because of stupid compiler.
    //return true;
  }


  protected void processMouseEvent(MouseEvent e) {
    super.processMouseEvent(e);
    switch (e.getID()) {
      case MouseEvent.MOUSE_ENTERED:
        mouseIn = true;
        if (statusText != null)
          showStatus(statusText);
        if (menuActivation.equalsIgnoreCase("MOUSEOVER"))
          showPopupMenu();
        // TODO: Check is repainting is necessary.
        repaint();
        break;
      case MouseEvent.MOUSE_EXITED:
        if (statusText != null)
          showStatus("");
        //mouseDown = false;
        mouseIn = false;
        repaint();
        break;
      case MouseEvent.MOUSE_PRESSED:
        mouseDown = true; // mouseIn is irelevant.
        repaint();
        break;
      case MouseEvent.MOUSE_RELEASED:
        mouseDown = false; // mouseIn is irelevant.
        if (
          e.getX() >= getBounds().x
          && e.getY() >= getBounds().y
          && e.getX() <= getBounds().x + getBounds().width
          && e.getY() <= getBounds().y + getBounds().height
        )
          showPopupMenu();
        else
          mouseIn = false; // Some browsers could avoid delivering MOUSE_EXITED event.
        repaint();
        break;
      case MouseEvent.MOUSE_CLICKED:
        break;
    }
  }


  //Get Applet information
  public String getAppletInfo() {
    return "PopupNavigatorApplet by Branko Dimitrijevic";
  }



  //Get parameter info
  //public String[][] getParameterInfo() {
  //  return null;
  //}



  //void menuButton_actionPerformed(ActionEvent e) {
  //  popupMenu.show(menuButton,0,menuButton.getBounds().height);
  //}



  private void navigate(PopupNavigatorMenuItem item) {

    if (selectionMode.equalsIgnoreCase(smRecursive)) {
      if (oldSelection != null)
        deselectItem(oldSelection,true);
      oldSelection = item;
      selectItem(item,true);
    }
    else if (selectionMode.equalsIgnoreCase(smItem)) {
      if (oldSelection != null)
        deselectItem(oldSelection,false);
      oldSelection = item;
      selectItem(item,false);
    }

    if (item.url == null)
      item.url = encodeURL(item.url_string);

    if (item.frame == null)
      getAppletContext().showDocument(item.url);
    else
      getAppletContext().showDocument(item.url,item.frame);

  } // navigate()

  //void onNavigationStart(ActionEvent e) {
  //  PopupNavigatorMenuItem source = (PopupNavigatorMenuItem)(e.getSource());
  //  navigate(source);
  //}

  //private void paintImage(Graphics g, Image img, String pos, String posX, String posY) {

  //  if buttonImagePosition.equalsIgnoreCase(bipAbsolute)

  //  g.drawImage(
  //    img,
  //    new Integer(posX).intValue(),
  //    new Integer(posY).intValue(),
  //    this
  //  );
  //}

  // Paints label.
  private void paintLabelAndImage(
    Graphics g,
    Color background,
    Color foreground,
    Font f,
    String text,
    Image img,
    String pos,  // ABSOLUTE, CENTER, RIGHT,...
    String posX,
    String posY
  ) {

    // Draw background.
    g.setColor(background);
    g.fillRect(0,0,getBounds().width,getBounds().height);

    g.setFont(f);
    FontMetrics FM = g.getFontMetrics(g.getFont());

    int appletWidth = getBounds().width;
    int appletHeight = getBounds().height;

    // TODO: Label position.

    // Calculate label coordinates.
    int labelWidth;
    if (text == null)
      labelWidth = 0;
    else
      labelWidth = FM.stringWidth(text);
    int labelX = (appletWidth  - labelWidth) / 2;
    int labelY = (appletHeight - FM.getDescent() + FM.getAscent()) / 2;

    // Calculate image, possibly change label coordinates and draw image.
    if (img != null) {

      int imageWidth = img.getWidth(this);
      int imageHeight = img.getHeight(this);

      // Image loaded?
      if (imageWidth > 0 && imageHeight > 0) {

        int imageX,imageY;

        if (pos.equalsIgnoreCase(bipAbsolute)) {
          imageX = new Integer(posX).intValue();
          if (imageX < 0)
            imageX = appletWidth + imageX - imageWidth;
          imageY = new Integer(posY).intValue();
          if (imageY < 0)
            imageY = appletHeight + imageY - imageHeight;
        }
        else if (pos.equalsIgnoreCase(bipCenter)) {
          imageX = (appletWidth - imageWidth) / 2;
          imageY = (appletHeight - imageHeight) / 2;
        }
        else if (pos.equalsIgnoreCase(bipLeft) || pos.equalsIgnoreCase(bipRight)) {
          int a = new Integer(posX).intValue();
          if (pos.equalsIgnoreCase(bipLeft)) {
            labelX += a/2;
            imageX = labelX - a - imageWidth;
          }
          else { // pos.equalsIgnoreCase(bipRight)
            labelX -= a/2;
            imageX = labelX + labelWidth + a;
          }
          imageY = (appletHeight - imageHeight) / 2;
        }
        else if (pos.equalsIgnoreCase(bipTop) || pos.equalsIgnoreCase(bipBottom)) {
          int a = new Integer(posX).intValue();
          if (pos.equalsIgnoreCase(bipTop)) {
            labelY += a/2 ;
            imageY = labelY - FM.getAscent() - a - imageHeight;
          }
          else { //pos.equalsIgnoreCase(bipTop);
            labelY -= a/2;
            imageY = labelY + FM.getDescent() + a;
          }
          imageX = (appletWidth - imageWidth) / 2;
        }
        else { // For robustness.
          imageX = 0;
          imageY = 0;
        }

        // Draw image.
        g.drawImage(img,imageX,imageY,this);

      } // if image loaded

    } // if (img != null)

    // Draw label.
    if (text != null) {
      g.setColor(foreground);
      g.drawString(
        text,
        labelX,
        labelY
      );
    }

  }

  private void paint3dRect(
    Graphics g,
    int x,
    int y,
    int w,
    int h,
    Color C1, // Light color.
    Color C2, // Dark color.
    boolean raised
  ) {
    if (!raised) {
      Color Tmp = C1;
      C1 = C2;
      C2 = Tmp;
    }
    g.setColor(C1);
    g.drawLine(x,y,w,y);
    g.drawLine(x,y,x,h);
    g.setColor(C2);
    g.drawLine(w,y,w,h);
    g.drawLine(x,h,w,h);
  }

  private void paintThinBorder(Graphics g, boolean raised) {
    paint3dRect(
      g,
      0,
      0,
      getBounds().width - 1,
      getBounds().height - 1,
      Color.white,
      Color.gray,
      raised
    );
  }

  private void paintNormalBorder(Graphics g, boolean raised) {
    paint3dRect(
      g,
      1,
      1,
      getBounds().width - 2,
      getBounds().height - 2,
      Color.lightGray,
      Color.gray,
      raised
    );
    paint3dRect(
      g,
      0,
      0,
      getBounds().width - 1,
      getBounds().height - 1,
      Color.white,
      Color.darkGray,
      raised
    );
  }

  private void paintThickBorder(Graphics g, boolean raised) {
    paint3dRect(
      g,
      2,
      2,
      getBounds().width - 3,
      getBounds().height - 3,
      Color.lightGray,
      Color.gray,
      raised
    );
    paint3dRect(
      g,
      1,
      1,
      getBounds().width - 2,
      getBounds().height - 2,
      Color.white,
      Color.darkGray,
      raised
    );
    g.setColor(Color.black);
    g.drawRect(0,0,getBounds().width-1,getBounds().height-1);
  }

  private void paintButtonBorder(Graphics g, boolean raised) {
    if (buttonStyle.equalsIgnoreCase(bsSemiflat))
      paintThinBorder(g,raised);
    else if (buttonStyle.equalsIgnoreCase(bsNormal))
      paintNormalBorder(g,raised);
  }

  private void paintHoverBorder(Graphics g, boolean raised) {
    if (buttonStyle.equalsIgnoreCase(bsFlat))
      paintThinBorder(g,raised);
    else if (buttonStyle.equalsIgnoreCase(bsSemiflat))
      paintNormalBorder(g,raised);
    else if (buttonStyle.equalsIgnoreCase(bsNormal))
      paintThickBorder(g,raised);
  }

  // TODO: Support for oval button border.

  public void paint(Graphics g) {
    //g.drawLine(1,1,10,10);
    //g.drawString("history", 10, 10);

    // Draw background.
    //g.setColor(labelBackground);
    //g.fillRect(0,0,getBounds().width,getBounds().height);

    // Draw label.
    //g.setFont(labelFont);
    //g.setColor(labelForeground);
    //FontMetrics FM = g.getFontMetrics(g.getFont());
    //g.drawString(
    //  labelText,
    //  (getBounds().width - FM.stringWidth(labelText)) / 2,
    //  (getBounds().height - FM.getDescent() + FM.getAscent()) / 2
    //);

    // Draw border.
    if (mouseDown) {
      paintLabelAndImage(
        g,clickLabelBackground,clickLabelForeground,clickLabelFont,clickLabelText,
        clickButtonImage,clickButtonImagePosition,clickButtonImagePositionX,clickButtonImagePositionY
      );
      if (buttonHover.equalsIgnoreCase(bhHover))
        paintHoverBorder(g,false);
      else
        paintButtonBorder(g,false);
    }
    else if (mouseIn) {
      paintLabelAndImage(
        g,mouseoverLabelBackground,mouseoverLabelForeground,mouseoverLabelFont,mouseoverLabelText,
        mouseoverButtonImage,mouseoverButtonImagePosition,mouseoverButtonImagePositionX,mouseoverButtonImagePositionY
      );
      if (buttonHover.equalsIgnoreCase(bhHover))
        paintHoverBorder(g,true);
      else
        paintButtonBorder(g,true);
    }
    else {
      paintLabelAndImage(
        g,labelBackground,labelForeground,labelFont,labelText,
        buttonImage,buttonImagePosition,buttonImagePositionX,buttonImagePositionY
      );
      paintButtonBorder(g,true);
    }
    //paintThickBorder(g,!mouseDown);
    //paintImage(g,buttonImage,buttonImagePosition,buttonImagePositionX,buttonImagePositionY);

  } // paint

} // SiteMenuBarApplet

Back to PopupNavigator

How to Add Java Applets to Your Site

New on the Java Boutique:

New Review:

Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling API boasts simplicity, ease-of-integration, a well-rounded feature set, and it's free!

New Applet:

Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA sequences into three useful formats.

Elsewhere on internet.com:

WebDeveloper Java
Lots of Java information on webdeveloper.com

WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.

ScriptSearch Java
Hundreds of free Java code files to download.

jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.

 Microsoft Visual Studio 2010 Showcase
 Avaya Developer Showcase
 MSDN Spotlight
 PHP for Windows Showcase
XML error: undefined entity at line 39
advertisement
Receive Articles via our XML/RSS feed
Receive Articles via our XML/RSS feed

JavaBytes
Internet Cyclone
This powerful, easy-to-use, internet optimizer is for Windows 95, 98, ME, NT, 2000 and XP. It's designed to automatically optimize your Windows settings, boosting your Internet connection up to 200%.

Windows 7: From Beta to Final Code in One Year
Google Shows Off Chrome OS, Releases Source
Microsoft Shows Off Silverlight 4, IE9 Plans
Metasploit Expands Vulnerability Test Framework
HyperCard Reborn?
Fedora 12 Takes Aim at Linux Networking
Top Supercomputer Nearly Doubles in Speed
Fedora 12 Linux Tackles Virtualization
Apple Gives iPhone Developers App Status Tracker
Novell Sets OpenSUSE 11.2 Free

Creating Custom Export Filters for StarOffice with XSLT
WPF Wonders: Using DataTemplates
Crystal Reports Family Offers Options for Developers
Avaya Aura Session Manager video
Avaya Aura Overview video
Exploring HTML 5's Audio/Video Multimedia Support
Overriding Virtual Functions? Use C++0x Attributes to Avoid Bugs.
Understanding the Cloud Computing Security Vulnerabilities
Cisco and IBM Target a Greener World
Upgrade to Visual Studio 2010 with the Ultimate Offer

Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map  |   Network Map  |   About

internet.commediabistro.comJusttechjobs.comGraphics.com

Search:

WebMediaBrands Corporate Info

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | Shopping | E-mail Offers | Freelance Jobs