/** * Returns the component in the currently selected path which contains sourcePoint. * * @param source The component in whose coordinate space sourcePoint is given * @param sourcePoint The point which is being tested * @return The component in the currently selected path which contains sourcePoint (relative to * the source component's coordinate space. If sourcePoint is not inside a component on the * currently selected path, null is returned. */ public Component componentForPoint(Component source, Point sourcePoint) { int screenX, screenY; Point p = sourcePoint; int i, c, j, d; Component mc; Rectangle r2; int cWidth, cHeight; MenuElement menuElement; MenuElement subElements[]; Vector<MenuElement> tmp; int selectionSize; SwingUtilities.convertPointToScreen(p, source); screenX = p.x; screenY = p.y; tmp = (Vector<MenuElement>) selection.clone(); selectionSize = tmp.size(); for (i = selectionSize - 1; i >= 0; i--) { menuElement = (MenuElement) tmp.elementAt(i); subElements = menuElement.getSubElements(); for (j = 0, d = subElements.length; j < d; j++) { if (subElements[j] == null) continue; mc = subElements[j].getComponent(); if (!mc.isShowing()) continue; if (mc instanceof JComponent) { cWidth = mc.getWidth(); cHeight = mc.getHeight(); } else { r2 = mc.getBounds(); cWidth = r2.width; cHeight = r2.height; } p.x = screenX; p.y = screenY; SwingUtilities.convertPointFromScreen(p, mc); /** * Return the deepest component on the selection path in whose bounds the event's point * occurs */ if (p.x >= 0 && p.x < cWidth && p.y >= 0 && p.y < cHeight) { return mc; } } } return null; }
/** * When a MenuElement receives an event from a MouseListener, it should never process the event * directly. Instead all MenuElements should call this method with the event. * * @param event a MouseEvent object */ public void processMouseEvent(MouseEvent event) { int screenX, screenY; Point p; int i, c, j, d; Component mc; Rectangle r2; int cWidth, cHeight; MenuElement menuElement; MenuElement subElements[]; MenuElement path[]; Vector<MenuElement> tmp; int selectionSize; p = event.getPoint(); Component source = event.getComponent(); if ((source != null) && !source.isShowing()) { // This can happen if a mouseReleased removes the // containing component -- bug 4146684 return; } int type = event.getID(); int modifiers = event.getModifiers(); // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2 if ((type == MouseEvent.MOUSE_ENTERED || type == MouseEvent.MOUSE_EXITED) && ((modifiers & (InputEvent.BUTTON1_MASK | InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) != 0)) { return; } if (source != null) { SwingUtilities.convertPointToScreen(p, source); } screenX = p.x; screenY = p.y; tmp = (Vector<MenuElement>) selection.clone(); selectionSize = tmp.size(); boolean success = false; for (i = selectionSize - 1; i >= 0 && success == false; i--) { menuElement = (MenuElement) tmp.elementAt(i); subElements = menuElement.getSubElements(); path = null; for (j = 0, d = subElements.length; j < d && success == false; j++) { if (subElements[j] == null) continue; mc = subElements[j].getComponent(); if (!mc.isShowing()) continue; if (mc instanceof JComponent) { cWidth = mc.getWidth(); cHeight = mc.getHeight(); } else { r2 = mc.getBounds(); cWidth = r2.width; cHeight = r2.height; } p.x = screenX; p.y = screenY; SwingUtilities.convertPointFromScreen(p, mc); /** * Send the event to visible menu element if menu element currently in the selected path or * contains the event location */ if ((p.x >= 0 && p.x < cWidth && p.y >= 0 && p.y < cHeight)) { int k; if (path == null) { path = new MenuElement[i + 2]; for (k = 0; k <= i; k++) path[k] = (MenuElement) tmp.elementAt(k); } path[i + 1] = subElements[j]; MenuElement currentSelection[] = getSelectedPath(); // Enter/exit detection -- needs tuning... if (currentSelection[currentSelection.length - 1] != path[i + 1] && (currentSelection.length < 2 || currentSelection[currentSelection.length - 2] != path[i + 1])) { Component oldMC = currentSelection[currentSelection.length - 1].getComponent(); MouseEvent exitEvent = new MouseEvent( oldMC, MouseEvent.MOUSE_EXITED, event.getWhen(), event.getModifiers(), p.x, p.y, event.getXOnScreen(), event.getYOnScreen(), event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); currentSelection[currentSelection.length - 1].processMouseEvent(exitEvent, path, this); MouseEvent enterEvent = new MouseEvent( mc, MouseEvent.MOUSE_ENTERED, event.getWhen(), event.getModifiers(), p.x, p.y, event.getXOnScreen(), event.getYOnScreen(), event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); subElements[j].processMouseEvent(enterEvent, path, this); } MouseEvent mouseEvent = new MouseEvent( mc, event.getID(), event.getWhen(), event.getModifiers(), p.x, p.y, event.getXOnScreen(), event.getYOnScreen(), event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); subElements[j].processMouseEvent(mouseEvent, path, this); success = true; event.consume(); } } } }