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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* BasicPopupMenuUI.java
2
   Copyright (C) 2002, 2004, 2005 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
package javax.swing.plaf.basic;
39
 
40
import java.awt.Component;
41
import java.awt.Dimension;
42
import java.awt.KeyboardFocusManager;
43
import java.awt.event.ActionEvent;
44
import java.awt.event.ComponentEvent;
45
import java.awt.event.ComponentListener;
46
import java.awt.event.MouseEvent;
47
import java.util.EventListener;
48
 
49
import javax.swing.AbstractAction;
50
import javax.swing.Action;
51
import javax.swing.ActionMap;
52
import javax.swing.BoxLayout;
53
import javax.swing.InputMap;
54
import javax.swing.JApplet;
55
import javax.swing.JComponent;
56
import javax.swing.JFrame;
57
import javax.swing.JMenu;
58
import javax.swing.JMenuBar;
59
import javax.swing.JMenuItem;
60
import javax.swing.JPopupMenu;
61
import javax.swing.JRootPane;
62
import javax.swing.LookAndFeel;
63
import javax.swing.MenuElement;
64
import javax.swing.MenuSelectionManager;
65
import javax.swing.SwingUtilities;
66
import javax.swing.UIManager;
67
import javax.swing.event.ChangeEvent;
68
import javax.swing.event.ChangeListener;
69
import javax.swing.event.PopupMenuEvent;
70
import javax.swing.event.PopupMenuListener;
71
import javax.swing.plaf.ActionMapUIResource;
72
import javax.swing.plaf.ComponentUI;
73
import javax.swing.plaf.PopupMenuUI;
74
 
75
/**
76
 * UI Delegate for JPopupMenu
77
 */
78
public class BasicPopupMenuUI extends PopupMenuUI
79
{
80
  /**
81
   * Handles keyboard navigation through menus.
82
   */
83
  private static class NavigateAction
84
    extends AbstractAction
85
  {
86
 
87
    /**
88
     * Creates a new NavigateAction instance.
89
     *
90
     * @param name the name of the action
91
     */
92
    NavigateAction(String name)
93
    {
94
      super(name);
95
    }
96
 
97
    /**
98
     * Actually performs the action.
99
     */
100
    public void actionPerformed(ActionEvent event)
101
    {
102
      String name = (String) getValue(Action.NAME);
103
      if (name.equals("selectNext"))
104
        navigateNextPrevious(true);
105
      else if (name.equals("selectPrevious"))
106
        navigateNextPrevious(false);
107
      else if (name.equals("selectChild"))
108
        navigateParentChild(true);
109
      else if (name.equals("selectParent"))
110
        navigateParentChild(false);
111
      else if (name.equals("cancel"))
112
        cancel();
113
      else if (name.equals("return"))
114
        doReturn();
115
      else
116
        assert false : "Must not reach here";
117
    }
118
 
119
    /**
120
     * Navigates to the next or previous menu item.
121
     *
122
     * @param dir <code>true</code>: navigate to next, <code>false</code>:
123
     *        navigate to previous
124
     */
125
    private void navigateNextPrevious(boolean dir)
126
    {
127
      MenuSelectionManager msm = MenuSelectionManager.defaultManager();
128
      MenuElement path[] = msm.getSelectedPath();
129
      int len = path.length;
130
      if (len >= 2)
131
        {
132
 
133
          if (path[0] instanceof JMenuBar &&
134
              path[1] instanceof JMenu && len == 2)
135
            {
136
 
137
              // A toplevel menu is selected, but its popup not yet shown.
138
              // Show the popup and select the first item
139
              JPopupMenu popup = ((JMenu)path[1]).getPopupMenu();
140
              MenuElement next =
141
                findEnabledChild(popup.getSubElements(), -1, true);
142
              MenuElement[] newPath;
143
 
144
              if (next != null)
145
                {
146
                  newPath = new MenuElement[4];
147
                  newPath[3] = next;
148
                }
149
              else
150
                {
151
                  // Menu has no enabled items, show the popup anyway.
152
                  newPath = new MenuElement[3];
153
                }
154
              System.arraycopy(path, 0, newPath, 0, 2);
155
              newPath[2] = popup;
156
              msm.setSelectedPath(newPath);
157
            }
158
          else if (path[len - 1] instanceof JPopupMenu &&
159
                   path[len - 2] instanceof JMenu)
160
            {
161
              // Select next item in already shown popup menu.
162
              JMenu menu = (JMenu) path[len - 2];
163
              JPopupMenu popup = menu.getPopupMenu();
164
              MenuElement next =
165
                findEnabledChild(popup.getSubElements(), -1, dir);
166
 
167
              if (next != null)
168
                {
169
                  MenuElement[] newPath = new MenuElement[len + 1];
170
                  System.arraycopy(path, 0, newPath, 0, len);
171
                  newPath[len] = next;
172
                  msm.setSelectedPath(newPath);
173
                }
174
              else
175
                {
176
                  // All items in the popup are disabled.
177
                  // Find the parent popup menu and select
178
                  // its next item. If there's no parent popup menu , do nothing.
179
                  if (len > 2 && path[len - 3] instanceof JPopupMenu)
180
                    {
181
                      popup = ((JPopupMenu) path[len - 3]);
182
                      next = findEnabledChild(popup.getSubElements(),
183
                                              menu, dir);
184
                      if (next != null && next != menu)
185
                        {
186
                          MenuElement[] newPath = new MenuElement[len - 1];
187
                          System.arraycopy(path, 0, newPath, 0, len - 2);
188
                          newPath[len - 2] = next;
189
                          msm.setSelectedPath(newPath);
190
                        }
191
                    }
192
                }
193
            }
194
          else
195
            {
196
              // Only select the next item.
197
              MenuElement subs[] = path[len - 2].getSubElements();
198
              MenuElement nextChild =
199
                findEnabledChild(subs, path[len - 1], dir);
200
              if (nextChild == null)
201
                {
202
                  nextChild = findEnabledChild(subs, -1, dir);
203
                }
204
              if (nextChild != null)
205
                {
206
                  path[len-1] = nextChild;
207
                  msm.setSelectedPath(path);
208
                }
209
            }
210
        }
211
    }
212
 
213
    private MenuElement findEnabledChild(MenuElement[] children,
214
                                         MenuElement start, boolean dir)
215
    {
216
      MenuElement found = null;
217
      for (int i = 0; i < children.length && found == null; i++)
218
        {
219
          if (children[i] == start)
220
            {
221
              found = findEnabledChild(children, i, dir);
222
            }
223
        }
224
      return found;
225
    }
226
 
227
    /**
228
     * Searches the next or previous enabled child menu element.
229
     *
230
     * @param children the children to search through
231
     * @param start the index at which to start
232
     * @param dir the direction (true == forward, false == backward)
233
     *
234
     * @return the found element or null
235
     */
236
    private MenuElement findEnabledChild(MenuElement[] children,
237
                                         int start, boolean dir)
238
    {
239
      MenuElement result = null;
240
      if (dir)
241
        {
242
          result = findNextEnabledChild(children, start + 1, children.length-1);
243
          if (result == null)
244
            result = findNextEnabledChild(children, 0, start - 1);
245
        }
246
      else
247
        {
248
          result = findPreviousEnabledChild(children, start - 1, 0);
249
          if (result == null)
250
            result = findPreviousEnabledChild(children, children.length-1,
251
                                          start + 1);
252
        }
253
      return result;
254
    }
255
 
256
    /**
257
     * Finds the next child element that is enabled and visible.
258
     *
259
     * @param children the children to search through
260
     * @param start the start index
261
     * @param end the end index
262
     *
263
     * @return the found child, or null
264
     */
265
    private MenuElement findNextEnabledChild(MenuElement[] children, int start,
266
                                             int end)
267
    {
268
      MenuElement found = null;
269
      for (int i = start; i <= end && found == null; i++)
270
        {
271
          if (children[i] != null)
272
            {
273
              Component comp = children[i].getComponent();
274
              if (comp != null && comp.isEnabled() && comp.isVisible())
275
                {
276
                  found = children[i];
277
                }
278
            }
279
        }
280
      return found;
281
    }
282
 
283
    /**
284
     * Finds the previous child element that is enabled and visible.
285
     *
286
     * @param children the children to search through
287
     * @param start the start index
288
     * @param end the end index
289
     *
290
     * @return the found child, or null
291
     */
292
    private MenuElement findPreviousEnabledChild(MenuElement[] children,
293
                                                 int start, int end)
294
    {
295
      MenuElement found = null;
296
      for (int i = start; i >= end && found == null; i--)
297
        {
298
          if (children[i] != null)
299
            {
300
              Component comp = children[i].getComponent();
301
              if (comp != null && comp.isEnabled() && comp.isVisible())
302
                {
303
                  found = children[i];
304
                }
305
            }
306
        }
307
      return found;
308
    }
309
 
310
    /**
311
     * Navigates to the parent or child menu item.
312
     *
313
     * @param selectChild <code>true</code>: navigate to child,
314
     *        <code>false</code>: navigate to parent
315
     */
316
    private void navigateParentChild(boolean selectChild)
317
    {
318
      MenuSelectionManager msm = MenuSelectionManager.defaultManager();
319
      MenuElement path[] = msm.getSelectedPath();
320
      int len = path.length;
321
 
322
      if (selectChild)
323
        {
324
          if (len > 0 && path[len - 1] instanceof JMenu
325
              && ! ((JMenu) path[len-1]).isTopLevelMenu())
326
            {
327
              // We have a submenu, open it.
328
              JMenu menu = (JMenu) path[len - 1];
329
              JPopupMenu popup = menu.getPopupMenu();
330
              MenuElement[] subs = popup.getSubElements();
331
              MenuElement item = findEnabledChild(subs, -1, true);
332
              MenuElement[] newPath;
333
 
334
              if (item == null)
335
                {
336
                  newPath = new MenuElement[len + 1];
337
                }
338
              else
339
                {
340
                  newPath = new MenuElement[len + 2];
341
                  newPath[len + 1] = item;
342
                }
343
              System.arraycopy(path, 0, newPath, 0, len);
344
              newPath[len] = popup;
345
              msm.setSelectedPath(newPath);
346
              return;
347
            }
348
        }
349
      else
350
        {
351
          int popupIndex = len-1;
352
          if (len > 2
353
              && (path[popupIndex] instanceof JPopupMenu
354
                  || path[--popupIndex] instanceof JPopupMenu)
355
                  && ! ((JMenu) path[popupIndex - 1]).isTopLevelMenu())
356
            {
357
              // We have a submenu, close it.
358
              MenuElement newPath[] = new MenuElement[popupIndex];
359
              System.arraycopy(path, 0, newPath, 0, popupIndex);
360
              msm.setSelectedPath(newPath);
361
              return;
362
            }
363
        }
364
 
365
      // If we got here, we have not selected a child or parent.
366
      // Check if we have a toplevel menu selected. If so, then select
367
      // another one.
368
      if (len > 1 && path[0] instanceof JMenuBar)
369
        {
370
          MenuElement currentMenu = path[1];
371
          MenuElement nextMenu = findEnabledChild(path[0].getSubElements(),
372
                                                  currentMenu, selectChild);
373
 
374
          if (nextMenu != null && nextMenu != currentMenu)
375
            {
376
              MenuElement newSelection[];
377
              if (len == 2)
378
                {
379
                  // Menu is selected but its popup not shown.
380
                  newSelection = new MenuElement[2];
381
                  newSelection[0] = path[0];
382
                  newSelection[1] = nextMenu;
383
                }
384
              else
385
                {
386
                  // Menu is selected and its popup is shown.
387
                  newSelection = new MenuElement[3];
388
                  newSelection[0] = path[0];
389
                  newSelection[1] = nextMenu;
390
                  newSelection[2] = ((JMenu) nextMenu).getPopupMenu();
391
                }
392
              msm.setSelectedPath(newSelection);
393
            }
394
        }
395
    }
396
 
397
    /**
398
     * Handles cancel requests (ESC key).
399
     */
400
    private void cancel()
401
    {
402
      // Fire popup menu cancelled event. Unfortunately the
403
      // firePopupMenuCancelled() is protected in JPopupMenu so we work
404
      // around this limitation by fetching the listeners and notifying them
405
      // directly.
406
      JPopupMenu lastPopup = (JPopupMenu) getLastPopup();
407
      EventListener[] ll = lastPopup.getListeners(PopupMenuListener.class);
408
      for (int i = 0; i < ll.length; i++)
409
        {
410
          PopupMenuEvent ev = new PopupMenuEvent(lastPopup);
411
          ((PopupMenuListener) ll[i]).popupMenuCanceled(ev);
412
        }
413
 
414
      // Close the last popup or the whole selection if there's only one
415
      // popup left.
416
      MenuSelectionManager msm = MenuSelectionManager.defaultManager();
417
      MenuElement path[] = msm.getSelectedPath();
418
      if(path.length > 4)
419
        {
420
          MenuElement newPath[] = new MenuElement[path.length - 2];
421
          System.arraycopy(path,0,newPath,0,path.length-2);
422
          MenuSelectionManager.defaultManager().setSelectedPath(newPath);
423
        }
424
      else
425
          msm.clearSelectedPath();
426
    }
427
 
428
    /**
429
     * Returns the last popup menu in the current selection or null.
430
     *
431
     * @return the last popup menu in the current selection or null
432
     */
433
    private JPopupMenu getLastPopup()
434
    {
435
      MenuSelectionManager msm = MenuSelectionManager.defaultManager();
436
      MenuElement[] p = msm.getSelectedPath();
437
      JPopupMenu popup = null;
438
      for(int i = p.length - 1; popup == null && i >= 0; i--)
439
        {
440
          if (p[i] instanceof JPopupMenu)
441
            popup = (JPopupMenu) p[i];
442
        }
443
      return popup;
444
    }
445
 
446
    /**
447
     * Handles ENTER key requests. This normally opens submenus on JMenu
448
     * items, or activates the menu item as if it's been clicked on it.
449
     */
450
    private void doReturn()
451
    {
452
      KeyboardFocusManager fmgr =
453
        KeyboardFocusManager.getCurrentKeyboardFocusManager();
454
      Component focusOwner = fmgr.getFocusOwner();
455
      if((focusOwner == null || (focusOwner instanceof JRootPane)))
456
        {
457
          MenuSelectionManager msm = MenuSelectionManager.defaultManager();
458
          MenuElement path[] = msm.getSelectedPath();
459
          MenuElement lastElement;
460
          if(path.length > 0)
461
            {
462
              lastElement = path[path.length - 1];
463
              if(lastElement instanceof JMenu)
464
                {
465
                  MenuElement newPath[] = new MenuElement[path.length + 1];
466
                  System.arraycopy(path,0,newPath,0,path.length);
467
                  newPath[path.length] = ((JMenu) lastElement).getPopupMenu();
468
                  msm.setSelectedPath(newPath);
469
                }
470
              else if(lastElement instanceof JMenuItem)
471
                {
472
                  JMenuItem mi = (JMenuItem)lastElement;
473
                  if (mi.getUI() instanceof BasicMenuItemUI)
474
                    {
475
                      ((BasicMenuItemUI)mi.getUI()).doClick(msm);
476
                    }
477
                  else
478
                    {
479
                      msm.clearSelectedPath();
480
                      mi.doClick(0);
481
                    }
482
                }
483
            }
484
        }
485
    }
486
  }
487
 
488
  /**
489
   * Installs keyboard actions when a popup is opened, and uninstalls the
490
   * keyboard actions when closed. This listens on the default
491
   * MenuSelectionManager.
492
   */
493
  private class KeyboardHelper
494
    implements ChangeListener
495
  {
496
    private MenuElement[] lastSelectedPath = new MenuElement[0];
497
    private Component lastFocused;
498
    private JRootPane invokerRootPane;
499
 
500
    public void stateChanged(ChangeEvent event)
501
    {
502
      MenuSelectionManager msm = (MenuSelectionManager) event.getSource();
503
      MenuElement[] p = msm.getSelectedPath();
504
      JPopupMenu popup = getActivePopup(p);
505
      if (popup == null || popup.isFocusable())
506
        {
507
          if (lastSelectedPath.length != 0 && p.length != 0 )
508
            {
509
              if (! invokerEquals(p[0], lastSelectedPath[0]))
510
                {
511
                  uninstallKeyboardActionsImpl();
512
                  lastSelectedPath = new MenuElement[0];
513
                }
514
            }
515
 
516
          if (lastSelectedPath.length == 0 && p.length > 0)
517
            {
518
              JComponent invoker;
519
              if (popup == null)
520
                {
521
                  if (p.length == 2 && p[0] instanceof JMenuBar
522
                      && p[1] instanceof JMenu)
523
                    {
524
                      // A menu has been selected but not opened.
525
                      invoker = (JComponent)p[1];
526
                      popup = ((JMenu)invoker).getPopupMenu();
527
                    }
528
                  else
529
                    {
530
                      return;
531
                    }
532
                }
533
              else
534
                {
535
                Component c = popup.getInvoker();
536
                if(c instanceof JFrame)
537
                  {
538
                    invoker = ((JFrame) c).getRootPane();
539
                  }
540
                else if(c instanceof JApplet)
541
                  {
542
                    invoker = ((JApplet) c).getRootPane();
543
                  }
544
                else
545
                  {
546
                    while (!(c instanceof JComponent))
547
                      {
548
                        if (c == null)
549
                          {
550
                            return;
551
                          }
552
                        c = c.getParent();
553
                      }
554
                    invoker = (JComponent)c;
555
                  }
556
                }
557
 
558
              // Remember current focus owner.
559
              lastFocused = KeyboardFocusManager.
560
                             getCurrentKeyboardFocusManager().getFocusOwner();
561
 
562
              // Install keybindings used for menu navigation.
563
              invokerRootPane = SwingUtilities.getRootPane(invoker);
564
              if (invokerRootPane != null)
565
                {
566
                  invokerRootPane.requestFocus(true);
567
                  installKeyboardActionsImpl();
568
                }
569
            }
570
          else if (lastSelectedPath.length != 0 && p.length == 0)
571
            {
572
              // menu hidden -- return focus to where it had been before
573
              // and uninstall menu keybindings
574
              uninstallKeyboardActionsImpl();
575
            }
576
        }
577
 
578
      // Remember the last path selected
579
      lastSelectedPath = p;
580
    }
581
 
582
    private JPopupMenu getActivePopup(MenuElement[] path)
583
    {
584
      JPopupMenu active = null;
585
      for (int i = path.length - 1; i >= 0 && active == null; i--)
586
        {
587
          MenuElement elem = path[i];
588
          if (elem instanceof JPopupMenu)
589
            {
590
              active = (JPopupMenu) elem;
591
            }
592
        }
593
      return active;
594
    }
595
 
596
    private boolean invokerEquals(MenuElement el1, MenuElement el2)
597
    {
598
      Component invoker1 = el1.getComponent();
599
      Component invoker2 = el2.getComponent();
600
      if (invoker1 instanceof JPopupMenu)
601
        invoker1 = ((JPopupMenu) invoker1).getInvoker();
602
      if (invoker2 instanceof JPopupMenu)
603
        invoker2 = ((JPopupMenu) invoker2).getInvoker();
604
      return invoker1 == invoker2;
605
    }
606
  }
607
 
608
  /* popupMenu for which this UI delegate is for*/
609
  protected JPopupMenu popupMenu;
610
 
611
  /* PopupMenuListener listens to popup menu events fired by JPopupMenu*/
612
  private transient PopupMenuListener popupMenuListener;
613
 
614
  /* ComponentListener listening to popupMenu's invoker.
615
   * This is package-private to avoid an accessor method.  */
616
  TopWindowListener topWindowListener;
617
 
618
  /**
619
   * Counts how many popup menus are handled by this UI or a subclass.
620
   * This is used to install a KeyboardHelper on the MenuSelectionManager
621
   * for the first popup, and uninstall this same KeyboardHelper when the
622
   * last popup is uninstalled.
623
   */
624
  private static int numPopups;
625
 
626
  /**
627
   * This is the KeyboardHelper that listens on the MenuSelectionManager.
628
   */
629
  private static KeyboardHelper keyboardHelper;
630
 
631
  /**
632
   * Creates a new BasicPopupMenuUI object.
633
   */
634
  public BasicPopupMenuUI()
635
  {
636
    popupMenuListener = new PopupMenuHandler();
637
    topWindowListener = new TopWindowListener();
638
  }
639
 
640
  /**
641
   * Factory method to create a BasicPopupMenuUI for the given {@link
642
   * JComponent}, which should be a {@link JMenuItem}.
643
   *
644
   * @param x The {@link JComponent} a UI is being created for.
645
   *
646
   * @return A BasicPopupMenuUI for the {@link JComponent}.
647
   */
648
  public static ComponentUI createUI(JComponent x)
649
  {
650
    return new BasicPopupMenuUI();
651
  }
652
 
653
  /**
654
   * Installs and initializes all fields for this UI delegate. Any properties
655
   * of the UI that need to be initialized and/or set to defaults will be
656
   * done now. It will also install any listeners necessary.
657
   *
658
   * @param c The {@link JComponent} that is having this UI installed.
659
   */
660
  public void installUI(JComponent c)
661
  {
662
    super.installUI(c);
663
 
664
    // Install KeyboardHelper when the first popup is initialized.
665
    if (numPopups == 0)
666
      {
667
        keyboardHelper = new KeyboardHelper();
668
        MenuSelectionManager msm = MenuSelectionManager.defaultManager();
669
        msm.addChangeListener(keyboardHelper);
670
      }
671
    numPopups++;
672
 
673
    popupMenu = (JPopupMenu) c;
674
    popupMenu.setLayout(new DefaultMenuLayout(popupMenu, BoxLayout.Y_AXIS));
675
    popupMenu.setBorderPainted(true);
676
    JPopupMenu.setDefaultLightWeightPopupEnabled(true);
677
 
678
    installDefaults();
679
    installListeners();
680
    installKeyboardActions();
681
  }
682
 
683
  /**
684
   * This method installs the defaults that are defined in  the Basic look
685
   * and feel for this {@link JPopupMenu}.
686
   */
687
  public void installDefaults()
688
  {
689
    LookAndFeel.installColorsAndFont(popupMenu, "PopupMenu.background",
690
                                     "PopupMenu.foreground", "PopupMenu.font");
691
    LookAndFeel.installBorder(popupMenu, "PopupMenu.border");
692
    popupMenu.setOpaque(true);
693
  }
694
 
695
  /**
696
   * This method installs the listeners for the {@link JMenuItem}.
697
   */
698
  protected void installListeners()
699
  {
700
    popupMenu.addPopupMenuListener(popupMenuListener);
701
  }
702
 
703
  /**
704
   * This method installs the keyboard actions for this {@link JPopupMenu}.
705
   */
706
  protected void installKeyboardActions()
707
  {
708
    // We can't install the keyboard actions here, because then all
709
    // popup menus would have their actions registered in the KeyboardManager.
710
    // So we install it when the popup menu is opened, and uninstall it
711
    // when it's closed. This is done in the KeyboardHelper class.
712
    // Install InputMap.
713
  }
714
 
715
  /**
716
   * Called by the KeyboardHandler when a popup is made visible.
717
   */
718
  void installKeyboardActionsImpl()
719
  {
720
    Object[] bindings;
721
    if (popupMenu.getComponentOrientation().isLeftToRight())
722
      {
723
        bindings = (Object[])
724
             SharedUIDefaults.get("PopupMenu.selectedWindowInputMapBindings");
725
      }
726
    else
727
      {
728
        bindings = (Object[]) SharedUIDefaults.get
729
                      ("PopupMenu.selectedWindowInputMapBindings.RightToLeft");
730
      }
731
    InputMap inputMap = LookAndFeel.makeComponentInputMap(popupMenu, bindings);
732
    SwingUtilities.replaceUIInputMap(popupMenu,
733
                                     JComponent.WHEN_IN_FOCUSED_WINDOW,
734
                                     inputMap);
735
 
736
    // Install ActionMap.
737
    SwingUtilities.replaceUIActionMap(popupMenu, getActionMap());
738
  }
739
 
740
  /**
741
   * Creates and returns the shared action map for JTrees.
742
   *
743
   * @return the shared action map for JTrees
744
   */
745
  private ActionMap getActionMap()
746
  {
747
    ActionMap am = (ActionMap) UIManager.get("PopupMenu.actionMap");
748
    if (am == null)
749
      {
750
        am = createDefaultActions();
751
        UIManager.getLookAndFeelDefaults().put("PopupMenu.actionMap", am);
752
      }
753
    return am;
754
  }
755
 
756
  /**
757
   * Creates the default actions when there are none specified by the L&F.
758
   *
759
   * @return the default actions
760
   */
761
  private ActionMap createDefaultActions()
762
  {
763
    ActionMapUIResource am = new ActionMapUIResource();
764
    Action action = new NavigateAction("selectNext");
765
    am.put(action.getValue(Action.NAME), action);
766
    action = new NavigateAction("selectPrevious");
767
    am.put(action.getValue(Action.NAME), action);
768
    action = new NavigateAction("selectParent");
769
    am.put(action.getValue(Action.NAME), action);
770
    action = new NavigateAction("selectChild");
771
    am.put(action.getValue(Action.NAME), action);
772
    action = new NavigateAction("return");
773
    am.put(action.getValue(Action.NAME), action);
774
    action = new NavigateAction("cancel");
775
    am.put(action.getValue(Action.NAME), action);
776
 
777
    return am;
778
  }
779
 
780
  /**
781
   * Performs the opposite of installUI. Any properties or resources that need
782
   * to be cleaned up will be done now. It will also uninstall any listeners
783
   * it has. In addition, any properties of this UI will be nulled.
784
   *
785
   * @param c The {@link JComponent} that is having this UI uninstalled.
786
   */
787
  public void uninstallUI(JComponent c)
788
  {
789
    uninstallListeners();
790
    uninstallDefaults();
791
    uninstallKeyboardActions();
792
    popupMenu = null;
793
 
794
    // Install KeyboardHelper when the first popup is initialized.
795
    numPopups--;
796
    if (numPopups == 0)
797
      {
798
        MenuSelectionManager msm = MenuSelectionManager.defaultManager();
799
        msm.removeChangeListener(keyboardHelper);
800
      }
801
 
802
  }
803
 
804
  /**
805
   * This method uninstalls the defaults and sets any objects created during
806
   * install to null
807
   */
808
  protected void uninstallDefaults()
809
  {
810
    popupMenu.setBackground(null);
811
    popupMenu.setBorder(null);
812
    popupMenu.setFont(null);
813
    popupMenu.setForeground(null);
814
  }
815
 
816
  /**
817
   * Unregisters all the listeners that this UI delegate was using.
818
   */
819
  protected void uninstallListeners()
820
  {
821
    popupMenu.removePopupMenuListener(popupMenuListener);
822
  }
823
 
824
  /**
825
   * Uninstalls any keyboard actions.
826
   */
827
  protected void uninstallKeyboardActions()
828
  {
829
    // We can't install the keyboard actions here, because then all
830
    // popup menus would have their actions registered in the KeyboardManager.
831
    // So we install it when the popup menu is opened, and uninstall it
832
    // when it's closed. This is done in the KeyboardHelper class.
833
    // Install InputMap.
834
  }
835
 
836
  /**
837
   * Called by the KeyboardHandler when a popup is made invisible.
838
   */
839
  void uninstallKeyboardActionsImpl()
840
  {
841
    SwingUtilities.replaceUIInputMap(popupMenu,
842
                                     JComponent.WHEN_IN_FOCUSED_WINDOW, null);
843
    SwingUtilities.replaceUIActionMap(popupMenu, null);
844
  }
845
 
846
  /**
847
   * This method returns the minimum size of the JPopupMenu.
848
   *
849
   * @param c The JComponent to find a size for.
850
   *
851
   * @return The minimum size.
852
   */
853
  public Dimension getMinimumSize(JComponent c)
854
  {
855
    return null;
856
  }
857
 
858
  /**
859
   * This method returns the preferred size of the JPopupMenu.
860
   *
861
   * @param c The JComponent to find a size for.
862
   *
863
   * @return The preferred size.
864
   */
865
  public Dimension getPreferredSize(JComponent c)
866
  {
867
    return null;
868
  }
869
 
870
  /**
871
   * This method returns the minimum size of the JPopupMenu.
872
   *
873
   * @param c The JComponent to find a size for.
874
   *
875
   * @return The minimum size.
876
   */
877
  public Dimension getMaximumSize(JComponent c)
878
  {
879
    return null;
880
  }
881
 
882
  /**
883
   * Return true if given mouse event is a platform popup trigger, and false
884
   * otherwise
885
   *
886
   * @param e MouseEvent that is to be checked for popup trigger event
887
   *
888
   * @return true if given mouse event is a platform popup trigger, and false
889
   *         otherwise
890
   */
891
  public boolean isPopupTrigger(MouseEvent e)
892
  {
893
    return false;
894
  }
895
 
896
  /**
897
   * This listener handles PopupMenuEvents fired by JPopupMenu
898
   */
899
  private class PopupMenuHandler implements PopupMenuListener
900
  {
901
    /**
902
     * This method is invoked when JPopupMenu is cancelled.
903
     *
904
     * @param event the PopupMenuEvent
905
     */
906
    public void popupMenuCanceled(PopupMenuEvent event)
907
    {
908
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
909
      manager.clearSelectedPath();
910
    }
911
 
912
    /**
913
     * This method is invoked when JPopupMenu becomes invisible
914
     *
915
     * @param event the PopupMenuEvent
916
     */
917
    public void popupMenuWillBecomeInvisible(PopupMenuEvent event)
918
    {
919
      // remove listener that listens to component events fired
920
      // by the top - level window that this popup belongs to.
921
      Component invoker = popupMenu.getInvoker();
922
      Component rootContainer = SwingUtilities.getRoot(invoker);
923
      if (rootContainer != null)
924
        rootContainer.removeComponentListener(topWindowListener);
925
    }
926
 
927
    /**
928
     * This method is invoked when JPopupMenu becomes visible
929
     *
930
     * @param event the PopupMenuEvent
931
     */
932
    public void popupMenuWillBecomeVisible(PopupMenuEvent event)
933
    {
934
      // Adds topWindowListener to top-level window to listener to
935
      // ComponentEvents fired by it. We need to cancel this popup menu
936
      // if topWindow to which this popup belongs was resized or moved.
937
      Component invoker = popupMenu.getInvoker();
938
      Component rootContainer = SwingUtilities.getRoot(invoker);
939
      if (rootContainer != null)
940
        rootContainer.addComponentListener(topWindowListener);
941
 
942
      // if this popup menu is a free floating popup menu,
943
      // then by default its first element should be always selected when
944
      // this popup menu becomes visible.
945
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
946
 
947
      if (manager.getSelectedPath().length == 0)
948
        {
949
          // Set selected path to point to the first item in the popup menu
950
          MenuElement[] path = new MenuElement[2];
951
          path[0] = popupMenu;
952
          Component[] comps = popupMenu.getComponents();
953
          if (comps.length != 0 && comps[0] instanceof MenuElement)
954
            {
955
              path[1] = (MenuElement) comps[0];
956
              manager.setSelectedPath(path);
957
            }
958
        }
959
    }
960
  }
961
 
962
  /**
963
   * ComponentListener that listens to Component Events fired by the top -
964
   * level window to which popup menu belongs. If top-level window was
965
   * resized, moved or hidded then popup menu will be hidded and selected
966
   * path of current menu hierarchy will be set to null.
967
   */
968
  private class TopWindowListener implements ComponentListener
969
  {
970
    /**
971
     * This method is invoked when top-level window is resized. This method
972
     * closes current menu hierarchy.
973
     *
974
     * @param e The ComponentEvent
975
     */
976
    public void componentResized(ComponentEvent e)
977
    {
978
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
979
      manager.clearSelectedPath();
980
    }
981
 
982
    /**
983
     * This method is invoked when top-level window is moved. This method
984
     * closes current menu hierarchy.
985
     *
986
     * @param e The ComponentEvent
987
     */
988
    public void componentMoved(ComponentEvent e)
989
    {
990
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
991
      manager.clearSelectedPath();
992
    }
993
 
994
    /**
995
     * This method is invoked when top-level window is shown This method
996
     * does nothing by default.
997
     *
998
     * @param e The ComponentEvent
999
     */
1000
    public void componentShown(ComponentEvent e)
1001
    {
1002
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1003
      manager.clearSelectedPath();
1004
    }
1005
 
1006
    /**
1007
     * This method is invoked when top-level window is hidden This method
1008
     * closes current menu hierarchy.
1009
     *
1010
     * @param e The ComponentEvent
1011
     */
1012
    public void componentHidden(ComponentEvent e)
1013
    {
1014
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
1015
      manager.clearSelectedPath();
1016
    }
1017
  }
1018
 
1019
}

powered by: WebSVN 2.1.0

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