OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [MenuSelectionManager.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* MenuSelectionManager.java --
2
   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
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.
10
 
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.
15
 
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.
20
 
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.
25
 
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. */
37
 
38
 
39
package javax.swing;
40
 
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;
48
 
49
import javax.swing.event.ChangeEvent;
50
import javax.swing.event.ChangeListener;
51
import javax.swing.event.EventListenerList;
52
 
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.
59
 *
60
 */
61
public class MenuSelectionManager
62
{
63
  /** ChangeEvent fired when selected path changes*/
64
  protected ChangeEvent changeEvent = new ChangeEvent(this);
65
 
66
  /** List of listeners for this MenuSelectionManager */
67
  protected EventListenerList listenerList = new EventListenerList();
68
 
69
  /** Default manager for the current menu hierarchy*/
70
  private static final MenuSelectionManager manager = new MenuSelectionManager();
71
 
72
  /** Path to the currently selected menu */
73
  private Vector selectedPath = new Vector();
74
 
75
  /**
76
   * Fires StateChange event to registered listeners
77
   */
78
  protected void fireStateChanged()
79
  {
80
    ChangeListener[] listeners = getChangeListeners();
81
 
82
    for (int i = 0; i < listeners.length; i++)
83
      listeners[i].stateChanged(changeEvent);
84
  }
85
 
86
  /**
87
   * Adds ChangeListener to this MenuSelectionManager
88
   *
89
   * @param listener ChangeListener to add
90
   */
91
  public void addChangeListener(ChangeListener listener)
92
  {
93
    listenerList.add(ChangeListener.class, listener);
94
  }
95
 
96
  /**
97
   * Removes ChangeListener from the list of registered listeners
98
   * for this MenuSelectionManager.
99
   *
100
   * @param listener ChangeListner to remove
101
   */
102
  public void removeChangeListener(ChangeListener listener)
103
  {
104
    listenerList.remove(ChangeListener.class, listener);
105
  }
106
 
107
  /**
108
   * Returns list of registered listeners with MenuSelectionManager
109
   *
110
   * @since 1.4
111
   */
112
  public ChangeListener[] getChangeListeners()
113
  {
114
    return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
115
  }
116
 
117
  /**
118
   * Unselects all the menu elements on the selection path
119
   */
120
  public void clearSelectedPath()
121
  {
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);
126
 
127
    // clear selected path
128
    selectedPath.clear();
129
 
130
    // notify all listeners that the selected path was changed
131
    fireStateChanged();
132
  }
133
 
134
  /**
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.
138
   *
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
141
   *
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.
144
   */
145
  public Component componentForPoint(Component source, Point sourcePoint)
146
  {
147
    // Convert sourcePoint to screen coordinates.
148
    Point sourcePointOnScreen = sourcePoint;
149
 
150
    if (source.isShowing())
151
      SwingUtilities.convertPointToScreen(sourcePointOnScreen, source);
152
 
153
    Point compPointOnScreen;
154
    Component resultComp = null;
155
 
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++)
160
      {
161
        Component comp = ((Component) selectedPath.get(i));
162
        Dimension size = comp.getSize();
163
 
164
        // convert location of this menu item to screen coordinates
165
        compPointOnScreen = comp.getLocationOnScreen();
166
 
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)
171
          {
172
            Point p = sourcePointOnScreen;
173
 
174
        if (comp.isShowing())
175
          SwingUtilities.convertPointFromScreen(p, comp);
176
 
177
            resultComp = SwingUtilities.getDeepestComponentAt(comp, p.x, p.y);
178
            break;
179
          }
180
      }
181
    return resultComp;
182
  }
183
 
184
  /**
185
   * Returns shared instance of MenuSelection Manager
186
   *
187
   * @return default Manager
188
   */
189
  public static MenuSelectionManager defaultManager()
190
  {
191
    return manager;
192
  }
193
 
194
  /**
195
   * Returns path representing current menu selection
196
   *
197
   * @return Current selection path
198
   */
199
  public MenuElement[] getSelectedPath()
200
  {
201
    MenuElement[] path = new MenuElement[selectedPath.size()];
202
 
203
    for (int i = 0; i < path.length; i++)
204
      path[i] = (MenuElement) selectedPath.get(i);
205
 
206
    return path;
207
  }
208
 
209
  /**
210
   * Returns true if specified component is part of current menu
211
   * heirarchy and false otherwise
212
   *
213
   * @param c Component for which to check
214
   * @return True if specified component is part of current menu
215
   */
216
  public boolean isComponentPartOfCurrentMenu(Component c)
217
  {
218
    MenuElement[] subElements;
219
    boolean ret = false;
220
    for (int i = 0; i < selectedPath.size(); i++)
221
      {
222
        // Check first element.
223
        MenuElement first = (MenuElement) selectedPath.get(i);
224
        if (SwingUtilities.isDescendingFrom(c, first.getComponent()))
225
          {
226
            ret = true;
227
            break;
228
          }
229
        else
230
          {
231
            // Check sub elements.
232
            subElements = first.getSubElements();
233
            for (int j = 0; j < subElements.length; j++)
234
              {
235
                MenuElement me = subElements[j];
236
                if (me != null
237
                    && (SwingUtilities.isDescendingFrom(c, me.getComponent())))
238
                  {
239
                    ret = true;
240
                    break;
241
                  }
242
              }
243
          }
244
      }
245
 
246
      return ret;
247
  }
248
 
249
  /**
250
   * Processes key events on behalf of the MenuElements. MenuElement
251
   * instances should always forward their key events to this method and
252
   * get their {@link MenuElement#processKeyEvent(KeyEvent, MenuElement[],
253
   * MenuSelectionManager)} eventually called back.
254
   *
255
   * @param e the key event
256
   */
257
  public void processKeyEvent(KeyEvent e)
258
  {
259
    MenuElement[] selection = (MenuElement[])
260
                    selectedPath.toArray(new MenuElement[selectedPath.size()]);
261
    if (selection.length == 0)
262
      return;
263
 
264
    MenuElement[] path;
265
    for (int index = selection.length - 1; index >= 0; index--)
266
      {
267
        MenuElement el = selection[index];
268
        // This method's main purpose is to forward key events to the
269
        // relevant menu items, so that they can act in response to their
270
        // mnemonics beeing typed. So we also need to forward the key event
271
        // to all the subelements of the currently selected menu elements
272
        // in the path.
273
        MenuElement[] subEls = el.getSubElements();
274
        path = null;
275
        for (int subIndex = 0; subIndex < subEls.length; subIndex++)
276
          {
277
            MenuElement sub = subEls[subIndex];
278
            // Skip elements that are not showing or not enabled.
279
            if (sub == null || ! sub.getComponent().isShowing()
280
                || ! sub.getComponent().isEnabled())
281
              {
282
                continue;
283
              }
284
 
285
            if (path == null)
286
              {
287
                path = new MenuElement[index + 2];
288
                System.arraycopy(selection, 0, path, 0, index + 1);
289
              }
290
            path[index + 1] = sub;
291
            sub.processKeyEvent(e, path, this);
292
            if (e.isConsumed())
293
              break;
294
          }
295
        if (e.isConsumed())
296
          break;
297
      }
298
 
299
    // Dispatch to first element in selection if it hasn't been consumed.
300
    if (! e.isConsumed())
301
      {
302
        path = new MenuElement[1];
303
        path[0] = selection[0];
304
        path[0].processKeyEvent(e, path, this);
305
      }
306
  }
307
 
308
  /**
309
   * Forwards given mouse event to all of the source subcomponents.
310
   *
311
   * @param event Mouse event
312
   */
313
  public void processMouseEvent(MouseEvent event)
314
  {
315
    Component source = ((Component) event.getSource());
316
 
317
    // In the case of drag event, event.getSource() returns component
318
    // where drag event originated. However menu element processing this
319
    // event should be the one over which mouse is currently located,
320
    // which is not necessary the source of the drag event.
321
    Component mouseOverMenuComp;
322
 
323
    // find over which menu element the mouse is currently located
324
    if (event.getID() == MouseEvent.MOUSE_DRAGGED
325
        || event.getID() == MouseEvent.MOUSE_RELEASED)
326
      mouseOverMenuComp = componentForPoint(source, event.getPoint());
327
    else
328
      mouseOverMenuComp = source;
329
 
330
    // Process this event only if mouse is located over some menu element
331
    if (mouseOverMenuComp != null && (mouseOverMenuComp instanceof MenuElement))
332
      {
333
        MenuElement[] path = getPath(mouseOverMenuComp);
334
        ((MenuElement) mouseOverMenuComp).processMouseEvent(event, path,
335
                                                            manager);
336
 
337
        // FIXME: Java specification says that mouse events should be
338
        // forwarded to subcomponents. The code below does it, but
339
        // menu's work fine without it. This code is commented for now.
340
 
341
        /*
342
        MenuElement[] subComponents = ((MenuElement) mouseOverMenuComp)
343
                                      .getSubElements();
344
 
345
        for (int i = 0; i < subComponents.length; i++)
346
         {
347
              subComponents[i].processMouseEvent(event, path, manager);
348
         }
349
        */
350
      }
351
    else
352
      {
353
        if (event.getID() == MouseEvent.MOUSE_RELEASED)
354
          clearSelectedPath();
355
      }
356
  }
357
 
358
  /**
359
   * Sets menu selection to the specified path
360
   *
361
   * @param path new selection path
362
   */
363
  public void setSelectedPath(MenuElement[] path)
364
  {
365
    if (path == null)
366
      {
367
        clearSelectedPath();
368
        return;
369
      }
370
 
371
    int minSize = path.length; // size of the smaller path.
372
    int currentSize = selectedPath.size();
373
    int firstDiff = 0;
374
 
375
    // Search first item that is different in the current and new path.
376
    for (int i = 0; i < minSize; i++)
377
      {
378
        if (i < currentSize && (MenuElement) selectedPath.get(i) == path[i])
379
          firstDiff++;
380
        else
381
          break;
382
      }
383
 
384
    // Remove items from selection and send notification.
385
    for (int i = currentSize - 1; i >= firstDiff; i--)
386
      {
387
        MenuElement el = (MenuElement) selectedPath.get(i);
388
        selectedPath.remove(i);
389
        el.menuSelectionChanged(false);
390
      }
391
 
392
    // Add new items to selection and send notification.
393
    for (int i = firstDiff; i < minSize; i++)
394
      {
395
        if (path[i] != null)
396
          {
397
            selectedPath.add(path[i]);
398
            path[i].menuSelectionChanged(true);
399
          }
400
      }
401
 
402
    fireStateChanged();
403
  }
404
 
405
  /**
406
   * Returns path to the specified component
407
   *
408
   * @param c component for which to find path for
409
   *
410
   * @return path to the specified component
411
   */
412
  private MenuElement[] getPath(Component c)
413
  {
414
    // FIXME: There is the same method in BasicMenuItemUI. However I
415
    // cannot use it here instead of this method, since I cannot assume that
416
    // all the menu elements on the selected path are JMenuItem or JMenu.
417
    // For now I've just duplicated it here. Please
418
    // fix me or delete me if another better approach will be found, and
419
    // this method will not be necessary.
420
    ArrayList path = new ArrayList();
421
 
422
    // if given component is JMenu, we also need to include
423
    // it's popup menu in the path
424
    if (c instanceof JMenu)
425
      path.add(((JMenu) c).getPopupMenu());
426
    while (c instanceof MenuElement)
427
      {
428
        path.add(0, (MenuElement) c);
429
 
430
        if (c instanceof JPopupMenu)
431
          c = ((JPopupMenu) c).getInvoker();
432
        else
433
          c = c.getParent();
434
      }
435
 
436
    MenuElement[] pathArray = new MenuElement[path.size()];
437
    path.toArray(pathArray);
438
    return pathArray;
439
  }
440
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.