components/visual-panels/core/src/java/util/com/oracle/solaris/vp/util/swing/PopupList.java
changeset 3553 f1d133b09a8c
parent 3552 077ebe3d0d24
child 3554 ef58713bafc4
equal deleted inserted replaced
3552:077ebe3d0d24 3553:f1d133b09a8c
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 package com.oracle.solaris.vp.util.swing;
       
    27 
       
    28 import java.awt.*;
       
    29 import java.awt.event.*;
       
    30 import javax.swing.*;
       
    31 import javax.swing.plaf.basic.BasicComboPopup;
       
    32 import com.oracle.solaris.vp.util.swing.event.ItemListeners;
       
    33 
       
    34 @SuppressWarnings({"serial"})
       
    35 public class PopupList implements ItemSelectable {
       
    36     //
       
    37     // Static data
       
    38     //
       
    39 
       
    40     // Taken from the JList API
       
    41     private static final int MAX_VISIBLE_ROW_COUNT = 8;
       
    42 
       
    43     //
       
    44     // Instance data
       
    45     //
       
    46 
       
    47     private JComponent component;
       
    48     private BasicComboPopup popup;
       
    49     private JComboBox combo;
       
    50     private ItemListeners listeners = new ItemListeners();
       
    51 
       
    52     //
       
    53     // Constructors
       
    54     //
       
    55 
       
    56     public PopupList(JComponent component) {
       
    57 	this.component = component;
       
    58 
       
    59 	configureComboBox();
       
    60 	configurePopup();
       
    61 	configureList();
       
    62     }
       
    63 
       
    64     public PopupList(JButton button) {
       
    65 	this((JComponent)button);
       
    66 
       
    67 	button.addActionListener(
       
    68 	    new AbstractAction() {
       
    69 		@Override
       
    70 		public void actionPerformed(ActionEvent e) {
       
    71 		    show();
       
    72 		}
       
    73 	    });
       
    74     }
       
    75 
       
    76     public PopupList(JComponent component, ComboBoxModel model) {
       
    77 	this(component);
       
    78 	setModel(model);
       
    79     }
       
    80 
       
    81     public PopupList(JButton button, ComboBoxModel model) {
       
    82 	this(button);
       
    83 	setModel(model);
       
    84     }
       
    85 
       
    86     //
       
    87     // ItemSelectable methods
       
    88     //
       
    89 
       
    90     @Override
       
    91     public void addItemListener(ItemListener l) {
       
    92 	listeners.add(l);
       
    93     }
       
    94 
       
    95     @Override
       
    96     public Object[] getSelectedObjects() {
       
    97 	return popup.getList().getSelectedValues();
       
    98     }
       
    99 
       
   100     @Override
       
   101     public void removeItemListener(ItemListener l) {
       
   102 	listeners.remove(l);
       
   103     }
       
   104 
       
   105     //
       
   106     // PopupList methods
       
   107     //
       
   108 
       
   109     public ComboBoxModel getModel() {
       
   110 	return combo.getModel();
       
   111     }
       
   112 
       
   113     public JComponent getComponent() {
       
   114 	return component;
       
   115     }
       
   116 
       
   117     public BasicComboPopup getPopup() {
       
   118 	return popup;
       
   119     }
       
   120 
       
   121     public void hide() {
       
   122 	popup.setVisible(false);
       
   123 
       
   124 	// Window change -- prefer requestFocus to requestFocusInWindow
       
   125 	component.requestFocus();
       
   126     }
       
   127 
       
   128     protected void itemSelected() {
       
   129 	hide();
       
   130 
       
   131 	Object item = popup.getList().getSelectedValue();
       
   132 	ItemEvent e = new ItemEvent(
       
   133 	    this, ItemEvent.ITEM_STATE_CHANGED, item, ItemEvent.SELECTED);
       
   134 
       
   135 	listeners.itemStateChanged(e);
       
   136     }
       
   137 
       
   138     public void setModel(ComboBoxModel model) {
       
   139 	combo.setModel(model);
       
   140     }
       
   141 
       
   142     public void show() {
       
   143 	JList list = popup.getList();
       
   144 	int size = list.getModel().getSize();
       
   145 	list.setVisibleRowCount(size < MAX_VISIBLE_ROW_COUNT ?
       
   146 	    size : MAX_VISIBLE_ROW_COUNT);
       
   147 
       
   148 	combo.setSelectedIndex(-1);
       
   149 	popup.show(component, 0, component.getHeight());
       
   150 
       
   151 	Window window = SwingUtilities.windowForComponent(popup);
       
   152 	if (window != null) {
       
   153 	    window.setFocusableWindowState(true);
       
   154 	}
       
   155 
       
   156 	// Window change -- prefer requestFocus to requestFocusInWindow
       
   157 	list.requestFocus();
       
   158     }
       
   159 
       
   160     public void showOnDownArrowKey() {
       
   161 	Action showAction =
       
   162 	    new AbstractAction() {
       
   163 		@Override
       
   164 		public void actionPerformed(ActionEvent e) {
       
   165 		    show();
       
   166 		}
       
   167 	    };
       
   168 
       
   169 	GUIUtil.installKeyBinding(component, JComponent.WHEN_FOCUSED,
       
   170 	    "showPopup", showAction, KeyEvent.VK_DOWN, KeyEvent.VK_KP_DOWN);
       
   171     }
       
   172 
       
   173     public void showOnMousePress() {
       
   174 	component.addMouseListener(
       
   175 	    new MouseAdapter() {
       
   176 		@Override
       
   177 		public void mousePressed(MouseEvent e) {
       
   178 		    if (e.getModifiersEx() == InputEvent.BUTTON1_DOWN_MASK) {
       
   179 			show();
       
   180 		    }
       
   181 		}
       
   182 	    });
       
   183     }
       
   184 
       
   185     //
       
   186     // Private methods
       
   187     //
       
   188 
       
   189     private void configureComboBox() {
       
   190 	combo = new JComboBox();
       
   191 	combo.addItemListener(
       
   192 	    new ItemListener() {
       
   193 		@Override
       
   194 		public void itemStateChanged(ItemEvent e) {
       
   195 		    if (e.getStateChange() == ItemEvent.SELECTED) {
       
   196 			itemSelected();
       
   197 		    }
       
   198 		}
       
   199 	    });
       
   200     }
       
   201 
       
   202     private void configureList() {
       
   203 	JList list = popup.getList();
       
   204 	list.setBackground(Color.white);
       
   205 	list.setOpaque(true);
       
   206 	list.setFocusable(true);
       
   207     }
       
   208 
       
   209     private void configurePopup() {
       
   210 	popup = new BasicComboPopup(combo);
       
   211 	popup.setFocusable(true);
       
   212 
       
   213 	Action commitAction =
       
   214 	    new AbstractAction() {
       
   215 		@Override
       
   216 		public void actionPerformed(ActionEvent e) {
       
   217 		    itemSelected();
       
   218 		}
       
   219 	    };
       
   220 
       
   221 	GUIUtil.installKeyBinding(popup,
       
   222 	    JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, "commitPopup",
       
   223 	    commitAction, KeyEvent.VK_ENTER);
       
   224 
       
   225 	Action cancelAction =
       
   226 	    new AbstractAction() {
       
   227 		@Override
       
   228 		public void actionPerformed(ActionEvent e) {
       
   229 		    hide();
       
   230 		}
       
   231 	    };
       
   232 
       
   233 	GUIUtil.installKeyBinding(popup,
       
   234 	    JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, "cancelPopup",
       
   235 	    cancelAction, KeyEvent.VK_ESCAPE);
       
   236     }
       
   237 
       
   238     //
       
   239     // Static methods
       
   240     //
       
   241 
       
   242     public static void main(String s[]) {
       
   243 	String[] data = {
       
   244 	    "Bee", "Skunk"
       
   245 	};
       
   246 	ComboBoxModel model = new DefaultComboBoxModel(data);
       
   247 
       
   248 	JButton b = new JButton("Hello");
       
   249 
       
   250 	PopupList popup = new PopupList(b, model);
       
   251 	popup.showOnDownArrowKey();
       
   252 
       
   253 	popup.addItemListener(
       
   254 	    new ItemListener() {
       
   255 		@Override
       
   256 		public void itemStateChanged(ItemEvent e) {
       
   257 		    System.out.printf("%s\n", e.getItem());
       
   258 		}
       
   259 	    });
       
   260 
       
   261 	JFrame frame = new JFrame();
       
   262 	Container c = frame.getContentPane();
       
   263 	c.setLayout(new BorderLayout());
       
   264 	c.add(b, BorderLayout.CENTER);
       
   265 	frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
       
   266 	frame.pack();
       
   267 	frame.setVisible(true);
       
   268     }
       
   269 }