1 /*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
122 selection.removeElementAt(i);
123 me.menuSelectionChanged(false);
124 }
125
126 for(i = firstDifference, c = path.length ; i < c ; i++) {
127 if (path[i] != null) {
128 selection.addElement(path[i]);
129 path[i].menuSelectionChanged(true);
130 }
131 }
132
133 fireStateChanged();
134 }
135
136 /**
137 * Returns the path to the currently selected menu item
138 *
139 * @return an array of MenuElement objects representing the selected path
140 */
141 public MenuElement[] getSelectedPath() {
142 MenuElement res[] = new MenuElement[selection.size()];
143 int i,c;
144 for(i=0,c=selection.size();i<c;i++)
145 res[i] = selection.elementAt(i);
146 return res;
147 }
148
149 /**
150 * Tell the menu selection to close and unselect all the menu components. Call this method
151 * when a choice has been made
152 */
153 public void clearSelectedPath() {
154 if (selection.size() > 0) {
155 setSelectedPath(null);
156 }
157 }
158
159 /**
160 * Adds a ChangeListener to the button.
161 *
162 * @param l the listener to add
206 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
207 }
208 }
209 }
210
211 /**
212 * When a MenuElement receives an event from a MouseListener, it should never process the event
213 * directly. Instead all MenuElements should call this method with the event.
214 *
215 * @param event a MouseEvent object
216 */
217 @SuppressWarnings("deprecation")
218 public void processMouseEvent(MouseEvent event) {
219 int screenX,screenY;
220 Point p;
221 int i,c,j,d;
222 Component mc;
223 Rectangle r2;
224 int cWidth,cHeight;
225 MenuElement menuElement;
226 MenuElement subElements[];
227 MenuElement path[];
228 int selectionSize;
229 p = event.getPoint();
230
231 Component source = event.getComponent();
232
233 if ((source != null) && !source.isShowing()) {
234 // This can happen if a mouseReleased removes the
235 // containing component -- bug 4146684
236 return;
237 }
238
239 int type = event.getID();
240 int modifiers = event.getModifiers();
241 // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2
242 if ((type==MouseEvent.MOUSE_ENTERED||
243 type==MouseEvent.MOUSE_EXITED)
244 && ((modifiers & (InputEvent.BUTTON1_MASK |
245 InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) !=0 )) {
246 return;
247 }
275 r2 = mc.getBounds();
276 cWidth = r2.width;
277 cHeight = r2.height;
278 }
279 p.x = screenX;
280 p.y = screenY;
281 SwingUtilities.convertPointFromScreen(p,mc);
282
283 /** Send the event to visible menu element if menu element currently in
284 * the selected path or contains the event location
285 */
286 if(
287 (p.x >= 0 && p.x < cWidth && p.y >= 0 && p.y < cHeight)) {
288 int k;
289 if(path == null) {
290 path = new MenuElement[i+2];
291 for(k=0;k<=i;k++)
292 path[k] = tmp.elementAt(k);
293 }
294 path[i+1] = subElements[j];
295 MenuElement currentSelection[] = getSelectedPath();
296
297 // Enter/exit detection -- needs tuning...
298 if (currentSelection[currentSelection.length-1] !=
299 path[i+1] &&
300 (currentSelection.length < 2 ||
301 currentSelection[currentSelection.length-2] !=
302 path[i+1])) {
303 Component oldMC = currentSelection[currentSelection.length-1].getComponent();
304
305 MouseEvent exitEvent = new MouseEvent(oldMC, MouseEvent.MOUSE_EXITED,
306 event.getWhen(),
307 event.getModifiers(), p.x, p.y,
308 event.getXOnScreen(),
309 event.getYOnScreen(),
310 event.getClickCount(),
311 event.isPopupTrigger(),
312 MouseEvent.NOBUTTON);
313 MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
314 meAccessor.setCausedByTouchEvent(exitEvent,
315 meAccessor.isCausedByTouchEvent(event));
330 subElements[j].processMouseEvent(enterEvent, path, this);
331 }
332 MouseEvent mouseEvent = new MouseEvent(mc, event.getID(),event. getWhen(),
333 event.getModifiers(), p.x, p.y,
334 event.getXOnScreen(),
335 event.getYOnScreen(),
336 event.getClickCount(),
337 event.isPopupTrigger(),
338 MouseEvent.NOBUTTON);
339 MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
340 meAccessor.setCausedByTouchEvent(mouseEvent,
341 meAccessor.isCausedByTouchEvent(event));
342 subElements[j].processMouseEvent(mouseEvent, path, this);
343 success = true;
344 event.consume();
345 }
346 }
347 }
348 }
349
350 private void printMenuElementArray(MenuElement path[]) {
351 printMenuElementArray(path, false);
352 }
353
354 private void printMenuElementArray(MenuElement path[], boolean dumpStack) {
355 System.out.println("Path is(");
356 int i, j;
357 for(i=0,j=path.length; i<j ;i++){
358 for (int k=0; k<=i; k++)
359 System.out.print(" ");
360 MenuElement me = path[i];
361 if(me instanceof JMenuItem) {
362 System.out.println(((JMenuItem)me).getText() + ", ");
363 } else if (me instanceof JMenuBar) {
364 System.out.println("JMenuBar, ");
365 } else if(me instanceof JPopupMenu) {
366 System.out.println("JPopupMenu, ");
367 } else if (me == null) {
368 System.out.println("NULL , ");
369 } else {
370 System.out.println("" + me + ", ");
371 }
372 }
373 System.out.println(")");
374
379 /**
380 * Returns the component in the currently selected path
381 * which contains sourcePoint.
382 *
383 * @param source The component in whose coordinate space sourcePoint
384 * is given
385 * @param sourcePoint The point which is being tested
386 * @return The component in the currently selected path which
387 * contains sourcePoint (relative to the source component's
388 * coordinate space. If sourcePoint is not inside a component
389 * on the currently selected path, null is returned.
390 */
391 public Component componentForPoint(Component source, Point sourcePoint) {
392 int screenX,screenY;
393 Point p = sourcePoint;
394 int i,c,j,d;
395 Component mc;
396 Rectangle r2;
397 int cWidth,cHeight;
398 MenuElement menuElement;
399 MenuElement subElements[];
400 int selectionSize;
401
402 SwingUtilities.convertPointToScreen(p,source);
403
404 screenX = p.x;
405 screenY = p.y;
406
407 @SuppressWarnings("unchecked")
408 Vector<MenuElement> tmp = (Vector<MenuElement>)selection.clone();
409 selectionSize = tmp.size();
410 for(i=selectionSize - 1 ; i >= 0 ; i--) {
411 menuElement = tmp.elementAt(i);
412 subElements = menuElement.getSubElements();
413
414 for(j = 0, d = subElements.length ; j < d ; j++) {
415 if (subElements[j] == null)
416 continue;
417 mc = subElements[j].getComponent();
418 if(!mc.isShowing())
419 continue;
487 return;
488 }
489 }
490
491 /**
492 * Return true if {@code c} is part of the currently used menu
493 *
494 * @param c a {@code Component}
495 * @return true if {@code c} is part of the currently used menu,
496 * false otherwise
497 */
498 public boolean isComponentPartOfCurrentMenu(Component c) {
499 if(selection.size() > 0) {
500 MenuElement me = selection.elementAt(0);
501 return isComponentPartOfCurrentMenu(me,c);
502 } else
503 return false;
504 }
505
506 private boolean isComponentPartOfCurrentMenu(MenuElement root,Component c) {
507 MenuElement children[];
508 int i,d;
509
510 if (root == null)
511 return false;
512
513 if(root.getComponent() == c)
514 return true;
515 else {
516 children = root.getSubElements();
517 for(i=0,d=children.length;i<d;i++) {
518 if(isComponentPartOfCurrentMenu(children[i],c))
519 return true;
520 }
521 }
522 return false;
523 }
524 }
|
1 /*
2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
122 selection.removeElementAt(i);
123 me.menuSelectionChanged(false);
124 }
125
126 for(i = firstDifference, c = path.length ; i < c ; i++) {
127 if (path[i] != null) {
128 selection.addElement(path[i]);
129 path[i].menuSelectionChanged(true);
130 }
131 }
132
133 fireStateChanged();
134 }
135
136 /**
137 * Returns the path to the currently selected menu item
138 *
139 * @return an array of MenuElement objects representing the selected path
140 */
141 public MenuElement[] getSelectedPath() {
142 MenuElement[] res = new MenuElement[selection.size()];
143 int i,c;
144 for(i=0,c=selection.size();i<c;i++)
145 res[i] = selection.elementAt(i);
146 return res;
147 }
148
149 /**
150 * Tell the menu selection to close and unselect all the menu components. Call this method
151 * when a choice has been made
152 */
153 public void clearSelectedPath() {
154 if (selection.size() > 0) {
155 setSelectedPath(null);
156 }
157 }
158
159 /**
160 * Adds a ChangeListener to the button.
161 *
162 * @param l the listener to add
206 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
207 }
208 }
209 }
210
211 /**
212 * When a MenuElement receives an event from a MouseListener, it should never process the event
213 * directly. Instead all MenuElements should call this method with the event.
214 *
215 * @param event a MouseEvent object
216 */
217 @SuppressWarnings("deprecation")
218 public void processMouseEvent(MouseEvent event) {
219 int screenX,screenY;
220 Point p;
221 int i,c,j,d;
222 Component mc;
223 Rectangle r2;
224 int cWidth,cHeight;
225 MenuElement menuElement;
226 MenuElement[] subElements;
227 MenuElement[] path;
228 int selectionSize;
229 p = event.getPoint();
230
231 Component source = event.getComponent();
232
233 if ((source != null) && !source.isShowing()) {
234 // This can happen if a mouseReleased removes the
235 // containing component -- bug 4146684
236 return;
237 }
238
239 int type = event.getID();
240 int modifiers = event.getModifiers();
241 // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2
242 if ((type==MouseEvent.MOUSE_ENTERED||
243 type==MouseEvent.MOUSE_EXITED)
244 && ((modifiers & (InputEvent.BUTTON1_MASK |
245 InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) !=0 )) {
246 return;
247 }
275 r2 = mc.getBounds();
276 cWidth = r2.width;
277 cHeight = r2.height;
278 }
279 p.x = screenX;
280 p.y = screenY;
281 SwingUtilities.convertPointFromScreen(p,mc);
282
283 /** Send the event to visible menu element if menu element currently in
284 * the selected path or contains the event location
285 */
286 if(
287 (p.x >= 0 && p.x < cWidth && p.y >= 0 && p.y < cHeight)) {
288 int k;
289 if(path == null) {
290 path = new MenuElement[i+2];
291 for(k=0;k<=i;k++)
292 path[k] = tmp.elementAt(k);
293 }
294 path[i+1] = subElements[j];
295 MenuElement[] currentSelection = getSelectedPath();
296
297 // Enter/exit detection -- needs tuning...
298 if (currentSelection[currentSelection.length-1] !=
299 path[i+1] &&
300 (currentSelection.length < 2 ||
301 currentSelection[currentSelection.length-2] !=
302 path[i+1])) {
303 Component oldMC = currentSelection[currentSelection.length-1].getComponent();
304
305 MouseEvent exitEvent = new MouseEvent(oldMC, MouseEvent.MOUSE_EXITED,
306 event.getWhen(),
307 event.getModifiers(), p.x, p.y,
308 event.getXOnScreen(),
309 event.getYOnScreen(),
310 event.getClickCount(),
311 event.isPopupTrigger(),
312 MouseEvent.NOBUTTON);
313 MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
314 meAccessor.setCausedByTouchEvent(exitEvent,
315 meAccessor.isCausedByTouchEvent(event));
330 subElements[j].processMouseEvent(enterEvent, path, this);
331 }
332 MouseEvent mouseEvent = new MouseEvent(mc, event.getID(),event. getWhen(),
333 event.getModifiers(), p.x, p.y,
334 event.getXOnScreen(),
335 event.getYOnScreen(),
336 event.getClickCount(),
337 event.isPopupTrigger(),
338 MouseEvent.NOBUTTON);
339 MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
340 meAccessor.setCausedByTouchEvent(mouseEvent,
341 meAccessor.isCausedByTouchEvent(event));
342 subElements[j].processMouseEvent(mouseEvent, path, this);
343 success = true;
344 event.consume();
345 }
346 }
347 }
348 }
349
350 private void printMenuElementArray(MenuElement[] path) {
351 printMenuElementArray(path, false);
352 }
353
354 private void printMenuElementArray(MenuElement[] path, boolean dumpStack) {
355 System.out.println("Path is(");
356 int i, j;
357 for(i=0,j=path.length; i<j ;i++){
358 for (int k=0; k<=i; k++)
359 System.out.print(" ");
360 MenuElement me = path[i];
361 if(me instanceof JMenuItem) {
362 System.out.println(((JMenuItem)me).getText() + ", ");
363 } else if (me instanceof JMenuBar) {
364 System.out.println("JMenuBar, ");
365 } else if(me instanceof JPopupMenu) {
366 System.out.println("JPopupMenu, ");
367 } else if (me == null) {
368 System.out.println("NULL , ");
369 } else {
370 System.out.println("" + me + ", ");
371 }
372 }
373 System.out.println(")");
374
379 /**
380 * Returns the component in the currently selected path
381 * which contains sourcePoint.
382 *
383 * @param source The component in whose coordinate space sourcePoint
384 * is given
385 * @param sourcePoint The point which is being tested
386 * @return The component in the currently selected path which
387 * contains sourcePoint (relative to the source component's
388 * coordinate space. If sourcePoint is not inside a component
389 * on the currently selected path, null is returned.
390 */
391 public Component componentForPoint(Component source, Point sourcePoint) {
392 int screenX,screenY;
393 Point p = sourcePoint;
394 int i,c,j,d;
395 Component mc;
396 Rectangle r2;
397 int cWidth,cHeight;
398 MenuElement menuElement;
399 MenuElement[] subElements;
400 int selectionSize;
401
402 SwingUtilities.convertPointToScreen(p,source);
403
404 screenX = p.x;
405 screenY = p.y;
406
407 @SuppressWarnings("unchecked")
408 Vector<MenuElement> tmp = (Vector<MenuElement>)selection.clone();
409 selectionSize = tmp.size();
410 for(i=selectionSize - 1 ; i >= 0 ; i--) {
411 menuElement = tmp.elementAt(i);
412 subElements = menuElement.getSubElements();
413
414 for(j = 0, d = subElements.length ; j < d ; j++) {
415 if (subElements[j] == null)
416 continue;
417 mc = subElements[j].getComponent();
418 if(!mc.isShowing())
419 continue;
487 return;
488 }
489 }
490
491 /**
492 * Return true if {@code c} is part of the currently used menu
493 *
494 * @param c a {@code Component}
495 * @return true if {@code c} is part of the currently used menu,
496 * false otherwise
497 */
498 public boolean isComponentPartOfCurrentMenu(Component c) {
499 if(selection.size() > 0) {
500 MenuElement me = selection.elementAt(0);
501 return isComponentPartOfCurrentMenu(me,c);
502 } else
503 return false;
504 }
505
506 private boolean isComponentPartOfCurrentMenu(MenuElement root,Component c) {
507 MenuElement[] children;
508 int i,d;
509
510 if (root == null)
511 return false;
512
513 if(root.getComponent() == c)
514 return true;
515 else {
516 children = root.getSubElements();
517 for(i=0,d=children.length;i<d;i++) {
518 if(isComponentPartOfCurrentMenu(children[i],c))
519 return true;
520 }
521 }
522 return false;
523 }
524 }
|