< prev index next >

src/java.desktop/unix/classes/sun/awt/X11/XChoicePeer.java

Print this page


   1 /*
   2  * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  25 
  26 package sun.awt.X11;
  27 
  28 import java.awt.*;
  29 import java.awt.peer.*;
  30 import java.awt.event.*;
  31 import sun.util.logging.PlatformLogger;
  32 
  33 // FIXME: tab traversal should be disabled when mouse is captured (4816336)
  34 
  35 // FIXME: key and mouse events should not be delivered to listeners when the Choice is unfurled.  Must override handleNativeKey/MouseEvent (4816336)
  36 
  37 // FIXME: test programmatic add/remove/clear/etc
  38 
  39 // FIXME: account for unfurling at the edge of the screen
  40 // Note: can't set x,y on layout(), 'cause moving the top-level to the
  41 // edge of the screen won't call layout().  Just do it on paint, I guess
  42 
  43 // TODO: make painting more efficient (i.e. when down arrow is pressed, only two items should need to be repainted.
  44 
  45 public class XChoicePeer extends XComponentPeer implements ChoicePeer, ToplevelStateListener {
  46     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XChoicePeer");
  47 
  48     private static final int MAX_UNFURLED_ITEMS = 10;  // Maximum number of
  49     // items to be displayed
  50     // at a time in an
  51     // unfurled Choice
  52     // Description of these constants in ListHelper
  53     public static final int TEXT_SPACE = 1;
  54     public static final int BORDER_WIDTH = 1;
  55     public static final int ITEM_MARGIN = 1;
  56     public static final int SCROLLBAR_WIDTH = 15;
  57 
  58 
  59     // SHARE THESE!
  60     private static final Insets focusInsets = new Insets(0,0,0,0);
  61 
  62 
  63     static final int WIDGET_OFFSET = 18;
  64 
  65     // Stolen from Tiny


 724         return unfurled;
 725     }
 726 
 727     /* fix for 6261352. We should detect if current parent Window (containing a Choice) become iconified and hide pop-down menu with grab release.
 728      * In this case we should hide pop-down menu.
 729      */
 730     //calls from XWindowPeer. Could accept X-styled state events
 731     public void stateChangedICCCM(int oldState, int newState) {
 732         if (unfurled && oldState != newState){
 733                 hidePopdownMenu();
 734         }
 735     }
 736 
 737     //calls from XFramePeer. Could accept Frame's states.
 738     public void stateChangedJava(int oldState, int newState) {
 739         if (unfurled && oldState != newState){
 740             hidePopdownMenu();
 741         }
 742     }
 743 










 744     /**************************************************************************/
 745     /* Common functionality between List & Choice
 746        /**************************************************************************/
 747 
 748     /**
 749      * Inner class for the unfurled Choice list
 750      * Much, much more docs
 751      */
 752     class UnfurledChoice extends XWindow /*implements XScrollbarClient*/ {
 753 
 754         // First try - use Choice as the target
 755 
 756         public UnfurledChoice(Component target) {
 757             super(target);
 758         }
 759 
 760         // Override so we can do our own create()
 761         public void preInit(XCreateWindowParams params) {
 762             // A parent of this window is the target, at this point: wrong.
 763             // Remove parent window; in the following preInit() call we'll calculate as a default
 764             // a correct root window which is the proper parent for override redirect.
 765             params.delete(PARENT_WINDOW);
 766             super.preInit(params);
 767             // Reset bounds(we'll set them later), set overrideRedirect
 768             params.remove(BOUNDS);
 769             params.add(OVERRIDE_REDIRECT, Boolean.TRUE);
 770         }
 771 
 772         // Generally, bounds should be:
 773         //  x = target.x
 774         //  y = target.y + target.height
 775         //  w = Max(target.width, getLongestItemWidth) + possible vertScrollbar
 776         //  h = Min(MAX_UNFURLED_ITEMS, target.getItemCount()) * itemHeight
 777         Rectangle placeOnScreen() {
 778             int numItemsDisplayed;
 779             // Motif paints an empty Choice the same size as a single item
 780             if (helper.isEmpty()) {
 781                 numItemsDisplayed = 1;
 782             }
 783             else {
 784                 int numItems = helper.getItemCount();
 785                 numItemsDisplayed = Math.min(MAX_UNFURLED_ITEMS, numItems);
 786             }
 787             Point global = XChoicePeer.this.toGlobal(0,0);
 788             Rectangle screen = graphicsConfig.getBounds();
 789 
 790             if (alignUnder != null) {
 791                 Rectangle choiceRec = XChoicePeer.this.getBounds();
 792                 choiceRec.setLocation(0, 0);
 793                 choiceRec = XChoicePeer.this.toGlobal(choiceRec);
 794                 Rectangle alignUnderRec = new Rectangle(alignUnder.getLocationOnScreen(), alignUnder.getSize()); // TODO: Security?
 795                 Rectangle result = choiceRec.union(alignUnderRec);
 796                 // we've got the left and width, calculate top and height
 797                 width = result.width;
 798                 x = result.x;
 799                 y = result.y + result.height;
 800                 height = 2*BORDER_WIDTH +
 801                     numItemsDisplayed*(helper.getItemHeight()+2*ITEM_MARGIN);
 802             } else {
 803                 x = global.x;
 804                 y = global.y + XChoicePeer.this.height;
 805                 width = Math.max(XChoicePeer.this.width,
 806                                  helper.getMaxItemWidth() + 2 * (BORDER_WIDTH + ITEM_MARGIN + TEXT_SPACE) + (helper.isVSBVisible() ? SCROLLBAR_WIDTH : 0));
 807                 height = 2*BORDER_WIDTH +
 808                     numItemsDisplayed*(helper.getItemHeight()+2*ITEM_MARGIN);
 809             }
 810             // Don't run off the edge of the screen
 811             if (x < 0) {
 812                 x = 0;
 813             }
 814             else if (x + width > screen.width) {
 815                 x = screen.width - width;
 816             }
 817 
 818             if (y + height > screen.height) {
 819                 y = global.y - height;
 820             }
 821             if (y < 0) {
 822                 y = 0;
 823             }
 824             return new Rectangle(x, y, width, height);
 825         }
 826 
 827         public void toFront() {
 828             // see 6240074 for more information
 829             if (choiceListener != null)
 830                 choiceListener.unfurledChoiceOpening(helper);
 831 
 832             Rectangle r = placeOnScreen();
 833             reshape(r.x, r.y, r.width, r.height);
 834             super.toFront();
 835             setVisible(true);
 836         }
 837 
 838         /*
 839          * Track a MouseEvent (either a drag or a press) and paint a new
 840          * selected item, if necessary.
 841          */
 842         // FIXME: first unfurl after move is not at edge of the screen  onto second monitor doesn't


   1 /*
   2  * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  25 
  26 package sun.awt.X11;
  27 
  28 import java.awt.*;
  29 import java.awt.peer.*;
  30 import java.awt.event.*;
  31 import sun.util.logging.PlatformLogger;
  32 
  33 // FIXME: tab traversal should be disabled when mouse is captured (4816336)
  34 
  35 // FIXME: key and mouse events should not be delivered to listeners when the Choice is unfurled.  Must override handleNativeKey/MouseEvent (4816336)
  36 
  37 // FIXME: test programmatic add/remove/clear/etc
  38 
  39 // FIXME: account for unfurling at the edge of the screen
  40 // Note: can't set x,y on layout(), 'cause moving the top-level to the
  41 // edge of the screen won't call layout().  Just do it on paint, I guess
  42 
  43 // TODO: make painting more efficient (i.e. when down arrow is pressed, only two items should need to be repainted.
  44 
  45 public final class XChoicePeer extends XComponentPeer implements ChoicePeer, ToplevelStateListener {
  46     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XChoicePeer");
  47 
  48     private static final int MAX_UNFURLED_ITEMS = 10;  // Maximum number of
  49     // items to be displayed
  50     // at a time in an
  51     // unfurled Choice
  52     // Description of these constants in ListHelper
  53     public static final int TEXT_SPACE = 1;
  54     public static final int BORDER_WIDTH = 1;
  55     public static final int ITEM_MARGIN = 1;
  56     public static final int SCROLLBAR_WIDTH = 15;
  57 
  58 
  59     // SHARE THESE!
  60     private static final Insets focusInsets = new Insets(0,0,0,0);
  61 
  62 
  63     static final int WIDGET_OFFSET = 18;
  64 
  65     // Stolen from Tiny


 724         return unfurled;
 725     }
 726 
 727     /* fix for 6261352. We should detect if current parent Window (containing a Choice) become iconified and hide pop-down menu with grab release.
 728      * In this case we should hide pop-down menu.
 729      */
 730     //calls from XWindowPeer. Could accept X-styled state events
 731     public void stateChangedICCCM(int oldState, int newState) {
 732         if (unfurled && oldState != newState){
 733                 hidePopdownMenu();
 734         }
 735     }
 736 
 737     //calls from XFramePeer. Could accept Frame's states.
 738     public void stateChangedJava(int oldState, int newState) {
 739         if (unfurled && oldState != newState){
 740             hidePopdownMenu();
 741         }
 742     }
 743 
 744     @Override
 745     protected void initGraphicsConfiguration() {
 746         super.initGraphicsConfiguration();
 747         // The popup have the same graphic config, so update it at the same time
 748         if (unfurledChoice != null) {
 749             unfurledChoice.initGraphicsConfiguration();
 750             unfurledChoice.doValidateSurface();
 751         }
 752     }
 753 
 754     /**************************************************************************/
 755     /* Common functionality between List & Choice
 756        /**************************************************************************/
 757 
 758     /**
 759      * Inner class for the unfurled Choice list
 760      * Much, much more docs
 761      */
 762     final class UnfurledChoice extends XWindow /*implements XScrollbarClient*/ {
 763 
 764         // First try - use Choice as the target
 765 
 766         public UnfurledChoice(Component target) {
 767             super(target);
 768         }
 769 
 770         // Override so we can do our own create()
 771         public void preInit(XCreateWindowParams params) {
 772             // A parent of this window is the target, at this point: wrong.
 773             // Remove parent window; in the following preInit() call we'll calculate as a default
 774             // a correct root window which is the proper parent for override redirect.
 775             params.delete(PARENT_WINDOW);
 776             super.preInit(params);
 777             // Reset bounds(we'll set them later), set overrideRedirect
 778             params.remove(BOUNDS);
 779             params.add(OVERRIDE_REDIRECT, Boolean.TRUE);
 780         }
 781 
 782         // Generally, bounds should be:
 783         //  x = target.x
 784         //  y = target.y + target.height
 785         //  w = Max(target.width, getLongestItemWidth) + possible vertScrollbar
 786         //  h = Min(MAX_UNFURLED_ITEMS, target.getItemCount()) * itemHeight
 787         Rectangle placeOnScreen() {
 788             int numItemsDisplayed;
 789             // Motif paints an empty Choice the same size as a single item
 790             if (helper.isEmpty()) {
 791                 numItemsDisplayed = 1;
 792             }
 793             else {
 794                 int numItems = helper.getItemCount();
 795                 numItemsDisplayed = Math.min(MAX_UNFURLED_ITEMS, numItems);
 796             }
 797             Point global = XChoicePeer.this.toGlobal(0,0);
 798             Rectangle screenBounds = graphicsConfig.getBounds();
 799 
 800             if (alignUnder != null) {
 801                 Rectangle choiceRec = XChoicePeer.this.getBounds();
 802                 choiceRec.setLocation(0, 0);
 803                 choiceRec = XChoicePeer.this.toGlobal(choiceRec);
 804                 Rectangle alignUnderRec = new Rectangle(alignUnder.getLocationOnScreen(), alignUnder.getSize()); // TODO: Security?
 805                 Rectangle result = choiceRec.union(alignUnderRec);
 806                 // we've got the left and width, calculate top and height
 807                 width = result.width;
 808                 x = result.x;
 809                 y = result.y + result.height;
 810                 height = 2*BORDER_WIDTH +
 811                     numItemsDisplayed*(helper.getItemHeight()+2*ITEM_MARGIN);
 812             } else {
 813                 x = global.x;
 814                 y = global.y + XChoicePeer.this.height;
 815                 width = Math.max(XChoicePeer.this.width,
 816                                  helper.getMaxItemWidth() + 2 * (BORDER_WIDTH + ITEM_MARGIN + TEXT_SPACE) + (helper.isVSBVisible() ? SCROLLBAR_WIDTH : 0));
 817                 height = 2*BORDER_WIDTH +
 818                     numItemsDisplayed*(helper.getItemHeight()+2*ITEM_MARGIN);
 819             }
 820             // Don't run off the edge of the screenBounds
 821             if (x < screenBounds.x) {
 822                 x = screenBounds.x;
 823             }
 824             else if (x + width > screenBounds.x + screenBounds.width) {
 825                 x = screenBounds.x + screenBounds.width - width;
 826             }
 827 
 828             if (y + height > screenBounds.y + screenBounds.height) {
 829                 y = global.y - height;
 830             }
 831             if (y < screenBounds.y) {
 832                 y = screenBounds.y;
 833             }
 834             return new Rectangle(x, y, width, height);
 835         }
 836 
 837         public void toFront() {
 838             // see 6240074 for more information
 839             if (choiceListener != null)
 840                 choiceListener.unfurledChoiceOpening(helper);
 841 
 842             Rectangle r = placeOnScreen();
 843             reshape(r.x, r.y, r.width, r.height);
 844             super.toFront();
 845             setVisible(true);
 846         }
 847 
 848         /*
 849          * Track a MouseEvent (either a drag or a press) and paint a new
 850          * selected item, if necessary.
 851          */
 852         // FIXME: first unfurl after move is not at edge of the screen  onto second monitor doesn't


< prev index next >