38 |
package javax.swing; |
package javax.swing; |
39 |
|
|
40 |
import java.awt.Component; |
import java.awt.Component; |
41 |
|
import java.awt.Dimension; |
42 |
import java.awt.Point; |
import java.awt.Point; |
43 |
import java.awt.event.KeyEvent; |
import java.awt.event.KeyEvent; |
44 |
import java.awt.event.MouseEvent; |
import java.awt.event.MouseEvent; |
125 |
for (int i = selectedPath.size() - 1; i >= 0; i--) |
for (int i = selectedPath.size() - 1; i >= 0; i--) |
126 |
((MenuElement) selectedPath.get(i)).menuSelectionChanged(false); |
((MenuElement) selectedPath.get(i)).menuSelectionChanged(false); |
127 |
|
|
|
// notify all listeners that the selected path was changed |
|
|
fireStateChanged(); |
|
|
|
|
128 |
// clear selected path |
// clear selected path |
129 |
selectedPath.clear(); |
selectedPath.clear(); |
130 |
|
|
131 |
|
// notify all listeners that the selected path was changed |
132 |
|
fireStateChanged(); |
133 |
} |
} |
134 |
|
|
135 |
/** |
/** |
136 |
* DOCUMENT ME! |
* This method returns menu element on the selected path that contains |
137 |
|
* given source point. If no menu element on the selected path contains this |
138 |
|
* point, then null is returned. |
139 |
* |
* |
140 |
* @param source DOCUMENT ME! |
* @param source Component relative to which sourcePoint is given |
141 |
* @param sourcePoint DOCUMENT ME! |
* @param sourcePoint point for which we want to find menu element that contains it |
142 |
* |
* |
143 |
* @return DOCUMENT ME! |
* @return Returns menu element that contains given source point and belongs |
144 |
|
* to the currently selected path. Null is return if no such menu element found. |
145 |
*/ |
*/ |
146 |
public Component componentForPoint(Component source, Point sourcePoint) |
public Component componentForPoint(Component source, Point sourcePoint) |
147 |
{ |
{ |
148 |
throw new UnsupportedOperationException("not implemented"); |
// Convert sourcePoint to screen coordinates. |
149 |
|
Point sourcePointOnScreen = sourcePoint; |
150 |
|
SwingUtilities.convertPointToScreen(sourcePointOnScreen, source); |
151 |
|
|
152 |
|
Point compPointOnScreen; |
153 |
|
Component resultComp = null; |
154 |
|
|
155 |
|
// For each menu element on the selected path, express its location |
156 |
|
// in terms of screen coordinates and check if there is any |
157 |
|
// menu element on the selected path that contains given source point. |
158 |
|
for (int i = 0; i < selectedPath.size(); i++) |
159 |
|
{ |
160 |
|
Component comp = ((Component) selectedPath.get(i)); |
161 |
|
Dimension size = comp.getSize(); |
162 |
|
|
163 |
|
// convert location of this menu item to screen coordinates |
164 |
|
compPointOnScreen = comp.getLocationOnScreen(); |
165 |
|
|
166 |
|
if (compPointOnScreen.x <= sourcePointOnScreen.x |
167 |
|
&& sourcePointOnScreen.x < compPointOnScreen.x + size.width |
168 |
|
&& compPointOnScreen.y <= sourcePointOnScreen.y |
169 |
|
&& sourcePointOnScreen.y < compPointOnScreen.y + size.height) |
170 |
|
{ |
171 |
|
Point p = sourcePointOnScreen; |
172 |
|
SwingUtilities.convertPointFromScreen(p, comp); |
173 |
|
resultComp = SwingUtilities.getDeepestComponentAt(comp, p.x, p.y); |
174 |
|
break; |
175 |
|
} |
176 |
|
} |
177 |
|
return resultComp; |
178 |
} |
} |
179 |
|
|
180 |
/** |
/** |
209 |
* @param c Component for which to check |
* @param c Component for which to check |
210 |
* @return True if specified component is part of current menu |
* @return True if specified component is part of current menu |
211 |
*/ |
*/ |
212 |
boolean isComponentPartOfCurrentMenu(Component c) |
public boolean isComponentPartOfCurrentMenu(Component c) |
213 |
{ |
{ |
214 |
MenuElement[] subElements; |
MenuElement[] subElements; |
215 |
for (int i = 0; i < selectedPath.size(); i++) |
for (int i = 0; i < selectedPath.size(); i++) |
242 |
*/ |
*/ |
243 |
public void processMouseEvent(MouseEvent event) |
public void processMouseEvent(MouseEvent event) |
244 |
{ |
{ |
245 |
Component c = ((Component) event.getSource()); |
Component source = ((Component) event.getSource()); |
246 |
|
|
247 |
MenuElement[] path = getPath(c); |
// In the case of drag event, event.getSource() returns component |
248 |
((MenuElement) c).processMouseEvent(event, path, manager); |
// where drag event originated. However menu element processing this |
249 |
|
// event should be the one over which mouse is currently located, |
250 |
|
// which is not necessary the source of the drag event. |
251 |
|
Component mouseOverMenuComp; |
252 |
|
|
253 |
|
// find over which menu element the mouse is currently located |
254 |
|
if (event.getID() == MouseEvent.MOUSE_DRAGGED |
255 |
|
|| event.getID() == MouseEvent.MOUSE_RELEASED) |
256 |
|
mouseOverMenuComp = componentForPoint(source, event.getPoint()); |
257 |
|
else |
258 |
|
mouseOverMenuComp = source; |
259 |
|
|
260 |
// forward events to subcomponents |
// Process this event only if mouse is located over some menu element |
261 |
MenuElement[] subComponents = ((MenuElement) c).getSubElements(); |
if (mouseOverMenuComp != null && (mouseOverMenuComp instanceof MenuElement)) |
262 |
|
{ |
263 |
|
MenuElement[] path = getPath(mouseOverMenuComp); |
264 |
|
((MenuElement) mouseOverMenuComp).processMouseEvent(event, path, |
265 |
|
manager); |
266 |
|
|
267 |
|
// FIXME: Java specification says that mouse events should be |
268 |
|
// forwarded to subcomponents. The code below does it, but |
269 |
|
// menu's work fine without it. This code is commented for now. |
270 |
|
|
271 |
|
/* |
272 |
|
MenuElement[] subComponents = ((MenuElement) mouseOverMenuComp) |
273 |
|
.getSubElements(); |
274 |
|
|
275 |
for (int i = 0; i < subComponents.length; i++) |
for (int i = 0; i < subComponents.length; i++) |
276 |
{ |
{ |
|
if (subComponents[i] instanceof JMenuItem) |
|
277 |
subComponents[i].processMouseEvent(event, path, manager); |
subComponents[i].processMouseEvent(event, path, manager); |
278 |
} |
} |
279 |
|
*/ |
280 |
|
} |
281 |
} |
} |
282 |
|
|
283 |
/** |
/** |
293 |
return; |
return; |
294 |
} |
} |
295 |
|
|
|
fireStateChanged(); |
|
|
|
|
296 |
int i; |
int i; |
297 |
int minSize = path.length; // size of the smaller path. |
int minSize = path.length; // size of the smaller path. |
298 |
|
|
299 |
if (path.length > selectedPath.size()) |
if (path.length > selectedPath.size()) |
300 |
{ |
{ |
301 |
|
minSize = selectedPath.size(); |
302 |
|
|
303 |
// if new selected path contains more elements then current |
// if new selected path contains more elements then current |
304 |
// selection then first add all elements at |
// selection then first add all elements at |
305 |
// the indexes > selectedPath.size |
// the indexes > selectedPath.size |
308 |
selectedPath.add(path[i]); |
selectedPath.add(path[i]); |
309 |
path[i].menuSelectionChanged(true); |
path[i].menuSelectionChanged(true); |
310 |
} |
} |
|
|
|
|
minSize = selectedPath.size(); |
|
311 |
} |
} |
312 |
|
|
313 |
else if (path.length < selectedPath.size()) |
else if (path.length < selectedPath.size()) |
328 |
// same location and adjust selection until |
// same location and adjust selection until |
329 |
// same menu elements will be encountered at the |
// same menu elements will be encountered at the |
330 |
// same index in both current and new selection path. |
// same index in both current and new selection path. |
331 |
MenuElement oldSelectedPath; |
MenuElement oldSelectedItem; |
332 |
|
|
333 |
for (i = minSize - 1; i >= 0; i--) |
for (i = minSize - 1; i >= 0; i--) |
334 |
{ |
{ |
335 |
oldSelectedPath = (MenuElement) selectedPath.get(i); |
oldSelectedItem = (MenuElement) selectedPath.get(i); |
336 |
|
|
337 |
if (path[i].equals(oldSelectedPath)) |
if (path[i].equals(oldSelectedItem)) |
338 |
break; |
break; |
339 |
|
|
340 |
oldSelectedPath.menuSelectionChanged(false); |
oldSelectedItem.menuSelectionChanged(false); |
341 |
path[i].menuSelectionChanged(true); |
path[i].menuSelectionChanged(true); |
342 |
selectedPath.setElementAt(path[i], i); |
selectedPath.setElementAt(path[i], i); |
343 |
} |
} |
344 |
|
|
345 |
|
fireStateChanged(); |
346 |
} |
} |
347 |
|
|
348 |
/** |
/** |
354 |
*/ |
*/ |
355 |
private MenuElement[] getPath(Component c) |
private MenuElement[] getPath(Component c) |
356 |
{ |
{ |
357 |
|
// FIXME: There is the same method in BasicMenuItemUI. However I |
358 |
|
// cannot use it here instead of this method, since I cannot assume that |
359 |
|
// all the menu elements on the selected path are JMenuItem or JMenu. |
360 |
|
// For now I've just duplicated it here. Please |
361 |
|
// fix me or delete me if another better approach will be found, and |
362 |
|
// this method will not be necessary. |
363 |
ArrayList path = new ArrayList(); |
ArrayList path = new ArrayList(); |
364 |
|
|
365 |
|
// if given component is JMenu, we also need to include |
366 |
|
// it's popup menu in the path |
367 |
|
if (c instanceof JMenu) |
368 |
|
path.add(((JMenu) c).getPopupMenu()); |
369 |
while (c instanceof MenuElement) |
while (c instanceof MenuElement) |
370 |
{ |
{ |
371 |
path.add(0, (MenuElement) c); |
path.add(0, (MenuElement) c); |