Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / javax / swing / MenuSelectionManager.java
blob4e52751065acca16f438289a39a7b68f40bb3e5a
1 /* MenuSelectionManager.java --
2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing;
41 import java.awt.Component;
42 import java.awt.Dimension;
43 import java.awt.Point;
44 import java.awt.event.KeyEvent;
45 import java.awt.event.MouseEvent;
46 import java.util.ArrayList;
47 import java.util.Vector;
49 import javax.swing.event.ChangeEvent;
50 import javax.swing.event.ChangeListener;
51 import javax.swing.event.EventListenerList;
53 /**
54 * This class manages current menu selectection. It provides
55 * methods to clear and set current selected menu path.
56 * It also fires StateChange event to its registered
57 * listeners whenever selected path of the current menu hierarchy
58 * changes.
61 public class MenuSelectionManager
63 /** ChangeEvent fired when selected path changes*/
64 protected ChangeEvent changeEvent = new ChangeEvent(this);
66 /** List of listeners for this MenuSelectionManager */
67 protected EventListenerList listenerList = new EventListenerList();
69 /** Default manager for the current menu hierarchy*/
70 private static final MenuSelectionManager manager = new MenuSelectionManager();
72 /** Path to the currently selected menu */
73 private Vector selectedPath = new Vector();
75 /**
76 * Fires StateChange event to registered listeners
78 protected void fireStateChanged()
80 ChangeListener[] listeners = getChangeListeners();
82 for (int i = 0; i < listeners.length; i++)
83 listeners[i].stateChanged(changeEvent);
86 /**
87 * Adds ChangeListener to this MenuSelectionManager
89 * @param listener ChangeListener to add
91 public void addChangeListener(ChangeListener listener)
93 listenerList.add(ChangeListener.class, listener);
96 /**
97 * Removes ChangeListener from the list of registered listeners
98 * for this MenuSelectionManager.
100 * @param listener ChangeListner to remove
102 public void removeChangeListener(ChangeListener listener)
104 listenerList.remove(ChangeListener.class, listener);
108 * Returns list of registered listeners with MenuSelectionManager
110 * @since 1.4
112 public ChangeListener[] getChangeListeners()
114 return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
118 * Unselects all the menu elements on the selection path
120 public void clearSelectedPath()
122 // Send events from the bottom most item in the menu - hierarchy to the
123 // top most
124 for (int i = selectedPath.size() - 1; i >= 0; i--)
125 ((MenuElement) selectedPath.get(i)).menuSelectionChanged(false);
127 // clear selected path
128 selectedPath.clear();
130 // notify all listeners that the selected path was changed
131 fireStateChanged();
135 * This method returns menu element on the selected path that contains
136 * given source point. If no menu element on the selected path contains this
137 * point, then null is returned.
139 * @param source Component relative to which sourcePoint is given
140 * @param sourcePoint point for which we want to find menu element that contains it
142 * @return Returns menu element that contains given source point and belongs
143 * to the currently selected path. Null is return if no such menu element found.
145 public Component componentForPoint(Component source, Point sourcePoint)
147 // Convert sourcePoint to screen coordinates.
148 Point sourcePointOnScreen = sourcePoint;
150 if (source.isShowing())
151 SwingUtilities.convertPointToScreen(sourcePointOnScreen, source);
153 Point compPointOnScreen;
154 Component resultComp = null;
156 // For each menu element on the selected path, express its location
157 // in terms of screen coordinates and check if there is any
158 // menu element on the selected path that contains given source point.
159 for (int i = 0; i < selectedPath.size(); i++)
161 Component comp = ((Component) selectedPath.get(i));
162 Dimension size = comp.getSize();
164 // convert location of this menu item to screen coordinates
165 compPointOnScreen = comp.getLocationOnScreen();
167 if (compPointOnScreen.x <= sourcePointOnScreen.x
168 && sourcePointOnScreen.x < compPointOnScreen.x + size.width
169 && compPointOnScreen.y <= sourcePointOnScreen.y
170 && sourcePointOnScreen.y < compPointOnScreen.y + size.height)
172 Point p = sourcePointOnScreen;
174 if (comp.isShowing())
175 SwingUtilities.convertPointFromScreen(p, comp);
177 resultComp = SwingUtilities.getDeepestComponentAt(comp, p.x, p.y);
178 break;
181 return resultComp;
185 * Returns shared instance of MenuSelection Manager
187 * @return default Manager
189 public static MenuSelectionManager defaultManager()
191 return manager;
195 * Returns path representing current menu selection
197 * @return Current selection path
199 public MenuElement[] getSelectedPath()
201 MenuElement[] path = new MenuElement[selectedPath.size()];
203 for (int i = 0; i < path.length; i++)
204 path[i] = (MenuElement) selectedPath.get(i);
206 return path;
210 * Returns true if specified component is part of current menu
211 * heirarchy and false otherwise
213 * @param c Component for which to check
214 * @return True if specified component is part of current menu
216 public boolean isComponentPartOfCurrentMenu(Component c)
218 MenuElement[] subElements;
219 for (int i = 0; i < selectedPath.size(); i++)
221 subElements = ((MenuElement) selectedPath.get(i)).getSubElements();
222 for (int j = 0; j < subElements.length; j++)
224 MenuElement me = subElements[j];
225 if (me != null && (me.getComponent()).equals(c))
226 return true;
230 return false;
234 * DOCUMENT ME!
236 * @param e DOCUMENT ME!
238 public void processKeyEvent(KeyEvent e)
240 throw new UnsupportedOperationException("not implemented");
244 * Forwards given mouse event to all of the source subcomponents.
246 * @param event Mouse event
248 public void processMouseEvent(MouseEvent event)
250 Component source = ((Component) event.getSource());
252 // In the case of drag event, event.getSource() returns component
253 // where drag event originated. However menu element processing this
254 // event should be the one over which mouse is currently located,
255 // which is not necessary the source of the drag event.
256 Component mouseOverMenuComp;
258 // find over which menu element the mouse is currently located
259 if (event.getID() == MouseEvent.MOUSE_DRAGGED
260 || event.getID() == MouseEvent.MOUSE_RELEASED)
261 mouseOverMenuComp = componentForPoint(source, event.getPoint());
262 else
263 mouseOverMenuComp = source;
265 // Process this event only if mouse is located over some menu element
266 if (mouseOverMenuComp != null && (mouseOverMenuComp instanceof MenuElement))
268 MenuElement[] path = getPath(mouseOverMenuComp);
269 ((MenuElement) mouseOverMenuComp).processMouseEvent(event, path,
270 manager);
272 // FIXME: Java specification says that mouse events should be
273 // forwarded to subcomponents. The code below does it, but
274 // menu's work fine without it. This code is commented for now.
277 MenuElement[] subComponents = ((MenuElement) mouseOverMenuComp)
278 .getSubElements();
280 for (int i = 0; i < subComponents.length; i++)
282 subComponents[i].processMouseEvent(event, path, manager);
286 else
288 if (event.getID() == MouseEvent.MOUSE_RELEASED)
289 clearSelectedPath();
294 * Sets menu selection to the specified path
296 * @param path new selection path
298 public void setSelectedPath(MenuElement[] path)
300 if (path == null)
302 clearSelectedPath();
303 return;
306 int i;
307 int minSize = path.length; // size of the smaller path.
309 if (path.length > selectedPath.size())
311 minSize = selectedPath.size();
313 // if new selected path contains more elements then current
314 // selection then first add all elements at
315 // the indexes > selectedPath.size
316 for (i = selectedPath.size(); i < path.length; i++)
318 selectedPath.add(path[i]);
319 path[i].menuSelectionChanged(true);
323 else if (path.length < selectedPath.size())
325 // if new selected path contains less elements then current
326 // selection then first remove all elements from the selection
327 // at the indexes > path.length
328 for (i = selectedPath.size() - 1; i >= path.length; i--)
330 ((MenuElement) selectedPath.get(i)).menuSelectionChanged(false);
331 selectedPath.remove(i);
334 minSize = path.length;
337 // Now compare elements in new and current selection path at the
338 // same location and adjust selection until
339 // same menu elements will be encountered at the
340 // same index in both current and new selection path.
341 MenuElement oldSelectedItem;
343 for (i = minSize - 1; i >= 0; i--)
345 oldSelectedItem = (MenuElement) selectedPath.get(i);
347 if (path[i].equals(oldSelectedItem))
348 break;
350 oldSelectedItem.menuSelectionChanged(false);
351 path[i].menuSelectionChanged(true);
352 selectedPath.setElementAt(path[i], i);
355 fireStateChanged();
359 * Returns path to the specified component
361 * @param c component for which to find path for
363 * @return path to the specified component
365 private MenuElement[] getPath(Component c)
367 // FIXME: There is the same method in BasicMenuItemUI. However I
368 // cannot use it here instead of this method, since I cannot assume that
369 // all the menu elements on the selected path are JMenuItem or JMenu.
370 // For now I've just duplicated it here. Please
371 // fix me or delete me if another better approach will be found, and
372 // this method will not be necessary.
373 ArrayList path = new ArrayList();
375 // if given component is JMenu, we also need to include
376 // it's popup menu in the path
377 if (c instanceof JMenu)
378 path.add(((JMenu) c).getPopupMenu());
379 while (c instanceof MenuElement)
381 path.add(0, (MenuElement) c);
383 if (c instanceof JPopupMenu)
384 c = ((JPopupMenu) c).getInvoker();
385 else
386 c = c.getParent();
389 MenuElement[] pathArray = new MenuElement[path.size()];
390 path.toArray(pathArray);
391 return pathArray;