/** squarehelper2.java Copyright 1998-1999 by Maier Media. All rights reserved. */ /** http://www.maiermedia.com This code is released under the terms of the General Public License Version 2 as published by the Free Software Foundation. For more information, please visit http://www.fsf.org */ /** Version History for squarehelper2.java -- Please log any changes here!! -- 5/17/1999 1.0 Original release 5/22/1999 1.0.1 Use of GNU GPL, source code cleanup and release */ import java.awt.*; import java.util.*; import java.awt.event.*; import java.lang.*; import squarelink2; import squarelisten2; /** squarehelper2 -- This is the "button" portion of the squarelink applet. Designed for Java 1.1.x. */ public class squarehelper2 extends Canvas { // Button shape constants public final static int RECTANGLE = 0; // Button style constants public final static int NORMAL = 0; public final static int FLAT = 0; public final static int RAISED = 1; public final static int MODERN = 2; // Button text positions public final static int VALIGN_CENTER = 0; public final static int VALIGN_TOP = 1; public final static int VALIGN_BOTTOM = 2; // Constant Strings that get used a lot public final static String sIMAGEBAR = "IMAGEBAR"; public final static String sIMAGEBUTTON = "IMAGEBUTTON"; public final static String sTOOLBAR = "TOOLBAR"; public final static String sPUSHBUTTON = "PUSHBUTTON"; public squarelink2 mApplet; // Declare properties with default values public int mnShape = RECTANGLE; public int mnStyle = NORMAL; public Color mBorderColor = Color.black; public Color mBackgroundColor = Color.white; public Color mTextColor = Color.blue; public Color mMouseBorderColor = Color.black; public Color mMouseBackgroundColor = Color.white; public Color mMouseTextColor = Color.blue; public Color mClickBorderColor = Color.black; public Color mClickBackgroundColor = Color.white; public Color mClickTextColor = Color.blue; public Color mTextShadowColor; public Color mMouseTextShadowColor; public Color mClickTextShadowColor; public int mnBorderWidth = 1; public String msFont = ""; public String msMouseFont = ""; public String msClickFont = ""; public int mnFontSize = 0; public int mnMouseFontSize = 0; public int mnClickFontSize = 0; public String msText = ""; public String msMouseText = ""; public String msClickText = ""; public int mnFontStyle = Font.PLAIN; public int mnMouseFontStyle = Font.PLAIN; public int mnClickFontStyle = Font.PLAIN; // Underlining public boolean mbUnderline = false; public boolean mbMouseUnderline = false; public boolean mbClickUnderline = false; public int mnTextVAlign = VALIGN_CENTER; public int mnMouseTextVAlign = VALIGN_CENTER; public int mnClickTextVAlign = VALIGN_CENTER; public Image miImage = null; public boolean mbImageReady = true; public Image miMouseImage = null; public boolean mbMouseImageReady = true; public Image miClickImage = null; public boolean mbClickImageReady = true; public String msPreset = ""; public squarehelper2(squarelink2 parent) { mApplet = parent; addMouseListener(new squarelisten2(this)); } // squarehelper() /** */ public void paint(Graphics g) { Rectangle r = getBounds(); switch(mnShape) { case RECTANGLE: drawRectangle(g); break; } } // paint() /** */ public void drawRectangle(Graphics g) { Rectangle r = getBounds(); int nX; int nY; int nWidth; int nHeight; Color BackgroundColor; Color BorderColor; Color TextColor; //********************************************** // Set up colors and positions based on mouse //********************************************** // Normal BackgroundColor = mBackgroundColor; BorderColor = mBorderColor; TextColor = mTextColor; // Being clicked if (mApplet.mbMouseOver && mApplet.mbMouseDown) { BackgroundColor = mClickBackgroundColor; BorderColor = mClickBorderColor; TextColor = mClickTextColor; } // MouseOver, but not clicking if (mApplet.mbMouseOver && (!mApplet.mbMouseDown)) { BackgroundColor = mMouseBackgroundColor; BorderColor = mMouseBorderColor; TextColor = mMouseTextColor; } nX = 0; nY = 0; nWidth = r.width; nHeight = r.height; // Fill the background g.setColor(BackgroundColor); g.fillRect(nX, nY, nWidth, nHeight); // Normally, the image is drawn first // and the text is on top. With IMAGEBUTTON // and IMAGEBAR the image is sized // to leave a clear space for text. if ((msPreset.toUpperCase().compareTo(sIMAGEBUTTON) != 0) && (msPreset.toUpperCase().compareTo(sIMAGEBAR) != 0)) { // Draw an Image? if ((miImage != null) || (miMouseImage != null) || (miClickImage != null)) { drawImage(g, (nX + mnBorderWidth), (nY + mnBorderWidth), (nWidth - (mnBorderWidth * 2) + 1), (nHeight - (mnBorderWidth * 2) + 1)); } } g.setColor(TextColor); // If the preset is IMAGEBUTTON or IMAGEBAR, // the drawText method will also use the // font size and line count to go ahead and // draw the image. // The math here compensates for a problem // with left-biased text that was noted in testing. drawText(g, nX + mnBorderWidth, nY + mnBorderWidth, nWidth - (mnBorderWidth * 2) + 1, nHeight - (mnBorderWidth * 2) + 1); g.setColor(BorderColor); drawBorder(g, nX, nY, nWidth, nHeight); } // drawRectangle() /** */ public void drawImage(Graphics g, int nX, int nY, int nWidth, int nHeight) { // Being clicked if (mApplet.mbMouseOver && mApplet.mbMouseDown && (miClickImage != null) && (mbClickImageReady == true)) { g.drawImage(miClickImage, nX, nY, nWidth, nHeight, mClickBackgroundColor, mApplet); return; } // MouseOver, but not clicking if (mApplet.mbMouseOver && (!mApplet.mbMouseDown) && (miMouseImage != null) && (mbMouseImageReady == true)) { g.drawImage(miMouseImage, nX, nY, nWidth, nHeight, mMouseBackgroundColor, mApplet); return; } // Normal if (!mApplet.mbMouseOver && (miImage != null) && (mbImageReady == true)) { g.drawImage(miImage, nX, nY, nWidth, nHeight, mBackgroundColor, mApplet); return; } } // drawImage() /** */ public void drawBorder(Graphics g, int nX, int nY, int nWidth, int nHeight) { // Store the current color; Color tempcolor = g.getColor(); switch (mnStyle) { case RAISED: if (!mApplet.mbMouseDown) { // Draw top and left g.setColor(Color.white); g.drawLine(nX, nY, nWidth, nY); g.drawLine(nX, nY, nX, nHeight); // Draw bottom and right g.setColor(Color.black); g.drawLine(nX, (nHeight - 1), nWidth, (nHeight - 1)); g.drawLine((nWidth - 1), nY, (nWidth - 1), nHeight); } else { // Draw top and left g.setColor(Color.black); g.drawLine(nX, nY, nWidth, nY); g.drawLine(nX, nY, nX, nHeight); // Draw bottom and right g.setColor(Color.white); g.drawLine(nX, (nHeight - 1), nWidth, (nHeight - 1)); g.drawLine((nWidth - 1), nY, (nWidth - 1), nHeight); } nX++; nY++; nWidth-=2; nHeight-=2; g.setColor(tempcolor); case NORMAL: case MODERN: for (int cnt = 0; cnt < mnBorderWidth; cnt++) { g.drawRect((nX + cnt), (nY + cnt), (nWidth - (cnt * 2) - 1), (nHeight - (cnt * 2) - 1)); } // If MODERN, have to raise or lower depending on mouse if (mnStyle == MODERN) { // Raise if MouseOver but not MouseDown if (mApplet.mbMouseOver && (!mApplet.mbMouseDown)) { // Draw top and left g.setColor(Color.white); g.drawLine(nX, nY, nWidth, nY); g.drawLine(nX, nY, nX, nHeight); // Draw bottom and right g.setColor(Color.black); g.drawLine(nX, (nHeight - 1), nWidth, (nHeight - 1)); g.drawLine((nWidth - 1), nY, (nWidth - 1), nHeight); nX++; nY++; nWidth-=2; nHeight-=2; g.setColor(tempcolor); } // Down if MouseDown if (mApplet.mbMouseDown) { // Draw top and left g.setColor(Color.black); g.drawLine(nX, nY, nWidth, nY); g.drawLine(nX, nY, nX, nHeight); // Draw bottom and right g.setColor(Color.white); g.drawLine(nX, (nHeight - 1), nWidth, (nHeight - 1)); g.drawLine((nWidth - 1), nY, (nWidth - 1), nHeight); g.setColor(tempcolor); } } // (mnStyle == MODERN) break; } // switch (mnStyle) } // drawBorder() /** */ public void drawText(Graphics g, int nX, int nY, int nWidth, int nHeight) { int nCenter = 0; int nXpos = 0; int nYpos = 0; Font buttonfont; FontMetrics fm; String sText = msText; String sFont = msFont; String sTestLine; int nVAlign = mnTextVAlign; int nTextSize = mnFontSize; int nStyle = mnFontStyle; int nLastSpace = 0; int nLineIdx = 0; int nCharIdx = 0; int nMaxLines = 0; int nImageHeight = nHeight; boolean bUnderline = mbUnderline; int nUnderlineThick = 0; // Arbitrary margins that // scale ok with different size buttons int nHMargin = nWidth / 30; int nVMargin = nHeight / 30; boolean bDone = false; String sLine[]; Color ShadowColor = mTextShadowColor; // Set normal shadow color Color OriginalColor = g.getColor(); // Capture the intended text color int nStringWidth = 0; int nActualTextHeight = 0; // Used to help position text int nTotalTextHeight = 0; float fStartPoint = 0; // Being clicked if (mApplet.mbMouseOver && mApplet.mbMouseDown) { sText = msClickText; sFont = msClickFont; nTextSize = mnClickFontSize; nStyle = mnClickFontStyle; nVAlign = mnClickTextVAlign; ShadowColor = mClickTextShadowColor; bUnderline = mbClickUnderline; } // MouseOver, but not clicking if (mApplet.mbMouseOver && (!mApplet.mbMouseDown)) { sText = msMouseText; sFont = msMouseFont; nTextSize = mnMouseFontSize; nStyle = mnMouseFontStyle; nVAlign = mnMouseTextVAlign; ShadowColor = mMouseTextShadowColor; bUnderline = mbMouseUnderline; } // Assign a width for the underline nUnderlineThick = nTextSize / 10; // Add one to thickness if it's BOLD if ((nStyle & Font.BOLD) == Font.BOLD) nUnderlineThick++; // If underlining, must always be at least 1 thick if ((bUnderline == true) && (!(nUnderlineThick > 0))) nUnderlineThick = 1; sTestLine = sText; buttonfont = new Font(sFont, nStyle, nTextSize); g.setFont(buttonfont); // How big a font? fm = g.getFontMetrics(); // How many lines of text // can really fit on this button? nMaxLines = (nHeight - nY) / fm.getHeight(); // Should always be at least one line if (nMaxLines < 1) nMaxLines = 1; sLine = new String[nMaxLines]; // If text is wider than the button, // must break it into multiple lines // by looking for spaces. while (!bDone) { // Must allow for extra space of text shadowing nStringWidth = fm.stringWidth(sTestLine); if (ShadowColor != null) nStringWidth += 2; // Reduce width of button to prevent // text overhang if (nStringWidth < (nWidth - 1)) { sLine[nLineIdx] = sTestLine; nLineIdx++; // Array bounds check if (nLineIdx > (nMaxLines - 1)) bDone = true; nCharIdx += (sTestLine.length() + 1); nLastSpace = 0; if (nCharIdx > sText.length()) { bDone = true; } else { sTestLine = sText.substring(nCharIdx); } } else { nLastSpace = sTestLine.lastIndexOf(" "); // Was there a space to break on? if (nLastSpace > 0) { sTestLine = sTestLine.substring(0, nLastSpace); } else { // No spaces in the last line. // Give up and print it as is. sLine[nLineIdx] = sTestLine; nLineIdx++; bDone = true; } // if (nLastSpace > 0); } // if (fm.stringWidth(sTestLine) < nWidth) } // while (!bDone) // Shadowing will add more height to string nActualTextHeight = fm.getHeight(); if (ShadowColor != null) nActualTextHeight += 2; nTotalTextHeight = nActualTextHeight * (nLineIdx - 1); // Vertical justification -- CENTER, TOP, BOTTOM switch (nVAlign) { case VALIGN_CENTER: // How big a button and where is the center? nCenter = (nHeight/2); nYpos = (nCenter + (int)(fm.getAscent()/2) - (int)(fm.getDescent() / 2)) + nY; fStartPoint = nYpos - (fm.getHeight() * (nLineIdx - 1) / 2); nYpos = (int)fStartPoint; break; case VALIGN_TOP: fStartPoint = nY + fm.getAscent() + nVMargin; nYpos = (int)fStartPoint - nTotalTextHeight; break; case VALIGN_BOTTOM: fStartPoint = nY + nHeight - fm.getDescent() - nVMargin; nYpos = (int)fStartPoint - nTotalTextHeight; break; } // Draw the strings in multiple lines for (int cnt = 0; cnt < (nLineIdx); cnt++) { // Rounding looks better than just casting to int. // Take your pick which method to use here. /* nXpos = Math.round(((float)nWidth - (float)fm.stringWidth(sLine[cnt])) / 2); */ nXpos = Math.round(((float)nWidth / 2) - ((float)fm.stringWidth(sLine[cnt]) / 2) + nX); // Reduce Xpos by one to allow for button offset nXpos -= 1; // Text shadowing done here if (ShadowColor != null) { g.setColor(ShadowColor); g.drawString(sLine[cnt], (nXpos + 1), (nYpos + 1)); if (bUnderline) { g.fillRect((nXpos + 1), (nYpos + 2), (fm.stringWidth(sLine[cnt])), nUnderlineThick); } g.setColor(OriginalColor); g.drawString(sLine[cnt], (nXpos - 1), (nYpos - 1)); if (bUnderline) { g.fillRect(nXpos, nYpos, (fm.stringWidth(sLine[cnt])), nUnderlineThick); } } else { g.drawString(sLine[cnt], nXpos, nYpos); if (bUnderline) { g.fillRect(nXpos, (nYpos + 1), (fm.stringWidth(sLine[cnt])), nUnderlineThick); } } nYpos += nActualTextHeight; } // If the preset mode is IMAGEBAR // or IMAGEBUTTON, must draw the image // after drawing the text if ((msPreset.toUpperCase().compareTo(sIMAGEBUTTON) == 0) || (msPreset.toUpperCase().compareTo(sIMAGEBAR) == 0)) { // Draw an Image? if (miImage != null || miMouseImage != null || miClickImage != null) { nImageHeight = nHeight - (nVMargin * 2); if (sText.length() > 0) { nImageHeight -= ((nActualTextHeight * nLineIdx) + nVMargin); // Make it square nHMargin = (nWidth / 2) - (nImageHeight / 2); } drawImage(g, (nX + nHMargin), (nY + nVMargin), (nWidth - (nHMargin * 2)), nImageHeight + 1); } } } // drawText() /** */ public void doPreset(String preset) { // An easy way to configure // the button. // Some of these options also affect // the parent applet. msPreset = preset.toUpperCase(); // TOOLBAR if ((msPreset.compareTo(sTOOLBAR) == 0) || (msPreset.compareTo(sIMAGEBAR) == 0)) { // Simulate a modern browser toolbar (text-only) mApplet.mBackgroundColor = Color.lightGray; mApplet.mBorderColor = Color.lightGray; // Give it a 1 pixel applet border all around mApplet.mnButtonX = 1; mApplet.mnButtonY = 1; mApplet.mnButtonWidth = mApplet.mnButtonWidth - 2; mApplet.mnButtonHeight = mApplet.mnButtonHeight - 2; mBackgroundColor = Color.lightGray; mTextColor = Color.black; mBorderColor = Color.lightGray; mMouseBackgroundColor = Color.lightGray; mMouseTextColor = Color.black; mMouseBorderColor = Color.lightGray; mClickBackgroundColor = Color.lightGray; mClickTextColor = Color.lightGray; mClickBorderColor = Color.lightGray; mnFontSize = 10; mnMouseFontSize = 10; mnClickFontSize = 10; msFont = "Dialog"; msMouseFont = "Dialog"; msClickFont = "Dialog"; mnStyle = MODERN; // If it's an image toolbar, align text at bottom if (msPreset.compareTo(sIMAGEBAR) == 0) { mnTextVAlign = VALIGN_BOTTOM; mnMouseTextVAlign = VALIGN_BOTTOM; mnClickTextVAlign = VALIGN_BOTTOM; } return; } // if (TOOLBAR or IMAGETOOLBAR) if ((msPreset.compareTo(sPUSHBUTTON) == 0) || (msPreset.compareTo(sIMAGEBUTTON) == 0)) { // Simulate a standard push button mApplet.mBackgroundColor = Color.lightGray; mApplet.mBorderColor = Color.lightGray; mBackgroundColor = Color.lightGray; mTextColor = Color.black; mBorderColor = Color.lightGray; mMouseBackgroundColor = Color.lightGray; mMouseTextColor = Color.black; mMouseBorderColor = Color.lightGray; mClickBackgroundColor = Color.lightGray; mClickTextColor = Color.lightGray; mClickBorderColor = Color.lightGray; mnFontSize = 10; mnMouseFontSize = 10; mnClickFontSize = 10; msFont = "Dialog"; msMouseFont = "Dialog"; msClickFont = "Dialog"; mnStyle = RAISED; // If it's an image button, align text at bottom if (msPreset.compareTo(sIMAGEBUTTON) == 0) { mnTextVAlign = VALIGN_BOTTOM; mnMouseTextVAlign = VALIGN_BOTTOM; mnClickTextVAlign = VALIGN_BOTTOM; } return; } // if (PUSHBUTTON or IMAGEBUTTON) } // doPreset() /** */ public void handleMouseEntered() { // If mbMouseOver is already true, it's just a redraw. if (mApplet.mbMouseOver == true) { return; } // Highlight the button when the mouse is over it mApplet.mbMouseOver = true; paint(getGraphics()); // Do the browser caption directly and // return true mApplet.showStatus(mApplet.msMouseCaption); } // handleMouseEnter() /** */ public void handleMouseExited() { // Highlight the button when the mouse is over it if (mApplet.mbMouseJustPressed) { mApplet.mbMouseJustPressed = false; return; } if (mApplet.mbMouseDown == false) { mApplet.mbMouseOver = false; paint(getGraphics()); return; } if (mApplet.mbMouseDown) { mApplet.mbMouseDown = false; mApplet.mbMouseOver = false; mApplet.mbMouseDragOut = true; mApplet.paint(mApplet.getGraphics()); } } // handleMouseExited() /** */ public void handleMousePressed() { mApplet.mbMouseDown = true; mApplet.mbMouseJustPressed = true; mApplet.paint(mApplet.getGraphics()); // Send a notice to the applet to change // to the msClickCaption mApplet.showStatus(mApplet.msClickCaption); } // handleMouseDown() /** */ public void handleMouseReleased() { // Is the button being clicked? if (mApplet.mbMouseDown && mApplet.mbMouseOver) { mApplet.mbMouseDown = false; // Refresh the applet and let it // take care of refreshing the button mApplet.paint(mApplet.getGraphics()); mApplet.fireLink(); // Refresh again because link might be // in a frame and not affected mApplet.mbMouseJustPressed = false; mApplet.mbMouseOver = true; mApplet.paint(mApplet.getGraphics()); } } // handleMouseUp() /** */ public void checkProperties() { // Make sure that the mouse and click // event properties are set. // If an event property is not set, just // copy the normal property. if (mMouseBackgroundColor == null) mMouseBackgroundColor = mBackgroundColor; if (mMouseBorderColor == null) mMouseBorderColor = mBorderColor; if (mMouseTextColor == null) mMouseTextColor = mTextColor; if (msMouseText == "") msMouseText = msText; if (msMouseFont == "") msMouseFont = msFont; if (mnMouseFontSize == 0) mnMouseFontSize = mnFontSize; if (miMouseImage == null) miMouseImage = miImage; if (mClickBackgroundColor == null) mClickBackgroundColor = mBackgroundColor; if (mClickBorderColor == null) mClickBorderColor = mBorderColor; if (mClickTextColor == null) mClickTextColor = mTextColor; if (msClickText == "") msClickText = msMouseText; if (msClickFont == "") msClickFont = msMouseFont; if (mnClickFontSize == 0) mnClickFontSize = mnMouseFontSize; if (miClickImage == null) miClickImage = miMouseImage; } // checkProperties() }