home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / jfc.bin / MenuSelectionManager.java < prev    next >
Text File  |  1998-02-26  |  11KB  |  315 lines

  1. /*
  2.  * @(#)MenuSelectionManager.java    1.7 98/02/07
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20. package com.sun.java.swing;
  21.  
  22. import java.awt.*;
  23. import java.util.*;
  24. import java.awt.event.*;
  25.  
  26. /* A MenuSelectionManager owns the selection in menu hierarchy.
  27.  * 
  28.  * @version 1.7 02/07/98
  29.  * @author Arnaud Weber
  30.  */
  31.  
  32. public class MenuSelectionManager {
  33.     private static final MenuSelectionManager instance = 
  34.         new MenuSelectionManager();
  35.  
  36.     Vector selection = new Vector();
  37.  
  38.     public static MenuSelectionManager defaultManager() {
  39.         return instance;
  40.     }
  41.     
  42.     /*
  43.      * Change the selection in the menu hierarchy
  44.      */
  45.     public void setSelectedPath(MenuElement path[]) {
  46.         int i,c;
  47.         int currentSelectionCount = selection.size();
  48.         int firstDifference = 0;
  49.  
  50.         if(path == null) {
  51.             path = new MenuElement[0];
  52.         }
  53.  
  54.         for(i=0,c=path.length;i<c;i++) {
  55.             if(i < currentSelectionCount && (MenuElement)selection.elementAt(i) == path[i]) 
  56.                 firstDifference++;
  57.             else
  58.                 break;
  59.         }
  60.  
  61.         for(i=currentSelectionCount - 1 ; i >= firstDifference ; i--) {
  62.             ((MenuElement)selection.elementAt(i)).menuSelectionChanged(false);
  63.             selection.removeElementAt(i);
  64.         }
  65.  
  66.         for(i = firstDifference, c = path.length ; i < c ; i++) {
  67.             path[i].menuSelectionChanged(true);
  68.             selection.addElement(path[i]);
  69.         }
  70.  
  71.         /**
  72.         System.out.println("Selection is (");
  73.         for(i=0,c=selection.size();i<c;i++){
  74.             MenuElement me = (MenuElement) selection.elementAt(i);
  75.             if(me instanceof JMenu) 
  76.                 System.out.print(((JMenu)me).getText() + ", ");
  77.             else if(me instanceof JMenuItem) 
  78.                 System.out.print(((JMenuItem)me).getText() + ", ");                
  79.             else
  80.                 System.out.print("" + me + ", ");
  81.         }
  82.         System.out.println(")");
  83.         **/
  84.     }
  85.  
  86.     public MenuElement[] getSelectedPath() {
  87.         MenuElement res[] = new MenuElement[selection.size()];
  88.         int i,c;
  89.         for(i=0,c=selection.size();i<c;i++) 
  90.             res[i] = (MenuElement) selection.elementAt(i);
  91.         return res;
  92.     }
  93.  
  94.     /*
  95.      * Tell the menu selection to close and unselect all the menu components. Call this method
  96.      * when a choice has been made
  97.      */
  98.     public void clearSelectedPath() {
  99.         setSelectedPath(null);
  100.     }
  101.  
  102.     /*
  103.      * When a MenuElement receives an event from a MouseListener, it should never process the event
  104.      * directly. Instead all MenuElements should call this method with the event.
  105.      */
  106.     public void processMouseEvent(MouseEvent event) {
  107.         int screenX,screenY;
  108.         Point p;
  109.         int i,c,j,d;
  110.         Component mc;
  111.         Rectangle r2;
  112.         int cWidth,cHeight;
  113.         MenuElement menuElement;
  114.         MenuElement subElements[];
  115.         MenuElement path[];
  116.         Vector tmp;
  117.         int selectionSize;
  118.         p = event.getPoint();
  119.     
  120.     Component source = (Component)event.getSource();
  121.     
  122.     if (!source.isShowing()) {
  123.          System.err.println("Received a mouse event from a non-showing Component " + source);
  124.         return;
  125.     }
  126.  
  127.         SwingUtilities.convertPointToScreen(p,source);
  128.  
  129.         screenX = p.x;
  130.         screenY = p.y;
  131.         //System.out.println("MouseEvent is " +event + " scr loc " + new Point(screenX,screenY));
  132.         tmp = (Vector)selection.clone();
  133.         selectionSize = tmp.size();
  134.         for(i=selectionSize - 1 ; i >= 0 ; i--) {
  135.             menuElement = (MenuElement) tmp.elementAt(i);
  136.             subElements = menuElement.getSubElements();
  137.             
  138.             path = null;
  139.             for(j = 0, d = subElements.length ; j < d ; j++) {
  140.         if (subElements[j] == null)
  141.             continue;
  142.                 mc = subElements[j].getComponent();
  143.                 if(!mc.isShowing())
  144.                     continue;
  145.                 if(mc instanceof JComponent) {
  146.                     cWidth  = ((JComponent)mc).getWidth();
  147.                     cHeight = ((JComponent)mc).getHeight();
  148.                 } else {
  149.                     r2 = mc.getBounds();
  150.                     cWidth  = r2.width;
  151.                     cHeight = r2.height;
  152.                 }
  153.                 p.x = screenX;
  154.                 p.y = screenY;
  155.                 SwingUtilities.convertPointFromScreen(p,mc);
  156.  
  157.                 /** Send the event to visible menu element if menu element currently in
  158.                  *  the selected path or contains the event location
  159.                  */
  160.                 if((i < (selectionSize-1) && tmp.elementAt(i+1) == subElements[j]) ||
  161.                    (p.x >= 0 && p.x < cWidth && p.y >= 0 && p.y < cHeight)) {
  162.                     int k;
  163.                     if(path == null) {
  164.                         path = new MenuElement[i+2];
  165.                         for(k=0;k<=i;k++)
  166.                             path[k] = (MenuElement)tmp.elementAt(k);
  167.                     }
  168.                     path[i+1] = subElements[j];
  169.                     subElements[j].processMouseEvent(new MouseEvent(mc,event.getID(),event.getWhen(),
  170.                                                                     event.getModifiers(),p.x,p.y,
  171.                                                                     event.getClickCount(),
  172.                                                                     event.isPopupTrigger()),
  173.                                                      path,this);
  174.                 }
  175.             }
  176.         }
  177.     }
  178.  
  179.     /*
  180.      * Returns the component in the currently selected path 
  181.      * which contains sourcePoint.
  182.      *
  183.      * @param source The component in whose coordinate space sourcePoint
  184.      * is given
  185.      * @param sourcePoint The point which is being tested
  186.      * @return The component in the currently selected path which
  187.      * contains sourcePoint (relative to the source component's 
  188.      * coordinate space.  If sourcePoint is not inside a component
  189.      * on the currently selected path, null is returned.
  190.      */
  191.     public Component componentForPoint(Component source, Point sourcePoint) {
  192.         int screenX,screenY;
  193.         Point p = sourcePoint;
  194.         int i,c,j,d;
  195.         Component mc;
  196.         Rectangle r2;
  197.         int cWidth,cHeight;
  198.         MenuElement menuElement;
  199.         MenuElement subElements[];
  200.         Vector tmp;
  201.         int selectionSize;
  202.  
  203.         SwingUtilities.convertPointToScreen(p,source);
  204.  
  205.         screenX = p.x;
  206.         screenY = p.y;
  207.  
  208.         tmp = (Vector)selection.clone();
  209.         selectionSize = tmp.size();
  210.         for(i=selectionSize - 1 ; i >= 0 ; i--) {
  211.             menuElement = (MenuElement) tmp.elementAt(i);
  212.             subElements = menuElement.getSubElements();
  213.             
  214.             for(j = 0, d = subElements.length ; j < d ; j++) {
  215.         if (subElements[j] == null)
  216.             continue;
  217.                 mc = subElements[j].getComponent();
  218.                 if(!mc.isShowing())
  219.                     continue;
  220.                 if(mc instanceof JComponent) {
  221.                     cWidth  = ((JComponent)mc).getWidth();
  222.                     cHeight = ((JComponent)mc).getHeight();
  223.                 } else {
  224.                     r2 = mc.getBounds();
  225.                     cWidth  = r2.width;
  226.                     cHeight = r2.height;
  227.                 }
  228.                 p.x = screenX;
  229.                 p.y = screenY;
  230.                 SwingUtilities.convertPointFromScreen(p,mc);
  231.         
  232.                 /** Return the deepest component on the selection
  233.          *  path in whose bounds the event's point occurs
  234.                  */
  235.                 if (p.x >= 0 && p.x < cWidth && p.y >= 0 && p.y < cHeight) {
  236.                     return mc;
  237.                 }
  238.             }
  239.         }
  240.     return null;
  241.     }
  242.  
  243.     /*
  244.      * When a MenuElement receives an event from a KeyListener, it should never process the event
  245.      * directly. Instead all MenuElements should call this method with the event.
  246.      */
  247.     public void processKeyEvent(KeyEvent e) {
  248.         Vector tmp;
  249.         int selectionSize;
  250.         int i,j,d;
  251.         MenuElement menuElement;
  252.         MenuElement subElements[];
  253.         MenuElement path[];
  254.         Component mc;
  255.  
  256.         tmp = (Vector)selection.clone();
  257.         selectionSize = tmp.size();
  258.         for(i=selectionSize - 1 ; i >= 0 ; i--) {
  259.             menuElement = (MenuElement) tmp.elementAt(i);
  260.             subElements = menuElement.getSubElements();
  261.             
  262.             path = null;
  263.             for(j = 0, d = subElements.length ; j < d ; j++) {
  264.         if (subElements[j] == null)
  265.             continue;
  266.                 mc = subElements[j].getComponent();
  267.                 if(!mc.isShowing())
  268.                     continue;
  269.                 if(path == null) {
  270.                     int k;
  271.                     path = new MenuElement[i+2];
  272.                     for(k=0;k<=i;k++)
  273.                         path[k] = (MenuElement)tmp.elementAt(k);
  274.                     }
  275.                 path[i+1] = subElements[j];
  276.                 subElements[j].processKeyEvent(e,path,this);
  277.                 if(e.isConsumed())
  278.                     return;
  279.             }
  280.         }
  281.     }
  282.     
  283.     /** 
  284.      * Return true if c is part of the currently used menu
  285.      */
  286.     public boolean isComponentPartOfCurrentMenu(Component c) {
  287.         if(selection.size() > 0) {
  288.             MenuElement me = (MenuElement)selection.elementAt(0);
  289.             return isComponentPartOfCurrentMenu(me,c);
  290.         } else
  291.             return false;
  292.     }
  293.  
  294.     private boolean isComponentPartOfCurrentMenu(MenuElement root,Component c) {
  295.         MenuElement children[];
  296.         int i,d;
  297.     
  298.     if (root == null)
  299.         return false;
  300.  
  301.         if(root.getComponent() == c)
  302.             return true;
  303.         else {
  304.             children = root.getSubElements();
  305.             for(i=0,d=children.length;i<d;i++) {
  306.                 if(isComponentPartOfCurrentMenu(children[i],c))
  307.                     return true;
  308.             }
  309.         }
  310.         return false;
  311.     }
  312. }
  313.  
  314.  
  315.