X-Received: by 10.129.95.133 with SMTP id t127mr3048893ywb.2.1460056892774; Thu, 07 Apr 2016 12:21:32 -0700 (PDT) X-Received: by 10.157.19.29 with SMTP id f29mr58462ote.19.1460056892648; Thu, 07 Apr 2016 12:21:32 -0700 (PDT) Path: csiph.com!usenet.blueworldhosting.com!feeder01.blueworldhosting.com!peer02.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!10no897523qgg.1!news-out.google.com!u9ni729igk.0!nntp.google.com!gy3no743255igb.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.java.programmer Date: Thu, 7 Apr 2016 12:21:32 -0700 (PDT) Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=50.78.95.177; posting-account=2czF5goAAAD4GBMPIGV4KcD2K4PhoB_H NNTP-Posting-Host: 50.78.95.177 User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: Subject: Scrollable Popup Menu Keyboard Navigation From: Eric Douglas Injection-Date: Thu, 07 Apr 2016 19:21:32 +0000 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Received-Bytes: 10052 X-Received-Body-CRC: 2342477771 Xref: csiph.com comp.lang.java.programmer:34083 Below is some runnable code of my scrollable popup menu, I think about as s= imple as I can get it. I did write a hack with the key map to make page-up= and page-down work. I'm just wondering if I'm missing something. Am I su= pposed to have to manually tell it what to do when someone presses page-up,= page-down, home, end? Why does just the up and down arrow keys work by de= fault? This also allows the down arrow to select menu items you can't see,= so I also wrote a hack to keep the current item visible. public class TestClass1 { public static void main(final String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { final int maximumVisibleRows =3D 5; final JFrame win =3D new JFrame(); final JScrollBar myScroll =3D new JScrollBar(); final JPopupMenu myMenu =3D new JPopupMenu() { { setLayout(new ScrollPopupMenuLayout()); add(myScroll); } @Override public void show(final Component invoker, final in= t x, final int y) { if (invoker instanceof JTextComponent && !(in= voker.isFocusOwner())) { invoker.requestFocusInWindow(); } if (myScroll.isVisible()) { int extent =3D 0; int max =3D 0; int i =3D 0; int unit =3D -1; int width =3D 0; for (final Component comp : getComponent= s()) { if (!(comp instanceof JScrollBar)) = { final Dimension preferredSize = =3D comp.getPreferredSize(); width =3D Math.max(width, pref= erredSize.width); if (unit < 0) { unit =3D preferredSize.he= ight; } if (i++ < maximumVisibleRows) = { extent +=3D preferredSize= .height; } max +=3D preferredSize.height; } } final Insets insets =3D getInsets(); final int widthMargin =3D insets.left + = insets.right; final int heightMargin =3D insets.top + = insets.bottom; myScroll.setUnitIncrement(unit); myScroll.setBlockIncrement(extent); myScroll.setValues(0, heightMargin + ext= ent, 0, heightMargin + max); width +=3D myScroll.getPreferredSize().w= idth + widthMargin; final int height =3D heightMargin + exte= nt; setPopupSize(new Dimension(width, height= )); } super.show(invoker, x, y); } }; myMenu.add(new JMenuItem("A")); myMenu.add(new JMenuItem("B")); myMenu.add(new JMenuItem("C")); myMenu.add(new JMenuItem("D")); myMenu.add(new JMenuItem("E")); myMenu.add(new JMenuItem("F")); myMenu.add(new JMenuItem("G")); win.addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { checkPopup(e); } @Override public void mouseClicked(final MouseEvent e) { checkPopup(e); } @Override public void mouseReleased(final MouseEvent e) { checkPopup(e); } private void checkPopup(final MouseEvent e) { if (e.isPopupTrigger()) { myMenu.show(win, e.getX(), e.getY()); } } }); win.setSize(200, 120); win.setVisible(true); } }); } protected static class ScrollPopupMenuLayout implements LayoutManager,= Serializable { @Override public void addLayoutComponent(final String name, final Component= comp) { } @Override public void removeLayoutComponent(final Component comp) { } @Override public Dimension preferredLayoutSize(final Container parent) { int visibleAmount =3D Integer.MAX_VALUE; final Dimension dim =3D new Dimension(); for (final Component comp : parent.getComponents()) { if (comp.isVisible()) { if (comp instanceof JScrollBar) { final JScrollBar scrollBar =3D (JScrollBar) c= omp; visibleAmount =3D scrollBar.getVisibleAmount(= ); } else { final Dimension pref =3D comp.getPreferredSiz= e(); dim.width =3D Math.max(dim.width, pref.width)= ; dim.height +=3D pref.height; } } } final Insets insets =3D parent.getInsets(); dim.height =3D Math.min(dim.height + insets.top + insets.bot= tom, visibleAmount); return dim; } @Override public Dimension minimumLayoutSize(final Container parent) { int visibleAmount =3D Integer.MAX_VALUE; final Dimension dim =3D new Dimension(); for (final Component comp : parent.getComponents()) { if (comp.isVisible()) { if (comp instanceof JScrollBar) { final JScrollBar scrollBar =3D (JScrollBar) c= omp; visibleAmount =3D scrollBar.getVisibleAmount(= ); } else { final Dimension min =3D comp.getMinimumSize()= ; dim.width =3D Math.max(dim.width, min.width); dim.height +=3D min.height; } } } final Insets insets =3D parent.getInsets(); dim.height =3D Math.min(dim.height + insets.top + insets.bot= tom, visibleAmount); return dim; } @Override public void layoutContainer(final Container parent) { final Insets insets =3D parent.getInsets(); int width =3D parent.getWidth() - insets.left - insets.right= ; final int height =3D parent.getHeight() - insets.top - inset= s.bottom; final int x =3D insets.left; int y =3D insets.top; int position =3D 0; for (final Component comp : parent.getComponents()) { if ((comp instanceof JScrollBar) && comp.isVisible()) { final JScrollBar scrollBar =3D (JScrollBar) comp; final Dimension dim =3D scrollBar.getPreferredSize= (); scrollBar.setBounds(x + width - dim.width, y, dim.= width, height); width -=3D dim.width; position =3D scrollBar.getValue(); } } y -=3D position; for (final Component comp : parent.getComponents()) { if (!(comp instanceof JScrollBar) && comp.isVisible()) = { final Dimension pref =3D comp.getPreferredSize(); comp.setBounds(x, y, width, pref.height); y +=3D pref.height; } } } } }