All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gate.swing.JMenuButton Maven / Gradle / Ivy

/*
 *  Copyright (c) 1995-2012, The University of Sheffield. See the file
 *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
 *
 *  This file is part of GATE (see http://gate.ac.uk/), and is free
 *  software, licenced under the GNU Library General Public License,
 *  Version 2, June 1991 (in the distribution as file licence.html,
 *  and also available at http://gate.ac.uk/gate/licence.html).
 *
 *  JMenuButton.java
 *
 *  Valentin Tablan, 21 Aug 2008
 *
 *  $Id: JMenuButton.java 17608 2014-03-09 12:38:50Z markagreenwood $
 */

package gate.swing;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

/**
 * A toggle button that shows a pop-up menu.
 */
@SuppressWarnings("serial")
public class JMenuButton extends JToggleButton {
  public JMenuButton(JMenu menu) {
    this(menu.getPopupMenu());
    this.menu = menu;
  }
  
  public JMenuButton(JPopupMenu popup) {
    this.popup = popup;
    popup.setInvoker(this);
    initListeners();
  }

  protected void initListeners() {
    
    addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        if(menu != null) menu.setSelected(isSelected());
        if(isSelected()) {
          // show the popup
          Point p = getPopupMenuOrigin();
          popup.show(JMenuButton.this, p.x, p.y);
        }
        else {
          // hide the popup
          popup.setVisible(false);
        }
      }
    });
    
    popup.addPopupMenuListener(new PopupMenuListener(){

      @Override
      public void popupMenuCanceled(PopupMenuEvent e) {
        setSelected(false);
        if(menu != null) menu.setSelected(false);
      }

      @Override
      public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
        setSelected(false);
        if(menu != null) menu.setSelected(false);
      }

      @Override
      public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
      }
    });
  }

  /**
   * Method largely borrowed from Swing's JMenu.
   * 
   * Computes the origin for the JMenu's popup menu. This
   * method uses Look and Feel properties named
   * Menu.menuPopupOffsetX,
   * Menu.menuPopupOffsetY,
   * Menu.submenuPopupOffsetX, and
   * Menu.submenuPopupOffsetY to adjust the exact location
   * of popup.
   * 
   * @return a Point in the coordinate space of the menu
   *         which should be used as the origin of the
   *         JMenu's popup menu
   */
  protected Point getPopupMenuOrigin() {
    int x = 0;
    int y = 0;
    // Figure out the sizes needed to caclulate the menu position
    Dimension s = getSize();
    Dimension pmSize = popup.getSize();
    // For the first time the menu is popped up,
    // the size has not yet been initiated
    if(pmSize.width == 0) {
      pmSize = popup.getPreferredSize();
    }
    Point position = getLocationOnScreen();
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    GraphicsConfiguration gc = getGraphicsConfiguration();
    Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice[] gd = ge.getScreenDevices();
    for(int i = 0; i < gd.length; i++) {
      if(gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
        GraphicsConfiguration dgc = gd[i].getDefaultConfiguration();
        if(dgc.getBounds().contains(position)) {
          gc = dgc;
          break;
        }
      }
    }

    if(gc != null) {
      screenBounds = gc.getBounds();
      // take screen insets (e.g. taskbar) into account
      Insets screenInsets = toolkit.getScreenInsets(gc);

      screenBounds.width -= Math.abs(screenInsets.left + screenInsets.right);
      screenBounds.height -= Math.abs(screenInsets.top + screenInsets.bottom);
      position.x -= Math.abs(screenInsets.left);
      position.y -= Math.abs(screenInsets.top);
    }

    // We are a toplevel menu (pull-down)
    int xOffset = UIManager.getInt("Menu.menuPopupOffsetX");
    int yOffset = UIManager.getInt("Menu.menuPopupOffsetY");

    if(getComponentOrientation().isLeftToRight()) {
      // First determine the x:
      x = xOffset; // Extend to the right
      if(position.x + x + pmSize.width >= screenBounds.width + screenBounds.x &&
      // popup doesn't fit - place it wherever there's more
              // room
              screenBounds.width - s.width < 2 * (position.x - screenBounds.x)) {

        x = s.width - xOffset - pmSize.width;
      }
    }
    else {
      // First determine the x:
      x = s.width - xOffset - pmSize.width; // Extend to the left
      if(position.x + x < screenBounds.x &&
      // popup doesn't fit - place it wherever there's more room
              screenBounds.width - s.width > 2 * (position.x - screenBounds.x)) {

        x = xOffset;
      }
    }
    // Then the y:
    y = s.height + yOffset; // Prefer dropping down
    if(position.y + y + pmSize.height >= screenBounds.height &&
    // popup doesn't fit - place it wherever there's more room
            screenBounds.height - s.height < 2 * (position.y - screenBounds.y)) {

      y = 0 - yOffset - pmSize.height; // Otherwise drop 'up'
    }
    return new Point(x, y);
  }

  protected JPopupMenu popup;
  protected JMenu menu;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy