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
|