/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
// 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: 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.
// items to be displayed
// at a time in an
// unfurled Choice
// Description of these constants in ListHelper
// SHARE THESE!
// Stolen from Tiny
// 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.
// 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
// dragged over the (unfurled)
// Choice
// scrollbar
// furled Choice so we
// not need to furl the
// Choice when MOUSE_RELEASED occured
// 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;
// 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.
// If cursor is outside of an unfurled Choice when the mouse is
// released, Choice item should NOT be updated. Remember the proper index.
// Holds the listener (XFileDialogPeer) which the processing events from the choice
// See 6240074 for more information
super(target);
}
getGUIcolors(),
false,
true,
false,
}
// Add all items
for (int i = 0; i < numItems; i++) {
}
}
}
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
int oldX = this.x;
int oldY = this.y;
if (unfurled && (oldX != this.x || oldY != this.y || oldWidth != this.width || oldHeight != this.height) ) {
}
}
// 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
*/
super.setEnabled(value);
}
}
// 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();
}
keyPressed(e);
}
}
switch(e.getKeyCode()) {
// UP & DOWN are same if furled or unfurled
case KeyEvent.VK_KP_DOWN: {
repaint();
}
break;
}
repaint();
}
break;
}
case KeyEvent.VK_PAGE_DOWN:
repaint();
}
}
break;
case KeyEvent.VK_PAGE_UP:
repaint();
}
}
break;
if (unfurled) {
if (dragging){
//This also happens on
// - MouseButton2,3, etc. press
// - ENTER press
} else { //KeyEvent.VK_ENTER:
}
}
dragging = false;
wasDragged = false;
mouseInSB = false;
// See 6240074 for more information
if (choiceListener != null){
}
}
break;
default:
if (unfurled) {
}
break;
}
}
public boolean handlesWheelScrolling() { return true; }
repaint();
}
}
}
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;
}
}
/*
* 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 (unfurled) {
//fix 6259328: PIT: Choice scrolls when dragging the parent frame while drop-down is active, XToolkit
if (! (isMouseEventInChoice(e) ||
{
}
// Press on unfurled Choice. Highlight the item under the cursor,
// but don't send item event or set the text on the button yet
}
else {
// Choice is up - unfurl it
grabInput();
firstPress = true;
wasDragged = false;
unfurled = true;
}
}
}
/*
* helper method for mouseReleased routine
*/
void hidePopdownMenu(){
ungrabInput();
unfurledChoice.setVisible(false);
unfurled = false;
}
if (unfurled) {
if (mouseInSB) {
}
else {
// We pressed and dragged onto the Choice, or, this is the
// second release after clicking to make the Choice "stick"
// unfurled.
// 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
// 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
// Set the selected item back how it was.
}
// Choice must be closed if user releases mouse on
// pop-down menu on the second click
if ( !firstPress && isMouseInListArea) {
}
// Choice must be closed if user releases mouse
// outside of Choice's pop-down menu on the second click
if ( !firstPress && !isMouseEventInside) {
}
//if user drags Mouse on pop-down menu, Scrollbar or
// outside the Choice
if ( firstPress && dragging) {
}
/* 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 &&
{
}
// Only update the Choice if the mouse button is released
// over the list of items.
if (unfurledChoice.isMouseInListArea(e)) {
if (newIdx >= 0) {
// Update the selected item in the target now that
// the mouse selection is complete.
if (newIdx != dragStartIdx) {
// NOTE: We get a repaint when Choice.select()
// calls our peer.select().
}
}
/*fix for 6239941 : Choice triggers ItemEvent when selecting an item with right mouse button, Xtoolkit
* We should generate ItemEvent if only
* LeftMouseButton used */
(!firstPress || wasDragged ))
{
}
// see 6240074 for more information
if (choiceListener != null) {
}
}
}
}
// See 6243382 for more information
}
}
dragging = false;
wasDragged = false;
firstPress = false;
dragStartIdx = -1;
}
/*
* 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.
*/
dragging = true;
wasDragged = true;
}
}
// Stolen from TinyChoicePeer
// TODO: move this impl into ListHelper?
int w = 0;
for (int i = c.countItems() ; i-- > 0 ;) {
}
}
/*
* 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
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
*/
flush();
// TODO: when mouse is down over button, widget should be drawn depressed
g.setColor(getPeerBackground());
g.setFont(getPeerFont());
if (isEnabled()) {
g.setColor(getPeerForeground());
}
else {
}
}
}
if (hasFocus()) {
paintFocus(g,focusInsets.left,focusInsets.top,size.width-(focusInsets.left+focusInsets.right)-1,size.height-(focusInsets.top+focusInsets.bottom)-1);
}
if (unfurled) {
}
flush();
}
int x, int y, int w, int h) {
g.setColor(focusColor);
g.drawRect(x,y,w,h);
}
/*
* ChoicePeer methods stolen from TinyChoicePeer
*/
repaint();
}
repaint();
}
if (selected) {
}
else {
}
}
/*
* 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
repaint();
}
return;
}
/*
* condition added only for performance
* the count of the visible items changed
*/
if (visibled){
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
*/
repaint();
}
}
public void removeAll() {
/*
* 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
*/
repaint();
}
/**
* DEPRECATED: Replaced by add(String, int).
*/
}
}
super.setForeground(c);
}
super.setBackground(c);
}
}
alignUnder = comp;
}
// see 6240074 for more information
choiceListener = l;
}
// see 6240074 for more information
public void removeXChoicePeerListener(){
}
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
}
}
//calls from XFramePeer. Could accept Frame's states.
}
}
/**************************************************************************/
/* Common functionality between List & Choice
/**************************************************************************/
/**
* Inner class for the unfurled Choice list
* Much, much more docs
*/
// First try - use Choice as the target
super(target);
}
// Override so we can do our own create()
// 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.
// Reset bounds(we'll set them later), set overrideRedirect
}
// 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
int numItemsDisplayed;
// Motif paints an empty Choice the same size as a single item
numItemsDisplayed = 1;
}
else {
}
if (alignUnder != null) {
Rectangle alignUnderRec = new Rectangle(alignUnder.getLocationOnScreen(), alignUnder.getSize()); // TODO: Security?
// we've got the left and width, calculate top and height
x = result.x;
} else {
x = global.x;
helper.getMaxItemWidth() + 2 * (BORDER_WIDTH + ITEM_MARGIN + TEXT_SPACE) + (helper.isVSBVisible() ? SCROLLBAR_WIDTH : 0));
}
// Don't run off the edge of the screen
if (x < 0) {
x = 0;
}
}
if (y < 0) {
y = 0;
}
}
}
public void toFront() {
// see 6240074 for more information
if (choiceListener != null)
Rectangle r = placeOnScreen();
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
// Event coords are relative to the button, so translate a bit
// 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
mouseInSB = true;
}
else {
}
break;
case MouseEvent.MOUSE_RELEASED:
if (mouseInSB) {
mouseInSB = false;
}else{
// See 6243382 for more information
}
/*
else {
trackSelection(local.x, local.y);
}
*/
break;
case MouseEvent.MOUSE_DRAGGED:
if (mouseInSB) {
}
else {
// See 6243382 for more information
}
break;
}
}
}
{
}
}
}
// 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(){
Graphics g = getGraphics();
g.setColor(getPeerBackground());
}
/*
* 6405689. In some cases we should erase background to eliminate painting
* artefacts.
*/
public void repaint() {
if (!isVisible()) {
return;
}
}
super.repaint();
}
//System.out.println("UC.paint()");
getBounds());
}
}
}
/**
* Return a MouseEvent's Point in coordinates relative to the
* UnfurledChoice.
*/
// Event coords are relative to the button, so translate a bit
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.
*/
return true;
}
return false;
}
/**
* Tests if the mouse cursor is in the Unfurled Choice, yet not
* in the vertical scrollbar
*/
if (isMouseEventInside(e)) {
return true;
}
}
return false;
}
/*
* Overridden from XWindow() because we don't want to send
* ComponentEvents
*/
} //UnfurledChoice
public void dispose() {
if (unfurledChoice != null) {
}
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.
*/
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
public void run() {
if(target.isFocusable() &&
{
}
}
});
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.
// fix 6251983: PIT: MouseDragged events not triggered
// fix 6251988: PIT: Choice consumes MouseReleased, MouseClicked events when clicking it with left button,
{
return handleMouseEventByChoice(me);
}
// MouseMoved events should be fired in Choice's comp if it's not opened
// Shouldn't generate Moved Events. CR : 6251995
return handleMouseEventByChoice(me);
}
//fix for 6272965: PIT: Choice triggers MousePressed when pressing mouse outside comp while drop-down is active, XTkt
)
{
return handleMouseEventByChoice(me);
}
}
}//else KeyEvent
}//if unfurled
return super.prePostEvent(e);
}
//convenient method
//do not generate this kind of Events
public void run() {
}
});
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).
*/
int x = e.getX();
int y = e.getY();
{
return false;
}
return true;
}
}
/*
* The listener interface for receiving "interesting" for XFileDialogPeer
* choice events (opening, closing).
* The listener added by means of the method addXChoicePeerListener
* A opening choice event is generated when the invoking unfurledChoice.toFront()
* A closing choice event is generated at the time of the processing the mouse releasing
* and the Enter pressing.
* see 6240074 for more information
*/
interface XChoicePeerListener{
public void unfurledChoiceClosing();
}