001: package Schmortopf.Utility.gui;
002:
003: /**
004: * Behaves completely like an ordinary V1.22 JMenu,
005: * but it will signalize mouseovers by slightly
006: * changing the fore/background contrast,
007: * like one is used from the internet.
008: *
009: * Additionally it will try to play the menumouseover.wav
010: * sound on each mouseover.
011: *
012: * To support change of constructors in future swing versions
013: * just change the constructors below accordingly.
014: *
015: */
016:
017: import java.util.EventListener;
018:
019: import java.awt.*;
020: import java.awt.event.*;
021: import java.awt.image.*;
022:
023: import javax.swing.JMenu;
024: import javax.swing.Icon;
025: import javax.swing.JInternalFrame;
026: import javax.swing.SwingUtilities;
027:
028: import Schmortopf.Main.IDE_MainFrameProvider;
029:
030: public class JSenseMenu extends JMenu implements MouseListener,
031: MouseMotionListener {
032:
033: Color saveBackGround = null; // cache for original background color,
034: // on mouseovers
035: Color saveForeGround = null; // cache for original background color,
036: // on mouseovers
037: private boolean isSelected = false;
038:
039: private IDE_MainFrameProvider mainFrameProvider;
040:
041: /**
042: * Creates a new JMenu with no text.
043: */
044: public JSenseMenu(IDE_MainFrameProvider mainFrameProvider) {
045: super ("");
046: this .mainFrameProvider = mainFrameProvider;
047: this .addMouseListener(this );
048: this .addMouseMotionListener(this );
049: }
050:
051: /**
052: * Creates a new JMenu with the supplied string as its text
053: *
054: * @param s The text for the menu label
055: */
056: public JSenseMenu(String s,
057: final IDE_MainFrameProvider mainFrameProvider) {
058: super (s);
059: this .mainFrameProvider = mainFrameProvider;
060: this .addMouseListener(this );
061: this .addMouseMotionListener(this );
062: }
063:
064: /**
065: * Creates a new JMenu with the supplied string as its text
066: * and specified as a tear-off menu or not.
067: *
068: * @param s The text for the menu label
069: * @param b can the menu be torn off (not yet implemented)
070: */
071: public JSenseMenu(String s, boolean b,
072: final IDE_MainFrameProvider mainFrameProvider) {
073: super (s);
074: this .mainFrameProvider = mainFrameProvider;
075: this .addMouseListener(this );
076: this .addMouseMotionListener(this );
077: }
078:
079: public void mouseEntered(MouseEvent e) {
080:
081: //if( true ) return;
082:
083: boolean mouseButtonDown = ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0);
084: // Important: Don't trigger on mousedrag operations over this menu,
085: // because this captures the focus.
086:
087: if ((!isSelected) && (this .isVisible())
088: && (this .getIsParentFrameOnTop()) && (!mouseButtonDown)) {
089: // this line was inserted, because the menu always gave the focus
090: // back to the component lastly having focus.
091: // So if the menu gets focus only by roll over the problem is solved.
092: // So this line is kind of work-around and can be "weggemacht" on demand.
093: this .getParent().requestFocus();
094:
095: isSelected = true;
096: saveForeGround = this .getForeground();
097: saveBackGround = this .getBackground();
098: int foreGroundGrayScale = saveForeGround.getRed()
099: + saveForeGround.getGreen()
100: + saveForeGround.getBlue();
101: int backGroundGrayScale = saveBackGround.getRed()
102: + saveBackGround.getGreen()
103: + saveBackGround.getBlue();
104: final int ColorDelta = 20;
105: if (foreGroundGrayScale < backGroundGrayScale) {
106: // we have dark text on light bg. Enlarger contrast :
107: int newRed;
108: newRed = saveBackGround.getRed() + ColorDelta;
109: if (newRed > 255) {
110: newRed = 255;
111: }
112: int newGreen;
113: newGreen = saveBackGround.getGreen() + ColorDelta;
114: if (newGreen > 255) {
115: newGreen = 255;
116: }
117: int newBlue;
118: newBlue = saveBackGround.getBlue() + ColorDelta;
119: if (newBlue > 255) {
120: newBlue = 255;
121: }
122: this
123: .setBackground(new Color(newRed, newGreen,
124: newBlue));
125: } else {
126: // we have light text on dark bg. Enlarger contrast :
127: int newRed;
128: newRed = saveBackGround.getRed() - ColorDelta;
129: if (newRed < 0) {
130: newRed = 0;
131: }
132: int newGreen;
133: newGreen = saveBackGround.getGreen() - ColorDelta;
134: if (newGreen < 0) {
135: newGreen = 0;
136: }
137: int newBlue;
138: newBlue = saveBackGround.getBlue() - ColorDelta;
139: if (newBlue < 0) {
140: newBlue = 0;
141: }
142: this
143: .setBackground(new Color(newRed, newGreen,
144: newBlue));
145: }
146:
147: SoundPlaybackThread t = new SoundPlaybackThread(
148: "menumouseover.wav", this .mainFrameProvider);
149: t.start();
150:
151: } // if
152: } // mouseEntered
153:
154: public void mouseExited(MouseEvent e) {
155:
156: //if( true ) return;
157:
158: if ((this .isVisible()) && (this .getIsParentFrameOnTop())) {
159: // reset original colors :
160: if (saveBackGround != null) {
161: this .setBackground(saveBackGround);
162: }
163: isSelected = false;
164: }
165: } // mouseExited
166:
167: /**
168: * Additional checks, which actually only are needed,
169: * if the button is inside an JInternalFrame.
170: */
171: public boolean getIsParentFrameOnTop() {
172: boolean onTop = true;
173: Container workParent = this ;
174: while (true) {
175: workParent = workParent.getParent(); // step back
176: if (workParent == null) {
177: break;
178: }
179: if (workParent instanceof JInternalFrame) {
180: JInternalFrame iframe = (JInternalFrame) workParent;
181: onTop = iframe.isSelected();
182: break;
183: }
184: } // while
185: return onTop;
186: } // getIsParentFrameActivated
187:
188: public void mouseReleased(MouseEvent e) {
189: }
190:
191: public void mousePressed(MouseEvent e) {
192: }
193:
194: public void mouseClicked(MouseEvent e) {
195: }
196:
197: public void mouseMoved(MouseEvent e) {
198: }
199:
200: public void mouseDragged(MouseEvent e) {
201: }
202:
203: } // JSenseMenu
|