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

package sun.awt.X11;

import java.awt.*;
import java.awt.peer.*;
import java.awt.event.*;
import sun.util.logging.PlatformLogger;

// FIXME: tab traversal should be disabled when mouse is captured (4816336)

// FIXME: key and mouse events should not be delivered to listeners when the Choice is unfurled.  Must override handleNativeKey/MouseEvent (4816336)

// FIXME: test programmatic add/remove/clear/etc

// FIXME: account for unfurling at the edge of the screen
// Note: can't set x,y on layout(), 'cause moving the top-level to the
// edge of the screen won't call layout().  Just do it on paint, I guess

// TODO: make painting more efficient (i.e. when down arrow is pressed, only two items should need to be repainted.

public final class XChoicePeer extends XComponentPeer implements ChoicePeer, ToplevelStateListener {
    private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XChoicePeer");

    private static final int MAX_UNFURLED_ITEMS = 10;  // Maximum number of
    // items to be displayed
    // at a time in an
    // unfurled Choice
    // Description of these constants in ListHelper
    public static final int TEXT_SPACE = 1;
    public static final int BORDER_WIDTH = 1;
    public static final int ITEM_MARGIN = 1;
    public static final int SCROLLBAR_WIDTH = 15;


    // SHARE THESE!
    private static final Insets focusInsets = new Insets(0,0,0,0);


    static final int WIDGET_OFFSET = 18;

    // Stolen from Tiny
    static final int            TEXT_XPAD = 8;
    static final int            TEXT_YPAD = 6;

    // FIXME: Motif uses a different focus color for the item within
    // the unfurled Choice list and for when the Choice itself is focused and
    // popped up.
    static final Color focusColor = Color.black;

    // TODO: there is a time value that the mouse is held down.  If short
    // enough,  the Choice stays popped down.  If long enough, Choice
    // is furled when the mouse is released

    private boolean unfurled = false;        // Choice list is popped down

    private boolean dragging = false;        // Mouse was pressed and is being
                                             // dragged over the (unfurled)
                                             // Choice

    private boolean mouseInSB = false;       // Mouse is interacting with the
                                             // scrollbar

    private boolean firstPress = false;      // mouse was pressed on
                                             // furled Choice so we
                                             // not need to furl the
                                             // Choice when MOUSE_RELEASED occurred

    // 6425067. Mouse was pressed on furled choice and dropdown list appeared over Choice itself
    // and then there were no mouse movements until MOUSE_RELEASE.
    // This scenario leads to ItemStateChanged as the choice logic uses
    // MouseReleased event to send ItemStateChanged. To prevent it we should
    // use a combination of firstPress and wasDragged variables.
    // The only difference in dragging and wasDragged is: last one will not
    // set to false on mouse ungrab. It become false after MouseRelased() finishes.
    private boolean wasDragged = false;
    private ListHelper helper;
    private UnfurledChoice unfurledChoice;

    // TODO: Choice remembers where it was scrolled to when unfurled - it's not
    // always to the currently selected item.

    // Indicates whether or not to paint selected item in the choice.
    // Default is to paint
    private boolean drawSelectedItem = true;

    // If set, indicates components under which choice popup should be showed.
    // The choice's popup width and location should be adjust to appear
    // under both choice and alignUnder component.
    private Component alignUnder;

    // If cursor is outside of an unfurled Choice when the mouse is
    // released, Choice item should NOT be updated.  Remember the proper index.
    private int dragStartIdx = -1;

    // Holds the listener (XFileDialogPeer) which the processing events from the choice
    // See 6240074 for more information
    private XChoicePeerListener choiceListener;

    XChoicePeer(Choice target) {
        super(target);
    }

    void preInit(XCreateWindowParams params) {
        super.preInit(params);
        Choice target = (Choice)this.target;
        int numItems = target.getItemCount();
        unfurledChoice = new UnfurledChoice(target);
        getToplevelXWindow().addToplevelStateListener(this);
        helper = new ListHelper(unfurledChoice,
                                getGUIcolors(),
                                numItems,
                                false,
                                true,
                                false,
                                target.getFont(),
                                MAX_UNFURLED_ITEMS,
                                TEXT_SPACE,
                                ITEM_MARGIN,
                                BORDER_WIDTH,
                                SCROLLBAR_WIDTH);
    }

    void postInit(XCreateWindowParams params) {
        super.postInit(params);
        Choice target = (Choice)this.target;
        int numItems = target.getItemCount();

        // Add all items
        for (int i = 0; i < numItems; i++) {
            helper.add(target.getItem(i));
        }
        if (!helper.isEmpty()) {
            helper.select(target.getSelectedIndex());
            helper.setFocusedIndex(target.getSelectedIndex());
        }
        helper.updateColors(getGUIcolors());
        updateMotifColors(getPeerBackground());
    }

    public boolean isFocusable() { return true; }

    // 6399679. check if super.setBounds() actually changes the size of the
    // component and then compare current Choice size with a new one. If
    // they differs then hide dropdown menu
    public void setBounds(int x, int y, int width, int height, int op) {
        int oldX = this.x;
        int oldY = this.y;
        int oldWidth = this.width;
        int oldHeight = this.height;
        super.setBounds(x, y, width, height, op);
        if (unfurled && (oldX != this.x || oldY != this.y || oldWidth != this.width || oldHeight != this.height) ) {
            hidePopdownMenu();
        }
    }

    public void focusGained(FocusEvent e) {
        // TODO: only need to paint the focus bit
        super.focusGained(e);
        repaint();
    }

    /*
     * Fix for 6246503 : Disabling a choice after selection locks keyboard, mouse and makes the system unusable, Xtoolkit
     * if setEnabled(false) invoked we should close opened choice in
     * order to prevent keyboard/mouse lock.
     */
    public void setEnabled(boolean value) {
        super.setEnabled(value);
        helper.updateColors(getGUIcolors());
        if (!value && unfurled){
            hidePopdownMenu();
        }
    }

    public void focusLost(FocusEvent e) {
        // TODO: only need to paint the focus bit?
        super.focusLost(e);
        repaint();
    }

    void ungrabInputImpl() {
        if (unfurled) {
            unfurled = false;
            dragging = false;
            mouseInSB = false;
            unfurledChoice.setVisible(false);
        }

        super.ungrabInputImpl();
    }

    void handleJavaKeyEvent(KeyEvent e) {
        if (e.getID() == KeyEvent.KEY_PRESSED) {
            keyPressed(e);
        }
    }

    public void keyPressed(KeyEvent e) {
        switch(e.getKeyCode()) {
            // UP & DOWN are same if furled or unfurled
          case KeyEvent.VK_DOWN:
          case KeyEvent.VK_KP_DOWN: {
              if (helper.getItemCount() > 1) {
                  helper.down();
                  int newIdx = helper.getSelectedIndex();

                  ((Choice)target).select(newIdx);
                  postEvent(new ItemEvent((Choice)target,
                                          ItemEvent.ITEM_STATE_CHANGED,
                                          ((Choice)target).getItem(newIdx),
                                          ItemEvent.SELECTED));
                  repaint();
              }
              break;
          }
          case KeyEvent.VK_UP:
          case KeyEvent.VK_KP_UP: {
              if (helper.getItemCount() > 1) {
                  helper.up();
                  int newIdx = helper.getSelectedIndex();

                  ((Choice)target).select(newIdx);
                  postEvent(new ItemEvent((Choice)target,
                                          ItemEvent.ITEM_STATE_CHANGED,
                                          ((Choice)target).getItem(newIdx),
                                          ItemEvent.SELECTED));
                  repaint();
              }
              break;
          }
          case KeyEvent.VK_PAGE_DOWN:
              if (unfurled && !dragging) {
                  int oldIdx = helper.getSelectedIndex();
                  helper.pageDown();
                  int newIdx = helper.getSelectedIndex();
                  if (oldIdx != newIdx) {
                      ((Choice)target).select(newIdx);
                      postEvent(new ItemEvent((Choice)target,
                                              ItemEvent.ITEM_STATE_CHANGED,
                                              ((Choice)target).getItem(newIdx),
                                              ItemEvent.SELECTED));
                      repaint();
                  }
              }
              break;
          case KeyEvent.VK_PAGE_UP:
              if (unfurled && !dragging) {
                  int oldIdx = helper.getSelectedIndex();
                  helper.pageUp();
                  int newIdx = helper.getSelectedIndex();
                  if (oldIdx != newIdx) {
                      ((Choice)target).select(newIdx);
                      postEvent(new ItemEvent((Choice)target,
                                              ItemEvent.ITEM_STATE_CHANGED,
                                              ((Choice)target).getItem(newIdx),
                                              ItemEvent.SELECTED));
                      repaint();
                  }
              }
              break;
          case KeyEvent.VK_ESCAPE:
          case KeyEvent.VK_ENTER:
              if (unfurled) {
                  if (dragging){
                      if (e.getKeyCode() == KeyEvent.VK_ESCAPE){
                          //This also happens on
                          // - MouseButton2,3, etc. press
                          // - ENTER press
                          helper.select(dragStartIdx);
                      } else { //KeyEvent.VK_ENTER:
                          int newIdx = helper.getSelectedIndex();
                          ((Choice)target).select(newIdx);
                          postEvent(new ItemEvent((Choice)target,
                                                  ItemEvent.ITEM_STATE_CHANGED,
                                                  ((Choice)target).getItem(newIdx),
                                                  ItemEvent.SELECTED));
                      }
                  }
                  hidePopdownMenu();
                  dragging = false;
                  wasDragged = false;
                  mouseInSB = false;

                  // See 6240074 for more information
                  if (choiceListener != null){
                      choiceListener.unfurledChoiceClosing();
                  }
              }
              break;
          default:
              if (unfurled) {
                  Toolkit.getDefaultToolkit().beep();
              }
              break;
        }
    }

    public boolean handlesWheelScrolling() { return true; }

    void handleJavaMouseWheelEvent(MouseWheelEvent e) {
        if (unfurled && helper.isVSBVisible()) {
            if (ListHelper.doWheelScroll(helper.getVSB(), null, e)) {
                repaint();
            }
        }
    }

    void handleJavaMouseEvent(MouseEvent e) {
        super.handleJavaMouseEvent(e);
        int i = e.getID();
        switch (i) {
          case MouseEvent.MOUSE_PRESSED:
              mousePressed(e);
              break;
          case MouseEvent.MOUSE_RELEASED:
              mouseReleased(e);
              break;
          case MouseEvent.MOUSE_DRAGGED:
              mouseDragged(e);
              break;
        }
    }

    public void mousePressed(MouseEvent e) {
        /*
         * fix for 5003166: a Choice on XAWT shouldn't react to any
         * mouse button presses except left. This involves presses on
         * Choice but not on opened part of choice.
         */
        if (e.getButton() == MouseEvent.BUTTON1){
            dragStartIdx = helper.getSelectedIndex();
            if (unfurled) {
                //fix 6259328: PIT: Choice scrolls when dragging the parent frame while drop-down is active, XToolkit
                if (! (isMouseEventInChoice(e) ||
                       unfurledChoice.isMouseEventInside(e)))
                {
                    hidePopdownMenu();
                }
                // Press on unfurled Choice.  Highlight the item under the cursor,
                // but don't send item event or set the text on the button yet
                unfurledChoice.trackMouse(e);
            }
            else {
                // Choice is up - unfurl it
                grabInput();
                unfurledChoice.toFront();
                firstPress = true;
                wasDragged = false;
                unfurled = true;
            }
        }
    }

    /*
     * helper method for mouseReleased routine
     */
    void hidePopdownMenu(){
        ungrabInput();
        unfurledChoice.setVisible(false);
        unfurled = false;
    }

    public void mouseReleased(MouseEvent e) {
        if (unfurled) {
            if (mouseInSB) {
                unfurledChoice.trackMouse(e);
            }
            else {
                // We pressed and dragged onto the Choice, or, this is the
                // second release after clicking to make the Choice "stick"
                // unfurled.
                // This release should ungrab/furl, and set the new item if
                // release was over the unfurled Choice.

                // Fix for 6239944 : Choice shouldn't close its
                // pop-down menu if user presses Mouse on Choice's Scrollbar
                // some additional cases like releasing mouse outside
                // of Choice are considered too
                boolean isMouseEventInside = unfurledChoice.isMouseEventInside( e );
                boolean isMouseInListArea = unfurledChoice.isMouseInListArea( e );

                // Fixed 6318746: REG: File Selection is failing
                // We shouldn't restore the selected item
                // if the mouse was dragged outside the drop-down choice area
                if (!helper.isEmpty() && !isMouseInListArea && dragging) {
                    // Set the selected item back how it was.
                    ((Choice)target).select(dragStartIdx);
                }

                // Choice must be closed if user releases mouse on
                // pop-down menu on the second click
                if ( !firstPress && isMouseInListArea) {
                    hidePopdownMenu();
                }
                // Choice must be closed if user releases mouse
                // outside of Choice's pop-down menu  on the second click
                if ( !firstPress && !isMouseEventInside) {
                    hidePopdownMenu();
                }
                //if user drags Mouse on pop-down menu, Scrollbar or
                // outside the Choice
                if ( firstPress && dragging) {
                    hidePopdownMenu();
                }
                /* this could happen when user has opened a Choice and
                 * released mouse button. Then he drags mouse on the
                 * Scrollbar and releases mouse again.
                 */
                if ( !firstPress && !isMouseInListArea &&
                     isMouseEventInside && dragging)
                {
                    hidePopdownMenu();
                }

                if (!helper.isEmpty()) {
                    // Only update the Choice if the mouse button is released
                    // over the list of items.
                    if (unfurledChoice.isMouseInListArea(e)) {
                        int newIdx = helper.getSelectedIndex();
                        if (newIdx >= 0) {
                            // Update the selected item in the target now that
                            // the mouse selection is complete.
                            if (newIdx != dragStartIdx) {
                                ((Choice)target).select(newIdx);
                                // NOTE: We get a repaint when Choice.select()
                                // calls our peer.select().
                            }
                            if (wasDragged && e.getButton() != MouseEvent.BUTTON1){
                                ((Choice)target).select(dragStartIdx);
                            }

                            /*fix for 6239941 : Choice triggers ItemEvent when selecting an item with right mouse button, Xtoolkit
                            * We should generate ItemEvent if only
                            * LeftMouseButton used */
                            if (e.getButton() == MouseEvent.BUTTON1 &&
                                (!firstPress || wasDragged ))
                            {
                                postEvent(new ItemEvent((Choice)target,
                                                        ItemEvent.ITEM_STATE_CHANGED,
                                                        ((Choice)target).getItem(newIdx),
                                                        ItemEvent.SELECTED));
                            }

                            // see 6240074 for more information
                            if (choiceListener != null) {
                                choiceListener.unfurledChoiceClosing();
                            }
                        }
                    }
                }
                // See 6243382 for more information
                unfurledChoice.trackMouse(e);
            }
        }

        dragging = false;
        wasDragged = false;
        firstPress = false;
        dragStartIdx = -1;
    }
    @SuppressWarnings("deprecation")
    public void mouseDragged(MouseEvent e) {
        /*
         * fix for 5003166. On Motif user are unable to drag
         * mouse inside opened Choice if he drags the mouse with
         * different from LEFT mouse button ( e.g. RIGHT or MIDDLE).
         * This fix make impossible to drag mouse inside opened choice
         * with other mouse buttons rather then LEFT one.
         */
        if ( e.getModifiers() == MouseEvent.BUTTON1_MASK ){
            dragging = true;
            wasDragged = true;
            unfurledChoice.trackMouse(e);
        }
    }

    // Stolen from TinyChoicePeer
    @SuppressWarnings("deprecation")
    public Dimension getMinimumSize() {
        // TODO: move this impl into ListHelper?
        FontMetrics fm = getFontMetrics(target.getFont());
        Choice c = (Choice)target;
        int w = 0;
        for (int i = c.countItems() ; i-- > 0 ;) {
            w = Math.max(fm.stringWidth(c.getItem(i)), w);
        }
        return new Dimension(w + TEXT_XPAD + WIDGET_OFFSET,
                             fm.getMaxAscent() + fm.getMaxDescent() + TEXT_YPAD);
    }

    /*
     * Layout the...
     */
    public void layout() {
        /*
          Dimension size = target.getSize();
          Font f = target.getFont();
          FontMetrics fm = target.getFontMetrics(f);
          String text = ((Choice)target).getLabel();

          textRect.height = fm.getHeight();

          checkBoxSize = getChoiceSize(fm);

          // Note - Motif appears to use an left inset that is slightly
          // scaled to the checkbox/font size.
          cbX = borderInsets.left + checkBoxInsetFromText;
          cbY = size.height / 2 - checkBoxSize / 2;
          int minTextX = borderInsets.left + 2 * checkBoxInsetFromText + checkBoxSize;
          // FIXME: will need to account for alignment?
          // FIXME: call layout() on alignment changes
          //textRect.width = fm.stringWidth(text);
          textRect.width = fm.stringWidth(text == null ? "" : text);
          textRect.x = Math.max(minTextX, size.width / 2 - textRect.width / 2);
          textRect.y = size.height / 2 - textRect.height / 2 + borderInsets.top;

          focusRect.x = focusInsets.left;
          focusRect.y = focusInsets.top;
          focusRect.width = size.width-(focusInsets.left+focusInsets.right)-1;
          focusRect.height = size.height-(focusInsets.top+focusInsets.bottom)-1;

          myCheckMark = AffineTransform.getScaleInstance((double)target.getFont().getSize() / MASTER_SIZE, (double)target.getFont().getSize() / MASTER_SIZE).createTransformedShape(MASTER_CHECKMARK);
        */

    }

    /**
     * Paint the choice
     */
    @Override
    void paintPeer(final Graphics g) {
        flush();
        Dimension size = getPeerSize();
        // TODO: when mouse is down over button, widget should be drawn depressed
        g.setColor(getPeerBackground());
        g.fillRect(0, 0, width, height);

        drawMotif3DRect(g, 1, 1, width-2, height-2, false);
        drawMotif3DRect(g, width - WIDGET_OFFSET, (height / 2) - 3, 12, 6, false);

        if (!helper.isEmpty() && helper.getSelectedIndex() != -1) {
            g.setFont(getPeerFont());
            FontMetrics fm = g.getFontMetrics();
            String lbl = helper.getItem(helper.getSelectedIndex());
            if (lbl != null && drawSelectedItem) {
                g.setClip(1, 1, width - WIDGET_OFFSET - 2, height);
                if (isEnabled()) {
                    g.setColor(getPeerForeground());
                    g.drawString(lbl, 5, (height + fm.getMaxAscent()-fm.getMaxDescent())/2);
                }
                else {
                    g.setColor(getPeerBackground().brighter());
                    g.drawString(lbl, 5, (height + fm.getMaxAscent()-fm.getMaxDescent())/2);
                    g.setColor(getPeerBackground().darker());
                    g.drawString(lbl, 4, ((height + fm.getMaxAscent()-fm.getMaxDescent())/2)-1);
                }
                g.setClip(0, 0, width, height);
            }
        }
        if (hasFocus()) {
            paintFocus(g,focusInsets.left,focusInsets.top,size.width-(focusInsets.left+focusInsets.right)-1,size.height-(focusInsets.top+focusInsets.bottom)-1);
        }
        if (unfurled) {
            unfurledChoice.repaint();
        }
        flush();
    }

    protected void paintFocus(Graphics g,
                              int x, int y, int w, int h) {
        g.setColor(focusColor);
        g.drawRect(x,y,w,h);
    }



    /*
     * ChoicePeer methods stolen from TinyChoicePeer
     */

    public void select(int index) {
        helper.select(index);
        helper.setFocusedIndex(index);
        repaint();
    }

    public void add(String item, int index) {
        helper.add(item, index);
        repaint();
    }

    public void remove(int index) {
        boolean selected = (index == helper.getSelectedIndex());
        boolean visibled = (index >= helper.firstDisplayedIndex() && index <= helper.lastDisplayedIndex());
        helper.remove(index);
        if (selected) {
            if (helper.isEmpty()) {
                helper.select(-1);
            }
            else {
                helper.select(0);
            }
        }
        /*
         * Fix for 6248016
         * After removing the item of the choice we need to reshape unfurled choice
         * in order to keep actual bounds of the choice
         */

        /*
         * condition added only for performance
         */
        if (!unfurled) {
            // Fix 6292186: PIT: Choice is not refreshed properly when the last item gets removed, XToolkit
            // We should take into account that there is no 'select' invoking (hence 'repaint')
            // if the choice is empty (see Choice.java method removeNoInvalidate())
            // The condition isn't 'visibled' since it would be cause of the twice repainting
            if (helper.isEmpty()) {
                repaint();
            }
            return;
        }

        /*
         * condition added only for performance
         * the count of the visible items changed
         */
        if (visibled){
            Rectangle r = unfurledChoice.placeOnScreen();
            unfurledChoice.reshape(r.x, r.y, r.width, r.height);
            return;
        }

        /*
         * condition added only for performance
         * the structure of visible items changed
         * if removable item is non visible and non selected then there is no repaint
         */
        if (visibled || selected){
            repaint();
        }
    }

    public void removeAll() {
        helper.removeAll();
        helper.select(-1);
        /*
         * Fix for 6248016
         * After removing the item of the choice we need to reshape unfurled choice
         * in order to keep actual bounds of the choice
         */
        Rectangle r = unfurledChoice.placeOnScreen();
        unfurledChoice.reshape(r.x, r.y, r.width, r.height);
        repaint();
    }

    /**
     * DEPRECATED: Replaced by add(String, int).
     */
    public void addItem(String item, int index) {
        add(item, index);
    }

    public void setFont(Font font) {
        super.setFont(font);
        helper.setFont(this.font);
    }

    public void setForeground(Color c) {
        super.setForeground(c);
        helper.updateColors(getGUIcolors());
    }

    public void setBackground(Color c) {
        super.setBackground(c);
        unfurledChoice.setBackground(c);
        helper.updateColors(getGUIcolors());
        updateMotifColors(c);
    }

    public void setDrawSelectedItem(boolean value) {
        drawSelectedItem = value;
    }

    public void setAlignUnder(Component comp) {
        alignUnder = comp;
    }

    // see 6240074 for more information
    public void addXChoicePeerListener(XChoicePeerListener l){
        choiceListener = l;
    }

    // see 6240074 for more information
    public void removeXChoicePeerListener(){
        choiceListener = null;
    }

    public boolean isUnfurled(){
        return unfurled;
    }

    /* fix for 6261352. We should detect if current parent Window (containing a Choice) become iconified and hide pop-down menu with grab release.
     * In this case we should hide pop-down menu.
     */
    //calls from XWindowPeer. Could accept X-styled state events
    public void stateChangedICCCM(int oldState, int newState) {
        if (unfurled && oldState != newState){
                hidePopdownMenu();
        }
    }

    //calls from XFramePeer. Could accept Frame's states.
    public void stateChangedJava(int oldState, int newState) {
        if (unfurled && oldState != newState){
            hidePopdownMenu();
        }
    }

    @Override
    protected void initGraphicsConfiguration() {
        super.initGraphicsConfiguration();
        // The popup have the same graphic config, so update it at the same time
        if (unfurledChoice != null) {
            unfurledChoice.initGraphicsConfiguration();
            unfurledChoice.doValidateSurface();
        }
    }

    /**************************************************************************/
    /* Common functionality between List & Choice
       /**************************************************************************/

    /**
     * Inner class for the unfurled Choice list
     * Much, much more docs
     */
    final class UnfurledChoice extends XWindow /*implements XScrollbarClient*/ {

        // First try - use Choice as the target

        public UnfurledChoice(Component target) {
            super(target);
        }

        // Override so we can do our own create()
        public void preInit(XCreateWindowParams params) {
            // A parent of this window is the target, at this point: wrong.
            // Remove parent window; in the following preInit() call we'll calculate as a default
            // a correct root window which is the proper parent for override redirect.
            params.delete(PARENT_WINDOW);
            super.preInit(params);
            // Reset bounds(we'll set them later), set overrideRedirect
            params.remove(BOUNDS);
            params.add(OVERRIDE_REDIRECT, Boolean.TRUE);
        }

        // Generally, bounds should be:
        //  x = target.x
        //  y = target.y + target.height
        //  w = Max(target.width, getLongestItemWidth) + possible vertScrollbar
        //  h = Min(MAX_UNFURLED_ITEMS, target.getItemCount()) * itemHeight
        Rectangle placeOnScreen() {
            int numItemsDisplayed;
            // Motif paints an empty Choice the same size as a single item
            if (helper.isEmpty()) {
                numItemsDisplayed = 1;
            }
            else {
                int numItems = helper.getItemCount();
                numItemsDisplayed = Math.min(MAX_UNFURLED_ITEMS, numItems);
            }
            Point global = XChoicePeer.this.toGlobal(0,0);
            Rectangle screenBounds = graphicsConfig.getBounds();

            if (alignUnder != null) {
                Rectangle choiceRec = XChoicePeer.this.getBounds();
                choiceRec.setLocation(0, 0);
                choiceRec = XChoicePeer.this.toGlobal(choiceRec);
                Rectangle alignUnderRec = new Rectangle(alignUnder.getLocationOnScreen(), alignUnder.getSize()); // TODO: Security?
                Rectangle result = choiceRec.union(alignUnderRec);
                // we've got the left and width, calculate top and height
                width = result.width;
                x = result.x;
                y = result.y + result.height;
                height = 2*BORDER_WIDTH +
                    numItemsDisplayed*(helper.getItemHeight()+2*ITEM_MARGIN);
            } else {
                x = global.x;
                y = global.y + XChoicePeer.this.height;
                width = Math.max(XChoicePeer.this.width,
                                 helper.getMaxItemWidth() + 2 * (BORDER_WIDTH + ITEM_MARGIN + TEXT_SPACE) + (helper.isVSBVisible() ? SCROLLBAR_WIDTH : 0));
                height = 2*BORDER_WIDTH +
                    numItemsDisplayed*(helper.getItemHeight()+2*ITEM_MARGIN);
            }
            // Don't run off the edge of the screenBounds
            if (x < screenBounds.x) {
                x = screenBounds.x;
            }
            else if (x + width > screenBounds.x + screenBounds.width) {
                x = screenBounds.x + screenBounds.width - width;
            }

            if (y + height > screenBounds.y + screenBounds.height) {
                y = global.y - height;
            }
            if (y < screenBounds.y) {
                y = screenBounds.y;
            }
            return new Rectangle(x, y, width, height);
        }

        public void toFront() {
            // see 6240074 for more information
            if (choiceListener != null)
                choiceListener.unfurledChoiceOpening(helper);

            Rectangle r = placeOnScreen();
            reshape(r.x, r.y, r.width, r.height);
            super.toFront();
            setVisible(true);
        }

        /*
         * Track a MouseEvent (either a drag or a press) and paint a new
         * selected item, if necessary.
         */
        // FIXME: first unfurl after move is not at edge of the screen  onto second monitor doesn't
        // track mouse correctly.  Problem is w/ UnfurledChoice coords
        public void trackMouse(MouseEvent e) {
            // Event coords are relative to the button, so translate a bit
            Point local = toLocalCoords(e);

            // If x,y is over unfurled Choice,
            // highlight item under cursor

            switch (e.getID()) {
              case MouseEvent.MOUSE_PRESSED:
                  // FIXME: If the Choice is unfurled and the mouse is pressed
                  // outside of the Choice, the mouse should ungrab on the
                  // the press, not the release
                  if (helper.isInVertSB(getBounds(), local.x, local.y)) {
                      mouseInSB = true;
                      helper.handleVSBEvent(e, getBounds(), local.x, local.y);
                  }
                  else {
                      trackSelection(local.x, local.y);
                  }
                  break;
              case MouseEvent.MOUSE_RELEASED:
                  if (mouseInSB) {
                      mouseInSB = false;
                      helper.handleVSBEvent(e, getBounds(), local.x, local.y);
                  }else{
                      // See 6243382 for more information
                      helper.trackMouseReleasedScroll();
                  }
                  /*
                    else {
                    trackSelection(local.x, local.y);
                    }
                  */
                  break;
              case MouseEvent.MOUSE_DRAGGED:
                  if (mouseInSB) {
                      helper.handleVSBEvent(e, getBounds(), local.x, local.y);
                  }
                  else {
                      // See 6243382 for more information
                      helper.trackMouseDraggedScroll(local.x, local.y, width, height);
                      trackSelection(local.x, local.y);
                  }
                  break;
            }
        }

        private void trackSelection(int transX, int transY) {
            if (!helper.isEmpty()) {
                if (transX > 0 && transX < width &&
                    transY > 0 && transY < height) {
                    int newIdx = helper.y2index(transY);
                    if (log.isLoggable(PlatformLogger.Level.FINE)) {
                        log.fine("transX=" + transX + ", transY=" + transY
                                 + ",width=" + width + ", height=" + height
                                 + ", newIdx=" + newIdx + " on " + target);
                    }
                    if ((newIdx >=0) && (newIdx < helper.getItemCount())
                        && (newIdx != helper.getSelectedIndex()))
                    {
                        helper.select(newIdx);
                        unfurledChoice.repaint();
                    }
                }
            }
            // FIXME: If dragged off top or bottom, scroll if there's a vsb
            // (ICK - we'll need a timer or our own event or something)
        }

        /*
         * fillRect with current Background color on the whole dropdown list.
         */
        public void paintBackground() {
            final Graphics g = getGraphics();
            if (g != null) {
                try {
                    g.setColor(getPeerBackground());
                    g.fillRect(0, 0, width, height);
                } finally {
                    g.dispose();
                }
            }
        }
        /*
         * 6405689. In some cases we should erase background to eliminate painting
         * artefacts.
         */
        @Override
        public void repaint() {
            if (!isVisible()) {
                return;
            }
            if (helper.checkVsbVisibilityChangedAndReset()){
                paintBackground();
            }
            super.repaint();
        }
        @Override
        public void paintPeer(Graphics g) {
            //System.out.println("UC.paint()");
            Choice choice = (Choice)target;
            Color colors[] = XChoicePeer.this.getGUIcolors();
            draw3DRect(g, getSystemColors(), 0, 0, width - 1, height - 1, true);
            draw3DRect(g, getSystemColors(), 1, 1, width - 3, height - 3, true);

            helper.paintAllItems(g,
                                 colors,
                                 getBounds());
        }

        public void setVisible(boolean vis) {
            xSetVisible(vis);

            if (!vis && alignUnder != null) {
                alignUnder.requestFocusInWindow();
            }
        }

        /**
         * Return a MouseEvent's Point in coordinates relative to the
         * UnfurledChoice.
         */
        private Point toLocalCoords(MouseEvent e) {
            // Event coords are relative to the button, so translate a bit
            Point global = e.getLocationOnScreen();

            global.x -= x;
            global.y -= y;
            return global;
        }

        /* Returns true if the MouseEvent coords (which are based on the Choice)
         * are inside of the UnfurledChoice.
         */
        private boolean isMouseEventInside(MouseEvent e) {
            Point local = toLocalCoords(e);
            if (local.x > 0 && local.x < width &&
                local.y > 0 && local.y < height) {
                return true;
            }
            return false;
        }

        /**
         * Tests if the mouse cursor is in the Unfurled Choice, yet not
         * in the vertical scrollbar
         */
        private boolean isMouseInListArea(MouseEvent e) {
            if (isMouseEventInside(e)) {
                Point local = toLocalCoords(e);
                Rectangle bounds = getBounds();
                if (!helper.isInVertSB(bounds, local.x, local.y)) {
                    return true;
                }
            }
            return false;
        }

        /*
         * Overridden from XWindow() because we don't want to send
         * ComponentEvents
         */
        public void handleConfigureNotifyEvent(XEvent xev) {}
        public void handleMapNotifyEvent(XEvent xev) {}
        public void handleUnmapNotifyEvent(XEvent xev) {}
    } //UnfurledChoice

    public void dispose() {
        if (unfurledChoice != null) {
            unfurledChoice.destroy();
        }
        super.dispose();
    }

    /*
     * fix for 6239938 : Choice drop-down does not disappear when it loses
     * focus, on XToolkit
     * We are able to handle all _Key_ events received by Choice when
     * it is in opened state without sending it to EventQueue.
     * If Choice is in closed state we should behave like before: send
     * all events to EventQueue.
     * To be compatible with Motif we should handle all KeyEvents in
     * Choice if it is opened. KeyEvents should be sent into Java if Choice is not opened.
     */
    boolean prePostEvent(final AWTEvent e) {
        if (unfurled){
            // fix for 6253211: PIT: MouseWheel events not triggered for Choice drop down in XAWT
            if (e instanceof MouseWheelEvent){
                return super.prePostEvent(e);
            }
            //fix 6252982: PIT: Keyboard FocusTraversal not working when choice's drop-down is visible, on XToolkit
            if (e instanceof KeyEvent){
                // notify XWindow that this event had been already handled and no need to post it again
                InvocationEvent ev = new InvocationEvent(target, new Runnable() {
                    public void run() {
                        if(target.isFocusable() &&
                                getParentTopLevel().isFocusableWindow() )
                        {
                            handleJavaKeyEvent((KeyEvent)e);
                        }
                    }
                });
                postEvent(ev);

                return true;
            } else {
                if (e instanceof MouseEvent){
                    // Fix for 6240046 : REG:Choice's Drop-down does not disappear when clicking somewhere, after popup menu is disposed
                    // if user presses Right Mouse Button on opened (unfurled)
                    // Choice then we mustn't open a popup menu. We could filter
                    // Mouse Events and handle them in XChoicePeer if Choice
                    // currently in opened state.
                    MouseEvent me = (MouseEvent)e;
                    int eventId = e.getID();
                    // fix 6251983: PIT: MouseDragged events not triggered
                    // fix 6251988: PIT: Choice consumes MouseReleased, MouseClicked events when clicking it with left button,
                    if ((unfurledChoice.isMouseEventInside(me) ||
                         (!firstPress && eventId == MouseEvent.MOUSE_DRAGGED)))
                    {
                        return handleMouseEventByChoice(me);
                    }
                    // MouseMoved events should be fired in Choice's comp if it's not opened
                    // Shouldn't generate Moved Events. CR : 6251995
                    if (eventId == MouseEvent.MOUSE_MOVED){
                        return handleMouseEventByChoice(me);
                    }
                    //fix for 6272965: PIT: Choice triggers MousePressed when pressing mouse outside comp while drop-down is active, XTkt
                    if (  !firstPress && !( isMouseEventInChoice(me) ||
                             unfurledChoice.isMouseEventInside(me)) &&
                             ( eventId == MouseEvent.MOUSE_PRESSED ||
                               eventId == MouseEvent.MOUSE_RELEASED ||
                               eventId == MouseEvent.MOUSE_CLICKED )
                          )
                    {
                        return handleMouseEventByChoice(me);
                    }
                }
            }//else KeyEvent
        }//if unfurled
        return super.prePostEvent(e);
    }

    //convenient method
    //do not generate this kind of Events
    public boolean handleMouseEventByChoice(final MouseEvent me){
        InvocationEvent ev = new InvocationEvent(target, new Runnable() {
            public void run() {
                handleJavaMouseEvent(me);
            }
        });
        postEvent(ev);

        return true;
    }

    /* Returns true if the MouseEvent coords
     * are inside of the Choice itself (it doesnt's depends on
     * if this choice opened or not).
     */
    private boolean isMouseEventInChoice(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        Rectangle choiceRect = getBounds();

        if (x < 0 || x > choiceRect.width ||
            y < 0 || y > choiceRect.height)
        {
            return false;
        }
        return true;
    }
}
