Source Code Cross Referenced for XChoicePeer.java in  » 6.0-JDK-Platform » solaris » sun » awt » X11 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Platform » solaris » sun.awt.X11 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package sun.awt.X11;
0027:
0028:        import java.awt.*;
0029:        import java.awt.peer.*;
0030:        import java.awt.event.*;
0031:        import java.util.logging.*;
0032:
0033:        // FIXME: tab traversal should be disabled when mouse is captured (4816336)
0034:
0035:        // FIXME: key and mouse events should not be delivered to listeners when the Choice is unfurled.  Must override handleNativeKey/MouseEvent (4816336)
0036:
0037:        // FIXME: test programmatic add/remove/clear/etc
0038:
0039:        // FIXME: account for unfurling at the edge of the screen
0040:        // Note: can't set x,y on layout(), 'cause moving the top-level to the
0041:        // edge of the screen won't call layout().  Just do it on paint, I guess
0042:
0043:        // TODO: make painting more efficient (i.e. when down arrow is pressed, only two items should need to be repainted.
0044:
0045:        public class XChoicePeer extends XComponentPeer implements  ChoicePeer,
0046:                ToplevelStateListener {
0047:            private static final Logger log = Logger
0048:                    .getLogger("sun.awt.X11.XChoicePeer");
0049:
0050:            private static final int MAX_UNFURLED_ITEMS = 10; // Maximum number of
0051:            // items to be displayed
0052:            // at a time in an
0053:            // unfurled Choice
0054:            // Description of these constants in ListHelper
0055:            public final static int TEXT_SPACE = 1;
0056:            public final static int BORDER_WIDTH = 1;
0057:            public final static int ITEM_MARGIN = 1;
0058:            public final static int SCROLLBAR_WIDTH = 15;
0059:
0060:            // SHARE THESE!
0061:            private static final Insets focusInsets = new Insets(0, 0, 0, 0);
0062:
0063:            static final int WIDGET_OFFSET = 18;
0064:
0065:            // Stolen from Tiny
0066:            static final int TEXT_XPAD = 8;
0067:            static final int TEXT_YPAD = 6;
0068:
0069:            // FIXME: Motif uses a different focus color for the item within
0070:            // the unfurled Choice list and for when the Choice itself is focused and
0071:            // popped up.
0072:            static final Color focusColor = Color.black;
0073:
0074:            // TODO: there is a time value that the mouse is held down.  If short
0075:            // enough,  the Choice stays popped down.  If long enough, Choice 
0076:            // is furled when the mouse is released
0077:
0078:            private boolean unfurled = false; // Choice list is popped down
0079:
0080:            private boolean dragging = false; // Mouse was pressed and is being
0081:            // dragged over the (unfurled)
0082:            // Choice
0083:
0084:            private boolean mouseInSB = false; // Mouse is interacting with the
0085:            // scrollbar
0086:
0087:            private boolean firstPress = false; // mouse was pressed on
0088:            // furled Choice so we
0089:            // not need to furl the
0090:            // Choice when MOUSE_RELEASED occured
0091:
0092:            // 6425067. Mouse was pressed on furled choice and dropdown list appeared over Choice itself
0093:            // and then there were no mouse movements until MOUSE_RELEASE.
0094:            // This scenario leads to ItemStateChanged as the choice logic uses 
0095:            // MouseReleased event to send ItemStateChanged. To prevent it we should 
0096:            // use a combination of firstPress and wasDragged variables.
0097:            // The only difference in dragging and wasDragged is: last one will not 
0098:            // set to false on mouse ungrab. It become false after MouseRelased() finishes.
0099:            private boolean wasDragged = false;
0100:            private ListHelper helper;
0101:            private UnfurledChoice unfurledChoice;
0102:
0103:            // TODO: Choice remembers where it was scrolled to when unfurled - it's not 
0104:            // always to the currently selected item.
0105:
0106:            // Indicates whether or not to paint selected item in the choice.
0107:            // Default is to paint
0108:            private boolean drawSelectedItem = true;
0109:
0110:            // If set, indicates components under which choice popup should be showed.
0111:            // The choice's popup width and location should be adjust to appear
0112:            // under both choice and alignUnder component.
0113:            private Component alignUnder;
0114:
0115:            // If cursor is outside of an unfurled Choice when the mouse is
0116:            // released, Choice item should NOT be updated.  Remember the proper index.
0117:            private int dragStartIdx = -1;
0118:
0119:            // Holds the listener (XFileDialogPeer) which the processing events from the choice
0120:            // See 6240074 for more information
0121:            private XChoicePeerListener choiceListener;
0122:
0123:            XChoicePeer(Choice target) {
0124:                super (target);
0125:            }
0126:
0127:            void preInit(XCreateWindowParams params) {
0128:                super .preInit(params);
0129:                Choice target = (Choice) this .target;
0130:                int numItems = target.getItemCount();
0131:                unfurledChoice = new UnfurledChoice(target);
0132:                getToplevelXWindow().addToplevelStateListener(this );
0133:                helper = new ListHelper(unfurledChoice, getGUIcolors(),
0134:                        numItems, false, true, false, target.getFont(),
0135:                        MAX_UNFURLED_ITEMS, TEXT_SPACE, ITEM_MARGIN,
0136:                        BORDER_WIDTH, SCROLLBAR_WIDTH);
0137:            }
0138:
0139:            void postInit(XCreateWindowParams params) {
0140:                super .postInit(params);
0141:                Choice target = (Choice) this .target;
0142:                int numItems = target.getItemCount();
0143:
0144:                // Add all items
0145:                for (int i = 0; i < numItems; i++) {
0146:                    helper.add(target.getItem(i));
0147:                }
0148:                if (!helper.isEmpty()) {
0149:                    helper.select(target.getSelectedIndex());
0150:                    helper.setFocusedIndex(target.getSelectedIndex());
0151:                }
0152:                helper.updateColors(getGUIcolors());
0153:                updateMotifColors(getPeerBackground());
0154:            }
0155:
0156:            public boolean isFocusable() {
0157:                return true;
0158:            }
0159:
0160:            // 6399679. check if super.setBounds() actually changes the size of the 
0161:            // component and then compare current Choice size with a new one. If
0162:            // they differs then hide dropdown menu
0163:            public void setBounds(int x, int y, int width, int height, int op) {
0164:                int oldX = this .x;
0165:                int oldY = this .y;
0166:                int oldWidth = this .width;
0167:                int oldHeight = this .height;
0168:                super .setBounds(x, y, width, height, op);
0169:                if (unfurled
0170:                        && (oldX != this .x || oldY != this .y
0171:                                || oldWidth != this .width || oldHeight != this .height)) {
0172:                    hidePopdownMenu();
0173:                }
0174:            }
0175:
0176:            public void focusGained(FocusEvent e) {
0177:                // TODO: only need to paint the focus bit
0178:                super .focusGained(e);
0179:                repaint();
0180:            }
0181:
0182:            /*
0183:             * Fix for 6246503 : Disabling a choice after selection locks keyboard, mouse and makes the system unusable, Xtoolkit 
0184:             * if setEnabled(false) invoked we should close opened choice in
0185:             * order to prevent keyboard/mouse lock.
0186:             */
0187:            public void setEnabled(boolean value) {
0188:                super .setEnabled(value);
0189:                helper.updateColors(getGUIcolors());
0190:                if (!value && unfurled) {
0191:                    hidePopdownMenu();
0192:                }
0193:            }
0194:
0195:            public void focusLost(FocusEvent e) {
0196:                // TODO: only need to paint the focus bit?
0197:                super .focusLost(e);
0198:                repaint();
0199:            }
0200:
0201:            void ungrabInputImpl() {
0202:                if (unfurled) {
0203:                    unfurled = false;
0204:                    dragging = false;
0205:                    mouseInSB = false;
0206:                    unfurledChoice.setVisible(false);
0207:                }
0208:
0209:                super .ungrabInputImpl();
0210:            }
0211:
0212:            void handleJavaKeyEvent(KeyEvent e) {
0213:                if (e.getID() == KeyEvent.KEY_PRESSED) {
0214:                    keyPressed(e);
0215:                }
0216:            }
0217:
0218:            public void keyPressed(KeyEvent e) {
0219:                switch (e.getKeyCode()) {
0220:                // UP & DOWN are same if furled or unfurled
0221:                case KeyEvent.VK_DOWN:
0222:                case KeyEvent.VK_KP_DOWN: {
0223:                    if (helper.getItemCount() > 1) {
0224:                        helper.down();
0225:                        int newIdx = helper.getSelectedIndex();
0226:
0227:                        ((Choice) target).select(newIdx);
0228:                        postEvent(new ItemEvent((Choice) target,
0229:                                ItemEvent.ITEM_STATE_CHANGED, ((Choice) target)
0230:                                        .getItem(newIdx), ItemEvent.SELECTED));
0231:                        repaint();
0232:                    }
0233:                    break;
0234:                }
0235:                case KeyEvent.VK_UP:
0236:                case KeyEvent.VK_KP_UP: {
0237:                    if (helper.getItemCount() > 1) {
0238:                        helper.up();
0239:                        int newIdx = helper.getSelectedIndex();
0240:
0241:                        ((Choice) target).select(newIdx);
0242:                        postEvent(new ItemEvent((Choice) target,
0243:                                ItemEvent.ITEM_STATE_CHANGED, ((Choice) target)
0244:                                        .getItem(newIdx), ItemEvent.SELECTED));
0245:                        repaint();
0246:                    }
0247:                    break;
0248:                }
0249:                case KeyEvent.VK_PAGE_DOWN:
0250:                    if (unfurled && !dragging) {
0251:                        int oldIdx = helper.getSelectedIndex();
0252:                        helper.pageDown();
0253:                        int newIdx = helper.getSelectedIndex();
0254:                        if (oldIdx != newIdx) {
0255:                            ((Choice) target).select(newIdx);
0256:                            postEvent(new ItemEvent((Choice) target,
0257:                                    ItemEvent.ITEM_STATE_CHANGED,
0258:                                    ((Choice) target).getItem(newIdx),
0259:                                    ItemEvent.SELECTED));
0260:                            repaint();
0261:                        }
0262:                    }
0263:                    break;
0264:                case KeyEvent.VK_PAGE_UP:
0265:                    if (unfurled && !dragging) {
0266:                        int oldIdx = helper.getSelectedIndex();
0267:                        helper.pageUp();
0268:                        int newIdx = helper.getSelectedIndex();
0269:                        if (oldIdx != newIdx) {
0270:                            ((Choice) target).select(newIdx);
0271:                            postEvent(new ItemEvent((Choice) target,
0272:                                    ItemEvent.ITEM_STATE_CHANGED,
0273:                                    ((Choice) target).getItem(newIdx),
0274:                                    ItemEvent.SELECTED));
0275:                            repaint();
0276:                        }
0277:                    }
0278:                    break;
0279:                case KeyEvent.VK_ESCAPE:
0280:                case KeyEvent.VK_ENTER:
0281:                    if (unfurled) {
0282:                        if (dragging) {
0283:                            if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
0284:                                //This also happens on 
0285:                                // - MouseButton2,3, etc. press
0286:                                // - ENTER press 
0287:                                helper.select(dragStartIdx);
0288:                            } else { //KeyEvent.VK_ENTER:
0289:                                int newIdx = helper.getSelectedIndex();
0290:                                ((Choice) target).select(newIdx);
0291:                                postEvent(new ItemEvent((Choice) target,
0292:                                        ItemEvent.ITEM_STATE_CHANGED,
0293:                                        ((Choice) target).getItem(newIdx),
0294:                                        ItemEvent.SELECTED));
0295:                            }
0296:                        }
0297:                        hidePopdownMenu();
0298:                        dragging = false;
0299:                        wasDragged = false;
0300:                        mouseInSB = false;
0301:
0302:                        // See 6240074 for more information
0303:                        if (choiceListener != null) {
0304:                            choiceListener.unfurledChoiceClosing();
0305:                        }
0306:                    }
0307:                    break;
0308:                default:
0309:                    if (unfurled) {
0310:                        Toolkit.getDefaultToolkit().beep();
0311:                    }
0312:                    break;
0313:                }
0314:            }
0315:
0316:            public boolean handlesWheelScrolling() {
0317:                return true;
0318:            }
0319:
0320:            void handleJavaMouseWheelEvent(MouseWheelEvent e) {
0321:                if (unfurled && helper.isVSBVisible()) {
0322:                    if (ListHelper.doWheelScroll(helper.getVSB(), null, e)) {
0323:                        repaint();
0324:                    }
0325:                }
0326:            }
0327:
0328:            void handleJavaMouseEvent(MouseEvent e) {
0329:                super .handleJavaMouseEvent(e);
0330:                int i = e.getID();
0331:                switch (i) {
0332:                case MouseEvent.MOUSE_PRESSED:
0333:                    mousePressed(e);
0334:                    break;
0335:                case MouseEvent.MOUSE_RELEASED:
0336:                    mouseReleased(e);
0337:                    break;
0338:                case MouseEvent.MOUSE_DRAGGED:
0339:                    mouseDragged(e);
0340:                    break;
0341:                }
0342:            }
0343:
0344:            public void mousePressed(MouseEvent e) {
0345:                /*
0346:                 * fix for 5003166: a Choice on XAWT shouldn't react to any
0347:                 * mouse button presses except left. This involves presses on
0348:                 * Choice but not on opened part of choice.
0349:                 */
0350:                if (e.getButton() == MouseEvent.BUTTON1) {
0351:                    dragStartIdx = helper.getSelectedIndex();
0352:                    if (unfurled) {
0353:                        //fix 6259328: PIT: Choice scrolls when dragging the parent frame while drop-down is active, XToolkit
0354:                        if (!(isMouseEventInChoice(e) || unfurledChoice
0355:                                .isMouseEventInside(e))) {
0356:                            hidePopdownMenu();
0357:                        }
0358:                        // Press on unfurled Choice.  Highlight the item under the cursor,
0359:                        // but don't send item event or set the text on the button yet
0360:                        unfurledChoice.trackMouse(e);
0361:                    } else {
0362:                        // Choice is up - unfurl it
0363:                        grabInput();
0364:                        unfurledChoice.toFront();
0365:                        firstPress = true;
0366:                        wasDragged = false;
0367:                        unfurled = true;
0368:                    }
0369:                }
0370:            }
0371:
0372:            /* 
0373:             * helper method for mouseReleased routine
0374:             */
0375:            void hidePopdownMenu() {
0376:                ungrabInput();
0377:                unfurledChoice.setVisible(false);
0378:                unfurled = false;
0379:            }
0380:
0381:            public void mouseReleased(MouseEvent e) {
0382:                if (unfurled) {
0383:                    if (mouseInSB) {
0384:                        unfurledChoice.trackMouse(e);
0385:                    } else {
0386:                        // We pressed and dragged onto the Choice, or, this is the
0387:                        // second release after clicking to make the Choice "stick"
0388:                        // unfurled.
0389:                        // This release should ungrab/furl, and set the new item if
0390:                        // release was over the unfurled Choice.
0391:
0392:                        // Fix for 6239944 : Choice shouldn't close its
0393:                        // pop-down menu if user presses Mouse on Choice's Scrollbar
0394:                        // some additional cases like releasing mouse outside
0395:                        // of Choice are considered too
0396:                        boolean isMouseEventInside = unfurledChoice
0397:                                .isMouseEventInside(e);
0398:                        boolean isMouseInListArea = unfurledChoice
0399:                                .isMouseInListArea(e);
0400:
0401:                        // Fixed 6318746: REG: File Selection is failing
0402:                        // We shouldn't restore the selected item
0403:                        // if the mouse was dragged outside the drop-down choice area
0404:                        if (!helper.isEmpty() && !isMouseInListArea && dragging) {
0405:                            // Set the selected item back how it was.
0406:                            ((Choice) target).select(dragStartIdx);
0407:                        }
0408:
0409:                        // Choice must be closed if user releases mouse on
0410:                        // pop-down menu on the second click
0411:                        if (!firstPress && isMouseInListArea) {
0412:                            hidePopdownMenu();
0413:                        }
0414:                        // Choice must be closed if user releases mouse
0415:                        // outside of Choice's pop-down menu  on the second click
0416:                        if (!firstPress && !isMouseEventInside) {
0417:                            hidePopdownMenu();
0418:                        }
0419:                        //if user drags Mouse on pop-down menu, Scrollbar or
0420:                        // outside the Choice 
0421:                        if (firstPress && dragging) {
0422:                            hidePopdownMenu();
0423:                        }
0424:                        /* this could happen when user has opened a Choice and
0425:                         * released mouse button. Then he drags mouse on the
0426:                         * Scrollbar and releases mouse again.
0427:                         */
0428:                        if (!firstPress && !isMouseInListArea
0429:                                && isMouseEventInside && dragging) {
0430:                            hidePopdownMenu();
0431:                        }
0432:
0433:                        if (!helper.isEmpty()) {
0434:                            // Only update the Choice if the mouse button is released
0435:                            // over the list of items.
0436:                            if (unfurledChoice.isMouseInListArea(e)) {
0437:                                int newIdx = helper.getSelectedIndex();
0438:                                if (newIdx >= 0) {
0439:                                    // Update the selected item in the target now that
0440:                                    // the mouse selection is complete.
0441:                                    if (newIdx != dragStartIdx) {
0442:                                        ((Choice) target).select(newIdx);
0443:                                        // NOTE: We get a repaint when Choice.select()
0444:                                        // calls our peer.select().
0445:                                    }
0446:                                    if (wasDragged
0447:                                            && e.getButton() != MouseEvent.BUTTON1) {
0448:                                        ((Choice) target).select(dragStartIdx);
0449:                                    }
0450:
0451:                                    /*fix for 6239941 : Choice triggers ItemEvent when selecting an item with right mouse button, Xtoolkit
0452:                                     * We should generate ItemEvent if only
0453:                                     * LeftMouseButton used */
0454:                                    if (e.getButton() == MouseEvent.BUTTON1
0455:                                            && (!firstPress || wasDragged)) {
0456:                                        postEvent(new ItemEvent(
0457:                                                (Choice) target,
0458:                                                ItemEvent.ITEM_STATE_CHANGED,
0459:                                                ((Choice) target)
0460:                                                        .getItem(newIdx),
0461:                                                ItemEvent.SELECTED));
0462:                                    }
0463:
0464:                                    // see 6240074 for more information
0465:                                    if (choiceListener != null) {
0466:                                        choiceListener.unfurledChoiceClosing();
0467:                                    }
0468:                                }
0469:                            }
0470:                        }
0471:                        // See 6243382 for more information
0472:                        unfurledChoice.trackMouse(e);
0473:                    }
0474:                }
0475:
0476:                dragging = false;
0477:                wasDragged = false;
0478:                firstPress = false;
0479:                dragStartIdx = -1;
0480:            }
0481:
0482:            public void mouseDragged(MouseEvent e) {
0483:                /*
0484:                 * fix for 5003166. On Motif user are unable to drag
0485:                 * mouse inside opened Choice if he drags the mouse with
0486:                 * different from LEFT mouse button ( e.g. RIGHT or MIDDLE).
0487:                 * This fix make impossible to drag mouse inside opened choice
0488:                 * with other mouse buttons rather then LEFT one.
0489:                 */
0490:                if (e.getModifiers() == MouseEvent.BUTTON1_MASK) {
0491:                    dragging = true;
0492:                    wasDragged = true;
0493:                    unfurledChoice.trackMouse(e);
0494:                }
0495:            }
0496:
0497:            // Stolen from TinyChoicePeer
0498:            public Dimension getMinimumSize() {
0499:                // TODO: move this impl into ListHelper?
0500:                FontMetrics fm = getFontMetrics(target.getFont());
0501:                Choice c = (Choice) target;
0502:                int w = 0;
0503:                for (int i = c.countItems(); i-- > 0;) {
0504:                    w = Math.max(fm.stringWidth(c.getItem(i)), w);
0505:                }
0506:                return new Dimension(w + TEXT_XPAD + WIDGET_OFFSET, fm
0507:                        .getMaxAscent()
0508:                        + fm.getMaxDescent() + TEXT_YPAD);
0509:            }
0510:
0511:            /*
0512:             * Layout the...
0513:             */
0514:            public void layout() {
0515:                /*
0516:                  Dimension size = target.getSize();
0517:                  Font f = target.getFont();
0518:                  FontMetrics fm = target.getFontMetrics(f);
0519:                  String text = ((Choice)target).getLabel();
0520:
0521:                  textRect.height = fm.getHeight();
0522:
0523:                  checkBoxSize = getChoiceSize(fm);
0524:
0525:                  // Note - Motif appears to use an left inset that is slightly
0526:                  // scaled to the checkbox/font size.
0527:                  cbX = borderInsets.left + checkBoxInsetFromText;
0528:                  cbY = size.height / 2 - checkBoxSize / 2;
0529:                  int minTextX = borderInsets.left + 2 * checkBoxInsetFromText + checkBoxSize;
0530:                  // FIXME: will need to account for alignment?
0531:                  // FIXME: call layout() on alignment changes
0532:                  //textRect.width = fm.stringWidth(text);
0533:                  textRect.width = fm.stringWidth(text == null ? "" : text);
0534:                  textRect.x = Math.max(minTextX, size.width / 2 - textRect.width / 2);
0535:                  textRect.y = size.height / 2 - textRect.height / 2 + borderInsets.top;
0536:
0537:                  focusRect.x = focusInsets.left;
0538:                  focusRect.y = focusInsets.top;
0539:                  focusRect.width = size.width-(focusInsets.left+focusInsets.right)-1;
0540:                  focusRect.height = size.height-(focusInsets.top+focusInsets.bottom)-1;
0541:
0542:                  myCheckMark = AffineTransform.getScaleInstance((double)target.getFont().getSize() / MASTER_SIZE, (double)target.getFont().getSize() / MASTER_SIZE).createTransformedShape(MASTER_CHECKMARK);
0543:                 */
0544:
0545:            }
0546:
0547:            /**
0548:             * Paint the choice
0549:             */
0550:            public void paint(Graphics g) {
0551:                flush();
0552:                Dimension size = getPeerSize();
0553:
0554:                // TODO: when mouse is down over button, widget should be drawn depressed
0555:                g.setColor(getPeerBackground());
0556:                g.fillRect(0, 0, width, height);
0557:
0558:                drawMotif3DRect(g, 1, 1, width - 2, height - 2, false);
0559:                drawMotif3DRect(g, width - WIDGET_OFFSET, (height / 2) - 3, 12,
0560:                        6, false);
0561:
0562:                if (!helper.isEmpty() && helper.getSelectedIndex() != -1) {
0563:                    g.setFont(getPeerFont());
0564:                    FontMetrics fm = g.getFontMetrics();
0565:                    String lbl = helper.getItem(helper.getSelectedIndex());
0566:                    if (lbl != null && drawSelectedItem) {
0567:                        g.setClip(1, 1, width - WIDGET_OFFSET - 2, height);
0568:                        if (isEnabled()) {
0569:                            g.setColor(getPeerForeground());
0570:                            g.drawString(lbl, 5,
0571:                                    (height + fm.getMaxAscent() - fm
0572:                                            .getMaxDescent()) / 2);
0573:                        } else {
0574:                            g.setColor(getPeerBackground().brighter());
0575:                            g.drawString(lbl, 5,
0576:                                    (height + fm.getMaxAscent() - fm
0577:                                            .getMaxDescent()) / 2);
0578:                            g.setColor(getPeerBackground().darker());
0579:                            g.drawString(lbl, 4,
0580:                                    ((height + fm.getMaxAscent() - fm
0581:                                            .getMaxDescent()) / 2) - 1);
0582:                        }
0583:                        g.setClip(0, 0, width, height);
0584:                    }
0585:                }
0586:                if (hasFocus()) {
0587:                    paintFocus(g, focusInsets.left, focusInsets.top, size.width
0588:                            - (focusInsets.left + focusInsets.right) - 1,
0589:                            size.height
0590:                                    - (focusInsets.top + focusInsets.bottom)
0591:                                    - 1);
0592:                }
0593:                if (unfurled) {
0594:                    unfurledChoice.repaint();
0595:                }
0596:                flush();
0597:            }
0598:
0599:            protected void paintFocus(Graphics g, int x, int y, int w, int h) {
0600:                g.setColor(focusColor);
0601:                g.drawRect(x, y, w, h);
0602:            }
0603:
0604:            /*
0605:             * ChoicePeer methods stolen from TinyChoicePeer
0606:             */
0607:
0608:            public void select(int index) {
0609:                helper.select(index);
0610:                helper.setFocusedIndex(index);
0611:                repaint();
0612:            }
0613:
0614:            public void add(String item, int index) {
0615:                helper.add(item, index);
0616:                repaint();
0617:            }
0618:
0619:            public void remove(int index) {
0620:                boolean selected = (index == helper.getSelectedIndex());
0621:                boolean visibled = (index >= helper.firstDisplayedIndex() && index <= helper
0622:                        .lastDisplayedIndex());
0623:                helper.remove(index);
0624:                if (selected) {
0625:                    if (helper.isEmpty()) {
0626:                        helper.select(-1);
0627:                    } else {
0628:                        helper.select(0);
0629:                    }
0630:                }
0631:                /*
0632:                 * Fix for 6248016
0633:                 * After removing the item of the choice we need to reshape unfurled choice 
0634:                 * in order to keep actual bounds of the choice
0635:                 */
0636:
0637:                /*
0638:                 * condition added only for performance
0639:                 */
0640:                if (!unfurled) {
0641:                    // Fix 6292186: PIT: Choice is not refreshed properly when the last item gets removed, XToolkit
0642:                    // We should take into account that there is no 'select' invoking (hence 'repaint') 
0643:                    // if the choice is empty (see Choice.java method removeNoInvalidate())
0644:                    // The condition isn't 'visibled' since it would be cause of the twice repainting
0645:                    if (helper.isEmpty()) {
0646:                        repaint();
0647:                    }
0648:                    return;
0649:                }
0650:
0651:                /*
0652:                 * condition added only for performance
0653:                 * the count of the visible items changed
0654:                 */
0655:                if (visibled) {
0656:                    Rectangle r = unfurledChoice.placeOnScreen();
0657:                    unfurledChoice.reshape(r.x, r.y, r.width, r.height);
0658:                    return;
0659:                }
0660:
0661:                /*
0662:                 * condition added only for performance
0663:                 * the structure of visible items changed
0664:                 * if removable item is non visible and non selected then there is no repaint
0665:                 */
0666:                if (visibled || selected) {
0667:                    repaint();
0668:                }
0669:            }
0670:
0671:            public void removeAll() {
0672:                helper.removeAll();
0673:                helper.select(-1);
0674:                /*
0675:                 * Fix for 6248016
0676:                 * After removing the item of the choice we need to reshape unfurled choice 
0677:                 * in order to keep actual bounds of the choice
0678:                 */
0679:                Rectangle r = unfurledChoice.placeOnScreen();
0680:                unfurledChoice.reshape(r.x, r.y, r.width, r.height);
0681:                repaint();
0682:            }
0683:
0684:            /**
0685:             * DEPRECATED: Replaced by add(String, int).
0686:             */
0687:            public void addItem(String item, int index) {
0688:                add(item, index);
0689:            }
0690:
0691:            public void setFont(Font font) {
0692:                super .setFont(font);
0693:                helper.setFont(this .font);
0694:            }
0695:
0696:            public void setForeground(Color c) {
0697:                super .setForeground(c);
0698:                helper.updateColors(getGUIcolors());
0699:            }
0700:
0701:            public void setBackground(Color c) {
0702:                super .setBackground(c);
0703:                unfurledChoice.setBackground(c);
0704:                helper.updateColors(getGUIcolors());
0705:                updateMotifColors(c);
0706:            }
0707:
0708:            public void setDrawSelectedItem(boolean value) {
0709:                drawSelectedItem = value;
0710:            }
0711:
0712:            public void setAlignUnder(Component comp) {
0713:                alignUnder = comp;
0714:            }
0715:
0716:            // see 6240074 for more information
0717:            public void addXChoicePeerListener(XChoicePeerListener l) {
0718:                choiceListener = l;
0719:            }
0720:
0721:            // see 6240074 for more information
0722:            public void removeXChoicePeerListener() {
0723:                choiceListener = null;
0724:            }
0725:
0726:            public boolean isUnfurled() {
0727:                return unfurled;
0728:            }
0729:
0730:            /* fix for 6261352. We should detect if current parent Window (containing a Choice) become iconified and hide pop-down menu with grab release.
0731:             * In this case we should hide pop-down menu.
0732:             */
0733:            //calls from XWindowPeer. Could accept X-styled state events
0734:            public void stateChangedICCCM(int oldState, int newState) {
0735:                if (unfurled && oldState != newState) {
0736:                    hidePopdownMenu();
0737:                }
0738:            }
0739:
0740:            //calls from XFramePeer. Could accept Frame's states.
0741:            public void stateChangedJava(int oldState, int newState) {
0742:                if (unfurled && oldState != newState) {
0743:                    hidePopdownMenu();
0744:                }
0745:            }
0746:
0747:            /**************************************************************************/
0748:            /* Common functionality between List & Choice
0749:               /**************************************************************************/
0750:
0751:            /**
0752:             * Inner class for the unfurled Choice list
0753:             * Much, much more docs
0754:             */
0755:            class UnfurledChoice extends XWindow /*implements XScrollbarClient*/{
0756:
0757:                // First try - use Choice as the target
0758:
0759:                public UnfurledChoice(Component target) {
0760:                    super (target);
0761:                }
0762:
0763:                // Override so we can do our own create()
0764:                public void preInit(XCreateWindowParams params) {
0765:                    // A parent of this window is the target, at this point: wrong.
0766:                    // Remove parent window; in the following preInit() call we'll calculate as a default
0767:                    // a correct root window which is the proper parent for override redirect.
0768:                    params.delete(PARENT_WINDOW);
0769:                    super .preInit(params);
0770:                    // Reset bounds(we'll set them later), set overrideRedirect
0771:                    params.remove(BOUNDS);
0772:                    params.add(OVERRIDE_REDIRECT, Boolean.TRUE);
0773:                }
0774:
0775:                // Generally, bounds should be:
0776:                //  x = target.x
0777:                //  y = target.y + target.height
0778:                //  w = Max(target.width, getLongestItemWidth) + possible vertScrollbar
0779:                //  h = Min(MAX_UNFURLED_ITEMS, target.getItemCount()) * itemHeight
0780:                Rectangle placeOnScreen() {
0781:                    int numItemsDisplayed;
0782:                    // Motif paints an empty Choice the same size as a single item
0783:                    if (helper.isEmpty()) {
0784:                        numItemsDisplayed = 1;
0785:                    } else {
0786:                        int numItems = helper.getItemCount();
0787:                        numItemsDisplayed = Math.min(MAX_UNFURLED_ITEMS,
0788:                                numItems);
0789:                    }
0790:                    Point global = XChoicePeer.this .toGlobal(0, 0);
0791:                    Dimension screen = Toolkit.getDefaultToolkit()
0792:                            .getScreenSize();
0793:
0794:                    if (alignUnder != null) {
0795:                        Rectangle choiceRec = XChoicePeer.this .getBounds();
0796:                        choiceRec.setLocation(0, 0);
0797:                        choiceRec = XChoicePeer.this .toGlobal(choiceRec);
0798:                        Rectangle alignUnderRec = new Rectangle(alignUnder
0799:                                .getLocationOnScreen(), alignUnder.getSize()); // TODO: Security?
0800:                        Rectangle result = choiceRec.union(alignUnderRec);
0801:                        // we've got the left and width, calculate top and height
0802:                        width = result.width;
0803:                        x = result.x;
0804:                        y = result.y + result.height;
0805:                        height = 2 * BORDER_WIDTH + numItemsDisplayed
0806:                                * (helper.getItemHeight() + 2 * ITEM_MARGIN);
0807:                    } else {
0808:                        x = global.x;
0809:                        y = global.y + XChoicePeer.this .height;
0810:                        width = Math
0811:                                .max(
0812:                                        XChoicePeer.this .width,
0813:                                        helper.getMaxItemWidth()
0814:                                                + 2
0815:                                                * (BORDER_WIDTH + ITEM_MARGIN + TEXT_SPACE)
0816:                                                + (helper.isVSBVisible() ? SCROLLBAR_WIDTH
0817:                                                        : 0));
0818:                        height = 2 * BORDER_WIDTH + numItemsDisplayed
0819:                                * (helper.getItemHeight() + 2 * ITEM_MARGIN);
0820:                    }
0821:                    // Don't run off the edge of the screen
0822:                    if (x < 0) {
0823:                        x = 0;
0824:                    } else if (x + width > screen.width) {
0825:                        x = screen.width - width;
0826:                    }
0827:
0828:                    if (y < 0) {
0829:                        y = 0;
0830:                    } else if (y + height > screen.height) {
0831:                        y = screen.height - height;
0832:                    }
0833:                    return new Rectangle(x, y, width, height);
0834:                }
0835:
0836:                public void toFront() {
0837:                    // see 6240074 for more information
0838:                    if (choiceListener != null)
0839:                        choiceListener.unfurledChoiceOpening(helper);
0840:
0841:                    Rectangle r = placeOnScreen();
0842:                    reshape(r.x, r.y, r.width, r.height);
0843:                    super .toFront();
0844:                    setVisible(true);
0845:                }
0846:
0847:                /*
0848:                 * Track a MouseEvent (either a drag or a press) and paint a new
0849:                 * selected item, if necessary.
0850:                 */
0851:                // FIXME: first unfurl after move is not at edge of the screen  onto second monitor doesn't
0852:                // track mouse correctly.  Problem is w/ UnfurledChoice coords
0853:                public void trackMouse(MouseEvent e) {
0854:                    // Event coords are relative to the button, so translate a bit
0855:                    Point local = toLocalCoords(e);
0856:
0857:                    // If x,y is over unfurled Choice,
0858:                    // highlight item under cursor
0859:
0860:                    switch (e.getID()) {
0861:                    case MouseEvent.MOUSE_PRESSED:
0862:                        // FIXME: If the Choice is unfurled and the mouse is pressed
0863:                        // outside of the Choice, the mouse should ungrab on the
0864:                        // the press, not the release
0865:                        if (helper.isInVertSB(getBounds(), local.x, local.y)) {
0866:                            mouseInSB = true;
0867:                            helper.handleVSBEvent(e, getBounds(), local.x,
0868:                                    local.y);
0869:                        } else {
0870:                            trackSelection(local.x, local.y);
0871:                        }
0872:                        break;
0873:                    case MouseEvent.MOUSE_RELEASED:
0874:                        if (mouseInSB) {
0875:                            mouseInSB = false;
0876:                            helper.handleVSBEvent(e, getBounds(), local.x,
0877:                                    local.y);
0878:                        } else {
0879:                            // See 6243382 for more information
0880:                            helper.trackMouseReleasedScroll();
0881:                        }
0882:                        /*
0883:                          else {
0884:                          trackSelection(local.x, local.y);
0885:                          }
0886:                         */
0887:                        break;
0888:                    case MouseEvent.MOUSE_DRAGGED:
0889:                        if (mouseInSB) {
0890:                            helper.handleVSBEvent(e, getBounds(), local.x,
0891:                                    local.y);
0892:                        } else {
0893:                            // See 6243382 for more information
0894:                            helper.trackMouseDraggedScroll(local.x, local.y,
0895:                                    width, height);
0896:                            trackSelection(local.x, local.y);
0897:                        }
0898:                        break;
0899:                    }
0900:                }
0901:
0902:                private void trackSelection(int transX, int transY) {
0903:                    if (!helper.isEmpty()) {
0904:                        if (transX > 0 && transX < width && transY > 0
0905:                                && transY < height) {
0906:                            int newIdx = helper.y2index(transY);
0907:                            if (log.isLoggable(Level.FINE)) {
0908:                                log.fine("transX=" + transX + ", transY="
0909:                                        + transY + ",width=" + width
0910:                                        + ", height=" + height + ", newIdx="
0911:                                        + newIdx + " on " + target);
0912:                            }
0913:                            if ((newIdx >= 0)
0914:                                    && (newIdx < helper.getItemCount())
0915:                                    && (newIdx != helper.getSelectedIndex())) {
0916:                                helper.select(newIdx);
0917:                                unfurledChoice.repaint();
0918:                            }
0919:                        }
0920:                    }
0921:                    // FIXME: If dragged off top or bottom, scroll if there's a vsb
0922:                    // (ICK - we'll need a timer or our own event or something)
0923:                }
0924:
0925:                /*
0926:                 * fillRect with current Background color on the whole dropdown list.
0927:                 */
0928:                public void paintBackground() {
0929:                    Graphics g = getGraphics();
0930:                    g.setColor(getPeerBackground());
0931:                    g.fillRect(0, 0, width, height);
0932:                }
0933:
0934:                /* 
0935:                 * 6405689. In some cases we should erase background to eliminate painting 
0936:                 * artefacts. 
0937:                 */
0938:                public void repaint() {
0939:                    if (!isVisible()) {
0940:                        return;
0941:                    }
0942:                    if (helper.checkVsbVisibilityChangedAndReset()) {
0943:                        paintBackground();
0944:                    }
0945:                    super .repaint();
0946:                }
0947:
0948:                public void paint(Graphics g) {
0949:                    //System.out.println("UC.paint()");
0950:                    Choice choice = (Choice) target;
0951:                    Color colors[] = XChoicePeer.this .getGUIcolors();
0952:                    draw3DRect(g, getSystemColors(), 0, 0, width - 1,
0953:                            height - 1, true);
0954:                    draw3DRect(g, getSystemColors(), 1, 1, width - 3,
0955:                            height - 3, true);
0956:
0957:                    helper.paintAllItems(g, colors, getBounds());
0958:                }
0959:
0960:                public void setVisible(boolean vis) {
0961:                    xSetVisible(vis);
0962:
0963:                    if (!vis && alignUnder != null) {
0964:                        alignUnder.requestFocusInWindow();
0965:                    }
0966:                }
0967:
0968:                /**
0969:                 * Return a MouseEvent's Point in coordinates relative to the
0970:                 * UnfurledChoice.
0971:                 */
0972:                private Point toLocalCoords(MouseEvent e) {
0973:                    // Event coords are relative to the button, so translate a bit
0974:                    Point global = XChoicePeer.this 
0975:                            .toGlobal(e.getX(), e.getY());
0976:
0977:                    global.x -= x;
0978:                    global.y -= y;
0979:                    return global;
0980:                }
0981:
0982:                /* Returns true if the MouseEvent coords (which are based on the Choice)
0983:                 * are inside of the UnfurledChoice.
0984:                 */
0985:                private boolean isMouseEventInside(MouseEvent e) {
0986:                    Point local = toLocalCoords(e);
0987:                    if (local.x > 0 && local.x < width && local.y > 0
0988:                            && local.y < height) {
0989:                        return true;
0990:                    }
0991:                    return false;
0992:                }
0993:
0994:                /**
0995:                 * Tests if the mouse cursor is in the Unfurled Choice, yet not
0996:                 * in the vertical scrollbar
0997:                 */
0998:                private boolean isMouseInListArea(MouseEvent e) {
0999:                    if (isMouseEventInside(e)) {
1000:                        Point local = toLocalCoords(e);
1001:                        Rectangle bounds = getBounds();
1002:                        if (!helper.isInVertSB(bounds, local.x, local.y)) {
1003:                            return true;
1004:                        }
1005:                    }
1006:                    return false;
1007:                }
1008:
1009:                /*
1010:                 * Overridden from XWindow() because we don't want to send
1011:                 * ComponentEvents
1012:                 */
1013:                public void handleConfigureNotifyEvent(XEvent xev) {
1014:                }
1015:
1016:                public void handleMapNotifyEvent(XEvent xev) {
1017:                }
1018:
1019:                public void handleUnmapNotifyEvent(XEvent xev) {
1020:                }
1021:            } //UnfurledChoice
1022:
1023:            public void dispose() {
1024:                if (unfurledChoice != null) {
1025:                    unfurledChoice.destroy();
1026:                }
1027:                super .dispose();
1028:            }
1029:
1030:            /*
1031:             * fix for 6239938 : Choice drop-down does not disappear when it loses
1032:             * focus, on XToolkit
1033:             * We are able to handle all _Key_ events received by Choice when
1034:             * it is in opened state without sending it to EventQueue.
1035:             * If Choice is in closed state we should behave like before: send
1036:             * all events to EventQueue.
1037:             * To be compatible with Motif we should handle all KeyEvents in
1038:             * Choice if it is opened. KeyEvents should be sent into Java if Choice is not opened.
1039:             */
1040:            boolean prePostEvent(final AWTEvent e) {
1041:                if (unfurled) {
1042:                    // fix for 6253211: PIT: MouseWheel events not triggered for Choice drop down in XAWT
1043:                    if (e instanceof  MouseWheelEvent) {
1044:                        return super .prePostEvent(e);
1045:                    }
1046:                    //fix 6252982: PIT: Keyboard FocusTraversal not working when choice's drop-down is visible, on XToolkit
1047:                    if (e instanceof  KeyEvent) {
1048:                        // notify XWindow that this event had been already handled and no need to post it again 
1049:                        EventQueue.invokeLater(new Runnable() {
1050:                            public void run() {
1051:                                if (target.isFocusable()
1052:                                        && getParentTopLevel()
1053:                                                .isFocusableWindow()) {
1054:                                    handleJavaKeyEvent((KeyEvent) e);
1055:                                }
1056:                            }
1057:                        });
1058:                        return true;
1059:                    } else {
1060:                        if (e instanceof  MouseEvent) {
1061:                            // Fix for 6240046 : REG:Choice's Drop-down does not disappear when clicking somewhere, after popup menu is disposed
1062:                            // if user presses Right Mouse Button on opened (unfurled)
1063:                            // Choice then we mustn't open a popup menu. We could filter
1064:                            // Mouse Events and handle them in XChoicePeer if Choice
1065:                            // currently in opened state.
1066:                            MouseEvent me = (MouseEvent) e;
1067:                            int eventId = e.getID();
1068:                            // fix 6251983: PIT: MouseDragged events not triggered
1069:                            // fix 6251988: PIT: Choice consumes MouseReleased, MouseClicked events when clicking it with left button,
1070:                            if ((unfurledChoice.isMouseEventInside(me) || (!firstPress && eventId == MouseEvent.MOUSE_DRAGGED))) {
1071:                                return handleMouseEventByChoice(me);
1072:                            }
1073:                            // MouseMoved events should be fired in Choice's comp if it's not opened
1074:                            // Shouldn't generate Moved Events. CR : 6251995
1075:                            if (eventId == MouseEvent.MOUSE_MOVED) {
1076:                                return handleMouseEventByChoice(me);
1077:                            }
1078:                            //fix for 6272965: PIT: Choice triggers MousePressed when pressing mouse outside comp while drop-down is active, XTkt
1079:                            if (!firstPress
1080:                                    && !(isMouseEventInChoice(me) || unfurledChoice
1081:                                            .isMouseEventInside(me))
1082:                                    && (eventId == MouseEvent.MOUSE_PRESSED
1083:                                            || eventId == MouseEvent.MOUSE_RELEASED || eventId == MouseEvent.MOUSE_CLICKED)) {
1084:                                return handleMouseEventByChoice(me);
1085:                            }
1086:                        }
1087:                    }//else KeyEvent
1088:                }//if unfurled
1089:                return super .prePostEvent(e);
1090:            }
1091:
1092:            //convenient method
1093:            //do not generate this kind of Events
1094:            public boolean handleMouseEventByChoice(final MouseEvent me) {
1095:                EventQueue.invokeLater(new Runnable() {
1096:                    public void run() {
1097:                        handleJavaMouseEvent(me);
1098:                    }
1099:                });
1100:                return true;
1101:            }
1102:
1103:            /* Returns true if the MouseEvent coords 
1104:             * are inside of the Choice itself (it doesnt's depends on 
1105:             * if this choice opened or not).
1106:             */
1107:            private boolean isMouseEventInChoice(MouseEvent e) {
1108:                int x = e.getX();
1109:                int y = e.getY();
1110:                Rectangle choiceRect = getBounds();
1111:
1112:                if (x < 0 || x > choiceRect.width || y < 0
1113:                        || y > choiceRect.height) {
1114:                    return false;
1115:                }
1116:                return true;
1117:            }
1118:        }
1119:
1120:        /*
1121:         * The listener interface for receiving "interesting" for XFileDialogPeer
1122:         * choice events (opening, closing).
1123:         * The listener added by means of the method addXChoicePeerListener
1124:         * A opening choice event is generated when the invoking unfurledChoice.toFront()
1125:         * A closing choice event is generated at the time of the processing the mouse releasing
1126:         * and the Enter pressing.
1127:         * see 6240074 for more information
1128:         */
1129:        interface XChoicePeerListener {
1130:            public void unfurledChoiceOpening(ListHelper choiceHelper);
1131:
1132:            public void unfurledChoiceClosing();
1133:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.